inotify_watch.h File Reference

Public interface for inotify backend to log watch. More...

#include "lwatch.h"

Go to the source code of this file.

Classes

struct  path_watch_t
 When a watch is established on a filesystem directory this struct is used to track it. More...

Defines

#define INOTIFY_WATCH_ERROR_BASE   -2500
 Base error code (minimum value) for inotify watch errors.
#define INOTIFY_WATCH_ERROR_LIMIT   (INOTIFY_WATCH_ERROR_BASE + 50)
 Maximum error code for inotify errors.
#define IS_INOTIFY_WATCH_ERROR(error)   (((error) >= INOTIFY_WATCH_ERROR_BASE) && ((error) < INOTIFY_WATCH_ERROR_LIMIT))
 Return true if error code is within the range for inotify watch errors.
#define INOTIFY_WATCH_ERROR_NULL_WATCH   (INOTIFY_WATCH_ERROR_BASE + 1)
 watch invalid, was NULL
#define INOTIFY_WATCH_ERROR_WATCH_ID_NOT_FOUND   (INOTIFY_WATCH_ERROR_BASE + 2)
 could not look up watch id
#define INOTIFY_WATCH_ALREADY_WATCHING   (INOTIFY_WATCH_ERROR_BASE + 3)
 already being watched
#define INOTIFY_WATCH_NOT_WATCHED   (INOTIFY_WATCH_ERROR_BASE + 4)
 not being watched

Functions

int inotify_watch_init (void)
 Initialize the inotify monitoring back end.
int inotify_watch_fini (void)
 Close the inotify monitoring back end, stop all monitoring, free all resources.
bool is_watch_target (const char *path)
 Return true if path parameter is a watch target.
bool is_path_watched (const char *path)
 Return true if the given path is being watched by inotify.
const char * inotify_watch_error_string (int error)
 Translate error code to string description.
char * inotify_mask_string (unsigned int mask, const char *separator)
 Given an inotify event bitmask return a string of all the enabled flags.
char * path_watch_string (struct path_watch_t *pw)
 Render a path_watch_t struct as a string.
struct path_watch_tfind_watch_by_path (const char *path)
 Given a path lookup the path watch object associated with it.
struct path_watch_tfind_watch_by_watch_id (int watch_id)
 Given an inotify watch id lookup the path watch object associated with it.
int inotify_start_monitoring (const char *path)
 Start monitoring the target path with inotify.
int inotify_stop_monitoring (const char *path)
 Stop monitoring the target path with inotify.
int read_events (void)
 Loop used to read inotify events and dispatch them.
int get_inotify_fd (void)
 Return the file descriptor used by the inotify back end.
lwatch_event_callback_t register_lwatch_event_callback (lwatch_event_callback_t callback)
 Register a callback to receive log watch events.

Variables

bool keep_watching
 Flag used to indicate if the read_events() loop should terminate or continue.


Detailed Description

Public interface for inotify backend to log watch.

Definition in file inotify_watch.h.


Define Documentation

#define IS_INOTIFY_WATCH_ERROR ( error   )     (((error) >= INOTIFY_WATCH_ERROR_BASE) && ((error) < INOTIFY_WATCH_ERROR_LIMIT))

Return true if error code is within the range for inotify watch errors.

Parameters:
[in] error The error code to test if it's a inotify watch error code.
Returns:
True if error code is a inotify watch error.

Definition at line 38 of file inotify_watch.h.

Referenced by error_string().


Function Documentation

struct path_watch_t* find_watch_by_path ( const char *  path  )  [read]

Given a path lookup the path watch object associated with it.

Parameters:
[in] path The path whose matching watch object is desired.
Returns:
Pointer to the path watch object or NULL if not found.

Definition at line 1407 of file inotify_watch.c.

Referenced by inotify_start_monitoring().

