diff options
-rw-r--r-- | ChangeLog | 24 | ||||
-rw-r--r-- | NEWS | 12 | ||||
-rw-r--r-- | nscd/cache.c | 28 | ||||
-rw-r--r-- | nscd/connections.c | 358 | ||||
-rw-r--r-- | nscd/nscd.h | 60 | ||||
-rw-r--r-- | nss/nss_db/db-init.c | 28 | ||||
-rw-r--r-- | nss/nss_files/files-init.c | 46 |
7 files changed, 398 insertions, 158 deletions
diff --git a/ChangeLog b/ChangeLog index d6526e9862..f5545b1c1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2015-03-13 Carlos O'Donell <carlos@redhat.com> + + [BZ #14906] + * nscd/cache.c (prune_cache): Use TRACED_FILE. Compare and update + traced file mtime. Use consistent log message. + * nscd/connections.c [HAVE_INOTIFY] (install_watches): New function. + (register_traced_file): Call install_watches. Always set mtime. + (invalidate_cache): Iterate over all trace files. Call install_watches. + (inotify_check_files): Don't inline. Handle watching parent + directories and configuration file movement in and out. + (handle_inotify_events): New function. + (main_loop_poll): Call handle_inotify_events. + (main_loop_epoll): Likewise. + * nscd/nscd.h: Define TRACED_FILE, TRACED_DIR, and PATH_MAX. + (struct traced_file): Use array of inotify fds. Add parent directory, + and basename. + (struct database_dyn): Remove unused file_mtime. + (init_traced_file): New inline function. + (define_traced_file): New macro. + * nss/nss_db/db-init.c: Use define_traced_file. + (_nss_db_init): Use init_traced_file. + * nss/nss_files/files-init.c: Use define_traced_file. + (_nss_files_init): Use init_traced_file. + 2015-03-12 Joseph Myers <joseph@codesourcery.com> * soft-fp/soft-fp.h (_FP_STATIC_ASSERT): New macro. diff --git a/NEWS b/NEWS index 88bfc44a33..4e0024bd1a 100644 --- a/NEWS +++ b/NEWS @@ -9,12 +9,12 @@ Version 2.22 * The following bugs are resolved with this release: - 4719, 13064, 14094, 14841, 15319, 15467, 15790, 15969, 16351, 16512, - 16560, 16783, 17269, 17523, 17569, 17588, 17631, 17711, 17776, 17779, - 17792, 17836, 17912, 17916, 17932, 17944, 17949, 17964, 17965, 17967, - 17969, 17978, 17987, 17991, 17996, 17998, 17999, 18019, 18020, 18029, - 18030, 18032, 18036, 18038, 18039, 18042, 18043, 18046, 18047, 18068, - 18080, 18093, 18104, 18110, 18111. + 4719, 13064, 14094, 14841, 14906, 15319, 15467, 15790, 15969, 16351, + 16512, 16560, 16783, 17269, 17523, 17569, 17588, 17631, 17711, 17776, + 17779, 17792, 17836, 17912, 17916, 17932, 17944, 17949, 17964, 17965, + 17967, 17969, 17978, 17987, 17991, 17996, 17998, 17999, 18019, 18020, + 18029, 18030, 18032, 18036, 18038, 18039, 18042, 18043, 18046, 18047, + 18068, 18080, 18093, 18104, 18110, 18111. * Character encoding and ctype tables were updated to Unicode 7.0.0, using new generator scripts contributed by Pravin Satpute and Mike FABIAN (Red diff --git a/nscd/cache.c b/nscd/cache.c index ea9f72311b..f0200c303c 100644 --- a/nscd/cache.c +++ b/nscd/cache.c @@ -272,28 +272,38 @@ prune_cache (struct database_dyn *table, time_t now, int fd) while (runp != NULL) { #ifdef HAVE_INOTIFY - if (runp->inotify_descr == -1) + if (runp->inotify_descr[TRACED_FILE] == -1) #endif { struct stat64 st; if (stat64 (runp->fname, &st) < 0) { + /* Print a diagnostic that the traced file was missing. + We must not disable tracing since the file might return + shortly and we want to reload it at the next pruning. + Disabling tracing here would go against the configuration + as specified by the user via check-files. */ char buf[128]; - /* We cannot stat() the file, disable file checking if the - file does not exist. */ - dbg_log (_("cannot stat() file `%s': %s"), + dbg_log (_("checking for monitored 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) + /* This must be `!=` to catch cases where users turn the + clocks back and we still want to detect any time difference + in mtime. */ + if (st.st_mtime != runp->mtime) { - /* The file changed. Invalidate all entries. */ + dbg_log (_("monitored file `%s` changed (mtime)"), + runp->fname); + /* The file changed. Invalidate all entries. */ now = LONG_MAX; - table->file_mtime = st.st_mtime; + runp->mtime = st.st_mtime; +#ifdef HAVE_INOTIFY + /* Attempt to install a watch on the file. */ + install_watches (runp); +#endif } } } diff --git a/nscd/connections.c b/nscd/connections.c index 985eab6a30..cba5e6ad9d 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -957,6 +957,44 @@ cannot change socket to nonblocking mode: %s"), finish_drop_privileges (); } +#ifdef HAVE_INOTIFY +#define TRACED_FILE_MASK (IN_DELETE_SELF | IN_CLOSE_WRITE | IN_MOVE_SELF) +#define TRACED_DIR_MASK (IN_DELETE_SELF | IN_CREATE | IN_MOVED_TO | IN_MOVE_SELF) +void +install_watches (struct traced_file *finfo) +{ + /* Use inotify support if we have it. */ + if (finfo->inotify_descr[TRACED_FILE] < 0) + finfo->inotify_descr[TRACED_FILE] = inotify_add_watch (inotify_fd, + finfo->fname, + TRACED_FILE_MASK); + if (finfo->inotify_descr[TRACED_FILE] < 0) + { + dbg_log (_("disabled inotify-based monitoring for file `%s': %s"), + finfo->fname, strerror (errno)); + return; + } + dbg_log (_("monitoring file `%s` (%d)"), + finfo->fname, finfo->inotify_descr[TRACED_FILE]); + /* Additionally listen for events in the file's parent directory. + We do this because the file to be watched might be + deleted and then added back again. When it is added back again + we must re-add the watch. We must also cover IN_MOVED_TO to + detect a file being moved into the directory. */ + if (finfo->inotify_descr[TRACED_DIR] < 0) + finfo->inotify_descr[TRACED_DIR] = inotify_add_watch (inotify_fd, + finfo->dname, + TRACED_DIR_MASK); + if (finfo->inotify_descr[TRACED_DIR] < 0) + { + dbg_log (_("disabled inotify-based monitoring for directory `%s': %s"), + finfo->fname, strerror (errno)); + return; + } + dbg_log (_("monitoring directory `%s` (%d)"), + finfo->dname, finfo->inotify_descr[TRACED_DIR]); +} +#endif /* Register the file in FINFO as a traced file for the database DBS[DBIX]. @@ -981,30 +1019,22 @@ register_traced_file (size_t dbidx, struct traced_file *finfo) return; if (__glibc_unlikely (debug_level > 0)) - dbg_log (_("register trace file %s for database %s"), + dbg_log (_("monitoring 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) + install_watches (finfo); #endif + struct stat64 st; + if (stat64 (finfo->fname, &st) < 0) { - /* 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; + /* We cannot stat() the file. Set mtime to zero and try again later. */ + dbg_log (_("stat failed for file `%s'; will try again later: %s"), + finfo->fname, strerror (errno)); + finfo->mtime = 0; } + else + finfo->mtime = st.st_mtime; /* Queue up the file name. */ finfo->next = dbs[dbidx].traced_files; @@ -1029,20 +1059,27 @@ invalidate_cache (char *key, int fd) for (number = pwddb; number < lastdb; ++number) if (strcmp (key, dbnames[number]) == 0) { - if (number == hstdb) + struct traced_file *runp = dbs[number].traced_files; + while (runp != NULL) { - struct traced_file *runp = dbs[hstdb].traced_files; - while (runp != NULL) - if (runp->call_res_init) - { - res_init (); - break; - } - else - runp = runp->next; + /* Make sure we reload from file when checking mtime. */ + runp->mtime = 0; +#ifdef HAVE_INOTIFY + /* During an invalidation we try to reload the traced + file watches. This allows the user to re-sync if + inotify events were lost. Similar to what we do during + pruning. */ + install_watches (runp); +#endif + if (runp->call_res_init) + { + res_init (); + break; + } + runp = runp->next; } break; - } + } if (number == lastdb) { @@ -1880,11 +1917,28 @@ union __inev char buf[sizeof (struct inotify_event) + PATH_MAX]; }; +/* Returns 0 if the file is there otherwise -1. */ +int +check_file (struct traced_file *finfo) +{ + struct stat64 st; + /* We could check mtime and if different re-add + the watches, and invalidate the database, but we + don't because we are called from inotify_check_files + which should be doing that work. If sufficient inotify + events were lost then the next pruning or invalidation + will do the stat and mtime check. We don't do it here to + keep the logic simple. */ + if (stat64 (finfo->fname, &st) < 0) + return -1; + return 0; +} + /* Process the inotify event in INEV. If the event matches any of the files registered with a database then mark that database as requiring its cache to be cleared. We indicate the cache needs clearing by setting TO_CLEAR[DBCNT] to true for the matching database. */ -static inline void +static void inotify_check_files (bool *to_clear, union __inev *inev) { /* Check which of the files changed. */ @@ -1894,16 +1948,124 @@ inotify_check_files (bool *to_clear, union __inev *inev) while (finfo != NULL) { - /* Inotify event watch descriptor matches. */ - if (finfo->inotify_descr == inev->i.wd) + /* The configuration file was moved or deleted. + We stop watching it at that point, and reinitialize. */ + if (finfo->inotify_descr[TRACED_FILE] == inev->i.wd + && ((inev->i.mask & IN_MOVE_SELF) + || (inev->i.mask & IN_DELETE_SELF) + || (inev->i.mask & IN_IGNORED))) + { + int ret; + bool moved = (inev->i.mask & IN_MOVE_SELF) != 0; + + if (check_file (finfo) == 0) + { + dbg_log (_("ignored inotify event for `%s` (file exists)"), + finfo->fname); + return; + } + + dbg_log (_("monitored file `%s` was %s, removing watch"), + finfo->fname, moved ? "moved" : "deleted"); + /* File was moved out, remove the watch. Watches are + automatically removed when the file is deleted. */ + if (moved) + { + ret = inotify_rm_watch (inotify_fd, inev->i.wd); + if (ret < 0) + dbg_log (_("failed to remove file watch `%s`: %s"), + finfo->fname, strerror (errno)); + } + finfo->inotify_descr[TRACED_FILE] = -1; + to_clear[dbcnt] = true; + if (finfo->call_res_init) + res_init (); + return; + } + /* The configuration file was open for writing and has just closed. + We reset the cache and reinitialize. */ + if (finfo->inotify_descr[TRACED_FILE] == inev->i.wd + && inev->i.mask & IN_CLOSE_WRITE) { /* Mark cache as needing to be cleared and reinitialize. */ + dbg_log (_("monitored file `%s` was written to"), finfo->fname); to_clear[dbcnt] = true; if (finfo->call_res_init) res_init (); return; } + /* The parent directory was moved or deleted. We trigger one last + invalidation. At the next pruning or invalidation we may add + this watch back if the file is present again. */ + if (finfo->inotify_descr[TRACED_DIR] == inev->i.wd + && ((inev->i.mask & IN_DELETE_SELF) + || (inev->i.mask & IN_MOVE_SELF) + || (inev->i.mask & IN_IGNORED))) + { + bool moved = (inev->i.mask & IN_MOVE_SELF) != 0; + /* The directory watch may have already been removed + but we don't know so we just remove it again and + ignore the error. Then we remove the file watch. + Note: watches are automatically removed for deleted + files. */ + if (moved) + inotify_rm_watch (inotify_fd, inev->i.wd); + if (finfo->inotify_descr[TRACED_FILE] != -1) + { + dbg_log (_("monitored parent directory `%s` was %s, removing watch on `%s`"), + finfo->dname, moved ? "moved" : "deleted", finfo->fname); + if (inotify_rm_watch (inotify_fd, finfo->inotify_descr[TRACED_FILE]) < 0) + dbg_log (_("failed to remove file watch `%s`: %s"), + finfo->dname, strerror (errno)); + } + finfo->inotify_descr[TRACED_FILE] = -1; + finfo->inotify_descr[TRACED_DIR] = -1; + to_clear[dbcnt] = true; + if (finfo->call_res_init) + res_init (); + /* Continue to the next entry since this might be the + parent directory for multiple registered files and + we want to remove watches for all registered files. */ + continue; + } + /* The parent directory had a create or moved to event. */ + if (finfo->inotify_descr[TRACED_DIR] == inev->i.wd + && ((inev->i.mask & IN_MOVED_TO) + || (inev->i.mask & IN_CREATE)) + && strcmp (inev->i.name, finfo->sfname) == 0) + { + /* We detected a directory change. We look for the creation + of the file we are tracking or the move of the same file + into the directory. */ + int ret; + dbg_log (_("monitored file `%s` was %s, adding watch"), + finfo->fname, + inev->i.mask & IN_CREATE ? "created" : "moved into place"); + /* File was moved in or created. Regenerate the watch. */ + if (finfo->inotify_descr[TRACED_FILE] != -1) + inotify_rm_watch (inotify_fd, + finfo->inotify_descr[TRACED_FILE]); + + ret = inotify_add_watch (inotify_fd, + finfo->fname, + TRACED_FILE_MASK); + if (ret < 0) + dbg_log (_("failed to add file watch `%s`: %s"), + finfo->fname, strerror (errno)); + + finfo->inotify_descr[TRACED_FILE] = ret; + + /* The file is new or moved so mark cache as needing to + be cleared and reinitialize. */ + to_clear[dbcnt] = true; + if (finfo->call_res_init) + res_init (); + /* Done re-adding the watch. Don't return, we may still + have other files in this same directory, same watch + descriptor, and need to process them. */ + } + /* Other events are ignored, and we move on to the next file. */ finfo = finfo->next; } } @@ -1925,6 +2087,51 @@ clear_db_cache (bool *to_clear) } } +int +handle_inotify_events (void) +{ + bool to_clear[lastdb] = { false, }; + union __inev inev; + + /* Read all inotify events for files registered via + register_traced_file(). */ + while (1) + { + /* Potentially read multiple events into buf. */ + ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, + &inev.buf, + sizeof (inev))); + if (nb < (ssize_t) sizeof (struct inotify_event)) + { + /* Not even 1 event. */ + if (__glibc_unlikely (nb == -1 && errno != EAGAIN)) + return -1; + /* Done reading events that are ready. */ + break; + } + /* Process all events. The normal inotify interface delivers + complete events on a read and never a partial event. */ + char *eptr = &inev.buf[0]; + ssize_t count; + while (1) + { + /* Check which of the files changed. */ + inotify_check_files (to_clear, &inev); + count = sizeof (struct inotify_event) + inev.i.len; + eptr += count; + nb -= count; + if (nb >= (ssize_t) sizeof (struct inotify_event)) + memcpy (&inev, eptr, nb); + else + break; + } + continue; + } + /* Actually perform the cache clearing. */ + clear_db_cache (to_clear); + return 0; +} + #endif static void @@ -2031,42 +2238,20 @@ main_loop_poll (void) { if (conns[1].revents != 0) { - bool to_clear[lastdb] = { false, }; - union __inev inev; - - /* Read all inotify events for files registered via - register_traced_file(). */ - while (1) + int ret; + ret = handle_inotify_events (); + if (ret == -1) { - ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev, - sizeof (inev))); - if (nb < (ssize_t) sizeof (struct inotify_event)) - { - if (__builtin_expect (nb == -1 && errno != EAGAIN, - 0)) - { - /* Something went wrong when reading the inotify - data. Better disable inotify. */ - dbg_log (_("\ -disabled inotify after read error %d"), - errno); - conns[1].fd = -1; - firstfree = 1; - if (nused == 2) - nused = 1; - close (inotify_fd); - inotify_fd = -1; - } - break; - } - - /* Check which of the files changed. */ - inotify_check_files (to_clear, &inev); + /* Something went wrong when reading the inotify + data. Better disable inotify. */ + dbg_log (_("disabled inotify-based monitoring after read error %d"), errno); + conns[1].fd = -1; + firstfree = 1; + if (nused == 2) + nused = 1; + close (inotify_fd); + inotify_fd = -1; } - - /* Actually perform the cache clearing. */ - clear_db_cache (to_clear); - --n; } @@ -2234,37 +2419,18 @@ main_loop_epoll (int efd) # ifdef HAVE_INOTIFY else if (revs[cnt].data.fd == inotify_fd) { - bool to_clear[lastdb] = { false, }; - union __inev inev; - - /* Read all inotify events for files registered via - register_traced_file(). */ - while (1) + int ret; + ret = handle_inotify_events (); + if (ret == -1) { - ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev, - sizeof (inev))); - if (nb < (ssize_t) sizeof (struct inotify_event)) - { - if (__glibc_unlikely (nb == -1 && errno != EAGAIN)) - { - /* Something went wrong when reading the inotify - data. Better disable inotify. */ - dbg_log (_("disabled inotify after read error %d"), - errno); - (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd, - NULL); - close (inotify_fd); - inotify_fd = -1; - } - break; - } - - /* Check which of the files changed. */ - inotify_check_files(to_clear, &inev); + /* Something went wrong when reading the inotify + data. Better disable inotify. */ + dbg_log (_("disabled inotify-based monitoring after read error %d"), errno); + (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd, NULL); + close (inotify_fd); + inotify_fd = -1; + break; } - - /* Actually perform the cache clearing. */ - clear_db_cache (to_clear); } # endif # ifdef HAVE_NETLINK @@ -2301,7 +2467,9 @@ main_loop_epoll (int efd) no reply in too long of a time. */ time_t laststart = now - ACCEPT_TIMEOUT; assert (starttime[sock] == 0); +# ifdef HAVE_INOTIFY assert (inotify_fd == -1 || starttime[inotify_fd] == 0); +# endif assert (nl_status_fd == -1 || starttime[nl_status_fd] == 0); for (int cnt = highest; cnt > STDERR_FILENO; --cnt) if (starttime[cnt] != 0 && starttime[cnt] < laststart) diff --git a/nscd/nscd.h b/nscd/nscd.h index 17a0a96278..75c2eccea0 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -61,17 +61,67 @@ typedef enum 80% of the thread stack size. */ #define MAX_STACK_USE ((8 * NSCD_THREAD_STACKSIZE) / 10) - -/* Registered filename used to fill database. */ +/* Records the file registered per database that when changed + or modified requires invalidating the database. */ struct traced_file { + /* Tracks the last modified time of the traced file. */ time_t mtime; + /* Support multiple registered files per database. */ struct traced_file *next; int call_res_init; - int inotify_descr; + /* Requires Inotify support to do anything useful. */ +#define TRACED_FILE 0 +#define TRACED_DIR 1 + int inotify_descr[2]; +# ifndef PATH_MAX +# define PATH_MAX 1024 +# endif + /* The parent directory is used to scan for creation/deletion. */ + char dname[PATH_MAX]; + /* Just the name of the file with no directory component. */ + char *sfname; + /* The full-path name of the registered file. */ char fname[]; }; +/* Initialize a `struct traced_file`. As input we need the name + of the file, and if invalidation requires calling res_init. + If CRINIT is 1 then res_init will be called after invalidation + or if the traced file is changed in any way, otherwise it will + not. */ +static inline void +init_traced_file(struct traced_file *file, const char *fname, int crinit) +{ + char *dname; + file->mtime = 0; + file->inotify_descr[TRACED_FILE] = -1; + file->inotify_descr[TRACED_DIR] = -1; + strcpy (file->fname, fname); + /* Compute the parent directory name and store a copy. The copy makes + it much faster to add/remove watches while nscd is running instead + of computing this over and over again in a temp buffer. */ + file->dname[0] = '\0'; + dname = strrchr (fname, '/'); + if (dname != NULL) + { + size_t len = (size_t)(dname - fname); + if (len > sizeof (file->dname)) + abort (); + strncpy (file->dname, file->fname, len); + file->dname[len] = '\0'; + } + /* The basename is the name just after the last forward slash. */ + file->sfname = &dname[1]; + file->call_res_init = crinit; +} + +#define define_traced_file(id, filename) \ +static union \ +{ \ + struct traced_file file; \ + char buf[sizeof (struct traced_file) + sizeof (filename)]; \ +} id##_traced_file; /* Structure describing dynamic part of one database. */ struct database_dyn @@ -90,7 +140,6 @@ struct database_dyn int propagate; struct traced_file *traced_files; const char *db_filename; - time_t file_mtime; size_t suggested_module; size_t max_db_size; @@ -211,6 +260,9 @@ void do_exit (int child_ret, int errnum, const char *format, ...); /* connections.c */ extern void nscd_init (void); extern void register_traced_file (size_t dbidx, struct traced_file *finfo); +#ifdef HAVE_INOTIFY +extern void install_watches (struct traced_file *finfo); +#endif extern void close_sockets (void); extern void start_threads (void) __attribute__ ((__noreturn__)); diff --git a/nss/nss_db/db-init.c b/nss/nss_db/db-init.c index 041471cad0..099d89b1f8 100644 --- a/nss/nss_db/db-init.c +++ b/nss/nss_db/db-init.c @@ -22,35 +22,25 @@ #include <nscd/nscd.h> #include <string.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; +#define PWD_FILENAME (_PATH_VARDB "passwd.db") +define_traced_file (pwd, PWD_FILENAME); -static union -{ - struct traced_file file; - char buf[sizeof (struct traced_file) + sizeof (_PATH_VARDB "services.db")]; -} serv_traced_file; +#define GRP_FILENAME (_PATH_VARDB "group.db") +define_traced_file (grp, GRP_FILENAME); +#define SERV_FILENAME (_PATH_VARDB "services.db") +define_traced_file (serv, SERV_FILENAME); void _nss_db_init (void (*cb) (size_t, struct traced_file *)) { - strcpy (pwd_traced_file.file.fname,_PATH_VARDB "passwd.db"); + init_traced_file (&pwd_traced_file.file, PWD_FILENAME, 0); cb (pwddb, &pwd_traced_file.file); - strcpy (grp_traced_file.file.fname, _PATH_VARDB "group.db"); + init_traced_file (&grp_traced_file.file, GRP_FILENAME, 0); cb (grpdb, &grp_traced_file.file); - strcpy (serv_traced_file.file.fname, _PATH_VARDB "services.db"); + init_traced_file (&serv_traced_file.file, SERV_FILENAME, 0); cb (servdb, &serv_traced_file.file); } diff --git a/nss/nss_files/files-init.c b/nss/nss_files/files-init.c index 94d440aaa4..72eced41bf 100644 --- a/nss/nss_files/files-init.c +++ b/nss/nss_files/files-init.c @@ -21,47 +21,43 @@ #include <string.h> #include <nscd/nscd.h> +#define PWD_FILENAME "/etc/passwd" +define_traced_file (pwd, PWD_FILENAME); -#define TF(id, filename, ...) \ -static union \ -{ \ - struct traced_file file; \ - char buf[sizeof (struct traced_file) + sizeof (filename)]; \ -} id##_traced_file = \ - { \ - .file = \ - { \ - __VA_ARGS__ \ - } \ - } - -TF (pwd, "/etc/passwd"); -TF (grp, "/etc/group"); -TF (hst, "/etc/hosts"); -TF (resolv, "/etc/resolv.conf", .call_res_init = 1); -TF (serv, "/etc/services"); -TF (netgr, "/etc/netgroup"); +#define GRP_FILENAME "/etc/group" +define_traced_file (grp, GRP_FILENAME); +#define HST_FILENAME "/etc/hosts" +define_traced_file (hst, HST_FILENAME); + +#define RESOLV_FILENAME "/etc/resolv.conf" +define_traced_file (resolv, RESOLV_FILENAME); + +#define SERV_FILENAME "/etc/services" +define_traced_file (serv, SERV_FILENAME); + +#define NETGR_FILENAME "/etc/netgroup" +define_traced_file (netgr, NETGR_FILENAME); void _nss_files_init (void (*cb) (size_t, struct traced_file *)) { - strcpy (pwd_traced_file.file.fname, "/etc/passwd"); + init_traced_file (&pwd_traced_file.file, PWD_FILENAME, 0); cb (pwddb, &pwd_traced_file.file); - strcpy (grp_traced_file.file.fname, "/etc/group"); + init_traced_file (&grp_traced_file.file, GRP_FILENAME, 0); cb (grpdb, &grp_traced_file.file); - strcpy (hst_traced_file.file.fname, "/etc/hosts"); + init_traced_file (&hst_traced_file.file, HST_FILENAME, 0); cb (hstdb, &hst_traced_file.file); - strcpy (resolv_traced_file.file.fname, "/etc/resolv.conf"); + init_traced_file (&resolv_traced_file.file, RESOLV_FILENAME, 1); cb (hstdb, &resolv_traced_file.file); - strcpy (serv_traced_file.file.fname, "/etc/services"); + init_traced_file (&serv_traced_file.file, SERV_FILENAME, 0); cb (servdb, &serv_traced_file.file); - strcpy (netgr_traced_file.file.fname, "/etc/netgroup"); + init_traced_file (&netgr_traced_file.file, NETGR_FILENAME, 0); cb (netgrdb, &netgr_traced_file.file); } |