annotate watcher.c @ 165:59e62710cbb5

rlgwebd.js: prevent races when reading ttyrecs. DglSession objects read a 12-byte TTYREC header, extract therefrom the length of the data chunk, and then read the data. In between these two reads, the file watcher could trigger another readchunk() invocation, which might attempt to read a header from the beginning of the data chunk. This usually results in expecting a data chunk of several GB and failing to create a Buffer for it. The race is remedied by setting a flag on the DglSession object whenever readchunk() is called, clearing it when both reads complete, and refusing to read if it is already set.
author John "Elwin" Edwards
date Wed, 07 Jan 2015 13:18:35 -0500
parents 245a2959f504
children 66fef65c34e7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
155
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
1 #include <stdio.h>
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
2 #include <stdlib.h>
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
3 #include <string.h>
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
4 #include <sys/inotify.h>
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
5 #include <sys/select.h>
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
6 #include <unistd.h>
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
7 #include <limits.h>
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
8 #include <dirent.h>
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
9
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
10 struct watchdir {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
11 int wd;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
12 char *name;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
13 };
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
14
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
15 char ibuf[sizeof(struct inotify_event) + NAME_MAX + 1];
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
16
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
17 int startwatch(int ifd, char *dir, struct watchdir *w) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
18 DIR *dstream;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
19 struct dirent *ent;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
20
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
21 w->name = dir;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
22 w->wd = inotify_add_watch(ifd, dir, IN_CREATE|IN_DELETE|IN_DELETE_SELF);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
23 if (w->wd < 0) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
24 fprintf(stderr, "Could not watch %s\n", dir);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
25 return 1;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
26 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
27 dstream = opendir(dir);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
28 if (dstream == NULL) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
29 fprintf(stderr, "%s is not a readable directory\n", dir);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
30 inotify_rm_watch(ifd, w->wd);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
31 w->wd = -1;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
32 return 1;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
33 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
34 ent = readdir(dstream);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
35 while (ent != NULL) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
36 if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
37 printf("E %s/%s\n", dir, ent->d_name);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
38 ent = readdir(dstream);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
39 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
40 closedir(dstream);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
41 fflush(stdout);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
42 return 0;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
43 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
44
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
45 int main(int argc, char *argv[]) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
46 int ifd, rsize, off, done, nwatchers, i;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
47 char typecode;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
48 struct inotify_event *iev;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
49 fd_set rfds;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
50 struct watchdir *watchers;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
51
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
52 done = 0;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
53 nwatchers = argc - 1;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
54 iev = (struct inotify_event *) ibuf;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
55 ifd = inotify_init();
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
56 if (nwatchers == 0) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
57 watchers = malloc(sizeof(struct watchdir));
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
58 nwatchers = 1;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
59 startwatch(ifd, ".", watchers);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
60 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
61 else {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
62 watchers = malloc(nwatchers * sizeof(struct watchdir));
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
63 for (i = 0; i < nwatchers; i++) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
64 startwatch(ifd, argv[i+1], watchers + i);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
65 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
66 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
67
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
68 while (!done) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
69 FD_ZERO(&rfds);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
70 FD_SET(0, &rfds);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
71 FD_SET(ifd, &rfds);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
72 select(ifd + 1, &rfds, NULL, NULL, NULL);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
73 if (FD_ISSET(ifd, &rfds)) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
74 off = 0;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
75 rsize = read(ifd, ibuf, sizeof(struct inotify_event) + NAME_MAX + 1);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
76 while (off < rsize) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
77 iev = (struct inotify_event *) (ibuf + off);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
78 if (iev->mask & IN_CREATE)
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
79 typecode = 'C';
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
80 else if (iev->mask & IN_DELETE)
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
81 typecode = 'D';
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
82 else
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
83 typecode = '?';
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
84 for (i = 0; i < nwatchers; i++) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
85 if (watchers[i].wd == iev->wd)
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
86 printf("%c %s/%s\n", typecode, watchers[i].name, iev->name);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
87 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
88 off += sizeof(struct inotify_event) + iev->len;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
89 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
90 fflush(stdout);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
91 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
92 if (FD_ISSET(0, &rfds)) {
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
93 read(0, &typecode, 1);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
94 if (typecode == '\n')
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
95 done = 1;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
96 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
97
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
98 }
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
99 close(ifd);
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
100 return 0;
245a2959f504 Begin support for watching dgamelaunch games.
John "Elwin" Edwards
parents:
diff changeset
101 }