Blame SOURCES/autofs-5.0.9-amd-lookup-update-lookup-program-to-handle-amd-keys.patch

6bbd11
autofs-5.0.9 - amd lookup update lookup program to handle amd keys
6bbd11
6bbd11
From: Ian Kent <raven@themaw.net>
6bbd11
6bbd11
6bbd11
---
6bbd11
 modules/lookup_program.c |  390 +++++++++++++++++++++++++++++++++-------------
6bbd11
 1 file changed, 282 insertions(+), 108 deletions(-)
6bbd11
6bbd11
diff --git a/modules/lookup_program.c b/modules/lookup_program.c
6bbd11
index 6ce94e4..08d14ff 100644
6bbd11
--- a/modules/lookup_program.c
6bbd11
+++ b/modules/lookup_program.c
6bbd11
@@ -113,123 +113,30 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
6bbd11
 	return NSS_STATUS_UNKNOWN;
6bbd11
 }
6bbd11
 
6bbd11
-int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
6bbd11
+static char *lookup_one(struct autofs_point *ap,
6bbd11
+			const char *name, int name_len,
6bbd11
+			struct lookup_context *ctxt)
6bbd11
 {
6bbd11
-	struct lookup_context *ctxt = (struct lookup_context *) context;
6bbd11
-	struct map_source *source;
6bbd11
-	struct mapent_cache *mc;
6bbd11
 	char *mapent = NULL, *mapp, *tmp;
6bbd11
-	struct mapent *me;
6bbd11
 	char buf[MAX_ERR_BUF];
6bbd11
 	char errbuf[1024], *errp;
6bbd11
 	char ch;
6bbd11
 	int pipefd[2], epipefd[2];
6bbd11
 	struct pollfd pfd[2];
6bbd11
 	pid_t f;
6bbd11
-	int status;
6bbd11
 	enum state { st_space, st_map, st_done } state;
6bbd11
 	int quoted = 0;
6bbd11
-	int ret = 1;
6bbd11
 	int distance;
6bbd11
 	int alloci = 1;
6bbd11
-
6bbd11
-	source = ap->entry->current;
6bbd11
-	ap->entry->current = NULL;
6bbd11
-	master_source_current_signal(ap->entry);
6bbd11
-
6bbd11
-	mc = source->mc;
6bbd11
-
6bbd11
-	/* Check if we recorded a mount fail for this key anywhere */
6bbd11
-	me = lookup_source_mapent(ap, name, LKP_DISTINCT);
6bbd11
-	if (me) {
6bbd11
-		if (me->status >= time(NULL)) {
6bbd11
-			cache_unlock(me->mc);
6bbd11
-			return NSS_STATUS_NOTFOUND;
6bbd11
-		} else {
6bbd11
-			struct mapent_cache *smc = me->mc;
6bbd11
-			struct mapent *sme;
6bbd11
-
6bbd11
-			if (me->mapent)
6bbd11
-				cache_unlock(smc);
6bbd11
-			else {
6bbd11
-				cache_unlock(smc);
6bbd11
-				cache_writelock(smc);
6bbd11
-				sme = cache_lookup_distinct(smc, name);
6bbd11
-				/* Negative timeout expired for non-existent entry. */
6bbd11
-				if (sme && !sme->mapent) {
6bbd11
-					if (cache_pop_mapent(sme) == CHE_FAIL)
6bbd11
-						cache_delete(smc, name);
6bbd11
-				}
6bbd11
-				cache_unlock(smc);
6bbd11
-			}
6bbd11
-		}
6bbd11
-	}
6bbd11
-
6bbd11
-	/* Catch installed direct offset triggers */
6bbd11
-	cache_readlock(mc);
6bbd11
-	me = cache_lookup_distinct(mc, name);
6bbd11
-	if (!me) {
6bbd11
-		cache_unlock(mc);
6bbd11
-		/*
6bbd11
-		 * If there's a '/' in the name and the offset is not in
6bbd11
-		 * the cache then it's not a valid path in the mount tree.
6bbd11
-		 */
6bbd11
-		if (strchr(name, '/')) {
6bbd11
-			debug(ap->logopt,
6bbd11
-			      MODPREFIX "offset %s not found", name);
6bbd11
-			return NSS_STATUS_NOTFOUND;
6bbd11
-		}
6bbd11
-	} else {
6bbd11
-		/* Otherwise we found a valid offset so try mount it */
6bbd11
-		debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent);
6bbd11
-
6bbd11
-		/*
6bbd11
-		 * If this is a request for an offset mount (whose entry
6bbd11
-		 * must be present in the cache to be valid) or the entry
6bbd11
-		 * is newer than the negative timeout value then just
6bbd11
-		 * try and mount it. Otherwise try and remove it and
6bbd11
-		 * proceed with the program map lookup.
6bbd11
-		 */
6bbd11
-		if (strchr(name, '/') ||
6bbd11
-		    me->age + ap->negative_timeout > time(NULL)) {
6bbd11
-			char *ent = NULL;
6bbd11
-
6bbd11
-			if (me->mapent) {
6bbd11
-				ent = alloca(strlen(me->mapent) + 1);
6bbd11
-				strcpy(ent, me->mapent);
6bbd11
-			}
6bbd11
-			cache_unlock(mc);
6bbd11
-			master_source_current_wait(ap->entry);
6bbd11
-			ap->entry->current = source;
6bbd11
-			ret = ctxt->parse->parse_mount(ap, name,
6bbd11
-				 name_len, ent, ctxt->parse->context);
6bbd11
-			goto out_free;
6bbd11
-		} else {
6bbd11
-			if (me->multi) {
6bbd11
-				cache_unlock(mc);
6bbd11
-				warn(ap->logopt, MODPREFIX
6bbd11
-				     "unexpected lookup for active multi-mount"
6bbd11
-				     " key %s, returning fail", name);
6bbd11
-				return NSS_STATUS_UNAVAIL;
6bbd11
-			}
6bbd11
-			cache_unlock(mc);
6bbd11
-			cache_writelock(mc);
6bbd11
-			me = cache_lookup_distinct(mc, name);
6bbd11
-			if (me)
6bbd11
-				cache_delete(mc, name);
6bbd11
-			cache_unlock(mc);
6bbd11
-		}
6bbd11
-	}
6bbd11
+	int status;
6bbd11
 
