Mercurial > vba-clojure
comparison src/win32/7zip/7z/CPP/Windows/FileIO.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // Windows/FileIO.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "FileIO.h" | |
6 #include "Defs.h" | |
7 #ifdef WIN_LONG_PATH | |
8 #include "../Common/MyString.h" | |
9 #endif | |
10 #ifndef _UNICODE | |
11 #include "../Common/StringConvert.h" | |
12 #endif | |
13 | |
14 #ifndef _UNICODE | |
15 extern bool g_IsNT; | |
16 #endif | |
17 | |
18 namespace NWindows { | |
19 namespace NFile { | |
20 | |
21 #if defined(WIN_LONG_PATH) && defined(_UNICODE) | |
22 #define WIN_LONG_PATH2 | |
23 #endif | |
24 | |
25 #ifdef WIN_LONG_PATH | |
26 bool GetLongPathBase(LPCWSTR s, UString &res) | |
27 { | |
28 res.Empty(); | |
29 int len = MyStringLen(s); | |
30 wchar_t c = s[0]; | |
31 if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) | |
32 return true; | |
33 UString curDir; | |
34 bool isAbs = false; | |
35 if (len > 3) | |
36 isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); | |
37 | |
38 if (!isAbs) | |
39 { | |
40 DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); | |
41 curDir.ReleaseBuffer(); | |
42 if (needLength == 0 || needLength > MAX_PATH) | |
43 return false; | |
44 if (curDir[curDir.Length() - 1] != L'\\') | |
45 curDir += L'\\'; | |
46 } | |
47 res = UString(L"\\\\?\\") + curDir + s; | |
48 return true; | |
49 } | |
50 | |
51 bool GetLongPath(LPCWSTR path, UString &longPath) | |
52 { | |
53 if (GetLongPathBase(path, longPath)) | |
54 return !longPath.IsEmpty(); | |
55 return false; | |
56 } | |
57 #endif | |
58 | |
59 namespace NIO { | |
60 | |
61 CFileBase::~CFileBase() { Close(); } | |
62 | |
63 bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, | |
64 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) | |
65 { | |
66 if (!Close()) | |
67 return false; | |
68 _handle = ::CreateFile(fileName, desiredAccess, shareMode, | |
69 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, | |
70 flagsAndAttributes, (HANDLE)NULL); | |
71 #ifdef WIN_LONG_PATH2 | |
72 if (_handle == INVALID_HANDLE_VALUE) | |
73 { | |
74 UString longPath; | |
75 if (GetLongPath(fileName, longPath)) | |
76 _handle = ::CreateFileW(longPath, desiredAccess, shareMode, | |
77 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, | |
78 flagsAndAttributes, (HANDLE)NULL); | |
79 } | |
80 #endif | |
81 return (_handle != INVALID_HANDLE_VALUE); | |
82 } | |
83 | |
84 #ifndef _UNICODE | |
85 bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, | |
86 DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) | |
87 { | |
88 if (!g_IsNT) | |
89 return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), | |
90 desiredAccess, shareMode, creationDisposition, flagsAndAttributes); | |
91 if (!Close()) | |
92 return false; | |
93 _handle = ::CreateFileW(fileName, desiredAccess, shareMode, | |
94 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, | |
95 flagsAndAttributes, (HANDLE)NULL); | |
96 #ifdef WIN_LONG_PATH | |
97 if (_handle == INVALID_HANDLE_VALUE) | |
98 { | |
99 UString longPath; | |
100 if (GetLongPath(fileName, longPath)) | |
101 _handle = ::CreateFileW(longPath, desiredAccess, shareMode, | |
102 (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, | |
103 flagsAndAttributes, (HANDLE)NULL); | |
104 } | |
105 #endif | |
106 return (_handle != INVALID_HANDLE_VALUE); | |
107 } | |
108 #endif | |
109 | |
110 bool CFileBase::Close() | |
111 { | |
112 if (_handle == INVALID_HANDLE_VALUE) | |
113 return true; | |
114 if (!::CloseHandle(_handle)) | |
115 return false; | |
116 _handle = INVALID_HANDLE_VALUE; | |
117 return true; | |
118 } | |
119 | |
120 bool CFileBase::GetPosition(UInt64 &position) const | |
121 { | |
122 return Seek(0, FILE_CURRENT, position); | |
123 } | |
124 | |
125 bool CFileBase::GetLength(UInt64 &length) const | |
126 { | |
127 DWORD sizeHigh; | |
128 DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); | |
129 if (sizeLow == 0xFFFFFFFF) | |
130 if (::GetLastError() != NO_ERROR) | |
131 return false; | |
132 length = (((UInt64)sizeHigh) << 32) + sizeLow; | |
133 return true; | |
134 } | |
135 | |
136 bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const | |
137 { | |
138 LARGE_INTEGER value; | |
139 value.QuadPart = distanceToMove; | |
140 value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); | |
141 if (value.LowPart == 0xFFFFFFFF) | |
142 if (::GetLastError() != NO_ERROR) | |
143 return false; | |
144 newPosition = value.QuadPart; | |
145 return true; | |
146 } | |
147 | |
148 bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) | |
149 { | |
150 return Seek(position, FILE_BEGIN, newPosition); | |
151 } | |
152 | |
153 bool CFileBase::SeekToBegin() | |
154 { | |
155 UInt64 newPosition; | |
156 return Seek(0, newPosition); | |
157 } | |
158 | |
159 bool CFileBase::SeekToEnd(UInt64 &newPosition) | |
160 { | |
161 return Seek(0, FILE_END, newPosition); | |
162 } | |
163 | |
164 bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const | |
165 { | |
166 BY_HANDLE_FILE_INFORMATION winFileInfo; | |
167 if (!::GetFileInformationByHandle(_handle, &winFileInfo)) | |
168 return false; | |
169 fileInfo.Attributes = winFileInfo.dwFileAttributes; | |
170 fileInfo.CTime = winFileInfo.ftCreationTime; | |
171 fileInfo.ATime = winFileInfo.ftLastAccessTime; | |
172 fileInfo.MTime = winFileInfo.ftLastWriteTime; | |
173 fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; | |
174 fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; | |
175 fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; | |
176 fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; | |
177 return true; | |
178 } | |
179 | |
180 ///////////////////////// | |
181 // CInFile | |
182 | |
183 bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) | |
184 { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } | |
185 | |
186 bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) | |
187 { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } | |
188 | |
189 bool CInFile::Open(LPCTSTR fileName) | |
190 { return OpenShared(fileName, false); } | |
191 | |
192 #ifndef _UNICODE | |
193 bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) | |
194 { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } | |
195 | |
196 bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) | |
197 { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } | |
198 | |
199 bool CInFile::Open(LPCWSTR fileName) | |
200 { return OpenShared(fileName, false); } | |
201 #endif | |
202 | |
203 // ReadFile and WriteFile functions in Windows have BUG: | |
204 // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) | |
205 // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES | |
206 // (Insufficient system resources exist to complete the requested service). | |
207 | |
208 // Probably in some version of Windows there are problems with other sizes: | |
209 // for 32 MB (maybe also for 16 MB). | |
210 // And message can be "Network connection was lost" | |
211 | |
212 static UInt32 kChunkSizeMax = (1 << 22); | |
213 | |
214 bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) | |
215 { | |
216 if (size > kChunkSizeMax) | |
217 size = kChunkSizeMax; | |
218 DWORD processedLoc = 0; | |
219 bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); | |
220 processedSize = (UInt32)processedLoc; | |
221 return res; | |
222 } | |
223 | |
224 bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) | |
225 { | |
226 processedSize = 0; | |
227 do | |
228 { | |
229 UInt32 processedLoc = 0; | |
230 bool res = ReadPart(data, size, processedLoc); | |
231 processedSize += processedLoc; | |
232 if (!res) | |
233 return false; | |
234 if (processedLoc == 0) | |
235 return true; | |
236 data = (void *)((unsigned char *)data + processedLoc); | |
237 size -= processedLoc; | |
238 } | |
239 while (size > 0); | |
240 return true; | |
241 } | |
242 | |
243 ///////////////////////// | |
244 // COutFile | |
245 | |
246 bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) | |
247 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } | |
248 | |
249 static inline DWORD GetCreationDisposition(bool createAlways) | |
250 { return createAlways? CREATE_ALWAYS: CREATE_NEW; } | |
251 | |
252 bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) | |
253 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } | |
254 | |
255 bool COutFile::Create(LPCTSTR fileName, bool createAlways) | |
256 { return Open(fileName, GetCreationDisposition(createAlways)); } | |
257 | |
258 #ifndef _UNICODE | |
259 | |
260 bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) | |
261 { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } | |
262 | |
263 bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) | |
264 { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } | |
265 | |
266 bool COutFile::Create(LPCWSTR fileName, bool createAlways) | |
267 { return Open(fileName, GetCreationDisposition(createAlways)); } | |
268 | |
269 #endif | |
270 | |
271 bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) | |
272 { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } | |
273 | |
274 bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } | |
275 | |
276 bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) | |
277 { | |
278 if (size > kChunkSizeMax) | |
279 size = kChunkSizeMax; | |
280 DWORD processedLoc = 0; | |
281 bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); | |
282 processedSize = (UInt32)processedLoc; | |
283 return res; | |
284 } | |
285 | |
286 bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) | |
287 { | |
288 processedSize = 0; | |
289 do | |
290 { | |
291 UInt32 processedLoc = 0; | |
292 bool res = WritePart(data, size, processedLoc); | |
293 processedSize += processedLoc; | |
294 if (!res) | |
295 return false; | |
296 if (processedLoc == 0) | |
297 return true; | |
298 data = (const void *)((const unsigned char *)data + processedLoc); | |
299 size -= processedLoc; | |
300 } | |
301 while (size > 0); | |
302 return true; | |
303 } | |
304 | |
305 bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } | |
306 | |
307 bool COutFile::SetLength(UInt64 length) | |
308 { | |
309 UInt64 newPosition; | |
310 if (!Seek(length, newPosition)) | |
311 return false; | |
312 if (newPosition != length) | |
313 return false; | |
314 return SetEndOfFile(); | |
315 } | |
316 | |
317 }}} |