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

[commits] r14524 - in /fsf/trunk/libc: ./ nscd/ nss/ nss/nss_db/ nss/nss_files/ sysdeps/unix/sysv/linux/



Author: eglibc
Date: Tue Jul 12 00:02:31 2011
New Revision: 14524

Log:
Import glibc-mainline for 2011-07-12

Added:
    fsf/trunk/libc/nss/nss_db/db-init.c
    fsf/trunk/libc/nss/nss_files/files-init.c
Modified:
    fsf/trunk/libc/ChangeLog
    fsf/trunk/libc/configure
    fsf/trunk/libc/configure.in
    fsf/trunk/libc/nscd/cache.c
    fsf/trunk/libc/nscd/connections.c
    fsf/trunk/libc/nscd/nscd.c
    fsf/trunk/libc/nscd/nscd.h
    fsf/trunk/libc/nss/Makefile
    fsf/trunk/libc/nss/Versions
    fsf/trunk/libc/nss/nsswitch.c
    fsf/trunk/libc/nss/nsswitch.h
    fsf/trunk/libc/sysdeps/unix/sysv/linux/Makefile

Modified: fsf/trunk/libc/ChangeLog
==============================================================================
--- fsf/trunk/libc/ChangeLog (original)
+++ fsf/trunk/libc/ChangeLog Tue Jul 12 00:02:31 2011
@@ -1,3 +1,51 @@
+2011-07-11  Roland McGrath  <roland@xxxxxxxxxxxxx>
+
+	* configure.in (-z relro check): Fix test code to make the variable
+	truly const.
+	* configure: Regenerated.
+
+2011-07-11  Ulrich Drepper  <drepper@xxxxxxxxx>
+
+	* nscd/nscd.h (struct traced_file): Define.
+	(struct database_dyn): Remove inotify_descr, reset_res, and filename
+	elements.  Add traced_files.
+	(inotify_fd): Declare.
+	(register_traced_file): Declare.
+	* nscd/connections.c (dbs): Remove reset_res and filename initializers.
+	(inotify_fd): Export.
+	(resolv_conf_descr): Remove.
+	(nscd_init): Move inotify descriptor creation to main.
+	Don't register files for notification here.
+	(register_traced_file): New function.
+	(invalidate_cache): Don't use reset_res to determine whether to call
+	res_init, go through the list of registered files.
+	(main_loop_poll): The inotify descriptors are now stored in the
+	structures for the traced files.
+	(main_loop_epoll): Likewise
+	* nscd/nscd.c (main): Create inotify socket here.  Pass extra argument
+	to __nss_disable_nscd.
+	* nscd/cache.c (prune_cache): There is no single inotify descriptor
+	for a database anymore.  Check the records for all the registered
+	files instead.
+	* nss/Makefile (libnss_files-routines): Add files-init.
+	(libnss_db-routines): Add db-init.
+	* nss/Versions [libnss_files] (GLIBC_PRIVATE): Add _nss_files_init.
+	[libnss_db] (GLIBC_PRIVATE): Add _nss_db_init.
+	* nss/nss_db/db-init.c: New file.
+	* nss/nss_files/files-init.c: New file.
+	* nss/nsswitch.c (nss_load_library): New function.  Broken out of
+	__nss_lookup_function.
+	(__nss_lookup_function): Call nss_load_library.
+	(nss_load_all_libraries): New function.
+	(__nss_disable_nscd): Take parameter with callback function for files
+	to register.  Set is_nscd.  Load all the DSOs for the NSS modules
+	used for the cached services.
+	* nss/nsswitch.h (__nss_disable_nscd): Adjust prototype.
+	* sysdeps/unix/sysv/linux/Makefile [subdir=nscd]: Pass the various -D
+	options for features to all the files in nscd.
+
+	* nss/nsswitch.c (nss_parse_file): Add missing fclose.
+
 2011-07-10  Roland McGrath  <roland@xxxxxxxxxxxxx>
 
 	* csu/elf-init.c (__libc_csu_init): Comment typo.

Modified: fsf/trunk/libc/configure
==============================================================================
--- fsf/trunk/libc/configure (original)
+++ fsf/trunk/libc/configure Tue Jul 12 00:02:31 2011
@@ -6404,7 +6404,7 @@
 
 int _start (void) { return 42; }
 extern void _exit (int);
