2 # Based on the following patch:
4 # Upstream bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14906
5 # URL: https://sourceware.org/ml/libc-alpha/2015-02/msg00504.html
7 # 2015-02-17 Carlos O'Donell <carlos@redhat.com>
10 # * nscd/cache.c (prune_cache): Use TRACED_FILE. Compare and update
11 # traced file mtime. Use consistent log message.
12 # * nscd/connections.c [HAVE_INOTIFY] (install_watches): New function.
13 # (register_traced_file): Call install_watches. Always set mtime.
14 # (invalidate_cache): Iterate over all trace files. Call install_watches.
15 # (inotify_check_files): Don't inline. Handle watching parent
16 # directories and configuration file movement in and out.
17 # (handle_inotify_events): New function.
18 # (main_loop_poll): Call handle_inotify_events.
19 # (main_loop_epoll): Likewise.
20 # * nscd/nscd.h: Define TRACED_FILE, TRACED_DIR, and PATH_MAX.
21 # (struct traced_file): Use array of inotify fds. Add parent directory,
23 # (struct database_dyn): Remove unused file_mtime.
24 # (init_traced_file): New inline function.
25 # (define_traced_file): New macro.
26 # * nss/nss_db/db-init.c: Use define_traced_file.
27 # (_nss_db_init): Use init_traced_file.
28 # * nss/nss_files/files-init.c: Use define_traced_file.
29 # (_nss_files_init): Use init_traced_file.
31 diff -urN glibc-2.12-2-gc4ccff1.orig/misc/sys/cdefs.h glibc-2.12-2-gc4ccff1.mod1/misc/sys/cdefs.h
32 --- glibc-2.12-2-gc4ccff1.orig/misc/sys/cdefs.h 2015-02-18 04:42:12.115187116 -0500
33 +++ glibc-2.12-2-gc4ccff1.mod1/misc/sys/cdefs.h 2015-02-18 04:02:03.635159090 -0500
39 +# define __glibc_unlikely(cond) __builtin_expect ((cond), 0)
40 +# define __glibc_likely(cond) __builtin_expect ((cond), 1)
42 +# define __glibc_unlikely(cond) (cond)
43 +# define __glibc_likely(cond) (cond)
46 #include <bits/wordsize.h>
48 #if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
49 diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/cache.c glibc-2.12-2-gc4ccff1.mod1/nscd/cache.c
50 --- glibc-2.12-2-gc4ccff1.orig/nscd/cache.c 2015-02-18 04:42:12.329180362 -0500
51 +++ glibc-2.12-2-gc4ccff1.mod1/nscd/cache.c 2015-02-18 04:02:03.635159090 -0500
54 /* If we check for the modification of the underlying file we invalidate
55 the entries also in this case. */
56 - if (table->inotify_descr < 0 && table->check_file && now != LONG_MAX)
57 + if (table->check_file && now != LONG_MAX)
60 + struct traced_file *runp = table->traced_files;
62 - if (stat64 (table->filename, &st) < 0)
63 + while (runp != NULL)
66 - /* We cannot stat() the file, disable file checking if the
67 - file does not exist. */
68 - dbg_log (_("cannot stat() file `%s': %s"),
69 - table->filename, strerror_r (errno, buf, sizeof (buf)));
70 - if (errno == ENOENT)
71 - table->check_file = 0;
75 - if (st.st_mtime != table->file_mtime)
77 + if (runp->inotify_descr[TRACED_FILE] == -1)
80 - /* The file changed. Invalidate all entries. */
82 - table->file_mtime = st.st_mtime;
85 + if (stat64 (runp->fname, &st) < 0)
87 + /* Print a diagnostic that the traced file was missing.
88 + We must not disable tracing since the file might return
89 + shortly and we want to reload it at the next pruning.
90 + Disabling tracing here would go against the configuration
91 + as specified by the user via check-files. */
93 + dbg_log (_("checking for monitored file `%s': %s"),
94 + runp->fname, strerror_r (errno, buf, sizeof (buf)));
98 + /* This must be `!=` to catch cases where users turn the
99 + clocks back and we still want to detect any time difference
101 + if (st.st_mtime != runp->mtime)
103 + dbg_log (_("monitored file `%s` changed (mtime)"),
105 + /* The file changed. Invalidate all entries. */
107 + runp->mtime = st.st_mtime;
109 + /* Attempt to install a watch on the file. */
110 + install_watches (runp);
121 /* We run through the table and find values which are not valid anymore.
122 diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/connections.c glibc-2.12-2-gc4ccff1.mod1/nscd/connections.c
123 --- glibc-2.12-2-gc4ccff1.orig/nscd/connections.c 2015-02-18 04:42:12.333180236 -0500
124 +++ glibc-2.12-2-gc4ccff1.mod1/nscd/connections.c 2015-02-18 04:40:51.674726008 -0500
126 static void begin_drop_privileges (void);
127 static void finish_drop_privileges (void);
129 +/* Define the traced files. */
130 +#define PWD_FILENAME "/etc/passwd"
131 +define_traced_file (pwd, PWD_FILENAME);
133 +#define GRP_FILENAME "/etc/group"
134 +define_traced_file (grp, GRP_FILENAME);
136 +#define HST_FILENAME "/etc/hosts"
137 +define_traced_file (hst, HST_FILENAME);
139 +#define RESOLV_FILENAME "/etc/resolv.conf"
140 +define_traced_file (resolv, RESOLV_FILENAME);
142 +#define SERV_FILENAME "/etc/services"
143 +define_traced_file (serv, SERV_FILENAME);
145 +#define NETGR_FILENAME "/etc/netgroup"
146 +define_traced_file (netgr, NETGR_FILENAME);
148 /* Map request type to a string. */
149 const char *const serv2str[LASTREQ] =
153 .max_db_size = DEFAULT_MAX_DB_SIZE,
154 .suggested_module = DEFAULT_SUGGESTED_MODULE,
156 - .filename = "/etc/passwd",
157 .db_filename = _PATH_NSCD_PASSWD_DB,
158 .disabled_iov = &pwd_iov_disabled,
162 .max_db_size = DEFAULT_MAX_DB_SIZE,
163 .suggested_module = DEFAULT_SUGGESTED_MODULE,
165 - .filename = "/etc/group",
166 .db_filename = _PATH_NSCD_GROUP_DB,
167 .disabled_iov = &grp_iov_disabled,
171 .max_db_size = DEFAULT_MAX_DB_SIZE,
172 .suggested_module = DEFAULT_SUGGESTED_MODULE,
174 - .filename = "/etc/hosts",
175 .db_filename = _PATH_NSCD_HOSTS_DB,
176 .disabled_iov = &hst_iov_disabled,
180 .max_db_size = DEFAULT_MAX_DB_SIZE,
181 .suggested_module = DEFAULT_SUGGESTED_MODULE,
183 - .filename = "/etc/services",
184 .db_filename = _PATH_NSCD_SERVICES_DB,
185 .disabled_iov = &serv_iov_disabled,
189 .max_db_size = DEFAULT_MAX_DB_SIZE,
190 .suggested_module = DEFAULT_SUGGESTED_MODULE,
192 - .filename = "/etc/netgroup",
193 .db_filename = _PATH_NSCD_NETGROUP_DB,
194 .disabled_iov = &netgroup_iov_disabled,
196 @@ -863,41 +872,26 @@
198 assert (dbs[cnt].ro_fd == -1);
202 - dbs[cnt].inotify_descr = -1;
203 - if (dbs[cnt].check_file)
207 - || (dbs[cnt].inotify_descr
208 - = inotify_add_watch (inotify_fd, dbs[cnt].filename,
209 - IN_DELETE_SELF | IN_MODIFY)) < 0)
210 - /* We cannot notice changes in the main thread. */
213 - /* We need the modification date of the file. */
215 + /* Initialize and register the traced files. */
216 + init_traced_file (&pwd_traced_file.file, PWD_FILENAME, 0);
217 + register_traced_file (pwddb, &pwd_traced_file.file);
219 - if (stat64 (dbs[cnt].filename, &st) < 0)
221 - /* We cannot stat() the file, disable file checking. */
222 - dbg_log (_("cannot stat() file `%s': %s"),
223 - dbs[cnt].filename, strerror (errno));
224 - dbs[cnt].check_file = 0;
227 - dbs[cnt].file_mtime = st.st_mtime;
230 + init_traced_file (&grp_traced_file.file, GRP_FILENAME, 0);
231 + register_traced_file (grpdb, &grp_traced_file.file);
234 - if (cnt == hstdb && inotify_fd >= -1)
235 - /* We also monitor the resolver configuration file. */
236 - resolv_conf_descr = inotify_add_watch (inotify_fd,
238 - IN_DELETE_SELF | IN_MODIFY);
241 + init_traced_file (&hst_traced_file.file, HST_FILENAME, 0);
242 + register_traced_file (hstdb, &hst_traced_file.file);
244 + init_traced_file (&resolv_traced_file.file, RESOLV_FILENAME, 1);
245 + register_traced_file (hstdb, &resolv_traced_file.file);
247 + init_traced_file (&serv_traced_file.file, SERV_FILENAME, 0);
248 + register_traced_file (servdb, &serv_traced_file.file);
250 + init_traced_file (&netgr_traced_file.file, NETGR_FILENAME, 0);
251 + register_traced_file (netgrdb, &netgr_traced_file.file);
253 /* Create the socket. */
254 #ifndef __ASSUME_SOCK_CLOEXEC
256 finish_drop_privileges ();
260 +#define TRACED_FILE_MASK (IN_DELETE_SELF | IN_CLOSE_WRITE | IN_MOVE_SELF)
261 +#define TRACED_DIR_MASK (IN_DELETE_SELF | IN_CREATE | IN_MOVED_TO | IN_MOVE_SELF)
263 +install_watches (struct traced_file *finfo)
265 + /* If we have inotify support use it exclusively with no fallback
266 + to stat. This is a design decision to make the implementation
267 + sipmler. Either we use fstat for the file name or we use inotify
268 + for both the file and parent directory. */
269 + if (finfo->inotify_descr[TRACED_FILE] < 0)
270 + finfo->inotify_descr[TRACED_FILE] = inotify_add_watch (inotify_fd,
273 + if (finfo->inotify_descr[TRACED_FILE] < 0)
275 + dbg_log (_("disabled inotify-based monitoring for file `%s': %s"),
276 + finfo->fname, strerror (errno));
279 + dbg_log (_("monitoring file `%s` (%d)"),
280 + finfo->fname, finfo->inotify_descr[TRACED_FILE]);
281 + /* Additionally listen for IN_CREATE events in the files parent
282 + directory. We do this because the file to be watched might be
283 + deleted and then added back again. When it is added back again
284 + we must re-add the watch. We must also cover IN_MOVED_TO to
285 + detect a file being moved into the directory. */
286 + if (finfo->inotify_descr[TRACED_DIR] < 0)
287 + finfo->inotify_descr[TRACED_DIR] = inotify_add_watch (inotify_fd,
290 + if (finfo->inotify_descr[TRACED_DIR] < 0)
292 + dbg_log (_("disabled inotify-based monitoring for directory `%s': %s"),
293 + finfo->fname, strerror (errno));
296 + dbg_log (_("monitoring directory `%s` (%d)"),
297 + finfo->dname, finfo->inotify_descr[TRACED_DIR]);
301 +/* Register the file in FINFO as a traced file for the database DBS[DBIX].
303 + We support registering multiple files per database. Each call to
304 + register_traced_file adds to the list of registered files.
306 + When we prune the database, either through timeout or a request to
307 + invalidate, we will check to see if any of the registered files has changed.
308 + When we accept new connections to handle a cache request we will also
309 + check to see if any of the registered files has changed.
311 + If we have inotify support then we install an inotify fd to notify us of
312 + file deletion or modification, both of which will require we invalidate
313 + the cache for the database. Without inotify support we stat the file and
314 + store st_mtime to determine if the file has been modified. */
316 +register_traced_file (size_t dbidx, struct traced_file *finfo)
318 + /* If the database is disabled or file checking is disabled
319 + then ignore the registration. */
320 + if (! dbs[dbidx].enabled || ! dbs[dbidx].check_file)
323 + if (__glibc_unlikely (debug_level > 0))
324 + dbg_log (_("monitoring file %s for database %s"),
325 + finfo->fname, dbnames[dbidx]);
328 + install_watches (finfo);
331 + if (stat64 (finfo->fname, &st) < 0)
333 + /* We cannot stat() the file, disable file checking. */
334 + dbg_log (_("disabled monitoring for file `%s': %s"),
335 + finfo->fname, strerror (errno));
339 + finfo->mtime = st.st_mtime;
341 + /* Queue up the file name. */
342 + finfo->next = dbs[dbidx].traced_files;
343 + dbs[dbidx].traced_files = finfo;
346 /* Close the connections. */
348 @@ -986,9 +1066,25 @@
349 for (number = pwddb; number < lastdb; ++number)
350 if (strcmp (key, dbnames[number]) == 0)
352 - if (dbs[number].reset_res)
355 + struct traced_file *runp = dbs[number].traced_files;
356 + while (runp != NULL)
358 + /* Make sure we reload from file when checking mtime. */
361 + /* During an invalidation we try to reload the traced
362 + file watches. This allows the user to re-sync if
363 + inotify events were lost. Similar to what we do during
365 + install_watches (runp);
367 + if (runp->call_res_init)
377 @@ -1817,6 +1913,231 @@
378 /* Array for times a connection was accepted. */
379 static time_t *starttime;
382 +/* Inotify event for changed file. */
385 + struct inotify_event i;
387 +# define PATH_MAX 1024
389 + char buf[sizeof (struct inotify_event) + PATH_MAX];
392 +/* Returns 0 if the file is there and matches the last mtime
393 + on record, otherwise -1. */
395 +check_file (struct traced_file *finfo)
398 + if (stat64 (finfo->fname, &st) < 0)
403 +/* Process the inotify event in INEV. If the event matches any of the files
404 + registered with a database then mark that database as requiring its cache
405 + to be cleared. We indicate the cache needs clearing by setting
406 + TO_CLEAR[DBCNT] to true for the matching database. */
408 +inotify_check_files (bool *to_clear, union __inev *inev)
410 + /* Check which of the files changed. */
411 + for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
413 + struct traced_file *finfo = dbs[dbcnt].traced_files;
415 + while (finfo != NULL)
417 + /* The configuration file was moved or deleted.
418 + We stop watching it at that point, and reinitialize. */
419 + if (finfo->inotify_descr[TRACED_FILE] == inev->i.wd
420 + && ((inev->i.mask & IN_MOVE_SELF)
421 + || (inev->i.mask & IN_DELETE_SELF)
422 + || (inev->i.mask & IN_IGNORED)))
425 + bool moved = (inev->i.mask & IN_MOVE_SELF) != 0;
427 + if (check_file (finfo) == 0)
429 + dbg_log (_("ignored out of order inotify event for `%s`"),
434 + dbg_log (_("monitored file `%s` was %s, removing watch"),
435 + finfo->fname, moved ? "moved" : "deleted");
436 + /* File was moved out, remove the watch. Watches are
437 + automatically removed when the file is deleted. */
440 + ret = inotify_rm_watch (inotify_fd, inev->i.wd);
442 + dbg_log (_("failed to remove file watch `%s`: %s"),
443 + finfo->fname, strerror (errno));
445 + finfo->inotify_descr[TRACED_FILE] = -1;
446 + to_clear[dbcnt] = true;
447 + if (finfo->call_res_init)
451 + /* The configuration file was open for writing and has just closed.
452 + We reset the cache and reinitialize. */
453 + if (finfo->inotify_descr[TRACED_FILE] == inev->i.wd
454 + && inev->i.mask & IN_CLOSE_WRITE)
456 + /* Mark cache as needing to be cleared and reinitialize. */
457 + dbg_log (_("monitored file `%s` was written to"), finfo->fname);
458 + to_clear[dbcnt] = true;
459 + if (finfo->call_res_init)
463 + /* The parent directory was moved or deleted. There is no coming
464 + back from this. We do not track the parent of the parent, and
465 + once this happens we trigger one last invalidation. You must
466 + restart nscd to track subsequent changes. We track this to
467 + do one last robust re-initialization and then we're done. */
468 + if (finfo->inotify_descr[TRACED_DIR] == inev->i.wd
469 + && ((inev->i.mask & IN_DELETE_SELF)
470 + || (inev->i.mask & IN_MOVE_SELF)
471 + || (inev->i.mask & IN_IGNORED)))
473 + bool moved = (inev->i.mask & IN_MOVE_SELF) != 0;
474 + /* The directory watch may have already been removed
475 + but we don't know so we just remove it again and
476 + ignore the error. Then we remove the file watch.
477 + Note: watches are automatically removed for deleted
480 + inotify_rm_watch (inotify_fd, inev->i.wd);
481 + if (finfo->inotify_descr[TRACED_FILE] != -1)
483 + dbg_log (_("monitored parent directory `%s` was %s, removing watch on `%s`"),
484 + finfo->dname, moved ? "moved" : "deleted", finfo->fname);
485 + if (inotify_rm_watch (inotify_fd, finfo->inotify_descr[TRACED_FILE]) < 0)
486 + dbg_log (_("failed to remove file watch `%s`: %s"),
487 + finfo->dname, strerror (errno));
489 + finfo->inotify_descr[TRACED_FILE] = -1;
490 + finfo->inotify_descr[TRACED_DIR] = -1;
491 + to_clear[dbcnt] = true;
492 + if (finfo->call_res_init)
494 + /* Continue to the next entry since this might be the
495 + parent directory for multiple registered files and
496 + we want to remove watches for all registered files. */
499 + /* The parent directory had a create or moved to event. */
500 + if (finfo->inotify_descr[TRACED_DIR] == inev->i.wd
501 + && ((inev->i.mask & IN_MOVED_TO)
502 + || (inev->i.mask & IN_CREATE))
503 + && strcmp (inev->i.name, finfo->sfname) == 0)
505 + /* We detected a directory change. We look for the creation
506 + of the file we are tracking or the move of the same file
507 + into the directory. */
509 + dbg_log (_("monitored file `%s` was %s, adding watch"),
511 + inev->i.mask & IN_CREATE ? "created" : "moved into place");
512 + /* File was moved in or created. Regenerate the watch. */
513 + if (finfo->inotify_descr[TRACED_FILE] != -1)
514 + inotify_rm_watch (inotify_fd,
515 + finfo->inotify_descr[TRACED_FILE]);
517 + ret = inotify_add_watch (inotify_fd,
521 + dbg_log (_("failed to add file watch `%s`: %s"),
522 + finfo->fname, strerror (errno));
524 + finfo->inotify_descr[TRACED_FILE] = ret;
526 + /* The file is new or moved so mark cache as needing to
527 + be cleared and reinitialize. */
528 + to_clear[dbcnt] = true;
529 + if (finfo->call_res_init)
532 + /* Done re-adding the watch. Don't return, we may still
533 + have other files in this same directory, same watch
534 + descriptor, and need to process them. */
536 + /* Other events are ignored, and we move on to the next file. */
537 + finfo = finfo->next;
542 +/* If an entry in the array of booleans TO_CLEAR is TRUE then clear the cache
543 + for the associated database, otherwise do nothing. The TO_CLEAR array must
544 + have LASTDB entries. */
546 +clear_db_cache (bool *to_clear)
548 + for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
549 + if (to_clear[dbcnt])
551 + pthread_mutex_lock (&dbs[dbcnt].prune_lock);
552 + dbs[dbcnt].clear_cache = 1;
553 + pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
554 + pthread_cond_signal (&dbs[dbcnt].prune_cond);
559 +handle_inotify_events (void)
561 + bool to_clear[lastdb] = { false, };
564 + /* Read all inotify events for files registered via
565 + register_traced_file(). */
568 + /* Potentially read multiple events into buf. */
569 + ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd,
572 + if (nb < (ssize_t) sizeof (struct inotify_event))
574 + /* Not even 1 event. */
575 + if (__glibc_unlikely (nb == -1 && errno != EAGAIN))
577 + /* Done reading events that are ready. */
580 + /* Process all events. The normal inotify interface delivers
581 + complete events on a read and never a partial event. */
582 + char *eptr = &inev.buf[0];
586 + /* Check which of the files changed. */
587 + inotify_check_files (to_clear, &inev);
588 + count = sizeof (struct inotify_event) + inev.i.len;
591 + if (nb >= (ssize_t) sizeof (struct inotify_event))
592 + memcpy (&inev, eptr, nb);
598 + /* Actually perform the cache clearing. */
599 + clear_db_cache (to_clear);
608 __attribute__ ((__noreturn__))
609 @@ -1910,66 +2231,21 @@
611 if (conns[1].revents != 0)
613 - bool to_clear[lastdb] = { false, };
617 -# define PATH_MAX 1024
619 - struct inotify_event i;
620 - char buf[sizeof (struct inotify_event) + PATH_MAX];
623 + ret = handle_inotify_events ();
628 - ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
630 - if (nb < (ssize_t) sizeof (struct inotify_event))
632 - if (__builtin_expect (nb == -1 && errno != EAGAIN,
635 - /* Something went wrong when reading the inotify
636 - data. Better disable inotify. */
638 -disabled inotify after read error %d"),
644 - close (inotify_fd);
650 - /* Check which of the files changed. */
651 - for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
652 - if (inev.i.wd == dbs[dbcnt].inotify_descr)
654 - to_clear[dbcnt] = true;
658 - if (inev.i.wd == resolv_conf_descr)
661 - to_clear[hstdb] = true;
664 + /* Something went wrong when reading the inotify
665 + data. Better disable inotify. */
666 + dbg_log (_("disabled inotify-based monitoring after read error %d"), errno);
671 + close (inotify_fd);
675 - /* Actually perform the cache clearing. */
676 - for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
677 - if (to_clear[dbcnt])
679 - pthread_mutex_lock (&dbs[dbcnt].prune_lock);
680 - dbs[dbcnt].clear_cache = 1;
681 - pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
682 - pthread_cond_signal (&dbs[dbcnt].prune_cond);
688 @@ -2112,58 +2388,18 @@
690 else if (revs[cnt].data.fd == inotify_fd)
692 - bool to_clear[lastdb] = { false, };
695 - struct inotify_event i;
696 - char buf[sizeof (struct inotify_event) + PATH_MAX];
701 + ret = handle_inotify_events ();
704 - ssize_t nb = TEMP_FAILURE_RETRY (read (inotify_fd, &inev,
706 - if (nb < (ssize_t) sizeof (struct inotify_event))
708 - if (__builtin_expect (nb == -1 && errno != EAGAIN, 0))
710 - /* Something went wrong when reading the inotify
711 - data. Better disable inotify. */
712 - dbg_log (_("disabled inotify after read error %d"),
714 - (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd,
716 - close (inotify_fd);
722 - /* Check which of the files changed. */
723 - for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
724 - if (inev.i.wd == dbs[dbcnt].inotify_descr)
726 - to_clear[dbcnt] = true;
730 - if (inev.i.wd == resolv_conf_descr)
733 - to_clear[hstdb] = true;
736 + /* Something went wrong when reading the inotify
737 + data. Better disable inotify. */
738 + dbg_log (_("disabled inotify-based monitoring after read error %d"), errno);
739 + (void) epoll_ctl (efd, EPOLL_CTL_DEL, inotify_fd, NULL);
740 + close (inotify_fd);
745 - /* Actually perform the cache clearing. */
746 - for (size_t dbcnt = 0; dbcnt < lastdb; ++dbcnt)
747 - if (to_clear[dbcnt])
749 - pthread_mutex_lock (&dbs[dbcnt].prune_lock);
750 - dbs[dbcnt].clear_cache = 1;
751 - pthread_mutex_unlock (&dbs[dbcnt].prune_lock);
752 - pthread_cond_signal (&dbs[dbcnt].prune_cond);
757 diff -urN glibc-2.12-2-gc4ccff1.orig/nscd/nscd.h glibc-2.12-2-gc4ccff1.mod1/nscd/nscd.h
758 --- glibc-2.12-2-gc4ccff1.orig/nscd/nscd.h 2015-02-18 04:42:12.329180362 -0500
759 +++ glibc-2.12-2-gc4ccff1.mod1/nscd/nscd.h 2015-02-18 04:02:03.636159059 -0500
761 80% of the thread stack size. */
762 #define MAX_STACK_USE ((8 * NSCD_THREAD_STACKSIZE) / 10)
764 +/* Records the file registered per database that when changed
765 + or modified requires invalidating the database. */
768 + /* Tracks the last modified time of the traced file. */
770 + /* Support multiple registered files per database. */
771 + struct traced_file *next;
773 + /* Requires Inotify support to do anything useful. */
774 +#define TRACED_FILE 0
775 +#define TRACED_DIR 1
776 + int inotify_descr[2];
778 +# define PATH_MAX 1024
780 + /* The parent directory is used to scan for creation/deletion. */
781 + char dname[PATH_MAX];
782 + /* Just the name of the file with no directory component. */
784 + /* The full-path name of the registered file. */
788 +/* Initialize a `struct traced_file`. As input we need the name
789 + of the file, and if invalidation requires calling res_init.
790 + If CRINIT is 1 then res_init will be called after invalidation
791 + or if the traced file is changed in any way, otherwise it will
794 +init_traced_file(struct traced_file *file, const char *fname, int crinit)
798 + file->inotify_descr[TRACED_FILE] = -1;
799 + file->inotify_descr[TRACED_DIR] = -1;
800 + strcpy (file->fname, fname);
801 + /* Compute the parent directory name and store a copy. The copy makes
802 + it much faster to add/remove watches while nscd is running instead
803 + of computing this over and over again in a temp buffer. */
804 + file->dname[0] = '\0';
805 + dname = strrchr (fname, '/');
808 + size_t len = (size_t)(dname - fname);
809 + if (len > sizeof (file->dname))
811 + strncpy (file->dname, file->fname, len);
812 + file->dname[len] = '\0';
814 + /* The basename is the name just after the last forward slash. */
815 + file->sfname = &dname[1];
816 + file->call_res_init = crinit;
819 +#define define_traced_file(id, filename) \
822 + struct traced_file file; \
823 + char buf[sizeof (struct traced_file) + sizeof (filename)]; \
826 /* Structure describing dynamic part of one database. */
838 - const char filename[16];
839 + struct traced_file *traced_files;
840 const char *db_filename;
842 size_t suggested_module;
848 extern void nscd_init (void);
849 +extern void register_traced_file (size_t dbidx, struct traced_file *finfo);
851 +extern void install_watches (struct traced_file *finfo);
853 extern void close_sockets (void);
854 extern void start_threads (void) __attribute__ ((__noreturn__));