OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / unrar / scantree.cpp
1 #include "rar.hpp"
2
3 ScanTree::ScanTree(StringList *FileMasks,int Recurse,bool GetLinks,int GetDirs)
4 {
5   ScanTree::FileMasks=FileMasks;
6   ScanTree::Recurse=Recurse;
7   ScanTree::GetLinks=GetLinks;
8   ScanTree::GetDirs=GetDirs;
9
10   SetAllMaskDepth=0;
11   *CurMask=0;
12   *CurMaskW=0;
13   memset(FindStack,0,sizeof(FindStack));
14   Depth=0;
15   Errors=0;
16   FastFindFile=false;
17   *ErrArcName=0;
18   Cmd=NULL;
19 }
20
21
22 ScanTree::~ScanTree()
23 {
24   for (int I=Depth;I>=0;I--)
25     if (FindStack[I]!=NULL)
26       delete FindStack[I];
27 }
28
29
30 int ScanTree::GetNext(FindData *FindData)
31 {
32   if (Depth<0)
33     return(SCAN_DONE);
34
35   int FindCode;
36   while (1)
37   {
38     if ((*CurMask==0 || FastFindFile && Depth==0) && !PrepareMasks())
39       return(SCAN_DONE);
40     FindCode=FindProc(FindData);
41     if (FindCode==SCAN_ERROR)
42     {
43       Errors++;
44       continue;
45     }
46     if (FindCode==SCAN_NEXT)
47       continue;
48     if (FindCode==SCAN_SUCCESS && FindData->IsDir && GetDirs==SCAN_SKIPDIRS)
49       continue;
50     if (FindCode==SCAN_DONE && PrepareMasks())
51       continue;
52     break;
53   }
54   return(FindCode);
55 }
56
57
58 bool ScanTree::PrepareMasks()
59 {
60   if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask)))
61     return(false);
62 #ifdef _WIN_32
63   UnixSlashToDos(CurMask);
64 #endif
65   char *Name=PointToName(CurMask);
66   if (*Name==0)
67     strcat(CurMask,MASKALL);
68   if (Name[0]=='.' && (Name[1]==0 || Name[1]=='.' && Name[2]==0))
69   {
70     AddEndSlash(CurMask);
71     strcat(CurMask,MASKALL);
72   }
73   SpecPathLength=Name-CurMask;
74 //  if (SpecPathLength>1)
75 //    SpecPathLength--;
76
77   bool WideName=(*CurMaskW!=0);
78
79   if (WideName)
80   {
81     wchar *NameW=PointToName(CurMaskW);
82     if (*NameW==0)
83       strcatw(CurMaskW,MASKALLW);
84     if (NameW[0]=='.' && (NameW[1]==0 || NameW[1]=='.' && NameW[2]==0))
85     {
86       AddEndSlash(CurMaskW);
87       strcatw(CurMaskW,MASKALLW);
88     }
89     SpecPathLengthW=NameW-CurMaskW;
90   }
91   else
92   {
93     wchar WideMask[NM];
94     CharToWide(CurMask,WideMask);
95     SpecPathLengthW=PointToName(WideMask)-WideMask;
96   }
97   Depth=0;
98
99   strcpy(OrigCurMask,CurMask);
100   strcpyw(OrigCurMaskW,CurMaskW);
101
102   return(true);
103 }
104
105
106 int ScanTree::FindProc(FindData *FindData)
107 {
108   if (*CurMask==0)
109     return(SCAN_NEXT);
110   FastFindFile=false;
111   if (FindStack[Depth]==NULL)
112   {
113     bool Wildcards=IsWildcard(CurMask,CurMaskW);
114     bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks);
115     bool IsDir=FindCode && FindData->IsDir;
116     bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
117                    Wildcards && Recurse==RECURSE_WILDCARDS);
118     if (Depth==0)
119       SearchAllInRoot=SearchAll;
120     if (SearchAll || Wildcards)
121     {
122       FindStack[Depth]=new FindFile;
123       char SearchMask[NM];
124       strcpy(SearchMask,CurMask);
125       if (SearchAll)
126         strcpy(PointToName(SearchMask),MASKALL);
127       FindStack[Depth]->SetMask(SearchMask);
128       if (*CurMaskW)
129       {
130         wchar SearchMaskW[NM];
131         strcpyw(SearchMaskW,CurMaskW);
132         if (SearchAll)
133           strcpyw(PointToName(SearchMaskW),MASKALLW);
134         FindStack[Depth]->SetMaskW(SearchMaskW);
135       }
136     }
137     else
138     {
139       FastFindFile=true;
140       if (!FindCode)
141       {
142         if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
143           return(SCAN_NEXT);
144         ErrHandler.OpenErrorMsg(ErrArcName,CurMask);
145         return(FindData->Error ? SCAN_ERROR:SCAN_NEXT);
146       }
147     }
148   }
149
150   if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks))
151   {
152     bool Error=FindData->Error;
153
154 #ifdef _WIN_32
155     if (Error && strstr(CurMask,"System Volume Information\\")!=NULL)
156       Error=false;
157 #endif
158
159     if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
160       Error=false;
161
162 #ifndef SILENT
163     if (Error)
164     {
165       Log(NULL,St(MScanError),CurMask);
166     }
167 #endif
168
169     char DirName[NM];
170     wchar DirNameW[NM];
171     *DirName=0;
172     *DirNameW=0;
173
174     delete FindStack[Depth];
175     FindStack[Depth--]=NULL;
176     while (Depth>=0 && FindStack[Depth]==NULL)
177       Depth--;
178     if (Depth < 0)
179     {
180       if (Error)
181         Errors++;
182       return(SCAN_DONE);
183     }
184     char *Slash=strrchrd(CurMask,CPATHDIVIDER);
185     if (Slash!=NULL)
186     {
187       char Mask[NM];
188       strcpy(Mask,Slash);
189       if (Depth<SetAllMaskDepth)
190         strcpy(Mask+1,PointToName(OrigCurMask));
191       *Slash=0;
192       strcpy(DirName,CurMask);
193       char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
194       if (PrevSlash==NULL)
195         strcpy(CurMask,Mask+1);
196       else
197         strcpy(PrevSlash,Mask);
198     }
199
200     if (*CurMaskW!=0)
201     {
202       wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER);
203       if (Slash!=NULL)
204       {
205         wchar Mask[NM];
206         strcpyw(Mask,Slash);
207         if (Depth<SetAllMaskDepth)
208           strcpyw(Mask+1,PointToName(OrigCurMaskW));
209         *Slash=0;
210         strcpyw(DirNameW,CurMaskW);
211         wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER);
212         if (PrevSlash==NULL)
213           strcpyw(CurMaskW,Mask+1);
214         else
215           strcpyw(PrevSlash,Mask);
216       }
217 #ifndef _WIN_CE
218       if (LowAscii(CurMaskW))
219         *CurMaskW=0;
220 #endif
221     }
222     if (GetDirs==SCAN_GETDIRSTWICE &&
223         FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir)
224       return(Error ? SCAN_ERROR:SCAN_SUCCESS);
225     return(Error ? SCAN_ERROR:SCAN_NEXT);
226   }
227
228   if (FindData->IsDir)
229   {
230     if (!FastFindFile && Depth==0 && !SearchAllInRoot)
231       return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);
232
233 //    if (GetDirs==SCAN_GETCURDIRS && Depth==0 && !SearchAllInRoot)
234 //      return(SCAN_SUCCESS);
235
236     char Mask[NM];
237     bool MaskAll=FastFindFile;
238
239 //    bool MaskAll=CmpName(CurMask,FindData->Name,MATCH_NAMES);
240
241     strcpy(Mask,MaskAll ? MASKALL:PointToName(CurMask));
242     strcpy(CurMask,FindData->Name);
243
244     if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
245     {
246 #ifndef SILENT
247       Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
248       Log(NULL,St(MPathTooLong));
249 #endif
250       return(SCAN_ERROR);
251     }
252
253     AddEndSlash(CurMask);
254     strcat(CurMask,Mask);
255
256     if (*CurMaskW && *FindData->NameW==0)
257       CharToWide(FindData->Name,FindData->NameW);
258     if (*FindData->NameW!=0)
259     {
260       wchar Mask[NM];
261       if (FastFindFile)
262         strcpyw(Mask,MASKALLW);
263       else
264         if (*CurMaskW)
265           strcpyw(Mask,PointToName(CurMaskW));
266         else
267           CharToWide(PointToName(CurMask),Mask);
268       strcpyw(CurMaskW,FindData->NameW);
269       AddEndSlash(CurMaskW);
270       strcatw(CurMaskW,Mask);
271     }
272     Depth++;
273     if (MaskAll)
274       SetAllMaskDepth=Depth;
275   }
276   if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES))
277     return(SCAN_NEXT);
278   return(SCAN_SUCCESS);
279 }