-const void *relro[] = { &_start, &_exit, 0 };
+const void *const relro[] = { &_start, &_exit, 0 };
 
 _ACEOF
     cat > conftest.awk <<\EOF

Modified: fsf/trunk/libc/configure.in
==============================================================================
--- fsf/trunk/libc/configure.in (original)
+++ fsf/trunk/libc/configure.in Tue Jul 12 00:02:31 2011
@@ -1607,7 +1607,7 @@
     AC_LANG_CONFTEST([AC_LANG_SOURCE([[
 int _start (void) { return 42; }
 extern void _exit (int);
-const void *relro[] = { &_start, &_exit, 0 };
+const void *const relro[] = { &_start, &_exit, 0 };
 ]])])
     cat > conftest.awk <<\EOF
 BEGIN {

Modified: fsf/trunk/libc/nscd/cache.c
==============================================================================
--- fsf/trunk/libc/nscd/cache.c (original)
+++ fsf/trunk/libc/nscd/cache.c Tue Jul 12 00:02:31 2011
@@ -264,28 +264,40 @@
 
   /* If we check for the modification of the underlying file we invalidate
      the entries also in this case.  */
-  if (table->inotify_descr < 0 && table->check_file && now != LONG_MAX)
-    {
-      struct stat64 st;
-
-      if (stat64 (table->filename, &st) < 0)
-	{
-	  char buf[128];
-	  /* We cannot stat() the file, disable file checking if the
-	     file does not exist.  */
-	  dbg_log (_("cannot stat() file `%s': %s"),
-		   table->filename, strerror_r (errno, buf, sizeof (buf)));
-	  if (errno == ENOENT)
-	    table->check_file = 0;
-	}
-      else
-	{
-	  if (st.st_mtime != table->file_mtime)
-	    {
-	      /* The file changed.  Invalidate all entries.  */
-	      now = LONG_MAX;
-	      table->file_mtime = st.st_mtime;
-	    }
+  if (table->check_file && now != LONG_MAX)
+    {
+      struct traced_file *runp = table->traced_files;
+
+      while (runp != NULL)
+	{
+#ifdef HAVE_INOTIFY
+	  if (runp->inotify_descr == -1)
+#endif
+	    {
+	      struct stat64 st;
+
+	      if (stat64 (runp->fname, &st) < 0)
+		{
+		  char buf[128];
+		  /* We cannot stat() the file, disable file checking if the
+		     file does not exist.  */
+		  dbg_log (_("cannot stat() file `%s': %s"),
+			   runp->fname, strerror_r (errno, buf, sizeof (buf)));
+		  if (errno == ENOENT)
+		    table->check_file = 0;
+		}
+	      else
+		{
+		  if (st.st_mtime != table->file_mtime)
+		    {
+		      /* The file changed.  Invalidate all entries.  */
+		      now = LONG_MAX;
+		      table->file_mtime = st.st_mtime;
+		    }
+		}
+	    }
+
+	  runp = runp->next;
 	}
     }
 

Modified: fsf/trunk/libc/nscd/connections.c
==============================================================================
--- fsf/trunk/libc/nscd/connections.c (original)
+++ fsf/trunk/libc/nscd/connections.c Tue Jul 12 00:02:31 2011
@@ -117,8 +117,6 @@
     .shared = 0,
     .max_db_size = DEFAULT_MAX_DB_SIZE,
     .suggested_module = DEFAULT_SUGGESTED_MODULE,
-   .reset_res = 0,
-    .filename = "/etc/passwd",
     .db_filename = _PATH_NSCD_PASSWD_DB,
     .disabled_iov = &pwd_iov_disabled,
     .postimeout = 3600,
@@ -138,8 +136,6 @@
     .shared = 0,
     .max_db_size = DEFAULT_MAX_DB_SIZE,
     .suggested_module = DEFAULT_SUGGESTED_MODULE,
-    .reset_res = 0,
-    .filename = "/etc/group",
     .db_filename = _PATH_NSCD_GROUP_DB,
     .disabled_iov = &grp_iov_disabled,
     .postimeout = 3600,
@@ -159,8 +155,6 @@
     .shared = 0,
     .max_db_size = DEFAULT_MAX_DB_SIZE,
     .suggested_module = DEFAULT_SUGGESTED_MODULE,
-    .reset_res = 1,
-    .filename = "/etc/hosts",
     .db_filename = _PATH_NSCD_HOSTS_DB,
     .disabled_iov = &hst_iov_disabled,
     .postimeout = 3600,
@@ -180,8 +174,6 @@
     .shared = 0,
     .max_db_size = DEFAULT_MAX_DB_SIZE,
     .suggested_module = DEFAULT_SUGGESTED_MODULE,
-    .reset_res = 0,
-    .filename = "/etc/services",
     .db_filename = _PATH_NSCD_SERVICES_DB,
     .disabled_iov = &serv_iov_disabled,
     .postimeout = 28800,
@@ -232,10 +224,7 @@
 
 #ifdef HAVE_INOTIFY
 /* Inotify descriptor.  */
-static int inotify_fd = -1;
-
-/* Watch descriptor for resolver configuration file.  */
-static int resolv_conf_descr = -1;
+int inotify_fd = -1;
 #endif
 
 #ifndef __ASSUME_SOCK_CLOEXEC
@@ -522,19 +511,6 @@
   if (nthreads == -1)
     /* No configuration for this value, assume a default.  */
     nthreads = 4;
-
-#ifdef HAVE_INOTIFY
-  /* Use inotify to recognize changed files.  */
-  inotify_fd = inotify_init1 (IN_NONBLOCK);
-# ifndef __ASSUME_IN_NONBLOCK
-  if (inotify_fd == -1 && errno == ENOSYS)
-    {
-      inotify_fd = inotify_init ();
-      if (inotify_fd != -1)
-	fcntl (inotify_fd, F_SETFL, O_RDONLY | O_NONBLOCK);
-    }
-# endif
-#endif
 
   for (size_t cnt = 0; cnt < lastdb; ++cnt)
     if (dbs[cnt].enabled)
@@ -840,40 +816,6 @@
 	    dbs[cnt].shared = 0;
 	    assert (dbs[cnt].ro_fd == -1);
 	  }
-
-	dbs[cnt].inotify_descr = -1;
-	if (dbs[cnt].check_file)
-	  {
-#ifdef HAVE_INOTIFY
-	    if (inotify_fd < 0
-		|| (dbs[cnt].inotify_descr
-		    = inotify_add_watch (inotify_fd, dbs[cnt].filename,
-					 IN_DELETE_SELF | IN_MODIFY)) < 0)
-	      /* We cannot notice changes in the main thread.  */
-#endif
-	      {
-		/* We need the modification date of the file.  */
-		struct stat64 st;
-
-		if (stat64 (dbs[cnt].filename, &st) < 0)
-		  {
-		    /* We cannot stat() the file, disable file checking.  */
-		    dbg_log (_("cannot stat() file `%s': %s"),
-			     dbs[cnt].filename, strerror (errno));
-		    dbs[cnt].check_file = 0;
-		  }
-		else
-		  dbs[cnt].file_mtime = st.st_mtime;
-	      }
-	  }
-
-#ifdef HAVE_INOTIFY
-	if (cnt == hstdb && inotify_fd >= -1)
-	  /* We also monitor the resolver configuration file.  */
-	  resolv_conf_descr = inotify_add_watch (inotify_fd,
-						 _PATH_RESCONF,
-						 IN_DELETE_SELF | IN_MODIFY);
-#endif
       }
 
   /* Create the socket.  */
@@ -940,12 +882,50 @@
       exit (1);
     }
 
