diff options
author | Igor Ostapenko <igoreisberg@gmail.com> | 2021-12-17 14:08:23 +0200 |
---|---|---|
committer | Gao Xiang <xiang@kernel.org> | 2021-12-18 21:35:41 +0800 |
commit | e6082718f7434628af5687e103090f3981ed6fea (patch) | |
tree | 4c58f8274dab2844c9b7b6b8cacb67c942dfc885 /dump/main.c | |
parent | 5a9ac8e057cf744eb844da840ea08468c1be1f30 (diff) | |
download | erofs-utils-e6082718f7434628af5687e103090f3981ed6fea.tar.gz |
erofs-utils: lib: add API to get pathname of EROFS inode
* General-purpose erofs_get_pathname function utilizing erofs_iterate_dir,
with recursion and a reused context to avoid overflowing the stack.
Recommended buffer size is PATH_MAX. Zero-filling the buffer is not
necessary.
* dump: PATH_MAX+1 is not required since the definition of PATH_MAX is
"chars in a path name including nul".
* Return err from erofs_iterate_dir instead of hardcoded 0, to allow
breaking the iteration by the callback using a non-zero return code.
Link: https://lore.kernel.org/r/CABjEcnE84FNBgiHFk6Q+V3d-4L-93bUFDkdfN4ftPX19kpC=ww@mail.gmail.com
Signed-off-by: Igor Ostapenko <igoreisberg@gmail.com>
[ Gao Xiang: let's use NID instead of (struct erofs_inode *). ]
Signed-off-by: Gao Xiang <xiang@kernel.org>
Diffstat (limited to 'dump/main.c')
-rw-r--r-- | dump/main.c | 72 |
1 files changed, 3 insertions, 69 deletions
diff --git a/dump/main.c b/dump/main.c index 7f3f743..997460c 100644 --- a/dump/main.c +++ b/dump/main.c @@ -328,71 +328,6 @@ static inline int erofs_checkdirent(struct erofs_dirent *de, return dname_len; } -static int erofs_get_pathname(erofs_nid_t nid, erofs_nid_t parent_nid, - erofs_nid_t target, char *path, unsigned int pos) -{ - int err; - erofs_off_t offset; - char buf[EROFS_BLKSIZ]; - struct erofs_inode inode = { .nid = nid }; - - path[pos++] = '/'; - if (target == sbi.root_nid) - return 0; - - err = erofs_read_inode_from_disk(&inode); - if (err) { - erofs_err("read inode failed @ nid %llu", nid | 0ULL); - return err; - } - - offset = 0; - while (offset < inode.i_size) { - erofs_off_t maxsize = min_t(erofs_off_t, - inode.i_size - offset, EROFS_BLKSIZ); - struct erofs_dirent *de = (void *)buf; - struct erofs_dirent *end; - unsigned int nameoff; - - err = erofs_pread(&inode, buf, maxsize, offset); - if (err) - return err; - - nameoff = le16_to_cpu(de->nameoff); - end = (void *)buf + nameoff; - while (de < end) { - const char *dname; - int len; - - nameoff = le16_to_cpu(de->nameoff); - dname = (char *)buf + nameoff; - len = erofs_checkdirent(de, end, maxsize, dname); - if (len < 0) - return len; - - if (le64_to_cpu(de->nid) == target) { - memcpy(path + pos, dname, len); - path[pos + len] = '\0'; - return 0; - } - - if (de->file_type == EROFS_FT_DIR && - le64_to_cpu(de->nid) != parent_nid && - le64_to_cpu(de->nid) != nid) { - memcpy(path + pos, dname, len); - err = erofs_get_pathname(le64_to_cpu(de->nid), - nid, target, path, pos + len); - if (!err) - return 0; - memset(path + pos, 0, len); - } - ++de; - } - offset += maxsize; - } - return -1; -} - static int erofsdump_map_blocks(struct erofs_inode *inode, struct erofs_map_blocks *map, int flags) { @@ -411,7 +346,7 @@ static void erofsdump_show_fileinfo(bool show_extent) erofs_off_t size; u16 access_mode; struct erofs_inode inode = { .nid = dumpcfg.nid }; - char path[PATH_MAX + 1] = {0}; + char path[PATH_MAX]; char access_mode_str[] = "rwxrwxrwx"; char timebuf[128] = {0}; unsigned int extent_count = 0; @@ -441,8 +376,7 @@ static void erofsdump_show_fileinfo(bool show_extent) return; } - err = erofs_get_pathname(sbi.root_nid, sbi.root_nid, - inode.nid, path, 0); + err = erofs_get_pathname(dumpcfg.nid, path, sizeof(path)); if (err < 0) { erofs_err("file path not found @ nid %llu", inode.nid | 0ULL); return; @@ -598,7 +532,7 @@ static void erofsdump_print_statistic(void) .cb = erofsdump_dirent_iter, .de_nid = sbi.root_nid, .dname = "", - .de_namelen = 0 + .de_namelen = 0, }; err = erofsdump_readdir(&ctx); |