From 584483d91fffb3cbe4c2d76cf54828c89fa8c73f Mon Sep 17 00:00:00 2001 From: Martin von Gagern Date: Fri, 18 Mar 2016 01:48:08 +0100 Subject: [PATCH 1/2] Support inotify to watch crontab directories This may lead to crontabs being re-read twice, once triggered by inotify and a second time by cron.update. This should be no serious problem, though. --- database.c | 30 ++++++++++++++++----------- defs.h | 5 +++++ main.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/database.c b/database.c index c0cdc11..d8d64da 100644 --- a/database.c +++ b/database.c @@ -18,6 +18,7 @@ #define ALL_DOW (FIRST_DOW|SECOND_DOW|THIRD_DOW|FOURTH_DOW|FIFTH_DOW|LAST_DOW) Prototype void CheckUpdates(const char *dpath, const char *user_override, time_t t1, time_t t2); +Prototype void CheckFile(const char *dpath, const char *fileName, const char *user_override); Prototype void SynchronizeDir(const char *dpath, const char *user_override, int initial_scan); Prototype void ReadTimestamps(const char *user); Prototype int TestJobs(time_t t1, time_t t2); @@ -216,18 +217,7 @@ SynchronizeDir(const char *dpath, const char *user_override, int initial_scan) */ if ((dir = opendir(dpath)) != NULL) { while ((den = readdir(dir)) != NULL) { - if (strchr(den->d_name, '.') != NULL) - continue; - if (strcmp(den->d_name, CRONUPDATE) == 0) - continue; - if (user_override) { - SynchronizeFile(dpath, den->d_name, user_override); - } else if (getpwnam(den->d_name)) { - SynchronizeFile(dpath, den->d_name, den->d_name); - } else { - printlogf(LOG_WARNING, "ignoring %s/%s (non-existent user)\n", - dpath, den->d_name); - } + CheckFile(dpath, den->d_name, user_override); } closedir(dir); } else { @@ -237,6 +227,22 @@ SynchronizeDir(const char *dpath, const char *user_override, int initial_scan) } } +void +CheckFile(const char *dpath, const char *fileName, const char *user_override) +{ + if (strchr(fileName, '.') != NULL) + return; + if (strcmp(fileName, CRONUPDATE) == 0) + return; + if (user_override) { + SynchronizeFile(dpath, fileName, user_override); + } else if (getpwnam(fileName)) { + SynchronizeFile(dpath, fileName, fileName); + } else { + printlogf(LOG_WARNING, "ignoring %s/%s (non-existent user)\n", + dpath, fileName); + } +} void ReadTimestamps(const char *user) diff --git a/defs.h b/defs.h index cf77b5f..7cd849f 100644 --- a/defs.h +++ b/defs.h @@ -45,6 +45,11 @@ #include #include +#ifdef USE_INOTIFY +#include +#include +#endif + #define Prototype extern #define arysize(ary) (sizeof(ary)/sizeof((ary)[0])) diff --git a/main.c b/main.c index 0eba280..47336ac 100644 --- a/main.c +++ b/main.c @@ -301,9 +301,67 @@ main(int ac, char **av) long dt; short rescan = 60; short stime = 60; +#ifdef USE_INOTIFY + int notify; + int wd[2]; + const char *watchDirs[2] = { CDir, SCDir }; + struct pollfd fds[1]; + int poll_num; + notify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + if (notify == -1) { + printlogf(LOG_ERR, "Failed to initialize inotify: %m\n"); + exit(EXIT_FAILURE); + } + for (i = 0; i < 2; ++i) { + wd[i] = inotify_add_watch(notify, watchDirs[i], IN_CLOSE_WRITE | IN_DELETE); + if (wd[i] == -1) { + printlogf(LOG_ERR, "Cannot watch '%s': %m\n", watchDirs[i]); + exit(EXIT_FAILURE); + } + } + fds[0].fd = notify; + fds[0].events = POLLIN; +#endif for (;;) { - sleep((stime + 1) - (short)(time(NULL) % stime)); + int seconds_to_wait = (stime + 1) - (short)(time(NULL) % stime); +#ifdef USE_INOTIFY + /* Follows example from Linux inotify man page */ + poll_num = poll(fds, 1, seconds_to_wait * 1000); + if (poll_num == -1) { + if (errno == EINTR) + continue; + printlogf(LOG_ERR, "Poll failed: %m\n"); + exit(EXIT_FAILURE); + } + if (poll_num > 0) { + char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event)))); + const struct inotify_event *event; + ssize_t len; + char *ptr; + for (;;) { + len = read(notify, buf, sizeof buf); + if (len == -1 && errno != EAGAIN) { + printlogf(LOG_ERR, "Read from inotify failed: %m\n"); + exit(EXIT_FAILURE); + } + if (len <= 0) + break; + for (ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len) { + event = (const struct inotify_event *) ptr; + if (event->mask & (IN_CLOSE_WRITE | IN_DELETE)) { + if (event->wd == wd[0]) + CheckFile(CDir, event->name, NULL); + else + CheckFile(SCDir, event->name, "root"); + } + } + } + continue; /* sleep again */ + } +#else + sleep(seconds_to_wait); +#endif t2 = time(NULL); dt = t2 - t1; From 7febdbe175cc172c5be83e222044d7e8e167ff78 Mon Sep 17 00:00:00 2001 From: Martin von Gagern Date: Fri, 18 Mar 2016 01:50:13 +0100 Subject: [PATCH 2/2] Ignore generated files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 797a05a..4a5fddf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ *.swp protos.h +*.o +crond +crontab +config