-  /* Change to unprivileged uid/gid/groups if specifed in config file */
+  /* Change to unprivileged uid/gid/groups if specified in config file */
   if (server_user != NULL)
     finish_drop_privileges ();
 }
 
 
+void
+register_traced_file (size_t dbidx, struct traced_file *finfo)
+{
+  if (! dbs[dbidx].check_file)
+    return;
+
+  if (__builtin_expect (debug_level > 0, 0))
+    dbg_log (_("register trace file %s for database %s"),
+	     finfo->fname, dbnames[dbidx]);
+
+#ifdef HAVE_INOTIFY
+  if (inotify_fd < 0
+      || (finfo->inotify_descr = inotify_add_watch (inotify_fd, finfo->fname,
+						    IN_DELETE_SELF
+						    | IN_MODIFY)) < 0)
+#endif
+    {
+      /* We need the modification date of the file.  */
+      struct stat64 st;
+
+      if (stat64 (finfo->fname, &st) < 0)
+	{
+	  /* We cannot stat() the file, disable file checking.  */
+	  dbg_log (_("cannot stat() file `%s': %s"),
+		   finfo->fname, strerror (errno));
+	  return;
+	}
+
+      finfo->inotify_descr = -1;
+      finfo->mtime = st.st_mtime;
+    }
+
+  /* Queue up the file name.  */
+  finfo->next = dbs[dbidx].traced_files;
+  dbs[dbidx].traced_files = finfo;
+}
+
+
 /* Close the connections.  */
 void
 close_sockets (void)
