@@ -6,11 +6,72 @@
#include <abuf.h>
#include <command.h>
+#include <dm.h>
+#include <file.h>
#include <fs_legacy.h>
#include <malloc.h>
#include <mapmem.h>
+#include <vfs.h>
#include <linux/errno.h>
+#if IS_ENABLED(CONFIG_VFS)
+
+#define CAT_BUF_SIZE 0x1000
+
+static int do_cat(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct file_uc_priv *uc_priv;
+ struct udevice *fil;
+ char buf[CAT_BUF_SIZE];
+ loff_t remaining;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ ret = vfs_open_file(argv[1], DIR_O_RDONLY, &fil);
+ if (ret) {
+ printf("Error: %dE\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ uc_priv = dev_get_uclass_priv(fil);
+ remaining = uc_priv->size;
+
+ while (remaining > 0) {
+ long chunk = min((loff_t)CAT_BUF_SIZE - 1, remaining);
+ long nread;
+
+ nread = file_read(fil, buf, chunk);
+ if (nread < 0) {
+ printf("Read failed: %ldE\n", nread);
+ return CMD_RET_FAILURE;
+ }
+ if (!nread)
+ break;
+
+ buf[nread] = '\0';
+ puts(buf);
+ remaining -= nread;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_LONGHELP(cat,
+ "<path>\n"
+ " - Print the contents of a file in the VFS");
+
+U_BOOT_CMD_COMPLETE(
+ cat, 2, 1, do_cat,
+ "print file to standard output",
+ cat_help_text,
+ vfs_cmd_complete
+);
+
+#else /* !CONFIG_VFS */
+
static int do_cat(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
@@ -29,28 +90,32 @@ static int do_cat(struct cmd_tbl *cmdtp, int flag, int argc,
ret = fs_load_alloc(ifname, dev, file, 0, 0, &buf);
- // check file exists
+ /* check file exists */
switch (ret) {
case 0:
break;
case -ENOMEDIUM:
return CMD_RET_FAILURE;
case -ENOENT:
- log_err("File does not exist: ifname=%s dev=%s file=%s\n", ifname, dev, file);
+ log_err("File does not exist: ifname=%s dev=%s file=%s\n",
+ ifname, dev, file);
return CMD_RET_FAILURE;
case -E2BIG:
- log_err("File is too large: ifname=%s dev=%s file=%s\n", ifname, dev, file);
+ log_err("File is too large: ifname=%s dev=%s file=%s\n",
+ ifname, dev, file);
return CMD_RET_FAILURE;
case -ENOMEM:
- log_err("Not enough memory: ifname=%s dev=%s file=%s\n", ifname, dev, file);
+ log_err("Not enough memory: ifname=%s dev=%s file=%s\n",
+ ifname, dev, file);
return CMD_RET_FAILURE;
default:
case -EIO:
- log_err("File-read failed: ifname=%s dev=%s file=%s\n", ifname, dev, file);
+ log_err("File-read failed: ifname=%s dev=%s file=%s\n",
+ ifname, dev, file);
return CMD_RET_FAILURE;
}
- // print file content
+ /* print file content */
((char *)buf.data)[buf.size] = '\0';
puts(buf.data);
@@ -67,3 +132,4 @@ U_BOOT_CMD(cat, 4, 1, do_cat,
"Print file to standard output",
cat_help_text
);
+#endif /* CONFIG_VFS */
@@ -614,6 +614,33 @@ static int dm_test_vfs_stat(struct unit_test_state *uts)
}
DM_TEST(dm_test_vfs_stat, UTF_SCAN_FDT);
+/* Test the cat command via VFS */
+static int dm_test_vfs_cat(struct unit_test_state *uts)
+{
+ ut_assertok(vfs_init());
+
+ ut_assertok(run_command("mount hostfs /host", 0));
+ ut_assert_console_end();
+
+ /* Write a small file and cat it */
+ memcpy(map_sysmem(0x1000, 11), "hello world", 11);
+ ut_assertok(run_command("save 1000 /host/.cat_test 0xb", 0));
+ ut_assert_nextlinen("11 bytes");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("cat /host/.cat_test", 0));
+ ut_assert_nextline("hello world");
+ ut_assert_console_end();
+
+ os_unlink(".cat_test");
+
+ ut_assertok(run_command("umount /host", 0));
+ ut_assert_console_end();
+
+ return 0;
+}
+DM_TEST(dm_test_vfs_cat, UTF_SCAN_FDT);
+
/* Test save and load round-trip via VFS */
static int dm_test_vfs_save(struct unit_test_state *uts)
{
@@ -6,7 +6,8 @@
import pytest
from tests.fs_helper import FsHelper
-@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('sandbox')
+@pytest.mark.boardspec('!sandbox')
@pytest.mark.buildconfigspec('cmd_cat')
def test_cat(ubman):
""" Unit test for cat