/* * Add key and val to the map m. * key and val are assumed to be safe copies */ void mapc_add_kv(mnt_map *m, char *key, char *val) { kv **h; kv *n; int hash = kvhash_of(key); #ifdef DEBUG dlog("add_kv: %s -> %s", key, val); #endif #ifdef HAS_REGEXP if (MAPC_ISRE(m)) { char keyb[MAXPATHLEN]; regex_t *re; /* * Make sure the string is bound to the start and end */ snprintf(keyb, sizeof(keyb), "^%s$", key); re = malloc(sizeof(*re)); if (!re || regcomp(re, keyb, 0)) { free(re); plog(XLOG_USER, "error compiling RE \"%s\": %s", keyb); return; } else { free(key); key = (char *)re; } } #endif h = &m->kvhash[hash]; n = ALLOC(kv); n->key = key; n->val = val; n->next = *h; *h = n; }
/* * Search the map for the key. * Put a safe copy in *pval or return * an error code */ int mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse) { int error = 0; kv *k = 0; /* * Firewall */ if (!m) { plog(XLOG_ERROR, "Null map request for %s", key); return ENOENT; } if (m->flags & MAPC_SYNC) { /* * Get modify time... */ time_t t; error = (*m->mtime)(m->map_name, &t); if (error || t > m->modify) { m->modify = t; plog(XLOG_INFO, "Map %s is out of date", m->map_name); mapc_sync(m); } } if (!MAPC_ISRE(m)) { /* * Compute the hash table offset */ k = m->kvhash[kvhash_of(key)]; /* * Scan the linked list for the key */ while (k && !FSTREQ(k->key, key)) k = k->next; } #ifdef HAS_REGEXP else if (recurse == MREC_FULL) { /* * Try for an RE match against the entire map. * Note that this will be done in a "random" * order. */ int i; for (i = 0; i < NKVHASH; i++) { k = m->kvhash[i]; while (k) { if (regexec((regex_t *)k->key, key, 0, NULL, 0) == 0) break; k = k->next; } if (k) break; } } #endif /* * If found then take a copy */ if (k) { if (k->val) *pval = strdup(k->val); else error = ENOENT; } else if (m->alloc >= MAPC_ALL) { /* * If the entire map is cached then this * key does not exist. */ error = ENOENT; } else { /* * Otherwise search the map. If we are * in incremental mode then add the key * to the cache. */ error = search_map(m, key, pval); if (!error && m->alloc == MAPC_INC) mapc_add_kv(m, strdup(key), strdup(*pval)); } /* * If an error, and a wildcard exists, * and the key is not internal then * return a copy of the wildcard. */ if (error > 0) { if (recurse == MREC_FULL && !MAPC_ISRE(m)) { char wildname[MAXPATHLEN]; char *subp; if (*key == '/') return error; /* * Keep chopping sub-directories from the RHS * and replacing with "/ *" and repeat the lookup. * For example: * "src/gnu/gcc" -> "src / gnu / *" -> "src / *" */ strlcpy(wildname, key, sizeof wildname); while (error && (subp = strrchr(wildname, '/'))) { strlcpy(subp, "/*", 3); #ifdef DEBUG dlog("mapc recurses on %s", wildname); #endif error = mapc_meta_search(m, wildname, pval, MREC_PART); if (error) *subp = 0; } if (error > 0 && m->wildcard) { *pval = strdup(m->wildcard); error = 0; } } } return error; }
/* * Add key and val to the map m. * key and val are assumed to be safe copies */ void mapc_add_kv(mnt_map *m, char *key, char *val) { kv **h; kv *n; int hash = kvhash_of(key); #ifdef HAVE_REGEXEC regex_t re; #endif /* HAVE_REGEXEC */ dlog("add_kv: %s -> %s", key, val); if (val != NULL && strchr(val, '\n') != NULL) { /* * If the entry value contains multiple lines we need to break * them up and add them recursively. This is a workaround to * support Sun style multi-mounts. Amd converts Sun style * mulit-mounts to type:=auto. The problem is that Sun packs all * the entries on one line. When Amd does the conversion it puts * each type:=auto entry on the same line separated by '\n'. */ char *entry, *tok; /* * The first line should contain the first entry. The key for * this entry is the key passed into this function. */ if ((tok = strtok(val, "\n")) != NULL) { mapc_add_kv(m, key, xstrdup(tok)); } /* * For the rest of the entries we need to tokenize them by '\n' * and separate the keys from there entries. */ while ((tok = strtok(NULL, "\n")) != NULL) { key = tok; /* find the entry */ for (entry = key; *entry && !isspace((unsigned char)*entry); entry++); if (*entry) { *entry++ = '\0'; } mapc_add_kv(m, xstrdup(key), xstrdup(entry)); } XFREE(val); return; } #ifdef HAVE_REGEXEC if (MAPC_ISRE(m)) { char pattern[MAXPATHLEN]; int retval; /* * Make sure the string is bound to the start and end */ xsnprintf(pattern, sizeof(pattern), "^%s$", key); retval = regcomp(&re, pattern, REG_ICASE); if (retval != 0) { char errstr[256]; /* XXX: this code was recently ported, and must be tested -Erez */ errstr[0] = '\0'; regerror(retval, &re, errstr, 256); plog(XLOG_USER, "error compiling RE \"%s\": %s", pattern, errstr); return; } } else memset(&re, 0, sizeof(re)); #endif /* HAVE_REGEXEC */ h = &m->kvhash[hash]; n = ALLOC(struct kv); n->key = key; #ifdef HAVE_REGEXEC memcpy(&n->re, &re, sizeof(regex_t)); #endif /* HAVE_REGEXEC */ n->val = val; n->next = *h; *h = n; m->nentries++; }