示例#1
0
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;
}
示例#2
0
static void
tr_watchdir_win32_free (tr_watchdir_backend * backend_base)
{
  tr_watchdir_win32 * const backend = BACKEND_UPCAST (backend_base);

  if (backend == NULL)
    return;

  assert (backend->base.free_func == &tr_watchdir_win32_free);

  if (backend->fd != INVALID_HANDLE_VALUE)
    CancelIoEx (backend->fd, &backend->overlapped);

  if (backend->thread != NULL)
    {
      WaitForSingleObject (backend->thread, INFINITE);
      CloseHandle (backend->thread);
    }

  if (backend->event != NULL)
    bufferevent_free (backend->event);

  if (backend->notify_pipe[0] != TR_BAD_SOCKET)
    evutil_closesocket (backend->notify_pipe[0]);
  if (backend->notify_pipe[1] != TR_BAD_SOCKET)
    evutil_closesocket (backend->notify_pipe[1]);

  if (backend->fd != INVALID_HANDLE_VALUE)
    CloseHandle (backend->fd);

  tr_free (backend);
}
示例#3
0
static void
tr_watchdir_kqueue_free (tr_watchdir_backend * backend_base)
{
  tr_watchdir_kqueue * const backend = BACKEND_UPCAST (backend_base);

  if (backend == NULL)
    return;

  assert (backend->base.free_func == &tr_watchdir_kqueue_free);

  if (backend->event != NULL)
    {
      event_del (backend->event);
      event_free (backend->event);
    }

  if (backend->kq != -1)
    close (backend->kq);
  if (backend->dirfd != -1)
    close (backend->dirfd);

  tr_ptrArrayDestruct (&backend->dir_entries, &tr_free);

  tr_free (backend);
}
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);
    }
示例#5
0
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);
}