📄 mapc.c
字号:
if (alloc == MAPC_DFLT) alloc = mt->def_alloc; switch (alloc) { default: plog(XLOG_USER, "Ambiguous map cache type \"%s\"; using \"inc\"", opt); alloc = MAPC_INC; /* fallthrough... */ case MAPC_NONE: case MAPC_INC: case MAPC_ROOT: break; case MAPC_ALL: /* * If there is no support for reload and it was requested * then back off to incremental instead. */ if (mt->reload == error_reload) { plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"all\"; using \"inc\"", mt->name); alloc = MAPC_INC; } break;#ifdef HAS_REGEXP case MAPC_RE: if (mt->reload == error_reload) { plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"re\"", mt->name); mt = &maptypes[sizeof(maptypes)/sizeof(maptypes[0]) - 1]; /* assert: mt->name == "error" */ } break;#endif }#ifdef DEBUG dlog("Map for %s coming from maptype %s", map, mt->name);#endif m->alloc = alloc; m->reload = mt->reload; m->modify = modify; m->search = alloc >= MAPC_ALL ? error_search : mt->search; m->mtime = mt->mtime; bzero((voidp) m->kvhash, sizeof(m->kvhash)); m->map_name = strdup(map); m->refc = 1; m->wildcard = 0; /* * synchronize cache with reality */ mapc_sync(m); return m;}/* * Free the cached data in a map */static void mapc_clear P((mnt_map *m));static void mapc_clear(m)mnt_map *m;{ int i; /* * For each of the hash slots, chain * along free'ing the data. */ for (i = 0; i < NKVHASH; i++) { kv *k = m->kvhash[i]; while (k) { kv *n = k->next; free((voidp) k->key); if (k->val) free((voidp) k->val); free((voidp) k); k = n; } } /* * Zero the hash slots */ bzero((voidp) m->kvhash, sizeof(m->kvhash)); /* * Free the wildcard if it exists */ if (m->wildcard) { free(m->wildcard); m->wildcard = 0; }}/* * Find a map, or create one if it does not exist */mnt_map *mapc_find P((char *map, char *opt));mnt_map *mapc_find(map, opt)char *map;char *opt;{ mnt_map *m; /* * Search the list of known maps to see if * it has already been loaded. If it is found * then return a duplicate reference to it. * Otherwise make a new map as required and * add it to the list of maps */ ITER(m, mnt_map, &map_list_head) if (STREQ(m->map_name, map)) return mapc_dup(m); m = mapc_create(map, opt); ins_que(&m->hdr, &map_list_head); return m;}/* * Free a map. */void mapc_free P((mnt_map *m));void mapc_free(m)mnt_map *m;{ /* * Decrement the reference count. * If the reference count hits zero * then throw the map away. */ if (m && --m->refc == 0) { mapc_clear(m); free((voidp) m->map_name); rem_que(&m->hdr); free((voidp) m); }}/* * Search the map for the key. * Put a safe copy in *pval or return * an error code */int mapc_meta_search P((mnt_map *m, char *key, char **pval, int recurse));int mapc_meta_search(m, key, pval, recurse)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((regexp *) k->key, key)) 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 / *" */ strcpy(wildname, key); while (error && (subp = strrchr(wildname, '/'))) { strcpy(subp, "/*");#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;}int mapc_search P((mnt_map *m, char *key, char **pval));int mapc_search(m, key, pval)mnt_map *m;char *key;char **pval;{ return mapc_meta_search(m, key, pval, MREC_FULL);}/* * Get map cache in sync with physical representation */static void mapc_sync P((mnt_map *m));static void mapc_sync(m)mnt_map *m;{ if (m->alloc != MAPC_ROOT) { mapc_clear(m); if (m->alloc >= MAPC_ALL) if (mapc_reload_map(m)) m->alloc = MAPC_INC; /* * Attempt to find the wildcard entry */ if (m->alloc < MAPC_ALL) mapc_find_wildcard(m); }}/* * Reload all the maps * Called when Amd gets hit by a SIGHUP. */void mapc_reload(P_void);void mapc_reload(){ mnt_map *m; /* * For all the maps, * Throw away the existing information. * Do a reload * Find the wildcard */ ITER(m, mnt_map, &map_list_head) mapc_sync(m);}/* * Root map. * The root map is used to bootstrap amd. * All the require top-level mounts are added * into the root map and then the map is iterated * and a lookup is done on all the mount points. * This causes the top level mounts to be automounted. */static int root_init P((char *map, time_t *tp));static int root_init(map, tp)char *map;time_t *tp;{ *tp = clocktime(); return strcmp(map, ROOT_MAP) == 0 ? 0 : ENOENT;}/* * Add a new entry to the root map * * dir - directory (key) * opts - mount options * map - map name */void root_newmap P((char *dir, char *opts, char *map));void root_newmap(dir, opts, map)char *dir;char *opts;char *map;{ char str[MAXPATHLEN]; /* * First make sure we have a root map to talk about... */ if (!root_map) root_map = mapc_find(ROOT_MAP, "mapdefault"); /* * Then add the entry... */ dir = strdup(dir); if (map) sprintf(str, "cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s", map, opts ? opts : ""); else strcpy(str, opts); mapc_repl_kv(root_map, dir, strdup(str));}int mapc_keyiter P((mnt_map *m, void (*fn)(char*,voidp), voidp arg));int mapc_keyiter(m, fn, arg)mnt_map *m;void (*fn)P((char*, voidp));voidp arg;{ int i; int c = 0; for (i = 0; i < NKVHASH; i++) { kv *k = m->kvhash[i]; while (k) { (*fn)(k->key, arg); k = k->next; c++; } } return c;}/* * Iterate of the the root map * and call (*fn)() on the key * of all the nodes. * Finally throw away the root map. */int root_keyiter P((void (*fn)(char*,voidp), voidp arg));int root_keyiter(fn, arg)void (*fn)P((char*,voidp));voidp arg;{ if (root_map) { int c = mapc_keyiter(root_map, fn, arg);#ifdef notdef mapc_free(root_map); root_map = 0;#endif return c; } return 0;}/* * Error map */static int error_init P((char *map, time_t *tp));static int error_init(map, tp)char *map;time_t *tp;{ plog(XLOG_USER, "No source data for map %s", map); *tp = 0; return 0;}/*ARGSUSED*/static int error_search P((mnt_map *m, char *map, char *key, char **pval, time_t *tp));static int error_search(m, map, key, pval, tp)mnt_map *m;char *map;char *key;char **pval;time_t *tp;{ return ENOENT;}/*ARGSUSED*/static int error_reload P((mnt_map *m, char *map, add_fn *fn));static int error_reload(m, map, fn)mnt_map *m;char *map;add_fn *fn;{ return ENOENT;}static int error_mtime P((char *map, time_t *tp));static int error_mtime(map, tp)char *map;time_t *tp;{ *tp = 0; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -