mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] automount support
@ 2012-03-18 14:26 Sascha Hauer
  2012-03-18 14:26 ` [PATCH 1/8] fs: change get_fs_device_by_path prototype Sascha Hauer
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

The following series adds automount support to barebox. With the
automount command it's possible to access arbitrary files just
by using them without having to care about whether devices have
to be brought up or mounted first. It has the potential of making
the environment simpler and more flexible at the same time. Also
this series contains some patches which either fix some bugs I came
along while implementing it or make using automount more convenient.

The idea of automount is quite simple. The automount command is called
with a path and a script file argument. When the path is first accessed
the script is executed with the destination path as argument. It's the
resposibility of the script to make this directory available. A simple
example could be:

/env/bin/automount_tftp:

|#!/bin/sh
|
|where="$1"
|dhcp
|mount $eth0.serverip tftp $where

and on the commandline:

barebox:/ automount /mnt/tftp /env/bin/automount_tftp
barebox:/ automount -l
/mnt/tftp       /env/bin/automount_tftp
barebox:/ cp mnt/tftp/barebox.bin /
phy0: Link is up - 100/Full
T T DHCP client bound to address 192.168.24.146
barebox:/ automount -l
barebox:/ ls -l barebox.bin
-rwxrwxrwx     158388 barebox.bin
barebox:/

It does not only work with filesystems mounted to directories but
also with flat devices:

/env/bin/automount_usbdisk:

|#!/bin/sh
|
|usb

barebox:/ automount /dev/usbdisk0.0 /env/bin/automount_usbdisk
barebox:/ bootm /dev/usbdisk0.0
USB: scanning bus for devices...
Bus 001 Device 002: ID 090c:1000 USB DISK
Using index 0 for the new disk
Bus 001 Device 001: ID 0000:0000 EHCI Host Controller
2 USB Device(s) found
commandline:  ip=dhcp root=mtd:nand0.root rootfstype=jffs2 mtdparts=mxc_nand:512k(nand0.barebox)ro,128k(nand0.bareboxenv),2M(nand0.kernel),-(nand0.root);physmap-flash.0:512k(nor0.barebox)ro,128k(nor0.bareboxenv),2M(nor0.kernel),-(nor0.root) console=ttymxc0,115200
arch_number: 1551
Uncompressing Linux... done, booting the kernel.
...


Comments welcome.

Thanks,
 Sascha

----------------------------------------------------------------
Sascha Hauer (8):
      fs: change get_fs_device_by_path prototype
      fs: drop struct mtab_entry
      Add automount support
      fs open: pass error from stat
      hush source: expand $PATH
      FAT: Fix error path
      usb command: by default scan only once for USB devices
      partition command: optionally do not automatically prepend the device name

 commands/Kconfig     |   10 ++
 commands/Makefile    |    1 +
 commands/automount.c |   66 ++++++++++++
 commands/mount.c     |   10 +-
 commands/partition.c |   33 +++++--
 commands/usb.c       |   26 ++++-
 common/hush.c        |   17 +++-
 fs/Kconfig           |    3 +
 fs/fat/fat.c         |   18 +++-
 fs/fat/ff.c          |    4 +-
 fs/fs.c              |  282 +++++++++++++++++++++++++++++++++++---------------
 include/fs.h         |   19 ++--
 12 files changed, 371 insertions(+), 118 deletions(-)
 create mode 100644 commands/automount.c

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] fs: change get_fs_device_by_path prototype
  2012-03-18 14:26 [PATCH] automount support Sascha Hauer
@ 2012-03-18 14:26 ` Sascha Hauer
  2012-03-18 14:26 ` [PATCH 2/8] fs: drop struct mtab_entry Sascha Hauer
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

get_fs_device_by_path returns a struct device_d instead of what the
name suggests a struct fs_device_d. Also it returns the rootpath
of the corresponding fs_device. This patch changes the name of
this function to get_fs_device_and_root_path to better reflect what
the function does and changes the return type to struct fs_device_d.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/fs.c |   65 ++++++++++++++++++++++++++++++--------------------------------
 1 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index a31a4ce..93a0f80 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -216,9 +216,8 @@ static int check_fd(int fd)
 	return 0;
 }
 
-static struct device_d *get_fs_device_by_path(char **path)
+static struct fs_device_d *get_fs_device_and_root_path(char **path)
 {
-	struct device_d *dev;
 	struct mtab_entry *e;
 
 	e = get_mtab_entry_by_path(*path);
@@ -227,9 +226,7 @@ static struct device_d *get_fs_device_by_path(char **path)
 	if (e != mtab_root)
 		*path += strlen(e->path);
 
-	dev = e->dev;
-
-	return dev;
+	return dev_to_fs_device(e->dev);
 }
 
 static int dir_is_empty(const char *pathname)
@@ -336,7 +333,7 @@ EXPORT_SYMBOL(chdir);
 
 int unlink(const char *pathname)
 {
-	struct device_d *dev;
+	struct fs_device_d *fsdev;
 	struct fs_driver_d *fsdrv;
 	char *p = normalise_path(pathname);
 	char *freep = p;
@@ -344,17 +341,17 @@ int unlink(const char *pathname)
 	if (path_check_prereq(pathname, S_IFREG))
 		goto out;
 
-	dev = get_fs_device_by_path(&p);
-	if (!dev)
+	fsdev = get_fs_device_and_root_path(&p);
+	if (!fsdev)
 		goto out;
-	fsdrv = dev_to_fs_driver(dev);
+	fsdrv = fsdev->driver;
 
 	if (!fsdrv->unlink) {
 		errno = -ENOSYS;
 		goto out;
 	}
 
-	errno = fsdrv->unlink(dev, p);
+	errno = fsdrv->unlink(&fsdev->dev, p);
 out:
 	free(freep);
 	return errno;
@@ -363,7 +360,7 @@ EXPORT_SYMBOL(unlink);
 
 int open(const char *pathname, int flags, ...)
 {
-	struct device_d *dev;
+	struct fs_device_d *fsdev;
 	struct fs_driver_d *fsdrv;
 	FILE *f;
 	int exist;
@@ -389,13 +386,13 @@ int open(const char *pathname, int flags, ...)
 		goto out1;
 	}
 
-	dev = get_fs_device_by_path(&path);
-	if (!dev)
+	fsdev = get_fs_device_and_root_path(&path);
+	if (!fsdev)
 		goto out;
 
-	fsdrv = dev_to_fs_driver(dev);
+	fsdrv = fsdev->driver;
 
-	f->dev = dev;
+	f->dev = &fsdev->dev;
 	f->flags = flags;
 
 	if ((flags & O_ACCMODE) && !fsdrv->write) {
@@ -405,20 +402,20 @@ int open(const char *pathname, int flags, ...)
 
 	if (!exist) {
 		if (NULL != fsdrv->create)
-			errno = fsdrv->create(dev, path,
+			errno = fsdrv->create(&fsdev->dev, path,
 					S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO);
 		else
 			errno = -EROFS;
 		if (errno)
 			goto out;
 	}
-	errno = fsdrv->open(dev, f, path);
+	errno = fsdrv->open(&fsdev->dev, f, path);
 	if (errno)
 		goto out;
 
 
 	if (flags & O_TRUNC) {
-		errno = fsdrv->truncate(dev, f, 0);
+		errno = fsdrv->truncate(&fsdev->dev, f, 0);
 		f->size = 0;
 		if (errno)
 			goto out;
@@ -867,7 +864,7 @@ EXPORT_SYMBOL(umount);
 DIR *opendir(const char *pathname)
 {
 	DIR *dir = NULL;
-	struct device_d *dev;
+	struct fs_device_d *fsdev;
 	struct fs_driver_d *fsdrv;
 	char *p = normalise_path(pathname);
 	char *freep = p;
@@ -875,16 +872,16 @@ DIR *opendir(const char *pathname)
 	if (path_check_prereq(pathname, S_IFDIR))
 		goto out;
 
-	dev = get_fs_device_by_path(&p);
-	if (!dev)
+	fsdev = get_fs_device_and_root_path(&p);
+	if (!fsdev)
 		goto out;
-	fsdrv = dev_to_fs_driver(dev);
+	fsdrv = fsdev->driver;
 
 	debug("opendir: fsdrv: %p\n",fsdrv);
 
-	dir = fsdrv->opendir(dev, p);
+	dir = fsdrv->opendir(&fsdev->dev, p);
 	if (dir) {
-		dir->dev = dev;
+		dir->dev = &fsdev->dev;
 		dir->fsdrv = fsdrv;
 	}
 
@@ -951,20 +948,20 @@ EXPORT_SYMBOL(stat);
 int mkdir (const char *pathname, mode_t mode)
 {
 	struct fs_driver_d *fsdrv;
-	struct device_d *dev;
+	struct fs_device_d *fsdev;
 	char *p = normalise_path(pathname);
 	char *freep = p;
 
 	if (path_check_prereq(pathname, S_UB_DOES_NOT_EXIST))
 		goto out;
 
-	dev = get_fs_device_by_path(&p);
-	if (!dev)
+	fsdev = get_fs_device_and_root_path(&p);
+	if (!fsdev)
 		goto out;
-	fsdrv = dev_to_fs_driver(dev);
+	fsdrv = fsdev->driver;
 
 	if (fsdrv->mkdir) {
-		errno = fsdrv->mkdir(dev, p);
+		errno = fsdrv->mkdir(&fsdev->dev, p);
 		goto out;
 	}
 
@@ -978,20 +975,20 @@ EXPORT_SYMBOL(mkdir);
 int rmdir (const char *pathname)
 {
 	struct fs_driver_d *fsdrv;
-	struct device_d *dev;
+	struct fs_device_d *fsdev;
 	char *p = normalise_path(pathname);
 	char *freep = p;
 
 	if (path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY))
 		goto out;
 
-	dev = get_fs_device_by_path(&p);
-	if (!dev)
+	fsdev = get_fs_device_and_root_path(&p);
+	if (!fsdev)
 		goto out;
-	fsdrv = dev_to_fs_driver(dev);
+	fsdrv = fsdev->driver;
 
 	if (fsdrv->rmdir) {
-		errno = fsdrv->rmdir(dev, p);
+		errno = fsdrv->rmdir(&fsdev->dev, p);
 		goto out;
 	}
 
-- 
1.7.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/8] fs: drop struct mtab_entry
  2012-03-18 14:26 [PATCH] automount support Sascha Hauer
  2012-03-18 14:26 ` [PATCH 1/8] fs: change get_fs_device_by_path prototype Sascha Hauer