01408 {
01409     int error;
01410     hash_key_t key;
01411     hash_value_t value;
01412     struct path_watch_t *pw;
01413 
01414     key.type = HASH_KEY_STRING;
01415     key.str = path;
01416 
01417     if ((error = hash_lookup(watch_path_table, &key, &value)) != HASH_SUCCESS) {
01418         log_msg(LOG_VERBOSE_DEBUG, _("cannot find pathname \"%s\"\n"),  path);
01419         return NULL;
01420     }
01421 
01422     pw = (struct path_watch_t *) value.ptr;
01423     return pw;
01424 }

struct path_watch_t* find_watch_by_watch_id ( int  watch_id  )  [read]

Given an inotify watch id lookup the path watch object associated with it.

Parameters:
[in] watch_id The watch_id assigned by inotify to identify the watch
Returns:
Pointer to the path watch object or NULL if not found.

Definition at line 1431 of file inotify_watch.c.

Referenced by process_event().

01432 {
01433     int error;
01434     hash_key_t key;
01435     hash_value_t value;
01436     struct path_watch_t *pw;
01437 
01438     key.type = HASH_KEY_ULONG;
01439     key.ul = watch_id;
01440 
01441     if ((error = hash_lookup(watch_id_table, &key, &value)) != HASH_SUCCESS) {
01442         log_msg(LOG_DEBUG, _("cannot find watch_id %d\n"),  watch_id);
01443         return NULL;
01444     }
01445 
01446     pw = (struct path_watch_t *) value.ptr;
01447     return pw;
01448 }

int get_inotify_fd ( void   ) 

Return the file descriptor used by the inotify back end.

Returns:
Integer file descriptor used to read inotify events
The inotify file descriptor is used to read inotify events.

Definition at line 1627 of file inotify_watch.c.

Referenced by main_loop().

01628 {
01629     return inotify_fd;
01630 }

char* inotify_mask_string ( unsigned int  mask,
const char *  separator 
)

Given an inotify event bitmask return a string of all the enabled flags.

Parameters:
[in] mask Bitmask of inotify event flags
[in] separator String used to separate individual flags
Returns:
static string with each enabled flag separated by the separator string

Definition at line 1305 of file inotify_watch.c.

Referenced by process_event().

