All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roger Knecht <rknecht@pm.me>
To: u-boot@lists.denx.de
Cc: Tom Rini <trini@konsulko.com>, Simon Glass <sjg@chromium.org>,
	Heinrich Schuchardt <xypron.glpk@gmx.de>,
	Roger Knecht <rknecht@pm.me>
Subject: [PATCH v6] cmd: cat: add new command
Date: Sat, 03 Sep 2022 11:34:53 +0000	[thread overview]
Message-ID: <20220903113413.411-1-rknecht@pm.me> (raw)

Add cat command to print file content to standard out

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Roger Knecht <rknecht@pm.me>
---
v6:
 - Fix pylint error "Undefined variable CalledProcessError"
 - Fix htmldoc error "cat.rst: document isn't included in any toctree"

v5:
 - Removed "default n" from Kconfig
 - Renamed 'buffer_sysmem_addr' in 'addr'
 - Use yield instead of return in conftest.py
 - Catch 'CalledProcessError' in conftest.py
 - Clean up files after test execution
 - Use u_boot_console.run_command_list() instead of u_boot_console.run_command()
 - Removed unnecessary unmap_sysmem() call
 - Added Reviewed-by Simon

v4:
 - Return only values from enum command_ret_t in do_cat()
 - Use calloc() instead of malloc() for zero initialized memory
 - Make use of CONFIG_SYS_LONGHELP
 - Improved error messages

v3:
 - Disable 'cat' by default (CONFIG_CMD_CAT=n)
 - Enable 'cat' in sandbox and sandbox64 defconfig
 - Use map_to_sysmem() to fix "phys_to_virt: Cannot map sandbox address"
 - Use puts() instead of a loop
 - Added python test
 - Added usage documentation

v2:
 - Moved cat from boot to shell commands
 - Added MAINTAINERS entry
 - Added comments
 - Improved variable naming

 MAINTAINERS                        |  5 ++
 cmd/Kconfig                        |  5 ++
 cmd/Makefile                       |  1 +
 cmd/cat.c                          | 85 ++++++++++++++++++++++++++++++
 configs/sandbox64_defconfig        |  1 +
 configs/sandbox_defconfig          |  1 +
 doc/usage/cmd/cat.rst              | 49 +++++++++++++++++
 doc/usage/index.rst                |  1 +
 test/py/tests/test_cat/conftest.py | 35 ++++++++++++
 test/py/tests/test_cat/test_cat.py | 20 +++++++
 10 files changed, 203 insertions(+)
 create mode 100644 cmd/cat.c
 create mode 100644 doc/usage/cmd/cat.rst
 create mode 100644 test/py/tests/test_cat/conftest.py
 create mode 100644 test/py/tests/test_cat/test_cat.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 36a2b69fcb..25688f2e13 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -765,6 +765,11 @@ M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
 F:	tools/buildman/

+CAT
+M:	Roger Knecht <rknecht@pm.me>
+S:	Maintained
+F:	cmd/cat.c
+
 CFI FLASH
 M:	Stefan Roese <sr@denx.de>
 S:	Maintained
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 8ea064b8d2..8341321f38 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1531,6 +1531,11 @@ endmenu

 menu "Shell scripting commands"

+config CMD_CAT
+	bool "cat"
+	help
+	  Print file to standard output
+
 config CMD_ECHO
 	bool "echo"
 	default y
diff --git a/cmd/Makefile b/cmd/Makefile
index 6e87522b62..1d2590e958 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_CMD_BOOTZ) += bootz.o
 obj-$(CONFIG_CMD_BOOTI) += booti.o
 obj-$(CONFIG_CMD_BTRFS) += btrfs.o
 obj-$(CONFIG_CMD_BUTTON) += button.o
+obj-$(CONFIG_CMD_CAT) += cat.o
 obj-$(CONFIG_CMD_CACHE) += cache.o
 obj-$(CONFIG_CMD_CBFS) += cbfs.o
 obj-$(CONFIG_CMD_CLK) += clk.o