@@ -963,11 +943,20 @@
   for (number = pwddb; number < lastdb; ++number)
     if (strcmp (key, dbnames[number]) == 0)
       {
-	if (dbs[number].reset_res)
-	  res_init ();
-
+	if (number == hstdb)
+	  {
+	    struct traced_file *runp = dbs[hstdb].traced_files;
+	    while (runp != NULL)
+	      if (runp->call_res_init)
+		{
+		  res_init ();
+		  break;
+		}
+	      else
+		runp = runp->next;
+	  }
 	break;
-      }
+    }
 
   if (number == lastdb)
     {
@@ -1913,16 +1902,21 @@
 
 		      /* Check which of the files changed.  */
 		      for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
-			if (inev.i.wd == dbs[dbcnt].inotify_descr)
-			  {
-			    to_clear[dbcnt] = true;
-			    goto next;
-			  }
-
-		      if (inev.i.wd == resolv_conf_descr)
 			{
-			  res_init ();
-			  to_clear[hstdb] = true;
+			  struct traced_file *finfo = dbs[dbcnt].traced_files;
+
+			  while (finfo != NULL)
+			    {
+			      if (finfo->inotify_descr == inev.i.wd)
+				{
+				  to_clear[dbcnt] = true;
+				  if (finfo->call_res_init)
+				    res_init ();
+				  goto next;
+				}
+
+			      finfo = finfo->next;
+			    }
 			}
 		    next:;
 		    }
@@ -2089,7 +2083,7 @@
 	    while (1)
 	      {
 		ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
-				 		 sizeof (inev)));
+						 sizeof (inev)));
 		if (nb < (ssize_t) sizeof (struct inotify_event))
 		  {
 		    if (__builtin_expect (nb == -1 && errno != EAGAIN, 0))
@@ -2108,16 +2102,21 @@
 
 		/* Check which of the files changed.  */
 		for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
-		  if (inev.i.wd == dbs[dbcnt].inotify_descr)
-		    {
-		      to_clear[dbcnt] = true;
-		      goto next;
-		    }
-
-		if (inev.i.wd == resolv_conf_descr)
 		  {
-		    res_init ();
-		    to_clear[hstdb] = true;
+		    struct traced_file *finfo = dbs[dbcnt].traced_files;
+
+		    while (finfo != NULL)
+		      {
+			if (finfo->inotify_descr == inev.i.wd)
+			  {
+			    to_clear[dbcnt] = true;
+			    if (finfo->call_res_init)
+			      res_init ();
+			    goto next;
+			  }
+
+			finfo = finfo->next;
+		      }
 		  }
 	      next:;
 	      }

Modified: fsf/trunk/libc/nscd/nscd.c
==============================================================================
--- fsf/trunk/libc/nscd/nscd.c (original)
+++ fsf/trunk/libc/nscd/nscd.c Tue Jul 12 00:02:31 2011
@@ -46,6 +46,9 @@
 #include "selinux.h"
 #include "../nss/nsswitch.h"
 #include <device-nrs.h>
+#ifdef HAVE_INOTIFY
+# include <sys/inotify.h>
+#endif
 
 /* Get libc version number.  */
 #include <version.h>