01306 {
01307     static __thread char buf[1024]; /* thread local static buffer */
01308     char *p, *buf_end;
01309     size_t separator_len;
01310     unsigned int unknown;
01311 
01312     p = buf;                     /* current position in buffer */
01313     buf_end = &buf[sizeof(buf)]; /* non-inclusive end of buffer */
01314     separator_len = strlen(separator);
01315     *p = 0;
01316 
01317     /* validate there is nothing in the event mask we don't know about */
01318     unknown = mask & ~(IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE |
01319                         IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | IN_MOVED_TO |
01320                         IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF |
01321                         IN_UNMOUNT | IN_Q_OVERFLOW | IN_IGNORED | IN_ONLYDIR |
01322                         IN_DONT_FOLLOW | IN_MASK_ADD | IN_ISDIR | IN_ONESHOT);
01323 
01324     if (unknown) p += snprintf(p, buf_end - p, "unknown bits=0x%x%s", unknown, separator);
01325     if (p >= buf_end) goto fail;
01326 
01327     if (mask & IN_ACCESS)        p += snprintf(p, buf_end - p, "ACCESS%s",        separator);
01328     if (p >= buf_end) goto fail;
01329     if (mask & IN_MODIFY)        p += snprintf(p, buf_end - p, "MODIFY%s",        separator);
01330     if (p >= buf_end) goto fail;
01331     if (mask & IN_ATTRIB)        p += snprintf(p, buf_end - p, "ATTRIB%s",        separator);
01332     if (p >= buf_end) goto fail;
01333     if (mask & IN_CLOSE_WRITE)   p += snprintf(p, buf_end - p, "CLOSE_WRITE%s",   separator);
01334     if (p >= buf_end) goto fail;
01335     if (mask & IN_CLOSE_NOWRITE) p += snprintf(p, buf_end - p, "CLOSE_NOWRITE%s", separator);
01336     if (p >= buf_end) goto fail;
01337     if (mask & IN_OPEN)          p += snprintf(p, buf_end - p, "OPEN%s",          separator);
01338     if (p >= buf_end) goto fail;
01339     if (mask & IN_MOVED_FROM)    p += snprintf(p, buf_end - p, "MOVED_FROM%s",    separator);
01340     if (p >= buf_end) goto fail;
01341     if (mask & IN_MOVED_TO)      p += snprintf(p, buf_end - p, "MOVED_TO%s",      separator);
01342     if (p >= buf_end) goto fail;
01343     if (mask & IN_CREATE)        p += snprintf(p, buf_end - p, "CREATE%s",        separator);
01344     if (p >= buf_end) goto fail;
01345     if (mask & IN_DELETE)        p += snprintf(p, buf_end - p, "DELETE%s",        separator);
01346     if (p >= buf_end) goto fail;
01347     if (mask & IN_DELETE_SELF)   p += snprintf(p, buf_end - p, "DELETE_SELF%s",   separator);
01348     if (p >= buf_end) goto fail;
01349     if (mask & IN_MOVE_SELF)     p += snprintf(p, buf_end - p, "MOVE_SELF%s",     separator);
01350     if (p >= buf_end) goto fail;
01351     if (mask & IN_UNMOUNT)       p += snprintf(p, buf_end - p, "UNMOUNT%s",       separator);
01352     if (p >= buf_end) goto fail;
01353     if (mask & IN_Q_OVERFLOW)    p += snprintf(p, buf_end - p, "Q_OVERFLOW%s",    separator);
01354     if (p >= buf_end) goto fail;
01355     if (mask & IN_IGNORED)       p += snprintf(p, buf_end - p, "IGNORED%s",       separator);
01356     if (p >= buf_end) goto fail;
01357     if (mask & IN_ONLYDIR)       p += snprintf(p, buf_end - p, "ONLYDIR%s",       separator);
01358     if (p >= buf_end) goto fail;
01359     if (mask & IN_DONT_FOLLOW)   p += snprintf(p, buf_end - p, "DONT_FOLLOW%s",   separator);
01360     if (p >= buf_end) goto fail;
01361     if (mask & IN_MASK_ADD)      p += snprintf(p, buf_end - p, "MASK_ADD%s",      separator);
01362     if (p >= buf_end) goto fail;
01363     if (mask & IN_ISDIR)         p += snprintf(p, buf_end - p, "ISDIR%s",         separator);
01364     if (p >= buf_end) goto fail;
01365     if (mask & IN_ONESHOT)       p += snprintf(p, buf_end - p, "ONESHOT%s",       separator);
01366     if (p >= buf_end) goto fail;
01367 
01368     if (p > buf) p[-separator_len] = 0;
01369 
01370     return buf;
01371  fail:
01372     /* exhausted the buffer; NULL terminate then return truncated string */
01373     buf_end[-1] = 0;   /* should already be NULL terminated, but be safe */
01374     return buf;
01375 }

int inotify_start_monitoring ( const char *  path_arg  ) 

Start monitoring the target path with inotify.

Parameters:
[in] path_arg The pathname to monitor, it will be normalized and made absolute
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1455 of file inotify_watch.c.

Referenced by process_file_rename(), relocate_watches(), start_monitoring(), and validate_backups_in_database().

