
From: Simon Glass <sjg@chromium.org> Create a test which looks for a file reads from it. Signed-off-by: Simon Glass <sjg@chromium.org> --- fs/sandbox/sandboxfs.c | 100 ++++++++++++++++++++++++++++++++++++++++- test/dm/fs.c | 41 +++++++++++++++++ 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c index 4648ac6b55e..3d624ab5f7f 100644 --- a/fs/sandbox/sandboxfs.c +++ b/fs/sandbox/sandboxfs.c @@ -7,7 +7,7 @@ #include <dir.h> #include <dm.h> -#include <stdio.h> +#include <file.h> #include <fs.h> #include <fs_legacy.h> #include <malloc.h> @@ -24,6 +24,15 @@ struct sandbox_dir_priv { struct os_dirent_node *head, *ptr; }; +/** + * struct sandbox_dir_priv - Private info about sandbox directories + * + * @fd: File descriptor for the file + */ +struct file_priv { + int fd; +}; + /** * struct sandbox_fs_priv - Private info about the sandbox filesystem * @@ -242,10 +251,99 @@ static int sandbox_dir_close(struct udevice *dev, struct fs_dir_stream *strm) return 0; } +static ssize_t sandbox_read_iter(struct udevice *dev, struct iov_iter *iter, + loff_t pos) +{ + struct file_priv *priv = dev_get_priv(dev); + ssize_t ret; + + log_debug("start dev '%s' len %lx\n", dev->name, iter->count); + ret = os_lseek(priv->fd, pos, OS_SEEK_SET); + if (ret < 0) + return log_msg_ret("vfs", ret); + + ret = os_read(priv->fd, iter_iov_ptr(iter), iter_iov_avail(iter)); + if (ret < 0) + return log_msg_ret("vfr", ret); + iter_advance(iter, ret); + log_debug("read %lx bytes\n", ret); + + return ret; +} + +static struct file_ops sandbox_file_ops = { + .read_iter = sandbox_read_iter, +}; + +static const struct udevice_id file_ids[] = { + { .compatible = "virtio-fs,file" }, + { } +}; + +U_BOOT_DRIVER(sandbox_file) = { + .name = "sandbox_file", + .id = UCLASS_FILE, + .of_match = file_ids, + .ops = &sandbox_file_ops, + .priv_auto = sizeof(struct file_priv), + .flags = DM_FLAG_ACTIVE_DMA, +}; + +static int sandbox_dir_open_file(struct udevice *dir, const char *leaf, + enum dir_open_flags_t oflags, + struct udevice **filp) +{ + struct dir_uc_priv *uc_priv = dev_get_uclass_priv(dir); + char pathname[FILE_MAX_PATH_LEN]; + struct file_priv *priv; + int mode, fd, ftype, ret; + struct udevice *dev; + off_t size; + + snprintf(pathname, sizeof(pathname), "%s/%s", uc_priv->path, leaf); + ftype = os_get_filetype(pathname); + if (ftype < 0) + return log_msg_ret("soF", ftype); + if (ftype != OS_FILET_REG) + return log_msg_ret("sOf", -EINVAL); + + if (oflags == DIR_O_RDONLY) + mode = OS_O_RDONLY; + else if (oflags == DIR_O_WRONLY) + mode = OS_O_WRONLY | OS_O_CREAT; + else if (oflags == DIR_O_RDWR) + mode = OS_O_RDWR; + else + return log_msg_ret("som", -EINVAL); + + ret = os_open(pathname, mode); + if (ret < 0) + return log_msg_ret("sOm", ret); + fd = ret; + + size = os_filesize(fd); + if (size < 0) + return log_msg_ret("sos", ret); + + ret = file_add_probe(dir, DM_DRIVER_GET(sandbox_file), leaf, size, + oflags, &dev); + if (ret) { + os_close(fd); + return log_msg_ret("sof", ret); + } + + priv = dev_get_priv(dev); + priv->fd = fd; + *filp = dev; + + return 0; +} + static struct dir_ops sandbox_dir_ops = { .open = sandbox_dir_open, .read = sandbox_dir_read, .close = sandbox_dir_close, + .open_file = sandbox_dir_open_file, }; static const struct udevice_id dir_ids[] = { diff --git a/test/dm/fs.c b/test/dm/fs.c index 6e198c8a541..e94b7854184 100644 --- a/test/dm/fs.c +++ b/test/dm/fs.c @@ -7,10 +7,13 @@ #include <dir.h> #include <dm.h> +#include <file.h> #include <fs.h> #include <dm/test.h> #include <test/ut.h> +#define READ_SIZE 0x20 + /* Test basic filesystem access */ static int dm_test_fs_base(struct unit_test_state *uts) { @@ -40,6 +43,7 @@ static int dm_test_fs_dir(struct unit_test_state *uts) ut_assertok(fs_mount(fsdev)); + ut_asserteq(-ENOENT, fs_lookup_dir(fsdev, "does-not-exit", &dir)); ut_assertok(fs_lookup_dir(fsdev, ".", &dir)); ut_assertnonnull(dir); ut_asserteq_str("fs.dir", dir->name); @@ -63,3 +67,40 @@ static int dm_test_fs_dir(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_fs_dir, UTF_SCAN_FDT); + +/* Test reading a file */ +static int dm_test_fs_file(struct unit_test_state *uts) +{ + struct udevice *fsdev, *dir, *fil; + struct file_uc_priv *uc_priv; + char buf[READ_SIZE + 1]; + + 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); + + /* check the start and end of the README, which perhaps won't change */ + ut_assertok(dir_open_file(dir, "README", DIR_O_RDONLY, &fil)); + ut_assertnonnull(fil); + ut_asserteq_str("fs.dir.file.1", fil->name); + uc_priv = dev_get_uclass_priv(fil); + ut_asserteq_str("README", uc_priv->leaf); + ut_asserteq(0, uc_priv->pos); + ut_assert(uc_priv->size > 0x10000); + + buf[READ_SIZE] = '\0'; + ut_asserteq(READ_SIZE, file_read(fil, buf, READ_SIZE)); + ut_asserteq_str("# SPDX-License-Identifier: GPL-2", buf); + ut_asserteq(0x20, uc_priv->pos); + + ut_asserteq(READ_SIZE, file_read_at(fil, buf, uc_priv->size - 0x20, 0)); + ut_asserteq_str("d the patch submission process.\n", buf); + ut_asserteq(uc_priv->size, uc_priv->pos); + + return 0; +} +DM_TEST(dm_test_fs_file, UTF_SCAN_FDT); -- 2.43.0