From aeeee5492133f91a69926eeca28040530a9c1605 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 20 Mar 2018 14:30:05 -0600 Subject: [PATCH] tools/gencromfs.c and fs/cromfs: More corrections to directory traversal logic. Still some bugs. --- fs/cromfs/fs_cromfs.c | 27 ++++++++++++++++++--------- tools/gencromfs.c | 34 ++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/fs/cromfs/fs_cromfs.c b/fs/cromfs/fs_cromfs.c index ce4809f1f7..c3addaf98a 100644 --- a/fs/cromfs/fs_cromfs.c +++ b/fs/cromfs/fs_cromfs.c @@ -104,6 +104,7 @@ static FAR void *cromfs_offset2addr(FAR const struct cromfs_volume_s *fs, static uint32_t cromfs_addr2offset(FAR const struct cromfs_volume_s *fs, FAR const void *addr); static int cromfs_foreach_node(FAR const struct cromfs_volume_s *fs, + FAR const struct cromfs_node_s *node, cromfs_foreach_t callback, FAR void *arg); static uint16_t cromfs_seglen(FAR const char *relpath); static int cromfs_comparenode(FAR const struct cromfs_volume_s *fs, @@ -256,12 +257,15 @@ static uint32_t cromfs_addr2offset(FAR const struct cromfs_volume_s *fs, ****************************************************************************/ static int cromfs_foreach_node(FAR const struct cromfs_volume_s *fs, - cromfs_foreach_t callback, FAR void *arg) + FAR const struct cromfs_node_s *node, + cromfs_foreach_t callback, FAR void *arg) { - FAR const struct cromfs_node_s *node; int ret = OK; - node = (FAR const struct cromfs_node_s *)cromfs_offset2addr(fs, fs->cv_root); + /* Traverse all entries in this directory (i.e., following the 'peer' + * links). + */ + while (node != NULL) { ret = callback(fs, node, arg); @@ -347,11 +351,11 @@ static int cromfs_comparenode(FAR const struct cromfs_volume_s *fs, */ *cpnode->node = (FAR const struct cromfs_node_s *) - cromfs_offset2addr(fs, node->u.cn_child); + cromfs_offset2addr(fs, node->u.cn_child); return 1; } - /* A specal cas is if the path ends in "/". In this case I suppose + /* A special case is if the path ends in "/". In this case I suppose * we need to interpret the as matching as long as it is a directory? */ @@ -391,7 +395,7 @@ static int cromfs_comparenode(FAR const struct cromfs_volume_s *fs, /* Then recurse */ - return cromfs_foreach_node(fs, cromfs_comparenode, cpnode); + return cromfs_foreach_node(fs, node, cromfs_comparenode, cpnode); } else { @@ -408,14 +412,19 @@ static int cromfs_findnode(FAR const struct cromfs_volume_s *fs, FAR const char *relpath) { struct cromfs_comparenode_s cpnode; + FAR const struct cromfs_node_s *root; int ret; + /* Get the root node */ + + root = (FAR const struct cromfs_node_s *) + cromfs_offset2addr(fs, fs->cv_root); + /* NULL or empty string refers to the root node */ if (relpath == NULL || relpath[0] == '\0') { - *node = (FAR const struct cromfs_node_s *) - cromfs_offset2addr(fs, fs->cv_root); + *node = root; return OK; } @@ -433,7 +442,7 @@ static int cromfs_findnode(FAR const struct cromfs_volume_s *fs, cpnode.segment = relpath; cpnode.seglen = (uint16_t)cromfs_seglen(relpath); - ret = cromfs_foreach_node(fs, cromfs_comparenode, &cpnode); + ret = cromfs_foreach_node(fs, root, cromfs_comparenode, &cpnode); if (ret > 0) { return OK; diff --git a/tools/gencromfs.c b/tools/gencromfs.c index d69b07cf9a..06c20b041e 100644 --- a/tools/gencromfs.c +++ b/tools/gencromfs.c @@ -260,7 +260,7 @@ static void gen_directory(const char *path, const char *name, mode_t mode, bool lastentry); static void gen_file(const char *path, const char *name, mode_t mode, bool lastentry); -static void process_direntry(const char *dirpath, struct dirent *direntry, +static void process_direntry(const char *dirpath, const char *name, bool lastentry); static void traverse_directory(const char *dirpath); @@ -1079,14 +1079,14 @@ static void gen_file(const char *path, const char *name, mode_t mode, append_tmpfile(g_tmpstream, outstream); } -static void process_direntry(const char *dirpath, struct dirent *direntry, +static void process_direntry(const char *dirpath, const char *name, bool lastentry) { struct stat buf; char *path; int ret; - asprintf(&path, "%s/%s", dirpath, direntry->d_name); + asprintf(&path, "%s/%s", dirpath, name); ret = stat(path, &buf); if (ret < 0) @@ -1109,11 +1109,11 @@ static void process_direntry(const char *dirpath, struct dirent *direntry, else if (S_ISDIR(buf.st_mode)) { - gen_directory(path, direntry->d_name, buf.st_mode, lastentry); + gen_directory(path, name, buf.st_mode, lastentry); } else if (S_ISREG(buf.st_mode)) { - gen_file(path, direntry->d_name, buf.st_mode, lastentry); + gen_file(path, name, buf.st_mode, lastentry); } else { @@ -1127,7 +1127,7 @@ static void traverse_directory(const char *dirpath) { DIR *dirp; struct dirent *direntry; - struct dirent *nextentry; + char name[NAME_MAX + 1]; /* Open the directory */ @@ -1144,25 +1144,27 @@ static void traverse_directory(const char *dirpath) direntry = readdir(dirp); while (direntry != NULL) { - /* Get the next entry so that we can anticipate the end of the - * directory. + /* Preserve the name from the directory entry. The return value + * from readdir() only persists until the next time that readdir() + * is called (alternatively, use readdir_r). */ - nextentry = readdir(dirp); + strncpy(name, direntry->d_name, NAME_MAX + 1); + + /* Get the next entry in advance so that we can anticipate the end of + * the directory. + */ + + direntry = readdir(dirp); /* Skip the '.' and '..' hard links */ - if (strcmp(direntry->d_name, ".") != 0 && - strcmp(direntry->d_name, "..") != 0) + if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) { /* Process the directory entry */ - process_direntry(dirpath, direntry, nextentry == NULL); + process_direntry(dirpath, name, direntry == NULL); } - - /* Skip to the next entry */ - - direntry = nextentry; } }