misc/libphysfs/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp
branchui-scaling
changeset 15283 c4fd2813b127
parent 13390 0135e64c6c66
parent 15279 7ab5cf405686
child 15663 d92eeb468dad
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
     1 // EnumDirItems.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 
       
     5 #include "Common/StringConvert.h"
       
     6 #include "Common/Wildcard.h"
       
     7 #include "Common/MyCom.h"
       
     8 
       
     9 #include "EnumDirItems.h"
       
    10 
       
    11 using namespace NWindows;
       
    12 using namespace NFile;
       
    13 using namespace NName;
       
    14 
       
    15 void AddDirFileInfo(
       
    16     const UString &prefix,        // prefix for logical path
       
    17     const UString &fullPathName,  // path on disk: can be relative to some basePrefix
       
    18     const NFind::CFileInfoW &fileInfo, 
       
    19     CObjectVector<CDirItem> &dirItems)
       
    20 {
       
    21   CDirItem item;
       
    22   item.Attributes = fileInfo.Attributes;
       
    23   item.Size = fileInfo.Size;
       
    24   item.CreationTime = fileInfo.CreationTime;
       
    25   item.LastAccessTime = fileInfo.LastAccessTime;
       
    26   item.LastWriteTime = fileInfo.LastWriteTime;
       
    27   item.Name = prefix + fileInfo.Name;
       
    28   item.FullPath = fullPathName;
       
    29   dirItems.Add(item);
       
    30 }
       
    31 
       
    32 static void EnumerateDirectory(
       
    33     const UString &baseFolderPrefix,  // base (disk) prefix for scanning  
       
    34     const UString &directory,         // additional disk prefix starting from baseFolderPrefix
       
    35     const UString &prefix,            // logical prefix
       
    36     CObjectVector<CDirItem> &dirItems,
       
    37     UStringVector &errorPaths,
       
    38     CRecordVector<DWORD> &errorCodes)
       
    39 {
       
    40   NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard));
       
    41   for (;;)
       
    42   { 
       
    43     NFind::CFileInfoW fileInfo;
       
    44     bool found;
       
    45     if (!enumerator.Next(fileInfo, found))
       
    46     {
       
    47       errorCodes.Add(::GetLastError());
       
    48       errorPaths.Add(baseFolderPrefix + directory);
       
    49       return;
       
    50     }
       
    51     if (!found)
       
    52       break;
       
    53     AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems);
       
    54     if (fileInfo.IsDirectory())
       
    55     {
       
    56       EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter), 
       
    57           prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes);
       
    58     }
       
    59   }
       
    60 }
       
    61 
       
    62 void EnumerateDirItems(
       
    63     const UString &baseFolderPrefix,   // base (disk) prefix for scanning  
       
    64     const UStringVector &fileNames,    // names relative to baseFolderPrefix
       
    65     const UString &archiveNamePrefix, 
       
    66     CObjectVector<CDirItem> &dirItems,
       
    67     UStringVector &errorPaths,
       
    68     CRecordVector<DWORD> &errorCodes)
       
    69 {
       
    70   for(int i = 0; i < fileNames.Size(); i++)
       
    71   {
       
    72     const UString &fileName = fileNames[i];
       
    73     NFind::CFileInfoW fileInfo;
       
    74     if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo))
       
    75     {
       
    76       errorCodes.Add(::GetLastError());
       
    77       errorPaths.Add(baseFolderPrefix + fileName);
       
    78       continue;
       
    79     }
       
    80     AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems);
       
    81     if (fileInfo.IsDirectory())
       
    82     {
       
    83       EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter), 
       
    84           archiveNamePrefix + fileInfo.Name +  wchar_t(kDirDelimiter), 
       
    85           dirItems, errorPaths, errorCodes);
       
    86     }
       
    87   }
       
    88 }
       
    89 
       
    90 static HRESULT EnumerateDirItems(
       
    91     const NWildcard::CCensorNode &curNode, 
       
    92     const UString &diskPrefix,        // full disk path prefix 
       
    93     const UString &archivePrefix,     // prefix from root
       
    94     const UStringVector &addArchivePrefix,  // prefix from curNode
       
    95     CObjectVector<CDirItem> &dirItems, 
       
    96     bool enterToSubFolders,
       
    97     IEnumDirItemCallback *callback,
       
    98     UStringVector &errorPaths,
       
    99     CRecordVector<DWORD> &errorCodes)
       
   100 {
       
   101   if (!enterToSubFolders)
       
   102     if (curNode.NeedCheckSubDirs())
       
   103       enterToSubFolders = true;
       
   104   if (callback)
       
   105     RINOK(callback->CheckBreak());
       
   106 
       
   107   // try direct_names case at first
       
   108   if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
       
   109   {
       
   110     // check that all names are direct
       
   111     int i;
       
   112     for (i = 0; i < curNode.IncludeItems.Size(); i++)
       
   113     {
       
   114       const NWildcard::CItem &item = curNode.IncludeItems[i];
       
   115       if (item.Recursive || item.PathParts.Size() != 1)
       
   116         break;
       
   117       const UString &name = item.PathParts.Front();
       
   118       if (name.IsEmpty() || DoesNameContainWildCard(name))
       
   119         break;
       
   120     }
       
   121     if (i == curNode.IncludeItems.Size())
       
   122     {
       
   123       // all names are direct (no wildcards)
       
   124       // so we don't need file_system's dir enumerator
       
   125       CRecordVector<bool> needEnterVector;
       
   126       for (i = 0; i < curNode.IncludeItems.Size(); i++)
       
   127       {
       
   128         const NWildcard::CItem &item = curNode.IncludeItems[i];
       
   129         const UString &name = item.PathParts.Front();
       
   130         const UString fullPath = diskPrefix + name;
       
   131         NFind::CFileInfoW fileInfo;
       
   132         if (!NFind::FindFile(fullPath, fileInfo))
       
   133         {
       
   134           errorCodes.Add(::GetLastError());
       
   135           errorPaths.Add(fullPath);
       
   136           continue;
       
   137         }
       
   138         bool isDir = fileInfo.IsDirectory();
       
   139         if (isDir && !item.ForDir || !isDir && !item.ForFile)
       
   140         {
       
   141           errorCodes.Add((DWORD)E_FAIL);
       
   142           errorPaths.Add(fullPath);
       
   143           continue;
       
   144         }
       
   145         const UString realName = fileInfo.Name;
       
   146         const UString realDiskPath = diskPrefix + realName;
       
   147         {
       
   148           UStringVector pathParts;
       
   149           pathParts.Add(fileInfo.Name);
       
   150           if (curNode.CheckPathToRoot(false, pathParts, !isDir))
       
   151             continue;
       
   152         }
       
   153         AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems);
       
   154         if (!isDir)
       
   155           continue;
       
   156         
       
   157         UStringVector addArchivePrefixNew;
       
   158         const NWildcard::CCensorNode *nextNode = 0;
       
   159         int index = curNode.FindSubNode(name);
       
   160         if (index >= 0)
       
   161         {
       
   162           for (int t = needEnterVector.Size(); t <= index; t++)
       
   163             needEnterVector.Add(true);
       
   164           needEnterVector[index] = false;
       
   165           nextNode = &curNode.SubNodes[index];
       
   166         }
       
   167         else
       
   168         {
       
   169           nextNode = &curNode;
       
   170           addArchivePrefixNew.Add(name); // don't change it to realName. It's for shortnames support
       
   171         }
       
   172         RINOK(EnumerateDirItems(*nextNode,   
       
   173             realDiskPath + wchar_t(kDirDelimiter), 
       
   174             archivePrefix + realName + wchar_t(kDirDelimiter), 
       
   175             addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));
       
   176       }
       
   177       for (i = 0; i < curNode.SubNodes.Size(); i++)
       
   178       {
       
   179         if (i < needEnterVector.Size())
       
   180           if (!needEnterVector[i])
       
   181             continue;
       
   182         const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
       
   183         const UString fullPath = diskPrefix + nextNode.Name;
       
   184         NFind::CFileInfoW fileInfo;
       
   185         if (!NFind::FindFile(fullPath, fileInfo))
       
   186         {
       
   187           if (!nextNode.AreThereIncludeItems())
       
   188             continue;
       
   189           errorCodes.Add(::GetLastError());
       
   190           errorPaths.Add(fullPath);
       
   191           continue;
       
   192         }
       
   193         if (!fileInfo.IsDirectory())
       
   194         {
       
   195           errorCodes.Add((DWORD)E_FAIL);
       
   196           errorPaths.Add(fullPath);
       
   197           continue;
       
   198         }
       
   199         RINOK(EnumerateDirItems(nextNode, 
       
   200             diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter), 
       
   201             archivePrefix + fileInfo.Name + wchar_t(kDirDelimiter), 
       
   202             UStringVector(), dirItems, false, callback, errorPaths, errorCodes));
       
   203       }
       
   204       return S_OK;
       
   205     }
       
   206   }
       
   207 
       
   208 
       
   209   NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard));
       
   210   for (;;)
       
   211   {
       
   212     NFind::CFileInfoW fileInfo;
       
   213     bool found;
       
   214     if (!enumerator.Next(fileInfo, found))
       
   215     {
       
   216       errorCodes.Add(::GetLastError());
       
   217       errorPaths.Add(diskPrefix);
       
   218       break;
       
   219     }
       
   220     if (!found)
       
   221       break;
       
   222 
       
   223     if (callback)
       
   224       RINOK(callback->CheckBreak());
       
   225     const UString &name = fileInfo.Name;
       
   226     bool enterToSubFolders2 = enterToSubFolders;
       
   227     UStringVector addArchivePrefixNew = addArchivePrefix;
       
   228     addArchivePrefixNew.Add(name);
       
   229     {
       
   230       UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
       
   231       if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory()))
       
   232         continue;
       
   233     }
       
   234     if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory()))
       
   235     {
       
   236       AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems);
       
   237       if (fileInfo.IsDirectory())
       
   238         enterToSubFolders2 = true;
       
   239     }
       
   240     if (!fileInfo.IsDirectory())
       
   241       continue;
       
   242 
       
   243     const NWildcard::CCensorNode *nextNode = 0;
       
   244     if (addArchivePrefix.IsEmpty())
       
   245     {
       
   246       int index = curNode.FindSubNode(name);
       
   247       if (index >= 0)
       
   248         nextNode = &curNode.SubNodes[index];
       
   249     }
       
   250     if (!enterToSubFolders2 && nextNode == 0)
       
   251       continue;
       
   252 
       
   253     addArchivePrefixNew = addArchivePrefix;
       
   254     if (nextNode == 0)
       
   255     {
       
   256       nextNode = &curNode;
       
   257       addArchivePrefixNew.Add(name);
       
   258     }
       
   259     RINOK(EnumerateDirItems(*nextNode,   
       
   260         diskPrefix + name + wchar_t(kDirDelimiter), 
       
   261         archivePrefix + name + wchar_t(kDirDelimiter), 
       
   262         addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));
       
   263   }
       
   264   return S_OK;
       
   265 }
       
   266 
       
   267 HRESULT EnumerateItems(
       
   268     const NWildcard::CCensor &censor, 
       
   269     CObjectVector<CDirItem> &dirItems, 
       
   270     IEnumDirItemCallback *callback,
       
   271     UStringVector &errorPaths,
       
   272     CRecordVector<DWORD> &errorCodes)
       
   273 {
       
   274   for (int i = 0; i < censor.Pairs.Size(); i++)
       
   275   {
       
   276     const NWildcard::CPair &pair = censor.Pairs[i];
       
   277     RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", UStringVector(), dirItems, false, 
       
   278         callback, errorPaths, errorCodes));
       
   279   }
       
   280   return S_OK;
       
   281 }