Blame SOURCES/autofs-5.0.7-teach-dumpmaps-to-output-simple-key-value-pairs.patch

ab3a3d
autofs-5.0.7 - teach dumpmaps to output simple key value pairs
ab3a3d
ab3a3d
From: Ian Kent <raven@themaw.net>
ab3a3d
ab3a3d
The dumpmaps option doesn't allow maps to be output in <key, value>
ab3a3d
pairs suitable for use as a file map.
ab3a3d
ab3a3d
This could be useful to save current maps as a backup for emergency
ab3a3d
use.
ab3a3d
ab3a3d
If the dumpmaps option is given and is followed by two parameters,
ab3a3d
"<map type> <map name>" then simple <key, value> pairs that would
ab3a3d
be read in by a map read are printed to stdout if the given map type
ab3a3d
and map name are found in the map configuration.
ab3a3d
ab3a3d
If the map is an LDAP map and there is more than one map of same name
ab3a3d
in different base dns only the first map encountered by autofs will
ab3a3d
be listed.
ab3a3d
ab3a3d
If the map type is an old style multi-map and any one of the map
ab3a3d
names in the multi-map entry matches the given map name the entries
ab3a3d
that would be used by autofs for the whole multi-map will be listed.
ab3a3d
---
ab3a3d
 CHANGELOG          |    1 
ab3a3d
 daemon/automount.c |   56 ++++++++++++---
ab3a3d
 include/master.h   |    1 
ab3a3d
 lib/master.c       |  187 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ab3a3d
 man/automount.8    |   20 +++++
ab3a3d
 5 files changed, 250 insertions(+), 15 deletions(-)
ab3a3d
ab3a3d
--- autofs-5.0.7.orig/CHANGELOG
ab3a3d
+++ autofs-5.0.7/CHANGELOG
ab3a3d
@@ -60,6 +60,7 @@
ab3a3d
 - fix fix wildcard multi map regression.
ab3a3d
 - fix dumpmaps multi output.
ab3a3d
 - try and cleanup after dumpmaps.
ab3a3d
+- teach dumpmaps to output simple key value pairs.
ab3a3d
 
ab3a3d
 25/07/2012 autofs-5.0.7
ab3a3d
 =======================
ab3a3d
--- autofs-5.0.7.orig/daemon/automount.c
ab3a3d
+++ autofs-5.0.7/daemon/automount.c
ab3a3d
@@ -1725,7 +1725,8 @@ static void usage(void)
ab3a3d
 		"	-f --foreground do not fork into background\n"
ab3a3d
 		"	-r --random-multimount-selection\n"
ab3a3d
 		"			use ramdom replicated server selection\n"
ab3a3d
-		"	-m --dumpmaps	dump automounter maps and exit\n"
ab3a3d
+		"	-m --dumpmaps [<map type> <map name>]\n"
ab3a3d
+		"			dump automounter maps and exit\n"
ab3a3d
 		"	-n --negative-timeout n\n"
ab3a3d
 		"			set the timeout for failed key lookups.\n"
ab3a3d
 		"	-O --global-options\n"
ab3a3d
@@ -2125,22 +2126,33 @@ int main(int argc, char *argv[])
ab3a3d
 			program);
ab3a3d
 #endif
ab3a3d
 
