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 = path_to_native_path (path1); if (wide_path1 == NULL) goto fail; wide_path2 = path_to_native_path (path2); 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; }
bool tr_sys_path_remove (const char * path, tr_error ** error) { bool ret = false; wchar_t * wide_path; assert (path != NULL); wide_path = path_to_native_path (path); 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; }
static tr_sys_file_t open_file (const char * path, DWORD access, DWORD disposition, DWORD flags, tr_error ** error) { tr_sys_file_t ret = TR_BAD_SYS_FILE; wchar_t * wide_path; assert (path != NULL); wide_path = path_to_native_path (path); if (wide_path != NULL) ret = CreateFileW (wide_path, access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, disposition, flags, NULL); if (ret == TR_BAD_SYS_FILE) set_system_error (error, GetLastError ()); tr_free (wide_path); return ret; }
bool tr_sys_path_remove(char const* path, tr_error** error) { TR_ASSERT(path != NULL); bool ret = false; wchar_t* wide_path = path_to_native_path(path); if (wide_path != NULL) { DWORD const 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; }
bool tr_sys_path_get_info(char const* path, int flags, tr_sys_path_info* info, tr_error** error) { TR_ASSERT(path != NULL); TR_ASSERT(info != NULL); bool ret = false; wchar_t* wide_path = path_to_native_path(path); 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 = tr_sys_file_get_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; }
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 = path_to_native_path (src_path); wide_dst_path = path_to_native_path (dst_path); 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; }
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 = INVALID_HANDLE_VALUE; DWORD wide_ret_size; assert (path != NULL); wide_path = path_to_native_path (path); 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; }
static bool create_dir(char const* path, int flags, int permissions, bool okay_if_exists, tr_error** error) { TR_ASSERT(path != NULL); (void)permissions; bool ret; DWORD error_code = ERROR_SUCCESS; wchar_t* wide_path = path_to_native_path(path); if ((flags & TR_SYS_DIR_CREATE_PARENTS) != 0) { error_code = SHCreateDirectoryExW(NULL, wide_path, NULL); ret = error_code == ERROR_SUCCESS; } else { ret = CreateDirectoryW(wide_path, NULL); if (!ret) { error_code = GetLastError(); } } if (!ret && error_code == ERROR_ALREADY_EXISTS && okay_if_exists) { DWORD const attributes = GetFileAttributesW(wide_path); if (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { ret = true; } } if (!ret) { set_system_error(error, error_code); } tr_free(wide_path); return ret; }
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 = path_to_native_path (path); 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; }