static void setup() { int i; if (!inotify_map_isempty()) return; for(i=0; i < 4; i++) inotify_map(wdref[i], pathref[i]); }
/* add a watch. The watch is removed when the caller calls talloc_free() on *handle */ NTSTATUS inotify_watch(struct sys_notify_context *ctx, const char *path, uint32_t *filter, uint32_t *subdir_filter, void (*callback)(struct sys_notify_context *ctx, void *private_data, struct notify_event *ev), void *private_data, void *handle_p) { struct inotify_private *in; int wd; uint32_t mask; struct inotify_watch_context *w; uint32_t orig_filter = *filter; void **handle = (void **)handle_p; /* maybe setup the inotify fd */ if (ctx->private_data == NULL) { NTSTATUS status; status = inotify_setup(ctx); NT_STATUS_NOT_OK_RETURN(status); } in = talloc_get_type(ctx->private_data, struct inotify_private); mask = inotify_map(filter); if (mask == 0) { /* this filter can't be handled by inotify */ return NT_STATUS_INVALID_PARAMETER; } /* using IN_MASK_ADD allows us to cope with inotify() returning the same watch descriptor for multiple watches on the same path */ mask |= (IN_MASK_ADD | IN_ONLYDIR); /* get a new watch descriptor for this path */ wd = inotify_add_watch(in->fd, path, mask); if (wd == -1) { *filter = orig_filter; DEBUG(1, ("inotify_add_watch returned %s\n", strerror(errno))); return map_nt_error_from_unix(errno); } DEBUG(10, ("inotify_add_watch for %s mask %x returned wd %d\n", path, mask, wd)); w = talloc(in, struct inotify_watch_context); if (w == NULL) { inotify_rm_watch(in->fd, wd); *filter = orig_filter; return NT_STATUS_NO_MEMORY; } w->in = in; w->wd = wd; w->callback = callback; w->private_data = private_data; w->mask = mask; w->filter = orig_filter; w->path = talloc_strdup(w, path); if (w->path == NULL) { inotify_rm_watch(in->fd, wd); *filter = orig_filter; return NT_STATUS_NO_MEMORY; } (*handle) = w; DLIST_ADD(in->watches, w); /* the caller frees the handle to stop watching */ talloc_set_destructor(w, watch_destructor); return NT_STATUS_OK; }