|
|
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 |
|