diff --git a/third_party/unrar/patches/chromium_changes.v6.0.3.patch b/third_party/unrar/patches/chromium_changes.v6.0.3.patch new file mode 100644 index 00000000000000..797b47c9e2d90b --- /dev/null +++ b/third_party/unrar/patches/chromium_changes.v6.0.3.patch @@ -0,0 +1,675 @@ +diff --git a/third_party/unrar/src/archive.cpp b/third_party/unrar/src/archive.cpp +index 8c5a1da81d14..cac841747d86 100644 +--- a/third_party/unrar/src/archive.cpp ++++ b/third_party/unrar/src/archive.cpp +@@ -336,3 +336,12 @@ int64 Archive::Tell() + } + #endif + ++#if defined(CHROMIUM_UNRAR) ++void Archive::SetTempFileHandle(FileHandle hF) { ++ hTempFile = hF; ++} ++ ++FileHandle Archive::GetTempFileHandle() { ++ return hTempFile; ++} ++#endif +diff --git a/third_party/unrar/src/archive.hpp b/third_party/unrar/src/archive.hpp +index d9518f1dc491..08fef7b0e6c0 100644 +--- a/third_party/unrar/src/archive.hpp ++++ b/third_party/unrar/src/archive.hpp +@@ -57,6 +57,13 @@ class Archive:public File + QuickOpen QOpen; + bool ProhibitQOpen; + #endif ++ ++#if defined(CHROMIUM_UNRAR) ++ // A handle for a temporary file that should be used when extracting the ++ // archive. This is used to extract the contents while in a sandbox. ++ FileHandle hTempFile; ++#endif ++ + public: + Archive(RAROptions *InitCmd=NULL); + ~Archive(); +@@ -96,6 +103,10 @@ class Archive:public File + void QOpenUnload() {QOpen.Unload();} + void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;} + #endif ++#if defined(CHROMIUM_UNRAR) ++ void SetTempFileHandle(FileHandle hF); ++ FileHandle GetTempFileHandle(); ++#endif + + BaseBlock ShortBlock; + MarkHeader MarkHead; +diff --git a/third_party/unrar/src/arcread.cpp b/third_party/unrar/src/arcread.cpp +index d1df6c04108c..468d387a2472 100644 +--- a/third_party/unrar/src/arcread.cpp ++++ b/third_party/unrar/src/arcread.cpp +@@ -142,7 +142,8 @@ size_t Archive::ReadHeader15() + + if (Decrypt) + { +-#ifdef RAR_NOCRYPT // For rarext.dll and unrar_nocrypt.dll. ++#if defined(RAR_NOCRYPT) || \ ++ defined(CHROMIUM_UNRAR) // For rarext.dll and unrar_nocrypt.dll. + return 0; + #else + RequestArcPassword(); +@@ -554,7 +555,7 @@ size_t Archive::ReadHeader50() + + if (Decrypt) + { +-#if defined(RAR_NOCRYPT) ++#if defined(RAR_NOCRYPT) || defined(CHROMIUM_UNRAR) + return 0; + #else + +diff --git a/third_party/unrar/src/crc.cpp b/third_party/unrar/src/crc.cpp +index cf23bbf4f2af..4c86c09e3b4f 100644 +--- a/third_party/unrar/src/crc.cpp ++++ b/third_party/unrar/src/crc.cpp +@@ -15,6 +15,7 @@ + #include "rar.hpp" + + static uint crc_tables[8][256]; // Tables for Slicing-by-8. ++static bool is_initialized = false; + + + // Build the classic CRC32 lookup table. +@@ -49,10 +50,13 @@ static void InitTables() + } + + +-struct CallInitCRC {CallInitCRC() {InitTables();}} static CallInit32; +- + uint CRC32(uint StartCRC,const void *Addr,size_t Size) + { ++ if (!is_initialized) { ++ is_initialized = true; ++ InitTables(); ++ } ++ + byte *Data=(byte *)Addr; + + // Align Data to 8 for better performance. +diff --git a/third_party/unrar/src/errhnd.cpp b/third_party/unrar/src/errhnd.cpp +index 18e91973e61b..dce0fbc09351 100644 +--- a/third_party/unrar/src/errhnd.cpp ++++ b/third_party/unrar/src/errhnd.cpp +@@ -1,9 +1,11 @@ +-#include "rar.hpp" ++// NOTE(vakh): The process.h file needs to be included first because "rar.hpp" ++// defines certain macros that cause symbol redefinition errors ++#if defined(UNRAR_NO_EXCEPTIONS) ++#include "base/check.h" ++#include "base/process/process.h" ++#endif // defined(UNRAR_NO_EXCEPTIONS) + +-ErrorHandler::ErrorHandler() +-{ +- Clean(); +-} ++#include "rar.hpp" + + + void ErrorHandler::Clean() +@@ -334,7 +336,11 @@ void ErrorHandler::Throw(RAR_EXIT Code) + mprintf(L"\n%s\n",St(MProgAborted)); + #endif + SetErrorCode(Code); ++#if defined(UNRAR_NO_EXCEPTIONS) ++ CHECK(false) << "Failed with RAR_EXIT code: " << Code; ++#else + throw Code; ++#endif // defined(UNRAR_NO_EXCEPTIONS) + } + + +diff --git a/third_party/unrar/src/errhnd.hpp b/third_party/unrar/src/errhnd.hpp +index 06f4f616fd96..3c5c54c490f7 100644 +--- a/third_party/unrar/src/errhnd.hpp ++++ b/third_party/unrar/src/errhnd.hpp +@@ -23,14 +23,13 @@ enum RAR_EXIT // RAR exit code. + class ErrorHandler + { + private: +- RAR_EXIT ExitCode; +- uint ErrCount; +- bool EnableBreak; +- bool Silent; +- bool DisableShutdown; // Shutdown is not suitable after last error. +- bool ReadErrIgnoreAll; ++ RAR_EXIT ExitCode = RARX_SUCCESS; ++ uint ErrCount = 0; ++ bool EnableBreak = true; ++ bool Silent = false; ++ bool DisableShutdown = false; // Shutdown is not suitable after last error. ++ bool ReadErrIgnoreAll = false; + public: +- ErrorHandler(); + void Clean(); + void MemoryError(); + void OpenError(const wchar *FileName); +@@ -67,8 +66,8 @@ class ErrorHandler + void SetDisableShutdown() {DisableShutdown=true;} + bool IsShutdownEnabled() {return !DisableShutdown;} + +- bool UserBreak; // Ctrl+Break is pressed. +- bool MainExit; // main() is completed. ++ bool UserBreak = false; // Ctrl+Break is pressed. ++ bool MainExit = false; // main() is completed. + }; + + +diff --git a/third_party/unrar/src/extract.cpp b/third_party/unrar/src/extract.cpp +index abcd3c3385c5..2c264b107040 100644 +--- a/third_party/unrar/src/extract.cpp ++++ b/third_party/unrar/src/extract.cpp +@@ -524,6 +524,11 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) + #endif + + File CurFile; ++#if defined(CHROMIUM_UNRAR) ++ // Since extraction is done in a sandbox, this must extract to the temp file ++ // handle instead of the default. ++ CurFile.SetFileHandle(Arc.GetTempFileHandle()); ++#endif + + bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE; + if (LinkEntry && Arc.FileHead.RedirType!=FSREDIR_FILECOPY) +@@ -1334,4 +1339,4 @@ void CmdExtract::GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wch + wcsncpyz(DestName,ResultName,DestSize); + } + +-#endif +\ No newline at end of file ++#endif +diff --git a/third_party/unrar/src/extract.hpp b/third_party/unrar/src/extract.hpp +index 159759b563f5..09757328f1c0 100644 +--- a/third_party/unrar/src/extract.hpp ++++ b/third_party/unrar/src/extract.hpp +@@ -62,6 +62,10 @@ class CmdExtract + void ExtractArchiveInit(Archive &Arc); + bool ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat); + static void UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize); ++ ++#if defined(CHROMIUM_UNRAR) ++ int64 GetCurrentFileSize() { return DataIO.CurUnpWrite; } ++#endif + }; + + #endif +diff --git a/third_party/unrar/src/file.cpp b/third_party/unrar/src/file.cpp +index 5a8099ec5bd1..cd6be338e486 100644 +--- a/third_party/unrar/src/file.cpp ++++ b/third_party/unrar/src/file.cpp +@@ -19,6 +19,10 @@ File::File() + #endif + ReadErrorMode=FREM_ASK; + TruncatedAfterReadError=false; ++ ++#ifdef CHROMIUM_UNRAR ++ hOpenFile=FILE_BAD_HANDLE; ++#endif + } + + +@@ -52,6 +56,11 @@ bool File::Open(const wchar *Name,uint Mode) + bool UpdateMode=(Mode & FMF_UPDATE)!=0; + bool WriteMode=(Mode & FMF_WRITE)!=0; + #ifdef _WIN_ALL ++#if defined(CHROMIUM_UNRAR) ++ // Do not open a file handle since the sandbox doesn't allow it. Use the ++ // handle provided by the caller. ++ hNewFile = hOpenFile; ++#else + uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ; + if (UpdateMode) + Access|=GENERIC_WRITE; +@@ -97,7 +106,14 @@ bool File::Open(const wchar *Name,uint Mode) + FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification. + SetFileTime(hNewFile,NULL,&ft,NULL); + } ++#endif // defined(CHROMIUM_UNRAR) ++ ++#else + ++#if defined(CHROMIUM_UNRAR) ++ // Do not open a file handle since the sandbox doesn't allow it. Use the ++ // handle provided by the caller. ++ int handle = hOpenFile; + #else + int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY); + #ifdef O_BINARY +@@ -115,6 +131,8 @@ bool File::Open(const wchar *Name,uint Mode) + WideToChar(Name,NameA,ASIZE(NameA)); + + int handle=open(NameA,flags); ++#endif // defined(CHROMIUM_UNRAR) ++ + #ifdef LOCK_EX + + #ifdef _OSF_SOURCE +@@ -174,6 +192,11 @@ bool File::WOpen(const wchar *Name) + + bool File::Create(const wchar *Name,uint Mode) + { ++#if defined(CHROMIUM_UNRAR) ++ // Since the Chromium sandbox does not allow the creation of files, use the ++ // provided file. ++ hFile = hOpenFile; ++#else + // OpenIndiana based NAS and CIFS shares fail to set the file time if file + // was created in read+write mode and some data was written and not flushed + // before SetFileTime call. So we should use the write only mode if we plan +@@ -211,6 +234,7 @@ bool File::Create(const wchar *Name,uint Mode) + hFile=fopen(NameA,WriteMode ? WRITEBINARY:CREATEBINARY); + #endif + #endif ++#endif // defined(CHROMIUM_UNRAR) + NewFile=true; + HandleType=FILE_HANDLENORMAL; + SkipClose=false; +@@ -245,6 +269,8 @@ bool File::Close() + { + if (!SkipClose) + { ++#if !defined(CHROMIUM_UNRAR) ++// unrar should not close the file handle since it wasn't opened by unrar. + #ifdef _WIN_ALL + // We use the standard system handle for stdout in Windows + // and it must not be closed here. +@@ -257,6 +283,7 @@ bool File::Close() + Success=fclose(hFile)!=EOF; + #endif + #endif ++#endif // defined(CHROMIUM_UNRAR) + } + hFile=FILE_BAD_HANDLE; + } +@@ -759,3 +786,9 @@ int64 File::Copy(File &Dest,int64 Length) + return CopySize; + } + #endif ++ ++#if defined(CHROMIUM_UNRAR) ++void File::SetFileHandle(FileHandle hF) { ++ hOpenFile = hF; ++} ++#endif // defined(CHROMIUM_UNRAR) +diff --git a/third_party/unrar/src/file.hpp b/third_party/unrar/src/file.hpp +index 1c436d4ef7bc..baf366dfa4a3 100644 +--- a/third_party/unrar/src/file.hpp ++++ b/third_party/unrar/src/file.hpp +@@ -76,6 +76,10 @@ class File + wchar FileName[NM]; + + FILE_ERRORTYPE ErrorType; ++ ++#if defined(CHROMIUM_UNRAR) ++ FileHandle hOpenFile; ++#endif // defined(CHROMIUM_UNRAR) + public: + File(); + virtual ~File(); +@@ -124,6 +128,14 @@ class File + #endif + void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;} + bool IsTruncatedAfterReadError() {return TruncatedAfterReadError;} ++ ++#if defined(CHROMIUM_UNRAR) ++ // Since unrar runs in a sandbox, it doesn't have the permission to open ++ // files on the filesystem. Instead, the caller opens the file and passes ++ // the file handle to unrar. This handle is then used to read the file. ++ void SetFileHandle(FileHandle file); ++#endif // defined(CHROMIUM_UNRAR) ++ + #ifdef _UNIX + int GetFD() + { +diff --git a/third_party/unrar/src/isnt.cpp b/third_party/unrar/src/isnt.cpp +index 6fadec049fe4..d30adf550925 100644 +--- a/third_party/unrar/src/isnt.cpp ++++ b/third_party/unrar/src/isnt.cpp +@@ -1,24 +1,18 @@ + #include "rar.hpp" + + #ifdef _WIN_ALL ++#include "versionhelpers.h" ++ + DWORD WinNT() + { +- static int dwPlatformId=-1; +- static DWORD dwMajorVersion,dwMinorVersion; +- if (dwPlatformId==-1) +- { +- OSVERSIONINFO WinVer; +- WinVer.dwOSVersionInfoSize=sizeof(WinVer); +- GetVersionEx(&WinVer); +- dwPlatformId=WinVer.dwPlatformId; +- dwMajorVersion=WinVer.dwMajorVersion; +- dwMinorVersion=WinVer.dwMinorVersion; +- } +- DWORD Result=0; +- if (dwPlatformId==VER_PLATFORM_WIN32_NT) +- Result=dwMajorVersion*0x100+dwMinorVersion; +- +- +- return Result; ++ if (!IsWindowsXPOrGreater()) ++ return WNT_NONE; ++ if (!IsWindowsVistaOrGreater()) ++ return WNT_WXP; ++ if (!IsWindows7OrGreater()) return WNT_VISTA; ++ if (!IsWindows8OrGreater()) return WNT_W7; ++ if (!IsWindows8Point1OrGreater()) return WNT_W8; ++ if (!IsWindows10OrGreater()) return WNT_W81; ++ return WNT_W10; + } + #endif +diff --git a/third_party/unrar/src/isnt.hpp b/third_party/unrar/src/isnt.hpp +index 85790da46290..a02174447e29 100644 +--- a/third_party/unrar/src/isnt.hpp ++++ b/third_party/unrar/src/isnt.hpp +@@ -1,6 +1,8 @@ + #ifndef _RAR_ISNT_ + #define _RAR_ISNT_ + ++#include "windows.h" ++ + enum WINNT_VERSION { + WNT_NONE=0,WNT_NT351=0x0333,WNT_NT4=0x0400,WNT_W2000=0x0500, + WNT_WXP=0x0501,WNT_W2003=0x0502,WNT_VISTA=0x0600,WNT_W7=0x0601, +@@ -9,5 +11,4 @@ enum WINNT_VERSION { + + DWORD WinNT(); + +- + #endif +diff --git a/third_party/unrar/src/model.cpp b/third_party/unrar/src/model.cpp +index 83391c5a4510..1ca9f03e9bcc 100644 +--- a/third_party/unrar/src/model.cpp ++++ b/third_party/unrar/src/model.cpp +@@ -43,13 +43,27 @@ void ModelPPM::RestartModelRare() + InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1; + MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext(); + if (MinContext == NULL) ++ { ++#if defined(UNRAR_NO_EXCEPTIONS) ++ base::TerminateBecauseOutOfMemory(0); ++#else + throw std::bad_alloc(); ++#endif // defined(UNRAR_NO_EXCEPTIONS) ++ } ++ + MinContext->Suffix=NULL; + OrderFall=MaxOrder; + MinContext->U.SummFreq=(MinContext->NumStats=256)+1; + FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2); + if (FoundState == NULL) ++ { ++#if defined(UNRAR_NO_EXCEPTIONS) ++ base::TerminateBecauseOutOfMemory(0); ++#else + throw std::bad_alloc(); ++#endif // defined(UNRAR_NO_EXCEPTIONS) ++ } ++ + for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++) + { + MinContext->U.Stats[i].Symbol=i; +diff --git a/third_party/unrar/src/os.hpp b/third_party/unrar/src/os.hpp +index b69f34878b3d..51d547b0f68b 100644 +--- a/third_party/unrar/src/os.hpp ++++ b/third_party/unrar/src/os.hpp +@@ -32,6 +32,7 @@ + #define STRICT 1 + #endif + ++#if !defined(CHROMIUM_UNRAR) + // 'ifndef' check here is needed for unrar.dll header to avoid macro + // re-definition warnings in third party projects. + #ifndef UNICODE +@@ -42,12 +43,15 @@ + #undef _WIN32_WINNT + #define WINVER 0x0501 + #define _WIN32_WINNT 0x0501 ++#endif // CHROMIUM_UNRAR + +-#if !defined(ZIPSFX) ++#if !defined(ZIPSFX) && !defined(CHROMIUM_UNRAR) + #define RAR_SMP + #endif + ++#if !defined(CHROMIUM_UNRAR) + #define WIN32_LEAN_AND_MEAN ++#endif // CHROMIUM_UNRAR + + #include + #include +@@ -79,8 +83,11 @@ + #include + #include + ++#if !defined(CHROMIUM_UNRAR) + #define USE_SSE + #define SSE_ALIGNMENT 16 ++#endif // CHROMIUM_UNRAR ++ + #else + #include + #endif // _MSC_VER +diff --git a/third_party/unrar/src/secpassword.cpp b/third_party/unrar/src/secpassword.cpp +index 4865b3fd02e2..c292b0e00285 100644 +--- a/third_party/unrar/src/secpassword.cpp ++++ b/third_party/unrar/src/secpassword.cpp +@@ -25,6 +25,7 @@ class CryptLoader + } + ~CryptLoader() + { ++ // We need to call FreeLibrary when RAR is exiting. + if (hCrypt!=NULL) + FreeLibrary(hCrypt); + hCrypt=NULL; +@@ -46,12 +47,14 @@ class CryptLoader + } + } + ++ static CryptLoader& GetInstance() { ++ static CryptLoader cryptLoader; ++ return cryptLoader; ++ } ++ + CRYPTPROTECTMEMORY pCryptProtectMemory; + CRYPTUNPROTECTMEMORY pCryptUnprotectMemory; + }; +- +-// We need to call FreeLibrary when RAR is exiting. +-CryptLoader GlobalCryptLoader; + #endif + + SecPassword::SecPassword() +@@ -169,16 +172,15 @@ void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess) + // increases data size not allowing in place conversion. + #if defined(_WIN_ALL) + // Try to utilize the secure Crypt[Un]ProtectMemory if possible. +- if (GlobalCryptLoader.pCryptProtectMemory==NULL) +- GlobalCryptLoader.Load(); ++ if (CryptLoader::GetInstance().pCryptProtectMemory == NULL) ++ CryptLoader::GetInstance().Load(); + size_t Aligned=DataSize-DataSize%CRYPTPROTECTMEMORY_BLOCK_SIZE; + DWORD Flags=CrossProcess ? CRYPTPROTECTMEMORY_CROSS_PROCESS : CRYPTPROTECTMEMORY_SAME_PROCESS; + if (Encode) + { +- if (GlobalCryptLoader.pCryptProtectMemory!=NULL) +- { +- if (!GlobalCryptLoader.pCryptProtectMemory(Data,DWORD(Aligned),Flags)) +- { ++ if (CryptLoader::GetInstance().pCryptProtectMemory != NULL) { ++ if (!CryptLoader::GetInstance().pCryptProtectMemory(Data, DWORD(Aligned), ++ Flags)) { + ErrHandler.GeneralErrMsg(L"CryptProtectMemory failed"); + ErrHandler.SysErrMsg(); + ErrHandler.Exit(RARX_FATAL); +@@ -188,10 +190,9 @@ void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess) + } + else + { +- if (GlobalCryptLoader.pCryptUnprotectMemory!=NULL) +- { +- if (!GlobalCryptLoader.pCryptUnprotectMemory(Data,DWORD(Aligned),Flags)) +- { ++ if (CryptLoader::GetInstance().pCryptUnprotectMemory != NULL) { ++ if (!CryptLoader::GetInstance().pCryptUnprotectMemory( ++ Data, DWORD(Aligned), Flags)) { + ErrHandler.GeneralErrMsg(L"CryptUnprotectMemory failed"); + ErrHandler.SysErrMsg(); + ErrHandler.Exit(RARX_FATAL); +diff --git a/third_party/unrar/src/unicode.cpp b/third_party/unrar/src/unicode.cpp +index 641f6c892a3f..48d7bb2fc44e 100644 +--- a/third_party/unrar/src/unicode.cpp ++++ b/third_party/unrar/src/unicode.cpp +@@ -576,7 +576,6 @@ int64 atoilw(const wchar *s) + + + #ifdef DBCS_SUPPORTED +-SupportDBCS gdbcs; + + SupportDBCS::SupportDBCS() + { +@@ -593,6 +592,11 @@ void SupportDBCS::Init() + IsLeadByte[I]=IsDBCSLeadByte(I)!=0; + } + ++// static ++SupportDBCS& SupportDBCS::GetInstance() { ++ static SupportDBCS supportDBCS; ++ return supportDBCS; ++} + + char* SupportDBCS::charnext(const char *s) + { +diff --git a/third_party/unrar/src/unicode.hpp b/third_party/unrar/src/unicode.hpp +index 031ac09ab94b..c66cc95a34cc 100644 +--- a/third_party/unrar/src/unicode.hpp ++++ b/third_party/unrar/src/unicode.hpp +@@ -33,6 +33,7 @@ class SupportDBCS + public: + SupportDBCS(); + void Init(); ++ static SupportDBCS& GetInstance(); + + char* charnext(const char *s); + size_t strlend(const char *s); +@@ -44,15 +45,13 @@ class SupportDBCS + bool DBCSMode; + }; + +-extern SupportDBCS gdbcs; +- +-inline char* charnext(const char *s) {return (char *)(gdbcs.DBCSMode ? gdbcs.charnext(s):s+1);} +-inline size_t strlend(const char *s) {return (uint)(gdbcs.DBCSMode ? gdbcs.strlend(s):strlen(s));} +-inline char* strchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strchrd(s,c):strchr(s,c));} +-inline char* strrchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strrchrd(s,c):strrchr(s,c));} +-inline void copychrd(char *dest,const char *src) {if (gdbcs.DBCSMode) gdbcs.copychrd(dest,src); else *dest=*src;} +-inline bool IsDBCSMode() {return(gdbcs.DBCSMode);} +-inline void InitDBCS() {gdbcs.Init();} ++inline char* charnext(const char *s) {return (char *)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().charnext(s):s+1);} ++inline size_t strlend(const char *s) {return (uint)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().strlend(s):strlen(s));} ++inline char* strchrd(const char *s, int c) {return (char *)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().strchrd(s,c):strchr(s,c));} ++inline char* strrchrd(const char *s, int c) {return (char *)(SupportDBCS::GetInstance().DBCSMode ? SupportDBCS::GetInstance().strrchrd(s,c):strrchr(s,c));} ++inline void copychrd(char *dest,const char *src) {if (SupportDBCS::GetInstance().DBCSMode) SupportDBCS::GetInstance().copychrd(dest,src); else *dest=*src;} ++inline bool IsDBCSMode() {return(SupportDBCS::GetInstance().DBCSMode);} ++inline void InitDBCS() {SupportDBCS::GetInstance().Init();} + + #else + #define charnext(s) ((s)+1) +diff --git a/third_party/unrar/src/unpack.cpp b/third_party/unrar/src/unpack.cpp +index 037c35546a89..7f579ff06ab3 100644 +--- a/third_party/unrar/src/unpack.cpp ++++ b/third_party/unrar/src/unpack.cpp +@@ -1,3 +1,9 @@ ++// NOTE(vakh): The process.h file needs to be included first because "rar.hpp" ++// defines certain macros that cause symbol redefinition errors ++#if defined(UNRAR_NO_EXCEPTIONS) ++#include "base/process/memory.h" ++#endif // defined(UNRAR_NO_EXCEPTIONS) ++ + #include "rar.hpp" + + #include "coder.cpp" +@@ -100,16 +106,27 @@ void Unpack::Init(size_t WinSize,bool Solid) + + // We do not handle growth for existing fragmented window. + if (Grow && Fragmented) ++ { ++#if defined(UNRAR_NO_EXCEPTIONS) ++ base::TerminateBecauseOutOfMemory(0); ++#else + throw std::bad_alloc(); ++#endif // defined(UNRAR_NO_EXCEPTIONS) ++ } + + byte *NewWindow=Fragmented ? NULL : (byte *)malloc(WinSize); + + if (NewWindow==NULL) ++ { + if (Grow || WinSize<0x1000000) + { + // We do not support growth for new fragmented window. + // Also exclude RAR4 and small dictionaries. ++#if defined(UNRAR_NO_EXCEPTIONS) ++ base::TerminateBecauseOutOfMemory(WinSize); ++#else + throw std::bad_alloc(); ++#endif // defined(UNRAR_NO_EXCEPTIONS) + } + else + { +@@ -121,6 +138,7 @@ void Unpack::Init(size_t WinSize,bool Solid) + FragWindow.Init(WinSize); + Fragmented=true; + } ++ } + + if (!Fragmented) + { +diff --git a/third_party/unrar/src/unpack50frag.cpp b/third_party/unrar/src/unpack50frag.cpp +index 3c008ff24539..16d5b1c3d5ef 100644 +--- a/third_party/unrar/src/unpack50frag.cpp ++++ b/third_party/unrar/src/unpack50frag.cpp +@@ -46,8 +46,14 @@ void FragmentedWindow::Init(size_t WinSize) + break; + Size-=Size/32; + } +- if (NewMem==NULL) ++ if (NewMem == NULL) ++ { ++#if defined(UNRAR_NO_EXCEPTIONS) ++ base::TerminateBecauseOutOfMemory(Size); ++#else + throw std::bad_alloc(); ++#endif // defined(UNRAR_NO_EXCEPTIONS) ++ } + + // Clean the window to generate the same output when unpacking corrupt + // RAR files, which may access to unused areas of sliding dictionary. +@@ -58,8 +64,14 @@ void FragmentedWindow::Init(size_t WinSize) + MemSize[BlockNum]=TotalSize; + BlockNum++; + } +- if (TotalSize *CmtData) { if (!MainComment) return false; - SaveFilePos SavePos(*this); + int64 SavePos=Tell(); + bool Success=DoGetComment(CmtData); + Seek(SavePos,SEEK_SET); + return Success; +} + +bool Archive::DoGetComment(Array *CmtData) +{ #ifndef SFX_MODULE uint CmtLength; if (Format==RARFMT14) @@ -136,7 +143,7 @@ bool Archive::GetComment(Array *CmtData) bool Archive::ReadCommentData(Array *CmtData) { Array CmtRaw; - if (!ReadSubData(&CmtRaw,NULL)) + if (!ReadSubData(&CmtRaw,NULL,false)) return false; size_t CmtSize=CmtRaw.Size(); CmtRaw.Push(0); diff --git a/third_party/unrar/src/archive.cpp b/third_party/unrar/src/archive.cpp index e4e35cb3f40744..cac841747d867b 100644 --- a/third_party/unrar/src/archive.cpp +++ b/third_party/unrar/src/archive.cpp @@ -208,8 +208,8 @@ bool Archive::IsArchive(bool EnableBroken) break; } - // This check allows to make RS based recovery even if password is incorrect. - // But we should not do it for EnableBroken or we'll get 'not RAR archive' + + // We should not do it for EnableBroken or we'll get 'not RAR archive' // messages when extracting encrypted archives with wrong password. if (FailedHeaderDecryption && !EnableBroken) return false; @@ -233,7 +233,7 @@ bool Archive::IsArchive(bool EnableBroken) // immediately after IsArchive call. if (HeadersLeft && (!SilentOpen || !Encrypted)) { - SaveFilePos SavePos(*this); + int64 SavePos=Tell(); int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; HEADER_TYPE SaveCurHeaderType=CurHeaderType; @@ -262,6 +262,7 @@ bool Archive::IsArchive(bool EnableBroken) CurBlockPos=SaveCurBlockPos; NextBlockPos=SaveNextBlockPos; CurHeaderType=SaveCurHeaderType; + Seek(SavePos,SEEK_SET); } if (!Volume || FirstVolume) wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName)); diff --git a/third_party/unrar/src/archive.hpp b/third_party/unrar/src/archive.hpp index bb05dded6b2034..08fef7b0e6c0ec 100644 --- a/third_party/unrar/src/archive.hpp +++ b/third_party/unrar/src/archive.hpp @@ -29,7 +29,6 @@ class Archive:public File void UpdateLatestTime(FileHeader *CurBlock); void ConvertNameCase(wchar *Name); void ConvertFileHeader(FileHeader *hd); - void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite); size_t ReadHeader14(); size_t ReadHeader15(); size_t ReadHeader50(); @@ -38,6 +37,7 @@ class Archive:public File void UnexpEndArcMsg(); void BrokenHeaderMsg(); void UnkEncVerMsg(const wchar *Name,const wchar *Info); + bool DoGetComment(Array *CmtData); bool ReadCommentData(Array *CmtData); #if !defined(RAR_NOCRYPT) @@ -72,8 +72,6 @@ class Archive:public File size_t SearchBlock(HEADER_TYPE HeaderType); size_t SearchSubBlock(const wchar *Type); size_t SearchRR(); - void WriteBlock(HEADER_TYPE HeaderType,BaseBlock *wb=NULL,bool OnlySetSize=false,bool NonFinalWrite=false); - void SetBlockSize(HEADER_TYPE HeaderType,BaseBlock *wb=NULL) {WriteBlock(HeaderType,wb,true);} size_t ReadHeader(); void CheckArc(bool EnableBroken); void CheckOpen(const wchar *Name); @@ -90,7 +88,7 @@ class Archive:public File int64 GetStartPos(); void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile, const wchar *Name,uint Flags); - bool ReadSubData(Array *UnpData,File *DestFile); + bool ReadSubData(Array *UnpData,File *DestFile,bool TestMode); HEADER_TYPE GetHeaderType() {return CurHeaderType;} RAROptions* GetRAROptions() {return Cmd;} void SetSilentOpen(bool Mode) {SilentOpen=Mode;} diff --git a/third_party/unrar/src/arcread.cpp b/third_party/unrar/src/arcread.cpp index f1ed7ba39bbb31..468d387a24721b 100644 --- a/third_party/unrar/src/arcread.cpp +++ b/third_party/unrar/src/arcread.cpp @@ -269,14 +269,14 @@ size_t Archive::ReadHeader15() uint FileTime=Raw.Get4(); hd->UnpVer=Raw.Get1(); - // RAR15 did not use the special dictionary size to mark dirs. - if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0) - hd->Dir=true; - hd->Method=Raw.Get1()-0x30; size_t NameSize=Raw.Get2(); hd->FileAttr=Raw.Get4(); + // RAR15 did not use the special dictionary size to mark dirs. + if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0) + hd->Dir=true; + hd->CryptMethod=CRYPT_NONE; if (hd->Encrypted) switch(hd->UnpVer) @@ -403,8 +403,8 @@ size_t Archive::ReadHeader15() if (rmode & 4) rlt.Second++; rlt.Reminder=0; - int count=rmode&3; - for (int J=0;JPassword.Clean(); } @@ -721,6 +720,7 @@ size_t Archive::ReadHeader50() UnkEncVerMsg(FileName,Info); return 0; } + Raw.GetB(CryptHead.Salt,SIZE_SALT50); if (CryptHead.UsePswCheck) { @@ -786,7 +786,7 @@ size_t Archive::ReadHeader50() case HEAD_SERVICE: { FileHeader *hd=ShortBlock.HeaderType==HEAD_FILE ? &FileHead:&SubHead; - hd->Reset(); + hd->Reset(); // Clear hash, time fields and other stuff like flags. *(BaseBlock *)hd=ShortBlock; bool FileBlock=ShortBlock.HeaderType==HEAD_FILE; @@ -1257,11 +1257,13 @@ size_t Archive::ReadHeader14() Raw.Read(NameSize); char FileName[NM]; - Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName))); - FileName[NameSize]=0; + size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1); + Raw.GetB((byte *)FileName,ReadNameSize); + FileName[ReadNameSize]=0; IntToExt(FileName,FileName,ASIZE(FileName)); CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName)); ConvertNameCase(FileHead.FileName); + ConvertFileHeader(&FileHead); if (Raw.Size()!=0) NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize; @@ -1415,7 +1417,7 @@ int64 Archive::GetStartPos() } -bool Archive::ReadSubData(Array *UnpData,File *DestFile) +bool Archive::ReadSubData(Array *UnpData,File *DestFile,bool TestMode) { if (BrokenHeader) { @@ -1463,6 +1465,7 @@ bool Archive::ReadSubData(Array *UnpData,File *DestFile) SubDataIO.SetPackedSizeToRead(SubHead.PackSize); SubDataIO.EnableShowProgress(false); SubDataIO.SetFiles(this,DestFile); + SubDataIO.SetTestMode(TestMode); SubDataIO.UnpVolume=SubHead.SplitAfter; SubDataIO.SetSubHeader(&SubHead,NULL); Unpack.SetDestSize(SubHead.UnpSize); diff --git a/third_party/unrar/src/blake2s.hpp b/third_party/unrar/src/blake2s.hpp index 7dd71571332c4a..f88ef37802c448 100644 --- a/third_party/unrar/src/blake2s.hpp +++ b/third_party/unrar/src/blake2s.hpp @@ -3,6 +3,7 @@ #define _RAR_BLAKE2_ #define BLAKE2_DIGEST_SIZE 32 +#define BLAKE2_THREADS_NUMBER 8 enum blake2s_constant { diff --git a/third_party/unrar/src/cmddata.cpp b/third_party/unrar/src/cmddata.cpp index 7b926868bcb7ec..455a07b2cff454 100644 --- a/third_party/unrar/src/cmddata.cpp +++ b/third_party/unrar/src/cmddata.cpp @@ -56,7 +56,6 @@ void CommandData::ParseCommandLine(bool Preprocess,int argc, char *argv[]) // In Windows we may prefer to implement our own command line parser // to avoid replacing \" by " in standard parser. Such replacing corrupts // destination paths like "dest path\" in extraction commands. - // Also our own parser is Unicode compatible. const wchar *CmdLine=GetCommandLine(); wchar *Par; @@ -123,6 +122,7 @@ void CommandData::ParseArg(wchar *Arg) wchar CmdChar=toupperw(*Command); bool Add=wcschr(L"AFUM",CmdChar)!=NULL; bool Extract=CmdChar=='X' || CmdChar=='E'; + bool Repair=CmdChar=='R' && Command[1]==0; if (EndSeparator && !Add) wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); else @@ -140,8 +140,8 @@ void CommandData::ParseArg(wchar *Arg) ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true); } - else - if (Found && FileData.IsDir && Extract && *ExtrPath==0) + else // We use 'destpath\' when extracting and reparing. + if (Found && FileData.IsDir && (Extract || Repair) && *ExtrPath==0) { wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); AddEndSlash(ExtrPath,ASIZE(ExtrPath)); @@ -287,17 +287,23 @@ void CommandData::ProcessSwitch(const wchar *Switch) AppendArcNameToPath=APPENDARCNAME_DESTPATH; else if (Switch[2]=='1') - AppendArcNameToPath=APPENDARCNAME_OWNDIR; + AppendArcNameToPath=APPENDARCNAME_OWNSUBDIR; + else + if (Switch[2]=='2') + AppendArcNameToPath=APPENDARCNAME_OWNDIR; break; #ifndef SFX_MODULE case 'G': if (Switch[2]=='-' && Switch[3]==0) GenerateArcName=0; else - { - GenerateArcName=true; - wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask)); - } + if (toupperw(Switch[2])=='F') + wcsncpyz(DefGenerateMask,Switch+3,ASIZE(DefGenerateMask)); + else + { + GenerateArcName=true; + wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask)); + } break; #endif case 'I': @@ -372,11 +378,11 @@ void CommandData::ProcessSwitch(const wchar *Switch) default: if (Switch[1]=='+') { - InclFileAttr|=GetExclAttr(Switch+2); + InclFileAttr|=GetExclAttr(Switch+2,InclDir); InclAttrSet=true; } else - ExclFileAttr|=GetExclAttr(Switch+1); + ExclFileAttr|=GetExclAttr(Switch+1,ExclDir); break; } break; @@ -432,9 +438,9 @@ void CommandData::ProcessSwitch(const wchar *Switch) wcsncpyz(EmailTo,Switch[4]!=0 ? Switch+4:L"@",ASIZE(EmailTo)); break; } - if (wcsicomp(Switch+1,L"M")==0) + if (wcsicomp(Switch+1,L"M")==0) // For compatibility with pre-WinRAR 6.0 -im syntax. Replaced with -idv. { - MoreInfo=true; + VerboseOutput=true; break; } if (wcsicomp(Switch+1,L"NUL")==0) @@ -461,6 +467,12 @@ void CommandData::ProcessSwitch(const wchar *Switch) case 'P': DisablePercentage=true; break; + case 'N': + DisableNames=true; + break; + case 'V': + VerboseOutput=true; + break; } break; } @@ -535,7 +547,6 @@ void CommandData::ProcessSwitch(const wchar *Switch) case 'D': Type=FILTER_DELTA; break; case 'A': Type=FILTER_AUDIO; break; case 'C': Type=FILTER_RGB; break; - case 'I': Type=FILTER_ITANIUM; break; case 'R': Type=FILTER_ARM; break; } if (*Str=='+' || *Str=='-') @@ -824,39 +835,7 @@ void CommandData::ProcessSwitch(const wchar *Switch) SetTimeFilters(Switch+2,false,false); break; case 'S': - { - EXTTIME_MODE Mode=EXTTIME_HIGH3; - bool CommonMode=Switch[2]>='0' && Switch[2]<='4'; - if (CommonMode) - Mode=(EXTTIME_MODE)(Switch[2]-'0'); - if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore. - Mode=EXTTIME_HIGH3; - if (Switch[2]=='-') - Mode=EXTTIME_NONE; - if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0) - xmtime=xctime=xatime=Mode; - else - { - if (Switch[3]>='0' && Switch[3]<='4') - Mode=(EXTTIME_MODE)(Switch[3]-'0'); - if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore. - Mode=EXTTIME_HIGH3; - if (Switch[3]=='-') - Mode=EXTTIME_NONE; - switch(toupperw(Switch[2])) - { - case 'M': - xmtime=Mode; - break; - case 'C': - xctime=Mode; - break; - case 'A': - xatime=Mode; - break; - } - } - } + SetStoreTimeMode(Switch+2); break; case '-': Test=false; @@ -959,7 +938,10 @@ void CommandData::ProcessCommand() if (wcschr(L"AFUMD",*Command)==NULL) { if (GenerateArcName) - GenerateArchiveName(ArcName,ASIZE(ArcName),GenerateMask,false); + { + const wchar *Mask=*GenerateMask!=0 ? GenerateMask:DefGenerateMask; + GenerateArchiveName(ArcName,ASIZE(ArcName),Mask,false); + } StringList ArcMasks; ArcMasks.AddString(ArcName); @@ -978,7 +960,6 @@ void CommandData::ProcessCommand() case 'X': case 'E': case 'T': - case 'I': { CmdExtract Extract(this); Extract.DoExtract(); @@ -1021,7 +1002,7 @@ bool CommandData::IsSwitch(int Ch) #ifndef SFX_MODULE -uint CommandData::GetExclAttr(const wchar *Str) +uint CommandData::GetExclAttr(const wchar *Str,bool &Dir) { if (IsDigit(*Str)) return wcstol(Str,NULL,0); @@ -1031,10 +1012,10 @@ uint CommandData::GetExclAttr(const wchar *Str) { switch(toupperw(*Str)) { -#ifdef _UNIX case 'D': - Attr|=S_IFDIR; + Dir=true; break; +#ifdef _UNIX case 'V': Attr|=S_IFCHR; break; @@ -1048,9 +1029,6 @@ uint CommandData::GetExclAttr(const wchar *Str) case 'S': Attr|=0x4; break; - case 'D': - Attr|=0x10; - break; case 'A': Attr|=0x20; break; diff --git a/third_party/unrar/src/cmddata.hpp b/third_party/unrar/src/cmddata.hpp index bf0efa66c7c801..719b4007e6d619 100644 --- a/third_party/unrar/src/cmddata.hpp +++ b/third_party/unrar/src/cmddata.hpp @@ -11,12 +11,12 @@ enum IS_PROCESS_FILE_FLAGS {IPFF_EXCLUDE_PARENT=1}; class CommandData:public RAROptions { private: - void ProcessSwitchesString(const wchar *Str); void ProcessSwitch(const wchar *Switch); void BadSwitch(const wchar *Switch); - uint GetExclAttr(const wchar *Str); + uint GetExclAttr(const wchar *Str,bool &Dir); #if !defined(SFX_MODULE) void SetTimeFilters(const wchar *Mod,bool Before,bool Age); + void SetStoreTimeMode(const wchar *S); #endif bool FileLists; @@ -33,6 +33,7 @@ class CommandData:public RAROptions void ParseEnvVar(); void ReadConfig(); void PreprocessArg(const wchar *Arg); + void ProcessSwitchesString(const wchar *Str); void OutTitle(); void OutHelp(RAR_EXIT ExitCode); bool IsSwitch(int Ch); diff --git a/third_party/unrar/src/cmdfilter.cpp b/third_party/unrar/src/cmdfilter.cpp index 20660cbdf5e907..d6517ceb79705d 100644 --- a/third_party/unrar/src/cmdfilter.cpp +++ b/third_party/unrar/src/cmdfilter.cpp @@ -128,16 +128,22 @@ void CommandData::SetTimeFilters(const wchar *Mod,bool Before,bool Age) { bool ModeOR=false,TimeMods=false; const wchar *S=Mod; - for (;wcschr(L"MCAOmcao",*S)!=NULL;S++) + // Check if any 'mca' modifiers are present, set OR mode if 'o' is present, + // skip modifiers and set S to beginning of time string. Be sure to check + // *S!=0, because termination 0 is a part of string for wcschr. + for (;*S!=0 && wcschr(L"MCAOmcao",*S)!=NULL;S++) if (*S=='o' || *S=='O') ModeOR=true; else TimeMods=true; - if (!TimeMods) + if (!TimeMods) // Assume 'm' if no modifiers are specified. Mod=L"m"; - for (;wcschr(L"MCAOmcao",*Mod)!=NULL;Mod++) + // Set the specified time for every modifier. Be sure to check *Mod!=0, + // because termination 0 is a part of string for wcschr. This check is + // important when we set Mod to "m" above. + for (;*Mod!=0 && wcschr(L"MCAOmcao",*Mod)!=NULL;Mod++) switch(toupperw(*Mod)) { case 'M': @@ -279,7 +285,10 @@ int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchTy #ifndef SFX_MODULE if (TimeCheck(FileHead.mtime,FileHead.ctime,FileHead.atime)) return 0; - if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0) + if ((FileHead.FileAttr & ExclFileAttr)!=0 || FileHead.Dir && ExclDir) + return 0; + if (InclAttrSet && (!FileHead.Dir && (FileHead.FileAttr & InclFileAttr)==0 || + FileHead.Dir && !InclDir)) return 0; if (!Dir && SizeCheck(FileHead.UnpSize)) return 0; @@ -297,3 +306,47 @@ int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchTy } return 0; } + + +#if !defined(SFX_MODULE) +void CommandData::SetStoreTimeMode(const wchar *S) +{ + if (*S==0 || IsDigit(*S) || *S=='-' || *S=='+') + { + // Apply -ts, -ts1, -ts-, -ts+ to all 3 times. + // Handle obsolete -ts[2,3,4] as ts+. + EXTTIME_MODE Mode=EXTTIME_MAX; + if (*S=='-') + Mode=EXTTIME_NONE; + if (*S=='1') + Mode=EXTTIME_1S; + xmtime=xctime=xatime=Mode; + S++; + } + + while (*S!=0) + { + EXTTIME_MODE Mode=EXTTIME_MAX; + if (S[1]=='-') + Mode=EXTTIME_NONE; + if (S[1]=='1') + Mode=EXTTIME_1S; + switch(toupperw(*S)) + { + case 'M': + xmtime=Mode; + break; + case 'C': + xctime=Mode; + break; + case 'A': + xatime=Mode; + break; + case 'P': + PreserveAtime=true; + break; + } + S++; + } +} +#endif diff --git a/third_party/unrar/src/consio.cpp b/third_party/unrar/src/consio.cpp index 196066ec9630fb..fedd5c05c5786c 100644 --- a/third_party/unrar/src/consio.cpp +++ b/third_party/unrar/src/consio.cpp @@ -164,7 +164,7 @@ static void GetPasswordText(wchar *Str,uint MaxLength) SetConsoleMode(hConIn,ConInMode); SetConsoleMode(hConOut,ConOutMode); #else - char StrA[MAXPASSWORD]; + char StrA[MAXPASSWORD*4]; // "*4" for multibyte UTF-8 characters. #if defined(_EMX) || defined (__VMS) fgets(StrA,ASIZE(StrA)-1,stdin); #elif defined(__sun) @@ -248,6 +248,12 @@ bool getwstr(wchar *str,size_t n) ErrHandler.Exit(RARX_USERBREAK); } StrA[ReadSize]=0; + + // We expect ANSI encoding here, but "echo text|rar ..." to pipe to RAR, + // such as send passwords, we get OEM encoding by default, unless we + // use "chcp" in console. But we avoid OEM to ANSI conversion, + // because we also want to handle ANSI files redirection correctly, + // like "rar ... < ansifile.txt". CharToWide(&StrA[0],str,n); cleandata(&StrA[0],StrA.Size()); // We can use this function to enter passwords. } @@ -305,7 +311,7 @@ int Ask(const wchar *AskStr) for (int I=0;I4 ? L"\n":L" "):L", "); + eprintf(I==0 ? (NumItems>3 ? L"\n":L" "):L", "); int KeyPos=ItemKeyPos[I]; for (int J=0;J> 16)] ^ crc_tables[4][(byte)(StartCRC >> 24)] ^ crc_tables[3][(byte) NextData ] ^ - crc_tables[2][(byte)(NextData >>8 ) ] ^ + crc_tables[2][(byte)(NextData >> 8) ] ^ crc_tables[1][(byte)(NextData >> 16)] ^ crc_tables[0][(byte)(NextData >> 24)]; } diff --git a/third_party/unrar/src/dll.cpp b/third_party/unrar/src/dll.cpp index 5f4d00edea91e8..31818e4980a8a6 100644 --- a/third_party/unrar/src/dll.cpp +++ b/third_party/unrar/src/dll.cpp @@ -95,23 +95,23 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r) r->Flags=0; if (Data->Arc.Volume) - r->Flags|=0x01; + r->Flags|=ROADF_VOLUME; if (Data->Arc.MainComment) - r->Flags|=0x02; + r->Flags|=ROADF_COMMENT; if (Data->Arc.Locked) - r->Flags|=0x04; + r->Flags|=ROADF_LOCK; if (Data->Arc.Solid) - r->Flags|=0x08; + r->Flags|=ROADF_SOLID; if (Data->Arc.NewNumbering) - r->Flags|=0x10; + r->Flags|=ROADF_NEWNUMBERING; if (Data->Arc.Signed) - r->Flags|=0x20; + r->Flags|=ROADF_SIGNED; if (Data->Arc.Protected) - r->Flags|=0x40; + r->Flags|=ROADF_RECOVERY; if (Data->Arc.Encrypted) - r->Flags|=0x80; + r->Flags|=ROADF_ENCHEADERS; if (Data->Arc.FirstVolume) - r->Flags|=0x100; + r->Flags|=ROADF_FIRSTVOLUME; Array CmtDataW; if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW)) @@ -474,6 +474,7 @@ static int RarErrorToDll(RAR_EXIT ErrCode) switch(ErrCode) { case RARX_FATAL: + case RARX_READ: return ERAR_EREAD; case RARX_CRC: return ERAR_BAD_DATA; diff --git a/third_party/unrar/src/dll.rc b/third_party/unrar/src/dll.rc index 4564d929749289..e12a927252c462 100644 --- a/third_party/unrar/src/dll.rc +++ b/third_party/unrar/src/dll.rc @@ -2,8 +2,8 @@ #include VS_VERSION_INFO VERSIONINFO -FILEVERSION 5, 70, 100, 2983 -PRODUCTVERSION 5, 70, 100, 2983 +FILEVERSION 6, 0, 100, 3629 +PRODUCTVERSION 6, 0, 100, 3629 FILEOS VOS__WINDOWS32 FILETYPE VFT_APP { @@ -14,9 +14,9 @@ FILETYPE VFT_APP VALUE "CompanyName", "Alexander Roshal\0" VALUE "ProductName", "RAR decompression library\0" VALUE "FileDescription", "RAR decompression library\0" - VALUE "FileVersion", "5.70.0\0" - VALUE "ProductVersion", "5.70.0\0" - VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2019\0" + VALUE "FileVersion", "6.0.0\0" + VALUE "ProductVersion", "6.0.0\0" + VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2020\0" VALUE "OriginalFilename", "Unrar.dll\0" } } diff --git a/third_party/unrar/src/errhnd.cpp b/third_party/unrar/src/errhnd.cpp index 8ccdaa7377d2ce..dce0fbc09351a2 100644 --- a/third_party/unrar/src/errhnd.cpp +++ b/third_party/unrar/src/errhnd.cpp @@ -17,6 +17,7 @@ void ErrorHandler::Clean() UserBreak=false; MainExit=false; DisableShutdown=false; + ReadErrIgnoreAll=false; } @@ -58,24 +59,34 @@ void ErrorHandler::ReadError(const wchar *FileName) ReadErrorMsg(FileName); #endif #if !defined(SILENT) || defined(RARDLL) - Exit(RARX_FATAL); + Exit(RARX_READ); #endif } -bool ErrorHandler::AskRepeatRead(const wchar *FileName) +void ErrorHandler::AskRepeatRead(const wchar *FileName,bool &Ignore,bool &Retry,bool &Quit) { + SetErrorCode(RARX_READ); #if !defined(SILENT) && !defined(SFX_MODULE) if (!Silent) { + uiMsg(UIERROR_FILEREAD,UINULL,FileName); SysErrMsg(); - bool Repeat=uiAskRepeatRead(FileName); - if (!Repeat) // Disable shutdown if user pressed Cancel in error dialog. - DisableShutdown=true; - return Repeat; + if (ReadErrIgnoreAll) + Ignore=true; + else + { + bool All=false; + uiAskRepeatRead(FileName,Ignore,All,Retry,Quit); + if (All) + ReadErrIgnoreAll=Ignore=true; + if (Quit) // Disable shutdown if user select Quit in read error prompt. + DisableShutdown=true; + } + return; } #endif - return false; + Ignore=true; // Saving the file part for -y or -inul or "Ignore all" choice. } @@ -160,6 +171,7 @@ void ErrorHandler::OpenErrorMsg(const wchar *FileName) void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName) { + Wait(); // Keep GUI responsive if many files cannot be opened when archiving. uiMsg(UIERROR_FILEOPEN,ArcName,FileName); SysErrMsg(); SetErrorCode(RARX_OPEN); @@ -190,7 +202,7 @@ void ErrorHandler::ReadErrorMsg(const wchar *ArcName,const wchar *FileName) { uiMsg(UIERROR_FILEREAD,ArcName,FileName); SysErrMsg(); - SetErrorCode(RARX_FATAL); + SetErrorCode(RARX_READ); } @@ -334,7 +346,7 @@ void ErrorHandler::Throw(RAR_EXIT Code) bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size) { -#if !defined(SFX_MODULE) && !defined(SILENT) +#ifndef SILENT #ifdef _WIN_ALL int ErrType=GetLastError(); if (ErrType!=0) @@ -367,7 +379,7 @@ void ErrorHandler::SysErrMsg() return; #ifdef _WIN_ALL wchar *CurMsg=Msg; - while (CurMsg!=NULL) + while (CurMsg!=NULL) // Print string with \r\n as several strings to multiple lines. { while (*CurMsg=='\r' || *CurMsg=='\n') CurMsg++; diff --git a/third_party/unrar/src/errhnd.hpp b/third_party/unrar/src/errhnd.hpp index 13027c12333ef1..3c5c54c490f7ae 100644 --- a/third_party/unrar/src/errhnd.hpp +++ b/third_party/unrar/src/errhnd.hpp @@ -15,9 +15,11 @@ enum RAR_EXIT // RAR exit code. RARX_CREATE = 9, RARX_NOFILES = 10, RARX_BADPWD = 11, + RARX_READ = 12, RARX_USERBREAK = 255 }; + class ErrorHandler { private: @@ -26,13 +28,14 @@ class ErrorHandler bool EnableBreak = true; bool Silent = false; bool DisableShutdown = false; // Shutdown is not suitable after last error. + bool ReadErrIgnoreAll = false; public: void Clean(); void MemoryError(); void OpenError(const wchar *FileName); void CloseError(const wchar *FileName); void ReadError(const wchar *FileName); - bool AskRepeatRead(const wchar *FileName); + void AskRepeatRead(const wchar *FileName,bool &Ignore,bool &Retry,bool &Quit); void WriteError(const wchar *ArcName,const wchar *FileName); void WriteErrorFAT(const wchar *FileName); bool AskRepeatWrite(const wchar *FileName,bool DiskFull); diff --git a/third_party/unrar/src/extract.cpp b/third_party/unrar/src/extract.cpp index a748718fe438aa..2c264b10704013 100644 --- a/third_party/unrar/src/extract.cpp +++ b/third_party/unrar/src/extract.cpp @@ -40,6 +40,9 @@ void CmdExtract::DoExtract() { if (Cmd->ManualPassword) Cmd->Password.Clean(); // Clean user entered password before processing next archive. + + ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit(). + UseExactVolName=false; // Must be reset here, not in ExtractArchiveInit(). while (true) { EXTRACT_ARC_CODE Code=ExtractArchive(); @@ -93,7 +96,6 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc) PrevProcessed=false; AllMatchesExact=true; - ReconstructDone=false; AnySolidDataUnpackedWell=false; StartTime.SetCurrentTime(); @@ -139,7 +141,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() return EXTRACT_ARC_NEXT; #ifndef SFX_MODULE - if (Arc.Volume && !Arc.FirstVolume) + if (Arc.Volume && !Arc.FirstVolume && !UseExactVolName) { wchar FirstVolName[NM]; VolNameToFirstName(ArcName,FirstVolName,ASIZE(FirstVolName),Arc.NewNumbering); @@ -157,6 +159,16 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive() if (Arc.Volume) { +#ifndef SFX_MODULE + // Try to speed up extraction for independent solid volumes by starting + // extraction from non-first volume if we can. + if (!UseExactVolName && Arc.Solid && DetectStartVolume(Arc.FileName,Arc.NewNumbering)) + { + UseExactVolName=true; + return EXTRACT_ARC_REPEAT; + } +#endif + // Calculate the total size of all accessible volumes. // This size is necessary to display the correct total progress indicator. @@ -317,11 +329,11 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) Arc.ConvertAttributes(); #if !defined(SFX_MODULE) && !defined(RARDLL) - if (Arc.FileHead.SplitBefore && FirstFile) + if (Arc.FileHead.SplitBefore && FirstFile && !UseExactVolName) { wchar CurVolName[NM]; wcsncpyz(CurVolName,ArcName,ASIZE(CurVolName)); - VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),Arc.NewNumbering); + GetFirstVolIfFullSet(ArcName,Arc.NewNumbering,ArcName,ASIZE(ArcName)); if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName)) { @@ -479,13 +491,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) { // This message is used by Android GUI to reset cached passwords. // Update appropriate code if changed. - uiMsg(UIERROR_BADPSW,ArcFileName); + uiMsg(UIERROR_BADPSW,Arc.FileName,ArcFileName); } else // For passwords entered manually. { // This message is used by Android GUI and Windows GUI and SFX to // reset cached passwords. Update appropriate code if changed. - uiMsg(UIWAIT_BADPSW,ArcFileName); + uiMsg(UIWAIT_BADPSW,Arc.FileName,ArcFileName); Cmd->Password.Clean(); // Avoid new requests for unrar.dll to prevent the infinite loop @@ -579,7 +591,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) TotalFileCount++; } FileCount++; - if (Command!='I') + if (Command!='I' && !Cmd->DisableNames) if (SkipSolid) mprintf(St(MExtrSkipFile),ArcFileName); else @@ -598,8 +610,10 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) mprintf(St(MExtrFile),DestFileName); break; } - if (!Cmd->DisablePercentage) + if (!Cmd->DisablePercentage && !Cmd->DisableNames) mprintf(L" "); + if (Cmd->DisableNames) + uiEolAfterMsg(); // Avoid erasing preceding messages by percentage indicator in -idn mode. DataIO.CurUnpRead=0; DataIO.CurUnpWrite=0; @@ -621,11 +635,14 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) } #endif - if (!TestMode && !Arc.BrokenHeader && - (Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize && + uint64 Preallocated=0; + if (!TestMode && !Arc.BrokenHeader && Arc.FileHead.UnpSize>1000000 && + Arc.FileHead.PackSize*1024>Arc.FileHead.UnpSize && (Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize)) + { CurFile.Prealloc(Arc.FileHead.UnpSize); - + Preallocated=Arc.FileHead.UnpSize; + } CurFile.SetAllowDelete(!Cmd->KeepBroken); bool FileCreateMode=!TestMode && !SkipSolid && Command!='P'; @@ -712,7 +729,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) { if (ValidCRC) { - if (Command!='P' && Command!='I') + if (Command!='P' && Command!='I' && !Cmd->DisableNames) mprintf(L"%s%s ",Cmd->DisablePercentage ? L" ":L"\b\b\b\b\b ", Arc.FileHead.FileHash.Type==HASH_NONE ? L" ?":St(MOk)); } @@ -737,37 +754,58 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) else mprintf(L"\b\b\b\b\b "); + // If we successfully unpacked a hard link, we wish to set its file + // attributes. Hard link shares file metadata with link target, + // so we do not need to set link time or owner. But when we overwrite + // an existing link, we can call PrepareToDelete(), which affects + // link target attributes as well. So we set link attributes to restore + // both target and link attributes if PrepareToDelete() changed them. + bool SetAttrOnly=LinkEntry && Arc.FileHead.RedirType==FSREDIR_HARDLINK && LinkSuccess; + if (!TestMode && (Command=='X' || Command=='E') && - (!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && + (!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) && (!BrokenFile || Cmd->KeepBroken)) { - // We could preallocate more space that really written to broken file. - if (BrokenFile) - CurFile.Truncate(); + // Below we use DestFileName instead of CurFile.FileName, + // so we can set file attributes also for hard links, which do not + // have the open CurFile. These strings are the same for other items. + + if (!SetAttrOnly) + { + // We could preallocate more space that really written to broken file + // or file with crafted header. + if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated)) + CurFile.Truncate(); -#if defined(_WIN_ALL) || defined(_EMX) - if (Cmd->ClearArc) - Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE; -#endif + CurFile.SetOpenFileTime( + Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, + Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime, + Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); + CurFile.Close(); - CurFile.SetOpenFileTime( - Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, - Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime, - Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); - CurFile.Close(); + SetFileHeaderExtra(Cmd,Arc,DestFileName); + + CurFile.SetCloseFileTime( + Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, + Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); + } + #if defined(_WIN_ALL) && !defined(SFX_MODULE) if (Cmd->SetCompressedAttr && (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0) - SetFileCompression(CurFile.FileName,true); + SetFileCompression(DestFileName,true); + if (Cmd->ClearArc) + Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE; #endif - SetFileHeaderExtra(Cmd,Arc,CurFile.FileName); - - CurFile.SetCloseFileTime( - Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime, - Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime); - if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr)) - uiMsg(UIERROR_FILEATTR,Arc.FileName,CurFile.FileName); + if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr)) + { + uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName); + // Android cannot set file attributes and while UIERROR_FILEATTR + // above is handled by Android RAR silently, this call would cause + // "Operation not permitted" message for every unpacked file. + ErrHandler.SysErrMsg(); + } PrevProcessed=true; } @@ -860,11 +898,21 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De #ifndef SFX_MODULE if (Cmd->AppendArcNameToPath!=APPENDARCNAME_NONE) { - if (Cmd->AppendArcNameToPath==APPENDARCNAME_DESTPATH) - wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize); - else - wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); // To archive own dir. - SetExt(DestName,NULL,DestSize); + switch(Cmd->AppendArcNameToPath) + { + case APPENDARCNAME_DESTPATH: // To subdir of destination path. + wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize); + SetExt(DestName,NULL,DestSize); + break; + case APPENDARCNAME_OWNSUBDIR: // To subdir of archive own dir. + wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); + SetExt(DestName,NULL,DestSize); + break; + case APPENDARCNAME_OWNDIR: // To archive own dir. + wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); + RemoveNameFromPath(DestName); + break; + } AddEndSlash(DestName,DestSize); } #endif @@ -976,7 +1024,11 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName) if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password)/* || !Cmd->Password.IsSet()*/) { // Suppress "test is ok" message if user cancelled the password prompt. - uiMsg(UIERROR_INCERRCOUNT); +// 2019.03.23: If some archives are tested ok and prompt is cancelled for others, +// do we really need to suppress "test is ok"? Also if we set an empty password +// and "Use for all archives" in WinRAR Ctrl+P and skip some encrypted archives. +// We commented out this UIERROR_INCERRCOUNT for now. +// uiMsg(UIERROR_INCERRCOUNT); return false; } Cmd->ManualPassword=true; @@ -1030,8 +1082,11 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) { if (Cmd->Test) { - mprintf(St(MExtrTestFile),ArcFileName); - mprintf(L" %s",St(MOk)); + if (!Cmd->DisableNames) + { + mprintf(St(MExtrTestFile),ArcFileName); + mprintf(L" %s",St(MOk)); + } return; } @@ -1068,8 +1123,11 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) } if (MDCode==MKDIR_SUCCESS) { - mprintf(St(MCreatDir),DestFileName); - mprintf(L" %s",St(MOk)); + if (!Cmd->DisableNames) + { + mprintf(St(MCreatDir),DestFileName); + mprintf(L" %s",St(MOk)); + } PrevProcessed=true; } else @@ -1123,6 +1181,9 @@ bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile) if (!UserReject) { ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName); + if (FileExist(DestFileName) && IsDir(GetFileAttr(DestFileName))) + uiMsg(UIERROR_DIRNAMEEXISTS); + #ifdef RARDLL Cmd->DllError=ERAR_ECREATE; #endif @@ -1178,3 +1239,104 @@ bool CmdExtract::CheckUnpVer(Archive &Arc,const wchar *ArcFileName) } return !WrongVer; } + + +#ifndef SFX_MODULE +// To speed up solid volumes extraction, try to find a non-first start volume, +// which still allows to unpack all files. It is possible for independent +// solid volumes with solid statistics reset in the beginning. +bool CmdExtract::DetectStartVolume(const wchar *VolName,bool NewNumbering) +{ + wchar *ArgName=Cmd->FileArgs.GetString(); + Cmd->FileArgs.Rewind(); + if (ArgName!=NULL && (wcscmp(ArgName,L"*")==0 || wcscmp(ArgName,L"*.*")==0)) + return false; // No need to check further for * and *.* masks. + + wchar StartName[NM]; + *StartName=0; + + // Start search from first volume if all volumes preceding current are available. + wchar NextName[NM]; + GetFirstVolIfFullSet(VolName,NewNumbering,NextName,ASIZE(NextName)); + + bool Matched=false; + while (!Matched) + { + Archive Arc(Cmd); + if (!Arc.Open(NextName) || !Arc.IsArchive(false) || !Arc.Volume) + break; + + bool OpenNext=false; + while (Arc.ReadHeader()>0) + { + Wait(); + + HEADER_TYPE HeaderType=Arc.GetHeaderType(); + if (HeaderType==HEAD_ENDARC) + { + OpenNext|=Arc.EndArcHead.NextVolume; // Allow open next volume. + break; + } + if (HeaderType==HEAD_FILE) + { + if (!Arc.FileHead.SplitBefore) + { + if (!Arc.FileHead.Solid) // Can start extraction from here. + wcsncpyz(StartName,NextName,ASIZE(StartName)); + + if (Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0) + { + Matched=true; // First matched file found, must stop further scan. + break; + } + } + if (Arc.FileHead.SplitAfter) + { + OpenNext=true; // Allow open next volume. + break; + } + } + Arc.SeekToNext(); + } + Arc.Close(); + + if (!OpenNext) + break; + + NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering); + } + bool NewStartFound=wcscmp(VolName,StartName)!=0; + if (NewStartFound) // Found a new volume to start extraction. + wcsncpyz(ArcName,StartName,ASIZE(ArcName)); + + return NewStartFound; +} +#endif + + +#ifndef SFX_MODULE +// Return the first volume name if all volumes preceding the specified +// are available. Otherwise return the specified volume name. +void CmdExtract::GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wchar *DestName,size_t DestSize) +{ + wchar FirstVolName[NM]; + VolNameToFirstName(SrcName,FirstVolName,ASIZE(FirstVolName),NewNumbering); + wchar NextName[NM]; + wcsncpyz(NextName,FirstVolName,ASIZE(NextName)); + wchar ResultName[NM]; + wcsncpyz(ResultName,SrcName,ASIZE(ResultName)); + while (true) + { + if (wcscmp(SrcName,NextName)==0) + { + wcsncpyz(ResultName,FirstVolName,DestSize); + break; + } + if (!FileExist(NextName)) + break; + NextVolumeName(NextName,ASIZE(NextName),!NewNumbering); + } + wcsncpyz(DestName,ResultName,DestSize); +} + +#endif diff --git a/third_party/unrar/src/extract.hpp b/third_party/unrar/src/extract.hpp index aa69a3dc3eddb2..09757328f1c020 100644 --- a/third_party/unrar/src/extract.hpp +++ b/third_party/unrar/src/extract.hpp @@ -20,8 +20,12 @@ class CmdExtract void ExtrCreateDir(Archive &Arc,const wchar *ArcFileName); bool ExtrCreateFile(Archive &Arc,File &CurFile); bool CheckUnpVer(Archive &Arc,const wchar *ArcFileName); +#ifndef SFX_MODULE + bool DetectStartVolume(const wchar *VolName,bool NewNumbering); + void GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wchar *DestName,size_t DestSize); +#endif - RarTime StartTime; // time when extraction started + RarTime StartTime; // Time when extraction started. CommandData *Cmd; @@ -34,6 +38,7 @@ class CmdExtract bool FirstFile; bool AllMatchesExact; bool ReconstructDone; + bool UseExactVolName; // If any non-zero solid file was successfully unpacked before current. // If true and if current encrypted file is broken, obviously diff --git a/third_party/unrar/src/file.cpp b/third_party/unrar/src/file.cpp index d8bf24a51b1eb0..cd6be338e486f4 100644 --- a/third_party/unrar/src/file.cpp +++ b/third_party/unrar/src/file.cpp @@ -8,15 +8,17 @@ File::File() LastWrite=false; HandleType=FILE_HANDLENORMAL; SkipClose=false; - IgnoreReadErrors=false; ErrorType=FILE_SUCCESS; OpenShared=false; AllowDelete=true; AllowExceptions=true; + PreserveAtime=false; #ifdef _WIN_ALL NoSequentialRead=false; CreateMode=FMF_UNDEFINED; #endif + ReadErrorMode=FREM_ASK; + TruncatedAfterReadError=false; #ifdef CHROMIUM_UNRAR hOpenFile=FILE_BAD_HANDLE; @@ -40,6 +42,7 @@ void File::operator = (File &SrcFile) NewFile=SrcFile.NewFile; LastWrite=SrcFile.LastWrite; HandleType=SrcFile.HandleType; + TruncatedAfterReadError=SrcFile.TruncatedAfterReadError; wcsncpyz(FileName,SrcFile.FileName,ASIZE(FileName)); SrcFile.SkipClose=true; } @@ -65,6 +68,9 @@ bool File::Open(const wchar *Name,uint Mode) if (OpenShared) ShareMode|=FILE_SHARE_WRITE; uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN; + FindData FD; + if (PreserveAtime) + Access|=FILE_WRITE_ATTRIBUTES; // Needed to preserve atime. hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); DWORD LastError; @@ -95,7 +101,11 @@ bool File::Open(const wchar *Name,uint Mode) } if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND) ErrorType=FILE_NOTFOUND; - + if (PreserveAtime && hNewFile!=FILE_BAD_HANDLE) + { + FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification. + SetFileTime(hNewFile,NULL,&ft,NULL); + } #endif // defined(CHROMIUM_UNRAR) #else @@ -111,9 +121,15 @@ bool File::Open(const wchar *Name,uint Mode) #if defined(_AIX) && defined(_LARGE_FILE_API) flags|=O_LARGEFILE; #endif +#endif + // NDK r20 has O_NOATIME, but fails to create files with it in Android 7+. +#if defined(O_NOATIME) + if (PreserveAtime) + flags|=O_NOATIME; #endif char NameA[NM]; WideToChar(Name,NameA,ASIZE(NameA)); + int handle=open(NameA,flags); #endif // defined(CHROMIUM_UNRAR) @@ -122,12 +138,12 @@ bool File::Open(const wchar *Name,uint Mode) #ifdef _OSF_SOURCE extern "C" int flock(int, int); #endif - if (!OpenShared && UpdateMode && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1) { close(handle); return false; } + #endif if (handle==-1) hNewFile=FILE_BAD_HANDLE; @@ -150,6 +166,7 @@ bool File::Open(const wchar *Name,uint Mode) { hFile=hNewFile; wcsncpyz(FileName,Name,ASIZE(FileName)); + TruncatedAfterReadError=false; } return Success; } @@ -256,7 +273,7 @@ bool File::Close() // unrar should not close the file handle since it wasn't opened by unrar. #ifdef _WIN_ALL // We use the standard system handle for stdout in Windows - // and it must not be closed here. + // and it must not be closed here. if (HandleType==FILE_HANDLENORMAL) Success=CloseHandle(hFile)==TRUE; #else @@ -382,9 +399,12 @@ bool File::Write(const void *Data,size_t Size) int File::Read(void *Data,size_t Size) { + if (TruncatedAfterReadError) + return 0; + int64 FilePos=0; // Initialized only to suppress some compilers warning. - if (IgnoreReadErrors) + if (ReadErrorMode==FREM_IGNORE) FilePos=Tell(); int ReadSize; while (true) @@ -394,7 +414,7 @@ int File::Read(void *Data,size_t Size) { ErrorType=FILE_READERROR; if (AllowExceptions) - if (IgnoreReadErrors) + if (ReadErrorMode==FREM_IGNORE) { ReadSize=0; for (size_t I=0;ITell(); #ifndef SILENT int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size; #endif @@ -415,6 +415,8 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size, if (Size!=INT64NDF) Size-=ReadSize; } + SrcFile->Seek(SavePos,SEEK_SET); + if ((Flags & CALCFSUM_SHOWPERCENT)!=0) uiMsg(UIEVENT_FILESUMEND); diff --git a/third_party/unrar/src/find.cpp b/third_party/unrar/src/find.cpp index 98cf7719cbd2c2..b22f82d8f224d9 100644 --- a/third_party/unrar/src/find.cpp +++ b/third_party/unrar/src/find.cpp @@ -63,12 +63,12 @@ bool FindFile::Next(FindData *fd,bool GetSymLink) } while (1) { + wchar Name[NM]; struct dirent *ent=readdir(dirp); if (ent==NULL) return false; if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0) continue; - wchar Name[NM]; if (!CharToWide(ent->d_name,Name,ASIZE(Name))) uiMsg(UIERROR_INVALIDNAME,UINULL,Name); diff --git a/third_party/unrar/src/hash.cpp b/third_party/unrar/src/hash.cpp index 42791f4f437a42..a4559e05c3cce0 100644 --- a/third_party/unrar/src/hash.cpp +++ b/third_party/unrar/src/hash.cpp @@ -53,7 +53,7 @@ DataHash::DataHash() DataHash::~DataHash() { #ifdef RAR_SMP - DestroyThreadPool(ThPool); + delete ThPool; #endif cleandata(&CurCRC32, sizeof(CurCRC32)); if (blake2ctx!=NULL) @@ -94,7 +94,7 @@ void DataHash::Update(const void *Data,size_t DataSize) { #ifdef RAR_SMP if (MaxThreads>1 && ThPool==NULL) - ThPool=CreateThreadPool(); + ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER); blake2ctx->ThPool=ThPool; blake2ctx->MaxThreads=MaxThreads; #endif diff --git a/third_party/unrar/src/list.cpp b/third_party/unrar/src/list.cpp index 11c404ea981693..476fd3c65cfab5 100644 --- a/third_party/unrar/src/list.cpp +++ b/third_party/unrar/src/list.cpp @@ -28,7 +28,7 @@ void ListArchive(CommandData *Cmd) if (!Arc.WOpen(ArcName)) continue; bool FileMatched=true; - while (1) + while (true) { int64 TotalPackSize=0,TotalUnpSize=0; uint FileCount=0; @@ -69,8 +69,9 @@ void ListArchive(CommandData *Cmd) wchar VolNumText[50]; *VolNumText=0; - while(Arc.ReadHeader()>0) + while (Arc.ReadHeader()>0) { + Wait(); // Allow quit listing with Ctrl+C. HEADER_TYPE HeaderType=Arc.GetHeaderType(); if (HeaderType==HEAD_ENDARC) { @@ -344,7 +345,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS); mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo), - Format==RARFMT15 ? L"3.0":L"5.0", + Format==RARFMT15 ? L"1.5":L"5.0", hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method, hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400, hd.WinSize>=0x100000 ? L"M":L"K"); diff --git a/third_party/unrar/src/loclang.hpp b/third_party/unrar/src/loclang.hpp index 181fcb4e1a61cc..99108c93615df4 100644 --- a/third_party/unrar/src/loclang.hpp +++ b/third_party/unrar/src/loclang.hpp @@ -4,6 +4,7 @@ #define MYesNoAllRenQ L"_Yes_No_All_nEver_Rename_Quit" #define MContinueQuit L"_Continue_Quit" #define MRetryAbort L"_Retry_Abort" +#define MIgnoreAllRetryQuit L"_Ignore_iGnore all_Retry_Quit" #define MCopyright L"\nRAR %s Copyright (c) 1993-%d Alexander Roshal %d %s %d" #define MRegTo L"\nRegistered to %s\n" #define MShare L"\nTrial version Type 'rar -?' for help\n" @@ -54,7 +55,7 @@ #define MCHelpSwm L"\n - Stop switches scanning" #define MCHelpSwAT L"\n @[+] Disable [enable] file lists" #define MCHelpSwAC L"\n ac Clear Archive attribute after compression or extraction" -#define MCHelpSwAD L"\n ad Append archive name to destination path" +#define MCHelpSwAD L"\n ad[1,2] Alternate destination path" #define MCHelpSwAG L"\n ag[format] Generate archive name using the current date" #define MCHelpSwAI L"\n ai Ignore file attributes" #define MCHelpSwAO L"\n ao Add files with Archive attribute set" @@ -79,13 +80,13 @@ #define MCHelpSwF L"\n f Freshen files" #define MCHelpSwHP L"\n hp[password] Encrypt both file data and headers" #define MCHelpSwHT L"\n ht[b|c] Select hash type [BLAKE2,CRC32] for file checksum" -#define MCHelpSwIDP L"\n id[c,d,p,q] Disable messages" +#define MCHelpSwIDP L"\n id[c,d,n,p,q] Display or disable messages" #define MCHelpSwIEML L"\n ieml[addr] Send archive by email" #define MCHelpSwIERR L"\n ierr Send all messages to stderr" #define MCHelpSwILOG L"\n ilog[name] Log errors to file" #define MCHelpSwINUL L"\n inul Disable all messages" #define MCHelpSwIOFF L"\n ioff[n] Turn PC off after completing an operation" -#define MCHelpSwISND L"\n isnd Control notification sounds" +#define MCHelpSwISND L"\n isnd[-] Control notification sounds" #define MCHelpSwIVER L"\n iver Display the version number" #define MCHelpSwK L"\n k Lock archive" #define MCHelpSwKB L"\n kb Keep broken extracted files" @@ -131,7 +132,7 @@ #define MCHelpSwTO L"\n to[mcao] Process files older than time" #define MCHelpSwTA L"\n ta[mcao] Process files modified after YYYYMMDDHHMMSS date" #define MCHelpSwTB L"\n tb[mcao] Process files modified before YYYYMMDDHHMMSS date" -#define MCHelpSwTS L"\n ts[m,c,a] Save or restore file time (modification, creation, access)" +#define MCHelpSwTS L"\n ts[m,c,a,p] Save or restore time (modification, creation, access, preserve)" #define MCHelpSwU L"\n u Update files" #define MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes" #define MCHelpSwVUnr L"\n v List all volumes" @@ -203,7 +204,6 @@ #define MErrOpenFile L"file" #define MAddNoFiles L"\nWARNING: No files" #define MMdfEncrSol L"\n%s: encrypted" -#define MCannotMdfEncrSol L"\nCannot modify solid archive containing encrypted files" #define MAddAnalyze L"\nAnalyzing archived files: " #define MRepacking L"\nRepacking archived files: " #define MCRCFailed L"\n%-20s - checksum error" @@ -342,7 +342,7 @@ #define MFAT32Size L"\nWARNING: FAT32 file system does not support 4 GB or larger files" #define MErrChangeAttr L"\nWARNING: Cannot change attributes of %s" #define MWrongSFXVer L"\nERROR: default SFX module does not support RAR %d.%d archives" -#define MCannotEncName L"\nCannot encrypt archive already containing encrypted files" +#define MHeadEncMismatch L"\nCannot change the header encryption mode in already encrypted archive" #define MCannotEmail L"\nCannot email the file %s" #define MCopyrightS L"\nRAR SFX archive" #define MSHelpCmd L"\n\n" @@ -352,7 +352,7 @@ #define MRecVolLimit L"\nTotal number of usual and recovery volumes must not exceed %d" #define MVolumeNumber L"volume %d" #define MCannotDelete L"\nCannot delete %s" -#define MRecycleFailed L"\nCannot move some files and folders to Recycle Bin" +#define MRecycleFailed L"\nCannot move some files and directories to Recycle Bin" #define MCalcCRC L"\nCalculating the checksum" #define MTooLargeSFXArc L"\nToo large SFX archive. Windows cannot run the executable file exceeding 4 GB." #define MCalcCRCAllVol L"\nCalculating checksums of all volumes." @@ -360,6 +360,7 @@ #define MNewerRAR L"\nYou may need a newer version of RAR." #define MUnkEncMethod L"\nUnknown encryption method in %s" #define MWrongPassword L"\nThe specified password is incorrect." +#define MWrongFilePassword L"\nIncorrect password for %s" #define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x" #define MBlocksRecovered L"\n%u blocks are recovered, %u blocks are relocated" #define MRRDamaged L"\nRecovery record is corrupt." @@ -379,3 +380,8 @@ #define MNeedAdmin L"\nYou may need to run RAR as administrator" #define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB." #define MUseSmalllerDict L"\nPlease use a smaller compression dictionary." +#define MOpenErrAtime L"\nYou may need to remove -tsp switch to open this file." +#define MErrReadInfo L"\nChoose 'Ignore' to continue with the already read file part only, 'Ignore all' to do it for all read errors, 'Retry' to repeat read and 'Quit' to abort." +#define MErrReadTrunc L"\n%s is archived incompletely because of read error.\n" +#define MErrReadCount L"\n%u files are archived incompletely because of read errors." +#define MDirNameExists L"\nDirectory with such name already exists" diff --git a/third_party/unrar/src/makefile b/third_party/unrar/src/makefile index f70755fc59259e..214f87ef3360f0 100644 --- a/third_party/unrar/src/makefile +++ b/third_party/unrar/src/makefile @@ -138,7 +138,9 @@ install: install-unrar uninstall: uninstall-unrar clean: - @rm -f *.o *.bak *~ + @rm -f *.bak *~ + @rm -f $(OBJECTS) $(UNRAR_OBJ) $(LIB_OBJ) + @rm -f unrar libunrar.* unrar: clean $(OBJECTS) $(UNRAR_OBJ) @rm -f unrar @@ -154,8 +156,7 @@ sfx: clean $(OBJECTS) lib: WHAT=RARDLL lib: CXXFLAGS+=$(LIBFLAGS) lib: clean $(OBJECTS) $(LIB_OBJ) - @rm -f libunrar.so - @rm -f libunrar.a + @rm -f libunrar.* $(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ) $(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ) diff --git a/third_party/unrar/src/options.cpp b/third_party/unrar/src/options.cpp index b53edc668010f5..40323be82863a6 100644 --- a/third_party/unrar/src/options.cpp +++ b/third_party/unrar/src/options.cpp @@ -22,7 +22,7 @@ void RAROptions::Init() Method=3; MsgStream=MSG_STDOUT; ConvertNames=NAMES_ORIGINALCASE; - xmtime=EXTTIME_HIGH3; + xmtime=EXTTIME_MAX; FileSizeLess=INT64NDF; FileSizeMore=INT64NDF; HashType=HASH_CRC32; diff --git a/third_party/unrar/src/options.hpp b/third_party/unrar/src/options.hpp index 7c33a034d36113..993b219633a956 100644 --- a/third_party/unrar/src/options.hpp +++ b/third_party/unrar/src/options.hpp @@ -21,7 +21,7 @@ enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4, enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST}; enum EXTTIME_MODE { - EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3 + EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_MAX }; enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE}; @@ -61,7 +61,8 @@ enum SAVECOPY_MODE { enum APPENDARCNAME_MODE { - APPENDARCNAME_NONE=0,APPENDARCNAME_DESTPATH,APPENDARCNAME_OWNDIR + APPENDARCNAME_NONE=0,APPENDARCNAME_DESTPATH,APPENDARCNAME_OWNSUBDIR, + APPENDARCNAME_OWNDIR }; enum POWER_MODE { @@ -92,6 +93,12 @@ class RAROptions uint ExclFileAttr; uint InclFileAttr; + + // We handle -ed and -e+d with special flags instead of attribute mask, + // so it works with both Windows and Unix archives. + bool ExclDir; + bool InclDir; + bool InclAttrSet; size_t WinSize; wchar TempPath[NM]; @@ -126,6 +133,7 @@ class RAROptions bool DisablePercentage; bool DisableCopyright; bool DisableDone; + bool DisableNames; bool PrintVersion; int Solid; int SolidCount; @@ -140,7 +148,7 @@ class RAROptions Array NextVolSizes; uint CurVolNum; bool AllYes; - bool MoreInfo; // -im, show more information, used only in "WinRAR t" now. + bool VerboseOutput; // -iv, display verbose output, used only in "WinRAR t" now. bool DisableSortSolid; int ArcTime; int ConvertNames; @@ -162,6 +170,7 @@ class RAROptions #ifndef SFX_MODULE bool GenerateArcName; wchar GenerateMask[MAX_GENERATE_MASK]; + wchar DefGenerateMask[MAX_GENERATE_MASK]; #endif bool SyncFiles; bool ProcessEA; @@ -185,6 +194,7 @@ class RAROptions EXTTIME_MODE xmtime; // Extended time modes (time precision to store). EXTTIME_MODE xctime; EXTTIME_MODE xatime; + bool PreserveAtime; wchar CompressStdin[NM]; uint Threads; // We use it to init hash even if RAR_SMP is not defined. diff --git a/third_party/unrar/src/os.hpp b/third_party/unrar/src/os.hpp index 707d604fc726fa..51d547b0f68ba0 100644 --- a/third_party/unrar/src/os.hpp +++ b/third_party/unrar/src/os.hpp @@ -140,7 +140,7 @@ #ifdef _UNIX -#define NM 2048 +#define NM 2048 #include #include diff --git a/third_party/unrar/src/pathfn.cpp b/third_party/unrar/src/pathfn.cpp index cb1d7edfc661cc..41594bf955278f 100644 --- a/third_party/unrar/src/pathfn.cpp +++ b/third_party/unrar/src/pathfn.cpp @@ -170,14 +170,17 @@ int GetPathDisk(const wchar *Path) void AddEndSlash(wchar *Path,size_t MaxLength) { size_t Length=wcslen(Path); - if (Length>0 && Path[Length-1]!=CPATHDIVIDER) - wcsncatz(Path,SPATHDIVIDER,MaxLength); + if (Length>0 && Path[Length-1]!=CPATHDIVIDER && Length+1Tell(); UnsyncSeekPos=false; - SaveFilePos SavePos(*Arc); + int64 SavePos=SeekPos; Arc->Seek(BlockPos,SEEK_SET); // If BlockPos points to original main header, we'll have the infinite @@ -83,10 +83,14 @@ void QuickOpen::Load(uint64 BlockPos) if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE || !Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN)) + { + Arc->Seek(SavePos,SEEK_SET); return; + } QOHeaderPos=Arc->CurBlockPos; RawDataStart=Arc->Tell(); RawDataSize=Arc->SubHead.UnpSize; + Arc->Seek(SavePos,SEEK_SET); Loaded=true; // Set only after all file processing calls like Tell, Seek, ReadHeader. } @@ -201,22 +205,28 @@ bool QuickOpen::Tell(int64 *Pos) uint QuickOpen::ReadBuffer() { - SaveFilePos SavePos(*Arc); + int64 SavePos=Arc->Tell(); Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET); size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize); if (Arc->SubHead.Encrypted) SizeToRead &= ~CRYPT_BLOCK_MASK; - if (SizeToRead==0) - return 0; - int ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead); - if (ReadSize<=0) - return 0; + int ReadSize=0; + if (SizeToRead!=0) + { + ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead); + if (ReadSize<=0) + ReadSize=0; + else + { #ifndef RAR_NOCRYPT - if (Arc->SubHead.Encrypted) - Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK); + if (Arc->SubHead.Encrypted) + Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK); #endif - RawDataPos+=ReadSize; - ReadBufSize+=ReadSize; + RawDataPos+=ReadSize; + ReadBufSize+=ReadSize; + } + } + Arc->Seek(SavePos,SEEK_SET); return ReadSize; } diff --git a/third_party/unrar/src/rar.hpp b/third_party/unrar/src/rar.hpp index 65e049671e651f..3f7414c87d41d6 100644 --- a/third_party/unrar/src/rar.hpp +++ b/third_party/unrar/src/rar.hpp @@ -39,7 +39,6 @@ #include "filestr.hpp" #include "find.hpp" #include "scantree.hpp" -#include "savepos.hpp" #include "getbits.hpp" #include "rdwrfn.hpp" #ifdef USE_QOPEN @@ -77,6 +76,9 @@ #include "rs.hpp" #include "rs16.hpp" + + + #include "recvol.hpp" #include "volume.hpp" #include "smallfn.hpp" diff --git a/third_party/unrar/src/rartypes.hpp b/third_party/unrar/src/rartypes.hpp index 1ec97c92323d88..3d3111bc3812ed 100644 --- a/third_party/unrar/src/rartypes.hpp +++ b/third_party/unrar/src/rartypes.hpp @@ -21,15 +21,12 @@ typedef wchar_t wchar; // Unicode character // Maximum int64 value. #define MAX_INT64 int64(INT32TO64(0x7fffffff,0xffffffff)) -// Special int64 value, large enough to never be found in real life. +// Special int64 value, large enough to never be found in real life +// and small enough to fit to both signed and unsigned 64-bit ints. // We use it in situations, when we need to indicate that parameter // is not defined and probably should be calculated inside of function. // Lower part is intentionally 0x7fffffff, not 0xffffffff, to make it -// compatible with 32 bit int64. +// compatible with 32 bit int64 if 64 bit type is not supported. #define INT64NDF INT32TO64(0x7fffffff,0x7fffffff) -// Maximum uint64 value. -#define MAX_UINT64 INT32TO64(0xffffffff,0xffffffff) -#define UINT64NDF MAX_UINT64 - #endif diff --git a/third_party/unrar/src/rdwrfn.hpp b/third_party/unrar/src/rdwrfn.hpp index 070010eaa55e45..fc38fd309214c0 100644 --- a/third_party/unrar/src/rdwrfn.hpp +++ b/third_party/unrar/src/rdwrfn.hpp @@ -3,6 +3,7 @@ class CmdAdd; class Unpack; +class ArcFileSearch; #if 0 // We use external i/o calls for Benchmark command. diff --git a/third_party/unrar/src/recvol.cpp b/third_party/unrar/src/recvol.cpp index 166eef4f73023f..adf5840443d8e0 100644 --- a/third_party/unrar/src/recvol.cpp +++ b/third_party/unrar/src/recvol.cpp @@ -31,12 +31,12 @@ bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent) // handling exceptions. So it can close and delete files on Cancel. if (Fmt==RARFMT15) { - RecVolumes3 RecVol(false); + RecVolumes3 RecVol(Cmd,false); return RecVol.Restore(Cmd,Name,Silent); } else { - RecVolumes5 RecVol(false); + RecVolumes5 RecVol(Cmd,false); return RecVol.Restore(Cmd,Name,Silent); } } @@ -100,12 +100,12 @@ void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name) RevFile.Close(); if (Rev5) { - RecVolumes5 RecVol(true); + RecVolumes5 RecVol(Cmd,true); RecVol.Test(Cmd,Name); } else { - RecVolumes3 RecVol(true); + RecVolumes3 RecVol(Cmd,true); RecVol.Test(Cmd,Name); } } diff --git a/third_party/unrar/src/recvol.hpp b/third_party/unrar/src/recvol.hpp index 7f2f1adb967e03..06510a211b1011 100644 --- a/third_party/unrar/src/recvol.hpp +++ b/third_party/unrar/src/recvol.hpp @@ -14,7 +14,7 @@ class RecVolumes3 ThreadPool *RSThreadPool; #endif public: - RecVolumes3(bool TestOnly); + RecVolumes3(RAROptions *Cmd,bool TestOnly); ~RecVolumes3(); void Make(RAROptions *Cmd,wchar *ArcName); bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent); @@ -71,11 +71,12 @@ class RecVolumes5 #ifdef RAR_SMP ThreadPool *RecThreadPool; #endif - RecRSThreadData ThreadData[MaxPoolThreads]; // Store thread parameters. + uint MaxUserThreads; // Maximum number of threads defined by user. + RecRSThreadData *ThreadData; // Array to store thread parameters. public: // 'public' only because called from thread functions. void ProcessAreaRS(RecRSThreadData *td); public: - RecVolumes5(bool TestOnly); + RecVolumes5(RAROptions *Cmd,bool TestOnly); ~RecVolumes5(); bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent); void Test(RAROptions *Cmd,const wchar *Name); diff --git a/third_party/unrar/src/recvol3.cpp b/third_party/unrar/src/recvol3.cpp index 51776d40498921..9fb846a28a16a0 100644 --- a/third_party/unrar/src/recvol3.cpp +++ b/third_party/unrar/src/recvol3.cpp @@ -36,7 +36,7 @@ THREAD_PROC(RSDecodeThread) } #endif -RecVolumes3::RecVolumes3(bool TestOnly) +RecVolumes3::RecVolumes3(RAROptions *Cmd,bool TestOnly) { memset(SrcFile,0,sizeof(SrcFile)); if (TestOnly) @@ -50,7 +50,7 @@ RecVolumes3::RecVolumes3(bool TestOnly) Buf.Alloc(TotalBufferSize); memset(SrcFile,0,sizeof(SrcFile)); #ifdef RAR_SMP - RSThreadPool=CreateThreadPool(); + RSThreadPool=new ThreadPool(Cmd->Threads); #endif } } @@ -61,7 +61,7 @@ RecVolumes3::~RecVolumes3() for (size_t I=0;IThreads; - RSEncode rse[MaxPoolThreads]; #else uint ThreadNumber=1; - RSEncode rse[1]; #endif + RSEncode *rse=new RSEncode[ThreadNumber]; for (uint I=0;IWrite(&Buf[I*RecBufferSize],MaxRead); } + delete[] rse; + for (int I=0;IThreads; +#else + MaxUserThreads=1; +#endif + + ThreadData=new RecRSThreadData[MaxUserThreads]; + for (uint I=0;IThreads; -#else - uint ThreadNumber=1; -#endif + uint ThreadNumber=MaxUserThreads; const uint MinThreadBlock=0x1000; ThreadNumber=Min(ThreadNumber,MaxRead/MinThreadBlock); @@ -238,7 +242,7 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent) uiMsg(UIMSG_STRING,Item->Name); uint RevCRC; - CalcFileSum(Item->f,&RevCRC,NULL,Cmd->Threads,INT64NDF,CALCFSUM_CURPOS); + CalcFileSum(Item->f,&RevCRC,NULL,MaxUserThreads,INT64NDF,CALCFSUM_CURPOS); Item->Valid=RevCRC==Item->CRC; if (!Item->Valid) { diff --git a/third_party/unrar/src/resource.cpp b/third_party/unrar/src/resource.cpp index 2eec79c76b4c83..dadd072360dc82 100644 --- a/third_party/unrar/src/resource.cpp +++ b/third_party/unrar/src/resource.cpp @@ -2,8 +2,10 @@ + + #ifndef RARDLL -const wchar *St(MSGID StringId) +const wchar* St(MSGID StringId) { return StringId; } diff --git a/third_party/unrar/src/rijndael.cpp b/third_party/unrar/src/rijndael.cpp index ba29c910e3d25e..dd19750a391965 100644 --- a/third_party/unrar/src/rijndael.cpp +++ b/third_party/unrar/src/rijndael.cpp @@ -75,8 +75,14 @@ void Rijndael::Init(bool Encrypt,const byte *key,uint keyLen,const byte * initVe // Check SSE here instead of constructor, so if object is a part of some // structure memset'ed before use, this variable is not lost. int CPUInfo[4]; - __cpuid(CPUInfo, 1); - AES_NI=(CPUInfo[2] & 0x2000000)!=0; + __cpuid(CPUInfo, 0x80000000); // Get the maximum supported cpuid function. + if ((CPUInfo[0] & 0x7fffffff)>=1) + { + __cpuid(CPUInfo, 1); + AES_NI=(CPUInfo[2] & 0x2000000)!=0; + } + else + AES_NI=0; #endif // Other developers asked us to initialize it to suppress "may be used diff --git a/third_party/unrar/src/savepos.hpp b/third_party/unrar/src/savepos.hpp index 10a0664697afa7..1f8353f65aa499 100644 --- a/third_party/unrar/src/savepos.hpp +++ b/third_party/unrar/src/savepos.hpp @@ -14,13 +14,26 @@ class SaveFilePos } ~SaveFilePos() { - // If file is already closed by current exception processing, - // we would get uneeded error messages and an exception inside of - // exception and terminate if we try to seek without checking - // if file is still opened. We should not also restore the position - // if external code closed the file on purpose. + // Unless the file is already closed either by current exception + // processing or intentionally by external code. if (SaveFile->IsOpened()) - SaveFile->Seek(SavePos,SEEK_SET); + { + try + { + SaveFile->Seek(SavePos,SEEK_SET); + } + catch(RAR_EXIT) + { + // Seek() can throw an exception and it terminates process + // if we are already processing another exception. Also in C++ 11 + // an exception in destructor always terminates process unless + // we mark destructor with noexcept(false). So we do not want to + // throw here. To prevent data loss we do not want to continue + // execution after seek error, so we close the file. + // Any next access to this file will return an error. + SaveFile->Close(); + } + } } }; diff --git a/third_party/unrar/src/strfn.cpp b/third_party/unrar/src/strfn.cpp index 6545f0ad092ead..8904b9072ef3eb 100644 --- a/third_party/unrar/src/strfn.cpp +++ b/third_party/unrar/src/strfn.cpp @@ -241,8 +241,8 @@ uint GetDigits(uint Number) bool LowAscii(const char *Str) { - for (int I=0;Str[I]!=0;I++) - if ((byte)Str[I]<32 || (byte)Str[I]>127) + for (size_t I=0;Str[I]!=0;I++) + if (/*(byte)Str[I]<32 || */(byte)Str[I]>127) return false; return true; } @@ -250,11 +250,11 @@ bool LowAscii(const char *Str) bool LowAscii(const wchar *Str) { - for (int I=0;Str[I]!=0;I++) + for (size_t I=0;Str[I]!=0;I++) { // We convert wchar_t to uint just in case if some compiler // uses signed wchar_t. - if ((uint)Str[I]<32 || (uint)Str[I]>127) + if (/*(uint)Str[I]<32 || */(uint)Str[I]>127) return false; } return true; diff --git a/third_party/unrar/src/system.cpp b/third_party/unrar/src/system.cpp index c13c81e16c06a4..4ae2b8905e93a0 100644 --- a/third_party/unrar/src/system.cpp +++ b/third_party/unrar/src/system.cpp @@ -187,18 +187,29 @@ SSE_VERSION _SSE_Version=GetSSEVersion(); SSE_VERSION GetSSEVersion() { int CPUInfo[4]; - __cpuid(CPUInfo, 7); - if ((CPUInfo[1] & 0x20)!=0) - return SSE_AVX2; - __cpuid(CPUInfo, 1); - if ((CPUInfo[2] & 0x80000)!=0) - return SSE_SSE41; - if ((CPUInfo[2] & 0x200)!=0) - return SSE_SSSE3; - if ((CPUInfo[3] & 0x4000000)!=0) - return SSE_SSE2; - if ((CPUInfo[3] & 0x2000000)!=0) - return SSE_SSE; + __cpuid(CPUInfo, 0x80000000); + + // Maximum supported cpuid function. For example, Pentium M 755 returns 4 here. + uint MaxSupported=CPUInfo[0] & 0x7fffffff; + + if (MaxSupported>=7) + { + __cpuid(CPUInfo, 7); + if ((CPUInfo[1] & 0x20)!=0) + return SSE_AVX2; + } + if (MaxSupported>=1) + { + __cpuid(CPUInfo, 1); + if ((CPUInfo[2] & 0x80000)!=0) + return SSE_SSE41; + if ((CPUInfo[2] & 0x200)!=0) + return SSE_SSSE3; + if ((CPUInfo[3] & 0x4000000)!=0) + return SSE_SSE2; + if ((CPUInfo[3] & 0x2000000)!=0) + return SSE_SSE; + } return SSE_NONE; } #endif diff --git a/third_party/unrar/src/threadmisc.cpp b/third_party/unrar/src/threadmisc.cpp index 9dfd2b9bc30155..742eda41d9b184 100644 --- a/third_party/unrar/src/threadmisc.cpp +++ b/third_party/unrar/src/threadmisc.cpp @@ -1,7 +1,3 @@ -// Typically we use the same global thread pool for all RAR modules. -static ThreadPool *GlobalPool=NULL; -static uint GlobalPoolUseCount=0; - static inline bool CriticalSectionCreate(CRITSECT_HANDLE *CritSection) { #ifdef _WIN_ALL @@ -43,62 +39,6 @@ static inline void CriticalSectionEnd(CRITSECT_HANDLE *CritSection) } -struct GlobalPoolCreateSync -{ - CRITSECT_HANDLE CritSection; - GlobalPoolCreateSync() { CriticalSectionCreate(&CritSection); } - ~GlobalPoolCreateSync() { CriticalSectionDelete(&CritSection); } -}; - -static GlobalPoolCreateSync& GetPoolCreateSync() { - static GlobalPoolCreateSync PoolCreateSync; - return PoolCreateSync; -} - - -ThreadPool* CreateThreadPool() -{ - CriticalSectionStart(&(GetPoolCreateSync().CritSection)); - - if (GlobalPoolUseCount++ == 0) - GlobalPool=new ThreadPool(MaxPoolThreads); - - // We use a simple thread pool, which does not allow to add tasks from - // different functions and threads in the same time. It is ok for RAR, - // but UnRAR.dll can be used in multithreaded environment. So if one of - // threads requests a copy of global pool and another copy is already - // in use, we create and return a new pool instead of existing global. - if (GlobalPoolUseCount > 1) - { - ThreadPool *Pool = new ThreadPool(MaxPoolThreads); - CriticalSectionEnd(&(GetPoolCreateSync().CritSection)); - return Pool; - } - - CriticalSectionEnd(&(GetPoolCreateSync().CritSection)); - return GlobalPool; -} - - -void DestroyThreadPool(ThreadPool *Pool) -{ - if (Pool!=NULL) - { - CriticalSectionStart(&(GetPoolCreateSync().CritSection)); - - if (Pool==GlobalPool && GlobalPoolUseCount > 0 && --GlobalPoolUseCount == 0) - delete GlobalPool; - - // To correctly work in multithreaded environment UnRAR.dll creates - // new pools if global pool is already in use. We delete such pools here. - if (Pool!=GlobalPool) - delete Pool; - - CriticalSectionEnd(&(GetPoolCreateSync().CritSection)); - } -} - - static THREAD_HANDLE ThreadCreate(NATIVE_THREAD_PTR Proc,void *Data) { #ifdef _UNIX diff --git a/third_party/unrar/src/threadpool.cpp b/third_party/unrar/src/threadpool.cpp index 732dd75375beba..8c63a8bd752c85 100644 --- a/third_party/unrar/src/threadpool.cpp +++ b/third_party/unrar/src/threadpool.cpp @@ -170,12 +170,13 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data) CreateThreads(); // If queue is full, wait until it is empty. - if ((QueueTop + 1) % ASIZE(TaskQueue) == QueueBottom) + if (ActiveThreads>=ASIZE(TaskQueue)) WaitDone(); TaskQueue[QueueTop].Proc = Proc; TaskQueue[QueueTop].Param = Data; QueueTop = (QueueTop + 1) % ASIZE(TaskQueue); + ActiveThreads++; } @@ -184,9 +185,6 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data) // are sleeping yet. void ThreadPool::WaitDone() { - // We add ASIZE(TaskQueue) for case if TaskQueue array size is not - // a power of two. Negative numbers would not suit our purpose here. - ActiveThreads=(QueueTop+ASIZE(TaskQueue)-QueueBottom) % ASIZE(TaskQueue); if (ActiveThreads==0) return; #ifdef _WIN_ALL diff --git a/third_party/unrar/src/threadpool.hpp b/third_party/unrar/src/threadpool.hpp index dc45ca0ab461d6..85ed90dc0e4491 100644 --- a/third_party/unrar/src/threadpool.hpp +++ b/third_party/unrar/src/threadpool.hpp @@ -4,7 +4,10 @@ #ifndef RAR_SMP const uint MaxPoolThreads=1; // For single threaded version. #else -const uint MaxPoolThreads=32; +// We need to use the processor groups API to increase it beyond 64. +// Also be sure to check and adjust if needed per thread and total block size +// when compressing if going above 64. +const uint MaxPoolThreads=64; #ifdef _UNIX @@ -98,9 +101,6 @@ class ThreadPool #endif }; -ThreadPool* CreateThreadPool(); -void DestroyThreadPool(ThreadPool *Pool); - #endif // RAR_SMP #endif // _RAR_THREADPOOL_ diff --git a/third_party/unrar/src/ui.hpp b/third_party/unrar/src/ui.hpp index 69ce2a583305f0..2654387c285b6b 100644 --- a/third_party/unrar/src/ui.hpp +++ b/third_party/unrar/src/ui.hpp @@ -20,7 +20,7 @@ enum UIMESSAGE_CODE { UIERROR_SUBHEADERDATABROKEN, UIERROR_RRDAMAGED, UIERROR_UNKNOWNMETHOD, UIERROR_UNKNOWNENCMETHOD, UIERROR_RENAMING, UIERROR_NEWERRAR, UIERROR_NOTSFX, UIERROR_OLDTOSFX, - UIERROR_WRONGSFXVER, UIERROR_ALREADYENC, UIERROR_DICTOUTMEM, + UIERROR_WRONGSFXVER, UIERROR_HEADENCMISMATCH, UIERROR_DICTOUTMEM, UIERROR_USESMALLERDICT, UIERROR_MODIFYUNKNOWN, UIERROR_MODIFYOLD, UIERROR_MODIFYLOCKED, UIERROR_MODIFYVOLUME, UIERROR_NOTVOLUME, UIERROR_NOTFIRSTVOLUME, UIERROR_RECVOLLIMIT, UIERROR_RECVOLDIFFSETS, @@ -38,6 +38,8 @@ enum UIMESSAGE_CODE { UIERROR_PATHTOOLONG, UIERROR_DIRSCAN, UIERROR_UOWNERGET, UIERROR_UOWNERBROKEN, UIERROR_UOWNERGETOWNERID, UIERROR_UOWNERGETGROUPID, UIERROR_UOWNERSET, UIERROR_ULINKREAD, UIERROR_ULINKEXIST, + UIERROR_OPENPRESERVEATIME, UIERROR_READERRTRUNCATED, UIERROR_READERRCOUNT, + UIERROR_DIRNAMEEXISTS, UIMSG_FIRST, UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_ANALYZEFILEDATA, @@ -91,16 +93,18 @@ bool uiIsGlobalPasswordSet(); enum UIALARM_TYPE {UIALARM_ERROR, UIALARM_INFO, UIALARM_QUESTION}; void uiAlarm(UIALARM_TYPE Type); +void uiEolAfterMsg(); bool uiAskNextVolume(wchar *VolName,size_t MaxSize); -bool uiAskRepeatRead(const wchar *FileName); +#if !defined(SILENT) && !defined(SFX_MODULE) +void uiAskRepeatRead(const wchar *FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit); +#endif bool uiAskRepeatWrite(const wchar *FileName,bool DiskFull); #ifndef SFX_MODULE const wchar *uiGetMonthName(int Month); #endif - class uiMsgStore { private: diff --git a/third_party/unrar/src/uiconsole.cpp b/third_party/unrar/src/uiconsole.cpp index 3f4c65429e93ff..f29ca477e10286 100644 --- a/third_party/unrar/src/uiconsole.cpp +++ b/third_party/unrar/src/uiconsole.cpp @@ -1,3 +1,5 @@ +static bool AnyMessageDisplayed=0; // For console -idn switch. + // Purely user interface function. Gets and returns user input. UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags) { @@ -83,6 +85,8 @@ void uiProcessProgress(const char *Command,int64 CurSize,int64 TotalSize) void uiMsgStore::Msg() { + AnyMessageDisplayed=true; + switch(Code) { case UIERROR_SYSERRMSG: @@ -99,6 +103,8 @@ void uiMsgStore::Msg() Log(Str[0],St(MDataBadCRC),Str[1],Str[0]); break; case UIERROR_BADPSW: + Log(Str[0],St(MWrongFilePassword),Str[1]); + break; case UIWAIT_BADPSW: Log(Str[0],St(MWrongPassword)); break; @@ -119,6 +125,7 @@ void uiMsgStore::Msg() Log(NULL,St(MErrSeek),Str[0]); break; case UIERROR_FILEREAD: + mprintf(L"\n"); Log(Str[0],St(MErrRead),Str[1]); break; case UIERROR_FILEWRITE: @@ -302,7 +309,15 @@ void uiMsgStore::Msg() case UIERROR_ULINKEXIST: Log(NULL,St(MSymLinkExists),Str[0]); break; - + case UIERROR_READERRTRUNCATED: + Log(NULL,St(MErrReadTrunc),Str[0]); + break; + case UIERROR_READERRCOUNT: + Log(NULL,St(MErrReadCount),Num[0]); + break; + case UIERROR_DIRNAMEEXISTS: + Log(NULL,St(MDirNameExists)); + break; #ifndef SFX_MODULE case UIMSG_STRING: @@ -395,11 +410,15 @@ bool uiAskNextVolume(wchar *VolName,size_t MaxSize) } -bool uiAskRepeatRead(const wchar *FileName) +void uiAskRepeatRead(const wchar *FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit) { - mprintf(L"\n"); - Log(NULL,St(MErrRead),FileName); - return Ask(St(MRetryAbort))==1; + eprintf(St(MErrReadInfo)); + int Code=Ask(St(MIgnoreAllRetryQuit)); + + Ignore=(Code==1); + All=(Code==2); + Quit=(Code==4); + Retry=!Ignore && !All && !Quit; // Default also for invalid input, not just for 'Retry'. } @@ -421,3 +440,15 @@ const wchar *uiGetMonthName(int Month) return St(MonthID[Month]); } #endif + + +void uiEolAfterMsg() +{ + if (AnyMessageDisplayed) + { + // Avoid deleting several last characters of any previous error message + // with percentage indicator in -idn mode. + AnyMessageDisplayed=false; + mprintf(L"\n"); + } +} diff --git a/third_party/unrar/src/uisilent.cpp b/third_party/unrar/src/uisilent.cpp index 1b5de13df525e5..1df0975665fde4 100644 --- a/third_party/unrar/src/uisilent.cpp +++ b/third_party/unrar/src/uisilent.cpp @@ -67,3 +67,8 @@ const wchar *uiGetMonthName(int Month) return L""; } #endif + + +void uiEolAfterMsg() +{ +} diff --git a/third_party/unrar/src/unicode.cpp b/third_party/unrar/src/unicode.cpp index b2015b8be649d6..48d7bb2fc44e79 100644 --- a/third_party/unrar/src/unicode.cpp +++ b/third_party/unrar/src/unicode.cpp @@ -1,7 +1,7 @@ #include "rar.hpp" #define MBFUNCTIONS -#if !defined(_WIN_ALL) && !defined(_APPLE) && defined(_UNIX) && defined(MBFUNCTIONS) +#if defined(_UNIX) && defined(MBFUNCTIONS) static bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success); static void CharToWideMap(const char *Src,wchar *Dest,size_t DestSize,bool &Success); @@ -30,7 +30,7 @@ bool WideToChar(const wchar *Src,char *Dest,size_t DestSize) #elif defined(_APPLE) WideToUtf(Src,Dest,DestSize); -#elif defined(_UNIX) && defined(MBFUNCTIONS) +#elif defined(MBFUNCTIONS) if (!WideToCharMap(Src,Dest,DestSize,RetCode)) { mbstate_t ps; // Use thread safe external state based functions. @@ -95,7 +95,7 @@ bool CharToWide(const char *Src,wchar *Dest,size_t DestSize) #elif defined(_APPLE) UtfToWide(Src,Dest,DestSize); -#elif defined(_UNIX) && defined(MBFUNCTIONS) +#elif defined(MBFUNCTIONS) mbstate_t ps; memset (&ps, 0, sizeof(ps)); const char *SrcParam=Src; // mbsrtowcs can change the pointer. @@ -128,8 +128,8 @@ bool CharToWide(const char *Src,wchar *Dest,size_t DestSize) } -#if !defined(_WIN_ALL) && !defined(_APPLE) && defined(_UNIX) && defined(MBFUNCTIONS) -// Convert and restore mapped inconvertible Unicode characters. +#if defined(_UNIX) && defined(MBFUNCTIONS) +// Convert and restore mapped inconvertible Unicode characters. // We use it for extended ASCII names in Unix. bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success) { @@ -142,7 +142,7 @@ bool WideToCharMap(const wchar *Src,char *Dest,size_t DestSize,bool &Success) // can produce uninitilized output while reporting success on garbage input. // So we clean the destination to calm analyzers. memset(Dest,0,DestSize); - + Success=true; uint SrcPos=0,DestPos=0; while (Src[SrcPos]!=0 && DestPos SubData; - if (!Arc.ReadSubData(&SubData,NULL)) + if (!Arc.ReadSubData(&SubData,NULL,false)) return; SetACLPrivileges(); diff --git a/third_party/unrar/src/win32stm.cpp b/third_party/unrar/src/win32stm.cpp index 54b872e1f1c81f..eaa43be2d97188 100644 --- a/third_party/unrar/src/win32stm.cpp +++ b/third_party/unrar/src/win32stm.cpp @@ -104,7 +104,8 @@ void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode) if (TestMode) { - Arc.ReadSubData(NULL,NULL); + File CurFile; + Arc.ReadSubData(NULL,&CurFile,true); return; } @@ -116,7 +117,7 @@ void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode) if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0) SetFileAttr(FileName,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY); File CurFile; - if (CurFile.WCreate(FullName) && Arc.ReadSubData(NULL,&CurFile)) + if (CurFile.WCreate(FullName) && Arc.ReadSubData(NULL,&CurFile,false)) CurFile.Close(); File HostFile; if (Found && HostFile.Open(FileName,FMF_OPENSHARED|FMF_UPDATE))