[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commits] r14209 - in /fsf/trunk/libc: ./ grp/ nss/ nss/nss_db/ nss/nss_files/ resolv/ sysdeps/unix/sysv/linux/wordsize-64/



Author: eglibc
Date: Thu Jun 16 00:03:12 2011
New Revision: 14209

Log:
Import glibc-mainline for 2011-06-16

Added:
    fsf/trunk/libc/nss/nss_db/db-initgroups.c
    fsf/trunk/libc/sysdeps/unix/sysv/linux/wordsize-64/dl-fxstatat64.c
Removed:
    fsf/trunk/libc/nss/nss_db/db-alias.c
    fsf/trunk/libc/nss/nss_db/dummy-db.h
Modified:
    fsf/trunk/libc/ChangeLog
    fsf/trunk/libc/Makeconfig
    fsf/trunk/libc/NEWS
    fsf/trunk/libc/Versions.def
    fsf/trunk/libc/grp/initgroups.c
    fsf/trunk/libc/nss/Makefile
    fsf/trunk/libc/nss/Versions
    fsf/trunk/libc/nss/databases.def
    fsf/trunk/libc/nss/db-Makefile
    fsf/trunk/libc/nss/getent.c
    fsf/trunk/libc/nss/makedb.c
    fsf/trunk/libc/nss/nss_db/db-XXX.c
    fsf/trunk/libc/nss/nss_db/db-netgrp.c
    fsf/trunk/libc/nss/nss_db/db-open.c
    fsf/trunk/libc/nss/nss_db/nss_db.h
    fsf/trunk/libc/nss/nss_files/files-XXX.c
    fsf/trunk/libc/nss/nss_files/files-ethers.c
    fsf/trunk/libc/nss/nss_files/files-grp.c
    fsf/trunk/libc/nss/nss_files/files-hosts.c
    fsf/trunk/libc/nss/nss_files/files-network.c
    fsf/trunk/libc/nss/nss_files/files-proto.c
    fsf/trunk/libc/nss/nss_files/files-pwd.c
    fsf/trunk/libc/nss/nss_files/files-rpc.c
    fsf/trunk/libc/nss/nss_files/files-service.c
    fsf/trunk/libc/nss/nss_files/files-sgrp.c
    fsf/trunk/libc/nss/nss_files/files-spwd.c
    fsf/trunk/libc/resolv/res_send.c
    fsf/trunk/libc/shlib-versions

Modified: fsf/trunk/libc/ChangeLog
==============================================================================
--- fsf/trunk/libc/ChangeLog (original)
+++ fsf/trunk/libc/ChangeLog Thu Jun 16 00:03:12 2011
@@ -1,3 +1,76 @@
+2011-06-15  Ulrich Drepper  <drepper@xxxxxxxxx>
+
+	* resolv/res_send.c (__libc_res_nsend): Fix typos in last patch.  We
+	need to dereference resplen2.
+
+2011-06-14  Andreas Schwab  <schwab@xxxxxxxxxx>
+
+	* sysdeps/unix/sysv/linux/wordsize-64/dl-fxstatat64.c: New file.
+
+2011-06-15  Ulrich Drepper  <drepper@xxxxxxxxx>
+
+	* Makeconfig: Define vardbdir and inst_vardbdir.
+	* nss/Makefile: Add rules to install db-Makefile.
+
+	* nss/nss_db/db-XXX.c: Cleanup.
+
+	* nss/Makefile (libnss_db-dbs): Add db-initgroups.
+	* nss/Versions [libnss_db]: Add _nss_db_initgroups_dyn for
+	GLIBC_PRIVATE.
+	* nss/db-Makefile (groups.db): Emit entries for initgroups lookups.
+	* nss/makedb.c: Implement -g option to specify that value strings
+	are generated and should not be added to table iterated over for
+	get*ent calls.
+	* nss/nss_db/db-initgroups.c: New file.
+
+	* nss/getent.c: Add support for initgroups lookups through getgrouplist
+	interface.
+
+	* grp/initgroups.c (__nss_initgroups_database): Renamed and exported.
+	(internal_getgrouplist): Adjust to name change.
+	Update use_initgroups_entry if this is not the first call.
+	* nss/databases.def: Add initgroups entry.
+
+	* nss/makedb.c (compute_tables): Check result of multiple hash table
+	sizes to minimize maximum chain length.
+
+2011-06-14  Ulrich Drepper  <drepper@xxxxxxxxx>
+
+	* 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@xxxxxxxxx>
+
+	* nss/makedb.c: Rewritten to not use database library.
+	* nss/Makefile: Update to build new makedb program.
+
 2011-06-14  Andreas Jaeger  <aj@xxxxxxx>
 
 	* sysdeps/unix/sysv/linux/check_native.c: Include <string.h> for

Modified: fsf/trunk/libc/Makeconfig
==============================================================================
--- fsf/trunk/libc/Makeconfig (original)
+++ fsf/trunk/libc/Makeconfig Thu Jun 16 00:03:12 2011
@@ -290,6 +290,12 @@
 sysconfdir = $(prefix)/etc
 endif
 inst_sysconfdir = $(install_root)$(sysconfdir)
+
+# Directory for the database files and Makefile for nss_db.
+ifndef vardbdir
+vardbdir = /var/db
+endif
+inst_vardbdir = $(install_root)$(vardbdir)
 
 # What timezone should be the installed default (e.g., US/Eastern).
 # Run `make -C time echo-zonenames' to see a list of available zone names.

Modified: fsf/trunk/libc/NEWS
==============================================================================
--- fsf/trunk/libc/NEWS (original)
+++ fsf/trunk/libc/NEWS Thu Jun 16 00:03:12 2011
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2011-6-9
+GNU C Library NEWS -- history of user-visible changes.  2011-6-15
 Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -8,6 +8,10 @@
 Version 2.15
 
 * New program pldd to list loaded object of a process
+  Implemented by Ulrich Drepper.
+
+* Add nss_db support back to glibc.  No more dependency on Berkeley db
+  and support for initgroups lookups.
   Implemented by Ulrich Drepper.
 
 Version 2.14

