~ubuntu-branches/ubuntu/lucid/unrar-nonfree/lucid

« back to all changes in this revision

Viewing changes to scantree.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Meredith
  • Date: 2009-06-06 17:46:05 UTC
  • mfrom: (1.1.11 upstream) (5.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20090606174605-h4ciqxlpy39jmjx0
Tags: 1:3.9.3-1
* New upstream release
* Updated Copyright file (Closes: #531432)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include "rar.hpp"
2
2
 
3
 
ScanTree::ScanTree(StringList *FileMasks,int Recurse,bool GetLinks,int GetDirs)
 
3
ScanTree::ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs)
4
4
{
5
5
  ScanTree::FileMasks=FileMasks;
6
6
  ScanTree::Recurse=Recurse;
15
15
  memset(FindStack,0,sizeof(FindStack));
16
16
  Depth=0;
17
17
  Errors=0;
18
 
  FastFindFile=false;
19
18
  *ErrArcName=0;
20
19
  Cmd=NULL;
21
20
}
29
28
}
30
29
 
31
30
 
32
 
int ScanTree::GetNext(FindData *FindData)
 
31
SCAN_CODE ScanTree::GetNext(FindData *FindData)
33
32
{
34
33
  if (Depth<0)
35
34
    return(SCAN_DONE);
36
35
 
37
 
  int FindCode;
 
36
  SCAN_CODE FindCode;
38
37
  while (1)
39
38
  {
40
 
    if ((*CurMask==0 || FastFindFile && Depth==0) && !PrepareMasks())
 
39
    if (*CurMask==0 && !GetNextMask())
41
40
      return(SCAN_DONE);
 
41
 
42
42
    FindCode=FindProc(FindData);
43
43
    if (FindCode==SCAN_ERROR)
44
44
    {
49
49
      continue;
50
50
    if (FindCode==SCAN_SUCCESS && FindData->IsDir && GetDirs==SCAN_SKIPDIRS)
51
51
      continue;
52
 
    if (FindCode==SCAN_DONE && PrepareMasks())
 
52
    if (FindCode==SCAN_DONE && GetNextMask())
53
53
      continue;
54
54
    break;
55
55
  }
57
57
}
58
58
 
59
59
 
60
 
bool ScanTree::PrepareMasks()
 
60
bool ScanTree::GetNextMask()
61
61
{
62
 
  ScanEntireDisk=false;
63
62
  if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask)))
64
63
    return(false);
65
64
  CurMask[ASIZE(CurMask)-1]=0;
82
81
    strcat(CurMask,MASKALL);
83
82
  }
84
83
  SpecPathLength=Name-CurMask;
85
 
//  if (SpecPathLength>1)
86
 
//    SpecPathLength--;
87
84
 
88
85
  bool WideName=(*CurMaskW!=0);
89
86
 
114
111
}
115
112
 
116
113
 
117
 
int ScanTree::FindProc(FindData *FindData)
 
114
SCAN_CODE ScanTree::FindProc(FindData *FindData)
118
115
{
119
116
  if (*CurMask==0)
120
117
    return(SCAN_NEXT);
121
 
  FastFindFile=false;
122
 
  if (FindStack[Depth]==NULL)
 
118
  bool FastFindFile=false;
 
119
  
 
120
  if (FindStack[Depth]==NULL) // No FindFile object for this depth yet.
123
121
  {
124
122
    bool Wildcards=IsWildcard(CurMask,CurMaskW);
 
123
 
 
124
    // If we have a file name without wildcards, we can try to use
 
125
    // FastFind to optimize speed. For example, in Unix it results in
 
126
    // stat call instead of opendir/readdir/closedir.
125
127
    bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks);
 
128
 
126
129
    bool IsDir=FindCode && FindData->IsDir;
 
130
 
 
131
    // SearchAll means that we'll use "*" mask for search, so we'll find
 
132
    // subdirectories and will be able to recurse into them.
 
133
    // We do not use "*" for directories at any level or for files
 
134
    // at top level in recursion mode.
127
135
    bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
128
 
                   Wildcards && Recurse==RECURSE_WILDCARDS || ScanEntireDisk);
 
136
                   Wildcards && Recurse==RECURSE_WILDCARDS || 
 
137
                   ScanEntireDisk && Recurse!=RECURSE_DISABLE);
129
138
    if (Depth==0)
130
139
      SearchAllInRoot=SearchAll;
131
140
    if (SearchAll || Wildcards)
132
141
    {
 
142
      // Create the new FindFile object for wildcard based search.
133
143
      FindStack[Depth]=new FindFile;
134
144
      char SearchMask[NM];
135
145
      strcpy(SearchMask,CurMask);
147
157
    }
148
158
    else