@ 2012-03-18 14:26 ` Sascha Hauer
  2012-03-18 14:26 ` [PATCH 3/8] Add automount support Sascha Hauer
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

every struct fs_device_d contains a struct mtab_entry, so they
have a 1:1 relationship. Instead of having to use container_of
to get from a struct mtab_entry to a struct fs_device_d we can
better embed the members of struct mtab_entry into struct fs_device_d
directly.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/mount.c |   10 +++---
 fs/fs.c          |   88 ++++++++++++++++++++++++++---------------------------
 include/fs.h     |   15 +++------
 3 files changed, 53 insertions(+), 60 deletions(-)

diff --git a/commands/mount.c b/commands/mount.c
index dd1ae63..b32faef 100644
--- a/commands/mount.c
+++ b/commands/mount.c
@@ -33,14 +33,14 @@
 static int do_mount(int argc, char *argv[])
 {
 	int ret = 0;
-	struct mtab_entry *entry;
+	struct fs_device_d *fsdev;
 
 	if (argc == 1) {
-		for_each_mtab_entry(entry) {
+		for_each_fs_device(fsdev) {
 			printf("%s on %s type %s\n",
-				entry->parent_device ? dev_name(entry->parent_device) : "none",
-				entry->path,
-				entry->dev->name);
+				fsdev->parent_device ? dev_name(fsdev->parent_device) : "none",
+				fsdev->path,
+				fsdev->dev.name);
 		}
 		return 0;
 	}
diff --git a/fs/fs.c b/fs/fs.c
index 93a0f80..03fe9c8 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -167,21 +167,21 @@ char *normalise_path(const char *pathname)
 }
 EXPORT_SYMBOL(normalise_path);
 
