• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Windows/FileFind.h
2 
3 #ifndef __WINDOWS_FILE_FIND_H
4 #define __WINDOWS_FILE_FIND_H
5 
6 #ifndef _WIN32
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 #include <dirent.h>
10 #endif
11 
12 #include "../Common/MyLinux.h"
13 #include "../Common/MyString.h"
14 #include "../Common/MyWindows.h"
15 
16 #include "Defs.h"
17 
18 #include "FileIO.h"
19 
20 namespace NWindows {
21 namespace NFile {
22 namespace NFind {
23 
24 // bool DoesFileExist(CFSTR name, bool followLink);
25 bool DoesFileExist_Raw(CFSTR name);
26 bool DoesFileExist_FollowLink(CFSTR name);
27 bool DoesDirExist(CFSTR name, bool followLink);
28 
DoesDirExist(CFSTR name)29 inline bool DoesDirExist(CFSTR name)
30   { return DoesDirExist(name, false); }
DoesDirExist_FollowLink(CFSTR name)31 inline bool DoesDirExist_FollowLink(CFSTR name)
32   { return DoesDirExist(name, true); }
33 
34 // it's always _Raw
35 bool DoesFileOrDirExist(CFSTR name);
36 
37 DWORD GetFileAttrib(CFSTR path);
38 
39 #ifdef _WIN32
40 
41 namespace NAttributes
42 {
IsReadOnly(DWORD attrib)43   inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; }
IsHidden(DWORD attrib)44   inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; }
IsSystem(DWORD attrib)45   inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; }
IsDir(DWORD attrib)46   inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; }
IsArchived(DWORD attrib)47   inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; }
IsCompressed(DWORD attrib)48   inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; }
IsEncrypted(DWORD attrib)49   inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; }
50 
Get_PosixMode_From_WinAttrib(DWORD attrib)51   inline UInt32 Get_PosixMode_From_WinAttrib(DWORD attrib)
52   {
53     UInt32 v = IsDir(attrib) ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG;
54     /* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY).
55     So extracting at Linux will be allowed to write files inside (0777) directories. */
56     v |= ((IsReadOnly(attrib) && !IsDir(attrib)) ? 0555 : 0777);
57     return v;
58   }
59 }
60 
61 #else
62 
63 UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode);
64 
65 #endif
66 
67 class CFileInfoBase
68 {
69  #ifdef _WIN32
MatchesMask(UINT32 mask)70   bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); }
71  #endif
72 public:
73   UInt64 Size;
74   CFiTime CTime;
75   CFiTime ATime;
76   CFiTime MTime;
77  #ifdef _WIN32
78   DWORD Attrib;
79   bool IsAltStream;
80   bool IsDevice;
81 
82   /*
83   #ifdef UNDER_CE
84   DWORD ObjectID;
85   #else
86   UINT32 ReparseTag;
87   #endif
88   */
89  #else
90   dev_t dev;     /* ID of device containing file */
91   ino_t ino;
92   mode_t mode;
93   nlink_t nlink;
94   uid_t uid;     /* user ID of owner */
95   gid_t gid;     /* group ID of owner */
96   dev_t rdev;    /* device ID (defined, if S_ISCHR(mode) || S_ISBLK(mode)) */
97   // bool Use_lstat;
98  #endif
99 
CFileInfoBase()100   CFileInfoBase() { ClearBase(); }
101   void ClearBase() throw();
102 
103  #ifdef _WIN32
104 
105   bool Fill_From_ByHandleFileInfo(CFSTR path);
SetAsDir()106   void SetAsDir()  { Attrib = FILE_ATTRIBUTE_DIRECTORY; } // |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16));
SetAsFile()107   void SetAsFile() { Attrib = 0; }
108 
IsArchived()109   bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }
IsCompressed()110   bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }
IsDir()111   bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); }
IsEncrypted()112   bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); }
IsHidden()113   bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); }
IsNormal()114   bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); }
IsOffline()115   bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); }
IsReadOnly()116   bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); }
HasReparsePoint()117   bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); }
IsSparse()118   bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); }
IsSystem()119   bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); }
IsTemporary()120   bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); }
121 
GetWinAttrib()122   UInt32 GetWinAttrib() const { return Attrib; }
GetPosixAttrib()123   UInt32 GetPosixAttrib() const
124   {
125     return NAttributes::Get_PosixMode_From_WinAttrib(Attrib);
126   }
Has_Attrib_ReparsePoint()127   bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; }
128 
129  #else
130 
GetPosixAttrib()131   UInt32 GetPosixAttrib() const { return mode; }
GetWinAttrib()132   UInt32 GetWinAttrib() const { return Get_WinAttribPosix_From_PosixMode(mode); }
133 
IsDir()134   bool IsDir() const { return S_ISDIR(mode); }
SetAsDir()135   void SetAsDir()  { mode = S_IFDIR; }
SetAsFile()136   void SetAsFile() { mode = S_IFREG; }
137 
IsReadOnly()138   bool IsReadOnly() const
139   {
140     // does linux support writing to ReadOnly files?
141     if ((mode & 0222) == 0) // S_IWUSR in p7zip
142       return true;
143     return false;
144   }
145 
IsPosixLink()146   bool IsPosixLink() const { return S_ISLNK(mode); }
147 
148  #endif
149 
IsOsSymLink()150   bool IsOsSymLink() const
151   {
152     #ifdef _WIN32
153       return HasReparsePoint();
154     #else
155       return IsPosixLink();
156     #endif
157   }
158 };
159 
160 struct CFileInfo: public CFileInfoBase
161 {
162   FString Name;
163   #if defined(_WIN32) && !defined(UNDER_CE)
164   // FString ShortName;
165   #endif
166 
167   bool IsDots() const throw();
168   bool Find(CFSTR path, bool followLink = false);
Find_FollowLinkCFileInfo169   bool Find_FollowLink(CFSTR path) { return Find(path, true); }
170 
171   #ifdef _WIN32
172   // bool Fill_From_ByHandleFileInfo(CFSTR path);
173   // bool FollowReparse(CFSTR path, bool isDir);
174   #else
175   bool Find_DontFill_Name(CFSTR path, bool followLink = false);
176   void SetFrom_stat(const struct stat &st);
177   #endif
178 };
179 
180 
181 #ifdef _WIN32
182 
183 class CFindFileBase  MY_UNCOPYABLE
184 {
185 protected:
186   HANDLE _handle;
187 public:
IsHandleAllocated()188   bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; }
CFindFileBase()189   CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {}
~CFindFileBase()190   ~CFindFileBase() { Close(); }
191   bool Close() throw();
192 };
193 
194 class CFindFile: public CFindFileBase
195 {
196 public:
197   bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo);
198   bool FindNext(CFileInfo &fileInfo);
199 };
200 
201 #if defined(_WIN32) && !defined(UNDER_CE)
202 
203 struct CStreamInfo
204 {
205   UString Name;
206   UInt64 Size;
207 
208   UString GetReducedName() const; // returns ":Name"
209   // UString GetReducedName2() const; // returns "Name"
210   bool IsMainStream() const throw();
211 };
212 
213 class CFindStream: public CFindFileBase
214 {
215 public:
216   bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo);
217   bool FindNext(CStreamInfo &streamInfo);
218 };
219 
220 class CStreamEnumerator  MY_UNCOPYABLE
221 {
222   CFindStream _find;
223   FString _filePath;
224 
225   bool NextAny(CFileInfo &fileInfo, bool &found);
226 public:
CStreamEnumerator(const FString & filePath)227   CStreamEnumerator(const FString &filePath): _filePath(filePath) {}
228   bool Next(CStreamInfo &streamInfo, bool &found);
229 };
230 
231 #endif // defined(_WIN32) && !defined(UNDER_CE)
232 
233 
234 class CEnumerator  MY_UNCOPYABLE
235 {
236   CFindFile _findFile;
237   FString _wildcard;
238 
239   bool NextAny(CFileInfo &fileInfo);
240 public:
241   void SetDirPrefix(const FString &dirPrefix);
242   bool Next(CFileInfo &fileInfo);
243   bool Next(CFileInfo &fileInfo, bool &found);
244 };
245 
246 
247 class CFindChangeNotification  MY_UNCOPYABLE
248 {
249   HANDLE _handle;
250 public:
HANDLE()251   operator HANDLE () { return _handle; }
IsHandleAllocated()252   bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; }
CFindChangeNotification()253   CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}
~CFindChangeNotification()254   ~CFindChangeNotification() { Close(); }
255   bool Close() throw();
256   HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter);
FindNext()257   bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }
258 };
259 
260 #ifndef UNDER_CE
261 bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings);
262 #endif
263 
264 typedef CFileInfo CDirEntry;
265 
266 
267 #else // WIN32
268 
269 
270 struct CDirEntry
271 {
272   ino_t iNode;
273   #if !defined(_AIX)
274   Byte Type;
275   #endif
276   FString Name;
277 
278   /*
279   #if !defined(_AIX)
280   bool IsDir() const
281   {
282     // (Type == DT_UNKNOWN) on some systems
283     return Type == DT_DIR;
284   }
285   #endif
286   */
287 
288   bool IsDots() const throw();
289 };
290 
291 class CEnumerator  MY_UNCOPYABLE
292 {
293   DIR *_dir;
294   FString _wildcard;
295 
296   bool NextAny(CDirEntry &fileInfo, bool &found);
297 public:
CEnumerator()298   CEnumerator(): _dir(NULL) {}
299   ~CEnumerator();
300   void SetDirPrefix(const FString &dirPrefix);
301 
302   bool Next(CDirEntry &fileInfo, bool &found);
303   bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const;
DirEntry_IsDir(const CDirEntry & de,bool followLink)304   bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const
305   {
306     #if !defined(_AIX)
307     if (de.Type == DT_DIR)
308       return true;
309     if (de.Type != DT_UNKNOWN)
310       return false;
311     #endif
312     CFileInfo fileInfo;
313     if (Fill_FileInfo(de, fileInfo, followLink))
314     {
315       return fileInfo.IsDir();
316     }
317     return false; // change it
318   }
319 };
320 
321 /*
322 inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode)
323 {
324   UInt32 attrib = S_ISDIR(mode) ?
325     FILE_ATTRIBUTE_DIRECTORY :
326     FILE_ATTRIBUTE_ARCHIVE;
327   if ((st.st_mode & 0222) == 0) // check it !!!
328     attrib |= FILE_ATTRIBUTE_READONLY;
329   return attrib;
330 }
331 */
332 
333 // UInt32 Get_WinAttrib_From_stat(const struct stat &st);
334 
335 
336 #endif // WIN32
337 
338 }}}
339 
340 #endif
341