OpenSDE Packages Database (without history before r20070)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1006 lines
27 KiB

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