diff options
author | Ulrich Drepper <drepper@gmail.com> | 2011-06-14 22:21:51 -0400 |
---|---|---|
committer | Ulrich Drepper <drepper@gmail.com> | 2011-06-15 21:06:18 -0400 |
commit | 2666d441c2d8107b1987b869714189af64b954c6 (patch) | |
tree | c7b8877d691db280202b4c7655907a1165ec84fc /nss | |
parent | Rewrite makedb to avoid using db library (diff) | |
download | glibc-2666d441c2d8107b1987b869714189af64b954c6.tar.gz glibc-2666d441c2d8107b1987b869714189af64b954c6.tar.bz2 glibc-2666d441c2d8107b1987b869714189af64b954c6.zip |
Reenable nss_db with a completely new implementation
No longer is Berkeley db used. Instead a simple hash function is used.
The database files are not updated once they are created and therefore
no complicated database is needed.
Diffstat (limited to 'nss')
-rw-r--r-- | nss/Makefile | 19 | ||||
-rw-r--r-- | nss/Versions | 58 | ||||
-rw-r--r-- | nss/db-Makefile | 70 | ||||
-rw-r--r-- | nss/makedb.c | 249 | ||||
-rw-r--r-- | nss/nss_db/db-XXX.c | 332 | ||||
-rw-r--r-- | nss/nss_db/db-alias.c | 215 | ||||
-rw-r--r-- | nss/nss_db/db-netgrp.c | 94 | ||||
-rw-r--r-- | nss/nss_db/db-open.c | 377 | ||||
-rw-r--r-- | nss/nss_db/dummy-db.h | 333 | ||||
-rw-r--r-- | nss/nss_db/nss_db.h | 96 | ||||
-rw-r--r-- | nss/nss_files/files-XXX.c | 10 | ||||
-rw-r--r-- | nss/nss_files/files-ethers.c | 6 | ||||
-rw-r--r-- | nss/nss_files/files-grp.c | 6 | ||||
-rw-r--r-- | nss/nss_files/files-hosts.c | 2 | ||||
-rw-r--r-- | nss/nss_files/files-network.c | 6 | ||||
-rw-r--r-- | nss/nss_files/files-proto.c | 6 | ||||
-rw-r--r-- | nss/nss_files/files-pwd.c | 6 | ||||
-rw-r--r-- | nss/nss_files/files-rpc.c | 6 | ||||
-rw-r--r-- | nss/nss_files/files-service.c | 11 | ||||
-rw-r--r-- | nss/nss_files/files-sgrp.c | 4 | ||||
-rw-r--r-- | nss/nss_files/files-spwd.c | 4 |
21 files changed, 519 insertions, 1391 deletions
diff --git a/nss/Makefile b/nss/Makefile index 16578a3548..a925cb5bf7 100644 --- a/nss/Makefile +++ b/nss/Makefile @@ -53,7 +53,7 @@ otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \ endif # Specify rules for the nss_* modules. We have some services. -services := files +services := files db extra-libs = $(services:%=libnss_%) # These libraries will be built in the `others' pass rather than @@ -69,10 +69,18 @@ libnss_files-routines := $(addprefix files-,$(databases)) \ files-initgroups files-have_o_cloexec distribute += files-XXX.c files-parse.c +libnss_db-dbs := $(addprefix db-,\ + $(filter-out hosts network key alias,\ + $(databases))) +libnss_db-routines := $(libnss_db-dbs) db-open hash-string +generated += $(filter-out db-alias.c db-netgrp.c, \ + $(addsuffix .c,$(libnss_db-dbs))) +distribute += $(addprefix nss_db/, db-XXX.c nss_db.h) # Build static module if requested ifneq ($(build-static-nss),yes) libnss_files-inhibit-o = $(filter-out .os,$(object-suffixes)) +libnss_db-inhibit-o = $(filter-out .os,$(object-suffixes)) endif include ../Rules @@ -93,6 +101,15 @@ libnss-libc = $(common-objpfx)linkobj/libc.so $(services:%=$(objpfx)libnss_%.so): $(libnss-libc) \ $(common-objpfx)libc_nonshared.a +$(objpfx)libnss_db.so: $(objpfx)libnss_files.so + +$(libnss_db-dbs:%=$(objpfx)%.c): $(objpfx)db-%.c: nss_files/files-%.c + @rm -f $@.new + (echo '#define EXTERN_PARSER';\ + echo '#define GENERIC "../nss_db/db-XXX.c"';\ + echo '#include "$<"') > $@.new + mv -f $@.new $@ + $(objpfx)makedb: $(makedb-modules:%=$(objpfx)%.o) diff --git a/nss/Versions b/nss/Versions index 1c6fd686f3..2f3a671af6 100644 --- a/nss/Versions +++ b/nss/Versions @@ -27,6 +27,8 @@ libnss_files { _nss_files_endetherent; _nss_files_getetherent_r; _nss_files_parse_etherent; + _nss_files_gethostton_r; + _nss_files_getntohost_r; _nss_files_setgrent; _nss_files_endgrent; @@ -41,14 +43,12 @@ libnss_files { _nss_files_gethostbyname4_r; _nss_files_gethostbyname_r; _nss_files_gethostent_r; - _nss_files_gethostton_r; _nss_files_setnetent; _nss_files_endnetent; _nss_files_getnetbyaddr_r; _nss_files_getnetbyname_r; _nss_files_getnetent_r; - _nss_files_getntohost_r; _nss_files_parse_netent; _nss_files_setnetgrent; @@ -99,3 +99,57 @@ libnss_files { _nss_files_initgroups_dyn; } } + +libnss_db { + GLIBC_PRIVATE { + _nss_db_setetherent; + _nss_db_endetherent; + _nss_db_getetherent_r; + _nss_db_gethostton_r; + _nss_db_getntohost_r; + + _nss_db_setgrent; + _nss_db_endgrent; + _nss_db_getgrent_r; + _nss_db_getgrgid_r; + _nss_db_getgrnam_r; + + _nss_db_setnetgrent; + _nss_db_endnetgrent; + _nss_db_getnetgrent_r; + + _nss_db_setprotoent; + _nss_db_endprotoent; + _nss_db_getprotoent_r; + _nss_db_getprotobyname_r; + _nss_db_getprotobynumber_r; + + _nss_db_setpwent; + _nss_db_endpwent; + _nss_db_getpwent_r; + _nss_db_getpwnam_r; + _nss_db_getpwuid_r; + + _nss_db_setrpcent; + _nss_db_endrpcent; + _nss_db_getrpcent_r; + _nss_db_getrpcbyname_r; + _nss_db_getrpcbynumber_r; + + _nss_db_setservent; + _nss_db_endservent; + _nss_db_getservent_r; + _nss_db_getservbyname_r; + _nss_db_getservbyport_r; + + _nss_db_setsgent; + _nss_db_endsgent; + _nss_db_getsgent_r; + _nss_db_getsgnam_r; + + _nss_db_setspent; + _nss_db_endspent; + _nss_db_getspent_r; + _nss_db_getspnam_r; + } +} diff --git a/nss/db-Makefile b/nss/db-Makefile index f9c6bd37d7..649e09ced6 100644 --- a/nss/db-Makefile +++ b/nss/db-Makefile @@ -1,5 +1,5 @@ # Makefile to (re-)generate db versions of system database files. -# Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 2011 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. # @@ -20,7 +20,8 @@ # 02111-1307 USA. DATABASES = $(wildcard /etc/passwd /etc/group /etc/ethers /etc/protocols \ - /etc/rpc /etc/services /etc/shadow /etc/netgroup) + /etc/rpc /etc/services /etc/shadow /etc/gshadow \ + /etc/netgroup) VAR_DB = /var/db @@ -32,10 +33,9 @@ all: $(patsubst %,$(VAR_DB)/%.db,$(notdir $(DATABASES))) $(VAR_DB)/passwd.db: /etc/passwd @echo -n "$(patsubst %.db,%,$(@F))... " - @$(AWK) 'BEGIN { FS=":"; OFS=":"; cnt=0 } \ + @$(AWK) 'BEGIN { FS=":"; OFS=":" } \ /^[ \t]*$$/ { next } \ /^[ \t]*#/ { next } \ - { printf "0%u ", cnt++; print } \ /^[^#]/ { printf ".%s ", $$1; print; \ printf "=%s ", $$3; print }' $^ | \ $(MAKEDB) -o $@ - @@ -43,10 +43,9 @@ $(VAR_DB)/passwd.db: /etc/passwd $(VAR_DB)/group.db: /etc/group @echo -n "$(patsubst %.db,%,$(@F))... " - @$(AWK) 'BEGIN { FS=":"; OFS=":"; cnt=0 } \ + @$(AWK) 'BEGIN { FS=":"; OFS=":" } \ /^[ \t]*$$/ { next } \ /^[ \t]*#/ { next } \ - { printf "0%u ", cnt++; print } \ /^[^#]/ { printf ".%s ", $$1; print; \ printf "=%s ", $$3; print }' $^ | \ $(MAKEDB) -o $@ - @@ -54,10 +53,8 @@ $(VAR_DB)/group.db: /etc/group $(VAR_DB)/ethers.db: /etc/ethers @echo -n "$(patsubst %.db,%,$(@F))... " - @$(AWK) 'BEGIN { cnt=0 } \ - /^[ \t]*$$/ { next } \ + @$(AWK) '/^[ \t]*$$/ { next } \ /^[ \t]*#/ { next } \ - { printf "0%u ", cnt++; print } \ /^[^#]/ { printf ".%s ", $$1; print; \ printf "=%s ", $$2; print }' $^ | \ $(MAKEDB) -o $@ - @@ -65,10 +62,8 @@ $(VAR_DB)/ethers.db: /etc/ethers $(VAR_DB)/protocols.db: /etc/protocols @echo -n "$(patsubst %.db,%,$(@F))... " - @$(AWK) 'BEGIN { cnt=0 } \ - /^[ \t]*$$/ { next } \ + @$(AWK) '/^[ \t]*$$/ { next } \ /^[ \t]*#/ { next } \ - { printf "0%u ", cnt++; print } \ /^[^#]/ { printf ".%s ", $$1; print; \ printf "=%s ", $$2; print; \ for (i = 3; i <= NF && !($$i ~ /^#/); ++i) \ @@ -78,10 +73,8 @@ $(VAR_DB)/protocols.db: /etc/protocols $(VAR_DB)/rpc.db: /etc/rpc @echo -n "$(patsubst %.db,%,$(@F))... " - @$(AWK) 'BEGIN { cnt=0 } \ - /^[ \t]*$$/ { next } \ + @$(AWK) '/^[ \t]*$$/ { next } \ /^[ \t]*#/ { next } \ - { printf "0%u ", cnt++; print } \ /^[^#]/ { printf ".%s ", $$1; print; \ printf "=%s ", $$2; print; \ for (i = 3; i <= NF && !($$i ~ /^#/); ++i) \ @@ -91,26 +84,25 @@ $(VAR_DB)/rpc.db: /etc/rpc $(VAR_DB)/services.db: /etc/services @echo -n "$(patsubst %.db,%,$(@F))... " - @$(AWK) 'BEGIN { FS="[ \t/]+"; cnt=0 } \ + @$(AWK) 'BEGIN { FS="[ \t/]+" } \ /^[ \t]*$$/ { next } \ /^[ \t]*#/ { next } \ - { printf "0%u ", cnt++; print } \ - /^[^#]/ { printf ".%s/%s ", $$1, $$3; print; \ - printf ".%s/ ", $$1; print; \ + /^[^#]/ { sub(/[ \t]*#.*$$/, "");\ + printf ":%s/%s ", $$1, $$3; print; \ + printf ":%s/ ", $$1; print; \ printf "=%s/%s ", $$2, $$3; print; \ printf "=%s/ ", $$2; print; \ for (i = 4; i <= NF && !($$i ~ /^#/); ++i) \ - { printf ".%s/%s ", $$i, $$3; print; \ - printf ".%s/ ", $$i; print } }' $^ | \ + { printf ":%s/%s ", $$i, $$3; print; \ + printf ":%s/ ", $$i; print } }' $^ | \ $(MAKEDB) -o $@ - @echo "done." $(VAR_DB)/shadow.db: /etc/shadow @echo -n "$(patsubst %.db,%,$(@F))... " - @$(AWK) 'BEGIN { FS=":"; OFS=":"; cnt=0 } \ + @$(AWK) 'BEGIN { FS=":"; OFS=":" } \ /^[ \t]*$$/ { next } \ /^[ \t]*#/ { next } \ - { printf "0%u ", cnt++; print } \ /^[^#]/ { printf ".%s ", $$1; print }' $^ | \ (umask 077 && $(MAKEDB) -o $@ -) @echo "done." @@ -126,14 +118,38 @@ $(VAR_DB)/shadow.db: /etc/shadow echo; \ fi +$(VAR_DB)/gshadow.db: /etc/gshadow + @echo -n "$(patsubst %.db,%,$(@F))... " + @$(AWK) 'BEGIN { FS=":"; OFS=":" } \ + /^[ \t]*$$/ { next } \ + /^[ \t]*#/ { next } \ + /^[^#]/ { printf ".%s ", $$1; print }' $^ | \ + (umask 077 && $(MAKEDB) -o $@ -) + @echo "done." + @if chgrp shadow $@ 2>/dev/null; then \ + chmod g+r $@; \ + else \ + chown 0 $@; chgrp 0 $@; chmod 600 $@; \ + echo; \ + echo "Warning: The shadow group database $@"; \ + echo "has been set to be readable only by root. You may want"; \ + echo "to make it readable by the \`shadow' group depending"; \ + echo "on your configuration."; \ + echo; \ + fi + $(VAR_DB)/netgroup.db: /etc/netgroup @echo -n "$(patsubst %.db,%,$(@F))... " - @$(AWK) 'BEGIN { cnt=0 } \ + @$(AWK) 'BEGIN { ini=1 } \ /^[ \t]*$$/ { next } \ /^[ \t]*#/ { next } \ - { printf "0%u ", cnt++; print } \ - /^[^#]/ { end=sub(/\\/, " "); \ + /^[^#]/ { if (sub(/[ \t]*\\$$/, " ") == 0) end="\n"; \ + else end=""; \ gsub(/[ \t]+/, " "); \ - if(end == 1) printf "%s", $$0; else print }' $^ | \ + sub(/^[ \t]*/, ""); \ + if (ini == 0) printf "%s%s", $$0, end; \ + else printf ".%s %s%s", $$1, $$0, end; \ + ini=end == "" ? 0 : 1; } \ + END { if (ini==0) printf "\n" }' $^ | \ $(MAKEDB) -o $@ - @echo "done." diff --git a/nss/makedb.c b/nss/makedb.c index a01b2350aa..687414b74f 100644 --- a/nss/makedb.c +++ b/nss/makedb.c @@ -34,7 +34,7 @@ #include <unistd.h> #include <sys/mman.h> #include <sys/stat.h> -#include "nss_db/dummy-db.h" +#include "nss_db/nss_db.h" /* Get libc version number. */ #include "../version.h" @@ -49,51 +49,21 @@ #define PACKAGE _libc_intl_domainname -/* String table index type. */ -typedef uint32_t stridx_t; - -/* Database file header. */ -struct nss_db_header -{ - uint32_t magic; -#define NSS_DB_MAGIC 0xdd110601 - uint32_t ndbs; - uint64_t valstroffset; - uint64_t valstrlen; - struct - { - char id; - enum nss_db_type { nss_db_type_hash = 0, - nss_db_type_iterate, - nss_db_type_int4 } type:8; - char pad[sizeof (uint32_t) - 2]; - uint32_t hashsize; - uint64_t hashoffset; - uint64_t stroffset; - } dbs[0]; -}; - -struct nss_db_entry -{ - stridx_t keyidx; - stridx_t dataidx; -}; - - /* List of data bases. */ struct database { char dbid; - enum nss_db_type type; struct database *next; void *entries; size_t nentries; - size_t keystrlen; size_t nhashentries; - struct nss_db_entry *hashtable; + stridx_t *hashtable; + size_t keystrlen; + stridx_t *keyidxtab; char *keystrtab; } *databases; static size_t ndatabases; +static size_t nhashentries; static size_t valstrlen; static void *valstrtree; static char *valstrtab; @@ -101,7 +71,6 @@ static char *valstrtab; /* Database entry. */ struct dbentry { - size_t keylen; stridx_t validx; uint32_t hashval; char str[0]; @@ -115,16 +84,6 @@ struct valstrentry }; -/* Database type specifiers. */ -struct dbtype -{ - char dbid; - enum nss_db_type type; - struct dbtype *next; -}; -static struct dbtype *dbtypes; - - /* True if any entry has been added. */ static bool any_dbentry; @@ -154,10 +113,6 @@ static const struct argp_option options[] = { "undo", 'u', NULL, 0, N_("Print content of database file, one entry a line") }, { NULL, 0, NULL, 0, N_("Select index type") }, - { "iterate", 'I', "KEY", 0, - N_("Index identified by KEY used to iterate over database") }, - { "binary", 'B', "KEY", 0, - N_("Index identified by KEY has binary key value") }, { NULL, 0, NULL, 0, NULL } }; @@ -210,7 +165,7 @@ main (int argc, char *argv[]) const char *input_name; FILE *input_file; int remaining; - int mode = 0666; + int mode = 0644; /* Set locale via LC_ALL. */ setlocale (LC_ALL, ""); @@ -292,7 +247,12 @@ main (int argc, char *argv[]) /* Bail out if nothing is to be done. */ if (!any_dbentry) - error (EXIT_SUCCESS, 0, gettext ("no entries to be processed")); + { + if (be_quiet) + return EXIT_SUCCESS; + else + error (EXIT_SUCCESS, 0, gettext ("no entries to be processed")); + } /* Compute hash and string tables. */ compute_tables (); @@ -308,7 +268,6 @@ main (int argc, char *argv[]) reset_file_creation_context (); if (fd == -1) error (EXIT_FAILURE, errno, gettext ("cannot create temporary file")); - // XXX SELinux context status = write_output (fd); @@ -352,7 +311,6 @@ main (int argc, char *argv[]) static error_t parse_opt (int key, char *arg, struct argp_state *state) { - struct dbtype *newtype; switch (key) { case 'f': @@ -367,17 +325,6 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'u': do_undo = 1; break; - case 'I': - case 'B': - if (arg[0] == '\0' || arg[1] != '\0') - error (EXIT_FAILURE, 0, gettext ("\ -argument for option to specify database type must be a single-byte character")); - newtype = xmalloc (sizeof (struct dbtype)); - newtype->dbid = arg[0]; - newtype->type = key == 'I' ? nss_db_type_iterate : nss_db_type_int4; - newtype->next = dbtypes; - dbtypes = newtype; - break; default: return ARGP_ERR_UNKNOWN; } @@ -424,13 +371,7 @@ dbentry_compare (const void *p1, const void *p2) if (d1->hashval != d2->hashval) return d1->hashval < d2->hashval ? -1 : 1; - if (d1->keylen < d2->keylen) - return -1; - - if (d1->keylen > d2->keylen) - return 1; - - return memcmp (d1->str, d2->str, d1->keylen); + return strcmp (d1->str, d2->str); } @@ -522,22 +463,11 @@ process_input (input, inname, to_lowercase, be_quiet) { last_database = xmalloc (sizeof (*last_database)); last_database->dbid = key[0]; - last_database->type = nss_db_type_hash; /* Default. */ last_database->next = databases; last_database->entries = NULL; last_database->nentries = 0; last_database->keystrlen = 0; databases = last_database; - - struct dbtype *typeit = dbtypes; - while (typeit != NULL) - if (typeit->dbid == last_database->dbid) - { - last_database->type = typeit->type; - break; - } - else - typeit = typeit->next; } } @@ -545,24 +475,6 @@ process_input (input, inname, to_lowercase, be_quiet) ++key; --keylen; - /* Check the key value if it has to be numeric. */ - unsigned long int keyvalue = 0; - if (last_database->type != nss_db_type_hash) - { - char *endp; - errno = 0; - keyvalue = strtoul (key, &endp, 0); - if ((keyvalue == ULONG_MAX && errno == ERANGE) - || keyvalue > ~((stridx_t) 0)) - error (EXIT_FAILURE, 0, - gettext ("index value in line %zu too large"), linenr); - - if (*endp != '\0') - error (EXIT_FAILURE, 0, - gettext ("index value in line %zu is not a number"), - linenr); - } - /* Store the data. */ struct valstrentry *nentry = xmalloc (sizeof (struct valstrentry) + datalen); @@ -584,24 +496,10 @@ process_input (input, inname, to_lowercase, be_quiet) valstrlen += datalen; /* Store the key. */ - struct dbentry *newp; - if (last_database->type == nss_db_type_hash) - { - newp = xmalloc (sizeof (struct dbentry) + keylen); - newp->keylen = keylen; - newp->validx = nentry->idx; - newp->hashval = __hash_string (key); - memcpy (newp->str, key, keylen); - } - else - { - newp = xmalloc (sizeof (struct dbentry) + sizeof (stridx_t)); - newp->keylen = keylen = sizeof (stridx_t); - newp->validx = nentry->idx; - newp->hashval = keyvalue; - stridx_t value = keyvalue; - memcpy (newp->str, &value, sizeof (stridx_t)); - } + struct dbentry *newp = xmalloc (sizeof (struct dbentry) + keylen); + newp->validx = nentry->idx; + newp->hashval = __hash_string (key); + memcpy (newp->str, key, keylen); struct dbentry **found = tsearch (newp, &last_database->entries, dbentry_compare); @@ -657,29 +555,14 @@ compute_tables (void) { ++ndatabases; - if (db->type == nss_db_type_iterate) - { - /* We need no hash table and no key value table in this case. */ - db->nhashentries = 0; - db->hashtable = NULL; - db->keystrtab = NULL; - db->keystrlen = 0; - continue; - } - - if (db->keystrlen > ~((stridx_t) 0)) - error (EXIT_FAILURE, 0, gettext ("\ -table size too large; recompile with larger stridx_t")); - /* We simply use an odd number large than twice the number of elements to store in the hash table for the size. This gives enough efficiency. */ db->nhashentries = db->nentries * 2 + 1; - db->hashtable = xmalloc (db->nhashentries - * sizeof (struct nss_db_entry)); - memset (db->hashtable, '\xff', - db->nhashentries * sizeof (struct nss_db_entry)); - db->keystrlen = roundup (db->keystrlen, sizeof (stridx_t)); + db->hashtable = xmalloc (db->nhashentries * sizeof (stridx_t)); + memset (db->hashtable, '\xff', db->nhashentries * sizeof (stridx_t)); + db->keyidxtab = xmalloc (db->nhashentries * sizeof (stridx_t)); + memset (db->keyidxtab, '\xff', db->nhashentries * sizeof (stridx_t)); db->keystrtab = xmalloc (db->keystrlen); size_t max_chainlength = 0; @@ -693,21 +576,21 @@ table size too large; recompile with larger stridx_t")); const struct dbentry *dbe = *(const struct dbentry **) nodep; ptrdiff_t stridx = wp - db->keystrtab; - wp = mempcpy (wp, dbe->str, dbe->keylen); + wp = stpcpy (wp, dbe->str) + 1; size_t hidx = dbe->hashval % db->nhashentries; size_t hval2 = 1 + dbe->hashval % (db->nhashentries - 2); size_t chainlength = 0; - while (db->hashtable[hidx].keyidx != ~((stridx_t) 0)) + while (db->hashtable[hidx] != ~((stridx_t) 0)) { ++chainlength; if ((hidx += hval2) >= db->nhashentries) hidx -= db->nhashentries; } - db->hashtable[hidx].keyidx = stridx; - db->hashtable[hidx].dataidx = dbe->validx; + db->hashtable[hidx] = dbe->validx; + db->keyidxtab[hidx] = stridx; max_chainlength = MAX (max_chainlength, chainlength); } @@ -716,8 +599,7 @@ table size too large; recompile with larger stridx_t")); // XXX if hash length is too long resize table and start again - while ((wp - db->keystrtab) % sizeof (stridx_t) != 0) - *wp++ = '\0'; + nhashentries += db->nhashentries; } } @@ -736,7 +618,7 @@ write_output (int fd) header->valstrlen = valstrlen; size_t filled_dbs = 0; - struct iovec iov[2 + 2 * ndatabases]; + struct iovec iov[2 + ndatabases * 3]; iov[0].iov_base = header; iov[0].iov_len = file_offset; @@ -744,6 +626,7 @@ write_output (int fd) iov[1].iov_len = valstrlen; file_offset += valstrlen; + size_t keydataoffset = file_offset + nhashentries * sizeof (stridx_t); for (struct database *db = databases; db != NULL; db = db->next) if (db->entries != NULL) { @@ -751,28 +634,35 @@ write_output (int fd) assert (filled_dbs < ndatabases); header->dbs[filled_dbs].id = db->dbid; - header->dbs[filled_dbs].type = db->type; memset (header->dbs[filled_dbs].pad, '\0', sizeof (header->dbs[0].pad)); header->dbs[filled_dbs].hashsize = db->nhashentries; - iov[2 + filled_dbs * 2].iov_base = db->hashtable; - iov[2 + filled_dbs * 2].iov_len = (db->nhashentries - * sizeof (struct nss_db_entry)); + iov[2 + filled_dbs].iov_base = db->hashtable; + iov[2 + filled_dbs].iov_len = db-> nhashentries * sizeof (stridx_t); header->dbs[filled_dbs].hashoffset = file_offset; - file_offset += iov[2 + filled_dbs * 2].iov_len; + file_offset += iov[2 + filled_dbs].iov_len; - iov[3 + filled_dbs * 2].iov_base = db->keystrtab; - iov[3 + filled_dbs * 2].iov_len = db->keystrlen; - header->dbs[filled_dbs].stroffset = file_offset; - file_offset += iov[3 + filled_dbs * 2].iov_len; + iov[2 + ndatabases + filled_dbs * 2].iov_base = db->keyidxtab; + iov[2 + ndatabases + filled_dbs * 2].iov_len + = db-> nhashentries * sizeof (stridx_t); + header->dbs[filled_dbs].keyidxoffset = keydataoffset; + keydataoffset += iov[2 + ndatabases + filled_dbs * 2].iov_len; + + iov[3 + ndatabases + filled_dbs * 2].iov_base = db->keystrtab; + iov[3 + ndatabases + filled_dbs * 2].iov_len = db->keystrlen; + header->dbs[filled_dbs].keystroffset = keydataoffset; + keydataoffset += iov[3 + ndatabases + filled_dbs * 2].iov_len; ++filled_dbs; } assert (filled_dbs == ndatabases); + assert (file_offset == (iov[0].iov_len + iov[1].iov_len + + nhashentries * sizeof (stridx_t))); + header->allocate = file_offset; - if (writev (fd, iov, 2 + 2 * ndatabases) != file_offset) + if (writev (fd, iov, 2 + ndatabases * 3) != keydataoffset) { error (0, errno, gettext ("failed to write new database file")); return EXIT_FAILURE; @@ -801,42 +691,21 @@ print_database (int fd) for (unsigned int dbidx = 0; dbidx < header->ndbs; ++dbidx) { + const stridx_t *stridxtab + = ((const stridx_t *) ((const char *) header + + header->dbs[dbidx].keyidxoffset)); const char *keystrtab - = (const char *) header + header->dbs[dbidx].stroffset; - const struct nss_db_entry *hashtab - = (const struct nss_db_entry *) ((const char *) header - + header->dbs[dbidx].hashoffset); - - if (header->dbs[dbidx].type == nss_db_type_hash) - { - for (uint32_t hidx = 0; hidx < header->dbs[dbidx].hashsize; ++hidx) - if (hashtab[hidx].keyidx != ~((stridx_t) 0)) - printf ("%c%s %s\n", - header->dbs[dbidx].id, - keystrtab + hashtab[hidx].keyidx, - valstrtab + hashtab[hidx].dataidx); - } - else if (header->dbs[dbidx].type == nss_db_type_iterate) - { - const char *endvalstrtab = valstrtab + header->valstrlen; - const char *cp = valstrtab; - unsigned int count = 0; - while (cp < endvalstrtab && *cp != '\0') - { - printf ("%c%u %s\n", header->dbs[dbidx].id, count++, cp); - cp = rawmemchr (cp, '\0') + 1; - } - } - else - { - assert (header->dbs[dbidx].type == nss_db_type_int4); - for (uint32_t hidx = 0; hidx < header->dbs[dbidx].hashsize; ++hidx) - if (hashtab[hidx].keyidx != ~((stridx_t) 0)) - printf ("%c%" PRIu32 " %s\n", - header->dbs[dbidx].id, - *((uint32_t *) (keystrtab + hashtab[hidx].keyidx)), - valstrtab + hashtab[hidx].dataidx); - } + = (const char *) header + header->dbs[dbidx].keystroffset; + const stridx_t *hashtab + = (const stridx_t *) ((const char *) header + + header->dbs[dbidx].hashoffset); + + for (uint32_t hidx = 0; hidx < header->dbs[dbidx].hashsize; ++hidx) + if (hashtab[hidx] != ~((stridx_t) 0)) + printf ("%c%s %s\n", + header->dbs[dbidx].id, + keystrtab + stridxtab[hidx], + valstrtab + hashtab[hidx]); } return EXIT_SUCCESS; diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c index aa8cfd0746..30026b1866 100644 --- a/nss/nss_db/db-XXX.c +++ b/nss/nss_db/db-XXX.c @@ -1,5 +1,5 @@ /* Common code for DB-based databases in nss_db module. - Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1996-2000, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,10 +19,14 @@ #include <dlfcn.h> #include <fcntl.h> +#include <sys/mman.h> #include <bits/libc-lock.h> #include "nsswitch.h" #include "nss_db.h" +/* The hashing function we use. */ +#include "../intl/hash-string.h" + /* These symbols are defined by the including source file: ENTNAME -- database name of the structure and functions (hostent, pwent). @@ -38,25 +42,25 @@ #define DBFILE _PATH_VARDB DATABASE ".db" #ifdef NEED_H_ERRNO -#define H_ERRNO_PROTO , int *herrnop -#define H_ERRNO_ARG , herrnop -#define H_ERRNO_SET(val) (*herrnop = (val)) +# define H_ERRNO_PROTO , int *herrnop +# define H_ERRNO_ARG , herrnop +# define H_ERRNO_SET(val) (*herrnop = (val)) #else -#define H_ERRNO_PROTO -#define H_ERRNO_ARG -#define H_ERRNO_SET(val) ((void) 0) +# define H_ERRNO_PROTO +# define H_ERRNO_ARG +# define H_ERRNO_SET(val) ((void) 0) #endif -/* Locks the static variables in this file. */ -__libc_lock_define_initialized (static, lock) - -/* Maintenance of the shared handle open on the database. */ +/* State for this database. */ +static struct nss_db_map state; +/* Lock to protect the state and global variables. */ +__libc_lock_define (static , lock); -static NSS_DB *db; +/* Maintenance of the shared handle open on the database. */ static int keep_db; -static int entidx; - +static const char *entidx; + /* Open the database. */ enum nss_status CONCAT(_nss_db_set,ENTNAME) (int stayopen) @@ -65,13 +69,13 @@ CONCAT(_nss_db_set,ENTNAME) (int stayopen) __libc_lock_lock (lock); - status = internal_setent (DBFILE, &db); + status = internal_setent (DBFILE, &state); /* Remember STAYOPEN flag. */ - if (db != NULL) + if (status == NSS_STATUS_SUCCESS) keep_db |= stayopen; /* Reset the sequential index. */ - entidx = 0; + entidx = (const char *) state.header + state.header->valstroffset; __libc_lock_unlock (lock); @@ -85,7 +89,7 @@ CONCAT(_nss_db_end,ENTNAME) (void) { __libc_lock_lock (lock); - internal_endent (&db); + internal_endent (&state); /* Reset STAYOPEN flag. */ keep_db = 0; @@ -94,132 +98,128 @@ CONCAT(_nss_db_end,ENTNAME) (void) return NSS_STATUS_SUCCESS; } - -/* Do a database lookup for KEY. */ -static enum nss_status -lookup (DBT *key, struct STRUCTURE *result, - void *buffer, size_t buflen, int *errnop H_ERRNO_PROTO EXTRA_ARGS_DECL) -{ - char *p; - enum nss_status status; - int err; - DBT value; - - /* Open the database. */ - if (db == NULL) - { - status = internal_setent (DBFILE, &db); - if (status != NSS_STATUS_SUCCESS) - { - *errnop = errno; - H_ERRNO_SET (NETDB_INTERNAL); - return status; - } - } - - /* Succeed iff it matches a value that parses correctly. */ - value.flags = 0; - err = DL_CALL_FCT (db->get, (db->db, NULL, key, &value, 0)); - if (err != 0) - { - if (err == db_notfound) - { - H_ERRNO_SET (HOST_NOT_FOUND); - status = NSS_STATUS_NOTFOUND; - } - else - { - *errnop = err; - H_ERRNO_SET (NETDB_INTERNAL); - status = NSS_STATUS_UNAVAIL; - } - } - else if (buflen < value.size) - { - /* No room to copy the data to. */ - *errnop = ERANGE; - H_ERRNO_SET (NETDB_INTERNAL); - status = NSS_STATUS_TRYAGAIN; - } - else - { - /* Copy the result to a safe place. */ - p = (char *) memcpy (buffer, value.data, value.size); - - /* Skip leading blanks. */ - while (isspace (*p)) - ++p; - - err = parse_line (p, result, buffer, buflen, errnop EXTRA_ARGS); - - if (err == 0) - { - /* If the key begins with '0' we are trying to get the next - entry. We want to ignore unparsable lines in this case. */ - if (((char *) key->data)[0] == '0') - { - /* Super magical return value. We need to tell our caller - that it should continue looping. This value cannot - happen in other cases. */ - status = NSS_STATUS_RETURN; - } - else - { - H_ERRNO_SET (HOST_NOT_FOUND); - status = NSS_STATUS_NOTFOUND; - } - } - else if (err < 0) - { - H_ERRNO_SET (NETDB_INTERNAL); - status = NSS_STATUS_TRYAGAIN; - } - else - status = NSS_STATUS_SUCCESS; - } - - if (! keep_db) - internal_endent (&db); - - return status; -} /* Macro for defining lookup functions for this DB-based database. NAME is the name of the lookup; e.g. `pwnam'. + DB_CHAR is index indicator for the database. + KEYPATTERN gives `printf' args to construct a key string; - e.g. `(".%s", name)'. + e.g. `("%d", id)'. KEYSIZE gives the allocation size of a buffer to construct it in; - e.g. `1 + strlen (name)'. + e.g. `1 + sizeof (id) * 4'. - PROTO describes the arguments for the lookup key; - e.g. `const char *name'. + PROTO is the potentially empty list of other parameters. - BREAK_IF_MATCH is ignored, but used by ../nss_files/files-XXX.c. */ + BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result' + to the lookup key arguments and does `break;' if they match. */ -#define DB_LOOKUP(name, keysize, keypattern, break_if_match, proto...) \ +#define DB_LOOKUP(name, db_char, keysize, keypattern, break_if_match, proto...)\ enum nss_status \ -_nss_db_get##name##_r (proto, \ - struct STRUCTURE *result, \ - char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO)\ + _nss_db_get##name##_r (proto, struct STRUCTURE *result, \ + char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO)\ { \ - DBT key; \ - enum nss_status status; \ - const size_t size = (keysize) + 1; \ - key.data = __alloca (size); \ - key.size = KEYPRINTF keypattern; \ - key.flags = 0; \ - __libc_lock_lock (lock); \ - status = lookup (&key, result, buffer, buflen, errnop H_ERRNO_ARG \ - EXTRA_ARGS_VALUE); \ - __libc_lock_unlock (lock); \ + enum nss_status status = NSS_STATUS_SUCCESS; \ + struct nss_db_map state = { NULL, 0 }; \ + struct parser_data *data = (void *) buffer; \ + \ + if (buflen < sizeof *data) \ + { \ + *errnop = ERANGE; \ + H_ERRNO_SET (NETDB_INTERNAL); \ + return NSS_STATUS_TRYAGAIN; \ + } \ + \ + status = internal_setent (DBFILE, &state); \ + if (status != NSS_STATUS_SUCCESS) \ + { \ + *errnop = errno; \ + H_ERRNO_SET (NETDB_INTERNAL); \ + return status; \ + } \ + \ + if (status == NSS_STATUS_SUCCESS) \ + { \ + const struct nss_db_header *header = state.header; \ + int i; \ + for (i = 0; i < header->ndbs; ++i) \ + if (header->dbs[i].id == db_char) \ + break; \ + if (i == header->ndbs) \ + { \ + status = NSS_STATUS_UNAVAIL; \ + goto out; \ + } \ + \ + char *key; \ + if (db_char == '.') \ + key = (char *) IGNOREPATTERN keypattern; \ + else \ + { \ + const size_t size = (keysize) + 1; \ + key = alloca (size); \ + \ + KEYPRINTF keypattern; \ + } \ + \ + const stridx_t *hashtable \ + = (const stridx_t *) ((const char *) header \ + + header->dbs[i].hashoffset); \ + const char *valstrtab = (const char *) header + header->valstroffset; \ + uint32_t hashval = __hash_string (key); \ + size_t hidx = hashval % header->dbs[i].hashsize; \ + size_t hval2 = 1 + hashval % (header->dbs[i].hashsize - 2); \ + \ + status = NSS_STATUS_NOTFOUND; \ + while (hashtable[hidx] != ~((stridx_t) 0)) \ + { \ + const char *valstr = valstrtab + hashtable[hidx]; \ + size_t len = strlen (valstr) + 1; \ + if (len > buflen) \ + { \ + /* No room to copy the data to. */ \ + *errnop = ERANGE; \ + H_ERRNO_SET (NETDB_INTERNAL); \ + status = NSS_STATUS_TRYAGAIN; \ + break; \ + } \ + \ + /* Copy the string to a place where it can be modified. */ \ + char *p = memcpy (buffer, valstr, len); \ + \ + int err = parse_line (p, result, data, buflen, errnop \ + EXTRA_ARGS); \ + if (err > 0) \ + { \ + status = NSS_STATUS_SUCCESS; \ + break_if_match; \ + status = NSS_STATUS_NOTFOUND; \ + } \ + else if (err == -1) \ + { \ + H_ERRNO_SET (NETDB_INTERNAL); \ + status = NSS_STATUS_TRYAGAIN; \ + break; \ + } \ + \ + if ((hidx += hval2) >= header->dbs[i].hashsize) \ + hidx -= header->dbs[i].hashsize; \ + } \ + \ + if (status == NSS_STATUS_NOTFOUND) \ + H_ERRNO_SET (HOST_NOT_FOUND); \ + } \ + out: \ + internal_endent (&state); \ + \ return status; \ } -#define KEYPRINTF(pattern, args...) snprintf (key.data, size, pattern ,##args) +#define KEYPRINTF(pattern, args...) snprintf (key, size, pattern ,##args) +#define IGNOREPATTERN(pattern, arg1, args...) (char *) (uintptr_t) arg1 @@ -231,30 +231,72 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer, { /* Return next entry in host file. */ enum nss_status status; - char buf[20]; - DBT key; + struct parser_data *data = (void *) buffer; + + if (buflen < sizeof *data) + { + *errnop = ERANGE; + H_ERRNO_SET (NETDB_INTERNAL); + return NSS_STATUS_TRYAGAIN; + } __libc_lock_lock (lock); - /* Loop until we find a valid entry or hit EOF. See above for the - special meaning of the status value. */ - do + if (state.header == NULL) { - key.size = snprintf (key.data = buf, sizeof buf, "0%u", entidx++); - key.flags = 0; - status = lookup (&key, result, buffer, buflen, errnop H_ERRNO_ARG - EXTRA_ARGS_VALUE); - if (status == NSS_STATUS_TRYAGAIN -#ifdef NEED_H_ERRNO - && *herrnop == NETDB_INTERNAL -#endif - && *errnop == ERANGE) - /* Give the user a chance to get the same entry with a larger - buffer. */ - --entidx; + status = internal_setent (DBFILE, &state); + if (status != NSS_STATUS_SUCCESS) + { + *errnop = errno; + H_ERRNO_SET (NETDB_INTERNAL); + goto out; + } + } + + status = NSS_STATUS_UNAVAIL; + if (state.header != MAP_FAILED) + { + const char *const end = ((const char *) state.header + + state.header->valstroffset + + state.header->valstrlen); + while (entidx < end) + { + const char *next = rawmemchr (entidx, '\0') + 1; + size_t len = next - entidx; + + if (len > buflen) + { + /* No room to copy the data to. */ + *errnop = ERANGE; + H_ERRNO_SET (NETDB_INTERNAL); + status = NSS_STATUS_TRYAGAIN; + break; + } + + /* Copy the string to a place where it can be modified. */ + char *p = memcpy (buffer, entidx, len); + + int err = parse_line (p, result, data, buflen, errnop EXTRA_ARGS); + + if (err > 0) + { + status = NSS_STATUS_SUCCESS; + entidx = next; + break; + } + if (err < 0) + { + H_ERRNO_SET (HOST_NOT_FOUND); + status = NSS_STATUS_NOTFOUND; + break; + } + + /* Continue with the next record, this one is ill-formed. */ + entidx = next; + } } - while (status == NSS_STATUS_RETURN); + out: __libc_lock_unlock (lock); return status; diff --git a/nss/nss_db/db-alias.c b/nss/nss_db/db-alias.c deleted file mode 100644 index de468cc592..0000000000 --- a/nss/nss_db/db-alias.c +++ /dev/null @@ -1,215 +0,0 @@ -/* Mail alias file parser in nss_db module. - Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <aliases.h> -#include <alloca.h> -#include <ctype.h> -#include <dlfcn.h> -#include <errno.h> -#include <bits/libc-lock.h> -#include <paths.h> -#include <string.h> - -#include "nsswitch.h" -#include "nss_db.h" - -/* Locks the static variables in this file. */ -__libc_lock_define_initialized (static, lock) - -/* Maintenance of the shared handle open on the database. */ - -static NSS_DB *db; -static int keep_db; -static unsigned int entidx; /* Index for `getaliasent_r'. */ - - -/* Open database. */ -enum nss_status -_nss_db_setaliasent (int stayopen) -{ - enum nss_status status; - - __libc_lock_lock (lock); - - status = internal_setent (_PATH_VARDB "aliases.db", &db); - - /* Remember STAYOPEN flag. */ - if (db != NULL) - keep_db |= stayopen; - - /* Reset the sequential index. */ - entidx = 0; - - __libc_lock_unlock (lock); - - return status; -} - - -/* Close it again. */ -enum nss_status -_nss_db_endaliasent (void) -{ - __libc_lock_lock (lock); - - internal_endent (&db); - - /* Reset STAYOPEN flag. */ - keep_db = 0; - - __libc_lock_unlock (lock); - - return NSS_STATUS_SUCCESS; -} - -/* We provide the parse function here. The parser in libnss_files - cannot be used. The generation of the db file already resolved all - :include: statements so we simply have to parse the list and store - the result. */ -static enum nss_status -lookup (DBT *key, struct aliasent *result, char *buffer, - size_t buflen, int *errnop) -{ - enum nss_status status; - DBT value; - - /* Open the database. */ - if (db == NULL) - { - status = internal_setent (_PATH_VARDB "aliases.db", &db); - if (status != NSS_STATUS_SUCCESS) - { - *errnop = errno; - return status; - } - } - - value.flags = 0; - if (DL_CALL_FCT (db->get, (db->db, NULL, key, &value, 0)) == 0) - { - const char *src = value.data; - char *cp; - size_t cnt; - - result->alias_members_len = 0; - - /* We now have to fill the BUFFER with all the information. */ - if (buflen < key->size + 1) - { - no_more_room: - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - buffer = stpncpy (buffer, key->data, key->size) + 1; - buflen -= key->size + 1; - - while (*src != '\0') - { - const char *end, *upto; - while (isspace (*src)) - ++src; - - end = strchr (src, ','); - if (end == NULL) - end = strchr (src, '\0'); - for (upto = end; upto > src && isspace (upto[-1]); --upto); - - if (upto != src) - { - if ((upto - src) + __alignof__ (char *) > buflen) - goto no_more_room; - buffer = stpncpy (buffer, src, upto - src) + 1; - buflen -= (upto - src) + __alignof (char *); - ++result->alias_members_len; - } - src = end + (*end != '\0'); - } - - /* Now prepare the return. Provide string pointers for the - currently selected aliases. */ - - /* Adjust the pointer so it is aligned for storing pointers. */ - buffer += __alignof__ (char *) - 1; - buffer -= ((buffer - (char *) 0) % __alignof__ (char *)); - result->alias_members = (char **) buffer; - - /* Compute addresses of alias entry strings. */ - cp = result->alias_name; - for (cnt = 0; cnt < result->alias_members_len; ++cnt) - { - cp = strchr (cp, '\0') + 1; - result->alias_members[cnt] = cp; - } - - status = (result->alias_members_len == 0 - ? NSS_STATUS_RETURN : NSS_STATUS_SUCCESS); - } - else - status = NSS_STATUS_NOTFOUND; - - if (! keep_db) - internal_endent (&db); - - return status; -} - -enum nss_status -_nss_db_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen, - int *errnop) -{ - /* Return next entry in alias file. */ - enum nss_status status; - char buf[20]; - DBT key; - - __libc_lock_lock (lock); - key.size = snprintf (key.data = buf, sizeof buf, "0%u", entidx++); - key.flags = 0; - status = lookup (&key, result, buffer, buflen, errnop); - if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) - /* Give the user a chance to get the same entry with a larger buffer. */ - --entidx; - __libc_lock_unlock (lock); - - return status; -} - - -enum nss_status -_nss_db_getaliasbyname_r (const char *name, struct aliasent *result, - char *buffer, size_t buflen, int *errnop) -{ - DBT key; - enum nss_status status; - - key.size = 1 + strlen (name); - - key.data = __alloca (key.size); - ((char *) key.data)[0] = '.'; - memcpy (&((char *) key.data)[1], name, key.size - 1); - key.flags = 0; - - __libc_lock_lock (lock); - status = lookup (&key, result, buffer, buflen, errnop); - __libc_lock_unlock (lock); - - return status; -} diff --git a/nss/nss_db/db-netgrp.c b/nss/nss_db/db-netgrp.c index 47e845a6b9..901d4f50b0 100644 --- a/nss/nss_db/db-netgrp.c +++ b/nss/nss_db/db-netgrp.c @@ -1,5 +1,5 @@ /* Netgroup file parser in nss_db modules. - Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1999, 2000, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -18,6 +18,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <ctype.h> #include <dlfcn.h> #include <errno.h> #include <fcntl.h> @@ -29,55 +30,75 @@ #include "nsswitch.h" #include "nss_db.h" - -#define DBFILE _PATH_VARDB "netgroup.db" +/* The hashing function we use. */ +#include "../intl/hash-string.h" -/* Locks the static variables in this file. */ -__libc_lock_define_initialized (static, lock) +#define DBFILE _PATH_VARDB "netgroup.db" /* Maintenance of the shared handle open on the database. */ -static NSS_DB *db; -static char *entry; -static char *cursor; - enum nss_status -_nss_db_setnetgrent (const char *group) +_nss_db_setnetgrent (const char *group, struct __netgrent *result) { - enum nss_status status; - - __libc_lock_lock (lock); - - status = internal_setent (DBFILE, &db); + struct nss_db_map state; + enum nss_status status = internal_setent (DBFILE, &state); if (status == NSS_STATUS_SUCCESS) { - DBT key = { data: (void *) group, size: strlen (group), flags: 0 }; - DBT value; - - value.flags = 0; - if (DL_CALL_FCT (db->get, (db->db, NULL, &key, &value, 0)) != 0) - status = NSS_STATUS_NOTFOUND; - else - cursor = entry = value.data; + const struct nss_db_header *header = state.header; + const stridx_t *hashtable + = (const stridx_t *) ((const char *) header + + header->dbs[0].hashoffset); + const char *valstrtab = (const char *) header + header->valstroffset; + uint32_t hashval = __hash_string (group); + size_t grouplen = strlen (group); + size_t hidx = hashval % header->dbs[0].hashsize; + size_t hval2 = 1 + hashval % (header->dbs[0].hashsize - 2); + + status = NSS_STATUS_NOTFOUND; + while (hashtable[hidx] != ~((stridx_t) 0)) + { + const char *valstr = valstrtab + hashtable[hidx]; + + if (strncmp (valstr, group, grouplen) == 0 + && isblank (valstr[grouplen])) + { + const char *cp = &valstr[grouplen + 1]; + while (isblank (*cp)) + ++cp; + if (*cp != '\0') + { + result->data = strdup (cp); + if (result->data == NULL) + status = NSS_STATUS_TRYAGAIN; + else + { + status = NSS_STATUS_SUCCESS; + result->cursor = result->data; + } + break; + } + } + + if ((hidx += hval2) >= header->dbs[0].hashsize) + hidx -= header->dbs[0].hashsize; + } + + internal_endent (&state); } - __libc_lock_unlock (lock); - return status; } enum nss_status -_nss_db_endnetgrent (void) +_nss_db_endnetgrent (struct __netgrent *result) { - __libc_lock_lock (lock); - - internal_endent (&db); - - __libc_lock_unlock (lock); - + free (result->data); + result->data = NULL; + result->data_size = 0; + result->cursor = NULL; return NSS_STATUS_SUCCESS; } @@ -91,13 +112,10 @@ enum nss_status _nss_db_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen, int *errnop) { - int status; - - __libc_lock_lock (lock); - - status = _nss_netgroup_parseline (&cursor, result, buffer, buflen, errnop); + enum nss_status status; - __libc_lock_unlock (lock); + status = _nss_netgroup_parseline (&result->cursor, result, buffer, buflen, + errnop); return status; } diff --git a/nss/nss_db/db-open.c b/nss/nss_db/db-open.c index 94dfe5b7da..36ce494d02 100644 --- a/nss/nss_db/db-open.c +++ b/nss/nss_db/db-open.c @@ -1,5 +1,5 @@ /* Common database routines for nss_db. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -22,368 +22,51 @@ #include <dlfcn.h> #include <stdlib.h> #include <string.h> -#include <bits/libc-lock.h> +#include <sys/mman.h> +#include <not-cancel.h> -#include "dummy-db.h" +#include <kernel-features.h> #include "nss_db.h" -/* This file contains the functions used to open and close the databases - read by the rest of libnss_db. Not all of them are thread safe; - make sure the caller does the appropriate locking. - - We dynamically load the database library, so that it does not have - to be present when glibc is compiled. Once loaded, the database - library is never never unloaded again until the libnss_db module is - unloaded (from the free_mem routine in nsswitch.c) -- we catch the - unload by providing a shlib destructor. (XXX Does that actually - work?) */ - -/* Handle for the shared Berkeley DB library. If non-null, the - database library is completely loaded and ready to be used by - multithreaded code. */ -static void *libdb_handle; - -/* The version of the Berkeley DB library we are using. */ -enum { - nodb, - db24, - db27, - db30 -} libdb_version; - -/* Pointer to the db_open function. For use with DB 2.x. */ -static int (*libdb_db_open) (const char *, int, - uint32_t, int, void *, void *, void **); - -/* Pointer to the db_create function. For use with DB 3.x. */ -static int (*libdb_db_create) (void *, void *, uint32_t); - -/* Constants which vary from version to version are actually variables - here. */ -int db_first; -int db_next; -int db_nooverwrite; -int db_truncate; -int db_rdonly; -/* Variables which keep track of the error values. */ -int db_keyexist; -int db_notfound; - -/* Locks the static variables in this file. */ -__libc_lock_define_initialized (static, lock) - -/* Dynamically load the database library. Return zero if successful, - non-zero if no suitable version of the library could be loaded. - Must be called with the above lock held if it might run in a - multithreaded context. - - We try currently: - - libdb.so.3: the name used by glibc 2.1 - - libdb-3.0.so: the name used by db-3.0.x - and maybe others in the future. */ - +/* Open the database stored in FILE. If succesful, store either a + pointer to the mapped file or a file handle for the file in H and + return NSS_STATUS_SUCCESS. On failure, return the appropriate + lookup status. */ enum nss_status -load_db (void) -{ - static const char *libnames[] = { "libdb.so.3", "libdb-3.0.so" }; - int x; - - for (x = 0; x < sizeof (libnames) / sizeof (libnames[0]); ++x) - { - libdb_handle = dlopen (libnames[x], RTLD_LAZY); - if (libdb_handle == NULL) - continue; - - /* DB 3.0 has db_create instead of db_open. */ - libdb_db_create = dlsym (libdb_handle, "db_create"); - - if (libdb_db_create == NULL) - /* DB 2.x uses db_open. */ - libdb_db_open = dlsym (libdb_handle, "db_open"); - - if (libdb_db_open != NULL || libdb_db_create != NULL) - { - /* Alright, we got a library. Now find out which version it is. */ - const char *(*db_version) (int *, int *, int *); - - db_version = dlsym (libdb_handle, "db_version"); - if (db_version != NULL) - { - /* Call the function and get the information. */ - int major, minor, subminor; - - DL_CALL_FCT (db_version, (&major, &minor, &subminor)); - switch (major) - { - case 2: - /* Sanity check: Do we have db_open? */ - if (libdb_db_open != NULL) - { - if (minor < 6 || (minor == 6 && subminor < 4)) - { - libdb_version = db24; - db_first = DB24_FIRST; - db_next = DB24_NEXT; - db_nooverwrite = DB24_NOOVERWRITE; - db_truncate = DB24_TRUNCATE; - } - else - { - libdb_version = db27; - db_first = DB27_FIRST; - db_next = DB27_NEXT; - db_nooverwrite = DB27_NOOVERWRITE; - db_truncate = DB27_TRUNCATE; - } - db_keyexist = DB2x_KEYEXIST; - db_notfound = DB2x_NOTFOUND; - db_rdonly = DB2x_RDONLY; - } - break; - - case 3: - /* Sanity check: Do we have db_create? */ - if (libdb_db_create != NULL) - { - libdb_version = db30; - db_first = DB30_FIRST; - db_next = DB30_NEXT; - db_keyexist = DB30_KEYEXIST; - db_notfound = DB30_NOTFOUND; - db_rdonly = DB30_RDONLY; - } - break; - - default: - break; - } - } - - if (libdb_version != nodb) - return NSS_STATUS_SUCCESS; - - /* Clear variables. */ - libdb_db_open = NULL; - libdb_db_create = NULL; - } - - dlclose (libdb_handle); - } - - (void) dlerror (); - return NSS_STATUS_UNAVAIL; -} - -/* Set the `FD_CLOEXEC' flag of FD. Return 0 on success, or -1 on - error with `errno' set. */ -static int -set_cloexec_flag (int fd) +internal_setent (const char *file, struct nss_db_map *mapping) { - int oldflags = fcntl (fd, F_GETFD, 0); - - if (oldflags < 0) - return oldflags; - - oldflags |= FD_CLOEXEC; - - return fcntl (fd, F_SETFD, oldflags); -} - -/* Make sure we don't use the library anymore once we are shutting down. */ -static void __attribute__ ((destructor)) -unload_db (void) -{ - if (libdb_handle != NULL) + enum nss_status status = NSS_STATUS_UNAVAIL; + + int mode = O_RDONLY | O_LARGEFILE; +#ifdef O_CLOEXEC + mode |= O_CLOEXEC; +#endif + int fd = open_not_cancel_2 (file, mode); + if (fd != -1) { - libdb_db_open = NULL; - libdb_db_create = NULL; - libdb_version = nodb; - dlclose (libdb_handle); - } -} - -/* Open the database stored in FILE. If succesful, store the database - handle in *DBP and return NSS_STATUS_SUCCESS. On failure, return - the appropriate lookup status. */ -enum nss_status -internal_setent (const char *file, NSS_DB **dbp) -{ - enum nss_status status = NSS_STATUS_SUCCESS; + struct nss_db_header header; - if (*dbp == NULL) - { - if (libdb_db_open == NULL && libdb_db_create == NULL) + if (read (fd, &header, sizeof (header)) == sizeof (header)) { - __libc_lock_lock (lock); - - if (libdb_db_open == NULL && libdb_db_create == NULL) - status = load_db (); - - __libc_lock_unlock (lock); + mapping->header = mmap (NULL, header.allocate, PROT_READ, + MAP_PRIVATE, fd, 0); + mapping->len = header.allocate; + if (mapping->header != MAP_FAILED) + status = NSS_STATUS_SUCCESS; + else if (errno == ENOMEM) + status = NSS_STATUS_TRYAGAIN; } - if (status == NSS_STATUS_SUCCESS) - status = dbopen (file, db_rdonly, 0, dbp); + close_not_cancel_no_status (fd); } return status; } -/* Close the database *DBP. */ +/* Close the database. */ void -internal_endent (NSS_DB **dbp) -{ - NSS_DB *db = *dbp; - - if (db != NULL) - { - DL_CALL_FCT (db->close, (db->db, 0)); - *dbp = NULL; - } -} - -/* Allocate a cursor for database DB and transaction TXN. On success, - store the cursor in *DBCP and return zero. Otherwise return an - error value. */ -int -db_cursor (void *db, void *txn, NSS_DBC **dbcp) -{ - NSS_DBC *dbc; - int ret; - - dbc = (NSS_DBC *) malloc (sizeof (NSS_DBC)); - if (dbc == NULL) - return ENOMEM; - - switch (libdb_version) - { - case db24: - ret = ((struct db24 *) db)->cursor (db, txn, &dbc->cursor); - - if (ret == 0) - dbc->c_get = ((struct dbc24 *) dbc->cursor)->c_get; - break; - - case db27: - ret = ((struct db27 *) db)->cursor (db, txn, &dbc->cursor, 0); - - if (ret == 0) - dbc->c_get = ((struct dbc27 *) dbc->cursor)->c_get; - break; - - case db30: - ret = ((struct db30 *) db)->cursor (db, txn, &dbc->cursor, 0); - - if (ret == 0) - dbc->c_get = ((struct dbc30 *) dbc->cursor)->c_get; - break; - - default: - abort (); - } - - if (ret != 0) - { - free (dbc); - return ret; - } - - *dbcp = dbc; - - return 0; -} - - -/* Open the database in FNAME, for access specified by FLAGS. If - opening the database causes the file FNAME to be created, it is - created with MODE. If succesful, store the database handle in *DBP - and return NSS_STATUS_SUCCESS. On failure, return the appropriate - lookup status. */ -int -dbopen (const char *fname, int oper, int mode, NSS_DB **dbp) +internal_endent (struct nss_db_map *mapping) { - int err; - int fd; - NSS_DB *db; - - /* Construct the object we pass up. */ - db = (NSS_DB *) calloc (1, sizeof (NSS_DB)); - if (db == NULL) - return NSS_STATUS_UNAVAIL; - - /* Initialize the object. */ - db->cursor = db_cursor; - - /* Actually open the database. */ - switch (libdb_version) - { - case db24: - case db27: - err = DL_CALL_FCT (libdb_db_open, - (fname, DB_BTREE, oper, mode, NULL, NULL, &db->db)); - if (err != 0) - goto fail; - - if (libdb_version) - { - db->close = ((struct db24 *) db->db)->close; - db->fd = ((struct db24 *) db->db)->fd; - db->get = ((struct db24 *) db->db)->get; - db->put = ((struct db24 *) db->db)->put; - } - else - { - db->close = ((struct db27 *) db->db)->close; - db->fd = ((struct db27 *) db->db)->fd; - db->get = ((struct db27 *) db->db)->get; - db->put = ((struct db27 *) db->db)->put; - } - break; - - case db30: - err = DL_CALL_FCT (libdb_db_create, (db->db, NULL, 0)); - if (err != 0) - goto fail; - - db->close = ((struct db30 *) db->db)->close; - db->fd = ((struct db30 *) db->db)->fd; - db->get = ((struct db30 *) db->db)->get; - db->put = ((struct db30 *) db->db)->put; - - err = ((struct db30 *) db->db)->open (db->db, fname, NULL, DB_BTREE, - oper, mode); - if (err != 0) - goto fail; - break; - - default: - abort (); - } - - /* We have to make sure the file is `closed on exec'. */ - err = DL_CALL_FCT (db->fd, (db->db, &fd)); - if (err != 0) - goto fail; - if (set_cloexec_flag (fd) < 0) - goto fail; - - *dbp = db; - - return NSS_STATUS_UNAVAIL; - - fail: - /* Something went wrong. Close the database if necessary. */ - if (db) - { - if (db->db && db->close) - DL_CALL_FCT (db->close, (db->db, 0)); - free (db); - } - - /* Make sure `errno' is set. */ - if (err) - __set_errno (err); - - return err == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + munmap (mapping->header, mapping->len); } diff --git a/nss/nss_db/dummy-db.h b/nss/nss_db/dummy-db.h deleted file mode 100644 index c96bbd93b7..0000000000 --- a/nss/nss_db/dummy-db.h +++ /dev/null @@ -1,333 +0,0 @@ -/* Constants and structures from the various Berkeley DB releases. - Copyright (C) 1999, 2000 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <stdint.h> - -#include "nss_db.h" - -/* This file contains dummy definitions for various constants and - structures from the Berkeley release. We only provide those - definitions that are actually needed. In case of the structures, - we're only interested in the function pointers, since that's the - interface to the database. Unfortunately the structures have been - changed several times. */ - -/* The value for the btree database type has not been changed (yet?). */ -#define DB_BTREE (1) - -/* Permission flags for all 2.x releases. */ -#define DB2x_RDONLY 0x010000 - -/* The error values for all 2.x releases. */ -#define DB2x_KEYEXIST ( -3) -#define DB2x_NOTFOUND ( -7) - -/* For all 2.x releases up to 2.6.3 we can use the same definitions. - We'll refer to them as 2.4 since that's the version distributed - with glibc 2.1. */ - -/* Access methods from version 2.4. */ -#define DB24_FIRST 0x000020 -#define DB24_NEXT 0x000800 -#define DB24_NOOVERWRITE 0x001000 - -/* Permission flags from version 2.4. */ -#define DB24_TRUNCATE 0x080000 - -/* The DB structure from version 2.4. */ -struct db24 -{ - void *mutexp; - enum { dummy24 } type; - void *dbenv; - void *mp_dbenv; - void *master; - void *internal; - void *mp; - void *mpf; - struct - { - void *tqh_first; - void **tqh_last; - } curs_queue; - struct { - void *lh_first; - } handleq; - struct { - void *le_next; - void **le_prev; - } links; - uint32_t log_fileid; - void *txn; - uint32_t locker; - struct db24_dbt { - void *data; - uint32_t size; - uint32_t ulen; - uint32_t dlen; - uint32_t doff; - uint32_t flags; - } lock_dbt; - struct{ - uint32_t pgno; - uint8_t fileid[20]; - } lock; - size_t pgsize; - void *db_malloc; - /* Functions. */ - int (*close) (void *, uint32_t); - int (*cursor) (void *, void *, void **); - int (*del) (void *, void *, DBT *, uint32_t); - int (*fd) (void *, int *); - int (*get) (void *, void *, DBT *, DBT *, uint32_t); - int (*put) (void *, void *, DBT *, DBT *, uint32_t); - int (*stat) (void *, void *, void *(*)(size_t), uint32_t); - int (*sync) (void *, uint32_t); - uint32_t flags; -}; - -/* The DBC structure for the 2.4 release. */ -struct dbc24 -{ - void *dbp; - void *txn; - struct - { - void *tqe_next; - void **tqe_prev; - } links; - void *internal; - void *c_close; - void *c_del; - int (*c_get) (void *, DBT *, DBT *, uint32_t); - void *c_put; -}; - -/* The 2.7 release is slighty different. */ - -/* Access methods from version 2.7. */ -#define DB27_FIRST 7 -#define DB27_NEXT 15 -#define DB27_NOOVERWRITE 17 - -/* Permission flags from version 2.7. */ -#define DB27_TRUNCATE 0x020000 - -/* The DB structure from version 2.7. */ -struct db27 -{ - void *mutexp; - enum { dummy27 } type; - int byteswapped; - int saved_open_fd; - void *dbenv; - void *mp_dbenv; - void *internal; - void *mp; - void *mpf; - struct - { - void *tqh_first; - void **tqh_last; - } free_queue; - struct - { - void *tqh_first; - void **tqh_last; - } active_queue; - uint8_t fileid[20]; - uint32_t log_fileid; - size_t pgsize; - void *db_malloc; - void *dup_compare; - void *h_hash; - /* Functions. */ - int (*am_close) (void *); - int (*close) (void *, uint32_t); - int (*cursor) (void *, void *, void **, uint32_t); - int (*del) (void *, void *, DBT *, uint32_t); - int (*fd) (void *, int *); - int (*get) (void *, void *, DBT *, DBT *, uint32_t); - int (*join) (void *, void **, uint32_t, void **); - int (*put) (void *, void *, DBT *, DBT *, uint32_t); - int (*stat) (void *, void *, void *(*)(size_t), uint32_t); - int (*sync) (void *, uint32_t); - uint32_t flags; -}; - -/* The DBC structure for version 2.7. */ -struct dbc27 -{ - void *dbp; - void *txn; - struct - { - void *tqe_next; - void **tqe_prev; - } links; - uint32_t lid; - uint32_t locker; - DBT lock_dbt; - struct{ - uint32_t pgno; - uint8_t fileid[20]; - } lock; - size_t mylock; - DBT rkey; - DBT rdata; - void *c_am_close; - void *c_am_destroy; - void *c_close; - void *c_del; - int (*c_get) (void *, DBT *, DBT *, uint32_t); - void *c_put; - void *internal; - uint32_t flags; -}; - -/* Version 3.0 is mostly incompatible with 2.x. */ - -/* Access methods from version 3.0. */ -#define DB30_FIRST 9 -#define DB30_NEXT 17 -#define DB30_NOOVERWRITE 20 - -/* Error values from version 3.0. */ -#define DB30_KEYEXIST (-30997) -#define DB30_NOTFOUND (-30994) - -/* Permission flags from version 3.0. */ -#define DB30_RDONLY 0x000010 -#define DB30_TRUNCATE 0x020000 - -/* The DB structure from version 3.0. */ -struct db30 -{ - size_t pgsize; - void (*db_feedback) (void *, int, int); - void *(*db_malloc) (size_t); - void *(*db_realloc) (void *, size_t); - int (*dup_compare) (const DBT *, const DBT *); - void *dbenv; - enum { dummy30 } type; - void *mpf; - void *mutexp; - u_int8_t fileid[20]; - int32_t log_fileid; - void *open_txn; - void *saved_open_fhp; - struct - { - void *tqh_first; - void **tqh_last; - } free_queue; - struct - { - void *tqh_first; - void **tqh_last; - } active_queue; - void *bt_internal; - void *cj_internal; - void *h_internal; - void *q_internal; - void *xa_internal; - /* Functions. */ - int (*close) (void *, uint32_t); - int (*cursor) (void *, void *, void **, uint32_t); - int (*del) (void *, void *, DBT *, uint32_t); - void (*err) (void *, int, const char *, ...); - void (*errx) (void *, const char *, ...); - int (*fd) (void *, int *); - int (*get) (void *, void *, DBT *, DBT *, uint32_t); - int (*get_byteswapped) (void *); - int (*get_type) (void *); - int (*join) (void *, void **, void **, uint32_t); - int (*open) (void *, const char *, const char *, int, uint32_t, int); - int (*put) (void *, void *, DBT *, DBT *, uint32_t); - int (*remove) (void *, const char *, const char *, uint32_t); - int (*set_cachesize) (void *, uint32_t, uint32_t, int); - int (*set_dup_compare) (void *, int (*)(const DBT *, const DBT *)); - void (*set_errcall) (void *, void (*)(const char *, char *)); - void (*set_errfile) (void *, void *); - void (*set_errpfx) (void *, const char *); - void (*set_feedback) (void *, void (*)(void *, int, int)); - int (*set_flags) (void *, uint32_t); - int (*set_lorder) (void *, int); - int (*set_malloc) (void *, void *(*)(size_t)); - int (*set_pagesize) (void *, uint32_t); - void (*set_paniccall) (void *, void (*)(void *, int)); - int (*set_realloc) (void *, void *(*)(void *, size_t)); - int (*stat) (void *, void *, void *(*)(size_t), uint32_t); - int (*sync) (void *, uint32_t); - int (*upgrade) (void *, const char *, uint32_t); - - int (*set_bt_compare) (void *, int (*)(const DBT *, const DBT *)); - int (*set_bt_maxkey) (void *, uint32_t); - int (*set_bt_minkey) (void *, uint32_t); - int (*set_bt_prefix) (void *, size_t (*)(const DBT *, const DBT *)); - - int (*set_h_ffactor) (void *, uint32_t); - int (*set_h_hash) (void *, uint32_t (*)(const void *, uint32_t)); - int (*set_h_nelem) (void *, uint32_t); - - int (*set_re_delim) (void *, int); - int (*set_re_len) (void *, uint32_t); - int (*set_re_pad) (void *, int); - int (*set_re_source) (void *, const char *); - - uint32_t am_ok; - uint32_t flags; -}; - -/* The DBC structure from version 3.0. */ -struct dbc30 -{ - void *dbp; - void *txn; - struct - { - void *tqe_next; - void **tqe_prev; - } links; - uint32_t lid; /* Default process' locker id. */ - uint32_t locker; /* Locker for this operation. */ - DBT lock_dbt; /* DBT referencing lock. */ - struct - { - uint32_t pgno; - uint8_t fileid[20]; - } lock; - struct - { - size_t off; - uint32_t ndx; - uint32_t gen; - } mylock; - DBT rkey; - DBT rdata; - int (*c_close) (void *); - int (*c_del) (void *, uint32_t); - int (*c_dup) (void *, void **, uint32_t); - int (*c_get) (void *, DBT *, DBT *, uint32_t); - int (*c_put) (void *, DBT *, DBT *, uint32_t); - int (*c_am_close) (void *); - int (*c_am_destroy) (void *); - void *internal; - uint32_t flags; -}; diff --git a/nss/nss_db/nss_db.h b/nss/nss_db/nss_db.h index 0edc9b6bea..a965ae33fe 100644 --- a/nss/nss_db/nss_db.h +++ b/nss/nss_db/nss_db.h @@ -1,5 +1,5 @@ /* Common database open/close routines for nss_db. - Copyright (C) 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -22,73 +22,49 @@ #include <nss.h> #include <stdint.h> +#include <bits/libc-lock.h> -/* Variables which keep track of the error values. */ -extern int db_keyexist; -extern int db_notfound; -/* This flag is the same for all versions of the Berkeley DB library. */ -#define DB_CREATE 0x000001 +/* String table index type. */ +typedef uint32_t stridx_t; -/* But constants which vary from version to version are actually - variables here. */ -extern int db_first; -extern int db_next; -extern int db_nooverwrite; -extern int db_truncate; -extern int db_rdonly; - -/* The `DBT' type is the same in all versions we support. */ -typedef struct +/* Database file header. */ +struct nss_db_header { - void *data; - uint32_t size; - uint32_t ulen; - uint32_t dlen; - uint32_t doff; - uint32_t flags; -} DBT; - -/* But the cursor object is very different from version to version. */ -typedef struct + uint32_t magic; +#define NSS_DB_MAGIC 0xdd110601 + uint32_t ndbs; + uint64_t valstroffset; + uint64_t valstrlen; + uint64_t allocate; + struct + { + char id; + char pad[sizeof (uint32_t) - 1]; + uint32_t hashsize; + uint64_t hashoffset; + uint64_t keyidxoffset; + uint64_t keystroffset; + } dbs[0]; +}; + + +/* Information about mapped database. */ +struct nss_db_map { - void *cursor; - int (*c_get) (void *, DBT *, DBT *, uint32_t); -} NSS_DBC; + struct nss_db_header *header; + size_t len; +}; -/* We need a helper function for it. */ -extern int db_cursor (void *db, void *txn, NSS_DBC **dbcp); - -/* This is the wrapper we put around the `DB' structures to provide a - uniform interface to the higher-level functions. */ -typedef struct -{ - void *db; - int (*close) (void *, uint32_t); - int (*cursor) (void *, void *, NSS_DBC **); - int (*fd) (void *, int *); - int (*get) (void *, void *, DBT *, DBT *, uint32_t); - int (*put) (void *, void *, DBT *, DBT *, uint32_t); -} NSS_DB; /* Open the database stored in FILE. If succesful, store the database - handle in *DBP and return NSS_STATUS_SUCCESS. On failure, return - the appropriate lookup status. */ -extern enum nss_status internal_setent (const char *file, NSS_DB **dbp); - -/* Close the database *DBP. */ -extern void internal_endent (NSS_DB **dbp); - -/* Dynamically load the Berkeley DB library. Return zero if - successful, non-zero if no suitable version of the library could be - loaded. */ -extern enum nss_status load_db (void); - -/* Open the database in FNAME, for access specified by FLAGS. If - opening the database causes the file FNAME to be created, it is - created with MODE. If succesful, store the database handle in *DBP - and return NSS_STATUS_SUCCESS. On failure, return the appropriate + handle in *MAPPINGP or a file descriptor for the file in *FDP and + return NSS_STATUS_SUCCESS. On failure, return the appropriate lookup status. */ -extern int dbopen (const char *fname, int oper, int mode, NSS_DB **dbp); +enum nss_status internal_setent (const char *file, + struct nss_db_map *mappingp); + +/* Close the database FD. */ +extern void internal_endent (struct nss_db_map *mapping); #endif /* nss_db.h */ diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c index 852b58a7e5..1a6fa0ddd5 100644 --- a/nss/nss_files/files-XXX.c +++ b/nss/nss_files/files-XXX.c @@ -1,5 +1,5 @@ /* Common code for file-based databases in nss_files module. - Copyright (C) 1996-1999,2001,2002,2004,2007,2008 + Copyright (C) 1996-1999,2001,2002,2004,2007,2008,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -306,15 +306,15 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer, NAME is the name of the lookup; e.g. `hostbyname'. - KEYSIZE and KEYPATTERN are ignored here but used by ../nss_db/db-XXX.c. + DB_CHAR, KEYPATTERN, KEYSIZE are ignored here but used by db-XXX.c + e.g. `1 + sizeof (id) * 4'. - PROTO describes the arguments for the lookup key; - e.g. `const char *hostname'. + PROTO is the potentially empty list of other parameters. BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result' to the lookup key arguments and does `break;' if they match. */ -#define DB_LOOKUP(name, keysize, keypattern, break_if_match, proto...) \ +#define DB_LOOKUP(name, db_char, keysize, keypattern, break_if_match, proto...)\ enum nss_status \ _nss_files_get##name##_r (proto, \ struct STRUCTURE *result, char *buffer, \ diff --git a/nss/nss_files/files-ethers.c b/nss/nss_files/files-ethers.c index e662c1a4e1..91363ba173 100644 --- a/nss/nss_files/files-ethers.c +++ b/nss/nss_files/files-ethers.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 2000, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -51,13 +51,13 @@ LINE_PARSER #include GENERIC -DB_LOOKUP (hostton, 1 + strlen (name), (".%s", name), +DB_LOOKUP (hostton, '.', 0, ("%s", name), { if (__strcasecmp (result->e_name, name) == 0) break; }, const char *name) -DB_LOOKUP (ntohost, 18, ("=%x:%x:%x:%x:%x:%x", +DB_LOOKUP (ntohost, '=', 18, ("%x:%x:%x:%x:%x:%x", addr->ether_addr_octet[0], addr->ether_addr_octet[1], addr->ether_addr_octet[2], addr->ether_addr_octet[3], addr->ether_addr_octet[4], addr->ether_addr_octet[5]), diff --git a/nss/nss_files/files-grp.c b/nss/nss_files/files-grp.c index 1f205c1093..30751ab048 100644 --- a/nss/nss_files/files-grp.c +++ b/nss/nss_files/files-grp.c @@ -1,5 +1,5 @@ /* Group file parser in nss_files module. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -30,14 +30,14 @@ struct grent_data {}; #include "files-parse.c" #include GENERIC -DB_LOOKUP (grnam, 1 + strlen (name), (".%s", name), +DB_LOOKUP (grnam, '.', 0, ("%s", name), { if (name[0] != '-' && name[0] != '+' && ! strcmp (name, result->gr_name)) break; }, const char *name) -DB_LOOKUP (grgid, 20, ("=%lu", (unsigned long int) gid), +DB_LOOKUP (grgid, '=', 20, ("%lu", (unsigned long int) gid), { if (result->gr_gid == gid && result->gr_name[0] != '+' && result->gr_name[0] != '-') diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c index 83de650756..f6f960ecbe 100644 --- a/nss/nss_files/files-hosts.c +++ b/nss/nss_files/files-hosts.c @@ -358,7 +358,7 @@ HOST_DB_LOOKUP (hostbyname2, ,, gethostbyaddr() function is an IPv6 address. */ #define EXTRA_ARGS_VALUE \ , af, (len == IN6ADDRSZ ? AI_V4MAPPED : 0) -DB_LOOKUP (hostbyaddr, ,, +DB_LOOKUP (hostbyaddr, ,,, { if (result->h_length == (int) len && ! memcmp (addr, result->h_addr_list[0], len)) diff --git a/nss/nss_files/files-network.c b/nss/nss_files/files-network.c index 92aea75d9e..9017c54997 100644 --- a/nss/nss_files/files-network.c +++ b/nss/nss_files/files-network.c @@ -1,5 +1,5 @@ /* Networks file parser in nss_files module. - Copyright (C) 1996-1998, 2000, 2001, 2009 Free Software Foundation, Inc. + Copyright (C) 1996-1998, 2000, 2001, 2009, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -75,11 +75,11 @@ LINE_PARSER #include "files-XXX.c" -DB_LOOKUP (netbyname, ,, +DB_LOOKUP (netbyname, ,,, LOOKUP_NAME_CASE (n_name, n_aliases), const char *name) -DB_LOOKUP (netbyaddr, ,, +DB_LOOKUP (netbyaddr, ,,, { if ((type == AF_UNSPEC || result->n_addrtype == type) && result->n_net == net) diff --git a/nss/nss_files/files-proto.c b/nss/nss_files/files-proto.c index 0cede6ebd4..5df325b496 100644 --- a/nss/nss_files/files-proto.c +++ b/nss/nss_files/files-proto.c @@ -1,5 +1,5 @@ /* Protocols file parser in nss_files module. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -36,11 +36,11 @@ LINE_PARSER #include GENERIC -DB_LOOKUP (protobyname, 1 + strlen (name), (".%s", name), +DB_LOOKUP (protobyname, '.', 0, ("%s", name), LOOKUP_NAME (p_name, p_aliases), const char *name) -DB_LOOKUP (protobynumber, 20, ("=%d", proto), +DB_LOOKUP (protobynumber, '=', 20, ("%zd", (ssize_t) proto), { if (result->p_proto == proto) break; diff --git a/nss/nss_files/files-pwd.c b/nss/nss_files/files-pwd.c index 4913c3183d..4763f0149a 100644 --- a/nss/nss_files/files-pwd.c +++ b/nss/nss_files/files-pwd.c @@ -1,5 +1,5 @@ /* User file parser in nss_files module. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -30,14 +30,14 @@ struct pwent_data {}; #include "files-parse.c" #include GENERIC -DB_LOOKUP (pwnam, 1 + strlen (name), (".%s", name), +DB_LOOKUP (pwnam, '.', 0, ("%s", name), { if (name[0] != '+' && name[0] != '-' && ! strcmp (name, result->pw_name)) break; }, const char *name) -DB_LOOKUP (pwuid, 20, ("=%lu", (unsigned long int) uid), +DB_LOOKUP (pwuid, '=', 20, ("%lu", (unsigned long int) uid), { if (result->pw_uid == uid && result->pw_name[0] != '+' && result->pw_name[0] != '-') diff --git a/nss/nss_files/files-rpc.c b/nss/nss_files/files-rpc.c index b99ede399b..2b41611d4c 100644 --- a/nss/nss_files/files-rpc.c +++ b/nss/nss_files/files-rpc.c @@ -1,5 +1,5 @@ /* SunRPC program number file parser in nss_files module. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -36,11 +36,11 @@ LINE_PARSER #include GENERIC -DB_LOOKUP (rpcbyname, 1 + strlen (name), (".%s", name), +DB_LOOKUP (rpcbyname, '.', 0, ("%s", name), LOOKUP_NAME (r_name, r_aliases), const char *name) -DB_LOOKUP (rpcbynumber, 20, ("=%d", number), +DB_LOOKUP (rpcbynumber, '=', 20, ("%zd", (ssize_t) number), { if (result->r_number == number) break; diff --git a/nss/nss_files/files-service.c b/nss/nss_files/files-service.c index 13532ddc9b..6f2b0e64a6 100644 --- a/nss/nss_files/files-service.c +++ b/nss/nss_files/files-service.c @@ -1,5 +1,5 @@ /* Services file parser in nss_files module. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -39,8 +39,9 @@ LINE_PARSER #include GENERIC -DB_LOOKUP (servbyname, 2 + strlen (name) + (proto ? strlen (proto) : 0), - (".%s/%s", name, proto ?: ""), +DB_LOOKUP (servbyname, ':', + strlen (name) + 2 + (proto == NULL ? 0 : strlen (proto)), + ("%s/%s", name, proto ?: ""), { /* Must match both protocol (if specified) and name. */ if (proto != NULL && strcmp (result->s_proto, proto)) @@ -49,8 +50,8 @@ DB_LOOKUP (servbyname, 2 + strlen (name) + (proto ? strlen (proto) : 0), }, const char *name, const char *proto) -DB_LOOKUP (servbyport, 21 + (proto ? strlen (proto) : 0), - ("=%d/%s", ntohs (port), proto ?: ""), +DB_LOOKUP (servbyport, '=', 21 + (proto ? strlen (proto) : 0), + ("%zd/%s", (ssize_t) ntohs (port), proto ?: ""), { /* Must match both port and protocol. */ if (result->s_port == port diff --git a/nss/nss_files/files-sgrp.c b/nss/nss_files/files-sgrp.c index 4e12cd83d4..684bacc3d0 100644 --- a/nss/nss_files/files-sgrp.c +++ b/nss/nss_files/files-sgrp.c @@ -1,5 +1,5 @@ /* User file parser in nss_files module. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -30,7 +30,7 @@ struct sgent_data {}; #include "files-parse.c" #include GENERIC -DB_LOOKUP (sgnam, 1 + strlen (name), (".%s", name), +DB_LOOKUP (sgnam, '.', 0, ("%s", name), { if (name[0] != '+' && name[0] != '-' && ! strcmp (name, result->sg_namp)) diff --git a/nss/nss_files/files-spwd.c b/nss/nss_files/files-spwd.c index 1825d36102..e227d71275 100644 --- a/nss/nss_files/files-spwd.c +++ b/nss/nss_files/files-spwd.c @@ -1,5 +1,5 @@ /* User file parser in nss_files module. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -30,7 +30,7 @@ struct spent_data {}; #include "files-parse.c" #include GENERIC -DB_LOOKUP (spnam, 1 + strlen (name), (".%s", name), +DB_LOOKUP (spnam, '.', 0, ("%s", name), { if (name[0] != '+' && name[0] != '-' && ! strcmp (name, result->sp_namp)) |