From: Rob Clark <robdclark@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 4/8] fs: add fs_readdir()
Date: Sun, 13 Aug 2017 06:45:24 -0400 [thread overview]
Message-ID: <20170813104531.16407-5-robdclark@gmail.com> (raw)
In-Reply-To: <20170813104531.16407-1-robdclark@gmail.com>
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.
Modelled after POSIX opendir()/readdir()/closedir(). Unlike the other
fs APIs, this is stateful (ie. state is held in the FS_DIR "directory
stream"), to avoid re-traversing of the directory structure at each
step. The directory stream must be released with closedir() when it
is no longer needed.
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
fs/fs.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/fs.h | 55 +++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+)
diff --git a/fs/fs.c b/fs/fs.c
index 595ff1fe69..f9ea3480e9 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -21,6 +21,7 @@
DECLARE_GLOBAL_DATA_PTR;
static struct blk_desc *fs_dev_desc;
+static int fs_dev_part;
static disk_partition_t fs_partition;
static int fs_type = FS_TYPE_ANY;
@@ -69,6 +70,11 @@ static inline int fs_uuid_unsupported(char *uuid_str)
return -1;
}
+static inline int fs_opendir_unsupported(const char *filename, FS_DIR **dirp)
+{
+ return -EACCES;
+}
+
struct fstype_info {
int fstype;
char *name;
@@ -92,6 +98,9 @@ struct fstype_info {
loff_t len, loff_t *actwrite);
void (*close)(void);
int (*uuid)(char *uuid_str);
+ int (*opendir)(const char *filename, FS_DIR **dirp);
+ int (*readdir)(FS_DIR *dirp);
+ void (*closedir)(FS_DIR *dirp);
};
static struct fstype_info fstypes[] = {
@@ -112,6 +121,7 @@ static struct fstype_info fstypes[] = {
.write = fs_write_unsupported,
#endif
.uuid = fs_uuid_unsupported,
+ .opendir = fs_opendir_unsupported,
},
#endif
#ifdef CONFIG_FS_EXT4
@@ -131,6 +141,7 @@ static struct fstype_info fstypes[] = {
.write = fs_write_unsupported,
#endif
.uuid = ext4fs_uuid,
+ .opendir = fs_opendir_unsupported,
},
#endif
#ifdef CONFIG_SANDBOX
@@ -146,6 +157,7 @@ static struct fstype_info fstypes[] = {
.read = fs_read_sandbox,
.write = fs_write_sandbox,
.uuid = fs_uuid_unsupported,
+ .opendir = fs_opendir_unsupported,
},
#endif
#ifdef CONFIG_CMD_UBIFS
@@ -161,6 +173,7 @@ static struct fstype_info fstypes[] = {
.read = ubifs_read,
.write = fs_write_unsupported,
.uuid = fs_uuid_unsupported,
+ .opendir = fs_opendir_unsupported,
},
#endif
{
@@ -175,6 +188,7 @@ static struct fstype_info fstypes[] = {
.read = fs_read_unsupported,
.write = fs_write_unsupported,
.uuid = fs_uuid_unsupported,
+ .opendir = fs_opendir_unsupported,
},
};
@@ -228,6 +242,28 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
if (!info->probe(fs_dev_desc, &fs_partition)) {
fs_type = info->fstype;
+ fs_dev_part = part;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* set current blk device w/ blk_desc + partition # */
+int fs_set_blk_dev2(struct blk_desc *desc, int part)
+{
+ struct fstype_info *info;
+ int ret, i;
+
+ ret = part_get_info(desc, part, &fs_partition);
+ if (ret)
+ return ret;
+ fs_dev_desc = desc;
+
+ for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
+ if (!info->probe(fs_dev_desc, &fs_partition)) {
+ fs_type = info->fstype;
return 0;
}
}
@@ -334,6 +370,58 @@ int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
return ret;
}
+FS_DIR *fs_opendir(const char *filename)
+{
+ struct fstype_info *info = fs_get_info(fs_type);
+ FS_DIR *dirp = NULL;
+ int ret;
+
+ ret = info->opendir(filename, &dirp);
+ fs_close();
+ if (ret) {
+ errno = -ret;
+ return NULL;
+ }
+
+ dirp->desc = fs_dev_desc;
+ dirp->part = fs_dev_part;
+
+ return dirp;
+}
+
+struct fs_dirent *fs_readdir(FS_DIR *dirp)
+{
+ struct fstype_info *info;
+ int ret;
+
+ fs_set_blk_dev2(dirp->desc, dirp->part);
+ info = fs_get_info(fs_type);
+
+ memset(&dirp->dirent, 0, sizeof(dirp->dirent));
+
+ ret = info->readdir(dirp);
+ fs_close();
+ if (ret)
+ return NULL;
+
+ return &dirp->dirent;;
+}
+
+void fs_closedir(FS_DIR *dirp)
+{
+ struct fstype_info *info;
+
+ if (!dirp)
+ return;
+
+ fs_set_blk_dev2(dirp->desc, dirp->part);
+ info = fs_get_info(fs_type);
+
+ info->closedir(dirp);
+ fs_close();
+}
+
+
int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
int fstype)
{
diff --git a/include/fs.h b/include/fs.h
index 2f2aca8378..0a6a366078 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -26,6 +26,8 @@
*/
int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype);
+int fs_set_blk_dev2(struct blk_desc *desc, int part);
+
/*
* Print the list of files on the partition previously set by fs_set_blk_dev(),
* in directory "dirname".
@@ -78,6 +80,59 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len,
loff_t *actwrite);
+/* Add additional FS_DT_* as supported by additional filesystems:*/
+#define FS_DT_DIR 0x4 /* directory */
+#define FS_DT_REG 0x8 /* regular file */
+
+/*
+ * A directory entry.
+ */
+struct fs_dirent {
+ unsigned type; /* one of FS_DT_* */
+ loff_t size;
+ char name[256];
+};
+
+typedef struct _FS_DIR FS_DIR;
+
+/*
+ * fs_opendir - Open a directory
+ *
+ * @filename: the path to directory to open
+ * @return a pointer to the directory stream or NULL on error and errno
+ * set appropriately
+ */
+FS_DIR *fs_opendir(const char *filename);
+
+/*
+ * fs_readdir - Read the next directory entry in the directory stream.
+ *
+ * @dirp: the directory stream
+ * @return the next directory entry (only valid until next fs_readdir() or
+ * fs_closedir() call, do not attempt to free()) or NULL if the end of
+ * the directory is reached.
+ */
+struct fs_dirent *fs_readdir(FS_DIR *dirp);
+
+/*
+ * fs_closedir - close a directory stream
+ *
+ * @dirp: the directory stream
+ */
+void fs_closedir(FS_DIR *dirp);
+
+/*
+ * private to fs implementations, would be in fs.c but we need to let
+ * implementations subclass:
+ */
+
+struct _FS_DIR {
+ struct fs_dirent dirent;
+ /* private to fs layer: */
+ struct blk_desc *desc;
+ int part;
+};
+
/*
* Common implementation for various filesystem commands, optionally limited
* to a specific filesystem type via the fstype parameter.
--
2.13.0
next prev parent reply other threads:[~2017-08-13 10:45 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-13 10:45 [U-Boot] [PATCH 0/8] fs/fat: cleanups + readdir implementation Rob Clark
2017-08-13 10:45 ` [U-Boot] [PATCH 1/8] fs/fat: split out helper to init fsdata Rob Clark
2017-08-13 10:45 ` [U-Boot] [PATCH 2/8] fs/fat: introduce new director iterators Rob Clark
2017-08-13 10:45 ` [U-Boot] [PATCH 3/8] fat/fs: convert to directory iterators Rob Clark
2017-08-13 10:45 ` Rob Clark [this message]
2017-08-13 10:45 ` [U-Boot] [PATCH 5/8] fs/fat: implement opendir/readdir/closedir Rob Clark
2017-08-13 10:45 ` [U-Boot] [PATCH 6/8] fat/fs: remove a bunch of dead code Rob Clark
2017-08-13 11:11 ` Stefan Bruens
2017-08-13 10:45 ` [U-Boot] [PATCH 7/8] fat/fs: move ls to generic implementation Rob Clark
2017-08-13 10:45 ` [U-Boot] [PATCH 8/8] fs/fat: fix case for FAT shortnames Rob Clark
2017-08-13 11:25 ` Stefan Bruens
2017-08-13 12:14 ` Rob Clark
2017-08-13 18:09 ` [U-Boot] [PATCH v2 " Rob Clark
2017-08-13 11:28 ` [U-Boot] [PATCH 0/8] fs/fat: cleanups + readdir implementation Heinrich Schuchardt
2017-08-13 12:13 ` Rob Clark
2017-08-13 21:13 ` Tom Rini
2017-08-13 21:50 ` Rob Clark
2017-08-13 21:59 ` Tom Rini
2017-08-14 12:48 ` Rob Clark
2017-08-14 13:05 ` Tom Rini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170813104531.16407-5-robdclark@gmail.com \
--to=robdclark@gmail.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.