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