138494Sobrien/* 2310490Scy * Copyright (c) 1997-2014 Erez Zadok 338494Sobrien * Copyright (c) 1989 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1989 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1989 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 19310490Scy * 3. Neither the name of the University nor the names of its contributors 2038494Sobrien * may be used to endorse or promote products derived from this software 2138494Sobrien * without specific prior written permission. 2238494Sobrien * 2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2638494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3338494Sobrien * SUCH DAMAGE. 3438494Sobrien * 3538494Sobrien * 36174294Sobrien * File: am-utils/amd/mapc.c 3738494Sobrien * 3838494Sobrien */ 3938494Sobrien 4038494Sobrien/* 4138494Sobrien * Mount map cache 4238494Sobrien */ 4338494Sobrien 4438494Sobrien#ifdef HAVE_CONFIG_H 4538494Sobrien# include <config.h> 4638494Sobrien#endif /* HAVE_CONFIG_H */ 4738494Sobrien#include <am_defs.h> 4838494Sobrien#include <amd.h> 4938494Sobrien 5038494Sobrien/* 5138494Sobrien * Make a duplicate reference to an existing map 5238494Sobrien */ 5338494Sobrien#define mapc_dup(m) ((m)->refc++, (m)) 5438494Sobrien 5538494Sobrien/* 5638494Sobrien * Map cache types 5738494Sobrien * default, none, incremental, all, regexp 5838494Sobrien * MAPC_RE implies MAPC_ALL and must be numerically 5938494Sobrien * greater. 6038494Sobrien */ 6138494Sobrien#define MAPC_DFLT 0x000 6238494Sobrien#define MAPC_NONE 0x001 6338494Sobrien#define MAPC_INC 0x002 6438494Sobrien#define MAPC_ROOT 0x004 6538494Sobrien#define MAPC_ALL 0x010 6638494Sobrien#define MAPC_CACHE_MASK 0x0ff 6738494Sobrien#define MAPC_SYNC 0x100 6838494Sobrien 6938494Sobrien#ifdef HAVE_REGEXEC 7038494Sobrien# define MAPC_RE 0x020 7138494Sobrien# define MAPC_ISRE(m) ((m)->alloc == MAPC_RE) 7238494Sobrien#else /* not HAVE_REGEXEC */ 7338494Sobrien# define MAPC_ISRE(m) FALSE 7438494Sobrien#endif /* not HAVE_REGEXEC */ 7538494Sobrien 7638494Sobrien/* 7738494Sobrien * Lookup recursion 7838494Sobrien */ 7938494Sobrien#define MREC_FULL 2 8038494Sobrien#define MREC_PART 1 8138494Sobrien#define MREC_NONE 0 8238494Sobrien 8338494Sobrienstatic struct opt_tab mapc_opt[] = 8438494Sobrien{ 8538494Sobrien {"all", MAPC_ALL}, 8638494Sobrien {"default", MAPC_DFLT}, 8738494Sobrien {"inc", MAPC_INC}, 8838494Sobrien {"mapdefault", MAPC_DFLT}, 8938494Sobrien {"none", MAPC_NONE}, 9038494Sobrien#ifdef HAVE_REGEXEC 9138494Sobrien {"re", MAPC_RE}, 9238494Sobrien {"regexp", MAPC_RE}, 9338494Sobrien#endif /* HAVE_REGEXEC */ 9438494Sobrien {"sync", MAPC_SYNC}, 95310490Scy {NULL, 0} 9638494Sobrien}; 9738494Sobrien 9838494Sobrien/* 9938494Sobrien * Wildcard key 10038494Sobrien */ 10138494Sobrienstatic char wildcard[] = "*"; 10238494Sobrien 10338494Sobrien/* 10438494Sobrien * Map type 10538494Sobrien */ 10638494Sobrientypedef struct map_type map_type; 10738494Sobrienstruct map_type { 10838494Sobrien char *name; /* Name of this map type */ 10942629Sobrien init_fn *init; /* Initialization */ 11038494Sobrien reload_fn *reload; /* Reload or fill */ 11138494Sobrien isup_fn *isup; /* Is service up or not? (1=up, 0=down) */ 11238494Sobrien search_fn *search; /* Search for new entry */ 11338494Sobrien mtime_fn *mtime; /* Find modify time */ 11438494Sobrien int def_alloc; /* Default allocation mode */ 11538494Sobrien}; 11638494Sobrien 11738494Sobrien/* 11838494Sobrien * Map for root node 11938494Sobrien */ 12038494Sobrienstatic mnt_map *root_map; 12138494Sobrien 12238494Sobrien/* 12338494Sobrien * List of known maps 12438494Sobrien */ 12538494Sobrienqelem map_list_head = {&map_list_head, &map_list_head}; 12638494Sobrien 12738494Sobrien/* 12838494Sobrien * Configuration 12938494Sobrien */ 13038494Sobrien 13138494Sobrien/* forward definitions */ 13238494Sobrienstatic const char *get_full_path(const char *map, const char *path, const char *type); 13338494Sobrienstatic int mapc_meta_search(mnt_map *, char *, char **, int); 13438494Sobrienstatic void mapc_sync(mnt_map *); 13552894Sobrienstatic void mapc_clear(mnt_map *); 136310490Scystatic void mapc_clear_kvhash(kv **); 13738494Sobrien 13838494Sobrien/* ROOT MAP */ 13938494Sobrienstatic int root_init(mnt_map *, char *, time_t *); 14038494Sobrien 14138494Sobrien/* ERROR MAP */ 14238494Sobrienstatic int error_init(mnt_map *, char *, time_t *); 14338494Sobrienstatic int error_reload(mnt_map *, char *, add_fn *); 14438494Sobrienstatic int error_search(mnt_map *, char *, char *, char **, time_t *); 14538494Sobrienstatic int error_mtime(mnt_map *, char *, time_t *); 14638494Sobrien 14738494Sobrien/* PASSWD MAPS */ 14838494Sobrien#ifdef HAVE_MAP_PASSWD 14938494Sobrienextern int passwd_init(mnt_map *, char *, time_t *); 15038494Sobrienextern int passwd_search(mnt_map *, char *, char *, char **, time_t *); 15138494Sobrien#endif /* HAVE_MAP_PASSWD */ 15238494Sobrien 15338494Sobrien/* HESIOD MAPS */ 15438494Sobrien#ifdef HAVE_MAP_HESIOD 15538494Sobrienextern int amu_hesiod_init(mnt_map *, char *map, time_t *tp); 15651292Sobrienextern int hesiod_isup(mnt_map *, char *); 15738494Sobrienextern int hesiod_search(mnt_map *, char *, char *, char **, time_t *); 15838494Sobrien#endif /* HAVE_MAP_HESIOD */ 15938494Sobrien 16038494Sobrien/* LDAP MAPS */ 16138494Sobrien#ifdef HAVE_MAP_LDAP 16238494Sobrienextern int amu_ldap_init(mnt_map *, char *map, time_t *tp); 16338494Sobrienextern int amu_ldap_search(mnt_map *, char *, char *, char **, time_t *); 16438494Sobrienextern int amu_ldap_mtime(mnt_map *, char *, time_t *); 16538494Sobrien#endif /* HAVE_MAP_LDAP */ 16638494Sobrien 16738494Sobrien/* UNION MAPS */ 16838494Sobrien#ifdef HAVE_MAP_UNION 16938494Sobrienextern int union_init(mnt_map *, char *, time_t *); 17038494Sobrienextern int union_search(mnt_map *, char *, char *, char **, time_t *); 17138494Sobrienextern int union_reload(mnt_map *, char *, add_fn *); 17238494Sobrien#endif /* HAVE_MAP_UNION */ 17338494Sobrien 17438494Sobrien/* Network Information Service PLUS (NIS+) */ 17538494Sobrien#ifdef HAVE_MAP_NISPLUS 17638494Sobrienextern int nisplus_init(mnt_map *, char *, time_t *); 17738494Sobrienextern int nisplus_reload(mnt_map *, char *, add_fn *); 17838494Sobrienextern int nisplus_search(mnt_map *, char *, char *, char **, time_t *); 17938494Sobrienextern int nisplus_mtime(mnt_map *, char *, time_t *); 18038494Sobrien#endif /* HAVE_MAP_NISPLUS */ 18138494Sobrien 18238494Sobrien/* Network Information Service (YP, Yellow Pages) */ 18338494Sobrien#ifdef HAVE_MAP_NIS 18438494Sobrienextern int nis_init(mnt_map *, char *, time_t *); 18538494Sobrienextern int nis_reload(mnt_map *, char *, add_fn *); 18638494Sobrienextern int nis_isup(mnt_map *, char *); 18738494Sobrienextern int nis_search(mnt_map *, char *, char *, char **, time_t *); 18838494Sobrienextern int nis_mtime(mnt_map *, char *, time_t *); 18938494Sobrien#endif /* HAVE_MAP_NIS */ 19038494Sobrien 19138494Sobrien/* NDBM MAPS */ 19238494Sobrien#ifdef HAVE_MAP_NDBM 19338494Sobrienextern int ndbm_init(mnt_map *, char *, time_t *); 19438494Sobrienextern int ndbm_search(mnt_map *, char *, char *, char **, time_t *); 19538494Sobrienextern int ndbm_mtime(mnt_map *, char *, time_t *); 19638494Sobrien#endif /* HAVE_MAP_NDBM */ 19738494Sobrien 19838494Sobrien/* FILE MAPS */ 19938494Sobrien#ifdef HAVE_MAP_FILE 200174294Sobrienextern int file_init_or_mtime(mnt_map *, char *, time_t *); 20138494Sobrienextern int file_reload(mnt_map *, char *, add_fn *); 20238494Sobrienextern int file_search(mnt_map *, char *, char *, char **, time_t *); 20338494Sobrien#endif /* HAVE_MAP_FILE */ 20438494Sobrien 205310490Scy/* EXECUTABLE MAPS */ 206310490Scy#ifdef HAVE_MAP_EXEC 207310490Scyextern int exec_init(mnt_map *, char *, time_t *); 208310490Scyextern int exec_search(mnt_map *, char *, char *, char **, time_t *); 209310490Scy#endif /* HAVE_MAP_EXEC */ 21038494Sobrien 211310490Scy/* Sun-syntax MAPS */ 212310490Scy#ifdef HAVE_MAP_SUN 213310490Scy/* XXX: fill in */ 214310490Scy#endif /* HAVE_MAP_SUN */ 215310490Scy 21638494Sobrien/* note that the choice of MAPC_{INC,ALL} will affect browsable_dirs */ 21738494Sobrienstatic map_type maptypes[] = 21838494Sobrien{ 21938494Sobrien { 22038494Sobrien "root", 22138494Sobrien root_init, 22238494Sobrien error_reload, 22338494Sobrien NULL, /* isup function */ 22438494Sobrien error_search, 22538494Sobrien error_mtime, 22638494Sobrien MAPC_ROOT 22738494Sobrien }, 22838494Sobrien#ifdef HAVE_MAP_PASSWD 22938494Sobrien { 23038494Sobrien "passwd", 23138494Sobrien passwd_init, 23238494Sobrien error_reload, 23338494Sobrien NULL, /* isup function */ 23438494Sobrien passwd_search, 23538494Sobrien error_mtime, 23682794Sobrien MAPC_INC 23738494Sobrien }, 23838494Sobrien#endif /* HAVE_MAP_PASSWD */ 23938494Sobrien#ifdef HAVE_MAP_HESIOD 24038494Sobrien { 24138494Sobrien "hesiod", 24238494Sobrien amu_hesiod_init, 24338494Sobrien error_reload, 24451292Sobrien hesiod_isup, /* is Hesiod up or not? */ 24538494Sobrien hesiod_search, 24638494Sobrien error_mtime, 24782794Sobrien MAPC_INC 24838494Sobrien }, 24938494Sobrien#endif /* HAVE_MAP_HESIOD */ 25038494Sobrien#ifdef HAVE_MAP_LDAP 25138494Sobrien { 25238494Sobrien "ldap", 25338494Sobrien amu_ldap_init, 25438494Sobrien error_reload, 25538494Sobrien NULL, /* isup function */ 25638494Sobrien amu_ldap_search, 25738494Sobrien amu_ldap_mtime, 25882794Sobrien MAPC_INC 25938494Sobrien }, 26038494Sobrien#endif /* HAVE_MAP_LDAP */ 26138494Sobrien#ifdef HAVE_MAP_UNION 26238494Sobrien { 26338494Sobrien "union", 26438494Sobrien union_init, 26538494Sobrien union_reload, 26638494Sobrien NULL, /* isup function */ 26738494Sobrien union_search, 26838494Sobrien error_mtime, 26938494Sobrien MAPC_ALL 27038494Sobrien }, 27138494Sobrien#endif /* HAVE_MAP_UNION */ 27238494Sobrien#ifdef HAVE_MAP_NISPLUS 27338494Sobrien { 27438494Sobrien "nisplus", 27538494Sobrien nisplus_init, 27638494Sobrien nisplus_reload, 27738494Sobrien NULL, /* isup function */ 27838494Sobrien nisplus_search, 27938494Sobrien nisplus_mtime, 28038494Sobrien MAPC_INC 28138494Sobrien }, 28238494Sobrien#endif /* HAVE_MAP_NISPLUS */ 28338494Sobrien#ifdef HAVE_MAP_NIS 28438494Sobrien { 28538494Sobrien "nis", 28638494Sobrien nis_init, 28738494Sobrien nis_reload, 28838494Sobrien nis_isup, /* is NIS up or not? */ 28938494Sobrien nis_search, 29038494Sobrien nis_mtime, 29138494Sobrien MAPC_ALL 29238494Sobrien }, 29338494Sobrien#endif /* HAVE_MAP_NIS */ 29438494Sobrien#ifdef HAVE_MAP_NDBM 29538494Sobrien { 29638494Sobrien "ndbm", 29738494Sobrien ndbm_init, 29838494Sobrien error_reload, 29938494Sobrien NULL, /* isup function */ 30038494Sobrien ndbm_search, 30138494Sobrien ndbm_mtime, 30282794Sobrien MAPC_INC 30338494Sobrien }, 30438494Sobrien#endif /* HAVE_MAP_NDBM */ 30538494Sobrien#ifdef HAVE_MAP_FILE 30638494Sobrien { 30738494Sobrien "file", 308174294Sobrien file_init_or_mtime, 30938494Sobrien file_reload, 31038494Sobrien NULL, /* isup function */ 31138494Sobrien file_search, 312174294Sobrien file_init_or_mtime, 31338494Sobrien MAPC_ALL 31438494Sobrien }, 31538494Sobrien#endif /* HAVE_MAP_FILE */ 316174294Sobrien#ifdef HAVE_MAP_EXEC 31738494Sobrien { 318174294Sobrien "exec", 319174294Sobrien exec_init, 320174294Sobrien error_reload, 321174294Sobrien NULL, /* isup function */ 322174294Sobrien exec_search, 323174294Sobrien error_mtime, 324174294Sobrien MAPC_INC 325174294Sobrien }, 326174294Sobrien#endif /* HAVE_MAP_EXEC */ 327310490Scy#ifdef notyet /* probe function needs to be there or SEGV */ 328310490Scy#ifdef HAVE_MAP_SUN 329174294Sobrien { 330310490Scy /* XXX: fill in */ 331310490Scy "sun", 332310490Scy NULL, 333310490Scy NULL, 334310490Scy NULL, /* isup function */ 335310490Scy NULL, 336310490Scy NULL, 337310490Scy 0 338310490Scy }, 339310490Scy#endif /* HAVE_MAP_SUN */ 340310490Scy#endif 341310490Scy { 34238494Sobrien "error", 34338494Sobrien error_init, 34438494Sobrien error_reload, 34538494Sobrien NULL, /* isup function */ 34638494Sobrien error_search, 34738494Sobrien error_mtime, 34838494Sobrien MAPC_NONE 34938494Sobrien }, 35038494Sobrien}; 35138494Sobrien 35238494Sobrien 35338494Sobrien/* 35438494Sobrien * Hash function 35538494Sobrien */ 35638494Sobrienstatic u_int 35738494Sobrienkvhash_of(char *key) 35838494Sobrien{ 35938494Sobrien u_int i, j; 36038494Sobrien 36138494Sobrien for (i = 0; (j = *key++); i += j) ; 36238494Sobrien 36338494Sobrien return i % NKVHASH; 36438494Sobrien} 36538494Sobrien 36638494Sobrien 36738494Sobrienvoid 368174294Sobrienmapc_showtypes(char *buf, size_t l) 36938494Sobrien{ 370174294Sobrien map_type *mt=NULL, *lastmt; 371174294Sobrien int linesize = 0, i; 37238494Sobrien 373174294Sobrien i = sizeof(maptypes) / sizeof(maptypes[0]); 374174294Sobrien lastmt = maptypes + i; 37538494Sobrien buf[0] = '\0'; 376174294Sobrien for (mt = maptypes; mt < lastmt; mt++) { 377174294Sobrien xstrlcat(buf, mt->name, l); 378174294Sobrien if (mt == (lastmt-1)) 379174294Sobrien break; /* if last one, don't do xstrlcat's that follows */ 380174294Sobrien linesize += strlen(mt->name); 381174294Sobrien if (--i > 0) { 382174294Sobrien xstrlcat(buf, ", ", l); 383174294Sobrien linesize += 2; 384174294Sobrien } 385174294Sobrien if (linesize > 54) { 386174294Sobrien linesize = 0; 387174294Sobrien xstrlcat(buf, "\n\t\t ", l); 388174294Sobrien } 38938494Sobrien } 39038494Sobrien} 39138494Sobrien 39238494Sobrien 39338494Sobrien/* 39441142Sobrien * Check if a map of a certain type exists. 39541142Sobrien * Return 1 (true) if exists, 0 (false) if not. 39641142Sobrien */ 39741142Sobrienint 39841142Sobrienmapc_type_exists(const char *type) 39941142Sobrien{ 40041142Sobrien map_type *mt; 40141142Sobrien 40241142Sobrien if (!type) 40341142Sobrien return 0; 40441142Sobrien for (mt = maptypes; 40541142Sobrien mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); 40641142Sobrien mt++) { 40741142Sobrien if (STREQ(type, mt->name)) 40841142Sobrien return 1; 40941142Sobrien } 41041142Sobrien return 0; /* not found anywhere */ 41141142Sobrien} 41241142Sobrien 41341142Sobrien 41441142Sobrien/* 41538494Sobrien * Add key and val to the map m. 41638494Sobrien * key and val are assumed to be safe copies 41738494Sobrien */ 41841142Sobrienvoid 41941142Sobrienmapc_add_kv(mnt_map *m, char *key, char *val) 42038494Sobrien{ 42138494Sobrien kv **h; 42238494Sobrien kv *n; 42338494Sobrien int hash = kvhash_of(key); 42438494Sobrien#ifdef HAVE_REGEXEC 42538494Sobrien regex_t re; 42638494Sobrien#endif /* HAVE_REGEXEC */ 42738494Sobrien 42838494Sobrien dlog("add_kv: %s -> %s", key, val); 42938494Sobrien 430310490Scy if (val != NULL && strchr(val, '\n') != NULL) { 431310490Scy /* 432310490Scy * If the entry value contains multiple lines we need to break 433310490Scy * them up and add them recursively. This is a workaround to 434310490Scy * support Sun style multi-mounts. Amd converts Sun style 435310490Scy * mulit-mounts to type:=auto. The problem is that Sun packs all 436310490Scy * the entries on one line. When Amd does the conversion it puts 437310490Scy * each type:=auto entry on the same line separated by '\n'. 438310490Scy */ 439310490Scy char *entry, *tok; 440310490Scy 441310490Scy /* 442310490Scy * The first line should contain the first entry. The key for 443310490Scy * this entry is the key passed into this function. 444310490Scy */ 445310490Scy if ((tok = strtok(val, "\n")) != NULL) { 446310490Scy mapc_add_kv(m, key, xstrdup(tok)); 447310490Scy } 448310490Scy 449310490Scy /* 450310490Scy * For the rest of the entries we need to tokenize them by '\n' 451310490Scy * and separate the keys from there entries. 452310490Scy */ 453310490Scy while ((tok = strtok(NULL, "\n")) != NULL) { 454310490Scy key = tok; 455310490Scy /* find the entry */ 456310490Scy for (entry = key; *entry && !isspace((unsigned char)*entry); entry++); 457310490Scy if (*entry) { 458310490Scy *entry++ = '\0'; 459310490Scy } 460310490Scy 461310490Scy mapc_add_kv(m, xstrdup(key), xstrdup(entry)); 462310490Scy } 463310490Scy 464310490Scy XFREE(val); 465310490Scy return; 466310490Scy } 467310490Scy 46838494Sobrien#ifdef HAVE_REGEXEC 46938494Sobrien if (MAPC_ISRE(m)) { 47038494Sobrien char pattern[MAXPATHLEN]; 47138494Sobrien int retval; 47238494Sobrien 47338494Sobrien /* 47438494Sobrien * Make sure the string is bound to the start and end 47538494Sobrien */ 476174294Sobrien xsnprintf(pattern, sizeof(pattern), "^%s$", key); 47738494Sobrien retval = regcomp(&re, pattern, REG_ICASE); 47838494Sobrien if (retval != 0) { 47938494Sobrien char errstr[256]; 48038494Sobrien 48138494Sobrien /* XXX: this code was recently ported, and must be tested -Erez */ 48238494Sobrien errstr[0] = '\0'; 48338494Sobrien regerror(retval, &re, errstr, 256); 48438494Sobrien plog(XLOG_USER, "error compiling RE \"%s\": %s", pattern, errstr); 48538494Sobrien return; 48638494Sobrien } 487310490Scy } else 488310490Scy memset(&re, 0, sizeof(re)); 48938494Sobrien#endif /* HAVE_REGEXEC */ 49038494Sobrien 49138494Sobrien h = &m->kvhash[hash]; 49238494Sobrien n = ALLOC(struct kv); 49338494Sobrien n->key = key; 49438494Sobrien#ifdef HAVE_REGEXEC 49538494Sobrien memcpy(&n->re, &re, sizeof(regex_t)); 49638494Sobrien#endif /* HAVE_REGEXEC */ 49738494Sobrien n->val = val; 49838494Sobrien n->next = *h; 49938494Sobrien *h = n; 500310490Scy m->nentries++; 50138494Sobrien} 50238494Sobrien 50338494Sobrien 50438494Sobrienstatic void 50538494Sobrienmapc_repl_kv(mnt_map *m, char *key, char *val) 50638494Sobrien{ 50738494Sobrien kv *k; 50838494Sobrien 50938494Sobrien /* 51038494Sobrien * Compute the hash table offset 51138494Sobrien */ 51238494Sobrien k = m->kvhash[kvhash_of(key)]; 51338494Sobrien 51438494Sobrien /* 51538494Sobrien * Scan the linked list for the key 51638494Sobrien */ 51738494Sobrien while (k && !FSTREQ(k->key, key)) 51838494Sobrien k = k->next; 51938494Sobrien 52038494Sobrien if (k) { 52138494Sobrien XFREE(k->val); 52238494Sobrien k->val = val; 52338494Sobrien } else { 52438494Sobrien mapc_add_kv(m, key, val); 52538494Sobrien } 52638494Sobrien} 52738494Sobrien 52838494Sobrien 52938494Sobrien/* 53038494Sobrien * Search a map for a key. 53138494Sobrien * Calls map specific search routine. 53238494Sobrien * While map is out of date, keep re-syncing. 53338494Sobrien */ 53438494Sobrienstatic int 53538494Sobriensearch_map(mnt_map *m, char *key, char **valp) 53638494Sobrien{ 53738494Sobrien int rc; 53838494Sobrien 53938494Sobrien do { 54038494Sobrien rc = (*m->search) (m, m->map_name, key, valp, &m->modify); 54138494Sobrien if (rc < 0) { 54238494Sobrien plog(XLOG_MAP, "Re-synchronizing cache for map %s", m->map_name); 54338494Sobrien mapc_sync(m); 54438494Sobrien } 54538494Sobrien } while (rc < 0); 54638494Sobrien 54738494Sobrien return rc; 54838494Sobrien} 54938494Sobrien 55038494Sobrien 55138494Sobrien/* 55238494Sobrien * Do a wildcard lookup in the map and 55338494Sobrien * save the result. 55438494Sobrien */ 55538494Sobrienstatic void 55638494Sobrienmapc_find_wildcard(mnt_map *m) 55738494Sobrien{ 55838494Sobrien /* 55938494Sobrien * Attempt to find the wildcard entry 56038494Sobrien */ 56138494Sobrien int rc = search_map(m, wildcard, &m->wildcard); 56238494Sobrien 56338494Sobrien if (rc != 0) 564310490Scy m->wildcard = NULL; 56538494Sobrien} 56638494Sobrien 56738494Sobrien 56838494Sobrien/* 56952894Sobrien * Do a map reload. 57052894Sobrien * Attempt to reload without losing current data by switching the hashes 57152894Sobrien * round. 572174294Sobrien * If reloading was needed and succeeded, return 1; else return 0. 57338494Sobrien */ 574174294Sobrienstatic int 57538494Sobrienmapc_reload_map(mnt_map *m) 57638494Sobrien{ 577174294Sobrien int error, ret = 0; 578310490Scy kv *maphash[NKVHASH]; 57982794Sobrien time_t t; 58038494Sobrien 58182794Sobrien error = (*m->mtime) (m, m->map_name, &t); 58282794Sobrien if (error) { 58382794Sobrien t = m->modify; 58482794Sobrien } 58582794Sobrien 58652894Sobrien /* 58752894Sobrien * skip reloading maps that have not been modified, unless 58852894Sobrien * amq -f was used (do_mapc_reload is 0) 58952894Sobrien */ 59052894Sobrien if (m->reloads != 0 && do_mapc_reload != 0) { 59182794Sobrien if (t <= m->modify) { 59252894Sobrien plog(XLOG_INFO, "reload of map %s is not needed (in sync)", m->map_name); 59352894Sobrien dlog("map %s last load time is %d, last modify time is %d", 59452894Sobrien m->map_name, (int) m->modify, (int) t); 595174294Sobrien return ret; 59652894Sobrien } 59752894Sobrien } 59852894Sobrien 59952894Sobrien /* copy the old hash and zero the map */ 60052894Sobrien memcpy((voidp) maphash, (voidp) m->kvhash, sizeof(m->kvhash)); 60152894Sobrien memset((voidp) m->kvhash, 0, sizeof(m->kvhash)); 60252894Sobrien 60338494Sobrien dlog("calling map reload on %s", m->map_name); 604310490Scy m->nentries = 0; 60538494Sobrien error = (*m->reload) (m, m->map_name, mapc_add_kv); 60652894Sobrien if (error) { 60752894Sobrien if (m->reloads == 0) 60852894Sobrien plog(XLOG_FATAL, "first time load of map %s failed!", m->map_name); 60952894Sobrien else 61052894Sobrien plog(XLOG_ERROR, "reload of map %s failed - using old values", 61152894Sobrien m->map_name); 61252894Sobrien mapc_clear(m); 61352894Sobrien memcpy((voidp) m->kvhash, (voidp) maphash, sizeof(m->kvhash)); 61452894Sobrien } else { 61552894Sobrien if (m->reloads++ == 0) 61652894Sobrien plog(XLOG_INFO, "first time load of map %s succeeded", m->map_name); 61752894Sobrien else 61852894Sobrien plog(XLOG_INFO, "reload #%d of map %s succeeded", 61952894Sobrien m->reloads, m->map_name); 620310490Scy mapc_clear_kvhash(maphash); 621310490Scy if (m->wildcard) { 622310490Scy XFREE(m->wildcard); 623310490Scy m->wildcard = NULL; 624310490Scy } 62582794Sobrien m->modify = t; 626174294Sobrien ret = 1; 62752894Sobrien } 62838494Sobrien 62938494Sobrien dlog("calling mapc_search for wildcard"); 63038494Sobrien error = mapc_search(m, wildcard, &m->wildcard); 63138494Sobrien if (error) 632310490Scy m->wildcard = NULL; 633174294Sobrien return ret; 63438494Sobrien} 63538494Sobrien 63638494Sobrien 63738494Sobrien/* 63838494Sobrien * Create a new map 63938494Sobrien */ 64038494Sobrienstatic mnt_map * 641310490Scymapc_create(char *map, char *opt, const char *type, const char *mntpt) 64238494Sobrien{ 64338494Sobrien mnt_map *m = ALLOC(struct mnt_map); 64438494Sobrien map_type *mt; 645174294Sobrien time_t modify = 0; 646310490Scy u_int alloc = 0; 64738494Sobrien 64838494Sobrien cmdoption(opt, mapc_opt, &alloc); 64938494Sobrien 65038494Sobrien /* 65138494Sobrien * If using a configuration file, and the map_type is defined, then look 65238494Sobrien * for it, in the maptypes array. If found, initialize the map using that 65338494Sobrien * map_type. If not found, return error. If no map_type was defined, 65438494Sobrien * default to cycling through all maptypes. 65538494Sobrien */ 65638494Sobrien if (use_conf_file && type) { 65738494Sobrien /* find what type of map this one is */ 65838494Sobrien for (mt = maptypes; 65938494Sobrien mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); 66038494Sobrien mt++) { 66138494Sobrien if (STREQ(type, mt->name)) { 66282794Sobrien plog(XLOG_INFO, "initializing amd.conf map %s of type %s", map, type); 66338494Sobrien if ((*mt->init) (m, map, &modify) == 0) { 66438494Sobrien break; 66538494Sobrien } else { 66638494Sobrien plog(XLOG_ERROR, "failed to initialize map %s", map); 66738494Sobrien error_init(m, map, &modify); 66838494Sobrien break; 66938494Sobrien } 67038494Sobrien } 67138494Sobrien } /* end of "for (mt =" loop */ 67238494Sobrien 67338494Sobrien } else { /* cycle through all known maptypes */ 67438494Sobrien 67538494Sobrien /* 67638494Sobrien * not using amd conf file or using it by w/o specifying map type 67738494Sobrien */ 67838494Sobrien for (mt = maptypes; 67938494Sobrien mt < maptypes + sizeof(maptypes) / sizeof(maptypes[0]); 68038494Sobrien mt++) { 68138494Sobrien dlog("trying to initialize map %s of type %s ...", map, mt->name); 68238494Sobrien if ((*mt->init) (m, map, &modify) == 0) { 68338494Sobrien break; 68438494Sobrien } 68538494Sobrien } 68638494Sobrien } /* end of "if (use_conf_file && (colpos = strchr ..." statement */ 68738494Sobrien 68838494Sobrien /* assert: mt in maptypes */ 68938494Sobrien 69038494Sobrien m->flags = alloc & ~MAPC_CACHE_MASK; 691310490Scy m->nentries = 0; 69238494Sobrien alloc &= MAPC_CACHE_MASK; 69338494Sobrien 69438494Sobrien if (alloc == MAPC_DFLT) 69538494Sobrien alloc = mt->def_alloc; 69638494Sobrien 69738494Sobrien switch (alloc) { 69838494Sobrien default: 69938494Sobrien plog(XLOG_USER, "Ambiguous map cache type \"%s\"; using \"inc\"", opt); 70038494Sobrien alloc = MAPC_INC; 70142629Sobrien /* fall-through... */ 70238494Sobrien case MAPC_NONE: 70338494Sobrien case MAPC_INC: 70438494Sobrien case MAPC_ROOT: 70538494Sobrien break; 70638494Sobrien 70738494Sobrien case MAPC_ALL: 70838494Sobrien /* 70938494Sobrien * If there is no support for reload and it was requested 71038494Sobrien * then back off to incremental instead. 71138494Sobrien */ 71238494Sobrien if (mt->reload == error_reload) { 71338494Sobrien plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"all\"; using \"inc\"", mt->name); 71438494Sobrien alloc = MAPC_INC; 71538494Sobrien } 71638494Sobrien break; 71738494Sobrien 71838494Sobrien#ifdef HAVE_REGEXEC 71938494Sobrien case MAPC_RE: 72038494Sobrien if (mt->reload == error_reload) { 72138494Sobrien plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"re\"", mt->name); 72238494Sobrien mt = &maptypes[sizeof(maptypes) / sizeof(maptypes[0]) - 1]; 72338494Sobrien /* assert: mt->name == "error" */ 72438494Sobrien } 72538494Sobrien break; 72638494Sobrien#endif /* HAVE_REGEXEC */ 72738494Sobrien } 72838494Sobrien 72938494Sobrien dlog("Map for %s coming from maptype %s", map, mt->name); 73038494Sobrien 73138494Sobrien m->alloc = alloc; 73238494Sobrien m->reload = mt->reload; 73338494Sobrien m->isup = mt->isup; 73438494Sobrien m->modify = modify; 73538494Sobrien m->search = alloc >= MAPC_ALL ? error_search : mt->search; 73638494Sobrien m->mtime = mt->mtime; 73738494Sobrien memset((voidp) m->kvhash, 0, sizeof(m->kvhash)); 738310490Scy m->map_name = xstrdup(map); 73938494Sobrien m->refc = 1; 740310490Scy m->wildcard = NULL; 74152894Sobrien m->reloads = 0; 742310490Scy /* initialize per-map information (flags, etc.) */ 743310490Scy m->cfm = find_cf_map(mntpt); 74438494Sobrien 74538494Sobrien /* 74638494Sobrien * synchronize cache with reality 74738494Sobrien */ 74838494Sobrien mapc_sync(m); 74938494Sobrien 75038494Sobrien return m; 75138494Sobrien} 75238494Sobrien 75338494Sobrien 75438494Sobrien/* 755310490Scy * Free the cached data in a map hash 75638494Sobrien */ 75738494Sobrienstatic void 758310490Scymapc_clear_kvhash(kv **kvhash) 75938494Sobrien{ 76038494Sobrien int i; 76138494Sobrien 76238494Sobrien /* 76338494Sobrien * For each of the hash slots, chain 76438494Sobrien * along free'ing the data. 76538494Sobrien */ 76638494Sobrien for (i = 0; i < NKVHASH; i++) { 767310490Scy kv *k = kvhash[i]; 76838494Sobrien while (k) { 76938494Sobrien kv *n = k->next; 77038494Sobrien XFREE(k->key); 771310490Scy XFREE(k->val); 77238494Sobrien XFREE(k); 77338494Sobrien k = n; 77438494Sobrien } 77538494Sobrien } 776310490Scy} 77738494Sobrien 778310490Scy 779310490Scy/* 780310490Scy * Free the cached data in a map 781310490Scy */ 782310490Scystatic void 783310490Scymapc_clear(mnt_map *m) 784310490Scy{ 785310490Scy mapc_clear_kvhash(m->kvhash); 786310490Scy 78738494Sobrien /* 78838494Sobrien * Zero the hash slots 78938494Sobrien */ 79038494Sobrien memset((voidp) m->kvhash, 0, sizeof(m->kvhash)); 79138494Sobrien 79238494Sobrien /* 79338494Sobrien * Free the wildcard if it exists 79438494Sobrien */ 795310490Scy XFREE(m->wildcard); 796310490Scy m->wildcard = NULL; 797310490Scy 798310490Scy m->nentries = 0; 79938494Sobrien} 80038494Sobrien 80138494Sobrien 80238494Sobrien/* 80338494Sobrien * Find a map, or create one if it does not exist 80438494Sobrien */ 80538494Sobrienmnt_map * 806310490Scymapc_find(char *map, char *opt, const char *maptype, const char *mntpt) 80738494Sobrien{ 80838494Sobrien mnt_map *m; 80938494Sobrien 81038494Sobrien /* 81138494Sobrien * Search the list of known maps to see if 81238494Sobrien * it has already been loaded. If it is found 81338494Sobrien * then return a duplicate reference to it. 81438494Sobrien * Otherwise make a new map as required and 81538494Sobrien * add it to the list of maps 81638494Sobrien */ 81738494Sobrien ITER(m, mnt_map, &map_list_head) 818174294Sobrien if (STREQ(m->map_name, map)) 81938494Sobrien return mapc_dup(m); 820310490Scy m = mapc_create(map, opt, maptype, mntpt); 82138494Sobrien ins_que(&m->hdr, &map_list_head); 82238494Sobrien 82338494Sobrien return m; 82438494Sobrien} 82538494Sobrien 82638494Sobrien 82738494Sobrien/* 82838494Sobrien * Free a map. 82938494Sobrien */ 83038494Sobrienvoid 831174294Sobrienmapc_free(opaque_t arg) 83238494Sobrien{ 833174294Sobrien mnt_map *m = (mnt_map *) arg; 83438494Sobrien 83538494Sobrien /* 83638494Sobrien * Decrement the reference count. 83738494Sobrien * If the reference count hits zero 83838494Sobrien * then throw the map away. 83938494Sobrien */ 84038494Sobrien if (m && --m->refc == 0) { 84138494Sobrien mapc_clear(m); 84238494Sobrien XFREE(m->map_name); 84338494Sobrien rem_que(&m->hdr); 84438494Sobrien XFREE(m); 84538494Sobrien } 84638494Sobrien} 84738494Sobrien 84838494Sobrien 84938494Sobrien/* 85038494Sobrien * Search the map for the key. Put a safe (malloc'ed) copy in *pval or 85138494Sobrien * return an error code 85238494Sobrien */ 85338494Sobrienstatic int 85438494Sobrienmapc_meta_search(mnt_map *m, char *key, char **pval, int recurse) 85538494Sobrien{ 85638494Sobrien int error = 0; 857310490Scy kv *k = NULL; 85838494Sobrien 85938494Sobrien /* 86038494Sobrien * Firewall 86138494Sobrien */ 86238494Sobrien if (!m) { 86338494Sobrien plog(XLOG_ERROR, "Null map request for %s", key); 86438494Sobrien return ENOENT; 86538494Sobrien } 86682794Sobrien 86738494Sobrien if (m->flags & MAPC_SYNC) { 86838494Sobrien /* 86938494Sobrien * Get modify time... 87038494Sobrien */ 87138494Sobrien time_t t; 87238494Sobrien error = (*m->mtime) (m, m->map_name, &t); 87338494Sobrien if (error || t > m->modify) { 87438494Sobrien plog(XLOG_INFO, "Map %s is out of date", m->map_name); 87538494Sobrien mapc_sync(m); 87638494Sobrien } 87738494Sobrien } 87838494Sobrien 87938494Sobrien if (!MAPC_ISRE(m)) { 88038494Sobrien /* 88138494Sobrien * Compute the hash table offset 88238494Sobrien */ 88338494Sobrien k = m->kvhash[kvhash_of(key)]; 88438494Sobrien 88538494Sobrien /* 88638494Sobrien * Scan the linked list for the key 88738494Sobrien */ 88838494Sobrien while (k && !FSTREQ(k->key, key)) 88938494Sobrien k = k->next; 89038494Sobrien 89138494Sobrien } 89238494Sobrien 89338494Sobrien#ifdef HAVE_REGEXEC 89438494Sobrien else if (recurse == MREC_FULL) { 89538494Sobrien /* 89638494Sobrien * Try for an RE match against the entire map. 89738494Sobrien * Note that this will be done in a "random" 89838494Sobrien * order. 89938494Sobrien */ 90038494Sobrien int i; 90138494Sobrien 90238494Sobrien for (i = 0; i < NKVHASH; i++) { 90338494Sobrien k = m->kvhash[i]; 90438494Sobrien while (k) { 90538494Sobrien int retval; 90638494Sobrien 90738494Sobrien /* XXX: this code was recently ported, and must be tested -Erez */ 908310490Scy retval = regexec(&k->re, key, 0, NULL, 0); 90938494Sobrien if (retval == 0) { /* succeeded */ 91038494Sobrien break; 91138494Sobrien } else { /* failed to match, log error */ 91238494Sobrien char errstr[256]; 91338494Sobrien 91438494Sobrien errstr[0] = '\0'; 91538494Sobrien regerror(retval, &k->re, errstr, 256); 91638494Sobrien plog(XLOG_USER, "error matching RE \"%s\" against \"%s\": %s", 91738494Sobrien key, k->key, errstr); 91838494Sobrien } 91938494Sobrien k = k->next; 92038494Sobrien } 92138494Sobrien if (k) 92238494Sobrien break; 92338494Sobrien } 92438494Sobrien } 92538494Sobrien#endif /* HAVE_REGEXEC */ 92638494Sobrien 92738494Sobrien /* 92838494Sobrien * If found then take a copy 92938494Sobrien */ 93038494Sobrien if (k) { 93138494Sobrien if (k->val) 932310490Scy *pval = xstrdup(k->val); 93338494Sobrien else 93438494Sobrien error = ENOENT; 93538494Sobrien } else if (m->alloc >= MAPC_ALL) { 93638494Sobrien /* 93738494Sobrien * If the entire map is cached then this 93838494Sobrien * key does not exist. 93938494Sobrien */ 94038494Sobrien error = ENOENT; 94138494Sobrien } else { 94238494Sobrien /* 94338494Sobrien * Otherwise search the map. If we are 94438494Sobrien * in incremental mode then add the key 94538494Sobrien * to the cache. 94638494Sobrien */ 94738494Sobrien error = search_map(m, key, pval); 94838494Sobrien if (!error && m->alloc == MAPC_INC) 949310490Scy mapc_add_kv(m, xstrdup(key), xstrdup(*pval)); 95038494Sobrien } 95138494Sobrien 95238494Sobrien /* 95338494Sobrien * If an error, and a wildcard exists, 95438494Sobrien * and the key is not internal then 95538494Sobrien * return a copy of the wildcard. 95638494Sobrien */ 95738494Sobrien if (error > 0) { 95838494Sobrien if (recurse == MREC_FULL && !MAPC_ISRE(m)) { 95938494Sobrien char wildname[MAXPATHLEN]; 96038494Sobrien char *subp; 96138494Sobrien if (*key == '/') 96238494Sobrien return error; 96338494Sobrien /* 96438494Sobrien * Keep chopping sub-directories from the RHS 96538494Sobrien * and replacing with "/ *" and repeat the lookup. 96638494Sobrien * For example: 96738494Sobrien * "src/gnu/gcc" -> "src / gnu / *" -> "src / *" 96838494Sobrien */ 969174294Sobrien xstrlcpy(wildname, key, sizeof(wildname)); 97038494Sobrien while (error && (subp = strrchr(wildname, '/'))) { 971174294Sobrien /* 972174294Sobrien * sizeof space left in subp is sizeof wildname minus what's left 973174294Sobrien * after the strchr above returned a pointer inside wildname into 974174294Sobrien * subp. 975174294Sobrien */ 976174294Sobrien xstrlcpy(subp, "/*", sizeof(wildname) - (subp - wildname)); 97738494Sobrien dlog("mapc recurses on %s", wildname); 97838494Sobrien error = mapc_meta_search(m, wildname, pval, MREC_PART); 97938494Sobrien if (error) 980310490Scy *subp = '\0'; 98138494Sobrien } 98238494Sobrien 98338494Sobrien if (error > 0 && m->wildcard) { 984310490Scy *pval = xstrdup(m->wildcard); 98538494Sobrien error = 0; 98638494Sobrien } 98738494Sobrien } 98838494Sobrien } 98938494Sobrien return error; 99038494Sobrien} 99138494Sobrien 99238494Sobrien 99338494Sobrienint 99438494Sobrienmapc_search(mnt_map *m, char *key, char **pval) 99538494Sobrien{ 99638494Sobrien return mapc_meta_search(m, key, pval, MREC_FULL); 99738494Sobrien} 99838494Sobrien 99938494Sobrien 100038494Sobrien/* 100138494Sobrien * Get map cache in sync with physical representation 100238494Sobrien */ 100338494Sobrienstatic void 100438494Sobrienmapc_sync(mnt_map *m) 100538494Sobrien{ 1006174294Sobrien int need_mtime_update = 0; 100738494Sobrien 1008174294Sobrien if (m->alloc == MAPC_ROOT) 1009174294Sobrien return; /* nothing to do */ 1010174294Sobrien 1011174294Sobrien /* do not clear map if map service is down */ 1012174294Sobrien if (m->isup) { 1013174294Sobrien if (!((*m->isup)(m, m->map_name))) { 1014174294Sobrien plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name); 1015174294Sobrien return; 101638494Sobrien } 1017174294Sobrien } 101838494Sobrien 1019174294Sobrien if (m->alloc >= MAPC_ALL) { 1020174294Sobrien /* mapc_reload_map() always works */ 1021174294Sobrien need_mtime_update = mapc_reload_map(m); 1022174294Sobrien } else { 1023174294Sobrien mapc_clear(m); 1024174294Sobrien /* 1025174294Sobrien * Attempt to find the wildcard entry 1026174294Sobrien */ 1027174294Sobrien mapc_find_wildcard(m); 1028174294Sobrien need_mtime_update = 1; /* because mapc_clear always works */ 1029174294Sobrien } 1030174294Sobrien 1031174294Sobrien /* 1032174294Sobrien * To be safe, update the mtime of the mnt_map's own node, so that the 1033174294Sobrien * kernel will flush all of its cached entries. 1034174294Sobrien */ 1035174294Sobrien if (need_mtime_update && m->cfm) { 1036174294Sobrien am_node *mp = find_ap(m->cfm->cfm_dir); 1037174294Sobrien if (mp) { 1038174294Sobrien clocktime(&mp->am_fattr.na_mtime); 103952894Sobrien } else { 1040174294Sobrien plog(XLOG_ERROR, "cannot find map %s to update its mtime", 1041174294Sobrien m->cfm->cfm_dir); 104252894Sobrien } 104338494Sobrien } 104438494Sobrien} 104538494Sobrien 104638494Sobrien 104738494Sobrien/* 104838494Sobrien * Reload all the maps 104938494Sobrien * Called when Amd gets hit by a SIGHUP. 105038494Sobrien */ 105138494Sobrienvoid 105238494Sobrienmapc_reload(void) 105338494Sobrien{ 105438494Sobrien mnt_map *m; 105538494Sobrien 105638494Sobrien /* 105738494Sobrien * For all the maps, 105838494Sobrien * Throw away the existing information. 105938494Sobrien * Do a reload 106038494Sobrien * Find the wildcard 106138494Sobrien */ 106238494Sobrien ITER(m, mnt_map, &map_list_head) 106338494Sobrien mapc_sync(m); 106438494Sobrien} 106538494Sobrien 106638494Sobrien 106738494Sobrien/* 106838494Sobrien * Root map. 106938494Sobrien * The root map is used to bootstrap amd. 107038494Sobrien * All the require top-level mounts are added 107138494Sobrien * into the root map and then the map is iterated 107238494Sobrien * and a lookup is done on all the mount points. 107338494Sobrien * This causes the top level mounts to be automounted. 107438494Sobrien */ 107538494Sobrienstatic int 107638494Sobrienroot_init(mnt_map *m, char *map, time_t *tp) 107738494Sobrien{ 1078174294Sobrien *tp = clocktime(NULL); 107938494Sobrien return STREQ(map, ROOT_MAP) ? 0 : ENOENT; 108038494Sobrien} 108138494Sobrien 108238494Sobrien 108338494Sobrien/* 108438494Sobrien * Add a new entry to the root map 108538494Sobrien * 108638494Sobrien * dir - directory (key) 108738494Sobrien * opts - mount options 108838494Sobrien * map - map name 108938494Sobrien * cfm - optional amd configuration file map section structure 109038494Sobrien */ 109138494Sobrienvoid 109238494Sobrienroot_newmap(const char *dir, const char *opts, const char *map, const cf_map_t *cfm) 109338494Sobrien{ 109438494Sobrien char str[MAXPATHLEN]; 109538494Sobrien 109638494Sobrien /* 109738494Sobrien * First make sure we have a root map to talk about... 109838494Sobrien */ 109938494Sobrien if (!root_map) 1100310490Scy root_map = mapc_find(ROOT_MAP, "mapdefault", NULL, NULL); 110138494Sobrien 110238494Sobrien /* 110338494Sobrien * Then add the entry... 110438494Sobrien */ 110538494Sobrien 110638494Sobrien /* 110738494Sobrien * Here I plug in the code to process other amd.conf options like 110838494Sobrien * map_type, search_path, and flags (browsable_dirs, mount_type). 110938494Sobrien */ 111038494Sobrien 111138494Sobrien if (cfm) { 111238494Sobrien if (map) { 1113174294Sobrien xsnprintf(str, sizeof(str), 1114174294Sobrien "cache:=mapdefault;type:=toplvl;mount_type:=%s;fs:=\"%s\"", 1115174294Sobrien cfm->cfm_flags & CFM_MOUNT_TYPE_AUTOFS ? "autofs" : "nfs", 1116174294Sobrien get_full_path(map, cfm->cfm_search_path, cfm->cfm_type)); 111738494Sobrien if (opts && opts[0] != '\0') { 1118174294Sobrien xstrlcat(str, ";", sizeof(str)); 1119174294Sobrien xstrlcat(str, opts, sizeof(str)); 112038494Sobrien } 112138494Sobrien if (cfm->cfm_flags & CFM_BROWSABLE_DIRS_FULL) 1122174294Sobrien xstrlcat(str, ";opts:=rw,fullybrowsable", sizeof(str)); 112338494Sobrien if (cfm->cfm_flags & CFM_BROWSABLE_DIRS) 1124174294Sobrien xstrlcat(str, ";opts:=rw,browsable", sizeof(str)); 112538494Sobrien if (cfm->cfm_type) { 1126174294Sobrien xstrlcat(str, ";maptype:=", sizeof(str)); 1127174294Sobrien xstrlcat(str, cfm->cfm_type, sizeof(str)); 112838494Sobrien } 112938494Sobrien } else { 1130174294Sobrien xstrlcpy(str, opts, sizeof(str)); 113138494Sobrien } 113238494Sobrien } else { 113338494Sobrien if (map) 1134174294Sobrien xsnprintf(str, sizeof(str), 1135174294Sobrien "cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s", 1136174294Sobrien map, opts ? opts : ""); 113738494Sobrien else 1138174294Sobrien xstrlcpy(str, opts, sizeof(str)); 113938494Sobrien } 1140310490Scy mapc_repl_kv(root_map, xstrdup(dir), xstrdup(str)); 114138494Sobrien} 114238494Sobrien 114338494Sobrien 114438494Sobrienint 1145174294Sobrienmapc_keyiter(mnt_map *m, key_fun *fn, opaque_t arg) 114638494Sobrien{ 114738494Sobrien int i; 114838494Sobrien int c = 0; 114938494Sobrien 115038494Sobrien for (i = 0; i < NKVHASH; i++) { 115138494Sobrien kv *k = m->kvhash[i]; 115238494Sobrien while (k) { 115338494Sobrien (*fn) (k->key, arg); 115438494Sobrien k = k->next; 115538494Sobrien c++; 115638494Sobrien } 115738494Sobrien } 115838494Sobrien 115938494Sobrien return c; 116038494Sobrien} 116138494Sobrien 116238494Sobrien 116338494Sobrien/* 116438494Sobrien * Iterate on the root map and call (*fn)() on the key of all the nodes. 1165174294Sobrien * Returns the number of entries in the root map. 116638494Sobrien */ 116738494Sobrienint 1168174294Sobrienroot_keyiter(key_fun *fn, opaque_t arg) 116938494Sobrien{ 117038494Sobrien if (root_map) { 117138494Sobrien int c = mapc_keyiter(root_map, fn, arg); 117238494Sobrien return c; 117338494Sobrien } 117438494Sobrien 117538494Sobrien return 0; 117638494Sobrien} 117738494Sobrien 117838494Sobrien 117938494Sobrien/* 118038494Sobrien * Error map 118138494Sobrien */ 118238494Sobrienstatic int 118338494Sobrienerror_init(mnt_map *m, char *map, time_t *tp) 118438494Sobrien{ 118538494Sobrien plog(XLOG_USER, "No source data for map %s", map); 118638494Sobrien *tp = 0; 118738494Sobrien 118838494Sobrien return 0; 118938494Sobrien} 119038494Sobrien 119138494Sobrien 119238494Sobrienstatic int 119338494Sobrienerror_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) 119438494Sobrien{ 119538494Sobrien return ENOENT; 119638494Sobrien} 119738494Sobrien 119838494Sobrien 119938494Sobrienstatic int 120038494Sobrienerror_reload(mnt_map *m, char *map, add_fn *fn) 120138494Sobrien{ 120238494Sobrien return ENOENT; 120338494Sobrien} 120438494Sobrien 120538494Sobrien 120638494Sobrienstatic int 120738494Sobrienerror_mtime(mnt_map *m, char *map, time_t *tp) 120838494Sobrien{ 120938494Sobrien *tp = 0; 121038494Sobrien 121138494Sobrien return 0; 121238494Sobrien} 121338494Sobrien 121438494Sobrien 121538494Sobrien/* 121638494Sobrien * Return absolute path of map, searched in a type-specific path. 121738494Sobrien * Note: uses a static buffer for returned data. 121838494Sobrien */ 121938494Sobrienstatic const char * 122038494Sobrienget_full_path(const char *map, const char *path, const char *type) 122138494Sobrien{ 122238494Sobrien char component[MAXPATHLEN], *str; 122338494Sobrien static char full_path[MAXPATHLEN]; 122438494Sobrien int len; 122538494Sobrien 122638494Sobrien /* for now, only file-type search paths are implemented */ 122738494Sobrien if (type && !STREQ(type, "file")) 122838494Sobrien return map; 122938494Sobrien 123038494Sobrien /* if null map, return it */ 123138494Sobrien if (!map) 123238494Sobrien return map; 123338494Sobrien 123438494Sobrien /* if map includes a '/', return it (absolute or relative path) */ 123538494Sobrien if (strchr(map, '/')) 123638494Sobrien return map; 123738494Sobrien 123838494Sobrien /* if path is empty, return map */ 123938494Sobrien if (!path) 124038494Sobrien return map; 124138494Sobrien 124238494Sobrien /* now break path into components, and search in each */ 1243174294Sobrien xstrlcpy(component, path, sizeof(component)); 124438494Sobrien 124538494Sobrien str = strtok(component, ":"); 124638494Sobrien do { 1247174294Sobrien xstrlcpy(full_path, str, sizeof(full_path)); 124838494Sobrien len = strlen(full_path); 124938494Sobrien if (full_path[len - 1] != '/') /* add trailing "/" if needed */ 1250174294Sobrien xstrlcat(full_path, "/", sizeof(full_path)); 1251174294Sobrien xstrlcat(full_path, map, sizeof(full_path)); 125238494Sobrien if (access(full_path, R_OK) == 0) 125338494Sobrien return full_path; 125438494Sobrien str = strtok(NULL, ":"); 125538494Sobrien } while (str); 125638494Sobrien 125738494Sobrien return map; /* if found nothing, return map */ 125838494Sobrien} 1259