diff --git a/cmd/cat.c b/cmd/cat.c
new file mode 100644
index 0000000000..1273a26b14
--- /dev/null
+++ b/cmd/cat.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022
+ * Roger Knecht <rknecht@pm.de>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <malloc.h>
+#include <mapmem.h>
+
+static int do_cat(struct cmd_tbl *cmdtp, int flag, int argc,
+		  char *const argv[])
+{
+	char *ifname;
+	char *dev;
+	char *file;
+	char *buffer;
+	phys_addr_t addr;
+	loff_t file_size;
+
+	if (argc < 4)
+		return CMD_RET_USAGE;
+
+	ifname = argv[1];
+	dev = argv[2];
+	file = argv[3];
+
+	// check file exists
+	if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY))
+		return CMD_RET_FAILURE;
+
+	if (!fs_exists(file)) {
+		log_err("File does not exist: ifname=%s dev=%s file=%s\n", ifname, dev, file);
+		return CMD_RET_FAILURE;
+	}
+
+	// get file size
+	if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY))
+		return CMD_RET_FAILURE;
+
+	if (fs_size(file, &file_size)) {
+		log_err("Cannot read file size: ifname=%s dev=%s file=%s\n", ifname, dev, file);
+		return CMD_RET_FAILURE;
+	}
+
+	// allocate memory for file content
+	buffer = calloc(sizeof(char), file_size + 1);
+	if (!buffer) {
+		log_err("Out of memory\n");
+		return CMD_RET_FAILURE;
+	}
+
+	// map pointer to system memory
+	addr = map_to_sysmem(buffer);
+
+	// read file to memory
+	if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY))
+		return CMD_RET_FAILURE;
+
+	if (fs_read(file, addr, 0, 0, &file_size)) {
+		log_err("Cannot read file: ifname=%s dev=%s file=%s\n", ifname, dev, file);
+		return CMD_RET_FAILURE;
+	}
+
+	// print file content
+	buffer[file_size] = '\0';
+	puts(buffer);
+
+	free(buffer);
+
+	return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char cat_help_text[] =
+	"<interface> <dev[:part]> <file>\n"
+	"  - Print file from 'dev' on 'interface' to standard output\n";
+#endif
+
+U_BOOT_CMD(cat, 4, 1, do_cat,
+	   "Print file to standard output",
+	   cat_help_text
+);
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 290d1506c2..cdf9745ed9 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -22,6 +22,7 @@ CONFIG_CONSOLE_RECORD=y
 CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
 CONFIG_PRE_CONSOLE_BUFFER=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_CMD_CAT=y
 CONFIG_CMD_CPU=y
 CONFIG_CMD_LICENSE=y
 CONFIG_CMD_BOOTZ=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index ab5d3f19bf..519b40a7c6 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -36,6 +36,7 @@ CONFIG_LOG_DEFAULT_LEVEL=6
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_STACKPROTECTOR=y
 CONFIG_ANDROID_AB=y
+CONFIG_CMD_CAT=y
 CONFIG_CMD_CPU=y
 CONFIG_CMD_LICENSE=y
 CONFIG_CMD_BOOTM_PRE_LOAD=y
diff --git a/doc/usage/cmd/cat.rst b/doc/usage/cmd/cat.rst
new file mode 100644
index 0000000000..5ef4731fe3
--- /dev/null
+++ b/doc/usage/cmd/cat.rst
@@ -0,0 +1,49 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+cat command
+===============
+
+Synopsis
+--------
+
+::
+
+    cat <interface> <dev[:part]> <file>
+
+Description
+-----------
+
+The cat command prints the file content to standard out.
+
+interface
+    interface for accessing the block device (mmc, sata, scsi, usb, ....)
+
+dev
+    device number
+
+part
+    partition number, defaults to 1
+
+file
+    path to file
+
+Example
+-------
+
+Here is the output for a example text file:
+
+::
+
+    => cat mmc 0:1 hello
+    hello world
+    =>
+
+Configuration
+-------------
+
+The cat command is only available if CONFIG_CMD_CAT=y.
+
+Return value
+------------
+
+The return value $? is set to 0 (true) if the file is readable, otherwise it returns a non-zero error code.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 28f9683a3e..4c2d56bae6 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -31,6 +31,7 @@ Shell commands
    cmd/bootmeth
    cmd/button
    cmd/bootz
+   cmd/cat
    cmd/cbsysinfo
    cmd/conitrace
    cmd/dm
diff --git a/test/py/tests/test_cat/conftest.py b/test/py/tests/test_cat/conftest.py
new file mode 100644
index 0000000000..058fe52352
--- /dev/null
+++ b/test/py/tests/test_cat/conftest.py
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier:      GPL-2.0+
+
+"""Fixture for cat command test
+"""
+
+import os
+import shutil
+from subprocess import check_call, CalledProcessError
+import pytest
+
+@pytest.fixture(scope='session')
+def cat_data(u_boot_config):
+    """Set up a file system to be used in cat tests
+
+    Args:
+        u_boot_config -- U-boot configuration.
+    """
+    mnt_point = u_boot_config.persistent_data_dir + '/test_cat'
+    image_path = u_boot_config.persistent_data_dir + '/cat.img'
+
+    try:
+        os.mkdir(mnt_point, mode = 0o755)
+
+        with open(mnt_point + '/hello', 'w', encoding = 'ascii') as file:
+            file.write('hello world\n')
+
+        check_call(f'virt-make-fs --partition=gpt --size=+1M --type=vfat {mnt_point} {image_path}',
+                   shell=True)
+
+        yield image_path
+    except CalledProcessError:
+        pytest.skip('Setup failed')
+    finally:
+        shutil.rmtree(mnt_point)
+        os.remove(image_path)
diff --git a/test/py/tests/test_cat/test_cat.py b/test/py/tests/test_cat/test_cat.py
new file mode 100644
index 0000000000..132527bd4c
--- /dev/null
+++ b/test/py/tests/test_cat/test_cat.py
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier:      GPL-2.0+
+
+""" Unit test for cat command
+"""
+
+import pytest
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_cat')
+def test_cat(u_boot_console, cat_data):
+    """ Unit test for cat
+
+    Args:
+        u_boot_console -- U-Boot console
+        cat_data -- Path to the disk image used for testing.
+    """
+    response = u_boot_console.run_command_list([
+        f'host bind 0 {cat_data}',
+        'cat host 0 hello'])
+    assert 'hello world' in response
--
2.25.1



             reply	other threads:[~2022-09-03 11:35 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-03 11:34 Roger Knecht [this message]
2022-10-11 21:36 ` [PATCH v6] cmd: cat: add new command Tom Rini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220903113413.411-1-rknecht@pm.me \
    --to=rknecht@pm.me \
    --cc=sjg@chromium.org \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    --cc=xypron.glpk@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.