-LIST_HEAD(mtab_list);
-static struct mtab_entry *mtab_root;
+LIST_HEAD(fs_device_list);
+static struct fs_device_d *fs_dev_root;
 
-static struct mtab_entry *get_mtab_entry_by_path(const char *path)
+static struct fs_device_d *get_fsdevice_by_path(const char *path)
 {
-	struct mtab_entry *e = NULL;
+	struct fs_device_d *fsdev = NULL;
 
-	for_each_mtab_entry(e) {
-		int len = strlen(e->path);
-		if (!strncmp(path, e->path, len) &&
+	for_each_fs_device(fsdev) {
+		int len = strlen(fsdev->path);
+		if (!strncmp(path, fsdev->path, len) &&
 				(path[len] == '/' || path[len] == 0))
-			return e;
+			return fsdev;
 	}
 
-	return mtab_root;
+	return fs_dev_root;
 }
 
 static FILE files[MAX_FILES];
@@ -218,15 +218,15 @@ static int check_fd(int fd)
 
 static struct fs_device_d *get_fs_device_and_root_path(char **path)
 {
-	struct mtab_entry *e;
+	struct fs_device_d *fsdev;
 
-	e = get_mtab_entry_by_path(*path);
-	if (!e)
+	fsdev = get_fsdevice_by_path(*path);
+	if (!fsdev)
 		return NULL;
-	if (e != mtab_root)
-		*path += strlen(e->path);
+	if (fsdev != fs_dev_root)
+		*path += strlen(fsdev->path);
 
-	return dev_to_fs_device(e->dev);
+	return fsdev;
 }
 
 static int dir_is_empty(const char *pathname)
@@ -702,7 +702,7 @@ static int fs_match(struct device_d *dev, struct driver_d *drv)
 static int fs_probe(struct device_d *dev)
 {
 	struct fs_device_d *fsdev = dev_to_fs_device(dev);
-	struct mtab_entry *entry = &fsdev->mtab;
+	struct fs_driver_d *fsdrv = dev_to_fs_driver(dev);
 	int ret;
 
 	ret = dev->driver->probe(dev);
@@ -711,15 +711,15 @@ static int fs_probe(struct device_d *dev)
 
 	if (fsdev->cdev) {
 		dev_add_child(fsdev->cdev->dev, &fsdev->dev);
-		entry->parent_device = fsdev->cdev->dev;
+		fsdev->parent_device = fsdev->cdev->dev;
 	}
 
-	entry->dev = &fsdev->dev;
+	fsdev->driver = fsdrv;
 
-	list_add_tail(&entry->list, &mtab_list);
+	list_add_tail(&fsdev->list, &fs_device_list);
 
-	if (!mtab_root)
-		mtab_root = entry;
+	if (!fs_dev_root)
+		fs_dev_root = fsdev;
 
 	return 0;
 }
@@ -727,17 +727,16 @@ static int fs_probe(struct device_d *dev)
 static void fs_remove(struct device_d *dev)
 {
 	struct fs_device_d *fsdev = dev_to_fs_device(dev);
-	struct mtab_entry *entry = &fsdev->mtab;
 
 	if (fsdev->dev.driver) {
 		dev->driver->remove(dev);
-		list_del(&entry->list);
+		list_del(&fsdev->list);
 	}
 
-	free(entry->path);
+	free(fsdev->path);
 
-	if (entry == mtab_root)
-		mtab_root = NULL;
+	if (fsdev == fs_dev_root)
+		fs_dev_root = NULL;
 
 	free(fsdev->backingstore);
 	free(fsdev);
@@ -774,10 +773,9 @@ int mount(const char *device, const char *fsname, const char *_path)
 
 	debug("mount: %s on %s type %s\n", device, path, fsname);
 
-	if (mtab_root) {
-		struct mtab_entry *entry;
-		entry = get_mtab_entry_by_path(path);
-		if (entry != mtab_root) {
+	if (fs_dev_root) {
+		fsdev = get_fsdevice_by_path(path);
+		if (fsdev != fs_dev_root) {
 			printf("sorry, no nested mounts\n");
 			errno = -EBUSY;
 			goto err_free_path;
@@ -796,7 +794,7 @@ int mount(const char *device, const char *fsname, const char *_path)
 	fsdev->backingstore = xstrdup(device);
 	safe_strncpy(fsdev->dev.name, fsname, MAX_DRIVER_NAME);
 	fsdev->dev.id = get_free_deviceid(fsdev->dev.name);
-	fsdev->mtab.path = xstrdup(path);
+	fsdev->path = xstrdup(path);
 	fsdev->dev.bus = &fs_bus;
 
 	if (!strncmp(device, "/dev/", 5))
@@ -833,29 +831,29 @@ EXPORT_SYMBOL(mount);
 
 int umount(const char *pathname)
 {
-	struct mtab_entry *entry = NULL, *e;
+	struct fs_device_d *fsdev = NULL, *f;
 	char *p = normalise_path(pathname);
 
-	for_each_mtab_entry(e) {
-		if (!strcmp(p, e->path)) {
-			entry = e;
+	for_each_fs_device(f) {
+		if (!strcmp(p, f->path)) {
+			fsdev = f;
 			break;
 		}
 	}
 
 	free(p);
 
-	if (e == mtab_root && !list_is_singular(&mtab_list)) {
+	if (f == fs_dev_root && !list_is_singular(&fs_device_list)) {
 		errno = -EBUSY;
 		return errno;
 	}
 
-	if (!entry) {
+	if (!fsdev) {
 		errno = -EFAULT;
 		return errno;
 	}
 
-	unregister_device(entry->dev);
+	unregister_device(&fsdev->dev);
 
 	return 0;
 }
@@ -915,23 +913,23 @@ int stat(const char *filename, struct stat *s)
 {
 	struct device_d *dev;
 	struct fs_driver_d *fsdrv;
-	struct mtab_entry *e;
+	struct fs_device_d *fsdev;
 	char *f = normalise_path(filename);
 	char *freep = f;
 
 	memset(s, 0, sizeof(struct stat));
 
-	e = get_mtab_entry_by_path(f);
-	if (!e) {
+	fsdev = get_fsdevice_by_path(f);
+	if (!fsdev) {
 		errno = -ENOENT;
 		goto out;
 	}
 
-	if (e != mtab_root && strcmp(f, e->path)) {
-		f += strlen(e->path);
-		dev = e->dev;
+	if (fsdev != fs_dev_root && strcmp(f, fsdev->path)) {
+		f += strlen(fsdev->path);
+		dev = &fsdev->dev;
 	} else
-		dev = mtab_root->dev;
+		dev = &fs_dev_root->dev;
 
 	fsdrv = dev_to_fs_driver(dev);
 
diff --git a/include/fs.h b/include/fs.h
index e5364f9..7815da5 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -77,15 +77,8 @@ struct fs_driver_d {
 #define dev_to_fs_driver(d) container_of(d->driver, struct fs_driver_d, drv)
 #define dev_to_fs_device(d) container_of(d, struct fs_device_d, dev)
 
-struct mtab_entry {
-	char *path;
-	struct device_d *dev;
-	struct device_d *parent_device;
-	struct list_head list;
-};
-
-extern struct list_head mtab_list;
-#define for_each_mtab_entry(e) list_for_each_entry(e, &mtab_list, list)
+extern struct list_head fs_device_list;
+#define for_each_fs_device(f) list_for_each_entry(f, &fs_device_list, list)
 
 struct fs_device_d {
 	char *backingstore; /* the device we are associated with */
@@ -94,7 +87,9 @@ struct fs_device_d {
 	struct fs_driver_d *driver;
 
 	struct cdev *cdev;
-	struct mtab_entry mtab;
+	char *path;
+	struct device_d *parent_device;
+	struct list_head list;
 };
 
 /*
-- 
1.7.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/8] Add automount support
  2012-03-18 14:26 [PATCH] automount support Sascha Hauer
  2012-03-18 14:26 ` [PATCH 1/8] fs: change get_fs_device_by_path prototype Sascha Hauer
  2012-03-18 14:26 ` [PATCH 2/8] fs: drop struct mtab_entry Sascha Hauer
@ 2012-03-18 14:26 ` Sascha Hauer
  2012-03-18 14:26 ` [PATCH 4/8] fs open: pass error from stat Sascha Hauer
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

This patch adds an automount command which makes it possible
to execute a script when a certain directory is first accessed.
It's the commands responsibility to make this directory available
(bringing devices up and mounting it). This results in automount
support which makes sure that from the shell every file can
be accessed without having to care for device bringup. Bringing
up devices may be expensive (USB, dhcp). The automount support
makes it easy for the environment to bringup devices when they
are actually needed.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/Kconfig     |   10 ++++
 commands/Makefile    |    1 +
 commands/automount.c |   66 +++++++++++++++++++++++++++
 fs/Kconfig           |    3 +
 fs/fs.c              |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/fs.h         |    4 ++
 6 files changed, 203 insertions(+), 0 deletions(-)
 create mode 100644 commands/automount.c

diff --git a/commands/Kconfig b/commands/Kconfig
index e332a85..7a8811e 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -181,6 +181,16 @@ config CMD_NANDTEST
 	select PARTITION_NEED_MTD
 	prompt "nandtest"
 
+config CMD_AUTOMOUNT
+	tristate
+	select FS_AUTOMOUNT
+	prompt "automount"
+	help
+	  automount allows it to automatically execute a script when a certain
+	  directory is accessed for the first time. The script should then make
+	  this directory available (discover USB devices, bring network interface
+	  up and finally mount the filesystem).
+
 endmenu
 
 menu "console                       "
diff --git a/commands/Makefile b/commands/Makefile
index 31442b5..f02b5ca 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -64,3 +64,4 @@ obj-$(CONFIG_CMD_OFTREE)	+= oftree.o
 obj-$(CONFIG_CMD_MAGICVAR)	+= magicvar.o
 obj-$(CONFIG_CMD_IOMEM)		+= iomem.o
 obj-$(CONFIG_CMD_LINUX_EXEC)	+= linux_exec.o
+obj-$(CONFIG_CMD_AUTOMOUNT)	+= automount.o
diff --git a/commands/automount.c b/commands/automount.c
new file mode 100644
index 0000000..5fc68f3
--- /dev/null
+++ b/commands/automount.c
@@ -0,0 +1,66 @@
+/*
+ * automount.c - automount devices
+ *
+ * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation.
+ */
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <errno.h>
+#include <getopt.h>
+
+static int do_automount(int argc, char *argv[])
+{
+	int opt, ret;
+
+	while ((opt = getopt(argc, argv, "lr:")) > 0) {
+		switch (opt) {
+		case 'l':
+			automount_print();
+			return 0;
+		case 'r':
+			automount_remove(optarg);
+			return 0;
+		}
+	}
+
+	if (argc != 3)
+		return COMMAND_ERROR_USAGE;
+
+	ret = automount_add(argv[1], argv[2]);
+	if (ret)
+		printf("adding automountpoint failed: %s\n",
+				strerror(-ret));
+
+	return ret ? 1 : 0;
+}
+
+BAREBOX_CMD_HELP_START(automount)
+BAREBOX_CMD_HELP_USAGE("automount [OPTIONS] <PATH> <cmd>\n")
+BAREBOX_CMD_HELP_SHORT("execute <cmd> when <PATH> is first accessed\n")
+BAREBOX_CMD_HELP_OPT("-l", "List currently registered automountpoints\n")
+BAREBOX_CMD_HELP_OPT("-r <PATH>", "remove an automountpoint\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(automount)
+	.cmd		= do_automount,
+	.usage		= "automount [OPTIONS] <PATH> <cmd>\n",
+	BAREBOX_CMD_HELP(cmd_automount_help)
+BAREBOX_CMD_END
+
diff --git a/fs/Kconfig b/fs/Kconfig
index 6208cd2..e5f307f 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1,6 +1,9 @@
 
 menu "Filesystem support            "
 
+config FS_AUTOMOUNT
+	bool
+
 config FS_CRAMFS
 	bool
 	select ZLIB
diff --git a/fs/fs.c b/fs/fs.c
index 03fe9c8..8473f81 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -216,10 +216,127 @@ static int check_fd(int fd)
 	return 0;
 }
 
+#ifdef CONFIG_FS_AUTOMOUNT
+
+#define AUTOMOUNT_IS_FILE (1 << 0)
+
+struct automount {
+	char *path;
+	char *cmd;
+	struct list_head list;
+	unsigned int flags;
+};
+
+static LIST_HEAD(automount_list);
+
+void automount_remove(const char *_path)
+{
+	char *path = normalise_path(_path);
+	struct automount *am;
+
+	list_for_each_entry(am, &automount_list, list) {
+		if (!strcmp(path, am->path))
+			goto found;
+	}
+
+	return;
+found:
+	list_del(&am->list);
+	free(am->path);
+	free(am->cmd);
+	free(am);
+}
+EXPORT_SYMBOL(automount_remove);
+
+int automount_add(const char *path, const char *cmd)
+{
+	struct automount *am = xzalloc(sizeof(*am));
+	struct stat s;
+	int ret;
+
+	am->path = normalise_path(path);
+	am->cmd = xstrdup(cmd);
+
+	ret = stat(path, &s);
+	if (!ret) {
+		/*
+		 * If it exists it must be a directory
+		 */
+		if (!S_ISDIR(s.st_mode))
+			return -ENOTDIR;
+	} else {
+		am->flags |= AUTOMOUNT_IS_FILE;
+	}
+
+	list_add_tail(&am->list, &automount_list);
+
+	return 0;
+}
+EXPORT_SYMBOL(automount_add);
+
+void automount_print(void)
+{
+	struct automount *am;
+
+	list_for_each_entry(am, &automount_list, list)
+		printf("%-20s %s\n", am->path, am->cmd);
+}
+EXPORT_SYMBOL(automount_print);
+
+static void automount_mount(const char *path, int instat)
+{
+	struct automount *am;
+	int ret;
+
+	list_for_each_entry(am, &automount_list, list) {
+		char *cmd;
+		int len_path = strlen(path);
+		int len_am_path = strlen(am->path);
+
+		/*
+		 * stat is a bit special. We do not want to trigger
+		 * automount when someone calls stat() on the automount
+		 * directory itself.
+		 */
+		if (instat && !(am->flags & AUTOMOUNT_IS_FILE) &&
+				len_path == len_am_path) {
+			continue;
+		}
+
+		if (len_path < len_am_path)
+			continue;
+
+		if (strncmp(path, am->path, len_am_path))
+			continue;
+
+		if (*(path + len_am_path) != 0 && *(path + len_am_path) != '/')
+			continue;
+
+		cmd = asprintf("%s %s", am->cmd, am->path);
+		ret = run_command(cmd, 0);
+		free(cmd);
+
+		if (ret)
+			printf("running automount command '%s' failed\n",
+					am->cmd);
+		else
+			automount_remove(am->path);
+
+		return;
+	}
+}
+#else
+static void automount_mount(const char *path, int instat)
+{
+}
+#endif /* CONFIG_FS_AUTOMOUNT */
+
 static struct fs_device_d *get_fs_device_and_root_path(char **path)
 {
 	struct fs_device_d *fsdev;
 
+	automount_mount(*path, 0);
+
 	fsdev = get_fsdevice_by_path(*path);
 	if (!fsdev)
 		return NULL;
@@ -917,6 +1034,8 @@ int stat(const char *filename, struct stat *s)
 	char *f = normalise_path(filename);
 	char *freep = f;
 
+	automount_mount(f, 1);
+
 	memset(s, 0, sizeof(struct stat));
 
 	fsdev = get_fsdevice_by_path(f);
diff --git a/include/fs.h b/include/fs.h
index 7815da5..d82f026 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -160,4 +160,8 @@ char *normalise_path(const char *path);
 /* Register a new filesystem driver */
 int register_fs_driver(struct fs_driver_d *fsdrv);
 
+void automount_remove(const char *_path);
+int automount_add(const char *path, const char *cmd);
+void automount_print(void);
+
 #endif /* __FS_H */
-- 
1.7.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4/8] fs open: pass error from stat
  2012-03-18 14:26 [PATCH] automount support Sascha Hauer
                   ` (2 preceding siblings ...)
  2012-03-18 14:26 ` [PATCH 3/8] Add automount support Sascha Hauer
@ 2012-03-18 14:26 ` Sascha Hauer
  2012-03-18 14:26 ` [PATCH 5/8] hush source: expand $PATH Sascha Hauer
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

We used to simply answer with -ENOENT in open() when the
initial call to stat() failed. Instead, forward the error from
stat().

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/fs.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index 8473f81..24ef258 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -480,20 +480,20 @@ int open(const char *pathname, int flags, ...)
 	struct fs_device_d *fsdev;
 	struct fs_driver_d *fsdrv;
 	FILE *f;
-	int exist;
+	int exist_err;
 	struct stat s;
 	char *path = normalise_path(pathname);
 	char *freep = path;
 
-	exist = (stat(path, &s) == 0) ? 1 : 0;
+	exist_err = stat(path, &s);
 
-	if (exist && S_ISDIR(s.st_mode)) {
+	if (!exist_err && S_ISDIR(s.st_mode)) {
 		errno = -EISDIR;
 		goto out1;
 	}
 
-	if (!exist && !(flags & O_CREAT)) {
-		errno = -ENOENT;
+	if (exist_err && !(flags & O_CREAT)) {
+		errno = exist_err;
 		goto out1;
 	}
 
@@ -517,7 +517,7 @@ int open(const char *pathname, int flags, ...)
 		goto out;
 	}
 
-	if (!exist) {
+	if (exist_err) {
 		if (NULL != fsdrv->create)
 			errno = fsdrv->create(&fsdev->dev, path,
 					S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO);
-- 
1.7.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 5/8] hush source: expand $PATH
  2012-03-18 14:26 [PATCH] automount support Sascha Hauer
                   ` (3 preceding siblings ...)
  2012-03-18 14:26 ` [PATCH 4/8] fs open: pass error from stat Sascha Hauer
@ 2012-03-18 14:26 ` Sascha Hauer
  2012-03-18 14:26 ` [PATCH 6/8] FAT: Fix error path Sascha Hauer
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

The behaviour of other shells suggest that with source or '.'
the path should be resolved using the PATH environment variable. Do
the same in barebox.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/hush.c |   17 ++++++++++++++++-
 1 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index 1dae0e8..053d9a5 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1678,10 +1678,25 @@ BAREBOX_CMD_END
 
 static int do_source(int argc, char *argv[])
 {
+	char *path;
+	int ret;
+
 	if (argc < 2)
 		return COMMAND_ERROR_USAGE;
 
-	return source_script(argv[1], argc - 1, argv + 1);
+	if (strchr(argv[1], '/')) {
+		path = xstrdup(argv[1]);
+	} else {
+		path = find_execable(argv[1]);
+		if (!path)
+			return 1;
+	}
+
+	ret = source_script(path, argc - 1, argv + 1);
+
+	free(path);
+
+	return ret;
 }
 
 static const char *source_aliases[] = { ".", NULL};
-- 
1.7.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 6/8] FAT: Fix error path
  2012-03-18 14:26 [PATCH] automount support Sascha Hauer
                   ` (4 preceding siblings ...)
  2012-03-18 14:26 ` [PATCH 5/8] hush source: expand $PATH Sascha Hauer
@ 2012-03-18 14:26 ` Sascha Hauer
  2012-03-18 14:26 ` [PATCH 7/8] usb command: by default scan only once for USB devices Sascha Hauer
  2012-03-18 14:26 ` [PATCH 8/8] partition command: optionally do not automatically prepend the device name Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

- forward the return value of chk_mounted to detect whether mount succeeded
- free resources on mount failure

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 fs/fat/fat.c |   18 +++++++++++++++---
 fs/fat/ff.c  |    4 +---
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 7d6e37a..21464bd 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -376,6 +376,7 @@ static int fat_probe(struct device_d *dev)
 	struct fs_device_d *fsdev = dev_to_fs_device(dev);
 	struct fat_priv *priv = xzalloc(sizeof(struct fat_priv));
 	char *backingstore = fsdev->backingstore;
+	int ret;
 
 	dev->priv = priv;
 
@@ -383,13 +384,24 @@ static int fat_probe(struct device_d *dev)
 		backingstore += 5;
 
 	priv->cdev = cdev_open(backingstore, O_RDWR);
-	if (!priv->cdev)
-		return -EINVAL;
+	if (!priv->cdev) {
+		ret = -ENOENT;
+		goto err_open;
+	}
 
 	priv->fat.userdata = priv;
-	f_mount(&priv->fat);
+	ret = f_mount(&priv->fat);
+	if (ret)
+		goto err_mount;
 
 	return 0;
+
+err_mount:
+	cdev_close(priv->cdev);
+err_open:
+	free(priv);
+
+	return ret;
 }
 
 static void fat_remove(struct device_d *dev)
diff --git a/fs/fat/ff.c b/fs/fat/ff.c
index a720389..2d476ee 100644
--- a/fs/fat/ff.c
+++ b/fs/fat/ff.c
@@ -1699,9 +1699,7 @@ int f_mount (
 {
 	fs->fs_type = 0; /* Clear new fs object */
 
-	chk_mounted(fs, 0);
-
-	return 0;
+	return chk_mounted(fs, 0);
 }
 
 /*
-- 
1.7.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 7/8] usb command: by default scan only once for USB devices
  2012-03-18 14:26 [PATCH] automount support Sascha Hauer
                   ` (5 preceding siblings ...)
  2012-03-18 14:26 ` [PATCH 6/8] FAT: Fix error path Sascha Hauer
@ 2012-03-18 14:26 ` Sascha Hauer
  2012-03-18 14:26 ` [PATCH 8/8] partition command: optionally do not automatically prepend the device name Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

We normally do not expect USB devices to be hotplugged. Instead of
rescanning each time the usb command is called, scan only once.
This makes the usb command safe for being called multiple times
without making already registered USB devices reinitialized. To
really scan multiple times a '-f' option is introduced.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/usb.c |   26 ++++++++++++++++++++++----
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/commands/usb.c b/commands/usb.c
index 6605e03..e28afd0 100644
--- a/commands/usb.c
+++ b/commands/usb.c
@@ -22,17 +22,35 @@
 #include <common.h>
 #include <command.h>
 #include <usb/usb.h>
+#include <getopt.h>
+
+static int scanned;
 
 static int do_usb(int argc, char *argv[])
 {
-	usb_rescan();
+	int opt;
+
+	while ((opt = getopt(argc, argv, "f")) > 0) {
+		switch (opt) {
+		case 'f':
+			scanned = 0;
+			break;
+		}
+	}
+
+	if (!scanned) {
+		usb_rescan();
+		scanned = 1;
+	}
 
 	return 0;
 }
 
-static const __maybe_unused char cmd_usb_help[] =
-"Usage: usb\n"
-"(re-)detect USB devices\n";
+BAREBOX_CMD_HELP_START(usb)
+BAREBOX_CMD_HELP_USAGE("usb [-f]\n")
+BAREBOX_CMD_HELP_SHORT("Scan for USB devices.\n")
+BAREBOX_CMD_HELP_OPT("-f", "force. Rescan if if if have scanned once\n")
+BAREBOX_CMD_HELP_END
 
 BAREBOX_CMD_START(usb)
 	.cmd		= do_usb,
-- 
1.7.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 8/8] partition command: optionally do not automatically prepend the device name
  2012-03-18 14:26 [PATCH] automount support Sascha Hauer
                   ` (6 preceding siblings ...)
  2012-03-18 14:26 ` [PATCH 7/8] usb command: by default scan only once for USB devices Sascha Hauer
@ 2012-03-18 14:26 ` Sascha Hauer
  7 siblings, 0 replies; 9+ messages in thread
From: Sascha Hauer @ 2012-03-18 14:26 UTC (permalink / raw)
  To: barebox

We used to automatically prepend the device name before the partition
name. So when we added a partition named 'barebox' to a device named
'nor0' the partition was named 'nor0.barebox'.

The Kernel can mount its rootfs based on the mtd name, for example with
root=mtd:root. If for example we have multiple mtd devices (nor and nand)
'root' is a bad name for the partition, it should better be 'nor0.root'

This patch adds an additional commandline switch to addpart to optionally
skip the automatic device name adding. This makes it possible to define
our mtd partitions like this:

nor_parts="512k(nor0.barebox)ro,128k(nor0.bareboxenv),2M(nor0.kernel),-(nor0.root)"

This way the barebox partition names stay the same, but we can now
pass the exact name to the kernel (root=mtd:nor0.root).

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/partition.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/commands/partition.c b/commands/partition.c
index acd1609..17e3678 100644
--- a/commands/partition.c
+++ b/commands/partition.c
@@ -40,16 +40,19 @@
 #include <fs.h>
 #include <linux/stat.h>
 #include <libgen.h>
+#include <getopt.h>
 
 #define SIZE_REMAINING ((ulong)-1)
 
+#define PART_ADD_DEVNAME (1 << 0)
+
 static int mtd_part_do_parse_one(char *devname, const char *partstr,
 				 char **endp, unsigned long *offset,
-				 off_t devsize, size_t *retsize)
+				 off_t devsize, size_t *retsize, unsigned int pflags)
 {
 	ulong size;
 	char *end;
-	char buf[PATH_MAX];
+	char buf[PATH_MAX] = {};
 	unsigned long flags = 0;
 	int ret;
 
@@ -78,7 +81,8 @@ static int mtd_part_do_parse_one(char *devname, const char *partstr,
 			return -EINVAL;
 		}
 
-		sprintf(buf, "%s.", devname);
+		if (pflags & PART_ADD_DEVNAME)
+			sprintf(buf, "%s.", devname);
 		memcpy(buf + strlen(buf), partstr, end - partstr);
 
 		end++;
@@ -114,24 +118,35 @@ static int do_addpart(int argc, char *argv[])
 	unsigned long offset = 0;
 	off_t devsize;
 	struct stat s;
+	int opt;
+	unsigned int flags = PART_ADD_DEVNAME;
+
+	while ((opt = getopt(argc, argv, "n")) > 0) {
+		switch (opt) {
+		case 'n':
+			flags &= ~PART_ADD_DEVNAME;
+			break;
+		}
+	}
 
-	if (argc != 3)
+	if (argc != optind + 2)
 		return COMMAND_ERROR_USAGE;
 
-	if (stat(argv[1], &s)) {
+	if (stat(argv[optind], &s)) {
 		perror("addpart");
 		return 1;
 	}
 	devsize = s.st_size;
 
-	devname = basename(argv[1]);
+	devname = basename(argv[optind]);
 
-	endp = argv[2];
+	endp = argv[optind + 1];
 
 	while (1) {
 		size_t size = 0;
 
-		if (mtd_part_do_parse_one(devname, endp, &endp, &offset, devsize, &size))
+		if (mtd_part_do_parse_one(devname, endp, &endp, &offset,
+					devsize, &size, flags))
 			return 1;
 
 		offset += size;
@@ -152,6 +167,8 @@ static int do_addpart(int argc, char *argv[])
 BAREBOX_CMD_HELP_START(addpart)
 BAREBOX_CMD_HELP_USAGE("addpart <device> <part_desc>\n")
 BAREBOX_CMD_HELP_SHORT("Add a partition description to a device.\n")
+BAREBOX_CMD_HELP_OPT  ("-n", "no prefix. Do not prepend the device name as prefix before the partition name\n")
+BAREBOX_CMD_HELP_OPT  ("<device>",    "device being worked on\n")
 BAREBOX_CMD_HELP_OPT  ("<device>",    "device being worked on\n")
 BAREBOX_CMD_HELP_OPT  ("<part_desc>", "size1[@offset1](name1)[ro],size2[@offset2](name2)[ro],...\n")
 BAREBOX_CMD_HELP_END
-- 
1.7.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-03-18 14:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-18 14:26 [PATCH] automount support Sascha Hauer
2012-03-18 14:26 ` [PATCH 1/8] fs: change get_fs_device_by_path prototype Sascha Hauer
2012-03-18 14:26 ` [PATCH 2/8] fs: drop struct mtab_entry Sascha Hauer
2012-03-18 14:26 ` [PATCH 3/8] Add automount support Sascha Hauer
2012-03-18 14:26 ` [PATCH 4/8] fs open: pass error from stat Sascha Hauer
2012-03-18 14:26 ` [PATCH 5/8] hush source: expand $PATH Sascha Hauer
2012-03-18 14:26 ` [PATCH 6/8] FAT: Fix error path Sascha Hauer
2012-03-18 14:26 ` [PATCH 7/8] usb command: by default scan only once for USB devices Sascha Hauer
2012-03-18 14:26 ` [PATCH 8/8] partition command: optionally do not automatically prepend the device name Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox