1 /*-
2 * Copyright (c) 1989 Jan-Simon Pendry
3 * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry at Imperial College, London.
9 *
10 * %sccs.include.redist.c%
11 *
12 * $Id: mapc.c,v 5.2.2.1 1992/02/09 15:08:38 jsp beta $
13 */
14
15 #ifndef lint
16 static char sccsid[] = "@(#)mapc.c 8.1 (Berkeley) 06/06/93";
17 #endif /* not lint */
18
19 /*
20 * Mount map cache
21 */
22
23 #include "am.h"
24 #ifdef HAS_REGEXP
25 #include RE_HDR
26 #endif
27
28 /*
29 * Hash table size
30 */
31 #define NKVHASH (1 << 2) /* Power of two */
32
33 /*
34 * Wildcard key
35 */
36 static char wildcard[] = "*";
37
38 /*
39 * Map cache types
40 * default, none, incremental, all, regexp
41 * MAPC_RE implies MAPC_ALL and must be numerically
42 * greater.
43 */
44 #define MAPC_DFLT 0x000
45 #define MAPC_NONE 0x001
46 #define MAPC_INC 0x002
47 #define MAPC_ROOT 0x004
48 #define MAPC_ALL 0x010
49 #ifdef HAS_REGEXP
50 #define MAPC_RE 0x020
51 #define MAPC_ISRE(m) ((m)->alloc == MAPC_RE)
52 #else
53 #define MAPC_ISRE(m) FALSE
54 #endif
55 #define MAPC_CACHE_MASK 0x0ff
56 #define MAPC_SYNC 0x100
57
58 static struct opt_tab mapc_opt[] = {
59 { "all", MAPC_ALL },
60 { "default", MAPC_DFLT },
61 { "inc", MAPC_INC },
62 { "mapdefault", MAPC_DFLT },
63 { "none", MAPC_NONE },
64 #ifdef HAS_REGEXP
65 { "re", MAPC_RE },
66 { "regexp", MAPC_RE },
67 #endif
68 { "sync", MAPC_SYNC },
69 { 0, 0 }
70 };
71
72 /*
73 * Lookup recursion
74 */
75 #define MREC_FULL 2
76 #define MREC_PART 1
77 #define MREC_NONE 0
78
79 /*
80 * Cache map operations
81 */
82 typedef void add_fn P((mnt_map*, char*, char*));
83 typedef int init_fn P((char*, time_t*));
84 typedef int search_fn P((mnt_map*, char*, char*, char**, time_t*));
85 typedef int reload_fn P((mnt_map*, char*, add_fn*));
86 typedef int mtime_fn P((char*, time_t*));
87
88 static void mapc_sync P((mnt_map*));
89
90 /*
91 * Map type
92 */
93 typedef struct map_type map_type;
94 struct map_type {
95 char *name; /* Name of this map type */
96 init_fn *init; /* Initialisation */
97 reload_fn *reload; /* Reload or fill */
98 search_fn *search; /* Search for new entry */
99 mtime_fn *mtime; /* Find modify time */
100 int def_alloc; /* Default allocation mode */
101 };
102
103 /*
104 * Key-value pair
105 */
106 typedef struct kv kv;
107 struct kv {
108 kv *next;
109 char *key;
110 char *val;
111 };
112
113 struct mnt_map {
114 qelem hdr;
115 int refc; /* Reference count */
116 short flags; /* Allocation flags */
117 short alloc; /* Allocation mode */
118 time_t modify; /* Modify time of map */
119 char *map_name; /* Name of this map */
120 char *wildcard; /* Wildcard value */
121 reload_fn *reload; /* Function to be used for reloads */
122 search_fn *search; /* Function to be used for searching */
123 mtime_fn *mtime; /* Modify time function */
124 kv *kvhash[NKVHASH]; /* Cached data */
125 };
126
127 /*
128 * Map for root node
129 */
130 static mnt_map *root_map;
131
132 /*
133 * List of known maps
134 */
135 extern qelem map_list_head;
136 qelem map_list_head = { &map_list_head, &map_list_head };
137
138 /*
139 * Configuration
140 */
141
142 /* ROOT MAP */
143 static int root_init P((char*, time_t*));
144
145 /* FILE MAPS */
146 #ifdef HAS_FILE_MAPS
147 extern int file_init P((char*, time_t*));
148 extern int file_reload P((mnt_map*, char*, add_fn*));
149 extern int file_search P((mnt_map*, char*, char*, char**, time_t*));
150 extern int file_mtime P((char*, time_t*));
151 #endif /* HAS_FILE_MAPS */
152
153 /* Network Information Service (NIS) MAPS */
154 #ifdef HAS_NIS_MAPS
155 extern int nis_init P((char*, time_t*));
156 #ifdef HAS_NIS_RELOAD
157 extern int nis_reload P((mnt_map*, char*, add_fn*));
158 #else
159 #define nis_reload error_reload
160 #endif
161 extern int nis_search P((mnt_map*, char*, char*, char**, time_t*));
162 #define nis_mtime nis_init
163 #endif /* HAS_NIS_MAPS */
164
165 /* NDBM MAPS */
166 #ifdef HAS_NDBM_MAPS
167 #ifdef OS_HAS_NDBM
168 extern int ndbm_init P((char*, time_t*));
169 extern int ndbm_search P((mnt_map*, char*, char*, char**, time_t*));
170 #define ndbm_mtime ndbm_init
171 #endif /* OS_HAS_NDBM */
172 #endif /* HAS_NDBM_MAPS */
173
174 /* PASSWD MAPS */
175 #ifdef HAS_PASSWD_MAPS
176 extern int passwd_init P((char*, time_t*));
177 extern int passwd_search P((mnt_map*, char*, char*, char**, time_t*));
178 #endif /* HAS_PASSWD_MAPS */
179
180 /* HESIOD MAPS */
181 #ifdef HAS_HESIOD_MAPS
182 extern int hesiod_init P((char*, time_t*));
183 #ifdef HAS_HESIOD_RELOAD
184 extern int hesiod_reload P((mnt_map*, char*, add_fn*));
185 #else
186 #define hesiod_reload error_reload
187 #endif
188 extern int hesiod_search P((mnt_map*, char*, char*, char**, time_t*));
189 #endif /* HAS_HESIOD_MAPS */
190
191 /* UNION MAPS */
192 #ifdef HAS_UNION_MAPS
193 extern int union_init P((char*, time_t*));
194 extern int union_search P((mnt_map*, char*, char*, char**, time_t*));
195 extern int union_reload P((mnt_map*, char*, add_fn*));
196 #endif /* HAS_UNION_MAPS */
197
198 /* ERROR MAP */
199 static int error_init P((char*, time_t*));
200 static int error_reload P((mnt_map*, char*, add_fn*));
201 static int error_search P((mnt_map*, char*, char*, char**, time_t*));
202 static int error_mtime P((char*, time_t*));
203
204 static map_type maptypes[] = {
205 { "root", root_init, error_reload, error_search, error_mtime, MAPC_ROOT },
206
207 #ifdef HAS_PASSWD_MAPS
208 { "passwd", passwd_init, error_reload, passwd_search, error_mtime, MAPC_INC },
209 #endif
210
211 #ifdef HAS_HESIOD_MAPS
212 { "hesiod", hesiod_init, hesiod_reload, hesiod_search, error_mtime, MAPC_ALL },
213 #endif
214
215 #ifdef HAS_UNION_MAPS
216 { "union", union_init, union_reload, union_search, error_mtime, MAPC_ALL },
217 #endif
218
219 #ifdef HAS_NIS_MAPS
220 { "nis", nis_init, nis_reload, nis_search, nis_mtime, MAPC_INC },
221 #endif
222
223 #ifdef HAS_NDBM_MAPS
224 { "ndbm", ndbm_init, error_reload, ndbm_search, ndbm_mtime, MAPC_INC },
225 #endif
226
227 #ifdef HAS_FILE_MAPS
228 { "file", file_init, file_reload, file_search, file_mtime, MAPC_ALL },
229 #endif
230
231 { "error", error_init, error_reload, error_search, error_mtime, MAPC_NONE },
232 };
233
234 /*
235 * Hash function
236 */
237 static unsigned int kvhash_of P((char *key));
kvhash_of(key)238 static unsigned int kvhash_of(key)
239 char *key;
240 {
241 unsigned int i, j;
242
243 for (i = 0; j = *key++; i += j)
244 ;
245
246 return i % NKVHASH;
247 }
248
249 void mapc_showtypes P((FILE *fp));
mapc_showtypes(fp)250 void mapc_showtypes(fp)
251 FILE *fp;
252 {
253 map_type *mt;
254 char *sep = "";
255 for (mt = maptypes; mt < maptypes+sizeof(maptypes)/sizeof(maptypes[0]); mt++) {
256 fprintf(fp, "%s%s", sep, mt->name);
257 sep = ", ";
258 }
259 }
260
261 static Const char *reg_error = "?";
262 void regerror P((Const char *m));
regerror(m)263 void regerror(m)
264 Const char *m;
265 {
266 reg_error = m;
267 }
268
269 /*
270 * Add key and val to the map m.
271 * key and val are assumed to be safe copies
272 */
273 void mapc_add_kv P((mnt_map *m, char *key, char *val));
mapc_add_kv(m,key,val)274 void mapc_add_kv(m, key, val)
275 mnt_map *m;
276 char *key;
277 char *val;
278 {
279 kv **h;
280 kv *n;
281 int hash = kvhash_of(key);
282
283 #ifdef DEBUG
284 dlog("add_kv: %s -> %s", key, val);
285 #endif
286
287 #ifdef HAS_REGEXP
288 if (MAPC_ISRE(m)) {
289 char keyb[MAXPATHLEN];
290 regexp *re;
291 /*
292 * Make sure the string is bound to the start and end
293 */
294 sprintf(keyb, "^%s$", key);
295 re = regcomp(keyb);
296 if (re == 0) {
297 plog(XLOG_USER, "error compiling RE \"%s\": %s", keyb, reg_error);
298 return;
299 } else {
300 free(key);
301 key = (char *) re;
302 }
303 }
304 #endif
305
306 h = &m->kvhash[hash];
307 n = ALLOC(kv);
308 n->key = key;
309 n->val = val;
310 n->next = *h;
311 *h = n;
312 }
313
314 void mapc_repl_kv P((mnt_map *m, char *key, char *val));
mapc_repl_kv(m,key,val)315 void mapc_repl_kv(m, key, val)
316 mnt_map *m;
317 char *key;
318 char *val;
319 {
320 kv *k;
321
322 /*
323 * Compute the hash table offset
324 */
325 k = m->kvhash[kvhash_of(key)];
326
327 /*
328 * Scan the linked list for the key
329 */
330 while (k && !FSTREQ(k->key, key))
331 k = k->next;
332
333 if (k) {
334 free(k->val);
335 k->val = val;
336 } else {
337 mapc_add_kv(m, key, val);
338 }
339
340 }
341
342 /*
343 * Search a map for a key.
344 * Calls map specific search routine.
345 * While map is out of date, keep re-syncing.
346 */
347 static int search_map P((mnt_map *m, char *key, char **valp));
search_map(m,key,valp)348 static int search_map(m, key, valp)
349 mnt_map *m;
350 char *key;
351 char **valp;
352 {
353 int rc;
354 do {
355 rc = (*m->search)(m, m->map_name, key, valp, &m->modify);
356 if (rc < 0) {
357 plog(XLOG_MAP, "Re-synchronizing cache for map %s", m->map_name);
358 mapc_sync(m);
359 }
360 } while (rc < 0);
361
362 return rc;
363 }
364
365 /*
366 * Do a wildcard lookup in the map and
367 * save the result.
368 */
369 static void mapc_find_wildcard P((mnt_map *m));
mapc_find_wildcard(m)370 static void mapc_find_wildcard(m)
371 mnt_map *m;
372 {
373 /*
374 * Attempt to find the wildcard entry
375 */
376 int rc = search_map(m, wildcard, &m->wildcard);
377
378 if (rc != 0)
379 m->wildcard = 0;
380 }
381
382 /*
383 * Make a duplicate reference to an existing map
384 */
385 #define mapc_dup(m) ((m)->refc++, (m))
386
387 /*
388 * Do a map reload
389 */
mapc_reload_map(m)390 static int mapc_reload_map(m)
391 mnt_map *m;
392 {
393 int error;
394 #ifdef DEBUG
395 dlog("calling map reload on %s", m->map_name);
396 #endif
397 error = (*m->reload)(m, m->map_name, mapc_add_kv);
398 if (error)
399 return error;
400 m->wildcard = 0;
401 #ifdef DEBUG
402 dlog("calling mapc_search for wildcard");
403 #endif
404 error = mapc_search(m, wildcard, &m->wildcard);
405 if (error)
406 m->wildcard = 0;
407 return 0;
408 }
409
410 /*
411 * Create a new map
412 */
413 static mnt_map *mapc_create P((char *map, char *opt));
mapc_create(map,opt)414 static mnt_map *mapc_create(map, opt)
415 char *map;
416 char *opt;
417 {
418 mnt_map *m = ALLOC(mnt_map);
419 map_type *mt;
420 time_t modify;
421 int alloc = 0;
422
423 (void) cmdoption(opt, mapc_opt, &alloc);
424
425 for (mt = maptypes; mt < maptypes+sizeof(maptypes)/sizeof(maptypes[0]); mt++)
426 if ((*mt->init)(map, &modify) == 0)
427 break;
428 /* assert: mt in maptypes */
429
430 m->flags = alloc & ~MAPC_CACHE_MASK;
431 alloc &= MAPC_CACHE_MASK;
432
433 if (alloc == MAPC_DFLT)
434 alloc = mt->def_alloc;
435 switch (alloc) {
436 default:
437 plog(XLOG_USER, "Ambiguous map cache type \"%s\"; using \"inc\"", opt);
438 alloc = MAPC_INC;
439 /* fallthrough... */
440 case MAPC_NONE:
441 case MAPC_INC:
442 case MAPC_ROOT:
443 break;
444 case MAPC_ALL:
445 /*
446 * If there is no support for reload and it was requested
447 * then back off to incremental instead.
448 */
449 if (mt->reload == error_reload) {
450 plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"all\"; using \"inc\"", mt->name);
451 alloc = MAPC_INC;
452 }
453 break;
454 #ifdef HAS_REGEXP
455 case MAPC_RE:
456 if (mt->reload == error_reload) {
457 plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"re\"", mt->name);
458 mt = &maptypes[sizeof(maptypes)/sizeof(maptypes[0]) - 1];
459 /* assert: mt->name == "error" */
460 }
461 break;
462 #endif
463 }
464
465 #ifdef DEBUG
466 dlog("Map for %s coming from maptype %s", map, mt->name);
467 #endif
468
469 m->alloc = alloc;
470 m->reload = mt->reload;
471 m->modify = modify;
472 m->search = alloc >= MAPC_ALL ? error_search : mt->search;
473 m->mtime = mt->mtime;
474 bzero((voidp) m->kvhash, sizeof(m->kvhash));
475 m->map_name = strdup(map);
476 m->refc = 1;
477 m->wildcard = 0;
478
479 /*
480 * synchronize cache with reality
481 */
482 mapc_sync(m);
483
484 return m;
485 }
486
487 /*
488 * Free the cached data in a map
489 */
490 static void mapc_clear P((mnt_map *m));
mapc_clear(m)491 static void mapc_clear(m)
492 mnt_map *m;
493 {
494 int i;
495
496 /*
497 * For each of the hash slots, chain
498 * along free'ing the data.
499 */
500 for (i = 0; i < NKVHASH; i++) {
501 kv *k = m->kvhash[i];
502 while (k) {
503 kv *n = k->next;
504 free((voidp) k->key);
505 if (k->val)
506 free((voidp) k->val);
507 free((voidp) k);
508 k = n;
509 }
510 }
511 /*
512 * Zero the hash slots
513 */
514 bzero((voidp) m->kvhash, sizeof(m->kvhash));
515 /*
516 * Free the wildcard if it exists
517 */
518 if (m->wildcard) {
519 free(m->wildcard);
520 m->wildcard = 0;
521 }
522 }
523
524 /*
525 * Find a map, or create one if it does not exist
526 */
527 mnt_map *mapc_find P((char *map, char *opt));
mapc_find(map,opt)528 mnt_map *mapc_find(map, opt)
529 char *map;
530 char *opt;
531 {
532 mnt_map *m;
533
534 /*
535 * Search the list of known maps to see if
536 * it has already been loaded. If it is found
537 * then return a duplicate reference to it.
538 * Otherwise make a new map as required and
539 * add it to the list of maps
540 */
541 ITER(m, mnt_map, &map_list_head)
542 if (STREQ(m->map_name, map))
543 return mapc_dup(m);
544
545 m = mapc_create(map, opt);
546 ins_que(&m->hdr, &map_list_head);
547 return m;
548 }
549
550 /*
551 * Free a map.
552 */
553 void mapc_free P((mnt_map *m));
mapc_free(m)554 void mapc_free(m)
555 mnt_map *m;
556 {
557 /*
558 * Decrement the reference count.
559 * If the reference count hits zero
560 * then throw the map away.
561 */
562 if (m && --m->refc == 0) {
563 mapc_clear(m);
564 free((voidp) m->map_name);
565 rem_que(&m->hdr);
566 free((voidp) m);
567 }
568 }
569
570 /*
571 * Search the map for the key.
572 * Put a safe copy in *pval or return
573 * an error code
574 */
575 int mapc_meta_search P((mnt_map *m, char *key, char **pval, int recurse));
mapc_meta_search(m,key,pval,recurse)576 int mapc_meta_search(m, key, pval, recurse)
577 mnt_map *m;
578 char *key;
579 char **pval;
580 int recurse;
581 {
582 int error = 0;
583 kv *k = 0;
584
585 /*
586 * Firewall
587 */
588 if (!m) {
589 plog(XLOG_ERROR, "Null map request for %s", key);
590 return ENOENT;
591 }
592
593 if (m->flags & MAPC_SYNC) {
594 /*
595 * Get modify time...
596 */
597 time_t t;
598 error = (*m->mtime)(m->map_name, &t);
599 if (error || t > m->modify) {
600 m->modify = t;
601 plog(XLOG_INFO, "Map %s is out of date", m->map_name);
602 mapc_sync(m);
603 }
604 }
605
606 if (!MAPC_ISRE(m)) {
607 /*
608 * Compute the hash table offset
609 */
610 k = m->kvhash[kvhash_of(key)];
611
612 /*
613 * Scan the linked list for the key
614 */
615 while (k && !FSTREQ(k->key, key)) k = k->next;
616
617 }
618 #ifdef HAS_REGEXP
619 else if (recurse == MREC_FULL) {
620 /*
621 * Try for an RE match against the entire map.
622 * Note that this will be done in a "random"
623 * order.
624 */
625
626 int i;
627
628 for (i = 0; i < NKVHASH; i++) {
629 k = m->kvhash[i];
630 while (k) {
631 if (regexec((regexp *) k->key, key))
632 break;
633 k = k->next;
634 }
635 if (k)
636 break;
637 }
638 }
639 #endif
640
641 /*
642 * If found then take a copy
643 */
644 if (k) {
645 if (k->val)
646 *pval = strdup(k->val);
647 else
648 error = ENOENT;
649 } else if (m->alloc >= MAPC_ALL) {
650 /*
651 * If the entire map is cached then this
652 * key does not exist.
653 */
654 error = ENOENT;
655 } else {
656 /*
657 * Otherwise search the map. If we are
658 * in incremental mode then add the key
659 * to the cache.
660 */
661 error = search_map(m, key, pval);
662 if (!error && m->alloc == MAPC_INC)
663 mapc_add_kv(m, strdup(key), strdup(*pval));
664 }
665
666 /*
667 * If an error, and a wildcard exists,
668 * and the key is not internal then
669 * return a copy of the wildcard.
670 */
671 if (error > 0) {
672 if (recurse == MREC_FULL && !MAPC_ISRE(m)) {
673 char wildname[MAXPATHLEN];
674 char *subp;
675 if (*key == '/')
676 return error;
677 /*
678 * Keep chopping sub-directories from the RHS
679 * and replacing with "/ *" and repeat the lookup.
680 * For example:
681 * "src/gnu/gcc" -> "src / gnu / *" -> "src / *"
682 */
683 strcpy(wildname, key);
684 while (error && (subp = strrchr(wildname, '/'))) {
685 strcpy(subp, "/*");
686 #ifdef DEBUG
687 dlog("mapc recurses on %s", wildname);
688 #endif
689 error = mapc_meta_search(m, wildname, pval, MREC_PART);
690 if (error)
691 *subp = 0;
692 }
693 if (error > 0 && m->wildcard) {
694 *pval = strdup(m->wildcard);
695 error = 0;
696 }
697 }
698 }
699
700 return error;
701 }
702
703 int mapc_search P((mnt_map *m, char *key, char **pval));
mapc_search(m,key,pval)704 int mapc_search(m, key, pval)
705 mnt_map *m;
706 char *key;
707 char **pval;
708 {
709 return mapc_meta_search(m, key, pval, MREC_FULL);
710 }
711
712 /*
713 * Get map cache in sync with physical representation
714 */
715 static void mapc_sync P((mnt_map *m));
mapc_sync(m)716 static void mapc_sync(m)
717 mnt_map *m;
718 {
719 if (m->alloc != MAPC_ROOT) {
720 mapc_clear(m);
721
722 if (m->alloc >= MAPC_ALL)
723 if (mapc_reload_map(m))
724 m->alloc = MAPC_INC;
725 /*
726 * Attempt to find the wildcard entry
727 */
728 if (m->alloc < MAPC_ALL)
729 mapc_find_wildcard(m);
730 }
731 }
732
733 /*
734 * Reload all the maps
735 * Called when Amd gets hit by a SIGHUP.
736 */
737 void mapc_reload(P_void);
mapc_reload()738 void mapc_reload()
739 {
740 mnt_map *m;
741
742 /*
743 * For all the maps,
744 * Throw away the existing information.
745 * Do a reload
746 * Find the wildcard
747 */
748 ITER(m, mnt_map, &map_list_head)
749 mapc_sync(m);
750 }
751
752 /*
753 * Root map.
754 * The root map is used to bootstrap amd.
755 * All the require top-level mounts are added
756 * into the root map and then the map is iterated
757 * and a lookup is done on all the mount points.
758 * This causes the top level mounts to be automounted.
759 */
760
761 static int root_init P((char *map, time_t *tp));
root_init(map,tp)762 static int root_init(map, tp)
763 char *map;
764 time_t *tp;
765 {
766 *tp = clocktime();
767 return strcmp(map, ROOT_MAP) == 0 ? 0 : ENOENT;
768 }
769
770 /*
771 * Add a new entry to the root map
772 *
773 * dir - directory (key)
774 * opts - mount options
775 * map - map name
776 */
777 void root_newmap P((char *dir, char *opts, char *map));
root_newmap(dir,opts,map)778 void root_newmap(dir, opts, map)
779 char *dir;
780 char *opts;
781 char *map;
782 {
783 char str[MAXPATHLEN];
784
785 /*
786 * First make sure we have a root map to talk about...
787 */
788 if (!root_map)
789 root_map = mapc_find(ROOT_MAP, "mapdefault");
790
791 /*
792 * Then add the entry...
793 */
794 dir = strdup(dir);
795 if (map)
796 sprintf(str, "cache:=mapdefault;type:=toplvl;fs:=\"%s\";%s",
797 map, opts ? opts : "");
798 else
799 strcpy(str, opts);
800 mapc_repl_kv(root_map, dir, strdup(str));
801 }
802
803 int mapc_keyiter P((mnt_map *m, void (*fn)(char*,voidp), voidp arg));
mapc_keyiter(m,fn,arg)804 int mapc_keyiter(m, fn, arg)
805 mnt_map *m;
806 void (*fn)P((char*, voidp));
807 voidp arg;
808 {
809 int i;
810 int c = 0;
811
812 for (i = 0; i < NKVHASH; i++) {
813 kv *k = m->kvhash[i];
814 while (k) {
815 (*fn)(k->key, arg);
816 k = k->next;
817 c++;
818 }
819 }
820
821 return c;
822 }
823
824 /*
825 * Iterate of the the root map
826 * and call (*fn)() on the key
827 * of all the nodes.
828 * Finally throw away the root map.
829 */
830 int root_keyiter P((void (*fn)(char*,voidp), voidp arg));
831 int root_keyiter(fn, arg)
832 void (*fn)P((char*,voidp));
833 voidp arg;
834 {
835 if (root_map) {
836 int c = mapc_keyiter(root_map, fn, arg);
837 #ifdef notdef
838 mapc_free(root_map);
839 root_map = 0;
840 #endif
841 return c;
842 }
843 return 0;
844 }
845
846 /*
847 * Error map
848 */
849 static int error_init P((char *map, time_t *tp));
error_init(map,tp)850 static int error_init(map, tp)
851 char *map;
852 time_t *tp;
853 {
854 plog(XLOG_USER, "No source data for map %s", map);
855 *tp = 0;
856 return 0;
857 }
858
859 /*ARGSUSED*/
860 static int error_search P((mnt_map *m, char *map, char *key, char **pval, time_t *tp));
error_search(m,map,key,pval,tp)861 static int error_search(m, map, key, pval, tp)
862 mnt_map *m;
863 char *map;
864 char *key;
865 char **pval;
866 time_t *tp;
867 {
868 return ENOENT;
869 }
870
871 /*ARGSUSED*/
872 static int error_reload P((mnt_map *m, char *map, add_fn *fn));
error_reload(m,map,fn)873 static int error_reload(m, map, fn)
874 mnt_map *m;
875 char *map;
876 add_fn *fn;
877 {
878 return ENOENT;
879 }
880
881 static int error_mtime P((char *map, time_t *tp));
error_mtime(map,tp)882 static int error_mtime(map, tp)
883 char *map;
884 time_t *tp;
885 {
886 *tp = 0;
887 return 0;
888 }
889