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_win32_on_event (struct bufferevent * event, void * context) { const tr_watchdir_t handle = context; size_t nread; size_t name_size = MAX_PATH * sizeof (WCHAR); char * buffer = tr_malloc (sizeof (FILE_NOTIFY_INFORMATION) + name_size); PFILE_NOTIFY_INFORMATION ev = (PFILE_NOTIFY_INFORMATION) buffer; const size_t header_size = offsetof (FILE_NOTIFY_INFORMATION, FileName); /* Read the size of the struct excluding name into buf. Guaranteed to have at least sizeof (*ev) available */ while ((nread = bufferevent_read (event, ev, header_size)) != 0) { if (nread == (size_t) -1) { log_error ("Failed to read event: %s", tr_strerror (errno)); break; } if (nread != header_size) { log_error ("Failed to read event: expected %zu, got %zu bytes.", header_size, nread); break; } const size_t nleft = ev->NextEntryOffset - nread; assert (ev->FileNameLength % sizeof (WCHAR) == 0); assert (ev->FileNameLength > 0); assert (ev->FileNameLength <= nleft); if (nleft > name_size) { name_size = nleft; buffer = tr_realloc (buffer, sizeof (FILE_NOTIFY_INFORMATION) + name_size); ev = (PFILE_NOTIFY_INFORMATION) buffer; } /* Consume entire name into buffer */ if ((nread = bufferevent_read (event, buffer + header_size, nleft)) == (size_t) -1) { log_error ("Failed to read name: %s", tr_strerror (errno)); break; } if (nread != nleft) { log_error ("Failed to read name: expected %zu, got %zu bytes.", nleft, nread); break; } if (ev->Action == FILE_ACTION_ADDED || ev->Action == FILE_ACTION_MODIFIED || ev->Action == FILE_ACTION_RENAMED_NEW_NAME) { char * name = tr_win32_native_to_utf8 (ev->FileName, ev->FileNameLength / sizeof (WCHAR)); if (name != NULL) { tr_watchdir_process (handle, name); tr_free (name); } } } tr_free (buffer); }