Blame SOURCES/autofs-5.1.0-beta1-fix-multi-entry-ldap-option-handling.patch

6bbd11
autofs-5.1.0-beta1 - fix multi entry ldap option handling
6bbd11
6bbd11
From: Ian Kent <raven@themaw.net>
6bbd11
6bbd11
Handling new and old configurations presents special problems for
6bbd11
configuration entries that may have repeated values, such as ldap_uris
6bbd11
and ldap_search_base, which can be overridden when the old configuration
6bbd11
is read.
6bbd11
6bbd11
If entries exist in the new configuration they need to be saved and
6bbd11
restored if there's no entries in the old configuration or, if entries
6bbd11
exist in the old configuration, they need to be discarded.
6bbd11
---
6bbd11
 CHANGELOG      |    1 
6bbd11
 lib/defaults.c |  241 ++++++++++++++++++++++++++++++++++++++++++++++-----------
6bbd11
 2 files changed, 198 insertions(+), 44 deletions(-)
6bbd11
6bbd11
--- autofs-5.0.7.orig/CHANGELOG
6bbd11
+++ autofs-5.0.7/CHANGELOG
6bbd11
@@ -122,6 +122,7 @@
6bbd11
 - fix typo in conf_load_autofs_defaults().
6bbd11
 - fix hash on confg option add and delete.
6bbd11
 - add plus to path match pattern.
6bbd11
+- fix multi entry ldap option handling.
6bbd11
 
6bbd11
 25/07/2012 autofs-5.0.7
6bbd11
 =======================
6bbd11
--- autofs-5.0.7.orig/lib/defaults.c
6bbd11
+++ autofs-5.0.7/lib/defaults.c
6bbd11
@@ -916,83 +916,236 @@ static int read_config(unsigned int to_s
6bbd11
 	return 0;
6bbd11
 }
6bbd11
 
