-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinotify_tree.c
More file actions
96 lines (90 loc) · 2.54 KB
/
Copy pathinotify_tree.c
File metadata and controls
96 lines (90 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
typedef struct watch_entry {
int wd;
char path[PATH_MAX];
} watch_entry_t;
static watch_entry_t table[1024];
static int tlen = 0;
static void add_watch_entry(int wd, const char *path)
{
if (tlen >= 1024) return;
table[tlen].wd = wd;
strncpy(table[tlen].path, path, sizeof(table[tlen].path) - 1);
table[tlen].path[sizeof(table[tlen].path) - 1] = 0;
tlen++;
}
static const char *lookup_path(int wd)
{
for (int i = 0; i < tlen; i++) {
if (table[i].wd == wd) return table[i].path;
}
return "?";
}
static void add_tree(int fd, const char *root)
{
int wd = inotify_add_watch(fd, root, IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO);
if (wd >= 0) add_watch_entry(wd, root);
DIR *d = opendir(root);
if (!d) return;
struct dirent *de;
while ((de = readdir(d)) != NULL) {
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
char path[PATH_MAX];
snprintf(path, sizeof path, "%s/%s", root, de->d_name);
struct stat st;
if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) {
add_tree(fd, path);
}
}
closedir(d);
}
int main(int argc, char **argv)
{
#if !defined(__linux__)
fprintf(stderr, "inotify_tree is Linux-only\n");
return 1;
#else
const char *root = argc > 1 ? argv[1] : ".";
int fd = inotify_init1(IN_NONBLOCK);
if (fd < 0) {
perror("inotify_init1");
return 1;
}
add_tree(fd, root);
printf("watching %s and subdirs\n", root);
char buf[4096];
for (;;) {
ssize_t n = read(fd, buf, sizeof buf);
if (n < 0) {
if (errno == EAGAIN || errno == EINTR) {
usleep(100000);
continue;
}
perror("read");
break;
}
size_t off = 0;
while (off < (size_t)n) {
struct inotify_event *ev = (struct inotify_event *)(buf + off);
const char *base = lookup_path(ev->wd);
char full[PATH_MAX];
if (ev->len > 0) snprintf(full, sizeof full, "%s/%s", base, ev->name);
else snprintf(full, sizeof full, "%s", base);
printf("event 0x%x on %s\n", ev->mask, full);
off += sizeof(struct inotify_event) + ev->len;
}
}
close(fd);
return 0;
#endif
}