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 bool SetAs_StdInFile();
103
104 #ifdef _WIN32
105
106 bool Fill_From_ByHandleFileInfo(CFSTR path);
SetAsDir()107 void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } // |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16));
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 | 0777; }
136 void SetFrom_stat(const struct stat &st);
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 #endif
177 };
178
179
180 #ifdef _WIN32
181
182 class CFindFileBase MY_UNCOPYABLE
183 {
184 protected:
185 HANDLE _handle;
186 public:
IsHandleAllocated()187 bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; }
CFindFileBase()188 CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {}
~CFindFileBase()189 ~CFindFileBase() { Close(); }
190 bool Close() throw();
191 };
192
193 class CFindFile: public CFindFileBase
194 {
195 public:
196 bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo);
197 bool FindNext(CFileInfo &fileInfo);
198 };
199
200 #if defined(_WIN32) && !defined(UNDER_CE)
201
202 struct CStreamInfo
203 {
204 UString Name;
205 UInt64 Size;
206
207 UString GetReducedName() const; // returns ":Name"
208 // UString GetReducedName2() const; // returns "Name"
209 bool IsMainStream() const throw();
210 };
211
212 class CFindStream: public CFindFileBase
213 {
214 public:
215 bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo);
216 bool FindNext(CStreamInfo &streamInfo);
217 };
218
219 class CStreamEnumerator MY_UNCOPYABLE
220 {
221 CFindStream _find;
222 FString _filePath;
223
224 bool NextAny(CFileInfo &fileInfo, bool &found);
225 public:
CStreamEnumerator(const FString & filePath)226 CStreamEnumerator(const FString &filePath): _filePath(filePath) {}
227 bool Next(CStreamInfo &streamInfo, bool &found);
228 };
229
230 #endif // defined(_WIN32) && !defined(UNDER_CE)
231
232
233 class CEnumerator MY_UNCOPYABLE
234 {
235 CFindFile _findFile;
236 FString _wildcard;
237
238 bool NextAny(CFileInfo &fileInfo);
239 public:
240 void SetDirPrefix(const FString &dirPrefix);
241 bool Next(CFileInfo &fileInfo);
242 bool Next(CFileInfo &fileInfo, bool &found);
243 };
244
245
246 class CFindChangeNotification MY_UNCOPYABLE
247 {
248 HANDLE _handle;
249 public:
HANDLE()250 operator HANDLE () { return _handle; }
IsHandleAllocated()251 bool IsHandleAllocated() const
252 {
253 /* at least on win2000/XP (undocumented):
254 if pathName is "" or NULL,
255 FindFirstChangeNotification() could return NULL.
256 So we check for INVALID_HANDLE_VALUE and NULL.
257 */
258 return _handle != INVALID_HANDLE_VALUE && _handle != NULL;
259 }
CFindChangeNotification()260 CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}
~CFindChangeNotification()261 ~CFindChangeNotification() { Close(); }
262 bool Close() throw();
263 HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter);
FindNext()264 bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }
265 };
266
267 #ifndef UNDER_CE
268 bool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings);
269 #endif
270
271 typedef CFileInfo CDirEntry;
272
273
274 #else // WIN32
275
276
277 struct CDirEntry
278 {
279 ino_t iNode;
280 #if !defined(_AIX) && !defined(__sun)
281 Byte Type;
282 #endif
283 FString Name;
284
285 /*
286 #if !defined(_AIX) && !defined(__sun)
287 bool IsDir() const
288 {
289 // (Type == DT_UNKNOWN) on some systems
290 return Type == DT_DIR;
291 }
292 #endif
293 */
294
295 bool IsDots() const throw();
296 };
297
298 class CEnumerator MY_UNCOPYABLE
299 {
300 DIR *_dir;
301 FString _wildcard;
302
303 bool NextAny(CDirEntry &fileInfo, bool &found);
304 public:
CEnumerator()305 CEnumerator(): _dir(NULL) {}
306 ~CEnumerator();
307 void SetDirPrefix(const FString &dirPrefix);
308
309 bool Next(CDirEntry &fileInfo, bool &found);
310 bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const;
DirEntry_IsDir(const CDirEntry & de,bool followLink)311 bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const
312 {
313 #if !defined(_AIX) && !defined(__sun)
314 if (de.Type == DT_DIR)
315 return true;
316 if (de.Type != DT_UNKNOWN)
317 return false;
318 #endif
319 CFileInfo fileInfo;
320 if (Fill_FileInfo(de, fileInfo, followLink))
321 {
322 return fileInfo.IsDir();
323 }
324 return false; // change it
325 }
326 };
327
328 /*
329 inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode)
330 {
331 UInt32 attrib = S_ISDIR(mode) ?
332 FILE_ATTRIBUTE_DIRECTORY :
333 FILE_ATTRIBUTE_ARCHIVE;
334 if ((st.st_mode & 0222) == 0) // check it !!!
335 attrib |= FILE_ATTRIBUTE_READONLY;
336 return attrib;
337 }
338 */
339
340 // UInt32 Get_WinAttrib_From_stat(const struct stat &st);
341
342
343 #endif // WIN32
344
345 }}}
346
347 #endif
348