Blame SOURCES/autofs-5.0.7-add-symlink-pseudo-option.patch

ab3a3d
autofs-5.0.7 - add symlink pseudo option
ab3a3d
ab3a3d
From: Ian Kent <raven@themaw.net>
ab3a3d
ab3a3d
Add a "symlink" pseudo option to tell the bind mount module to symlink
ab3a3d
instead of bind when mounting mounts other than direct mounts and
ab3a3d
non-root indirect mount offset mounts (aka. non-root multi-mount
ab3a3d
entries).
ab3a3d
---
ab3a3d
 CHANGELOG              |    1 +
ab3a3d
 include/automount.h    |    3 +++
ab3a3d
 lib/master_parse.y     |    8 +++++++-
ab3a3d
 lib/master_tok.l       |    1 +
ab3a3d
 man/auto.master.5.in   |    8 ++++++++
ab3a3d
 modules/mount_autofs.c |    5 +++++
ab3a3d
 modules/mount_bind.c   |   36 +++++++++++++++++++++++++++++++++++-
ab3a3d
 7 files changed, 60 insertions(+), 2 deletions(-)
ab3a3d
ab3a3d
diff --git a/CHANGELOG b/CHANGELOG
ab3a3d
index c189483..247d334 100644
ab3a3d
--- a/CHANGELOG
ab3a3d
+++ b/CHANGELOG
ab3a3d
@@ -32,6 +32,7 @@
ab3a3d
 - fix wildcard multi map regression.
ab3a3d
 - fix file descriptor leak when reloading the daemon.
ab3a3d
 - depricate nosymlink pseudo option.
ab3a3d
+- add symlink pseudo option.
ab3a3d
 
ab3a3d
 25/07/2012 autofs-5.0.7
ab3a3d
 =======================
