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.
This commit is contained in:
Ulrich Drepper 2011-06-14 22:21:51 -04:00
parent 9ee76b5ae8
commit 2666d441c2
24 changed files with 552 additions and 1388 deletions

View File

@ -1,3 +1,35 @@
2011-06-14 Ulrich Drepper <drepper@gmail.com>
* Versions.def: Add entry for libnss_db.
* shlib-versions: Likewise.
* nss/Makefile: Add rules to build libnss_db.
* nss/Versions: Add libnss_db information. Organize libnss_files
entries better.
* nss/db-Makefile: Add gshadow support. Change rules for the new
makedb progra. Some minor improvements to generate smaller files.
* nss/nss_db/nss_db.h: Move NSS database header data structures to
here from...
* nss/makedb.c: ...here.
Improve database format to be smaller and require less memory at
runtime.
* nss/nss_db/db-XXX.x: Adjust for new database format. Don't use
db anymore.
* nss/nss_db/db-netgrp.c: Likewise.
* nss/nss_db/db-open.c: Likewise.
* nss/nss_files/flies-XXX.x: Adjust comments.
* nss/nss_files/files-ethers.c: Adjust for new DB_LOOKUP definition.
* nss/nss_files/files-grp.c: Likewise.
* nss/nss_files/files-hosts.c: Likewise.
* nss/nss_files/files-network.c: Likewise.
* nss/nss_files/files-proto.c: Likewise.
* nss/nss_files/files-pwd.c: Likewise.
* nss/nss_files/files-rpc.c: Likewise.
* nss/nss_files/files-service.c: Likewise.
* nss/nss_files/files-sgrp.c: Likewise.
* nss/nss_files/files-spwd.c: Likewise.
* nss/nss_db/db-alias.c: Removed.
* nss/nss_db/dummy-db.h: Removed.
2011-06-02 Ulrich Drepper <drepper@gmail.com>
* nss/makedb.c: Rewritten to not use database library.

View File

@ -67,6 +67,9 @@ libnss_compat {
libnss_dns {
GLIBC_PRIVATE
}
libnss_db {
GLIBC_PRIVATE
}
libnss_files {
GLIBC_PRIVATE
}

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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)/netgroup.db: /etc/netgroup
$(VAR_DB)/gshadow.db: /etc/gshadow
@echo -n "$(patsubst %.db,%,$(@F))... "
@$(AWK) 'BEGIN { cnt=0 } \
@$(AWK) 'BEGIN { FS=":"; OFS=":" } \
/^[ \t]*$$/ { next } \
/^[ \t]*#/ { next } \
{ printf "0%u ", cnt++; print } \
/^[^#]/ { end=sub(/\\/, " "); \
/^[^#]/ { 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 { ini=1 } \
/^[ \t]*$$/ { next } \
/^[ \t]*#/ { next } \
/^[^#]/ { 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."

View File

@ -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);
= (const char *) header + header->dbs[dbidx].keystroffset;
const stridx_t *hashtab
= (const stridx_t *) ((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);
}
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;

View File

@ -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)
/* State for this database. */
static struct nss_db_map state;
/* Lock to protect the state and global variables. */
__libc_lock_define (static , lock);
/* Maintenance of the shared handle open on the database. */
static NSS_DB *db;
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;
}
}
while (status == NSS_STATUS_RETURN);
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;
}
}
out:
__libc_lock_unlock (lock);
return status;

View File

@ -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;
}

View File

@ -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"
/* The hashing function we use. */
#include "../intl/hash-string.h"
#define DBFILE _PATH_VARDB "netgroup.db"
/* 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 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;
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);
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;
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;
enum nss_status status;
__libc_lock_lock (lock);
status = _nss_netgroup_parseline (&cursor, result, buffer, buflen, errnop);
__libc_lock_unlock (lock);
status = _nss_netgroup_parseline (&result->cursor, result, buffer, buflen,
errnop);
return status;
}

View File

@ -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)
internal_setent (const char *file, struct nss_db_map *mapping)
{
static const char *libnames[] = { "libdb.so.3", "libdb-3.0.so" };
int x;
enum nss_status status = NSS_STATUS_UNAVAIL;
for (x = 0; x < sizeof (libnames) / sizeof (libnames[0]); ++x)
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_handle = dlopen (libnames[x], RTLD_LAZY);
if (libdb_handle == NULL)
continue;
struct nss_db_header header;
/* 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)
if (read (fd, &header, sizeof (header)) == sizeof (header))
{
/* 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;
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;
}
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)
{
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)
{
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;
if (*dbp == NULL)
{
if (libdb_db_open == NULL && libdb_db_create == NULL)
{
__libc_lock_lock (lock);
if (libdb_db_open == NULL && libdb_db_create == NULL)
status = load_db ();
__libc_lock_unlock (lock);
}
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)
internal_endent (struct nss_db_map *mapping)
{
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)
{
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);
}

View File

@ -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;
};

View File

@ -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;
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];
};
/* But the cursor object is very different from version to version. */
typedef struct
/* 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 */

View File

@ -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, \

View File

@ -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]),

View File

@ -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] != '-')

View File

@ -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))

View File

@ -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)

View File

@ -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;

View File

@ -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] != '-')

View File

@ -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;

View File

@ -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

View File

@ -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))

View File

@ -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))

View File

@ -113,6 +113,7 @@ alpha.*-.*-linux.* libresolv=2.1
.*-.*-.* libnss_nisplus=2
.*-.*-.* libnss_ldap=2
.*-.*-.* libnss_hesiod=2
.*-.*-.* libnss_db=2
# Tests for NSS. They must have the same NSS_SHLIB_REVISION number as
# the rest.