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

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