Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
*.swp
protos.h
*.o
crond
crontab
config
30 changes: 18 additions & 12 deletions database.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
#include <string.h>
#include <stdio.h>

#ifdef USE_INOTIFY
#include <poll.h>
#include <sys/inotify.h>
#endif

#define Prototype extern
#define arysize(ary) (sizeof(ary)/sizeof((ary)[0]))

Expand Down
60 changes: 59 additions & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down