1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

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.
This commit is contained in:
Ulrich Drepper
2011-07-11 14:50:24 -04:00
parent 23bee3e867
commit 319b9ad4bc
12 changed files with 446 additions and 159 deletions

View File

@ -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> 2011-07-10 Roland McGrath <roland@hack.frob.com>
* csu/elf-init.c (__libc_csu_init): Comment typo. * csu/elf-init.c (__libc_csu_init): Comment typo.

View File

@ -264,17 +264,25 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
/* If we check for the modification of the underlying file we invalidate /* If we check for the modification of the underlying file we invalidate
the entries also in this case. */ 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 traced_file *runp = table->traced_files;
while (runp != NULL)
{
#ifdef HAVE_INOTIFY
if (runp->inotify_descr == -1)
#endif
{ {
struct stat64 st; struct stat64 st;
if (stat64 (table->filename, &st) < 0) if (stat64 (runp->fname, &st) < 0)
{ {
char buf[128]; char buf[128];
/* We cannot stat() the file, disable file checking if the /* We cannot stat() the file, disable file checking if the
file does not exist. */ file does not exist. */
dbg_log (_("cannot stat() file `%s': %s"), dbg_log (_("cannot stat() file `%s': %s"),
table->filename, strerror_r (errno, buf, sizeof (buf))); runp->fname, strerror_r (errno, buf, sizeof (buf)));
if (errno == ENOENT) if (errno == ENOENT)
table->check_file = 0; table->check_file = 0;
} }
@ -289,6 +297,10 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
} }
} }
runp = runp->next;
}
}
/* We run through the table and find values which are not valid anymore. /* We run through the table and find values which are not valid anymore.
Note that for the initial step, finding the entries to be removed, Note that for the initial step, finding the entries to be removed,

View File

@ -117,8 +117,6 @@ struct database_dyn dbs[lastdb] =
.shared = 0, .shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE, .max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE, .suggested_module = DEFAULT_SUGGESTED_MODULE,
.reset_res = 0,
.filename = "/etc/passwd",
.db_filename = _PATH_NSCD_PASSWD_DB, .db_filename = _PATH_NSCD_PASSWD_DB,
.disabled_iov = &pwd_iov_disabled, .disabled_iov = &pwd_iov_disabled,
.postimeout = 3600, .postimeout = 3600,
@ -138,8 +136,6 @@ struct database_dyn dbs[lastdb] =
.shared = 0, .shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE, .max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE, .suggested_module = DEFAULT_SUGGESTED_MODULE,
.reset_res = 0,
.filename = "/etc/group",
.db_filename = _PATH_NSCD_GROUP_DB, .db_filename = _PATH_NSCD_GROUP_DB,
.disabled_iov = &grp_iov_disabled, .disabled_iov = &grp_iov_disabled,
.postimeout = 3600, .postimeout = 3600,
@ -159,8 +155,6 @@ struct database_dyn dbs[lastdb] =
.shared = 0, .shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE, .max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE, .suggested_module = DEFAULT_SUGGESTED_MODULE,
.reset_res = 1,
.filename = "/etc/hosts",
.db_filename = _PATH_NSCD_HOSTS_DB, .db_filename = _PATH_NSCD_HOSTS_DB,
.disabled_iov = &hst_iov_disabled, .disabled_iov = &hst_iov_disabled,
.postimeout = 3600, .postimeout = 3600,
@ -180,8 +174,6 @@ struct database_dyn dbs[lastdb] =
.shared = 0, .shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE, .max_db_size = DEFAULT_MAX_DB_SIZE,
.suggested_module = DEFAULT_SUGGESTED_MODULE, .suggested_module = DEFAULT_SUGGESTED_MODULE,
.reset_res = 0,
.filename = "/etc/services",
.db_filename = _PATH_NSCD_SERVICES_DB, .db_filename = _PATH_NSCD_SERVICES_DB,
.disabled_iov = &serv_iov_disabled, .disabled_iov = &serv_iov_disabled,
.postimeout = 28800, .postimeout = 28800,
@ -232,10 +224,7 @@ static int sock;
#ifdef HAVE_INOTIFY #ifdef HAVE_INOTIFY
/* Inotify descriptor. */ /* Inotify descriptor. */
static int inotify_fd = -1; int inotify_fd = -1;
/* Watch descriptor for resolver configuration file. */
static int resolv_conf_descr = -1;
#endif #endif
#ifndef __ASSUME_SOCK_CLOEXEC #ifndef __ASSUME_SOCK_CLOEXEC
@ -523,19 +512,6 @@ nscd_init (void)
/* No configuration for this value, assume a default. */ /* No configuration for this value, assume a default. */
nthreads = 4; 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) for (size_t cnt = 0; cnt < lastdb; ++cnt)
if (dbs[cnt].enabled) if (dbs[cnt].enabled)
{ {
@ -840,40 +816,6 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
dbs[cnt].shared = 0; dbs[cnt].shared = 0;
assert (dbs[cnt].ro_fd == -1); 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. */ /* Create the socket. */
@ -940,12 +882,50 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
exit (1); 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) if (server_user != NULL)
finish_drop_privileges (); 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. */ /* Close the connections. */
void void
close_sockets (void) close_sockets (void)
@ -963,9 +943,18 @@ invalidate_cache (char *key, int fd)
for (number = pwddb; number < lastdb; ++number) for (number = pwddb; number < lastdb; ++number)
if (strcmp (key, dbnames[number]) == 0) if (strcmp (key, dbnames[number]) == 0)
{ {
if (dbs[number].reset_res) if (number == hstdb)
{
struct traced_file *runp = dbs[hstdb].traced_files;
while (runp != NULL)
if (runp->call_res_init)
{
res_init (); res_init ();
break;
}
else
runp = runp->next;
}
break; break;
} }
@ -1913,16 +1902,21 @@ disabled inotify after read error %d"),
/* Check which of the files changed. */ /* Check which of the files changed. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt) for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
if (inev.i.wd == dbs[dbcnt].inotify_descr) {
struct traced_file *finfo = dbs[dbcnt].traced_files;
while (finfo != NULL)
{
if (finfo->inotify_descr == inev.i.wd)
{ {
to_clear[dbcnt] = true; to_clear[dbcnt] = true;
if (finfo->call_res_init)
res_init ();
goto next; goto next;
} }
if (inev.i.wd == resolv_conf_descr) finfo = finfo->next;
{ }
res_init ();
to_clear[hstdb] = true;
} }
next:; next:;
} }
@ -2108,16 +2102,21 @@ main_loop_epoll (int efd)
/* Check which of the files changed. */ /* Check which of the files changed. */
for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt) for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
if (inev.i.wd == dbs[dbcnt].inotify_descr) {
struct traced_file *finfo = dbs[dbcnt].traced_files;
while (finfo != NULL)
{
if (finfo->inotify_descr == inev.i.wd)
{ {
to_clear[dbcnt] = true; to_clear[dbcnt] = true;
if (finfo->call_res_init)
res_init ();
goto next; goto next;
} }
if (inev.i.wd == resolv_conf_descr) finfo = finfo->next;
{ }
res_init ();
to_clear[hstdb] = true;
} }
next:; next:;
} }