01456 {
01457     int error;
01458     char path[PATH_MAX];
01459     hash_key_t key;
01460     hash_value_t value;
01461     char existing_directory_ancestor[PATH_MAX];
01462     struct path_watch_t *pw;
01463 
01464     /* Normalize the path passed to us */
01465     if ((error = make_normalized_absolute_path(path, sizeof(path), path_arg)) != SUCCESS) {
01466         log_msg(LOG_ERROR, _("failed make_normalized_absolute_path from \"%s\" (%s)\n"),
01467                 path_arg, error_string(error));
01468         return error;
01469     }
01470 
01471     /* Assure we're not already watching this path */
01472     if (is_watch_target(path)) {
01473         error = INOTIFY_WATCH_ALREADY_WATCHING;
01474         log_msg(LOG_ERROR, _("path is already being watched \"%s\"\n"),  path);
01475         return error;
01476     }
01477 
01478     log_msg(LOG_INFO, _("watching target \"%s\"\n"),  path);
01479 
01480     /*
01481      * We watch the directory which contains the path, not the path itself. To
01482      * establish a watch on a directory the directory must exist in the
01483      * filesystem so we search for the nearest directory ancestor containing the
01484      * path which exists in the file system.  This is where the watch will be
01485      * established.
01486      *
01487      * If the directory containing the path does not yet exist we watch the
01488      * closest directory to the final path component and will move the watch to
01489      * a closer directory when the missing directory component is later created
01490      * in the directory which was chosen to watch.
01491      *
01492      * FIXME
01493      * WARNING: Race Condition. If the missing directory is created before the
01494      * watch is established we won't see the directory creation event which
01495      * tells us we can move the watch directory closer to the target. The only
01496      * way to protect against this is to periodically walk all the watch targets
01497      * and and adjust their watch directories.
01498      */
01499     if ((error = find_existing_directory_ancestor(existing_directory_ancestor,
01500                                                   sizeof(existing_directory_ancestor),
01501                                                   path) != SUCCESS)) {
01502         log_msg(LOG_ERROR, _("failed find_existing_directory_ancestor \"%s\" (%s)\n"),
01503                 path, error_string(error));
01504         return error;
01505     }
01506 
01507     /*
01508      * If we're already watching the selected directory get the watch object
01509      * previously created for watching that directory, otherwise create a new
01510      * watch object for the directory.
01511      */
01512     if ((pw = find_watch_by_path(existing_directory_ancestor)) == NULL) {
01513         if ((error = new_path_watch(existing_directory_ancestor, &pw)) != SUCCESS) {
01514             log_msg(LOG_ERROR, _("could not allocate new watch for \"%s\" (%s)\n"),
01515                     existing_directory_ancestor, error_string(error));
01516             return error;
01517         }
01518     }
01519 
01520     /* Do some basic bookkeeping */
01521 
01522     /* Add the path to our list of targets. */
01523     if ((error = add_path_to_target_list(path)) != SUCCESS) {
01524         log_msg(LOG_ERROR, _("could not insert path into target table \"%s\" (%s)\n"),
01525                 pw->path, error_string(error));
01526         inotify_rm_watch(inotify_fd, pw->watch_id);
01527         free_path_watch(&pw);
01528         return error;
01529     }
01530 
01531     /* Add the watch object to our list of directories we're watching. */
01532     if ((error = track_path_watch(pw)) != SUCCESS) {
01533         log_msg(LOG_ERROR, _("could not insert watch into tables for \"%s\" (%s)\n"),
01534                 pw->path, error_string(error));
01535         inotify_rm_watch(inotify_fd, pw->watch_id);
01536         free_path_watch(&pw);
01537         return error;
01538     }
01539 
01540     log_msg(LOG_DEBUG, _("adding path \"%s\" to descendant_path_table for directory \"%s\"\n"),
01541             path, pw->path);
01542 
01543     /* Add the path to the list of targets the watch object is responsible for watching (e.g. descendants). */
01544     key.type = HASH_KEY_STRING;
01545     key.str = path;
01546     value.type = HASH_VALUE_UNDEF;
01547 
01548     if ((error = hash_enter(pw->descendant_path_table, &key, &value)) != HASH_SUCCESS) {
01549         log_msg(LOG_ERROR, _("cannot add path \"%s\" to path_watch_t descendant_path_table \"%s\" (%s)\n"),
01550                 path, pw->path, error_string(error));
01551         return error;
01552     }
01553 
01554     return SUCCESS;
01555 }

