Blame SOURCES/autofs-5.1.3-add-amd-mount-type-program-mount-support.patch

306fa1
autofs-5.1.3 - add amd mount type program mount support
306fa1
306fa1
From: Ian Kent <raven@themaw.net>
306fa1
306fa1
Add support for the amd mount type "program" and its option "mount",
306fa1
and its mutually exclusive options "umount" or "unmount" for specifying
306fa1
the program to be used to perform the mount and optionally also the
306fa1
umount.
306fa1
306fa1
Signed-off-by: Ian Kent <raven@themaw.net>
306fa1
---
306fa1
 CHANGELOG           |    1 
306fa1
 README.amd-maps     |    6 +-
306fa1
 include/parse_amd.h |    3 +
306fa1
 lib/mounts.c        |   42 ++++++++++++++-
306fa1
 modules/amd_parse.y |   36 +++++++++----
306fa1
 modules/parse_amd.c |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++++
306fa1
 6 files changed, 216 insertions(+), 15 deletions(-)
306fa1
306fa1
--- autofs-5.0.7.orig/CHANGELOG
306fa1
+++ autofs-5.0.7/CHANGELOG
306fa1
@@ -281,6 +281,7 @@
306fa1
 - add function umount_amd_ext_mount().
306fa1
 - add function ext_mount_inuse().
306fa1
 - add function construct_argv().
306fa1
+- add amd mount type program mount support.
306fa1
 
306fa1
 25/07/2012 autofs-5.0.7
306fa1
 =======================
306fa1
--- autofs-5.0.7.orig/README.amd-maps
306fa1
+++ autofs-5.0.7/README.amd-maps
306fa1
@@ -146,9 +146,9 @@ always used for available map sources.
306fa1
 
306fa1
 The regex map key matching feature is not implemented.
306fa1
 
306fa1
-Mount types lustre, nfsx, jfs, program and direct haven't been
306fa1
-implemented and other mount types that aren't implemented in amd are
306fa1
-also not available.
306fa1
+Mount types lustre, nfsx, jfs and direct haven't been implemented
306fa1
+and other mount types that aren't implemented in amd are also not
306fa1
+available.
306fa1
 
306fa1
 How to find out more
306fa1
 --------------------
306fa1
--- autofs-5.0.7.orig/include/parse_amd.h
306fa1
+++ autofs-5.0.7/include/parse_amd.h
306fa1
@@ -30,6 +30,7 @@
306fa1
 #define AMD_MOUNT_TYPE_JFS	0x00000800
306fa1
 #define AMD_MOUNT_TYPE_CACHEFS	0x00001000
306fa1
 #define AMD_MOUNT_TYPE_CDFS	0x00002000
306fa1
+#define AMD_MOUNT_TYPE_PROGRAM	0x00004000
306fa1
 #define AMD_MOUNT_TYPE_MASK	0x0000ffff
306fa1
 
306fa1
 #define AMD_ENTRY_CUT		0x00010000
