int64_t do_inotify_add_watch (const char *path, int mask) { #ifdef HAVE_SYS_INOTIFY_H int64_t r; char *buf; NEED_INOTIFY (-1); buf = sysroot_path (path); if (!buf) { reply_with_perror ("malloc"); return -1; } r = inotify_add_watch (inotify_fd, buf, mask); free (buf); if (r == -1) { reply_with_perror ("%s", path); return -1; } return r; #else NOT_AVAILABLE (-1); #endif }
int do_inotify_rm_watch (int wd) { NEED_INOTIFY (-1); if (inotify_rm_watch (inotify_fd, wd) == -1) { reply_with_perror ("%d", wd); return -1; } return 0; }
int do_inotify_rm_watch (int wd) { #ifdef HAVE_SYS_INOTIFY_H NEED_INOTIFY (-1); if (inotify_rm_watch (inotify_fd, wd) == -1) { reply_with_perror ("%d", wd); return -1; } return 0; #else NOT_AVAILABLE (-1); #endif }
int do_inotify_close (void) { NEED_INOTIFY (-1); if (inotify_fd == -1) { reply_with_error ("handle is not open"); return -1; } if (close (inotify_fd) == -1) { reply_with_perror ("close"); return -1; } inotify_fd = -1; inotify_posn = 0; return 0; }
int64_t do_inotify_add_watch (const char *path, int mask) { int64_t r; CLEANUP_FREE char *buf = NULL; NEED_INOTIFY (-1); buf = sysroot_path (path); if (!buf) { reply_with_perror ("malloc"); return -1; } r = inotify_add_watch (inotify_fd, buf, mask); if (r == -1) { reply_with_perror ("%s", path); return -1; } return r; }
int do_inotify_close (void) { #ifdef HAVE_SYS_INOTIFY_H NEED_INOTIFY (-1); if (inotify_fd == -1) { reply_with_error ("handle is not open"); return -1; } if (close (inotify_fd) == -1) { reply_with_perror ("close"); return -1; } inotify_fd = -1; inotify_posn = 0; return 0; #else NOT_AVAILABLE (-1); #endif }
guestfs_int_inotify_event_list * do_inotify_read (void) { int space; guestfs_int_inotify_event_list *ret; NEED_INOTIFY (NULL); ret = malloc (sizeof *ret); if (ret == NULL) { reply_with_perror ("malloc"); return NULL; } ret->guestfs_int_inotify_event_list_len = 0; ret->guestfs_int_inotify_event_list_val = NULL; /* Read events that are available, but make sure we won't exceed * maximum message size. In order to achieve this we have to * guesstimate the remaining space available. */ space = GUESTFS_MESSAGE_MAX / 2; while (space > 0) { struct inotify_event *event; int r; size_t n; r = read (inotify_fd, inotify_buf + inotify_posn, sizeof (inotify_buf) - inotify_posn); if (r == -1) { if (errno == EWOULDBLOCK || errno == EAGAIN) /* End of list. */ break; reply_with_perror ("read"); goto error; } if (r == 0) { /* End of file - we're not expecting it. */ reply_with_error ("unexpected end of file"); goto error; } inotify_posn += r; /* Read complete events from the buffer and add them to the result. */ n = 0; while (n < inotify_posn) { guestfs_int_inotify_event *np; guestfs_int_inotify_event *in; event = (struct inotify_event *) &inotify_buf[n]; /* Have we got a complete event in the buffer? */ #ifdef __GNUC__ if (n + sizeof (struct inotify_event) > inotify_posn || n + sizeof (struct inotify_event) + event->len > inotify_posn) break; #else #error "this code needs fixing so it works on non-GCC compilers" #endif /* Check event->len is reasonable (note the field is uint32_t). */ if (event->len > PATH_MAX) { reply_with_error ("event->len = %" PRIu32 " > PATH_MAX", event->len); goto error; } np = realloc (ret->guestfs_int_inotify_event_list_val, (ret->guestfs_int_inotify_event_list_len + 1) * sizeof (guestfs_int_inotify_event)); if (np == NULL) { reply_with_perror ("realloc"); goto error; } ret->guestfs_int_inotify_event_list_val = np; in = &ret->guestfs_int_inotify_event_list_val[ret->guestfs_int_inotify_event_list_len]; ret->guestfs_int_inotify_event_list_len++; in->in_wd = event->wd; in->in_mask = event->mask; in->in_cookie = event->cookie; if (event->len > 0) in->in_name = strdup (event->name); else in->in_name = strdup (""); /* Should have optional string fields XXX. */ if (in->in_name == NULL) { reply_with_perror ("strdup"); goto error; } /* Estimate space used by this event in the message. */ space -= 16 + 4 + strlen (in->in_name) + 4; /* Move pointer to next event. */ #ifdef __GNUC__ n += sizeof (struct inotify_event) + event->len; #else #error "this code needs fixing so it works on non-GCC compilers" #endif } /* 'n' now points to the first unprocessed/incomplete * message in the buffer. Copy that to offset 0 in the buffer. */ memmove (inotify_buf, &inotify_buf[n], inotify_posn - n); inotify_posn -= n; } /* Return the messages. */ return ret; error: xdr_free ((xdrproc_t) xdr_guestfs_int_inotify_event_list, (char *) ret); free (ret); return NULL; }