int inotify_stop_monitoring ( const char *  path_arg  ) 

Stop monitoring the target path with inotify.

Parameters:
[in] path_arg The pathname cease monitoring, it will be normalized and made absolute
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1562 of file inotify_watch.c.

01563 {
01564     int error;
01565     char path[PATH_MAX];
01566     unsigned long i, count;
01567     hash_key_t key;
01568     hash_entry_t *entries, *entry;
01569     struct path_watch_t *pw;
01570     int path_count;
01571 
01572     if ((error = make_normalized_absolute_path(path, sizeof(path), path_arg)) != SUCCESS) {
01573         log_msg(LOG_ERROR, _("failed make_normalized_absolute_path from \"%s\" (%s)\n"),
01574                 path_arg, error_string(error));
01575         return error;
01576     }
01577 
01578     if (!is_watch_target(path)) {
01579         error = INOTIFY_WATCH_NOT_WATCHED;
01580         log_msg(LOG_ERROR, _("path was not being watched \"%s\"\n"),  path);
01581         return error;
01582     }
01583 
01584     log_msg(LOG_INFO, _("removing watch target \"%s\"\n"),  path);
01585 
01586     key.type = HASH_KEY_STRING;
01587     key.str = path;
01588 
01589     path_count = 0;
01590     hash_entries(watch_id_table, &count, &entries);
01591     for (i = 0, entry = entries; i < count; i++, entry++) {
01592         pw = entry->value.ptr;
01593 
01594         if (hash_has_key(pw->descendant_path_table, &key)) {
01595             path_count++;
01596             if ((error = hash_delete(pw->descendant_path_table, &key)) != HASH_SUCCESS) {
01597                 log_msg(LOG_ERROR, _("cannot delete path \"%s\" from path_watch_t descendant_path_table \"%s\" (%s)\n"),
01598                         path, pw->path, error_string(error));
01599             }
01600             if ((error = destroy_path_watch_if_empty(&pw)) != SUCCESS) {
01601                 log_msg(LOG_ERROR, _("destroy_path_watch_if_empty failed (%s)\n"), error_string(error));
01602             }
01603         }
01604     }
01605     free(entries);
01606 
01607     if (path_count != 1) {
01608         log_msg(LOG_ERROR, _("found %d instances of \"%s\" but expected exactly one\n"),
01609                 path_count, path);
01610     }
01611 
01612     if ((error = remove_path_from_target_list(path)) != SUCCESS) {
01613         log_msg(LOG_ERROR, _("could not remove path from target table \"%s\" (%s)\n"),
01614                 path, error_string(error));
01615     }
01616 
01617     return error;
01618 }

const char* inotify_watch_error_string ( int  error  ) 

Translate error code to string description.

Parameters:
[in] error Error code whose string description is sought.
Returns:
string describing the error
Note: IS_INOTIFY_WATCH_ERROR(error) should true otherwise the error code is outside the set of values this function knows about. If the error code is not recognized the string "unknown(XXX)" will be returned instead where XXX is the decimal representation of the error code.

Definition at line 1287 of file inotify_watch.c.

Referenced by error_string().

01288 {
01289     switch(error) {
01290     case SUCCESS:                                return _("success");
01291     case INOTIFY_WATCH_ERROR_NULL_WATCH:         return _("watch invalid, was NULL");
01292     case INOTIFY_WATCH_ERROR_WATCH_ID_NOT_FOUND: return _("could not look up watch id");
01293     case INOTIFY_WATCH_ALREADY_WATCHING:         return _("already being watched");
01294     case INOTIFY_WATCH_NOT_WATCHED:              return _("not being watched");
01295     }
01296     return NULL;
01297 }