@@ -272,8 +275,21 @@
   /* Cleanup files created by a previous 'bind'.  */
   unlink (_PATH_NSCDSOCKET);
 
+#ifdef HAVE_INOTIFY
+  /* Use inotify to recognize changed files.  */
+  inotify_fd = inotify_init1 (IN_NONBLOCK);
+# ifndef __ASSUME_IN_NONBLOCK
+  if (inotify_fd == -1 && errno == ENOSYS)
+    {
+      inotify_fd = inotify_init ();
+      if (inotify_fd != -1)
+	fcntl (inotify_fd, F_SETFL, O_RDONLY | O_NONBLOCK);
+    }
+# endif
+#endif
+
   /* Make sure we do not get recursive calls.  */
-  __nss_disable_nscd ();
+  __nss_disable_nscd (register_traced_file);
 
   /* Init databases.  */
   nscd_init ();

Modified: fsf/trunk/libc/nscd/nscd.h
==============================================================================
--- fsf/trunk/libc/nscd/nscd.h (original)
+++ fsf/trunk/libc/nscd/nscd.h Tue Jul 12 00:02:31 2011
@@ -62,6 +62,17 @@
 #define MAX_STACK_USE ((8 * NSCD_THREAD_STACKSIZE) / 10)
 
 
+/* Registered filename used to fill database.  */
+struct traced_file
+{
+  time_t mtime;
+  struct traced_file *next;
+  int call_res_init;
+  int inotify_descr;
+  char fname[];
+};
+
+
 /* Structure describing dynamic part of one database.  */
 struct database_dyn
 {
@@ -73,13 +84,11 @@
 
   int enabled;
   int check_file;
-  int inotify_descr;
   int clear_cache;
   int persistent;
   int shared;
   int propagate;
-  int reset_res;
-  const char filename[16];
+  struct traced_file *traced_files;
   const char *db_filename;
   time_t file_mtime;
   size_t suggested_module;
@@ -146,6 +155,9 @@
 extern int nthreads;
 /* Maximum number of threads to use.  */
 extern int max_nthreads;
+
+/* Inotify descriptor.  */
+extern int inotify_fd;
 
 /* User name to run server processes as.  */
 extern const char *server_user;
@@ -191,6 +203,7 @@
 
 /* connections.c */
 extern void nscd_init (void);
+extern void register_traced_file (size_t dbidx, struct traced_file *finfo);
 extern void close_sockets (void);
 extern void start_threads (void) __attribute__ ((__noreturn__));
 

Modified: fsf/trunk/libc/nss/Makefile
==============================================================================
--- fsf/trunk/libc/nss/Makefile (original)
+++ fsf/trunk/libc/nss/Makefile Tue Jul 12 00:02:31 2011
@@ -66,14 +66,14 @@
 
 
 libnss_files-routines	:= $(addprefix files-,$(databases)) \
-			   files-initgroups files-have_o_cloexec
+			   files-initgroups files-have_o_cloexec files-init
 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
+libnss_db-routines	:= $(libnss_db-dbs) db-open db-init 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)

Modified: fsf/trunk/libc/nss/Versions
==============================================================================
--- fsf/trunk/libc/nss/Versions (original)
+++ fsf/trunk/libc/nss/Versions Tue Jul 12 00:02:31 2011
@@ -97,6 +97,8 @@
     _nss_files_getsecretkey;
 
     _nss_files_initgroups_dyn;
+
+    _nss_files_init;
   }
 }
 
@@ -153,5 +155,7 @@
     _nss_db_getspnam_r;
 
     _nss_db_initgroups_dyn;
+
+    _nss_db_init;
   }
 }

