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

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