| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- // EnumDirItems.cpp
- #include "StdAfx.h"
- #include "Common/StringConvert.h"
- #include "Common/Wildcard.h"
- #include "Common/MyCom.h"
- #include "EnumDirItems.h"
- using namespace NWindows;
- using namespace NFile;
- using namespace NName;
- void AddDirFileInfo(
- const UString &prefix, // prefix for logical path
- const UString &fullPathName, // path on disk: can be relative to some basePrefix
- const NFind::CFileInfoW &fileInfo,
- CObjectVector<CDirItem> &dirItems)
- {
- CDirItem item;
- item.Attributes = fileInfo.Attributes;
- item.Size = fileInfo.Size;
- item.CreationTime = fileInfo.CreationTime;
- item.LastAccessTime = fileInfo.LastAccessTime;
- item.LastWriteTime = fileInfo.LastWriteTime;
- item.Name = prefix + fileInfo.Name;
- item.FullPath = fullPathName;
- dirItems.Add(item);
- }
- static void EnumerateDirectory(
- const UString &baseFolderPrefix, // base (disk) prefix for scanning
- const UString &directory, // additional disk prefix starting from baseFolderPrefix
- const UString &prefix, // logical prefix
- CObjectVector<CDirItem> &dirItems,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes)
- {
- NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard));
- for (;;)
- {
- NFind::CFileInfoW fileInfo;
- bool found;
- if (!enumerator.Next(fileInfo, found))
- {
- errorCodes.Add(::GetLastError());
- errorPaths.Add(baseFolderPrefix + directory);
- return;
- }
- if (!found)
- break;
- AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems);
- if (fileInfo.IsDirectory())
- {
- EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter),
- prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes);
- }
- }
- }
- void EnumerateDirItems(
- const UString &baseFolderPrefix, // base (disk) prefix for scanning
- const UStringVector &fileNames, // names relative to baseFolderPrefix
- const UString &archiveNamePrefix,
- CObjectVector<CDirItem> &dirItems,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes)
- {
- for(int i = 0; i < fileNames.Size(); i++)
- {
- const UString &fileName = fileNames[i];
- NFind::CFileInfoW fileInfo;
- if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo))
- {
- errorCodes.Add(::GetLastError());
- errorPaths.Add(baseFolderPrefix + fileName);
- continue;
- }
- AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems);
- if (fileInfo.IsDirectory())
- {
- EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter),
- archiveNamePrefix + fileInfo.Name + wchar_t(kDirDelimiter),
- dirItems, errorPaths, errorCodes);
- }
- }
- }
- static HRESULT EnumerateDirItems(
- const NWildcard::CCensorNode &curNode,
- const UString &diskPrefix, // full disk path prefix
- const UString &archivePrefix, // prefix from root
- const UStringVector &addArchivePrefix, // prefix from curNode
- CObjectVector<CDirItem> &dirItems,
- bool enterToSubFolders,
- IEnumDirItemCallback *callback,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes)
- {
- if (!enterToSubFolders)
- if (curNode.NeedCheckSubDirs())
- enterToSubFolders = true;
- if (callback)
- RINOK(callback->CheckBreak());
- // try direct_names case at first
- if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
- {
- // check that all names are direct
- int i;
- for (i = 0; i < curNode.IncludeItems.Size(); i++)
- {
- const NWildcard::CItem &item = curNode.IncludeItems[i];
- if (item.Recursive || item.PathParts.Size() != 1)
- break;
- const UString &name = item.PathParts.Front();
- if (name.IsEmpty() || DoesNameContainWildCard(name))
- break;
- }
- if (i == curNode.IncludeItems.Size())
- {
- // all names are direct (no wildcards)
- // so we don't need file_system's dir enumerator
- CRecordVector<bool> needEnterVector;
- for (i = 0; i < curNode.IncludeItems.Size(); i++)
- {
- const NWildcard::CItem &item = curNode.IncludeItems[i];
- const UString &name = item.PathParts.Front();
- const UString fullPath = diskPrefix + name;
- NFind::CFileInfoW fileInfo;
- if (!NFind::FindFile(fullPath, fileInfo))
- {
- errorCodes.Add(::GetLastError());
- errorPaths.Add(fullPath);
- continue;
- }
- bool isDir = fileInfo.IsDirectory();
- if (isDir && !item.ForDir || !isDir && !item.ForFile)
- {
- errorCodes.Add((DWORD)E_FAIL);
- errorPaths.Add(fullPath);
- continue;
- }
- const UString realName = fileInfo.Name;
- const UString realDiskPath = diskPrefix + realName;
- {
- UStringVector pathParts;
- pathParts.Add(fileInfo.Name);
- if (curNode.CheckPathToRoot(false, pathParts, !isDir))
- continue;
- }
- AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems);
- if (!isDir)
- continue;
-
- UStringVector addArchivePrefixNew;
- const NWildcard::CCensorNode *nextNode = 0;
- int index = curNode.FindSubNode(name);
- if (index >= 0)
- {
- for (int t = needEnterVector.Size(); t <= index; t++)
- needEnterVector.Add(true);
- needEnterVector[index] = false;
- nextNode = &curNode.SubNodes[index];
- }
- else
- {
- nextNode = &curNode;
- addArchivePrefixNew.Add(name); // don't change it to realName. It's for shortnames support
- }
- RINOK(EnumerateDirItems(*nextNode,
- realDiskPath + wchar_t(kDirDelimiter),
- archivePrefix + realName + wchar_t(kDirDelimiter),
- addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));
- }
- for (i = 0; i < curNode.SubNodes.Size(); i++)
- {
- if (i < needEnterVector.Size())
- if (!needEnterVector[i])
- continue;
- const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
- const UString fullPath = diskPrefix + nextNode.Name;
- NFind::CFileInfoW fileInfo;
- if (!NFind::FindFile(fullPath, fileInfo))
- {
- if (!nextNode.AreThereIncludeItems())
- continue;
- errorCodes.Add(::GetLastError());
- errorPaths.Add(fullPath);
- continue;
- }
- if (!fileInfo.IsDirectory())
- {
- errorCodes.Add((DWORD)E_FAIL);
- errorPaths.Add(fullPath);
- continue;
- }
- RINOK(EnumerateDirItems(nextNode,
- diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter),
- archivePrefix + fileInfo.Name + wchar_t(kDirDelimiter),
- UStringVector(), dirItems, false, callback, errorPaths, errorCodes));
- }
- return S_OK;
- }
- }
- NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard));
- for (;;)
- {
- NFind::CFileInfoW fileInfo;
- bool found;
- if (!enumerator.Next(fileInfo, found))
- {
- errorCodes.Add(::GetLastError());
- errorPaths.Add(diskPrefix);
- break;
- }
- if (!found)
- break;
- if (callback)
- RINOK(callback->CheckBreak());
- const UString &name = fileInfo.Name;
- bool enterToSubFolders2 = enterToSubFolders;
- UStringVector addArchivePrefixNew = addArchivePrefix;
- addArchivePrefixNew.Add(name);
- {
- UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
- if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory()))
- continue;
- }
- if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory()))
- {
- AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems);
- if (fileInfo.IsDirectory())
- enterToSubFolders2 = true;
- }
- if (!fileInfo.IsDirectory())
- continue;
- const NWildcard::CCensorNode *nextNode = 0;
- if (addArchivePrefix.IsEmpty())
- {
- int index = curNode.FindSubNode(name);
- if (index >= 0)
- nextNode = &curNode.SubNodes[index];
- }
- if (!enterToSubFolders2 && nextNode == 0)
- continue;
- addArchivePrefixNew = addArchivePrefix;
- if (nextNode == 0)
- {
- nextNode = &curNode;
- addArchivePrefixNew.Add(name);
- }
- RINOK(EnumerateDirItems(*nextNode,
- diskPrefix + name + wchar_t(kDirDelimiter),
- archivePrefix + name + wchar_t(kDirDelimiter),
- addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));
- }
- return S_OK;
- }
- HRESULT EnumerateItems(
- const NWildcard::CCensor &censor,
- CObjectVector<CDirItem> &dirItems,
- IEnumDirItemCallback *callback,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes)
- {
- for (int i = 0; i < censor.Pairs.Size(); i++)
- {
- const NWildcard::CPair &pair = censor.Pairs[i];
- RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", UStringVector(), dirItems, false,
- callback, errorPaths, errorCodes));
- }
- return S_OK;
- }
|