mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-08 22:30:07 +00:00
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:
parent
9ee76b5ae8
commit
2666d441c2
32
ChangeLog
32
ChangeLog
@ -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.
|
||||
|
@ -67,6 +67,9 @@ libnss_compat {
|
||||
libnss_dns {
|
||||
GLIBC_PRIVATE
|
||||
}
|
||||
libnss_db {
|
||||
GLIBC_PRIVATE
|
||||
}
|
||||
libnss_files {
|
||||
GLIBC_PRIVATE
|
||||
}
|
||||
|
19
nss/Makefile
19
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)
|
||||
|
||||
|
58
nss/Versions
58
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;
|
||||
}
|
||||
}
|
||||
|
@ -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."
|
||||
|
247
nss/makedb.c
247
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);
|
||||
= (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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
@ -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 */
|
||||
|
@ -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, \
|
||||
|
@ -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]),
|
||||
|
@ -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] != '-')
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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] != '-')
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user