Modified: fsf/trunk/libc/Versions.def
==============================================================================
--- fsf/trunk/libc/Versions.def (original)
+++ fsf/trunk/libc/Versions.def Thu Jun 16 00:03:12 2011
@@ -65,6 +65,9 @@
   GLIBC_PRIVATE
 }
 libnss_dns {
+  GLIBC_PRIVATE
+}
+libnss_db {
   GLIBC_PRIVATE
 }
 libnss_files {

Modified: fsf/trunk/libc/grp/initgroups.c
==============================================================================
--- fsf/trunk/libc/grp/initgroups.c (original)
+++ fsf/trunk/libc/grp/initgroups.c Thu Jun 16 00:03:12 2011
@@ -44,7 +44,7 @@
 extern void *__nss_lookup_function (service_user *ni, const char *fct_name);
 
 extern service_user *__nss_group_database attribute_hidden;
-static service_user *initgroups_database;
+service_user *__nss_initgroups_database;
 static bool use_initgroups_entry;
 
 
@@ -80,26 +80,31 @@
   /* Start is one, because we have the first group as parameter.  */
   long int start = 1;
 
-  if (initgroups_database == NULL)
+  if (__nss_initgroups_database == NULL)
     {
       no_more = __nss_database_lookup ("initgroups", NULL, "",
-				       &initgroups_database);
-      if (no_more == 0 && initgroups_database == NULL)
+				       &__nss_initgroups_database);
+      if (no_more == 0 && __nss_initgroups_database == NULL)
 	{
 	  if (__nss_group_database == NULL)
 	    no_more = __nss_database_lookup ("group", NULL, "compat files",
 					     &__nss_group_database);
 
-	  initgroups_database = __nss_group_database;
+	  __nss_initgroups_database = __nss_group_database;
 	}
-      else if (initgroups_database != NULL)
+      else if (__nss_initgroups_database != NULL)
 	{
 	  assert (no_more == 0);
 	  use_initgroups_entry = true;
 	}
     }
-
-  service_user *nip = initgroups_database;
+  else
+    /* __nss_initgroups_database might have been set through
+       __nss_configure_lookup in which case use_initgroups_entry was
+       not set here.  */
+    use_initgroups_entry = __nss_initgroups_database != __nss_group_database;
+
+  service_user *nip = __nss_initgroups_database;
   while (! no_more)
     {
       long int prev_start = start;

Modified: fsf/trunk/libc/nss/Makefile
==============================================================================
--- fsf/trunk/libc/nss/Makefile (original)
+++ fsf/trunk/libc/nss/Makefile Thu Jun 16 00:03:12 2011
@@ -37,8 +37,10 @@
 databases		= proto service hosts network grp pwd rpc ethers \
 			  spwd netgrp key alias sgrp
 
-others                  := getent
-install-bin             := getent
+others                  := getent makedb
+install-bin             := getent makedb
+makedb-modules = xmalloc hash-string
+extra-objs		+= $(makedb-modules:=.o)
 
 tests			= test-netdb tst-nss-test1
 xtests			= bug-erange
@@ -51,7 +53,7 @@
 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
@@ -60,17 +62,28 @@
 
 # The sources are found in the appropriate subdir.
 subdir-dirs = $(services:%=nss_%)
-vpath %.c $(subdir-dirs)
+vpath %.c $(subdir-dirs) ../locale/programs ../intl
 
 
 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))) \
+			   db-initgroups
+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)
+
+install-others		+= $(inst_vardbdir)/Makefile
 
 # 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
@@ -80,6 +93,10 @@
 $(objpfx)getent: $(objpfx)libnss_files.a
 endif
 
+ifeq (yes,$(have-selinux))
+LDLIBS-makedb		:= -lselinux
+endif
+
 # Depend on libc.so so a DT_NEEDED is generated in the shared objects.
 # This ensures they will load libc.so for needed symbols if loaded by
 # a statically-linked program that hasn't already loaded it.
@@ -87,6 +104,20 @@
 $(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)
+
+$(inst_vardbdir)/Makefile: db-Makefile $(+force)
+	$(do-install)
 
 distribute		+= nss_test1.c
 

Modified: fsf/trunk/libc/nss/Versions
==============================================================================
--- fsf/trunk/libc/nss/Versions (original)
+++ fsf/trunk/libc/nss/Versions Thu Jun 16 00:03:12 2011
@@ -27,6 +27,8 @@
     _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 @@
     _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,59 @@
     _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;
+
+    _nss_db_initgroups_dyn;
+  }
+}

Modified: fsf/trunk/libc/nss/databases.def
==============================================================================
--- fsf/trunk/libc/nss/databases.def (original)
+++ fsf/trunk/libc/nss/databases.def Thu Jun 16 00:03:12 2011
@@ -1,5 +1,5 @@
 /* List of all databases defined for the NSS in GNU C Library.
-   Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 2005, 2011 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 1996.
 
@@ -25,6 +25,7 @@
 DEFINE_DATABASE (ethers)
 DEFINE_DATABASE (group)
 DEFINE_DATABASE (hosts)
+DEFINE_DATABASE (initgroups)
 DEFINE_DATABASE (netgroup)
 DEFINE_DATABASE (networks)
 DEFINE_DATABASE (passwd)

Modified: fsf/trunk/libc/nss/db-Makefile
==============================================================================
--- fsf/trunk/libc/nss/db-Makefile (original)
+++ fsf/trunk/libc/nss/db-Makefile Thu Jun 16 00:03:12 2011
@@ -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@xxxxxxxxxx>, 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 @@
 
 $(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,21 +43,30 @@
 
 $(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 }' $^ | \
+			   printf "=%s ", $$3; print; \
+			   if ($$4 != "") { \
+			     split($$4, grmems, ","); \
+			     for (memidx in grmems) { \
+			       mem=grmems[memidx]; \
+			       if (members[mem] == "") \
+				 members[mem]=$$3; \
+			       else \
+				 members[mem]=members[mem] "," $$3; \
+			     } \
+			     delete grmems; } } \
+		 END { for (mem in members) \
+			 printf ":%s $s %s\n", mem, mem, members[mem]; }' $^ | \
 	$(MAKEDB) -o $@ -
 	@echo "done."
 
 $(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 +74,8 @@
 
 $(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 +85,8 @@
 
 $(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 +96,25 @@
 
 $(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 +130,38 @@
 	  echo; \
 	fi
 
+$(VAR_DB)/gshadow.db: /etc/gshadow
+	@echo -n "$(patsubst %.db,%,$(@F))... "
+	@$(AWK) 'BEGIN { FS=":"; OFS=":" } \
+		 /^[ \t]*$$/ { next } \
+		 /^[ \t]*#/ { next } \
+		 /^[^#]/ { printf ".%s ", $$1; print }' $^ | \
+	(umask 077 && $(MAKEDB) -o $@ -)
+	@echo "done."
+	@if chgrp shadow $@ 2>/dev/null; then \
+	  chmod g+r $@; \
+	else \
+	  chown 0 $@; chgrp 0 $@; chmod 600 $@; \
+	  echo; \
+	  echo "Warning: The shadow group database $@"; \
+	  echo "has been set to be readable only by root.  You may want"; \
+	  echo "to make it readable by the \`shadow' group depending"; \
+	  echo "on your configuration."; \
+	  echo; \
+	fi
+
 $(VAR_DB)/netgroup.db: /etc/netgroup
 	@echo -n "$(patsubst %.db,%,$(@F))... "
-	@$(AWK) 'BEGIN { cnt=0 } \
+	@$(AWK) 'BEGIN { ini=1 } \
 		 /^[ \t]*$$/ { next } \
 		 /^[ \t]*#/ { next } \
-		 { printf "0%u ", cnt++; print } \
-		 /^[^#]/ { end=sub(/\\/, " "); \
+		 /^[^#]/ { if (sub(/[ \t]*\\$$/, " ") == 0) end="\n"; \
+			   else end=""; \
 			   gsub(/[ \t]+/, " "); \
-			   if(end == 1) printf "%s", $$0; else print }' $^ | \
+			   sub(/^[ \t]*/, ""); \
+			   if (ini == 0) printf "%s%s", $$0, end; \
+			   else printf ".%s %s%s", $$1, $$0, end; \
+			   ini=end == "" ? 0 : 1; } \
+			   END { if (ini==0) printf "\n" }' $^ | \
 	$(MAKEDB) -o $@ -
 	@echo "done."

