aboutsummaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2017-10-21 18:56:00 +0800
committerIan Kent <raven@themaw.net>2017-12-18 08:47:08 +0800
commit4cfefdcb1bad8f7b9783e6ffb00fb9559b540fba (patch)
tree31bdc0e3a6a0b1d80a8d8fc62b603b1c1241ccdb /modules
parent3385634820b43e11422c88d1abb109432cbd67f7 (diff)
downloadautofs-4cfefdcb1bad8f7b9783e6ffb00fb9559b540fba.tar.gz
autofs-5.1.3 - add amd mount type program mount support
Add support for the amd mount type "program" and its option "mount", and its mutually exclusive options "umount" or "unmount" for specifying the program to be used to perform the mount and optionally also the umount. Signed-off-by: Ian Kent <raven@themaw.net>
Diffstat (limited to 'modules')
-rw-r--r--modules/amd_parse.y36
-rw-r--r--modules/parse_amd.c143
2 files changed, 168 insertions, 11 deletions
diff --git a/modules/amd_parse.y b/modules/amd_parse.y
index 3820d1cb..1d72f190 100644
--- a/modules/amd_parse.y
+++ b/modules/amd_parse.y
@@ -347,13 +347,18 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE
amd_set_value(&entry.rfs, fs_opt_val);
else if (!strcmp($1, "dev"))
amd_set_value(&entry.dev, fs_opt_val);
- else if (!strcmp($1, "mount") ||
- !strcmp($1, "unmount") ||
+ else if (!strcmp($1, "mount"))
+ amd_set_value(&entry.mount, fs_opt_val);
+ else if (!strcmp($1, "unmount") ||
!strcmp($1, "umount")) {
- amd_info("file system type program is not "
- "yet implemented, option ignored");
- free(fs_opt_val);
- YYABORT;
+ if (entry.umount) {
+ sprintf(msg_buf,
+ "unmount or umount may only be used once");
+ amd_info(msg_buf);
+ free(fs_opt_val);
+ YYABORT;
+ }
+ entry.umount = fs_opt_val;
} else if (!strcmp($1, "delay") ||
!strcmp($1, "cachedir")) {
sprintf(msg_buf, "option %s is not used by autofs", $1);
@@ -381,7 +386,14 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE
amd_set_value(&entry.rfs, empty);
else if (!strcmp($1, "dev"))
amd_set_value(&entry.dev, empty);
- else {
+ else if (!strcmp($1, "mount")) {
+ amd_set_value(&entry.mount, NULL);
+ free(empty);
+ } else if (!strcmp($1, "umount") ||
+ !strcmp($1, "unmount")) {
+ amd_set_value(&entry.umount, NULL);
+ free(empty);
+ } else {
amd_notify($1);
free(empty);
YYABORT;
@@ -426,8 +438,7 @@ option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE
options: OPTION
{
if (!strcmp($1, "fullybrowsable") ||
- !strcmp($1, "nounmount") ||
- !strcmp($1, "unmount")) {
+ !strcmp($1, "nounmount")) {
sprintf(msg_buf, "option %s is not currently "
"implemented, ignored", $1);
amd_info(msg_buf);
@@ -496,7 +507,9 @@ static int match_map_option_fs_type(char *map_option, char *type)
!strcmp(fs_type, "ext3") ||
!strcmp(fs_type, "ext4"))
entry.flags |= AMD_MOUNT_TYPE_EXT;
- } else if (!strcmp(fs_type, "ufs")) {
+ else if (!strcmp(fs_type, "program"))
+ entry.flags |= AMD_MOUNT_TYPE_PROGRAM;
+ else if (!strcmp(fs_type, "ufs")) {
entry.flags |= AMD_MOUNT_TYPE_UFS;
entry.type = conf_amd_get_linux_ufs_mount_type();
if (!entry.type) {
@@ -520,7 +533,6 @@ static int match_map_option_fs_type(char *map_option, char *type)
fs_type = NULL;
} else if (!strcmp(fs_type, "jfs") ||
!strcmp(fs_type, "nfsx") ||
- !strcmp(fs_type, "program") ||
!strcmp(fs_type, "lustre") ||
!strcmp(fs_type, "direct")) {
sprintf(msg_buf, "file system type %s is "
@@ -880,6 +892,8 @@ static int add_location(void)
new->addopts = entry.addopts;
new->remopts = entry.remopts;
new->sublink = entry.sublink;
+ new->mount = entry.mount;
+ new->umount = entry.umount;
new->selector = entry.selector;
list_add_tail(&new->list, entries);
memset(&entry, 0, sizeof(struct amd_entry));
diff --git a/modules/parse_amd.c b/modules/parse_amd.c
index eeb74d41..0b2440ea 100644
--- a/modules/parse_amd.c
+++ b/modules/parse_amd.c
@@ -788,6 +788,35 @@ next:
sv = macro_addvar(sv, "remopts", 7, entry->remopts);
}
+ if (entry->mount) {
+ if (!expand_selectors(ap, entry->mount, &expand, sv)) {
+ free(entry->mount);
+ if (entry->umount)
+ free(entry->umount);
+ entry->mount = NULL;
+ entry->umount = NULL;
+ goto done;
+ }
+ debug(logopt, MODPREFIX
+ "mount expand(\"%s\") -> %s", entry->mount, expand);
+ free(entry->mount);
+ entry->mount = expand;
+ sv = macro_addvar(sv, "mount", 5, entry->mount);
+ }
+
+ if (entry->umount) {
+ if (!expand_selectors(ap, entry->umount, &expand, sv)) {
+ free(entry->umount);
+ entry->umount = NULL;
+ goto done;
+ }
+ debug(logopt, MODPREFIX
+ "umount expand(\"%s\") -> %s", entry->umount, expand);
+ free(entry->umount);
+ entry->umount = expand;
+ sv = macro_addvar(sv, "umount", 5, entry->umount);
+ }
+done:
return sv;
}
@@ -1222,6 +1251,91 @@ out:
return ret;
}
+static int do_program_mount(struct autofs_point *ap,
+ struct amd_entry *entry, const char *name)
+{
+ char *prog, *str;
+ char **argv;
+ int argc = -1;
+ int rv = 1;
+
+ str = strdup(entry->mount);
+ if (!str)
+ goto out;
+
+ prog = NULL;
+ argv = NULL;
+
+ argc = construct_argv(str, &prog, &argv);
+ if (argc == -1) {
+ error(ap->logopt, MODPREFIX
+ "%s: error creating mount arguments", entry->type);
+ free(str);
+ goto out;
+ }
+
+ /* The am-utils documentation doesn't actually say that the
+ * mount (and umount, if given) command need to use ${fs} as
+ * the mount point in the command.
+ *
+ * For program mounts there's no way to know what the mount
+ * point is so ${fs} must be used in the mount (and umount,
+ * if given) in order to create the mount point directory
+ * before executing the mount command and removing it at
+ * umount.
+ */
+ if (ext_mount_inuse(entry->fs)) {
+ rv = 0;
+ ext_mount_add(&entry->ext_mount, entry->fs, 1);
+ } else {
+ rv = mkdir_path(entry->fs, 0555);
+ if (rv && errno != EEXIST) {
+ char *buf[MAX_ERR_BUF];
+ char * estr;
+
+ estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ error(ap->logopt,
+ MODPREFIX "%s: mkdir_path %s failed: %s",
+ entry->type, entry->fs, estr);
+ goto do_free;
+ }
+
+ rv = spawnv(ap->logopt, prog, (const char * const *) argv);
+ if (WIFEXITED(rv) && !WEXITSTATUS(rv)) {
+ rv = 0;
+ ext_mount_add(&entry->ext_mount, entry->fs, 1);
+ debug(ap->logopt, MODPREFIX
+ "%s: mounted %s", entry->type, entry->fs);
+ } else {
+ if (!ext_mount_inuse(entry->fs))
+ rmdir_path(ap, entry->fs, ap->dev);
+ error(ap->logopt, MODPREFIX
+ "%s: failed to mount using: %s",
+ entry->type, entry->mount);
+ }
+ }
+do_free:
+ free_argv(argc, (const char **) argv);
+ free(str);
+
+ if (rv)
+ goto out;
+
+ rv = do_link_mount(ap, name, entry, 0);
+ if (!rv)
+ goto out;
+
+ if (umount_amd_ext_mount(ap, entry)) {
+ if (!ext_mount_inuse(entry->fs))
+ rmdir_path(ap, entry->fs, ap->dev);
+ debug(ap->logopt, MODPREFIX
+ "%s: failed to umount external mount at %s",
+ entry->type, entry->fs);
+ }
+out:
+ return rv;
+}
+
static unsigned int validate_auto_options(unsigned int logopt,
struct amd_entry *entry)
{
@@ -1348,6 +1462,29 @@ static unsigned int validate_host_options(unsigned int logopt,
return 1;
}
+static unsigned int validate_program_options(unsigned int logopt,
+ struct amd_entry *entry)
+{
+ /*
+ * entry->mount will be NULL if there is a problem expanding
+ * ${} macros in expandamdent().
+ */
+ if (!entry->mount) {
+ error(logopt, MODPREFIX
+ "%s: mount program invalid or not set", entry->type);
+ return 0;
+ }
+
+ if (!entry->fs && !*entry->fs) {
+ error(logopt, MODPREFIX
+ "%s: ${fs} must be used as the mount point but is not set",
+ entry->type);
+ return 0;
+ }
+
+ return 1;
+}
+
static int amd_mount(struct autofs_point *ap, const char *name,
struct amd_entry *entry, struct map_source *source,
struct substvar *sv, unsigned int flags,
@@ -1413,6 +1550,12 @@ static int amd_mount(struct autofs_point *ap, const char *name,
ret = do_host_mount(ap, name, entry, source, flags);
break;
+ case AMD_MOUNT_TYPE_PROGRAM:
+ if (!validate_program_options(ap->logopt, entry))
+ return 1;
+ ret = do_program_mount(ap, entry, name);
+ break;
+
default:
info(ap->logopt,
MODPREFIX "unknown file system type %x", fstype);