@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * VFS commands - 'fs mount', 'fs umount'
+ * VFS commands - 'fs mount', 'fs umount', 'fs ls'
*
* Provides a new 'fs' command with subcommands for the virtual filesystem
* layer, co-existing with the legacy filesystem commands in cmd/fs.c.
@@ -87,10 +87,28 @@ static int do_fs_umount(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_SUCCESS;
}
+static int do_fs_ls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *path = argc >= 2 ? argv[1] : "/";
+ int ret;
+
+ ret = vfs_ls(path);
+ if (ret) {
+ printf("fs ls failed: %dE\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
U_BOOT_LONGHELP(fs,
- "mount [<dev> <mountpoint>] - list or create mounts\n"
- "fs umount <mountpoint> - unmount a filesystem");
+ "mount [<dev> <mountpoint>] - list or create mounts\n"
+ "fs mount -t <type> <iface> <dev:part> <path> - mount from block device\n"
+ "fs umount <mountpoint> - unmount a filesystem\n"
+ "fs ls [<path>] - list directory (default /)");
U_BOOT_CMD_WITH_SUBCMDS(fs, "Filesystem operations", fs_help_text,
- U_BOOT_SUBCMD_MKENT(mount, 3, 1, do_fs_mount),
- U_BOOT_SUBCMD_MKENT(umount, 2, 1, do_fs_umount));
+ U_BOOT_SUBCMD_MKENT(mount, 6, 1, do_fs_mount),
+ U_BOOT_SUBCMD_MKENT(umount, 2, 1, do_fs_umount),
+ U_BOOT_SUBCMD_MKENT(ls, 2, 1, do_fs_ls));
@@ -331,6 +331,52 @@ void vfs_print_mounts(void)
}
}
+int vfs_ls(const char *path)
+{
+ struct udevice *vfs, *mnt, *dir = NULL;
+ struct fs_dir_stream *strm;
+ struct fs_dirent dent;
+ const char *subpath;
+ bool empty = true;
+ int ret;
+
+ vfs = vfs_root();
+ if (!vfs)
+ return -ENXIO;
+
+ ret = vfs_find_mount(vfs, path, &mnt, &subpath);
+ if (!ret && mnt) {
+ struct vfsmount *m = dev_get_uclass_priv(mnt);
+
+ ret = fs_lookup_dir(m->target, subpath, &dir);
+ if (ret)
+ return ret;
+ } else if (!ret || !path[1]) {
+ /* Root "/" - list the VFS root dir */
+ ret = fs_lookup_dir(vfs, "", &dir);
+ if (ret)
+ return ret;
+ } else {
+ return ret;
+ }
+
+ ret = dir_open(dir, &strm);
+ if (ret)
+ return ret;
+
+ while (!dir_read(dir, strm, &dent)) {
+ if (dent.type == FS_DT_DIR)
+ printf("DIR %10u %s\n", 0, dent.name);
+ else
+ printf(" %10llu %s\n", dent.size, dent.name);
+ empty = false;
+ }
+
+ dir_close(dir, strm);
+
+ return 0;
+}
+
struct udevice *vfs_root(void)
{
struct udevice *dev;
@@ -125,4 +125,15 @@ bool vfs_is_mount_point(struct udevice *dir);
*/
void vfs_print_mounts(void);
+/**
+ * vfs_ls() - List directory contents
+ *
+ * Resolves the path through the mount table and lists directory entries
+ * using dir_open(), dir_read() and dir_close().
+ *
+ * @path: Absolute path to list, or "/" for root
+ * Return: 0 if OK, -ve on error
+ */
+int vfs_ls(const char *path);
+
#endif
@@ -262,6 +262,16 @@ static int dm_test_vfs_cmd(struct unit_test_state *uts)
ut_assert_nextlinen("/host");
ut_assert_console_end();
+ /* Root should show the "host" mount point */
+ ut_assertok(run_command("fs ls /", 0));
+ ut_assert_nextline("DIR %10u host", 0);
+ ut_assert_console_end();
+
+ /* Listing /host should show sandbox directory contents */
+ ut_assertok(run_command("fs ls /host", 0));
+ ut_assert_skip_to_linen("DIR ");
+ console_record_reset_enable();
+
/* Unmount */
ut_assertok(run_command("fs umount /host", 0));
ut_assert_console_end();