diff options
| author | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2008-08-21 20:39:02 +0200 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2008-08-21 20:39:02 +0200 |
| commit | c6db81b5e20f62e8a5d24373d73b19d519b2fa44 (patch) | |
| tree | 1e6cb2346b47ed9302de372aebdb10f0d5b32023 /unrar | |
| parent | 3d051722dea893c1b813db8bbeae1430b9eddd52 (diff) | |
| download | tuxcmd-modules-c6db81b5e20f62e8a5d24373d73b19d519b2fa44.tar.xz | |
Update unrar sources to v3.8.2
Unfortunately, I had to make some small compatibility fixes in unrar code. Changes are commented with my name.
Diffstat (limited to 'unrar')
49 files changed, 589 insertions, 236 deletions
diff --git a/unrar/unrar.c b/unrar/unrar.c index 6435aeb..8a725f6 100644 --- a/unrar/unrar.c +++ b/unrar/unrar.c @@ -1,5 +1,5 @@ /* UNRAR plugin for Tux Commander - * version 0.2.2, designed for unrar v3.7.1 beta1 + * version 0.2.3, designed for unrar v3.8.2 * Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net> * Check for updates on tuxcmd.sourceforge.net * @@ -55,8 +55,8 @@ enum HOST_SYSTEM { }; -#define VERSION "0.2.2" -#define BUILD_DATE "2008-05-11" +#define VERSION "0.2.3" +#define BUILD_DATE "2008-08-21" #define DEFAULT_BLOCK_SIZE 65536 @@ -139,7 +139,7 @@ struct TVFSInfo VFSGetInfo() module_info.About = strdup(s); free(s); s = (char*)malloc(255); - snprintf(s, 255, "Plugin Copyright (C) 2008 Tomáš Bžatek\nUNRAR sources Copyright (C) 2002-2007 Alexander Roshal"); + snprintf(s, 255, "Plugin Copyright (C) 2008 Tomáš Bžatek\nUNRAR sources Copyright (C) 2002-2008 Alexander Roshal"); module_info.Copyright = strdup(s); return module_info; } diff --git a/unrar/unrar/archive.hpp b/unrar/unrar/archive.hpp index 1e0675e..a278aff 100644 --- a/unrar/unrar/archive.hpp +++ b/unrar/unrar/archive.hpp @@ -14,7 +14,6 @@ class Archive:public File void ConvertNameCase(wchar *Name); void ConvertUnknownHeader(); int ReadOldHeader(); - void PrepareExtraTime(FileHeader *hd,EXTTIME_MODE etm,EXTTIME_MODE etc,EXTTIME_MODE eta,EXTTIME_MODE etarc,Array<byte> &TimeData); #if !defined(SHELL_EXT) && !defined(NOCRYPT) CryptData HeadersCrypt; diff --git a/unrar/unrar/arcread.cpp b/unrar/unrar/arcread.cpp index 43a23db..8dd03fa 100644 --- a/unrar/unrar/arcread.cpp +++ b/unrar/unrar/arcread.cpp @@ -52,7 +52,7 @@ int Archive::ReadHeader() if (*Cmd->Password==0) #ifdef RARDLL if (Cmd->Callback==NULL || - Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1) + Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,sizeof(Cmd->Password))==-1) { Close(); ErrHandler.Exit(USER_BREAK); @@ -370,6 +370,8 @@ int Archive::ReadHeader() bool Recovered=false; if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0) { + // Last 7 bytes of recovered volume can contain zeroes, because + // REV files store its own information (volume number, etc.) here. SaveFilePos SavePos(*this); Int64 Length=Tell(); Seek(Length-7,SEEK_SET); @@ -582,10 +584,32 @@ void Archive::ConvertUnknownHeader() if ((byte)*s<32 || (byte)*s>127) *s='_'; #endif + +#if defined(_WIN_32) || defined(_EMX) + // ':' in file names is allowed in Unix, but not in Windows. + // Even worse, file data will be written to NTFS stream on NTFS, + // so automatic name correction on file create error in extraction + // routine does not work. Let's better replace ':' now. + if (NewLhd.HostOS==HOST_UNIX && *s==':') + *s='_'; +#endif + } + for (wchar *s=NewLhd.FileNameW;*s!=0;s++) + { if (*s=='/' || *s=='\\') *s=CPATHDIVIDER; + +#if defined(_WIN_32) || defined(_EMX) + // ':' in file names is allowed in Unix, but not in Windows. + // Even worse, file data will be written to NTFS stream on NTFS, + // so automatic name correction on file create error in extraction + // routine does not work. Let's better replace ':' now. + if (NewLhd.HostOS==HOST_UNIX && *s==':') + *s='_'; +#endif + } } diff --git a/unrar/unrar/cmddata.cpp b/unrar/unrar/cmddata.cpp index 41f3dd7..1f17cce 100644 --- a/unrar/unrar/cmddata.cpp +++ b/unrar/unrar/cmddata.cpp @@ -51,7 +51,7 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW) if (Arg[1]=='-') NoMoreSwitches=true; else - ProcessSwitch(&Arg[1]); + ProcessSwitch(&Arg[1],(ArgW!=NULL && *ArgW!=0 ? &ArgW[1]:NULL)); else if (*Command==0) { @@ -81,8 +81,8 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW) } else { - int Length=strlen(Arg); - char EndChar=Arg[Length-1]; + size_t Length=strlen(Arg); + char EndChar=Length==0 ? 0:Arg[Length-1]; char CmdChar=etoupper(*Command); bool Add=strchr("AFUM",CmdChar)!=NULL; bool Extract=CmdChar=='X' || CmdChar=='E'; @@ -113,7 +113,7 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW) Charset=RCH_OEM; #endif - ReadTextFile(Arg+1,FileArgs,false,true,Charset,true,true); + ReadTextFile(Arg+1,FileArgs,false,true,Charset,true,true,true); } else if (Found && FileData.IsDir && Extract && *ExtrPath==0) @@ -226,7 +226,7 @@ void CommandData::ProcessSwitchesString(char *Str) #if !defined(SFX_MODULE) -void CommandData::ProcessSwitch(char *Switch) +void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW) { switch(etoupper(Switch[0])) @@ -375,6 +375,8 @@ void CommandData::ProcessSwitch(char *Switch) break; case 'P': strcpy(ArcPath,Switch+2); + if (SwitchW!=NULL && *SwitchW!=0) + strcpyw(ArcPathW,SwitchW+2); break; case 'S': SyncFiles=true; @@ -408,6 +410,9 @@ void CommandData::ProcessSwitch(char *Switch) case '-': Overwrite=OVERWRITE_NONE; break; + case 0: + Overwrite=OVERWRITE_FORCE_ASK; + break; case 'R': Overwrite=OVERWRITE_AUTORENAME; break; @@ -480,7 +485,7 @@ void CommandData::ProcessSwitch(char *Switch) Charset=RCH_OEM; #endif - ReadTextFile(Switch+2,Args,false,true,Charset,true,true); + ReadTextFile(Switch+2,Args,false,true,Charset,true,true,true); } else Args->AddString(Switch+1); @@ -794,7 +799,7 @@ void CommandData::ProcessSwitch(char *Switch) break; case 'C': { - RAR_CHARSET rch; + RAR_CHARSET rch=RCH_DEFAULT; switch(etoupper(Switch[2])) { case 'A': @@ -908,6 +913,18 @@ void CommandData::OutTitle() #endif +inline bool CmpMSGID(MSGID i1,MSGID i2) +{ +#ifdef MSGID_INT + return(i1==i2); +#else + // If MSGID is const char*, we cannot compare pointers only. + // Pointers to different instances of same strings can differ, + // so we need to compare complete strings. + return(strcmp(i1,i2)==0); +#endif +} + void CommandData::OutHelp() { #if !defined(GUI) && !defined(SILENT) @@ -916,12 +933,13 @@ void CommandData::OutHelp() #ifdef SFX_MODULE MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV #elif defined(UNRAR) - MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,MCHelpCmdP, - MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,MCHelpSwAC,MCHelpSwAD, - MCHelpSwAP,MCHelpSwAVm,MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU, + MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL, + MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw, + MCHelpSwm,MCHelpSwAC,MCHelpSwAD,MCHelpSwAP, + MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU, MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR, MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal, - MCHelpSwOp,MCHelpSwOm,MCHelpSwOC,MCHelpSwOR,MCHelpSwOW,MCHelpSwP, + MCHelpSwO,MCHelpSwOC,MCHelpSwOR,MCHelpSwOW,MCHelpSwP, MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSL,MCHelpSwSM,MCHelpSwTA, MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwVUnr, MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal,MCHelpSwY @@ -932,13 +950,13 @@ void CommandData::OutHelp() MCHelpCmdRN,MCHelpCmdRR,MCHelpCmdRV,MCHelpCmdS,MCHelpCmdT,MCHelpCmdU, MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG, MCHelpSwAO,MCHelpSwAP,MCHelpSwAS,MCHelpSwAV,MCHelpSwAVm,MCHelpSwCm, - MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,MCHelpSwDF,MCHelpSwDH,MCHelpSwDS, - MCHelpSwEa,MCHelpSwED,MCHelpSwEE,MCHelpSwEN,MCHelpSwEP,MCHelpSwEP1, - MCHelpSwEP2,MCHelpSwEP3,MCHelpSwF,MCHelpSwHP,MCHelpSwIDP, - MCHelpSwIEML,MCHelpSwIERR,MCHelpSwILOG,MCHelpSwINUL,MCHelpSwIOFF, - MCHelpSwISND,MCHelpSwK,MCHelpSwKB,MCHelpSwMn,MCHelpSwMC,MCHelpSwMD, - MCHelpSwMS,MCHelpSwMT,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,MCHelpSwOp, - MCHelpSwOm,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOS,MCHelpSwOW, + MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,MCHelpSwDF,MCHelpSwDH,MCHelpSwDR, + MCHelpSwDS,MCHelpSwDW,MCHelpSwEa,MCHelpSwED,MCHelpSwEE,MCHelpSwEN, + MCHelpSwEP,MCHelpSwEP1,MCHelpSwEP2,MCHelpSwEP3,MCHelpSwF,MCHelpSwHP, + MCHelpSwIDP,MCHelpSwIEML,MCHelpSwIERR,MCHelpSwILOG,MCHelpSwINUL, + MCHelpSwIOFF,MCHelpSwISND,MCHelpSwK,MCHelpSwKB,MCHelpSwMn,MCHelpSwMC, + MCHelpSwMD,MCHelpSwMS,MCHelpSwMT,MCHelpSwN,MCHelpSwNa,MCHelpSwNal, + MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOS,MCHelpSwOW, MCHelpSwP,MCHelpSwPm,MCHelpSwR,MCHelpSwR0,MCHelpSwRI,MCHelpSwRR, MCHelpSwRV,MCHelpSwS,MCHelpSwSm,MCHelpSwSC,MCHelpSwSFX,MCHelpSwSI, MCHelpSwSL,MCHelpSwSM,MCHelpSwT,MCHelpSwTA,MCHelpSwTB,MCHelpSwTK, @@ -958,11 +976,11 @@ void CommandData::OutHelp() #ifndef _WIN_32 static MSGID Win32Only[]={ MCHelpSwIEML,MCHelpSwVD,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF, - MCHelpSwEP2,MCHelpSwOC + MCHelpSwEP2,MCHelpSwOC,MCHelpSwDR,MCHelpSwRI }; bool Found=false; for (int J=0;J<sizeof(Win32Only)/sizeof(Win32Only[0]);J++) - if (Help[I]==Win32Only[J]) + if (CmpMSGID(Help[I],Win32Only[J])) { Found=true; break; @@ -971,27 +989,23 @@ void CommandData::OutHelp() continue; #endif #if !defined(_UNIX) && !defined(_WIN_32) - if (Help[I]==MCHelpSwOW) + if (CmpMSGID(Help[I],MCHelpSwOW)) continue; #endif #if !defined(_WIN_32) && !defined(_EMX) - if (Help[I]==MCHelpSwAC) + if (CmpMSGID(Help[I],MCHelpSwAC)) continue; #endif #ifndef SAVE_LINKS - if (Help[I]==MCHelpSwOL) - continue; -#endif -#ifndef _WIN_32 - if (Help[I]==MCHelpSwRI) + if (CmpMSGID(Help[I],MCHelpSwOL)) continue; #endif #ifndef PACK_SMP - if (Help[I]==MCHelpSwMT) + if (CmpMSGID(Help[I],MCHelpSwMT)) continue; #endif #ifndef _BEOS - if (Help[I]==MCHelpSwEE) + if (CmpMSGID(Help[I],MCHelpSwEE)) { #if defined(_EMX) && !defined(_DJGPP) if (_osmode != OS2_MODE) diff --git a/unrar/unrar/cmddata.hpp b/unrar/unrar/cmddata.hpp index 5dfe2dc..64a336d 100644 --- a/unrar/unrar/cmddata.hpp +++ b/unrar/unrar/cmddata.hpp @@ -7,7 +7,7 @@ class CommandData:public RAROptions { private: void ProcessSwitchesString(char *Str); - void ProcessSwitch(char *Switch); + void ProcessSwitch(char *Switch,wchar *SwitchW=NULL); void BadSwitch(char *Switch); bool ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath,int MatchMode); uint GetExclAttr(char *Str); diff --git a/unrar/unrar/consio.cpp b/unrar/unrar/consio.cpp index f1f4ba0..6644dce 100644 --- a/unrar/unrar/consio.cpp +++ b/unrar/unrar/consio.cpp @@ -4,8 +4,11 @@ #include "log.cpp" #endif +static int KbdAnsi(char *Addr,int Size); + #if !defined(GUI) && !defined(SILENT) static void RawPrint(char *Msg,MESSAGE_TYPE MessageType); +static uint GetKey(); #endif static MESSAGE_TYPE MsgStream=MSG_STDOUT; @@ -133,27 +136,6 @@ void GetPasswordText(char *Str,int MaxLength) #endif -#if !defined(GUI) && !defined(SILENT) -unsigned int GetKey() -{ -#ifdef SILENT - return(0); -#else - char Str[80]; -#ifdef __GNUC__ - fgets(Str,sizeof(Str),stdin); - return(Str[0]); -#else - File SrcFile; - SrcFile.SetHandleType(FILE_HANDLESTD); - SrcFile.Read(Str,sizeof(Str)); - return(Str[0]); -#endif -#endif -} -#endif - - #ifndef SILENT bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength) { @@ -199,6 +181,29 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL #if !defined(GUI) && !defined(SILENT) +uint GetKey() +{ + char Str[80]; + bool EndOfFile; +#if defined(__GNUC__) || defined(sun) + EndOfFile=(fgets(Str,sizeof(Str),stdin)==NULL); +#else + File SrcFile; + SrcFile.SetHandleType(FILE_HANDLESTD); + EndOfFile=(SrcFile.Read(Str,sizeof(Str))==0); +#endif + if (EndOfFile) + { + // Looks like stdin is a null device. We can enter to infinite loop + // calling Ask(), so let's better exit. + ErrHandler.Exit(USER_BREAK); + } + return(Str[0]); +} +#endif + + +#if !defined(GUI) && !defined(SILENT) int Ask(const char *AskStr) { const int MaxItems=10; diff --git a/unrar/unrar/consio.hpp b/unrar/unrar/consio.hpp index 003a011..b077cea 100644 --- a/unrar/unrar/consio.hpp +++ b/unrar/unrar/consio.hpp @@ -12,12 +12,10 @@ void mprintf(const char *fmt,...); void eprintf(const char *fmt,...); void Alarm(); void GetPasswordText(char *Str,int MaxLength); -unsigned int GetKey(); bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxLength); int Ask(const char *AskStr); #endif -int KbdAnsi(char *Addr,int Size); void OutComment(char *Comment,int Size); #ifdef SILENT diff --git a/unrar/unrar/crc.cpp b/unrar/unrar/crc.cpp index 1d91e45..9758241 100644 --- a/unrar/unrar/crc.cpp +++ b/unrar/unrar/crc.cpp @@ -14,12 +14,18 @@ void InitCRC() } -uint CRC(uint StartCRC,const void *Addr,uint Size) +uint CRC(uint StartCRC,const void *Addr,size_t Size) { if (CRCTab[1]==0) InitCRC(); byte *Data=(byte *)Addr; #if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT) + +#ifdef _MSC_VER + // avoid a warning about 'Data' pointer truncation in 64 bit mode + #pragma warning( disable : 4311 ) +#endif + while (Size>0 && ((long)Data & 7)) { StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8); @@ -42,16 +48,16 @@ uint CRC(uint StartCRC,const void *Addr,uint Size) Size-=8; } #endif - for (int I=0;I<Size;I++) + for (size_t I=0;I<Size;I++) StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8); return(StartCRC); } #ifndef SFX_MODULE -ushort OldCRC(ushort StartCRC,const void *Addr,uint Size) +ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size) { byte *Data=(byte *)Addr; - for (int I=0;I<Size;I++) + for (size_t I=0;I<Size;I++) { StartCRC=(StartCRC+Data[I])&0xffff; StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff; diff --git a/unrar/unrar/crc.hpp b/unrar/unrar/crc.hpp index 47ee7e2..a632a54 100644 --- a/unrar/unrar/crc.hpp +++ b/unrar/unrar/crc.hpp @@ -4,7 +4,7 @@ extern uint CRCTab[256]; void InitCRC(); -uint CRC(uint StartCRC,const void *Addr,uint Size); -ushort OldCRC(ushort StartCRC,const void *Addr,uint Size); +uint CRC(uint StartCRC,const void *Addr,size_t Size); +ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size); #endif diff --git a/unrar/unrar/dll.cpp b/unrar/unrar/dll.cpp index f1a2cc9..18e62bd 100644 --- a/unrar/unrar/dll.cpp +++ b/unrar/unrar/dll.cpp @@ -221,9 +221,10 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa try { Data->Cmd.DllError=0; - if (Data->OpenMode==RAR_OM_LIST || Operation==RAR_SKIP && !Data->Arc.Solid) + if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT || + Operation==RAR_SKIP && !Data->Arc.Solid) { - if (/*Data->OpenMode==RAR_OM_LIST && */Data->Arc.Volume && + if (Data->Arc.Volume && Data->Arc.GetHeaderType()==FILE_HEAD && (Data->Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0) if (MergeArchive(Data->Arc,NULL,false,'L')) @@ -265,6 +266,9 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa strncpyw(Data->Cmd.ExtrPathW,NullToEmpty(DestPathW),NM-2); AddEndSlash(Data->Cmd.ExtrPathW); strncpyw(Data->Cmd.DllDestNameW,NullToEmpty(DestNameW),NM-1); + + if (*Data->Cmd.DllDestNameW!=0 && *Data->Cmd.DllDestName==0) + WideToChar(Data->Cmd.DllDestNameW,Data->Cmd.DllDestName); } else { @@ -312,7 +316,7 @@ void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc) } -void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData) +void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData) { DataSet *Data=(DataSet *)hArcData; Data->Cmd.Callback=Callback; diff --git a/unrar/unrar/dll.hpp b/unrar/unrar/dll.hpp index 4b67744..c7cf622 100644 --- a/unrar/unrar/dll.hpp +++ b/unrar/unrar/dll.hpp @@ -1,6 +1,9 @@ #ifndef _UNRAR_DLL_ #define _UNRAR_DLL_ +/* Added by Tomas Bzatek - GCC 4.3 compatibility */ +#define LPARAM LONG + #define ERAR_END_ARCHIVE 10 #define ERAR_NO_MEMORY 11 #define ERAR_BAD_DATA 12 @@ -15,8 +18,9 @@ #define ERAR_UNKNOWN 21 #define ERAR_MISSING_PASSWORD 22 -#define RAR_OM_LIST 0 -#define RAR_OM_EXTRACT 1 +#define RAR_OM_LIST 0 +#define RAR_OM_EXTRACT 1 +#define RAR_OM_LIST_INCSPLIT 2 #define RAR_SKIP 0 #define RAR_TEST 1 @@ -109,7 +113,7 @@ enum UNRARCALLBACK_MESSAGES { UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD }; -typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LONG UserData,LONG P1,LONG P2); +typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2); typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode); typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size); @@ -125,7 +129,7 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData); int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData); int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName); int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName); -void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData); +void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData); void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc); void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc); void PASCAL RARSetPassword(HANDLE hArcData,char *Password); diff --git a/unrar/unrar/errhnd.cpp b/unrar/unrar/errhnd.cpp index 035eae9..2797f63 100644 --- a/unrar/unrar/errhnd.cpp +++ b/unrar/unrar/errhnd.cpp @@ -290,7 +290,8 @@ void _stdfunction ProcessSignal(int SigType) ExtRes.UnloadDLL(); #endif exit(USER_BREAK); -#ifdef _WIN_32 +#if defined(_WIN_32) && !defined(_MSC_VER) + // never reached, just to avoid a compiler warning return(TRUE); #endif } diff --git a/unrar/unrar/errhnd.hpp b/unrar/unrar/errhnd.hpp index 732243c..950a62c 100644 --- a/unrar/unrar/errhnd.hpp +++ b/unrar/unrar/errhnd.hpp @@ -12,6 +12,7 @@ #define rarrealloc realloc #define rarfree free #define rarstrdup strdup +#define rarstrdupw strdupw diff --git a/unrar/unrar/extract.cpp b/unrar/unrar/extract.cpp index e9d7517..712dc90 100644 --- a/unrar/unrar/extract.cpp +++ b/unrar/unrar/extract.cpp @@ -25,6 +25,7 @@ void CmdExtract::DoExtract(CommandData *Cmd) while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName))) if (FindFile::FastFind(ArcName,ArcNameW,&FD)) DataIO.TotalArcSize+=FD.Size; + Cmd->ArcNames->Rewind(); while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName))) { @@ -35,10 +36,8 @@ void CmdExtract::DoExtract(CommandData *Cmd) EXTRACT_ARC_CODE Code=ExtractArchive(Cmd); -/* - restore Cmd->Password which could be changed in IsArchive() call - for next header encrypted archive -*/ + // restore Cmd->Password which could be changed in IsArchive() call + // for next header encrypted archive strcpy(Cmd->Password,PrevCmdPassword); if (Code!=EXTRACT_ARC_REPEAT) @@ -90,6 +89,8 @@ void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc) SignatureFound=false; AllMatchesExact=true; ReconstructDone=false; + + StartTime.SetCurrentTime(); } @@ -112,6 +113,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd) return(EXTRACT_ARC_NEXT); } + // archive with corrupt encrypted header can be closed in IsArchive() call if (!Arc.IsOpened()) return(EXTRACT_ARC_NEXT); @@ -119,13 +121,42 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd) if (Arc.Volume && Arc.NotFirstVolume) { char FirstVolName[NM]; - VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)); + + // If several volume names from same volume set are specified + // and current volume is not first in set and first volume is present + // and specified too, let's skip the current volume. if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) && Cmd->ArcNames->Search(FirstVolName,NULL,false)) return(EXTRACT_ARC_NEXT); } #endif + + if (Arc.Volume) + { + // Calculate the total size of all accessible volumes. + // This size is necessary to display the correct total progress indicator. + + char NextName[NM]; + wchar NextNameW[NM]; + + strcpy(NextName,Arc.FileName); + strcpyw(NextNameW,Arc.FileNameW); + + while (true) + { + // First volume is already added to DataIO.TotalArcSize + // in initial TotalArcSize calculation in DoExtract. + // So we skip it and start from second volume. + NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat); + struct FindData FD; + if (FindFile::FastFind(NextName,NextNameW,&FD)) + DataIO.TotalArcSize+=FD.Size; + else + break; + } + } + ExtractArchiveInit(Cmd,Arc); if (*Cmd->Command=='T' || *Cmd->Command=='I') @@ -174,7 +205,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize #ifdef NOVOLUME return(false); #else - if (!MergeArchive(Arc,NULL,false,Command)) + if (!MergeArchive(Arc,&DataIO,false,Command)) { ErrHandler.SetErrorCode(WARNING); return(false); @@ -206,7 +237,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize if (Arc.EndArcHead.Flags & EARC_NEXT_VOLUME) { #ifndef NOVOLUME - if (!MergeArchive(Arc,NULL,false,Command)) + if (!MergeArchive(Arc,&DataIO,false,Command)) { ErrHandler.SetErrorCode(WARNING); return(false); @@ -352,7 +383,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize #ifdef RARDLL Cmd->DllError=ERAR_BAD_DATA; #endif - ErrHandler.SetErrorCode(WARNING); + ErrHandler.SetErrorCode(OPEN_ERROR); } ExactMatch=false; } @@ -370,7 +401,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize #ifdef RARDLL if (*Cmd->Password==0) if (Cmd->Callback==NULL || - Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1) + Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)Cmd->Password,sizeof(Cmd->Password))==-1) return(false); strcpy(Password,Cmd->Password); @@ -488,7 +519,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize if (Length>0) { wchar ArcPathW[NM]; - CharToWide(Cmd->ArcPath,ArcPathW); + GetWideName(Cmd->ArcPath,Cmd->ArcPathW,ArcPathW); Length=strlenw(ArcPathW); } ExtrNameW+=Length; @@ -518,7 +549,16 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize if (FindFile::FastFind(DestFileName,DestNameW,&FD)) { if (FD.mtime >= Arc.NewLhd.mtime) - ExtrFile=false; + { + // If directory already exists and its modification time is newer + // than start of extraction, it is likely it was created + // when creating a path to one of already extracted items. + // In such case we'll better update its time even if archived + // directory is older. + + if (!FD.IsDir || FD.mtime<StartTime) + ExtrFile=false; + } } else if (Cmd->FreshFiles) @@ -637,9 +677,9 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize #if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) if (Cmd->SetCompressedAttr && (Arc.NewLhd.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()) - SetFileCompression(DestFileName,DestFileNameW,true); + SetFileCompression(DestFileName,DestNameW,true); #endif - SetDirTime(DestFileName, + SetDirTime(DestFileName,DestNameW, Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime, Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime, Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime); diff --git a/unrar/unrar/extract.hpp b/unrar/unrar/extract.hpp index 09dfc94..dcf4534 100644 --- a/unrar/unrar/extract.hpp +++ b/unrar/unrar/extract.hpp @@ -7,6 +7,7 @@ class CmdExtract { private: EXTRACT_ARC_CODE ExtractArchive(CommandData *Cmd); + RarTime StartTime; // time when extraction started ComprDataIO DataIO; Unpack *Unp; diff --git a/unrar/unrar/filcreat.cpp b/unrar/unrar/filcreat.cpp index 175736a..c377dd6 100644 --- a/unrar/unrar/filcreat.cpp +++ b/unrar/unrar/filcreat.cpp @@ -30,7 +30,7 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW, #endif if (Cmd->AllYes || Mode==OVERWRITE_ALL) break; - if (Mode==OVERWRITE_ASK) + if (Mode==OVERWRITE_DEFAULT || Mode==OVERWRITE_FORCE_ASK) { eprintf(St(MFileExists),Name); int Choice=Ask(St(MYesNoAllRenQ)); @@ -88,7 +88,7 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,char *Name,wchar *NameW, *NameW=0; } else - Mode=OVERWRITE_ASK; + Mode=OVERWRITE_DEFAULT; continue; } } diff --git a/unrar/unrar/file.cpp b/unrar/unrar/file.cpp index a2c43b8..8fe71ec 100644 --- a/unrar/unrar/file.cpp +++ b/unrar/unrar/file.cpp @@ -135,14 +135,15 @@ bool File::WOpen(const char *Name,const wchar *NameW) } -bool File::Create(const char *Name,const wchar *NameW) +bool File::Create(const char *Name,const wchar *NameW,bool ShareRead) { #ifdef _WIN_32 + DWORD ShareMode=(ShareRead || File::OpenShared) ? FILE_SHARE_READ:0; if (WinNT() && NameW!=NULL && *NameW!=0) - hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL, + hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL, CREATE_ALWAYS,0,NULL); else - hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL, + hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,ShareMode,NULL, CREATE_ALWAYS,0,NULL); #else hFile=fopen(Name,CREATEBINARY); @@ -176,17 +177,17 @@ void File::AddFileToList(FileHandle hFile) #if !defined(SHELL_EXT) && !defined(SFX_MODULE) -void File::TCreate(const char *Name,const wchar *NameW) +void File::TCreate(const char *Name,const wchar *NameW,bool ShareRead) { - if (!WCreate(Name,NameW)) + if (!WCreate(Name,NameW,ShareRead)) ErrHandler.Exit(FATAL_ERROR); } #endif -bool File::WCreate(const char *Name,const wchar *NameW) +bool File::WCreate(const char *Name,const wchar *NameW,bool ShareRead) { - if (Create(Name,NameW)) + if (Create(Name,NameW,ShareRead)) return(true); ErrHandler.SetErrorCode(CREATE_ERROR); ErrHandler.CreateErrorMsg(Name); @@ -248,15 +249,21 @@ bool File::Delete() } -bool File::Rename(const char *NewName) +bool File::Rename(const char *NewName,const wchar *NewNameW) { + // we do not need to rename if names are already same bool Success=strcmp(FileName,NewName)==0; + if (Success && *FileNameW!=0 && *NullToEmpty(NewNameW)!=0) + Success=strcmpw(FileNameW,NewNameW)==0; + if (!Success) - Success=rename(FileName,NewName)==0; + Success=RenameFile(FileName,FileNameW,NewName,NewNameW); + if (Success) { + // renamed successfully, storing the new name strcpy(FileName,NewName); - *FileNameW=0; + strcpyw(FileNameW,NullToEmpty(NewNameW)); } return(Success); } @@ -288,11 +295,12 @@ void File::Write(const void *Data,int Size) #endif while (1) { - bool Success; + bool Success=false; #ifdef _WIN_32 - DWORD Written; + DWORD Written=0; if (HandleType!=FILE_HANDLENORMAL) { + // writing to stdout can fail in old Windows if data block is too large const int MaxSize=0x4000; for (int I=0;I<Size;I+=MaxSize) if (!(Success=WriteFile(hFile,(byte *)Data+I,Min(Size-I,MaxSize),&Written,NULL))) @@ -333,7 +341,8 @@ void File::Write(const void *Data,int Size) int File::Read(void *Data,int Size) { - Int64 FilePos; + Int64 FilePos=0; //initialized only to suppress some compilers warning + if (IgnoreReadErrors) FilePos=Tell(); int ReadSize; diff --git a/unrar/unrar/file.hpp b/unrar/unrar/file.hpp index afa9529..e5f768c 100644 --- a/unrar/unrar/file.hpp +++ b/unrar/unrar/file.hpp @@ -56,13 +56,13 @@ class File bool Open(const char *Name,const wchar *NameW=NULL,bool OpenShared=false,bool Update=false); void TOpen(const char *Name,const wchar *NameW=NULL); bool WOpen(const char *Name,const wchar *NameW=NULL); - bool Create(const char *Name,const wchar *NameW=NULL); - void TCreate(const char *Name,const wchar *NameW=NULL); - bool WCreate(const char *Name,const wchar *NameW=NULL); + bool Create(const char *Name,const wchar *NameW=NULL,bool ShareRead=true); + void TCreate(const char *Name,const wchar *NameW=NULL,bool ShareRead=true); + bool WCreate(const char *Name,const wchar *NameW=NULL,bool ShareRead=true); bool Close(); void Flush(); bool Delete(); - bool Rename(const char *NewName); + bool Rename(const char *NewName,const wchar *NewNameW=NULL); void Write(const void *Data,int Size); int Read(void *Data,int Size); int DirectRead(void *Data,int Size); diff --git a/unrar/unrar/filefn.cpp b/unrar/unrar/filefn.cpp index 1c43eae..54b0b99 100644 --- a/unrar/unrar/filefn.cpp +++ b/unrar/unrar/filefn.cpp @@ -109,7 +109,7 @@ bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName) } -void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta) +void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta) { #ifdef _WIN_32 if (!WinNT()) @@ -119,11 +119,14 @@ void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta) bool sc=ftc!=NULL && ftc->IsSet(); bool sa=fta!=NULL && fta->IsSet(); - unsigned int DirAttr=GetFileAttr(Name); + unsigned int DirAttr=GetFileAttr(Name,NameW); bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FA_RDONLY)!=0); if (ResetAttr) - SetFileAttr(Name,NULL,0); - HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, + SetFileAttr(Name,NameW,0); + + wchar DirNameW[NM]; + GetWideName(Name,NameW,DirNameW); + HANDLE hFile=CreateFileW(DirNameW,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL); if (hFile==INVALID_HANDLE_VALUE) return; @@ -137,7 +140,7 @@ void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta) SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL); CloseHandle(hFile); if (ResetAttr) - SetFileAttr(Name,NULL,DirAttr); + SetFileAttr(Name,NameW,DirAttr); #endif #if defined(_UNIX) || defined(_EMX) File::SetCloseFileTimeByName(Name,ftm,fta); @@ -455,7 +458,7 @@ void ConvertNameToFull(const wchar *Src,wchar *Dest) #ifndef SFX_MODULE char *MkTemp(char *Name) { - int Length=strlen(Name); + size_t Length=strlen(Name); if (Length<=6) return(NULL); int Random=clock(); @@ -568,3 +571,9 @@ bool SetFileCompression(char *Name,wchar *NameW,bool State) return(RetCode!=0); } #endif + + + + + + diff --git a/unrar/unrar/filefn.hpp b/unrar/unrar/filefn.hpp index ec6cba5..cd8e3fc 100644 --- a/unrar/unrar/filefn.hpp +++ b/unrar/unrar/filefn.hpp @@ -5,7 +5,7 @@ enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH}; MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr); bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName); -void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta); +void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta); bool IsRemovable(const char *Name); Int64 GetFreeDisk(const char *Name); bool FileExist(const char *Name,const wchar *NameW=NULL); @@ -38,4 +38,7 @@ bool DelDir(const char *Name,const wchar *NameW); bool SetFileCompression(char *Name,wchar *NameW,bool State); #endif + + + #endif diff --git a/unrar/unrar/filestr.cpp b/unrar/unrar/filestr.cpp index 55e79a1..c7217af 100644 --- a/unrar/unrar/filestr.cpp +++ b/unrar/unrar/filestr.cpp @@ -3,7 +3,8 @@ static bool IsUnicode(byte *Data,int Size); bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError, - RAR_CHARSET SrcCharset,bool Unquote,bool SkipComments) + RAR_CHARSET SrcCharset,bool Unquote,bool SkipComments, + bool ExpandEnvStr) { char FileName[NM]; if (Config) @@ -79,7 +80,28 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError, CurStr++; } WideToChar(CurStr,&AnsiName[0],AnsiName.Size()); - List->AddString(&AnsiName[0],CurStr); + + bool Expanded=false; +#if defined(_WIN_32) && !defined(_WIN_CE) + if (ExpandEnvStr && *CurStr=='%') + { + // expanding environment variables in Windows version + + char ExpName[NM]; + wchar ExpNameW[NM]; + *ExpNameW=0; + int ret,retw=1; + ret=ExpandEnvironmentStrings(&AnsiName[0],ExpName,ASIZE(ExpName)); + if (ret!=0 && WinNT()) + retw=ExpandEnvironmentStringsW(CurStr,ExpNameW,ASIZE(ExpNameW)); + Expanded=ret!=0 && ret<ASIZE(ExpName) && + retw!=0 && retw<ASIZE(ExpNameW); + if (Expanded) + List->AddString(ExpName,ExpNameW); + } +#endif + if (!Expanded) + List->AddString(&AnsiName[0],CurStr); } CurStr=NextStr+1; while (*CurStr=='\r' || *CurStr=='\n') @@ -112,7 +134,7 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError, { if (Unquote && *CurStr=='\"') { - int Length=strlen(CurStr); + size_t Length=strlen(CurStr); if (CurStr[Length-1]=='\"') { CurStr[Length-1]=0; @@ -123,7 +145,22 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError, if (SrcCharset==RCH_OEM) OemToChar(CurStr,CurStr); #endif - List->AddString(CurStr); + + bool Expanded=false; +#if defined(_WIN_32) && !defined(_WIN_CE) + if (ExpandEnvStr && *CurStr=='%') + { + // expanding environment variables in Windows version + + char ExpName[NM]; + int ret=ExpandEnvironmentStrings(CurStr,ExpName,ASIZE(ExpName)); + Expanded=ret!=0 && ret<ASIZE(ExpName); + if (Expanded) + List->AddString(ExpName); + } +#endif + if (!Expanded) + List->AddString(CurStr); } CurStr=NextStr+1; while (*CurStr=='\r' || *CurStr=='\n') diff --git a/unrar/unrar/filestr.hpp b/unrar/unrar/filestr.hpp index 43ce417..927711b 100644 --- a/unrar/unrar/filestr.hpp +++ b/unrar/unrar/filestr.hpp @@ -3,6 +3,7 @@ bool ReadTextFile(char *Name,StringList *List,bool Config, bool AbortOnError=false,RAR_CHARSET SrcCharset=RCH_DEFAULT, - bool Unquote=false,bool SkipComments=false); + bool Unquote=false,bool SkipComments=false, + bool ExpandEnvStr=false); #endif diff --git a/unrar/unrar/find.cpp b/unrar/unrar/find.cpp index 9885ee6..50a0af6 100644 --- a/unrar/unrar/find.cpp +++ b/unrar/unrar/find.cpp @@ -4,7 +4,7 @@ FindFile::FindFile() { *FindMask=0; *FindMaskW=0; - FirstCall=TRUE; + FirstCall=true; #ifdef _WIN_32 hFind=INVALID_HANDLE_VALUE; #else @@ -30,7 +30,7 @@ void FindFile::SetMask(const char *FindMask) strcpy(FindFile::FindMask,FindMask); if (*FindMaskW==0) CharToWide(FindMask,FindMaskW); - FirstCall=TRUE; + FirstCall=true; } @@ -41,7 +41,7 @@ void FindFile::SetMaskW(const wchar *FindMaskW) strcpyw(FindFile::FindMaskW,FindMaskW); if (*FindMask==0) WideToChar(FindMaskW,FindMask); - FirstCall=TRUE; + FirstCall=true; } @@ -120,8 +120,9 @@ bool FindFile::Next(struct FindData *fd,bool GetSymLink) CharToWide(fd->Name,fd->NameW); #endif #endif + fd->Flags=0; fd->IsDir=IsDir(fd->FileAttr); - FirstCall=FALSE; + FirstCall=false; char *Name=PointToName(fd->Name); if (strcmp(Name,".")==0 || strcmp(Name,"..")==0) return(Next(fd)); @@ -185,6 +186,7 @@ bool FindFile::FastFind(const char *FindMask,const wchar *FindMaskW,struct FindD CharToWide(fd->Name,fd->NameW); #endif #endif + fd->Flags=0; fd->IsDir=IsDir(fd->FileAttr); return(true); } @@ -290,6 +292,7 @@ HANDLE FindFile::Win32Find(HANDLE hFind,const char *Mask,const wchar *MaskW,stru } } #endif + fd->Flags=0; return(hFind); } #endif diff --git a/unrar/unrar/find.hpp b/unrar/unrar/find.hpp index 8154819..3320d50 100644 --- a/unrar/unrar/find.hpp +++ b/unrar/unrar/find.hpp @@ -1,6 +1,10 @@ #ifndef _RAR_FINDDATA_ #define _RAR_FINDDATA_ +enum FINDDATA_FLAGS { + FDDF_SECONDDIR=1 // second entry of directory in SCAN_GETDIRSTWICE ScanTree mode +}; + struct FindData { char Name[NM]; @@ -18,6 +22,7 @@ struct FindData FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; #endif + uint Flags; bool Error; }; @@ -30,7 +35,7 @@ class FindFile char FindMask[NM]; wchar FindMaskW[NM]; - int FirstCall; + bool FirstCall; #ifdef _WIN_32 HANDLE hFind; #else diff --git a/unrar/unrar/headers.hpp b/unrar/unrar/headers.hpp index acf597d..94e8aa0 100644 --- a/unrar/unrar/headers.hpp +++ b/unrar/unrar/headers.hpp @@ -65,9 +65,9 @@ #define LONG_BLOCK 0x8000 #define EARC_NEXT_VOLUME 0x0001 // not last volume -#define EARC_DATACRC 0x0002 -#define EARC_REVSPACE 0x0004 -#define EARC_VOLNUMBER 0x0008 +#define EARC_DATACRC 0x0002 // store CRC32 of RAR archive (now used only in volumes) +#define EARC_REVSPACE 0x0004 // reserve space for end of REV file 7 byte record +#define EARC_VOLNUMBER 0x0008 // store a number of current volume enum HEADER_TYPE { MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76, @@ -218,11 +218,13 @@ struct FileHeader:BlockHeader struct EndArcHeader:BaseBlock { - uint ArcDataCRC; - ushort VolNumber; + uint ArcDataCRC; // optional archive CRC32 + ushort VolNumber; // optional current volume number }; +// SubBlockHeader and its successors were used in RAR 2.x format. +// RAR 3.x uses FileHeader with NEWSUB_HEAD HeadType for subblocks. struct SubBlockHeader:BlockHeader { ushort SubType; diff --git a/unrar/unrar/list.cpp b/unrar/unrar/list.cpp index d569006..99d730f 100644 --- a/unrar/unrar/list.cpp +++ b/unrar/unrar/list.cpp @@ -270,13 +270,20 @@ void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown, void ListSymLink(Archive &Arc) { if (Arc.NewLhd.HostOS==HOST_UNIX && (Arc.NewLhd.FileAttr & 0xF000)==0xA000) - { - char FileName[NM]; - int DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1); - Arc.Read(FileName,DataSize); - FileName[DataSize]=0; - mprintf("\n%22s %s","-->",FileName); - } + if ((Arc.NewLhd.Flags & LHD_PASSWORD)==0) + { + char FileName[NM]; + int DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1); + Arc.Read(FileName,DataSize); + FileName[DataSize]=0; + mprintf("\n%22s %s","-->",FileName); + } + else + { + // Link data are encrypted. We would need to ask for password + // and initialize decryption routine to display the link target. + mprintf("\n%22s %s","-->","*<-?->"); + } } diff --git a/unrar/unrar/loclang.hpp b/unrar/unrar/loclang.hpp index c425bb3..37da3a0 100644 --- a/unrar/unrar/loclang.hpp +++ b/unrar/unrar/loclang.hpp @@ -1,5 +1,6 @@ #define MYesNo "_Yes_No" #define MYesNoAll "_Yes_No_All" +#define MYesNoAllQ "_Yes_No_All_nEver_Quit" #define MYesNoAllRenQ "_Yes_No_All_nEver_Rename_Quit" #define MContinueQuit "_Continue_Quit" #define MRetryAbort "_Retry_Abort" @@ -63,7 +64,9 @@ #define MCHelpSwCU "\n cu Convert names to upper case" #define MCHelpSwDF "\n df Delete files after archiving" #define MCHelpSwDH "\n dh Open shared files" +#define MCHelpSwDR "\n dr Delete files to Recycle Bin" #define MCHelpSwDS "\n ds Disable name sort for solid archive" +#define MCHelpSwDW "\n dw Wipe files after archiving" #define MCHelpSwEa "\n e[+]<attr> Set file exclude and include attributes" #define MCHelpSwED "\n ed Do not add empty directories" #define MCHelpSwEE "\n ee Do not save and extract extended attributes" @@ -91,8 +94,7 @@ #define MCHelpSwN "\n n<file> Include only specified file" #define MCHelpSwNa "\n n@ Read file names to include from stdin" #define MCHelpSwNal "\n n@<list> Include files in specified list file" -#define MCHelpSwOp "\n o+ Overwrite existing files" -#define MCHelpSwOm "\n o- Do not overwrite existing files" +#define MCHelpSwO "\n o[+|-] Set the overwrite mode" #define MCHelpSwOC "\n oc Set NTFS Compressed attribute" #define MCHelpSwOL "\n ol Save symbolic links as the link instead of the file" #define MCHelpSwOR "\n or Rename files automatically" @@ -347,3 +349,4 @@ #define MCannotDelete "\nCannot delete %s" #define MCalcCRC "\nCalculating the control sum" #define MTooLargeSFXArc "\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB." +#define MCalcCRCAllVol "\nCalculating control sums of all volumes." diff --git a/unrar/unrar/makefile.unix b/unrar/unrar/makefile.unix index f2a7dcf..d22ed58 100644 --- a/unrar/unrar/makefile.unix +++ b/unrar/unrar/makefile.unix @@ -10,30 +10,35 @@ CXX=g++ CXXFLAGS=-O2 DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE STRIP=strip +DESTDIR=/usr # Linux using LCC #CXX=lcc #CXXFLAGS=-O2 #DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE #STRIP=strip +#DESTDIR=/usr # HP UX using aCC #CXX=aCC #CXXFLAGS=-AA +O2 +Onolimit #DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE #STRIP=strip +#DESTDIR=/usr # IRIX using GCC #CXX=g++ #CXXFLAGS=-O2 #DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1 #STRIP=strip +#DESTDIR=/usr # IRIX using MIPSPro (experimental) #CXX=CC #CXXFLAGS=-O2 -mips3 -woff 1234,1156,3284 -LANG:std #DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_BSD_COMPAT -DNATIVE_INT64 -DInt64=int64_t #STRIP=strip +#DESTDIR=/usr # AIX using xlC (IBM VisualAge C++ 5.0) #CXX=xlC @@ -41,36 +46,42 @@ STRIP=strip #DEFINES=-D_LARGE_FILES -D_LARGE_FILE_API #LIBS=-lbsd #STRIP=strip +#DESTDIR=/usr # Solaris using CC (SUN Forte Developer 7 C++) #CXX=CC #CXXFLAGS=-xO2 -xbuiltin=%all -xinline=%auto #DEFINES=-DBIG_ENDIAN -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE #STRIP=strip +#DESTDIR=/usr # Solaris using GCC (optimized for UltraSPARC 1 CPU) #CXX=g++ #CXXFLAGS=-O3 -mcpu=v9 -mtune=ultrasparc -m32 #DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE #STRIP=/usr/ccs/bin/strip +#DESTDIR=/usr # Tru64 5.1B using GCC3 #CXX=g++ #CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_XOPEN_SOURCE=500 #STRIP=strip #LDFLAGS=-rpath /usr/local/gcc/lib +#DESTDIR=/usr # Tru64 5.1B using DEC C++ #CXX=cxx #CXXFLAGS=-O4 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DNATIVE_INT64 -DInt64=long #STRIP=strip #LDFLAGS= +#DESTDIR=/usr # QNX 6.x using GCC #CXX=g++ #CXXFLAGS=-O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fexceptions #STRIP=strip #LDFLAGS=-fexceptions +#DESTDIR=/usr # Cross-compile # Linux using arm-linux-g++ @@ -79,6 +90,7 @@ STRIP=strip #DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE #STRIP=arm-linux-strip #LDFLAGS=-static +#DESTDIR=/usr ########################## @@ -98,6 +110,10 @@ OBJECTS=rar.o strlist.o strfn.o pathfn.o int64.o savepos.o global.o file.o filef all: unrar +install: install-unrar + +uninstall: uninstall-unrar + clean: @rm -f *.o *.bak *~ @@ -117,3 +133,15 @@ lib: WHAT=RARDLL lib: $(OBJECTS) $(LIB_OBJ) @rm -f libunrar.so $(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ) + +install-unrar: + install unrar $(DESTDIR)/bin + +uninstall-unrar: + rm -f $(DESTDIR)/bin/unrar + +install-lib: + install libunrar.so $(DESTDIR)/lib + +uninstall-lib: + rm -f $(DESTDIR)/lib/libunrar.so diff --git a/unrar/unrar/match.cpp b/unrar/unrar/match.cpp index de03fb4..bd1c02f 100644 --- a/unrar/unrar/match.cpp +++ b/unrar/unrar/match.cpp @@ -5,15 +5,15 @@ static bool match(wchar *pattern,wchar *string,bool ForceCase); static int mstricompc(const char *Str1,const char *Str2,bool ForceCase); static int mstricompcw(const wchar *Str1,const wchar *Str2,bool ForceCase); -static int mstrnicompc(const char *Str1,const char *Str2,int N,bool ForceCase); -static int mstrnicompcw(const wchar *Str1,const wchar *Str2,int N,bool ForceCase); +static int mstrnicompc(const char *Str1,const char *Str2,size_t N,bool ForceCase); +static int mstrnicompcw(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase); inline uint toupperc(byte ch,bool ForceCase) { if (ForceCase) return(ch); #ifdef _WIN_32 - return((uint)CharUpper((LPTSTR)(ch))); + return((uint)(LPARAM)CharUpper((LPTSTR)(ch))); #elif defined(_UNIX) return(ch); #else @@ -42,7 +42,7 @@ bool CmpName(char *Wildcard,char *Name,int CmpPath) if (CmpPath!=MATCH_NAMES) { - int WildLength=strlen(Wildcard); + size_t WildLength=strlen(Wildcard); if (CmpPath!=MATCH_EXACTPATH && mstrnicompc(Wildcard,Name,WildLength,ForceCase)==0) { char NextCh=Name[WildLength]; @@ -71,8 +71,12 @@ bool CmpName(char *Wildcard,char *Name,int CmpPath) } char *Name1=PointToName(Wildcard); char *Name2=PointToName(Name); + + // always return false for RAR temporary files to exclude them + // from archiving operations if (mstrnicompc("__rar_",Name2,6,false)==0) return(false); + return(match(Name1,Name2,ForceCase)); } @@ -86,7 +90,7 @@ bool CmpName(wchar *Wildcard,wchar *Name,int CmpPath) if (CmpPath!=MATCH_NAMES) { - int WildLength=strlenw(Wildcard); + size_t WildLength=strlenw(Wildcard); if (CmpPath!=MATCH_EXACTPATH && mstrnicompcw(Wildcard,Name,WildLength,ForceCase)==0) { wchar NextCh=Name[WildLength]; @@ -113,8 +117,12 @@ bool CmpName(wchar *Wildcard,wchar *Name,int CmpPath) } wchar *Name1=PointToName(Wildcard); wchar *Name2=PointToName(Name); + + // always return false for RAR temporary files to exclude them + // from archiving operations if (mstrnicompcw(L"__rar_",Name2,6,false)==0) return(false); + return(match(Name1,Name2,ForceCase)); } #endif @@ -236,7 +244,7 @@ int mstricompcw(const wchar *Str1,const wchar *Str2,bool ForceCase) #endif -int mstrnicompc(const char *Str1,const char *Str2,int N,bool ForceCase) +int mstrnicompc(const char *Str1,const char *Str2,size_t N,bool ForceCase) { if (ForceCase) return(strncmp(Str1,Str2,N)); @@ -249,7 +257,7 @@ int mstrnicompc(const char *Str1,const char *Str2,int N,bool ForceCase) #ifndef SFX_MODULE -int mstrnicompcw(const wchar *Str1,const wchar *Str2,int N,bool ForceCase) +int mstrnicompcw(const wchar *Str1,const wchar *Str2,size_t N,bool ForceCase) { if (ForceCase) return(strncmpw(Str1,Str2,N)); diff --git a/unrar/unrar/match.hpp b/unrar/unrar/match.hpp index 5ea6115..0e43514 100644 --- a/unrar/unrar/match.hpp +++ b/unrar/unrar/match.hpp @@ -1,7 +1,22 @@ #ifndef _RAR_MATCH_ #define _RAR_MATCH_ -enum {MATCH_NAMES,MATCH_PATH,MATCH_EXACTPATH,MATCH_SUBPATH,MATCH_WILDSUBPATH}; +enum { + MATCH_NAMES, // Compare names only. + + MATCH_PATH, // Compares names and paths. Both must match exactly. + // Unlike MATCH_EXACTPATH, also matches names if + // mask contains path only and this path is a part + // of name path. + + MATCH_EXACTPATH, // Compares names and paths. Both must match exactly. + + MATCH_SUBPATH, // Names must be the same, but path in mask is allowed + // to be only a part of name path. + + MATCH_WILDSUBPATH // Works as MATCH_SUBPATH if mask contains wildcards + // and as MATCH_PATH otherwise. +}; #define MATCH_MODEMASK 0x0000ffff #define MATCH_FORCECASESENSITIVE 0x80000000 diff --git a/unrar/unrar/options.cpp b/unrar/unrar/options.cpp index e6efb42..57ca92f 100644 --- a/unrar/unrar/options.cpp +++ b/unrar/unrar/options.cpp @@ -16,7 +16,7 @@ void RAROptions::Init() { memset(this,0,sizeof(RAROptions)); WinSize=0x400000; - Overwrite=OVERWRITE_ASK; + Overwrite=OVERWRITE_DEFAULT; Method=3; MsgStream=MSG_STDOUT; ConvertNames=NAMES_ORIGINALCASE; diff --git a/unrar/unrar/options.hpp b/unrar/unrar/options.hpp index cc2db48..8af0e8b 100644 --- a/unrar/unrar/options.hpp +++ b/unrar/unrar/options.hpp @@ -17,8 +17,13 @@ enum EXTTIME_MODE { }; enum {NAMES_ORIGINALCASE,NAMES_UPPERCASE,NAMES_LOWERCASE}; enum MESSAGE_TYPE {MSG_STDOUT,MSG_STDERR,MSG_ERRONLY,MSG_NULL}; + enum OVERWRITE_MODE { - OVERWRITE_ASK,OVERWRITE_ALL,OVERWRITE_NONE,OVERWRITE_AUTORENAME + OVERWRITE_DEFAULT, // ask for extraction, silently overwrite for archiving + OVERWRITE_ALL, + OVERWRITE_NONE, + OVERWRITE_AUTORENAME, + OVERWRITE_FORCE_ASK }; enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE }; @@ -54,6 +59,7 @@ class RAROptions RAR_CHARSET CommentCharset; RAR_CHARSET FilelistCharset; char ArcPath[NM]; + wchar ArcPathW[NM]; char Password[MAXPASSWORD]; bool EncryptHeaders; char LogName[NM]; @@ -133,7 +139,7 @@ class RAROptions wchar DllDestNameW[NM]; int DllOpMode; int DllError; - LONG UserData; + LPARAM UserData; UNRARCALLBACK Callback; CHANGEVOLPROC ChangeVolProc; PROCESSDATAPROC ProcessDataProc; diff --git a/unrar/unrar/os.hpp b/unrar/unrar/os.hpp index 453b9b0..fbcf3a0 100644 --- a/unrar/unrar/os.hpp +++ b/unrar/unrar/os.hpp @@ -33,6 +33,7 @@ #include <prsht.h> #ifndef _WIN_CE + #include <shellapi.h> #include <shlobj.h> #include <winioctl.h> #endif @@ -213,7 +214,7 @@ #endif -typedef const char* MSGID; + typedef const char* MSGID; #define safebuf static diff --git a/unrar/unrar/pathfn.cpp b/unrar/unrar/pathfn.cpp index e635d16..3621916 100644 --- a/unrar/unrar/pathfn.cpp +++ b/unrar/unrar/pathfn.cpp @@ -29,6 +29,8 @@ char* PointToLastChar(const char *Path) } + + char* ConvertPath(const char *SrcPath,char *DestPath) { const char *DestPtr=SrcPath; @@ -325,6 +327,26 @@ void GetAppDataPath(char *Path) #endif +#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) +void GetRarDataPath(char *Path) +{ + *Path=0; + + HKEY hKey; + if (RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\WinRAR\\Paths",0, + KEY_QUERY_VALUE,&hKey)==ERROR_SUCCESS) + { + DWORD DataSize=NM,Type; + RegQueryValueEx(hKey,"AppData",0,&Type,(BYTE *)Path,&DataSize); + RegCloseKey(hKey); + } + + if (*Path==0 || !FileExist(Path)) + GetAppDataPath(Path); +} +#endif + + #ifndef SFX_MODULE bool EnumConfigPaths(char *Path,int Number) { @@ -348,18 +370,16 @@ bool EnumConfigPaths(char *Path,int Number) RemoveNameFromPath(Path); return(true); #elif defined(_UNIX) + static const char *AltPath[]={ + "/etc","/etc/rar","/usr/lib","/usr/local/lib","/usr/local/etc" + }; if (Number==0) { char *EnvStr=getenv("HOME"); - if (EnvStr==NULL) - return(false); - strncpy(Path,EnvStr,NM-1); + strncpy(Path, (EnvStr==NULL) ? AltPath[0] : EnvStr, NM-1); Path[NM-1]=0; return(true); } - static const char *AltPath[]={ - "/etc","/etc/rar","/usr/lib","/usr/local/lib","/usr/local/etc" - }; Number--; if (Number<0 || Number>=sizeof(AltPath)/sizeof(AltPath[0])) return(false); @@ -370,7 +390,7 @@ bool EnumConfigPaths(char *Path,int Number) if (Number<0 || Number>1) return(false); if (Number==0) - GetAppDataPath(Path); + GetRarDataPath(Path); else { GetModuleFileName(NULL,Path,NM); @@ -388,6 +408,7 @@ bool EnumConfigPaths(char *Path,int Number) #ifndef SFX_MODULE void GetConfigName(const char *Name,char *FullName,bool CheckExist) { + *FullName=0; for (int I=0;EnumConfigPaths(FullName,I);I++) { AddEndSlash(FullName); @@ -423,7 +444,7 @@ char* GetVolNumPart(char *ArcName) } -void NextVolumeName(char *ArcName,bool OldNumbering) +void NextVolumeName(char *ArcName,wchar *ArcNameW,uint MaxLength,bool OldNumbering) { char *ChPtr; if ((ChPtr=GetExt(ArcName))==NULL) @@ -469,6 +490,29 @@ void NextVolumeName(char *ArcName,bool OldNumbering) ChPtr--; } } + if (ArcNameW!=NULL && *ArcNameW!=0) + { + // Copy incremented trailing low ASCII volume name part to Unicode name. + // It is simpler than implementing Unicode version of entire function. + char *NumPtr=GetVolNumPart(ArcName); + + // moving to first digit in volume number + while (NumPtr>ArcName && isdigit(*NumPtr) && isdigit(*(NumPtr-1))) + NumPtr--; + + // also copy the first character before volume number, + // because it can be changed when going from .r99 to .s00 + if (NumPtr>ArcName) + NumPtr--; + + int CharsToCopy=strlen(ArcName)-(NumPtr-ArcName); + int DestPos=strlenw(ArcNameW)-CharsToCopy; + if (DestPos>0) + { + CharToWide(NumPtr,ArcNameW+DestPos,MaxLength-DestPos-1); + ArcNameW[MaxLength-1]=0; + } + } } @@ -579,7 +623,22 @@ bool IsFullPath(const char *Path) { char PathOnly[NM]; GetFilePath(Path,PathOnly,ASIZE(PathOnly)); - if (IsWildcard(PathOnly)) + if (IsWildcard(PathOnly,NULL)) + return(true); +#if defined(_WIN_32) || defined(_EMX) + return(Path[0]=='\\' && Path[1]=='\\' || + IsDiskLetter(Path) && IsPathDiv(Path[2])); +#else + return(IsPathDiv(Path[0])); +#endif +} + + +bool IsFullPath(const wchar *Path) +{ + wchar PathOnly[NM]; + GetFilePath(Path,PathOnly,ASIZE(PathOnly)); + if (IsWildcard(NULL,PathOnly)) return(true); #if defined(_WIN_32) || defined(_EMX) return(Path[0]=='\\' && Path[1]=='\\' || @@ -597,6 +656,13 @@ bool IsDiskLetter(const char *Path) } +bool IsDiskLetter(const wchar *Path) +{ + int Letter=etoupper(Path[0]); + return(Letter>='A' && Letter<='Z' && IsDriveDiv(Path[1])); +} + + void GetPathRoot(const char *Path,char *Root) { *Root=0; @@ -608,7 +674,7 @@ void GetPathRoot(const char *Path,char *Root) const char *Slash=strchr(Path+2,'\\'); if (Slash!=NULL) { - int Length; + size_t Length; if ((Slash=strchr(Slash+1,'\\'))!=NULL) Length=Slash-Path+1; else diff --git a/unrar/unrar/pathfn.hpp b/unrar/unrar/pathfn.hpp index 6975993..6b0ac31 100644 --- a/unrar/unrar/pathfn.hpp +++ b/unrar/unrar/pathfn.hpp @@ -24,17 +24,20 @@ void GetFilePath(const wchar *FullName,wchar *Path,int MaxLength); void RemoveNameFromPath(char *Path); void RemoveNameFromPath(wchar *Path); void GetAppDataPath(char *Path); +void GetRarDataPath(char *Path); bool EnumConfigPaths(char *Path,int Number); void GetConfigName(const char *Name,char *FullName,bool CheckExist); char* GetVolNumPart(char *ArcName); -void NextVolumeName(char *ArcName,bool OldNumbering); +void NextVolumeName(char *ArcName,wchar *ArcNameW,uint MaxLength,bool OldNumbering); bool IsNameUsable(const char *Name); void MakeNameUsable(char *Name,bool Extended); char* UnixSlashToDos(char *SrcName,char *DestName=NULL,uint MaxLength=NM); char* DosSlashToUnix(char *SrcName,char *DestName=NULL,uint MaxLength=NM); wchar* UnixSlashToDos(wchar *SrcName,wchar *DestName=NULL,uint MaxLength=NM); bool IsFullPath(const char *Path); +bool IsFullPath(const wchar *Path); bool IsDiskLetter(const char *Path); +bool IsDiskLetter(const wchar *Path); void GetPathRoot(const char *Path,char *Root); int ParseVersionFileName(char *Name,wchar *NameW,bool Truncate); char* VolNameToFirstName(const char *VolName,char *FirstName,bool NewNumbering); diff --git a/unrar/unrar/rdwrfn.cpp b/unrar/unrar/rdwrfn.cpp index 2454377..2662bdb 100644 --- a/unrar/unrar/rdwrfn.cpp +++ b/unrar/unrar/rdwrfn.cpp @@ -118,7 +118,7 @@ void ComprDataIO::UnpWrite(byte *Addr,uint Count) if (Cmd->DllOpMode!=RAR_SKIP) { if (Cmd->Callback!=NULL && - Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LONG)Addr,Count)==-1) + Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LPARAM)Addr,Count)==-1) ErrHandler.Exit(USER_BREAK); if (Cmd->ProcessDataProc!=NULL) { @@ -169,19 +169,21 @@ void ComprDataIO::ShowUnpRead(Int64 ArcPos,Int64 ArcSize) { if (ShowProgress && SrcFile!=NULL) { - Archive *SrcArc=(Archive *)SrcFile; - RAROptions *Cmd=SrcArc->GetRAROptions(); if (TotalArcSize!=0) + { + // important when processing several archives or multivolume archive ArcSize=TotalArcSize; - ArcPos+=ProcessedArcSize; - if (!SrcArc->Volume) + ArcPos+=ProcessedArcSize; + } + + Archive *SrcArc=(Archive *)SrcFile; + RAROptions *Cmd=SrcArc->GetRAROptions(); + + int CurPercent=ToPercent(ArcPos,ArcSize); + if (!Cmd->DisablePercentage && CurPercent!=LastPercent) { - int CurPercent=ToPercent(ArcPos,ArcSize); - if (!Cmd->DisablePercentage && CurPercent!=LastPercent) - { - mprintf("\b\b\b\b%3d%%",CurPercent); - LastPercent=CurPercent; - } + mprintf("\b\b\b\b%3d%%",CurPercent); + LastPercent=CurPercent; } } } diff --git a/unrar/unrar/rdwrfn.hpp b/unrar/unrar/rdwrfn.hpp index 8313627..b80ae28 100644 --- a/unrar/unrar/rdwrfn.hpp +++ b/unrar/unrar/rdwrfn.hpp @@ -72,7 +72,12 @@ class ComprDataIO Int64 TotalPackRead; Int64 UnpArcSize; Int64 CurPackRead,CurPackWrite,CurUnpRead,CurUnpWrite; - Int64 ProcessedArcSize,TotalArcSize; + + // Size of already processed archives. + // Used to calculate the total operation progress. + Int64 ProcessedArcSize; + + Int64 TotalArcSize; uint PackFileCRC,UnpFileCRC,PackedCRC; diff --git a/unrar/unrar/recvol.cpp b/unrar/unrar/recvol.cpp index 0296b02..6d6f6af 100644 --- a/unrar/unrar/recvol.cpp +++ b/unrar/unrar/recvol.cpp @@ -79,6 +79,11 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name, #ifndef SILENT Int64 RecFileSize=0; #endif + +#ifndef SILENT + mprintf(St(MCalcCRCAllVol)); +#endif + FindFile Find; Find.SetMask(RecVolMask); struct FindData RecData; @@ -236,7 +241,7 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name, #endif } SrcFile[CurArcNum]=(File*)NewFile; - NextVolumeName(ArcName,!NewNumbering); + NextVolumeName(ArcName,ArcNameW,ASIZE(ArcName),!NewNumbering); } #ifndef SILENT @@ -273,8 +278,10 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name, #ifndef SILENT Int64 ProcessedSize=0; -#ifndef GUI + +/* Modified by Tomas Bzatek - bug in defines */ int LastPercent=-1; +#ifndef GUI mprintf(" "); #endif #endif diff --git a/unrar/unrar/scantree.cpp b/unrar/unrar/scantree.cpp index 416de6d..cfd2ef7 100644 --- a/unrar/unrar/scantree.cpp +++ b/unrar/unrar/scantree.cpp @@ -7,6 +7,8 @@ ScanTree::ScanTree(StringList *FileMasks,int Recurse,bool GetLinks,int GetDirs) ScanTree::GetLinks=GetLinks; ScanTree::GetDirs=GetDirs; + ScanEntireDisk=false; + SetAllMaskDepth=0; *CurMask=0; *CurMaskW=0; @@ -57,6 +59,7 @@ int ScanTree::GetNext(FindData *FindData) bool ScanTree::PrepareMasks() { + ScanEntireDisk=false; if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask))) return(false); CurMask[ASIZE(CurMask)-1]=0; @@ -64,6 +67,12 @@ bool ScanTree::PrepareMasks() #ifdef _WIN_32 UnixSlashToDos(CurMask); #endif + + // We wish to scan entire disk if mask like c:\ is specified + // regardless of recursion mode. Use c:\*.* mask when need to scan only + // the root directory. + ScanEntireDisk=IsDiskLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0; + char *Name=PointToName(CurMask); if (*Name==0) strcat(CurMask,MASKALL); @@ -116,7 +125,7 @@ int ScanTree::FindProc(FindData *FindData) bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks); bool IsDir=FindCode && FindData->IsDir; bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS || - Wildcards && Recurse==RECURSE_WILDCARDS); + Wildcards && Recurse==RECURSE_WILDCARDS || ScanEntireDisk); if (Depth==0) SearchAllInRoot=SearchAll; if (SearchAll || Wildcards) @@ -234,7 +243,10 @@ int ScanTree::FindProc(FindData *FindData) } if (GetDirs==SCAN_GETDIRSTWICE && FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir) + { + FindData->Flags|=FDDF_SECONDDIR; return(Error ? SCAN_ERROR:SCAN_SUCCESS); + } return(Error ? SCAN_ERROR:SCAN_NEXT); } diff --git a/unrar/unrar/scantree.hpp b/unrar/unrar/scantree.hpp index 2f206ba..34d52fe 100644 --- a/unrar/unrar/scantree.hpp +++ b/unrar/unrar/scantree.hpp @@ -26,6 +26,9 @@ class ScanTree int GetDirs; int Errors; + // set when processing paths like c:\ (root directory without wildcards) + bool ScanEntireDisk; + char CurMask[NM]; wchar CurMaskW[NM]; char OrigCurMask[NM]; diff --git a/unrar/unrar/strfn.cpp b/unrar/unrar/strfn.cpp index 4c22799..52b7a5f 100644 --- a/unrar/unrar/strfn.cpp +++ b/unrar/unrar/strfn.cpp @@ -86,7 +86,7 @@ int strnicomp(const char *Str1,const char *Str2,int N) char* RemoveEOL(char *Str) { - for (int I=strlen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n' || Str[I]==' ' || Str[I]=='\t');I--) + for (int I=(int)strlen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n' || Str[I]==' ' || Str[I]=='\t');I--) Str[I]=0; return(Str); } @@ -94,7 +94,7 @@ char* RemoveEOL(char *Str) char* RemoveLF(char *Str) { - for (int I=strlen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--) + for (int I=(int)strlen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--) Str[I]=0; return(Str); } @@ -103,7 +103,8 @@ char* RemoveLF(char *Str) unsigned int loctolower(byte ch) { #ifdef _WIN_32 - return((int)CharLower((LPTSTR)ch)); + // convert to LPARAM first to avoid a warning in 64 bit mode + return((int)(LPARAM)CharLower((LPTSTR)ch)); #else return(tolower(ch)); #endif @@ -113,7 +114,8 @@ unsigned int loctolower(byte ch) unsigned int loctoupper(byte ch) { #ifdef _WIN_32 - return((int)CharUpper((LPTSTR)ch)); + // convert to LPARAM first to avoid a warning in 64 bit mode + return((int)(LPARAM)CharUpper((LPTSTR)ch)); #else return(toupper(ch)); #endif diff --git a/unrar/unrar/strlist.cpp b/unrar/unrar/strlist.cpp index 86cace5..7e7e50c 100644 --- a/unrar/unrar/strlist.cpp +++ b/unrar/unrar/strlist.cpp @@ -31,7 +31,7 @@ unsigned int StringList::AddString(const char *Str) unsigned int StringList::AddString(const char *Str,const wchar *StrW) { int PrevSize=StringData.Size(); - StringData.Add(strlen(Str)+1); + StringData.Add((int)(strlen(Str)+1)); strcpy(&StringData[PrevSize],Str); if (StrW!=NULL && *StrW!=0) { diff --git a/unrar/unrar/timefn.cpp b/unrar/unrar/timefn.cpp index d11c663..3a7b834 100644 --- a/unrar/unrar/timefn.cpp +++ b/unrar/unrar/timefn.cpp @@ -248,7 +248,6 @@ void RarTime::SetAgeText(char *TimeText) #endif -#ifndef SFX_MODULE void RarTime::SetCurrentTime() { #ifdef _WIN_32 @@ -263,7 +262,6 @@ void RarTime::SetCurrentTime() *this=st; #endif } -#endif #if !defined(SFX_MODULE) && !defined(_WIN_CE) diff --git a/unrar/unrar/unicode.cpp b/unrar/unrar/unicode.cpp index 83d1187..affc905 100644 --- a/unrar/unrar/unicode.cpp +++ b/unrar/unrar/unicode.cpp @@ -16,7 +16,10 @@ bool WideToChar(const wchar *Src,char *Dest,int DestSize) #else #ifdef MBFUNCTIONS - if (wcstombs(Dest,Src,DestSize)==(size_t)-1) + size_t ResultingSize=wcstombs(Dest,Src,DestSize); + if (ResultingSize==(size_t)-1) + RetCode=false; + if (ResultingSize==0 && *Src!=0) RetCode=false; if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlenw(Src)<NM) @@ -66,7 +69,10 @@ bool CharToWide(const char *Src,wchar *Dest,int DestSize) #else #ifdef MBFUNCTIONS - if (mbstowcs(Dest,Src,DestSize)==(size_t)-1) + size_t ResultingSize=mbstowcs(Dest,Src,DestSize); + if (ResultingSize==(size_t)-1) + RetCode=false; + if (ResultingSize==0 && *Src!=0) RetCode=false; if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlen(Src)<NM) @@ -241,11 +247,11 @@ wchar* strcpyw(wchar *dest,const wchar *src) } -wchar* strncpyw(wchar *dest,const wchar *src,int n) +wchar* strncpyw(wchar *dest,const wchar *src,size_t n) { do { *(dest++)=*src; - } while (*(src++)!=0 && --n > 0); + } while (*(src++)!=0 && (int)(--n) > 0); return(dest); } @@ -257,11 +263,11 @@ wchar* strcatw(wchar *dest,const wchar *src) #ifndef SFX_MODULE -wchar* strncatw(wchar *dest,const wchar *src,int n) +wchar* strncatw(wchar *dest,const wchar *src,size_t n) { dest+=strlenw(dest); while (true) - if (--n<0) + if ((int)(--n)<0) { *dest=0; break; @@ -287,9 +293,9 @@ int strcmpw(const wchar *s1,const wchar *s2) } -int strncmpw(const wchar *s1,const wchar *s2,int n) +int strncmpw(const wchar *s1,const wchar *s2,size_t n) { - while (n-->0) + while ((int)(n--)>0) { if (*s1<*s2) return(-1); @@ -316,7 +322,7 @@ int stricmpw(const wchar *s1,const wchar *s2) #if !defined(SFX_MODULE) && !defined(_WIN_CE) -inline int strnicmpw_w2c(const wchar *s1,const wchar *s2,int n) +inline int strnicmpw_w2c(const wchar *s1,const wchar *s2,size_t n) { wchar Wide1[NM*2],Wide2[NM*2]; strncpyw(Wide1,s1,sizeof(Wide1)/sizeof(Wide1[0])-1); @@ -332,7 +338,7 @@ inline int strnicmpw_w2c(const wchar *s1,const wchar *s2,int n) #ifndef SFX_MODULE -int strnicmpw(const wchar *s1,const wchar *s2,int n) +int strnicmpw(const wchar *s1,const wchar *s2,size_t n) { return(strnicmpw_w2c(s1,s2,n)); } @@ -395,6 +401,20 @@ wchar* strupperw(wchar *Str) #ifndef SFX_MODULE +wchar* strdupw(const wchar *Str) +{ + if (Str==NULL) + return(NULL); + wchar *n=(wchar *)malloc((strlenw(Str)+1)*sizeof(wchar)); + if (n==NULL) + return(NULL); + strcpyw(n,Str); + return(n); +} +#endif + + +#ifndef SFX_MODULE int toupperw(int ch) { return((ch<128) ? loctoupper(ch):ch); diff --git a/unrar/unrar/unicode.hpp b/unrar/unrar/unicode.hpp index 8175c00..3b4e2c3 100644 --- a/unrar/unrar/unicode.hpp +++ b/unrar/unrar/unicode.hpp @@ -28,18 +28,19 @@ bool UnicodeEnabled(); int strlenw(const wchar *str); wchar* strcpyw(wchar *dest,const wchar *src); -wchar* strncpyw(wchar *dest,const wchar *src,int n); +wchar* strncpyw(wchar *dest,const wchar *src,size_t n); wchar* strcatw(wchar *dest,const wchar *src); -wchar* strncatw(wchar *dest,const wchar *src,int n); +wchar* strncatw(wchar *dest,const wchar *src,size_t n); int strcmpw(const wchar *s1,const wchar *s2); -int strncmpw(const wchar *s1,const wchar *s2,int n); +int strncmpw(const wchar *s1,const wchar *s2,size_t n); int stricmpw(const wchar *s1,const wchar *s2); -int strnicmpw(const wchar *s1,const wchar *s2,int n); +int strnicmpw(const wchar *s1,const wchar *s2,size_t n); wchar *strchrw(const wchar *s,int c); wchar* strrchrw(const wchar *s,int c); wchar* strpbrkw(const wchar *s1,const wchar *s2); wchar* strlowerw(wchar *Str); wchar* strupperw(wchar *Str); +wchar* strdupw(const wchar *Str); int toupperw(int ch); int atoiw(const wchar *s); diff --git a/unrar/unrar/unpack.cpp b/unrar/unrar/unpack.cpp index 1b239ca..3e26153 100644 --- a/unrar/unrar/unpack.cpp +++ b/unrar/unrar/unpack.cpp @@ -262,6 +262,11 @@ void Unpack::Unpack29(bool Solid) } if (Failed) break; + +#ifdef _MSC_VER + // avoid a warning about uninitialized 'Length' variable + #pragma warning( disable : 4701 ) +#endif CopyString(Length+32,Distance+2); continue; } diff --git a/unrar/unrar/uowners.cpp b/unrar/unrar/uowners.cpp index c906059..38471e0 100644 --- a/unrar/unrar/uowners.cpp +++ b/unrar/unrar/uowners.cpp @@ -34,7 +34,7 @@ void ExtractUnixOwner(Archive &Arc,char *FileName) #endif { Log(Arc.FileName,St(MSetOwnersError),FileName); - ErrHandler.SetErrorCode(CRC_ERROR); + ErrHandler.SetErrorCode(CREATE_ERROR); } SetFileAttr(FileName,NULL,Attr); } @@ -74,7 +74,7 @@ void ExtractUnixOwnerNew(Archive &Arc,char *FileName) #endif { Log(Arc.FileName,St(MSetOwnersError),FileName); - ErrHandler.SetErrorCode(CRC_ERROR); + ErrHandler.SetErrorCode(CREATE_ERROR); } SetFileAttr(FileName,NULL,Attr); } diff --git a/unrar/unrar/version.hpp b/unrar/unrar/version.hpp index d29ecec..616d34d 100644 --- a/unrar/unrar/version.hpp +++ b/unrar/unrar/version.hpp @@ -1,6 +1,6 @@ #define RARVER_MAJOR 3 -#define RARVER_MINOR 71 -#define RARVER_BETA 1 -#define RARVER_DAY 10 -#define RARVER_MONTH 9 -#define RARVER_YEAR 2007 +#define RARVER_MINOR 80 +#define RARVER_BETA 2 +#define RARVER_DAY 15 +#define RARVER_MONTH 6 +#define RARVER_YEAR 2008 diff --git a/unrar/unrar/volume.cpp b/unrar/unrar/volume.cpp index 9a79662..4c138db 100644 --- a/unrar/unrar/volume.cpp +++ b/unrar/unrar/volume.cpp @@ -19,39 +19,17 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman } Int64 PosBeforeClose=Arc.Tell(); + + if (DataIO!=NULL) + DataIO->ProcessedArcSize+=Arc.FileLength(); + Arc.Close(); char NextName[NM]; wchar NextNameW[NM]; - *NextNameW=0; strcpy(NextName,Arc.FileName); - NextVolumeName(NextName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat); - - if (*Arc.FileNameW!=0) - { - // Copy incremented trailing low ASCII volume name part to Unicode name. - // It is simpler than also implementing Unicode version of NextVolumeName. - - strcpyw(NextNameW,Arc.FileNameW); - char *NumPtr=GetVolNumPart(NextName); - - // moving to first digit in volume number - while (NumPtr>NextName && isdigit(*NumPtr) && isdigit(*(NumPtr-1))) - NumPtr--; - - // also copy the first character before volume number, - // because it can be changed when going from .r99 to .s00 - if (NumPtr>NextName) - NumPtr--; - - int CharsToCopy=strlen(NextName)-(NumPtr-NextName); - int DestPos=strlenw(NextNameW)-CharsToCopy; - if (DestPos>0) - { - CharToWide(NumPtr,NextNameW+DestPos,ASIZE(NextNameW)-DestPos-1); - NextNameW[ASIZE(NextNameW)-1]=0; - } - } + strcpyw(NextNameW,Arc.FileNameW); + NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat); #if !defined(SFX_MODULE) && !defined(RARDLL) bool RecoveryDone=false; @@ -60,22 +38,33 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman while (!Arc.Open(NextName,NextNameW)) { + // We need to open a new volume which size was not calculated + // in total size before, so we cannot calculate the total progress + // anymore. Let's reset the total size to zero and stop + // the total progress. + if (DataIO!=NULL) + DataIO->TotalArcSize=0; + if (!OldSchemeTested) { + // Checking for new style volumes renamed by user to old style + // name format. Some users did it for unknown reason. char AltNextName[NM]; + wchar AltNextNameW[NM]; strcpy(AltNextName,Arc.FileName); - NextVolumeName(AltNextName,true); + strcpyw(AltNextNameW,Arc.FileNameW); + NextVolumeName(AltNextName,AltNextNameW,ASIZE(AltNextName),true); OldSchemeTested=true; - if (Arc.Open(AltNextName)) + if (Arc.Open(AltNextName,AltNextNameW)) { strcpy(NextName,AltNextName); - *NextNameW=0; + strcpyw(NextNameW,AltNextNameW); break; } } #ifdef RARDLL if (Cmd->Callback==NULL && Cmd->ChangeVolProc==NULL || - Cmd->Callback!=NULL && Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LONG)NextName,RAR_VOL_ASK)==-1) + Cmd->Callback!=NULL && Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)==-1) { Cmd->DllError=ERAR_EOPEN; FailedOpen=true; @@ -123,6 +112,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman FailedOpen=true; break; } + #endif // RARDLL *NextNameW=0; } @@ -138,7 +128,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman Arc.CheckArc(true); #ifdef RARDLL if (Cmd->Callback!=NULL && - Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LONG)NextName,RAR_VOL_NOTIFY)==-1) + Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1) return(false); if (Cmd->ChangeVolProc!=NULL) { @@ -197,8 +187,13 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman } #ifdef SFX_MODULE DataIO->UnpArcSize=Arc.FileLength(); - DataIO->CurUnpRead=0; #endif + + // Reset the size of packed data read from current volume. It is used + // to display the total progress and preceding volumes are already + // compensated with ProcessedArcSize, so we need to reset this variable. + DataIO->CurUnpRead=0; + DataIO->PackedCRC=0xffffffff; // DataIO->SetFiles(&Arc,NULL); } |
