Пример #1
0
static bool
create_symlink (const char * dst_path, const char * src_path, bool dst_is_dir)
{
#ifndef _WIN32

  (void) dst_is_dir;

  return symlink (src_path, dst_path) != -1;

#else

  wchar_t * wide_src_path;
  wchar_t * wide_dst_path;
  bool ret = false;

  wide_src_path = tr_win32_utf8_to_native (src_path, -1);
  wide_dst_path = tr_win32_utf8_to_native (dst_path, -1);

  ret = CreateSymbolicLinkW (wide_dst_path, wide_src_path,
                             dst_is_dir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0);

  tr_free (wide_dst_path);
  tr_free (wide_src_path);

  return ret;

#endif
}
Пример #2
0
bool
tr_sys_path_is_same (const char  * path1,
                     const char  * path2,
                     tr_error   ** error)
{
  bool ret = false;
  wchar_t * wide_path1 = NULL;
  wchar_t * wide_path2 = NULL;
  HANDLE handle1 = INVALID_HANDLE_VALUE;
  HANDLE handle2 = INVALID_HANDLE_VALUE;
  BY_HANDLE_FILE_INFORMATION fi1, fi2;

  assert (path1 != NULL);
  assert (path2 != NULL);

  wide_path1 = tr_win32_utf8_to_native (path1, -1);
  if (wide_path1 == NULL)
    goto fail;

  wide_path2 = tr_win32_utf8_to_native (path2, -1);
  if (wide_path2 == NULL)
    goto fail;

  handle1 = CreateFileW (wide_path1, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  if (handle1 == INVALID_HANDLE_VALUE)
    goto fail;

  handle2 = CreateFileW (wide_path2, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  if (handle2 == INVALID_HANDLE_VALUE)
    goto fail;

  /* TODO: Use GetFileInformationByHandleEx on >= Server 2012 */

  if (!GetFileInformationByHandle (handle1, &fi1) || !GetFileInformationByHandle (handle2, &fi2))
    goto fail;

  ret = fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber &&
        fi1.nFileIndexHigh == fi2.nFileIndexHigh &&
        fi1.nFileIndexLow  == fi2.nFileIndexLow;

  goto cleanup;

fail:
  set_system_error_if_file_found (error, GetLastError ());

cleanup:
  CloseHandle (handle2);
  CloseHandle (handle1);

  tr_free (wide_path2);
  tr_free (wide_path1);

  return ret;
}
Пример #3
0
bool
tr_sys_path_remove (const char  * path,
                    tr_error   ** error)
{
  bool ret = false;
  wchar_t * wide_path;

  assert (path != NULL);

  wide_path = tr_win32_utf8_to_native (path, -1);

  if (wide_path != NULL)
    {
      const DWORD attributes = GetFileAttributesW (wide_path);

      if (attributes != INVALID_FILE_ATTRIBUTES)
        {
          if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
            ret = RemoveDirectoryW (wide_path);
          else
            ret = DeleteFileW (wide_path);
        }
    }

  if (!ret)
    set_system_error (error, GetLastError ());

  tr_free (wide_path);

  return ret;
}
Пример #4
0
bool
tr_sys_path_rename (const char  * src_path,
                    const char  * dst_path,
                    tr_error   ** error)
{
  bool ret = false;
  wchar_t * wide_src_path;
  wchar_t * wide_dst_path;

  assert (src_path != NULL);
  assert (dst_path != NULL);

  wide_src_path = tr_win32_utf8_to_native (src_path, -1);
  wide_dst_path = tr_win32_utf8_to_native (dst_path, -1);

  if (wide_src_path != NULL && wide_dst_path != NULL)
    {
      DWORD flags = MOVEFILE_REPLACE_EXISTING;
      DWORD attributes;

      attributes = GetFileAttributesW (wide_src_path);
      if (attributes != INVALID_FILE_ATTRIBUTES &&
          (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
        {
          flags = 0;
        }
      else
        {
          attributes = GetFileAttributesW (wide_dst_path);
          if (attributes != INVALID_FILE_ATTRIBUTES &&
              (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
            flags = 0;
        }

      ret = MoveFileExW (wide_src_path, wide_dst_path, flags);
    }

  if (!ret)
    set_system_error (error, GetLastError ());

  tr_free (wide_dst_path);
  tr_free (wide_src_path);

  return ret;
}
Пример #5
0
bool
tr_sys_path_get_info (const char        * path,
                      int                 flags,
                      tr_sys_path_info  * info,
                      tr_error         ** error)
{
  bool ret = false;
  wchar_t * wide_path;

  assert (path != NULL);
  assert (info != NULL);

  wide_path = tr_win32_utf8_to_native (path, -1);

  if ((flags & TR_SYS_PATH_NO_FOLLOW) == 0)
    {
      HANDLE handle = INVALID_HANDLE_VALUE;

      if (wide_path != NULL)
        handle = CreateFileW (wide_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

      if (handle != INVALID_HANDLE_VALUE)
        {
          tr_error * my_error = NULL;
          ret = get_file_info (handle, info, &my_error);
          if (!ret)
            tr_error_propagate (error, &my_error);
          CloseHandle (handle);
        }
      else
        {
          set_system_error (error, GetLastError ());
        }
    }
  else
    {
      WIN32_FILE_ATTRIBUTE_DATA attributes;

      if (wide_path != NULL)
        ret = GetFileAttributesExW (wide_path, GetFileExInfoStandard, &attributes);

      if (ret)
        stat_to_sys_path_info (attributes.dwFileAttributes, attributes.nFileSizeLow,
                               attributes.nFileSizeHigh, &attributes.ftLastWriteTime,
                               info);
      else
        set_system_error (error, GetLastError ());
    }

  tr_free (wide_path);

  return ret;
}
Пример #6
0
static bool
create_hardlink (const char * dst_path, const char * src_path)
{
#ifndef _WIN32

  return link (src_path, dst_path) != -1;

#else

  wchar_t * wide_src_path = tr_win32_utf8_to_native (src_path, -1);
  wchar_t * wide_dst_path = tr_win32_utf8_to_native (dst_path, -1);

  bool ret = CreateHardLinkW (wide_dst_path, wide_src_path, NULL);

  tr_free (wide_dst_path);
  tr_free (wide_src_path);

  return ret;

#endif
}
Пример #7
0
char *
tr_sys_path_resolve (const char  * path,
                     tr_error   ** error)
{
  char * ret = NULL;
  wchar_t * wide_path;
  wchar_t * wide_ret = NULL;
  HANDLE handle;
  DWORD wide_ret_size;

  assert (path != NULL);

  wide_path = tr_win32_utf8_to_native (path, -1);
  if (wide_path == NULL)
    goto fail;

  handle = CreateFileW (wide_path, FILE_READ_EA,
                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  if (handle == INVALID_HANDLE_VALUE)
    goto fail;

  wide_ret_size = GetFinalPathNameByHandleW (handle, NULL, 0, 0);
  if (wide_ret_size == 0)
    goto fail;

  wide_ret = tr_new (wchar_t, wide_ret_size);
  if (GetFinalPathNameByHandleW (handle, wide_ret, wide_ret_size, 0) != wide_ret_size - 1)
    goto fail;

  /* Resolved path always begins with "\\?\", so skip those first four chars. */
  ret = tr_win32_native_to_utf8 (wide_ret + 4, -1);
  if (ret != NULL)
    goto cleanup;

fail:
  set_system_error (error, GetLastError ());

  tr_free (ret);
  ret = NULL;

cleanup:
  tr_free (wide_ret);
  tr_free (wide_path);

  if (handle != INVALID_HANDLE_VALUE)
    CloseHandle (handle);

  return ret;
}
Пример #8
0
bool
tr_sys_path_exists (const char  * path,
                    tr_error   ** error)
{
  bool ret = false;
  wchar_t * wide_path;
  HANDLE handle = INVALID_HANDLE_VALUE;

  assert (path != NULL);

  wide_path = tr_win32_utf8_to_native (path, -1);

  if (wide_path != NULL)
    {
      DWORD attributes = GetFileAttributesW (wide_path);
      if (attributes != INVALID_FILE_ATTRIBUTES)
        {
          if (attributes & FILE_ATTRIBUTE_REPARSE_POINT)
            {
              handle = CreateFileW (wide_path, 0, 0, NULL, OPEN_EXISTING,
                                    FILE_FLAG_BACKUP_SEMANTICS, NULL);

              ret = handle != INVALID_HANDLE_VALUE;
            }
          else
            {
              ret = true;
            }
        }
    }

  if (!ret)
    set_system_error_if_file_found (error, GetLastError ());

  if (handle != INVALID_HANDLE_VALUE)
    CloseHandle (handle);

  tr_free (wide_path);

  return ret;
}
Пример #9
0
tr_watchdir_backend *
tr_watchdir_win32_new (tr_watchdir_t handle)
{
  const char * const path = tr_watchdir_get_path (handle);
  wchar_t * wide_path;
  tr_watchdir_win32 * backend;

  backend = tr_new0 (tr_watchdir_win32, 1);
  backend->base.free_func = &tr_watchdir_win32_free;
  backend->fd = INVALID_HANDLE_VALUE;
  backend->notify_pipe[0] = backend->notify_pipe[1] = TR_BAD_SOCKET;

  if ((wide_path = tr_win32_utf8_to_native (path, -1)) == NULL)
    {
      log_error ("Failed to convert \"%s\" to native path", path);
      goto fail;
    }

  if ((backend->fd = CreateFileW (wide_path, FILE_LIST_DIRECTORY,
                                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                                  NULL, OPEN_EXISTING,
                                  FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
                                  NULL)) == INVALID_HANDLE_VALUE)
    {
      log_error ("Failed to open directory \"%s\"", path);
      goto fail;
    }

  tr_free (wide_path);
  wide_path = NULL;

  backend->overlapped.Pointer = handle;

  if (!ReadDirectoryChangesW (backend->fd, backend->buffer, sizeof (backend->buffer), FALSE,
                              WIN32_WATCH_MASK, NULL, &backend->overlapped, NULL))
    {
      log_error ("Failed to read directory changes");
      goto fail;
    }

  if (evutil_socketpair (AF_INET, SOCK_STREAM, 0, backend->notify_pipe) == -1)
    {
      log_error ("Failed to create notify pipe: %s", tr_strerror (errno));
      goto fail;
    }

  if ((backend->event = bufferevent_socket_new (tr_watchdir_get_event_base (handle),
                                                backend->notify_pipe[0], 0)) == NULL)
    {
      log_error ("Failed to create event buffer: %s", tr_strerror (errno));
      goto fail;
    }

  bufferevent_setwatermark (backend->event, EV_READ, sizeof (FILE_NOTIFY_INFORMATION), 0);
  bufferevent_setcb (backend->event, &tr_watchdir_win32_on_event, NULL, NULL, handle);
  bufferevent_enable (backend->event, EV_READ);

  if ((backend->thread = (HANDLE) _beginthreadex (NULL, 0, &tr_watchdir_win32_thread,
                                                  handle, 0, NULL)) == NULL)
    {
      log_error ("Failed to create thread");
      goto fail;
    }

  /* Perform an initial scan on the directory */
  if (event_base_once (tr_watchdir_get_event_base (handle), -1, EV_TIMEOUT,
                       &tr_watchdir_win32_on_first_scan, handle, NULL) == -1)
    log_error ("Failed to perform initial scan: %s", tr_strerror (errno));

  return BACKEND_DOWNCAST (backend);

fail:
  tr_watchdir_win32_free (BACKEND_DOWNCAST (backend));
  tr_free (wide_path);
  return NULL;
}