Added: fsf/trunk/libc/nss/nss_db/db-init.c
==============================================================================
--- fsf/trunk/libc/nss/nss_db/db-init.c (added)
+++ fsf/trunk/libc/nss/nss_db/db-init.c Tue Jul 12 00:02:31 2011
@@ -1,0 +1,54 @@
+/* Initialization in nss_db module.
+   Copyright (C) 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
+   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 <paths.h>
+#include <nscd/nscd.h>
+
+
+static union
+{
+  struct traced_file file;
+  char buf[sizeof (struct traced_file) + sizeof (_PATH_VARDB "passwd.db")];
+} pwd_traced_file;
+
+static union
+{
+  struct traced_file file;
+  char buf[sizeof (struct traced_file) + sizeof (_PATH_VARDB "group.db")];
+} grp_traced_file;
+
+static union
+{
+  struct traced_file file;
+  char buf[sizeof (struct traced_file) + sizeof (_PATH_VARDB "services.db")];
+} serv_traced_file;
+
+
+void
+_nss_db_init (void (*cb) (size_t, struct traced_file *))
+{
+  strcpy (pwd_traced_file.file.fname,_PATH_VARDB  "passwd.db");
+  cb (pwddb, &pwd_traced_file.file);
+
+  strcpy (grp_traced_file.file.fname, _PATH_VARDB "group.db");
+  cb (grpdb, &grp_traced_file.file);
+
+  strcpy (serv_traced_file.file.fname, _PATH_VARDB "services.db");
+  cb (servdb, &serv_traced_file.file);
+}

Added: fsf/trunk/libc/nss/nss_files/files-init.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-init.c (added)
+++ fsf/trunk/libc/nss/nss_files/files-init.c Tue Jul 12 00:02:31 2011
@@ -1,0 +1,72 @@
+/* Initialization in nss_files module.
+   Copyright (C) 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
+   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 <nscd/nscd.h>
+
+
+static union
+{
+  struct traced_file file;
+  char buf[sizeof (struct traced_file) + sizeof ("/etc/passwd")];
+} pwd_traced_file;
+
+static union
+{
+  struct traced_file file;
+  char buf[sizeof (struct traced_file) + sizeof ("/etc/group")];
+} grp_traced_file;
+
+static union
+{
+  struct traced_file file;
+  char buf[sizeof (struct traced_file) + sizeof ("/etc/hosts")];
+} hst_traced_file;
+
+static union
+{
+  struct traced_file file;
+  char buf[sizeof (struct traced_file) + sizeof ("/etc/resolv.conf")];
+} resolv_traced_file;
+
+static union
+{
+  struct traced_file file;
+  char buf[sizeof (struct traced_file) + sizeof ("/etc/services")];
+} serv_traced_file;
+
+
+void
+_nss_files_init (void (*cb) (size_t, struct traced_file *))
+{
+  strcpy (pwd_traced_file.file.fname, "/etc/passwd");
+  cb (pwddb, &pwd_traced_file.file);
+
+  strcpy (grp_traced_file.file.fname, "/etc/group");
+  cb (grpdb, &grp_traced_file.file);
+
+  strcpy (hst_traced_file.file.fname, "/etc/hosts");
+  cb (hstdb, &hst_traced_file.file);
+
+  resolv_traced_file.file.call_res_init = 1;
+  strcpy (resolv_traced_file.file.fname, "/etc/resolv.conf");
+  cb (hstdb, &resolv_traced_file.file);
+
+  strcpy (serv_traced_file.file.fname, "/etc/services");
+  cb (servdb, &serv_traced_file.file);
+}

Modified: fsf/trunk/libc/nss/nsswitch.c
==============================================================================
--- fsf/trunk/libc/nss/nsswitch.c (original)
+++ fsf/trunk/libc/nss/nsswitch.c Tue Jul 12 00:02:31 2011
@@ -1,4 +1,5 @@
-/* Copyright (C) 1996-1999,2001-2007,2009,2010 Free Software Foundation, Inc.
+/* Copyright (C) 1996-1999,2001-2007,2009,2010,2011
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 1996.
 
@@ -40,6 +41,7 @@
 
 #include "nsswitch.h"
 #include "../nscd/nscd_proto.h"
+#include <sysdep.h>
 
 /* Prototypes for the local functions.  */
 static name_database *nss_parse_file (const char *fname) internal_function;
@@ -86,6 +88,12 @@
 static name_database *service_table;
 
 
+/* Nonzero if this is the nscd process.  */
+static bool is_nscd;
+/* The callback passed to the init functions when nscd is used.  */
+static void (*nscd_init_cb) (size_t, struct traced_file *);
+
+
 /* -1 == database not found
     0 == database entry pointer stored */
 int
