diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2021-12-27 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-03-18 15:35:13 +0500 |
commit | f19f813537c7aea1c20749c914e756b54a9c3cf5 (patch) | |
tree | 816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Windows/FileIO.h | |
parent | 98e06a519b63b81986abe76d28887f6984a7732b (diff) | |
download | 7zip-21.07.tar.gz 7zip-21.07.tar.bz2 7zip-21.07.zip |
'21.07'21.07
Diffstat (limited to 'CPP/Windows/FileIO.h')
-rw-r--r-- | CPP/Windows/FileIO.h | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h new file mode 100644 index 0000000..22998eb --- /dev/null +++ b/CPP/Windows/FileIO.h | |||
@@ -0,0 +1,347 @@ | |||
1 | // Windows/FileIO.h | ||
2 | |||
3 | #ifndef __WINDOWS_FILE_IO_H | ||
4 | #define __WINDOWS_FILE_IO_H | ||
5 | |||
6 | #include "../Common/MyWindows.h" | ||
7 | |||
8 | #define _my_IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) | ||
9 | #define _my_IO_REPARSE_TAG_SYMLINK (0xA000000CL) | ||
10 | #define _my_IO_REPARSE_TAG_LX_SYMLINK (0xA000001DL) | ||
11 | |||
12 | #define _my_SYMLINK_FLAG_RELATIVE 1 | ||
13 | |||
14 | // what the meaning of that FLAG or field (2)? | ||
15 | #define _my_LX_SYMLINK_FLAG 2 | ||
16 | |||
17 | #ifdef _WIN32 | ||
18 | |||
19 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
20 | #include <WinIoCtl.h> | ||
21 | #endif | ||
22 | |||
23 | #else | ||
24 | |||
25 | #include <sys/types.h> | ||
26 | #include <sys/stat.h> | ||
27 | |||
28 | #endif | ||
29 | |||
30 | #include "../Common/MyString.h" | ||
31 | #include "../Common/MyBuffer.h" | ||
32 | |||
33 | #include "Defs.h" | ||
34 | |||
35 | HRESULT GetLastError_noZero_HRESULT(); | ||
36 | |||
37 | #define my_FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER | ||
38 | #define my_FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER | ||
39 | #define my_FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER | ||
40 | |||
41 | namespace NWindows { | ||
42 | namespace NFile { | ||
43 | |||
44 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
45 | bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL); | ||
46 | #endif | ||
47 | |||
48 | struct CReparseShortInfo | ||
49 | { | ||
50 | unsigned Offset; | ||
51 | unsigned Size; | ||
52 | |||
53 | bool Parse(const Byte *p, size_t size); | ||
54 | }; | ||
55 | |||
56 | struct CReparseAttr | ||
57 | { | ||
58 | UInt32 Tag; | ||
59 | UInt32 Flags; | ||
60 | UString SubsName; | ||
61 | UString PrintName; | ||
62 | |||
63 | AString WslName; | ||
64 | |||
65 | bool HeaderError; | ||
66 | bool TagIsUnknown; | ||
67 | bool MinorError; | ||
68 | DWORD ErrorCode; | ||
69 | |||
70 | CReparseAttr(): Tag(0), Flags(0) {} | ||
71 | |||
72 | // Parse() | ||
73 | // returns (true) and (ErrorCode = 0), if (it'a correct known link) | ||
74 | // returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag | ||
75 | bool Parse(const Byte *p, size_t size); | ||
76 | |||
77 | bool IsMountPoint() const { return Tag == _my_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction | ||
78 | bool IsSymLink_Win() const { return Tag == _my_IO_REPARSE_TAG_SYMLINK; } | ||
79 | bool IsSymLink_WSL() const { return Tag == _my_IO_REPARSE_TAG_LX_SYMLINK; } | ||
80 | |||
81 | bool IsRelative_Win() const { return Flags == _my_SYMLINK_FLAG_RELATIVE; } | ||
82 | |||
83 | bool IsRelative_WSL() const | ||
84 | { | ||
85 | if (WslName.IsEmpty()) | ||
86 | return true; | ||
87 | char c = WslName[0]; | ||
88 | return !IS_PATH_SEPAR(c); | ||
89 | } | ||
90 | |||
91 | // bool IsVolume() const; | ||
92 | |||
93 | bool IsOkNamePair() const; | ||
94 | UString GetPath() const; | ||
95 | }; | ||
96 | |||
97 | |||
98 | #ifdef _WIN32 | ||
99 | |||
100 | namespace NIO { | ||
101 | |||
102 | bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL); | ||
103 | bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); | ||
104 | bool DeleteReparseData(CFSTR path); | ||
105 | |||
106 | class CFileBase MY_UNCOPYABLE | ||
107 | { | ||
108 | protected: | ||
109 | HANDLE _handle; | ||
110 | |||
111 | bool Create(CFSTR path, DWORD desiredAccess, | ||
112 | DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); | ||
113 | |||
114 | public: | ||
115 | |||
116 | bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize, | ||
117 | LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const | ||
118 | { | ||
119 | return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize, | ||
120 | outBuffer, outSize, bytesReturned, overlapped)); | ||
121 | } | ||
122 | |||
123 | bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const | ||
124 | { | ||
125 | return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned); | ||
126 | } | ||
127 | |||
128 | bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const | ||
129 | { | ||
130 | DWORD bytesReturned; | ||
131 | return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned); | ||
132 | } | ||
133 | |||
134 | public: | ||
135 | bool PreserveATime; | ||
136 | #ifdef SUPPORT_DEVICE_FILE | ||
137 | bool IsDeviceFile; | ||
138 | bool SizeDefined; | ||
139 | UInt64 Size; // it can be larger than real available size | ||
140 | #endif | ||
141 | |||
142 | CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {}; | ||
143 | ~CFileBase() { Close(); } | ||
144 | |||
145 | bool Close() throw(); | ||
146 | |||
147 | bool GetPosition(UInt64 &position) const throw(); | ||
148 | bool GetLength(UInt64 &length) const throw(); | ||
149 | |||
150 | bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw(); | ||
151 | bool Seek(UInt64 position, UInt64 &newPosition) const throw(); | ||
152 | bool SeekToBegin() const throw(); | ||
153 | bool SeekToEnd(UInt64 &newPosition) const throw(); | ||
154 | |||
155 | bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const | ||
156 | { return BOOLToBool(GetFileInformationByHandle(_handle, info)); } | ||
157 | |||
158 | static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info) | ||
159 | { | ||
160 | // probably it can work for complex paths: unsupported by another things | ||
161 | NIO::CFileBase file; | ||
162 | if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)) | ||
163 | return false; | ||
164 | return file.GetFileInformation(info); | ||
165 | } | ||
166 | }; | ||
167 | |||
168 | #ifndef UNDER_CE | ||
169 | #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM | ||
170 | #define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) | ||
171 | // #define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) | ||
172 | |||
173 | // IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP | ||
174 | #define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) | ||
175 | |||
176 | struct my_DISK_GEOMETRY_EX | ||
177 | { | ||
178 | DISK_GEOMETRY Geometry; | ||
179 | LARGE_INTEGER DiskSize; | ||
180 | BYTE Data[1]; | ||
181 | }; | ||
182 | #endif | ||
183 | |||
184 | class CInFile: public CFileBase | ||
185 | { | ||
186 | #ifdef SUPPORT_DEVICE_FILE | ||
187 | |||
188 | #ifndef UNDER_CE | ||
189 | |||
190 | bool GetGeometry(DISK_GEOMETRY *res) const | ||
191 | { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } | ||
192 | |||
193 | bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const | ||
194 | { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); } | ||
195 | |||
196 | bool GetCdRomGeometry(DISK_GEOMETRY *res) const | ||
197 | { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); } | ||
198 | |||
199 | bool GetPartitionInfo(PARTITION_INFORMATION *res) | ||
200 | { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); } | ||
201 | |||
202 | #endif | ||
203 | |||
204 | void CorrectDeviceSize(); | ||
205 | void CalcDeviceSize(CFSTR name); | ||
206 | |||
207 | #endif | ||
208 | |||
209 | public: | ||
210 | bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); | ||
211 | bool OpenShared(CFSTR fileName, bool shareForWrite); | ||
212 | bool Open(CFSTR fileName); | ||
213 | |||
214 | #ifndef UNDER_CE | ||
215 | |||
216 | bool OpenReparse(CFSTR fileName) | ||
217 | { | ||
218 | // 17.02 fix: to support Windows XP compatibility junctions: | ||
219 | // we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ | ||
220 | return | ||
221 | Create(fileName, 0, | ||
222 | // Open(fileName, | ||
223 | FILE_SHARE_READ, OPEN_EXISTING, | ||
224 | FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); | ||
225 | } | ||
226 | |||
227 | #endif | ||
228 | |||
229 | bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw(); | ||
230 | bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw(); | ||
231 | bool Read(void *data, UInt32 size, UInt32 &processedSize) throw(); | ||
232 | bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); | ||
233 | }; | ||
234 | |||
235 | class COutFile: public CFileBase | ||
236 | { | ||
237 | public: | ||
238 | bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); | ||
239 | bool Open(CFSTR fileName, DWORD creationDisposition); | ||
240 | bool Create(CFSTR fileName, bool createAlways); | ||
241 | bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); | ||
242 | |||
243 | bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); | ||
244 | bool SetMTime(const FILETIME *mTime) throw(); | ||
245 | bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); | ||
246 | bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); | ||
247 | bool WriteFull(const void *data, size_t size) throw(); | ||
248 | bool SetEndOfFile() throw(); | ||
249 | bool SetLength(UInt64 length) throw(); | ||
250 | bool SetLength_KeepPosition(UInt64 length) throw(); | ||
251 | }; | ||
252 | |||
253 | } | ||
254 | |||
255 | |||
256 | #else // _WIN32 | ||
257 | |||
258 | namespace NIO { | ||
259 | |||
260 | bool GetReparseData(CFSTR path, CByteBuffer &reparseData); | ||
261 | // bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size); | ||
262 | |||
263 | // parameters are in reverse order of symlink() function !!! | ||
264 | bool SetSymLink(CFSTR from, CFSTR to); | ||
265 | bool SetSymLink_UString(CFSTR from, const UString &to); | ||
266 | |||
267 | |||
268 | class CFileBase | ||
269 | { | ||
270 | protected: | ||
271 | int _handle; | ||
272 | |||
273 | bool OpenBinary(const char *name, int flags); | ||
274 | public: | ||
275 | bool PreserveATime; | ||
276 | |||
277 | CFileBase(): _handle(-1), PreserveATime(false) {}; | ||
278 | ~CFileBase() { Close(); } | ||
279 | bool Close(); | ||
280 | bool GetLength(UInt64 &length) const; | ||
281 | off_t seek(off_t distanceToMove, int moveMethod) const; | ||
282 | off_t seekToBegin() const throw(); | ||
283 | off_t seekToCur() const throw(); | ||
284 | // bool SeekToBegin() throw(); | ||
285 | int my_fstat(struct stat *st) const { return fstat(_handle, st); } | ||
286 | }; | ||
287 | |||
288 | class CInFile: public CFileBase | ||
289 | { | ||
290 | public: | ||
291 | bool Open(const char *name); | ||
292 | bool OpenShared(const char *name, bool shareForWrite); | ||
293 | ssize_t read_part(void *data, size_t size) throw(); | ||
294 | // ssize_t read_full(void *data, size_t size, size_t &processed); | ||
295 | bool ReadFull(void *data, size_t size, size_t &processedSize) throw(); | ||
296 | }; | ||
297 | |||
298 | class COutFile: public CFileBase | ||
299 | { | ||
300 | bool CTime_defined; | ||
301 | bool ATime_defined; | ||
302 | bool MTime_defined; | ||
303 | |||
304 | FILETIME CTime; | ||
305 | FILETIME ATime; | ||
306 | FILETIME MTime; | ||
307 | |||
308 | AString Path; | ||
309 | ssize_t write_part(const void *data, size_t size) throw(); | ||
310 | public: | ||
311 | COutFile(): | ||
312 | CTime_defined(false), | ||
313 | ATime_defined(false), | ||
314 | MTime_defined(false) | ||
315 | {} | ||
316 | |||
317 | bool Close(); | ||
318 | bool Create(const char *name, bool createAlways); | ||
319 | bool Open(const char *name, DWORD creationDisposition); | ||
320 | ssize_t write_full(const void *data, size_t size, size_t &processed) throw(); | ||
321 | |||
322 | bool WriteFull(const void *data, size_t size) throw() | ||
323 | { | ||
324 | size_t processed; | ||
325 | ssize_t res = write_full(data, size, processed); | ||
326 | if (res == -1) | ||
327 | return false; | ||
328 | return processed == size; | ||
329 | } | ||
330 | |||
331 | bool SetLength(UInt64 length) throw(); | ||
332 | bool SetLength_KeepPosition(UInt64 length) throw() | ||
333 | { | ||
334 | return SetLength(length); | ||
335 | } | ||
336 | bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); | ||
337 | bool SetMTime(const FILETIME *mTime) throw(); | ||
338 | }; | ||
339 | |||
340 | } | ||
341 | |||
342 | #endif // _WIN32 | ||
343 | |||
344 | }} | ||
345 | |||
346 | |||
347 | #endif | ||