Modified: fsf/trunk/libc/nss/getent.c
==============================================================================
--- fsf/trunk/libc/nss/getent.c (original)
+++ fsf/trunk/libc/nss/getent.c Thu Jun 16 00:03:12 2011
@@ -501,6 +501,38 @@
   return result;
 }
 
+/* This is for initgroups */
+static int
+initgroups_keys (int number, char *key[])
+{
+  int ngrps = 100;
+  size_t grpslen = ngrps * sizeof (gid_t);
+  gid_t *grps = alloca (grpslen);
+
+  for (int i = 0; i < number; ++i)
+    {
+      int no = ngrps;
+      int n;
+      while ((n = getgrouplist (key[i], -1, grps, &no)) == -1
+	     && no > ngrps)
+	{
+	  grps = extend_alloca (grps, grpslen, no * sizeof (gid_t));
+	  ngrps = no;
+	}
+
+      if (n == -1)
+	return 1;
+
+      printf ("%-21s", key[i]);
+      for (int j = 0; j < n; ++j)
+	if (grps[j] != -1)
+	  printf (" %ld", (long int) grps[j]);
+      putchar_unlocked ('\n');
+    }
+
+  return 0;
+}
+
 /* This is for networks */
 static void
 print_networks (struct netent *net)
@@ -829,6 +861,7 @@
 D(group)
 D(gshadow)
 D(hosts)
+D(initgroups)
 D(netgroup)
 D(networks)
 D(passwd)

Modified: fsf/trunk/libc/nss/makedb.c
==============================================================================
--- fsf/trunk/libc/nss/makedb.c (original)
+++ fsf/trunk/libc/nss/makedb.c Thu Jun 16 00:03:12 2011
@@ -1,5 +1,5 @@
 /* Create simple DB database from textual input.
-   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.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 1996.
 
@@ -19,24 +19,76 @@
    02111-1307 USA.  */
 
 #include <argp.h>
+#include <assert.h>
 #include <ctype.h>
-#include <dlfcn.h>
 #include <errno.h>
 #include <error.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <libintl.h>
 #include <locale.h>
+#include <search.h>
 #include <stdio.h>
-#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#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"
 
+/* The hashing function we use.  */
+#include "../intl/hash-string.h"
+
+/* SELinux support.  */
+#ifdef HAVE_SELINUX
+# include <selinux/selinux.h>
+#endif
+
 #define PACKAGE _libc_intl_domainname
+
+/* List of data bases.  */
+struct database
+{
+  char dbid;
+  bool extra_string;
+  struct database *next;
+  void *entries;
+  size_t nentries;
+  size_t nhashentries;
+  stridx_t *hashtable;
+  size_t keystrlen;
+  stridx_t *keyidxtab;
+  char *keystrtab;
+} *databases;
+static size_t ndatabases;
+static size_t nhashentries_total;
+static size_t valstrlen;
+static void *valstrtree;
+static char *valstrtab;
+static size_t extrastrlen;
+
+/* Database entry.  */
+struct dbentry
+{
+  stridx_t validx;
+  uint32_t hashval;
+  char str[0];
+};
+
+/* Stored string entry.  */
+struct valstrentry
+{
+  stridx_t idx;
+  bool extra_string;
+  char str[0];
+};
+
+
+/* True if any entry has been added.  */
+static bool any_dbentry;
 
 /* If non-zero convert key to lower case.  */
 static int to_lowercase;
@@ -63,11 +115,13 @@
     N_("Do not print messages while building database") },
   { "undo", 'u', NULL, 0,
     N_("Print content of database file, one entry a line") },
+  { "generated", 'g', N_("CHAR"), 0,
+    N_("Generated line not part of iteration") },
   { NULL, 0, NULL, 0, NULL }
 };
 
 /* Short description of program.  */
-static const char doc[] = N_("Create simple DB database from textual input.");
+static const char doc[] = N_("Create simple database from textual input.");
 
 /* Strings for arguments in help texts.  */
 static const char args_doc[] = N_("\
@@ -86,10 +140,35 @@
 };
 
 
+/* List of databases which are not part of the iteration table.  */
+static struct db_option
+{
+  char dbid;
+  struct db_option *next;
+} *db_options;
+
+
 /* Prototypes for local functions.  */
