fs: Add a sandbox test for the directory uclass
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>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
10
include/os.h
10
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
|
||||
*
|
||||
|
||||
37
test/dm/fs.c
37
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);
|
||||
|
||||
Reference in New Issue
Block a user