This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit cacded6ab90fb34ad6f294f7b47787aab415bb58 Author: yezhonghui <[email protected]> AuthorDate: Thu Nov 12 00:35:11 2026 +0800 fs/procfs: list registered entries once and in their directory procfs_readdir() assumes that the entries of one directory are adjacent in g_procfs_entries, and drops a first-level name only when it repeats the name reported just before it. procfs_register() appends to the end of the table, so after registering "fs/foo" and "foo_bar": - "ls /proc" reports "fs" a second time, and hides "foo_bar" because its first two characters match the "fs" reported before it. - "ls /proc/fs" stops at the first entry outside fs/ and never reaches "foo". Scan the rest of the table for each directory instead, and skip a name when an earlier entry already yields it. Since the scan now covers the whole table, a member of a subdirectory must also have '/' right after the directory name, so "foo_bar" is not taken as part of "fs". Signed-off-by: yezhonghui <[email protected]> Signed-off-by: jingfei <[email protected]> --- fs/procfs/fs_procfs.c | 93 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 21 deletions(-) diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index aa198ff23f7..91c0e83750d 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -823,6 +823,45 @@ static int procfs_closedir(FAR struct inode *mountpt, return ret; } +/**************************************************************************** + * Name: procfs_listed + * + * Description: + * Return true if an entry before 'index' already yields the directory + * entry 'name' ('len' bytes) under the directory 'dir' ('dirlen' bytes, + * 0 for the procfs root). + * + ****************************************************************************/ + +static bool procfs_listed(unsigned int index, FAR const char *dir, + size_t dirlen, FAR const char *name, size_t len) +{ + unsigned int x; + + for (x = 0; x < index; x++) + { + FAR const char *path = g_procfs_entries[x].pathpattern; + + if (dirlen > 0) + { + if (strncmp(path, dir, dirlen) != 0 || path[dirlen] != '/') + { + continue; + } + + path += dirlen + 1; + } + + if (strncmp(path, name, len) == 0 && + (path[len] == '/' || path[len] == '*' || path[len] == '\0')) + { + return true; + } + } + + return false; +} + /**************************************************************************** * Name: procfs_readdir * @@ -839,6 +878,7 @@ static int procfs_readdir(FAR struct inode *mountpt, FAR struct procfs_level0_s *level0; FAR const char *name = NULL; unsigned int index; + size_t len; int ret = -ENOENT; DEBUGASSERT(mountpt && dir); @@ -898,8 +938,8 @@ static int procfs_readdir(FAR struct inode *mountpt, */ name = g_procfs_entries[index].pathpattern; - if (!level0->lastlen || - strncmp(name, level0->lastread, level0->lastlen) != 0) + if (!procfs_listed(index, NULL, 0, name, + strcspn(name, "/"))) { /* Not a duplicate, return the first segment of this * entry @@ -943,7 +983,7 @@ static int procfs_readdir(FAR struct inode *mountpt, /* Advance to next entry for the next read */ - priv->index = priv->nentries + index; + priv->index = priv->nentries + index + 1; ret = OK; } } @@ -984,37 +1024,48 @@ static int procfs_readdir(FAR struct inode *mountpt, level1 = (FAR struct procfs_level1_s *)priv; - /* Test if this entry matches. We assume all entries of the same - * subdirectory are listed in order in the procfs_entry array. + /* procfs_register() appends to the table, so the entries of one + * subdirectory need not be adjacent: scan the rest of the table and + * skip names already reported. */ - if (level1->base.index < g_procfs_entrycount && - level1->firstindex < g_procfs_entrycount && - strncmp(g_procfs_entries[level1->base.index].pathpattern, - g_procfs_entries[level1->firstindex].pathpattern, - level1->subdirlen) == 0) + while (level1->firstindex < g_procfs_entrycount && + level1->base.index < g_procfs_entrycount) { - /* This entry matches. Report the subdir entry */ + FAR const char *subdir = + g_procfs_entries[level1->firstindex].pathpattern; - name = &g_procfs_entries[level1->base.index]. - pathpattern[level1->subdirlen + 1]; - level1->lastlen = strcspn(name, "/"); - level1->lastread = name; - strlcpy(entry->d_name, name, level1->lastlen + 1); + index = level1->base.index++; + name = g_procfs_entries[index].pathpattern; + if (strncmp(name, subdir, level1->subdirlen) != 0 || + name[level1->subdirlen] != '/') + { + continue; + } /* Some of the search entries contain '**' wildcards. When we * report the entry name, we must remove this wildcard search * specifier. */ - while (entry->d_name[level1->lastlen - 1] == '*') + name += level1->subdirlen + 1; + len = strcspn(name, "/"); + while (len > 0 && name[len - 1] == '*') { - level1->lastlen--; + len--; } - entry->d_name[level1->lastlen] = '\0'; + if (len == 0 || + procfs_listed(index, subdir, level1->subdirlen, name, len)) + { + continue; + } + + level1->lastlen = len; + level1->lastread = name; + strlcpy(entry->d_name, name, len + 1); - if (name[level1->lastlen] == '/') + if (name[len] == '/') { entry->d_type = DTYPE_DIRECTORY; } @@ -1023,8 +1074,8 @@ static int procfs_readdir(FAR struct inode *mountpt, entry->d_type = DTYPE_FILE; } - level1->base.index++; ret = OK; + break; } } else
