EFI loader support will need to map barebox VFS paths to fs_device and
back. Make development easier by providing a findmnt command to test
the mapping.

Signed-off-by: Ahmad Fatoum <a.fat...@pengutronix.de>
---
 commands/Kconfig   |  15 +++++++
 commands/Makefile  |   1 +
 commands/findmnt.c | 108 +++++++++++++++++++++++++++++++++++++++++++++
 fs/fs.c            |   4 +-
 include/driver.h   |   5 +++
 include/fs.h       |   2 +
 6 files changed, 132 insertions(+), 3 deletions(-)
 create mode 100644 commands/findmnt.c

diff --git a/commands/Kconfig b/commands/Kconfig
index d27c20478fcf..cd2eab801a84 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -655,6 +655,21 @@ config CMD_MOUNT
                  -o OPTIONS    set file system OPTIONS
                  -v            verbose
 
+config CMD_FINDMNT
+       tristate
+       prompt "findmnt"
+       help
+         Find a file system
+
+         Usage: findmnt [ DEVICE | -T FILE ]
+
+         findmnt will list all mounted filesystems or search
+         for a filesystem when given the mountpoint or the
+         source device as an argument
+
+         Options:
+               -T              mount target file path
+
 config CMD_UBI
        tristate
        default y if MTD_UBI
diff --git a/commands/Makefile b/commands/Makefile
index c8cb21a7db88..81bf5651ddc2 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_CMD_RM)          += rm.o
 obj-$(CONFIG_CMD_CAT)          += cat.o
 obj-$(CONFIG_CMD_MOUNT)                += mount.o
 obj-$(CONFIG_CMD_UMOUNT)       += umount.o
+obj-$(CONFIG_CMD_FINDMNT)      += findmnt.o
 obj-$(CONFIG_CMD_REGINFO)      += reginfo.o
 obj-$(CONFIG_CMD_CRC)          += crc.o
 obj-$(CONFIG_CMD_CLEAR)                += clear.o
diff --git a/commands/findmnt.c b/commands/findmnt.c
new file mode 100644
index 000000000000..da8f58835f28
--- /dev/null
+++ b/commands/findmnt.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2022 Ahmad Fatoum, Pengutronix
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <errno.h>
+#include <getopt.h>
+
+static void print_header(bool *header_printed)
+{
+       if (*header_printed)
+               return;
+       printf("%-20s%-25s%-10s%-20s\n", "TARGET", "SOURCE", "FSTYPE", 
"OPTIONS");
+       *header_printed = true;
+}
+
+static void report_findmnt(const struct fs_device *fsdev)
+{
+       const char *backingstore;
+
+       backingstore = fsdev->backingstore ?: cdev_name(fsdev->cdev) ?: "none";
+
+       printf("%-20s%-25s%-10s%-20s\n", fsdev->path, backingstore,
+              fsdev->driver->drv.name, fsdev->options);
+}
+
+static int do_findmnt(int argc, char *argv[])
+{
+       bool header_printed = false;
+       struct fs_device *target = NULL;
+       char *device = NULL;
+       int opt, dirfd = AT_FDCWD;
+
+       while ((opt = getopt(argc, argv, "T:")) > 0) {
+               switch(opt) {
+               case 'T':
+                       target = get_fsdevice_by_path(dirfd, optarg);
+                       if (!target)
+                               return COMMAND_ERROR;
+                       break;
+               default:
+                       return COMMAND_ERROR_USAGE;
+               }
+       }
+
+       argv += optind;
+       argc -= optind;
+
+       if ((target && argc > 0) || (!target && argc > 1))
+               return COMMAND_ERROR_USAGE;
+
+       if (target) {
+               print_header(&header_printed);
+               report_findmnt(target);
+               return 0;
+       }
+
+       if (argv[0]) {
+               device = canonicalize_path(dirfd, argv[0]);
+               if (!device)
+                       return COMMAND_ERROR;
+       }
+
+       for_each_fs_device(target) {
+               if (!device || streq_ptr(target->path, device) ||
+                   streq_ptr(target->backingstore, device)) {
+                       print_header(&header_printed);
+                       report_findmnt(target);
+               } else {
+                       const char *backingstore;
+                       struct cdev *cdev;
+
+                       cdev = cdev_by_name(devpath_to_name(device));
+                       if (!cdev)
+                               continue;
+
+                       backingstore = target->backingstore;
+                       backingstore += str_has_prefix(backingstore, "/dev/");
+
+                       if (streq_ptr(backingstore, cdev->name)) {
+                               print_header(&header_printed);
+                               report_findmnt(target);
+                       }
+               }
+       }
+
+       free(device);
+
+       return header_printed ? 0 : COMMAND_ERROR;
+}
+
+BAREBOX_CMD_HELP_START(findmnt)
+BAREBOX_CMD_HELP_TEXT("findmnt will list all mounted filesystems or search")
+BAREBOX_CMD_HELP_TEXT("for a filesystem when given the mountpoint or the")
+BAREBOX_CMD_HELP_TEXT("source device as an argument")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-T",  "mount target file path")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(findmnt)
+       .cmd            = do_findmnt,
+       BAREBOX_CMD_DESC("find a file system")
+       BAREBOX_CMD_OPTS("[ DEVICE | -T FILE ]")
+       BAREBOX_CMD_GROUP(CMD_GRP_FILE)
+       BAREBOX_CMD_HELP(cmd_findmnt_help)
+BAREBOX_CMD_END
diff --git a/fs/fs.c b/fs/fs.c
index 5f46918caafe..bd6b9f504adb 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -130,8 +130,6 @@ void cdev_print(const struct cdev *cdev)
 }
 EXPORT_SYMBOL(cdev_print);
 
-static struct fs_device *get_fsdevice_by_path(int dirfd, const char *path);
-
 void stat_print(const char *filename, const struct stat *st)
 {
        int dirfd = AT_FDCWD;
@@ -2383,7 +2381,7 @@ static int filename_lookup(int dirfd, struct filename 
*name, unsigned flags,
        return err;
 }
 
-static struct fs_device *get_fsdevice_by_path(int dirfd, const char *pathname)
+struct fs_device *get_fsdevice_by_path(int dirfd, const char *pathname)
 {
        struct fs_device *fsdev;
        struct path path;
diff --git a/include/driver.h b/include/driver.h
index b6fe8712837b..7a8b46ac4109 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -568,6 +568,11 @@ static inline void cdev_set_of_node(struct cdev *cdev, 
struct device_node *np)
                cdev->device_node = np;
 }
 
+static inline const char *cdev_name(struct cdev *cdev)
+{
+       return cdev ? cdev->name : NULL;
+}
+
 int devfs_create(struct cdev *);
 int devfs_create_link(struct cdev *, const char *name);
 int devfs_remove(struct cdev *);
diff --git a/include/fs.h b/include/fs.h
index c4af8659b0d3..020761692cad 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -152,6 +152,8 @@ void cdev_print(const struct cdev *cdev);
 
 char *canonicalize_path(int dirfd, const char *pathname);
 
+struct fs_device *get_fsdevice_by_path(int dirfd, const char *path);
+
 char *get_mounted_path(const char *path);
 
 struct cdev *get_cdev_by_mountpath(const char *path);
-- 
2.39.2


Reply via email to