xref: /aosp_15_r20/external/lzma/CPP/Windows/FileFind.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Windows/FileFind.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
8*f6dc9357SAndroid Build Coastguard Worker #include <fcntl.h>           /* Definition of AT_* constants */
9*f6dc9357SAndroid Build Coastguard Worker #include "TimeUtils.h"
10*f6dc9357SAndroid Build Coastguard Worker // for major
11*f6dc9357SAndroid Build Coastguard Worker // #include <sys/sysmacros.h>
12*f6dc9357SAndroid Build Coastguard Worker #endif
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "FileFind.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "FileIO.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "FileName.h"
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
19*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
20*f6dc9357SAndroid Build Coastguard Worker #endif
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
23*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
24*f6dc9357SAndroid Build Coastguard Worker using namespace NName;
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
27*f6dc9357SAndroid Build Coastguard Worker 
28*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502  // Win2003
29*f6dc9357SAndroid Build Coastguard Worker #define Z7_USE_DYN_FindFirstStream
30*f6dc9357SAndroid Build Coastguard Worker #endif
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_FindFirstStream
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_BEGIN
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker typedef enum
39*f6dc9357SAndroid Build Coastguard Worker {
40*f6dc9357SAndroid Build Coastguard Worker   My_FindStreamInfoStandard,
41*f6dc9357SAndroid Build Coastguard Worker   My_FindStreamInfoMaxInfoLevel
42*f6dc9357SAndroid Build Coastguard Worker } MY_STREAM_INFO_LEVELS;
43*f6dc9357SAndroid Build Coastguard Worker 
44*f6dc9357SAndroid Build Coastguard Worker typedef struct
45*f6dc9357SAndroid Build Coastguard Worker {
46*f6dc9357SAndroid Build Coastguard Worker   LARGE_INTEGER StreamSize;
47*f6dc9357SAndroid Build Coastguard Worker   WCHAR cStreamName[MAX_PATH + 36];
48*f6dc9357SAndroid Build Coastguard Worker } MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA;
49*f6dc9357SAndroid Build Coastguard Worker 
50*f6dc9357SAndroid Build Coastguard Worker typedef HANDLE (WINAPI *Func_FindFirstStreamW)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel,
51*f6dc9357SAndroid Build Coastguard Worker     LPVOID findStreamData, DWORD flags);
52*f6dc9357SAndroid Build Coastguard Worker 
53*f6dc9357SAndroid Build Coastguard Worker typedef BOOL (APIENTRY *Func_FindNextStreamW)(HANDLE findStream, LPVOID findStreamData);
54*f6dc9357SAndroid Build Coastguard Worker 
55*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_END
56*f6dc9357SAndroid Build Coastguard Worker 
57*f6dc9357SAndroid Build Coastguard Worker #else
58*f6dc9357SAndroid Build Coastguard Worker 
59*f6dc9357SAndroid Build Coastguard Worker #define MY_WIN32_FIND_STREAM_DATA  WIN32_FIND_STREAM_DATA
60*f6dc9357SAndroid Build Coastguard Worker #define My_FindStreamInfoStandard  FindStreamInfoStandard
61*f6dc9357SAndroid Build Coastguard Worker 
62*f6dc9357SAndroid Build Coastguard Worker #endif
63*f6dc9357SAndroid Build Coastguard Worker #endif // defined(_WIN32) && !defined(UNDER_CE)
64*f6dc9357SAndroid Build Coastguard Worker 
65*f6dc9357SAndroid Build Coastguard Worker 
66*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
67*f6dc9357SAndroid Build Coastguard Worker namespace NFile {
68*f6dc9357SAndroid Build Coastguard Worker 
69*f6dc9357SAndroid Build Coastguard Worker 
70*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
71*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
72*f6dc9357SAndroid Build Coastguard Worker namespace NSystem
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
75*f6dc9357SAndroid Build Coastguard Worker }
76*f6dc9357SAndroid Build Coastguard Worker #endif
77*f6dc9357SAndroid Build Coastguard Worker #endif
78*f6dc9357SAndroid Build Coastguard Worker 
79*f6dc9357SAndroid Build Coastguard Worker namespace NFind {
80*f6dc9357SAndroid Build Coastguard Worker 
81*f6dc9357SAndroid Build Coastguard Worker /*
82*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
83*f6dc9357SAndroid Build Coastguard Worker #define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;
84*f6dc9357SAndroid Build Coastguard Worker #else
85*f6dc9357SAndroid Build Coastguard Worker #define MY_CLEAR_FILETIME(ft) ft.tv_sec = 0;  ft.tv_nsec = 0;
86*f6dc9357SAndroid Build Coastguard Worker #endif
87*f6dc9357SAndroid Build Coastguard Worker */
88*f6dc9357SAndroid Build Coastguard Worker 
ClearBase()89*f6dc9357SAndroid Build Coastguard Worker void CFileInfoBase::ClearBase() throw()
90*f6dc9357SAndroid Build Coastguard Worker {
91*f6dc9357SAndroid Build Coastguard Worker   Size = 0;
92*f6dc9357SAndroid Build Coastguard Worker   FiTime_Clear(CTime);
93*f6dc9357SAndroid Build Coastguard Worker   FiTime_Clear(ATime);
94*f6dc9357SAndroid Build Coastguard Worker   FiTime_Clear(MTime);
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker  #ifdef _WIN32
97*f6dc9357SAndroid Build Coastguard Worker   Attrib = 0;
98*f6dc9357SAndroid Build Coastguard Worker   // ReparseTag = 0;
99*f6dc9357SAndroid Build Coastguard Worker   IsAltStream = false;
100*f6dc9357SAndroid Build Coastguard Worker   IsDevice = false;
101*f6dc9357SAndroid Build Coastguard Worker  #else
102*f6dc9357SAndroid Build Coastguard Worker   dev = 0;
103*f6dc9357SAndroid Build Coastguard Worker   ino = 0;
104*f6dc9357SAndroid Build Coastguard Worker   mode = 0;
105*f6dc9357SAndroid Build Coastguard Worker   nlink = 0;
106*f6dc9357SAndroid Build Coastguard Worker   uid = 0;
107*f6dc9357SAndroid Build Coastguard Worker   gid = 0;
108*f6dc9357SAndroid Build Coastguard Worker   rdev = 0;
109*f6dc9357SAndroid Build Coastguard Worker  #endif
110*f6dc9357SAndroid Build Coastguard Worker }
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker 
SetAs_StdInFile()113*f6dc9357SAndroid Build Coastguard Worker bool CFileInfoBase::SetAs_StdInFile()
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker   ClearBase();
116*f6dc9357SAndroid Build Coastguard Worker   Size = (UInt64)(Int64)-1;
117*f6dc9357SAndroid Build Coastguard Worker   NTime::GetCurUtc_FiTime(MTime);
118*f6dc9357SAndroid Build Coastguard Worker   CTime = ATime = MTime;
119*f6dc9357SAndroid Build Coastguard Worker 
120*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker   /* in GUI mode : GetStdHandle(STD_INPUT_HANDLE) returns NULL,
123*f6dc9357SAndroid Build Coastguard Worker      and it doesn't set LastError.  */
124*f6dc9357SAndroid Build Coastguard Worker #if 1
125*f6dc9357SAndroid Build Coastguard Worker   SetLastError(0);
126*f6dc9357SAndroid Build Coastguard Worker   const HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
127*f6dc9357SAndroid Build Coastguard Worker   if (!h || h == INVALID_HANDLE_VALUE)
128*f6dc9357SAndroid Build Coastguard Worker   {
129*f6dc9357SAndroid Build Coastguard Worker     if (GetLastError() == 0)
130*f6dc9357SAndroid Build Coastguard Worker       SetLastError(ERROR_INVALID_HANDLE);
131*f6dc9357SAndroid Build Coastguard Worker     return false;
132*f6dc9357SAndroid Build Coastguard Worker   }
133*f6dc9357SAndroid Build Coastguard Worker   BY_HANDLE_FILE_INFORMATION info;
134*f6dc9357SAndroid Build Coastguard Worker   if (GetFileInformationByHandle(h, &info)
135*f6dc9357SAndroid Build Coastguard Worker       && info.dwVolumeSerialNumber)
136*f6dc9357SAndroid Build Coastguard Worker   {
137*f6dc9357SAndroid Build Coastguard Worker     Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
138*f6dc9357SAndroid Build Coastguard Worker     // FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
139*f6dc9357SAndroid Build Coastguard Worker     // NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;
140*f6dc9357SAndroid Build Coastguard Worker     Attrib = info.dwFileAttributes;
141*f6dc9357SAndroid Build Coastguard Worker     CTime = info.ftCreationTime;
142*f6dc9357SAndroid Build Coastguard Worker     ATime = info.ftLastAccessTime;
143*f6dc9357SAndroid Build Coastguard Worker     MTime = info.ftLastWriteTime;
144*f6dc9357SAndroid Build Coastguard Worker   }
145*f6dc9357SAndroid Build Coastguard Worker #if 0
146*f6dc9357SAndroid Build Coastguard Worker   printf(
147*f6dc9357SAndroid Build Coastguard Worker     "\ndwFileAttributes = %8x"
148*f6dc9357SAndroid Build Coastguard Worker     "\nftCreationTime   = %8x"
149*f6dc9357SAndroid Build Coastguard Worker     "\nftLastAccessTime = %8x"
150*f6dc9357SAndroid Build Coastguard Worker     "\nftLastWriteTime  = %8x"
151*f6dc9357SAndroid Build Coastguard Worker     "\ndwVolumeSerialNumber  = %8x"
152*f6dc9357SAndroid Build Coastguard Worker     "\nnFileSizeHigh  = %8x"
153*f6dc9357SAndroid Build Coastguard Worker     "\nnFileSizeLow   = %8x"
154*f6dc9357SAndroid Build Coastguard Worker     "\nnNumberOfLinks  = %8x"
155*f6dc9357SAndroid Build Coastguard Worker     "\nnFileIndexHigh  = %8x"
156*f6dc9357SAndroid Build Coastguard Worker     "\nnFileIndexLow   = %8x \n",
157*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.dwFileAttributes,
158*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.ftCreationTime.dwHighDateTime,
159*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.ftLastAccessTime.dwHighDateTime,
160*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.ftLastWriteTime.dwHighDateTime,
161*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.dwVolumeSerialNumber,
162*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.nFileSizeHigh,
163*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.nFileSizeLow,
164*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.nNumberOfLinks,
165*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.nFileIndexHigh,
166*f6dc9357SAndroid Build Coastguard Worker       (unsigned)info.nFileIndexLow);
167*f6dc9357SAndroid Build Coastguard Worker #endif
168*f6dc9357SAndroid Build Coastguard Worker #endif
169*f6dc9357SAndroid Build Coastguard Worker 
170*f6dc9357SAndroid Build Coastguard Worker #else // non-Wiondow
171*f6dc9357SAndroid Build Coastguard Worker 
172*f6dc9357SAndroid Build Coastguard Worker   mode = S_IFIFO | 0777; // 0755 : 0775 : 0664 : 0644 :
173*f6dc9357SAndroid Build Coastguard Worker #if 1
174*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
175*f6dc9357SAndroid Build Coastguard Worker   if (fstat(0, &st) == 0)
176*f6dc9357SAndroid Build Coastguard Worker   {
177*f6dc9357SAndroid Build Coastguard Worker     SetFrom_stat(st);
178*f6dc9357SAndroid Build Coastguard Worker     if (!S_ISREG(st.st_mode)
179*f6dc9357SAndroid Build Coastguard Worker         // S_ISFIFO(st->st_mode)
180*f6dc9357SAndroid Build Coastguard Worker         || st.st_size == 0)
181*f6dc9357SAndroid Build Coastguard Worker     {
182*f6dc9357SAndroid Build Coastguard Worker       Size = (UInt64)(Int64)-1;
183*f6dc9357SAndroid Build Coastguard Worker       // mode = S_IFIFO | 0777;
184*f6dc9357SAndroid Build Coastguard Worker     }
185*f6dc9357SAndroid Build Coastguard Worker   }
186*f6dc9357SAndroid Build Coastguard Worker #endif
187*f6dc9357SAndroid Build Coastguard Worker #endif
188*f6dc9357SAndroid Build Coastguard Worker 
189*f6dc9357SAndroid Build Coastguard Worker   return true;
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker 
IsDots() const192*f6dc9357SAndroid Build Coastguard Worker bool CFileInfo::IsDots() const throw()
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker   if (!IsDir() || Name.IsEmpty())
195*f6dc9357SAndroid Build Coastguard Worker     return false;
196*f6dc9357SAndroid Build Coastguard Worker   if (Name[0] != '.')
197*f6dc9357SAndroid Build Coastguard Worker     return false;
198*f6dc9357SAndroid Build Coastguard Worker   return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');
199*f6dc9357SAndroid Build Coastguard Worker }
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
203*f6dc9357SAndroid Build Coastguard Worker 
204*f6dc9357SAndroid Build Coastguard Worker 
205*f6dc9357SAndroid Build Coastguard Worker #define WIN_FD_TO_MY_FI(fi, fd) \
206*f6dc9357SAndroid Build Coastguard Worker   fi.Attrib = fd.dwFileAttributes; \
207*f6dc9357SAndroid Build Coastguard Worker   fi.CTime = fd.ftCreationTime; \
208*f6dc9357SAndroid Build Coastguard Worker   fi.ATime = fd.ftLastAccessTime; \
209*f6dc9357SAndroid Build Coastguard Worker   fi.MTime = fd.ftLastWriteTime; \
210*f6dc9357SAndroid Build Coastguard Worker   fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \
211*f6dc9357SAndroid Build Coastguard Worker   /* fi.ReparseTag = fd.dwReserved0; */ \
212*f6dc9357SAndroid Build Coastguard Worker   fi.IsAltStream = false; \
213*f6dc9357SAndroid Build Coastguard Worker   fi.IsDevice = false;
214*f6dc9357SAndroid Build Coastguard Worker 
215*f6dc9357SAndroid Build Coastguard Worker   /*
216*f6dc9357SAndroid Build Coastguard Worker   #ifdef UNDER_CE
217*f6dc9357SAndroid Build Coastguard Worker   fi.ObjectID = fd.dwOID;
218*f6dc9357SAndroid Build Coastguard Worker   #else
219*f6dc9357SAndroid Build Coastguard Worker   fi.ReparseTag = fd.dwReserved0;
220*f6dc9357SAndroid Build Coastguard Worker   #endif
221*f6dc9357SAndroid Build Coastguard Worker   */
222*f6dc9357SAndroid Build Coastguard Worker 
Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW & fd,CFileInfo & fi)223*f6dc9357SAndroid Build Coastguard Worker static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi)
224*f6dc9357SAndroid Build Coastguard Worker {
225*f6dc9357SAndroid Build Coastguard Worker   WIN_FD_TO_MY_FI(fi, fd)
226*f6dc9357SAndroid Build Coastguard Worker   fi.Name = us2fs(fd.cFileName);
227*f6dc9357SAndroid Build Coastguard Worker   #if defined(_WIN32) && !defined(UNDER_CE)
228*f6dc9357SAndroid Build Coastguard Worker   // fi.ShortName = us2fs(fd.cAlternateFileName);
229*f6dc9357SAndroid Build Coastguard Worker   #endif
230*f6dc9357SAndroid Build Coastguard Worker }
231*f6dc9357SAndroid Build Coastguard Worker 
232*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA & fd,CFileInfo & fi)233*f6dc9357SAndroid Build Coastguard Worker static void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)
234*f6dc9357SAndroid Build Coastguard Worker {
235*f6dc9357SAndroid Build Coastguard Worker   WIN_FD_TO_MY_FI(fi, fd)
236*f6dc9357SAndroid Build Coastguard Worker   fi.Name = fas2fs(fd.cFileName);
237*f6dc9357SAndroid Build Coastguard Worker   #if defined(_WIN32) && !defined(UNDER_CE)
238*f6dc9357SAndroid Build Coastguard Worker   // fi.ShortName = fas2fs(fd.cAlternateFileName);
239*f6dc9357SAndroid Build Coastguard Worker   #endif
240*f6dc9357SAndroid Build Coastguard Worker }
241*f6dc9357SAndroid Build Coastguard Worker #endif
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker ////////////////////////////////
244*f6dc9357SAndroid Build Coastguard Worker // CFindFile
245*f6dc9357SAndroid Build Coastguard Worker 
Close()246*f6dc9357SAndroid Build Coastguard Worker bool CFindFileBase::Close() throw()
247*f6dc9357SAndroid Build Coastguard Worker {
248*f6dc9357SAndroid Build Coastguard Worker   if (_handle == INVALID_HANDLE_VALUE)
249*f6dc9357SAndroid Build Coastguard Worker     return true;
250*f6dc9357SAndroid Build Coastguard Worker   if (!::FindClose(_handle))
251*f6dc9357SAndroid Build Coastguard Worker     return false;
252*f6dc9357SAndroid Build Coastguard Worker   _handle = INVALID_HANDLE_VALUE;
253*f6dc9357SAndroid Build Coastguard Worker   return true;
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker 
256*f6dc9357SAndroid Build Coastguard Worker /*
257*f6dc9357SAndroid Build Coastguard Worker WinXP-64 FindFirstFile():
258*f6dc9357SAndroid Build Coastguard Worker   ""      -  ERROR_PATH_NOT_FOUND
259*f6dc9357SAndroid Build Coastguard Worker   folder\ -  ERROR_FILE_NOT_FOUND
260*f6dc9357SAndroid Build Coastguard Worker   \       -  ERROR_FILE_NOT_FOUND
261*f6dc9357SAndroid Build Coastguard Worker   c:\     -  ERROR_FILE_NOT_FOUND
262*f6dc9357SAndroid Build Coastguard Worker   c:      -  ERROR_FILE_NOT_FOUND, if current dir is ROOT     ( c:\ )
263*f6dc9357SAndroid Build Coastguard Worker   c:      -  OK,                   if current dir is NOT ROOT ( c:\folder )
264*f6dc9357SAndroid Build Coastguard Worker   folder  -  OK
265*f6dc9357SAndroid Build Coastguard Worker 
266*f6dc9357SAndroid Build Coastguard Worker   \\               - ERROR_INVALID_NAME
267*f6dc9357SAndroid Build Coastguard Worker   \\Server         - ERROR_INVALID_NAME
268*f6dc9357SAndroid Build Coastguard Worker   \\Server\        - ERROR_INVALID_NAME
269*f6dc9357SAndroid Build Coastguard Worker 
270*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share            - ERROR_BAD_NETPATH
271*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share            - ERROR_BAD_NET_NAME (Win7).
272*f6dc9357SAndroid Build Coastguard Worker              !!! There is problem : Win7 makes some requests for "\\Server\Shar" (look in Procmon),
273*f6dc9357SAndroid Build Coastguard Worker                  when we call it for "\\Server\Share"
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share\           - ERROR_FILE_NOT_FOUND
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker   \\?\UNC\Server\Share      - ERROR_INVALID_NAME
278*f6dc9357SAndroid Build Coastguard Worker   \\?\UNC\Server\Share      - ERROR_BAD_PATHNAME (Win7)
279*f6dc9357SAndroid Build Coastguard Worker   \\?\UNC\Server\Share\     - ERROR_FILE_NOT_FOUND
280*f6dc9357SAndroid Build Coastguard Worker 
281*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share_RootDrive  - ERROR_INVALID_NAME
282*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share_RootDrive\ - ERROR_INVALID_NAME
283*f6dc9357SAndroid Build Coastguard Worker 
284*f6dc9357SAndroid Build Coastguard Worker   e:\* - ERROR_FILE_NOT_FOUND, if there are no items in that root folder
285*f6dc9357SAndroid Build Coastguard Worker   w:\* - ERROR_PATH_NOT_FOUND, if there is no such drive w:
286*f6dc9357SAndroid Build Coastguard Worker */
287*f6dc9357SAndroid Build Coastguard Worker 
FindFirst(CFSTR path,CFileInfo & fi)288*f6dc9357SAndroid Build Coastguard Worker bool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)
289*f6dc9357SAndroid Build Coastguard Worker {
290*f6dc9357SAndroid Build Coastguard Worker   if (!Close())
291*f6dc9357SAndroid Build Coastguard Worker     return false;
292*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
293*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
294*f6dc9357SAndroid Build Coastguard Worker   {
295*f6dc9357SAndroid Build Coastguard Worker     WIN32_FIND_DATAA fd;
296*f6dc9357SAndroid Build Coastguard Worker     _handle = ::FindFirstFileA(fs2fas(path), &fd);
297*f6dc9357SAndroid Build Coastguard Worker     if (_handle == INVALID_HANDLE_VALUE)
298*f6dc9357SAndroid Build Coastguard Worker       return false;
299*f6dc9357SAndroid Build Coastguard Worker     Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);
300*f6dc9357SAndroid Build Coastguard Worker   }
301*f6dc9357SAndroid Build Coastguard Worker   else
302*f6dc9357SAndroid Build Coastguard Worker   #endif
303*f6dc9357SAndroid Build Coastguard Worker   {
304*f6dc9357SAndroid Build Coastguard Worker     WIN32_FIND_DATAW fd;
305*f6dc9357SAndroid Build Coastguard Worker 
306*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
307*f6dc9357SAndroid Build Coastguard Worker       _handle = ::FindFirstFileW(fs2us(path), &fd);
308*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
309*f6dc9357SAndroid Build Coastguard Worker     if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
310*f6dc9357SAndroid Build Coastguard Worker     {
311*f6dc9357SAndroid Build Coastguard Worker       UString superPath;
312*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPath(path, superPath, USE_MAIN_PATH))
313*f6dc9357SAndroid Build Coastguard Worker         _handle = ::FindFirstFileW(superPath, &fd);
314*f6dc9357SAndroid Build Coastguard Worker     }
315*f6dc9357SAndroid Build Coastguard Worker     #endif
316*f6dc9357SAndroid Build Coastguard Worker     if (_handle == INVALID_HANDLE_VALUE)
317*f6dc9357SAndroid Build Coastguard Worker       return false;
318*f6dc9357SAndroid Build Coastguard Worker     Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);
319*f6dc9357SAndroid Build Coastguard Worker   }
320*f6dc9357SAndroid Build Coastguard Worker   return true;
321*f6dc9357SAndroid Build Coastguard Worker }
322*f6dc9357SAndroid Build Coastguard Worker 
FindNext(CFileInfo & fi)323*f6dc9357SAndroid Build Coastguard Worker bool CFindFile::FindNext(CFileInfo &fi)
324*f6dc9357SAndroid Build Coastguard Worker {
325*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
326*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
327*f6dc9357SAndroid Build Coastguard Worker   {
328*f6dc9357SAndroid Build Coastguard Worker     WIN32_FIND_DATAA fd;
329*f6dc9357SAndroid Build Coastguard Worker     if (!::FindNextFileA(_handle, &fd))
330*f6dc9357SAndroid Build Coastguard Worker       return false;
331*f6dc9357SAndroid Build Coastguard Worker     Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);
332*f6dc9357SAndroid Build Coastguard Worker   }
333*f6dc9357SAndroid Build Coastguard Worker   else
334*f6dc9357SAndroid Build Coastguard Worker   #endif
335*f6dc9357SAndroid Build Coastguard Worker   {
336*f6dc9357SAndroid Build Coastguard Worker     WIN32_FIND_DATAW fd;
337*f6dc9357SAndroid Build Coastguard Worker     if (!::FindNextFileW(_handle, &fd))
338*f6dc9357SAndroid Build Coastguard Worker       return false;
339*f6dc9357SAndroid Build Coastguard Worker     Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);
340*f6dc9357SAndroid Build Coastguard Worker   }
341*f6dc9357SAndroid Build Coastguard Worker   return true;
342*f6dc9357SAndroid Build Coastguard Worker }
343*f6dc9357SAndroid Build Coastguard Worker 
344*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(UNDER_CE)
345*f6dc9357SAndroid Build Coastguard Worker 
346*f6dc9357SAndroid Build Coastguard Worker ////////////////////////////////
347*f6dc9357SAndroid Build Coastguard Worker // AltStreams
348*f6dc9357SAndroid Build Coastguard Worker 
349*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_FindFirstStream
350*f6dc9357SAndroid Build Coastguard Worker static Func_FindFirstStreamW g_FindFirstStreamW;
351*f6dc9357SAndroid Build Coastguard Worker static Func_FindNextStreamW  g_FindNextStreamW;
352*f6dc9357SAndroid Build Coastguard Worker #define MY_FindFirstStreamW  g_FindFirstStreamW
353*f6dc9357SAndroid Build Coastguard Worker #define MY_FindNextStreamW   g_FindNextStreamW
354*f6dc9357SAndroid Build Coastguard Worker static struct CFindStreamLoader
355*f6dc9357SAndroid Build Coastguard Worker {
CFindStreamLoaderNWindows::NFile::NFind::CFindStreamLoader356*f6dc9357SAndroid Build Coastguard Worker   CFindStreamLoader()
357*f6dc9357SAndroid Build Coastguard Worker   {
358*f6dc9357SAndroid Build Coastguard Worker     const HMODULE hm = ::GetModuleHandleA("kernel32.dll");
359*f6dc9357SAndroid Build Coastguard Worker        g_FindFirstStreamW = Z7_GET_PROC_ADDRESS(
360*f6dc9357SAndroid Build Coastguard Worker     Func_FindFirstStreamW, hm,
361*f6dc9357SAndroid Build Coastguard Worker         "FindFirstStreamW");
362*f6dc9357SAndroid Build Coastguard Worker        g_FindNextStreamW = Z7_GET_PROC_ADDRESS(
363*f6dc9357SAndroid Build Coastguard Worker     Func_FindNextStreamW, hm,
364*f6dc9357SAndroid Build Coastguard Worker         "FindNextStreamW");
365*f6dc9357SAndroid Build Coastguard Worker   }
366*f6dc9357SAndroid Build Coastguard Worker } g_FindStreamLoader;
367*f6dc9357SAndroid Build Coastguard Worker #else
368*f6dc9357SAndroid Build Coastguard Worker #define MY_FindFirstStreamW  FindFirstStreamW
369*f6dc9357SAndroid Build Coastguard Worker #define MY_FindNextStreamW   FindNextStreamW
370*f6dc9357SAndroid Build Coastguard Worker #endif
371*f6dc9357SAndroid Build Coastguard Worker 
372*f6dc9357SAndroid Build Coastguard Worker 
IsMainStream() const373*f6dc9357SAndroid Build Coastguard Worker bool CStreamInfo::IsMainStream() const throw()
374*f6dc9357SAndroid Build Coastguard Worker {
375*f6dc9357SAndroid Build Coastguard Worker   return StringsAreEqualNoCase_Ascii(Name, "::$DATA");
376*f6dc9357SAndroid Build Coastguard Worker }
377*f6dc9357SAndroid Build Coastguard Worker 
GetReducedName() const378*f6dc9357SAndroid Build Coastguard Worker UString CStreamInfo::GetReducedName() const
379*f6dc9357SAndroid Build Coastguard Worker {
380*f6dc9357SAndroid Build Coastguard Worker   // remove ":$DATA" postfix, but keep postfix, if Name is "::$DATA"
381*f6dc9357SAndroid Build Coastguard Worker   UString s (Name);
382*f6dc9357SAndroid Build Coastguard Worker   if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), ":$DATA"))
383*f6dc9357SAndroid Build Coastguard Worker     s.DeleteFrom(s.Len() - 6);
384*f6dc9357SAndroid Build Coastguard Worker   return s;
385*f6dc9357SAndroid Build Coastguard Worker }
386*f6dc9357SAndroid Build Coastguard Worker 
387*f6dc9357SAndroid Build Coastguard Worker /*
388*f6dc9357SAndroid Build Coastguard Worker UString CStreamInfo::GetReducedName2() const
389*f6dc9357SAndroid Build Coastguard Worker {
390*f6dc9357SAndroid Build Coastguard Worker   UString s = GetReducedName();
391*f6dc9357SAndroid Build Coastguard Worker   if (!s.IsEmpty() && s[0] == ':')
392*f6dc9357SAndroid Build Coastguard Worker     s.Delete(0);
393*f6dc9357SAndroid Build Coastguard Worker   return s;
394*f6dc9357SAndroid Build Coastguard Worker }
395*f6dc9357SAndroid Build Coastguard Worker */
396*f6dc9357SAndroid Build Coastguard Worker 
Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA & sd,CStreamInfo & si)397*f6dc9357SAndroid Build Coastguard Worker static void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si)
398*f6dc9357SAndroid Build Coastguard Worker {
399*f6dc9357SAndroid Build Coastguard Worker   si.Size = (UInt64)sd.StreamSize.QuadPart;
400*f6dc9357SAndroid Build Coastguard Worker   si.Name = sd.cStreamName;
401*f6dc9357SAndroid Build Coastguard Worker }
402*f6dc9357SAndroid Build Coastguard Worker 
403*f6dc9357SAndroid Build Coastguard Worker /*
404*f6dc9357SAndroid Build Coastguard Worker   WinXP-64 FindFirstStream():
405*f6dc9357SAndroid Build Coastguard Worker   ""      -  ERROR_PATH_NOT_FOUND
406*f6dc9357SAndroid Build Coastguard Worker   folder\ -  OK
407*f6dc9357SAndroid Build Coastguard Worker   folder  -  OK
408*f6dc9357SAndroid Build Coastguard Worker   \       -  OK
409*f6dc9357SAndroid Build Coastguard Worker   c:\     -  OK
410*f6dc9357SAndroid Build Coastguard Worker   c:      -  OK, if current dir is ROOT     ( c:\ )
411*f6dc9357SAndroid Build Coastguard Worker   c:      -  OK, if current dir is NOT ROOT ( c:\folder )
412*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share   - OK
413*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share\  - OK
414*f6dc9357SAndroid Build Coastguard Worker 
415*f6dc9357SAndroid Build Coastguard Worker   \\               - ERROR_INVALID_NAME
416*f6dc9357SAndroid Build Coastguard Worker   \\Server         - ERROR_INVALID_NAME
417*f6dc9357SAndroid Build Coastguard Worker   \\Server\        - ERROR_INVALID_NAME
418*f6dc9357SAndroid Build Coastguard Worker */
419*f6dc9357SAndroid Build Coastguard Worker 
FindFirst(CFSTR path,CStreamInfo & si)420*f6dc9357SAndroid Build Coastguard Worker bool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)
421*f6dc9357SAndroid Build Coastguard Worker {
422*f6dc9357SAndroid Build Coastguard Worker   if (!Close())
423*f6dc9357SAndroid Build Coastguard Worker     return false;
424*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_FindFirstStream
425*f6dc9357SAndroid Build Coastguard Worker   if (!g_FindFirstStreamW)
426*f6dc9357SAndroid Build Coastguard Worker   {
427*f6dc9357SAndroid Build Coastguard Worker     ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
428*f6dc9357SAndroid Build Coastguard Worker     return false;
429*f6dc9357SAndroid Build Coastguard Worker   }
430*f6dc9357SAndroid Build Coastguard Worker #endif
431*f6dc9357SAndroid Build Coastguard Worker   {
432*f6dc9357SAndroid Build Coastguard Worker     MY_WIN32_FIND_STREAM_DATA sd;
433*f6dc9357SAndroid Build Coastguard Worker     SetLastError(0);
434*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
435*f6dc9357SAndroid Build Coastguard Worker       _handle = MY_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0);
436*f6dc9357SAndroid Build Coastguard Worker     if (_handle == INVALID_HANDLE_VALUE)
437*f6dc9357SAndroid Build Coastguard Worker     {
438*f6dc9357SAndroid Build Coastguard Worker       if (::GetLastError() == ERROR_HANDLE_EOF)
439*f6dc9357SAndroid Build Coastguard Worker         return false;
440*f6dc9357SAndroid Build Coastguard Worker       // long name can be tricky for path like ".\dirName".
441*f6dc9357SAndroid Build Coastguard Worker       #ifdef Z7_LONG_PATH
442*f6dc9357SAndroid Build Coastguard Worker       if (USE_SUPER_PATH)
443*f6dc9357SAndroid Build Coastguard Worker       {
444*f6dc9357SAndroid Build Coastguard Worker         UString superPath;
445*f6dc9357SAndroid Build Coastguard Worker         if (GetSuperPath(path, superPath, USE_MAIN_PATH))
446*f6dc9357SAndroid Build Coastguard Worker           _handle = MY_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0);
447*f6dc9357SAndroid Build Coastguard Worker       }
448*f6dc9357SAndroid Build Coastguard Worker       #endif
449*f6dc9357SAndroid Build Coastguard Worker     }
450*f6dc9357SAndroid Build Coastguard Worker     if (_handle == INVALID_HANDLE_VALUE)
451*f6dc9357SAndroid Build Coastguard Worker       return false;
452*f6dc9357SAndroid Build Coastguard Worker     Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);
453*f6dc9357SAndroid Build Coastguard Worker   }
454*f6dc9357SAndroid Build Coastguard Worker   return true;
455*f6dc9357SAndroid Build Coastguard Worker }
456*f6dc9357SAndroid Build Coastguard Worker 
FindNext(CStreamInfo & si)457*f6dc9357SAndroid Build Coastguard Worker bool CFindStream::FindNext(CStreamInfo &si)
458*f6dc9357SAndroid Build Coastguard Worker {
459*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_USE_DYN_FindFirstStream
460*f6dc9357SAndroid Build Coastguard Worker   if (!g_FindNextStreamW)
461*f6dc9357SAndroid Build Coastguard Worker   {
462*f6dc9357SAndroid Build Coastguard Worker     ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
463*f6dc9357SAndroid Build Coastguard Worker     return false;
464*f6dc9357SAndroid Build Coastguard Worker   }
465*f6dc9357SAndroid Build Coastguard Worker #endif
466*f6dc9357SAndroid Build Coastguard Worker   {
467*f6dc9357SAndroid Build Coastguard Worker     MY_WIN32_FIND_STREAM_DATA sd;
468*f6dc9357SAndroid Build Coastguard Worker     if (!MY_FindNextStreamW(_handle, &sd))
469*f6dc9357SAndroid Build Coastguard Worker       return false;
470*f6dc9357SAndroid Build Coastguard Worker     Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);
471*f6dc9357SAndroid Build Coastguard Worker   }
472*f6dc9357SAndroid Build Coastguard Worker   return true;
473*f6dc9357SAndroid Build Coastguard Worker }
474*f6dc9357SAndroid Build Coastguard Worker 
Next(CStreamInfo & si,bool & found)475*f6dc9357SAndroid Build Coastguard Worker bool CStreamEnumerator::Next(CStreamInfo &si, bool &found)
476*f6dc9357SAndroid Build Coastguard Worker {
477*f6dc9357SAndroid Build Coastguard Worker   bool res;
478*f6dc9357SAndroid Build Coastguard Worker   if (_find.IsHandleAllocated())
479*f6dc9357SAndroid Build Coastguard Worker     res = _find.FindNext(si);
480*f6dc9357SAndroid Build Coastguard Worker   else
481*f6dc9357SAndroid Build Coastguard Worker     res = _find.FindFirst(_filePath, si);
482*f6dc9357SAndroid Build Coastguard Worker   if (res)
483*f6dc9357SAndroid Build Coastguard Worker   {
484*f6dc9357SAndroid Build Coastguard Worker     found = true;
485*f6dc9357SAndroid Build Coastguard Worker     return true;
486*f6dc9357SAndroid Build Coastguard Worker   }
487*f6dc9357SAndroid Build Coastguard Worker   found = false;
488*f6dc9357SAndroid Build Coastguard Worker   return (::GetLastError() == ERROR_HANDLE_EOF);
489*f6dc9357SAndroid Build Coastguard Worker }
490*f6dc9357SAndroid Build Coastguard Worker 
491*f6dc9357SAndroid Build Coastguard Worker #endif
492*f6dc9357SAndroid Build Coastguard Worker 
493*f6dc9357SAndroid Build Coastguard Worker 
494*f6dc9357SAndroid Build Coastguard Worker /*
495*f6dc9357SAndroid Build Coastguard Worker WinXP-64 GetFileAttributes():
496*f6dc9357SAndroid Build Coastguard Worker   If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code
497*f6dc9357SAndroid Build Coastguard Worker 
498*f6dc9357SAndroid Build Coastguard Worker   \    - OK
499*f6dc9357SAndroid Build Coastguard Worker   C:\  - OK, if there is such drive,
500*f6dc9357SAndroid Build Coastguard Worker   D:\  - ERROR_PATH_NOT_FOUND, if there is no such drive,
501*f6dc9357SAndroid Build Coastguard Worker 
502*f6dc9357SAndroid Build Coastguard Worker   C:\folder     - OK
503*f6dc9357SAndroid Build Coastguard Worker   C:\folder\    - OK
504*f6dc9357SAndroid Build Coastguard Worker   C:\folderBad  - ERROR_FILE_NOT_FOUND
505*f6dc9357SAndroid Build Coastguard Worker 
506*f6dc9357SAndroid Build Coastguard Worker   \\Server\BadShare  - ERROR_BAD_NETPATH
507*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share     - WORKS OK, but MSDN says:
508*f6dc9357SAndroid Build Coastguard Worker                           GetFileAttributes for a network share, the function fails, and GetLastError
509*f6dc9357SAndroid Build Coastguard Worker                           returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.
510*f6dc9357SAndroid Build Coastguard Worker */
511*f6dc9357SAndroid Build Coastguard Worker 
GetFileAttrib(CFSTR path)512*f6dc9357SAndroid Build Coastguard Worker DWORD GetFileAttrib(CFSTR path)
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
515*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
516*f6dc9357SAndroid Build Coastguard Worker     return ::GetFileAttributes(fs2fas(path));
517*f6dc9357SAndroid Build Coastguard Worker   else
518*f6dc9357SAndroid Build Coastguard Worker   #endif
519*f6dc9357SAndroid Build Coastguard Worker   {
520*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
521*f6dc9357SAndroid Build Coastguard Worker     {
522*f6dc9357SAndroid Build Coastguard Worker       DWORD dw = ::GetFileAttributesW(fs2us(path));
523*f6dc9357SAndroid Build Coastguard Worker       if (dw != INVALID_FILE_ATTRIBUTES)
524*f6dc9357SAndroid Build Coastguard Worker         return dw;
525*f6dc9357SAndroid Build Coastguard Worker     }
526*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
527*f6dc9357SAndroid Build Coastguard Worker     if (USE_SUPER_PATH)
528*f6dc9357SAndroid Build Coastguard Worker     {
529*f6dc9357SAndroid Build Coastguard Worker       UString superPath;
530*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPath(path, superPath, USE_MAIN_PATH))
531*f6dc9357SAndroid Build Coastguard Worker         return ::GetFileAttributesW(superPath);
532*f6dc9357SAndroid Build Coastguard Worker     }
533*f6dc9357SAndroid Build Coastguard Worker     #endif
534*f6dc9357SAndroid Build Coastguard Worker     return INVALID_FILE_ATTRIBUTES;
535*f6dc9357SAndroid Build Coastguard Worker   }
536*f6dc9357SAndroid Build Coastguard Worker }
537*f6dc9357SAndroid Build Coastguard Worker 
538*f6dc9357SAndroid Build Coastguard Worker /* if path is "c:" or "c::" then CFileInfo::Find() returns name of current folder for that disk
539*f6dc9357SAndroid Build Coastguard Worker    so instead of absolute path we have relative path in Name. That is not good in some calls */
540*f6dc9357SAndroid Build Coastguard Worker 
541*f6dc9357SAndroid Build Coastguard Worker /* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */
542*f6dc9357SAndroid Build Coastguard Worker 
543*f6dc9357SAndroid Build Coastguard Worker /* CFileInfo::Find()
544*f6dc9357SAndroid Build Coastguard Worker We alow the following paths (as FindFirstFile):
545*f6dc9357SAndroid Build Coastguard Worker   C:\folder
546*f6dc9357SAndroid Build Coastguard Worker   c:                      - if current dir is NOT ROOT ( c:\folder )
547*f6dc9357SAndroid Build Coastguard Worker 
548*f6dc9357SAndroid Build Coastguard Worker also we support paths that are not supported by FindFirstFile:
549*f6dc9357SAndroid Build Coastguard Worker   \
550*f6dc9357SAndroid Build Coastguard Worker   \\.\c:
551*f6dc9357SAndroid Build Coastguard Worker   c:\                     - Name will be without tail slash ( c: )
552*f6dc9357SAndroid Build Coastguard Worker   \\?\c:\                 - Name will be without tail slash ( c: )
553*f6dc9357SAndroid Build Coastguard Worker   \\Server\Share
554*f6dc9357SAndroid Build Coastguard Worker   \\?\UNC\Server\Share
555*f6dc9357SAndroid Build Coastguard Worker 
556*f6dc9357SAndroid Build Coastguard Worker   c:\folder:stream  - Name = folder:stream
557*f6dc9357SAndroid Build Coastguard Worker   c:\:stream        - Name = :stream
558*f6dc9357SAndroid Build Coastguard Worker   c::stream         - Name = c::stream
559*f6dc9357SAndroid Build Coastguard Worker */
560*f6dc9357SAndroid Build Coastguard Worker 
Find(CFSTR path,bool followLink)561*f6dc9357SAndroid Build Coastguard Worker bool CFileInfo::Find(CFSTR path, bool followLink)
562*f6dc9357SAndroid Build Coastguard Worker {
563*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_DEVICE_FILE
564*f6dc9357SAndroid Build Coastguard Worker 
565*f6dc9357SAndroid Build Coastguard Worker   if (IS_PATH_SEPAR(path[0]) &&
566*f6dc9357SAndroid Build Coastguard Worker       IS_PATH_SEPAR(path[1]) &&
567*f6dc9357SAndroid Build Coastguard Worker       path[2] == '.' &&
568*f6dc9357SAndroid Build Coastguard Worker       path[3] == 0)
569*f6dc9357SAndroid Build Coastguard Worker   {
570*f6dc9357SAndroid Build Coastguard Worker     // 22.00 : it's virtual directory for devices
571*f6dc9357SAndroid Build Coastguard Worker     // IsDevice = true;
572*f6dc9357SAndroid Build Coastguard Worker     ClearBase();
573*f6dc9357SAndroid Build Coastguard Worker     Name = path + 2;
574*f6dc9357SAndroid Build Coastguard Worker     Attrib = FILE_ATTRIBUTE_DIRECTORY;
575*f6dc9357SAndroid Build Coastguard Worker     return true;
576*f6dc9357SAndroid Build Coastguard Worker   }
577*f6dc9357SAndroid Build Coastguard Worker 
578*f6dc9357SAndroid Build Coastguard Worker   if (IsDevicePath(path))
579*f6dc9357SAndroid Build Coastguard Worker   {
580*f6dc9357SAndroid Build Coastguard Worker     ClearBase();
581*f6dc9357SAndroid Build Coastguard Worker     Name = path + 4;
582*f6dc9357SAndroid Build Coastguard Worker     IsDevice = true;
583*f6dc9357SAndroid Build Coastguard Worker 
584*f6dc9357SAndroid Build Coastguard Worker     if (NName::IsDrivePath2(path + 4) && path[6] == 0)
585*f6dc9357SAndroid Build Coastguard Worker     {
586*f6dc9357SAndroid Build Coastguard Worker       FChar drive[4] = { path[4], ':', '\\', 0 };
587*f6dc9357SAndroid Build Coastguard Worker       UInt64 clusterSize, totalSize, freeSize;
588*f6dc9357SAndroid Build Coastguard Worker       if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize))
589*f6dc9357SAndroid Build Coastguard Worker       {
590*f6dc9357SAndroid Build Coastguard Worker         Size = totalSize;
591*f6dc9357SAndroid Build Coastguard Worker         return true;
592*f6dc9357SAndroid Build Coastguard Worker       }
593*f6dc9357SAndroid Build Coastguard Worker     }
594*f6dc9357SAndroid Build Coastguard Worker 
595*f6dc9357SAndroid Build Coastguard Worker     NIO::CInFile inFile;
596*f6dc9357SAndroid Build Coastguard Worker     // ::OutputDebugStringW(path);
597*f6dc9357SAndroid Build Coastguard Worker     if (!inFile.Open(path))
598*f6dc9357SAndroid Build Coastguard Worker       return false;
599*f6dc9357SAndroid Build Coastguard Worker     // ::OutputDebugStringW(L"---");
600*f6dc9357SAndroid Build Coastguard Worker     if (inFile.SizeDefined)
601*f6dc9357SAndroid Build Coastguard Worker       Size = inFile.Size;
602*f6dc9357SAndroid Build Coastguard Worker     return true;
603*f6dc9357SAndroid Build Coastguard Worker   }
604*f6dc9357SAndroid Build Coastguard Worker   #endif
605*f6dc9357SAndroid Build Coastguard Worker 
606*f6dc9357SAndroid Build Coastguard Worker   #if defined(_WIN32) && !defined(UNDER_CE)
607*f6dc9357SAndroid Build Coastguard Worker 
608*f6dc9357SAndroid Build Coastguard Worker   const int colonPos = FindAltStreamColon(path);
609*f6dc9357SAndroid Build Coastguard Worker   if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0)
610*f6dc9357SAndroid Build Coastguard Worker   {
611*f6dc9357SAndroid Build Coastguard Worker     UString streamName = fs2us(path + (unsigned)colonPos);
612*f6dc9357SAndroid Build Coastguard Worker     FString filePath (path);
613*f6dc9357SAndroid Build Coastguard Worker     filePath.DeleteFrom((unsigned)colonPos);
614*f6dc9357SAndroid Build Coastguard Worker     /* we allow both cases:
615*f6dc9357SAndroid Build Coastguard Worker       name:stream
616*f6dc9357SAndroid Build Coastguard Worker       name:stream:$DATA
617*f6dc9357SAndroid Build Coastguard Worker     */
618*f6dc9357SAndroid Build Coastguard Worker     const unsigned kPostfixSize = 6;
619*f6dc9357SAndroid Build Coastguard Worker     if (streamName.Len() <= kPostfixSize
620*f6dc9357SAndroid Build Coastguard Worker         || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), ":$DATA"))
621*f6dc9357SAndroid Build Coastguard Worker       streamName += ":$DATA";
622*f6dc9357SAndroid Build Coastguard Worker 
623*f6dc9357SAndroid Build Coastguard Worker     bool isOk = true;
624*f6dc9357SAndroid Build Coastguard Worker 
625*f6dc9357SAndroid Build Coastguard Worker     if (IsDrivePath2(filePath) &&
626*f6dc9357SAndroid Build Coastguard Worker         (colonPos == 2 || (colonPos == 3 && filePath[2] == '\\')))
627*f6dc9357SAndroid Build Coastguard Worker     {
628*f6dc9357SAndroid Build Coastguard Worker       // FindFirstFile doesn't work for "c:\" and for "c:" (if current dir is ROOT)
629*f6dc9357SAndroid Build Coastguard Worker       ClearBase();
630*f6dc9357SAndroid Build Coastguard Worker       Name.Empty();
631*f6dc9357SAndroid Build Coastguard Worker       if (colonPos == 2)
632*f6dc9357SAndroid Build Coastguard Worker         Name = filePath;
633*f6dc9357SAndroid Build Coastguard Worker     }
634*f6dc9357SAndroid Build Coastguard Worker     else
635*f6dc9357SAndroid Build Coastguard Worker       isOk = Find(filePath, followLink); // check it (followLink)
636*f6dc9357SAndroid Build Coastguard Worker 
637*f6dc9357SAndroid Build Coastguard Worker     if (isOk)
638*f6dc9357SAndroid Build Coastguard Worker     {
639*f6dc9357SAndroid Build Coastguard Worker       Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
640*f6dc9357SAndroid Build Coastguard Worker       Size = 0;
641*f6dc9357SAndroid Build Coastguard Worker       CStreamEnumerator enumerator(filePath);
642*f6dc9357SAndroid Build Coastguard Worker       for (;;)
643*f6dc9357SAndroid Build Coastguard Worker       {
644*f6dc9357SAndroid Build Coastguard Worker         CStreamInfo si;
645*f6dc9357SAndroid Build Coastguard Worker         bool found;
646*f6dc9357SAndroid Build Coastguard Worker         if (!enumerator.Next(si, found))
647*f6dc9357SAndroid Build Coastguard Worker           return false;
648*f6dc9357SAndroid Build Coastguard Worker         if (!found)
649*f6dc9357SAndroid Build Coastguard Worker         {
650*f6dc9357SAndroid Build Coastguard Worker           ::SetLastError(ERROR_FILE_NOT_FOUND);
651*f6dc9357SAndroid Build Coastguard Worker           return false;
652*f6dc9357SAndroid Build Coastguard Worker         }
653*f6dc9357SAndroid Build Coastguard Worker         if (si.Name.IsEqualTo_NoCase(streamName))
654*f6dc9357SAndroid Build Coastguard Worker         {
655*f6dc9357SAndroid Build Coastguard Worker           // we delete postfix, if alt stream name is not "::$DATA"
656*f6dc9357SAndroid Build Coastguard Worker           if (si.Name.Len() > kPostfixSize + 1)
657*f6dc9357SAndroid Build Coastguard Worker             si.Name.DeleteFrom(si.Name.Len() - kPostfixSize);
658*f6dc9357SAndroid Build Coastguard Worker           Name += us2fs(si.Name);
659*f6dc9357SAndroid Build Coastguard Worker           Size = si.Size;
660*f6dc9357SAndroid Build Coastguard Worker           IsAltStream = true;
661*f6dc9357SAndroid Build Coastguard Worker           return true;
662*f6dc9357SAndroid Build Coastguard Worker         }
663*f6dc9357SAndroid Build Coastguard Worker       }
664*f6dc9357SAndroid Build Coastguard Worker     }
665*f6dc9357SAndroid Build Coastguard Worker   }
666*f6dc9357SAndroid Build Coastguard Worker 
667*f6dc9357SAndroid Build Coastguard Worker   #endif
668*f6dc9357SAndroid Build Coastguard Worker 
669*f6dc9357SAndroid Build Coastguard Worker   CFindFile finder;
670*f6dc9357SAndroid Build Coastguard Worker 
671*f6dc9357SAndroid Build Coastguard Worker   #if defined(_WIN32) && !defined(UNDER_CE)
672*f6dc9357SAndroid Build Coastguard Worker   {
673*f6dc9357SAndroid Build Coastguard Worker     /*
674*f6dc9357SAndroid Build Coastguard Worker     DWORD lastError = GetLastError();
675*f6dc9357SAndroid Build Coastguard Worker     if (lastError == ERROR_FILE_NOT_FOUND
676*f6dc9357SAndroid Build Coastguard Worker         || lastError == ERROR_BAD_NETPATH  // XP64: "\\Server\Share"
677*f6dc9357SAndroid Build Coastguard Worker         || lastError == ERROR_BAD_NET_NAME // Win7: "\\Server\Share"
678*f6dc9357SAndroid Build Coastguard Worker         || lastError == ERROR_INVALID_NAME // XP64: "\\?\UNC\Server\Share"
679*f6dc9357SAndroid Build Coastguard Worker         || lastError == ERROR_BAD_PATHNAME // Win7: "\\?\UNC\Server\Share"
680*f6dc9357SAndroid Build Coastguard Worker         )
681*f6dc9357SAndroid Build Coastguard Worker     */
682*f6dc9357SAndroid Build Coastguard Worker 
683*f6dc9357SAndroid Build Coastguard Worker     unsigned rootSize = 0;
684*f6dc9357SAndroid Build Coastguard Worker     if (IsSuperPath(path))
685*f6dc9357SAndroid Build Coastguard Worker       rootSize = kSuperPathPrefixSize;
686*f6dc9357SAndroid Build Coastguard Worker 
687*f6dc9357SAndroid Build Coastguard Worker     if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0)
688*f6dc9357SAndroid Build Coastguard Worker     {
689*f6dc9357SAndroid Build Coastguard Worker       DWORD attrib = GetFileAttrib(path);
690*f6dc9357SAndroid Build Coastguard Worker       if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
691*f6dc9357SAndroid Build Coastguard Worker       {
692*f6dc9357SAndroid Build Coastguard Worker         ClearBase();
693*f6dc9357SAndroid Build Coastguard Worker         Attrib = attrib;
694*f6dc9357SAndroid Build Coastguard Worker         Name = path + rootSize;
695*f6dc9357SAndroid Build Coastguard Worker         Name.DeleteFrom(2);
696*f6dc9357SAndroid Build Coastguard Worker         if (!Fill_From_ByHandleFileInfo(path))
697*f6dc9357SAndroid Build Coastguard Worker         {
698*f6dc9357SAndroid Build Coastguard Worker         }
699*f6dc9357SAndroid Build Coastguard Worker         return true;
700*f6dc9357SAndroid Build Coastguard Worker       }
701*f6dc9357SAndroid Build Coastguard Worker     }
702*f6dc9357SAndroid Build Coastguard Worker     else if (IS_PATH_SEPAR(path[0]))
703*f6dc9357SAndroid Build Coastguard Worker     {
704*f6dc9357SAndroid Build Coastguard Worker       if (path[1] == 0)
705*f6dc9357SAndroid Build Coastguard Worker       {
706*f6dc9357SAndroid Build Coastguard Worker         DWORD attrib = GetFileAttrib(path);
707*f6dc9357SAndroid Build Coastguard Worker         if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
708*f6dc9357SAndroid Build Coastguard Worker         {
709*f6dc9357SAndroid Build Coastguard Worker           ClearBase();
710*f6dc9357SAndroid Build Coastguard Worker           Name.Empty();
711*f6dc9357SAndroid Build Coastguard Worker           Attrib = attrib;
712*f6dc9357SAndroid Build Coastguard Worker           return true;
713*f6dc9357SAndroid Build Coastguard Worker         }
714*f6dc9357SAndroid Build Coastguard Worker       }
715*f6dc9357SAndroid Build Coastguard Worker       else
716*f6dc9357SAndroid Build Coastguard Worker       {
717*f6dc9357SAndroid Build Coastguard Worker         const unsigned prefixSize = GetNetworkServerPrefixSize(path);
718*f6dc9357SAndroid Build Coastguard Worker         if (prefixSize > 0 && path[prefixSize] != 0)
719*f6dc9357SAndroid Build Coastguard Worker         {
720*f6dc9357SAndroid Build Coastguard Worker           if (NName::FindSepar(path + prefixSize) < 0)
721*f6dc9357SAndroid Build Coastguard Worker           {
722*f6dc9357SAndroid Build Coastguard Worker             if (Fill_From_ByHandleFileInfo(path))
723*f6dc9357SAndroid Build Coastguard Worker             {
724*f6dc9357SAndroid Build Coastguard Worker               Name = path + prefixSize;
725*f6dc9357SAndroid Build Coastguard Worker               return true;
726*f6dc9357SAndroid Build Coastguard Worker             }
727*f6dc9357SAndroid Build Coastguard Worker 
728*f6dc9357SAndroid Build Coastguard Worker             FString s (path);
729*f6dc9357SAndroid Build Coastguard Worker             s.Add_PathSepar();
730*f6dc9357SAndroid Build Coastguard Worker             s.Add_Char('*'); // CHAR_ANY_MASK
731*f6dc9357SAndroid Build Coastguard Worker             bool isOK = false;
732*f6dc9357SAndroid Build Coastguard Worker             if (finder.FindFirst(s, *this))
733*f6dc9357SAndroid Build Coastguard Worker             {
734*f6dc9357SAndroid Build Coastguard Worker               if (Name == FTEXT("."))
735*f6dc9357SAndroid Build Coastguard Worker               {
736*f6dc9357SAndroid Build Coastguard Worker                 Name = path + prefixSize;
737*f6dc9357SAndroid Build Coastguard Worker                 return true;
738*f6dc9357SAndroid Build Coastguard Worker               }
739*f6dc9357SAndroid Build Coastguard Worker               isOK = true;
740*f6dc9357SAndroid Build Coastguard Worker               /* if "\\server\share" maps to root folder "d:\", there is no "." item.
741*f6dc9357SAndroid Build Coastguard Worker                  But it's possible that there are another items */
742*f6dc9357SAndroid Build Coastguard Worker             }
743*f6dc9357SAndroid Build Coastguard Worker             {
744*f6dc9357SAndroid Build Coastguard Worker               const DWORD attrib = GetFileAttrib(path);
745*f6dc9357SAndroid Build Coastguard Worker               if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0))
746*f6dc9357SAndroid Build Coastguard Worker               {
747*f6dc9357SAndroid Build Coastguard Worker                 ClearBase();
748*f6dc9357SAndroid Build Coastguard Worker                 if (attrib != INVALID_FILE_ATTRIBUTES)
749*f6dc9357SAndroid Build Coastguard Worker                   Attrib = attrib;
750*f6dc9357SAndroid Build Coastguard Worker                 else
751*f6dc9357SAndroid Build Coastguard Worker                   SetAsDir();
752*f6dc9357SAndroid Build Coastguard Worker                 Name = path + prefixSize;
753*f6dc9357SAndroid Build Coastguard Worker                 return true;
754*f6dc9357SAndroid Build Coastguard Worker               }
755*f6dc9357SAndroid Build Coastguard Worker             }
756*f6dc9357SAndroid Build Coastguard Worker             // ::SetLastError(lastError);
757*f6dc9357SAndroid Build Coastguard Worker           }
758*f6dc9357SAndroid Build Coastguard Worker         }
759*f6dc9357SAndroid Build Coastguard Worker       }
760*f6dc9357SAndroid Build Coastguard Worker     }
761*f6dc9357SAndroid Build Coastguard Worker   }
762*f6dc9357SAndroid Build Coastguard Worker   #endif
763*f6dc9357SAndroid Build Coastguard Worker 
764*f6dc9357SAndroid Build Coastguard Worker   bool res = finder.FindFirst(path, *this);
765*f6dc9357SAndroid Build Coastguard Worker   if (!followLink
766*f6dc9357SAndroid Build Coastguard Worker       || !res
767*f6dc9357SAndroid Build Coastguard Worker       || !HasReparsePoint())
768*f6dc9357SAndroid Build Coastguard Worker     return res;
769*f6dc9357SAndroid Build Coastguard Worker 
770*f6dc9357SAndroid Build Coastguard Worker   // return FollowReparse(path, IsDir());
771*f6dc9357SAndroid Build Coastguard Worker   return Fill_From_ByHandleFileInfo(path);
772*f6dc9357SAndroid Build Coastguard Worker }
773*f6dc9357SAndroid Build Coastguard Worker 
Fill_From_ByHandleFileInfo(CFSTR path)774*f6dc9357SAndroid Build Coastguard Worker bool CFileInfoBase::Fill_From_ByHandleFileInfo(CFSTR path)
775*f6dc9357SAndroid Build Coastguard Worker {
776*f6dc9357SAndroid Build Coastguard Worker   BY_HANDLE_FILE_INFORMATION info;
777*f6dc9357SAndroid Build Coastguard Worker   if (!NIO::CFileBase::GetFileInformation(path, &info))
778*f6dc9357SAndroid Build Coastguard Worker     return false;
779*f6dc9357SAndroid Build Coastguard Worker   {
780*f6dc9357SAndroid Build Coastguard Worker     Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
781*f6dc9357SAndroid Build Coastguard Worker     CTime = info.ftCreationTime;
782*f6dc9357SAndroid Build Coastguard Worker     ATime = info.ftLastAccessTime;
783*f6dc9357SAndroid Build Coastguard Worker     MTime = info.ftLastWriteTime;
784*f6dc9357SAndroid Build Coastguard Worker     Attrib = info.dwFileAttributes;
785*f6dc9357SAndroid Build Coastguard Worker     return true;
786*f6dc9357SAndroid Build Coastguard Worker   }
787*f6dc9357SAndroid Build Coastguard Worker }
788*f6dc9357SAndroid Build Coastguard Worker 
789*f6dc9357SAndroid Build Coastguard Worker /*
790*f6dc9357SAndroid Build Coastguard Worker bool CFileInfo::FollowReparse(CFSTR path, bool isDir)
791*f6dc9357SAndroid Build Coastguard Worker {
792*f6dc9357SAndroid Build Coastguard Worker   if (isDir)
793*f6dc9357SAndroid Build Coastguard Worker   {
794*f6dc9357SAndroid Build Coastguard Worker     FString prefix = path;
795*f6dc9357SAndroid Build Coastguard Worker     prefix.Add_PathSepar();
796*f6dc9357SAndroid Build Coastguard Worker 
797*f6dc9357SAndroid Build Coastguard Worker     // "folder/." refers to folder itself. So we can't use that path
798*f6dc9357SAndroid Build Coastguard Worker     // we must use enumerator and search "." item
799*f6dc9357SAndroid Build Coastguard Worker     CEnumerator enumerator;
800*f6dc9357SAndroid Build Coastguard Worker     enumerator.SetDirPrefix(prefix);
801*f6dc9357SAndroid Build Coastguard Worker     for (;;)
802*f6dc9357SAndroid Build Coastguard Worker     {
803*f6dc9357SAndroid Build Coastguard Worker       CFileInfo fi;
804*f6dc9357SAndroid Build Coastguard Worker       if (!enumerator.NextAny(fi))
805*f6dc9357SAndroid Build Coastguard Worker         break;
806*f6dc9357SAndroid Build Coastguard Worker       if (fi.Name.IsEqualTo_Ascii_NoCase("."))
807*f6dc9357SAndroid Build Coastguard Worker       {
808*f6dc9357SAndroid Build Coastguard Worker         // we can copy preperies;
809*f6dc9357SAndroid Build Coastguard Worker         CTime = fi.CTime;
810*f6dc9357SAndroid Build Coastguard Worker         ATime = fi.ATime;
811*f6dc9357SAndroid Build Coastguard Worker         MTime = fi.MTime;
812*f6dc9357SAndroid Build Coastguard Worker         Attrib = fi.Attrib;
813*f6dc9357SAndroid Build Coastguard Worker         Size = fi.Size;
814*f6dc9357SAndroid Build Coastguard Worker         return true;
815*f6dc9357SAndroid Build Coastguard Worker       }
816*f6dc9357SAndroid Build Coastguard Worker       break;
817*f6dc9357SAndroid Build Coastguard Worker     }
818*f6dc9357SAndroid Build Coastguard Worker     // LastError(lastError);
819*f6dc9357SAndroid Build Coastguard Worker     return false;
820*f6dc9357SAndroid Build Coastguard Worker   }
821*f6dc9357SAndroid Build Coastguard Worker 
822*f6dc9357SAndroid Build Coastguard Worker   {
823*f6dc9357SAndroid Build Coastguard Worker     NIO::CInFile inFile;
824*f6dc9357SAndroid Build Coastguard Worker     if (inFile.Open(path))
825*f6dc9357SAndroid Build Coastguard Worker     {
826*f6dc9357SAndroid Build Coastguard Worker       BY_HANDLE_FILE_INFORMATION info;
827*f6dc9357SAndroid Build Coastguard Worker       if (inFile.GetFileInformation(&info))
828*f6dc9357SAndroid Build Coastguard Worker       {
829*f6dc9357SAndroid Build Coastguard Worker         ClearBase();
830*f6dc9357SAndroid Build Coastguard Worker         Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
831*f6dc9357SAndroid Build Coastguard Worker         CTime = info.ftCreationTime;
832*f6dc9357SAndroid Build Coastguard Worker         ATime = info.ftLastAccessTime;
833*f6dc9357SAndroid Build Coastguard Worker         MTime = info.ftLastWriteTime;
834*f6dc9357SAndroid Build Coastguard Worker         Attrib = info.dwFileAttributes;
835*f6dc9357SAndroid Build Coastguard Worker         return true;
836*f6dc9357SAndroid Build Coastguard Worker       }
837*f6dc9357SAndroid Build Coastguard Worker     }
838*f6dc9357SAndroid Build Coastguard Worker     return false;
839*f6dc9357SAndroid Build Coastguard Worker   }
840*f6dc9357SAndroid Build Coastguard Worker }
841*f6dc9357SAndroid Build Coastguard Worker */
842*f6dc9357SAndroid Build Coastguard Worker 
DoesFileExist_Raw(CFSTR name)843*f6dc9357SAndroid Build Coastguard Worker bool DoesFileExist_Raw(CFSTR name)
844*f6dc9357SAndroid Build Coastguard Worker {
845*f6dc9357SAndroid Build Coastguard Worker   CFileInfo fi;
846*f6dc9357SAndroid Build Coastguard Worker   return fi.Find(name) && !fi.IsDir();
847*f6dc9357SAndroid Build Coastguard Worker }
848*f6dc9357SAndroid Build Coastguard Worker 
DoesFileExist_FollowLink(CFSTR name)849*f6dc9357SAndroid Build Coastguard Worker bool DoesFileExist_FollowLink(CFSTR name)
850*f6dc9357SAndroid Build Coastguard Worker {
851*f6dc9357SAndroid Build Coastguard Worker   CFileInfo fi;
852*f6dc9357SAndroid Build Coastguard Worker   return fi.Find_FollowLink(name) && !fi.IsDir();
853*f6dc9357SAndroid Build Coastguard Worker }
854*f6dc9357SAndroid Build Coastguard Worker 
DoesDirExist(CFSTR name,bool followLink)855*f6dc9357SAndroid Build Coastguard Worker bool DoesDirExist(CFSTR name, bool followLink)
856*f6dc9357SAndroid Build Coastguard Worker {
857*f6dc9357SAndroid Build Coastguard Worker   CFileInfo fi;
858*f6dc9357SAndroid Build Coastguard Worker   return fi.Find(name, followLink) && fi.IsDir();
859*f6dc9357SAndroid Build Coastguard Worker }
860*f6dc9357SAndroid Build Coastguard Worker 
DoesFileOrDirExist(CFSTR name)861*f6dc9357SAndroid Build Coastguard Worker bool DoesFileOrDirExist(CFSTR name)
862*f6dc9357SAndroid Build Coastguard Worker {
863*f6dc9357SAndroid Build Coastguard Worker   CFileInfo fi;
864*f6dc9357SAndroid Build Coastguard Worker   return fi.Find(name);
865*f6dc9357SAndroid Build Coastguard Worker }
866*f6dc9357SAndroid Build Coastguard Worker 
867*f6dc9357SAndroid Build Coastguard Worker 
SetDirPrefix(const FString & dirPrefix)868*f6dc9357SAndroid Build Coastguard Worker void CEnumerator::SetDirPrefix(const FString &dirPrefix)
869*f6dc9357SAndroid Build Coastguard Worker {
870*f6dc9357SAndroid Build Coastguard Worker   _wildcard = dirPrefix;
871*f6dc9357SAndroid Build Coastguard Worker   _wildcard.Add_Char('*');
872*f6dc9357SAndroid Build Coastguard Worker }
873*f6dc9357SAndroid Build Coastguard Worker 
NextAny(CFileInfo & fi)874*f6dc9357SAndroid Build Coastguard Worker bool CEnumerator::NextAny(CFileInfo &fi)
875*f6dc9357SAndroid Build Coastguard Worker {
876*f6dc9357SAndroid Build Coastguard Worker   if (_findFile.IsHandleAllocated())
877*f6dc9357SAndroid Build Coastguard Worker     return _findFile.FindNext(fi);
878*f6dc9357SAndroid Build Coastguard Worker   else
879*f6dc9357SAndroid Build Coastguard Worker     return _findFile.FindFirst(_wildcard, fi);
880*f6dc9357SAndroid Build Coastguard Worker }
881*f6dc9357SAndroid Build Coastguard Worker 
Next(CFileInfo & fi)882*f6dc9357SAndroid Build Coastguard Worker bool CEnumerator::Next(CFileInfo &fi)
883*f6dc9357SAndroid Build Coastguard Worker {
884*f6dc9357SAndroid Build Coastguard Worker   for (;;)
885*f6dc9357SAndroid Build Coastguard Worker   {
886*f6dc9357SAndroid Build Coastguard Worker     if (!NextAny(fi))
887*f6dc9357SAndroid Build Coastguard Worker       return false;
888*f6dc9357SAndroid Build Coastguard Worker     if (!fi.IsDots())
889*f6dc9357SAndroid Build Coastguard Worker       return true;
890*f6dc9357SAndroid Build Coastguard Worker   }
891*f6dc9357SAndroid Build Coastguard Worker }
892*f6dc9357SAndroid Build Coastguard Worker 
Next(CFileInfo & fi,bool & found)893*f6dc9357SAndroid Build Coastguard Worker bool CEnumerator::Next(CFileInfo &fi, bool &found)
894*f6dc9357SAndroid Build Coastguard Worker {
895*f6dc9357SAndroid Build Coastguard Worker   /*
896*f6dc9357SAndroid Build Coastguard Worker   for (;;)
897*f6dc9357SAndroid Build Coastguard Worker   {
898*f6dc9357SAndroid Build Coastguard Worker     if (!NextAny(fi))
899*f6dc9357SAndroid Build Coastguard Worker       break;
900*f6dc9357SAndroid Build Coastguard Worker     if (!fi.IsDots())
901*f6dc9357SAndroid Build Coastguard Worker     {
902*f6dc9357SAndroid Build Coastguard Worker       found = true;
903*f6dc9357SAndroid Build Coastguard Worker       return true;
904*f6dc9357SAndroid Build Coastguard Worker     }
905*f6dc9357SAndroid Build Coastguard Worker   }
906*f6dc9357SAndroid Build Coastguard Worker   */
907*f6dc9357SAndroid Build Coastguard Worker 
908*f6dc9357SAndroid Build Coastguard Worker   if (Next(fi))
909*f6dc9357SAndroid Build Coastguard Worker   {
910*f6dc9357SAndroid Build Coastguard Worker     found = true;
911*f6dc9357SAndroid Build Coastguard Worker     return true;
912*f6dc9357SAndroid Build Coastguard Worker   }
913*f6dc9357SAndroid Build Coastguard Worker 
914*f6dc9357SAndroid Build Coastguard Worker   found = false;
915*f6dc9357SAndroid Build Coastguard Worker   DWORD lastError = ::GetLastError();
916*f6dc9357SAndroid Build Coastguard Worker   if (_findFile.IsHandleAllocated())
917*f6dc9357SAndroid Build Coastguard Worker     return (lastError == ERROR_NO_MORE_FILES);
918*f6dc9357SAndroid Build Coastguard Worker   // we support the case for empty root folder: FindFirstFile("c:\\*") returns ERROR_FILE_NOT_FOUND
919*f6dc9357SAndroid Build Coastguard Worker   if (lastError == ERROR_FILE_NOT_FOUND)
920*f6dc9357SAndroid Build Coastguard Worker     return true;
921*f6dc9357SAndroid Build Coastguard Worker   if (lastError == ERROR_ACCESS_DENIED)
922*f6dc9357SAndroid Build Coastguard Worker   {
923*f6dc9357SAndroid Build Coastguard Worker     // here we show inaccessible root system folder as empty folder to eliminate redundant user warnings
924*f6dc9357SAndroid Build Coastguard Worker     const char *s = "System Volume Information" STRING_PATH_SEPARATOR "*";
925*f6dc9357SAndroid Build Coastguard Worker     const int len = (int)strlen(s);
926*f6dc9357SAndroid Build Coastguard Worker     const int delta = (int)_wildcard.Len() - len;
927*f6dc9357SAndroid Build Coastguard Worker     if (delta == 0 || (delta > 0 && IS_PATH_SEPAR(_wildcard[(unsigned)delta - 1])))
928*f6dc9357SAndroid Build Coastguard Worker       if (StringsAreEqual_Ascii(_wildcard.Ptr((unsigned)delta), s))
929*f6dc9357SAndroid Build Coastguard Worker         return true;
930*f6dc9357SAndroid Build Coastguard Worker   }
931*f6dc9357SAndroid Build Coastguard Worker   return false;
932*f6dc9357SAndroid Build Coastguard Worker }
933*f6dc9357SAndroid Build Coastguard Worker 
934*f6dc9357SAndroid Build Coastguard Worker 
935*f6dc9357SAndroid Build Coastguard Worker ////////////////////////////////
936*f6dc9357SAndroid Build Coastguard Worker // CFindChangeNotification
937*f6dc9357SAndroid Build Coastguard Worker // FindFirstChangeNotification can return 0. MSDN doesn't tell about it.
938*f6dc9357SAndroid Build Coastguard Worker 
Close()939*f6dc9357SAndroid Build Coastguard Worker bool CFindChangeNotification::Close() throw()
940*f6dc9357SAndroid Build Coastguard Worker {
941*f6dc9357SAndroid Build Coastguard Worker   if (!IsHandleAllocated())
942*f6dc9357SAndroid Build Coastguard Worker     return true;
943*f6dc9357SAndroid Build Coastguard Worker   if (!::FindCloseChangeNotification(_handle))
944*f6dc9357SAndroid Build Coastguard Worker     return false;
945*f6dc9357SAndroid Build Coastguard Worker   _handle = INVALID_HANDLE_VALUE;
946*f6dc9357SAndroid Build Coastguard Worker   return true;
947*f6dc9357SAndroid Build Coastguard Worker }
948*f6dc9357SAndroid Build Coastguard Worker 
FindFirst(CFSTR path,bool watchSubtree,DWORD notifyFilter)949*f6dc9357SAndroid Build Coastguard Worker HANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter)
950*f6dc9357SAndroid Build Coastguard Worker {
951*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
952*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
953*f6dc9357SAndroid Build Coastguard Worker     _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter);
954*f6dc9357SAndroid Build Coastguard Worker   else
955*f6dc9357SAndroid Build Coastguard Worker   #endif
956*f6dc9357SAndroid Build Coastguard Worker   {
957*f6dc9357SAndroid Build Coastguard Worker     IF_USE_MAIN_PATH
958*f6dc9357SAndroid Build Coastguard Worker     _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter);
959*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_LONG_PATH
960*f6dc9357SAndroid Build Coastguard Worker     if (!IsHandleAllocated())
961*f6dc9357SAndroid Build Coastguard Worker     {
962*f6dc9357SAndroid Build Coastguard Worker       UString superPath;
963*f6dc9357SAndroid Build Coastguard Worker       if (GetSuperPath(path, superPath, USE_MAIN_PATH))
964*f6dc9357SAndroid Build Coastguard Worker         _handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter);
965*f6dc9357SAndroid Build Coastguard Worker     }
966*f6dc9357SAndroid Build Coastguard Worker     #endif
967*f6dc9357SAndroid Build Coastguard Worker   }
968*f6dc9357SAndroid Build Coastguard Worker   return _handle;
969*f6dc9357SAndroid Build Coastguard Worker }
970*f6dc9357SAndroid Build Coastguard Worker 
971*f6dc9357SAndroid Build Coastguard Worker #ifndef UNDER_CE
972*f6dc9357SAndroid Build Coastguard Worker 
MyGetLogicalDriveStrings(CObjectVector<FString> & driveStrings)973*f6dc9357SAndroid Build Coastguard Worker bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)
974*f6dc9357SAndroid Build Coastguard Worker {
975*f6dc9357SAndroid Build Coastguard Worker   driveStrings.Clear();
976*f6dc9357SAndroid Build Coastguard Worker   #ifndef _UNICODE
977*f6dc9357SAndroid Build Coastguard Worker   if (!g_IsNT)
978*f6dc9357SAndroid Build Coastguard Worker   {
979*f6dc9357SAndroid Build Coastguard Worker     driveStrings.Clear();
980*f6dc9357SAndroid Build Coastguard Worker     UINT32 size = GetLogicalDriveStrings(0, NULL);
981*f6dc9357SAndroid Build Coastguard Worker     if (size == 0)
982*f6dc9357SAndroid Build Coastguard Worker       return false;
983*f6dc9357SAndroid Build Coastguard Worker     CObjArray<char> buf(size);
984*f6dc9357SAndroid Build Coastguard Worker     UINT32 newSize = GetLogicalDriveStrings(size, buf);
985*f6dc9357SAndroid Build Coastguard Worker     if (newSize == 0 || newSize > size)
986*f6dc9357SAndroid Build Coastguard Worker       return false;
987*f6dc9357SAndroid Build Coastguard Worker     AString s;
988*f6dc9357SAndroid Build Coastguard Worker     UINT32 prev = 0;
989*f6dc9357SAndroid Build Coastguard Worker     for (UINT32 i = 0; i < newSize; i++)
990*f6dc9357SAndroid Build Coastguard Worker     {
991*f6dc9357SAndroid Build Coastguard Worker       if (buf[i] == 0)
992*f6dc9357SAndroid Build Coastguard Worker       {
993*f6dc9357SAndroid Build Coastguard Worker         s = buf + prev;
994*f6dc9357SAndroid Build Coastguard Worker         prev = i + 1;
995*f6dc9357SAndroid Build Coastguard Worker         driveStrings.Add(fas2fs(s));
996*f6dc9357SAndroid Build Coastguard Worker       }
997*f6dc9357SAndroid Build Coastguard Worker     }
998*f6dc9357SAndroid Build Coastguard Worker     return prev == newSize;
999*f6dc9357SAndroid Build Coastguard Worker   }
1000*f6dc9357SAndroid Build Coastguard Worker   else
1001*f6dc9357SAndroid Build Coastguard Worker   #endif
1002*f6dc9357SAndroid Build Coastguard Worker   {
1003*f6dc9357SAndroid Build Coastguard Worker     UINT32 size = GetLogicalDriveStringsW(0, NULL);
1004*f6dc9357SAndroid Build Coastguard Worker     if (size == 0)
1005*f6dc9357SAndroid Build Coastguard Worker       return false;
1006*f6dc9357SAndroid Build Coastguard Worker     CObjArray<wchar_t> buf(size);
1007*f6dc9357SAndroid Build Coastguard Worker     UINT32 newSize = GetLogicalDriveStringsW(size, buf);
1008*f6dc9357SAndroid Build Coastguard Worker     if (newSize == 0 || newSize > size)
1009*f6dc9357SAndroid Build Coastguard Worker       return false;
1010*f6dc9357SAndroid Build Coastguard Worker     UString s;
1011*f6dc9357SAndroid Build Coastguard Worker     UINT32 prev = 0;
1012*f6dc9357SAndroid Build Coastguard Worker     for (UINT32 i = 0; i < newSize; i++)
1013*f6dc9357SAndroid Build Coastguard Worker     {
1014*f6dc9357SAndroid Build Coastguard Worker       if (buf[i] == 0)
1015*f6dc9357SAndroid Build Coastguard Worker       {
1016*f6dc9357SAndroid Build Coastguard Worker         s = buf + prev;
1017*f6dc9357SAndroid Build Coastguard Worker         prev = i + 1;
1018*f6dc9357SAndroid Build Coastguard Worker         driveStrings.Add(us2fs(s));
1019*f6dc9357SAndroid Build Coastguard Worker       }
1020*f6dc9357SAndroid Build Coastguard Worker     }
1021*f6dc9357SAndroid Build Coastguard Worker     return prev == newSize;
1022*f6dc9357SAndroid Build Coastguard Worker   }
1023*f6dc9357SAndroid Build Coastguard Worker }
1024*f6dc9357SAndroid Build Coastguard Worker 
1025*f6dc9357SAndroid Build Coastguard Worker #endif // UNDER_CE
1026*f6dc9357SAndroid Build Coastguard Worker 
1027*f6dc9357SAndroid Build Coastguard Worker 
1028*f6dc9357SAndroid Build Coastguard Worker 
1029*f6dc9357SAndroid Build Coastguard Worker #else // _WIN32
1030*f6dc9357SAndroid Build Coastguard Worker 
1031*f6dc9357SAndroid Build Coastguard Worker // ---------- POSIX ----------
1032*f6dc9357SAndroid Build Coastguard Worker 
MY_lstat(CFSTR path,struct stat * st,bool followLink)1033*f6dc9357SAndroid Build Coastguard Worker static int MY_lstat(CFSTR path, struct stat *st, bool followLink)
1034*f6dc9357SAndroid Build Coastguard Worker {
1035*f6dc9357SAndroid Build Coastguard Worker   memset(st, 0, sizeof(*st));
1036*f6dc9357SAndroid Build Coastguard Worker   int res;
1037*f6dc9357SAndroid Build Coastguard Worker   // #ifdef ENV_HAVE_LSTAT
1038*f6dc9357SAndroid Build Coastguard Worker   if (/* global_use_lstat && */ !followLink)
1039*f6dc9357SAndroid Build Coastguard Worker   {
1040*f6dc9357SAndroid Build Coastguard Worker     // printf("\nlstat\n");
1041*f6dc9357SAndroid Build Coastguard Worker     res = lstat(path, st);
1042*f6dc9357SAndroid Build Coastguard Worker   }
1043*f6dc9357SAndroid Build Coastguard Worker   else
1044*f6dc9357SAndroid Build Coastguard Worker   // #endif
1045*f6dc9357SAndroid Build Coastguard Worker   {
1046*f6dc9357SAndroid Build Coastguard Worker     // printf("\nstat\n");
1047*f6dc9357SAndroid Build Coastguard Worker     res = stat(path, st);
1048*f6dc9357SAndroid Build Coastguard Worker   }
1049*f6dc9357SAndroid Build Coastguard Worker #if 0
1050*f6dc9357SAndroid Build Coastguard Worker #if defined(__clang__) && __clang_major__ >= 14
1051*f6dc9357SAndroid Build Coastguard Worker   #pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
1052*f6dc9357SAndroid Build Coastguard Worker #endif
1053*f6dc9357SAndroid Build Coastguard Worker 
1054*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_dev = %lld", (long long)(st->st_dev));
1055*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_ino = %lld", (long long)(st->st_ino));
1056*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_mode = %llx", (long long)(st->st_mode));
1057*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_nlink = %lld", (long long)(st->st_nlink));
1058*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_uid = %lld", (long long)(st->st_uid));
1059*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_gid = %lld", (long long)(st->st_gid));
1060*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_size = %lld", (long long)(st->st_size));
1061*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_blksize = %lld", (long long)(st->st_blksize));
1062*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_blocks = %lld", (long long)(st->st_blocks));
1063*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_ctim = %lld", (long long)(ST_CTIME((*st)).tv_sec));
1064*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_mtim = %lld", (long long)(ST_MTIME((*st)).tv_sec));
1065*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_atim = %lld", (long long)(ST_ATIME((*st)).tv_sec));
1066*f6dc9357SAndroid Build Coastguard Worker      printf(S_ISFIFO(st->st_mode) ? "\n FIFO" : "\n NO FIFO");
1067*f6dc9357SAndroid Build Coastguard Worker   printf("\n");
1068*f6dc9357SAndroid Build Coastguard Worker #endif
1069*f6dc9357SAndroid Build Coastguard Worker 
1070*f6dc9357SAndroid Build Coastguard Worker   return res;
1071*f6dc9357SAndroid Build Coastguard Worker }
1072*f6dc9357SAndroid Build Coastguard Worker 
1073*f6dc9357SAndroid Build Coastguard Worker 
Get_Name_from_Path(CFSTR path)1074*f6dc9357SAndroid Build Coastguard Worker static const char *Get_Name_from_Path(CFSTR path) throw()
1075*f6dc9357SAndroid Build Coastguard Worker {
1076*f6dc9357SAndroid Build Coastguard Worker   size_t len = strlen(path);
1077*f6dc9357SAndroid Build Coastguard Worker   if (len == 0)
1078*f6dc9357SAndroid Build Coastguard Worker     return path;
1079*f6dc9357SAndroid Build Coastguard Worker   const char *p = path + len - 1;
1080*f6dc9357SAndroid Build Coastguard Worker   {
1081*f6dc9357SAndroid Build Coastguard Worker     if (p == path)
1082*f6dc9357SAndroid Build Coastguard Worker       return path;
1083*f6dc9357SAndroid Build Coastguard Worker     p--;
1084*f6dc9357SAndroid Build Coastguard Worker   }
1085*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1086*f6dc9357SAndroid Build Coastguard Worker   {
1087*f6dc9357SAndroid Build Coastguard Worker     char c = *p;
1088*f6dc9357SAndroid Build Coastguard Worker     if (IS_PATH_SEPAR(c))
1089*f6dc9357SAndroid Build Coastguard Worker       return p + 1;
1090*f6dc9357SAndroid Build Coastguard Worker     if (p == path)
1091*f6dc9357SAndroid Build Coastguard Worker       return path;
1092*f6dc9357SAndroid Build Coastguard Worker     p--;
1093*f6dc9357SAndroid Build Coastguard Worker   }
1094*f6dc9357SAndroid Build Coastguard Worker }
1095*f6dc9357SAndroid Build Coastguard Worker 
1096*f6dc9357SAndroid Build Coastguard Worker 
Get_WinAttribPosix_From_PosixMode(UInt32 mode)1097*f6dc9357SAndroid Build Coastguard Worker UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode)
1098*f6dc9357SAndroid Build Coastguard Worker {
1099*f6dc9357SAndroid Build Coastguard Worker   UInt32 attrib = S_ISDIR(mode) ?
1100*f6dc9357SAndroid Build Coastguard Worker       FILE_ATTRIBUTE_DIRECTORY :
1101*f6dc9357SAndroid Build Coastguard Worker       FILE_ATTRIBUTE_ARCHIVE;
1102*f6dc9357SAndroid Build Coastguard Worker   if ((mode & 0222) == 0) // S_IWUSR in p7zip
1103*f6dc9357SAndroid Build Coastguard Worker     attrib |= FILE_ATTRIBUTE_READONLY;
1104*f6dc9357SAndroid Build Coastguard Worker   return attrib | FILE_ATTRIBUTE_UNIX_EXTENSION | ((mode & 0xFFFF) << 16);
1105*f6dc9357SAndroid Build Coastguard Worker }
1106*f6dc9357SAndroid Build Coastguard Worker 
1107*f6dc9357SAndroid Build Coastguard Worker /*
1108*f6dc9357SAndroid Build Coastguard Worker UInt32 Get_WinAttrib_From_stat(const struct stat &st)
1109*f6dc9357SAndroid Build Coastguard Worker {
1110*f6dc9357SAndroid Build Coastguard Worker   UInt32 attrib = S_ISDIR(st.st_mode) ?
1111*f6dc9357SAndroid Build Coastguard Worker     FILE_ATTRIBUTE_DIRECTORY :
1112*f6dc9357SAndroid Build Coastguard Worker     FILE_ATTRIBUTE_ARCHIVE;
1113*f6dc9357SAndroid Build Coastguard Worker 
1114*f6dc9357SAndroid Build Coastguard Worker   if ((st.st_mode & 0222) == 0) // check it !!!
1115*f6dc9357SAndroid Build Coastguard Worker     attrib |= FILE_ATTRIBUTE_READONLY;
1116*f6dc9357SAndroid Build Coastguard Worker 
1117*f6dc9357SAndroid Build Coastguard Worker   attrib |= FILE_ATTRIBUTE_UNIX_EXTENSION + ((st.st_mode & 0xFFFF) << 16);
1118*f6dc9357SAndroid Build Coastguard Worker   return attrib;
1119*f6dc9357SAndroid Build Coastguard Worker }
1120*f6dc9357SAndroid Build Coastguard Worker */
1121*f6dc9357SAndroid Build Coastguard Worker 
SetFrom_stat(const struct stat & st)1122*f6dc9357SAndroid Build Coastguard Worker void CFileInfoBase::SetFrom_stat(const struct stat &st)
1123*f6dc9357SAndroid Build Coastguard Worker {
1124*f6dc9357SAndroid Build Coastguard Worker   // IsDevice = false;
1125*f6dc9357SAndroid Build Coastguard Worker 
1126*f6dc9357SAndroid Build Coastguard Worker   if (S_ISDIR(st.st_mode))
1127*f6dc9357SAndroid Build Coastguard Worker   {
1128*f6dc9357SAndroid Build Coastguard Worker     Size = 0;
1129*f6dc9357SAndroid Build Coastguard Worker   }
1130*f6dc9357SAndroid Build Coastguard Worker   else
1131*f6dc9357SAndroid Build Coastguard Worker   {
1132*f6dc9357SAndroid Build Coastguard Worker     Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename
1133*f6dc9357SAndroid Build Coastguard Worker   }
1134*f6dc9357SAndroid Build Coastguard Worker 
1135*f6dc9357SAndroid Build Coastguard Worker   // Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode);
1136*f6dc9357SAndroid Build Coastguard Worker 
1137*f6dc9357SAndroid Build Coastguard Worker   // NTime::UnixTimeToFileTime(st.st_ctime, CTime);
1138*f6dc9357SAndroid Build Coastguard Worker   // NTime::UnixTimeToFileTime(st.st_mtime, MTime);
1139*f6dc9357SAndroid Build Coastguard Worker   // NTime::UnixTimeToFileTime(st.st_atime, ATime);
1140*f6dc9357SAndroid Build Coastguard Worker   #ifdef __APPLE__
1141*f6dc9357SAndroid Build Coastguard Worker   // #ifdef _DARWIN_FEATURE_64_BIT_INODE
1142*f6dc9357SAndroid Build Coastguard Worker   /*
1143*f6dc9357SAndroid Build Coastguard Worker     here we can use birthtime instead of st_ctimespec.
1144*f6dc9357SAndroid Build Coastguard Worker     but we use st_ctimespec for compatibility with previous versions and p7zip.
1145*f6dc9357SAndroid Build Coastguard Worker     st_birthtimespec in OSX
1146*f6dc9357SAndroid Build Coastguard Worker     st_birthtim : at FreeBSD, NetBSD
1147*f6dc9357SAndroid Build Coastguard Worker   */
1148*f6dc9357SAndroid Build Coastguard Worker   // timespec_To_FILETIME(st.st_birthtimespec, CTime);
1149*f6dc9357SAndroid Build Coastguard Worker   // #else
1150*f6dc9357SAndroid Build Coastguard Worker   // timespec_To_FILETIME(st.st_ctimespec, CTime);
1151*f6dc9357SAndroid Build Coastguard Worker   // #endif
1152*f6dc9357SAndroid Build Coastguard Worker   // timespec_To_FILETIME(st.st_mtimespec, MTime);
1153*f6dc9357SAndroid Build Coastguard Worker   // timespec_To_FILETIME(st.st_atimespec, ATime);
1154*f6dc9357SAndroid Build Coastguard Worker   CTime = st.st_ctimespec;
1155*f6dc9357SAndroid Build Coastguard Worker   MTime = st.st_mtimespec;
1156*f6dc9357SAndroid Build Coastguard Worker   ATime = st.st_atimespec;
1157*f6dc9357SAndroid Build Coastguard Worker 
1158*f6dc9357SAndroid Build Coastguard Worker   #else
1159*f6dc9357SAndroid Build Coastguard Worker   // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100);
1160*f6dc9357SAndroid Build Coastguard Worker   // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100);
1161*f6dc9357SAndroid Build Coastguard Worker   // timespec_To_FILETIME(st.st_atim, ATime, &ATime_ns100);
1162*f6dc9357SAndroid Build Coastguard Worker   CTime = st.st_ctim;
1163*f6dc9357SAndroid Build Coastguard Worker   MTime = st.st_mtim;
1164*f6dc9357SAndroid Build Coastguard Worker   ATime = st.st_atim;
1165*f6dc9357SAndroid Build Coastguard Worker 
1166*f6dc9357SAndroid Build Coastguard Worker   #endif
1167*f6dc9357SAndroid Build Coastguard Worker 
1168*f6dc9357SAndroid Build Coastguard Worker   dev = st.st_dev;
1169*f6dc9357SAndroid Build Coastguard Worker   ino = st.st_ino;
1170*f6dc9357SAndroid Build Coastguard Worker   mode = st.st_mode;
1171*f6dc9357SAndroid Build Coastguard Worker   nlink = st.st_nlink;
1172*f6dc9357SAndroid Build Coastguard Worker   uid = st.st_uid;
1173*f6dc9357SAndroid Build Coastguard Worker   gid = st.st_gid;
1174*f6dc9357SAndroid Build Coastguard Worker   rdev = st.st_rdev;
1175*f6dc9357SAndroid Build Coastguard Worker 
1176*f6dc9357SAndroid Build Coastguard Worker   /*
1177*f6dc9357SAndroid Build Coastguard Worker   printf("\n sizeof timespec = %d", (int)sizeof(timespec));
1178*f6dc9357SAndroid Build Coastguard Worker   printf("\n sizeof st_rdev = %d", (int)sizeof(rdev));
1179*f6dc9357SAndroid Build Coastguard Worker   printf("\n sizeof st_ino = %d", (int)sizeof(ino));
1180*f6dc9357SAndroid Build Coastguard Worker   printf("\n sizeof mode_t = %d", (int)sizeof(mode_t));
1181*f6dc9357SAndroid Build Coastguard Worker   printf("\n sizeof nlink_t = %d", (int)sizeof(nlink_t));
1182*f6dc9357SAndroid Build Coastguard Worker   printf("\n sizeof uid_t = %d", (int)sizeof(uid_t));
1183*f6dc9357SAndroid Build Coastguard Worker   printf("\n");
1184*f6dc9357SAndroid Build Coastguard Worker   */
1185*f6dc9357SAndroid Build Coastguard Worker   /*
1186*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_rdev = %llx", (long long)rdev);
1187*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_dev  = %llx", (long long)dev);
1188*f6dc9357SAndroid Build Coastguard Worker   printf("\n dev  : major = %5x minor = %5x", (unsigned)major(dev), (unsigned)minor(dev));
1189*f6dc9357SAndroid Build Coastguard Worker   printf("\n st_ino = %lld", (long long)(ino));
1190*f6dc9357SAndroid Build Coastguard Worker   printf("\n rdev : major = %5x minor = %5x", (unsigned)major(rdev), (unsigned)minor(rdev));
1191*f6dc9357SAndroid Build Coastguard Worker   printf("\n size = %lld \n", (long long)(Size));
1192*f6dc9357SAndroid Build Coastguard Worker   printf("\n");
1193*f6dc9357SAndroid Build Coastguard Worker   */
1194*f6dc9357SAndroid Build Coastguard Worker }
1195*f6dc9357SAndroid Build Coastguard Worker 
1196*f6dc9357SAndroid Build Coastguard Worker /*
1197*f6dc9357SAndroid Build Coastguard Worker int Uid_To_Uname(uid_t uid, AString &name)
1198*f6dc9357SAndroid Build Coastguard Worker {
1199*f6dc9357SAndroid Build Coastguard Worker   name.Empty();
1200*f6dc9357SAndroid Build Coastguard Worker   struct passwd *passwd;
1201*f6dc9357SAndroid Build Coastguard Worker 
1202*f6dc9357SAndroid Build Coastguard Worker   if (uid != 0 && uid == cached_no_such_uid)
1203*f6dc9357SAndroid Build Coastguard Worker     {
1204*f6dc9357SAndroid Build Coastguard Worker       *uname = xstrdup ("");
1205*f6dc9357SAndroid Build Coastguard Worker       return;
1206*f6dc9357SAndroid Build Coastguard Worker     }
1207*f6dc9357SAndroid Build Coastguard Worker 
1208*f6dc9357SAndroid Build Coastguard Worker   if (!cached_uname || uid != cached_uid)
1209*f6dc9357SAndroid Build Coastguard Worker     {
1210*f6dc9357SAndroid Build Coastguard Worker       passwd = getpwuid (uid);
1211*f6dc9357SAndroid Build Coastguard Worker       if (passwd)
1212*f6dc9357SAndroid Build Coastguard Worker   {
1213*f6dc9357SAndroid Build Coastguard Worker     cached_uid = uid;
1214*f6dc9357SAndroid Build Coastguard Worker     assign_string (&cached_uname, passwd->pw_name);
1215*f6dc9357SAndroid Build Coastguard Worker   }
1216*f6dc9357SAndroid Build Coastguard Worker       else
1217*f6dc9357SAndroid Build Coastguard Worker   {
1218*f6dc9357SAndroid Build Coastguard Worker     cached_no_such_uid = uid;
1219*f6dc9357SAndroid Build Coastguard Worker     *uname = xstrdup ("");
1220*f6dc9357SAndroid Build Coastguard Worker     return;
1221*f6dc9357SAndroid Build Coastguard Worker   }
1222*f6dc9357SAndroid Build Coastguard Worker     }
1223*f6dc9357SAndroid Build Coastguard Worker   *uname = xstrdup (cached_uname);
1224*f6dc9357SAndroid Build Coastguard Worker }
1225*f6dc9357SAndroid Build Coastguard Worker */
1226*f6dc9357SAndroid Build Coastguard Worker 
Find_DontFill_Name(CFSTR path,bool followLink)1227*f6dc9357SAndroid Build Coastguard Worker bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink)
1228*f6dc9357SAndroid Build Coastguard Worker {
1229*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
1230*f6dc9357SAndroid Build Coastguard Worker   if (MY_lstat(path, &st, followLink) != 0)
1231*f6dc9357SAndroid Build Coastguard Worker     return false;
1232*f6dc9357SAndroid Build Coastguard Worker   // printf("\nFind_DontFill_Name : name=%s\n", path);
1233*f6dc9357SAndroid Build Coastguard Worker   SetFrom_stat(st);
1234*f6dc9357SAndroid Build Coastguard Worker   return true;
1235*f6dc9357SAndroid Build Coastguard Worker }
1236*f6dc9357SAndroid Build Coastguard Worker 
1237*f6dc9357SAndroid Build Coastguard Worker 
Find(CFSTR path,bool followLink)1238*f6dc9357SAndroid Build Coastguard Worker bool CFileInfo::Find(CFSTR path, bool followLink)
1239*f6dc9357SAndroid Build Coastguard Worker {
1240*f6dc9357SAndroid Build Coastguard Worker   // printf("\nCEnumerator::Find() name = %s\n", path);
1241*f6dc9357SAndroid Build Coastguard Worker   if (!Find_DontFill_Name(path, followLink))
1242*f6dc9357SAndroid Build Coastguard Worker     return false;
1243*f6dc9357SAndroid Build Coastguard Worker 
1244*f6dc9357SAndroid Build Coastguard Worker   // printf("\nOK\n");
1245*f6dc9357SAndroid Build Coastguard Worker 
1246*f6dc9357SAndroid Build Coastguard Worker   Name = Get_Name_from_Path(path);
1247*f6dc9357SAndroid Build Coastguard Worker   if (!Name.IsEmpty())
1248*f6dc9357SAndroid Build Coastguard Worker   {
1249*f6dc9357SAndroid Build Coastguard Worker     char c = Name.Back();
1250*f6dc9357SAndroid Build Coastguard Worker     if (IS_PATH_SEPAR(c))
1251*f6dc9357SAndroid Build Coastguard Worker       Name.DeleteBack();
1252*f6dc9357SAndroid Build Coastguard Worker   }
1253*f6dc9357SAndroid Build Coastguard Worker   return true;
1254*f6dc9357SAndroid Build Coastguard Worker }
1255*f6dc9357SAndroid Build Coastguard Worker 
1256*f6dc9357SAndroid Build Coastguard Worker 
DoesFileExist_Raw(CFSTR name)1257*f6dc9357SAndroid Build Coastguard Worker bool DoesFileExist_Raw(CFSTR name)
1258*f6dc9357SAndroid Build Coastguard Worker {
1259*f6dc9357SAndroid Build Coastguard Worker   // FIXME for symbolic links.
1260*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
1261*f6dc9357SAndroid Build Coastguard Worker   if (MY_lstat(name, &st, false) != 0)
1262*f6dc9357SAndroid Build Coastguard Worker     return false;
1263*f6dc9357SAndroid Build Coastguard Worker   return !S_ISDIR(st.st_mode);
1264*f6dc9357SAndroid Build Coastguard Worker }
1265*f6dc9357SAndroid Build Coastguard Worker 
DoesFileExist_FollowLink(CFSTR name)1266*f6dc9357SAndroid Build Coastguard Worker bool DoesFileExist_FollowLink(CFSTR name)
1267*f6dc9357SAndroid Build Coastguard Worker {
1268*f6dc9357SAndroid Build Coastguard Worker   // FIXME for symbolic links.
1269*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
1270*f6dc9357SAndroid Build Coastguard Worker   if (MY_lstat(name, &st, true) != 0)
1271*f6dc9357SAndroid Build Coastguard Worker     return false;
1272*f6dc9357SAndroid Build Coastguard Worker   return !S_ISDIR(st.st_mode);
1273*f6dc9357SAndroid Build Coastguard Worker }
1274*f6dc9357SAndroid Build Coastguard Worker 
DoesDirExist(CFSTR name,bool followLink)1275*f6dc9357SAndroid Build Coastguard Worker bool DoesDirExist(CFSTR name, bool followLink)
1276*f6dc9357SAndroid Build Coastguard Worker {
1277*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
1278*f6dc9357SAndroid Build Coastguard Worker   if (MY_lstat(name, &st, followLink) != 0)
1279*f6dc9357SAndroid Build Coastguard Worker     return false;
1280*f6dc9357SAndroid Build Coastguard Worker   return S_ISDIR(st.st_mode);
1281*f6dc9357SAndroid Build Coastguard Worker }
1282*f6dc9357SAndroid Build Coastguard Worker 
DoesFileOrDirExist(CFSTR name)1283*f6dc9357SAndroid Build Coastguard Worker bool DoesFileOrDirExist(CFSTR name)
1284*f6dc9357SAndroid Build Coastguard Worker {
1285*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
1286*f6dc9357SAndroid Build Coastguard Worker   if (MY_lstat(name, &st, false) != 0)
1287*f6dc9357SAndroid Build Coastguard Worker     return false;
1288*f6dc9357SAndroid Build Coastguard Worker   return true;
1289*f6dc9357SAndroid Build Coastguard Worker }
1290*f6dc9357SAndroid Build Coastguard Worker 
1291*f6dc9357SAndroid Build Coastguard Worker 
~CEnumerator()1292*f6dc9357SAndroid Build Coastguard Worker CEnumerator::~CEnumerator()
1293*f6dc9357SAndroid Build Coastguard Worker {
1294*f6dc9357SAndroid Build Coastguard Worker   if (_dir)
1295*f6dc9357SAndroid Build Coastguard Worker     closedir(_dir);
1296*f6dc9357SAndroid Build Coastguard Worker }
1297*f6dc9357SAndroid Build Coastguard Worker 
SetDirPrefix(const FString & dirPrefix)1298*f6dc9357SAndroid Build Coastguard Worker void CEnumerator::SetDirPrefix(const FString &dirPrefix)
1299*f6dc9357SAndroid Build Coastguard Worker {
1300*f6dc9357SAndroid Build Coastguard Worker   _wildcard = dirPrefix;
1301*f6dc9357SAndroid Build Coastguard Worker }
1302*f6dc9357SAndroid Build Coastguard Worker 
IsDots() const1303*f6dc9357SAndroid Build Coastguard Worker bool CDirEntry::IsDots() const throw()
1304*f6dc9357SAndroid Build Coastguard Worker {
1305*f6dc9357SAndroid Build Coastguard Worker   /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
1306*f6dc9357SAndroid Build Coastguard Worker      we can call fstatat() for that case, but we use only (Name) check here */
1307*f6dc9357SAndroid Build Coastguard Worker 
1308*f6dc9357SAndroid Build Coastguard Worker #if !defined(_AIX) && !defined(__sun)
1309*f6dc9357SAndroid Build Coastguard Worker   if (Type != DT_DIR && Type != DT_UNKNOWN)
1310*f6dc9357SAndroid Build Coastguard Worker     return false;
1311*f6dc9357SAndroid Build Coastguard Worker #endif
1312*f6dc9357SAndroid Build Coastguard Worker 
1313*f6dc9357SAndroid Build Coastguard Worker   return Name.Len() != 0
1314*f6dc9357SAndroid Build Coastguard Worker       && Name.Len() <= 2
1315*f6dc9357SAndroid Build Coastguard Worker       && Name[0] == '.'
1316*f6dc9357SAndroid Build Coastguard Worker       && (Name.Len() == 1 || Name[1] == '.');
1317*f6dc9357SAndroid Build Coastguard Worker }
1318*f6dc9357SAndroid Build Coastguard Worker 
1319*f6dc9357SAndroid Build Coastguard Worker 
NextAny(CDirEntry & fi,bool & found)1320*f6dc9357SAndroid Build Coastguard Worker bool CEnumerator::NextAny(CDirEntry &fi, bool &found)
1321*f6dc9357SAndroid Build Coastguard Worker {
1322*f6dc9357SAndroid Build Coastguard Worker   found = false;
1323*f6dc9357SAndroid Build Coastguard Worker 
1324*f6dc9357SAndroid Build Coastguard Worker   if (!_dir)
1325*f6dc9357SAndroid Build Coastguard Worker   {
1326*f6dc9357SAndroid Build Coastguard Worker     const char *w = "./";
1327*f6dc9357SAndroid Build Coastguard Worker     if (!_wildcard.IsEmpty())
1328*f6dc9357SAndroid Build Coastguard Worker       w = _wildcard.Ptr();
1329*f6dc9357SAndroid Build Coastguard Worker     _dir = ::opendir((const char *)w);
1330*f6dc9357SAndroid Build Coastguard Worker     if (_dir == NULL)
1331*f6dc9357SAndroid Build Coastguard Worker       return false;
1332*f6dc9357SAndroid Build Coastguard Worker   }
1333*f6dc9357SAndroid Build Coastguard Worker 
1334*f6dc9357SAndroid Build Coastguard Worker   // To distinguish end of stream from an error, we must set errno to zero before readdir()
1335*f6dc9357SAndroid Build Coastguard Worker   errno = 0;
1336*f6dc9357SAndroid Build Coastguard Worker 
1337*f6dc9357SAndroid Build Coastguard Worker   struct dirent *de = readdir(_dir);
1338*f6dc9357SAndroid Build Coastguard Worker   if (!de)
1339*f6dc9357SAndroid Build Coastguard Worker   {
1340*f6dc9357SAndroid Build Coastguard Worker     if (errno == 0)
1341*f6dc9357SAndroid Build Coastguard Worker       return true; // it's end of stream, and we report it with (found = false)
1342*f6dc9357SAndroid Build Coastguard Worker     // it's real error
1343*f6dc9357SAndroid Build Coastguard Worker     return false;
1344*f6dc9357SAndroid Build Coastguard Worker   }
1345*f6dc9357SAndroid Build Coastguard Worker 
1346*f6dc9357SAndroid Build Coastguard Worker   fi.iNode = de->d_ino;
1347*f6dc9357SAndroid Build Coastguard Worker 
1348*f6dc9357SAndroid Build Coastguard Worker #if !defined(_AIX) && !defined(__sun)
1349*f6dc9357SAndroid Build Coastguard Worker   fi.Type = de->d_type;
1350*f6dc9357SAndroid Build Coastguard Worker   /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
1351*f6dc9357SAndroid Build Coastguard Worker      we can set (Type) from fstatat() in that case.
1352*f6dc9357SAndroid Build Coastguard Worker      But (Type) is not too important. So we don't set it here with slow fstatat() */
1353*f6dc9357SAndroid Build Coastguard Worker   /*
1354*f6dc9357SAndroid Build Coastguard Worker   // fi.Type = DT_UNKNOWN; // for debug
1355*f6dc9357SAndroid Build Coastguard Worker   if (fi.Type == DT_UNKNOWN)
1356*f6dc9357SAndroid Build Coastguard Worker   {
1357*f6dc9357SAndroid Build Coastguard Worker     struct stat st;
1358*f6dc9357SAndroid Build Coastguard Worker     if (fstatat(dirfd(_dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) == 0)
1359*f6dc9357SAndroid Build Coastguard Worker       if (S_ISDIR(st.st_mode))
1360*f6dc9357SAndroid Build Coastguard Worker         fi.Type = DT_DIR;
1361*f6dc9357SAndroid Build Coastguard Worker   }
1362*f6dc9357SAndroid Build Coastguard Worker   */
1363*f6dc9357SAndroid Build Coastguard Worker #endif
1364*f6dc9357SAndroid Build Coastguard Worker 
1365*f6dc9357SAndroid Build Coastguard Worker   /*
1366*f6dc9357SAndroid Build Coastguard Worker   if (de->d_type == DT_DIR)
1367*f6dc9357SAndroid Build Coastguard Worker     fi.Attrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(S_IFDIR) << 16);
1368*f6dc9357SAndroid Build Coastguard Worker   else if (de->d_type < 16)
1369*f6dc9357SAndroid Build Coastguard Worker     fi.Attrib = FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(de->d_type) << (16 + 12));
1370*f6dc9357SAndroid Build Coastguard Worker   */
1371*f6dc9357SAndroid Build Coastguard Worker   fi.Name = de->d_name;
1372*f6dc9357SAndroid Build Coastguard Worker 
1373*f6dc9357SAndroid Build Coastguard Worker   /*
1374*f6dc9357SAndroid Build Coastguard Worker   printf("\nCEnumerator::NextAny; len = %d %s \n", (int)fi.Name.Len(), fi.Name.Ptr());
1375*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < fi.Name.Len(); i++)
1376*f6dc9357SAndroid Build Coastguard Worker     printf (" %02x", (unsigned)(Byte)de->d_name[i]);
1377*f6dc9357SAndroid Build Coastguard Worker   printf("\n");
1378*f6dc9357SAndroid Build Coastguard Worker   */
1379*f6dc9357SAndroid Build Coastguard Worker 
1380*f6dc9357SAndroid Build Coastguard Worker   found = true;
1381*f6dc9357SAndroid Build Coastguard Worker   return true;
1382*f6dc9357SAndroid Build Coastguard Worker }
1383*f6dc9357SAndroid Build Coastguard Worker 
1384*f6dc9357SAndroid Build Coastguard Worker 
Next(CDirEntry & fi,bool & found)1385*f6dc9357SAndroid Build Coastguard Worker bool CEnumerator::Next(CDirEntry &fi, bool &found)
1386*f6dc9357SAndroid Build Coastguard Worker {
1387*f6dc9357SAndroid Build Coastguard Worker   // printf("\nCEnumerator::Next()\n");
1388*f6dc9357SAndroid Build Coastguard Worker   // PrintName("Next", "");
1389*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1390*f6dc9357SAndroid Build Coastguard Worker   {
1391*f6dc9357SAndroid Build Coastguard Worker     if (!NextAny(fi, found))
1392*f6dc9357SAndroid Build Coastguard Worker       return false;
1393*f6dc9357SAndroid Build Coastguard Worker     if (!found)
1394*f6dc9357SAndroid Build Coastguard Worker       return true;
1395*f6dc9357SAndroid Build Coastguard Worker     if (!fi.IsDots())
1396*f6dc9357SAndroid Build Coastguard Worker     {
1397*f6dc9357SAndroid Build Coastguard Worker       /*
1398*f6dc9357SAndroid Build Coastguard Worker       if (!NeedFullStat)
1399*f6dc9357SAndroid Build Coastguard Worker         return true;
1400*f6dc9357SAndroid Build Coastguard Worker       // we silently skip error file here - it can be wrong link item
1401*f6dc9357SAndroid Build Coastguard Worker       if (fi.Find_DontFill_Name(path))
1402*f6dc9357SAndroid Build Coastguard Worker         return true;
1403*f6dc9357SAndroid Build Coastguard Worker       */
1404*f6dc9357SAndroid Build Coastguard Worker       return true;
1405*f6dc9357SAndroid Build Coastguard Worker     }
1406*f6dc9357SAndroid Build Coastguard Worker   }
1407*f6dc9357SAndroid Build Coastguard Worker }
1408*f6dc9357SAndroid Build Coastguard Worker 
1409*f6dc9357SAndroid Build Coastguard Worker /*
1410*f6dc9357SAndroid Build Coastguard Worker bool CEnumerator::Next(CDirEntry &fileInfo, bool &found)
1411*f6dc9357SAndroid Build Coastguard Worker {
1412*f6dc9357SAndroid Build Coastguard Worker   bool found;
1413*f6dc9357SAndroid Build Coastguard Worker   if (!Next(fi, found))
1414*f6dc9357SAndroid Build Coastguard Worker     return false;
1415*f6dc9357SAndroid Build Coastguard Worker   return found;
1416*f6dc9357SAndroid Build Coastguard Worker }
1417*f6dc9357SAndroid Build Coastguard Worker */
1418*f6dc9357SAndroid Build Coastguard Worker 
Fill_FileInfo(const CDirEntry & de,CFileInfo & fileInfo,bool followLink) const1419*f6dc9357SAndroid Build Coastguard Worker bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const
1420*f6dc9357SAndroid Build Coastguard Worker {
1421*f6dc9357SAndroid Build Coastguard Worker   // printf("\nCEnumerator::Fill_FileInfo()\n");
1422*f6dc9357SAndroid Build Coastguard Worker   struct stat st;
1423*f6dc9357SAndroid Build Coastguard Worker   // probably it's OK to use fstatat() even if it changes file position dirfd(_dir)
1424*f6dc9357SAndroid Build Coastguard Worker   int res = fstatat(dirfd(_dir), de.Name, &st, followLink ? 0 : AT_SYMLINK_NOFOLLOW);
1425*f6dc9357SAndroid Build Coastguard Worker   // if fstatat() is not supported, we can use stat() / lstat()
1426*f6dc9357SAndroid Build Coastguard Worker 
1427*f6dc9357SAndroid Build Coastguard Worker   /*
1428*f6dc9357SAndroid Build Coastguard Worker   const FString path = _wildcard + s;
1429*f6dc9357SAndroid Build Coastguard Worker   int res = MY_lstat(path, &st, followLink);
1430*f6dc9357SAndroid Build Coastguard Worker   */
1431*f6dc9357SAndroid Build Coastguard Worker 
1432*f6dc9357SAndroid Build Coastguard Worker   if (res != 0)
1433*f6dc9357SAndroid Build Coastguard Worker     return false;
1434*f6dc9357SAndroid Build Coastguard Worker   // printf("\nname=%s\n", de.Name.Ptr());
1435*f6dc9357SAndroid Build Coastguard Worker   fileInfo.SetFrom_stat(st);
1436*f6dc9357SAndroid Build Coastguard Worker   fileInfo.Name = de.Name;
1437*f6dc9357SAndroid Build Coastguard Worker   return true;
1438*f6dc9357SAndroid Build Coastguard Worker }
1439*f6dc9357SAndroid Build Coastguard Worker 
1440*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32
1441*f6dc9357SAndroid Build Coastguard Worker 
1442*f6dc9357SAndroid Build Coastguard Worker }}}
1443