Пример #1
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);
    }
Пример #2
0
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);
}