+DEBUG(D_tls) debug_printf("notify_add_watch: %s\n", strerror(errno));
+return FALSE;
+}
+# endif
+# ifdef EXIM_HAVE_KEVENT
+{
+uschar * s, * t;
+int fd1, fd2, i, j, cnt = 0;
+struct stat sb;
+#ifdef OpenBSD
+struct kevent k_dummy;
+struct timespec ts = {0};
+#endif
+
+errno = 0;
+if (Ustrcmp(filename, "system,cache") == 0) return TRUE;
+
+for (;;)
+ {
+ if (kev_used > KEV_SIZE-2) { s = US"out of kev space"; goto bad; }
+ if (!(s = Ustrrchr(filename, '/'))) return FALSE;
+ s = string_copyn(filename, s - filename); /* mem released by tls_set_watch */
+
+ /* The dir open will fail if there is a symlink on the path. Fine; it's too
+ much effort to handle all possible cases; just refuse the preload. */
+
+ if ((fd2 = open(CCS s, O_RDONLY | O_NOFOLLOW)) < 0) { s = US"open dir"; goto bad; }
+
+ if ((lstat(CCS filename, &sb)) < 0) { s = US"lstat"; goto bad; }
+ if (!S_ISLNK(sb.st_mode))
+ {
+ if ((fd1 = open(CCS filename, O_RDONLY | O_NOFOLLOW)) < 0)
+ { s = US"open file"; goto bad; }
+ DEBUG(D_tls) debug_printf("watch file '%s':\t%d\n", filename, fd1);
+ EV_SET(&kev[kev_used++],
+ (uintptr_t)fd1,
+ EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_ONESHOT,
+ NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND
+ | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
+ 0,
+ NULL);
+ cnt++;
+ }
+ DEBUG(D_tls) debug_printf("watch dir '%s':\t%d\n", s, fd2);
+ EV_SET(&kev[kev_used++],
+ (uintptr_t)fd2,
+ EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_ONESHOT,
+ NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND
+ | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
+ 0,
+ NULL);
+ cnt++;
+
+ if (!(S_ISLNK(sb.st_mode))) break;
+
+ t = store_get(1024, GET_UNTAINTED);
+ Ustrncpy(t, s, 1022);
+ j = Ustrlen(s);
+ t[j++] = '/';
+ if ((i = readlink(CCS filename, (void *)(t+j), 1023-j)) < 0) { s = US"readlink"; goto bad; }
+ filename = t;
+ *(t += i+j) = '\0';
+ store_release_above(t+1);
+ }
+
+#ifdef OpenBSD
+if (kevent(tls_watch_fd, &kev[kev_used-cnt], cnt, &k_dummy, 1, &ts) >= 0)
+ return TRUE;
+#else
+if (kevent(tls_watch_fd, &kev[kev_used-cnt], cnt, NULL, 0, NULL) >= 0)
+ return TRUE;
+#endif
+s = US"kevent";
+
+bad:
+DEBUG(D_tls)
+ if (errno)
+ debug_printf("%s: %s: %s\n", __FUNCTION__, s, strerror(errno));
+ else
+ debug_printf("%s: %s\n", __FUNCTION__, s);