6bbd11
 	mapent = (char *) malloc(MAPENT_MAX_LEN + 1);
6bbd11
 	if (!mapent) {
6bbd11
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
6bbd11
 		logerr(MODPREFIX "malloc: %s", estr);
6bbd11
-		return NSS_STATUS_UNAVAIL;
6bbd11
+		return NULL;
6bbd11
 	}
6bbd11
 
6bbd11
-	debug(ap->logopt, MODPREFIX "looking up %s", name);
6bbd11
-
6bbd11
 	/*
6bbd11
 	 * We don't use popen because we don't want to run /bin/sh plus we
6bbd11
 	 * want to send stderr to the syslog, and we don't use spawnl()
6bbd11
@@ -238,12 +145,12 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
6bbd11
 	if (open_pipe(pipefd)) {
6bbd11
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
6bbd11
 		logerr(MODPREFIX "pipe: %s", estr);
6bbd11
-		goto out_free;
6bbd11
+		goto out_error;
6bbd11
 	}
6bbd11
 	if (open_pipe(epipefd)) {
6bbd11
 		close(pipefd[0]);
6bbd11
 		close(pipefd[1]);
6bbd11
-		goto out_free;
6bbd11
+		goto out_error;
6bbd11
 	}
6bbd11
 
6bbd11
 	f = fork();
6bbd11
@@ -254,7 +161,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
6bbd11
 		close(pipefd[1]);
6bbd11
 		close(epipefd[0]);
6bbd11
 		close(epipefd[1]);
6bbd11
-		goto out_free;
6bbd11
+		goto out_error;
6bbd11
 	} else if (f == 0) {
6bbd11
 		reset_signals();
6bbd11
 		close(pipefd[0]);
6bbd11
@@ -420,21 +327,288 @@ next:
6bbd11
 	if (waitpid(f, &status, 0) != f) {
6bbd11
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
6bbd11
 		logerr(MODPREFIX "waitpid: %s", estr);
6bbd11
-		goto out_free;
6bbd11
+		goto out_error;
6bbd11
 	}
6bbd11
 
6bbd11
 	if (mapp == mapent || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
6bbd11
 		info(ap->logopt, MODPREFIX "lookup for %s failed", name);
6bbd11
-		goto out_free;
6bbd11
+		goto out_error;
6bbd11
 	}
6bbd11
 
6bbd11
-	cache_writelock(mc);
6bbd11
-	ret = cache_update(mc, source, name, mapent, time(NULL));
6bbd11
-	cache_unlock(mc);
6bbd11
-	if (ret == CHE_FAIL) {
6bbd11
+	return mapent;
6bbd11
+
6bbd11
+out_error:
6bbd11
+	if (mapent)
6bbd11
 		free(mapent);
6bbd11
-		return NSS_STATUS_UNAVAIL;
6bbd11
+
6bbd11
+	return NULL;
6bbd11
+}
6bbd11
+
6bbd11
+static int lookup_amd_defaults(struct autofs_point *ap,
6bbd11
+			       struct map_source *source,
6bbd11
+			       struct lookup_context *ctxt)
6bbd11
+{
6bbd11
+	struct mapent_cache *mc = source->mc;
6bbd11
+	char *ment = lookup_one(ap, "/defaults", 9, ctxt);
6bbd11
+	if (ment) {
6bbd11
+		char *start = ment + 9;
6bbd11
+		int ret;
6bbd11
+
6bbd11
+		while (isblank(*start))
6bbd11
+			start++;
6bbd11
+		cache_writelock(mc);
6bbd11
+		ret = cache_update(mc, source, "/defaults", start, time(NULL));
6bbd11
+		cache_unlock(mc);
6bbd11
+		if (ret == CHE_FAIL) {
6bbd11
+			free(ment);
6bbd11
+			return NSS_STATUS_UNAVAIL;
6bbd11
+		}
6bbd11
+		free(ment);
6bbd11
 	}
6bbd11
+	return NSS_STATUS_SUCCESS;
6bbd11
+}
6bbd11
+
6bbd11
+static int match_key(struct autofs_point *ap,
6bbd11
+		     struct map_source *source,
6bbd11
+		     const char *name, int name_len,
6bbd11
+		     char **mapent, struct lookup_context *ctxt)
6bbd11
+{
6bbd11
+	unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD;
6bbd11
+	struct mapent_cache *mc = source->mc;
6bbd11
+	char buf[MAX_ERR_BUF];
6bbd11
+	char *ment;
6bbd11
+	char *lkp_key;
6bbd11
+	size_t lkp_len;
6bbd11
+	char *prefix;
6bbd11
+	int ret;
6bbd11
+
6bbd11
+	if (source->flags & MAP_FLAG_FORMAT_AMD) {
6bbd11
+		ret = lookup_amd_defaults(ap, source, ctxt);
6bbd11
+		if (ret != NSS_STATUS_SUCCESS) {
6bbd11
+			warn(ap->logopt,
6bbd11
+			     MODPREFIX "failed to save /defaults entry");
6bbd11
+		}
6bbd11
+	}
6bbd11
+
6bbd11
+	if (!is_amd_format) {
6bbd11
+		lkp_key = strdup(name);
6bbd11
+		lkp_len = name_len;
6bbd11
+	} else {
6bbd11
+		size_t len;
6bbd11
+
6bbd11
+		if (ap->pref)
6bbd11
+			len = strlen(ap->pref) + strlen(name);
6bbd11
+		else
6bbd11
+			len = strlen(name);
6bbd11
+
6bbd11
+		lkp_key = malloc(len + 1);
6bbd11
+		if (!lkp_key) {
6bbd11
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
6bbd11
+			error(ap->logopt, MODPREFIX "malloc: %s", estr);
6bbd11
+			return NSS_STATUS_UNAVAIL;
6bbd11
+		}
6bbd11
+
6bbd11
+		if (ap->pref) {
6bbd11
+			strcpy(lkp_key, ap->pref);
6bbd11
+			strcat(lkp_key, name);
6bbd11
+		} else
6bbd11
+			strcpy(lkp_key, name);
6bbd11
+
6bbd11
+		lkp_len = len;
6bbd11
+	}
6bbd11
+
6bbd11
+	ment = lookup_one(ap, lkp_key, lkp_len, ctxt);
6bbd11
+	if (ment) {
6bbd11
+		char *start = ment;
6bbd11
+		if (source->flags & MAP_FLAG_FORMAT_AMD) {
6bbd11
+			start = ment + lkp_len;
6bbd11
+			while (isblank(*start))
6bbd11
+				start++;
6bbd11
+		}
6bbd11
+		cache_writelock(mc);
6bbd11
+		ret = cache_update(mc, source, lkp_key, start, time(NULL));
6bbd11
+		cache_unlock(mc);
6bbd11
+		if (ret == CHE_FAIL) {
6bbd11
+			free(ment);
6bbd11
+			free(lkp_key);
6bbd11
+			return NSS_STATUS_UNAVAIL;
6bbd11
+		}
6bbd11
+		*mapent = strdup(start);
6bbd11
+		if (!*mapent) {
6bbd11
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
6bbd11
+			error(ap->logopt, MODPREFIX "malloc: %s", estr);
6bbd11
+			free(lkp_key);
6bbd11
+			free(ment);
6bbd11
+			return NSS_STATUS_UNAVAIL;
6bbd11
+		}
6bbd11
+		free(lkp_key);
6bbd11
+		free(ment);
6bbd11
+		return NSS_STATUS_SUCCESS;
6bbd11
+	}
6bbd11
+
6bbd11
+	if (!is_amd_format) {
6bbd11
+		free(lkp_key);
6bbd11
+		return NSS_STATUS_NOTFOUND;
6bbd11
+	}
6bbd11
+
6bbd11
+	ret = NSS_STATUS_NOTFOUND;
6bbd11
+
6bbd11
+	/*
6bbd11
+	 * Now strip successive directory components and try a
6bbd11
+	 * match against map entries ending with a wildcard and
6bbd11
+	 * finally try the wilcard entry itself.
6bbd11
+	 */
6bbd11
+	while ((prefix = strrchr(lkp_key, '/'))) {
6bbd11
+		char *match;
6bbd11
+		size_t len;
6bbd11
+		*prefix = '\0';
6bbd11
+		len = strlen(lkp_key) + 3;
6bbd11
+		match = malloc(len);
6bbd11
+		if (!match) {
6bbd11
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
6bbd11
+			error(ap->logopt, MODPREFIX "malloc: %s", estr);
6bbd11
+			free(lkp_key);
6bbd11
+			return NSS_STATUS_UNAVAIL;
6bbd11
+		}
6bbd11
+		len--;
6bbd11
+		strcpy(match, lkp_key);
6bbd11
+		strcat(match, "/*");
6bbd11
+		ment = lookup_one(ap, match, len, ctxt);
6bbd11
+		if (ment) {
6bbd11
+			char *start = ment + len;
6bbd11
+			while (isblank(*start))
6bbd11
+				start++;
6bbd11
+			cache_writelock(mc);
6bbd11
+			ret = cache_update(mc, source, match, start, time(NULL));
6bbd11
+			cache_unlock(mc);
6bbd11
+			if (ret == CHE_FAIL) {
6bbd11
+				free(match);
6bbd11
+				free(ment);
6bbd11
+				free(lkp_key);
6bbd11
+				return NSS_STATUS_UNAVAIL;
6bbd11
+			}
6bbd11
+			free(match);
6bbd11
+			*mapent = strdup(start);
6bbd11
+			if (!*mapent) {
6bbd11
+				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
6bbd11
+				error(ap->logopt, MODPREFIX "malloc: %s", estr);
6bbd11
+				free(ment);
6bbd11
+				free(lkp_key);
6bbd11
+				return NSS_STATUS_UNAVAIL;
6bbd11
+			}
6bbd11
+			free(ment);
6bbd11
+			free(lkp_key);
6bbd11
+			return NSS_STATUS_SUCCESS;
6bbd11
+		}
6bbd11
+		free(match);
6bbd11
+	}
6bbd11
+	free(lkp_key);
6bbd11
+
6bbd11
+	return ret;
6bbd11
+}
6bbd11
+
6bbd11
+int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
6bbd11
+{
6bbd11
+	struct lookup_context *ctxt = (struct lookup_context *) context;
6bbd11
+	struct map_source *source;
6bbd11
+	struct mapent_cache *mc;
6bbd11
+	char *mapent = NULL;
6bbd11
+	struct mapent *me;
6bbd11
+	int ret = 1;
6bbd11
+
6bbd11
+	source = ap->entry->current;
6bbd11
+	ap->entry->current = NULL;
6bbd11
+	master_source_current_signal(ap->entry);
6bbd11
+
6bbd11
+	mc = source->mc;
6bbd11
+
6bbd11
+	/* Check if we recorded a mount fail for this key anywhere */
6bbd11
+	me = lookup_source_mapent(ap, name, LKP_DISTINCT);
6bbd11
+	if (me) {
6bbd11
+		if (me->status >= time(NULL)) {
6bbd11
+			cache_unlock(me->mc);
6bbd11
+			return NSS_STATUS_NOTFOUND;
6bbd11
+		} else {
6bbd11
+			struct mapent_cache *smc = me->mc;
6bbd11
+			struct mapent *sme;
6bbd11
+
6bbd11
+			if (me->mapent)
6bbd11
+				cache_unlock(smc);
6bbd11
+			else {
6bbd11
+				cache_unlock(smc);
6bbd11
+				cache_writelock(smc);
6bbd11
+				sme = cache_lookup_distinct(smc, name);
6bbd11
+				/* Negative timeout expired for non-existent entry. */
6bbd11
+				if (sme && !sme->mapent) {
6bbd11
+					if (cache_pop_mapent(sme) == CHE_FAIL)
6bbd11
+						cache_delete(smc, name);
6bbd11
+				}
6bbd11
+				cache_unlock(smc);
6bbd11
+			}
6bbd11
+		}
6bbd11
+	}
6bbd11
+
6bbd11
+	/* Catch installed direct offset triggers */
6bbd11
+	cache_readlock(mc);
6bbd11
+	me = cache_lookup_distinct(mc, name);
6bbd11
+	if (!me) {
6bbd11
+		cache_unlock(mc);
6bbd11
+		/*
6bbd11
+		 * If there's a '/' in the name and the offset is not in
6bbd11
+		 * the cache then it's not a valid path in the mount tree.
6bbd11
+		 */
6bbd11
+		if (strchr(name, '/')) {
6bbd11
+			debug(ap->logopt,
6bbd11
+			      MODPREFIX "offset %s not found", name);
6bbd11
+			return NSS_STATUS_NOTFOUND;
6bbd11
+		}
6bbd11
+	} else {
6bbd11
+		/* Otherwise we found a valid offset so try mount it */
6bbd11
+		debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent);
6bbd11
+
6bbd11
+		/*
6bbd11
+		 * If this is a request for an offset mount (whose entry
6bbd11
+		 * must be present in the cache to be valid) or the entry
6bbd11
+		 * is newer than the negative timeout value then just
6bbd11
+		 * try and mount it. Otherwise try and remove it and
6bbd11
+		 * proceed with the program map lookup.
6bbd11
+		 */
6bbd11
+		if (strchr(name, '/') ||
6bbd11
+		    me->age + ap->negative_timeout > time(NULL)) {
6bbd11
+			char *ent = NULL;
6bbd11
+
6bbd11
+			if (me->mapent) {
6bbd11
+				ent = alloca(strlen(me->mapent) + 1);
6bbd11
+				strcpy(ent, me->mapent);
6bbd11
+			}
6bbd11
+			cache_unlock(mc);
6bbd11
+			master_source_current_wait(ap->entry);
6bbd11
+			ap->entry->current = source;
6bbd11
+			ret = ctxt->parse->parse_mount(ap, name,
6bbd11
+				 name_len, ent, ctxt->parse->context);
6bbd11
+			goto out_free;
6bbd11
+		} else {
6bbd11
+			if (me->multi) {
6bbd11
+				cache_unlock(mc);
6bbd11
+				warn(ap->logopt, MODPREFIX
6bbd11
+				     "unexpected lookup for active multi-mount"
6bbd11
+				     " key %s, returning fail", name);
6bbd11
+				return NSS_STATUS_UNAVAIL;
6bbd11
+			}
6bbd11
+			cache_unlock(mc);
6bbd11
+			cache_writelock(mc);
6bbd11
+			me = cache_lookup_distinct(mc, name);
6bbd11
+			if (me)
6bbd11
+				cache_delete(mc, name);
6bbd11
+			cache_unlock(mc);
6bbd11
+		}
6bbd11
+	}
6bbd11
+
6bbd11
+	debug(ap->logopt, MODPREFIX "looking up %s", name);
6bbd11
+
6bbd11
+	ret = match_key(ap, source, name, name_len, &mapent, ctxt);
6bbd11
+	if (ret != NSS_STATUS_SUCCESS)
6bbd11
+		goto out_free;
6bbd11
 
6bbd11
 	debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent);
6bbd11