Monitoring File Open in a Directory
Here is part of an experiment I have been working on. I did not find any use for this (yet), but the method is worth considering. The following program uses the Linux kernel's "inotify" mechanism to print a message whenever a file is opened in a specific directory.
Have a look:
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define WATCH_FILES_MAX 256
typedef struct watch_s {
int wd;
char file[PATH_MAX];
} watch_t;
static watch_t watch[WATCH_FILES_MAX];
static int watch_n = 0;
static int ifd;
static int watch_files(char *dir)
{
struct dirent *entry;
struct stat st;
DIR *dh;
char path[PATH_MAX];
ifd = inotify_init();
if (ifd == -1) {
fprintf(stderr, "inotify_init() failed: %s\n", strerror(errno));
return -1;
}
dh = opendir(dir);
if (dh == NULL) {
fprintf(stderr, "opendir(%s) failed: %s\n", dir, strerror(errno));
return -1;
}
watch_n = 0;
while ((entry = readdir(dh))) {
if (entry->d_name[0] == '.')
continue;
snprintf(path, PATH_MAX, "%s/%s", dir, entry->d_name);
if (stat(path, &st) == -1) {
fprintf(stderr, "stat(%s) failed: %s\n", path, strerror(errno));
closedir(dh);
return -1;
}
if (S_ISREG(st.st_mode)) {
watch[watch_n].wd = inotify_add_watch(ifd, path, IN_OPEN);
if (watch[watch_n].wd == -1) {
fprintf(stderr, "inotify_add_watch(%s) failed: %s\n", path, strerror(errno));
closedir(dh);
return -1;
}
strncpy(watch[watch_n].file, entry->d_name, PATH_MAX);
fprintf(stderr, "Watching: %s\n", entry->d_name);
watch_n++;
if (watch_n >= WATCH_FILES_MAX) {
fprintf(stderr, "Max files reached, skipping the rest!\n");
break;
}
}
}
closedir(dh);
return 0;
}
int main(int argc, char *argv[])
{
struct inotify_event iev;
time_t now;
int i;
if (argc != 2) {
fprintf(stderr, "Usage: %s <watch directory>\n", argv[0]);
return 1;
}
if (watch_files(argv[1]) != 0) {
return 1;
}
setlinebuf(stdout);
while (1) {
if (read(ifd, &iev, sizeof(struct inotify_event)) > 0) {
for (i = 0; i < watch_n; i++) {
if (iev.wd == watch[i].wd) {
time(&now);
fprintf(stdout, "%s @ %s", watch[i].file, ctime(&now));
}
}
}
}
/* NOTE: No file descriptors explicitly closed. */
return 0;
}