@@ -129,7 +137,7 @@
     }
 
   /* No configuration data is available, either because nsswitch.conf
-     doesn't exist or because it doesn't has a line for this database.
+     doesn't exist or because it doesn't have a line for this database.
 
      DEFCONFIG specifies the default service list for this database,
      or null to use the most common default.  */
@@ -283,6 +291,79 @@
   return p1 == p2 ? 0 : strcmp (*(const char *const *) p1,
 				*(const char *const *) p2);
 }
+
+
+#if !defined DO_STATIC_NSS || defined SHARED
+/* Load library.  */
+static int
+nss_load_library (service_user *ni)
+{
+  if (ni->library == NULL)
+    {
+      /* This service has not yet been used.  Fetch the service
+	 library for it, creating a new one if need be.  If there
+	 is no service table from the file, this static variable
+	 holds the head of the service_library list made from the
+	 default configuration.  */
+      static name_database default_table;
+      ni->library = nss_new_service (service_table ?: &default_table,
+				     ni->name);
+      if (ni->library == NULL)
+	return -1;
+    }
+
+  if (ni->library->lib_handle == NULL)
+    {
+      /* Load the shared library.  */
+      size_t shlen = (7 + strlen (ni->library->name) + 3
+		      + strlen (__nss_shlib_revision) + 1);
+      int saved_errno = errno;
+      char shlib_name[shlen];
+
+      /* Construct shared object name.  */
+      __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
+					      "libnss_"),
+				    ni->library->name),
+			  ".so"),
+		__nss_shlib_revision);
+
+      ni->library->lib_handle = __libc_dlopen (shlib_name);
+      if (ni->library->lib_handle == NULL)
+	{
+	  /* Failed to load the library.  */
+	  ni->library->lib_handle = (void *) -1l;
+	  __set_errno (saved_errno);
+	}
+      else if (is_nscd)
+	{
+	  /* Call the init function when nscd is used.  */
+	  size_t initlen = (5 + strlen (ni->library->name)
+			    + strlen ("_init") + 1);
+	  char init_name[initlen];
+
+	  /* Construct the init function name.  */
+	  __stpcpy (__stpcpy (__stpcpy (init_name,
+					"_nss_"),
+			      ni->library->name),
+		    "_init");
+
+	  /* Find the optional init function.  */
+	  void (*ifct) (void (*) (size_t, struct traced_file *))
+	    = __libc_dlsym (ni->library->lib_handle, init_name);
+	  if (ifct != NULL)
+	    {
+	      void (*cb) (size_t, struct traced_file *) = nscd_init_cb;
+# ifdef PTR_DEMANGLE
+	      PTR_DEMANGLE (cb);
+# endif
+	      ifct (cb);
+	    }
+	}
+    }
+
+  return 0;
+}
+#endif
 
 
 void *
@@ -331,47 +412,13 @@
 	  *found = known;
 	  known->fct_name = fct_name;
 
-	  if (ni->library == NULL)
+#if !defined DO_STATIC_NSS || defined SHARED
+	  /* Load the appropriate library.  */
+	  if (nss_load_library (ni) != 0)
 	    {
-	      /* This service has not yet been used.  Fetch the service
-		 library for it, creating a new one if need be.  If there
-		 is no service table from the file, this static variable
-		 holds the head of the service_library list made from the
-		 default configuration.  */
-	      static name_database default_table;
-	      ni->library = nss_new_service (service_table ?: &default_table,
-					     ni->name);
-	      if (ni->library == NULL)
-		{
-		  /* This only happens when out of memory.  */
-		  free (known);
-		  goto remove_from_tree;
-		}
-	    }
-
-#if !defined DO_STATIC_NSS || defined SHARED
-	  if (ni->library->lib_handle == NULL)
-	    {
-	      /* Load the shared library.  */
-	      size_t shlen = (7 + strlen (ni->library->name) + 3
-			      + strlen (__nss_shlib_revision) + 1);
-	      int saved_errno = errno;
-	      char shlib_name[shlen];
-
-	      /* Construct shared object name.  */
-	      __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
-						      "libnss_"),
-					    ni->library->name),
-				  ".so"),
-			__nss_shlib_revision);
-
-	      ni->library->lib_handle = __libc_dlopen (shlib_name);
-	      if (ni->library->lib_handle == NULL)
-		{
-		  /* Failed to load the library.  */
-		  ni->library->lib_handle = (void *) -1l;
-		  __set_errno (saved_errno);
-		}
+	      /* This only happens when out of memory.  */
+	      free (known);
+	      goto remove_from_tree;
 	    }
 
 	  if (ni->library->lib_handle == (void *) -1l)
