[U-Boot] [PATCH v1 01/15] fs: add fs_readdir()
Rob Clark
robdclark at gmail.com
Thu Aug 10 18:29:29 UTC 2017
Needed to support efi file protocol. The fallback.efi loader wants
to be able to read the contents of the /EFI directory to find an OS
to boot.
Also included is an ls2 command which implements ls on top of
fs_readdir(), to more easily test the readdir functionality.
Signed-off-by: Rob Clark <robdclark at gmail.com>
---
cmd/fs.c | 14 +++++++++++
fs/fs.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/fs.h | 23 +++++++++++++++++
3 files changed, 117 insertions(+)
diff --git a/cmd/fs.c b/cmd/fs.c
index abfe5be172..58ddcec1a9 100644
--- a/cmd/fs.c
+++ b/cmd/fs.c
@@ -75,6 +75,20 @@ U_BOOT_CMD(
" device type 'interface' instance 'dev'."
)
+static int do_ls2_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return do_ls2(cmdtp, flag, argc, argv, FS_TYPE_ANY);
+}
+
+U_BOOT_CMD(
+ ls2, 4, 1, do_ls2_wrapper,
+ "list files in a directory using fs_readdir (default /)",
+ "<interface> [<dev[:part]> [directory]]\n"
+ " - List files in directory 'directory' of partition 'part' on\n"
+ " device type 'interface' instance 'dev'."
+)
+
static int do_fstype_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
diff --git a/fs/fs.c b/fs/fs.c
index 595ff1fe69..5720ceec49 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -69,6 +69,12 @@ static inline int fs_uuid_unsupported(char *uuid_str)
return -1;
}
+static inline int fs_readdir_unsupported(const char *filename, loff_t offset,
+ struct fs_dirent *dent)
+{
+ return -ENXIO;
+}
+
struct fstype_info {
int fstype;
char *name;
@@ -92,6 +98,7 @@ struct fstype_info {
loff_t len, loff_t *actwrite);
void (*close)(void);
int (*uuid)(char *uuid_str);
+ int (*readdir)(const char *filename, loff_t offset, struct fs_dirent *dent);
};
static struct fstype_info fstypes[] = {
@@ -112,6 +119,7 @@ static struct fstype_info fstypes[] = {
.write = fs_write_unsupported,
#endif
.uuid = fs_uuid_unsupported,
+ .readdir = fs_readdir_unsupported,
},
#endif
#ifdef CONFIG_FS_EXT4
@@ -131,6 +139,7 @@ static struct fstype_info fstypes[] = {
.write = fs_write_unsupported,
#endif
.uuid = ext4fs_uuid,
+ .readdir = fs_readdir_unsupported,
},
#endif
#ifdef CONFIG_SANDBOX
@@ -146,6 +155,7 @@ static struct fstype_info fstypes[] = {
.read = fs_read_sandbox,
.write = fs_write_sandbox,
.uuid = fs_uuid_unsupported,
+ .readdir = fs_readdir_unsupported,
},
#endif
#ifdef CONFIG_CMD_UBIFS
@@ -161,6 +171,7 @@ static struct fstype_info fstypes[] = {
.read = ubifs_read,
.write = fs_write_unsupported,
.uuid = fs_uuid_unsupported,
+ .readdir = fs_readdir_unsupported,
},
#endif
{
@@ -175,6 +186,7 @@ static struct fstype_info fstypes[] = {
.read = fs_read_unsupported,
.write = fs_write_unsupported,
.uuid = fs_uuid_unsupported,
+ .readdir = fs_readdir_unsupported,
},
};
@@ -334,6 +346,19 @@ int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
return ret;
}
+int fs_readdir(const char *filename, loff_t offset, struct fs_dirent *dent)
+{
+ struct fstype_info *info = fs_get_info(fs_type);
+ int ret;
+
+ memset(dent, 0, sizeof(*dent));
+
+ ret = info->readdir(filename, offset, dent);
+ fs_close();
+
+ return ret;
+}
+
int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
int fstype)
{
@@ -440,6 +465,61 @@ int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
return 0;
}
+int do_ls2(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+ int fstype)
+{
+ const char *filename = argc >= 4 ? argv[3] : "/";
+ const char *ifname = argv[1];
+ const char *dev_part_str = (argc >= 3) ? argv[2] : NULL;
+ loff_t offset = 0;
+ int ret, files = 0, dirs = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ if (argc > 4)
+ return CMD_RET_USAGE;
+
+ while (1) {
+ struct fs_dirent dent, dent2;
+ char buf[256];
+
+ if (fs_set_blk_dev(ifname, dev_part_str, fstype))
+ return 1;
+
+ ret = fs_readdir(filename, offset, &dent);
+ if (ret == -ENOENT) {
+ /* no more directory entries */
+ break;
+ } else if (ret) {
+ printf("command failed at offset %lld (%d)\n",
+ offset, ret);
+ return 1;
+ }
+
+ /* figure out if the entry is a directory: */
+ ret = snprintf(buf, sizeof(buf), "%s/%s", filename, dent.name);
+ if (ret >= sizeof(buf))
+ return 1;
+
+ fs_set_blk_dev(ifname, dev_part_str, fstype);
+ ret = fs_readdir(buf, 0, &dent2);
+
+ if (ret == -ENOTDIR) {
+ printf(" %8lld %s\n", dent.size, dent.name);
+ files++;
+ } else {
+ printf(" %s/\n", dent.name);
+ dirs++;
+ }
+
+ offset++;
+ }
+
+ printf("\n%d file(s), %d dir(s)\n\n", files, dirs);
+
+ return 0;
+}
+
int file_exists(const char *dev_type, const char *dev_part, const char *file,
int fstype)
{
diff --git a/include/fs.h b/include/fs.h
index 2f2aca8378..d8be5cc9a6 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -79,6 +79,27 @@ int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
loff_t *actwrite);
/*
+ * A directory entry.
+ */
+struct fs_dirent {
+ loff_t size;
+ char name[256];
+};
+
+/*
+ * fs_readdir - Read a directory.
+ *
+ * @filename: Name of file to read from
+ * @offset: The offset into the directory to read, ie. offset of N returns
+ * the N'th directory entry
+ * @dent: on success, filled in with directory entry
+ * @return 0 on success, -ENOTDIR if specified file is not a directory,
+ * or -ENOENT if offset is beyond last directory entry, or -ENXIO if
+ * operation is not supported.
+ */
+int fs_readdir(const char *filename, loff_t offset, struct fs_dirent *dent);
+
+/*
* Common implementation for various filesystem commands, optionally limited
* to a specific filesystem type via the fstype parameter.
*/
@@ -88,6 +109,8 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
int fstype);
int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
int fstype);
+int do_ls2(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+ int fstype);
int file_exists(const char *dev_type, const char *dev_part, const char *file,
int fstype);
int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
--
2.13.0
More information about the U-Boot
mailing list