View File

@ -46,6 +46,9 @@
#include "selinux.h" #include "selinux.h"
#include "../nss/nsswitch.h" #include "../nss/nsswitch.h"
#include <device-nrs.h> #include <device-nrs.h>
#ifdef HAVE_INOTIFY
# include <sys/inotify.h>
#endif
/* Get libc version number. */ /* Get libc version number. */
#include <version.h> #include <version.h>
@ -272,8 +275,21 @@ main (int argc, char **argv)
/* Cleanup files created by a previous 'bind'. */ /* Cleanup files created by a previous 'bind'. */
unlink (_PATH_NSCDSOCKET); 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. */ /* Make sure we do not get recursive calls. */
__nss_disable_nscd (); __nss_disable_nscd (register_traced_file);
/* Init databases. */ /* Init databases. */
nscd_init (); nscd_init ();

View File

@ -62,6 +62,17 @@ typedef enum
#define MAX_STACK_USE ((8 * NSCD_THREAD_STACKSIZE) / 10) #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. */ /* Structure describing dynamic part of one database. */
struct database_dyn struct database_dyn
{ {
@ -73,13 +84,11 @@ struct database_dyn
int enabled; int enabled;
int check_file; int check_file;
int inotify_descr;
int clear_cache; int clear_cache;
int persistent; int persistent;
int shared; int shared;
int propagate; int propagate;
int reset_res; struct traced_file *traced_files;
const char filename[16];
const char *db_filename; const char *db_filename;
time_t file_mtime; time_t file_mtime;
size_t suggested_module; size_t suggested_module;
@ -147,6 +156,9 @@ extern int nthreads;
/* Maximum number of threads to use. */ /* Maximum number of threads to use. */
extern int max_nthreads; extern int max_nthreads;
/* Inotify descriptor. */
extern int inotify_fd;
/* User name to run server processes as. */ /* User name to run server processes as. */
extern const char *server_user; extern const char *server_user;
@ -191,6 +203,7 @@ extern int nscd_open_socket (void);
/* connections.c */ /* connections.c */
extern void nscd_init (void); extern void nscd_init (void);
extern void register_traced_file (size_t dbidx, struct traced_file *finfo);
extern void close_sockets (void); extern void close_sockets (void);
extern void start_threads (void) __attribute__ ((__noreturn__)); extern void start_threads (void) __attribute__ ((__noreturn__));

View File

@ -66,14 +66,14 @@ vpath %.c $(subdir-dirs) ../locale/programs ../intl
libnss_files-routines := $(addprefix files-,$(databases)) \ 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 distribute += files-XXX.c files-parse.c
libnss_db-dbs := $(addprefix db-,\ libnss_db-dbs := $(addprefix db-,\
$(filter-out hosts network key alias,\ $(filter-out hosts network key alias,\
$(databases))) \ $(databases))) \
db-initgroups 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, \ generated += $(filter-out db-alias.c db-netgrp.c, \
$(addsuffix .c,$(libnss_db-dbs))) $(addsuffix .c,$(libnss_db-dbs)))
distribute += $(addprefix nss_db/, db-XXX.c nss_db.h) distribute += $(addprefix nss_db/, db-XXX.c nss_db.h)

View File

@ -97,6 +97,8 @@ libnss_files {
_nss_files_getsecretkey; _nss_files_getsecretkey;
_nss_files_initgroups_dyn; _nss_files_initgroups_dyn;
_nss_files_init;
} }
} }
@ -153,5 +155,7 @@ libnss_db {
_nss_db_getspnam_r; _nss_db_getspnam_r;
_nss_db_initgroups_dyn; _nss_db_initgroups_dyn;
_nss_db_init;
} }
} }

