summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2012-02-19 18:22:04 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2012-03-18 15:03:26 +0100
commitb5e5b06d8bf87908a5c4bec87e751ee2681cad4f (patch)
treeaed701ab0ed8be47f39c24c880dc14086fe9e097 /fs
parentb55fbf7f5f14a8a60b4f5bdf1416c25fc4d3e59d (diff)
downloadbarebox-b5e5b06d8bf87908a5c4bec87e751ee2681cad4f.tar.gz
barebox-b5e5b06d8bf87908a5c4bec87e751ee2681cad4f.tar.xz
Add automount support
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/Kconfig3
-rw-r--r--fs/fs.c119
2 files changed, 122 insertions, 0 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index 6208cd2119..e5f307fd26 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 03fe9c81d5..8473f81aed 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);