-static int process_input (FILE *input, const char *inname, NSS_DB *output,
+static int process_input (FILE *input, const char *inname,
 			  int to_lowercase, int be_quiet);
-static int print_database (NSS_DB *db);
+static int print_database (int fd);
+static void compute_tables (void);
+static int write_output (int fd);
+
+/* SELinux support.  */
+#ifdef HAVE_SELINUX
+/* Set the SELinux file creation context for the given file. */
+static void set_file_creation_context (const char *outname, mode_t mode);
+static void reset_file_creation_context (void);
+#else
+# define set_file_creation_context(_outname,_mode)
+# define reset_file_creation_context()
+#endif
+
+
+/* External functions.  */
+extern void *xmalloc (size_t n) __attribute_malloc__;
+extern void *xcalloc (size_t n, size_t m) __attribute_malloc__;
 
 
 int
@@ -97,10 +176,8 @@
 {
   const char *input_name;
   FILE *input_file;
-  NSS_DB *db_file;
-  int status;
   int remaining;
-  int mode = 0666;
+  int mode = 0644;
 
   /* Set locale via LC_ALL.  */
   setlocale (LC_ALL, "");
@@ -136,24 +213,17 @@
       output_name = argv[remaining];
     }
 
-  /* First load the shared object to initialize version dependend
-     variables.  */
-  if (load_db () != NSS_STATUS_SUCCESS)
-    error (EXIT_FAILURE, 0, gettext ("No usable database library found."));
-
   /* Special handling if we are asked to print the database.  */
   if (do_undo)
     {
-      dbopen (input_name, db_rdonly, 0666, &db_file);
-      if (db_file == NULL)
-	error (EXIT_FAILURE, 0, gettext ("cannot open database file `%s': %s"),
-	       input_name,
-	       (errno == EINVAL ? gettext ("incorrectly formatted file")
-		: strerror (errno)));
-
-      status = print_database (db_file);
-
-      db_file->close (db_file->db, 0);
+      int fd = open (input_name, O_RDONLY);
+      if (fd == -1)
+	error (EXIT_FAILURE, errno, gettext ("cannot open database file `%s'"),
+	       input_name);
+
+      int status = print_database (fd);
+
+      close (fd);
 
       return status;
     }
@@ -163,34 +233,87 @@
     input_file = stdin;
   else
     {
-      struct stat st;
-
-      input_file = fopen (input_name, "r");
+      struct stat64 st;
+
+      input_file = fopen64 (input_name, "r");
       if (input_file == NULL)
 	error (EXIT_FAILURE, errno, gettext ("cannot open input file `%s'"),
 	       input_name);
 
       /* Get the access rights from the source file.  The output file should
 	 have the same.  */
-      if (fstat (fileno (input_file), &st) >= 0)
+      if (fstat64 (fileno (input_file), &st) >= 0)
 	mode = st.st_mode & ACCESSPERMS;
     }
 
-  /* Open output file.  This must not be standard output so we don't
-     handle "-" and "/dev/stdout" special.  */
-  dbopen (output_name, DB_CREATE | db_truncate, mode, &db_file);
-  if (db_file == NULL)
-    error (EXIT_FAILURE, errno, gettext ("cannot open output file `%s'"),
-	   output_name);
-
   /* Start the real work.  */
-  status = process_input (input_file, input_name, db_file, to_lowercase,
-			  be_quiet);
+  int status = process_input (input_file, input_name, to_lowercase, be_quiet);
 
   /* Close files.  */
   if (input_file != stdin)
     fclose (input_file);
-  db_file->close (db_file->db, 0);
+
+  /* No need to continue when we did not read the file successfully.  */
+  if (status != EXIT_SUCCESS)
+    return status;
+
+  /* Bail out if nothing is to be done.  */
+  if (!any_dbentry)
+    {
+      if (be_quiet)
+	return EXIT_SUCCESS;
+      else
+	error (EXIT_SUCCESS, 0, gettext ("no entries to be processed"));
+    }
+
+  /* Compute hash and string tables.  */
+  compute_tables ();
+
+  /* Open output file.  This must not be standard output so we don't
+     handle "-" and "/dev/stdout" special.  */
+  char *tmp_output_name;
+  if (asprintf (&tmp_output_name, "%s.XXXXXX", output_name) == -1)
+    error (EXIT_FAILURE, errno, gettext ("cannot create temporary file name"));
+
+  set_file_creation_context (output_name, mode);
+  int fd = mkstemp (tmp_output_name);
+  reset_file_creation_context ();
+  if (fd == -1)
+    error (EXIT_FAILURE, errno, gettext ("cannot create temporary file"));
+
+  status = write_output (fd);
+
+  if (status == EXIT_SUCCESS)
+    {
+      struct stat64 st;
+
+      if (fstat64 (fd, &st) == 0)
+	{
+	  if ((st.st_mode & ACCESSPERMS) != mode)
+	    /* We ignore problems with changing the mode.  */
+	    fchmod (fd, mode);
+	}
+      else
+	{
+	  error (0, errno, gettext ("cannot stat newly created file"));
+	  status = EXIT_FAILURE;
+	}
+    }
+
+  close (fd);
+
+  if (status == EXIT_SUCCESS)
+    {
+      if (rename (tmp_output_name, output_name) != 0)
+	{
+	  error (0, errno, gettext ("cannot rename temporary file"));
+	  status = EXIT_FAILURE;
+	  goto do_unlink;
+	}
+    }
+  else
+  do_unlink:
+    unlink (tmp_output_name);
 
   return status;
 }
@@ -200,6 +323,8 @@
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
+  struct db_option *newp;
+
   switch (key)
     {
     case 'f':
@@ -214,6 +339,12 @@
     case 'u':
       do_undo = 1;
       break;
+    case 'g':
+      newp = xmalloc (sizeof (*newp));
+      newp->dbid = arg[0];
+      newp->next = db_options;
+      db_options = newp;
+      break;
     default:
       return ARGP_ERR_UNKNOWN;
     }
@@ -246,16 +377,38 @@
 Copyright (C) %s Free Software Foundation, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2000");
+"), "2011");
   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
 }
 
 
 static int
-process_input (input, inname, output, to_lowercase, be_quiet)
+dbentry_compare (const void *p1, const void *p2)
+{
+  const struct dbentry *d1 = (const struct dbentry *) p1;
+  const struct dbentry *d2 = (const struct dbentry *) p2;
+
+  if (d1->hashval != d2->hashval)
+    return d1->hashval < d2->hashval ? -1 : 1;
+
+  return strcmp (d1->str, d2->str);
+}
+
+
+static int
+valstr_compare (const void *p1, const void *p2)
+{
+  const struct valstrentry *d1 = (const struct valstrentry *) p1;
+  const struct valstrentry *d2 = (const struct valstrentry *) p2;
+
+  return strcmp (d1->str, d2->str);
+}
+
+
+static int
+process_input (input, inname, to_lowercase, be_quiet)
      FILE *input;
      const char *inname;
