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

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