void CommandData::ParseArg(char *Arg,wchar *ArgW) { if (IsSwitch(*Arg) && !NoMoreSwitches) if (Arg[1]=='-') NoMoreSwitches=true; else ProcessSwitch(&Arg[1]); else if (*Command==0) { strncpy(Command,Arg,sizeof(Command)); if (ArgW!=NULL) strncpyw(CommandW,ArgW,sizeof(CommandW)/sizeof(CommandW[0])); if (toupper(*Command)=='S') { const char *SFXName=Command[1] ? Command+1:DefSFXName; if (PointToName(SFXName)!=SFXName || FileExist(SFXName)) strcpy(SFXModule,SFXName); else GetConfigName(SFXName,SFXModule,true); } #ifndef GUI *Command=toupper(*Command); if (*Command!='I' && *Command!='S') strupper(Command); #endif } else if (*ArcName==0) { strncpy(ArcName,Arg,sizeof(ArcName)); if (ArgW!=NULL) strncpyw(ArcNameW,ArgW,sizeof(ArcNameW)/sizeof(ArcNameW[0])); } else { int Length=strlen(Arg); char EndChar=Arg[Length-1]; char CmdChar=toupper(*Command); bool Add=strchr("AFUM",CmdChar)!=NULL; bool Extract=CmdChar=='X' || CmdChar=='E'; if ((IsDriveDiv(EndChar) || IsPathDiv(EndChar)) && !Add) strcpy(ExtrPath,Arg); else if ((Add || CmdChar=='T') && *Arg!='@') FileArgs->AddString(Arg); else { struct FindData FileData; bool Found=FindFile::FastFind(Arg,NULL,&FileData); if (!Found && *Arg=='@' && !IsWildcard(Arg)) { ReadTextFile(Arg+1,FileArgs,false,true,true,true,true); FileLists=true; } else if (Found && FileData.IsDir && Extract && *ExtrPath==0) { strcpy(ExtrPath,Arg); AddEndSlash(ExtrPath); } else FileArgs->AddString(Arg); } } }
SCAN_CODE ScanTree::FindProc(FindData *FD) { if (*CurMask==0) return SCAN_NEXT; bool FastFindFile=false; if (FindStack[Depth]==NULL) // No FindFile object for this depth yet. { bool Wildcards=IsWildcard(CurMask); // If we have a file name without wildcards, we can try to use // FastFind to optimize speed. For example, in Unix it results in // stat call instead of opendir/readdir/closedir. bool FindCode=!Wildcards && FindFile::FastFind(CurMask,FD,GetLinks); // Link check is important for NTFS, where links can have "Directory" // attribute, but we do not want to recurse to them in "get links" mode. bool IsDir=FindCode && FD->IsDir && (!GetLinks || !FD->IsLink); // SearchAll means that we'll use "*" mask for search, so we'll find // subdirectories and will be able to recurse into them. // We do not use "*" for directories at any level or for files // at top level in recursion mode. We always comrpess the entire directory // if folder wildcard is specified. bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS || FolderWildcards && Recurse!=RECURSE_DISABLE || Wildcards && Recurse==RECURSE_WILDCARDS || ScanEntireDisk && Recurse!=RECURSE_DISABLE); if (Depth==0) SearchAllInRoot=SearchAll; if (SearchAll || Wildcards) { // Create the new FindFile object for wildcard based search. FindStack[Depth]=new FindFile; wchar SearchMask[NM]; wcsncpyz(SearchMask,CurMask,ASIZE(SearchMask)); if (SearchAll) SetName(SearchMask,MASKALL,ASIZE(SearchMask)); FindStack[Depth]->SetMask(SearchMask); } else { // Either we failed to fast find or we found a file or we found // a directory in RECURSE_DISABLE mode, so we do not need to scan it. // We can return here and do not need to process further. // We need to process further only if we fast found a directory. if (!FindCode || !IsDir || Recurse==RECURSE_DISABLE) { // Return SCAN_SUCCESS if we found a file. SCAN_CODE RetCode=SCAN_SUCCESS; if (!FindCode) { // Return SCAN_ERROR if problem is more serious than just // "file not found". RetCode=FD->Error ? SCAN_ERROR:SCAN_NEXT; // If we failed to find an object, but our current mask is excluded, // we skip this object and avoid indicating an error. if (Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true)) RetCode=SCAN_NEXT; else { ErrHandler.OpenErrorMsg(ErrArcName,CurMask); // User asked to return RARX_NOFILES and not RARX_OPEN here. ErrHandler.SetErrorCode(RARX_NOFILES); } } // If we searched only for one file or directory in "fast find" // (without a wildcard) mode, let's set masks to zero, // so calling function will know that current mask is used // and next one must be read from mask list for next call. // It is not necessary for directories, because even in "fast find" // mode, directory recursing will quit by (Depth < 0) condition, // which returns SCAN_DONE to calling function. *CurMask=0; return RetCode; } // We found a directory using only FindFile::FastFind function. FastFindFile=true; } } if (!FastFindFile && !FindStack[Depth]->Next(FD,GetLinks)) { // We cannot find anything more in directory either because of // some error or just as result of all directory entries already read. bool Error=FD->Error; if (Error) ScanError(Error); wchar DirName[NM]; *DirName=0; // Going to at least one directory level higher. delete FindStack[Depth]; FindStack[Depth--]=NULL; while (Depth>=0 && FindStack[Depth]==NULL) Depth--; if (Depth < 0) { // Directories scanned both in normal and FastFindFile mode, // finally exit from scan here, by (Depth < 0) condition. if (Error) Errors++; return SCAN_DONE; } wchar *Slash=wcsrchr(CurMask,CPATHDIVIDER); if (Slash!=NULL) { wchar Mask[NM]; wcsncpyz(Mask,Slash,ASIZE(Mask)); if (Depth<SetAllMaskDepth) wcsncpyz(Mask+1,PointToName(OrigCurMask),ASIZE(Mask)-1); *Slash=0; wcsncpyz(DirName,CurMask,ASIZE(DirName)); wchar *PrevSlash=wcsrchr(CurMask,CPATHDIVIDER); if (PrevSlash==NULL) wcsncpyz(CurMask,Mask+1,ASIZE(CurMask)); else { *PrevSlash=0; wcsncatz(CurMask,Mask,ASIZE(CurMask)); } } if (GetDirs==SCAN_GETDIRSTWICE && FindFile::FastFind(DirName,FD,GetLinks) && FD->IsDir) { FD->Flags|=FDDF_SECONDDIR; return Error ? SCAN_ERROR:SCAN_SUCCESS; } return Error ? SCAN_ERROR:SCAN_NEXT; } // Link check is required for NTFS links, not for Unix. if (FD->IsDir && (!GetLinks || !FD->IsLink)) { // If we found the directory in top (Depth==0) directory // and if we are not in "fast find" (directory name only as argument) // or in recurse (SearchAll was set when opening the top directory) mode, // we do not recurse into this directory. We either return it by itself // or skip it. if (!FastFindFile && Depth==0 && !SearchAllInRoot) return GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT; // Let's check if directory name is excluded, so we do not waste // time searching in directory, which will be excluded anyway. if (Cmd!=NULL && (Cmd->ExclCheck(FD->Name,true,false,false) || Cmd->ExclDirByAttr(FD->FileAttr))) { // If we are here in "fast find" mode, it means that entire directory // specified in command line is excluded. Then we need to return // SCAN_DONE to go to next mask and avoid the infinite loop // in GetNext() function. Such loop would be possible in case of // SCAN_NEXT code and "rar a arc dir -xdir" command. return FastFindFile ? SCAN_DONE:SCAN_NEXT; } wchar Mask[NM]; wcsncpyz(Mask,FastFindFile ? MASKALL:PointToName(CurMask),ASIZE(Mask)); wcsncpyz(CurMask,FD->Name,ASIZE(CurMask)); if (wcslen(CurMask)+wcslen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1) { uiMsg(UIERROR_PATHTOOLONG,CurMask,SPATHDIVIDER,Mask); return SCAN_ERROR; } AddEndSlash(CurMask,ASIZE(CurMask)); wcsncatz(CurMask,Mask,ASIZE(CurMask)); Depth++; // We need to use OrigCurMask for depths less than SetAllMaskDepth // and "*" for depths equal or larger than SetAllMaskDepth. // It is important when "fast finding" directories at Depth > 0. // For example, if current directory is RootFolder and we compress // the following directories structure: // RootFolder // +--Folder1 // | +--Folder2 // | +--Folder3 // +--Folder4 // with 'rar a -r arcname Folder2' command, rar could add not only // Folder1\Folder2 contents, but also Folder1\Folder3 if we were using // "*" mask at all levels. We need to use "*" mask inside of Folder2, // but return to "Folder2" mask when completing scanning Folder2. // We can rewrite SearchAll expression above to avoid fast finding // directories at Depth > 0, but then 'rar a -r arcname Folder2' // will add the empty Folder2 and do not add its contents. if (FastFindFile) SetAllMaskDepth=Depth; } if (!FastFindFile && !CmpName(CurMask,FD->Name,MATCH_NAMES)) return SCAN_NEXT; return SCAN_SUCCESS; }
void CommandData::ProcessSwitch(char *Switch) { switch(toupper(Switch[0])) { case 'I': if (strnicomp(&Switch[1],"LOG",3)==0) { strncpy(LogName,Switch[4] ? Switch+4:DefLogName,sizeof(LogName)); break; } if (stricomp(&Switch[1],"SND")==0) { Sound=true; break; } if (stricomp(&Switch[1],"ERR")==0) { MsgStream=MSG_STDERR; break; } if (strnicomp(&Switch[1],"EML",3)==0) { strncpy(EmailTo,Switch[4] ? Switch+4:"@",sizeof(EmailTo)); EmailTo[sizeof(EmailTo)-1]=0; break; } if (stricomp(&Switch[1],"NUL")==0) { MsgStream=MSG_NULL; break; } if (toupper(Switch[1])=='D') { for (int I=2;Switch[I]!=0;I++) switch(toupper(Switch[I])) { case 'Q': MsgStream=MSG_ERRONLY; break; case 'C': DisableCopyright=true; break; case 'D': DisableDone=true; break; case 'P': DisablePercentage=true; break; } break; } if (stricomp(&Switch[1],"OFF")==0) { Shutdown=true; break; } break; case 'T': switch(toupper(Switch[1])) { case 'K': ArcTime=ARCTIME_KEEP; break; case 'L': ArcTime=ARCTIME_LATEST; break; case 'O': FileTimeBefore.SetAgeText(Switch+2); break; case 'N': FileTimeAfter.SetAgeText(Switch+2); break; case 'B': FileTimeBefore.SetIsoText(Switch+2); break; case 'A': FileTimeAfter.SetIsoText(Switch+2); 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 (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 (Switch[3]=='-') Mode=EXTTIME_NONE; switch(toupper(Switch[2])) { case 'M': xmtime=Mode; break; case 'C': xctime=Mode; break; case 'A': xatime=Mode; break; case 'R': xarctime=Mode; break; } } } break; case '-': Test=false; break; case 0: Test=true; break; default: BadSwitch(Switch); break; } break; case 'A': switch(toupper(Switch[1])) { case 'C': ClearArc=true; break; case 'D': AppendArcNameToPath=true; break; case 'G': if (Switch[2]=='-' && Switch[3]==0) GenerateArcName=0; else { GenerateArcName=true; strncpy(GenerateMask,Switch+2,sizeof(GenerateMask)); } break; case 'N': //reserved for archive name break; case 'O': AddArcOnly=true; break; case 'P': strcpy(ArcPath,Switch+2); break; case 'S': SyncFiles=true; break; } break; case 'D': if (Switch[2]==0) switch(toupper(Switch[1])) { case 'S': DisableSortSolid=true; break; case 'H': OpenShared=true; break; case 'F': DeleteFiles=true; break; } break; case 'O': switch(toupper(Switch[1])) { case '+': Overwrite=OVERWRITE_ALL; break; case '-': Overwrite=OVERWRITE_NONE; break; case 'W': ProcessOwners=true; break; #ifdef SAVE_LINKS case 'L': SaveLinks=true; break; #endif #ifdef _WIN_32 case 'S': SaveStreams=true; break; case 'C': SetCompressedAttr=true; break; #endif default : BadSwitch(Switch); break; } break; case 'R': switch(toupper(Switch[1])) { case 0: Recurse=RECURSE_ALWAYS; break; case '-': Recurse=0; break; case '0': Recurse=RECURSE_WILDCARDS; break; case 'I': { Priority=atoi(Switch+2); char *ChPtr=strchr(Switch+2,':'); if (ChPtr!=NULL) { SleepTime=atoi(ChPtr+1); InitSystemOptions(SleepTime); } SetPriority(Priority); } break; } break; case 'Y': AllYes=true; break; case 'N': case 'X': if (Switch[1]!=0) { StringList *Args=toupper(Switch[0])=='N' ? InclArgs:ExclArgs; if (Switch[1]=='@' && !IsWildcard(Switch)) ReadTextFile(Switch+2,Args,false,true,true,true,true); else Args->AddString(Switch+1); } break; case 'E': switch(toupper(Switch[1])) { case 'P': switch(Switch[2]) { case 0: ExclPath=EXCL_SKIPWHOLEPATH; break; case '1': ExclPath=EXCL_BASEPATH; break; case '2': ExclPath=EXCL_SAVEFULLPATH; break; case '3': ExclPath=EXCL_ABSPATH; break; } break; case 'D': ExclEmptyDir=true; break; case 'E': ProcessEA=false; break; case 'N': NoEndBlock=true; break; default: if (Switch[1]=='+') { InclFileAttr=GetExclAttr(&Switch[2]); InclAttrSet=true; } else ExclFileAttr=GetExclAttr(&Switch[1]); break; } break; case 'P': if (Switch[1]==0) { GetPassword(PASSWORD_GLOBAL,NULL,Password,sizeof(Password)); eprintf("\n"); } else strncpy(Password,Switch+1,sizeof(Password)); break; case 'H': if (toupper(Switch[1])=='P') { EncryptHeaders=true; if (Switch[2]!=0) strncpy(Password,Switch+2,sizeof(Password)); else if (*Password==0) { GetPassword(PASSWORD_GLOBAL,NULL,Password,sizeof(Password)); eprintf("\n"); } } break; case 'Z': strncpy(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",sizeof(CommentFile)); break; case 'M': switch(toupper(Switch[1])) { case 'C': { char *Str=Switch+2; if (*Str=='-') for (int I=0;I<sizeof(FilterModes)/sizeof(FilterModes[0]);I++) FilterModes[I].State=FILTER_DISABLE; else while (*Str) { int Param1=0,Param2=0; FilterState State=FILTER_AUTO; FilterType Type=FILTER_NONE; if (isdigit(*Str)) { Param1=atoi(Str); while (isdigit(*Str)) Str++; } if (*Str==':' && isdigit(Str[1])) { Param2=atoi(++Str); while (isdigit(*Str)) Str++; } switch(toupper(*(Str++))) { case 'T': Type=FILTER_PPM; break; case 'E': Type=FILTER_E8; break; 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 'L': Type=FILTER_UPCASETOLOW; break; } if (*Str=='+' || *Str=='-') State=*(Str++)=='+' ? FILTER_FORCE:FILTER_DISABLE; FilterModes[Type].State=State; FilterModes[Type].Param1=Param1; FilterModes[Type].Param2=Param2; } } break; case 'M': break; case 'D': { if ((WinSize=atoi(&Switch[2]))==0) WinSize=0x10000<<(toupper(Switch[2])-'A'); else WinSize*=1024; if (!CheckWinSize()) BadSwitch(Switch); } break; case 'S': { char *Names=Switch+2,DefNames[512]; if (*Names==0) { strcpy(DefNames,DefaultStoreList); Names=DefNames; } while (*Names!=0) { char *End=strchr(Names,';'); if (End!=NULL) *End=0; if (*Names=='.') Names++; char Mask[NM]; if (strpbrk(Names,"*?.")==NULL) sprintf(Mask,"*.%s",Names); else strcpy(Mask,Names); StoreArgs->AddString(Mask); if (End==NULL) break; Names=End+1; } } break; default: Method=Switch[1]-'0'; if (Method>5 || Method<0) BadSwitch(Switch); break; } break; case 'V': switch(toupper(Switch[1])) { #ifdef _WIN_32 case 'D': EraseDisk=true; break; #endif case 'N': OldNumbering=true; break; case 'P': VolumePause=true; break; case 'E': if (toupper(Switch[2])=='R') VersionControl=atoi(Switch+3)+1; break; case '-': VolSize=0; break; default: { Int64 NewVolSize=atoil(&Switch[1]); if (NewVolSize==0) NewVolSize=INT64ERR; else switch (Switch[strlen(Switch)-1]) { case 'f': case 'F': switch(int64to32(NewVolSize)) { case 360: NewVolSize=362496; break; case 720: NewVolSize=730112; break; case 1200: NewVolSize=1213952; break; case 1440: NewVolSize=1457664; break; case 2880: NewVolSize=2915328; break; } break; case 'k': NewVolSize*=1024; break; case 'm': NewVolSize*=1024*1024; break; case 'M': NewVolSize*=1000*1000; break; case 'g': NewVolSize*=1024*1024; NewVolSize*=1024; break; case 'G': NewVolSize*=1000*1000; NewVolSize*=1000; break; case 'b': case 'B': break; default: NewVolSize*=1000; break; } if (VolSize==0) VolSize=NewVolSize; else NextVolSizes.Push(NewVolSize); } break; } break; case 'F': if (Switch[1]==0) FreshFiles=true; break; case 'U': if (Switch[1]==0) UpdateFiles=true; break; case 'W': strncpy(TempPath,&Switch[1],sizeof(TempPath)-1); AddEndSlash(TempPath); break; case 'S': if (strnicomp(Switch,"SFX",3)==0) { const char *SFXName=Switch[3] ? Switch+3:DefSFXName; if (PointToName(SFXName)!=SFXName || FileExist(SFXName)) strcpy(SFXModule,SFXName); else GetConfigName(SFXName,SFXModule,true); } if (isdigit(Switch[1])) { Solid|=SOLID_COUNT; SolidCount=atoi(&Switch[1]); } else switch(toupper(Switch[1])) { case 0: Solid|=SOLID_NORMAL; break; case '-': Solid=SOLID_NONE; break; case 'E': Solid|=SOLID_FILEEXT; break; case 'V': Solid|=Switch[2]=='-' ? SOLID_VOLUME_DEPENDENT:SOLID_VOLUME_INDEPENDENT; break; case 'D': Solid|=SOLID_VOLUME_DEPENDENT; break; } break; case 'C': if (Switch[2]==0) switch(toupper(Switch[1])) { case '-': DisableComment=true; break; case 'U': ConvertNames=NAMES_UPPERCASE; break; case 'L': ConvertNames=NAMES_LOWERCASE; break; } break; case 'K': switch(toupper(Switch[1])) { case 'B': KeepBroken=true; break; case 0: Lock=true; break; } break; #ifndef GUI case '?' : OutHelp(); break; #endif default : BadSwitch(Switch); break; } }
void CommandData::ProcessSwitch(char *Switch,wchar *SwitchW) { bool WidePresent=SwitchW!=NULL && *SwitchW!=0; // If 'true', SwitchW is not empty. switch(etoupper(Switch[0])) { case 'I': if (strnicomp(&Switch[1],"LOG",3)==0) { strncpyz(LogName,Switch[4] ? Switch+4:DefLogName,ASIZE(LogName)); break; } if (stricomp(&Switch[1],"SND")==0) { Sound=true; break; } if (stricomp(&Switch[1],"ERR")==0) { MsgStream=MSG_STDERR; break; } if (strnicomp(&Switch[1],"EML",3)==0) { strncpyz(EmailTo,Switch[4] ? Switch+4:"@",ASIZE(EmailTo)); EmailTo[sizeof(EmailTo)-1]=0; break; } if (stricomp(&Switch[1],"NUL")==0) { MsgStream=MSG_NULL; break; } if (etoupper(Switch[1])=='D') { for (int I=2;Switch[I]!=0;I++) switch(etoupper(Switch[I])) { case 'Q': MsgStream=MSG_ERRONLY; break; case 'C': DisableCopyright=true; break; case 'D': DisableDone=true; break; case 'P': DisablePercentage=true; break; } break; } if (stricomp(&Switch[1],"OFF")==0) { Shutdown=true; break; } break; case 'T': switch(etoupper(Switch[1])) { case 'K': ArcTime=ARCTIME_KEEP; break; case 'L': ArcTime=ARCTIME_LATEST; break; case 'O': FileTimeBefore.SetAgeText(Switch+2); break; case 'N': FileTimeAfter.SetAgeText(Switch+2); break; case 'B': FileTimeBefore.SetIsoText(Switch+2); break; case 'A': FileTimeAfter.SetIsoText(Switch+2); 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 (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 (Switch[3]=='-') Mode=EXTTIME_NONE; switch(etoupper(Switch[2])) { case 'M': xmtime=Mode; break; case 'C': xctime=Mode; break; case 'A': xatime=Mode; break; case 'R': xarctime=Mode; break; } } } break; case '-': Test=false; break; case 0: Test=true; break; default: BadSwitch(Switch); break; } break; case 'A': switch(etoupper(Switch[1])) { case 'C': ClearArc=true; break; case 'D': AppendArcNameToPath=true; break; case 'I': IgnoreGeneralAttr=true; break; case 'N': //reserved for archive name break; case 'O': AddArcOnly=true; break; case 'P': strcpy(ArcPath,Switch+2); if (WidePresent) wcscpy(ArcPathW,SwitchW+2); break; case 'S': SyncFiles=true; break; default: BadSwitch(Switch); break; } break; case 'D': if (Switch[2]==0) switch(etoupper(Switch[1])) { case 'S': DisableSortSolid=true; break; case 'H': OpenShared=true; break; case 'F': DeleteFiles=true; break; } break; case 'O': switch(etoupper(Switch[1])) { case '+': Overwrite=OVERWRITE_ALL; break; case '-': Overwrite=OVERWRITE_NONE; break; case 0: Overwrite=OVERWRITE_FORCE_ASK; break; case 'R': Overwrite=OVERWRITE_AUTORENAME; break; case 'W': ProcessOwners=true; break; #ifdef SAVE_LINKS case 'L': SaveLinks=true; break; #endif #ifdef _WIN_ALL case 'S': SaveStreams=true; break; case 'C': SetCompressedAttr=true; break; #endif default : BadSwitch(Switch); break; } break; case 'R': switch(etoupper(Switch[1])) { case 0: Recurse=RECURSE_ALWAYS; break; case '-': Recurse=RECURSE_DISABLE; break; case '0': Recurse=RECURSE_WILDCARDS; break; #ifndef _WIN_CE case 'I': { Priority=atoi(Switch+2); char *ChPtr=strchr(Switch+2,':'); if (ChPtr!=NULL) { SleepTime=atoi(ChPtr+1); InitSystemOptions(SleepTime); } SetPriority(Priority); } break; #endif } break; case 'Y': AllYes=true; break; case 'N': case 'X': if (Switch[1]!=0) { StringList *Args=etoupper(Switch[0])=='N' ? InclArgs.get():ExclArgs.get(); if (Switch[1]=='@' && !IsWildcard(Switch)) { RAR_CHARSET Charset=FilelistCharset; #if defined(_WIN_ALL) && !defined(GUI) // for compatibility reasons we use OEM encoding // in Win32 console version by default if (Charset==RCH_DEFAULT) Charset=RCH_OEM; #endif ReadTextFile(Switch+2,NULL,Args,false,true,Charset,true,true,true); } else Args->AddString(Switch+1); } break; case 'E': switch(etoupper(Switch[1])) { case 'P': switch(Switch[2]) { case 0: ExclPath=EXCL_SKIPWHOLEPATH; break; case '1': ExclPath=EXCL_BASEPATH; break; case '2': ExclPath=EXCL_SAVEFULLPATH; break; case '3': ExclPath=EXCL_ABSPATH; break; } break; case 'E': ProcessEA=false; break; case 'N': NoEndBlock=true; break; default: if (Switch[1]=='+') { InclFileAttr=GetExclAttr(&Switch[2]); InclAttrSet=true; } else ExclFileAttr=GetExclAttr(&Switch[1]); break; } break; case 'P': if (Switch[1]==0) { GetPassword(PASSWORD_GLOBAL,NULL,NULL,Password,ASIZE(Password)); eprintf("\n"); } else { CharToWide(Switch+1,Password,ASIZE(Password)); Password[ASIZE(Password)-1]=0; } break; case 'H': if (etoupper(Switch[1])=='P') { EncryptHeaders=true; if (Switch[2]!=0) { CharToWide(Switch+2,Password,ASIZE(Password)); Password[ASIZE(Password)-1]=0; } else if (*Password==0) { GetPassword(PASSWORD_GLOBAL,NULL,NULL,Password,ASIZE(Password)); eprintf("\n"); } } break; case 'Z': if (Switch[1]==0 && (!WidePresent || SwitchW[1]==0)) { // If comment file is not specified, we read data from stdin. strcpy(CommentFile,"stdin"); } strncpyz(CommentFile,Switch+1,ASIZE(CommentFile)); if (WidePresent) wcsncpyz(CommentFileW,SwitchW+1,ASIZE(CommentFileW)); break; case 'M': switch(etoupper(Switch[1])) { case 'C': { char *Str=Switch+2; if (*Str=='-') for (int I=0;I<sizeof(FilterModes)/sizeof(FilterModes[0]);I++) FilterModes[I].State=FILTER_DISABLE; else while (*Str) { int Param1=0,Param2=0; FilterState State=FILTER_AUTO; FilterType Type=FILTER_NONE; if (IsDigit(*Str)) { Param1=atoi(Str); while (IsDigit(*Str)) Str++; } if (*Str==':' && IsDigit(Str[1])) { Param2=atoi(++Str); while (IsDigit(*Str)) Str++; } switch(etoupper(*(Str++))) { case 'T': Type=FILTER_PPM; break; case 'E': Type=FILTER_E8; break; 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 'L': Type=FILTER_UPCASETOLOW; break; } if (*Str=='+' || *Str=='-') State=*(Str++)=='+' ? FILTER_FORCE:FILTER_DISABLE; FilterModes[Type].State=State; FilterModes[Type].Param1=Param1; FilterModes[Type].Param2=Param2; } } break; case 'M': break; case 'D': { if ((WinSize=atoi(&Switch[2]))==0) WinSize=0x10000<<(etoupper(Switch[2])-'A'); else WinSize*=1024; if (!CheckWinSize()) BadSwitch(Switch); } break; case 'S': { char *Names=Switch+2,DefNames[512]; if (*Names==0) { strcpy(DefNames,DefaultStoreList); Names=DefNames; } while (*Names!=0) { char *End=strchr(Names,';'); if (End!=NULL) *End=0; if (*Names=='.') Names++; char Mask[NM]; if (strpbrk(Names,"*?.")==NULL) sprintf(Mask,"*.%s",Names); else strcpy(Mask,Names); StoreArgs->AddString(Mask); if (End==NULL) break; Names=End+1; } } break; #ifdef PACK_SMP case 'T': Threads=atoi(Switch+2); if (Threads>16) BadSwitch(Switch); else { } break; #endif default: Method=Switch[1]-'0'; if (Method>5 || Method<0) BadSwitch(Switch); break; } break; case 'V': switch(etoupper(Switch[1])) { case 'N': OldNumbering=true; break; case 'P': VolumePause=true; break; case 'E': if (etoupper(Switch[2])=='R') VersionControl=atoi(Switch+3)+1; break; case '-': VolSize=0; break; default: { int64 NewVolSize=atoil(&Switch[1]); if (NewVolSize==0) NewVolSize=INT64NDF; // Autodetecting volume size. else switch (Switch[strlen(Switch)-1]) { case 'f': case 'F': switch(NewVolSize) { case 360: NewVolSize=362496; break; case 720: NewVolSize=730112; break; case 1200: NewVolSize=1213952; break; case 1440: NewVolSize=1457664; break; case 2880: NewVolSize=2915328; break; } break; case 'k': NewVolSize*=1024; break; case 'm': NewVolSize*=1024*1024; break; case 'M': NewVolSize*=1000*1000; break; case 'g': NewVolSize*=1024*1024; NewVolSize*=1024; break; case 'G': NewVolSize*=1000*1000; NewVolSize*=1000; break; case 'b': case 'B': break; default: NewVolSize*=1000; break; } if (VolSize==0) VolSize=NewVolSize; else NextVolSizes.Push(NewVolSize); } break; } break; case 'F': if (Switch[1]==0) FreshFiles=true; else BadSwitch(Switch); break; case 'U': if (Switch[1]==0) UpdateFiles=true; else BadSwitch(Switch); break; case 'W': strncpyz(TempPath,&Switch[1],ASIZE(TempPath)); AddEndSlash(TempPath); break; case 'S': if (IsDigit(Switch[1])) { Solid|=SOLID_COUNT; SolidCount=atoi(&Switch[1]); } else switch(etoupper(Switch[1])) { case 0: Solid|=SOLID_NORMAL; break; case '-': Solid=SOLID_NONE; break; case 'E': Solid|=SOLID_FILEEXT; break; case 'V': Solid|=Switch[2]=='-' ? SOLID_VOLUME_DEPENDENT:SOLID_VOLUME_INDEPENDENT; break; case 'D': Solid|=SOLID_VOLUME_DEPENDENT; break; case 'L': if (IsDigit(Switch[2])) FileSizeLess=atoil(Switch+2); break; case 'M': if (IsDigit(Switch[2])) FileSizeMore=atoil(Switch+2); break; case 'C': { // Switch is already found bad, avoid reporting it several times. bool AlreadyBad=false; RAR_CHARSET rch=RCH_DEFAULT; switch(etoupper(Switch[2])) { case 'A': rch=RCH_ANSI; break; case 'O': rch=RCH_OEM; break; case 'U': rch=RCH_UNICODE; break; default : BadSwitch(Switch); AlreadyBad=true; break; }; if (!AlreadyBad) if (Switch[3]==0) CommentCharset=FilelistCharset=rch; else for (int I=3;Switch[I]!=0 && !AlreadyBad;I++) switch(etoupper(Switch[I])) { case 'C': CommentCharset=rch; break; case 'L': FilelistCharset=rch; break; default: BadSwitch(Switch); AlreadyBad=true; break; } } break; } break; case 'C': if (Switch[2]==0) switch(etoupper(Switch[1])) { case '-': DisableComment=true; break; case 'U': ConvertNames=NAMES_UPPERCASE; break; case 'L': ConvertNames=NAMES_LOWERCASE; break; } break; case 'K': switch(etoupper(Switch[1])) { case 'B': KeepBroken=true; break; case 0: Lock=true; break; } break; #ifndef GUI case '?' : OutHelp(); break; #endif default : BadSwitch(Switch); break; } }
void CommandData::ParseArg(char *Arg,wchar *ArgW) { if (IsSwitch(*Arg) && !NoMoreSwitches) if (Arg[1]=='-') NoMoreSwitches=true; else ProcessSwitch(Arg+1,(ArgW!=NULL && *ArgW!=0 ? ArgW+1:NULL)); else if (*Command==0) { strncpyz(Command,Arg,ASIZE(Command)); if (ArgW!=NULL) wcsncpy(CommandW,ArgW,ASIZE(CommandW)); #ifndef GUI *Command=etoupper(*Command); // 'I' and 'S' commands can contain case sensitive strings after // the first character, so we must not modify their case. // 'S' can contain SFX name, which case is important in Unix. if (*Command!='I' && *Command!='S') strupper(Command); #endif } else if (*ArcName==0 && *ArcNameW==0) { strncpyz(ArcName,Arg,ASIZE(ArcName)); if (ArgW!=NULL) wcsncpyz(ArcNameW,ArgW,ASIZE(ArcNameW)); } else { bool EndSeparator; // If last character is the path separator. if (ArgW!=NULL) { size_t Length=wcslen(ArgW); wchar EndChar=Length==0 ? 0:ArgW[Length-1]; EndSeparator=IsDriveDiv(EndChar) || IsPathDiv(EndChar); } else { size_t Length=strlen(Arg); char EndChar=Length==0 ? 0:Arg[Length-1]; EndSeparator=IsDriveDiv(EndChar) || IsPathDiv(EndChar); } char CmdChar=etoupper(*Command); bool Add=strchr("AFUM",CmdChar)!=NULL; bool Extract=CmdChar=='X' || CmdChar=='E'; if (EndSeparator && !Add) { strncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); if (ArgW!=NULL) wcsncpyz(ExtrPathW,ArgW,ASIZE(ExtrPathW)); } else if ((Add || CmdChar=='T') && *Arg!='@') FileArgs->AddString(Arg,ArgW); else { FindData FileData; bool Found=FindFile::FastFind(Arg,ArgW,&FileData); if (!Found && *Arg=='@' && !IsWildcard(Arg,ArgW)) { FileLists=true; RAR_CHARSET Charset=FilelistCharset; #if defined(_WIN_ALL) && !defined(GUI) // for compatibility reasons we use OEM encoding // in Win32 console version by default if (Charset==RCH_DEFAULT) Charset=RCH_OEM; #endif wchar *WideArgName=(ArgW!=NULL && *ArgW!=0 ? ArgW+1:NULL); ReadTextFile(Arg+1,WideArgName,FileArgs.get(),false,true,Charset,true,true,true); } else if (Found && FileData.IsDir && Extract && *ExtrPath==0 && *ExtrPathW==0) { strncpyz(ExtrPath,Arg,ASIZE(ExtrPath)-1); AddEndSlash(ExtrPath); if (ArgW!=NULL) { wcsncpyz(ExtrPathW,ArgW,ASIZE(ExtrPathW)-1); AddEndSlash(ExtrPathW); } } else FileArgs->AddString(Arg,ArgW); } } }
void CommandData::ParseArg(wchar *Arg) { if (IsSwitch(*Arg) && !NoMoreSwitches) if (Arg[1]=='-' && Arg[2]==0) NoMoreSwitches=true; else ProcessSwitch(Arg+1); else if (*Command==0) { wcsncpyz(Command,Arg,ASIZE(Command)); *Command=toupperw(*Command); // 'I' and 'S' commands can contain case sensitive strings after // the first character, so we must not modify their case. // 'S' can contain SFX name, which case is important in Unix. if (*Command!='I' && *Command!='S') wcsupper(Command); } else if (*ArcName==0) wcsncpyz(ArcName,Arg,ASIZE(ArcName)); else { // Check if last character is the path separator. size_t Length=wcslen(Arg); wchar EndChar=Length==0 ? 0:Arg[Length-1]; bool EndSeparator=IsDriveDiv(EndChar) || IsPathDiv(EndChar); wchar CmdChar=toupperw(*Command); bool Add=wcschr(L"AFUM",CmdChar)!=NULL; bool Extract=CmdChar=='X' || CmdChar=='E'; if (EndSeparator && !Add) wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); else if ((Add || CmdChar=='T') && (*Arg!='@' || ListMode==RCLM_REJECT_LISTS)) FileArgs.AddString(Arg); else { FindData FileData; bool Found=FindFile::FastFind(Arg,&FileData); if ((!Found || ListMode==RCLM_ACCEPT_LISTS) && ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg)) { FileLists=true; ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true); } else if (Found && FileData.IsDir && Extract && *ExtrPath==0) { wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); AddEndSlash(ExtrPath,ASIZE(ExtrPath)); } else FileArgs.AddString(Arg); } } }
bool CommandData::ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode) { char *Name=ConvertPath(CheckName,NULL); char FullName[NM]; char CurMask[NM+1]; // We reserve the space to append "*" to mask. *FullName=0; Args->Rewind(); while (Args->GetString(CurMask,ASIZE(CurMask)-1)) { char *LastMaskChar=PointToLastChar(CurMask); bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only. if (Dir) { // CheckName is a directory. if (DirMask) { // We process the directory and have the directory exclusion mask. // So let's convert "mask\" to "mask" and process it normally. *LastMaskChar=0; } else { // If mask has wildcards in name part and does not have the trailing // '\' character, we cannot use it for directories. if (IsWildcard(PointToName(CurMask))) continue; } } else { // If we process a file inside of directory excluded by "dirmask\". // we want to exclude such file too. So we convert "dirmask\" to // "dirmask\*". It is important for operations other than archiving. // When archiving, directory matched by "dirmask\" is excluded // from further scanning. if (DirMask) strcat(CurMask,"*"); } #ifndef SFX_MODULE if (CheckFullPath && IsFullPath(CurMask)) { // We do not need to do the special "*\" processing here, because // onlike the "else" part of this "if", now we convert names to full // format, so they all include the path, which is matched by "*\" // correctly. Moreover, removing "*\" from mask would break // the comparison, because now all names have the path. if (*FullName==0) ConvertNameToFull(CheckName,FullName); if (CmpName(CurMask,FullName,MatchMode)) return(true); } else #endif { char NewName[NM+2],*CurName=Name; if (CurMask[0]=='*' && IsPathDiv(CurMask[1])) { // We want "*\name" to match 'name' not only in subdirectories, // but also in the current directory. We convert the name // from 'name' to '.\name' to be matched by "*\" part even if it is // in current directory. NewName[0]='.'; NewName[1]=CPATHDIVIDER; strncpyz(NewName+2,Name,ASIZE(NewName)-2); CurName=NewName; } if (CmpName(ConvertPath(CurMask,NULL),CurName,MatchMode)) return(true); } } return(false); }
int ScanTree::FindProc(FindData *FindData) { if (*CurMask==0) return(SCAN_NEXT); FastFindFile=false; if (FindStack[Depth]==NULL) { bool Wildcards=IsWildcard(CurMask,CurMaskW); 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); if (Depth==0) SearchAllInRoot=SearchAll; if (SearchAll || Wildcards) { FindStack[Depth]=new FindFile; char SearchMask[NM]; strcpy(SearchMask,CurMask); if (SearchAll) strcpy(PointToName(SearchMask),MASKALL); FindStack[Depth]->SetMask(SearchMask); if (*CurMaskW) { wchar SearchMaskW[NM]; strcpyw(SearchMaskW,CurMaskW); if (SearchAll) strcpyw(PointToName(SearchMaskW),MASKALLW); FindStack[Depth]->SetMaskW(SearchMaskW); } } else { FastFindFile=true; if (!FindCode) { if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true)) return(SCAN_NEXT); ErrHandler.OpenErrorMsg(ErrArcName,CurMask); return(FindData->Error ? SCAN_ERROR:SCAN_NEXT); } } } if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks)) { bool Error=FindData->Error; #ifdef _WIN_32 if (Error) { // Do not display an error if we cannot scan contents of reparse // point. Vista contains a lot of reparse (or junction) points, // which are not accessible. if ((FindData->FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0) Error=false; // Do not display an error if we cannot scan contents of // "System Volume Information" folder. Normally it is not accessible. if (strstr(CurMask,"System Volume Information\\")!=NULL) Error=false; } #endif if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true)) Error=false; #ifndef SILENT if (Error) { Log(NULL,St(MScanError),CurMask); } #endif char DirName[NM]; wchar DirNameW[NM]; *DirName=0; *DirNameW=0; delete FindStack[Depth]; FindStack[Depth--]=NULL; while (Depth>=0 && FindStack[Depth]==NULL) Depth--; if (Depth < 0) { if (Error) Errors++; return(SCAN_DONE); } char *Slash=strrchrd(CurMask,CPATHDIVIDER); if (Slash!=NULL) { char Mask[NM]; strcpy(Mask,Slash); if (Depth<SetAllMaskDepth) strcpy(Mask+1,PointToName(OrigCurMask)); *Slash=0; strcpy(DirName,CurMask); char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER); if (PrevSlash==NULL) strcpy(CurMask,Mask+1); else strcpy(PrevSlash,Mask); } if (*CurMaskW!=0) { wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER); if (Slash!=NULL) { wchar Mask[NM]; strcpyw(Mask,Slash); if (Depth<SetAllMaskDepth) strcpyw(Mask+1,PointToName(OrigCurMaskW)); *Slash=0; strcpyw(DirNameW,CurMaskW); wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER); if (PrevSlash==NULL) strcpyw(CurMaskW,Mask+1); else strcpyw(PrevSlash,Mask); } #ifndef _WIN_CE if (LowAscii(CurMaskW)) *CurMaskW=0; #endif } if (GetDirs==SCAN_GETDIRSTWICE && FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir) return(Error ? SCAN_ERROR:SCAN_SUCCESS); return(Error ? SCAN_ERROR:SCAN_NEXT); } if (FindData->IsDir) { if (!FastFindFile && Depth==0 && !SearchAllInRoot) return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT); // if (GetDirs==SCAN_GETCURDIRS && Depth==0 && !SearchAllInRoot) // return(SCAN_SUCCESS); char Mask[NM]; bool MaskAll=FastFindFile; // bool MaskAll=CmpName(CurMask,FindData->Name,MATCH_NAMES); strcpy(Mask,MaskAll ? MASKALL:PointToName(CurMask)); strcpy(CurMask,FindData->Name); if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1) { #ifndef SILENT Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask); Log(NULL,St(MPathTooLong)); #endif return(SCAN_ERROR); } AddEndSlash(CurMask); strcat(CurMask,Mask); if (*CurMaskW && *FindData->NameW==0) CharToWide(FindData->Name,FindData->NameW); if (*FindData->NameW!=0) { wchar Mask[NM]; if (FastFindFile) strcpyw(Mask,MASKALLW); else if (*CurMaskW) strcpyw(Mask,PointToName(CurMaskW)); else CharToWide(PointToName(CurMask),Mask); strcpyw(CurMaskW,FindData->NameW); AddEndSlash(CurMaskW); strcatw(CurMaskW,Mask); } Depth++; if (MaskAll) SetAllMaskDepth=Depth; } if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES)) return(SCAN_NEXT); return(SCAN_SUCCESS); }
void CommandData::ProcessSwitch(const wchar *Switch) { switch(toupperw(Switch[0])) { case '@': ListMode=Switch[1]=='+' ? RCLM_ACCEPT_LISTS:RCLM_REJECT_LISTS; break; case 'A': switch(toupperw(Switch[1])) { case 'C': ClearArc=true; break; case 'D': AppendArcNameToPath=true; break; #ifndef SFX_MODULE case 'G': if (Switch[2]=='-' && Switch[3]==0) GenerateArcName=0; else { GenerateArcName=true; wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask)); } break; #endif case 'I': IgnoreGeneralAttr=true; break; case 'N': // Reserved for archive name. break; case 'O': AddArcOnly=true; break; case 'P': wcscpy(ArcPath,Switch+2); break; case 'S': SyncFiles=true; break; default: BadSwitch(Switch); break; } break; case 'C': if (Switch[2]==0) switch(toupperw(Switch[1])) { case '-': DisableComment=true; break; case 'U': ConvertNames=NAMES_UPPERCASE; break; case 'L': ConvertNames=NAMES_LOWERCASE; break; } break; case 'D': if (Switch[2]==0) switch(toupperw(Switch[1])) { case 'S': DisableSortSolid=true; break; case 'H': OpenShared=true; break; case 'F': DeleteFiles=true; break; } break; case 'E': switch(toupperw(Switch[1])) { case 'P': switch(Switch[2]) { case 0: ExclPath=EXCL_SKIPWHOLEPATH; break; case '1': ExclPath=EXCL_BASEPATH; break; case '2': ExclPath=EXCL_SAVEFULLPATH; break; case '3': ExclPath=EXCL_ABSPATH; break; } break; default: if (Switch[1]=='+') { InclFileAttr|=GetExclAttr(Switch+2); InclAttrSet=true; } else ExclFileAttr|=GetExclAttr(Switch+1); break; } break; case 'F': if (Switch[1]==0) FreshFiles=true; else BadSwitch(Switch); break; case 'H': switch (toupperw(Switch[1])) { case 'P': EncryptHeaders=true; if (Switch[2]!=0) { Password.Set(Switch+2); cleandata((void *)Switch,wcslen(Switch)*sizeof(Switch[0])); } else if (!Password.IsSet()) { uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password); eprintf(L"\n"); } break; default : BadSwitch(Switch); break; } break; case 'I': if (wcsnicomp(Switch+1,L"LOG",3)==0) { wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName)); break; } if (wcsicomp(Switch+1,L"SND")==0) { Sound=true; break; } if (wcsicomp(Switch+1,L"ERR")==0) { MsgStream=MSG_STDERR; // Set it immediately when parsing the command line, so it also // affects messages issued while parsing the command line. SetConsoleMsgStream(MSG_STDERR); break; } if (wcsnicomp(Switch+1,L"EML",3)==0) { wcsncpyz(EmailTo,Switch[4]!=0 ? Switch+4:L"@",ASIZE(EmailTo)); break; } if (wcsicomp(Switch+1,L"M")==0) { MoreInfo=true; break; } if (wcsicomp(Switch+1,L"NUL")==0) { MsgStream=MSG_NULL; SetConsoleMsgStream(MSG_NULL); break; } if (toupperw(Switch[1])=='D') { for (uint I=2;Switch[I]!=0;I++) switch(toupperw(Switch[I])) { case 'Q': MsgStream=MSG_ERRONLY; SetConsoleMsgStream(MSG_ERRONLY); break; case 'C': DisableCopyright=true; break; case 'D': DisableDone=true; break; case 'P': DisablePercentage=true; break; } break; } if (wcsnicomp(Switch+1,L"OFF",3)==0) { switch(Switch[4]) { case 0: case '1': Shutdown=POWERMODE_OFF; break; case '2': Shutdown=POWERMODE_HIBERNATE; break; case '3': Shutdown=POWERMODE_SLEEP; break; case '4': Shutdown=POWERMODE_RESTART; break; } break; } if (wcsicomp(Switch+1,L"VER")==0) { PrintVersion=true; break; } break; case 'K': switch(toupperw(Switch[1])) { case 'B': KeepBroken=true; break; case 0: Lock=true; break; } break; case 'M': switch(toupperw(Switch[1])) { case 'C': { const wchar *Str=Switch+2; if (*Str=='-') for (uint I=0;I<ASIZE(FilterModes);I++) FilterModes[I].State=FILTER_DISABLE; else while (*Str!=0) { int Param1=0,Param2=0; FilterState State=FILTER_AUTO; FilterType Type=FILTER_NONE; if (IsDigit(*Str)) { Param1=atoiw(Str); while (IsDigit(*Str)) Str++; } if (*Str==':' && IsDigit(Str[1])) { Param2=atoiw(++Str); while (IsDigit(*Str)) Str++; } switch(toupperw(*(Str++))) { case 'T': Type=FILTER_PPM; break; case 'E': Type=FILTER_E8; break; 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=='-') State=*(Str++)=='+' ? FILTER_FORCE:FILTER_DISABLE; FilterModes[Type].State=State; FilterModes[Type].Param1=Param1; FilterModes[Type].Param2=Param2; } } break; case 'M': break; case 'D': break; case 'S': { wchar StoreNames[1024]; wcsncpyz(StoreNames,(Switch[2]==0 ? DefaultStoreList:Switch+2),ASIZE(StoreNames)); wchar *Names=StoreNames; while (*Names!=0) { wchar *End=wcschr(Names,';'); if (End!=NULL) *End=0; if (*Names=='.') Names++; wchar Mask[NM]; if (wcspbrk(Names,L"*?.")==NULL) swprintf(Mask,ASIZE(Mask),L"*.%ls",Names); else wcsncpyz(Mask,Names,ASIZE(Mask)); StoreArgs.AddString(Mask); if (End==NULL) break; Names=End+1; } } break; #ifdef RAR_SMP case 'T': Threads=atoiw(Switch+2); if (Threads>MaxPoolThreads || Threads<1) BadSwitch(Switch); else { } break; #endif default: Method=Switch[1]-'0'; if (Method>5 || Method<0) BadSwitch(Switch); break; } break; case 'N': case 'X': if (Switch[1]!=0) { StringList *Args=toupperw(Switch[0])=='N' ? &InclArgs:&ExclArgs; if (Switch[1]=='@' && !IsWildcard(Switch)) ReadTextFile(Switch+2,Args,false,true,FilelistCharset,true,true,true); else Args->AddString(Switch+1); } break; case 'O': switch(toupperw(Switch[1])) { case '+': Overwrite=OVERWRITE_ALL; break; case '-': Overwrite=OVERWRITE_NONE; break; case 0: Overwrite=OVERWRITE_FORCE_ASK; break; #ifdef _WIN_ALL case 'C': SetCompressedAttr=true; break; #endif case 'H': SaveHardLinks=true; break; #ifdef SAVE_LINKS case 'L': SaveSymLinks=true; if (toupperw(Switch[2])=='A') AbsoluteLinks=true; break; #endif #ifdef _WIN_ALL case 'N': if (toupperw(Switch[2])=='I') AllowIncompatNames=true; break; #endif case 'R': Overwrite=OVERWRITE_AUTORENAME; break; #ifdef _WIN_ALL case 'S': SaveStreams=true; break; #endif case 'W': ProcessOwners=true; break; default : BadSwitch(Switch); break; } break; case 'P': if (Switch[1]==0) { uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password); eprintf(L"\n"); } else { Password.Set(Switch+1); cleandata((void *)Switch,wcslen(Switch)*sizeof(Switch[0])); } break; #ifndef SFX_MODULE case 'Q': if (toupperw(Switch[1])=='O') switch(toupperw(Switch[2])) { case 0: QOpenMode=QOPEN_AUTO; break; case '-': QOpenMode=QOPEN_NONE; break; case '+': QOpenMode=QOPEN_ALWAYS; break; default: BadSwitch(Switch); break; } else BadSwitch(Switch); break; #endif case 'R': switch(toupperw(Switch[1])) { case 0: Recurse=RECURSE_ALWAYS; break; case '-': Recurse=RECURSE_DISABLE; break; case '0': Recurse=RECURSE_WILDCARDS; break; case 'I': { Priority=atoiw(Switch+2); if (Priority<0 || Priority>15) BadSwitch(Switch); const wchar *ChPtr=wcschr(Switch+2,':'); if (ChPtr!=NULL) { SleepTime=atoiw(ChPtr+1); if (SleepTime>1000) BadSwitch(Switch); InitSystemOptions(SleepTime); } SetPriority(Priority); } break; } break; case 'S': if (IsDigit(Switch[1])) { Solid|=SOLID_COUNT; SolidCount=atoiw(&Switch[1]); } else switch(toupperw(Switch[1])) { case 0: Solid|=SOLID_NORMAL; break; case '-': Solid=SOLID_NONE; break; case 'E': Solid|=SOLID_FILEEXT; break; case 'V': Solid|=Switch[2]=='-' ? SOLID_VOLUME_DEPENDENT:SOLID_VOLUME_INDEPENDENT; break; case 'D': Solid|=SOLID_VOLUME_DEPENDENT; break; case 'L': if (IsDigit(Switch[2])) FileSizeLess=atoilw(Switch+2); break; case 'M': if (IsDigit(Switch[2])) FileSizeMore=atoilw(Switch+2); break; case 'C': { bool AlreadyBad=false; // Avoid reporting "bad switch" several times. RAR_CHARSET rch=RCH_DEFAULT; switch(toupperw(Switch[2])) { case 'A': rch=RCH_ANSI; break; case 'O': rch=RCH_OEM; break; case 'U': rch=RCH_UNICODE; break; case 'F': rch=RCH_UTF8; break; default : BadSwitch(Switch); AlreadyBad=true; break; }; if (!AlreadyBad) if (Switch[3]==0) CommentCharset=FilelistCharset=ErrlogCharset=RedirectCharset=rch; else for (uint I=3;Switch[I]!=0 && !AlreadyBad;I++) switch(toupperw(Switch[I])) { case 'C': CommentCharset=rch; break; case 'L': FilelistCharset=rch; break; case 'R': RedirectCharset=rch; break; default: BadSwitch(Switch); AlreadyBad=true; break; } // Set it immediately when parsing the command line, so it also // affects messages issued while parsing the command line. SetConsoleRedirectCharset(RedirectCharset); } break; } break; case 'T': switch(toupperw(Switch[1])) { case 'K': ArcTime=ARCTIME_KEEP; break; case 'L': ArcTime=ARCTIME_LATEST; break; case 'O': FileTimeBefore.SetAgeText(Switch+2); break; case 'N': FileTimeAfter.SetAgeText(Switch+2); break; case 'B': FileTimeBefore.SetIsoText(Switch+2); break; case 'A': FileTimeAfter.SetIsoText(Switch+2); 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; } } } break; case '-': Test=false; break; case 0: Test=true; break; default: BadSwitch(Switch); break; } break; case 'U': if (Switch[1]==0) UpdateFiles=true; else BadSwitch(Switch); break; case 'V': switch(toupperw(Switch[1])) { case 'P': VolumePause=true; break; case 'E': if (toupperw(Switch[2])=='R') VersionControl=atoiw(Switch+3)+1; break; case '-': VolSize=0; break; default: VolSize=VOLSIZE_AUTO; // UnRAR -v switch for list command. break; } break; case 'W': wcsncpyz(TempPath,Switch+1,ASIZE(TempPath)); AddEndSlash(TempPath,ASIZE(TempPath)); break; case 'Y': AllYes=true; break; case 'Z': if (Switch[1]==0) { // If comment file is not specified, we read data from stdin. wcscpy(CommentFile,L"stdin"); } else wcsncpyz(CommentFile,Switch+1,ASIZE(CommentFile)); break; case '?' : OutHelp(RARX_SUCCESS); break; default : BadSwitch(Switch); break; } }
bool FindFile::FastFind(const char *FindMask,FindData *fd,bool GetSymLink) #endif { fd->Error=false; #ifndef _UNIX #ifndef __BIONIC__ if (IsWildcard(FindMask,FindMaskW)) #else if (IsWildcard(FindMask)) #endif return(false); #endif #ifdef _WIN_ALL HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd); if (hFind==INVALID_HANDLE_VALUE) return(false); FindClose(hFind); #else struct stat st; if (GetSymLink) { #ifdef SAVE_LINKS if (lstat(FindMask,&st)!=0) #else if (stat(FindMask,&st)!=0) #endif { fd->Error=(errno!=ENOENT); return(false); } } else if (stat(FindMask,&st)!=0) { fd->Error=(errno!=ENOENT); return(false); } #ifdef _DJGPP fd->FileAttr=_chmod(FindMask,0); #elif defined(_EMX) fd->FileAttr=st.st_attr; #else fd->FileAttr=st.st_mode; #endif fd->IsDir=IsDir(st.st_mode); fd->Size=st.st_size; fd->mtime=st.st_mtime; fd->atime=st.st_atime; fd->ctime=st.st_ctime; fd->FileTime=fd->mtime.GetDos(); strcpy(fd->Name,FindMask); #ifndef __BIONIC__ *fd->NameW=0; #ifdef _APPLE if (!LowAscii(fd->Name)) UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW)); #elif defined(UNICODE_SUPPORTED) if (!LowAscii(fd->Name) && UnicodeEnabled()) CharToWide(fd->Name,fd->NameW); #endif #endif #endif fd->Flags=0; fd->IsDir=IsDir(fd->FileAttr); return(true); }
void MSA::GetFractionalWeightedCounts(unsigned uColIndex, bool bNormalize, FCOUNT fcCounts[], FCOUNT *ptrfcGapStart, FCOUNT *ptrfcGapEnd, FCOUNT *ptrfcGapExtend, FCOUNT *ptrfOcc, FCOUNT *ptrfcLL, FCOUNT *ptrfcLG, FCOUNT *ptrfcGL, FCOUNT *ptrfcGG) const { const unsigned uSeqCount = GetSeqCount(); const unsigned uColCount = GetColCount(); const char* seqName; memset(fcCounts, 0, g_AlphaSize*sizeof(FCOUNT)); WEIGHT wTotal = 0; FCOUNT fGap = 0; for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) { const WEIGHT w = GetSeqWeight(uSeqIndex); if (IsGap(uSeqIndex, uColIndex)) { fGap += w; continue; } else if (IsWildcard(uSeqIndex, uColIndex)) { const unsigned uLetter = GetLetterEx(uSeqIndex, uColIndex); switch (g_Alpha) { case ALPHA_Amino: switch (uLetter) { case AX_B: // D or N fcCounts[AX_D] += w/2; fcCounts[AX_N] += w/2; break; case AX_Z: // E or Q fcCounts[AX_E] += w/2; fcCounts[AX_Q] += w/2; break; default: // any { const FCOUNT f = w/20; for (unsigned uLetter = 0; uLetter < 20; ++uLetter) fcCounts[uLetter] += f; break; } } break; case ALPHA_DNA: case ALPHA_RNA: switch (uLetter) { case AX_R: // G or A fcCounts[NX_G] += w/2; fcCounts[NX_A] += w/2; break; case AX_Y: // C or T/U fcCounts[NX_C] += w/2; fcCounts[NX_T] += w/2; break; default: // any const FCOUNT f = w/20; for (unsigned uLetter = 0; uLetter < 4; ++uLetter) fcCounts[uLetter] += f; break; } break; default: Quit("Alphabet %d not supported", g_Alpha); } continue; } unsigned uLetter = GetLetter(uSeqIndex, uColIndex); //BEGIN MODIFICATIONS TO MUSCLE int original=0; for(unsigned i=0; i<uColIndex; i++){ if (i >= this->GetColCount()){break;} ++original; char c = GetChar(uSeqIndex, i); if(c== '-'){ original--; } } seqName = this->GetSeqName(uSeqIndex); int compositeVectPosition; compositeVectPosition = atoi(seqName); CompositeVect CV = *CVLocation; Composite* CVL = CV[compositeVectPosition]; Composite C = *CVL; for(int j=0; j<21; j++){ fcCounts[j] = w*C[original][j]; wTotal = w*C[original][j]; } //ORIGINAL MUSLCE LINE WAS: //fcCounts[uLetter] += w; //wTotal += w; //END MODIFICATIONS TO MUSCLE } *ptrfOcc = (float) (1.0 - fGap); if (bNormalize && wTotal > 0) { if (wTotal > 1.001) Quit("wTotal=%g\n", wTotal); for (unsigned uLetter = 0; uLetter < g_AlphaSize; ++uLetter) fcCounts[uLetter] /= wTotal; // AssertNormalized(fcCounts); } FCOUNT fcStartCount = 0; if (uColIndex == 0) { for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex)) fcStartCount += GetSeqWeight(uSeqIndex); } else { for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex) && !IsGap(uSeqIndex, uColIndex - 1)) fcStartCount += GetSeqWeight(uSeqIndex); } FCOUNT fcEndCount = 0; if (uColCount - 1 == uColIndex) { for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex)) fcEndCount += GetSeqWeight(uSeqIndex); } else { for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex) && !IsGap(uSeqIndex, uColIndex + 1)) fcEndCount += GetSeqWeight(uSeqIndex); } FCOUNT LL = 0; FCOUNT LG = 0; FCOUNT GL = 0; FCOUNT GG = 0; for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) { WEIGHT w = GetSeqWeight(uSeqIndex); bool bLetterHere = !IsGap(uSeqIndex, uColIndex); bool bLetterPrev = (uColIndex == 0 || !IsGap(uSeqIndex, uColIndex - 1)); if (bLetterHere) { if (bLetterPrev) LL += w; else GL += w; } else { if (bLetterPrev) LG += w; else GG += w; } } FCOUNT fcExtendCount = 0; if (uColIndex > 0 && uColIndex < GetColCount() - 1) for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex) && IsGap(uSeqIndex, uColIndex - 1) && IsGap(uSeqIndex, uColIndex + 1)) fcExtendCount += GetSeqWeight(uSeqIndex); *ptrfcLL = LL; *ptrfcLG = LG; *ptrfcGL = GL; *ptrfcGG = GG; *ptrfcGapStart = fcStartCount; *ptrfcGapEnd = fcEndCount; *ptrfcGapExtend = fcExtendCount; }
bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) { wchar Command=Cmd->Command[0]; if (HeaderSize==0) { if (DataIO.UnpVolume) { #ifdef NOVOLUME return false; #else // Supposing we unpack an old RAR volume without end of archive record // and last file is not split between volumes. if (!MergeArchive(Arc,&DataIO,false,Command)) { ErrHandler.SetErrorCode(RARX_WARNING); return false; } #endif } else return false; } HEADER_TYPE HeaderType=Arc.GetHeaderType(); if (HeaderType!=HEAD_FILE) { #ifndef SFX_MODULE if (HeaderType==HEAD3_OLDSERVICE && PrevExtracted) SetExtraInfo20(Cmd,Arc,DestFileName); #endif if (HeaderType==HEAD_SERVICE && PrevExtracted) SetExtraInfo(Cmd,Arc,DestFileName); if (HeaderType==HEAD_ENDARC) { if (Arc.EndArcHead.NextVolume) { #ifndef NOVOLUME if (!MergeArchive(Arc,&DataIO,false,Command)) { ErrHandler.SetErrorCode(RARX_WARNING); return false; } #endif Arc.Seek(Arc.CurBlockPos,SEEK_SET); return true; } else return false; } Arc.SeekToNext(); return true; } PrevExtracted=false; if (!Cmd->Recurse && MatchedArgs>=Cmd->FileArgs.ItemsCount() && AllMatchesExact) return false; int MatchType=MATCH_WILDSUBPATH; bool EqualNames=false; wchar MatchedArg[NM]; int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,MatchedArg,ASIZE(MatchedArg)); bool MatchFound=MatchNumber!=0; #ifndef SFX_MODULE if (Cmd->ExclPath==EXCL_BASEPATH) { wcsncpyz(Cmd->ArcPath,MatchedArg,ASIZE(Cmd->ArcPath)); *PointToName(Cmd->ArcPath)=0; if (IsWildcard(Cmd->ArcPath)) // Cannot correctly process path*\* masks here. *Cmd->ArcPath=0; } #endif if (MatchFound && !EqualNames) AllMatchesExact=false; Arc.ConvertAttributes(); #if !defined(SFX_MODULE) && !defined(RARDLL) if (Arc.FileHead.SplitBefore && FirstFile) { wchar CurVolName[NM]; wcsncpyz(CurVolName,ArcName,ASIZE(CurVolName)); VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),Arc.NewNumbering); if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName)) { // If first volume name does not match the current name and if such // volume name really exists, let's unpack from this first volume. Repeat=true; return false; } #ifndef RARDLL if (!ReconstructDone) { ReconstructDone=true; if (RecVolumesRestore(Cmd,Arc.FileName,true)) { Repeat=true; return false; } } #endif wcsncpyz(ArcName,CurVolName,ASIZE(ArcName)); } #endif wchar ArcFileName[NM]; ConvertPath(Arc.FileHead.FileName,ArcFileName); if (Arc.FileHead.Version) { if (Cmd->VersionControl!=1 && !EqualNames) { if (Cmd->VersionControl==0) MatchFound=false; int Version=ParseVersionFileName(ArcFileName,false); if (Cmd->VersionControl-1==static_cast<uint>(Version)) ParseVersionFileName(ArcFileName,true); else MatchFound=false; } } else if (!Arc.IsArcDir() && Cmd->VersionControl>1) MatchFound=false; DataIO.UnpVolume=Arc.FileHead.SplitAfter; DataIO.NextVolumeMissing=false; Arc.Seek(Arc.NextBlockPos-Arc.FileHead.PackSize,SEEK_SET); bool ExtrFile=false; bool SkipSolid=false; #ifndef SFX_MODULE if (FirstFile && (MatchFound || Arc.Solid) && Arc.FileHead.SplitBefore) { if (MatchFound) { uiMsg(UIERROR_NEEDPREVVOL,Arc.FileName,ArcFileName); #ifdef RARDLL Cmd->DllError=ERAR_BAD_DATA; #endif ErrHandler.SetErrorCode(RARX_OPEN); } MatchFound=false; } FirstFile=false; #endif if (MatchFound || (SkipSolid=Arc.Solid)!=0) { // First common call of uiStartFileExtract. It is done before overwrite // prompts, so if SkipSolid state is changed below, we'll need to make // additional uiStartFileExtract calls with updated parameters. if (!uiStartFileExtract(ArcFileName,!Cmd->Test,Cmd->Test && Command!='I',SkipSolid)) return false; ExtrPrepareName(Arc,ArcFileName,DestFileName,ASIZE(DestFileName)); // DestFileName can be set empty in case of excessive -ap switch. ExtrFile=!SkipSolid && *DestFileName!=0 && !Arc.FileHead.SplitBefore; if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X')) { FindData FD; if (FindFile::FastFind(DestFileName,&FD)) { if (FD.mtime >= Arc.FileHead.mtime) { // 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) ExtrFile=false; } if (Arc.FileHead.Encrypted) { #ifdef RARDLL if (!ExtrDllGetPassword()) return false; #else if (!ExtrGetPassword(Arc,ArcFileName)) { PasswordCancelled=true; return false; } #endif // Skip only the current encrypted file if empty password is entered. if (!Cmd->Password.IsSet()) { ErrHandler.SetErrorCode(RARX_WARNING); #ifdef RARDLL Cmd->DllError=ERAR_MISSING_PASSWORD; #endif ExtrFile=false; } } #ifdef RARDLL if (*Cmd->DllDestName!=0) wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName)); #endif if (!CheckUnpVer(Arc,ArcFileName)) { ExtrFile=false; ErrHandler.SetErrorCode(RARX_FATAL); #ifdef RARDLL Cmd->DllError=ERAR_UNKNOWN_FORMAT; #endif } File CurFile; bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE; if (LinkEntry && Arc.FileHead.RedirType!=FSREDIR_FILECOPY) { if (ExtrFile && Command!='P' && !Cmd->Test) { // Overwrite prompt for symbolic and hard links. bool UserReject=false; if (FileExist(DestFileName) && !UserReject) FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime); if (UserReject) ExtrFile=false; } } else if (Arc.IsArcDir()) { if (!ExtrFile || Command=='P' || Command=='I' || Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH) return true; TotalFileCount++; ExtrCreateDir(Arc,ArcFileName); return true; } else if (ExtrFile) // Create files and file copies (FSREDIR_FILECOPY). ExtrFile=ExtrCreateFile(Arc,CurFile); if (!ExtrFile && Arc.Solid) { SkipSolid=true; ExtrFile=true; // We changed SkipSolid, so we need to call uiStartFileExtract // with "Skip" parameter to change the operation status // from "extracting" to "skipping". For example, it can be necessary // if user answered "No" to overwrite prompt when unpacking // a solid archive. if (!uiStartFileExtract(ArcFileName,false,false,true)) return false; } if (ExtrFile) { bool TestMode=Cmd->Test || SkipSolid; // Unpack to memory, not to disk. if (!SkipSolid) { if (!TestMode && Command!='P' && CurFile.IsDevice()) { uiMsg(UIERROR_INVALIDNAME,Arc.FileName,DestFileName); ErrHandler.WriteError(Arc.FileName,DestFileName); } TotalFileCount++; } FileCount++; #ifndef GUI if (Command!='I') { if (SkipSolid) mprintf(St(MExtrSkipFile),ArcFileName); else switch(Cmd->Test ? 'T':Command) // "Test" can be also enabled by -t switch. { case 'T': mprintf(St(MExtrTestFile),ArcFileName); break; #ifndef SFX_MODULE case 'P': mprintf(St(MExtrPrinting),ArcFileName); break; #endif case 'X': case 'E': mprintf(St(MExtrFile),DestFileName); break; } } if (!Cmd->DisablePercentage) mprintf(L" "); #endif SecPassword FilePassword=Cmd->Password; #if defined(_WIN_ALL) && !defined(SFX_MODULE) ConvertDosPassword(Arc,FilePassword); #endif byte PswCheck[SIZE_PSWCHECK]; DataIO.SetEncryption(false,Arc.FileHead.CryptMethod,&FilePassword, Arc.FileHead.SaltSet ? Arc.FileHead.Salt:NULL, Arc.FileHead.InitV,Arc.FileHead.Lg2Count, PswCheck,Arc.FileHead.HashKey); bool WrongPassword=false; // If header is damaged, we cannot rely on password check value, // because it can be damaged too. if (Arc.FileHead.Encrypted && Arc.FileHead.UsePswCheck && memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 && !Arc.BrokenHeader) { uiMsg(UIERROR_BADPSW,Arc.FileName); ErrHandler.SetErrorCode(RARX_BADPWD); WrongPassword=true; } DataIO.CurUnpRead=0; DataIO.CurUnpWrite=0; DataIO.UnpHash.Init(Arc.FileHead.FileHash.Type,Cmd->Threads); DataIO.PackedDataHash.Init(Arc.FileHead.FileHash.Type,Cmd->Threads); DataIO.SetPackedSizeToRead(Arc.FileHead.PackSize); DataIO.SetFiles(&Arc,&CurFile); DataIO.SetTestMode(TestMode); DataIO.SetSkipUnpCRC(SkipSolid); #if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT) if (!TestMode && !WrongPassword && !Arc.BrokenHeader && Arc.FileHead.UnpSize>0xffffffff && (Fat32 || !NotFat32)) { if (!Fat32) // Not detected yet. NotFat32=!(Fat32=IsFAT(Cmd->ExtrPath)); if (Fat32) uiMsg(UIMSG_FAT32SIZE); // Inform user about FAT32 size limit. } #endif if (!TestMode && !WrongPassword && !Arc.BrokenHeader && (Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize && (Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize)) CurFile.Prealloc(Arc.FileHead.UnpSize); CurFile.SetAllowDelete(!Cmd->KeepBroken); bool FileCreateMode=!TestMode && !SkipSolid && Command!='P'; bool ShowChecksum=true; // Display checksum verification result. bool LinkSuccess=true; // Assume success for test mode. if (LinkEntry) { FILE_SYSTEM_REDIRECT Type=Arc.FileHead.RedirType; if (Type==FSREDIR_HARDLINK || Type==FSREDIR_FILECOPY) { wchar NameExisting[NM]; ExtrPrepareName(Arc,Arc.FileHead.RedirName,NameExisting,ASIZE(NameExisting)); if (FileCreateMode && *NameExisting!=0) // *NameExisting can be 0 in case of excessive -ap switch. { if (Type==FSREDIR_HARDLINK) LinkSuccess=ExtractHardlink(DestFileName,NameExisting,ASIZE(NameExisting)); else LinkSuccess=ExtractFileCopy(CurFile,Arc.FileName,DestFileName,NameExisting,ASIZE(NameExisting)); } } else if (Type==FSREDIR_UNIXSYMLINK || Type==FSREDIR_WINSYMLINK || Type==FSREDIR_JUNCTION) { if (FileCreateMode) LinkSuccess=ExtractSymlink(Cmd,DataIO,Arc,DestFileName); } else { uiMsg(UIERROR_UNKNOWNEXTRA, Arc.FileName, DestFileName); LinkSuccess=false; } if (!LinkSuccess || (Arc.Format==RARFMT15 && !FileCreateMode)) { // RAR 5.x links have a valid data checksum even in case of // failure, because they do not store any data. // We do not want to display "OK" in this case. // For 4.x symlinks we verify the checksum only when extracting, // but not when testing an archive. ShowChecksum=false; } PrevExtracted=FileCreateMode && LinkSuccess; } else if (!Arc.FileHead.SplitBefore && !WrongPassword) { if (Arc.FileHead.Method==0) UnstoreFile(DataIO,Arc.FileHead.UnpSize); else { #ifdef _ANDROID // malloc and new do not report memory allocation errors // in Android, so if free memory is set, check it here // trying to prevent crash. if (Cmd->FreeMem!=0 && Cmd->FreeMem < Arc.FileHead.WinSize) throw std::bad_alloc(); #endif Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid); Unp->SetDestSize(Arc.FileHead.UnpSize); #ifndef SFX_MODULE if (Arc.Format!=RARFMT50 && Arc.FileHead.UnpVer<=15) Unp->DoUnpack(15,FileCount>1 && Arc.Solid); else #endif Unp->DoUnpack(Arc.FileHead.UnpVer,Arc.FileHead.Solid); } } Arc.SeekToNext(); // We check for "split after" flag to detect partially extracted files // from incomplete volume sets. For them file header contains packed // data hash, which must not be compared against unpacked data hash // to prevent accidental match. Moreover, for -m0 volumes packed data // hash would match truncated unpacked data hash and lead to fake "OK" // in incomplete volume set. bool ValidCRC=!Arc.FileHead.SplitAfter && DataIO.UnpHash.Cmp(&Arc.FileHead.FileHash,Arc.FileHead.UseHashKey ? Arc.FileHead.HashKey:NULL); // We set AnySolidDataUnpackedWell to true if we found at least one // valid non-zero solid file in preceding solid stream. If it is true // and if current encrypted file is broken, we do not need to hint // about a wrong password and can report CRC error only. if (!Arc.FileHead.Solid) AnySolidDataUnpackedWell=false; // Reset the flag, because non-solid file is found. else if (Arc.FileHead.Method!=0 && Arc.FileHead.UnpSize>0 && ValidCRC) AnySolidDataUnpackedWell=true; bool BrokenFile=false; // Checksum is not calculated in skip solid mode for performance reason. if (!SkipSolid && ShowChecksum) { if (!WrongPassword && ValidCRC) { #ifndef GUI if (Command!='P' && Command!='I') mprintf(L"%s%s ",Cmd->DisablePercentage ? L" ":L"\b\b\b\b\b ", Arc.FileHead.FileHash.Type==HASH_NONE ? L" ?":St(MOk)); #endif } else { if (!WrongPassword) { if (Arc.FileHead.Encrypted && (!Arc.FileHead.UsePswCheck || Arc.BrokenHeader) && !AnySolidDataUnpackedWell) uiMsg(UIERROR_CHECKSUMENC,Arc.FileName,ArcFileName); else uiMsg(UIERROR_CHECKSUM,Arc.FileName,ArcFileName); } BrokenFile=true; ErrHandler.SetErrorCode(RARX_CRC); #ifdef RARDLL // If we already have ERAR_EOPEN as result of missing volume, // we should not replace it with less precise ERAR_BAD_DATA. if (Cmd->DllError!=ERAR_EOPEN) Cmd->DllError=WrongPassword ? ERAR_BAD_PASSWORD : ERAR_BAD_DATA; #endif } } #ifndef GUI else mprintf(L"\b\b\b\b\b "); #endif if (!TestMode && !WrongPassword && (Command=='X' || Command=='E') && (!LinkEntry || (Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess)) && (!BrokenFile || Cmd->KeepBroken)) { // We could preallocate more space that really written to broken file. if (BrokenFile) 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(); #if defined(_WIN_ALL) && !defined(SFX_MODULE) if (Cmd->SetCompressedAttr && (Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0) SetFileCompression(CurFile.FileName,true); #endif #ifdef _UNIX if (Cmd->ProcessOwners && Arc.Format==RARFMT50 && Arc.FileHead.UnixOwnerSet) SetUnixOwner(Arc,CurFile.FileName); #endif 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); PrevExtracted=true; } } } if (MatchFound) MatchedArgs++; if (DataIO.NextVolumeMissing) return false; if (!ExtrFile) { if (!Arc.Solid) Arc.SeekToNext(); else if (!SkipSolid) return false; } return true; }
void CommandData::ParseArg(char *Arg,wchar *ArgW) { if (IsSwitch(*Arg) && !NoMoreSwitches) if (Arg[1]=='-') NoMoreSwitches=true; else ProcessSwitch(&Arg[1],(ArgW!=NULL && *ArgW!=0 ? &ArgW[1]:NULL)); else if (*Command==0) { strncpyz(Command,Arg,ASIZE(Command)); if (ArgW!=NULL) strncpyw(CommandW,ArgW,sizeof(CommandW)/sizeof(CommandW[0])); if (etoupper(*Command)=='S') { const char *SFXName=Command[1] ? Command+1:DefSFXName; if (PointToName(SFXName)!=SFXName || FileExist(SFXName)) strcpy(SFXModule,SFXName); else GetConfigName(SFXName,SFXModule,true); } #ifndef GUI *Command=etoupper(*Command); if (*Command!='I' && *Command!='S') strupper(Command); #endif } else if (*ArcName==0) { strncpyz(ArcName,Arg,ASIZE(ArcName)); if (ArgW!=NULL) strncpyzw(ArcNameW,ArgW,ASIZE(ArcNameW)); } else { 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'; if ((IsDriveDiv(EndChar) || IsPathDiv(EndChar)) && !Add) { strncpyz(ExtrPath,Arg,ASIZE(ExtrPath)); if (ArgW!=NULL) strncpyzw(ExtrPathW,ArgW,ASIZE(ExtrPathW)); } else if ((Add || CmdChar=='T') && *Arg!='@') FileArgs->AddString(Arg); else { struct FindData FileData; bool Found=FindFile::FastFind(Arg,NULL,&FileData); if (!Found && *Arg=='@' && !IsWildcard(Arg)) { FileLists=true; RAR_CHARSET Charset=FilelistCharset; #if defined(_WIN_32) && !defined(GUI) // for compatibility reasons we use OEM encoding // in Win32 console version by default if (Charset==RCH_DEFAULT) Charset=RCH_OEM; #endif ReadTextFile(Arg+1,FileArgs,false,true,Charset,true,true,true); } else if (Found && FileData.IsDir && Extract && *ExtrPath==0) { strcpy(ExtrPath,Arg); AddEndSlash(ExtrPath); } else FileArgs->AddString(Arg); } } }
int ScanTree::FindProc(FindData *FindData) { if (*CurMask==0) return(SCAN_NEXT); FastFindFile=false; if (FindStack[Depth]==NULL) { bool Wildcards=IsWildcard(CurMask,CurMaskW); 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); if (Depth==0) SearchAllInRoot=SearchAll; if (SearchAll || Wildcards) { FindStack[Depth]=new FindFile; char SearchMask[NM]; strcpy(SearchMask,CurMask); if (SearchAll) strcpy(PointToName(SearchMask),MASKALL); FindStack[Depth]->SetMask(SearchMask); if (*CurMaskW) { wchar SearchMaskW[NM]; strcpyw(SearchMaskW,CurMaskW); if (SearchAll) strcpyw(PointToName(SearchMaskW),MASKALLW); FindStack[Depth]->SetMaskW(SearchMaskW); } } else { FastFindFile=true; if (!FindCode) { ErrHandler.OpenErrorMsg(CurMask); return(FindData->Error ? SCAN_ERROR:SCAN_NEXT); } } } if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks)) { bool Error=FindData->Error; #ifdef _WIN_32 if (Error && strstr(CurMask,"System Volume Information\\")!=NULL) Error=false; #endif #ifndef SILENT if (Error) { Log(NULL,St(MScanError),CurMask); } #endif char DirName[NM]; wchar DirNameW[NM]; *DirName=0; *DirNameW=0; delete FindStack[Depth]; FindStack[Depth--]=NULL; while (Depth>=0 && FindStack[Depth]==NULL) Depth--; if (Depth < 0) return(SCAN_DONE); char *Slash=strrchrd(CurMask,CPATHDIVIDER); if (Slash!=NULL) { char Mask[NM]; strcpy(Mask,Slash); *Slash=0; strcpy(DirName,CurMask); char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER); if (PrevSlash==NULL) strcpy(CurMask,Mask+1); else strcpy(PrevSlash,Mask); } if (*CurMaskW!=0) { wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER); if (Slash!=NULL) { wchar Mask[NM]; strcpyw(Mask,Slash); *Slash=0; strcpyw(DirNameW,CurMaskW); wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER); if (PrevSlash==NULL) strcpyw(CurMaskW,Mask+1); else strcpyw(PrevSlash,Mask); } if (LowAscii(CurMaskW)) *CurMaskW=0; } if (GetDirs==SCAN_GETDIRSTWICE && FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir) return(Error ? SCAN_ERROR:SCAN_SUCCESS); return(Error ? SCAN_ERROR:SCAN_NEXT); } if (FindData->IsDir) { if (!FastFindFile && Depth==0 && !SearchAllInRoot) return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT); char Mask[NM]; strcpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask)); strcpy(CurMask,FindData->Name); if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1) { #ifndef SILENT Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask); Log(NULL,St(MPathTooLong)); #endif return(SCAN_ERROR); } AddEndSlash(CurMask); strcat(CurMask,Mask); if (*CurMaskW && *FindData->NameW==0) CharToWide(FindData->Name,FindData->NameW); if (*FindData->NameW!=0) { wchar Mask[NM]; if (FastFindFile) strcpyw(Mask,MASKALLW); else if (*CurMaskW) strcpyw(Mask,PointToName(CurMaskW)); else CharToWide(PointToName(CurMask),Mask); strcpyw(CurMaskW,FindData->NameW); AddEndSlash(CurMaskW); strcatw(CurMaskW,Mask); } Depth++; } if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES)) return(SCAN_NEXT); return(SCAN_SUCCESS); }
void MSA::GetFractionalWeightedCounts(unsigned uColIndex, bool bNormalize, FCOUNT fcCounts[], FCOUNT *ptrfcGapStart, FCOUNT *ptrfcGapEnd, FCOUNT *ptrfcGapExtend, FCOUNT *ptrfOcc, FCOUNT *ptrfcLL, FCOUNT *ptrfcLG, FCOUNT *ptrfcGL, FCOUNT *ptrfcGG) const { const unsigned uSeqCount = GetSeqCount(); const unsigned uColCount = GetColCount(); memset(fcCounts, 0, g_AlphaSize*sizeof(FCOUNT)); WEIGHT wTotal = 0; FCOUNT fGap = 0; for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) { const WEIGHT w = GetSeqWeight(uSeqIndex); if (IsGap(uSeqIndex, uColIndex)) { fGap += w; continue; } else if (IsWildcard(uSeqIndex, uColIndex)) { const unsigned uLetter = GetLetterEx(uSeqIndex, uColIndex); switch (g_Alpha) { case ALPHA_Amino: switch (uLetter) { case AX_B: // D or N fcCounts[AX_D] += w/2; fcCounts[AX_N] += w/2; break; case AX_Z: // E or Q fcCounts[AX_E] += w/2; fcCounts[AX_Q] += w/2; break; default: // any { const FCOUNT f = w/20; for (unsigned uLetter = 0; uLetter < 20; ++uLetter) fcCounts[uLetter] += f; break; } } break; case ALPHA_DNA: case ALPHA_RNA: switch (uLetter) { case AX_R: // G or A fcCounts[NX_G] += w/2; fcCounts[NX_A] += w/2; break; case AX_Y: // C or T/U fcCounts[NX_C] += w/2; fcCounts[NX_T] += w/2; break; default: // any const FCOUNT f = w/20; for (unsigned uLetter = 0; uLetter < 4; ++uLetter) fcCounts[uLetter] += f; break; } break; default: Quit("Alphabet %d not supported", g_Alpha); } continue; } unsigned uLetter = GetLetter(uSeqIndex, uColIndex); fcCounts[uLetter] += w; wTotal += w; } *ptrfOcc = (float) (1.0 - fGap); if (bNormalize && wTotal > 0) { if (wTotal > 1.001) Quit("wTotal=%g\n", wTotal); for (unsigned uLetter = 0; uLetter < g_AlphaSize; ++uLetter) fcCounts[uLetter] /= wTotal; // AssertNormalized(fcCounts); } FCOUNT fcStartCount = 0; if (uColIndex == 0) { for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex)) fcStartCount += GetSeqWeight(uSeqIndex); } else { for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex) && !IsGap(uSeqIndex, uColIndex - 1)) fcStartCount += GetSeqWeight(uSeqIndex); } FCOUNT fcEndCount = 0; if (uColCount - 1 == uColIndex) { for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex)) fcEndCount += GetSeqWeight(uSeqIndex); } else { for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex) && !IsGap(uSeqIndex, uColIndex + 1)) fcEndCount += GetSeqWeight(uSeqIndex); } FCOUNT LL = 0; FCOUNT LG = 0; FCOUNT GL = 0; FCOUNT GG = 0; for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) { WEIGHT w = GetSeqWeight(uSeqIndex); bool bLetterHere = !IsGap(uSeqIndex, uColIndex); bool bLetterPrev = (uColIndex == 0 || !IsGap(uSeqIndex, uColIndex - 1)); if (bLetterHere) { if (bLetterPrev) LL += w; else GL += w; } else { if (bLetterPrev) LG += w; else GG += w; } } FCOUNT fcExtendCount = 0; if (uColIndex > 0 && uColIndex < GetColCount() - 1) for (unsigned uSeqIndex = 0; uSeqIndex < uSeqCount; ++uSeqIndex) if (IsGap(uSeqIndex, uColIndex) && IsGap(uSeqIndex, uColIndex - 1) && IsGap(uSeqIndex, uColIndex + 1)) fcExtendCount += GetSeqWeight(uSeqIndex); *ptrfcLL = LL; *ptrfcLG = LG; *ptrfcGL = GL; *ptrfcGG = GG; *ptrfcGapStart = fcStartCount; *ptrfcGapEnd = fcEndCount; *ptrfcGapExtend = fcExtendCount; }
SCAN_CODE ScanTree::FindProc(FindData *FD) { if (*CurMask==0) return(SCAN_NEXT); bool FastFindFile=false; if (FindStack[Depth]==NULL) // No FindFile object for this depth yet. { bool Wildcards=IsWildcard(CurMask,CurMaskW); // If we have a file name without wildcards, we can try to use // FastFind to optimize speed. For example, in Unix it results in // stat call instead of opendir/readdir/closedir. bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FD,GetLinks); bool IsDir=FindCode && FD->IsDir; // SearchAll means that we'll use "*" mask for search, so we'll find // subdirectories and will be able to recurse into them. // We do not use "*" for directories at any level or for files // at top level in recursion mode. bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS || Wildcards && Recurse==RECURSE_WILDCARDS || ScanEntireDisk && Recurse!=RECURSE_DISABLE); if (Depth==0) SearchAllInRoot=SearchAll; if (SearchAll || Wildcards) { // Create the new FindFile object for wildcard based search. FindStack[Depth].reset(new FindFile); char SearchMask[NM]; strcpy(SearchMask,CurMask); if (SearchAll) strcpy(PointToName(SearchMask),MASKALL); FindStack[Depth]->SetMask(SearchMask); if (*CurMaskW!=0) { wchar SearchMaskW[NM]; wcscpy(SearchMaskW,CurMaskW); if (SearchAll) wcscpy(PointToName(SearchMaskW),MASKALLW); FindStack[Depth]->SetMaskW(SearchMaskW); } } else { // Either we failed to fast find or we found a file or we found // a directory in RECURSE_DISABLE mode, so we do not need to scan it. // We can return here and do not need to process further. // We need to process further only if we fast found a directory. if (!FindCode || !FD->IsDir || Recurse==RECURSE_DISABLE) { // Return SCAN_SUCCESS if we found a file. SCAN_CODE RetCode=SCAN_SUCCESS; if (!FindCode) { // Return SCAN_ERROR if problem is more serious than just // "file not found". RetCode=FD->Error ? SCAN_ERROR:SCAN_NEXT; // If we failed to find an object, but our current mask is excluded, // we skip this object and avoid indicating an error. if (Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true)) RetCode=SCAN_NEXT; else ErrHandler.OpenErrorMsg(ErrArcName,NULL,CurMask,CurMaskW); } // If we searched only for one file or directory in "fast find" // (without a wildcard) mode, let's set masks to zero, // so calling function will know that current mask is used // and next one must be read from mask list for next call. // It is not necessary for directories, because even in "fast find" // mode, directory recursing will quit by (Depth < 0) condition, // which returns SCAN_DONE to calling function. *CurMask=0; *CurMaskW=0; return(RetCode); } // We found a directory using only FindFile::FastFind function. FastFindFile=true; } } if (!FastFindFile && !FindStack[Depth]->Next(FD,GetLinks)) { // We cannot find anything more in directory either because of // some error or just as result of all directory entries already read. bool Error=FD->Error; #ifdef _WIN_ALL if (Error) { // Do not display an error if we cannot scan contents of reparse // point. Vista contains a lot of reparse (or junction) points, // which are not accessible. if ((FD->FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0) Error=false; // Do not display an error if we cannot scan contents of // "System Volume Information" folder. Normally it is not accessible. if (strstr(CurMask,"System Volume Information\\")!=NULL) Error=false; } #endif if (Error && Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true)) Error=false; #ifndef SILENT if (Error) { Log(NULL,St(MScanError),CurMask); ErrHandler.SysErrMsg(); } #endif char DirName[NM]; wchar DirNameW[NM]; *DirName=0; *DirNameW=0; // Going to at least one directory level higher. FindStack[Depth--].reset(); while (Depth>=0 && FindStack[Depth]==NULL) Depth--; if (Depth < 0) { // Directories scanned both in normal and FastFindFile mode, // finally exit from scan here, by (Depth < 0) condition. if (Error) Errors++; return(SCAN_DONE); } char *Slash=strrchrd(CurMask,CPATHDIVIDER); if (Slash!=NULL) { char Mask[NM]; strcpy(Mask,Slash); if (Depth<SetAllMaskDepth) strcpy(Mask+1,PointToName(OrigCurMask)); *Slash=0; strcpy(DirName,CurMask); char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER); if (PrevSlash==NULL) strcpy(CurMask,Mask+1); else strcpy(PrevSlash,Mask); } if (*CurMaskW!=0) { wchar *Slash=wcsrchr(CurMaskW,CPATHDIVIDER); if (Slash!=NULL) { wchar Mask[NM]; wcscpy(Mask,Slash); if (Depth<SetAllMaskDepth) wcscpy(Mask+1,PointToName(OrigCurMaskW)); *Slash=0; wcscpy(DirNameW,CurMaskW); wchar *PrevSlash=wcsrchr(CurMaskW,CPATHDIVIDER); if (PrevSlash==NULL) wcscpy(CurMaskW,Mask+1); else wcscpy(PrevSlash,Mask); } #ifndef _WIN_CE // if (LowAscii(CurMaskW)) // *CurMaskW=0; #endif } if (GetDirs==SCAN_GETDIRSTWICE && FindFile::FastFind(DirName,DirNameW,FD,GetLinks) && FD->IsDir) { FD->Flags|=FDDF_SECONDDIR; return(Error ? SCAN_ERROR:SCAN_SUCCESS); } return(Error ? SCAN_ERROR:SCAN_NEXT); } if (FD->IsDir) { // If we found the directory in top (Depth==0) directory // and if we are not in "fast find" (directory name only as argument) // or in recurse (SearchAll was set when opening the top directory) mode, // we do not recurse into this directory. We either return it by itself // or skip it. if (!FastFindFile && Depth==0 && !SearchAllInRoot) return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT); // Let's check if directory name is excluded, so we do not waste // time searching in directory, which will be excluded anyway. if (Cmd!=NULL && (Cmd->ExclCheck(FD->Name,true,false,false) || Cmd->ExclDirByAttr(FD->FileAttr))) { // If we are here in "fast find" mode, it means that entire directory // specified in command line is excluded. Then we need to return // SCAN_DONE to go to next mask and avoid the infinite loop // in GetNext() function. Such loop would be possible in case of // SCAN_NEXT code and "rar a arc dir -xdir" command. return(FastFindFile ? SCAN_DONE:SCAN_NEXT); } char Mask[NM]; strcpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask)); strcpy(CurMask,FD->Name); if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1) { #ifndef SILENT Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask); Log(NULL,St(MPathTooLong)); #endif return(SCAN_ERROR); } AddEndSlash(CurMask); strcat(CurMask,Mask); if (*CurMaskW && *FD->NameW==0) CharToWide(FD->Name,FD->NameW); if (*FD->NameW!=0) { wchar Mask[NM]; if (FastFindFile) wcscpy(Mask,MASKALLW); else if (*CurMaskW) wcscpy(Mask,PointToName(CurMaskW)); else CharToWide(PointToName(CurMask),Mask); wcscpy(CurMaskW,FD->NameW); AddEndSlash(CurMaskW); wcscat(CurMaskW,Mask); } Depth++; // We need to use OrigCurMask for depths less than SetAllMaskDepth // and "*" for depths equal or larger than SetAllMaskDepth. // It is important when "fast finding" directories at Depth > 0. // For example, if current directory is RootFolder and we compress // the following directories structure: // RootFolder // +--Folder1 // | +--Folder2 // | +--Folder3 // +--Folder4 // with 'rar a -r arcname Folder2' command, rar could add not only // Folder1\Folder2 contents, but also Folder1\Folder3 if we were using // "*" mask at all levels. We need to use "*" mask inside of Folder2, // but return to "Folder2" mask when completing scanning Folder2. // We can rewrite SearchAll expression above to avoid fast finding // directories at Depth > 0, but then 'rar a -r arcname Folder2' // will add the empty Folder2 and do not add its contents. if (FastFindFile) SetAllMaskDepth=Depth; } if (!FastFindFile && !CmpName(CurMask,FD->Name,MATCH_NAMES)) return(SCAN_NEXT); return(SCAN_SUCCESS); }