-     NSS_DB *output;
      int to_lowercase;
      int be_quiet;
 {
@@ -269,14 +422,11 @@
   status = EXIT_SUCCESS;
   linenr = 0;
 
-  while (!feof (input))
-    {
-      DBT key;
-      DBT val;
-      char *cp;
-      int n;
-
-      n = getline (&line, &linelen, input);
+  struct database *last_database = NULL;
+
+  while (!feof_unlocked (input))
+    {
+      ssize_t n = getline (&line, &linelen, input);
       if (n < 0)
 	/* This means end of file or some bug.  */
 	break;
@@ -290,15 +440,18 @@
 	/* Remove trailing newline.  */
 	line[--n] = '\0';
 
-      cp = line;
+      char *cp = line;
       while (isspace (*cp))
 	++cp;
 
-      if (*cp == '#')
-	/* First non-space character in line '#': it's a comment.  */
+      if (*cp == '#' || *cp == '\0')
+	/* First non-space character in line '#': it's a comment.
+	   Also go to the next line if it is empty except for whitespaces. */
 	continue;
 
-      key.data = cp;
+      /* Skip over the character indicating the database so that it is not
+	 affected by TO_LOWERCASE.  */
+      char *key = cp++;
       while (*cp != '\0' && !isspace (*cp))
 	{
 	  if (to_lowercase)
@@ -306,85 +459,411 @@
 	  ++cp;
 	}
 
-      if (key.data == cp)
-	/* It's an empty line.  */
+      if (*cp == '\0')
+	/* It's a line without a value field.  */
 	continue;
 
-      key.size = cp - (char *) key.data;
-      key.flags = 0;
+      *cp++ = '\0';
+      size_t keylen = cp - key;
 
       while (isspace (*cp))
 	++cp;
 
-      val.data = cp;
-      val.size = (&line[n] - cp) + 1;
-      val.flags = 0;
-
-      /* Store the value.  */
-      status = output->put (output->db, NULL, &key, &val, db_nooverwrite);
-      if (status != 0)
+      char *data = cp;
+      size_t datalen = (&line[n] - cp) + 1;
+
+      /* Find the database.  */
+      if (last_database == NULL || last_database->dbid != key[0])
 	{
-	  if (status == db_keyexist)
+	  last_database = databases;
+	  while (last_database != NULL && last_database->dbid != key[0])
+	    last_database = last_database->next;
+
+	  if (last_database == NULL)
 	    {
-	      if (!be_quiet)
-		error_at_line (0, 0, inname, linenr,
-			       gettext ("duplicate key"));
-	      /* This is no real error.  Just give a warning.  */
-	      status = 0;
-	      continue;
+	      last_database = xmalloc (sizeof (*last_database));
+	      last_database->dbid = key[0];
+	      last_database->extra_string = false;
+	      last_database->next = databases;
+	      last_database->entries = NULL;
+	      last_database->nentries = 0;
+	      last_database->keystrlen = 0;
+	      databases = last_database;
+
+	      struct db_option *runp = db_options;
+	      while (runp != NULL)
+		if (runp->dbid == key[0])
+		  {
+		    last_database->extra_string = true;
+		    break;
+		  }
+		else
+		  runp = runp->next;
+	    }
+	}
+
+      /* Skip the database selector.  */
+      ++key;
+      --keylen;
+
+      /* Store the data.  */
+      struct valstrentry *nentry = xmalloc (sizeof (struct valstrentry)
+					    + datalen);
+      if (last_database->extra_string)
+	nentry->idx = extrastrlen;
+      else
+	nentry->idx = valstrlen;
+      nentry->extra_string = last_database->extra_string;
+      memcpy (nentry->str, data, datalen);
+
+      struct valstrentry **fdata = tsearch (nentry, &valstrtree,
+					    valstr_compare);
+      if (fdata == NULL)
+	error (EXIT_FAILURE, errno, gettext ("cannot create search tree"));
+
+      if (*fdata != nentry)
+	{
+	  /* We can reuse a string.  */
+	  free (nentry);
+	  nentry = *fdata;
+	}
+      else
+	if (last_database->extra_string)
+	  extrastrlen += datalen;
+	else
+	  valstrlen += datalen;
+
+      /* Store the key.  */
+      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);
+      if (found == NULL)
+	error (EXIT_FAILURE, errno, gettext ("cannot create search tree"));
+
+      if (*found != newp)
+	{
+	  free (newp);
+	  if (!be_quiet)
+	    error_at_line (0, 0, inname, linenr, gettext ("duplicate key"));
+	  continue;
+	}
+
+      ++last_database->nentries;
+      last_database->keystrlen += keylen;
+
+      any_dbentry = true;
+    }
+
+  if (ferror_unlocked (input))
+    {
+      error (0, 0, gettext ("problems while reading `%s'"), inname);
+      status = EXIT_FAILURE;
+    }
+
+  return status;
+}
+
+
+static void
+copy_valstr (const void *nodep, const VISIT which, const int depth)
+{
+  if (which != leaf && which != postorder)
+    return;
+
+  const struct valstrentry *p = *(const struct valstrentry **) nodep;
+
+  strcpy (valstrtab + (p->extra_string ? valstrlen : 0) + p->idx, p->str);
+}
+
+
+static int
+is_prime (size_t candidate)
+{
+  /* No even number and none less than 10 will be passed here.  */
+  size_t divn = 3;
+  size_t sq = divn * divn;
+
+  while (sq < candidate && candidate % divn != 0)
+    {
+      ++divn;
+      sq += 4 * divn;
+      ++divn;
+    }
+
+  return candidate % divn != 0;
+}
+
+
+static size_t
+next_prime (size_t seed)
+{
+  /* Make it definitely odd.  */
+  seed |= 1;
+
+  while (!is_prime (seed))
+    seed += 2;
+
+  return seed;
+}
+
+
+static void
+compute_tables (void)
+{
+  valstrtab = xmalloc (roundup (valstrlen + extrastrlen, sizeof (stridx_t)));
+  while ((valstrlen + extrastrlen) % sizeof (stridx_t) != 0)
+    valstrtab[valstrlen++] = '\0';
+  twalk (valstrtree, copy_valstr);
+
+  for (struct database *db = databases; db != NULL; db = db->next)
+    if (db->nentries != 0)
+      {
+	++ndatabases;
+
+	/* 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.  */
+#define TEST_RANGE 30
+	size_t nhashentries_min = next_prime (db->nentries < TEST_RANGE
+					      ? db->nentries
+					      : db->nentries * 2 - TEST_RANGE);
+	size_t nhashentries_max = MAX (nhashentries_min, db->nentries * 4);
+	size_t nhashentries_best = nhashentries_min;
+	size_t chainlength_best = db->nentries;
+
+	db->hashtable = xmalloc (2 * nhashentries_max * sizeof (stridx_t)
+				 + db->keystrlen);
+	db->keyidxtab = db->hashtable + nhashentries_max;
+	db->keystrtab = (char *) (db->keyidxtab + nhashentries_max);
+
+	size_t max_chainlength;
+	char *wp;
+	size_t nhashentries;
+	bool copy_string = false;
+
+	void add_key(const void *nodep, const VISIT which, const int depth)
+	{
+	  if (which != leaf && which != postorder)
+	    return;
+
+	  const struct dbentry *dbe = *(const struct dbentry **) nodep;
+
+	  ptrdiff_t stridx;
+	  if (copy_string)
+	    {
+	      stridx = wp - db->keystrtab;
+	      wp = stpcpy (wp, dbe->str) + 1;
 	    }
 	  else
-	    error (0, status, gettext ("while writing database file"));
-
-	  status = EXIT_FAILURE;
-
-	  clearerr (input);
-	  break;
+	    stridx = 0;
+
+	  size_t hidx = dbe->hashval % nhashentries;
+	  size_t hval2 = 1 + dbe->hashval % (nhashentries - 2);
+	  size_t chainlength = 0;
+
+	  while (db->hashtable[hidx] != ~((stridx_t) 0))
+	    {
+	      ++chainlength;
+	      if ((hidx += hval2) >= nhashentries)
+		hidx -= nhashentries;
+	    }
+
+	  db->hashtable[hidx] = ((db->extra_string ? valstrlen : 0)
+				 + dbe->validx);
+	  db->keyidxtab[hidx] = stridx;
+
+	  max_chainlength = MAX (max_chainlength, chainlength);
 	}
-    }
-
-  if (ferror (input))
-    {
-      error (0, 0, gettext ("problems while reading `%s'"), inname);
-      status = EXIT_FAILURE;
-    }
-
-  return status;
+
+	nhashentries = nhashentries_min;
+	for (size_t cnt = 0; cnt < TEST_RANGE; ++cnt)
+	  {
+	    memset (db->hashtable, '\xff', nhashentries * sizeof (stridx_t));
+
+	    max_chainlength = 0;
+	    wp = db->keystrtab;
+
+	    twalk (db->entries, add_key);
+
+	    if (max_chainlength == 0)
+	      {
+		/* No need to look further, this is as good as it gets.  */
+		nhashentries_best = nhashentries;
+		break;
+	      }
+
+	    if (max_chainlength < chainlength_best)
+	      {
+		chainlength_best = max_chainlength;
+		nhashentries_best = nhashentries;
+	      }
+
+	    nhashentries = next_prime (nhashentries + 1);
+	    if (nhashentries > nhashentries_max)
+	      break;
+	  }
+
+	/* Recompute the best table again, this time fill in the strings.  */
+	nhashentries = nhashentries_best;
+	memset (db->hashtable, '\xff',
+		2 * nhashentries_max * sizeof (stridx_t));
+	copy_string = true;
+	wp = db->keystrtab;
+
+	twalk (db->entries, add_key);
+
+	db->nhashentries = nhashentries_best;
+	nhashentries_total += nhashentries_best;
+    }
 }
 
 
 static int