@@ -463,7 +510,10 @@
 
   result = (name_database *) malloc (sizeof (name_database));
   if (result == NULL)
-    return NULL;
+    {
+      fclose (fp);
+      return NULL;
+    }
 
   result->entry = NULL;
   result->library = NULL;
@@ -724,16 +774,45 @@
 }
 
 
+#ifdef SHARED
+/* Load all libraries for the service.  */
+static void
+nss_load_all_libraries (const char *service, const char *def)
+{
+  service_user *ni = NULL;
+
+  if (__nss_database_lookup (service, NULL, def, &ni) == 0)
+    while (ni != NULL)
+      {
+	nss_load_library (ni);
+	ni = ni->next;
+      }
+}
+
+
 /* Called by nscd and nscd alone.  */
 void
-__nss_disable_nscd (void)
-{
+__nss_disable_nscd (void (*cb) (size_t, struct traced_file *))
+{
+# ifdef PTR_MANGLE
+  PTR_MANGLE (cb);
+# endif
+  nscd_init_cb = cb;
+  is_nscd = true;
+
+  /* Find all the relevant modules so that the init functions are called.  */
+  nss_load_all_libraries ("passwd", "compat [NOTFOUND=return] files");
+  nss_load_all_libraries ("group", "compat [NOTFOUND=return] files");
+  nss_load_all_libraries ("hosts", "dns [!UNAVAIL=return] files");
+  nss_load_all_libraries ("services", NULL);
+
   /* Disable all uses of NSCD.  */
   __nss_not_use_nscd_passwd = -1;
   __nss_not_use_nscd_group = -1;
   __nss_not_use_nscd_hosts = -1;
   __nss_not_use_nscd_services = -1;
 }
+#endif
 
 
 /* Free all resources if necessary.  */

Modified: fsf/trunk/libc/nss/nsswitch.h
==============================================================================
--- fsf/trunk/libc/nss/nsswitch.h (original)
+++ fsf/trunk/libc/nss/nsswitch.h Tue Jul 12 00:02:31 2011
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-1999,2001,2002,2003,2004,2007,2010
+/* Copyright (C) 1996-1999,2001,2002,2003,2004,2007,2010,2011
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -153,8 +153,10 @@
 libc_hidden_proto (__nss_lookup_function)
 
 
-/* Called by NSCD to disable recursive calls.  */
-extern void __nss_disable_nscd (void);
+/* Called by NSCD to disable recursive calls and enable special handling
+   when used in nscd.  */
+struct traced_file;
+extern void __nss_disable_nscd (void (*) (size_t, struct traced_file *));
 
 
 typedef int (*db_lookup_function) (service_user **, const char *, const char *,

Modified: fsf/trunk/libc/sysdeps/unix/sysv/linux/Makefile
==============================================================================
--- fsf/trunk/libc/sysdeps/unix/sysv/linux/Makefile (original)
+++ fsf/trunk/libc/sysdeps/unix/sysv/linux/Makefile Tue Jul 12 00:02:31 2011
@@ -161,12 +161,6 @@
 endif
 
 ifeq ($(subdir),nscd)
-CFLAGS-connections.c += -DHAVE_EPOLL -DHAVE_SENDFILE -DHAVE_INOTIFY
-CFLAGS-pwdcache.c += -DHAVE_SENDFILE
-CFLAGS-grpcache.c += -DHAVE_SENDFILE
-CFLAGS-hstcache.c += -DHAVE_SENDFILE
-CFLAGS-aicache.c += -DHAVE_SENDFILE
-CFLAGS-initgrcache.c += -DHAVE_SENDFILE
-CFLAGS-servicescache.c += -DHAVE_SENDFILE
+sysdep-CFLAGS += -DHAVE_EPOLL -DHAVE_SENDFILE -DHAVE_INOTIFY
 CFLAGS-gai.c += -DNEED_NETLINK
 endif