ab3a3d
-	if (argc == 0)
ab3a3d
-		master_list = master_new(NULL, timeout, ghost);
ab3a3d
-	else
ab3a3d
-		master_list = master_new(argv[0], timeout, ghost);
ab3a3d
-
ab3a3d
-	if (!master_list) {
ab3a3d
-		printf("%s: can't create master map %s", program, argv[0]);
ab3a3d
-		exit(1);
ab3a3d
-	}
ab3a3d
-
ab3a3d
 	if (dumpmaps) {
ab3a3d
 		struct master_mapent *entry;
ab3a3d
 		struct list_head *head, *p;
ab3a3d
 		struct mapent_cache *nc;
ab3a3d
+		const char *type = NULL;
ab3a3d
+		const char *name = NULL;
ab3a3d
+		const char *master = NULL;
ab3a3d
+
ab3a3d
+		if (argc > 0) {
ab3a3d
+			if (argc >= 2) {
ab3a3d
+				type = argv[0];
ab3a3d
+				name = argv[1];
ab3a3d
+			}
ab3a3d
+			if (argc == 3)
ab3a3d
+				master = argv[2];
ab3a3d
+		}
ab3a3d
 
ab3a3d
-		open_log();
ab3a3d
+		if (master)
ab3a3d
+			master_list = master_new(NULL, timeout, ghost);
ab3a3d
+		else
ab3a3d
+			master_list = master_new(master, timeout, ghost);
ab3a3d
+		if (!master_list) {
ab3a3d
+			printf("%s: can't create master map", program);
ab3a3d
+			exit(1);
ab3a3d
+		}
ab3a3d
+
ab3a3d
+		log_to_stderr();
ab3a3d
 
ab3a3d
 		master_init_scan();
ab3a3d
 
ab3a3d
@@ -2153,7 +2165,15 @@ int main(int argc, char *argv[])
ab3a3d
 		master_list->nc = nc;
ab3a3d
 
ab3a3d
 		lookup_nss_read_master(master_list, 0);
ab3a3d
-		master_show_mounts(master_list);
ab3a3d
+		if (type) {
ab3a3d
+			const char *map = basename(name);
ab3a3d
+			if (!map)
ab3a3d
+				printf("%s: invalid map name %s\n",
ab3a3d
+					program, name);
ab3a3d
+			else
ab3a3d
+				dump_map(master_list, type, map);
ab3a3d
+		} else
ab3a3d
+			master_show_mounts(master_list);
ab3a3d
 
ab3a3d
 		head = &master_list->mounts;
ab3a3d
 		p = head->next;
ab3a3d
@@ -2168,6 +2188,16 @@ int main(int argc, char *argv[])
ab3a3d
 		exit(0);
ab3a3d
 	}
ab3a3d
 
ab3a3d
+	if (argc == 0)
ab3a3d
+		master_list = master_new(NULL, timeout, ghost);
ab3a3d
+	else
ab3a3d
+		master_list = master_new(argv[0], timeout, ghost);
ab3a3d
+
ab3a3d
+	if (!master_list) {
ab3a3d
+		printf("%s: can't create master map %s", program, argv[0]);
ab3a3d
+		exit(1);
ab3a3d
+	}
ab3a3d
+
ab3a3d
 	become_daemon(foreground, daemon_check);
ab3a3d
 
