• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Windows/FileFind.h
2 
3 #ifndef ZIP7_INC_WINDOWS_FILE_FIND_H
4 #define ZIP7_INC_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
253   {
254     /* at least on win2000/XP (undocumented):
255        if pathName is "" or NULL,
256        FindFirstChangeNotification() could return NULL.
257        So we check for INVALID_HANDLE_VALUE and NULL.
258     */
259     return _handle != INVALID_HANDLE_VALUE && _handle != NULL;
260   }
CFindChangeNotification()261   CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}
~CFindChangeNotification()262   ~CFindChangeNotification() { Close(); }
263   bool Close() throw();
264   HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter);
FindNext()265   bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }
266 };
267 
268 #ifndef UNDER_CE
269 bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings);
270 #endif
271 
272 typedef CFileInfo CDirEntry;
273 
274 
275 #else // WIN32
276 
277 
278 struct CDirEntry
279 {
280   ino_t iNode;
281   #if !defined(_AIX)
282   Byte Type;
283   #endif
284   FString Name;
285 
286   /*
287   #if !defined(_AIX)
288   bool IsDir() const
289   {
290     // (Type == DT_UNKNOWN) on some systems
291     return Type == DT_DIR;
292   }
293   #endif
294   */
295 
296   bool IsDots() const throw();
297 };
298 
299 class CEnumerator  MY_UNCOPYABLE
300 {
301   DIR *_dir;
302   FString _wildcard;
303 
304   bool NextAny(CDirEntry &fileInfo, bool &found);
305 public:
CEnumerator()306   CEnumerator(): _dir(NULL) {}
307   ~CEnumerator();
308   void SetDirPrefix(const FString &dirPrefix);
309 
310   bool Next(CDirEntry &fileInfo, bool &found);
311   bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const;
DirEntry_IsDir(const CDirEntry & de,bool followLink)312   bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const
313   {
314     #if !defined(_AIX)
315     if (de.Type == DT_DIR)
316       return true;
317     if (de.Type != DT_UNKNOWN)
318       return false;
319     #endif
320     CFileInfo fileInfo;
321     if (Fill_FileInfo(de, fileInfo, followLink))
322     {
323       return fileInfo.IsDir();
324     }
325     return false; // change it
326   }
327 };
328 
329 /*
330 inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode)
331 {
332   UInt32 attrib = S_ISDIR(mode) ?
333     FILE_ATTRIBUTE_DIRECTORY :
334     FILE_ATTRIBUTE_ARCHIVE;
335   if ((st.st_mode & 0222) == 0) // check it !!!
336     attrib |= FILE_ATTRIBUTE_READONLY;
337   return attrib;
338 }
339 */
340 
341 // UInt32 Get_WinAttrib_From_stat(const struct stat &st);
342 
343 
344 #endif // WIN32
345 
346 }}}
347 
348 #endif
349