int inotify_watch_fini ( void   ) 

Close the inotify monitoring back end, stop all monitoring, free all resources.

Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1197 of file inotify_watch.c.

Referenced by lwatch_fini().

01198 {
01199     unsigned long i, count;
01200     hash_entry_t *entries, *entry;
01201     struct path_watch_t *pw;
01202 
01203     flush_inotify_cookie_cache();
01204 
01205     hash_entries(watch_id_table, &count, &entries);
01206     for (i = 0, entry = entries; i < count; i++, entry++) {
01207         pw = entry->value.ptr;
01208         log_msg(LOG_VERBOSE_DEBUG, _("destroying [%d] \"%s\"\n"),  pw->watch_id, pw->path);
01209         destroy_path_watch(&pw);
01210     }
01211     free(entries);
01212 
01213     if (hash_count(watch_path_table) != 0) {
01214         log_msg(LOG_ERROR, _("watch_path_table not empty (%d) after removing all watches\n"),
01215                 hash_count(watch_path_table));
01216     }
01217 
01218     if (hash_count(watch_id_table) != 0) {
01219         log_msg(LOG_ERROR, _("watch_id_table not empty (%d) after removing all watches\n"),
01220                 hash_count(watch_id_table));
01221     }
01222 
01223     hash_destroy(watch_path_table);
01224     hash_destroy(watch_id_table);
01225     hash_destroy(target_table);
01226     close(inotify_fd);
01227 
01228     return SUCCESS;
01229 }

int inotify_watch_init ( void   ) 

Initialize the inotify monitoring back end.

Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1162 of file inotify_watch.c.

Referenced by lwatch_init().

01163 {
01164     int error;
01165 
01166     inotify_lost_cookie_callback = lost_rename_callback;
01167 
01168     if ((inotify_fd = inotify_init()) < 0) {
01169         error = errno;
01170         log_msg(LOG_ERROR, _("inotify_init() failed (%s)\n"), error_string(error));
01171         return error;
01172     }
01173 
01174 
01175     if ((error = hash_create(INITIAL_HASH_TABLE_SIZE, &watch_path_table, NULL)) != HASH_SUCCESS) {
01176         log_msg(LOG_ERROR, _("inotify_watch_init: cannot create pathname hash table\n"));
01177         return error;
01178     }
01179 
01180     if ((error = hash_create(INITIAL_HASH_TABLE_SIZE, &watch_id_table, NULL)) != HASH_SUCCESS) {
01181         log_msg(LOG_ERROR, _("inotify_watch_init: cannot create watch id hash table\n"));
01182         return error;
01183     }
01184 
01185     if ((error = hash_create(INITIAL_HASH_TABLE_SIZE, &target_table, NULL)) != HASH_SUCCESS) {
01186         log_msg(LOG_ERROR, _("%s: cannot create target hash table\n"));
01187         return error;
01188     }
01189 
01190     return SUCCESS;
01191 }

bool is_path_watched ( const char *  path  ) 

Return true if the given path is being watched by inotify.

Parameters:
[in] path The path to check for inotify watching
Returns:
true if the path is watched by inotify, false otherwise
Note, this is distinct from asking if a path is target, a target is something we've been asked to monitor. In the process of monitoring we will ask inotify to watch certain directories which are not targets, but may contain targets.

See also:
is_watch_target() Also see Vocabulary Terms for an explanation of targets vs. watched objects.

Definition at line 1267 of file inotify_watch.c.

01268 {
01269     hash_key_t key;
01270 
01271     key.type = HASH_KEY_STRING;
01272     key.str = path;
01273 
01274     return hash_has_key(watch_path_table, &key);
01275 }

bool is_watch_target ( const char *  path  ) 

Return true if path parameter is a watch target.

