This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch, master, updated. glibc-2.14-100-g319b9ad


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  319b9ad4bccedb2a6b1a222cf446e873b2bc6de1 (commit)
      from  23bee3e8677c9357662ce789ed77fe25f3991c66 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=319b9ad4bccedb2a6b1a222cf446e873b2bc6de1

commit 319b9ad4bccedb2a6b1a222cf446e873b2bc6de1
Author: Ulrich Drepper <drepper@gmail.com>
Date:   Mon Jul 11 14:50:24 2011 -0400

    Generalize framework to register monitoring of files in nscd
    
    nscd can clear caches when certain files change.  The list of files
    was hardcoded so far and worked for nss_files and nss_dns and those
    modules which need no monitoring.  nss_db, for instance, has its
    own set of files to monitor.  Now the NSS modules themselves can
    request that certain files are monitored.

diff --git a/ChangeLog b/ChangeLog
index 953e879..31902a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2011-07-11  Ulrich Drepper  <drepper@gmail.com>
+
+	* 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@hack.frob.com>
 
 	* csu/elf-init.c (__libc_csu_init): Comment typo.
diff --git a/nscd/cache.c b/nscd/cache.c
index ebc6e4c..58f0bcc 100644
--- a/nscd/cache.c
+++ b/nscd/cache.c
@@ -264,28 +264,40 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
 
   /* 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)
+  if (table->check_file && now != LONG_MAX)
     {
-      struct stat64 st;
+      struct traced_file *runp = table->traced_files;
 
-      if (stat64 (table->filename, &st) < 0)
+      while (runp != NULL)
 	{
-	  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)
+#ifdef HAVE_INOTIFY
+	  if (runp->inotify_descr == -1)
+#endif
 	    {
-	      /* The file changed.  Invalidate all entries.  */
-	      now = LONG_MAX;
-	      table->file_mtime = st.st_mtime;
+	      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;
 	}
     }
 
diff --git a/nscd/connections.c b/nscd/connections.c
index 1e47931..6e48869 100644
--- a/nscd/connections.c
+++ b/nscd/connections.c
@@ -117,8 +117,6 @@ struct database_dyn dbs[lastdb] =
     .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 @@ struct database_dyn dbs[lastdb] =
     .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 @@ struct database_dyn dbs[lastdb] =
     .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 @@ struct database_dyn dbs[lastdb] =
     .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 @@ static int sock;
 
 #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
@@ -523,19 +512,6 @@ nscd_init (void)
     /* 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 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
 	    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 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
       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 @@ invalidate_cache (char *key, int fd)
   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 @@ disabled inotify after read error %d"),
 
 		      /* 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 @@ main_loop_epoll (int efd)
 	    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 @@ main_loop_epoll (int efd)
 
 		/* 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:;
 	      }
diff --git a/nscd/nscd.c b/nscd/nscd.c
index c3d9fe6..4894cb2 100644
--- a/nscd/nscd.c
+++ b/nscd/nscd.c
@@ -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 @@ main (int argc, char **argv)
   /* 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 ();
diff --git a/nscd/nscd.h b/nscd/nscd.h
index 5e3c865..c15e88b 100644
--- a/nscd/nscd.h
+++ b/nscd/nscd.h
@@ -62,6 +62,17 @@ typedef enum
 #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 @@ struct database_dyn
 
   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;
@@ -147,6 +156,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 @@ extern int nscd_open_socket (void);
 
 /* 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__));
 
diff --git a/nss/Makefile b/nss/Makefile
index 60c6549..fb64283 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -66,14 +66,14 @@ vpath %.c $(subdir-dirs) ../locale/programs ../intl
 
 
 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)
diff --git a/nss/Versions b/nss/Versions
index 9137512..666915d 100644
--- a/nss/Versions
+++ b/nss/Versions
@@ -97,6 +97,8 @@ libnss_files {
     _nss_files_getsecretkey;
 
     _nss_files_initgroups_dyn;
+
+    _nss_files_init;
   }
 }
 
@@ -153,5 +155,7 @@ libnss_db {
     _nss_db_getspnam_r;
 
     _nss_db_initgroups_dyn;
+
+    _nss_db_init;
   }
 }
diff --git a/nss/nss_db/db-init.c b/nss/nss_db/db-init.c
new file mode 100644
index 0000000..8228d61
--- /dev/null
+++ b/nss/nss_db/db-init.c
@@ -0,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);
+}
diff --git a/nss/nss_files/files-init.c b/nss/nss_files/files-init.c
new file mode 100644
index 0000000..cc6822d
--- /dev/null
+++ b/nss/nss_files/files-init.c
@@ -0,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);
+}
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index 92e6f5f..6c15c3a 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -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@cygnus.com>, 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 const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15;
 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 @@ __nss_database_lookup (const char *database, const char *alternate_name,
     }
 
   /* 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.  */
@@ -285,6 +293,79 @@ known_compare (const void *p1, const void *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 *
 __nss_lookup_function (service_user *ni, const char *fct_name)
 {
@@ -331,47 +412,13 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
 	  *found = known;
 	  known->fct_name = fct_name;
 
-	  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)
-		{
-		  /* 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 appropriate library.  */
+	  if (nss_load_library (ni) != 0)
 	    {
-	      /* 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 @@ nss_parse_file (const char *fname)
 
   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 @@ nss_new_service (name_database *database, const char *name)
 }
 
 
+#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.  */
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
index ae5657e..3e37bc8 100644
--- a/nss/nsswitch.h
+++ b/nss/nsswitch.h
@@ -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 @@ extern void *__nss_lookup_function (service_user *ni, const char *fct_name);
 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 *,
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index f626a22..63ef597 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -161,12 +161,6 @@ CFLAGS-mq_receive.c += -fexceptions
 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

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                        |   42 ++++++++++
 nscd/cache.c                     |   46 +++++++----
 nscd/connections.c               |  165 +++++++++++++++++++-------------------
 nscd/nscd.c                      |   18 ++++-
 nscd/nscd.h                      |   19 ++++-
 nss/Makefile                     |    4 +-
 nss/Versions                     |    4 +
 nss/nss_db/db-init.c             |   54 ++++++++++++
 nss/nss_files/files-init.c       |   72 +++++++++++++++++
 nss/nsswitch.c                   |  165 ++++++++++++++++++++++++++++----------
 nss/nsswitch.h                   |    8 +-
 sysdeps/unix/sysv/linux/Makefile |    8 +--
 12 files changed, 446 insertions(+), 159 deletions(-)
 create mode 100644 nss/nss_db/db-init.c
 create mode 100644 nss/nss_files/files-init.c


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]