static unsigned int __stdcall tr_watchdir_win32_thread (void * context) { const tr_watchdir_t handle = context; tr_watchdir_win32 * const backend = BACKEND_UPCAST (tr_watchdir_get_backend (handle)); DWORD bytes_transferred; while (tr_get_overlapped_result_ex (backend->fd, &backend->overlapped, &bytes_transferred, INFINITE, FALSE)) { PFILE_NOTIFY_INFORMATION info = (PFILE_NOTIFY_INFORMATION) backend->buffer; while (info->NextEntryOffset != 0) *((BYTE **) &info) += info->NextEntryOffset; info->NextEntryOffset = bytes_transferred - ((BYTE *) info - (BYTE *) backend->buffer); send (backend->notify_pipe[1], (const char *) backend->buffer, bytes_transferred, 0); if (!ReadDirectoryChangesW (backend->fd, backend->buffer, sizeof (backend->buffer), FALSE, WIN32_WATCH_MASK, NULL, &backend->overlapped, NULL)) { log_error ("Failed to read directory changes"); return 0; } } if (GetLastError () != ERROR_OPERATION_ABORTED) log_error ("Failed to wait for directory changes"); return 0; }
static void tr_watchdir_inotify_on_event (struct bufferevent * event, void * context) { assert (context != NULL); const tr_watchdir_t handle = context; tr_watchdir_inotify * const backend = BACKEND_UPCAST (tr_watchdir_get_backend (handle)); struct inotify_event ev; size_t nread; size_t name_size = NAME_MAX + 1; char * name = tr_new (char, name_size); /* Read the size of the struct excluding name into buf. Guaranteed to have at least sizeof (ev) available */ while ((nread = bufferevent_read (event, &ev, sizeof (ev))) != 0) { if (nread == (size_t) -1) { log_error ("Failed to read inotify event: %s", tr_strerror (errno)); break; } if (nread != sizeof (ev)) { log_error ("Failed to read inotify event: expected %zu, got %zu bytes.", sizeof (ev), nread); break; } assert (ev.wd == backend->inwd); assert ((ev.mask & INOTIFY_WATCH_MASK) != 0); assert (ev.len > 0); if (ev.len > name_size) { name_size = ev.len; name = tr_renew (char, name, name_size); } /* Consume entire name into buffer */ if ((nread = bufferevent_read (event, name, ev.len)) == (size_t) -1) { log_error ("Failed to read inotify name: %s", tr_strerror (errno)); break; } if (nread != ev.len) { log_error ("Failed to read inotify name: expected %" PRIu32 ", got %zu bytes.", ev.len, nread); break; } tr_watchdir_process (handle, name); }
static void tr_watchdir_kqueue_on_event (evutil_socket_t fd UNUSED, short type UNUSED, void * context) { const tr_watchdir_t handle = context; tr_watchdir_kqueue * const backend = BACKEND_UPCAST (tr_watchdir_get_backend (handle)); struct kevent ke; const struct timespec ts = { 0, 0 }; if (kevent (backend->kq, NULL, 0, &ke, 1, &ts) == -1) { log_error ("Failed to fetch kevent: %s", tr_strerror (errno)); return; } /* Read directory with generic scan */ tr_watchdir_scan (handle, &backend->dir_entries); }