]>
Commit | Line | Data |
---|---|---|
5d36a0c6 | 1 | --- /dev/null 2003-09-15 15:40:47.000000000 +0200 |
2948bff6 | 2 | +++ fam-2.6.10/src/DNotify.c++ 2004-02-04 11:13:04.000000000 +0100 |
5d36a0c6 | 3 | @@ -0,0 +1,655 @@ |
38e7688f AM |
4 | +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. |
5 | +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. | |
6 | +// | |
7 | +// This program is free software; you can redistribute it and/or modify it | |
8 | +// under the terms of version 2 of the GNU General Public License as | |
9 | +// published by the Free Software Foundation. | |
10 | +// | |
11 | +// This program is distributed in the hope that it would be useful, but | |
12 | +// WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any | |
14 | +// license provided herein, whether implied or otherwise, is limited to | |
15 | +// this program in accordance with the express provisions of the GNU | |
16 | +// General Public License. Patent licenses, if any, provided herein do not | |
17 | +// apply to combinations of this program with other product or programs, or | |
18 | +// any other product whatsoever. This program is distributed without any | |
19 | +// warranty that the program is delivered free of the rightful claim of any | |
20 | +// third person by way of infringement or the like. See the GNU General | |
21 | +// Public License for more details. | |
22 | +// | |
23 | +// You should have received a copy of the GNU General Public License along | |
24 | +// with this program; if not, write the Free Software Foundation, Inc., 59 | |
25 | +// Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
26 | + | |
27 | +#define _GNU_SOURCE | |
28 | +#include <fcntl.h> | |
29 | + | |
30 | +#include <string.h> | |
31 | +#include <signal.h> | |
32 | +#include <stdio.h> | |
33 | +#include <unistd.h> | |
34 | +#include <sys/types.h> | |
35 | +#include <sys/stat.h> | |
36 | +#include <libgen.h> | |
37 | + | |
38 | +#include "DNotify.h" | |
39 | + | |
40 | +#include "Interest.h" | |
41 | +#include "Log.h" | |
42 | +#include "Scheduler.h" | |
43 | +#include "alloc.h" | |
44 | + | |
45 | + | |
46 | +int DNotify::pipe_write_fd = -2; | |
47 | +int DNotify::pipe_read_fd = -2; | |
48 | +volatile sig_atomic_t DNotify::queue_overflowed = 0; | |
49 | +volatile sig_atomic_t DNotify::queue_changed = 0; | |
50 | +int DNotify::change_queue[QUEUESIZE]; | |
51 | +volatile int DNotify::queue_head = 0; // Only modified by read handler | |
52 | +volatile int DNotify::queue_tail = 0; // Only modified by signal handler | |
53 | +DNotify::EventHandler DNotify::ehandler; | |
54 | + | |
55 | +DNotify::DirWatch *DNotify::dir_hash[DIR_HASHSIZE]; | |
56 | +DNotify::FileWatch *DNotify::file_hash[FILE_HASHSIZE]; | |
57 | + | |
58 | +struct DNotify::FileWatch | |
59 | +{ | |
5d36a0c6 | 60 | + DirWatch **dir_watch; |
61 | + int n_dir_watches; | |
38e7688f AM |
62 | + dev_t file_dev; |
63 | + ino_t file_ino; | |
38e7688f | 64 | + FileWatch *hash_link; |
5d36a0c6 | 65 | + |
66 | + FileWatch(void) { | |
7e0cae36 | 67 | + dir_watch = 0; |
5d36a0c6 | 68 | + n_dir_watches = 0; |
69 | + } | |
70 | + | |
71 | + void add_dir_watch (DirWatch *w); | |
72 | + bool has_dir_watch (DirWatch *w); | |
38e7688f AM |
73 | +}; |
74 | + | |
5d36a0c6 | 75 | + |
38e7688f AM |
76 | +struct DNotify::DirWatch |
77 | +{ | |
5d36a0c6 | 78 | + class FileWatchList { |
79 | + public: | |
80 | + struct Node { | |
81 | + FileWatch *watch; | |
82 | + Node *next; | |
83 | + }; | |
84 | + | |
85 | + Node *first; | |
86 | + | |
87 | + FileWatchList(void) { | |
7e0cae36 | 88 | + first = 0; |
5d36a0c6 | 89 | + } |
90 | + | |
91 | + void prepend(FileWatch *watch); | |
92 | + void remove(FileWatch *watch); | |
93 | + bool empty(void); | |
94 | + int len(void); | |
95 | + | |
96 | + }; | |
97 | + | |
38e7688f AM |
98 | + dev_t dir_dev; |
99 | + ino_t dir_ino; | |
5d36a0c6 | 100 | + int fd; |
101 | + | |
38e7688f | 102 | + DirWatch *hash_link; |
5d36a0c6 | 103 | + FileWatchList file_watches; |
38e7688f AM |
104 | +}; |
105 | + | |
5d36a0c6 | 106 | +struct DNotify::ChangeEventData |
107 | +{ | |
108 | + dev_t file_dev; | |
109 | + ino_t file_ino; | |
110 | +}; | |
111 | + | |
112 | +bool | |
113 | +DNotify::FileWatch::has_dir_watch (DirWatch *w) | |
114 | +{ | |
115 | + int i; | |
116 | + | |
117 | + for (i = 0; i < n_dir_watches; i++) { | |
118 | + if (dir_watch[i] == w) | |
119 | + return true; | |
120 | + } | |
121 | + return false; | |
122 | +} | |
123 | + | |
124 | + | |
125 | +void | |
126 | +DNotify::FileWatch::add_dir_watch (DirWatch *w) | |
127 | +{ | |
128 | + n_dir_watches++; | |
129 | + dir_watch = (DirWatch **)realloc (dir_watch, n_dir_watches*sizeof(DirWatch *)); | |
130 | + dir_watch[n_dir_watches-1] = w; | |
131 | +} | |
132 | + | |
133 | +bool | |
134 | +DNotify::DirWatch::FileWatchList::empty(void) | |
135 | +{ | |
7e0cae36 | 136 | + return first == 0; |
5d36a0c6 | 137 | +} |
138 | + | |
139 | +int | |
140 | +DNotify::DirWatch::FileWatchList::len(void) | |
141 | +{ | |
142 | + int i; | |
143 | + Node *n; | |
144 | + | |
145 | + i = 0; | |
146 | + n = first; | |
147 | + while (n) { | |
148 | + i++; | |
149 | + n = n->next; | |
150 | + } | |
151 | + | |
152 | + return i; | |
153 | +} | |
154 | + | |
155 | + | |
156 | +void | |
157 | +DNotify::DirWatch::FileWatchList::prepend(FileWatch *watch) | |
158 | +{ | |
159 | + Node *node; | |
160 | + | |
161 | + node = new Node; | |
162 | + node->watch = watch; | |
163 | + node->next = first; | |
164 | + | |
165 | + first = node; | |
166 | +} | |
167 | + | |
168 | +void | |
169 | +DNotify::DirWatch::FileWatchList::remove(FileWatch *watch) { | |
170 | + Node *l, *prev; | |
171 | + | |
172 | + l = first; | |
7e0cae36 | 173 | + prev = 0; |
5d36a0c6 | 174 | + while (l) { |
175 | + if (l->watch == watch) { | |
176 | + if (prev) | |
177 | + prev->next = l->next; | |
178 | + else | |
179 | + first = l->next; | |
180 | + | |
181 | + delete l; | |
182 | + break; | |
183 | + } | |
184 | + prev = l; | |
185 | + l = prev->next; | |
186 | + } | |
187 | +} | |
188 | + | |
189 | + | |
38e7688f AM |
190 | +DNotify::DNotify(EventHandler h) |
191 | +{ | |
7e0cae36 | 192 | + assert(ehandler == 0); |
38e7688f AM |
193 | + ehandler = h; |
194 | +} | |
195 | + | |
196 | +DNotify::~DNotify() | |
197 | +{ | |
5d36a0c6 | 198 | + if (pipe_read_fd >= 0) { |
38e7688f AM |
199 | + // Tell the scheduler. |
200 | + | |
201 | + (void) Scheduler::remove_read_handler(pipe_read_fd); | |
202 | + | |
203 | + // Close the pipe. | |
204 | + | |
205 | + if (close(pipe_read_fd) < 0) | |
206 | + Log::perror("can't pipe read end"); | |
207 | + else | |
208 | + Log::debug("closed pipe read end"); | |
209 | + | |
210 | + if (close(pipe_write_fd) < 0) | |
211 | + Log::perror("can't pipe write end"); | |
212 | + else | |
213 | + Log::debug("closed pipe write end"); | |
214 | + pipe_read_fd = -1; | |
215 | + } | |
7e0cae36 | 216 | + ehandler = 0; |
38e7688f AM |
217 | +} |
218 | + | |
219 | +void | |
220 | +DNotify::overflow_signal_handler(int sig, siginfo_t *si, void *data) | |
221 | +{ | |
222 | + char c = 'x'; | |
5d36a0c6 | 223 | + |
38e7688f AM |
224 | + { |
225 | + char *str = "*************** overflow sigqueue ***********************\n"; | |
5d36a0c6 | 226 | + write (STDERR_FILENO, str, strlen(str)); |
38e7688f AM |
227 | + } |
228 | + | |
5d36a0c6 | 229 | + if (!queue_overflowed) { |
38e7688f AM |
230 | + queue_overflowed = 1; |
231 | + // Trigger the read handler | |
232 | + write(pipe_write_fd, &c, 1); | |
233 | + } | |
234 | +} | |
235 | + | |
236 | +void | |
237 | +DNotify::signal_handler(int sig, siginfo_t *si, void *data) | |
238 | +{ | |
239 | + int left; | |
240 | + char c = 'x'; | |
241 | + | |
242 | + if (queue_head <= queue_tail) | |
243 | + left = (QUEUESIZE + queue_head) - queue_tail; | |
244 | + else | |
245 | + left = queue_head - queue_tail; | |
246 | + | |
247 | + // Must leave at least one item unused to see difference | |
248 | + // Betweeen empty and full | |
5d36a0c6 | 249 | + if (left <= 1) { |
38e7688f AM |
250 | + queue_overflowed = 1; |
251 | + { | |
252 | + char *str = "*************** overflow famqueue ****************\n"; | |
5d36a0c6 | 253 | + write (STDERR_FILENO, str, strlen(str)); |
38e7688f | 254 | + } |
5d36a0c6 | 255 | + } else { |
38e7688f AM |
256 | + change_queue[queue_tail] = si->si_fd; |
257 | + queue_tail = (queue_tail + 1) % QUEUESIZE; | |
258 | + } | |
259 | + | |
5d36a0c6 | 260 | + if (!queue_changed) { |
38e7688f AM |
261 | + queue_changed = 1; |
262 | + // Trigger the read handler | |
263 | + write(pipe_write_fd, &c, 1); | |
264 | + } | |
265 | +} | |
266 | + | |
267 | +bool | |
268 | +DNotify::is_active() | |
269 | +{ | |
5d36a0c6 | 270 | + if (pipe_read_fd == -2) { |
38e7688f AM |
271 | + int filedes[2]; |
272 | + int res; | |
273 | + | |
274 | + res = pipe (filedes); | |
5d36a0c6 | 275 | + if (res >= 0) { |
276 | + Log::debug("opened pipe"); | |
38e7688f AM |
277 | + pipe_read_fd = filedes[0]; |
278 | + pipe_write_fd = filedes[1]; | |
279 | + | |
280 | + // Setup signal handler: | |
281 | + struct sigaction act; | |
282 | + | |
283 | + act.sa_sigaction = signal_handler; | |
284 | + sigemptyset(&act.sa_mask); | |
285 | + act.sa_flags = SA_SIGINFO; | |
286 | + sigaction(SIGRTMIN, &act, NULL); | |
287 | + | |
288 | + // When the RT queue overflows we get a SIGIO | |
289 | + act.sa_sigaction = overflow_signal_handler; | |
290 | + sigemptyset(&act.sa_mask); | |
291 | + sigaction(SIGIO, &act, NULL); | |
292 | + | |
293 | + (void) Scheduler::install_read_handler(pipe_read_fd, read_handler, NULL); | |
294 | + } | |
295 | + } | |
296 | + return pipe_read_fd >= 0; | |
297 | +} | |
298 | + | |
299 | +DNotify::DirWatch * | |
300 | +DNotify::lookup_dirwatch (int fd) | |
301 | +{ | |
302 | + DirWatch **p; | |
303 | + DirWatch *w; | |
304 | + | |
305 | + p = dir_hashchain (fd); | |
306 | + | |
5d36a0c6 | 307 | + while (*p) { |
38e7688f AM |
308 | + w = *p; |
309 | + | |
310 | + if (w->fd == fd) | |
5d36a0c6 | 311 | + return w; |
38e7688f AM |
312 | + |
313 | + p = &w->hash_link; | |
5d36a0c6 | 314 | + } |
38e7688f AM |
315 | + |
316 | + return *p; | |
317 | +} | |
318 | + | |
319 | +// This colud be made faster by using another hash table. | |
320 | +// But it's not that bad, since it is only used by express/revoke | |
321 | +DNotify::DirWatch * | |
322 | +DNotify::lookup_dirwatch (dev_t dir_dev, ino_t dir_ino) | |
323 | +{ | |
324 | + DirWatch *p; | |
325 | + int i; | |
326 | + | |
5d36a0c6 | 327 | + for (i=0;i<DIR_HASHSIZE;i++) { |
38e7688f AM |
328 | + p = dir_hash[i]; |
329 | + | |
5d36a0c6 | 330 | + while (p) { |
38e7688f | 331 | + if (p->dir_dev == dir_dev && p->dir_ino == dir_ino) |
5d36a0c6 | 332 | + return p; |
38e7688f AM |
333 | + |
334 | + p = p->hash_link; | |
5d36a0c6 | 335 | + } |
336 | + } | |
38e7688f | 337 | + |
7e0cae36 | 338 | + return 0; |
38e7688f AM |
339 | +} |
340 | + | |
341 | +DNotify::FileWatch * | |
342 | +DNotify::lookup_filewatch (dev_t dev, ino_t ino) | |
343 | +{ | |
344 | + FileWatch **p; | |
345 | + FileWatch *w; | |
346 | + | |
347 | + p = file_hashchain (dev, ino); | |
348 | + | |
5d36a0c6 | 349 | + while (*p) { |
38e7688f | 350 | + w = *p; |
5d36a0c6 | 351 | + |
38e7688f | 352 | + if (w->file_dev == dev && w->file_ino == ino) |
5d36a0c6 | 353 | + return w; |
38e7688f AM |
354 | + |
355 | + p = &w->hash_link; | |
5d36a0c6 | 356 | + } |
38e7688f AM |
357 | + |
358 | + return *p; | |
359 | +} | |
360 | + | |
361 | +// Make sure w is not already in the hash table before calling | |
362 | +// this function. | |
363 | +void | |
364 | +DNotify::hash_dirwatch(DirWatch *w) | |
365 | +{ | |
5d36a0c6 | 366 | + DirWatch **p; |
367 | + p = dir_hashchain (w->fd); | |
368 | + w->hash_link = *p; | |
369 | + *p = w; | |
38e7688f AM |
370 | +} |
371 | + | |
372 | +// Make sure w is not already in the hash table before calling | |
373 | +// this function. | |
374 | +void | |
375 | +DNotify::hash_filewatch(FileWatch *w) | |
376 | +{ | |
5d36a0c6 | 377 | + FileWatch **p; |
378 | + p = file_hashchain (w->file_dev, w->file_ino); | |
379 | + w->hash_link = *p; | |
380 | + *p = w; | |
38e7688f AM |
381 | +} |
382 | + | |
383 | +void | |
384 | +DNotify::unhash_dirwatch(DirWatch *w) | |
385 | +{ | |
386 | + DirWatch **p; | |
387 | + | |
388 | + p = dir_hashchain (w->fd); | |
389 | + | |
5d36a0c6 | 390 | + while (*p) { |
391 | + if (*p == w) { | |
38e7688f AM |
392 | + *p = w->hash_link; |
393 | + break; | |
5d36a0c6 | 394 | + } |
38e7688f | 395 | + p = &(*p)->hash_link; |
5d36a0c6 | 396 | + } |
7e0cae36 | 397 | + w->hash_link = 0; |
38e7688f AM |
398 | +} |
399 | + | |
400 | +void | |
401 | +DNotify::unhash_filewatch(FileWatch *w) | |
402 | +{ | |
403 | + FileWatch **p; | |
404 | + | |
405 | + p = file_hashchain (w->file_dev, w->file_ino); | |
406 | + | |
5d36a0c6 | 407 | + while (*p) { |
408 | + if (*p == w) { | |
38e7688f AM |
409 | + *p = w->hash_link; |
410 | + break; | |
5d36a0c6 | 411 | + } |
38e7688f | 412 | + p = &(*p)->hash_link; |
5d36a0c6 | 413 | + } |
7e0cae36 | 414 | + w->hash_link = 0; |
38e7688f AM |
415 | +} |
416 | + | |
417 | +DNotify::Status | |
418 | +DNotify::watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino) | |
419 | +{ | |
5d36a0c6 | 420 | + struct stat stat; |
421 | + dev_t dir_dev; | |
422 | + ino_t dir_ino; | |
423 | + DirWatch *dwatch; | |
424 | + FileWatch *fw; | |
38e7688f | 425 | + |
5d36a0c6 | 426 | + if (lstat (notify_dir, &stat) == -1) |
427 | + return BAD; | |
428 | + | |
429 | + dwatch = lookup_dirwatch(stat.st_dev, stat.st_ino); | |
430 | + if (!dwatch) { | |
431 | + Log::debug ("New DirWatch for %s (%x %x)\n", | |
432 | + notify_dir, (int)stat.st_dev, (int)stat.st_ino); | |
433 | + dwatch = new DirWatch; | |
7e0cae36 | 434 | + dwatch->hash_link = 0; |
5d36a0c6 | 435 | + dwatch->dir_dev = stat.st_dev; |
436 | + dwatch->dir_ino = stat.st_ino; | |
437 | + dwatch->fd = open(notify_dir, O_RDONLY); | |
438 | + fcntl (dwatch->fd, F_SETSIG, SIGRTMIN); | |
439 | + fcntl (dwatch->fd, F_NOTIFY, | |
440 | + (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB) | DN_MULTISHOT); | |
441 | + hash_dirwatch (dwatch); | |
38e7688f | 442 | + } |
5d36a0c6 | 443 | + |
444 | + fw = lookup_filewatch(file_dev, file_ino); | |
445 | + if (fw) { | |
446 | + if (!fw->has_dir_watch(dwatch)) { | |
447 | + fw->add_dir_watch(dwatch); | |
448 | + dwatch->file_watches.prepend(fw); | |
449 | + } | |
38e7688f AM |
450 | + return OK; |
451 | + } | |
5d36a0c6 | 452 | + |
453 | + // No old FileWatch, need to add one: | |
454 | + Log::debug("New FileWatch for %x %x\n", (int)file_dev, (int)file_ino); | |
455 | + fw = new FileWatch; | |
456 | + fw->add_dir_watch(dwatch); | |
457 | + dwatch->file_watches.prepend(fw); | |
458 | + fw->file_dev = file_dev; | |
459 | + fw->file_ino = file_ino; | |
460 | + hash_filewatch(fw); | |
461 | + return OK; | |
38e7688f AM |
462 | +} |
463 | + | |
464 | +char * | |
465 | +dirname_dup (const char *name) | |
466 | +{ | |
5d36a0c6 | 467 | + char *copy = strdup(name); |
468 | + char *res = dirname(copy); | |
469 | + res = strdup(res); | |
470 | + free (copy); | |
471 | + return res; | |
38e7688f AM |
472 | +} |
473 | + | |
474 | +DNotify::Status | |
475 | +DNotify::express(const char *name, struct stat *status) | |
476 | +{ | |
477 | + struct stat stat; | |
478 | + char *notify_dir; | |
479 | + int res; | |
480 | + Status s; | |
481 | + dev_t dev; | |
482 | + ino_t ino; | |
483 | + | |
484 | + Log::debug("express() name: %s\n", name); | |
485 | + | |
486 | + if (!is_active()) | |
487 | + return BAD; | |
488 | + | |
489 | + if (::lstat (name, &stat) == -1) | |
490 | + return BAD; | |
491 | + | |
492 | + dev = stat.st_dev; | |
493 | + ino = stat.st_ino; | |
494 | + | |
495 | + if ((stat.st_mode & S_IFMT) != S_IFDIR) | |
496 | + notify_dir = dirname_dup (name); | |
497 | + else | |
498 | + notify_dir = (char *)name; | |
499 | + | |
500 | + s = watch_dir (notify_dir, dev, ino); | |
501 | + if (notify_dir != name) | |
502 | + free (notify_dir); | |
503 | + if (s) | |
504 | + return s; | |
505 | + | |
506 | + // Check for a race condition; if someone removed or changed the | |
507 | + // file at the same time that we are expressing interest in it, | |
508 | + // revoke the interest so we don't get notifications about changes | |
509 | + // to a recycled inode that we don't otherwise care about. | |
510 | + // | |
511 | + struct stat st; | |
7e0cae36 | 512 | + if (status == 0) { |
38e7688f AM |
513 | + status = &st; |
514 | + } | |
515 | + if (::lstat(name, status) == -1) { | |
516 | + Log::perror("stat on \"%s\" failed", name); | |
517 | + revoke(name, stat.st_dev, stat.st_ino); | |
518 | + return BAD; | |
519 | + } | |
520 | + if (status->st_dev != stat.st_dev | |
521 | + || status->st_ino != stat.st_ino) { | |
522 | + Log::error("File \"%s\" changed between express and stat", | |
523 | + name); | |
524 | + revoke(name, stat.st_dev, stat.st_ino); | |
525 | + return BAD; | |
526 | + } | |
527 | + | |
528 | + Log::debug("told dnotify to monitor \"%s\" = dev %d/%d, ino %d", name, | |
529 | + major(status->st_dev), minor(status->st_dev), | |
530 | + status->st_ino); | |
531 | + return OK; | |
532 | +} | |
533 | + | |
534 | +DNotify::Status | |
535 | +DNotify::revoke(const char *name, dev_t dev, ino_t ino) | |
536 | +{ | |
537 | + FileWatch *fwatch; | |
538 | + DirWatch *dwatch; | |
5d36a0c6 | 539 | + int i; |
38e7688f AM |
540 | + |
541 | + Log::debug("revoke() name: %s, dev: %x, ino: %x\n", name, dev, ino); | |
542 | + | |
543 | + if (!is_active()) | |
544 | + return BAD; | |
545 | + | |
546 | + // Lookup FileWatch by dev:ino, and its DirWatch. | |
547 | + fwatch = lookup_filewatch (dev, ino); | |
7e0cae36 | 548 | + if (fwatch == 0) |
38e7688f | 549 | + return BAD; |
5d36a0c6 | 550 | + |
38e7688f AM |
551 | + // delete FileWatch, if last FileWatch: close fd, delete DirWatch |
552 | + Log::debug ("Destroying FileWatch for (%x %x)\n", | |
553 | + (int)fwatch->file_dev, (int)fwatch->file_ino); | |
5d36a0c6 | 554 | + for (i = 0; i < fwatch->n_dir_watches; i++) { |
555 | + dwatch = fwatch->dir_watch[i]; | |
556 | + dwatch->file_watches.remove (fwatch); | |
557 | + | |
558 | + if (dwatch->file_watches.empty()) { | |
559 | + Log::debug ("Destroying DirWatch for (%x %x)\n", | |
560 | + (int)dwatch->dir_dev, (int)dwatch->dir_ino); | |
561 | + close(dwatch->fd); | |
562 | + unhash_dirwatch(dwatch); | |
563 | + delete dwatch; | |
38e7688f AM |
564 | + } |
565 | + } | |
566 | + unhash_filewatch(fwatch); | |
567 | + delete fwatch; | |
38e7688f AM |
568 | + |
569 | + return OK; | |
570 | +} | |
571 | + | |
572 | + | |
573 | +void | |
574 | +DNotify::all_watches_changed(void) | |
575 | +{ | |
576 | + int i; | |
577 | + FileWatch *fw; | |
578 | + | |
5d36a0c6 | 579 | + for (i=0; i<FILE_HASHSIZE; i++) { |
38e7688f | 580 | + fw = file_hash[i]; |
5d36a0c6 | 581 | + while (fw) { |
38e7688f AM |
582 | + (*ehandler)(fw->file_dev, fw->file_ino, CHANGE); |
583 | + | |
584 | + fw = fw->hash_link; | |
585 | + } | |
586 | + } | |
587 | +} | |
588 | + | |
589 | + | |
590 | +void | |
591 | +DNotify::read_handler(int fd, void *) | |
592 | +{ | |
593 | + static char readbuf[5000]; | |
594 | + DirWatch *dw; | |
595 | + FileWatch *fw; | |
596 | + int snap_queue_tail; | |
597 | + int last_fd; | |
598 | + | |
599 | + int rc = read(fd, readbuf, sizeof readbuf); | |
600 | + queue_changed = 0; | |
601 | + if (rc < 0) | |
602 | + Log::perror("pipe read"); | |
5d36a0c6 | 603 | + else if (queue_overflowed) { |
38e7688f AM |
604 | + // There is a *slight* race condition here. Between reading |
605 | + // the queue_overflow flag and resetting it. But it doesn't | |
606 | + // matter, since I'm gonna handle the overflow after reseting | |
607 | + // anyway. | |
608 | + queue_overflowed = false; | |
609 | + | |
610 | + // We're soon gonna check all watches anyway, so | |
611 | + // get rid of the current queue | |
612 | + queue_head = queue_tail; | |
613 | + | |
614 | + all_watches_changed (); | |
5d36a0c6 | 615 | + } else { |
38e7688f AM |
616 | + // Don't read events that happen later than |
617 | + // the initial read. (Otherwise skipping fd's | |
618 | + // might miss some changes). | |
619 | + snap_queue_tail = queue_tail; | |
620 | + last_fd = -1; | |
5d36a0c6 | 621 | + while (queue_head != snap_queue_tail) { |
38e7688f AM |
622 | + fd = change_queue[queue_head]; |
623 | + queue_head = (queue_head + 1) % QUEUESIZE; | |
624 | + | |
625 | + // Skip multiple changes to the same fd | |
5d36a0c6 | 626 | + if (fd != last_fd) { |
38e7688f | 627 | + dw = lookup_dirwatch (fd); |
5d36a0c6 | 628 | + if (dw) { |
629 | + int n_watches, i; | |
630 | + ChangeEventData *data; | |
631 | + DirWatch::FileWatchList::Node *n; | |
632 | + | |
38e7688f AM |
633 | + Log::debug("dnotify said dev %d/%d, ino %ld changed", |
634 | + major(dw->dir_dev), minor(dw->dir_dev), dw->dir_ino); | |
5d36a0c6 | 635 | + |
636 | + n_watches = dw->file_watches.len(); | |
637 | + data = new ChangeEventData[n_watches]; | |
638 | + | |
639 | + i = 0; | |
640 | + for (n=dw->file_watches.first; n; n=n->next) { | |
641 | + data[i].file_dev = n->watch->file_dev; | |
642 | + data[i].file_ino = n->watch->file_ino; | |
643 | + i++; | |
38e7688f | 644 | + } |
5d36a0c6 | 645 | + assert(i == n_watches); |
646 | + | |
647 | + for (i = 0; i < n_watches; i++) { | |
648 | + (*ehandler)(data[i].file_dev, data[i].file_ino, CHANGE); | |
649 | + } | |
650 | + | |
651 | + delete[] data; | |
38e7688f AM |
652 | + } |
653 | + } | |
654 | + last_fd = fd; | |
655 | + } | |
656 | + } | |
657 | +} | |
658 | + | |
5d36a0c6 | 659 | --- /dev/null 2003-09-15 15:40:47.000000000 +0200 |
2948bff6 | 660 | +++ fam-2.6.10/src/DNotify.h 2004-02-03 18:30:26.000000000 +0100 |
5d36a0c6 | 661 | @@ -0,0 +1,98 @@ |
38e7688f AM |
662 | +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. |
663 | +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. | |
664 | +// | |
665 | +// This program is free software; you can redistribute it and/or modify it | |
666 | +// under the terms of version 2 of the GNU General Public License as | |
667 | +// published by the Free Software Foundation. | |
668 | +// | |
669 | +// This program is distributed in the hope that it would be useful, but | |
670 | +// WITHOUT ANY WARRANTY; without even the implied warranty of | |
671 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any | |
672 | +// license provided herein, whether implied or otherwise, is limited to | |
673 | +// this program in accordance with the express provisions of the GNU | |
674 | +// General Public License. Patent licenses, if any, provided herein do not | |
675 | +// apply to combinations of this program with other product or programs, or | |
676 | +// any other product whatsoever. This program is distributed without any | |
677 | +// warranty that the program is delivered free of the rightful claim of any | |
678 | +// third person by way of infringement or the like. See the GNU General | |
679 | +// Public License for more details. | |
680 | +// | |
681 | +// You should have received a copy of the GNU General Public License along | |
682 | +// with this program; if not, write the Free Software Foundation, Inc., 59 | |
683 | +// Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
684 | + | |
685 | +#ifndef DNotify_included | |
686 | +#define DNotify_included | |
687 | + | |
688 | +#include "config.h" | |
689 | +#include "Monitor.h" | |
690 | +#include <signal.h> | |
691 | + | |
692 | +// DNotify is an object encapsulating the dnotify linux fcntl. | |
693 | +// It "emulates" the IMon interface. | |
694 | +// There can only be one instantiation of the DNotify object. | |
695 | +// | |
696 | +// The user of this object uses express() and revoke() to | |
697 | +// express/revoke interest in a file. There is also | |
698 | +// a callback, the EventHandler. When an dnotify event comes in, | |
699 | +// the EventHandler is called. | |
700 | +// | |
701 | +// The user of the DNotify object is the Interest class. | |
702 | + | |
703 | +class DNotify : public Monitor { | |
704 | +public: | |
705 | + DNotify(EventHandler h); | |
706 | + ~DNotify(); | |
707 | + | |
708 | + static bool is_active(); | |
709 | + | |
710 | + virtual Status express(const char *name, struct stat *stat_return); | |
711 | + virtual Status revoke(const char *name, dev_t dev, ino_t ino); | |
712 | + | |
713 | +private: | |
714 | + struct FileWatch; | |
715 | + struct DirWatch; | |
5d36a0c6 | 716 | + struct ChangeEventData; |
38e7688f AM |
717 | + |
718 | + // Class Variables | |
719 | + enum { QUEUESIZE = 1024 }; | |
720 | + static int pipe_write_fd; | |
721 | + static int pipe_read_fd; | |
722 | + static int change_queue[QUEUESIZE]; | |
723 | + static volatile sig_atomic_t DNotify::queue_overflowed; | |
724 | + static volatile sig_atomic_t DNotify::queue_changed; | |
725 | + static volatile int queue_head; // Only modified by read handler | |
726 | + static volatile int queue_tail; // Only modified by signal handler | |
727 | + static EventHandler ehandler; | |
728 | + static void overflow_signal_handler(int sig, siginfo_t *si, void *data); | |
729 | + static void signal_handler(int sig, siginfo_t *si, void *data); | |
730 | + static void read_handler(int fd, void *closure); | |
731 | + | |
5d36a0c6 | 732 | + enum { DIR_HASHSIZE = 367 }; |
38e7688f | 733 | + static DirWatch *dir_hash[DIR_HASHSIZE]; |
5d36a0c6 | 734 | + enum { FILE_HASHSIZE = 823 }; |
38e7688f AM |
735 | + static FileWatch *file_hash[FILE_HASHSIZE]; |
736 | + | |
737 | + static DirWatch **dir_hashchain(int fd) | |
738 | + { return &dir_hash[(unsigned) (fd) % DIR_HASHSIZE]; } | |
739 | + static FileWatch **file_hashchain(dev_t d, ino_t i) | |
740 | + { return &file_hash[(unsigned) (d+i) % FILE_HASHSIZE]; } | |
741 | + | |
742 | + static DirWatch *lookup_dirwatch (int fd); | |
743 | + static DirWatch *lookup_dirwatch (dev_t dir_dev, ino_t dir_ino); | |
744 | + static FileWatch *lookup_filewatch (dev_t file_dev, ino_t file_ino); | |
745 | + static void hash_dirwatch(DirWatch *w); | |
746 | + static void hash_filewatch(FileWatch *w); | |
747 | + static void unhash_dirwatch(DirWatch *w); | |
748 | + static void unhash_filewatch(FileWatch *w); | |
749 | + static Status watch_dir(const char *notify_dir, dev_t file_dev, ino_t file_ino); | |
750 | + | |
751 | + static void all_watches_changed(void); | |
752 | + | |
753 | + DNotify(const DNotify&); // Do not copy | |
754 | + DNotify & operator = (const DNotify&); // or assign. | |
755 | +}; | |
756 | + | |
757 | +#endif /* !IMon_included */ | |
758 | + | |
759 | + | |
2948bff6 JR |
760 | --- fam-2.6.10/src/IMon.h.dnotify 2003-04-15 06:21:34.000000000 +0200 |
761 | +++ fam-2.6.10/src/IMon.h 2004-02-03 18:30:26.000000000 +0100 | |
38e7688f AM |
762 | @@ -24,10 +24,7 @@ |
763 | #define IMon_included | |
764 | ||
765 | #include "config.h" | |
766 | -#include <sys/stat.h> | |
767 | -#include <sys/types.h> | |
768 | - | |
769 | -#include "Boolean.h" | |
770 | +#include "Monitor.h" | |
771 | ||
772 | struct stat; | |
773 | ||
774 | @@ -41,25 +38,18 @@ | |
775 | // | |
776 | // The user of the IMon object is the Interest class. | |
777 | ||
778 | -class IMon { | |
779 | +class IMon : public Monitor { | |
780 | ||
781 | public: | |
782 | - | |
783 | - enum Status { OK = 0, BAD = -1 }; | |
784 | - enum Event { EXEC, EXIT, CHANGE }; | |
785 | - | |
786 | - typedef void (*EventHandler)(dev_t, ino_t, int event); | |
787 | - | |
788 | IMon(EventHandler h); | |
789 | ~IMon(); | |
790 | ||
791 | static bool is_active(); | |
792 | ||
793 | - Status express(const char *name, struct stat *stat_return); | |
794 | - Status revoke(const char *name, dev_t dev, ino_t ino); | |
795 | + virtual Status express(const char *name, struct stat *stat_return); | |
796 | + virtual Status revoke(const char *name, dev_t dev, ino_t ino); | |
797 | ||
798 | private: | |
799 | - | |
800 | // Class Variables | |
801 | ||
802 | static int imonfd; | |
2948bff6 JR |
803 | --- fam-2.6.10/src/Interest.c++.dnotify 2003-04-15 06:21:34.000000000 +0200 |
804 | +++ fam-2.6.10/src/Interest.c++ 2004-02-03 18:30:26.000000000 +0100 | |
5d36a0c6 | 805 | @@ -43,12 +43,21 @@ |
38e7688f AM |
806 | #include "Event.h" |
807 | #include "FileSystem.h" | |
808 | #include "IMon.h" | |
809 | +#include "DNotify.h" | |
810 | #include "Log.h" | |
811 | #include "Pollster.h" | |
812 | #include "timeval.h" | |
813 | ||
814 | Interest *Interest::hashtable[]; | |
815 | -IMon Interest::imon(imon_handler); | |
816 | + | |
817 | +#ifdef USE_DNOTIFY | |
818 | +static DNotify dnotify(Interest::monitor_handler); | |
819 | +Monitor * Interest::monitor = &dnotify; | |
820 | +#else | |
821 | +static IMon imon(Interest::monitor_handler); | |
822 | +Monitor * Interest::monitor = &imon; | |
823 | +#endif | |
824 | + | |
825 | bool Interest::xtab_verification = true; | |
826 | ||
827 | Interest::Interest(const char *name, FileSystem *fs, in_addr host, ExportVerification ev) | |
5d36a0c6 | 828 | @@ -60,11 +69,11 @@ |
38e7688f AM |
829 | myhost(host), |
830 | mypath_exported_to_host(ev == NO_VERIFY_EXPORTED) | |
831 | { | |
832 | - memset(&old_stat, 0, sizeof(old_stat)); | |
833 | - IMon::Status s = IMon::BAD; | |
834 | - | |
835 | - s = imon.express(name, &old_stat); | |
836 | - if (s != IMon::OK) | |
837 | + memset(&old_stat, 0, sizeof(old_stat)); | |
838 | + | |
839 | + Monitor::Status s = Monitor::BAD; | |
840 | + s = monitor->express(name, &old_stat); | |
841 | + if (s != Monitor::OK) | |
842 | { int rc = lstat(name, &old_stat); | |
843 | if (rc < 0) | |
844 | { Log::info("can't lstat %s", name); | |
5d36a0c6 | 845 | @@ -101,7 +110,7 @@ |
38e7688f AM |
846 | } |
847 | #endif | |
848 | ||
849 | - if (exported_to_host()) fs->ll_monitor(this, s == IMon::OK); | |
850 | + if (exported_to_host()) fs->ll_monitor(this, s == Monitor::OK); | |
851 | } | |
852 | ||
853 | Interest::~Interest() | |
5d36a0c6 | 854 | @@ -129,7 +138,7 @@ |
38e7688f AM |
855 | pp = &p->hashlink; // move to next element |
856 | } | |
857 | if (!found_same) | |
858 | - (void) imon.revoke(name(), dev, ino); | |
859 | + (void) monitor->revoke(name(), dev, ino); | |
860 | } | |
861 | } | |
862 | ||
5d36a0c6 | 863 | @@ -148,7 +157,7 @@ |
38e7688f AM |
864 | |
865 | // Express interest. | |
866 | IMon::Status s = IMon::BAD; | |
867 | - s = imon.express(name(), NULL); | |
7e0cae36 | 868 | + s = monitor->express(name(), 0); |
38e7688f AM |
869 | if (s != IMon::OK) { |
870 | return true; | |
871 | } | |
5d36a0c6 | 872 | @@ -249,23 +258,23 @@ |
38e7688f AM |
873 | } |
874 | ||
875 | void | |
876 | -Interest::imon_handler(dev_t device, ino_t inumber, int event) | |
877 | +Interest::monitor_handler(dev_t device, ino_t inumber, int event) | |
878 | { | |
879 | assert(device || inumber); | |
880 | ||
881 | for (Interest *p = *hashchain(device, inumber), *next = p; p; p = next) | |
882 | { next = p->hashlink; | |
883 | if (p->ino == inumber && p->dev == device) | |
884 | - { if (event == IMon::EXEC) | |
885 | + { if (event == Monitor::EXEC) | |
886 | { p->cur_exec_state = EXECUTING; | |
887 | (void) p->report_exec_state(); | |
888 | } | |
889 | - else if (event == IMon::EXIT) | |
890 | + else if (event == Monitor::EXIT) | |
891 | { p->cur_exec_state = NOT_EXECUTING; | |
892 | (void) p->report_exec_state(); | |
893 | } | |
894 | else | |
895 | - { assert(event == IMon::CHANGE); | |
896 | + { assert(event == Monitor::CHANGE); | |
897 | p->scan(); | |
898 | } | |
899 | } | |
2948bff6 JR |
900 | --- fam-2.6.10/src/Interest.h.dnotify 2003-04-15 06:21:34.000000000 +0200 |
901 | +++ fam-2.6.10/src/Interest.h 2004-02-03 18:30:26.000000000 +0100 | |
38e7688f AM |
902 | @@ -32,7 +32,7 @@ |
903 | ||
904 | class Event; | |
905 | class FileSystem; | |
906 | -class IMon; | |
907 | +class Monitor; | |
908 | struct stat; | |
909 | ||
910 | // Interest -- abstract base class for filesystem entities of interest. | |
911 | @@ -74,7 +74,7 @@ | |
912 | ||
913 | // Public Class Method | |
914 | ||
915 | - static void imon_handler(dev_t, ino_t, int event); | |
916 | + static void monitor_handler(dev_t, ino_t, int event); | |
917 | ||
918 | static void enable_xtab_verification(bool enable); | |
919 | ||
920 | @@ -121,7 +121,7 @@ | |
921 | ||
922 | // Class Variables | |
923 | ||
924 | - static IMon imon; | |
925 | + static Monitor *monitor; | |
926 | static Interest *hashtable[HASHSIZE]; | |
927 | static bool xtab_verification; | |
928 | ||
2948bff6 JR |
929 | --- fam-2.6.10/src/Makefile.am.dnotify 2003-04-15 06:21:26.000000000 +0200 |
930 | +++ fam-2.6.10/src/Makefile.am 2004-02-03 18:30:26.000000000 +0100 | |
38e7688f | 931 | @@ -3,6 +3,12 @@ |
2948bff6 JR |
932 | |
933 | sbin_PROGRAMS = famd | |
38e7688f AM |
934 | |
935 | +if USE_DNOTIFY | |
936 | +DNOTIFY_FILES = DNotify.c++ | |
937 | +else | |
938 | +DNOTIFY_FILES = | |
939 | +endif | |
940 | + | |
2948bff6 | 941 | famd_SOURCES = \ |
38e7688f AM |
942 | Activity.c++ \ |
943 | Activity.h \ | |
944 | @@ -20,6 +26,7 @@ | |
945 | Directory.h \ | |
946 | DirectoryScanner.c++ \ | |
947 | DirectoryScanner.h \ | |
948 | + DNotify.h \ | |
949 | Event.c++ \ | |
950 | Event.h \ | |
951 | File.c++ \ | |
952 | @@ -48,6 +55,7 @@ | |
953 | NFSFileSystem.h \ | |
954 | NetConnection.c++ \ | |
955 | NetConnection.h \ | |
956 | + Monitor.h \ | |
957 | Pollster.c++ \ | |
958 | Pollster.h \ | |
959 | Request.h \ | |
2948bff6 | 960 | @@ -72,7 +80,8 @@ |
38e7688f AM |
961 | main.c++ \ |
962 | timeval.c++ \ | |
963 | timeval.h \ | |
2948bff6 JR |
964 | - @MONITOR_FUNCS@.c++ |
965 | + @MONITOR_FUNCS@.c++ \ | |
38e7688f AM |
966 | + $(DNOTIFY_FILES) |
967 | ||
2948bff6 JR |
968 | -EXTRA_famd_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ |
969 | +EXTRA_famd_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++ DNotify.c++ | |
38e7688f | 970 | |
5d36a0c6 | 971 | --- /dev/null 2003-09-15 15:40:47.000000000 +0200 |
2948bff6 | 972 | +++ fam-2.6.10/src/Monitor.h 2004-02-03 18:30:26.000000000 +0100 |
38e7688f AM |
973 | @@ -0,0 +1,57 @@ |
974 | +// Copyright (C) 2001 Red Hat, Inc. All Rights Reserved. | |
975 | +// Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved. | |
976 | +// | |
977 | +// This program is free software; you can redistribute it and/or modify it | |
978 | +// under the terms of version 2 of the GNU General Public License as | |
979 | +// published by the Free Software Foundation. | |
980 | +// | |
981 | +// This program is distributed in the hope that it would be useful, but | |
982 | +// WITHOUT ANY WARRANTY; without even the implied warranty of | |
983 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any | |
984 | +// license provided herein, whether implied or otherwise, is limited to | |
985 | +// this program in accordance with the express provisions of the GNU | |
986 | +// General Public License. Patent licenses, if any, provided herein do not | |
987 | +// apply to combinations of this program with other product or programs, or | |
988 | +// any other product whatsoever. This program is distributed without any | |
989 | +// warranty that the program is delivered free of the rightful claim of any | |
990 | +// third person by way of infringement or the like. See the GNU General | |
991 | +// Public License for more details. | |
992 | +// | |
993 | +// You should have received a copy of the GNU General Public License along | |
994 | +// with this program; if not, write the Free Software Foundation, Inc., 59 | |
995 | +// Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
996 | + | |
997 | +#ifndef Monitor_included | |
998 | +#define Monitor_included | |
999 | + | |
1000 | +#include "config.h" | |
1001 | +#include <sys/stat.h> | |
1002 | +#include <sys/types.h> | |
1003 | + | |
1004 | +struct stat; | |
1005 | + | |
1006 | +// Monitor is an abstract baseclass for differend file monitoring | |
1007 | +// systems. The original system used was IMon, and the Montor API | |
1008 | +// is heavily influenced by that. | |
1009 | +// There can only be one instantiation of the Monitor object. | |
1010 | +// | |
1011 | +// The user of this object uses express() and revoke() to | |
1012 | +// express/revoke interest in a file to imon. There is also | |
1013 | +// a callback, the EventHandler. When an event comes in, | |
1014 | +// the EventHandler is called. | |
1015 | +// | |
1016 | +// The main implementers of the Monitor class is IMon and DNotify | |
1017 | + | |
1018 | +class Monitor { | |
1019 | +public: | |
1020 | + | |
1021 | + enum Status { OK = 0, BAD = -1 }; | |
1022 | + enum Event { EXEC, EXIT, CHANGE }; | |
1023 | + | |
1024 | + typedef void (*EventHandler)(dev_t, ino_t, int event); | |
1025 | + | |
1026 | + virtual Status express(const char *name, struct stat *stat_return) = 0; | |
1027 | + virtual Status revoke(const char *name, dev_t dev, ino_t ino) = 0; | |
1028 | +}; | |
1029 | + | |
1030 | +#endif /* !Monitor_included */ | |
5d36a0c6 | 1031 | --- fam-2.6.10/include/BTree.h.dnotify 2003-04-15 06:21:19.000000000 +0200 |
1032 | +++ fam-2.6.10/include/BTree.h 2004-02-03 18:30:26.000000000 +0100 | |
1033 | @@ -271,7 +271,7 @@ | |
38e7688f AM |
1034 | n += that->n + 1; |
1035 | link[n] = that->link[that->n]; | |
1036 | that->n = 0; | |
1037 | - that->link[0] = NULL; | |
1038 | + that->link[0] = 0; | |
1039 | } | |
1040 | ||
1041 | /////////////////////////////////////////////////////////////////////////////// | |
5d36a0c6 | 1042 | @@ -280,7 +280,7 @@ |
38e7688f AM |
1043 | |
1044 | template <class K, class V> | |
1045 | BTree<K, V>::BTree() | |
1046 | - : root(NULL), npairs(0) | |
1047 | + : root(0), npairs(0) | |
1048 | { | |
1049 | assert(!(fanout % 2)); | |
1050 | } | |
5d36a0c6 | 1051 | @@ -407,7 +407,7 @@ |
38e7688f AM |
1052 | BTree<Key, Value>::Closure |
1053 | BTree<Key, Value>::insert(Node *p, const Key& key, const Value& value) | |
1054 | { | |
1055 | - if (!p) return Closure(key, value, NULL); | |
1056 | + if (!p) return Closure(key, value, 0); | |
1057 | // If you're running Purify on a client linking with libfam, and it says | |
1058 | // that line is causing a 3-byte UMR for BTree<int, bool>::insert() in | |
1059 | // FAMNextEvent() ("Reading 8 bytes from 0x... on the stack (3 bytes at | |
5d36a0c6 | 1060 | @@ -475,7 +475,7 @@ |
38e7688f AM |
1061 | case UNDER: |
1062 | if (root->n == 0) | |
1063 | { Node *nr = root->link[0]; | |
1064 | - root->link[0] = NULL; // don't delete subtree | |
1065 | + root->link[0] = 0; // don't delete subtree | |
1066 | delete root; | |
1067 | root = nr; | |
1068 | } | |
5d36a0c6 | 1069 | @@ -507,8 +507,8 @@ |
38e7688f AM |
1070 | Node *cp = p->link[i]; |
1071 | assert(cp); | |
1072 | ||
1073 | - Node *rp = i < p->n ? p->link[i + 1] : NULL; | |
1074 | - Node *lp = i > 0 ? p->link[i - 1] : NULL; | |
1075 | + Node *rp = i < p->n ? p->link[i + 1] : 0; | |
1076 | + Node *lp = i > 0 ? p->link[i - 1] : 0; | |
1077 | assert(!rp || rp->n >= fanout / 2); | |
1078 | assert(!lp || lp->n >= fanout / 2); | |
1079 | ||
2948bff6 JR |
1080 | --- fam-2.6.10/configure.ac.dnotify 2003-04-15 08:05:00.000000000 +0200 |
1081 | +++ fam-2.6.10/configure.ac 2004-02-03 18:30:26.000000000 +0100 | |
5d36a0c6 | 1082 | @@ -100,6 +100,24 @@ |
2948bff6 JR |
1083 | AC_HEADER_DIRENT |
1084 | AC_CHECK_HEADERS([fcntl.h limits.h linux/imon.h netinet/in.h rpc/rpc.h rpcsvc/mount.h stddef.h stdlib.h string.h syslog.h sys/imon.h sys/param.h sys/select.h sys/statvfs.h sys/syssgi.h sys/time.h sys/types.h sys/un.h unistd.h]) | |
5d36a0c6 | 1085 | |
2948bff6 | 1086 | +dnl |
5d36a0c6 | 1087 | +dnl Test for the linux dnotify fcntl |
1088 | +dnl | |
1089 | +AC_MSG_CHECKING([for dnotify fcntl support]) | |
1090 | +fam_save_cppflags="$CPPFLAGS" | |
1091 | +CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" | |
1092 | +AC_TRY_COMPILE([ | |
1093 | +#define _GNU_SOURCE | |
1094 | +#include <fcntl.h> | |
1095 | +#include <unistd.h> | |
1096 | +], | |
1097 | +[ int fd = 1; | |
1098 | + fcntl (fd, F_NOTIFY, (DN_MODIFY|DN_CREATE|DN_DELETE|DN_RENAME|DN_ATTRIB)|DN_MULTISHOT); | |
1099 | +], have_dnotify=yes, have_dnotify=no) | |
1100 | +use_dnotify=false | |
1101 | +CPPFLAGS="$pango_save_cppflags" | |
1102 | +AC_MSG_RESULT($have_dnotify) | |
1103 | + | |
2948bff6 JR |
1104 | if test "$have_sys_imon_h"; then |
1105 | MONITOR_FUNCS=IMonIRIX | |
1106 | elif test "$have_linux_imon_h"; then | |
1107 | @@ -122,9 +140,14 @@ | |
1108 | elif test "$have_linux_imon_h"; then | |
1109 | MONITOR_FUNCS=IMonLinux | |
1110 | else | |
1111 | + if test "$have_dnotify" = "yes"; then | |
1112 | + use_dnotify=true | |
1113 | + AC_DEFINE([USE_DNOTIFY], [1], [Define if the system has the dnotify fcntl and it's gonna be used.]) | |
1114 | + fi | |
1115 | MONITOR_FUNCS=IMonNone | |
5d36a0c6 | 1116 | fi |
2948bff6 | 1117 | AC_SUBST(MONITOR_FUNCS) |
5d36a0c6 | 1118 | +AM_CONDITIONAL(USE_DNOTIFY, $use_dnotify) |
5d36a0c6 | 1119 | |
2948bff6 JR |
1120 | # Checks for typedefs, structures, and compiler characteristics. |
1121 | AC_HEADER_STDBOOL |