| OLD | NEW |
| (Empty) |
| 1 // EnumDirItems.cpp | |
| 2 | |
| 3 #include "StdAfx.h" | |
| 4 | |
| 5 #include <stdio.h> | |
| 6 | |
| 7 #include "Common/StringConvert.h" | |
| 8 #include "Common/Wildcard.h" | |
| 9 #include "Common/MyCom.h" | |
| 10 | |
| 11 #include "EnumDirItems.h" | |
| 12 | |
| 13 using namespace NWindows; | |
| 14 using namespace NFile; | |
| 15 using namespace NName; | |
| 16 | |
| 17 void AddDirFileInfo(int phyParent, int logParent, | |
| 18 const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems) | |
| 19 { | |
| 20 CDirItem di; | |
| 21 di.Size = fi.Size; | |
| 22 di.CTime = fi.CTime; | |
| 23 di.ATime = fi.ATime; | |
| 24 di.MTime = fi.MTime; | |
| 25 di.Attrib = fi.Attrib; | |
| 26 di.PhyParent = phyParent; | |
| 27 di.LogParent = logParent; | |
| 28 di.Name = fi.Name; | |
| 29 dirItems.Add(di); | |
| 30 } | |
| 31 | |
| 32 UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const U
String &name) const | |
| 33 { | |
| 34 UString path; | |
| 35 int len = name.Length(); | |
| 36 int i; | |
| 37 for (i = index; i >= 0; i = parents[i]) | |
| 38 len += Prefixes[i].Length(); | |
| 39 int totalLen = len; | |
| 40 wchar_t *p = path.GetBuffer(len); | |
| 41 p[len] = 0; | |
| 42 len -= name.Length(); | |
| 43 memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); | |
| 44 for (i = index; i >= 0; i = parents[i]) | |
| 45 { | |
| 46 const UString &s = Prefixes[i]; | |
| 47 len -= s.Length(); | |
| 48 memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); | |
| 49 } | |
| 50 path.ReleaseBuffer(totalLen); | |
| 51 return path; | |
| 52 } | |
| 53 | |
| 54 UString CDirItems::GetPhyPath(int index) const | |
| 55 { | |
| 56 const CDirItem &di = Items[index]; | |
| 57 return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); | |
| 58 } | |
| 59 | |
| 60 UString CDirItems::GetLogPath(int index) const | |
| 61 { | |
| 62 const CDirItem &di = Items[index]; | |
| 63 return GetPrefixesPath(LogParents, di.LogParent, di.Name); | |
| 64 } | |
| 65 | |
| 66 void CDirItems::ReserveDown() | |
| 67 { | |
| 68 Prefixes.ReserveDown(); | |
| 69 PhyParents.ReserveDown(); | |
| 70 LogParents.ReserveDown(); | |
| 71 Items.ReserveDown(); | |
| 72 } | |
| 73 | |
| 74 int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) | |
| 75 { | |
| 76 PhyParents.Add(phyParent); | |
| 77 LogParents.Add(logParent); | |
| 78 return Prefixes.Add(prefix); | |
| 79 } | |
| 80 | |
| 81 void CDirItems::DeleteLastPrefix() | |
| 82 { | |
| 83 PhyParents.DeleteBack(); | |
| 84 LogParents.DeleteBack(); | |
| 85 Prefixes.DeleteBack(); | |
| 86 } | |
| 87 | |
| 88 void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &
phyPrefix, | |
| 89 UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) | |
| 90 { | |
| 91 NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); | |
| 92 for (;;) | |
| 93 { | |
| 94 NFind::CFileInfoW fi; | |
| 95 bool found; | |
| 96 if (!enumerator.Next(fi, found)) | |
| 97 { | |
| 98 errorCodes.Add(::GetLastError()); | |
| 99 errorPaths.Add(phyPrefix); | |
| 100 return; | |
| 101 } | |
| 102 if (!found) | |
| 103 break; | |
| 104 AddDirFileInfo(phyParent, logParent, fi, Items); | |
| 105 if (fi.IsDir()) | |
| 106 { | |
| 107 const UString name2 = fi.Name + (wchar_t)kDirDelimiter; | |
| 108 int parent = AddPrefix(phyParent, logParent, name2); | |
| 109 EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCod
es); | |
| 110 } | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logP
refix, | |
| 115 const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWO
RD> &errorCodes) | |
| 116 { | |
| 117 int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); | |
| 118 int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); | |
| 119 | |
| 120 for (int i = 0; i < filePaths.Size(); i++) | |
| 121 { | |
| 122 const UString &filePath = filePaths[i]; | |
| 123 NFind::CFileInfoW fi; | |
| 124 const UString phyPath = phyPrefix + filePath; | |
| 125 if (!NFind::FindFile(phyPath, fi)) | |
| 126 { | |
| 127 errorCodes.Add(::GetLastError()); | |
| 128 errorPaths.Add(phyPath); | |
| 129 continue; | |
| 130 } | |
| 131 int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); | |
| 132 UString phyPrefixCur; | |
| 133 int phyParentCur = phyParent; | |
| 134 if (delimiter >= 0) | |
| 135 { | |
| 136 phyPrefixCur = filePath.Left(delimiter + 1); | |
| 137 phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); | |
| 138 } | |
| 139 AddDirFileInfo(phyParentCur, logParent, fi, Items); | |
| 140 if (fi.IsDir()) | |
| 141 { | |
| 142 const UString name2 = fi.Name + (wchar_t)kDirDelimiter; | |
| 143 int parent = AddPrefix(phyParentCur, logParent, name2); | |
| 144 EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, error
Paths, errorCodes); | |
| 145 } | |
| 146 } | |
| 147 ReserveDown(); | |
| 148 } | |
| 149 | |
| 150 static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, | |
| 151 int phyParent, int logParent, const UString &phyPrefix, | |
| 152 const UStringVector &addArchivePrefix, | |
| 153 CDirItems &dirItems, | |
| 154 bool enterToSubFolders, | |
| 155 IEnumDirItemCallback *callback, | |
| 156 UStringVector &errorPaths, | |
| 157 CRecordVector<DWORD> &errorCodes); | |
| 158 | |
| 159 static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, | |
| 160 int phyParent, int logParent, const UString &curFolderName, | |
| 161 const UString &phyPrefix, | |
| 162 const UStringVector &addArchivePrefix, | |
| 163 CDirItems &dirItems, | |
| 164 bool enterToSubFolders, | |
| 165 IEnumDirItemCallback *callback, | |
| 166 UStringVector &errorPaths, | |
| 167 CRecordVector<DWORD> &errorCodes) | |
| 168 | |
| 169 { | |
| 170 const UString name2 = curFolderName + (wchar_t)kDirDelimiter; | |
| 171 int parent = dirItems.AddPrefix(phyParent, logParent, name2); | |
| 172 int numItems = dirItems.Items.Size(); | |
| 173 HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, | |
| 174 addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCo
des); | |
| 175 if (numItems == dirItems.Items.Size()) | |
| 176 dirItems.DeleteLastPrefix(); | |
| 177 return res; | |
| 178 } | |
| 179 | |
| 180 | |
| 181 static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, | |
| 182 int phyParent, int logParent, const UString &phyPrefix, | |
| 183 const UStringVector &addArchivePrefix, // prefix from curNode | |
| 184 CDirItems &dirItems, | |
| 185 bool enterToSubFolders, | |
| 186 IEnumDirItemCallback *callback, | |
| 187 UStringVector &errorPaths, | |
| 188 CRecordVector<DWORD> &errorCodes) | |
| 189 { | |
| 190 if (!enterToSubFolders) | |
| 191 if (curNode.NeedCheckSubDirs()) | |
| 192 enterToSubFolders = true; | |
| 193 if (callback) | |
| 194 RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size()
, phyPrefix)); | |
| 195 | |
| 196 // try direct_names case at first | |
| 197 if (addArchivePrefix.IsEmpty() && !enterToSubFolders) | |
| 198 { | |
| 199 // check that all names are direct | |
| 200 int i; | |
| 201 for (i = 0; i < curNode.IncludeItems.Size(); i++) | |
| 202 { | |
| 203 const NWildcard::CItem &item = curNode.IncludeItems[i]; | |
| 204 if (item.Recursive || item.PathParts.Size() != 1) | |
| 205 break; | |
| 206 const UString &name = item.PathParts.Front(); | |
| 207 if (name.IsEmpty() || DoesNameContainWildCard(name)) | |
| 208 break; | |
| 209 } | |
| 210 if (i == curNode.IncludeItems.Size()) | |
| 211 { | |
| 212 // all names are direct (no wildcards) | |
| 213 // so we don't need file_system's dir enumerator | |
| 214 CRecordVector<bool> needEnterVector; | |
| 215 for (i = 0; i < curNode.IncludeItems.Size(); i++) | |
| 216 { | |
| 217 const NWildcard::CItem &item = curNode.IncludeItems[i]; | |
| 218 const UString &name = item.PathParts.Front(); | |
| 219 const UString fullPath = phyPrefix + name; | |
| 220 NFind::CFileInfoW fi; | |
| 221 if (!NFind::FindFile(fullPath, fi)) | |
| 222 { | |
| 223 errorCodes.Add(::GetLastError()); | |
| 224 errorPaths.Add(fullPath); | |
| 225 continue; | |
| 226 } | |
| 227 bool isDir = fi.IsDir(); | |
| 228 if (isDir && !item.ForDir || !isDir && !item.ForFile) | |
| 229 { | |
| 230 errorCodes.Add((DWORD)E_FAIL); | |
| 231 errorPaths.Add(fullPath); | |
| 232 continue; | |
| 233 } | |
| 234 { | |
| 235 UStringVector pathParts; | |
| 236 pathParts.Add(fi.Name); | |
| 237 if (curNode.CheckPathToRoot(false, pathParts, !isDir)) | |
| 238 continue; | |
| 239 } | |
| 240 AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); | |
| 241 if (!isDir) | |
| 242 continue; | |
| 243 | |
| 244 UStringVector addArchivePrefixNew; | |
| 245 const NWildcard::CCensorNode *nextNode = 0; | |
| 246 int index = curNode.FindSubNode(name); | |
| 247 if (index >= 0) | |
| 248 { | |
| 249 for (int t = needEnterVector.Size(); t <= index; t++) | |
| 250 needEnterVector.Add(true); | |
| 251 needEnterVector[index] = false; | |
| 252 nextNode = &curNode.SubNodes[index]; | |
| 253 } | |
| 254 else | |
| 255 { | |
| 256 nextNode = &curNode; | |
| 257 addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for
shortnames support | |
| 258 } | |
| 259 | |
| 260 RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, p
hyPrefix, | |
| 261 addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCode
s)); | |
| 262 } | |
| 263 for (i = 0; i < curNode.SubNodes.Size(); i++) | |
| 264 { | |
| 265 if (i < needEnterVector.Size()) | |
| 266 if (!needEnterVector[i]) | |
| 267 continue; | |
| 268 const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; | |
| 269 const UString fullPath = phyPrefix + nextNode.Name; | |
| 270 NFind::CFileInfoW fi; | |
| 271 if (!NFind::FindFile(fullPath, fi)) | |
| 272 { | |
| 273 if (!nextNode.AreThereIncludeItems()) | |
| 274 continue; | |
| 275 errorCodes.Add(::GetLastError()); | |
| 276 errorPaths.Add(fullPath); | |
| 277 continue; | |
| 278 } | |
| 279 if (!fi.IsDir()) | |
| 280 { | |
| 281 errorCodes.Add((DWORD)E_FAIL); | |
| 282 errorPaths.Add(fullPath); | |
| 283 continue; | |
| 284 } | |
| 285 | |
| 286 RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, ph
yPrefix, | |
| 287 UStringVector(), dirItems, false, callback, errorPaths, errorCodes))
; | |
| 288 } | |
| 289 return S_OK; | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 | |
| 294 NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); | |
| 295 for (int ttt = 0; ; ttt++) | |
| 296 { | |
| 297 NFind::CFileInfoW fi; | |
| 298 bool found; | |
| 299 if (!enumerator.Next(fi, found)) | |
| 300 { | |
| 301 errorCodes.Add(::GetLastError()); | |
| 302 errorPaths.Add(phyPrefix); | |
| 303 break; | |
| 304 } | |
| 305 if (!found) | |
| 306 break; | |
| 307 | |
| 308 if (callback && (ttt & 0xFF) == 0xFF) | |
| 309 RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size
(), phyPrefix)); | |
| 310 const UString &name = fi.Name; | |
| 311 bool enterToSubFolders2 = enterToSubFolders; | |
| 312 UStringVector addArchivePrefixNew = addArchivePrefix; | |
| 313 addArchivePrefixNew.Add(name); | |
| 314 { | |
| 315 UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); | |
| 316 if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) | |
| 317 continue; | |
| 318 } | |
| 319 if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) | |
| 320 { | |
| 321 AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); | |
| 322 if (fi.IsDir()) | |
| 323 enterToSubFolders2 = true; | |
| 324 } | |
| 325 if (!fi.IsDir()) | |
| 326 continue; | |
| 327 | |
| 328 const NWildcard::CCensorNode *nextNode = 0; | |
| 329 if (addArchivePrefix.IsEmpty()) | |
| 330 { | |
| 331 int index = curNode.FindSubNode(name); | |
| 332 if (index >= 0) | |
| 333 nextNode = &curNode.SubNodes[index]; | |
| 334 } | |
| 335 if (!enterToSubFolders2 && nextNode == 0) | |
| 336 continue; | |
| 337 | |
| 338 addArchivePrefixNew = addArchivePrefix; | |
| 339 if (nextNode == 0) | |
| 340 { | |
| 341 nextNode = &curNode; | |
| 342 addArchivePrefixNew.Add(name); | |
| 343 } | |
| 344 | |
| 345 RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefi
x, | |
| 346 addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths,
errorCodes)); | |
| 347 } | |
| 348 return S_OK; | |
| 349 } | |
| 350 | |
| 351 HRESULT EnumerateItems( | |
| 352 const NWildcard::CCensor &censor, | |
| 353 CDirItems &dirItems, | |
| 354 IEnumDirItemCallback *callback, | |
| 355 UStringVector &errorPaths, | |
| 356 CRecordVector<DWORD> &errorCodes) | |
| 357 { | |
| 358 for (int i = 0; i < censor.Pairs.Size(); i++) | |
| 359 { | |
| 360 const NWildcard::CPair &pair = censor.Pairs[i]; | |
| 361 int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair
.Prefix); | |
| 362 RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector
(), dirItems, false, | |
| 363 callback, errorPaths, errorCodes)); | |
| 364 } | |
| 365 dirItems.ReserveDown(); | |
| 366 return S_OK; | |
| 367 } | |
| OLD | NEW |