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