diff --git a/subsys/fs/fs.c b/subsys/fs/fs.c index 92f9ea08a6..6ec4bc59cd 100644 --- a/subsys/fs/fs.c +++ b/subsys/fs/fs.c @@ -213,11 +213,23 @@ int fs_opendir(struct fs_dir_t *zdp, const char *abs_path) int rc = -EINVAL; if ((abs_path == NULL) || - (strlen(abs_path) <= 1) || (abs_path[0] != '/')) { + (strlen(abs_path) < 1) || (abs_path[0] != '/')) { LOG_ERR("invalid file name!!"); return -EINVAL; } + if (strcmp(abs_path, "/") == 0) { + /* Open VFS root dir, marked by zdp->mp == NULL */ + k_mutex_lock(&mutex, K_FOREVER); + + zdp->mp = NULL; + zdp->dirp = sys_dlist_peek_head(&fs_mnt_list); + + k_mutex_unlock(&mutex); + + return 0; + } + rc = fs_get_mnt_point(&mp, abs_path, NULL); if (rc < 0) { LOG_ERR("%s:mount point not found!!", __func__); @@ -238,21 +250,76 @@ int fs_opendir(struct fs_dir_t *zdp, const char *abs_path) int fs_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry) { - int rc = -EINVAL; + if (zdp->mp) { + /* Delegate to mounted filesystem */ + int rc = -EINVAL; - if (zdp->mp->fs->readdir != NULL) { - rc = zdp->mp->fs->readdir(zdp, entry); - if (rc < 0) { - LOG_ERR("directory read error (%d)", rc); + if (zdp->mp->fs->readdir != NULL) { + rc = zdp->mp->fs->readdir(zdp, entry); + if (rc < 0) { + LOG_ERR("directory read error (%d)", rc); + } + } + return rc; + } + + /* VFS root dir */ + if (zdp->dirp == NULL) { + /* No more entries */ + entry->name[0] = 0; + return 0; + } + + /* Find the current and next entries in the mount point dlist */ + sys_dnode_t *node, *next = NULL; + bool found = false; + + k_mutex_lock(&mutex, K_FOREVER); + + SYS_DLIST_FOR_EACH_NODE(&fs_mnt_list, node) { + if (node == zdp->dirp) { + found = true; + + /* Pull info from current entry */ + struct fs_mount_t *mnt; + + mnt = CONTAINER_OF(node, struct fs_mount_t, node); + + entry->type = FS_DIR_ENTRY_DIR; + strncpy(entry->name, mnt->mnt_point + 1, + sizeof(entry->name) - 1); + entry->name[sizeof(entry->name) - 1] = 0; + entry->size = 0; + + /* Save pointer to the next one, for later */ + next = sys_dlist_peek_next(&fs_mnt_list, node); + break; } } - return rc; + + k_mutex_unlock(&mutex); + + if (!found) { + /* Current entry must have been removed before this + * call to readdir -- return an error + */ + return -ENOENT; + } + + zdp->dirp = next; + return 0; } int fs_closedir(struct fs_dir_t *zdp) { int rc = -EINVAL; + if (zdp->mp == NULL) { + /* VFS root dir */ + zdp->dirp = NULL; + return 0; + } + if (zdp->mp->fs->closedir != NULL) { rc = zdp->mp->fs->closedir(zdp); if (rc < 0) {