* $Id: mapc.c,v 5.2 90/06/23 22:19:37 jsp Rel $
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)mapc.c 5.1 (Berkeley) 6/29/90
#define NKVHASH (1 << 2) /* Power of two */
static char wildcard
[] = "*";
* default, none, incremental, all
#define mapc_reload_map(m) \
((*(m)->reload)(m, m->map_name, mapc_add_kv))
typedef void add_fn
P((mnt_map
*, char*, char*));
typedef int init_fn
P((char*));
typedef int search_fn
P((mnt_map
*, char*, char*, char**, time_t*));
typedef int reload_fn
P((mnt_map
*, char*, add_fn
*));
static void mapc_sync
P((mnt_map
*));
typedef struct map_type map_type
;
char *name
; /* Name of this map type */
init_fn
*init
; /* Initialisation */
reload_fn
*reload
; /* Reload or fill */
search_fn
*search
; /* Search for new entry */
int def_alloc
; /* Default allocation mode */
int refc
; /* Reference count */
int alloc
; /* Allocation mode */
time_t modify
; /* Modify time of map */
char *map_name
; /* Name of this map */
char *wildcard
; /* Wildcard value */
reload_fn
*reload
; /* Function to be used for reloads */
search_fn
*search
; /* Function to be used for searching */
kv
*kvhash
[NKVHASH
]; /* Cached data */
static mnt_map
*root_map
;
extern qelem map_list_head
;
qelem map_list_head
= { &map_list_head
, &map_list_head
};
static int root_init
P((char*));
extern int file_init
P((char*));
extern int file_reload
P((mnt_map
*, char*, add_fn
*));
extern int file_search
P((mnt_map
*, char*, char*, char**, time_t*));
#endif /* HAS_FILE_MAPS */
/* Network Information Service (NIS) MAPS */
extern int nis_init
P((char*));
extern int nis_search
P((mnt_map
*, char*, char*, char**, time_t*));
#endif /* HAS_NIS_MAPS */
extern int ndbm_init
P((char*));
extern int ndbm_search
P((mnt_map
*, char*, char*, char**, time_t*));
#endif /* HAS_NDBM_MAPS */
extern int passwd_init
P((char*));
extern int passwd_search
P((mnt_map
*, char*, char*, char**, time_t*));
#endif /* HAS_PASSWD_MAPS */
extern int hesiod_init
P((char*));
extern int hesiod_search
P((mnt_map
*, char*, char*, char**, time_t*));
#endif /* HAS_HESIOD_MAPS */
static int error_init
P((char*));
static int error_reload
P((mnt_map
*, char*, add_fn
*));
static int error_search
P((mnt_map
*, char*, char*, char**, time_t*));
static map_type maptypes
[] = {
{ "root", root_init
, error_reload
, error_search
, MAPC_ALL
},
{ "passwd", passwd_init
, error_reload
, passwd_search
, MAPC_INC
},
#endif /* HAS_PASSWD_MAPS */
{ "hesiod", hesiod_init
, error_reload
, hesiod_search
, MAPC_INC
},
#endif /* HAS_HESIOD_MAPS */
{ "nis", nis_init
, error_reload
, nis_search
, MAPC_INC
},
#endif /* HAS_NIS_MAPS */
{ "ndbm", ndbm_init
, error_reload
, ndbm_search
, MAPC_INC
},
#endif /* HAS_NDBM_MAPS */
{ "file", file_init
, file_reload
, file_search
, MAPC_ALL
},
#endif /* HAS_FILE_MAPS */
{ "error", error_init
, error_reload
, error_search
, MAPC_NONE
},
static unsigned int kvhash_of(key
)
for (i
= 0; j
= *key
++; i
+= j
)
for (mt
= maptypes
; mt
< maptypes
+sizeof(maptypes
)/sizeof(maptypes
[0]); mt
++) {
fprintf(fp
, "%s%s", sep
, mt
->name
);
* Add key and val to the map m.
* key and val are assumed to be safe copies
void mapc_add_kv(m
, key
, val
)
kv
**h
= &m
->kvhash
[kvhash_of(key
)];
static int search_map(m
, key
, valp
)
rc
= (*m
->search
)(m
, m
->map_name
, key
, valp
, &m
->modify
);
plog(XLOG_MAP
, "Re-synchronizing cache for map %s", m
->map_name
);
* Do a wildcard lookup in the map and
static void mapc_find_wildcard(m
)
* Attempt to find the wildcard entry
int rc
= search_map(m
, wildcard
, &m
->wildcard
);
* Make a duplicate reference to an existing map
#define mapc_dup(m) ((m)->refc++, (m))
static mnt_map
*mapc_create(map
, opt
)
mnt_map
*m
= ALLOC(mnt_map
);
int alloc
= STREQ(opt
, "all") ? MAPC_ALL
:
(STREQ(opt
, "inc") ? MAPC_INC
:
((STREQ(opt
, "default") || STREQ(opt
, "mapdefault")) ? MAPC_DFLT
:
for (mt
= maptypes
; mt
< maptypes
+sizeof(maptypes
)/sizeof(maptypes
[0]); mt
++)
if ((*mt
->init
)(map
) == 0)
dlog("Map for %s coming from maptype %s", map
, mt
->name
);
* If there is no support for reload and it was requested
* then back off to incremental instead.
if (mt
->reload
== error_reload
&& alloc
== MAPC_ALL
&& mt
->def_alloc
!= MAPC_ALL
) {
plog(XLOG_WARNING
, "Map type \"%s\" does not support cache type \"all\"",
} else if (alloc
== MAPC_DFLT
)
m
->search
= alloc
== MAPC_ALL
? error_search
: mt
->search
;
bzero((voidp
) m
->kvhash
, sizeof(m
->kvhash
));
m
->map_name
= strdup(map
);
* Attempt to find the wildcard entry
* If cache all is specified then load the cache
if (mapc_reload_map(m
)) {
* If that doesn't work then fallback to
* Free the cached data in a map
static void mapc_clear(m
)
* For each of the hash slots, chain
* along free'ing the data.
for (i
= 0; i
< NKVHASH
; i
++) {
bzero((voidp
) m
->kvhash
, sizeof(m
->kvhash
));
* Free the wildcard if it exists
* Find a map, or create one if it does not exist
mnt_map
*mapc_find(map
, opt
)
* 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
))
m
= mapc_create(map
, opt
);
ins_que(&m
->hdr
, &map_list_head
);
* Decrement the reference count.
* If the reference count hits zero
* then throw the map away.
* Search the map for the key.
* Put a safe copy in *pval or return
int mapc_search(m
, key
, pval
)
* Compute the hash table offset
k
= m
->kvhash
[kvhash_of(key
)];
* Scan the linked list for the key
while (k
&& !FSTREQ(k
->key
, key
))
* If found then take a copy
} else if (m
->alloc
== MAPC_ALL
) {
* If the entire map is cached then this
* Otherwise search the map. If we are
* in incremental mode then add the key
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
&& m
->wildcard
&& *key
!= '/') {
*pval
= strdup(m
->wildcard
);
if (m
->alloc
== MAPC_ALL
)
* Called when amd gets hit by a SIGHUP.
* Throw away the existing information.
ITER(m
, mnt_map
, &map_list_head
)
* 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(map
)
return strcmp(map
, ROOT_MAP
) == 0 ? 0 : ENOENT
;
* Add a new entry to the root map
void root_newmap(dir
, opts
, map
)
* First make sure we have a root map to talk about...
root_map
= mapc_find(ROOT_MAP
, "all");
sprintf(str
, "cache:=none;type:=auto;fs:=\"%s\";%s", map
, opts
? opts
: "");
mapc_add_kv(root_map
, dir
, strdup(str
));
* Iterate of the the root map
* and call (*fn)() on the key
* Finally throw away the root map.
for (i
= 0; i
< NKVHASH
; i
++) {
kv
*k
= root_map
->kvhash
[i
];
static int error_init(map
)
static int error_search(m
, map
, key
, pval
, tp
)
static int error_reload(m
, map
, fn
)