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

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