-print_database (db)
-     NSS_DB *db;
-{
-  DBT key;
-  DBT val;
-  NSS_DBC *cursor;
-  int status;
-
-  status = db->cursor (db->db, NULL, &cursor);
-  if (status != 0)
-    {
-      error (0, status, gettext ("while reading database"));
+write_output (int fd)
+{
+  struct nss_db_header *header;
+  uint64_t file_offset = (sizeof (struct nss_db_header)
+			  + (ndatabases * sizeof (header->dbs[0])));
+  header = alloca (file_offset);
+
+  header->magic = NSS_DB_MAGIC;
+  header->ndbs = ndatabases;
+  header->valstroffset = file_offset;
+  header->valstrlen = valstrlen;
+
+  size_t filled_dbs = 0;
+  struct iovec iov[2 + ndatabases * 3];
+  iov[0].iov_base = header;
+  iov[0].iov_len = file_offset;
+
+  iov[1].iov_base = valstrtab;
+  iov[1].iov_len = valstrlen + extrastrlen;
+  file_offset += iov[1].iov_len;
+
+  size_t keydataoffset = file_offset + nhashentries_total * sizeof (stridx_t);
+  for (struct database *db = databases; db != NULL; db = db->next)
+    if (db->entries != NULL)
+      {
+	assert (file_offset % sizeof (stridx_t) == 0);
+	assert (filled_dbs < ndatabases);
+
+	header->dbs[filled_dbs].id = db->dbid;
+	memset (header->dbs[filled_dbs].pad, '\0',
+		sizeof (header->dbs[0].pad));
+	header->dbs[filled_dbs].hashsize = db->nhashentries;
+
+	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].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_total * sizeof (stridx_t)));
+  header->allocate = file_offset;
+
+  if (writev (fd, iov, 2 + ndatabases * 3) != keydataoffset)
+    {
+      error (0, errno, gettext ("failed to write new database file"));
       return EXIT_FAILURE;
     }
 
-  key.flags = 0;
-  val.flags = 0;
-  status = cursor->c_get (cursor->cursor, &key, &val, db_first);
-  while (status == 0)
-    {
-      printf ("%.*s %s\n", (int) key.size, (char *) key.data,
-	      (char *) val.data);
-
-      status = cursor->c_get (cursor->cursor, &key, &val, db_next);
-    }
-
-  if (status != db_notfound)
-    {
-      error (0, status, gettext ("while reading database"));
-      return EXIT_FAILURE;
-    }
-
   return EXIT_SUCCESS;
 }
+
+
+static int
+print_database (int fd)
+{
+  struct stat64 st;
+  if (fstat64 (fd, &st) != 0)
+    error (EXIT_FAILURE, errno, gettext ("cannot stat database file"));
+
+  const struct nss_db_header *header = mmap (NULL, st.st_size, PROT_READ,
+					     MAP_PRIVATE|MAP_POPULATE, fd, 0);
+  if (header == MAP_FAILED)
+    error (EXIT_FAILURE, errno, gettext ("cannot map database file"));
+
+  if (header->magic != NSS_DB_MAGIC)
+    error (EXIT_FAILURE, 0, gettext ("file not a database file"));
+
+  const char *valstrtab = (const char *) header + header->valstroffset;
+
+  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].keystroffset;
+      const stridx_t *hashtab
+	= (const stridx_t *) ((const char *) header
+			      + header->dbs[dbidx].hashoffset);
+
+      for (uint32_t hidx = 0; hidx < header->dbs[dbidx].hashsize; ++hidx)
+	if (hashtab[hidx] != ~((stridx_t) 0))
+	  printf ("%c%s %s\n",
+		  header->dbs[dbidx].id,
+		  keystrtab + stridxtab[hidx],
+		  valstrtab + hashtab[hidx]);
+    }
+
+  return EXIT_SUCCESS;
+}
+
+
+#ifdef HAVE_SELINUX
+static void
+set_file_creation_context (const char *outname, mode_t mode)
+{
+  static int enabled;
+  static int enforcing;
+  security_context_t ctx;
+
+  /* Check if SELinux is enabled, and remember. */
+  if (enabled == 0)
+    enabled = is_selinux_enabled ();
+  if (enabled < 0)
+    return;
+
+  /* Check if SELinux is enforcing, and remember. */
+  if (enforcing == 0)
+    enforcing = security_getenforce () ? 1 : -1;
+
+  /* Determine the context which the file should have. */
+  ctx = NULL;
+  if (matchpathcon (outname, S_IFREG | mode, &ctx) == 0 && ctx != NULL)
+    {
+      if (setfscreatecon (ctx) != 0)
+	error (enforcing > 0 ? EXIT_FAILURE : 0, 0,
+	       gettext ("cannot set file creation context for `%s'"),
+	       outname);
+
+      freecon (ctx);
+    }
+}
+
+static void
+reset_file_creation_context (void)
+{
+  setfscreatecon (NULL);
+}
+#endif