306fa1
@@ -60,6 +61,8 @@ struct amd_entry {
306fa1
 	char *addopts;
306fa1
 	char *remopts;
306fa1
 	char *sublink;
306fa1
+	char *mount;
306fa1
+	char *umount;
306fa1
 	struct selector *selector;
306fa1
 	struct list_head list;
306fa1
 	struct list_head entries;
306fa1
--- autofs-5.0.7.orig/lib/mounts.c
306fa1
+++ autofs-5.0.7/lib/mounts.c
306fa1
@@ -2056,6 +2056,46 @@ int umount_amd_ext_mount(struct autofs_p
306fa1
 {
306fa1
 	int rv = 1;
306fa1
 
306fa1
+	if (entry->umount) {
306fa1
+		char *prog, *str;
306fa1
+		char **argv;
306fa1
+		int argc = -1;
306fa1
+
306fa1
+		str = strdup(entry->umount);
306fa1
+		if (!str)
306fa1
+			goto out;
306fa1
+
306fa1
+		prog = NULL;
306fa1
+		argv = NULL;
306fa1
+
306fa1
+		argc = construct_argv(str, &prog, &argv);
306fa1
+		if (argc == -1) {
306fa1
+			free(str);
306fa1
+			goto out;
306fa1
+		}
306fa1
+
306fa1
+		if (!ext_mount_remove(&entry->ext_mount, entry->fs)) {
306fa1
+			rv =0;
306fa1
+			goto out;
306fa1
+		}
306fa1
+
306fa1
+		rv = spawnv(ap->logopt, prog, (const char * const *) argv);
306fa1
+		if (rv == -1 || (WIFEXITED(rv) && WEXITSTATUS(rv)))
306fa1
+			error(ap->logopt,
306fa1
+			     "failed to umount program mount at %s", entry->fs);
306fa1
+		else {
306fa1
+			rv = 0;
306fa1
+			debug(ap->logopt,
306fa1
+			      "umounted program mount at %s", entry->fs);
306fa1
+			rmdir_path(ap, entry->fs, ap->dev);
306fa1
+		}
306fa1
+
306fa1
+		free_argv(argc, (const char **) argv);
306fa1
+		free(str);
306fa1
+
306fa1
+		goto out;
306fa1
+	}
306fa1
+
306fa1
 	if (ext_mount_remove(&entry->ext_mount, entry->fs)) {
306fa1
 		rv = umount_ent(ap, entry->fs);
306fa1
 		if (rv)
306fa1
@@ -2065,7 +2105,7 @@ int umount_amd_ext_mount(struct autofs_p
306fa1
 			debug(ap->logopt,
306fa1
 			      "umounted external mount %s", entry->fs);
306fa1
 	}
306fa1
-
306fa1
+out:
306fa1
 	return rv;
306fa1
 }
306fa1
 
306fa1
--- autofs-5.0.7.orig/modules/amd_parse.y
306fa1
+++ autofs-5.0.7/modules/amd_parse.y
306fa1
@@ -347,13 +347,18 @@ option_assignment: MAP_OPTION OPTION_ASS
306fa1
 			amd_set_value(&entry.rfs, fs_opt_val);
306fa1
 		else if (!strcmp($1, "dev"))
306fa1
 			amd_set_value(&entry.dev, fs_opt_val);
306fa1
-		else if (!strcmp($1, "mount") ||
306fa1
-			 !strcmp($1, "unmount") ||
306fa1
+		else if (!strcmp($1, "mount"))
306fa1
+			amd_set_value(&entry.mount, fs_opt_val);
306fa1
+		else if (!strcmp($1, "unmount") ||
306fa1
 			 !strcmp($1, "umount")) {
306fa1
-			amd_info("file system type program is not "
306fa1
-				 "yet implemented, option ignored");
306fa1
-			free(fs_opt_val);
306fa1
-			YYABORT;
306fa1
+			if (entry.umount) {
306fa1
+				sprintf(msg_buf,
306fa1
+				    "unmount or umount may only be used once");
306fa1
+				amd_info(msg_buf);
306fa1
+				free(fs_opt_val);
306fa1
+				YYABORT;
306fa1
+			}
306fa1
+			entry.umount = fs_opt_val;
306fa1
 		} else if (!strcmp($1, "delay") ||
306fa1
 			   !strcmp($1, "cachedir")) {
306fa1
 			sprintf(msg_buf, "option %s is not used by autofs", $1);
306fa1
@@ -381,7 +386,14 @@ option_assignment: MAP_OPTION OPTION_ASS
306fa1
 			amd_set_value(&entry.rfs, empty);
306fa1
 		else if (!strcmp($1, "dev"))
306fa1
 			amd_set_value(&entry.dev, empty);
306fa1
-		else {
306fa1
+		else if (!strcmp($1, "mount")) {
306fa1
+			amd_set_value(&entry.mount, NULL);
306fa1
+			free(empty);
306fa1
+		} else if (!strcmp($1, "umount") ||
306fa1
+			   !strcmp($1, "unmount")) {
306fa1
+			amd_set_value(&entry.umount, NULL);
306fa1
+			free(empty);
306fa1
+		} else {
306fa1
 			amd_notify($1);
306fa1
 			free(empty);
306fa1
 			YYABORT;
306fa1
@@ -426,8 +438,7 @@ option_assignment: MAP_OPTION OPTION_ASS
306fa1
 options: OPTION
306fa1
 	{
306fa1
 		if (!strcmp($1, "fullybrowsable") ||
306fa1
-		    !strcmp($1, "nounmount") ||
306fa1
-		    !strcmp($1, "unmount")) {
306fa1
+		    !strcmp($1, "nounmount")) {
306fa1
 			sprintf(msg_buf, "option %s is not currently "
306fa1
 					 "implemented, ignored", $1);
306fa1
 			amd_info(msg_buf);
306fa1
@@ -496,7 +507,9 @@ static int match_map_option_fs_type(char
306fa1
 		   !strcmp(fs_type, "ext3") ||
306fa1
 		   !strcmp(fs_type, "ext4"))
306fa1
 		entry.flags |= AMD_MOUNT_TYPE_EXT;
306fa1
-	} else if (!strcmp(fs_type, "ufs")) {
306fa1
+	else if (!strcmp(fs_type, "program"))
306fa1
+		entry.flags |= AMD_MOUNT_TYPE_PROGRAM;
306fa1
+	else if (!strcmp(fs_type, "ufs")) {
306fa1
 		entry.flags |= AMD_MOUNT_TYPE_UFS;
306fa1
 		entry.type = conf_amd_get_linux_ufs_mount_type();
306fa1
 		if (!entry.type) {
306fa1
@@ -520,7 +533,6 @@ static int match_map_option_fs_type(char
306fa1
 		fs_type = NULL;
306fa1
 	} else if (!strcmp(fs_type, "jfs") ||
306fa1
 		   !strcmp(fs_type, "nfsx") ||
306fa1
-		   !strcmp(fs_type, "program") ||
306fa1
 		   !strcmp(fs_type, "lustre") ||
306fa1
 		   !strcmp(fs_type, "direct")) {
306fa1
 		sprintf(msg_buf, "file system type %s is "
306fa1
@@ -880,6 +892,8 @@ static int add_location(void)
306fa1
 	new->addopts = entry.addopts;
306fa1
 	new->remopts = entry.remopts;
306fa1
 	new->sublink = entry.sublink;
306fa1
+	new->mount = entry.mount;
306fa1
+	new->umount = entry.umount;
306fa1
 	new->selector = entry.selector;
306fa1
 	list_add_tail(&new->list, entries);
306fa1
 	memset(&entry, 0, sizeof(struct amd_entry));
306fa1
--- autofs-5.0.7.orig/modules/parse_amd.c
306fa1
+++ autofs-5.0.7/modules/parse_amd.c
306fa1
@@ -790,6 +790,35 @@ next:
306fa1
 		sv = macro_addvar(sv, "remopts", 7, entry->remopts);
306fa1
 	}
306fa1
 
306fa1
+	if (entry->mount) {
306fa1
+		if (!expand_selectors(ap, entry->mount, &expand, sv)) {
306fa1
+			free(entry->mount);
306fa1
+			if (entry->umount)
306fa1
+				free(entry->umount);
306fa1
+			entry->mount = NULL;
306fa1
+			entry->umount = NULL;
306fa1
+			goto done;
306fa1
+		}
306fa1
+		debug(logopt, MODPREFIX
306fa1
+		      "mount expand(\"%s\") -> %s", entry->mount, expand);
306fa1
+		free(entry->mount);
306fa1
+		entry->mount = expand;
306fa1
+		sv = macro_addvar(sv, "mount", 5, entry->mount);
306fa1
+	}
306fa1
+
306fa1
+	if (entry->umount) {
306fa1
+		if (!expand_selectors(ap, entry->umount, &expand, sv)) {
306fa1
+			free(entry->umount);
306fa1
+			entry->umount = NULL;
306fa1
+			goto done;
306fa1
+		}
306fa1
+		debug(logopt, MODPREFIX
306fa1
+		      "umount expand(\"%s\") -> %s", entry->umount, expand);
306fa1
+		free(entry->umount);
306fa1
+		entry->umount = expand;
306fa1
+		sv = macro_addvar(sv, "umount", 5, entry->umount);
306fa1
+	}
306fa1
+done:
306fa1
 	return sv;
306fa1
 }
306fa1
 
306fa1
@@ -1224,6 +1253,91 @@ out:
306fa1
 	return ret;
306fa1
 }
306fa1
 
306fa1
+static int do_program_mount(struct autofs_point *ap,
306fa1
+			    struct amd_entry *entry, const char *name)
306fa1
+{
306fa1
+	char *prog, *str;
306fa1
+	char **argv;
306fa1
+	int argc = -1;
306fa1
+	int rv = 1;
306fa1
+
306fa1
+	str = strdup(entry->mount);
306fa1
+	if (!str)
306fa1
+		goto out;
306fa1
+
306fa1
+	prog = NULL;
306fa1
+	argv = NULL;
306fa1
+
306fa1
+	argc = construct_argv(str, &prog, &argv);
306fa1
+	if (argc == -1) {
306fa1
+		error(ap->logopt, MODPREFIX
306fa1
+		      "%s: error creating mount arguments", entry->type);
306fa1
+		free(str);
306fa1
+		goto out;
306fa1
+	}
306fa1
+
306fa1
+	/* The am-utils documentation doesn't actually say that the
306fa1
+	 * mount (and umount, if given) command need to use ${fs} as
306fa1
+	 * the mount point in the command.
306fa1
+	 *
306fa1
+	 * For program mounts there's no way to know what the mount
306fa1
+	 * point is so ${fs} must be used in the mount (and umount,
306fa1
+	 * if given) in order to create the mount point directory
306fa1
+	 * before executing the mount command and removing it at
306fa1
+	 * umount.
306fa1
+	 */
306fa1
+	if (ext_mount_inuse(entry->fs)) {
306fa1
+		rv = 0;
306fa1
+		ext_mount_add(&entry->ext_mount, entry->fs, 1);
306fa1
+	} else {
306fa1
+		rv = mkdir_path(entry->fs, 0555);
306fa1
+		if (rv && errno != EEXIST) {
306fa1
+			char *buf[MAX_ERR_BUF];
306fa1
+			char * estr;
306fa1
+
306fa1
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
306fa1
+			error(ap->logopt,
306fa1
+			      MODPREFIX "%s: mkdir_path %s failed: %s",
306fa1
+			      entry->type, entry->fs, estr);
306fa1
+			goto do_free;
306fa1
+		}
306fa1
+
306fa1
+		rv = spawnv(ap->logopt, prog, (const char * const *) argv);
306fa1
+		if (WIFEXITED(rv) && !WEXITSTATUS(rv)) {
306fa1
+			rv = 0;
306fa1
+			ext_mount_add(&entry->ext_mount, entry->fs, 1);
306fa1
+			debug(ap->logopt, MODPREFIX
306fa1
+			      "%s: mounted %s", entry->type, entry->fs);
306fa1
+		} else {
306fa1
+			if (!ext_mount_inuse(entry->fs))
306fa1
+				rmdir_path(ap, entry->fs, ap->dev);
306fa1
+			error(ap->logopt, MODPREFIX
306fa1
+			     "%s: failed to mount using: %s",
306fa1
+			     entry->type, entry->mount);
306fa1
+		}
306fa1
+	}
306fa1
+do_free:
306fa1
+	free_argv(argc, (const char **) argv);
306fa1
+	free(str);
306fa1
+
306fa1
+	if (rv)
306fa1
+		goto out;
306fa1
+
306fa1
+	rv = do_link_mount(ap, name, entry, 0);
306fa1
+	if (!rv)
306fa1
+		goto out;
306fa1
+
306fa1
+	if (umount_amd_ext_mount(ap, entry)) {
306fa1
+		if (!ext_mount_inuse(entry->fs))
306fa1
+			rmdir_path(ap, entry->fs, ap->dev);
306fa1
+		debug(ap->logopt, MODPREFIX
306fa1
+		      "%s: failed to umount external mount at %s",
306fa1
+		      entry->type, entry->fs);
306fa1
+	}
306fa1
+out:
306fa1
+	return rv;
306fa1
+}
306fa1
+
306fa1
 static unsigned int validate_auto_options(unsigned int logopt,
306fa1
 					  struct amd_entry *entry)
306fa1
 {
306fa1
@@ -1350,6 +1464,29 @@ static unsigned int validate_host_option
306fa1
 	return 1;
306fa1
 }
306fa1
 
306fa1
+static unsigned int validate_program_options(unsigned int logopt,
306fa1
+					     struct amd_entry *entry)
306fa1
+{
306fa1
+	/*
306fa1
+	 * entry->mount will be NULL if there is a problem expanding
306fa1
+	 * ${} macros in expandamdent().
306fa1
+	 */
306fa1
+	if (!entry->mount) {
306fa1
+		error(logopt, MODPREFIX
306fa1
+		      "%s: mount program invalid or not set", entry->type);
306fa1
+		return 0;
306fa1
+	}
306fa1
+
306fa1
+	if (!entry->fs && !*entry->fs) {
306fa1
+		error(logopt, MODPREFIX
306fa1
+		    "%s: ${fs} must be used as the mount point but is not set",
306fa1
+		    entry->type);
306fa1
+		return 0;
306fa1
+	}
306fa1
+
306fa1
+	return 1;
306fa1
+}
306fa1
+
306fa1
 static int amd_mount(struct autofs_point *ap, const char *name,
306fa1
 		     struct amd_entry *entry, struct map_source *source,
306fa1
 		     struct substvar *sv, unsigned int flags,
306fa1
@@ -1415,6 +1552,12 @@ static int amd_mount(struct autofs_point
306fa1
 		ret = do_host_mount(ap, name, entry, source, flags);
306fa1
 		break;
306fa1
 
306fa1
+	case AMD_MOUNT_TYPE_PROGRAM:
306fa1
+		if (!validate_program_options(ap->logopt, entry))
306fa1
+			return 1;
306fa1
+		ret = do_program_mount(ap, entry, name);
306fa1
+		break;
306fa1
+
306fa1
 	default:
306fa1
 		info(ap->logopt,
306fa1
 		     MODPREFIX "unkown file system type %x", fstype);