From 0c737d3b2e4728347cf4d52025f9fc2ebbee6e90 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Wed, 1 May 2024 10:01:56 -0400 Subject: readdir_r use in tagcache.check_dir, ft_load Change-Id: Ibcde39ed247e100dd47ae877fb2a3625bbb38d8b --- apps/filetree.c | 20 ++++++------- apps/tagcache.c | 6 ++-- firmware/common/dir.c | 40 ++++++++++++++++++-------- firmware/target/hosted/filesystem-app.c | 50 +++++++++++++++++++++++++++++++++ firmware/target/hosted/filesystem-app.h | 1 + uisimulator/common/filesystem-sim.c | 35 +++++++++++++++++++++++ uisimulator/common/filesystem-sim.h | 1 + 7 files changed, 129 insertions(+), 24 deletions(-) diff --git a/apps/filetree.c b/apps/filetree.c index b5f5dece5a..99bb1340d7 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -292,6 +292,7 @@ int ft_load(struct tree_context* c, const char* tempdir) int files_in_dir = 0; int name_buffer_used = 0; + struct dirent direntry; struct dirent *entry; bool (*callback_show_item)(char *, int, struct tree_context *) = NULL; DIR *dir; @@ -313,7 +314,7 @@ int ft_load(struct tree_context* c, const char* tempdir) c->dirfull = false; tree_lock_cache(c); - while ((entry = readdir(dir))) { + while (readdir_r(dir, &direntry, &entry) == 0 && entry) { int len; struct dirinfo info; struct entry* dptr = tree_get_entry_at(c, files_in_dir); @@ -326,18 +327,18 @@ int ft_load(struct tree_context* c, const char* tempdir) info = dir_get_info(dir, entry); len = strlen((char *)entry->d_name); - /* skip directories . and .. */ - if ((info.attribute & ATTR_DIRECTORY) && - (((len == 1) && (!strncmp((char *)entry->d_name, ".", 1))) || - ((len == 2) && (!strncmp((char *)entry->d_name, "..", 2))))) { - continue; - } - /* Skip FAT volume ID */ if (info.attribute & ATTR_VOLUME_ID) { continue; } + dptr->attr = info.attribute; + int dir_attr = (dptr->attr & ATTR_DIRECTORY); + + /* skip directories . and .. */ + if (dir_attr && is_dotdir_name(entry->d_name)) + continue; + /* filter out dotfiles and hidden files */ if (*c->dirfilter != SHOW_ALL && ((entry->d_name[0]=='.') || @@ -345,9 +346,6 @@ int ft_load(struct tree_context* c, const char* tempdir) continue; } - dptr->attr = info.attribute; - int dir_attr = (dptr->attr & ATTR_DIRECTORY); - /* check for known file types */ if ( !(dir_attr) ) dptr->attr |= filetype_get_attr((char *)entry->d_name); diff --git a/apps/tagcache.c b/apps/tagcache.c index 9463d7c865..302b6ad9de 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -4863,8 +4863,8 @@ static int free_search_roots(struct search_roots_ll * start) static bool check_dir(const char *dirname, int add_files) { + static struct dirent direntry; /* function is recursive, static uses less stack */ int success = false; - DIR *dir = opendir(dirname); if (!dir) { @@ -4883,7 +4883,9 @@ static bool check_dir(const char *dirname, int add_files) /* Recursively scan the dir. */ while (!check_event_queue()) { - struct dirent *entry = readdir(dir); + struct dirent *entry; + readdir_r(dir, &direntry, &entry); + if (entry == NULL) { success = true; diff --git a/firmware/common/dir.c b/firmware/common/dir.c index 9a78d910a7..27af5f7fca 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c @@ -159,6 +159,7 @@ file_error: return rc; } +#if 0 /* read a directory */ struct dirent * readdir(DIR *dirp) { @@ -182,23 +183,19 @@ file_error: return res; } +#endif -#if 0 /* not included now but probably should be */ -/* read a directory (reentrant) */ -int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) +/* readdir, readdir_r common fn */ +static int readdir_common(DIR *dirp, struct dirent *entry, struct dirent **result) { - if (!result) - FILE_ERROR_RETURN(EFAULT, -2); - - *result = NULL; - - if (!entry) - FILE_ERROR_RETURN(EFAULT, -3); - + *result = NULL; /* we checked for validity before calling, yes? */ struct dirstr_desc * const dir = GET_DIRSTR(READER, dirp); if (!dir) FILE_ERROR_RETURN(ERRNO, -1); + if (!entry) + entry = &dir->entry; + int rc = ns_readdir_dirent(&dir->stream, &dir->scan, entry); if (rc < 0) FILE_ERROR(EIO, rc * 10 - 4); @@ -218,6 +215,27 @@ file_error: return rc; } +/* read a directory */ +struct dirent * readdir(DIR *dirp) +{ + struct dirent *entry; + readdir_common(dirp, NULL, &entry); + return entry; +} + +/* read a directory (reentrant) */ +int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) +{ + if (!result) + FILE_ERROR_RETURN(EFAULT, -2); + *result = NULL; + if (!entry) + FILE_ERROR_RETURN(EFAULT, -3); + return readdir_common(dirp, entry, result); +} + + +#if 0 /* not included now but probably should be */ /* reset the position of a directory stream to the beginning of a directory */ void rewinddir(DIR *dirp) { diff --git a/firmware/target/hosted/filesystem-app.c b/firmware/target/hosted/filesystem-app.c index 7d59a174dc..fc4fff0eb5 100644 --- a/firmware/target/hosted/filesystem-app.c +++ b/firmware/target/hosted/filesystem-app.c @@ -453,6 +453,56 @@ struct dirent * app_readdir(DIR *dirp) return (struct dirent *)osdirent; } +/* read a directory (reentrant) */ +int app_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) +{ + struct __dir *this = (struct __dir *)dirp; + if (!this) + FILE_ERROR_RETURN(EBADF, -6); + + if (!result) + FILE_ERROR_RETURN(EFAULT, -2); + + *result = NULL; + + if (!entry) + FILE_ERROR_RETURN(EFAULT, -3); + +#ifdef HAVE_MULTIDRIVE + if (this->volumes_returned < NUM_VOLUMES) + { + while (++this->volumes_returned < NUM_VOLUMES) + { + if (!volume_present(this->volumes_returned)) + continue; + + get_volume_name(this->volumes_returned, entry->d_name); + *result = entry; + return 0; + } + } + /* do normal directory reads */ +#endif /* HAVE_MULTIDRIVE */ + + OS_DIRENT_T *osdirent = os_readdir(this->osdirp); + if (!osdirent) + FILE_ERROR_RETURN(ERRNO, -4); +#ifdef OS_DIRENT_CONVERT + size_t name_size = sizeof (entry->d_name); + if (strlcpy_from_os(entry->d_name, osdirent->d_name, + name_size) >= name_size) + { + entry->d_name[0] = '\0'; + errno = EOVERFLOW; + FILE_ERROR_RETURN(ENAMETOOLONG, -5); + } + + *result = entry; +#endif /* OS_DIRENT_CONVERT */ + + return 0; +} + int app_mkdir(const char *path) { char realpath[MAX_PATH]; diff --git a/firmware/target/hosted/filesystem-app.h b/firmware/target/hosted/filesystem-app.h index b35b63e95f..2d7d6e817d 100644 --- a/firmware/target/hosted/filesystem-app.h +++ b/firmware/target/hosted/filesystem-app.h @@ -107,6 +107,7 @@ ssize_t app_readlink(const char *path, char *buf, size_t bufsize); #ifndef DIRFUNCTIONS_DECLARED DIR * app_opendir(const char *dirname); struct dirent * app_readdir(DIR *dirp); +int app_readdir_r(DIR *dirp, struct dirent* entry, struct dirent **result); int app_closedir(DIR *dirp); int app_mkdir(const char *path); int app_rmdir(const char *path); diff --git a/uisimulator/common/filesystem-sim.c b/uisimulator/common/filesystem-sim.c index f4f6321b7d..54e703ff40 100644 --- a/uisimulator/common/filesystem-sim.c +++ b/uisimulator/common/filesystem-sim.c @@ -704,6 +704,41 @@ struct sim_dirent * sim_readdir(DIR *dirp) return entry; } +/* read a directory (reentrant) */ +int sim_readdir_r(DIR *dirp, struct sim_dirent *entry, struct sim_dirent **result) +{ + if (!result) + FILE_ERROR_RETURN(EFAULT, -2); + + *result = NULL; + + if (!entry) + FILE_ERROR_RETURN(EFAULT, -3); + + struct dirstr_desc *dirstr = get_dirstr(dirp); + if (!dirstr) + FILE_ERROR_RETURN(ERRNO, -1); + + entry->info.osdirent = NULL; + + if (readdir_volume(dirstr, entry)) + { + *result = entry; + return 0; + } + OS_DIRENT_T *osdirent = os_readdir(dirstr->osdirp); + if (!osdirent) + FILE_ERROR_RETURN(ERRNO, -4); + + size_t size = sizeof (entry->d_name); + if (strlcpy_from_os(entry->d_name, osdirent->d_name, size) >= size) + FILE_ERROR_RETURN(ENAMETOOLONG, -5); + + entry->info.osdirent = osdirent; + *result = entry; + return 0; +} + int sim_mkdir(const char *path) { char ospath[SIM_TMPBUF_MAX_PATH]; diff --git a/uisimulator/common/filesystem-sim.h b/uisimulator/common/filesystem-sim.h index 346d6fa74e..1b6c6dfe69 100644 --- a/uisimulator/common/filesystem-sim.h +++ b/uisimulator/common/filesystem-sim.h @@ -98,6 +98,7 @@ struct dirinfo_native #ifndef DIRFUNCTIONS_DECLARED DIR * sim_opendir(const char *dirname); struct sim_dirent * sim_readdir(DIR *dirp); +int sim_readdir_r(DIR *dirp, struct sim_dirent* entry, struct sim_dirent **result); int sim_closedir(DIR *dirp); int sim_mkdir(const char *path); int sim_rmdir(const char *path); -- cgit v1.2.3