6bbd11
-/*
6bbd11
- * Read config env variables and check they have been set.
6bbd11
- *
6bbd11
- * This simple minded routine assumes the config file
6bbd11
- * is valid bourne shell script without spaces around "="
6bbd11
- * and that it has valid values.
6bbd11
- */
6bbd11
-unsigned int defaults_read_config(unsigned int to_syslog)
6bbd11
+struct conf_option *save_ldap_option_list(const char *key)
6bbd11
 {
6bbd11
-	FILE *f;
6bbd11
-	struct stat stb;
6bbd11
-	int ret;
6bbd11
+	struct conf_option *co, *head, *this, *last;
6bbd11
+	unsigned int size = CFG_TABLE_SIZE;
6bbd11
+	u_int32_t key_hash;
6bbd11
+
6bbd11
+	key_hash = get_hash(key, size);
6bbd11
+	co = config->hash[key_hash];
6bbd11
+	if (!co)
6bbd11
+		return NULL;
6bbd11
+	last = co;
6bbd11
+
6bbd11
+	head = this = NULL;
6bbd11
+	while (co) {
6bbd11
+		if (strcasecmp(autofs_gbl_sec, co->section)) {
6bbd11
+			last = co;
6bbd11
+			goto next;
6bbd11
+		}
6bbd11
 
6bbd11
-	pthread_mutex_lock(&conf_mutex);
6bbd11
-	if (!config) {
6bbd11
-		if (conf_init()) {
6bbd11
-			pthread_mutex_unlock(&conf_mutex);
6bbd11
-			message(to_syslog, "failed to init config");
6bbd11
-			return 0;
6bbd11
+		if (!strcasecmp(co->name, key)) {
6bbd11
+			/* Unlink from old */
6bbd11
+			if (co == config->hash[key_hash])
6bbd11
+				config->hash[key_hash] = co->next;
6bbd11
+			else
6bbd11
+				last->next = co->next;
6bbd11
+			last = co->next;
6bbd11
+			co->next = NULL;
6bbd11
+			/* Add to new */
6bbd11
+			if (this)
6bbd11
+				this->next = co;
6bbd11
+			this = co;
6bbd11
+			/* If none have been found yet */
6bbd11
+			if (!head)
6bbd11
+				head = co;
6bbd11
+			co = last;
6bbd11
+			continue;
6bbd11
 		}
6bbd11
+next:
6bbd11
+		co = co->next;
6bbd11
+	}
6bbd11
+
6bbd11
+	return head;
6bbd11
+}
6bbd11
+
6bbd11
+void restore_ldap_option_list(struct conf_option *list)
6bbd11
+{
6bbd11
+	struct conf_option *co, *this, *last;
6bbd11
+	unsigned int size = CFG_TABLE_SIZE;
6bbd11
+	u_int32_t key_hash;
6bbd11
+
6bbd11
+	if (!list)
6bbd11
+		return;
6bbd11
+
6bbd11
+	this = list;
6bbd11
+	while (this) {
6bbd11
+		last = this;
6bbd11
+		this = this->next;
6bbd11
+	}
6bbd11
+
6bbd11
+	key_hash = get_hash(list->name, size);
6bbd11
+	co = config->hash[key_hash];
6bbd11
+	config->hash[key_hash] = list;
6bbd11
+	if (co)
6bbd11
+		last->next = co;
6bbd11
+
6bbd11
+	return;
6bbd11
+}
6bbd11
+
6bbd11
+void free_ldap_option_list(struct conf_option *list)
6bbd11
+{
6bbd11
+	struct conf_option *next, *this;
6bbd11
+
6bbd11
+	if (!list)
6bbd11
+		return;
6bbd11
+
6bbd11
+	this = list;
6bbd11
+	while (this) {
6bbd11
+		next = this->next;
6bbd11
+		free(this->section);
6bbd11
+		free(this->name);
6bbd11
+		free(this->value);
6bbd11
+		free(this);
6bbd11
+		this = next;
6bbd11
 	}
6bbd11
 
6bbd11
-	/* Set configuration to defaults */
6bbd11
+	return;
6bbd11
+}
6bbd11
+
6bbd11
+static void clean_ldap_multi_option(const char *key)
6bbd11
+{
6bbd11
+	const char *sec = autofs_gbl_sec;
6bbd11
+	struct conf_option *co;
6bbd11
+
6bbd11
+	while ((co = conf_lookup(sec, key)))
6bbd11
+		conf_delete(co->section, co->name);
6bbd11
+
6bbd11
+	return;
6bbd11
+}
6bbd11
+
6bbd11
+static int reset_defaults(unsigned int to_syslog)
6bbd11
+{
6bbd11
+	int ret;
6bbd11
+
6bbd11
 	ret = conf_load_autofs_defaults();
6bbd11
 	if (!ret) {
6bbd11
-		pthread_mutex_unlock(&conf_mutex);
6bbd11
 		message(to_syslog, "failed to reset autofs default config");
6bbd11
 		return 0;
6bbd11
 	}
6bbd11
 
6bbd11
 	ret = conf_load_amd_defaults();
6bbd11
 	if (!ret) {
6bbd11
-		pthread_mutex_unlock(&conf_mutex);
6bbd11
 		message(to_syslog, "failed to reset amd default config");
6bbd11
 		return 0;
6bbd11
 	}
6bbd11
 
6bbd11
-	f = open_fopen_r(DEFAULT_CONFIG_FILE);
6bbd11
-	if (!f) {
6bbd11
+	return 1;
6bbd11
+}
6bbd11
+
6bbd11
+/*
6bbd11
+ * Read config env variables and check they have been set.
6bbd11
+ *
6bbd11
+ * This simple minded routine assumes the config file
6bbd11
+ * is valid bourne shell script without spaces around "="
6bbd11
+ * and that it has valid values.
6bbd11
+ */
6bbd11
+unsigned int defaults_read_config(unsigned int to_syslog)
6bbd11
+{
6bbd11
+	FILE *conf, *oldconf;
6bbd11
+	struct stat stb, oldstb;
6bbd11
+	int ret, stat, oldstat;
6bbd11
+
6bbd11
+	ret = 1;
6bbd11
+
6bbd11
+	pthread_mutex_lock(&conf_mutex);
6bbd11
+	if (!config) {
6bbd11
+		if (conf_init()) {
6bbd11
+			message(to_syslog, "failed to init config");
6bbd11
+			ret = 0;
6bbd11
+			goto out;
6bbd11
+		}
6bbd11
+	}
6bbd11
+
6bbd11
+	conf = open_fopen_r(DEFAULT_CONFIG_FILE);
6bbd11
+	if (!conf)
6bbd11
 		message(to_syslog, "failed to to open config %s",
6bbd11
 			DEFAULT_CONFIG_FILE);
6bbd11
+
6bbd11
+	oldconf = open_fopen_r(OLD_CONFIG_FILE);
6bbd11
+	if (!oldconf)
6bbd11
+		message(to_syslog, "failed to to open old config %s",
6bbd11
+			OLD_CONFIG_FILE);
6bbd11
+
6bbd11
+	/* Neither config has been updated */
6bbd11
+	stat = oldstat = -1;
6bbd11
+	if (conf && oldconf &&
6bbd11
+	    (stat = fstat(fileno(conf), &stb) != -1) &&
6bbd11
+	    stb.st_mtime <= config->modified &&
6bbd11
+	    (oldstat = fstat(fileno(oldconf), &oldstb) == -1) &&
6bbd11
+	    oldstb.st_mtime <= config->modified) {
6bbd11
+		fclose(conf);
6bbd11
+		fclose(oldconf);
6bbd11
 		goto out;
6bbd11
 	}
6bbd11
 
6bbd11
-	if (fstat(fileno(f), &stb) != -1) {
6bbd11
-		/* Config hasn't been updated */
6bbd11
-		if (stb.st_mtime <= config->modified) {
6bbd11
-			fclose(f);
6bbd11
+	if (conf || oldconf) {
6bbd11
+		if (!reset_defaults(to_syslog)) {
6bbd11
+			fclose(conf);
6bbd11
+			fclose(oldconf);
6bbd11
+			ret = 0;
6bbd11
 			goto out;
6bbd11
 		}
6bbd11
 	}
6bbd11
 
6bbd11
-	ret = read_config(to_syslog, f, DEFAULT_CONFIG_FILE);
6bbd11
-
6bbd11
-	if (fstat(fileno(f), &stb) != -1)
6bbd11
-		config->modified = stb.st_mtime;
6bbd11
-	else
6bbd11
-		message(to_syslog, "failed to update config modified time");
6bbd11
+	/* Update last modified */
6bbd11
+	if (stat != -1) {
6bbd11
+		if (oldstat == -1)
6bbd11
+			config->modified = stb.st_mtime;
6bbd11
+		else {
6bbd11
+			if (oldstb.st_mtime < stb.st_mtime)
6bbd11
+				config->modified = oldstb.st_mtime;
6bbd11
+			else
6bbd11
+				config->modified = stb.st_mtime;
6bbd11
+		}
6bbd11
+	}
6bbd11
 
6bbd11
-	fclose(f);
6bbd11
+	if (conf) {
6bbd11
+		read_config(to_syslog, conf, DEFAULT_CONFIG_FILE);
6bbd11
+		fclose(conf);
6bbd11
+	}
6bbd11
 
6bbd11
 	/*
6bbd11
-	 * Try to read the old config file and override the installed
6bbd11
-	 * defaults in case user has a stale config following updating
6bbd11
-	 * to the new config file location.
6bbd11
+	 * Read the old config file and override the installed
6bbd11
+	 * defaults in case user has a stale config following
6bbd11
+	 * updating to the new config file location.
6bbd11
 	 */
6bbd11
+	if (oldconf) {
6bbd11
+		struct conf_option *ldap_search_base, *ldap_uris;
6bbd11
+		const char *sec = amd_gbl_sec;
6bbd11
+		struct conf_option *co;
6bbd11
+
6bbd11
+		ldap_search_base = save_ldap_option_list(NAME_SEARCH_BASE);
6bbd11
+		if (ldap_search_base)
6bbd11
+			clean_ldap_multi_option(NAME_SEARCH_BASE);
6bbd11
+
6bbd11
+		ldap_uris = save_ldap_option_list(NAME_LDAP_URI);
6bbd11
+		if (ldap_uris)
6bbd11
+			clean_ldap_multi_option(NAME_LDAP_URI);
6bbd11
+
6bbd11
+		read_config(to_syslog, oldconf, OLD_CONFIG_FILE);
6bbd11
+		fclose(oldconf);
6bbd11
+
6bbd11
+		if (ldap_search_base) {
6bbd11
+			co = conf_lookup(sec, NAME_SEARCH_BASE);
6bbd11
+			if (co)
6bbd11
+				free_ldap_option_list(ldap_search_base);
6bbd11
+			else
6bbd11
+				restore_ldap_option_list(ldap_search_base);
6bbd11
+		}
6bbd11
 
6bbd11
-	f = open_fopen_r(OLD_CONFIG_FILE);
6bbd11
-	if (!f)
6bbd11
-		goto out;
6bbd11
-
6bbd11
-	read_config(to_syslog, f, OLD_CONFIG_FILE);
6bbd11
-
6bbd11
-	fclose(f);
6bbd11
+		if (ldap_uris) {
6bbd11
+			co = conf_lookup(sec, NAME_LDAP_URI);
6bbd11
+			if (co)
6bbd11
+				free_ldap_option_list(ldap_uris);
6bbd11
+			else
6bbd11
+				restore_ldap_option_list(ldap_uris);
6bbd11
+		}
6bbd11
+	}
6bbd11
 out:
6bbd11
 	pthread_mutex_unlock(&conf_mutex);
6bbd11
-	return 1;
6bbd11
+	return ret;
6bbd11
 }
6bbd11
 
6bbd11
 static char *conf_get_string(const char *section, const char *name)