54
nss/nss_db/db-init.c Normal file
View File

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

View File

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

View File

@ -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. This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -40,6 +41,7 @@
#include "nsswitch.h" #include "nsswitch.h"
#include "../nscd/nscd_proto.h" #include "../nscd/nscd_proto.h"
#include <sysdep.h>
/* Prototypes for the local functions. */ /* Prototypes for the local functions. */
static name_database *nss_parse_file (const char *fname) internal_function; 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; 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 /* -1 == database not found
0 == database entry pointer stored */ 0 == database entry pointer stored */
int int
@ -129,7 +137,7 @@ __nss_database_lookup (const char *database, const char *alternate_name,
} }
/* No configuration data is available, either because nsswitch.conf /* 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, DEFCONFIG specifies the default service list for this database,
or null to use the most common default. */ 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 * void *
__nss_lookup_function (service_user *ni, const char *fct_name) __nss_lookup_function (service_user *ni, const char *fct_name)
{ {
@ -331,48 +412,14 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
*found = known; *found = known;
known->fct_name = fct_name; known->fct_name = fct_name;
if (ni->library == NULL) #if !defined DO_STATIC_NSS || defined SHARED
{ /* Load the appropriate library. */
/* This service has not yet been used. Fetch the service if (nss_load_library (ni) != 0)
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. */ /* This only happens when out of memory. */
free (known); free (known);
goto remove_from_tree; 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);
}
}
if (ni->library->lib_handle == (void *) -1l) if (ni->library->lib_handle == (void *) -1l)
/* Library not found => function not found. */ /* Library not found => function not found. */
@ -463,7 +510,10 @@ nss_parse_file (const char *fname)
result = (name_database *) malloc (sizeof (name_database)); result = (name_database *) malloc (sizeof (name_database));
if (result == NULL) if (result == NULL)
{
fclose (fp);
return NULL; return NULL;
}
result->entry = NULL; result->entry = NULL;
result->library = 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. */ /* Called by nscd and nscd alone. */
void 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. */ /* Disable all uses of NSCD. */
__nss_not_use_nscd_passwd = -1; __nss_not_use_nscd_passwd = -1;
__nss_not_use_nscd_group = -1; __nss_not_use_nscd_group = -1;
__nss_not_use_nscd_hosts = -1; __nss_not_use_nscd_hosts = -1;
__nss_not_use_nscd_services = -1; __nss_not_use_nscd_services = -1;
} }
#endif
/* Free all resources if necessary. */ /* Free all resources if necessary. */

View File

@ -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. Free Software Foundation, Inc.
This file is part of the GNU C Library. 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) libc_hidden_proto (__nss_lookup_function)
/* Called by NSCD to disable recursive calls. */ /* Called by NSCD to disable recursive calls and enable special handling
extern void __nss_disable_nscd (void); 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 *, typedef int (*db_lookup_function) (service_user **, const char *, const char *,

View File

@ -161,12 +161,6 @@ CFLAGS-mq_receive.c += -fexceptions
endif endif
ifeq ($(subdir),nscd) ifeq ($(subdir),nscd)
CFLAGS-connections.c += -DHAVE_EPOLL -DHAVE_SENDFILE -DHAVE_INOTIFY sysdep-CFLAGS += -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
CFLAGS-gai.c += -DNEED_NETLINK CFLAGS-gai.c += -DNEED_NETLINK
endif endif