mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-28 00:21:52 +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:
42
ChangeLog
42
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>
|
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.
|
||||||
|
46
nscd/cache.c
46
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
|
/* 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 stat64 st;
|
struct traced_file *runp = table->traced_files;
|
||||||
|
|
||||||
if (stat64 (table->filename, &st) < 0)
|
while (runp != NULL)
|
||||||
{
|
{
|
||||||
char buf[128];
|
#ifdef HAVE_INOTIFY
|
||||||
/* We cannot stat() the file, disable file checking if the
|
if (runp->inotify_descr == -1)
|
||||||
file does not exist. */
|
#endif
|
||||||
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. */
|
struct stat64 st;
|
||||||
now = LONG_MAX;
|
|
||||||
table->file_mtime = st.st_mtime;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,11 +943,20 @@ 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)
|
||||||
res_init ();
|
{
|
||||||
|
struct traced_file *runp = dbs[hstdb].traced_files;
|
||||||
|
while (runp != NULL)
|
||||||
|
if (runp->call_res_init)
|
||||||
|
{
|
||||||
|
res_init ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
runp = runp->next;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (number == lastdb)
|
if (number == lastdb)
|
||||||
{
|
{
|
||||||
@ -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)
|
|
||||||
{
|
|
||||||
to_clear[dbcnt] = true;
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inev.i.wd == resolv_conf_descr)
|
|
||||||
{
|
{
|
||||||
res_init ();
|
struct traced_file *finfo = dbs[dbcnt].traced_files;
|
||||||
to_clear[hstdb] = true;
|
|
||||||
|
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:;
|
next:;
|
||||||
}
|
}
|
||||||
@ -2089,7 +2083,7 @@ main_loop_epoll (int efd)
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
|
ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
|
||||||
sizeof (inev)));
|
sizeof (inev)));
|
||||||
if (nb < (ssize_t) sizeof (struct inotify_event))
|
if (nb < (ssize_t) sizeof (struct inotify_event))
|
||||||
{
|
{
|
||||||
if (__builtin_expect (nb == -1 && errno != EAGAIN, 0))
|
if (__builtin_expect (nb == -1 && errno != EAGAIN, 0))
|
||||||
@ -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)
|
|
||||||
{
|
|
||||||
to_clear[dbcnt] = true;
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inev.i.wd == resolv_conf_descr)
|
|
||||||
{
|
{
|
||||||
res_init ();
|
struct traced_file *finfo = dbs[dbcnt].traced_files;
|
||||||
to_clear[hstdb] = true;
|
|
||||||
|
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:;
|
next:;
|
||||||
}
|
}
|
||||||
|
18
nscd/nscd.c
18
nscd/nscd.c
@ -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 ();
|
||||||
|
19
nscd/nscd.h
19
nscd/nscd.h
@ -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__));
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
54
nss/nss_db/db-init.c
Normal 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);
|
||||||
|
}
|
72
nss/nss_files/files-init.c
Normal file
72
nss/nss_files/files-init.c
Normal 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);
|
||||||
|
}
|
165
nss/nsswitch.c
165
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.
|
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,47 +412,13 @@ __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)
|
|
||||||
{
|
|
||||||
/* 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 !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. */
|
/* This only happens when out of memory. */
|
||||||
size_t shlen = (7 + strlen (ni->library->name) + 3
|
free (known);
|
||||||
+ strlen (__nss_shlib_revision) + 1);
|
goto remove_from_tree;
|
||||||
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)
|
||||||
@ -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)
|
||||||
return NULL;
|
{
|
||||||
|
fclose (fp);
|
||||||
|
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. */
|
||||||
|
@ -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 *,
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user