diff --git a/ChangeLog b/ChangeLog index 4e6e8b9fb..f6280b660 100644 --- a/ChangeLog +++ b/ChangeLog @@ -78,6 +78,7 @@ * almost completely changed the storage interface (for custom storage) * added support for hashing pieces in multiple threads + * fix support for symlinks on windows * fix long filename issue (on unixes) * fixed performance bug in DHT torrent eviction * fixed win64 build (GetFileAttributesEx) diff --git a/src/file.cpp b/src/file.cpp index b0f1cf562..e127f418f 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -359,29 +359,39 @@ namespace libtorrent TORRENT_UNUSED(flags); -#if TORRENT_USE_WSTRING && defined TORRENT_WINDOWS -#define GetFileAttributesEx_ GetFileAttributesExW - std::wstring f = convert_to_wstring(inf); - - // apparently windows doesn't expect paths - // to directories to ever end with a \ or / - if (!f.empty() && (f[f.size() - 1] == L'\\' - || f[f.size() - 1] == L'/')) - f.resize(f.size() - 1); -#else -#define GetFileAttributesEx_ GetFileAttributesExA - std::string f = convert_to_native(inf); - - // apparently windows doesn't expect paths - // to directories to ever end with a \ or / - if (!f.empty() && (f[f.size() - 1] == '\\' - || f[f.size() - 1] == '/')) - f.resize(f.size() - 1); + std::string p = convert_separators(inf); +#if TORRENT_USE_UNC_PATHS + // UNC paths must be absolute + // network paths are already UNC paths + if (inf.substr(0,2) == "\\\\") p = inf; + else p = "\\\\?\\" + (is_complete(p) ? p : combine_path(current_working_directory(), p)); #endif - WIN32_FILE_ATTRIBUTE_DATA data; - if (!GetFileAttributesEx_(f.c_str(), GetFileExInfoStandard, &data)) + +#if TORRENT_USE_WSTRING +#define CreateFile_ CreateFileW + std::wstring f = convert_to_wstring(p); +#else +#define CreateFile_ CreateFileA + std::string f = convert_to_native(p); +#endif + + // in order to open a directory, we need the FILE_FLAG_BACKUP_SEMANTICS + HANDLE h = CreateFile_(f.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ + | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (h == INVALID_HANDLE_VALUE) { ec.assign(GetLastError(), system_category()); + TORRENT_ASSERT(ec); + return; + } + + BY_HANDLE_FILE_INFORMATION data; + if (!GetFileInformationByHandle(h, &data)) + { + ec.assign(GetLastError(), system_category()); + TORRENT_ASSERT(ec); + CloseHandle(h); return; } @@ -394,9 +404,9 @@ namespace libtorrent ? file_status::directory : (data.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) ? file_status::character_special : file_status::regular_file; - + CloseHandle(h); #else - + // posix version std::string const& f = convert_to_native(inf);