Modified: fsf/trunk/libc/nss/nss_db/db-XXX.c
==============================================================================
--- fsf/trunk/libc/nss/nss_db/db-XXX.c (original)
+++ fsf/trunk/libc/nss/nss_db/db-XXX.c Thu Jun 16 00:03:12 2011
@@ -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 int keep_db;
+static const char *entidx;
+
 
-/* Maintenance of the shared handle open on the database.  */
-
-static NSS_DB *db;
-static int keep_db;
-static int entidx;
-
-
 /* Open the database.  */
 enum nss_status
 CONCAT(_nss_db_set,ENTNAME) (int stayopen)
@@ -65,13 +69,13 @@
 
   __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 @@
 {
   __libc_lock_lock (lock);
 
-  internal_endent (&db);
+  internal_endent (&state);
 
   /* Reset STAYOPEN flag.  */
   keep_db = 0;
@@ -94,132 +98,124 @@
 
   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)'.
-
-   PROTO describes the arguments for the lookup key;
-   e.g. `const char *name'.
-
-   BREAK_IF_MATCH is ignored, but used by ../nss_files/files-XXX.c.  */
-
-#define DB_LOOKUP(name, keysize, keypattern, break_if_match, proto...)	      \
+   e.g. `1 + sizeof (id) * 4'.
+
+   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, 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);						      \
+  struct parser_data *data = (void *) buffer;				      \
+									      \
+  if (buflen < sizeof *data)						      \
+    {									      \
+      *errnop = ERANGE;							      \
+      H_ERRNO_SET (NETDB_INTERNAL);					      \
+      return NSS_STATUS_TRYAGAIN;					      \
+    }									      \
+									      \
+  struct nss_db_map state = { NULL, 0 };				      \
+  enum nss_status status = internal_setent (DBFILE, &state);		      \
+  if (status != NSS_STATUS_SUCCESS)					      \
+    {									      \
+      *errnop = errno;							      \
+      H_ERRNO_SET (NETDB_INTERNAL);					      \
+      return status;							      \
+    }									      \
+									      \
+  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 +227,72 @@
 {
   /* 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;

Added: fsf/trunk/libc/nss/nss_db/db-initgroups.c
==============================================================================
--- fsf/trunk/libc/nss/nss_db/db-initgroups.c (added)
+++ fsf/trunk/libc/nss/nss_db/db-initgroups.c Thu Jun 16 00:03:12 2011
@@ -1,0 +1,138 @@
+/* Initgroups handling in nss_db module.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@xxxxxxxxx>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <paths.h>
+
+#include "nss_db.h"
+
+/* The hashing function we use.  */
+#include "../intl/hash-string.h"
+
+
+enum nss_status
+_nss_db_initgroups_dyn (const char *user, gid_t group, long int *start,
+			long int *size, gid_t **groupsp, long int limit,
+			int *errnop)
+{
+  struct nss_db_map state = { NULL, 0 };
+  enum nss_status status = internal_setent (_PATH_VARDB "group.db", &state);
+  if (status != NSS_STATUS_SUCCESS)
+    {
+      *errnop = errno;
+      return status;
+    }
+
+  const struct nss_db_header *header = state.header;
+  int i;
+  for (i = 0; i < header->ndbs; ++i)
+    if (header->dbs[i].id == ':')
+      break;
+  if (i == header->ndbs)
+    {
+      status = NSS_STATUS_UNAVAIL;
+      goto out;
+    }
+
+  const stridx_t *hashtable
+    = (const stridx_t *) ((const char *) header
+			  + header->dbs[i].hashoffset);
+  const char *valstrtab = (const char *) header + header->valstroffset;
+  size_t userlen = strlen (user);
+  uint32_t hashval = __hash_string (user);
+  size_t hidx = hashval % header->dbs[i].hashsize;
+  size_t hval2 = 1 + hashval % (header->dbs[i].hashsize - 2);
+
+  gid_t *groups = *groupsp;
+
+  status = NSS_STATUS_NOTFOUND;
+  while (hashtable[hidx] != ~((stridx_t) 0))
+    {
+      const char *valstr = valstrtab + hashtable[hidx];
+      while (isblank (*valstr))
+	++valstr;
+
+      if (strncmp (valstr, user, userlen) == 0 && isblank (valstr[userlen]))
+	{
+	  valstr += userlen + 1;
+	  while (isblank (*valstr))
+	    ++valstr;
+
+	  while (*valstr != '\0')
+	    {
+	      errno = 0;
+	      char *endp;
+	      unsigned long int n = strtoul (valstr, &endp, 10);
+	      if (*endp != ',' && *endp != '\0')
+		break;
+	      valstr = *endp == '\0' ? endp : endp + 1;
+
+	      if (n != ULONG_MAX || errno != ERANGE)
+		{
+		  /* Insert the group.  */
+		  if (*start == *size)
+		    {
+		      /* Need a bigger buffer.  */
+		      if (limit > 0 && *size == limit)
+			{
+			  /* We reached the maximum.  */
+			  status = NSS_STATUS_SUCCESS;
+			  goto out;
+			}
+
+		      long int newsize;
+		      if (limit <= 0)
+			newsize = 2 * *size;
+		      else
+			newsize = MIN (limit, 2 * *size);
+
+		      gid_t *newgroups = realloc (groups,
+						  newsize * sizeof (*groups));
+		      if (newgroups == NULL)
+			{
+			  *errnop = ENOMEM;
+			  status = NSS_STATUS_TRYAGAIN;
+			  goto out;
+			}
+
+		      *groupsp = groups = newgroups;
+		      *size = newsize;
+		    }
+
+		  groups[*start] = n;
+		  *start += 1;
+		}
+	    }
+
+	  status = NSS_STATUS_SUCCESS;
+	  break;
+	}
+
+      if ((hidx += hval2) >= header->dbs[i].hashsize)
+	hidx -= header->dbs[i].hashsize;
+    }
+
+ out:
+  internal_endent (&state);
+
+  return status;
+}

Modified: fsf/trunk/libc/nss/nss_db/db-netgrp.c
==============================================================================
--- fsf/trunk/libc/nss/nss_db/db-netgrp.c (original)
+++ fsf/trunk/libc/nss/nss_db/db-netgrp.c Thu Jun 16 00:03:12 2011
@@ -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@xxxxxxxxxx>, 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,40 +30,62 @@
 #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;
 
@@ -70,14 +93,12 @@
 
 
 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 @@
 _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;
 }

