123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- #include "rar.hpp"
- ScanTree::ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs)
- {
- ScanTree::FileMasks=FileMasks;
- ScanTree::Recurse=Recurse;
- ScanTree::GetLinks=GetLinks;
- ScanTree::GetDirs=GetDirs;
- ScanEntireDisk=false;
- FolderWildcards=false;
- SetAllMaskDepth=0;
- *CurMask=0;
- memset(FindStack,0,sizeof(FindStack));
- Depth=0;
- Errors=0;
- *ErrArcName=0;
- Cmd=NULL;
- ErrDirList=NULL;
- ErrDirSpecPathLength=NULL;
- }
- ScanTree::~ScanTree()
- {
- for (int I=Depth;I>=0;I--)
- if (FindStack[I]!=NULL)
- delete FindStack[I];
- }
- SCAN_CODE ScanTree::GetNext(FindData *FD)
- {
- if (Depth<0)
- return SCAN_DONE;
- #ifndef SILENT
- uint LoopCount=0;
- #endif
- SCAN_CODE FindCode;
- while (1)
- {
- if (*CurMask==0 && !GetNextMask())
- return SCAN_DONE;
- #ifndef SILENT
-
-
-
- if ((++LoopCount & 0x3ff)==0)
- Wait();
- #endif
- FindCode=FindProc(FD);
- if (FindCode==SCAN_ERROR)
- {
- Errors++;
- continue;
- }
- if (FindCode==SCAN_NEXT)
- continue;
- if (FindCode==SCAN_SUCCESS && FD->IsDir && GetDirs==SCAN_SKIPDIRS)
- continue;
- if (FindCode==SCAN_DONE && GetNextMask())
- continue;
- if (FilterList.ItemsCount()>0 && FindCode==SCAN_SUCCESS)
- if (!CommandData::CheckArgs(&FilterList,FD->IsDir,FD->Name,false,MATCH_WILDSUBPATH))
- continue;
- break;
- }
- return FindCode;
- }
- bool ScanTree::ExpandFolderMask()
- {
- bool WildcardFound=false;
- uint SlashPos=0;
- for (int I=0;CurMask[I]!=0;I++)
- {
- if (CurMask[I]=='?' || CurMask[I]=='*')
- WildcardFound=true;
- if (WildcardFound && IsPathDiv(CurMask[I]))
- {
-
-
-
- SlashPos=I;
- break;
- }
- }
- wchar Mask[NM];
- wcsncpyz(Mask,CurMask,ASIZE(Mask));
- Mask[SlashPos]=0;
-
- ExpandedFolderList.Reset();
- FindFile Find;
- Find.SetMask(Mask);
- FindData FD;
- while (Find.Next(&FD))
- if (FD.IsDir)
- {
- wcsncatz(FD.Name,CurMask+SlashPos,ASIZE(FD.Name));
-
-
- wchar *LastMask=PointToName(FD.Name);
- if (wcscmp(LastMask,L"*")==0 || wcscmp(LastMask,L"*.*")==0)
- RemoveNameFromPath(FD.Name);
- ExpandedFolderList.AddString(FD.Name);
- }
- if (ExpandedFolderList.ItemsCount()==0)
- return false;
-
- ExpandedFolderList.GetString(CurMask,ASIZE(CurMask));
- return true;
- }
- bool ScanTree::GetFilteredMask()
- {
-
-
- if (ExpandedFolderList.ItemsCount()>0 && ExpandedFolderList.GetString(CurMask,ASIZE(CurMask)))
- return true;
- FolderWildcards=false;
- FilterList.Reset();
- if (!FileMasks->GetString(CurMask,ASIZE(CurMask)))
- return false;
-
- bool WildcardFound=false;
- uint FolderWildcardCount=0;
- uint SlashPos=0;
- uint StartPos=0;
- #ifdef _WIN_ALL
- if (CurMask[0]=='\\' && CurMask[1]=='\\' && CurMask[2]=='?' && CurMask[3]=='\\')
- StartPos=4;
- #endif
- for (uint I=StartPos;CurMask[I]!=0;I++)
- {
- if (CurMask[I]=='?' || CurMask[I]=='*')
- WildcardFound=true;
- if (IsPathDiv(CurMask[I]) || IsDriveDiv(CurMask[I]))
- {
- if (WildcardFound)
- {
-
- FolderWildcardCount++;
- WildcardFound=false;
- }
- if (FolderWildcardCount==0)
- SlashPos=I;
- }
- }
- if (FolderWildcardCount==0)
- return true;
- FolderWildcards=true;
-
-
-
-
- if ((Recurse==RECURSE_NONE || Recurse==RECURSE_DISABLE) && FolderWildcardCount==1)
- return ExpandFolderMask();
- wchar Filter[NM];
-
- wcsncpyz(Filter,L"*",ASIZE(Filter));
- AddEndSlash(Filter,ASIZE(Filter));
-
- wchar *WildName=IsPathDiv(CurMask[SlashPos]) || IsDriveDiv(CurMask[SlashPos]) ? CurMask+SlashPos+1 : CurMask+SlashPos;
- wcsncatz(Filter,WildName,ASIZE(Filter));
-
-
- wchar *LastMask=PointToName(Filter);
- if (wcscmp(LastMask,L"*")==0 || wcscmp(LastMask,L"*.*")==0)
- *LastMask=0;
- FilterList.AddString(Filter);
- bool RelativeDrive=IsDriveDiv(CurMask[SlashPos]);
- if (RelativeDrive)
- SlashPos++;
- CurMask[SlashPos]=0;
- if (!RelativeDrive)
- {
-
-
- AddEndSlash(CurMask,ASIZE(CurMask));
- wcsncatz(CurMask,MASKALL,ASIZE(CurMask));
- }
- return true;
- }
- bool ScanTree::GetNextMask()
- {
- if (!GetFilteredMask())
- return false;
- #ifdef _WIN_ALL
- UnixSlashToDos(CurMask,CurMask,ASIZE(CurMask));
- #endif
-
-
-
- ScanEntireDisk=IsDriveLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;
- wchar *Name=PointToName(CurMask);
- if (*Name==0)
- wcsncatz(CurMask,MASKALL,ASIZE(CurMask));
- if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
- {
- AddEndSlash(CurMask,ASIZE(CurMask));
- wcsncatz(CurMask,MASKALL,ASIZE(CurMask));
- }
- SpecPathLength=Name-CurMask;
- Depth=0;
- wcsncpyz(OrigCurMask,CurMask,ASIZE(OrigCurMask));
- return true;
- }
- SCAN_CODE ScanTree::FindProc(FindData *FD)
- {
- if (*CurMask==0)
- return SCAN_NEXT;
- bool FastFindFile=false;
-
- if (FindStack[Depth]==NULL)
- {
- bool Wildcards=IsWildcard(CurMask);
-
-
-
- bool FindCode=!Wildcards && FindFile::FastFind(CurMask,FD,GetLinks);
-
-
- bool IsDir=FindCode && FD->IsDir && (!GetLinks || !FD->IsLink);
-
-
-
-
-
- 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)
- {
-
- FindStack[Depth]=new FindFile;
- wchar SearchMask[NM];
- wcsncpyz(SearchMask,CurMask,ASIZE(SearchMask));
- if (SearchAll)
- SetName(SearchMask,MASKALL,ASIZE(SearchMask));
- FindStack[Depth]->SetMask(SearchMask);
- }
- else
- {
-
-
-
-
- if (!FindCode || !IsDir || Recurse==RECURSE_DISABLE)
- {
-
- SCAN_CODE RetCode=SCAN_SUCCESS;
- if (!FindCode)
- {
-
-
- RetCode=FD->Error ? SCAN_ERROR:SCAN_NEXT;
-
-
- if (Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true))
- RetCode=SCAN_NEXT;
- else
- {
- ErrHandler.OpenErrorMsg(ErrArcName,CurMask);
-
- ErrHandler.SetErrorCode(RARX_NOFILES);
- }
- }
-
-
-
-
-
-
-
- *CurMask=0;
- return RetCode;
- }
-
- FastFindFile=true;
- }
- }
- if (!FastFindFile && !FindStack[Depth]->Next(FD,GetLinks))
- {
-
-
- bool Error=FD->Error;
- if (Error)
- ScanError(Error);
- wchar DirName[NM];
- *DirName=0;
-
- delete FindStack[Depth];
- FindStack[Depth--]=NULL;
- while (Depth>=0 && FindStack[Depth]==NULL)
- Depth--;
- if (Depth < 0)
- {
-
-
- 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;
- }
-
- if (FD->IsDir && (!GetLinks || !FD->IsLink))
- {
-
-
-
-
-
- if (!FastFindFile && Depth==0 && !SearchAllInRoot)
- return GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT;
-
-
- if (Cmd!=NULL && (Cmd->ExclCheck(FD->Name,true,false,false) ||
- Cmd->ExclDirByAttr(FD->FileAttr)))
- {
-
-
-
-
-
- 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++;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (FastFindFile)
- SetAllMaskDepth=Depth;
- }
- if (!FastFindFile && !CmpName(CurMask,FD->Name,MATCH_NAMES))
- return SCAN_NEXT;
- return SCAN_SUCCESS;
- }
- void ScanTree::ScanError(bool &Error)
- {
- #ifdef _WIN_ALL
- if (Error)
- {
-
-
-
-
-
-
-
- wchar *Slash=PointToName(CurMask);
- if (Slash>CurMask)
- {
- *(Slash-1)=0;
- DWORD Attr=GetFileAttributes(CurMask);
- *(Slash-1)=CPATHDIVIDER;
- if (Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
- Error=false;
- }
-
-
- if (wcsstr(CurMask,L"System Volume Information\\")!=NULL)
- Error=false;
- }
- #endif
- if (Error && Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true))
- Error=false;
- if (Error)
- {
- if (ErrDirList!=NULL)
- ErrDirList->AddString(CurMask);
- if (ErrDirSpecPathLength!=NULL)
- ErrDirSpecPathLength->Push((uint)SpecPathLength);
- wchar FullName[NM];
-
- ConvertNameToFull(CurMask,FullName,ASIZE(FullName));
- uiMsg(UIERROR_DIRSCAN,FullName);
- ErrHandler.SysErrMsg();
- }
- }
|