fs: add support for mount point listing on vfs root

This will list all mount points in response to opendir("/").

This isn't perfect; mount points in subdirectories will show up as
their full path in this listing.  But it's better than just returning
-EINVAL.

Signed-off-by: Jim Paris <jim@jtan.com>
This commit is contained in:
Jim Paris 2019-07-24 14:15:08 -04:00 committed by Carles Cufí
parent 1630292e5f
commit fae62fc4fc

View file

@ -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) {