From 696dfa6ce29cb44d22e48bf66032e217383d8a2f Mon Sep 17 00:00:00 2001
From: zhouliang3 <zhouliang3@xiaomi.com>
Date: Tue, 24 Aug 2021 12:48:22 +0800
Subject: [PATCH] fs/littlefs: Add the function of obtaining absolute path

Signed-off-by: zhouliang3 <zhouliang3@xiaomi.com>
---
 lfs.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lfs.h |  8 ++++++
 2 files changed, 87 insertions(+)

--- ./littlefs/littlefs/lfs.c
+++ ./littlefs/littlefs/lfs.c
@@ -542,6 +542,8 @@ static uint16_t lfs_fs_disk_version_minor(lfs_t *lfs) {
 
 
 /// Internal operations predeclared here ///
+static lfs_ssize_t lfs_dir_rawpath(lfs_t *lfs,
+        lfs_mdir_t *dir, uint16_t id, char *path, lfs_size_t size);
 #ifndef LFS_READONLY
 static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
         const struct lfs_mattr *attrs, int attrcount);
@@ -3790,6 +3792,53 @@ static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file) {
     return file->ctz.size;
 }
 
+static lfs_ssize_t lfs_dir_rawpath(lfs_t *lfs,
+         lfs_mdir_t *dir, uint16_t id, char *path, lfs_size_t size) {
+    struct lfs_info info;
+    char *next = path;
+    lfs_mdir_t parent;
+    lfs_ssize_t len;
+    lfs_stag_t tag;
+    int err;
+
+    if (lfs_pair_cmp(lfs->root, dir->pair) != 0) {
+        tag = lfs_fs_parent(lfs, dir->pair, &parent);
+        if (tag < 0) {
+            return tag;
+        }
+
+        len = lfs_dir_rawpath(lfs, &parent, lfs_tag_id(tag), next, size);
+        if (len < 0) {
+            return len;
+        }
+
+        next += len;
+        size -= len;
+    }
+
+    err = lfs_dir_getinfo(lfs, dir, id, &info);
+    if (err < 0) {
+        return err;
+    }
+
+    len = strlen(info.name);
+    if (len >= size) {
+        return LFS_ERR_INVAL;
+    }
+
+    memcpy(next, info.name, len + 1);
+    next += len;
+
+    if (info.type == LFS_TYPE_DIR) {
+        *next++ = '/';
+        if (++len >= size) {
+            return LFS_ERR_INVAL;
+        }
+        *next = '\0';
+    }
+
+    return next - path;
+}
 
 /// General fs operations ///
 static int lfs_rawstat(lfs_t *lfs, const char *path, struct lfs_info *info) {
@@ -6042,6 +6091,22 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
     return res;
 }
 
+int lfs_file_path(lfs_t *lfs, lfs_file_t *file, char *path, lfs_size_t size) {
+    int err = LFS_LOCK(lfs->cfg);
+    if (err) {
+        return err;
+    }
+
+    LFS_TRACE("lfs_file_path(%p, %p)", (void*)lfs, (void*)file);
+    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
+
+    err = lfs_dir_rawpath(lfs, &file->m, file->id, path, size);
+
+    LFS_TRACE("lfs_file_path -> %d", err);
+    LFS_UNLOCK(lfs->cfg);
+    return err < 0 ? err : 0;
+}
+
 #ifndef LFS_READONLY
 int lfs_mkdir(lfs_t *lfs, const char *path) {
     int err = LFS_LOCK(lfs->cfg);
@@ -6173,6 +6238,20 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs) {
     return res;
 }
 
+int lfs_dir_path(lfs_t *lfs, lfs_dir_t *dir, char *path, lfs_size_t size) {
+    int err = LFS_LOCK(lfs->cfg);
+    if (err) {
+        return err;
+    }
+
+    LFS_TRACE("lfs_dir_path(%p, %p)", (void*)lfs, (void*)dir);
+    err = lfs_dir_rawpath(lfs, &dir->m, dir->id, path, size);
+
+    LFS_TRACE("lfs_dir_path -> %d", err);
+    LFS_UNLOCK(lfs->cfg);
+    return err < 0 ? err : 0;
+}
+
 int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data) {
     int err = LFS_LOCK(lfs->cfg);
     if (err) {
--- ./littlefs/littlefs/lfs.h
+++ ./littlefs/littlefs/lfs.h
@@ -629,6 +629,10 @@ int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
 // Returns the size of the file, or a negative error code on failure.
 lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
 
+// Get the absolute path of the open file.
+//
+// Returns a negative error code on failure.
+int lfs_file_path(lfs_t *lfs, lfs_file_t *file, char *path, lfs_size_t size);
 
 /// Directory operations ///
 
@@ -679,6 +683,10 @@ lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
 // Returns a negative error code on failure.
 int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
 
+// Get the absolute path of the directory
+//
+// Returns a negative error code on failure.
+int lfs_dir_path(lfs_t *lfs, lfs_dir_t *dir, char *path, lfs_size_t size);
 
 /// Filesystem-level filesystem operations
 
-- 
2.25.1