Blob Blame History Raw
autofs-5.0.7 - allow use of hosts map in maps

From: Ian Kent <raven@themaw.net>

At the moment the internal hosts map can only be use as an entry in the
master map but there's no reason (I can think of so far) that it shouldn't
be possible to use it in map entries.
---
 lib/parse_subs.c       |   17 ++++++-----
 modules/mount_autofs.c |   29 ++++++++++++++++----
 modules/parse_sun.c    |   71 +++++++++++++++++++++++++++++++------------------
 3 files changed, 80 insertions(+), 37 deletions(-)

--- autofs-5.0.7.orig/lib/parse_subs.c
+++ autofs-5.0.7/lib/parse_subs.c
@@ -35,6 +35,7 @@ static struct types map_type[] = {
 	{ "ldaps", 5 },
 	{ "hesiod", 6 },
 	{ "userdir", 7 },
+	{ "hosts", 5 },
 };
 static unsigned int map_type_count = sizeof(map_type)/sizeof(struct types);
 
@@ -384,7 +385,7 @@ struct map_type_info *parse_map_type_inf
 					return NULL;
 				} else {
 					*pos++ = '\0';
-					while (*pos == ' ')
+					while (*pos && *pos == ' ')
 						*pos++ = '\0';
 					map = pos;
 					break;
@@ -412,7 +413,7 @@ struct map_type_info *parse_map_type_inf
 							return NULL;
 						} else {
 							*pos++ = '\0';
-							while (*pos == ' ')
+							while (*pos && *pos == ' ')
 								*pos++ = '\0';
 							map = pos;
 							break;
@@ -458,11 +459,13 @@ struct map_type_info *parse_map_type_inf
 		}
 	}
 
