[U-Boot] [PATCH v2 4/8] fs: add fs_readdir()
Łukasz Majewski
lukma at denx.de
Sun Sep 3 15:16:07 UTC 2017
On 09/02/2017 06:37 PM, Rob Clark wrote:
> 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.
>
Reviewed-by: Łukasz Majewski <lukma at denx.de>
> Signed-off-by: Rob Clark <robdclark at gmail.com>
> ---
> disk/part.c | 31 ++++++++++++--------
> fs/fs.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/fs.h | 55 +++++++++++++++++++++++++++++++++++
> include/part.h | 4 +++
> 4 files changed, 169 insertions(+), 12 deletions(-)
>
> diff --git a/disk/part.c b/disk/part.c
> index c67fdacc79..aa9183d696 100644
> --- a/disk/part.c
> +++ b/disk/part.c
> @@ -331,6 +331,24 @@ int part_get_info(struct blk_desc *dev_desc, int part,
> return -1;
> }
>
> +int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info)
> +{
> + info->start = 0;
> + info->size = dev_desc->lba;
> + info->blksz = dev_desc->blksz;
> + info->bootable = 0;
> + strcpy((char *)info->type, BOOT_PART_TYPE);
> + strcpy((char *)info->name, "Whole Disk");
> +#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
> + info->uuid[0] = 0;
> +#endif
> +#ifdef CONFIG_PARTITION_TYPE_GUID
> + info->type_guid[0] = 0;
> +#endif
> +
> + return 0;
> +}
> +
> int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
> struct blk_desc **dev_desc)
> {
> @@ -523,18 +541,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
>
> (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz);
>
> - info->start = 0;
> - info->size = (*dev_desc)->lba;
> - info->blksz = (*dev_desc)->blksz;
> - info->bootable = 0;
> - strcpy((char *)info->type, BOOT_PART_TYPE);
> - strcpy((char *)info->name, "Whole Disk");
> -#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
> - info->uuid[0] = 0;
> -#endif
> -#ifdef CONFIG_PARTITION_TYPE_GUID
> - info->type_guid[0] = 0;
> -#endif
> + part_get_info_whole_disk(*dev_desc, info);
>
> ret = 0;
> goto cleanup;
> diff --git a/fs/fs.c b/fs/fs.c
> index 13cd3626c6..441c880654 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,31 @@ 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;
> +
> + if (part >= 1)
> + ret = part_get_info(desc, part, &fs_partition);
> + else
> + ret = part_get_info_whole_disk(desc, &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 +373,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.
> diff --git a/include/part.h b/include/part.h
> index 0cd803a933..48e8ff6d8a 100644
> --- a/include/part.h
> +++ b/include/part.h
> @@ -98,6 +98,7 @@ int host_get_dev_err(int dev, struct blk_desc **blk_devp);
>
> /* disk/part.c */
> int part_get_info(struct blk_desc *dev_desc, int part, disk_partition_t *info);
> +int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info);
> void part_print(struct blk_desc *dev_desc);
> void part_init(struct blk_desc *dev_desc);
> void dev_print(struct blk_desc *dev_desc);
> @@ -203,6 +204,9 @@ static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }
>
> static inline int part_get_info(struct blk_desc *dev_desc, int part,
> disk_partition_t *info) { return -1; }
> +static inline int part_get_info_whole_disk(struct blk_desc *dev_desc,
> + disk_partition_t *info)
> +{ return -1; }
> static inline void part_print(struct blk_desc *dev_desc) {}
> static inline void part_init(struct blk_desc *dev_desc) {}
> static inline void dev_print(struct blk_desc *dev_desc) {}
>
--
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
More information about the U-Boot
mailing list