Modified: fsf/trunk/libc/nss/nss_db/db-open.c
==============================================================================
--- fsf/trunk/libc/nss/nss_db/db-open.c (original)
+++ fsf/trunk/libc/nss/nss_db/db-open.c Thu Jun 16 00:03:12 2011
@@ -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.
+/* 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
+internal_setent (const char *file, struct nss_db_map *mapping)
+{
+  enum nss_status status = NSS_STATUS_UNAVAIL;
 
-   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?)  */
+  int mode = O_RDONLY | O_LARGEFILE;
+#ifdef O_CLOEXEC
+  mode |= O_CLOEXEC;
+#endif
+  int fd = open_not_cancel_2 (file, mode);
+  if (fd != -1)
+    {
+      struct nss_db_header header;
 
-/* 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.  */
-
-enum nss_status
-load_db (void)
-{
-  static const char *libnames[] = { "libdb.so.3", "libdb-3.0.so" };
-  int x;
-
-  for (x = 0; x < sizeof (libnames) / sizeof (libnames[0]); ++x)
-    {
-      libdb_handle = dlopen (libnames[x], RTLD_LAZY);
-      if (libdb_handle == NULL)
-	continue;
-
-      /* DB 3.0 has db_create instead of db_open.  */
-      libdb_db_create = dlsym (libdb_handle, "db_create");
-
-      if (libdb_db_create == NULL)
-	/* DB 2.x uses db_open.  */
-	libdb_db_open = dlsym (libdb_handle, "db_open");
-
-      if (libdb_db_open != NULL || libdb_db_create != NULL)
+      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;
-    }
+  munmap (mapping->header, mapping->len);
 }
-
-/* 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;
-}

Modified: fsf/trunk/libc/nss/nss_db/nss_db.h
==============================================================================
--- fsf/trunk/libc/nss/nss_db/nss_db.h (original)
+++ fsf/trunk/libc/nss/nss_db/nss_db.h Thu Jun 16 00:03:12 2011
@@ -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;
+/* Database file header.  */
+struct nss_db_header
+{
+  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];
+};
 
-/* The `DBT' type is the same in all versions we support.  */
-typedef struct
+
+/* Information about mapped database.  */
+struct nss_db_map
 {
-  void *data;
-  uint32_t size;
-  uint32_t ulen;
-  uint32_t dlen;
-  uint32_t doff;
-  uint32_t flags;
-} DBT;
+  struct nss_db_header *header;
+  size_t len;
+};
 
-/* But the cursor object is very different from version to version.  */
-typedef struct
-{
-  void *cursor;
-  int (*c_get) (void *, DBT *, DBT *, uint32_t);
-} NSS_DBC;
-
-/* 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);
+   handle in *MAPPINGP or a file descriptor for the file in *FDP and
+   return NSS_STATUS_SUCCESS.  On failure, return the appropriate
+   lookup status.  */
+enum nss_status internal_setent (const char *file,
+				 struct nss_db_map *mappingp);
 
-/* 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
-   lookup status.  */
-extern int dbopen (const char *fname, int oper, int mode, NSS_DB **dbp);
+/* Close the database FD.  */
+extern void internal_endent (struct nss_db_map *mapping);
 
 #endif	/* nss_db.h */

Modified: fsf/trunk/libc/nss/nss_files/files-XXX.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-XXX.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-XXX.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 
    NAME is the name of the lookup; e.g. `hostbyname'.
 
-   KEYSIZE and KEYPATTERN are ignored here but used by ../nss_db/db-XXX.c.
-
-   PROTO describes the arguments for the lookup key;
-   e.g. `const char *hostname'.
+   DB_CHAR, KEYPATTERN, KEYSIZE are ignored here but used by db-XXX.c
+   e.g. `1 + sizeof (id) * 4'.
+
+   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,	      \

Modified: fsf/trunk/libc/nss/nss_files/files-ethers.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-ethers.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-ethers.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 
 #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]),

Modified: fsf/trunk/libc/nss/nss_files/files-grp.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-grp.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-grp.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 #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] != '-')

Modified: fsf/trunk/libc/nss/nss_files/files-hosts.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-hosts.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-hosts.c Thu Jun 16 00:03:12 2011
@@ -358,7 +358,7 @@
    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))

Modified: fsf/trunk/libc/nss/nss_files/files-network.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-network.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-network.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 
 #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)

Modified: fsf/trunk/libc/nss/nss_files/files-proto.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-proto.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-proto.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 
 #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;

Modified: fsf/trunk/libc/nss/nss_files/files-pwd.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-pwd.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-pwd.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 #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] != '-')

Modified: fsf/trunk/libc/nss/nss_files/files-rpc.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-rpc.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-rpc.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 
 #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;

Modified: fsf/trunk/libc/nss/nss_files/files-service.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-service.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-service.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 
 #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 @@
 	   },
 	   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

Modified: fsf/trunk/libc/nss/nss_files/files-sgrp.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-sgrp.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-sgrp.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 #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))

Modified: fsf/trunk/libc/nss/nss_files/files-spwd.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-spwd.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-spwd.c Thu Jun 16 00:03:12 2011
@@ -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 @@
 #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))

Modified: fsf/trunk/libc/resolv/res_send.c
==============================================================================
--- fsf/trunk/libc/resolv/res_send.c (original)
+++ fsf/trunk/libc/resolv/res_send.c Thu Jun 16 00:03:12 2011
@@ -549,7 +549,7 @@
 				    ns, ansp, ansp2, nansp2, resplen2);
 			if (n < 0)
 				return (-1);
-			if (n == 0 && (buf2 == NULL || resplen2 == 0))
+			if (n == 0 && (buf2 == NULL || *resplen2 == 0))
 				goto next_ns;
 		} else {
 			/* Use datagrams. */
@@ -559,7 +559,7 @@
 				    ansp2, nansp2, resplen2);
 			if (n < 0)
 				return (-1);
-			if (n == 0 && (buf2 == NULL || resplen2 == 0))
+			if (n == 0 && (buf2 == NULL || *resplen2 == 0))
 				goto next_ns;
 			if (v_circuit)
 			  // XXX Check whether both requests failed or

Modified: fsf/trunk/libc/shlib-versions
==============================================================================
--- fsf/trunk/libc/shlib-versions (original)
+++ fsf/trunk/libc/shlib-versions Thu Jun 16 00:03:12 2011
@@ -113,6 +113,7 @@
 .*-.*-.*		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.

Added: fsf/trunk/libc/sysdeps/unix/sysv/linux/wordsize-64/dl-fxstatat64.c
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/wordsize-64/dl-fxstatat64.c (added)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/wordsize-64/dl-fxstatat64.c Thu Jun 16 00:03:12 2011
@@ -1,0 +1,6 @@
+/* In this implementation we do not really care whether the call fails
+   because of missing kernel support since we do not even call the
+   function in this case.  */
+#undef __ASSUME_ATFCTS
+#define __ASSUME_ATFCTS 1
+#include "fxstatat.c"