-	info->map = strdup(map);
-	if (!info->map) {
-		free(buf);
-		free_map_type_info(info);
-		return NULL;
+	if (map) {
+		info->map = strdup(map);
+		if (!info->map) {
+			free(buf);
+			free_map_type_info(info);
+			return NULL;
+		}
 	}
 
 	free(buf);
--- autofs-5.0.7.orig/modules/mount_autofs.c
+++ autofs-5.0.7/modules/mount_autofs.c
@@ -62,6 +62,7 @@ int mount_mount(struct autofs_point *ap,
 	char buf[MAX_ERR_BUF];
 	char *options, *p;
 	int len, ret;
+	int hosts = 0;
 
 	/* Root offset of multi-mount */
 	len = strlen(root);
@@ -123,6 +124,8 @@ int mount_mount(struct autofs_point *ap,
 				ghost = 1;
 			else if (strncmp(cp, "symlink", 7) == 0)
 				symlnk = 1;
+			else if (strncmp(cp, "hosts", 5) == 0)
+				hosts = 1;
 			else if (strncmp(cp, "timeout=", 8) == 0) {
 				char *val = strchr(cp, '=');
 				unsigned tout;
@@ -164,7 +167,10 @@ int mount_mount(struct autofs_point *ap,
 	if (symlnk)
 		nap->flags |= MOUNT_FLAG_SYMLINK;
 
-	argc = 1;
+	if (hosts)
+		argc = 0;
+	else
+		argc = 1;
 
 	if (options) {
 		char *t = options;
@@ -176,14 +182,27 @@ int mount_mount(struct autofs_point *ap,
 	}
 	argv = (const char **) alloca((argc + 1) * sizeof(char *));
 
-	argc = 1;
-
-	if (!(info = parse_map_type_info(what))) {
+	if (hosts)
+		argc = 0;
+	else
+		argc = 1;
+
+	/*
+	 * If a mount of a hosts map is being requested it will come
+	 * ro us via the options. Catch that below when processing the
+	 * option and create type info struct then.
+	 */
+	if (hosts)
+		info = parse_map_type_info("hosts:");
+	else
+		info = parse_map_type_info(what);
+	if (!info) {
 		error(ap->logopt, MODPREFIX "failed to parse map info");
 		master_free_mapent(entry);
 		return 1;
 	}
-	argv[0] = info->map;
+	if (info->map)
+		argv[0] = info->map;
 
 	if (options) {
 		p = options;
--- autofs-5.0.7.orig/modules/parse_sun.c
+++ autofs-5.0.7/modules/parse_sun.c
@@ -695,14 +695,18 @@ static int sun_mount(struct autofs_point
 		rv = mount_nfs->mount_mount(ap, root, mountpoint, strlen(mountpoint),
 					    what, fstype, options, mount_nfs->context);
 	} else {
-		what = alloca(loclen + 1);
-		if (*loc == ':') {
-			loclen--;
-			memcpy(what, loc + 1, loclen);
-			what[loclen] = '\0';
-		} else {
-			memcpy(what, loc, loclen);
-			what[loclen] = '\0';
+		if (!loclen)
+			what = NULL;
+		else {
+			what = alloca(loclen + 1);
+			if (*loc == ':') {
+				loclen--;
+				memcpy(what, loc + 1, loclen);
+				what[loclen] = '\0';
+			} else {
+				memcpy(what, loc, loclen);
+				what[loclen] = '\0';
+			}
 		}
 
 		debug(ap->logopt, MODPREFIX
@@ -799,7 +803,8 @@ update_offset_entry(struct autofs_point
 
 	mc = source->mc;
 
-	if (!*path || !*loc) {
+	/* Internal hosts map may have loc == NULL */
+	if (!*path) {
 		error(ap->logopt,
 		      MODPREFIX "syntax error in offset %s -> %s", path, loc);
 		return CHE_FAIL;
@@ -833,8 +838,10 @@ update_offset_entry(struct autofs_point
 	if (*myoptions) {
 		strcpy(m_mapent, "-");
 		strcat(m_mapent, myoptions);
-		strcat(m_mapent, " ");
-		strcat(m_mapent, loc);
+		if (loc) {
+			strcat(m_mapent, " ");
+			strcat(m_mapent, loc);
+		}
 	} else
 		strcpy(m_mapent, loc);
 
@@ -1435,13 +1442,17 @@ int parse_mount(struct autofs_point *ap,
 
 			l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
 			if (!l) {
-				cache_delete_offset_list(mc, name);
-				cache_multi_unlock(me);
-				cache_unlock(mc);
-				free(path);
-				free(options);
-				pthread_setcancelstate(cur_state, NULL);
-				return 1;
+				if (!(strstr(myoptions, "fstype=autofs") &&
+				      strstr(myoptions, "hosts"))) {
+					error(LOGOPT_ANY, "I think I'm a hosts map? l %d", l);
+					cache_delete_offset_list(mc, name);
+					cache_multi_unlock(me);
+					cache_unlock(mc);
+					free(path);
+					free(options);
+					pthread_setcancelstate(cur_state, NULL);
+					return 1;
+				}
 			}
 
 			p += l;
@@ -1592,13 +1603,23 @@ int parse_mount(struct autofs_point *ap,
 			p = skipspace(p);
 		}
 
-		loclen = strlen(loc);
-		if (loclen == 0) {
-			free(loc);
-			free(options);
-			error(ap->logopt,
-			      MODPREFIX "entry %s is empty!", name);
-			return 1;
+		/*
+		 * If options are asking for a hosts map loc should be
+		 * NULL but we see it can contain junk, so ....
+		 */
+		if ((strstr(options, "fstype=autofs") &&
+		     strstr(options, "hosts"))) {
+			loc = NULL;
+			loclen = 0;
+		} else {
+			loclen = strlen(loc);
+			if (loclen == 0) {
+				free(loc);
+				free(options);
+				error(ap->logopt,
+				      MODPREFIX "entry %s is empty!", name);
+				return 1;
+			}
 		}
 
 		debug(ap->logopt,