ab3a3d
 	if (pthread_attr_init(&th_attr)) {
ab3a3d
--- autofs-5.0.7.orig/include/master.h
ab3a3d
+++ autofs-5.0.7/include/master.h
ab3a3d
@@ -112,6 +112,7 @@ int master_submount_list_empty(struct au
ab3a3d
 int master_notify_submount(struct autofs_point *, const char *path, enum states);
ab3a3d
 void master_notify_state_change(struct master *, int);
ab3a3d
 int master_mount_mounts(struct master *, time_t, int);
ab3a3d
+int dump_map(struct master *, const char *, const char *);
ab3a3d
 int master_show_mounts(struct master *);
ab3a3d
 extern inline unsigned int master_get_logopt(void);
ab3a3d
 int master_list_empty(struct master *);
ab3a3d
--- autofs-5.0.7.orig/lib/master.c
ab3a3d
+++ autofs-5.0.7/lib/master.c
ab3a3d
@@ -1329,6 +1329,193 @@ static void print_map_info(struct map_so
ab3a3d
 	return;
ab3a3d
 }
ab3a3d
 
ab3a3d
+static int match_type(const char *source, const char *type)
ab3a3d
+{
ab3a3d
+	if (!strcmp(source, type))
ab3a3d
+		return 1;
ab3a3d
+	/* Sources file and files are synonymous */
ab3a3d
+	if (!strncmp(source, type, 4) && (strlen(source) <= 5))
ab3a3d
+		return 1;
ab3a3d
+	return 0;
ab3a3d
+}
ab3a3d
+
ab3a3d
+static char *get_map_name(const char *string)
ab3a3d
+{
ab3a3d
+	char *name, *tmp;
ab3a3d
+	char *start, *end, *base;
ab3a3d
+
ab3a3d
+	tmp = strdup(string);
ab3a3d
+	if (!tmp) {
ab3a3d
+		printf("error: allocation failure: %s\n", strerror(errno));
ab3a3d
+		return NULL;
ab3a3d
+	}
ab3a3d
+
ab3a3d
+	base = basename(tmp);
ab3a3d
+	end = strchr(base, ',');
ab3a3d
+	if (end)
ab3a3d
+		*end = '\0';
ab3a3d
+	start = strchr(tmp, '=');
ab3a3d
+	if (start)
ab3a3d
+		start++;
ab3a3d
+	else {
ab3a3d
+		char *colon = strrchr(base, ':');
ab3a3d
+		if (colon)
ab3a3d
+			start = ++colon;
ab3a3d
+		else
ab3a3d
+			start = base;
ab3a3d
+	}
ab3a3d
+
ab3a3d
+	name = strdup(start);
ab3a3d
+	if (!name)
ab3a3d
+		printf("error: allocation failure: %s\n", strerror(errno));
ab3a3d
+	free(tmp);
ab3a3d
+
ab3a3d
+	return name;
ab3a3d
+}
ab3a3d
+
ab3a3d
+static int match_name(struct map_source *source, const char *name)
ab3a3d
+{
ab3a3d
+	int argc = source->argc;
ab3a3d
+	int ret = 0;
ab3a3d
+	int i;
ab3a3d
+
ab3a3d
+	/*
ab3a3d
+	 * This can't work for old style "multi" type sources since
ab3a3d
+	 * there's no way to know from which map the cache entry came
ab3a3d
+	 * from and duplicate entries are ignored at map read time.
ab3a3d
+	 * All we can really do is list all the entries for the given
ab3a3d
+	 * multi map if one of its map names matches.
ab3a3d
+	 */
ab3a3d
+	for (i = 0; i < argc; i++) {
ab3a3d
+		if (i == 0 || !strcmp(source->argv[i], "--")) {
ab3a3d
+			if (i != 0) {
ab3a3d
+				i++;
ab3a3d
+				if (i >= argc)
ab3a3d
+					break;
ab3a3d
+			}
ab3a3d
+
ab3a3d
+			if (source->argv[i] && *source->argv[i] != '-') {
ab3a3d
+				char *map = get_map_name(source->argv[i]);
ab3a3d
+				if (!map)
ab3a3d
+					break;
ab3a3d
+				if (!strcmp(map, name)) {
ab3a3d
+					ret = 1;
ab3a3d
+					free(map);
ab3a3d
+					break;
ab3a3d
+				}
ab3a3d
+				free(map);
ab3a3d
+			}
ab3a3d
+		}
ab3a3d
+	}
ab3a3d
+
ab3a3d
+	return ret;
ab3a3d
+}
ab3a3d
+
ab3a3d
+int dump_map(struct master *master, const char *type, const char *name)
ab3a3d
+{
ab3a3d
+	struct list_head *p, *head;
ab3a3d
+
ab3a3d
+	if (list_empty(&master->mounts)) {
ab3a3d
+		printf("no master map entries found\n");
ab3a3d
+		return 1;
ab3a3d
+	}
ab3a3d
+
ab3a3d
+	head = &master->mounts;
ab3a3d
+	p = head->next;
ab3a3d
+	while (p != head) {
ab3a3d
+		struct map_source *source;
ab3a3d
+		struct master_mapent *this;
ab3a3d
+		struct autofs_point *ap;
ab3a3d
+		time_t now = time(NULL);
ab3a3d
+
ab3a3d
+		this = list_entry(p, struct master_mapent, list);
ab3a3d
+		p = p->next;
ab3a3d
+
ab3a3d
+		ap = this->ap;
ab3a3d
+
ab3a3d
+		/*
ab3a3d
+		 * Ensure we actually read indirect map entries so we can
ab3a3d
+		 * list them. The map reads won't read any indirect map
ab3a3d
+		 * entries (other than those in a file map) unless the
ab3a3d
+		 * browse option is set.
ab3a3d
+		 */
ab3a3d
+		if (ap->type == LKP_INDIRECT)
ab3a3d
+			ap->flags |= MOUNT_FLAG_GHOST;
ab3a3d
+
ab3a3d
+		/* Read the map content into the cache */
ab3a3d
+		if (lookup_nss_read_map(ap, NULL, now))
ab3a3d
+			lookup_prune_cache(ap, now);
ab3a3d
+		else {
ab3a3d
+			printf("failed to read map\n");
ab3a3d
+			lookup_close_lookup(ap);
ab3a3d
+			continue;
ab3a3d
+		}
ab3a3d
+
ab3a3d
+		if (!this->maps) {
ab3a3d
+			printf("no map sources found for %s\n", ap->path);
ab3a3d
+			lookup_close_lookup(ap);
ab3a3d
+			continue;
ab3a3d
+		}
ab3a3d
+
ab3a3d
+		source = this->maps;
ab3a3d
+		while (source) {
ab3a3d
+			struct map_source *instance;
ab3a3d
+			struct mapent *me;
ab3a3d
+
ab3a3d
+			instance = NULL;
ab3a3d
+			if (source->type) {
ab3a3d
+				if (!match_type(source->type, type)) {
ab3a3d
+					source = source->next;
ab3a3d
+					continue;
ab3a3d
+				}
ab3a3d
+				if (!match_name(source, name)) {
ab3a3d
+					source = source->next;
ab3a3d
+					continue;
ab3a3d
+				}
ab3a3d
+				instance = source;
ab3a3d
+			} else {
ab3a3d
+				struct map_source *map;
ab3a3d
+
ab3a3d
+				map = source->instance;
ab3a3d
+				while (map) {
ab3a3d
+					if (!match_type(map->type, type)) {
ab3a3d
+						map = map->next;
ab3a3d
+						continue;
ab3a3d
+					}
ab3a3d
+					if (!match_name(map, name)) {
ab3a3d
+						map = map->next;
ab3a3d
+						continue;
ab3a3d
+					}
ab3a3d
+					instance = map;
ab3a3d
+					break;
ab3a3d
+				}
ab3a3d
+			}
ab3a3d
+
ab3a3d
+			if (!instance) {
ab3a3d
+				source = source->next;
ab3a3d
+				lookup_close_lookup(ap);
ab3a3d
+				continue;
ab3a3d
+			}
ab3a3d
+
ab3a3d
+			me = cache_lookup_first(source->mc);
ab3a3d
+			if (!me)
ab3a3d
+				printf("no keys found in map\n");
ab3a3d
+			else {
ab3a3d
+				do {
ab3a3d
+					if (me->source == instance)
ab3a3d
+						printf("%s\t%s\n", me->key, me->mapent);
ab3a3d
+				} while ((me = cache_lookup_next(source->mc, me)));
ab3a3d
+			}
ab3a3d
+
ab3a3d
+			lookup_close_lookup(ap);
ab3a3d
+			return 1;
ab3a3d
+		}
ab3a3d
+		lookup_close_lookup(ap);
ab3a3d
+	}
ab3a3d
+
ab3a3d
+	return 0;
ab3a3d
+}
ab3a3d
+
ab3a3d
 int master_show_mounts(struct master *master)
ab3a3d
 {
ab3a3d
 	struct list_head *p, *head;
ab3a3d
--- autofs-5.0.7.orig/man/automount.8
ab3a3d
+++ autofs-5.0.7/man/automount.8
ab3a3d
@@ -57,8 +57,24 @@ Run the daemon in the foreground and log
ab3a3d
 Enables the use of ramdom selection when choosing a host from a
ab3a3d
 list of replicated servers.
ab3a3d
 .TP
ab3a3d
-.I "\-m, \-\-dumpmaps"
ab3a3d
-Dump configured automounter maps, then exit.
ab3a3d
+.I "\-m, \-\-dumpmaps [<map type> <map name>]"
ab3a3d
+With no parameters, list information about the configured automounter
ab3a3d
+maps, then exit.
ab3a3d
+
ab3a3d
+If the dumpmaps option is given and is followed by two parameters,
ab3a3d
+"<map type> <map name>" then simple "<key, value>" pairs that would
ab3a3d
+be read in by a map read are printed to stdout if the given map type
ab3a3d
+and map name are found in the map configuration.
ab3a3d
+
ab3a3d
+If the map is an LDAP map and there is more than one map of same name
ab3a3d
+in different base dns only the first map encountered by autofs will
ab3a3d
+be listed. Similarly, if the map is a file map and there is more than
ab3a3d
+one map of the same name in different directories, only the first map
ab3a3d
+encountered will be listed.
ab3a3d
+
ab3a3d
+If the map type is an old style multi-map and any one of the map
ab3a3d
+names in the multi-map entry matches the given map name the entries
ab3a3d
+that would be used by autofs for the whole multi-map will be listed.
ab3a3d
 .TP
ab3a3d
 .I "\-O, \-\-global-options"
ab3a3d
 Allows the specification of global mount options used for all master