Parameters:
[in] path The path we're testing to see if it's a watch target
Returns:
True if path parameter is a watch target
Note, This answers the question if the path is a target to monitor. In other words it's something we've specifically been asked to monitor. Our implementation will establish inotify watches as a consequence of monitoring a target and is_path_watched() is correct way to ask if inotify is watching a path as opposed to this function which reports if path is target to monitor.

See also:
is_path_watched() Also see Vocabulary Terms for an explanation of targets vs. watched objects.

Definition at line 1245 of file inotify_watch.c.

Referenced by inotify_start_monitoring(), inotify_stop_monitoring(), process_event(), and start_monitoring().

01246 {
01247     hash_key_t key;
01248 
01249     key.type = HASH_KEY_STRING;
01250     key.str = path;
01251 
01252     return hash_has_key(target_table, &key);
01253 }

char* path_watch_string ( struct path_watch_t pw  ) 

Render a path_watch_t struct as a string.

Parameters:
[in] pw The path watch object to render as a string
Returns:
malloc'ed string, caller must free

Definition at line 1382 of file inotify_watch.c.

Referenced by process_event(), and watch_path_table_string().

01383 {
01384     char *files;
01385     char *fw_string;
01386     int len;
01387 
01388     if (!pw) return strdup("(null)");
01389 
01390     files = keys_string(pw->descendant_path_table, "        ", "\n");
01391 
01392     len = asprintf(&fw_string, "[%d] \"%s\" n_files=%ld%s%s",
01393                    pw->watch_id, pw->path,
01394                    hash_count(pw->descendant_path_table),
01395                    hash_count(pw->descendant_path_table) ? "\n" : "", files);
01396 
01397     free(files);
01398     return fw_string;
01399 }

int read_events ( void   ) 

Loop used to read inotify events and dispatch them.

Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1636 of file inotify_watch.c.

Referenced by main_loop().

01637 {
01638     char buf[1024 * (INOTIFY_EVENT_SIZE + 16)]; /* reasonable guess as to size of 1024 events */
01639     int len, error, i;
01640     bool done;
01641 
01642     /*
01643      * The behavior when the buffer given to read(2) is too small to return information
01644      * about the next event depends on the kernel version: in kernels before 2.6.21,
01645      * read(2) returns 0; since kernel 2.6.21, read(2) fails with the error EINVAL.
01646      */
01647 
01648     done = false;
01649     while (!done) {
01650         len = read (inotify_fd, buf, sizeof(buf));
01651         i = 0;
01652         if (len <= 0) {
01653             error = errno;
01654             if (error == EINTR || error == EAGAIN) { /* need to reissue system call */
01655                 continue;
01656             }
01657             else if (error == EINVAL || len == 0) {
01658                 log_msg(LOG_ERROR, _("failed, buffer too small (%s)\n"),
01659                         error_string(error));
01660                 return error;
01661             } else {
01662                 log_msg(LOG_ERROR, _("failed (%s)\n"),
01663                         error_string(error));
01664                 return error;
01665             }
01666         }
01667         while (i < len) {
01668             struct inotify_event *event;
01669 
01670             event = (struct inotify_event *) &buf[i];
01671 
01672             process_event(event);
01673             i += INOTIFY_EVENT_SIZE + event->len;
01674         }
01675         done = true;
01676     }
01677     return SUCCESS;
01678 }

lwatch_event_callback_t register_lwatch_event_callback ( lwatch_event_callback_t  callback  ) 

Register a callback to receive log watch events.

Parameters:
[in] callback The callback which will be invoked to send a log watch event.
Returns:
The previous callback pointer.

Definition at line 1685 of file inotify_watch.c.

Referenced by lwatch_init().

01686 {
01687     lwatch_event_callback_t prev_callback = lwatch_event_callback;
01688     lwatch_event_callback = callback;
01689     return prev_callback;
01690 }


Generated on Mon Aug 31 10:06:21 2009 by  doxygen 1.5.8