ab3a3d
diff --git a/include/automount.h b/include/automount.h
ab3a3d
index 37541f5..e72fa0d 100644
ab3a3d
--- a/include/automount.h
ab3a3d
+++ b/include/automount.h
ab3a3d
@@ -455,6 +455,9 @@ struct kernel_mod_version {
ab3a3d
 /* Don't use bind mounts even when system supports them */
ab3a3d
 #define MOUNT_FLAG_NOBIND		0x0020
ab3a3d
 
ab3a3d
+/* Use symlinks instead of bind mounting local mounts */
ab3a3d
+#define MOUNT_FLAG_SYMLINK		0x0040
ab3a3d
+
ab3a3d
 struct autofs_point {
ab3a3d
 	pthread_t thid;
ab3a3d
 	char *path;			/* Mount point name */
ab3a3d
diff --git a/lib/master_parse.y b/lib/master_parse.y
ab3a3d
index f925b5a..11caf5b 100644
ab3a3d
--- a/lib/master_parse.y
ab3a3d
+++ b/lib/master_parse.y
ab3a3d
@@ -57,6 +57,7 @@ static char *type;
ab3a3d
 static char *format;
ab3a3d
 static long timeout;
ab3a3d
 static long negative_timeout;
ab3a3d
+static unsigned symlnk;
ab3a3d
 static unsigned nobind;
ab3a3d
 static unsigned ghost;
ab3a3d
 extern unsigned global_selection_options;
ab3a3d
@@ -100,7 +101,7 @@ static int master_fprintf(FILE *, char *, ...);
ab3a3d
 %token COMMENT
ab3a3d
 %token MAP
ab3a3d
 %token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
ab3a3d
-%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT
ab3a3d
+%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK
ab3a3d
 %token COLON COMMA NL DDASH
ab3a3d
 %type <strtype> map
ab3a3d
 %type <strtype> options
ab3a3d
@@ -186,6 +187,7 @@ line:
ab3a3d
 	| PATH OPT_USE_WEIGHT { master_notify($1); YYABORT; }
ab3a3d
 	| PATH OPT_DEBUG { master_notify($1); YYABORT; }
ab3a3d
 	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
ab3a3d
+	| PATH OPT_SYMLINK { master_notify($1); YYABORT; }
ab3a3d
 	| PATH OPT_NOBIND { master_notify($1); YYABORT; }
ab3a3d
 	| PATH OPT_GHOST { master_notify($1); YYABORT; }
ab3a3d
 	| PATH OPT_NOGHOST { master_notify($1); YYABORT; }
ab3a3d
@@ -557,6 +559,7 @@ option: daemon_option
ab3a3d
 
ab3a3d
 daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
ab3a3d
 	| OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
ab3a3d
+	| OPT_SYMLINK	{ symlnk = 1; }
ab3a3d
 	| OPT_NOBIND	{ nobind = 1; }
ab3a3d
 	| OPT_NOGHOST	{ ghost = 0; }
ab3a3d
 	| OPT_GHOST	{ ghost = 1; }
ab3a3d
@@ -627,6 +630,7 @@ static void local_init_vars(void)
ab3a3d
 	debug = 0;
ab3a3d
 	timeout = -1;
ab3a3d
 	negative_timeout = 0;
ab3a3d
+	symlnk = 0;
ab3a3d
 	nobind = 0;
ab3a3d
 	ghost = defaults_get_browse_mode();
ab3a3d
 	random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
ab3a3d
@@ -811,6 +815,8 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
ab3a3d
 		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
ab3a3d
 	if (use_weight)
ab3a3d
 		entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
ab3a3d
+	if (symlnk)
ab3a3d
+		entry->ap->flags |= MOUNT_FLAG_SYMLINK;
ab3a3d
 	if (negative_timeout)
ab3a3d
 		entry->ap->negative_timeout = negative_timeout;
ab3a3d
 
ab3a3d
diff --git a/lib/master_tok.l b/lib/master_tok.l
ab3a3d
index 30abb15..f9b4e55 100644
ab3a3d
--- a/lib/master_tok.l
ab3a3d
+++ b/lib/master_tok.l
ab3a3d
@@ -361,6 +361,7 @@ OPTNTOUT	(-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeo
ab3a3d
 		return(NUMBER);
ab3a3d
 	}
ab3a3d
 
ab3a3d
+	-?symlink		{ return(OPT_SYMLINK); }
ab3a3d
 	-?nobind		{ return(OPT_NOBIND); }
ab3a3d
 	-?nobrowse		{ return(OPT_NOGHOST); }
ab3a3d
 	-g|--ghost|-?browse	{ return(OPT_GHOST); }
ab3a3d
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
ab3a3d
index 8007542..bbea43a 100644
ab3a3d
--- a/man/auto.master.5.in
ab3a3d
+++ b/man/auto.master.5.in
ab3a3d
@@ -159,6 +159,14 @@ on individual map entries of both types. Bind mounting of NFS file
ab3a3d
 systems can also be prevented for specific map entrys by adding the
ab3a3d
 "port=" mount option to the entries.
ab3a3d
 .TP
ab3a3d
+.I "symlink"
ab3a3d
+This option makes bind mounting use a symlink instead of an actual bind
ab3a3d
+mount. It is an autofs specific option that is a pseudo mount option and
ab3a3d
+so is given without a leading dash. It may be used with indirect map
ab3a3d
+entries only, either in the master map (so it effects all map entries)
ab3a3d
+or with individual map entries. The option is ignored for direct mounts
ab3a3d
+and non-root offest mount entries.
ab3a3d
+.TP
ab3a3d
 .I "\-r, \-\-random-multimount-selection"
ab3a3d
 Enables the use of ramdom selection when choosing a host from a
ab3a3d
 list of replicated servers. This option is applied to this mount
ab3a3d
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
ab3a3d
index ef16020..8c1e600 100644
ab3a3d
--- a/modules/mount_autofs.c
ab3a3d
+++ b/modules/mount_autofs.c
ab3a3d
@@ -51,6 +51,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
ab3a3d
 	int argc, status;
ab3a3d
 	int nobind = ap->flags & MOUNT_FLAG_NOBIND;
ab3a3d
 	int ghost = ap->flags & MOUNT_FLAG_GHOST;
ab3a3d
+	int symlnk = ap->flags & MOUNT_FLAG_SYMLINK;
ab3a3d
 	time_t timeout = ap->entry->maps->exp_timeout;
ab3a3d
 	unsigned logopt = ap->logopt;
ab3a3d
 	struct map_type_info *info;
ab3a3d
@@ -120,6 +121,8 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
ab3a3d
 				nobind = 1;
ab3a3d
 			else if (strncmp(cp, "browse", 6) == 0)
ab3a3d
 				ghost = 1;
ab3a3d
+			else if (strncmp(cp, "symlink", 7) == 0)
ab3a3d
+				symlnk = 1;
ab3a3d
 			else if (strncmp(cp, "timeout=", 8) == 0) {
ab3a3d
 				char *val = strchr(cp, '=');
ab3a3d
 				unsigned tout;
ab3a3d
@@ -158,6 +161,8 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
ab3a3d
 	}
ab3a3d
 	nap = entry->ap;
ab3a3d
 	nap->parent = ap;
ab3a3d
+	if (symlnk)
ab3a3d
+		nap->flags |= MOUNT_FLAG_SYMLINK;
ab3a3d
 
ab3a3d
 	argc = 1;
ab3a3d
 
ab3a3d
diff --git a/modules/mount_bind.c b/modules/mount_bind.c
ab3a3d
index 9bce686..4975294 100644
ab3a3d
--- a/modules/mount_bind.c
ab3a3d
+++ b/modules/mount_bind.c
ab3a3d
@@ -73,10 +73,44 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
ab3a3d
 	char buf[MAX_ERR_BUF];
ab3a3d
 	int err;
ab3a3d
 	int i, len;
ab3a3d
+	int symlnk = (*name != '/' && (ap->flags & MOUNT_FLAG_SYMLINK));
ab3a3d
 
ab3a3d
 	if (ap->flags & MOUNT_FLAG_REMOUNT)
ab3a3d
 		return 0;
ab3a3d
 
ab3a3d
+	/* Extract "symlink" pseudo-option which forces local filesystems
ab3a3d
+	 * to be symlinked instead of bound.
ab3a3d
+	 */
ab3a3d
+	if (*name != '/' && !symlnk && options) {
ab3a3d
+		const char *comma;
ab3a3d
+		int o_len = strlen(options) + 1;
ab3a3d
+
ab3a3d
+		for (comma = options; *comma != '\0';) {
ab3a3d
+			const char *cp;
ab3a3d
+			const char *end;
ab3a3d
+
ab3a3d
+			while (*comma == ',')
ab3a3d
+				comma++;
ab3a3d
+
ab3a3d
+			/* Skip leading white space */
ab3a3d
+			while (*comma == ' ' || *comma == '\t')
ab3a3d
+				comma++;
ab3a3d
+
ab3a3d
+			cp = comma;
ab3a3d
+			while (*comma != '\0' && *comma != ',')
ab3a3d
+				comma++;
ab3a3d
+
ab3a3d
+			/* Skip trailing white space */
ab3a3d
+			end = comma - 1;
ab3a3d
+			while (*comma == ' ' || *comma == '\t')
ab3a3d
+				end--;
ab3a3d
+
ab3a3d
+			o_len = end - cp + 1;
ab3a3d
+			if (strncmp("symlink", cp, o_len) == 0)
ab3a3d
+				symlnk = 1;
ab3a3d
+		}
ab3a3d
+	}
ab3a3d
+
ab3a3d
 	/* Root offset of multi-mount */
ab3a3d
 	len = strlen(root);
ab3a3d
 	if (root[len - 1] == '/') {
ab3a3d
@@ -100,7 +134,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
ab3a3d
 	if (options == NULL || *options == '\0')
ab3a3d
 		options = "defaults";
ab3a3d
 
ab3a3d
-	if (bind_works) {
ab3a3d
+	if (!symlnk && bind_works) {
ab3a3d
 		int status, existed = 1;
ab3a3d
 
ab3a3d
 		debug(ap->logopt, MODPREFIX "calling mkdir_path %s", fullpath);