149
159
    {
 
160
      // Either we failed to fast find or we found a file or we found
 
161
      // a directory in RECURSE_DISABLE mode, so we do not need to scan it.
 
162
      // We can return here and do not need to process further.
 
163
      // We need to process further only if we fast found a directory.
 
164
      if (!FindCode || !FindData->IsDir || Recurse==RECURSE_DISABLE)
 
165
      {
 
166
         // Return SCAN_SUCCESS if we found a file.
 
167
        SCAN_CODE RetCode=SCAN_SUCCESS;
 
168
 
 
169
        if (!FindCode)
 
170
        {
 
171
          // Return SCAN_ERROR if problem is more serious than just
 
172
          // "file not found".
 
173
          RetCode=FindData->Error ? SCAN_ERROR:SCAN_NEXT;
 
174
 
 
175
          // If we failed to find an object, but our current mask is excluded,
 
176
          // we skip this object and avoid indicating an error.
 
177
          if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
 
178
            RetCode=SCAN_NEXT;
 
179
          else
 
180
            ErrHandler.OpenErrorMsg(ErrArcName,CurMask);
 
181
        }
 
182
 
 
183
        // If we searched only for one file or directory in "fast find" 
 
184
        // (without a wildcard) mode, let's set masks to zero, 
 
185
        // so calling function will know that current mask is used 
 
186
        // and next one must be read from mask list for next call.
 
187
        // It is not necessary for directories, because even in "fast find"
 
188
        // mode, directory recursing will quit by (Depth < 0) condition,
 
189
        // which returns SCAN_DONE to calling function.
 
190
        *CurMask=0;
 
191
        *CurMaskW=0;
 
192
 
 
193
        return(RetCode);
 
194
      }
 
195
 
 
196
      // We found a directory using only FindFile::FastFind function.
150
197
      FastFindFile=true;
151
 
      if (!FindCode)
152
 
      {
153
 
        if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
154
 
          return(SCAN_NEXT);
155
 
        ErrHandler.OpenErrorMsg(ErrArcName,CurMask);
156
 
        return(FindData->Error ? SCAN_ERROR:SCAN_NEXT);
157
 
      }
158
198
    }
159
199
  }
160
200
 
161
201
  if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks))
162
202
  {
 
203
    // We cannot find anything more in directory either because of
 
204
    // some error or just as result of all directory entries already read.
 
205
 
163
206
    bool Error=FindData->Error;
164
207
 
165
208
#ifdef _WIN_32
178
221
    }
179
222
#endif
180
223
 
181
 
    if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
 
224
    if (Error && Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
182
225
      Error=false;
183
226
 
184
227
#ifndef SILENT
193
236
    *DirName=0;
194
237
    *DirNameW=0;
195
238
 
 
239
    // Going to at least one directory level higher.
196
240
    delete FindStack[Depth];
197
241
    FindStack[Depth--]=NULL;
198
242
    while (Depth>=0 && FindStack[Depth]==NULL)
199
243
      Depth--;
200
244
    if (Depth < 0)
201
245
    {
 
246
      // Directories scanned both in normal and FastFindFile mode,
 
247
      // finally exit from scan here, by (Depth < 0) condition.
 
248
 
202
249
      if (Error)
203
250
        Errors++;
204
251
      return(SCAN_DONE);
252
299
 
253
300
  if (FindData->IsDir)
254
301
  {
 
302
    // If we found the directory in top (Depth==0) directory
 
303
    // and if we are not in "fast find" (directory name only as argument)
 
304
    // or in recurse (SearchAll was set when opening the top directory) mode,
 
305
    // we do not recurse into this directory. We either return it by itself
 
306
    // or skip it.
255
307
    if (!FastFindFile && Depth==0 && !SearchAllInRoot)
256
308
      return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);
257
309
 
258
 
//    if (GetDirs==SCAN_GETCURDIRS && Depth==0 && !SearchAllInRoot)
259
 
//      return(SCAN_SUCCESS);
 
310
    // Let's check if directory name is excluded, so we do not waste
 
311
    // time searching in directory, which will be excluded anyway.
 
312
    if (Cmd!=NULL && Cmd->ExclCheck(FindData->Name,false))
 
313
    {
 
314
      // If we are here in "fast find" mode, it means that entire directory
 
315
      // specified in command line is excluded. Then we need to return
 
316
      // SCAN_DONE to go to next mask and avoid the infinite loop
 
317
      // in GetNext() function. Such loop would be possible in case of
 
318
      // SCAN_NEXT code and "rar a arc dir -xdir" command.
260
319
 
 
320
      return(FastFindFile ? SCAN_DONE:SCAN_NEXT);
 
321
    }
 
322
    
261
323
    char Mask[NM];
262
 
    bool MaskAll=FastFindFile;
263
 
 
264
 
//    bool MaskAll=CmpName(CurMask,FindData->Name,MATCH_NAMES);
265
 
 
266
 
    strcpy(Mask,MaskAll ? MASKALL:PointToName(CurMask));
 
324
 
 
325
    strcpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask));
267
326
    strcpy(CurMask,FindData->Name);
268
327
 
269
328
    if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
295
354
      strcatw(CurMaskW,Mask);
296
355
    }
297
356
    Depth++;
298
 
    if (MaskAll)
 
357
 
 
358
    // We need to use OrigCurMask for depths less than SetAllMaskDepth
 
359
    // and "*" for depths equal or larger than SetAllMaskDepth.
 
360
    // It is important when "fast finding" directories at Depth > 0.
 
361
    // For example, if current directory is RootFolder and we compress
 
362
    // the following directories structure:
 
363
    //   RootFolder
 
364
    //     +--Folder1
 
365
    //     |  +--Folder2
 
366
    //     |  +--Folder3
 
367
    //     +--Folder4
 
368
    // with 'rar a -r arcname Folder2' command, rar could add not only
 
369
    // Folder1\Folder2 contents, but also Folder1\Folder3 if we were using
 
370
    // "*" mask at all levels. We need to use "*" mask inside of Folder2,
 
371
    // but return to "Folder2" mask when completing scanning Folder2.
 
372
    // We can rewrite SearchAll expression above to avoid fast finding
 
373
    // directories at Depth > 0, but then 'rar a -r arcname Folder2'
 
374
    // will add the empty Folder2 and do not add its contents.
 
375
 
 
376
    if (FastFindFile)
299
377
      SetAllMaskDepth=Depth;
300
378
  }
301
379
  if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES))
302
380
    return(SCAN_NEXT);
 
381
 
303
382
  return(SCAN_SUCCESS);
304
383
}