aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows/FileIO.h
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Windows/FileIO.h
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-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.h347
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
35HRESULT 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
41namespace NWindows {
42namespace NFile {
43
44#if defined(_WIN32) && !defined(UNDER_CE)
45bool FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL);
46#endif
47
48struct CReparseShortInfo
49{
50 unsigned Offset;
51 unsigned Size;
52
53 bool Parse(const Byte *p, size_t size);
54};
55
56struct 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
100namespace NIO {
101
102bool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL);
103bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);
104bool DeleteReparseData(CFSTR path);
105
106class CFileBase MY_UNCOPYABLE
107{
108protected:
109 HANDLE _handle;
110
111 bool Create(CFSTR path, DWORD desiredAccess,
112 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
113
114public:
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
134public:
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
176struct my_DISK_GEOMETRY_EX
177{
178 DISK_GEOMETRY Geometry;
179 LARGE_INTEGER DiskSize;
180 BYTE Data[1];
181};
182#endif
183
184class 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
209public:
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
235class COutFile: public CFileBase
236{
237public:
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
258namespace NIO {
259
260bool 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 !!!
264bool SetSymLink(CFSTR from, CFSTR to);
265bool SetSymLink_UString(CFSTR from, const UString &to);
266
267
268class CFileBase
269{
270protected:
271 int _handle;
272
273 bool OpenBinary(const char *name, int flags);
274public:
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
288class CInFile: public CFileBase
289{
290public:
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
298class 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();
310public:
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