diff --git a/daemon/postprocess/Unpack.cpp b/daemon/postprocess/Unpack.cpp index 940eb6c8..2660d9d5 100644 --- a/daemon/postprocess/Unpack.cpp +++ b/daemon/postprocess/Unpack.cpp @@ -297,7 +297,7 @@ void UnpackController::ExecuteUnrar(const char* password) } params.push_back(strdup(m_hasNonStdRarFiles ? "*.*" : "*.rar")); - params.push_back(strdup(FileSystem::MakeLongPath(BString<1024>("%s%c", *m_unpackDir, PATH_SEPARATOR)))); + params.push_back(strdup(FileSystem::MakeExtendedPath(BString<1024>("%s%c", *m_unpackDir, PATH_SEPARATOR)))); params.push_back(NULL); SetArgs((const char**)¶ms.front(), false); SetScript(params.at(0)); diff --git a/daemon/util/FileSystem.cpp b/daemon/util/FileSystem.cpp index 1382c746..d5bb6a6b 100644 --- a/daemon/util/FileSystem.cpp +++ b/daemon/util/FileSystem.cpp @@ -26,28 +26,6 @@ #include "nzbget.h" #include "FileSystem.h" -#ifdef WIN32 -WString::WString(const char* utfstr) -{ - int len = MultiByteToWideChar(CP_UTF8, 0, utfstr, -1, NULL, 0); - m_data = (wchar_t*)malloc((len + 1) * sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, utfstr, -1, m_data, len); -} - -WString MakeWPath(const char* utfpath) -{ - return *FileSystem::MakeLongPath(utfpath); -} - -CString WPathToCString(const wchar_t* wstr) -{ - char utfstr[1024]; - int copied = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, utfstr, 1024, NULL, NULL); - return utfstr; -} -#endif - - CString FileSystem::GetLastErrorMessage() { BString<1024> msg; @@ -109,7 +87,7 @@ bool FileSystem::ForceDirectories(const char* path, CString& errmsg) } } - if (_wmkdir(MakeWPath(normPath)) != 0 && errno != EEXIST) + if (_wmkdir(UtfPathToWidePath(normPath)) != 0 && errno != EEXIST) { errmsg.Format("could not create directory %s: %s", *normPath, *GetLastErrorMessage()); return false; @@ -198,7 +176,7 @@ CString FileSystem::GetCurrentDirectory() #ifdef WIN32 wchar_t unistr[1024]; ::GetCurrentDirectoryW(1024, unistr); - return WPathToCString(unistr); + return WidePathToUtfPath(unistr); #else char str[1024]; getcwd(str, 1024); @@ -209,7 +187,7 @@ CString FileSystem::GetCurrentDirectory() bool FileSystem::SetCurrentDirectory(const char* dirFilename) { #ifdef WIN32 - return ::SetCurrentDirectoryW(MakeWPath(dirFilename)); + return ::SetCurrentDirectoryW(UtfPathToWidePath(dirFilename)); #else return chdir(dirFilename) == 0; #endif @@ -270,7 +248,7 @@ bool FileSystem::CreateSparseFile(const char* filename, int64 size, CString& err errmsg.Clear(); bool ok = false; #ifdef WIN32 - HANDLE hFile = CreateFileW(MakeWPath(filename), GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_NEW, 0, NULL); + HANDLE hFile = CreateFileW(UtfPathToWidePath(filename), GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_NEW, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { errmsg = GetLastErrorMessage(); @@ -325,7 +303,7 @@ bool FileSystem::CreateSparseFile(const char* filename, int64 size, CString& err bool FileSystem::TruncateFile(const char* filename, int size) { #ifdef WIN32 - FILE* file = _wfopen(MakeWPath(filename), WString(FOPEN_RBP)); + FILE* file = _wfopen(UtfPathToWidePath(filename), WString(FOPEN_RBP)); fseek(file, size, SEEK_SET); bool ok = SetEndOfFile((HANDLE)_get_osfhandle(_fileno(file))) != 0; fclose(file); @@ -427,7 +405,7 @@ CString FileSystem::MakeUniqueFilename(const char* destDir, const char* basename bool FileSystem::MoveFile(const char* srcFilename, const char* dstFilename) { #ifdef WIN32 - return _wrename(MakeWPath(srcFilename), MakeWPath(dstFilename)) == 0; + return _wrename(UtfPathToWidePath(srcFilename), UtfPathToWidePath(dstFilename)) == 0; #else bool ok = rename(srcFilename, dstFilename) == 0; if (!ok && errno == EXDEV) @@ -472,7 +450,7 @@ bool FileSystem::CopyFile(const char* srcFilename, const char* dstFilename) bool FileSystem::DeleteFile(const char* filename) { #ifdef WIN32 - return _wremove(MakeWPath(filename)) == 0; + return _wremove(UtfPathToWidePath(filename)) == 0; #else return remove(filename) == 0; #endif @@ -483,7 +461,7 @@ bool FileSystem::FileExists(const char* filename) #ifdef WIN32 // we use a native windows call because c-lib function "stat" fails on windows if file date is invalid WIN32_FIND_DATAW findData; - HANDLE handle = FindFirstFileW(MakeWPath(filename), &findData); + HANDLE handle = FindFirstFileW(UtfPathToWidePath(filename), &findData); if (handle != INVALID_HANDLE_VALUE) { bool exists = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0; @@ -510,7 +488,7 @@ bool FileSystem::DirectoryExists(const char* dirFilename) #ifdef WIN32 // we use a native windows call because c-lib function "stat" fails on windows if file date is invalid WIN32_FIND_DATAW findData; - HANDLE handle = FindFirstFileW(MakeWPath(dirFilename), &findData); + HANDLE handle = FindFirstFileW(UtfPathToWidePath(dirFilename), &findData); if (handle != INVALID_HANDLE_VALUE) { bool exists = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; @@ -528,7 +506,7 @@ bool FileSystem::DirectoryExists(const char* dirFilename) bool FileSystem::CreateDirectory(const char* dirFilename) { #ifdef WIN32 - _wmkdir(MakeWPath(dirFilename)); + _wmkdir(UtfPathToWidePath(dirFilename)); #else mkdir(dirFilename, S_DIRMODE); #endif @@ -538,7 +516,7 @@ bool FileSystem::CreateDirectory(const char* dirFilename) bool FileSystem::RemoveDirectory(const char* dirFilename) { #ifdef WIN32 - return _wrmdir(MakeWPath(dirFilename)) == 0; + return _wrmdir(UtfPathToWidePath(dirFilename)) == 0; #else return rmdir(dirFilename) == 0; #endif @@ -585,7 +563,7 @@ int64 FileSystem::FileSize(const char* filename) #ifdef WIN32 // we use a native windows call because c-lib function "stat" fails on windows if file date is invalid WIN32_FIND_DATAW findData; - HANDLE handle = FindFirstFileW(MakeWPath(filename), &findData); + HANDLE handle = FindFirstFileW(UtfPathToWidePath(filename), &findData); if (handle != INVALID_HANDLE_VALUE) { int64 size = ((int64)(findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; @@ -689,8 +667,8 @@ CString FileSystem::ExpandFileName(const char* filename) { #ifdef WIN32 wchar_t unistr[1024]; - _wfullpath(unistr, MakeWPath(filename), 1024); - return WPathToCString(unistr); + _wfullpath(unistr, UtfPathToWidePath(filename), 1024); + return WidePathToUtfPath(unistr); #else CString result; result.Reserve(1024); @@ -781,7 +759,7 @@ bool FileSystem::FlushFileBuffers(int fileDescriptor, CString& errmsg) bool FileSystem::FlushDirBuffers(const char* filename, CString& errmsg) { #ifdef WIN32 - FILE* file = _wfopen(MakeWPath(filename), WString(FOPEN_RBP)); + FILE* file = _wfopen(UtfPathToWidePath(filename), WString(FOPEN_RBP)); #else BString<1024> parentPath = filename; char* p = (char*)strrchr(parentPath, PATH_SEPARATOR); @@ -815,7 +793,7 @@ void FileSystem::FixExecPermission(const char* filename) } #endif -CString FileSystem::MakeLongPath(const char* path) +CString FileSystem::MakeExtendedPath(const char* path) { #ifdef WIN32 if (strlen(path) > 260 - 14) @@ -832,13 +810,48 @@ CString FileSystem::MakeLongPath(const char* path) } } +#ifdef WIN32 +WString FileSystem::UtfPathToWidePath(const char* utfpath) +{ + return *FileSystem::MakeExtendedPath(utfpath); +} + +CString FileSystem::WidePathToUtfPath(const wchar_t* wpath) +{ + char utfstr[1024]; + int copied = WideCharToMultiByte(CP_UTF8, 0, wpath, -1, utfstr, 1024, NULL, NULL); + return utfstr; +} + +CString FileSystem::AnsiPathToUtfPath(const char* ansipath) +{ + wchar_t wstr[1024]; + char utfstr[1024]; + int copied = MultiByteToWideChar(CP_ACP, 0, ansipath, -1, wstr, 1024); + if (copied > 0) + { + copied = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, utfstr, 1024, NULL, NULL); + } + return copied > 0 ? utfstr : ansipath; +} +#endif + #ifdef WIN32 +WString::WString(const char* utfstr) +{ + int len = MultiByteToWideChar(CP_UTF8, 0, utfstr, -1, NULL, 0); + m_data = (wchar_t*)malloc((len + 1) * sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, utfstr, -1, m_data, len); +} +#endif + +#ifdef WIN32 DirBrowser::DirBrowser(const char* path) { BString<1024> mask("%s%c*.*", path, (int)PATH_SEPARATOR); - m_file = FindFirstFileW(MakeWPath(mask), &m_findData); + m_file = FindFirstFileW(FileSystem::UtfPathToWidePath(mask), &m_findData); m_first = true; } @@ -864,7 +877,7 @@ const char* DirBrowser::InternNext() } if (ok) { - m_filename = WPathToCString(m_findData.cFileName); + m_filename = FileSystem::WidePathToUtfPath(m_findData.cFileName); return m_filename; } return NULL; @@ -963,7 +976,7 @@ bool DiskFile::Open(const char* filename, EOpenMode mode) const char* strmode = mode == omRead ? FOPEN_RB : mode == omReadWrite ? FOPEN_RBP : mode == omWrite ? FOPEN_WB : FOPEN_AB; #ifdef WIN32 - m_file = _wfopen(MakeWPath(filename), WString(strmode)); + m_file = _wfopen(FileSystem::UtfPathToWidePath(filename), WString(strmode)); #else m_file = fopen(filename, strmode); #endif diff --git a/daemon/util/FileSystem.h b/daemon/util/FileSystem.h index 4511b345..8bdb64f1 100644 --- a/daemon/util/FileSystem.h +++ b/daemon/util/FileSystem.h @@ -28,6 +28,10 @@ #include "NString.h" +#ifdef WIN32 +class WString; +#endif + class FileSystem { public: @@ -70,7 +74,13 @@ public: /* Flush disk buffers for file metadata (after file renaming) */ static bool FlushDirBuffers(const char* filename, CString& errmsg); - static CString MakeLongPath(const char* path); + static CString MakeExtendedPath(const char* path); + +#ifdef WIN32 + static WString UtfPathToWidePath(const char* utfpath); + static CString WidePathToUtfPath(const wchar_t* wpath); + static CString AnsiPathToUtfPath(const char* ansipath); +#endif }; class DirBrowser diff --git a/daemon/util/Script.cpp b/daemon/util/Script.cpp index afab1b62..fac609b1 100644 --- a/daemon/util/Script.cpp +++ b/daemon/util/Script.cpp @@ -471,9 +471,8 @@ int ScriptController::StartProcess() cmdLine = cmdLineBuf; } - bool longWorkingDir = strlen(m_workingDir) > 260 - 14; - WString wideWorkingDir(longWorkingDir ? FileSystem::MakeLongPath(m_workingDir) : m_workingDir); - if (longWorkingDir) + WString wideWorkingDir = FileSystem::UtfPathToWidePath(m_workingDir); + if (strlen(m_workingDir) > 260 - 14) { GetShortPathNameW(wideWorkingDir, wideWorkingDir, wideWorkingDir.Length() + 1); } diff --git a/lib/par2/descriptionpacket.cpp b/lib/par2/descriptionpacket.cpp index ebbe2401..a14c54e0 100644 --- a/lib/par2/descriptionpacket.cpp +++ b/lib/par2/descriptionpacket.cpp @@ -19,6 +19,7 @@ #include "nzbget.h" #include "par2cmdline.h" +#include "FileSystem.h" #ifdef _MSC_VER #ifdef _DEBUG @@ -107,6 +108,10 @@ bool DescriptionPacket::Load(DiskFile *diskfile, u64 offset, PACKET_HEADER &head (size_t)packet->header.length - sizeof(PACKET_HEADER))) return false; +#ifdef WIN32 + filename = *FileSystem::AnsiPathToUtfPath((char*)((FILEDESCRIPTIONPACKET*)packetdata)->name); +#endif + // Are the file and 16k hashes consistent if (packet->length <= 16384 && packet->hash16k != packet->hashfull) { diff --git a/lib/par2/descriptionpacket.h b/lib/par2/descriptionpacket.h index 45dfdb5e..c1144afc 100644 --- a/lib/par2/descriptionpacket.h +++ b/lib/par2/descriptionpacket.h @@ -58,6 +58,10 @@ public: // Get the Hash values from the packet const MD5Hash& HashFull(void) const; const MD5Hash& Hash16k(void) const; +#ifdef WIN32 +protected: + mutable string filename; +#endif }; // Get the file id from the packet @@ -85,8 +89,12 @@ inline string DescriptionPacket::FileName(void) const { assert(packetdata != 0); +#ifdef WIN32 + return filename.c_str(); +#else // return (char*)((const FILEDESCRIPTIONPACKET*)packetdata)->name(); return (char*)((const FILEDESCRIPTIONPACKET*)packetdata)->name; +#endif } // Get the full file hash value from the packet diff --git a/lib/par2/diskfile.cpp b/lib/par2/diskfile.cpp index bcc9c4cd..474089a9 100644 --- a/lib/par2/diskfile.cpp +++ b/lib/par2/diskfile.cpp @@ -19,6 +19,7 @@ #include "nzbget.h" #include "par2cmdline.h" +#include "FileSystem.h" #ifdef _MSC_VER #ifdef _DEBUG @@ -66,7 +67,7 @@ bool DiskFile::Create(string _filename, u64 _filesize) filesize = _filesize; // Create the file - hFile = ::CreateFileA(_filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + hFile = ::CreateFileW(FileSystem::UtfPathToWidePath(_filename.c_str()), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { DWORD error = ::GetLastError(); @@ -178,7 +179,7 @@ bool DiskFile::Open(string _filename, u64 _filesize) filename = _filename; filesize = _filesize; - hFile = ::CreateFileA(_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + hFile = ::CreateFileW(FileSystem::UtfPathToWidePath(_filename.c_str()), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { DWORD error = ::GetLastError(); @@ -323,17 +324,17 @@ list* DiskFile::FindFiles(string path, string wildcard) list *matches = new list; wildcard = path + wildcard; - WIN32_FIND_DATA fd; - HANDLE h = ::FindFirstFile(wildcard.c_str(), &fd); + WIN32_FIND_DATAW fd; + HANDLE h = ::FindFirstFileW(FileSystem::UtfPathToWidePath(wildcard.c_str()), &fd); if (h != INVALID_HANDLE_VALUE) { do { if (0 == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - matches->push_back(path + fd.cFileName); + matches->push_back(path + *FileSystem::WidePathToUtfPath(fd.cFileName)); } - } while (::FindNextFile(h, &fd)); + } while (::FindNextFileW(h, &fd)); ::FindClose(h); } @@ -798,21 +799,13 @@ void DiskFile::SplitFilename(string filename, string &path, string &name) bool DiskFile::FileExists(string filename) { - struct stat st; - return ((0 == stat(filename.c_str(), &st)) && (0 != (st.st_mode & S_IFREG))); + return FileSystem::FileExists(filename.c_str()); } u64 DiskFile::GetFileSize(string filename) { - struct stat st; - if ((0 == stat(filename.c_str(), &st)) && (0 != (st.st_mode & S_IFREG))) - { - return st.st_size; - } - else - { - return 0; - } + int64 size = FileSystem::FileSize(filename.c_str()); + return size > 0 ? size : 0; } @@ -885,21 +878,19 @@ string DiskFile::TranslateFilename(string filename) bool DiskFile::Rename(void) { - char newname[_MAX_PATH+1]; + char newname[1024+1]; u32 index = 0; - struct stat st; - do { - int length = snprintf(newname, _MAX_PATH, "%s.%d", filename.c_str(), ++index); - if (length < 0 || length >= _MAX_PATH) + int length = snprintf(newname, 1024, "%s.%d", filename.c_str(), ++index); + if (length < 0 || length >= 1024) { cerr << filename << " cannot be renamed." << endl; return false; } newname[length] = 0; - } while (stat(newname, &st) == 0); + } while (FileSystem::FileExists(newname)); return Rename(newname); } @@ -912,7 +903,7 @@ bool DiskFile::Rename(string _filename) assert(file == 0); #endif - if (::rename(filename.c_str(), _filename.c_str()) == 0) + if (FileSystem::MoveFile(filename.c_str(), _filename.c_str())) { filename = _filename;