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

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