
From: Simon Glass <sjg@chromium.org> Create a test which looks for a file and a directory in the U-Boot source tree. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/sandbox/cpu/os.c | 19 +++++++ fs/sandbox/sandboxfs.c | 112 +++++++++++++++++++++++++++++++++++++++++ include/os.h | 10 ++++ test/dm/fs.c | 37 ++++++++++++++ 4 files changed, 178 insertions(+) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index d1fda05444d..c19f859d4e0 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -747,6 +747,25 @@ int os_get_filesize(const char *fname, long long *size) return 0; } +int os_get_filetype(const char *fname) +{ + struct stat buf; + int ret; + + ret = stat(fname, &buf); + if (ret) + return -errno; + + if (buf.st_mode & S_IFREG) + return OS_FILET_REG; + if (buf.st_mode & S_IFDIR) + return OS_FILET_DIR; + if (buf.st_mode & S_IFLNK) + return OS_FILET_LNK; + + return OS_FILET_UNKNOWN; +} + void os_putc(int ch) { os_write(1, &ch, 1); diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c index 74c94528cf4..4648ac6b55e 100644 --- a/fs/sandbox/sandboxfs.c +++ b/fs/sandbox/sandboxfs.c @@ -5,6 +5,7 @@ * Copyright (c) 2012, Google Inc. */ +#include <dir.h> #include <dm.h> #include <stdio.h> #include <fs.h> @@ -13,10 +14,23 @@ #include <os.h> #include <sandboxfs.h> +/** + * struct sandbox_dir_priv - Private info about sandbox directories + * + * @head: List of directory entries, or NULL if not known + * @ptr: Current position in the list + */ +struct sandbox_dir_priv { + struct os_dirent_node *head, *ptr; +}; + /** * struct sandbox_fs_priv - Private info about the sandbox filesystem + * + * @entries: List of directory entries, or NULL if not scanned yet */ struct sandbox_fs_priv { + struct os_dirent_node *entries; }; int sandbox_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info) @@ -177,6 +191,103 @@ static int sandbox_fs_unmount(struct udevice *dev) return 0; } +static int sandbox_dir_open(struct udevice *dev, struct fs_dir_stream *strm) +{ + struct sandbox_dir_priv *priv = dev_get_priv(dev); + struct dir_uc_priv *dir_uc_priv = dev_get_uclass_priv(dev); + int ret; + + ret = os_dirent_ls(dir_uc_priv->path, &priv->head); + if (ret) { + log_err("Failed to open directory: %d\n", ret); + return ret; + } + priv->ptr = priv->head; + + return 0; +} + +int sandbox_dir_read(struct udevice *dev, struct fs_dir_stream *strm, + struct fs_dirent *dent) +{ + struct sandbox_dir_priv *dir_priv = dev_get_priv(dev); + struct os_dirent_node *ptr = dir_priv->ptr; + + if (!ptr) + return log_msg_ret("sdr", -ENOENT); + + if (ptr->type == OS_FILET_REG) + dent->type = FS_DT_REG; + else if (ptr->type == OS_FILET_DIR) + dent->type = FS_DT_DIR; + else if (ptr->type == OS_FILET_LNK) + dent->type = FS_DT_LNK; + dent->size = ptr->size; + strlcpy(dent->name, ptr->name, FS_DIRENT_NAME_LEN); + dir_priv->ptr = ptr->next; + + return 0; +} + +static int sandbox_dir_close(struct udevice *dev, struct fs_dir_stream *strm) +{ + struct sandbox_dir_priv *dir_priv = dev_get_priv(dev); + + log_debug("close\n"); + os_dirent_free(dir_priv->head); + dir_priv->ptr = NULL; + + log_debug("close done\n"); + + return 0; +} + +static struct dir_ops sandbox_dir_ops = { + .open = sandbox_dir_open, + .read = sandbox_dir_read, + .close = sandbox_dir_close, +}; + +static const struct udevice_id dir_ids[] = { + { .compatible = "virtio-fs,directory" }, + { } +}; + +U_BOOT_DRIVER(sandbox_dir) = { + .name = "sandbox_dir", + .id = UCLASS_DIR, + .of_match = dir_ids, + .ops = &sandbox_dir_ops, + .priv_auto = sizeof(struct sandbox_dir_priv), + .flags = DM_FLAG_ACTIVE_DMA, +}; + +static int sandbox_fs_lookup_dir(struct udevice *dev, const char *path, + struct udevice **dirp) +{ + struct udevice *dir; + int ftype; + int ret; + + ftype = os_get_filetype(path ?: "/"); + if (ftype < 0) + return ftype; + if (ftype != OS_FILET_DIR) + return log_msg_ret("sld", -ENOTDIR); + + log_debug("looking up path '%s'\n", path); + + ret = dir_add_probe(dev, DM_DRIVER_GET(sandbox_dir), path, &dir); + if (ret) + return log_msg_ret("slD", ret); + + log_debug("added new dir '%s'\n", path); + + *dirp = dir; + + return 0; +} + static int sandbox_fs_remove(struct udevice *dev) { return 0; @@ -185,6 +296,7 @@ static int sandbox_fs_remove(struct udevice *dev) static const struct fs_ops sandbox_fs_ops = { .mount = sandbox_fs_mount, .unmount = sandbox_fs_unmount, + .lookup_dir = sandbox_fs_lookup_dir, }; static const struct udevice_id sandbox_fs_ids[] = { diff --git a/include/os.h b/include/os.h index f4f2667d206..35757fc8bb8 100644 --- a/include/os.h +++ b/include/os.h @@ -319,6 +319,16 @@ const char *os_dirent_get_typename(enum os_dirent_t type); */ int os_get_filesize(const char *fname, long long *size); +/** + * os_get_filetype() - get the type of a file + * + * @fname: Filename to check + * Return: -ve error code if the file does not exist, OS_FILET_REG for a regular + * file, OS_FILET_DIR for a directory, OS_FILET_LNK for a link, or + * OS_FILET_UNKNOWN for some other type of file + */ +int os_get_filetype(const char *fname); + /** * os_putc() - write a character to the controlling OS terminal * diff --git a/test/dm/fs.c b/test/dm/fs.c index d82d2250c59..6e198c8a541 100644 --- a/test/dm/fs.c +++ b/test/dm/fs.c @@ -5,6 +5,7 @@ * Copyright 2025 Simon Glass <sjg@chromium.org> */ +#include <dir.h> #include <dm.h> #include <fs.h> #include <dm/test.h> @@ -26,3 +27,39 @@ static int dm_test_fs_base(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_fs_base, UTF_SCAN_FDT); + +/* Test accessing a directory */ +static int dm_test_fs_dir(struct unit_test_state *uts) +{ + struct udevice *fsdev, *dir; + struct fs_dir_stream *strm; + struct fs_dirent dent; + int found; + + ut_assertok(uclass_first_device_err(UCLASS_FS, &fsdev)); + + ut_assertok(fs_mount(fsdev)); + + ut_assertok(fs_lookup_dir(fsdev, ".", &dir)); + ut_assertnonnull(dir); + ut_asserteq_str("fs.dir", dir->name); + + ut_assertok(dir_open(dir, &strm)); + found = 0; + do { + ut_assertok(dir_read(dir, strm, &dent)); + if (!strcmp("README", dent.name)) { + ut_asserteq(FS_DT_REG, dent.type); + found += 1; + } else if (!strcmp("common", dent.name)) { + ut_asserteq(FS_DT_DIR, dent.type); + found += 1; + } + } while (found < 2); + ut_assertok(dir_close(dir, strm)); + + ut_assertok(fs_unmount(fsdev)); + + return 0; +} +DM_TEST(dm_test_fs_dir, UTF_SCAN_FDT); -- 2.43.0