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

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