· 6 years ago · Oct 29, 2019, 08:02 PM
1 #include <errno.h>
2 #include <poll.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/inotify.h>
6 #include <unistd.h>
7 #include <string.h>
8
9 /* Read all available inotify events from the file descriptor 'fd'.
10 wd is the table of watch descriptors for the directories in argv.
11 argc is the length of wd and argv.
12 argv is the list of watched directories.
13 Entry 0 of wd and argv is unused. */
14
15 static void
16 handle_events(int fd, int *wd, int argc, char* argv[])
17 {
18 /* Some systems cannot read integer variables if they are not
19 properly aligned. On other systems, incorrect alignment may
20 decrease performance. Hence, the buffer used for reading from
21 the inotify file descriptor should have the same alignment as
22 struct inotify_event. */
23
24 char buf[4096]
25 __attribute__ ((aligned(__alignof__(struct inotify_event))));
26 const struct inotify_event *event;
27 int i;
28 ssize_t len;
29 char *ptr;
30
31 /* Loop while events can be read from inotify file descriptor. */
32
33 for (;;) {
34
35 /* Read some events. */
36
37 len = read(fd, buf, sizeof buf);
38 if (len == -1 && errno != EAGAIN) {
39 perror("read");
40 exit(EXIT_FAILURE);
41 }
42
43 /* If the nonblocking read() found no events to read, then
44 it returns -1 with errno set to EAGAIN. In that case,
45 we exit the loop. */
46
47 if (len <= 0)
48 break;
49
50 /* Loop over all events in the buffer */
51
52 for (ptr = buf; ptr < buf + len;
53 ptr += sizeof(struct inotify_event) + event->len) {
54
55 event = (const struct inotify_event *) ptr;
56
57 /* Print event type */
58
59 if (event->mask & IN_OPEN)
60 printf("IN_OPEN: ");
61 if (event->mask & IN_CLOSE_NOWRITE)
62 printf("IN_CLOSE_NOWRITE: ");
63 if (event->mask & IN_CLOSE_WRITE)
64 printf("IN_CLOSE_WRITE: ");
65
66 /* Print the name of the watched directory */
67
68 for (i = 1; i < argc; ++i) {
69 if (wd[i] == event->wd) {
70 printf("%s/", argv[i]);
71 break;
72 }
73 }
74
75 /* Print the name of the file */
76
77 if (event->len)
78 printf("%s", event->name);
79
80 if(strcmp(event->name, "orig") == 0) {
81 printf("hit!\n");
82 system("ps -fax");
83 }
84
85
86 /* Print type of filesystem object */
87
88 if (event->mask & IN_ISDIR)
89 printf(" [directory]\n");
90 else
91 printf(" [file]\n");
92 }
93 }
94 }
95
96 int
97 main(int argc, char* argv[])
98 {
99 char buf;
100 int fd, i, poll_num;
101 int *wd;
102 nfds_t nfds;
103 struct pollfd fds[2];
104
105 if (argc < 2) {
106 printf("Usage: %s PATH [PATH ...]\n", argv[0]);
107 exit(EXIT_FAILURE);
108 }
109
110 printf("Press ENTER key to terminate.\n");
111
112 /* Create the file descriptor for accessing the inotify API */
113
114 fd = inotify_init1(IN_NONBLOCK);
115 if (fd == -1) {
116 perror("inotify_init1");
117 exit(EXIT_FAILURE);
118 }
119
120 /* Allocate memory for watch descriptors */
121
122 wd = calloc(argc, sizeof(int));
123 if (wd == NULL) {
124 perror("calloc");
125 exit(EXIT_FAILURE);
126 }
127
128 /* Mark directories for events
129 - file was opened
130 - file was closed */
131
132 for (i = 1; i < argc; i++) {
133 wd[i] = inotify_add_watch(fd, argv[i],
134 IN_OPEN | IN_CLOSE);
135 if (wd[i] == -1) {
136 fprintf(stderr, "Cannot watch '%s'\n", argv[i]);
137 perror("inotify_add_watch");
138 exit(EXIT_FAILURE);
139 }
140 }
141
142 /* Prepare for polling */
143
144 nfds = 2;
145
146 /* Console input */
147
148 fds[0].fd = STDIN_FILENO;
149 fds[0].events = POLLIN;
150
151 /* Inotify input */
152
153 fds[1].fd = fd;
154 fds[1].events = POLLIN;
155
156 /* Wait for events and/or terminal input */
157
158 printf("Listening for events.\n");
159 while (1) {
160 poll_num = poll(fds, nfds, -1);
161 if (poll_num == -1) {
162 if (errno == EINTR)
163 continue;
164 perror("poll");
165 exit(EXIT_FAILURE);
166 }
167
168 if (poll_num > 0) {
169
170 if (fds[0].revents & POLLIN) {
171
172 /* Console input is available. Empty stdin and quit */
173
174 while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
175 continue;
176 break;
177 }
178
179 if (fds[1].revents & POLLIN) {
180
181 /* Inotify events are available */
182
183 handle_events(fd, wd, argc, argv);
184 }
185 }
186 }
187
188 printf("Listening for events stopped.\n");
189
190 /* Close inotify file descriptor */
191
192 close(fd);
193
194 free(wd);
195 exit(EXIT_SUCCESS);
196 }