Mercurial > hg > rlgwebd
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 |
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 } |