1370b324cSopenharmony_ci// EnumDirItems.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include <wchar.h>
6370b324cSopenharmony_ci// #include <stdio.h>
7370b324cSopenharmony_ci
8370b324cSopenharmony_ci#ifndef _WIN32
9370b324cSopenharmony_ci#include <grp.h>
10370b324cSopenharmony_ci#include <pwd.h>
11370b324cSopenharmony_ci#include "../../../Common/UTFConvert.h"
12370b324cSopenharmony_ci#endif
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci#include "../../../Common/Wildcard.h"
15370b324cSopenharmony_ci
16370b324cSopenharmony_ci#include "../../../Windows/FileDir.h"
17370b324cSopenharmony_ci#include "../../../Windows/FileIO.h"
18370b324cSopenharmony_ci#include "../../../Windows/FileName.h"
19370b324cSopenharmony_ci
20370b324cSopenharmony_ci#if defined(_WIN32) && !defined(UNDER_CE)
21370b324cSopenharmony_ci#define Z7_USE_SECURITY_CODE
22370b324cSopenharmony_ci#include "../../../Windows/SecurityUtils.h"
23370b324cSopenharmony_ci#endif
24370b324cSopenharmony_ci
25370b324cSopenharmony_ci#include "EnumDirItems.h"
26370b324cSopenharmony_ci#include "SortUtils.h"
27370b324cSopenharmony_ci
28370b324cSopenharmony_ciusing namespace NWindows;
29370b324cSopenharmony_ciusing namespace NFile;
30370b324cSopenharmony_ciusing namespace NName;
31370b324cSopenharmony_ci
32370b324cSopenharmony_ci
33370b324cSopenharmony_cistatic bool FindFile_KeepDots(NFile::NFind::CFileInfo &fi, const FString &path, bool followLink)
34370b324cSopenharmony_ci{
35370b324cSopenharmony_ci  const bool res = fi.Find(path, followLink);
36370b324cSopenharmony_ci  if (!res)
37370b324cSopenharmony_ci    return res;
38370b324cSopenharmony_ci  if (path.IsEmpty())
39370b324cSopenharmony_ci    return res;
40370b324cSopenharmony_ci  // we keep name "." and "..", if it's without tail slash
41370b324cSopenharmony_ci  const FChar *p = path.RightPtr(1);
42370b324cSopenharmony_ci  if (*p != '.')
43370b324cSopenharmony_ci    return res;
44370b324cSopenharmony_ci  if (p != path.Ptr())
45370b324cSopenharmony_ci  {
46370b324cSopenharmony_ci    FChar c = p[-1];
47370b324cSopenharmony_ci    if (!IS_PATH_SEPAR(c))
48370b324cSopenharmony_ci    {
49370b324cSopenharmony_ci      if (c != '.')
50370b324cSopenharmony_ci        return res;
51370b324cSopenharmony_ci      p--;
52370b324cSopenharmony_ci      if (p != path.Ptr())
53370b324cSopenharmony_ci      {
54370b324cSopenharmony_ci        c = p[-1];
55370b324cSopenharmony_ci        if (!IS_PATH_SEPAR(c))
56370b324cSopenharmony_ci          return res;
57370b324cSopenharmony_ci      }
58370b324cSopenharmony_ci    }
59370b324cSopenharmony_ci  }
60370b324cSopenharmony_ci  fi.Name = p;
61370b324cSopenharmony_ci  return res;
62370b324cSopenharmony_ci}
63370b324cSopenharmony_ci
64370b324cSopenharmony_ci
65370b324cSopenharmony_civoid CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex,
66370b324cSopenharmony_ci    const NFind::CFileInfo &fi)
67370b324cSopenharmony_ci{
68370b324cSopenharmony_ci  /*
69370b324cSopenharmony_ci  CDirItem di(fi);
70370b324cSopenharmony_ci  di.PhyParent = phyParent;
71370b324cSopenharmony_ci  di.LogParent = logParent;
72370b324cSopenharmony_ci  di.SecureIndex = secureIndex;
73370b324cSopenharmony_ci  Items.Add(di);
74370b324cSopenharmony_ci  */
75370b324cSopenharmony_ci  VECTOR_ADD_NEW_OBJECT (Items, CDirItem(fi, phyParent, logParent, secureIndex))
76370b324cSopenharmony_ci
77370b324cSopenharmony_ci  if (fi.IsDir())
78370b324cSopenharmony_ci    Stat.NumDirs++;
79370b324cSopenharmony_ci #ifdef _WIN32
80370b324cSopenharmony_ci  else if (fi.IsAltStream)
81370b324cSopenharmony_ci  {
82370b324cSopenharmony_ci    Stat.NumAltStreams++;
83370b324cSopenharmony_ci    Stat.AltStreamsSize += fi.Size;
84370b324cSopenharmony_ci  }
85370b324cSopenharmony_ci #endif
86370b324cSopenharmony_ci  else
87370b324cSopenharmony_ci  {
88370b324cSopenharmony_ci    Stat.NumFiles++;
89370b324cSopenharmony_ci    Stat.FilesSize += fi.Size;
90370b324cSopenharmony_ci  }
91370b324cSopenharmony_ci}
92370b324cSopenharmony_ci
93370b324cSopenharmony_ci// (DWORD)E_FAIL
94370b324cSopenharmony_ci#define DI_DEFAULT_ERROR  ERROR_INVALID_FUNCTION
95370b324cSopenharmony_ci
96370b324cSopenharmony_ciHRESULT CDirItems::AddError(const FString &path, DWORD errorCode)
97370b324cSopenharmony_ci{
98370b324cSopenharmony_ci  if (errorCode == 0)
99370b324cSopenharmony_ci    errorCode = DI_DEFAULT_ERROR;
100370b324cSopenharmony_ci  Stat.NumErrors++;
101370b324cSopenharmony_ci  if (Callback)
102370b324cSopenharmony_ci    return Callback->ScanError(path, errorCode);
103370b324cSopenharmony_ci  return S_OK;
104370b324cSopenharmony_ci}
105370b324cSopenharmony_ci
106370b324cSopenharmony_ciHRESULT CDirItems::AddError(const FString &path)
107370b324cSopenharmony_ci{
108370b324cSopenharmony_ci  return AddError(path, ::GetLastError());
109370b324cSopenharmony_ci}
110370b324cSopenharmony_ci
111370b324cSopenharmony_cistatic const unsigned kScanProgressStepMask = (1 << 12) - 1;
112370b324cSopenharmony_ci
113370b324cSopenharmony_ciHRESULT CDirItems::ScanProgress(const FString &dirPath)
114370b324cSopenharmony_ci{
115370b324cSopenharmony_ci  if (Callback)
116370b324cSopenharmony_ci    return Callback->ScanProgress(Stat, dirPath, true);
117370b324cSopenharmony_ci  return S_OK;
118370b324cSopenharmony_ci}
119370b324cSopenharmony_ci
120370b324cSopenharmony_ciUString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const
121370b324cSopenharmony_ci{
122370b324cSopenharmony_ci  UString path;
123370b324cSopenharmony_ci  unsigned len = name.Len();
124370b324cSopenharmony_ci
125370b324cSopenharmony_ci  int i;
126370b324cSopenharmony_ci  for (i = index; i >= 0; i = parents[(unsigned)i])
127370b324cSopenharmony_ci    len += Prefixes[(unsigned)i].Len();
128370b324cSopenharmony_ci
129370b324cSopenharmony_ci  wchar_t *p = path.GetBuf_SetEnd(len) + len;
130370b324cSopenharmony_ci
131370b324cSopenharmony_ci  p -= name.Len();
132370b324cSopenharmony_ci  wmemcpy(p, (const wchar_t *)name, name.Len());
133370b324cSopenharmony_ci
134370b324cSopenharmony_ci  for (i = index; i >= 0; i = parents[(unsigned)i])
135370b324cSopenharmony_ci  {
136370b324cSopenharmony_ci    const UString &s = Prefixes[(unsigned)i];
137370b324cSopenharmony_ci    p -= s.Len();
138370b324cSopenharmony_ci    wmemcpy(p, (const wchar_t *)s, s.Len());
139370b324cSopenharmony_ci  }
140370b324cSopenharmony_ci
141370b324cSopenharmony_ci  return path;
142370b324cSopenharmony_ci}
143370b324cSopenharmony_ci
144370b324cSopenharmony_ciFString CDirItems::GetPhyPath(unsigned index) const
145370b324cSopenharmony_ci{
146370b324cSopenharmony_ci  const CDirItem &di = Items[index];
147370b324cSopenharmony_ci  return us2fs(GetPrefixesPath(PhyParents, di.PhyParent, di.Name));
148370b324cSopenharmony_ci}
149370b324cSopenharmony_ci
150370b324cSopenharmony_ciUString CDirItems::GetLogPath(unsigned index) const
151370b324cSopenharmony_ci{
152370b324cSopenharmony_ci  const CDirItem &di = Items[index];
153370b324cSopenharmony_ci  return GetPrefixesPath(LogParents, di.LogParent, di.Name);
154370b324cSopenharmony_ci}
155370b324cSopenharmony_ci
156370b324cSopenharmony_civoid CDirItems::ReserveDown()
157370b324cSopenharmony_ci{
158370b324cSopenharmony_ci  Prefixes.ReserveDown();
159370b324cSopenharmony_ci  PhyParents.ReserveDown();
160370b324cSopenharmony_ci  LogParents.ReserveDown();
161370b324cSopenharmony_ci  Items.ReserveDown();
162370b324cSopenharmony_ci}
163370b324cSopenharmony_ci
164370b324cSopenharmony_ciunsigned CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)
165370b324cSopenharmony_ci{
166370b324cSopenharmony_ci  PhyParents.Add(phyParent);
167370b324cSopenharmony_ci  LogParents.Add(logParent);
168370b324cSopenharmony_ci  return Prefixes.Add(prefix);
169370b324cSopenharmony_ci}
170370b324cSopenharmony_ci
171370b324cSopenharmony_civoid CDirItems::DeleteLastPrefix()
172370b324cSopenharmony_ci{
173370b324cSopenharmony_ci  PhyParents.DeleteBack();
174370b324cSopenharmony_ci  LogParents.DeleteBack();
175370b324cSopenharmony_ci  Prefixes.DeleteBack();
176370b324cSopenharmony_ci}
177370b324cSopenharmony_ci
178370b324cSopenharmony_cibool InitLocalPrivileges();
179370b324cSopenharmony_ci
180370b324cSopenharmony_ciCDirItems::CDirItems():
181370b324cSopenharmony_ci    SymLinks(false),
182370b324cSopenharmony_ci    ScanAltStreams(false)
183370b324cSopenharmony_ci    , ExcludeDirItems(false)
184370b324cSopenharmony_ci    , ExcludeFileItems(false)
185370b324cSopenharmony_ci    , ShareForWrite(false)
186370b324cSopenharmony_ci   #ifdef Z7_USE_SECURITY_CODE
187370b324cSopenharmony_ci    , ReadSecure(false)
188370b324cSopenharmony_ci   #endif
189370b324cSopenharmony_ci   #ifndef _WIN32
190370b324cSopenharmony_ci    , StoreOwnerName(false)
191370b324cSopenharmony_ci   #endif
192370b324cSopenharmony_ci    , Callback(NULL)
193370b324cSopenharmony_ci{
194370b324cSopenharmony_ci  #ifdef Z7_USE_SECURITY_CODE
195370b324cSopenharmony_ci  _saclEnabled = InitLocalPrivileges();
196370b324cSopenharmony_ci  #endif
197370b324cSopenharmony_ci}
198370b324cSopenharmony_ci
199370b324cSopenharmony_ci
200370b324cSopenharmony_ci#ifdef Z7_USE_SECURITY_CODE
201370b324cSopenharmony_ci
202370b324cSopenharmony_ciHRESULT CDirItems::AddSecurityItem(const FString &path, int &secureIndex)
203370b324cSopenharmony_ci{
204370b324cSopenharmony_ci  secureIndex = -1;
205370b324cSopenharmony_ci
206370b324cSopenharmony_ci  SECURITY_INFORMATION securInfo =
207370b324cSopenharmony_ci      DACL_SECURITY_INFORMATION |
208370b324cSopenharmony_ci      GROUP_SECURITY_INFORMATION |
209370b324cSopenharmony_ci      OWNER_SECURITY_INFORMATION;
210370b324cSopenharmony_ci  if (_saclEnabled)
211370b324cSopenharmony_ci    securInfo |= SACL_SECURITY_INFORMATION;
212370b324cSopenharmony_ci
213370b324cSopenharmony_ci  DWORD errorCode = 0;
214370b324cSopenharmony_ci  DWORD secureSize;
215370b324cSopenharmony_ci
216370b324cSopenharmony_ci  BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize);
217370b324cSopenharmony_ci
218370b324cSopenharmony_ci  if (res)
219370b324cSopenharmony_ci  {
220370b324cSopenharmony_ci    if (secureSize == 0)
221370b324cSopenharmony_ci      return S_OK;
222370b324cSopenharmony_ci    if (secureSize > TempSecureBuf.Size())
223370b324cSopenharmony_ci      errorCode = ERROR_INVALID_FUNCTION;
224370b324cSopenharmony_ci  }
225370b324cSopenharmony_ci  else
226370b324cSopenharmony_ci  {
227370b324cSopenharmony_ci    errorCode = GetLastError();
228370b324cSopenharmony_ci    if (errorCode == ERROR_INSUFFICIENT_BUFFER)
229370b324cSopenharmony_ci    {
230370b324cSopenharmony_ci      if (secureSize <= TempSecureBuf.Size())
231370b324cSopenharmony_ci        errorCode = ERROR_INVALID_FUNCTION;
232370b324cSopenharmony_ci      else
233370b324cSopenharmony_ci      {
234370b324cSopenharmony_ci        TempSecureBuf.Alloc(secureSize);
235370b324cSopenharmony_ci        res = ::GetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(Byte *)TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize);
236370b324cSopenharmony_ci        if (res)
237370b324cSopenharmony_ci        {
238370b324cSopenharmony_ci          if (secureSize != TempSecureBuf.Size())
239370b324cSopenharmony_ci            errorCode = ERROR_INVALID_FUNCTION;
240370b324cSopenharmony_ci        }
241370b324cSopenharmony_ci        else
242370b324cSopenharmony_ci          errorCode = GetLastError();
243370b324cSopenharmony_ci      }
244370b324cSopenharmony_ci    }
245370b324cSopenharmony_ci  }
246370b324cSopenharmony_ci
247370b324cSopenharmony_ci  if (res)
248370b324cSopenharmony_ci  {
249370b324cSopenharmony_ci    secureIndex = (int)SecureBlocks.AddUniq(TempSecureBuf, secureSize);
250370b324cSopenharmony_ci    return S_OK;
251370b324cSopenharmony_ci  }
252370b324cSopenharmony_ci
253370b324cSopenharmony_ci  return AddError(path, errorCode);
254370b324cSopenharmony_ci}
255370b324cSopenharmony_ci
256370b324cSopenharmony_ci#endif // Z7_USE_SECURITY_CODE
257370b324cSopenharmony_ci
258370b324cSopenharmony_ci
259370b324cSopenharmony_ciHRESULT CDirItems::EnumerateOneDir(const FString &phyPrefix, CObjectVector<NFind::CFileInfo> &files)
260370b324cSopenharmony_ci{
261370b324cSopenharmony_ci  NFind::CEnumerator enumerator;
262370b324cSopenharmony_ci  // printf("\n  enumerator.SetDirPrefix(phyPrefix) \n");
263370b324cSopenharmony_ci
264370b324cSopenharmony_ci  enumerator.SetDirPrefix(phyPrefix);
265370b324cSopenharmony_ci
266370b324cSopenharmony_ci  #ifdef _WIN32
267370b324cSopenharmony_ci
268370b324cSopenharmony_ci  NFind::CFileInfo fi;
269370b324cSopenharmony_ci
270370b324cSopenharmony_ci  for (unsigned ttt = 0; ; ttt++)
271370b324cSopenharmony_ci  {
272370b324cSopenharmony_ci    bool found;
273370b324cSopenharmony_ci    if (!enumerator.Next(fi, found))
274370b324cSopenharmony_ci      return AddError(phyPrefix);
275370b324cSopenharmony_ci    if (!found)
276370b324cSopenharmony_ci      return S_OK;
277370b324cSopenharmony_ci    files.Add(fi);
278370b324cSopenharmony_ci    if (Callback && (ttt & kScanProgressStepMask) == kScanProgressStepMask)
279370b324cSopenharmony_ci    {
280370b324cSopenharmony_ci      RINOK(ScanProgress(phyPrefix))
281370b324cSopenharmony_ci    }
282370b324cSopenharmony_ci  }
283370b324cSopenharmony_ci
284370b324cSopenharmony_ci  #else // _WIN32
285370b324cSopenharmony_ci
286370b324cSopenharmony_ci  // enumerator.SolveLinks = !SymLinks;
287370b324cSopenharmony_ci
288370b324cSopenharmony_ci  CObjectVector<NFind::CDirEntry> entries;
289370b324cSopenharmony_ci
290370b324cSopenharmony_ci  for (unsigned ttt = 0; ; ttt++)
291370b324cSopenharmony_ci  {
292370b324cSopenharmony_ci    bool found;
293370b324cSopenharmony_ci    NFind::CDirEntry de;
294370b324cSopenharmony_ci    if (!enumerator.Next(de, found))
295370b324cSopenharmony_ci    {
296370b324cSopenharmony_ci      return AddError(phyPrefix);
297370b324cSopenharmony_ci    }
298370b324cSopenharmony_ci    if (!found)
299370b324cSopenharmony_ci      break;
300370b324cSopenharmony_ci    entries.Add(de);
301370b324cSopenharmony_ci  }
302370b324cSopenharmony_ci
303370b324cSopenharmony_ci  FOR_VECTOR(i, entries)
304370b324cSopenharmony_ci  {
305370b324cSopenharmony_ci    const NFind::CDirEntry &de = entries[i];
306370b324cSopenharmony_ci    NFind::CFileInfo fi;
307370b324cSopenharmony_ci    if (!enumerator.Fill_FileInfo(de, fi, !SymLinks))
308370b324cSopenharmony_ci    // if (!fi.Find_AfterEnumerator(path))
309370b324cSopenharmony_ci    {
310370b324cSopenharmony_ci      const FString path = phyPrefix + de.Name;
311370b324cSopenharmony_ci      {
312370b324cSopenharmony_ci        RINOK(AddError(path))
313370b324cSopenharmony_ci        continue;
314370b324cSopenharmony_ci      }
315370b324cSopenharmony_ci    }
316370b324cSopenharmony_ci
317370b324cSopenharmony_ci    files.Add(fi);
318370b324cSopenharmony_ci
319370b324cSopenharmony_ci    if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask)
320370b324cSopenharmony_ci    {
321370b324cSopenharmony_ci      RINOK(ScanProgress(phyPrefix))
322370b324cSopenharmony_ci    }
323370b324cSopenharmony_ci  }
324370b324cSopenharmony_ci
325370b324cSopenharmony_ci  return S_OK;
326370b324cSopenharmony_ci
327370b324cSopenharmony_ci  #endif // _WIN32
328370b324cSopenharmony_ci}
329370b324cSopenharmony_ci
330370b324cSopenharmony_ci
331370b324cSopenharmony_ci
332370b324cSopenharmony_ci
333370b324cSopenharmony_ciHRESULT CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix)
334370b324cSopenharmony_ci{
335370b324cSopenharmony_ci  RINOK(ScanProgress(phyPrefix))
336370b324cSopenharmony_ci
337370b324cSopenharmony_ci  CObjectVector<NFind::CFileInfo> files;
338370b324cSopenharmony_ci  RINOK(EnumerateOneDir(phyPrefix, files))
339370b324cSopenharmony_ci
340370b324cSopenharmony_ci  FOR_VECTOR (i, files)
341370b324cSopenharmony_ci  {
342370b324cSopenharmony_ci    #ifdef _WIN32
343370b324cSopenharmony_ci    const NFind::CFileInfo &fi = files[i];
344370b324cSopenharmony_ci    #else
345370b324cSopenharmony_ci    const NFind::CFileInfo &fi = files[i];
346370b324cSopenharmony_ci    /*
347370b324cSopenharmony_ci    NFind::CFileInfo fi;
348370b324cSopenharmony_ci    {
349370b324cSopenharmony_ci      const NFind::CDirEntry &di = files[i];
350370b324cSopenharmony_ci      const FString path = phyPrefix + di.Name;
351370b324cSopenharmony_ci      if (!fi.Find_AfterEnumerator(path))
352370b324cSopenharmony_ci      {
353370b324cSopenharmony_ci        RINOK(AddError(path));
354370b324cSopenharmony_ci        continue;
355370b324cSopenharmony_ci      }
356370b324cSopenharmony_ci      fi.Name = di.Name;
357370b324cSopenharmony_ci    }
358370b324cSopenharmony_ci    */
359370b324cSopenharmony_ci    #endif
360370b324cSopenharmony_ci
361370b324cSopenharmony_ci    if (CanIncludeItem(fi.IsDir()))
362370b324cSopenharmony_ci    {
363370b324cSopenharmony_ci    int secureIndex = -1;
364370b324cSopenharmony_ci    #ifdef Z7_USE_SECURITY_CODE
365370b324cSopenharmony_ci    if (ReadSecure)
366370b324cSopenharmony_ci    {
367370b324cSopenharmony_ci      RINOK(AddSecurityItem(phyPrefix + fi.Name, secureIndex))
368370b324cSopenharmony_ci    }
369370b324cSopenharmony_ci    #endif
370370b324cSopenharmony_ci    AddDirFileInfo(phyParent, logParent, secureIndex, fi);
371370b324cSopenharmony_ci    }
372370b324cSopenharmony_ci
373370b324cSopenharmony_ci    if (Callback && (i & kScanProgressStepMask) == kScanProgressStepMask)
374370b324cSopenharmony_ci    {
375370b324cSopenharmony_ci      RINOK(ScanProgress(phyPrefix))
376370b324cSopenharmony_ci    }
377370b324cSopenharmony_ci
378370b324cSopenharmony_ci    if (fi.IsDir())
379370b324cSopenharmony_ci    {
380370b324cSopenharmony_ci      const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;
381370b324cSopenharmony_ci      unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2));
382370b324cSopenharmony_ci      RINOK(EnumerateDir((int)parent, (int)parent, phyPrefix + name2))
383370b324cSopenharmony_ci    }
384370b324cSopenharmony_ci  }
385370b324cSopenharmony_ci  return S_OK;
386370b324cSopenharmony_ci}
387370b324cSopenharmony_ci
388370b324cSopenharmony_ci
389370b324cSopenharmony_ci/*
390370b324cSopenharmony_ciEnumerateItems2()
391370b324cSopenharmony_ci  const FStringVector &filePaths - are path without tail slashes.
392370b324cSopenharmony_ci  All dir prefixes of filePaths will be not stores in logical paths
393370b324cSopenharmony_cifix it: we can scan AltStream also.
394370b324cSopenharmony_ci*/
395370b324cSopenharmony_ci
396370b324cSopenharmony_ci#ifdef _WIN32
397370b324cSopenharmony_ci// #define FOLLOW_LINK_PARAM
398370b324cSopenharmony_ci// #define FOLLOW_LINK_PARAM2
399370b324cSopenharmony_ci#define FOLLOW_LINK_PARAM , (!SymLinks)
400370b324cSopenharmony_ci#define FOLLOW_LINK_PARAM2 , (!dirItems.SymLinks)
401370b324cSopenharmony_ci#else
402370b324cSopenharmony_ci#define FOLLOW_LINK_PARAM , (!SymLinks)
403370b324cSopenharmony_ci#define FOLLOW_LINK_PARAM2 , (!dirItems.SymLinks)
404370b324cSopenharmony_ci#endif
405370b324cSopenharmony_ci
406370b324cSopenharmony_ciHRESULT CDirItems::EnumerateItems2(
407370b324cSopenharmony_ci    const FString &phyPrefix,
408370b324cSopenharmony_ci    const UString &logPrefix,
409370b324cSopenharmony_ci    const FStringVector &filePaths,
410370b324cSopenharmony_ci    FStringVector *requestedPaths)
411370b324cSopenharmony_ci{
412370b324cSopenharmony_ci  const int phyParent = phyPrefix.IsEmpty() ? -1 : (int)AddPrefix(-1, -1, fs2us(phyPrefix));
413370b324cSopenharmony_ci  const int logParent = logPrefix.IsEmpty() ? -1 : (int)AddPrefix(-1, -1, logPrefix);
414370b324cSopenharmony_ci
415370b324cSopenharmony_ci #ifdef _WIN32
416370b324cSopenharmony_ci  const bool phyPrefix_isAltStreamPrefix =
417370b324cSopenharmony_ci      NFile::NName::IsAltStreamPrefixWithColon(fs2us(phyPrefix));
418370b324cSopenharmony_ci #endif
419370b324cSopenharmony_ci
420370b324cSopenharmony_ci  FOR_VECTOR (i, filePaths)
421370b324cSopenharmony_ci  {
422370b324cSopenharmony_ci    const FString &filePath = filePaths[i];
423370b324cSopenharmony_ci    NFind::CFileInfo fi;
424370b324cSopenharmony_ci    const FString phyPath = phyPrefix + filePath;
425370b324cSopenharmony_ci    if (!FindFile_KeepDots(fi, phyPath  FOLLOW_LINK_PARAM))
426370b324cSopenharmony_ci    {
427370b324cSopenharmony_ci      RINOK(AddError(phyPath))
428370b324cSopenharmony_ci      continue;
429370b324cSopenharmony_ci    }
430370b324cSopenharmony_ci    if (requestedPaths)
431370b324cSopenharmony_ci      requestedPaths->Add(phyPath);
432370b324cSopenharmony_ci
433370b324cSopenharmony_ci    const int delimiter = filePath.ReverseFind_PathSepar();
434370b324cSopenharmony_ci    FString phyPrefixCur;
435370b324cSopenharmony_ci    int phyParentCur = phyParent;
436370b324cSopenharmony_ci    if (delimiter >= 0)
437370b324cSopenharmony_ci    {
438370b324cSopenharmony_ci      phyPrefixCur.SetFrom(filePath, (unsigned)(delimiter + 1));
439370b324cSopenharmony_ci      phyParentCur = (int)AddPrefix(phyParent, logParent, fs2us(phyPrefixCur));
440370b324cSopenharmony_ci    }
441370b324cSopenharmony_ci
442370b324cSopenharmony_ci    if (CanIncludeItem(fi.IsDir()))
443370b324cSopenharmony_ci    {
444370b324cSopenharmony_ci    int secureIndex = -1;
445370b324cSopenharmony_ci    #ifdef Z7_USE_SECURITY_CODE
446370b324cSopenharmony_ci    if (ReadSecure)
447370b324cSopenharmony_ci    {
448370b324cSopenharmony_ci      RINOK(AddSecurityItem(phyPath, secureIndex))
449370b324cSopenharmony_ci    }
450370b324cSopenharmony_ci    #endif
451370b324cSopenharmony_ci   #ifdef _WIN32
452370b324cSopenharmony_ci    if (phyPrefix_isAltStreamPrefix && fi.IsAltStream)
453370b324cSopenharmony_ci    {
454370b324cSopenharmony_ci      const int pos = fi.Name.Find(FChar(':'));
455370b324cSopenharmony_ci      if (pos >= 0)
456370b324cSopenharmony_ci        fi.Name.DeleteFrontal((unsigned)pos + 1);
457370b324cSopenharmony_ci    }
458370b324cSopenharmony_ci   #endif
459370b324cSopenharmony_ci    AddDirFileInfo(phyParentCur, logParent, secureIndex, fi);
460370b324cSopenharmony_ci    }
461370b324cSopenharmony_ci
462370b324cSopenharmony_ci    if (fi.IsDir())
463370b324cSopenharmony_ci    {
464370b324cSopenharmony_ci      const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;
465370b324cSopenharmony_ci      const unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2));
466370b324cSopenharmony_ci      RINOK(EnumerateDir((int)parent, (int)parent, phyPrefix + phyPrefixCur + name2))
467370b324cSopenharmony_ci    }
468370b324cSopenharmony_ci  }
469370b324cSopenharmony_ci
470370b324cSopenharmony_ci  ReserveDown();
471370b324cSopenharmony_ci  return S_OK;
472370b324cSopenharmony_ci}
473370b324cSopenharmony_ci
474370b324cSopenharmony_ci
475370b324cSopenharmony_ci
476370b324cSopenharmony_ci
477370b324cSopenharmony_cistatic HRESULT EnumerateDirItems(
478370b324cSopenharmony_ci    const NWildcard::CCensorNode &curNode,
479370b324cSopenharmony_ci    const int phyParent, const int logParent,
480370b324cSopenharmony_ci    const FString &phyPrefix,
481370b324cSopenharmony_ci    const UStringVector &addParts, // additional parts from curNode
482370b324cSopenharmony_ci    CDirItems &dirItems,
483370b324cSopenharmony_ci    bool enterToSubFolders);
484370b324cSopenharmony_ci
485370b324cSopenharmony_ci
486370b324cSopenharmony_ci/* EnumerateDirItems_Spec()
487370b324cSopenharmony_ci   adds new Dir item prefix, and enumerates dir items,
488370b324cSopenharmony_ci   then it can remove that Dir item prefix, if there are no items in that dir.
489370b324cSopenharmony_ci*/
490370b324cSopenharmony_ci
491370b324cSopenharmony_ci
492370b324cSopenharmony_ci/*
493370b324cSopenharmony_ci  EnumerateDirItems_Spec()
494370b324cSopenharmony_ci  it's similar to EnumerateDirItems, but phyPrefix doesn't include (curFolderName)
495370b324cSopenharmony_ci*/
496370b324cSopenharmony_ci
497370b324cSopenharmony_cistatic HRESULT EnumerateDirItems_Spec(
498370b324cSopenharmony_ci    const NWildcard::CCensorNode &curNode,
499370b324cSopenharmony_ci    const int phyParent, const int logParent, const FString &curFolderName,
500370b324cSopenharmony_ci    const FString &phyPrefix,      // without (curFolderName)
501370b324cSopenharmony_ci    const UStringVector &addParts, // (curNode + addParts) includes (curFolderName)
502370b324cSopenharmony_ci    CDirItems &dirItems,
503370b324cSopenharmony_ci    bool enterToSubFolders)
504370b324cSopenharmony_ci{
505370b324cSopenharmony_ci  const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR;
506370b324cSopenharmony_ci  const unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2));
507370b324cSopenharmony_ci  const unsigned numItems = dirItems.Items.Size();
508370b324cSopenharmony_ci  HRESULT res = EnumerateDirItems(
509370b324cSopenharmony_ci      curNode, (int)parent, (int)parent, phyPrefix + name2,
510370b324cSopenharmony_ci      addParts, dirItems, enterToSubFolders);
511370b324cSopenharmony_ci  if (numItems == dirItems.Items.Size())
512370b324cSopenharmony_ci    dirItems.DeleteLastPrefix();
513370b324cSopenharmony_ci  return res;
514370b324cSopenharmony_ci}
515370b324cSopenharmony_ci
516370b324cSopenharmony_ci
517370b324cSopenharmony_ci#ifndef UNDER_CE
518370b324cSopenharmony_ci
519370b324cSopenharmony_ci#ifdef _WIN32
520370b324cSopenharmony_ci
521370b324cSopenharmony_cistatic HRESULT EnumerateAltStreams(
522370b324cSopenharmony_ci    const NFind::CFileInfo &fi,
523370b324cSopenharmony_ci    const NWildcard::CCensorNode &curNode,
524370b324cSopenharmony_ci    const int phyParent, const int logParent,
525370b324cSopenharmony_ci    const FString &phyPath,         // with (fi.Name), without tail slash for folders
526370b324cSopenharmony_ci    const UStringVector &addParts,  // with (fi.Name), prefix parts from curNode
527370b324cSopenharmony_ci    bool addAllSubStreams,
528370b324cSopenharmony_ci    CDirItems &dirItems)
529370b324cSopenharmony_ci{
530370b324cSopenharmony_ci  // we don't use (ExcludeFileItems) rules for AltStreams
531370b324cSopenharmony_ci  // if (dirItems.ExcludeFileItems) return S_OK;
532370b324cSopenharmony_ci
533370b324cSopenharmony_ci  NFind::CStreamEnumerator enumerator(phyPath);
534370b324cSopenharmony_ci  for (;;)
535370b324cSopenharmony_ci  {
536370b324cSopenharmony_ci    NFind::CStreamInfo si;
537370b324cSopenharmony_ci    bool found;
538370b324cSopenharmony_ci    if (!enumerator.Next(si, found))
539370b324cSopenharmony_ci    {
540370b324cSopenharmony_ci      return dirItems.AddError(phyPath + FTEXT(":*")); // , (DWORD)E_FAIL
541370b324cSopenharmony_ci    }
542370b324cSopenharmony_ci    if (!found)
543370b324cSopenharmony_ci      return S_OK;
544370b324cSopenharmony_ci    if (si.IsMainStream())
545370b324cSopenharmony_ci      continue;
546370b324cSopenharmony_ci    UStringVector parts = addParts;
547370b324cSopenharmony_ci    const UString reducedName = si.GetReducedName();
548370b324cSopenharmony_ci    parts.Back() += reducedName;
549370b324cSopenharmony_ci    if (curNode.CheckPathToRoot(false, parts, true))
550370b324cSopenharmony_ci      continue;
551370b324cSopenharmony_ci    if (!addAllSubStreams)
552370b324cSopenharmony_ci      if (!curNode.CheckPathToRoot(true, parts, true))
553370b324cSopenharmony_ci        continue;
554370b324cSopenharmony_ci
555370b324cSopenharmony_ci    NFind::CFileInfo fi2 = fi;
556370b324cSopenharmony_ci    fi2.Name += us2fs(reducedName);
557370b324cSopenharmony_ci    fi2.Size = si.Size;
558370b324cSopenharmony_ci    fi2.Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
559370b324cSopenharmony_ci    fi2.IsAltStream = true;
560370b324cSopenharmony_ci    dirItems.AddDirFileInfo(phyParent, logParent, -1, fi2);
561370b324cSopenharmony_ci  }
562370b324cSopenharmony_ci}
563370b324cSopenharmony_ci
564370b324cSopenharmony_ci#endif // _WIN32
565370b324cSopenharmony_ci
566370b324cSopenharmony_ci
567370b324cSopenharmony_ci/* We get Reparse data and parse it.
568370b324cSopenharmony_ci   If there is Reparse error, we free dirItem.Reparse data.
569370b324cSopenharmony_ci   Do we need to work with empty reparse data?
570370b324cSopenharmony_ci*/
571370b324cSopenharmony_ci
572370b324cSopenharmony_ciHRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,
573370b324cSopenharmony_ci    const FString &phyPrefix)
574370b324cSopenharmony_ci{
575370b324cSopenharmony_ci  if (!SymLinks)
576370b324cSopenharmony_ci    return S_OK;
577370b324cSopenharmony_ci
578370b324cSopenharmony_ci  #ifdef _WIN32
579370b324cSopenharmony_ci    if (!fi.HasReparsePoint() || fi.IsAltStream)
580370b324cSopenharmony_ci  #else // _WIN32
581370b324cSopenharmony_ci    if (!fi.IsPosixLink())
582370b324cSopenharmony_ci  #endif // _WIN32
583370b324cSopenharmony_ci      return S_OK;
584370b324cSopenharmony_ci
585370b324cSopenharmony_ci  const FString path = phyPrefix + fi.Name;
586370b324cSopenharmony_ci  CByteBuffer &buf = dirItem.ReparseData;
587370b324cSopenharmony_ci  if (NIO::GetReparseData(path, buf))
588370b324cSopenharmony_ci  {
589370b324cSopenharmony_ci    // if (dirItem.ReparseData.Size() != 0)
590370b324cSopenharmony_ci    Stat.FilesSize -= fi.Size;
591370b324cSopenharmony_ci    return S_OK;
592370b324cSopenharmony_ci  }
593370b324cSopenharmony_ci
594370b324cSopenharmony_ci  DWORD res = ::GetLastError();
595370b324cSopenharmony_ci  buf.Free();
596370b324cSopenharmony_ci  return AddError(path, res);
597370b324cSopenharmony_ci}
598370b324cSopenharmony_ci
599370b324cSopenharmony_ci#endif // UNDER_CE
600370b324cSopenharmony_ci
601370b324cSopenharmony_ci
602370b324cSopenharmony_ci
603370b324cSopenharmony_cistatic HRESULT EnumerateForItem(
604370b324cSopenharmony_ci    const NFind::CFileInfo &fi,
605370b324cSopenharmony_ci    const NWildcard::CCensorNode &curNode,
606370b324cSopenharmony_ci    const int phyParent, const int logParent, const FString &phyPrefix,
607370b324cSopenharmony_ci    const UStringVector &addParts, // additional parts from curNode, without (fi.Name)
608370b324cSopenharmony_ci    CDirItems &dirItems,
609370b324cSopenharmony_ci    bool enterToSubFolders)
610370b324cSopenharmony_ci{
611370b324cSopenharmony_ci  const UString name = fs2us(fi.Name);
612370b324cSopenharmony_ci  UStringVector newParts = addParts;
613370b324cSopenharmony_ci  newParts.Add(name);
614370b324cSopenharmony_ci
615370b324cSopenharmony_ci  // check the path in exclude rules
616370b324cSopenharmony_ci  if (curNode.CheckPathToRoot(false, newParts, !fi.IsDir()))
617370b324cSopenharmony_ci    return S_OK;
618370b324cSopenharmony_ci
619370b324cSopenharmony_ci  #if !defined(UNDER_CE)
620370b324cSopenharmony_ci  int dirItemIndex = -1;
621370b324cSopenharmony_ci  #if defined(_WIN32)
622370b324cSopenharmony_ci  bool addAllSubStreams = false;
623370b324cSopenharmony_ci  bool needAltStreams = true;
624370b324cSopenharmony_ci  #endif // _WIN32
625370b324cSopenharmony_ci  #endif // !defined(UNDER_CE)
626370b324cSopenharmony_ci
627370b324cSopenharmony_ci  // check the path in inlcude rules
628370b324cSopenharmony_ci  if (curNode.CheckPathToRoot(true, newParts, !fi.IsDir()))
629370b324cSopenharmony_ci  {
630370b324cSopenharmony_ci    #if !defined(UNDER_CE)
631370b324cSopenharmony_ci    // dirItemIndex = (int)dirItems.Items.Size();
632370b324cSopenharmony_ci    #if defined(_WIN32)
633370b324cSopenharmony_ci    // we will not check include rules for substreams.
634370b324cSopenharmony_ci    addAllSubStreams = true;
635370b324cSopenharmony_ci    #endif // _WIN32
636370b324cSopenharmony_ci    #endif // !defined(UNDER_CE)
637370b324cSopenharmony_ci
638370b324cSopenharmony_ci    if (dirItems.CanIncludeItem(fi.IsDir()))
639370b324cSopenharmony_ci    {
640370b324cSopenharmony_ci      int secureIndex = -1;
641370b324cSopenharmony_ci    #ifdef Z7_USE_SECURITY_CODE
642370b324cSopenharmony_ci      if (dirItems.ReadSecure)
643370b324cSopenharmony_ci      {
644370b324cSopenharmony_ci        RINOK(dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex))
645370b324cSopenharmony_ci      }
646370b324cSopenharmony_ci    #endif
647370b324cSopenharmony_ci    #if !defined(UNDER_CE)
648370b324cSopenharmony_ci      dirItemIndex = (int)dirItems.Items.Size();
649370b324cSopenharmony_ci    #endif // !defined(UNDER_CE)
650370b324cSopenharmony_ci      dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
651370b324cSopenharmony_ci    }
652370b324cSopenharmony_ci    else
653370b324cSopenharmony_ci    {
654370b324cSopenharmony_ci      #if defined(_WIN32) && !defined(UNDER_CE)
655370b324cSopenharmony_ci        needAltStreams = false;
656370b324cSopenharmony_ci      #endif
657370b324cSopenharmony_ci    }
658370b324cSopenharmony_ci
659370b324cSopenharmony_ci    if (fi.IsDir())
660370b324cSopenharmony_ci      enterToSubFolders = true;
661370b324cSopenharmony_ci  }
662370b324cSopenharmony_ci
663370b324cSopenharmony_ci  #if !defined(UNDER_CE)
664370b324cSopenharmony_ci
665370b324cSopenharmony_ci  // we don't scan AltStreams for link files
666370b324cSopenharmony_ci
667370b324cSopenharmony_ci  if (dirItemIndex >= 0)
668370b324cSopenharmony_ci  {
669370b324cSopenharmony_ci    CDirItem &dirItem = dirItems.Items[(unsigned)dirItemIndex];
670370b324cSopenharmony_ci    RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix))
671370b324cSopenharmony_ci    if (dirItem.ReparseData.Size() != 0)
672370b324cSopenharmony_ci      return S_OK;
673370b324cSopenharmony_ci  }
674370b324cSopenharmony_ci
675370b324cSopenharmony_ci  #if defined(_WIN32)
676370b324cSopenharmony_ci  if (needAltStreams && dirItems.ScanAltStreams)
677370b324cSopenharmony_ci  {
678370b324cSopenharmony_ci    RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
679370b324cSopenharmony_ci        phyPrefix + fi.Name,    // with (fi.Name)
680370b324cSopenharmony_ci        newParts,               // with (fi.Name)
681370b324cSopenharmony_ci        addAllSubStreams,
682370b324cSopenharmony_ci        dirItems))
683370b324cSopenharmony_ci  }
684370b324cSopenharmony_ci  #endif
685370b324cSopenharmony_ci
686370b324cSopenharmony_ci  #endif // !defined(UNDER_CE)
687370b324cSopenharmony_ci
688370b324cSopenharmony_ci
689370b324cSopenharmony_ci  #ifndef _WIN32
690370b324cSopenharmony_ci  if (!fi.IsPosixLink()) // posix link can follow to dir
691370b324cSopenharmony_ci  #endif
692370b324cSopenharmony_ci  if (!fi.IsDir())
693370b324cSopenharmony_ci    return S_OK;
694370b324cSopenharmony_ci
695370b324cSopenharmony_ci  const NWildcard::CCensorNode *nextNode = NULL;
696370b324cSopenharmony_ci
697370b324cSopenharmony_ci  if (addParts.IsEmpty())
698370b324cSopenharmony_ci  {
699370b324cSopenharmony_ci    int index = curNode.FindSubNode(name);
700370b324cSopenharmony_ci    if (index >= 0)
701370b324cSopenharmony_ci    {
702370b324cSopenharmony_ci      nextNode = &curNode.SubNodes[(unsigned)index];
703370b324cSopenharmony_ci      newParts.Clear();
704370b324cSopenharmony_ci    }
705370b324cSopenharmony_ci  }
706370b324cSopenharmony_ci
707370b324cSopenharmony_ci  if (!nextNode)
708370b324cSopenharmony_ci  {
709370b324cSopenharmony_ci    if (!enterToSubFolders)
710370b324cSopenharmony_ci      return S_OK;
711370b324cSopenharmony_ci
712370b324cSopenharmony_ci   #ifndef _WIN32
713370b324cSopenharmony_ci    if (fi.IsPosixLink())
714370b324cSopenharmony_ci    {
715370b324cSopenharmony_ci      // here we can try to resolve posix link
716370b324cSopenharmony_ci      // if the link to dir, then can we follow it
717370b324cSopenharmony_ci      return S_OK; // we don't follow posix link
718370b324cSopenharmony_ci    }
719370b324cSopenharmony_ci   #else
720370b324cSopenharmony_ci    if (dirItems.SymLinks && fi.HasReparsePoint())
721370b324cSopenharmony_ci    {
722370b324cSopenharmony_ci      /* 20.03: in SymLinks mode: we don't enter to directory that
723370b324cSopenharmony_ci         has reparse point and has no CCensorNode
724370b324cSopenharmony_ci         NOTE: (curNode and parent nodes) still can have wildcard rules
725370b324cSopenharmony_ci         to include some items of target directory (of reparse point),
726370b324cSopenharmony_ci         but we ignore these rules here.
727370b324cSopenharmony_ci      */
728370b324cSopenharmony_ci      return S_OK;
729370b324cSopenharmony_ci    }
730370b324cSopenharmony_ci   #endif
731370b324cSopenharmony_ci    nextNode = &curNode;
732370b324cSopenharmony_ci  }
733370b324cSopenharmony_ci
734370b324cSopenharmony_ci  return EnumerateDirItems_Spec(
735370b324cSopenharmony_ci      *nextNode, phyParent, logParent, fi.Name,
736370b324cSopenharmony_ci      phyPrefix,   // without (fi.Name)
737370b324cSopenharmony_ci      newParts,    // relative to (*nextNode). (*nextNode + newParts) includes (fi.Name)
738370b324cSopenharmony_ci      dirItems,
739370b324cSopenharmony_ci      enterToSubFolders);
740370b324cSopenharmony_ci}
741370b324cSopenharmony_ci
742370b324cSopenharmony_ci
743370b324cSopenharmony_cistatic bool CanUseFsDirect(const NWildcard::CCensorNode &curNode)
744370b324cSopenharmony_ci{
745370b324cSopenharmony_ci  FOR_VECTOR (i, curNode.IncludeItems)
746370b324cSopenharmony_ci  {
747370b324cSopenharmony_ci    const NWildcard::CItem &item = curNode.IncludeItems[i];
748370b324cSopenharmony_ci    if (item.Recursive || item.PathParts.Size() != 1)
749370b324cSopenharmony_ci      return false;
750370b324cSopenharmony_ci    const UString &name = item.PathParts.Front();
751370b324cSopenharmony_ci    /*
752370b324cSopenharmony_ci    if (name.IsEmpty())
753370b324cSopenharmony_ci      return false;
754370b324cSopenharmony_ci    */
755370b324cSopenharmony_ci
756370b324cSopenharmony_ci    /* Windows doesn't support file name with wildcard
757370b324cSopenharmony_ci       But if another system supports file name with wildcard,
758370b324cSopenharmony_ci       and wildcard mode is disabled, we can ignore wildcard in name
759370b324cSopenharmony_ci    */
760370b324cSopenharmony_ci    /*
761370b324cSopenharmony_ci    #ifndef _WIN32
762370b324cSopenharmony_ci    if (!item.WildcardParsing)
763370b324cSopenharmony_ci      continue;
764370b324cSopenharmony_ci    #endif
765370b324cSopenharmony_ci    */
766370b324cSopenharmony_ci    if (DoesNameContainWildcard(name))
767370b324cSopenharmony_ci      return false;
768370b324cSopenharmony_ci  }
769370b324cSopenharmony_ci  return true;
770370b324cSopenharmony_ci}
771370b324cSopenharmony_ci
772370b324cSopenharmony_ci
773370b324cSopenharmony_ci#if defined(_WIN32) && !defined(UNDER_CE)
774370b324cSopenharmony_ci
775370b324cSopenharmony_cistatic bool IsVirtualFsFolder(const FString &prefix, const UString &name)
776370b324cSopenharmony_ci{
777370b324cSopenharmony_ci  UString s = fs2us(prefix);
778370b324cSopenharmony_ci  s += name;
779370b324cSopenharmony_ci  s.Add_PathSepar();
780370b324cSopenharmony_ci  // it returns (true) for non real FS folder path like - "\\SERVER\"
781370b324cSopenharmony_ci  return IsPathSepar(s[0]) && GetRootPrefixSize(s) == 0;
782370b324cSopenharmony_ci}
783370b324cSopenharmony_ci
784370b324cSopenharmony_ci#endif
785370b324cSopenharmony_ci
786370b324cSopenharmony_ci
787370b324cSopenharmony_ci
788370b324cSopenharmony_cistatic HRESULT EnumerateDirItems(
789370b324cSopenharmony_ci    const NWildcard::CCensorNode &curNode,
790370b324cSopenharmony_ci    const int phyParent, const int logParent, const FString &phyPrefix,
791370b324cSopenharmony_ci    const UStringVector &addParts,  // prefix from curNode including
792370b324cSopenharmony_ci    CDirItems &dirItems,
793370b324cSopenharmony_ci    bool enterToSubFolders)
794370b324cSopenharmony_ci{
795370b324cSopenharmony_ci  if (!enterToSubFolders)
796370b324cSopenharmony_ci  {
797370b324cSopenharmony_ci    /* if there are IncludeItems censor rules that affect items in subdirs,
798370b324cSopenharmony_ci       then we will enter to all subfolders */
799370b324cSopenharmony_ci    if (curNode.NeedCheckSubDirs())
800370b324cSopenharmony_ci      enterToSubFolders = true;
801370b324cSopenharmony_ci  }
802370b324cSopenharmony_ci
803370b324cSopenharmony_ci  RINOK(dirItems.ScanProgress(phyPrefix))
804370b324cSopenharmony_ci
805370b324cSopenharmony_ci  // try direct_names case at first
806370b324cSopenharmony_ci  if (addParts.IsEmpty() && !enterToSubFolders)
807370b324cSopenharmony_ci  {
808370b324cSopenharmony_ci    if (CanUseFsDirect(curNode))
809370b324cSopenharmony_ci    {
810370b324cSopenharmony_ci      // all names are direct (no wildcards)
811370b324cSopenharmony_ci      // so we don't need file_system's dir enumerator
812370b324cSopenharmony_ci      CRecordVector<bool> needEnterVector;
813370b324cSopenharmony_ci      unsigned i;
814370b324cSopenharmony_ci
815370b324cSopenharmony_ci      for (i = 0; i < curNode.IncludeItems.Size(); i++)
816370b324cSopenharmony_ci      {
817370b324cSopenharmony_ci        const NWildcard::CItem &item = curNode.IncludeItems[i];
818370b324cSopenharmony_ci        const UString &name = item.PathParts.Front();
819370b324cSopenharmony_ci        FString fullPath = phyPrefix + us2fs(name);
820370b324cSopenharmony_ci
821370b324cSopenharmony_ci        /*
822370b324cSopenharmony_ci        // not possible now
823370b324cSopenharmony_ci        if (!item.ForDir && !item.ForFile)
824370b324cSopenharmony_ci        {
825370b324cSopenharmony_ci          RINOK(dirItems.AddError(fullPath, ERROR_INVALID_PARAMETER));
826370b324cSopenharmony_ci          continue;
827370b324cSopenharmony_ci        }
828370b324cSopenharmony_ci        */
829370b324cSopenharmony_ci
830370b324cSopenharmony_ci        #if defined(_WIN32) && !defined(UNDER_CE)
831370b324cSopenharmony_ci        bool needAltStreams = true;
832370b324cSopenharmony_ci        #endif
833370b324cSopenharmony_ci
834370b324cSopenharmony_ci        #ifdef Z7_USE_SECURITY_CODE
835370b324cSopenharmony_ci        bool needSecurity = true;
836370b324cSopenharmony_ci        #endif
837370b324cSopenharmony_ci
838370b324cSopenharmony_ci        if (phyPrefix.IsEmpty())
839370b324cSopenharmony_ci        {
840370b324cSopenharmony_ci          if (!item.ForFile)
841370b324cSopenharmony_ci          {
842370b324cSopenharmony_ci            /* we don't like some names for alt streams inside archive:
843370b324cSopenharmony_ci               ":sname"     for "\"
844370b324cSopenharmony_ci               "c:::sname"  for "C:\"
845370b324cSopenharmony_ci               So we ignore alt streams for these cases */
846370b324cSopenharmony_ci            if (name.IsEmpty())
847370b324cSopenharmony_ci            {
848370b324cSopenharmony_ci              #if defined(_WIN32) && !defined(UNDER_CE)
849370b324cSopenharmony_ci              needAltStreams = false;
850370b324cSopenharmony_ci              #endif
851370b324cSopenharmony_ci
852370b324cSopenharmony_ci              /*
853370b324cSopenharmony_ci              // do we need to ignore security info for "\\" folder ?
854370b324cSopenharmony_ci              #ifdef Z7_USE_SECURITY_CODE
855370b324cSopenharmony_ci              needSecurity = false;
856370b324cSopenharmony_ci              #endif
857370b324cSopenharmony_ci              */
858370b324cSopenharmony_ci
859370b324cSopenharmony_ci              fullPath = CHAR_PATH_SEPARATOR;
860370b324cSopenharmony_ci            }
861370b324cSopenharmony_ci            #if defined(_WIN32) && !defined(UNDER_CE)
862370b324cSopenharmony_ci            else if (item.IsDriveItem())
863370b324cSopenharmony_ci            {
864370b324cSopenharmony_ci              needAltStreams = false;
865370b324cSopenharmony_ci              fullPath.Add_PathSepar();
866370b324cSopenharmony_ci            }
867370b324cSopenharmony_ci            #endif
868370b324cSopenharmony_ci          }
869370b324cSopenharmony_ci        }
870370b324cSopenharmony_ci
871370b324cSopenharmony_ci        NFind::CFileInfo fi;
872370b324cSopenharmony_ci        #if defined(_WIN32) && !defined(UNDER_CE)
873370b324cSopenharmony_ci        if (IsVirtualFsFolder(phyPrefix, name))
874370b324cSopenharmony_ci        {
875370b324cSopenharmony_ci          fi.SetAsDir();
876370b324cSopenharmony_ci          fi.Name = us2fs(name);
877370b324cSopenharmony_ci        }
878370b324cSopenharmony_ci        else
879370b324cSopenharmony_ci        #endif
880370b324cSopenharmony_ci        if (!FindFile_KeepDots(fi, fullPath  FOLLOW_LINK_PARAM2))
881370b324cSopenharmony_ci        {
882370b324cSopenharmony_ci          RINOK(dirItems.AddError(fullPath))
883370b324cSopenharmony_ci          continue;
884370b324cSopenharmony_ci        }
885370b324cSopenharmony_ci
886370b324cSopenharmony_ci        /*
887370b324cSopenharmony_ci        #ifdef _WIN32
888370b324cSopenharmony_ci          #define MY_ERROR_IS_DIR     ERROR_FILE_NOT_FOUND
889370b324cSopenharmony_ci          #define MY_ERROR_NOT_DIR    DI_DEFAULT_ERROR
890370b324cSopenharmony_ci        #else
891370b324cSopenharmony_ci          #define MY_ERROR_IS_DIR     EISDIR
892370b324cSopenharmony_ci          #define MY_ERROR_NOT_DIR    ENOTDIR
893370b324cSopenharmony_ci        #endif
894370b324cSopenharmony_ci        */
895370b324cSopenharmony_ci
896370b324cSopenharmony_ci        const bool isDir = fi.IsDir();
897370b324cSopenharmony_ci        if (isDir ? !item.ForDir : !item.ForFile)
898370b324cSopenharmony_ci        {
899370b324cSopenharmony_ci          // RINOK(dirItems.AddError(fullPath, isDir ? MY_ERROR_IS_DIR: MY_ERROR_NOT_DIR));
900370b324cSopenharmony_ci          RINOK(dirItems.AddError(fullPath, DI_DEFAULT_ERROR))
901370b324cSopenharmony_ci          continue;
902370b324cSopenharmony_ci        }
903370b324cSopenharmony_ci        {
904370b324cSopenharmony_ci          UStringVector pathParts;
905370b324cSopenharmony_ci          pathParts.Add(fs2us(fi.Name));
906370b324cSopenharmony_ci          if (curNode.CheckPathToRoot(false, pathParts, !isDir))
907370b324cSopenharmony_ci            continue;
908370b324cSopenharmony_ci        }
909370b324cSopenharmony_ci
910370b324cSopenharmony_ci
911370b324cSopenharmony_ci       if (dirItems.CanIncludeItem(fi.IsDir()))
912370b324cSopenharmony_ci       {
913370b324cSopenharmony_ci        int secureIndex = -1;
914370b324cSopenharmony_ci        #ifdef Z7_USE_SECURITY_CODE
915370b324cSopenharmony_ci        if (needSecurity && dirItems.ReadSecure)
916370b324cSopenharmony_ci        {
917370b324cSopenharmony_ci          RINOK(dirItems.AddSecurityItem(fullPath, secureIndex))
918370b324cSopenharmony_ci        }
919370b324cSopenharmony_ci        #endif
920370b324cSopenharmony_ci
921370b324cSopenharmony_ci        dirItems.AddDirFileInfo(phyParent, logParent, secureIndex, fi);
922370b324cSopenharmony_ci
923370b324cSopenharmony_ci        // we don't scan AltStreams for link files
924370b324cSopenharmony_ci
925370b324cSopenharmony_ci        #if !defined(UNDER_CE)
926370b324cSopenharmony_ci        {
927370b324cSopenharmony_ci          CDirItem &dirItem = dirItems.Items.Back();
928370b324cSopenharmony_ci          RINOK(dirItems.SetLinkInfo(dirItem, fi, phyPrefix))
929370b324cSopenharmony_ci          if (dirItem.ReparseData.Size() != 0)
930370b324cSopenharmony_ci            continue;
931370b324cSopenharmony_ci        }
932370b324cSopenharmony_ci
933370b324cSopenharmony_ci        #if defined(_WIN32)
934370b324cSopenharmony_ci        if (needAltStreams && dirItems.ScanAltStreams)
935370b324cSopenharmony_ci        {
936370b324cSopenharmony_ci          UStringVector pathParts;
937370b324cSopenharmony_ci          pathParts.Add(fs2us(fi.Name));
938370b324cSopenharmony_ci          RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent,
939370b324cSopenharmony_ci              fullPath,  // including (name)
940370b324cSopenharmony_ci              pathParts, // including (fi.Name)
941370b324cSopenharmony_ci              true, /* addAllSubStreams */
942370b324cSopenharmony_ci              dirItems))
943370b324cSopenharmony_ci        }
944370b324cSopenharmony_ci        #endif // defined(_WIN32)
945370b324cSopenharmony_ci
946370b324cSopenharmony_ci        #endif // !defined(UNDER_CE)
947370b324cSopenharmony_ci       }
948370b324cSopenharmony_ci
949370b324cSopenharmony_ci
950370b324cSopenharmony_ci        #ifndef _WIN32
951370b324cSopenharmony_ci        if (!fi.IsPosixLink()) // posix link can follow to dir
952370b324cSopenharmony_ci        #endif
953370b324cSopenharmony_ci        if (!isDir)
954370b324cSopenharmony_ci          continue;
955370b324cSopenharmony_ci
956370b324cSopenharmony_ci        UStringVector newParts;
957370b324cSopenharmony_ci        const NWildcard::CCensorNode *nextNode = NULL;
958370b324cSopenharmony_ci        int index = curNode.FindSubNode(name);
959370b324cSopenharmony_ci        if (index >= 0)
960370b324cSopenharmony_ci        {
961370b324cSopenharmony_ci          for (int t = (int)needEnterVector.Size(); t <= index; t++)
962370b324cSopenharmony_ci            needEnterVector.Add(true);
963370b324cSopenharmony_ci          needEnterVector[(unsigned)index] = false;
964370b324cSopenharmony_ci          nextNode = &curNode.SubNodes[(unsigned)index];
965370b324cSopenharmony_ci        }
966370b324cSopenharmony_ci        else
967370b324cSopenharmony_ci        {
968370b324cSopenharmony_ci         #ifndef _WIN32
969370b324cSopenharmony_ci          if (fi.IsPosixLink())
970370b324cSopenharmony_ci          {
971370b324cSopenharmony_ci            // here we can try to resolve posix link
972370b324cSopenharmony_ci            // if the link to dir, then can we follow it
973370b324cSopenharmony_ci            continue; // we don't follow posix link
974370b324cSopenharmony_ci          }
975370b324cSopenharmony_ci         #else
976370b324cSopenharmony_ci          if (dirItems.SymLinks)
977370b324cSopenharmony_ci          {
978370b324cSopenharmony_ci            if (fi.HasReparsePoint())
979370b324cSopenharmony_ci            {
980370b324cSopenharmony_ci              /* 20.03: in SymLinks mode: we don't enter to directory that
981370b324cSopenharmony_ci              has reparse point and has no CCensorNode */
982370b324cSopenharmony_ci              continue;
983370b324cSopenharmony_ci            }
984370b324cSopenharmony_ci          }
985370b324cSopenharmony_ci         #endif
986370b324cSopenharmony_ci          nextNode = &curNode;
987370b324cSopenharmony_ci          newParts.Add(name); // don't change it to fi.Name. It's for shortnames support
988370b324cSopenharmony_ci        }
989370b324cSopenharmony_ci
990370b324cSopenharmony_ci        RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,
991370b324cSopenharmony_ci            newParts, dirItems, true))
992370b324cSopenharmony_ci      }
993370b324cSopenharmony_ci
994370b324cSopenharmony_ci      for (i = 0; i < curNode.SubNodes.Size(); i++)
995370b324cSopenharmony_ci      {
996370b324cSopenharmony_ci        if (i < needEnterVector.Size())
997370b324cSopenharmony_ci          if (!needEnterVector[i])
998370b324cSopenharmony_ci            continue;
999370b324cSopenharmony_ci        const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
1000370b324cSopenharmony_ci        FString fullPath = phyPrefix + us2fs(nextNode.Name);
1001370b324cSopenharmony_ci        NFind::CFileInfo fi;
1002370b324cSopenharmony_ci
1003370b324cSopenharmony_ci        if (nextNode.Name.IsEmpty())
1004370b324cSopenharmony_ci        {
1005370b324cSopenharmony_ci          if (phyPrefix.IsEmpty())
1006370b324cSopenharmony_ci            fullPath = CHAR_PATH_SEPARATOR;
1007370b324cSopenharmony_ci        }
1008370b324cSopenharmony_ci      #ifdef _WIN32
1009370b324cSopenharmony_ci        else if(phyPrefix.IsEmpty()
1010370b324cSopenharmony_ci            || (phyPrefix.Len() == NName::kSuperPathPrefixSize
1011370b324cSopenharmony_ci                && IsSuperPath(phyPrefix)))
1012370b324cSopenharmony_ci        {
1013370b324cSopenharmony_ci          if (NWildcard::IsDriveColonName(nextNode.Name))
1014370b324cSopenharmony_ci            fullPath.Add_PathSepar();
1015370b324cSopenharmony_ci        }
1016370b324cSopenharmony_ci      #endif
1017370b324cSopenharmony_ci
1018370b324cSopenharmony_ci        // we don't want to call fi.Find() for root folder or virtual folder
1019370b324cSopenharmony_ci        if ((phyPrefix.IsEmpty() && nextNode.Name.IsEmpty())
1020370b324cSopenharmony_ci            #if defined(_WIN32) && !defined(UNDER_CE)
1021370b324cSopenharmony_ci            || IsVirtualFsFolder(phyPrefix, nextNode.Name)
1022370b324cSopenharmony_ci            #endif
1023370b324cSopenharmony_ci            )
1024370b324cSopenharmony_ci        {
1025370b324cSopenharmony_ci          fi.SetAsDir();
1026370b324cSopenharmony_ci          fi.Name = us2fs(nextNode.Name);
1027370b324cSopenharmony_ci        }
1028370b324cSopenharmony_ci        else
1029370b324cSopenharmony_ci        {
1030370b324cSopenharmony_ci          if (!FindFile_KeepDots(fi, fullPath  FOLLOW_LINK_PARAM2))
1031370b324cSopenharmony_ci          {
1032370b324cSopenharmony_ci            if (!nextNode.AreThereIncludeItems())
1033370b324cSopenharmony_ci              continue;
1034370b324cSopenharmony_ci            RINOK(dirItems.AddError(fullPath))
1035370b324cSopenharmony_ci            continue;
1036370b324cSopenharmony_ci          }
1037370b324cSopenharmony_ci
1038370b324cSopenharmony_ci          if (!fi.IsDir())
1039370b324cSopenharmony_ci          {
1040370b324cSopenharmony_ci            RINOK(dirItems.AddError(fullPath, DI_DEFAULT_ERROR))
1041370b324cSopenharmony_ci            continue;
1042370b324cSopenharmony_ci          }
1043370b324cSopenharmony_ci        }
1044370b324cSopenharmony_ci
1045370b324cSopenharmony_ci        RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,
1046370b324cSopenharmony_ci            UStringVector(), dirItems, false))
1047370b324cSopenharmony_ci      }
1048370b324cSopenharmony_ci
1049370b324cSopenharmony_ci      return S_OK;
1050370b324cSopenharmony_ci    }
1051370b324cSopenharmony_ci  }
1052370b324cSopenharmony_ci
1053370b324cSopenharmony_ci  #ifdef _WIN32
1054370b324cSopenharmony_ci  #ifndef UNDER_CE
1055370b324cSopenharmony_ci
1056370b324cSopenharmony_ci  // scan drives, if wildcard is "*:\"
1057370b324cSopenharmony_ci
1058370b324cSopenharmony_ci  if (phyPrefix.IsEmpty() && curNode.IncludeItems.Size() > 0)
1059370b324cSopenharmony_ci  {
1060370b324cSopenharmony_ci    unsigned i;
1061370b324cSopenharmony_ci    for (i = 0; i < curNode.IncludeItems.Size(); i++)
1062370b324cSopenharmony_ci    {
1063370b324cSopenharmony_ci      const NWildcard::CItem &item = curNode.IncludeItems[i];
1064370b324cSopenharmony_ci      if (item.PathParts.Size() < 1)
1065370b324cSopenharmony_ci        break;
1066370b324cSopenharmony_ci      const UString &name = item.PathParts.Front();
1067370b324cSopenharmony_ci      if (name.Len() != 2 || name[1] != ':')
1068370b324cSopenharmony_ci        break;
1069370b324cSopenharmony_ci      if (item.PathParts.Size() == 1)
1070370b324cSopenharmony_ci        if (item.ForFile || !item.ForDir)
1071370b324cSopenharmony_ci          break;
1072370b324cSopenharmony_ci      if (NWildcard::IsDriveColonName(name))
1073370b324cSopenharmony_ci        continue;
1074370b324cSopenharmony_ci      if (name[0] != '*' && name[0] != '?')
1075370b324cSopenharmony_ci        break;
1076370b324cSopenharmony_ci    }
1077370b324cSopenharmony_ci    if (i == curNode.IncludeItems.Size())
1078370b324cSopenharmony_ci    {
1079370b324cSopenharmony_ci      FStringVector driveStrings;
1080370b324cSopenharmony_ci      NFind::MyGetLogicalDriveStrings(driveStrings);
1081370b324cSopenharmony_ci      for (i = 0; i < driveStrings.Size(); i++)
1082370b324cSopenharmony_ci      {
1083370b324cSopenharmony_ci        FString driveName = driveStrings[i];
1084370b324cSopenharmony_ci        if (driveName.Len() < 3 || driveName.Back() != '\\')
1085370b324cSopenharmony_ci          return E_FAIL;
1086370b324cSopenharmony_ci        driveName.DeleteBack();
1087370b324cSopenharmony_ci        NFind::CFileInfo fi;
1088370b324cSopenharmony_ci        fi.SetAsDir();
1089370b324cSopenharmony_ci        fi.Name = driveName;
1090370b324cSopenharmony_ci
1091370b324cSopenharmony_ci        RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,
1092370b324cSopenharmony_ci            addParts, dirItems, enterToSubFolders))
1093370b324cSopenharmony_ci      }
1094370b324cSopenharmony_ci      return S_OK;
1095370b324cSopenharmony_ci    }
1096370b324cSopenharmony_ci  }
1097370b324cSopenharmony_ci
1098370b324cSopenharmony_ci  #endif
1099370b324cSopenharmony_ci  #endif
1100370b324cSopenharmony_ci
1101370b324cSopenharmony_ci
1102370b324cSopenharmony_ci  CObjectVector<NFind::CFileInfo> files;
1103370b324cSopenharmony_ci
1104370b324cSopenharmony_ci  // for (int y = 0; y < 1; y++)
1105370b324cSopenharmony_ci  {
1106370b324cSopenharmony_ci    // files.Clear();
1107370b324cSopenharmony_ci    RINOK(dirItems.EnumerateOneDir(phyPrefix, files))
1108370b324cSopenharmony_ci  /*
1109370b324cSopenharmony_ci  FOR_VECTOR (i, files)
1110370b324cSopenharmony_ci  {
1111370b324cSopenharmony_ci    #ifdef _WIN32
1112370b324cSopenharmony_ci    // const NFind::CFileInfo &fi = files[i];
1113370b324cSopenharmony_ci    #else
1114370b324cSopenharmony_ci    NFind::CFileInfo &fi = files[i];
1115370b324cSopenharmony_ci    {
1116370b324cSopenharmony_ci      const NFind::CFileInfo &di = files[i];
1117370b324cSopenharmony_ci      const FString path = phyPrefix + di.Name;
1118370b324cSopenharmony_ci      if (!fi.Find_AfterEnumerator(path))
1119370b324cSopenharmony_ci      {
1120370b324cSopenharmony_ci        RINOK(dirItems.AddError(path));
1121370b324cSopenharmony_ci        continue;
1122370b324cSopenharmony_ci      }
1123370b324cSopenharmony_ci      fi.Name = di.Name;
1124370b324cSopenharmony_ci    }
1125370b324cSopenharmony_ci    #endif
1126370b324cSopenharmony_ci
1127370b324cSopenharmony_ci  }
1128370b324cSopenharmony_ci  */
1129370b324cSopenharmony_ci  }
1130370b324cSopenharmony_ci
1131370b324cSopenharmony_ci  FOR_VECTOR (i, files)
1132370b324cSopenharmony_ci  {
1133370b324cSopenharmony_ci    #ifdef _WIN32
1134370b324cSopenharmony_ci    const NFind::CFileInfo &fi = files[i];
1135370b324cSopenharmony_ci    #else
1136370b324cSopenharmony_ci    const NFind::CFileInfo &fi = files[i];
1137370b324cSopenharmony_ci    /*
1138370b324cSopenharmony_ci    NFind::CFileInfo fi;
1139370b324cSopenharmony_ci    {
1140370b324cSopenharmony_ci      const NFind::CDirEntry &di = files[i];
1141370b324cSopenharmony_ci      const FString path = phyPrefix + di.Name;
1142370b324cSopenharmony_ci      if (!fi.Find_AfterEnumerator(path))
1143370b324cSopenharmony_ci      {
1144370b324cSopenharmony_ci        RINOK(dirItems.AddError(path));
1145370b324cSopenharmony_ci        continue;
1146370b324cSopenharmony_ci      }
1147370b324cSopenharmony_ci      fi.Name = di.Name;
1148370b324cSopenharmony_ci    }
1149370b324cSopenharmony_ci    */
1150370b324cSopenharmony_ci    #endif
1151370b324cSopenharmony_ci
1152370b324cSopenharmony_ci    RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,
1153370b324cSopenharmony_ci          addParts, dirItems, enterToSubFolders))
1154370b324cSopenharmony_ci    if (dirItems.Callback && (i & kScanProgressStepMask) == kScanProgressStepMask)
1155370b324cSopenharmony_ci    {
1156370b324cSopenharmony_ci      RINOK(dirItems.ScanProgress(phyPrefix))
1157370b324cSopenharmony_ci    }
1158370b324cSopenharmony_ci  }
1159370b324cSopenharmony_ci
1160370b324cSopenharmony_ci  return S_OK;
1161370b324cSopenharmony_ci}
1162370b324cSopenharmony_ci
1163370b324cSopenharmony_ci
1164370b324cSopenharmony_ci
1165370b324cSopenharmony_ci
1166370b324cSopenharmony_ciHRESULT EnumerateItems(
1167370b324cSopenharmony_ci    const NWildcard::CCensor &censor,
1168370b324cSopenharmony_ci    const NWildcard::ECensorPathMode pathMode,
1169370b324cSopenharmony_ci    const UString &addPathPrefix, // prefix that will be added to Logical Path
1170370b324cSopenharmony_ci    CDirItems &dirItems)
1171370b324cSopenharmony_ci{
1172370b324cSopenharmony_ci  FOR_VECTOR (i, censor.Pairs)
1173370b324cSopenharmony_ci  {
1174370b324cSopenharmony_ci    const NWildcard::CPair &pair = censor.Pairs[i];
1175370b324cSopenharmony_ci    const int phyParent = pair.Prefix.IsEmpty() ? -1 : (int)dirItems.AddPrefix(-1, -1, pair.Prefix);
1176370b324cSopenharmony_ci    int logParent = -1;
1177370b324cSopenharmony_ci
1178370b324cSopenharmony_ci    if (pathMode == NWildcard::k_AbsPath)
1179370b324cSopenharmony_ci      logParent = phyParent;
1180370b324cSopenharmony_ci    else
1181370b324cSopenharmony_ci    {
1182370b324cSopenharmony_ci      if (!addPathPrefix.IsEmpty())
1183370b324cSopenharmony_ci        logParent = (int)dirItems.AddPrefix(-1, -1, addPathPrefix);
1184370b324cSopenharmony_ci    }
1185370b324cSopenharmony_ci
1186370b324cSopenharmony_ci    RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(),
1187370b324cSopenharmony_ci        dirItems,
1188370b324cSopenharmony_ci        false // enterToSubFolders
1189370b324cSopenharmony_ci        ))
1190370b324cSopenharmony_ci  }
1191370b324cSopenharmony_ci  dirItems.ReserveDown();
1192370b324cSopenharmony_ci
1193370b324cSopenharmony_ci #if defined(_WIN32) && !defined(UNDER_CE)
1194370b324cSopenharmony_ci  RINOK(dirItems.FillFixedReparse())
1195370b324cSopenharmony_ci #endif
1196370b324cSopenharmony_ci
1197370b324cSopenharmony_ci #ifndef _WIN32
1198370b324cSopenharmony_ci  RINOK(dirItems.FillDeviceSizes())
1199370b324cSopenharmony_ci #endif
1200370b324cSopenharmony_ci
1201370b324cSopenharmony_ci  return S_OK;
1202370b324cSopenharmony_ci}
1203370b324cSopenharmony_ci
1204370b324cSopenharmony_ci
1205370b324cSopenharmony_ci#if defined(_WIN32) && !defined(UNDER_CE)
1206370b324cSopenharmony_ci
1207370b324cSopenharmony_ciHRESULT CDirItems::FillFixedReparse()
1208370b324cSopenharmony_ci{
1209370b324cSopenharmony_ci  FOR_VECTOR(i, Items)
1210370b324cSopenharmony_ci  {
1211370b324cSopenharmony_ci    CDirItem &item = Items[i];
1212370b324cSopenharmony_ci
1213370b324cSopenharmony_ci    if (!SymLinks)
1214370b324cSopenharmony_ci    {
1215370b324cSopenharmony_ci      // continue; // for debug
1216370b324cSopenharmony_ci      if (!item.Has_Attrib_ReparsePoint())
1217370b324cSopenharmony_ci        continue;
1218370b324cSopenharmony_ci
1219370b324cSopenharmony_ci      // if (item.IsDir()) continue;
1220370b324cSopenharmony_ci
1221370b324cSopenharmony_ci      const FString phyPath = GetPhyPath(i);
1222370b324cSopenharmony_ci
1223370b324cSopenharmony_ci      NFind::CFileInfo fi;
1224370b324cSopenharmony_ci      if (fi.Fill_From_ByHandleFileInfo(phyPath)) // item.IsDir()
1225370b324cSopenharmony_ci      {
1226370b324cSopenharmony_ci        item.Size = fi.Size;
1227370b324cSopenharmony_ci        item.CTime = fi.CTime;
1228370b324cSopenharmony_ci        item.ATime = fi.ATime;
1229370b324cSopenharmony_ci        item.MTime = fi.MTime;
1230370b324cSopenharmony_ci        item.Attrib = fi.Attrib;
1231370b324cSopenharmony_ci        continue;
1232370b324cSopenharmony_ci      }
1233370b324cSopenharmony_ci
1234370b324cSopenharmony_ci      /*
1235370b324cSopenharmony_ci      // we request properties of target file instead of properies of symbolic link
1236370b324cSopenharmony_ci      // here we also can manually parse unsupported links (like WSL links)
1237370b324cSopenharmony_ci      NIO::CInFile inFile;
1238370b324cSopenharmony_ci      if (inFile.Open(phyPath))
1239370b324cSopenharmony_ci      {
1240370b324cSopenharmony_ci        BY_HANDLE_FILE_INFORMATION info;
1241370b324cSopenharmony_ci        if (inFile.GetFileInformation(&info))
1242370b324cSopenharmony_ci        {
1243370b324cSopenharmony_ci          // Stat.FilesSize doesn't contain item.Size already
1244370b324cSopenharmony_ci          // Stat.FilesSize -= item.Size;
1245370b324cSopenharmony_ci          item.Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
1246370b324cSopenharmony_ci          Stat.FilesSize += item.Size;
1247370b324cSopenharmony_ci          item.CTime = info.ftCreationTime;
1248370b324cSopenharmony_ci          item.ATime = info.ftLastAccessTime;
1249370b324cSopenharmony_ci          item.MTime = info.ftLastWriteTime;
1250370b324cSopenharmony_ci          item.Attrib = info.dwFileAttributes;
1251370b324cSopenharmony_ci          continue;
1252370b324cSopenharmony_ci        }
1253370b324cSopenharmony_ci      }
1254370b324cSopenharmony_ci      */
1255370b324cSopenharmony_ci
1256370b324cSopenharmony_ci      RINOK(AddError(phyPath))
1257370b324cSopenharmony_ci      continue;
1258370b324cSopenharmony_ci    }
1259370b324cSopenharmony_ci
1260370b324cSopenharmony_ci    // (SymLinks == true) here
1261370b324cSopenharmony_ci
1262370b324cSopenharmony_ci    if (item.ReparseData.Size() == 0)
1263370b324cSopenharmony_ci      continue;
1264370b324cSopenharmony_ci
1265370b324cSopenharmony_ci    // if (item.Size == 0)
1266370b324cSopenharmony_ci    {
1267370b324cSopenharmony_ci      // 20.03: we use Reparse Data instead of real data
1268370b324cSopenharmony_ci      item.Size = item.ReparseData.Size();
1269370b324cSopenharmony_ci    }
1270370b324cSopenharmony_ci
1271370b324cSopenharmony_ci    CReparseAttr attr;
1272370b324cSopenharmony_ci    if (!attr.Parse(item.ReparseData, item.ReparseData.Size()))
1273370b324cSopenharmony_ci    {
1274370b324cSopenharmony_ci      const FString phyPath = GetPhyPath(i);
1275370b324cSopenharmony_ci      AddError(phyPath, attr.ErrorCode);
1276370b324cSopenharmony_ci      continue;
1277370b324cSopenharmony_ci    }
1278370b324cSopenharmony_ci
1279370b324cSopenharmony_ci    /* imagex/WIM reduces absolute paths in links (raparse data),
1280370b324cSopenharmony_ci       if we archive non root folder. We do same thing here */
1281370b324cSopenharmony_ci
1282370b324cSopenharmony_ci    bool isWSL = false;
1283370b324cSopenharmony_ci    if (attr.IsSymLink_WSL())
1284370b324cSopenharmony_ci    {
1285370b324cSopenharmony_ci      // isWSL = true;
1286370b324cSopenharmony_ci      // we don't change WSL symlinks
1287370b324cSopenharmony_ci      continue;
1288370b324cSopenharmony_ci    }
1289370b324cSopenharmony_ci    else
1290370b324cSopenharmony_ci    {
1291370b324cSopenharmony_ci      if (attr.IsRelative_Win())
1292370b324cSopenharmony_ci        continue;
1293370b324cSopenharmony_ci    }
1294370b324cSopenharmony_ci
1295370b324cSopenharmony_ci    const UString &link = attr.GetPath();
1296370b324cSopenharmony_ci    if (!IsDrivePath(link))
1297370b324cSopenharmony_ci      continue;
1298370b324cSopenharmony_ci    // maybe we need to support networks paths also ?
1299370b324cSopenharmony_ci
1300370b324cSopenharmony_ci    FString fullPathF;
1301370b324cSopenharmony_ci    if (!NDir::MyGetFullPathName(GetPhyPath(i), fullPathF))
1302370b324cSopenharmony_ci      continue;
1303370b324cSopenharmony_ci    const UString fullPath = fs2us(fullPathF);
1304370b324cSopenharmony_ci    const UString logPath = GetLogPath(i);
1305370b324cSopenharmony_ci    if (logPath.Len() >= fullPath.Len())
1306370b324cSopenharmony_ci      continue;
1307370b324cSopenharmony_ci    if (CompareFileNames(logPath, fullPath.RightPtr(logPath.Len())) != 0)
1308370b324cSopenharmony_ci      continue;
1309370b324cSopenharmony_ci
1310370b324cSopenharmony_ci    const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len());
1311370b324cSopenharmony_ci    if (!IsPathSepar(prefix.Back()))
1312370b324cSopenharmony_ci      continue;
1313370b324cSopenharmony_ci
1314370b324cSopenharmony_ci    const unsigned rootPrefixSize = GetRootPrefixSize(prefix);
1315370b324cSopenharmony_ci    if (rootPrefixSize == 0)
1316370b324cSopenharmony_ci      continue;
1317370b324cSopenharmony_ci    if (rootPrefixSize == prefix.Len())
1318370b324cSopenharmony_ci      continue; // simple case: paths are from root
1319370b324cSopenharmony_ci
1320370b324cSopenharmony_ci    if (link.Len() <= prefix.Len())
1321370b324cSopenharmony_ci      continue;
1322370b324cSopenharmony_ci
1323370b324cSopenharmony_ci    if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0)
1324370b324cSopenharmony_ci      continue;
1325370b324cSopenharmony_ci
1326370b324cSopenharmony_ci    UString newLink = prefix.Left(rootPrefixSize);
1327370b324cSopenharmony_ci    newLink += link.Ptr(prefix.Len());
1328370b324cSopenharmony_ci
1329370b324cSopenharmony_ci    CByteBuffer data;
1330370b324cSopenharmony_ci    bool isSymLink = !attr.IsMountPoint();
1331370b324cSopenharmony_ci    if (!FillLinkData(data, newLink, isSymLink, isWSL))
1332370b324cSopenharmony_ci      continue;
1333370b324cSopenharmony_ci    item.ReparseData2 = data;
1334370b324cSopenharmony_ci  }
1335370b324cSopenharmony_ci  return S_OK;
1336370b324cSopenharmony_ci}
1337370b324cSopenharmony_ci
1338370b324cSopenharmony_ci#endif
1339370b324cSopenharmony_ci
1340370b324cSopenharmony_ci
1341370b324cSopenharmony_ci#ifndef _WIN32
1342370b324cSopenharmony_ci
1343370b324cSopenharmony_ciHRESULT CDirItems::FillDeviceSizes()
1344370b324cSopenharmony_ci{
1345370b324cSopenharmony_ci  {
1346370b324cSopenharmony_ci    FOR_VECTOR (i, Items)
1347370b324cSopenharmony_ci    {
1348370b324cSopenharmony_ci      CDirItem &item = Items[i];
1349370b324cSopenharmony_ci
1350370b324cSopenharmony_ci      if (S_ISBLK(item.mode) && item.Size == 0)
1351370b324cSopenharmony_ci      {
1352370b324cSopenharmony_ci        const FString phyPath = GetPhyPath(i);
1353370b324cSopenharmony_ci        NIO::CInFile inFile;
1354370b324cSopenharmony_ci        inFile.PreserveATime = true;
1355370b324cSopenharmony_ci        if (inFile.OpenShared(phyPath, ShareForWrite)) // fixme: OpenShared ??
1356370b324cSopenharmony_ci        {
1357370b324cSopenharmony_ci          UInt64 size = 0;
1358370b324cSopenharmony_ci          if (inFile.GetLength(size))
1359370b324cSopenharmony_ci            item.Size = size;
1360370b324cSopenharmony_ci        }
1361370b324cSopenharmony_ci      }
1362370b324cSopenharmony_ci      if (StoreOwnerName)
1363370b324cSopenharmony_ci      {
1364370b324cSopenharmony_ci        OwnerNameMap.Add_UInt32(item.uid);
1365370b324cSopenharmony_ci        OwnerGroupMap.Add_UInt32(item.gid);
1366370b324cSopenharmony_ci      }
1367370b324cSopenharmony_ci    }
1368370b324cSopenharmony_ci  }
1369370b324cSopenharmony_ci
1370370b324cSopenharmony_ci  if (StoreOwnerName)
1371370b324cSopenharmony_ci  {
1372370b324cSopenharmony_ci    UString u;
1373370b324cSopenharmony_ci    AString a;
1374370b324cSopenharmony_ci    {
1375370b324cSopenharmony_ci      FOR_VECTOR (i, OwnerNameMap.Numbers)
1376370b324cSopenharmony_ci      {
1377370b324cSopenharmony_ci        // 200K/sec speed
1378370b324cSopenharmony_ci        u.Empty();
1379370b324cSopenharmony_ci        const passwd *pw = getpwuid(OwnerNameMap.Numbers[i]);
1380370b324cSopenharmony_ci        // printf("\ngetpwuid=%s\n", pw->pw_name);
1381370b324cSopenharmony_ci        if (pw)
1382370b324cSopenharmony_ci        {
1383370b324cSopenharmony_ci          a = pw->pw_name;
1384370b324cSopenharmony_ci          ConvertUTF8ToUnicode(a, u);
1385370b324cSopenharmony_ci        }
1386370b324cSopenharmony_ci        OwnerNameMap.Strings.Add(u);
1387370b324cSopenharmony_ci      }
1388370b324cSopenharmony_ci    }
1389370b324cSopenharmony_ci    {
1390370b324cSopenharmony_ci      FOR_VECTOR (i, OwnerGroupMap.Numbers)
1391370b324cSopenharmony_ci      {
1392370b324cSopenharmony_ci        u.Empty();
1393370b324cSopenharmony_ci        const group *gr = getgrgid(OwnerGroupMap.Numbers[i]);
1394370b324cSopenharmony_ci        if (gr)
1395370b324cSopenharmony_ci        {
1396370b324cSopenharmony_ci          // printf("\ngetgrgid %d %s\n", OwnerGroupMap.Numbers[i], gr->gr_name);
1397370b324cSopenharmony_ci          a = gr->gr_name;
1398370b324cSopenharmony_ci          ConvertUTF8ToUnicode(a, u);
1399370b324cSopenharmony_ci        }
1400370b324cSopenharmony_ci        OwnerGroupMap.Strings.Add(u);
1401370b324cSopenharmony_ci      }
1402370b324cSopenharmony_ci    }
1403370b324cSopenharmony_ci
1404370b324cSopenharmony_ci    FOR_VECTOR (i, Items)
1405370b324cSopenharmony_ci    {
1406370b324cSopenharmony_ci      CDirItem &item = Items[i];
1407370b324cSopenharmony_ci      {
1408370b324cSopenharmony_ci        const int index = OwnerNameMap.Find(item.uid);
1409370b324cSopenharmony_ci        if (index < 0) throw 1;
1410370b324cSopenharmony_ci        item.OwnerNameIndex = index;
1411370b324cSopenharmony_ci      }
1412370b324cSopenharmony_ci      {
1413370b324cSopenharmony_ci        const int index = OwnerGroupMap.Find(item.gid);
1414370b324cSopenharmony_ci        if (index < 0) throw 1;
1415370b324cSopenharmony_ci        item.OwnerGroupIndex = index;
1416370b324cSopenharmony_ci      }
1417370b324cSopenharmony_ci    }
1418370b324cSopenharmony_ci  }
1419370b324cSopenharmony_ci
1420370b324cSopenharmony_ci
1421370b324cSopenharmony_ci  // if (NeedOwnerNames)
1422370b324cSopenharmony_ci  {
1423370b324cSopenharmony_ci    /*
1424370b324cSopenharmony_ci    {
1425370b324cSopenharmony_ci      for (unsigned i = 0 ; i < 10000; i++)
1426370b324cSopenharmony_ci      {
1427370b324cSopenharmony_ci        const passwd *pw = getpwuid(i);
1428370b324cSopenharmony_ci        if (pw)
1429370b324cSopenharmony_ci        {
1430370b324cSopenharmony_ci          UString u;
1431370b324cSopenharmony_ci          ConvertUTF8ToUnicode(AString(pw->pw_name), u);
1432370b324cSopenharmony_ci          OwnerNameMap.Add(i, u);
1433370b324cSopenharmony_ci          OwnerNameMap.Add(i, u);
1434370b324cSopenharmony_ci          OwnerNameMap.Add(i, u);
1435370b324cSopenharmony_ci        }
1436370b324cSopenharmony_ci        const group *gr = getgrgid(i);
1437370b324cSopenharmony_ci        if (gr)
1438370b324cSopenharmony_ci        {
1439370b324cSopenharmony_ci          // we can use utf-8 here.
1440370b324cSopenharmony_ci          UString u;
1441370b324cSopenharmony_ci          ConvertUTF8ToUnicode(AString(gr->gr_name), u);
1442370b324cSopenharmony_ci          OwnerGroupMap.Add(i, u);
1443370b324cSopenharmony_ci        }
1444370b324cSopenharmony_ci      }
1445370b324cSopenharmony_ci    }
1446370b324cSopenharmony_ci    */
1447370b324cSopenharmony_ci    /*
1448370b324cSopenharmony_ci    {
1449370b324cSopenharmony_ci      FOR_VECTOR (i, OwnerNameMap.Strings)
1450370b324cSopenharmony_ci      {
1451370b324cSopenharmony_ci        AString s;
1452370b324cSopenharmony_ci        ConvertUnicodeToUTF8(OwnerNameMap.Strings[i], s);
1453370b324cSopenharmony_ci        printf("\n%5d %s", (unsigned)OwnerNameMap.Numbers[i], s.Ptr());
1454370b324cSopenharmony_ci      }
1455370b324cSopenharmony_ci    }
1456370b324cSopenharmony_ci    {
1457370b324cSopenharmony_ci      printf("\n\n=========Groups\n");
1458370b324cSopenharmony_ci      FOR_VECTOR (i, OwnerGroupMap.Strings)
1459370b324cSopenharmony_ci      {
1460370b324cSopenharmony_ci        AString s;
1461370b324cSopenharmony_ci        ConvertUnicodeToUTF8(OwnerGroupMap.Strings[i], s);
1462370b324cSopenharmony_ci        printf("\n%5d %s", (unsigned)OwnerGroupMap.Numbers[i], s.Ptr());
1463370b324cSopenharmony_ci      }
1464370b324cSopenharmony_ci    }
1465370b324cSopenharmony_ci    */
1466370b324cSopenharmony_ci  }
1467370b324cSopenharmony_ci      /*
1468370b324cSopenharmony_ci      for (unsigned i = 0 ; i < 100000000; i++)
1469370b324cSopenharmony_ci      {
1470370b324cSopenharmony_ci        // const passwd *pw = getpwuid(1000);
1471370b324cSopenharmony_ci        // pw = pw;
1472370b324cSopenharmony_ci        int pos = OwnerNameMap.Find(1000);
1473370b324cSopenharmony_ci        if (pos < 0 - (int)i)
1474370b324cSopenharmony_ci          throw 1;
1475370b324cSopenharmony_ci      }
1476370b324cSopenharmony_ci      */
1477370b324cSopenharmony_ci
1478370b324cSopenharmony_ci  return S_OK;
1479370b324cSopenharmony_ci}
1480370b324cSopenharmony_ci
1481370b324cSopenharmony_ci#endif
1482370b324cSopenharmony_ci
1483370b324cSopenharmony_ci
1484370b324cSopenharmony_ci
1485370b324cSopenharmony_cistatic const char * const kCannotFindArchive = "Cannot find archive";
1486370b324cSopenharmony_ci
1487370b324cSopenharmony_ciHRESULT EnumerateDirItemsAndSort(
1488370b324cSopenharmony_ci    NWildcard::CCensor &censor,
1489370b324cSopenharmony_ci    NWildcard::ECensorPathMode censorPathMode,
1490370b324cSopenharmony_ci    const UString &addPathPrefix,
1491370b324cSopenharmony_ci    UStringVector &sortedPaths,
1492370b324cSopenharmony_ci    UStringVector &sortedFullPaths,
1493370b324cSopenharmony_ci    CDirItemsStat &st,
1494370b324cSopenharmony_ci    IDirItemsCallback *callback)
1495370b324cSopenharmony_ci{
1496370b324cSopenharmony_ci  FStringVector paths;
1497370b324cSopenharmony_ci
1498370b324cSopenharmony_ci  {
1499370b324cSopenharmony_ci    CDirItems dirItems;
1500370b324cSopenharmony_ci    dirItems.Callback = callback;
1501370b324cSopenharmony_ci    {
1502370b324cSopenharmony_ci      HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems);
1503370b324cSopenharmony_ci      st = dirItems.Stat;
1504370b324cSopenharmony_ci      RINOK(res)
1505370b324cSopenharmony_ci    }
1506370b324cSopenharmony_ci
1507370b324cSopenharmony_ci    FOR_VECTOR (i, dirItems.Items)
1508370b324cSopenharmony_ci    {
1509370b324cSopenharmony_ci      const CDirItem &dirItem = dirItems.Items[i];
1510370b324cSopenharmony_ci      if (!dirItem.IsDir())
1511370b324cSopenharmony_ci        paths.Add(dirItems.GetPhyPath(i));
1512370b324cSopenharmony_ci    }
1513370b324cSopenharmony_ci  }
1514370b324cSopenharmony_ci
1515370b324cSopenharmony_ci  if (paths.Size() == 0)
1516370b324cSopenharmony_ci  {
1517370b324cSopenharmony_ci    // return S_OK;
1518370b324cSopenharmony_ci    throw CMessagePathException(kCannotFindArchive);
1519370b324cSopenharmony_ci  }
1520370b324cSopenharmony_ci
1521370b324cSopenharmony_ci  UStringVector fullPaths;
1522370b324cSopenharmony_ci
1523370b324cSopenharmony_ci  unsigned i;
1524370b324cSopenharmony_ci
1525370b324cSopenharmony_ci  for (i = 0; i < paths.Size(); i++)
1526370b324cSopenharmony_ci  {
1527370b324cSopenharmony_ci    FString fullPath;
1528370b324cSopenharmony_ci    NFile::NDir::MyGetFullPathName(paths[i], fullPath);
1529370b324cSopenharmony_ci    fullPaths.Add(fs2us(fullPath));
1530370b324cSopenharmony_ci  }
1531370b324cSopenharmony_ci
1532370b324cSopenharmony_ci  CUIntVector indices;
1533370b324cSopenharmony_ci  SortFileNames(fullPaths, indices);
1534370b324cSopenharmony_ci  sortedPaths.ClearAndReserve(indices.Size());
1535370b324cSopenharmony_ci  sortedFullPaths.ClearAndReserve(indices.Size());
1536370b324cSopenharmony_ci
1537370b324cSopenharmony_ci  for (i = 0; i < indices.Size(); i++)
1538370b324cSopenharmony_ci  {
1539370b324cSopenharmony_ci    unsigned index = indices[i];
1540370b324cSopenharmony_ci    sortedPaths.AddInReserved(fs2us(paths[index]));
1541370b324cSopenharmony_ci    sortedFullPaths.AddInReserved(fullPaths[index]);
1542370b324cSopenharmony_ci    if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0)
1543370b324cSopenharmony_ci      throw CMessagePathException("Duplicate archive path:", sortedFullPaths[i]);
1544370b324cSopenharmony_ci  }
1545370b324cSopenharmony_ci
1546370b324cSopenharmony_ci  return S_OK;
1547370b324cSopenharmony_ci}
1548370b324cSopenharmony_ci
1549370b324cSopenharmony_ci
1550370b324cSopenharmony_ci
1551370b324cSopenharmony_ci
1552370b324cSopenharmony_ci#ifdef _WIN32
1553370b324cSopenharmony_ci
1554370b324cSopenharmony_cistatic bool IsDotsName(const wchar_t *s)
1555370b324cSopenharmony_ci{
1556370b324cSopenharmony_ci  return s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0));
1557370b324cSopenharmony_ci}
1558370b324cSopenharmony_ci
1559370b324cSopenharmony_ci// This code converts all short file names to long file names.
1560370b324cSopenharmony_ci
1561370b324cSopenharmony_cistatic void ConvertToLongName(const UString &prefix, UString &name)
1562370b324cSopenharmony_ci{
1563370b324cSopenharmony_ci  if (name.IsEmpty()
1564370b324cSopenharmony_ci      || DoesNameContainWildcard(name)
1565370b324cSopenharmony_ci      || IsDotsName(name))
1566370b324cSopenharmony_ci    return;
1567370b324cSopenharmony_ci  NFind::CFileInfo fi;
1568370b324cSopenharmony_ci  const FString path (us2fs(prefix + name));
1569370b324cSopenharmony_ci  #ifndef UNDER_CE
1570370b324cSopenharmony_ci  if (NFile::NName::IsDevicePath(path))
1571370b324cSopenharmony_ci    return;
1572370b324cSopenharmony_ci  #endif
1573370b324cSopenharmony_ci  if (fi.Find(path))
1574370b324cSopenharmony_ci    name = fs2us(fi.Name);
1575370b324cSopenharmony_ci}
1576370b324cSopenharmony_ci
1577370b324cSopenharmony_cistatic void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)
1578370b324cSopenharmony_ci{
1579370b324cSopenharmony_ci  FOR_VECTOR (i, items)
1580370b324cSopenharmony_ci  {
1581370b324cSopenharmony_ci    NWildcard::CItem &item = items[i];
1582370b324cSopenharmony_ci    if (item.Recursive || item.PathParts.Size() != 1)
1583370b324cSopenharmony_ci      continue;
1584370b324cSopenharmony_ci    if (prefix.IsEmpty() && item.IsDriveItem())
1585370b324cSopenharmony_ci      continue;
1586370b324cSopenharmony_ci    ConvertToLongName(prefix, item.PathParts.Front());
1587370b324cSopenharmony_ci  }
1588370b324cSopenharmony_ci}
1589370b324cSopenharmony_ci
1590370b324cSopenharmony_cistatic void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node)
1591370b324cSopenharmony_ci{
1592370b324cSopenharmony_ci  ConvertToLongNames(prefix, node.IncludeItems);
1593370b324cSopenharmony_ci  ConvertToLongNames(prefix, node.ExcludeItems);
1594370b324cSopenharmony_ci  unsigned i;
1595370b324cSopenharmony_ci  for (i = 0; i < node.SubNodes.Size(); i++)
1596370b324cSopenharmony_ci  {
1597370b324cSopenharmony_ci    UString &name = node.SubNodes[i].Name;
1598370b324cSopenharmony_ci    if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name))
1599370b324cSopenharmony_ci      continue;
1600370b324cSopenharmony_ci    ConvertToLongName(prefix, name);
1601370b324cSopenharmony_ci  }
1602370b324cSopenharmony_ci  // mix folders with same name
1603370b324cSopenharmony_ci  for (i = 0; i < node.SubNodes.Size(); i++)
1604370b324cSopenharmony_ci  {
1605370b324cSopenharmony_ci    NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];
1606370b324cSopenharmony_ci    for (unsigned j = i + 1; j < node.SubNodes.Size();)
1607370b324cSopenharmony_ci    {
1608370b324cSopenharmony_ci      const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
1609370b324cSopenharmony_ci      if (nextNode1.Name.IsEqualTo_NoCase(nextNode2.Name))
1610370b324cSopenharmony_ci      {
1611370b324cSopenharmony_ci        nextNode1.IncludeItems += nextNode2.IncludeItems;
1612370b324cSopenharmony_ci        nextNode1.ExcludeItems += nextNode2.ExcludeItems;
1613370b324cSopenharmony_ci        node.SubNodes.Delete(j);
1614370b324cSopenharmony_ci      }
1615370b324cSopenharmony_ci      else
1616370b324cSopenharmony_ci        j++;
1617370b324cSopenharmony_ci    }
1618370b324cSopenharmony_ci  }
1619370b324cSopenharmony_ci  for (i = 0; i < node.SubNodes.Size(); i++)
1620370b324cSopenharmony_ci  {
1621370b324cSopenharmony_ci    NWildcard::CCensorNode &nextNode = node.SubNodes[i];
1622370b324cSopenharmony_ci    ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode);
1623370b324cSopenharmony_ci  }
1624370b324cSopenharmony_ci}
1625370b324cSopenharmony_ci
1626370b324cSopenharmony_civoid ConvertToLongNames(NWildcard::CCensor &censor)
1627370b324cSopenharmony_ci{
1628370b324cSopenharmony_ci  FOR_VECTOR (i, censor.Pairs)
1629370b324cSopenharmony_ci  {
1630370b324cSopenharmony_ci    NWildcard::CPair &pair = censor.Pairs[i];
1631370b324cSopenharmony_ci    ConvertToLongNames(pair.Prefix, pair.Head);
1632370b324cSopenharmony_ci  }
1633370b324cSopenharmony_ci}
1634370b324cSopenharmony_ci
1635370b324cSopenharmony_ci#endif
1636370b324cSopenharmony_ci
1637370b324cSopenharmony_ci
1638370b324cSopenharmony_ciCMessagePathException::CMessagePathException(const char *a, const wchar_t *u)
1639370b324cSopenharmony_ci{
1640370b324cSopenharmony_ci  (*this) += a;
1641370b324cSopenharmony_ci  if (u)
1642370b324cSopenharmony_ci  {
1643370b324cSopenharmony_ci    Add_LF();
1644370b324cSopenharmony_ci    (*this) += u;
1645370b324cSopenharmony_ci  }
1646370b324cSopenharmony_ci}
1647370b324cSopenharmony_ci
1648370b324cSopenharmony_ciCMessagePathException::CMessagePathException(const wchar_t *a, const wchar_t *u)
1649370b324cSopenharmony_ci{
1650370b324cSopenharmony_ci  (*this) += a;
1651370b324cSopenharmony_ci  if (u)
1652370b324cSopenharmony_ci  {
1653370b324cSopenharmony_ci    Add_LF();
1654370b324cSopenharmony_ci    (*this) += u;
1655370b324cSopenharmony_ci  }
1656370b324cSopenharmony_ci}
1657