1*f6dc9357SAndroid Build Coastguard Worker // Windows/FileIO.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
6*f6dc9357SAndroid Build Coastguard Worker #include "../../C/Alloc.h"
7*f6dc9357SAndroid Build Coastguard Worker #endif
8*f6dc9357SAndroid Build Coastguard Worker
9*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
10*f6dc9357SAndroid Build Coastguard Worker
11*f6dc9357SAndroid Build Coastguard Worker /*
12*f6dc9357SAndroid Build Coastguard Worker #ifndef _WIN32
13*f6dc9357SAndroid Build Coastguard Worker // for ioctl BLKGETSIZE64
14*f6dc9357SAndroid Build Coastguard Worker #include <sys/ioctl.h>
15*f6dc9357SAndroid Build Coastguard Worker #include <linux/fs.h>
16*f6dc9357SAndroid Build Coastguard Worker #endif
17*f6dc9357SAndroid Build Coastguard Worker */
18*f6dc9357SAndroid Build Coastguard Worker
19*f6dc9357SAndroid Build Coastguard Worker #include "FileIO.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "FileName.h"
21*f6dc9357SAndroid Build Coastguard Worker
GetLastError_noZero_HRESULT()22*f6dc9357SAndroid Build Coastguard Worker HRESULT GetLastError_noZero_HRESULT()
23*f6dc9357SAndroid Build Coastguard Worker {
24*f6dc9357SAndroid Build Coastguard Worker const DWORD res = ::GetLastError();
25*f6dc9357SAndroid Build Coastguard Worker if (res == 0)
26*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
27*f6dc9357SAndroid Build Coastguard Worker return HRESULT_FROM_WIN32(res);
28*f6dc9357SAndroid Build Coastguard Worker }
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
33*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
34*f6dc9357SAndroid Build Coastguard Worker #endif
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
37*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
38*f6dc9357SAndroid Build Coastguard Worker using namespace NName;
39*f6dc9357SAndroid Build Coastguard Worker
40*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
41*f6dc9357SAndroid Build Coastguard Worker namespace NFile {
42*f6dc9357SAndroid Build Coastguard Worker
43*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
44*f6dc9357SAndroid Build Coastguard Worker
45*f6dc9357SAndroid Build Coastguard Worker namespace NSystem
46*f6dc9357SAndroid Build Coastguard Worker {
47*f6dc9357SAndroid Build Coastguard Worker bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);
48*f6dc9357SAndroid Build Coastguard Worker }
49*f6dc9357SAndroid Build Coastguard Worker #endif
50*f6dc9357SAndroid Build Coastguard Worker
51*f6dc9357SAndroid Build Coastguard Worker namespace NIO {
52*f6dc9357SAndroid Build Coastguard Worker
53*f6dc9357SAndroid Build Coastguard Worker /*
54*f6dc9357SAndroid Build Coastguard Worker WinXP-64 CreateFile():
55*f6dc9357SAndroid Build Coastguard Worker "" - ERROR_PATH_NOT_FOUND
56*f6dc9357SAndroid Build Coastguard Worker :stream - OK
57*f6dc9357SAndroid Build Coastguard Worker .:stream - ERROR_PATH_NOT_FOUND
58*f6dc9357SAndroid Build Coastguard Worker .\:stream - OK
59*f6dc9357SAndroid Build Coastguard Worker
60*f6dc9357SAndroid Build Coastguard Worker folder\:stream - ERROR_INVALID_NAME
61*f6dc9357SAndroid Build Coastguard Worker folder:stream - OK
62*f6dc9357SAndroid Build Coastguard Worker
63*f6dc9357SAndroid Build Coastguard Worker c:\:stream - OK
64*f6dc9357SAndroid Build Coastguard Worker
65*f6dc9357SAndroid Build Coastguard Worker c::stream - ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\dir1 )
66*f6dc9357SAndroid Build Coastguard Worker c::stream - OK, if current dir is ROOT ( c:\ )
67*f6dc9357SAndroid Build Coastguard Worker */
68*f6dc9357SAndroid Build Coastguard Worker
Create(CFSTR path,DWORD desiredAccess,DWORD shareMode,DWORD creationDisposition,DWORD flagsAndAttributes)69*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::Create(CFSTR path, DWORD desiredAccess,
70*f6dc9357SAndroid Build Coastguard Worker DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
71*f6dc9357SAndroid Build Coastguard Worker {
72*f6dc9357SAndroid Build Coastguard Worker if (!Close())
73*f6dc9357SAndroid Build Coastguard Worker return false;
74*f6dc9357SAndroid Build Coastguard Worker
75*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
76*f6dc9357SAndroid Build Coastguard Worker IsDeviceFile = false;
77*f6dc9357SAndroid Build Coastguard Worker #endif
78*f6dc9357SAndroid Build Coastguard Worker
79*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
80*f6dc9357SAndroid Build Coastguard Worker if (!g_IsNT)
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode,
83*f6dc9357SAndroid Build Coastguard Worker (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
84*f6dc9357SAndroid Build Coastguard Worker }
85*f6dc9357SAndroid Build Coastguard Worker else
86*f6dc9357SAndroid Build Coastguard Worker #endif
87*f6dc9357SAndroid Build Coastguard Worker {
88*f6dc9357SAndroid Build Coastguard Worker IF_USE_MAIN_PATH
89*f6dc9357SAndroid Build Coastguard Worker _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode,
90*f6dc9357SAndroid Build Coastguard Worker (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
91*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LONG_PATH
92*f6dc9357SAndroid Build Coastguard Worker if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
93*f6dc9357SAndroid Build Coastguard Worker {
94*f6dc9357SAndroid Build Coastguard Worker UString superPath;
95*f6dc9357SAndroid Build Coastguard Worker if (GetSuperPath(path, superPath, USE_MAIN_PATH))
96*f6dc9357SAndroid Build Coastguard Worker _handle = ::CreateFileW(superPath, desiredAccess, shareMode,
97*f6dc9357SAndroid Build Coastguard Worker (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);
98*f6dc9357SAndroid Build Coastguard Worker }
99*f6dc9357SAndroid Build Coastguard Worker #endif
100*f6dc9357SAndroid Build Coastguard Worker }
101*f6dc9357SAndroid Build Coastguard Worker
102*f6dc9357SAndroid Build Coastguard Worker /*
103*f6dc9357SAndroid Build Coastguard Worker #ifndef UNDER_CE
104*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_SFX
105*f6dc9357SAndroid Build Coastguard Worker if (_handle == INVALID_HANDLE_VALUE)
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker // it's debug hack to open symbolic links in Windows XP and WSL links in Windows 10
108*f6dc9357SAndroid Build Coastguard Worker DWORD lastError = GetLastError();
109*f6dc9357SAndroid Build Coastguard Worker if (lastError == ERROR_CANT_ACCESS_FILE)
110*f6dc9357SAndroid Build Coastguard Worker {
111*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buf;
112*f6dc9357SAndroid Build Coastguard Worker if (NIO::GetReparseData(path, buf, NULL))
113*f6dc9357SAndroid Build Coastguard Worker {
114*f6dc9357SAndroid Build Coastguard Worker CReparseAttr attr;
115*f6dc9357SAndroid Build Coastguard Worker if (attr.Parse(buf, buf.Size()))
116*f6dc9357SAndroid Build Coastguard Worker {
117*f6dc9357SAndroid Build Coastguard Worker FString dirPrefix, fileName;
118*f6dc9357SAndroid Build Coastguard Worker if (NDir::GetFullPathAndSplit(path, dirPrefix, fileName))
119*f6dc9357SAndroid Build Coastguard Worker {
120*f6dc9357SAndroid Build Coastguard Worker FString fullPath;
121*f6dc9357SAndroid Build Coastguard Worker if (GetFullPath(dirPrefix, us2fs(attr.GetPath()), fullPath))
122*f6dc9357SAndroid Build Coastguard Worker {
123*f6dc9357SAndroid Build Coastguard Worker // FIX IT: recursion levels must be restricted
124*f6dc9357SAndroid Build Coastguard Worker return Create(fullPath, desiredAccess,
125*f6dc9357SAndroid Build Coastguard Worker shareMode, creationDisposition, flagsAndAttributes);
126*f6dc9357SAndroid Build Coastguard Worker }
127*f6dc9357SAndroid Build Coastguard Worker }
128*f6dc9357SAndroid Build Coastguard Worker }
129*f6dc9357SAndroid Build Coastguard Worker }
130*f6dc9357SAndroid Build Coastguard Worker SetLastError(lastError);
131*f6dc9357SAndroid Build Coastguard Worker }
132*f6dc9357SAndroid Build Coastguard Worker }
133*f6dc9357SAndroid Build Coastguard Worker #endif
134*f6dc9357SAndroid Build Coastguard Worker #endif
135*f6dc9357SAndroid Build Coastguard Worker */
136*f6dc9357SAndroid Build Coastguard Worker
137*f6dc9357SAndroid Build Coastguard Worker return (_handle != INVALID_HANDLE_VALUE);
138*f6dc9357SAndroid Build Coastguard Worker }
139*f6dc9357SAndroid Build Coastguard Worker
Close()140*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::Close() throw()
141*f6dc9357SAndroid Build Coastguard Worker {
142*f6dc9357SAndroid Build Coastguard Worker if (_handle == INVALID_HANDLE_VALUE)
143*f6dc9357SAndroid Build Coastguard Worker return true;
144*f6dc9357SAndroid Build Coastguard Worker #if 0
145*f6dc9357SAndroid Build Coastguard Worker if (!IsStdStream)
146*f6dc9357SAndroid Build Coastguard Worker #endif
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker if (!::CloseHandle(_handle))
149*f6dc9357SAndroid Build Coastguard Worker return false;
150*f6dc9357SAndroid Build Coastguard Worker }
151*f6dc9357SAndroid Build Coastguard Worker #if 0
152*f6dc9357SAndroid Build Coastguard Worker IsStdStream = false;
153*f6dc9357SAndroid Build Coastguard Worker IsStdPipeStream = false;
154*f6dc9357SAndroid Build Coastguard Worker #endif
155*f6dc9357SAndroid Build Coastguard Worker _handle = INVALID_HANDLE_VALUE;
156*f6dc9357SAndroid Build Coastguard Worker return true;
157*f6dc9357SAndroid Build Coastguard Worker }
158*f6dc9357SAndroid Build Coastguard Worker
GetLength(UInt64 & length) const159*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::GetLength(UInt64 &length) const throw()
160*f6dc9357SAndroid Build Coastguard Worker {
161*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
162*f6dc9357SAndroid Build Coastguard Worker if (IsDeviceFile && SizeDefined)
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker length = Size;
165*f6dc9357SAndroid Build Coastguard Worker return true;
166*f6dc9357SAndroid Build Coastguard Worker }
167*f6dc9357SAndroid Build Coastguard Worker #endif
168*f6dc9357SAndroid Build Coastguard Worker
169*f6dc9357SAndroid Build Coastguard Worker DWORD high = 0;
170*f6dc9357SAndroid Build Coastguard Worker const DWORD low = ::GetFileSize(_handle, &high);
171*f6dc9357SAndroid Build Coastguard Worker if (low == INVALID_FILE_SIZE)
172*f6dc9357SAndroid Build Coastguard Worker if (::GetLastError() != NO_ERROR)
173*f6dc9357SAndroid Build Coastguard Worker return false;
174*f6dc9357SAndroid Build Coastguard Worker length = (((UInt64)high) << 32) + low;
175*f6dc9357SAndroid Build Coastguard Worker return true;
176*f6dc9357SAndroid Build Coastguard Worker
177*f6dc9357SAndroid Build Coastguard Worker /*
178*f6dc9357SAndroid Build Coastguard Worker LARGE_INTEGER fileSize;
179*f6dc9357SAndroid Build Coastguard Worker // GetFileSizeEx() is unsupported in 98/ME/NT, and supported in Win2000+
180*f6dc9357SAndroid Build Coastguard Worker if (!GetFileSizeEx(_handle, &fileSize))
181*f6dc9357SAndroid Build Coastguard Worker return false;
182*f6dc9357SAndroid Build Coastguard Worker length = (UInt64)fileSize.QuadPart;
183*f6dc9357SAndroid Build Coastguard Worker return true;
184*f6dc9357SAndroid Build Coastguard Worker */
185*f6dc9357SAndroid Build Coastguard Worker }
186*f6dc9357SAndroid Build Coastguard Worker
187*f6dc9357SAndroid Build Coastguard Worker
188*f6dc9357SAndroid Build Coastguard Worker /* Specification for SetFilePointer():
189*f6dc9357SAndroid Build Coastguard Worker
190*f6dc9357SAndroid Build Coastguard Worker If a new file pointer is a negative value,
191*f6dc9357SAndroid Build Coastguard Worker {
192*f6dc9357SAndroid Build Coastguard Worker the function fails,
193*f6dc9357SAndroid Build Coastguard Worker the file pointer is not moved,
194*f6dc9357SAndroid Build Coastguard Worker the code returned by GetLastError() is ERROR_NEGATIVE_SEEK.
195*f6dc9357SAndroid Build Coastguard Worker }
196*f6dc9357SAndroid Build Coastguard Worker
197*f6dc9357SAndroid Build Coastguard Worker If the hFile handle is opened with the FILE_FLAG_NO_BUFFERING flag set
198*f6dc9357SAndroid Build Coastguard Worker {
199*f6dc9357SAndroid Build Coastguard Worker an application can move the file pointer only to sector-aligned positions.
200*f6dc9357SAndroid Build Coastguard Worker A sector-aligned position is a position that is a whole number multiple of
201*f6dc9357SAndroid Build Coastguard Worker the volume sector size.
202*f6dc9357SAndroid Build Coastguard Worker An application can obtain a volume sector size by calling the GetDiskFreeSpace.
203*f6dc9357SAndroid Build Coastguard Worker }
204*f6dc9357SAndroid Build Coastguard Worker
205*f6dc9357SAndroid Build Coastguard Worker It is not an error to set a file pointer to a position beyond the end of the file.
206*f6dc9357SAndroid Build Coastguard Worker The size of the file does not increase until you call the SetEndOfFile, WriteFile, or WriteFileEx function.
207*f6dc9357SAndroid Build Coastguard Worker
208*f6dc9357SAndroid Build Coastguard Worker If the return value is INVALID_SET_FILE_POINTER and if lpDistanceToMoveHigh is non-NULL,
209*f6dc9357SAndroid Build Coastguard Worker an application must call GetLastError to determine whether or not the function has succeeded or failed.
210*f6dc9357SAndroid Build Coastguard Worker */
211*f6dc9357SAndroid Build Coastguard Worker
GetPosition(UInt64 & position) const212*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::GetPosition(UInt64 &position) const throw()
213*f6dc9357SAndroid Build Coastguard Worker {
214*f6dc9357SAndroid Build Coastguard Worker LONG high = 0;
215*f6dc9357SAndroid Build Coastguard Worker const DWORD low = ::SetFilePointer(_handle, 0, &high, FILE_CURRENT);
216*f6dc9357SAndroid Build Coastguard Worker if (low == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
217*f6dc9357SAndroid Build Coastguard Worker {
218*f6dc9357SAndroid Build Coastguard Worker // for error case we can set (position) to (-1) or (0) or leave (position) unchanged.
219*f6dc9357SAndroid Build Coastguard Worker // position = (UInt64)(Int64)-1; // for debug
220*f6dc9357SAndroid Build Coastguard Worker position = 0;
221*f6dc9357SAndroid Build Coastguard Worker return false;
222*f6dc9357SAndroid Build Coastguard Worker }
223*f6dc9357SAndroid Build Coastguard Worker position = (((UInt64)(UInt32)high) << 32) + low;
224*f6dc9357SAndroid Build Coastguard Worker return true;
225*f6dc9357SAndroid Build Coastguard Worker // we don't want recursed GetPosition()
226*f6dc9357SAndroid Build Coastguard Worker // return Seek(0, FILE_CURRENT, position);
227*f6dc9357SAndroid Build Coastguard Worker }
228*f6dc9357SAndroid Build Coastguard Worker
Seek(Int64 distanceToMove,DWORD moveMethod,UInt64 & newPosition) const229*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw()
230*f6dc9357SAndroid Build Coastguard Worker {
231*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
232*f6dc9357SAndroid Build Coastguard Worker if (IsDeviceFile && SizeDefined && moveMethod == FILE_END)
233*f6dc9357SAndroid Build Coastguard Worker {
234*f6dc9357SAndroid Build Coastguard Worker distanceToMove += Size;
235*f6dc9357SAndroid Build Coastguard Worker moveMethod = FILE_BEGIN;
236*f6dc9357SAndroid Build Coastguard Worker }
237*f6dc9357SAndroid Build Coastguard Worker #endif
238*f6dc9357SAndroid Build Coastguard Worker
239*f6dc9357SAndroid Build Coastguard Worker LONG high = (LONG)(distanceToMove >> 32);
240*f6dc9357SAndroid Build Coastguard Worker const DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod);
241*f6dc9357SAndroid Build Coastguard Worker if (low == INVALID_SET_FILE_POINTER)
242*f6dc9357SAndroid Build Coastguard Worker {
243*f6dc9357SAndroid Build Coastguard Worker const DWORD lastError = ::GetLastError();
244*f6dc9357SAndroid Build Coastguard Worker if (lastError != NO_ERROR)
245*f6dc9357SAndroid Build Coastguard Worker {
246*f6dc9357SAndroid Build Coastguard Worker // 21.07: we set (newPosition) to real position even after error.
247*f6dc9357SAndroid Build Coastguard Worker GetPosition(newPosition);
248*f6dc9357SAndroid Build Coastguard Worker SetLastError(lastError); // restore LastError
249*f6dc9357SAndroid Build Coastguard Worker return false;
250*f6dc9357SAndroid Build Coastguard Worker }
251*f6dc9357SAndroid Build Coastguard Worker }
252*f6dc9357SAndroid Build Coastguard Worker newPosition = (((UInt64)(UInt32)high) << 32) + low;
253*f6dc9357SAndroid Build Coastguard Worker return true;
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker
Seek(UInt64 position,UInt64 & newPosition) const256*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw()
257*f6dc9357SAndroid Build Coastguard Worker {
258*f6dc9357SAndroid Build Coastguard Worker return Seek((Int64)position, FILE_BEGIN, newPosition);
259*f6dc9357SAndroid Build Coastguard Worker }
260*f6dc9357SAndroid Build Coastguard Worker
SeekToBegin() const261*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::SeekToBegin() const throw()
262*f6dc9357SAndroid Build Coastguard Worker {
263*f6dc9357SAndroid Build Coastguard Worker UInt64 newPosition = 0;
264*f6dc9357SAndroid Build Coastguard Worker return Seek(0, newPosition) && (newPosition == 0);
265*f6dc9357SAndroid Build Coastguard Worker }
266*f6dc9357SAndroid Build Coastguard Worker
SeekToEnd(UInt64 & newPosition) const267*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::SeekToEnd(UInt64 &newPosition) const throw()
268*f6dc9357SAndroid Build Coastguard Worker {
269*f6dc9357SAndroid Build Coastguard Worker return Seek(0, FILE_END, newPosition);
270*f6dc9357SAndroid Build Coastguard Worker }
271*f6dc9357SAndroid Build Coastguard Worker
272*f6dc9357SAndroid Build Coastguard Worker // ---------- CInFile ---------
273*f6dc9357SAndroid Build Coastguard Worker
274*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_DEVICE_FILE
275*f6dc9357SAndroid Build Coastguard Worker
CorrectDeviceSize()276*f6dc9357SAndroid Build Coastguard Worker void CInFile::CorrectDeviceSize()
277*f6dc9357SAndroid Build Coastguard Worker {
278*f6dc9357SAndroid Build Coastguard Worker // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail
279*f6dc9357SAndroid Build Coastguard Worker const UInt32 kClusterSize = 1 << 14;
280*f6dc9357SAndroid Build Coastguard Worker UInt64 pos = Size & ~(UInt64)(kClusterSize - 1);
281*f6dc9357SAndroid Build Coastguard Worker UInt64 realNewPosition;
282*f6dc9357SAndroid Build Coastguard Worker if (!Seek(pos, realNewPosition))
283*f6dc9357SAndroid Build Coastguard Worker return;
284*f6dc9357SAndroid Build Coastguard Worker Byte *buf = (Byte *)MidAlloc(kClusterSize);
285*f6dc9357SAndroid Build Coastguard Worker
286*f6dc9357SAndroid Build Coastguard Worker bool needbackward = true;
287*f6dc9357SAndroid Build Coastguard Worker
288*f6dc9357SAndroid Build Coastguard Worker for (;;)
289*f6dc9357SAndroid Build Coastguard Worker {
290*f6dc9357SAndroid Build Coastguard Worker UInt32 processed = 0;
291*f6dc9357SAndroid Build Coastguard Worker // up test is slow for "PhysicalDrive".
292*f6dc9357SAndroid Build Coastguard Worker // processed size for latest block for "PhysicalDrive0" is 0.
293*f6dc9357SAndroid Build Coastguard Worker if (!Read1(buf, kClusterSize, processed))
294*f6dc9357SAndroid Build Coastguard Worker break;
295*f6dc9357SAndroid Build Coastguard Worker if (processed == 0)
296*f6dc9357SAndroid Build Coastguard Worker break;
297*f6dc9357SAndroid Build Coastguard Worker needbackward = false;
298*f6dc9357SAndroid Build Coastguard Worker Size = pos + processed;
299*f6dc9357SAndroid Build Coastguard Worker if (processed != kClusterSize)
300*f6dc9357SAndroid Build Coastguard Worker break;
301*f6dc9357SAndroid Build Coastguard Worker pos += kClusterSize;
302*f6dc9357SAndroid Build Coastguard Worker }
303*f6dc9357SAndroid Build Coastguard Worker
304*f6dc9357SAndroid Build Coastguard Worker if (needbackward && pos != 0)
305*f6dc9357SAndroid Build Coastguard Worker {
306*f6dc9357SAndroid Build Coastguard Worker pos -= kClusterSize;
307*f6dc9357SAndroid Build Coastguard Worker for (;;)
308*f6dc9357SAndroid Build Coastguard Worker {
309*f6dc9357SAndroid Build Coastguard Worker // break;
310*f6dc9357SAndroid Build Coastguard Worker if (!Seek(pos, realNewPosition))
311*f6dc9357SAndroid Build Coastguard Worker break;
312*f6dc9357SAndroid Build Coastguard Worker if (!buf)
313*f6dc9357SAndroid Build Coastguard Worker {
314*f6dc9357SAndroid Build Coastguard Worker buf = (Byte *)MidAlloc(kClusterSize);
315*f6dc9357SAndroid Build Coastguard Worker if (!buf)
316*f6dc9357SAndroid Build Coastguard Worker break;
317*f6dc9357SAndroid Build Coastguard Worker }
318*f6dc9357SAndroid Build Coastguard Worker UInt32 processed = 0;
319*f6dc9357SAndroid Build Coastguard Worker // that code doesn't work for "PhysicalDrive0"
320*f6dc9357SAndroid Build Coastguard Worker if (!Read1(buf, kClusterSize, processed))
321*f6dc9357SAndroid Build Coastguard Worker break;
322*f6dc9357SAndroid Build Coastguard Worker if (processed != 0)
323*f6dc9357SAndroid Build Coastguard Worker {
324*f6dc9357SAndroid Build Coastguard Worker Size = pos + processed;
325*f6dc9357SAndroid Build Coastguard Worker break;
326*f6dc9357SAndroid Build Coastguard Worker }
327*f6dc9357SAndroid Build Coastguard Worker if (pos == 0)
328*f6dc9357SAndroid Build Coastguard Worker break;
329*f6dc9357SAndroid Build Coastguard Worker pos -= kClusterSize;
330*f6dc9357SAndroid Build Coastguard Worker }
331*f6dc9357SAndroid Build Coastguard Worker }
332*f6dc9357SAndroid Build Coastguard Worker MidFree(buf);
333*f6dc9357SAndroid Build Coastguard Worker }
334*f6dc9357SAndroid Build Coastguard Worker
335*f6dc9357SAndroid Build Coastguard Worker
CalcDeviceSize(CFSTR s)336*f6dc9357SAndroid Build Coastguard Worker void CInFile::CalcDeviceSize(CFSTR s)
337*f6dc9357SAndroid Build Coastguard Worker {
338*f6dc9357SAndroid Build Coastguard Worker SizeDefined = false;
339*f6dc9357SAndroid Build Coastguard Worker Size = 0;
340*f6dc9357SAndroid Build Coastguard Worker if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile)
341*f6dc9357SAndroid Build Coastguard Worker return;
342*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
343*f6dc9357SAndroid Build Coastguard Worker
344*f6dc9357SAndroid Build Coastguard Worker SizeDefined = true;
345*f6dc9357SAndroid Build Coastguard Worker Size = 128 << 20;
346*f6dc9357SAndroid Build Coastguard Worker
347*f6dc9357SAndroid Build Coastguard Worker #else
348*f6dc9357SAndroid Build Coastguard Worker
349*f6dc9357SAndroid Build Coastguard Worker PARTITION_INFORMATION partInfo;
350*f6dc9357SAndroid Build Coastguard Worker bool needCorrectSize = true;
351*f6dc9357SAndroid Build Coastguard Worker
352*f6dc9357SAndroid Build Coastguard Worker /*
353*f6dc9357SAndroid Build Coastguard Worker WinXP 64-bit:
354*f6dc9357SAndroid Build Coastguard Worker
355*f6dc9357SAndroid Build Coastguard Worker HDD \\.\PhysicalDrive0 (MBR):
356*f6dc9357SAndroid Build Coastguard Worker GetPartitionInfo == GeometryEx : corrrect size? (includes tail)
357*f6dc9357SAndroid Build Coastguard Worker Geometry : smaller than GeometryEx (no tail, maybe correct too?)
358*f6dc9357SAndroid Build Coastguard Worker MyGetDiskFreeSpace : FAIL
359*f6dc9357SAndroid Build Coastguard Worker Size correction is slow and block size (kClusterSize) must be small?
360*f6dc9357SAndroid Build Coastguard Worker
361*f6dc9357SAndroid Build Coastguard Worker HDD partition \\.\N: (NTFS):
362*f6dc9357SAndroid Build Coastguard Worker MyGetDiskFreeSpace : Size of NTFS clusters. Same size can be calculated after correction
363*f6dc9357SAndroid Build Coastguard Worker GetPartitionInfo : size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS
364*f6dc9357SAndroid Build Coastguard Worker Geometry / CdRomGeometry / GeometryEx : size of HDD (not that partition)
365*f6dc9357SAndroid Build Coastguard Worker
366*f6dc9357SAndroid Build Coastguard Worker CD-ROM drive (ISO):
367*f6dc9357SAndroid Build Coastguard Worker MyGetDiskFreeSpace : correct size. Same size can be calculated after correction
368*f6dc9357SAndroid Build Coastguard Worker Geometry == CdRomGeometry : smaller than corrrect size
369*f6dc9357SAndroid Build Coastguard Worker GetPartitionInfo == GeometryEx : larger than corrrect size
370*f6dc9357SAndroid Build Coastguard Worker
371*f6dc9357SAndroid Build Coastguard Worker Floppy \\.\a: (FAT):
372*f6dc9357SAndroid Build Coastguard Worker Geometry : correct size.
373*f6dc9357SAndroid Build Coastguard Worker CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL
374*f6dc9357SAndroid Build Coastguard Worker correction works OK for FAT.
375*f6dc9357SAndroid Build Coastguard Worker correction works OK for non-FAT, if kClusterSize = 512.
376*f6dc9357SAndroid Build Coastguard Worker */
377*f6dc9357SAndroid Build Coastguard Worker
378*f6dc9357SAndroid Build Coastguard Worker if (GetPartitionInfo(&partInfo))
379*f6dc9357SAndroid Build Coastguard Worker {
380*f6dc9357SAndroid Build Coastguard Worker Size = (UInt64)partInfo.PartitionLength.QuadPart;
381*f6dc9357SAndroid Build Coastguard Worker SizeDefined = true;
382*f6dc9357SAndroid Build Coastguard Worker needCorrectSize = false;
383*f6dc9357SAndroid Build Coastguard Worker if ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\' && (s)[5] == ':' && (s)[6] == 0)
384*f6dc9357SAndroid Build Coastguard Worker {
385*f6dc9357SAndroid Build Coastguard Worker FChar path[4] = { s[4], ':', '\\', 0 };
386*f6dc9357SAndroid Build Coastguard Worker UInt64 clusterSize, totalSize, freeSize;
387*f6dc9357SAndroid Build Coastguard Worker if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize))
388*f6dc9357SAndroid Build Coastguard Worker Size = totalSize;
389*f6dc9357SAndroid Build Coastguard Worker else
390*f6dc9357SAndroid Build Coastguard Worker needCorrectSize = true;
391*f6dc9357SAndroid Build Coastguard Worker }
392*f6dc9357SAndroid Build Coastguard Worker }
393*f6dc9357SAndroid Build Coastguard Worker
394*f6dc9357SAndroid Build Coastguard Worker if (!SizeDefined)
395*f6dc9357SAndroid Build Coastguard Worker {
396*f6dc9357SAndroid Build Coastguard Worker my_DISK_GEOMETRY_EX geomEx;
397*f6dc9357SAndroid Build Coastguard Worker SizeDefined = GetGeometryEx(&geomEx);
398*f6dc9357SAndroid Build Coastguard Worker if (SizeDefined)
399*f6dc9357SAndroid Build Coastguard Worker Size = (UInt64)geomEx.DiskSize.QuadPart;
400*f6dc9357SAndroid Build Coastguard Worker else
401*f6dc9357SAndroid Build Coastguard Worker {
402*f6dc9357SAndroid Build Coastguard Worker DISK_GEOMETRY geom;
403*f6dc9357SAndroid Build Coastguard Worker SizeDefined = GetGeometry(&geom);
404*f6dc9357SAndroid Build Coastguard Worker if (!SizeDefined)
405*f6dc9357SAndroid Build Coastguard Worker SizeDefined = GetCdRomGeometry(&geom);
406*f6dc9357SAndroid Build Coastguard Worker if (SizeDefined)
407*f6dc9357SAndroid Build Coastguard Worker Size = (UInt64)geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;
408*f6dc9357SAndroid Build Coastguard Worker }
409*f6dc9357SAndroid Build Coastguard Worker }
410*f6dc9357SAndroid Build Coastguard Worker
411*f6dc9357SAndroid Build Coastguard Worker if (needCorrectSize && SizeDefined && Size != 0)
412*f6dc9357SAndroid Build Coastguard Worker {
413*f6dc9357SAndroid Build Coastguard Worker CorrectDeviceSize();
414*f6dc9357SAndroid Build Coastguard Worker SeekToBegin();
415*f6dc9357SAndroid Build Coastguard Worker }
416*f6dc9357SAndroid Build Coastguard Worker
417*f6dc9357SAndroid Build Coastguard Worker // SeekToBegin();
418*f6dc9357SAndroid Build Coastguard Worker #endif
419*f6dc9357SAndroid Build Coastguard Worker }
420*f6dc9357SAndroid Build Coastguard Worker
421*f6dc9357SAndroid Build Coastguard Worker // ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 &&
422*f6dc9357SAndroid Build Coastguard Worker
423*f6dc9357SAndroid Build Coastguard Worker #define MY_DEVICE_EXTRA_CODE \
424*f6dc9357SAndroid Build Coastguard Worker IsDeviceFile = IsDevicePath(fileName); \
425*f6dc9357SAndroid Build Coastguard Worker CalcDeviceSize(fileName);
426*f6dc9357SAndroid Build Coastguard Worker #else
427*f6dc9357SAndroid Build Coastguard Worker #define MY_DEVICE_EXTRA_CODE
428*f6dc9357SAndroid Build Coastguard Worker #endif
429*f6dc9357SAndroid Build Coastguard Worker
Open(CFSTR fileName,DWORD shareMode,DWORD creationDisposition,DWORD flagsAndAttributes)430*f6dc9357SAndroid Build Coastguard Worker bool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
431*f6dc9357SAndroid Build Coastguard Worker {
432*f6dc9357SAndroid Build Coastguard Worker DWORD desiredAccess = GENERIC_READ;
433*f6dc9357SAndroid Build Coastguard Worker
434*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
435*f6dc9357SAndroid Build Coastguard Worker if (PreserveATime)
436*f6dc9357SAndroid Build Coastguard Worker desiredAccess |= FILE_WRITE_ATTRIBUTES;
437*f6dc9357SAndroid Build Coastguard Worker #endif
438*f6dc9357SAndroid Build Coastguard Worker
439*f6dc9357SAndroid Build Coastguard Worker bool res = Create(fileName, desiredAccess, shareMode, creationDisposition, flagsAndAttributes);
440*f6dc9357SAndroid Build Coastguard Worker
441*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
442*f6dc9357SAndroid Build Coastguard Worker if (res && PreserveATime)
443*f6dc9357SAndroid Build Coastguard Worker {
444*f6dc9357SAndroid Build Coastguard Worker FILETIME ft;
445*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = ft.dwLowDateTime = 0xFFFFFFFF;
446*f6dc9357SAndroid Build Coastguard Worker ::SetFileTime(_handle, NULL, &ft, NULL);
447*f6dc9357SAndroid Build Coastguard Worker }
448*f6dc9357SAndroid Build Coastguard Worker #endif
449*f6dc9357SAndroid Build Coastguard Worker
450*f6dc9357SAndroid Build Coastguard Worker MY_DEVICE_EXTRA_CODE
451*f6dc9357SAndroid Build Coastguard Worker return res;
452*f6dc9357SAndroid Build Coastguard Worker }
453*f6dc9357SAndroid Build Coastguard Worker
OpenShared(CFSTR fileName,bool shareForWrite)454*f6dc9357SAndroid Build Coastguard Worker bool CInFile::OpenShared(CFSTR fileName, bool shareForWrite)
455*f6dc9357SAndroid Build Coastguard Worker { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }
456*f6dc9357SAndroid Build Coastguard Worker
Open(CFSTR fileName)457*f6dc9357SAndroid Build Coastguard Worker bool CInFile::Open(CFSTR fileName)
458*f6dc9357SAndroid Build Coastguard Worker { return OpenShared(fileName, false); }
459*f6dc9357SAndroid Build Coastguard Worker
460*f6dc9357SAndroid Build Coastguard Worker // ReadFile and WriteFile functions in Windows have BUG:
461*f6dc9357SAndroid Build Coastguard Worker // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
462*f6dc9357SAndroid Build Coastguard Worker // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
463*f6dc9357SAndroid Build Coastguard Worker // (Insufficient system resources exist to complete the requested service).
464*f6dc9357SAndroid Build Coastguard Worker
465*f6dc9357SAndroid Build Coastguard Worker // Probably in some version of Windows there are problems with other sizes:
466*f6dc9357SAndroid Build Coastguard Worker // for 32 MB (maybe also for 16 MB).
467*f6dc9357SAndroid Build Coastguard Worker // And message can be "Network connection was lost"
468*f6dc9357SAndroid Build Coastguard Worker
469*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kChunkSizeMax = 1 << 22;
470*f6dc9357SAndroid Build Coastguard Worker
Read1(void * data,UInt32 size,UInt32 & processedSize)471*f6dc9357SAndroid Build Coastguard Worker bool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw()
472*f6dc9357SAndroid Build Coastguard Worker {
473*f6dc9357SAndroid Build Coastguard Worker DWORD processedLoc = 0;
474*f6dc9357SAndroid Build Coastguard Worker const bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL));
475*f6dc9357SAndroid Build Coastguard Worker processedSize = (UInt32)processedLoc;
476*f6dc9357SAndroid Build Coastguard Worker return res;
477*f6dc9357SAndroid Build Coastguard Worker }
478*f6dc9357SAndroid Build Coastguard Worker
ReadPart(void * data,UInt32 size,UInt32 & processedSize)479*f6dc9357SAndroid Build Coastguard Worker bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw()
480*f6dc9357SAndroid Build Coastguard Worker {
481*f6dc9357SAndroid Build Coastguard Worker #if 0
482*f6dc9357SAndroid Build Coastguard Worker const UInt32 chunkSizeMax = (0 || IsStdStream) ? (1 << 20) : kChunkSizeMax;
483*f6dc9357SAndroid Build Coastguard Worker if (size > chunkSizeMax)
484*f6dc9357SAndroid Build Coastguard Worker size = chunkSizeMax;
485*f6dc9357SAndroid Build Coastguard Worker #else
486*f6dc9357SAndroid Build Coastguard Worker if (size > kChunkSizeMax)
487*f6dc9357SAndroid Build Coastguard Worker size = kChunkSizeMax;
488*f6dc9357SAndroid Build Coastguard Worker #endif
489*f6dc9357SAndroid Build Coastguard Worker return Read1(data, size, processedSize);
490*f6dc9357SAndroid Build Coastguard Worker }
491*f6dc9357SAndroid Build Coastguard Worker
Read(void * data,UInt32 size,UInt32 & processedSize)492*f6dc9357SAndroid Build Coastguard Worker bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw()
493*f6dc9357SAndroid Build Coastguard Worker {
494*f6dc9357SAndroid Build Coastguard Worker processedSize = 0;
495*f6dc9357SAndroid Build Coastguard Worker do
496*f6dc9357SAndroid Build Coastguard Worker {
497*f6dc9357SAndroid Build Coastguard Worker UInt32 processedLoc = 0;
498*f6dc9357SAndroid Build Coastguard Worker const bool res = ReadPart(data, size, processedLoc);
499*f6dc9357SAndroid Build Coastguard Worker processedSize += processedLoc;
500*f6dc9357SAndroid Build Coastguard Worker if (!res)
501*f6dc9357SAndroid Build Coastguard Worker return false;
502*f6dc9357SAndroid Build Coastguard Worker if (processedLoc == 0)
503*f6dc9357SAndroid Build Coastguard Worker return true;
504*f6dc9357SAndroid Build Coastguard Worker data = (void *)((Byte *)data + processedLoc);
505*f6dc9357SAndroid Build Coastguard Worker size -= processedLoc;
506*f6dc9357SAndroid Build Coastguard Worker }
507*f6dc9357SAndroid Build Coastguard Worker while (size);
508*f6dc9357SAndroid Build Coastguard Worker return true;
509*f6dc9357SAndroid Build Coastguard Worker }
510*f6dc9357SAndroid Build Coastguard Worker
ReadFull(void * data,size_t size,size_t & processedSize)511*f6dc9357SAndroid Build Coastguard Worker bool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw()
512*f6dc9357SAndroid Build Coastguard Worker {
513*f6dc9357SAndroid Build Coastguard Worker processedSize = 0;
514*f6dc9357SAndroid Build Coastguard Worker do
515*f6dc9357SAndroid Build Coastguard Worker {
516*f6dc9357SAndroid Build Coastguard Worker UInt32 processedLoc = 0;
517*f6dc9357SAndroid Build Coastguard Worker const UInt32 sizeLoc = (size > kChunkSizeMax ? (UInt32)kChunkSizeMax : (UInt32)size);
518*f6dc9357SAndroid Build Coastguard Worker const bool res = Read1(data, sizeLoc, processedLoc);
519*f6dc9357SAndroid Build Coastguard Worker processedSize += processedLoc;
520*f6dc9357SAndroid Build Coastguard Worker if (!res)
521*f6dc9357SAndroid Build Coastguard Worker return false;
522*f6dc9357SAndroid Build Coastguard Worker if (processedLoc == 0)
523*f6dc9357SAndroid Build Coastguard Worker return true;
524*f6dc9357SAndroid Build Coastguard Worker data = (void *)((Byte *)data + processedLoc);
525*f6dc9357SAndroid Build Coastguard Worker size -= processedLoc;
526*f6dc9357SAndroid Build Coastguard Worker }
527*f6dc9357SAndroid Build Coastguard Worker while (size);
528*f6dc9357SAndroid Build Coastguard Worker return true;
529*f6dc9357SAndroid Build Coastguard Worker }
530*f6dc9357SAndroid Build Coastguard Worker
531*f6dc9357SAndroid Build Coastguard Worker // ---------- COutFile ---------
532*f6dc9357SAndroid Build Coastguard Worker
Open(CFSTR fileName,DWORD shareMode,DWORD creationDisposition,DWORD flagsAndAttributes)533*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
534*f6dc9357SAndroid Build Coastguard Worker { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }
535*f6dc9357SAndroid Build Coastguard Worker
Open_Disposition(CFSTR fileName,DWORD creationDisposition)536*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Open_Disposition(CFSTR fileName, DWORD creationDisposition)
537*f6dc9357SAndroid Build Coastguard Worker { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }
538*f6dc9357SAndroid Build Coastguard Worker
Create_ALWAYS_with_Attribs(CFSTR fileName,DWORD flagsAndAttributes)539*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes)
540*f6dc9357SAndroid Build Coastguard Worker { return Open(fileName, FILE_SHARE_READ, CREATE_ALWAYS, flagsAndAttributes); }
541*f6dc9357SAndroid Build Coastguard Worker
SetTime(const FILETIME * cTime,const FILETIME * aTime,const FILETIME * mTime)542*f6dc9357SAndroid Build Coastguard Worker bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw()
543*f6dc9357SAndroid Build Coastguard Worker { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }
544*f6dc9357SAndroid Build Coastguard Worker
SetMTime(const FILETIME * mTime)545*f6dc9357SAndroid Build Coastguard Worker bool COutFile::SetMTime(const FILETIME *mTime) throw() { return SetTime(NULL, NULL, mTime); }
546*f6dc9357SAndroid Build Coastguard Worker
WritePart(const void * data,UInt32 size,UInt32 & processedSize)547*f6dc9357SAndroid Build Coastguard Worker bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw()
548*f6dc9357SAndroid Build Coastguard Worker {
549*f6dc9357SAndroid Build Coastguard Worker if (size > kChunkSizeMax)
550*f6dc9357SAndroid Build Coastguard Worker size = kChunkSizeMax;
551*f6dc9357SAndroid Build Coastguard Worker DWORD processedLoc = 0;
552*f6dc9357SAndroid Build Coastguard Worker bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL));
553*f6dc9357SAndroid Build Coastguard Worker processedSize = (UInt32)processedLoc;
554*f6dc9357SAndroid Build Coastguard Worker return res;
555*f6dc9357SAndroid Build Coastguard Worker }
556*f6dc9357SAndroid Build Coastguard Worker
Write(const void * data,UInt32 size,UInt32 & processedSize)557*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw()
558*f6dc9357SAndroid Build Coastguard Worker {
559*f6dc9357SAndroid Build Coastguard Worker processedSize = 0;
560*f6dc9357SAndroid Build Coastguard Worker do
561*f6dc9357SAndroid Build Coastguard Worker {
562*f6dc9357SAndroid Build Coastguard Worker UInt32 processedLoc = 0;
563*f6dc9357SAndroid Build Coastguard Worker const bool res = WritePart(data, size, processedLoc);
564*f6dc9357SAndroid Build Coastguard Worker processedSize += processedLoc;
565*f6dc9357SAndroid Build Coastguard Worker if (!res)
566*f6dc9357SAndroid Build Coastguard Worker return false;
567*f6dc9357SAndroid Build Coastguard Worker if (processedLoc == 0)
568*f6dc9357SAndroid Build Coastguard Worker return true;
569*f6dc9357SAndroid Build Coastguard Worker data = (const void *)((const Byte *)data + processedLoc);
570*f6dc9357SAndroid Build Coastguard Worker size -= processedLoc;
571*f6dc9357SAndroid Build Coastguard Worker }
572*f6dc9357SAndroid Build Coastguard Worker while (size);
573*f6dc9357SAndroid Build Coastguard Worker return true;
574*f6dc9357SAndroid Build Coastguard Worker }
575*f6dc9357SAndroid Build Coastguard Worker
WriteFull(const void * data,size_t size)576*f6dc9357SAndroid Build Coastguard Worker bool COutFile::WriteFull(const void *data, size_t size) throw()
577*f6dc9357SAndroid Build Coastguard Worker {
578*f6dc9357SAndroid Build Coastguard Worker do
579*f6dc9357SAndroid Build Coastguard Worker {
580*f6dc9357SAndroid Build Coastguard Worker UInt32 processedLoc = 0;
581*f6dc9357SAndroid Build Coastguard Worker const UInt32 sizeCur = (size > kChunkSizeMax ? kChunkSizeMax : (UInt32)size);
582*f6dc9357SAndroid Build Coastguard Worker if (!WritePart(data, sizeCur, processedLoc))
583*f6dc9357SAndroid Build Coastguard Worker return false;
584*f6dc9357SAndroid Build Coastguard Worker if (processedLoc == 0)
585*f6dc9357SAndroid Build Coastguard Worker return (size == 0);
586*f6dc9357SAndroid Build Coastguard Worker data = (const void *)((const Byte *)data + processedLoc);
587*f6dc9357SAndroid Build Coastguard Worker size -= processedLoc;
588*f6dc9357SAndroid Build Coastguard Worker }
589*f6dc9357SAndroid Build Coastguard Worker while (size);
590*f6dc9357SAndroid Build Coastguard Worker return true;
591*f6dc9357SAndroid Build Coastguard Worker }
592*f6dc9357SAndroid Build Coastguard Worker
SetEndOfFile()593*f6dc9357SAndroid Build Coastguard Worker bool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); }
594*f6dc9357SAndroid Build Coastguard Worker
SetLength(UInt64 length)595*f6dc9357SAndroid Build Coastguard Worker bool COutFile::SetLength(UInt64 length) throw()
596*f6dc9357SAndroid Build Coastguard Worker {
597*f6dc9357SAndroid Build Coastguard Worker UInt64 newPosition;
598*f6dc9357SAndroid Build Coastguard Worker if (!Seek(length, newPosition))
599*f6dc9357SAndroid Build Coastguard Worker return false;
600*f6dc9357SAndroid Build Coastguard Worker if (newPosition != length)
601*f6dc9357SAndroid Build Coastguard Worker return false;
602*f6dc9357SAndroid Build Coastguard Worker return SetEndOfFile();
603*f6dc9357SAndroid Build Coastguard Worker }
604*f6dc9357SAndroid Build Coastguard Worker
SetLength_KeepPosition(UInt64 length)605*f6dc9357SAndroid Build Coastguard Worker bool COutFile::SetLength_KeepPosition(UInt64 length) throw()
606*f6dc9357SAndroid Build Coastguard Worker {
607*f6dc9357SAndroid Build Coastguard Worker UInt64 currentPos = 0;
608*f6dc9357SAndroid Build Coastguard Worker if (!GetPosition(currentPos))
609*f6dc9357SAndroid Build Coastguard Worker return false;
610*f6dc9357SAndroid Build Coastguard Worker DWORD lastError = 0;
611*f6dc9357SAndroid Build Coastguard Worker const bool result = SetLength(length);
612*f6dc9357SAndroid Build Coastguard Worker if (!result)
613*f6dc9357SAndroid Build Coastguard Worker lastError = GetLastError();
614*f6dc9357SAndroid Build Coastguard Worker UInt64 currentPos2;
615*f6dc9357SAndroid Build Coastguard Worker const bool result2 = Seek(currentPos, currentPos2);
616*f6dc9357SAndroid Build Coastguard Worker if (lastError != 0)
617*f6dc9357SAndroid Build Coastguard Worker SetLastError(lastError);
618*f6dc9357SAndroid Build Coastguard Worker return (result && result2);
619*f6dc9357SAndroid Build Coastguard Worker }
620*f6dc9357SAndroid Build Coastguard Worker
621*f6dc9357SAndroid Build Coastguard Worker }}}
622*f6dc9357SAndroid Build Coastguard Worker
623*f6dc9357SAndroid Build Coastguard Worker #else // _WIN32
624*f6dc9357SAndroid Build Coastguard Worker
625*f6dc9357SAndroid Build Coastguard Worker
626*f6dc9357SAndroid Build Coastguard Worker // POSIX
627*f6dc9357SAndroid Build Coastguard Worker
628*f6dc9357SAndroid Build Coastguard Worker #include <fcntl.h>
629*f6dc9357SAndroid Build Coastguard Worker #include <unistd.h>
630*f6dc9357SAndroid Build Coastguard Worker
631*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
632*f6dc9357SAndroid Build Coastguard Worker namespace NFile {
633*f6dc9357SAndroid Build Coastguard Worker
634*f6dc9357SAndroid Build Coastguard Worker namespace NDir {
635*f6dc9357SAndroid Build Coastguard Worker bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);
636*f6dc9357SAndroid Build Coastguard Worker }
637*f6dc9357SAndroid Build Coastguard Worker
638*f6dc9357SAndroid Build Coastguard Worker namespace NIO {
639*f6dc9357SAndroid Build Coastguard Worker
OpenBinary(const char * name,int flags,mode_t mode)640*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::OpenBinary(const char *name, int flags, mode_t mode)
641*f6dc9357SAndroid Build Coastguard Worker {
642*f6dc9357SAndroid Build Coastguard Worker #ifdef O_BINARY
643*f6dc9357SAndroid Build Coastguard Worker flags |= O_BINARY;
644*f6dc9357SAndroid Build Coastguard Worker #endif
645*f6dc9357SAndroid Build Coastguard Worker
646*f6dc9357SAndroid Build Coastguard Worker Close();
647*f6dc9357SAndroid Build Coastguard Worker _handle = ::open(name, flags, mode);
648*f6dc9357SAndroid Build Coastguard Worker return _handle != -1;
649*f6dc9357SAndroid Build Coastguard Worker
650*f6dc9357SAndroid Build Coastguard Worker /*
651*f6dc9357SAndroid Build Coastguard Worker if (_handle == -1)
652*f6dc9357SAndroid Build Coastguard Worker return false;
653*f6dc9357SAndroid Build Coastguard Worker if (IsString1PrefixedByString2(name, "/dev/"))
654*f6dc9357SAndroid Build Coastguard Worker {
655*f6dc9357SAndroid Build Coastguard Worker // /dev/sda
656*f6dc9357SAndroid Build Coastguard Worker // IsDeviceFile = true; // for debug
657*f6dc9357SAndroid Build Coastguard Worker // SizeDefined = false;
658*f6dc9357SAndroid Build Coastguard Worker // SizeDefined = (GetDeviceSize_InBytes(Size) == 0);
659*f6dc9357SAndroid Build Coastguard Worker }
660*f6dc9357SAndroid Build Coastguard Worker return true;
661*f6dc9357SAndroid Build Coastguard Worker */
662*f6dc9357SAndroid Build Coastguard Worker }
663*f6dc9357SAndroid Build Coastguard Worker
Close()664*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::Close()
665*f6dc9357SAndroid Build Coastguard Worker {
666*f6dc9357SAndroid Build Coastguard Worker if (_handle == -1)
667*f6dc9357SAndroid Build Coastguard Worker return true;
668*f6dc9357SAndroid Build Coastguard Worker if (close(_handle) != 0)
669*f6dc9357SAndroid Build Coastguard Worker return false;
670*f6dc9357SAndroid Build Coastguard Worker _handle = -1;
671*f6dc9357SAndroid Build Coastguard Worker /*
672*f6dc9357SAndroid Build Coastguard Worker IsDeviceFile = false;
673*f6dc9357SAndroid Build Coastguard Worker SizeDefined = false;
674*f6dc9357SAndroid Build Coastguard Worker */
675*f6dc9357SAndroid Build Coastguard Worker return true;
676*f6dc9357SAndroid Build Coastguard Worker }
677*f6dc9357SAndroid Build Coastguard Worker
GetLength(UInt64 & length) const678*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::GetLength(UInt64 &length) const
679*f6dc9357SAndroid Build Coastguard Worker {
680*f6dc9357SAndroid Build Coastguard Worker length = 0;
681*f6dc9357SAndroid Build Coastguard Worker // length = (UInt64)(Int64)-1; // for debug
682*f6dc9357SAndroid Build Coastguard Worker const off_t curPos = seekToCur();
683*f6dc9357SAndroid Build Coastguard Worker if (curPos == -1)
684*f6dc9357SAndroid Build Coastguard Worker return false;
685*f6dc9357SAndroid Build Coastguard Worker const off_t lengthTemp = seek(0, SEEK_END);
686*f6dc9357SAndroid Build Coastguard Worker seek(curPos, SEEK_SET);
687*f6dc9357SAndroid Build Coastguard Worker length = (UInt64)lengthTemp;
688*f6dc9357SAndroid Build Coastguard Worker
689*f6dc9357SAndroid Build Coastguard Worker /*
690*f6dc9357SAndroid Build Coastguard Worker // 22.00:
691*f6dc9357SAndroid Build Coastguard Worker if (lengthTemp == 1)
692*f6dc9357SAndroid Build Coastguard Worker if (IsDeviceFile && SizeDefined)
693*f6dc9357SAndroid Build Coastguard Worker {
694*f6dc9357SAndroid Build Coastguard Worker length = Size;
695*f6dc9357SAndroid Build Coastguard Worker return true;
696*f6dc9357SAndroid Build Coastguard Worker }
697*f6dc9357SAndroid Build Coastguard Worker */
698*f6dc9357SAndroid Build Coastguard Worker
699*f6dc9357SAndroid Build Coastguard Worker return (lengthTemp != -1);
700*f6dc9357SAndroid Build Coastguard Worker }
701*f6dc9357SAndroid Build Coastguard Worker
seek(off_t distanceToMove,int moveMethod) const702*f6dc9357SAndroid Build Coastguard Worker off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const
703*f6dc9357SAndroid Build Coastguard Worker {
704*f6dc9357SAndroid Build Coastguard Worker /*
705*f6dc9357SAndroid Build Coastguard Worker if (IsDeviceFile && SizeDefined && moveMethod == SEEK_END)
706*f6dc9357SAndroid Build Coastguard Worker {
707*f6dc9357SAndroid Build Coastguard Worker printf("\n seek : IsDeviceFile moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove);
708*f6dc9357SAndroid Build Coastguard Worker distanceToMove += Size;
709*f6dc9357SAndroid Build Coastguard Worker moveMethod = SEEK_SET;
710*f6dc9357SAndroid Build Coastguard Worker }
711*f6dc9357SAndroid Build Coastguard Worker */
712*f6dc9357SAndroid Build Coastguard Worker
713*f6dc9357SAndroid Build Coastguard Worker // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove);
714*f6dc9357SAndroid Build Coastguard Worker // off_t res = ::lseek(_handle, distanceToMove, moveMethod);
715*f6dc9357SAndroid Build Coastguard Worker // printf("\n lseek : moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove);
716*f6dc9357SAndroid Build Coastguard Worker return ::lseek(_handle, distanceToMove, moveMethod);
717*f6dc9357SAndroid Build Coastguard Worker // return res;
718*f6dc9357SAndroid Build Coastguard Worker }
719*f6dc9357SAndroid Build Coastguard Worker
seekToBegin() const720*f6dc9357SAndroid Build Coastguard Worker off_t CFileBase::seekToBegin() const throw()
721*f6dc9357SAndroid Build Coastguard Worker {
722*f6dc9357SAndroid Build Coastguard Worker return seek(0, SEEK_SET);
723*f6dc9357SAndroid Build Coastguard Worker }
724*f6dc9357SAndroid Build Coastguard Worker
seekToCur() const725*f6dc9357SAndroid Build Coastguard Worker off_t CFileBase::seekToCur() const throw()
726*f6dc9357SAndroid Build Coastguard Worker {
727*f6dc9357SAndroid Build Coastguard Worker return seek(0, SEEK_CUR);
728*f6dc9357SAndroid Build Coastguard Worker }
729*f6dc9357SAndroid Build Coastguard Worker
730*f6dc9357SAndroid Build Coastguard Worker /*
731*f6dc9357SAndroid Build Coastguard Worker bool CFileBase::SeekToBegin() const throw()
732*f6dc9357SAndroid Build Coastguard Worker {
733*f6dc9357SAndroid Build Coastguard Worker return (::seek(0, SEEK_SET) != -1);
734*f6dc9357SAndroid Build Coastguard Worker }
735*f6dc9357SAndroid Build Coastguard Worker */
736*f6dc9357SAndroid Build Coastguard Worker
737*f6dc9357SAndroid Build Coastguard Worker
738*f6dc9357SAndroid Build Coastguard Worker /////////////////////////
739*f6dc9357SAndroid Build Coastguard Worker // CInFile
740*f6dc9357SAndroid Build Coastguard Worker
Open(const char * name)741*f6dc9357SAndroid Build Coastguard Worker bool CInFile::Open(const char *name)
742*f6dc9357SAndroid Build Coastguard Worker {
743*f6dc9357SAndroid Build Coastguard Worker return CFileBase::OpenBinary(name, O_RDONLY);
744*f6dc9357SAndroid Build Coastguard Worker }
745*f6dc9357SAndroid Build Coastguard Worker
OpenShared(const char * name,bool)746*f6dc9357SAndroid Build Coastguard Worker bool CInFile::OpenShared(const char *name, bool)
747*f6dc9357SAndroid Build Coastguard Worker {
748*f6dc9357SAndroid Build Coastguard Worker return Open(name);
749*f6dc9357SAndroid Build Coastguard Worker }
750*f6dc9357SAndroid Build Coastguard Worker
751*f6dc9357SAndroid Build Coastguard Worker
752*f6dc9357SAndroid Build Coastguard Worker /*
753*f6dc9357SAndroid Build Coastguard Worker int CFileBase::my_ioctl_BLKGETSIZE64(unsigned long long *numBlocks)
754*f6dc9357SAndroid Build Coastguard Worker {
755*f6dc9357SAndroid Build Coastguard Worker // we can read "/sys/block/sda/size" "/sys/block/sda/sda1/size" - partition
756*f6dc9357SAndroid Build Coastguard Worker // #include <linux/fs.h>
757*f6dc9357SAndroid Build Coastguard Worker return ioctl(_handle, BLKGETSIZE64, numBlocks);
758*f6dc9357SAndroid Build Coastguard Worker // in block size
759*f6dc9357SAndroid Build Coastguard Worker }
760*f6dc9357SAndroid Build Coastguard Worker
761*f6dc9357SAndroid Build Coastguard Worker int CFileBase::GetDeviceSize_InBytes(UInt64 &size)
762*f6dc9357SAndroid Build Coastguard Worker {
763*f6dc9357SAndroid Build Coastguard Worker size = 0;
764*f6dc9357SAndroid Build Coastguard Worker unsigned long long numBlocks;
765*f6dc9357SAndroid Build Coastguard Worker int res = my_ioctl_BLKGETSIZE64(&numBlocks);
766*f6dc9357SAndroid Build Coastguard Worker if (res == 0)
767*f6dc9357SAndroid Build Coastguard Worker size = numBlocks; // another blockSize s possible?
768*f6dc9357SAndroid Build Coastguard Worker printf("\nGetDeviceSize_InBytes res = %d, size = %lld\n", res, (long long)size);
769*f6dc9357SAndroid Build Coastguard Worker return res;
770*f6dc9357SAndroid Build Coastguard Worker }
771*f6dc9357SAndroid Build Coastguard Worker */
772*f6dc9357SAndroid Build Coastguard Worker
773*f6dc9357SAndroid Build Coastguard Worker /*
774*f6dc9357SAndroid Build Coastguard Worker On Linux (32-bit and 64-bit):
775*f6dc9357SAndroid Build Coastguard Worker read(), write() (and similar system calls) will transfer at most
776*f6dc9357SAndroid Build Coastguard Worker 0x7ffff000 = (2GiB - 4 KiB) bytes, returning the number of bytes actually transferred.
777*f6dc9357SAndroid Build Coastguard Worker */
778*f6dc9357SAndroid Build Coastguard Worker
779*f6dc9357SAndroid Build Coastguard Worker static const size_t kChunkSizeMax = ((size_t)1 << 22);
780*f6dc9357SAndroid Build Coastguard Worker
read_part(void * data,size_t size)781*f6dc9357SAndroid Build Coastguard Worker ssize_t CInFile::read_part(void *data, size_t size) throw()
782*f6dc9357SAndroid Build Coastguard Worker {
783*f6dc9357SAndroid Build Coastguard Worker if (size > kChunkSizeMax)
784*f6dc9357SAndroid Build Coastguard Worker size = kChunkSizeMax;
785*f6dc9357SAndroid Build Coastguard Worker return ::read(_handle, data, size);
786*f6dc9357SAndroid Build Coastguard Worker }
787*f6dc9357SAndroid Build Coastguard Worker
ReadFull(void * data,size_t size,size_t & processed)788*f6dc9357SAndroid Build Coastguard Worker bool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw()
789*f6dc9357SAndroid Build Coastguard Worker {
790*f6dc9357SAndroid Build Coastguard Worker processed = 0;
791*f6dc9357SAndroid Build Coastguard Worker do
792*f6dc9357SAndroid Build Coastguard Worker {
793*f6dc9357SAndroid Build Coastguard Worker const ssize_t res = read_part(data, size);
794*f6dc9357SAndroid Build Coastguard Worker if (res < 0)
795*f6dc9357SAndroid Build Coastguard Worker return false;
796*f6dc9357SAndroid Build Coastguard Worker if (res == 0)
797*f6dc9357SAndroid Build Coastguard Worker break;
798*f6dc9357SAndroid Build Coastguard Worker data = (void *)((Byte *)data + (size_t)res);
799*f6dc9357SAndroid Build Coastguard Worker processed += (size_t)res;
800*f6dc9357SAndroid Build Coastguard Worker size -= (size_t)res;
801*f6dc9357SAndroid Build Coastguard Worker }
802*f6dc9357SAndroid Build Coastguard Worker while (size);
803*f6dc9357SAndroid Build Coastguard Worker return true;
804*f6dc9357SAndroid Build Coastguard Worker }
805*f6dc9357SAndroid Build Coastguard Worker
806*f6dc9357SAndroid Build Coastguard Worker
807*f6dc9357SAndroid Build Coastguard Worker /////////////////////////
808*f6dc9357SAndroid Build Coastguard Worker // COutFile
809*f6dc9357SAndroid Build Coastguard Worker
OpenBinary_forWrite_oflag(const char * name,int oflag)810*f6dc9357SAndroid Build Coastguard Worker bool COutFile::OpenBinary_forWrite_oflag(const char *name, int oflag)
811*f6dc9357SAndroid Build Coastguard Worker {
812*f6dc9357SAndroid Build Coastguard Worker Path = name; // change it : set it only if open is success.
813*f6dc9357SAndroid Build Coastguard Worker return OpenBinary(name, oflag, mode_for_Create);
814*f6dc9357SAndroid Build Coastguard Worker }
815*f6dc9357SAndroid Build Coastguard Worker
816*f6dc9357SAndroid Build Coastguard Worker
817*f6dc9357SAndroid Build Coastguard Worker /*
818*f6dc9357SAndroid Build Coastguard Worker windows exist non-exist posix
819*f6dc9357SAndroid Build Coastguard Worker CREATE_NEW Fail Create O_CREAT | O_EXCL
820*f6dc9357SAndroid Build Coastguard Worker CREATE_ALWAYS Trunc Create O_CREAT | O_TRUNC
821*f6dc9357SAndroid Build Coastguard Worker OPEN_ALWAYS Open Create O_CREAT
822*f6dc9357SAndroid Build Coastguard Worker OPEN_EXISTING Open Fail 0
823*f6dc9357SAndroid Build Coastguard Worker TRUNCATE_EXISTING Trunc Fail O_TRUNC ???
824*f6dc9357SAndroid Build Coastguard Worker
825*f6dc9357SAndroid Build Coastguard Worker // O_CREAT = If the file exists, this flag has no effect except as noted under O_EXCL below.
826*f6dc9357SAndroid Build Coastguard Worker // If O_CREAT and O_EXCL are set, open() shall fail if the file exists.
827*f6dc9357SAndroid Build Coastguard Worker // O_TRUNC : If the file exists and the file is successfully opened, its length shall be truncated to 0.
828*f6dc9357SAndroid Build Coastguard Worker */
Open_EXISTING(const char * name)829*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Open_EXISTING(const char *name)
830*f6dc9357SAndroid Build Coastguard Worker { return OpenBinary_forWrite_oflag(name, O_WRONLY); }
Create_ALWAYS(const char * name)831*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Create_ALWAYS(const char *name)
832*f6dc9357SAndroid Build Coastguard Worker { return OpenBinary_forWrite_oflag(name, O_WRONLY | O_CREAT | O_TRUNC); }
Create_NEW(const char * name)833*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Create_NEW(const char *name)
834*f6dc9357SAndroid Build Coastguard Worker { return OpenBinary_forWrite_oflag(name, O_WRONLY | O_CREAT | O_EXCL); }
Create_ALWAYS_or_Open_ALWAYS(const char * name,bool createAlways)835*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Create_ALWAYS_or_Open_ALWAYS(const char *name, bool createAlways)
836*f6dc9357SAndroid Build Coastguard Worker {
837*f6dc9357SAndroid Build Coastguard Worker return OpenBinary_forWrite_oflag(name,
838*f6dc9357SAndroid Build Coastguard Worker createAlways ?
839*f6dc9357SAndroid Build Coastguard Worker O_WRONLY | O_CREAT | O_TRUNC :
840*f6dc9357SAndroid Build Coastguard Worker O_WRONLY | O_CREAT);
841*f6dc9357SAndroid Build Coastguard Worker }
842*f6dc9357SAndroid Build Coastguard Worker /*
843*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Create_ALWAYS_or_NEW(const char *name, bool createAlways)
844*f6dc9357SAndroid Build Coastguard Worker {
845*f6dc9357SAndroid Build Coastguard Worker return OpenBinary_forWrite_oflag(name,
846*f6dc9357SAndroid Build Coastguard Worker createAlways ?
847*f6dc9357SAndroid Build Coastguard Worker O_WRONLY | O_CREAT | O_TRUNC :
848*f6dc9357SAndroid Build Coastguard Worker O_WRONLY | O_CREAT | O_EXCL);
849*f6dc9357SAndroid Build Coastguard Worker }
850*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Open_Disposition(const char *name, DWORD creationDisposition)
851*f6dc9357SAndroid Build Coastguard Worker {
852*f6dc9357SAndroid Build Coastguard Worker int flag;
853*f6dc9357SAndroid Build Coastguard Worker switch (creationDisposition)
854*f6dc9357SAndroid Build Coastguard Worker {
855*f6dc9357SAndroid Build Coastguard Worker case CREATE_NEW: flag = O_WRONLY | O_CREAT | O_EXCL; break;
856*f6dc9357SAndroid Build Coastguard Worker case CREATE_ALWAYS: flag = O_WRONLY | O_CREAT | O_TRUNC; break;
857*f6dc9357SAndroid Build Coastguard Worker case OPEN_ALWAYS: flag = O_WRONLY | O_CREAT; break;
858*f6dc9357SAndroid Build Coastguard Worker case OPEN_EXISTING: flag = O_WRONLY; break;
859*f6dc9357SAndroid Build Coastguard Worker case TRUNCATE_EXISTING: flag = O_WRONLY | O_TRUNC; break;
860*f6dc9357SAndroid Build Coastguard Worker default:
861*f6dc9357SAndroid Build Coastguard Worker SetLastError(EINVAL);
862*f6dc9357SAndroid Build Coastguard Worker return false;
863*f6dc9357SAndroid Build Coastguard Worker }
864*f6dc9357SAndroid Build Coastguard Worker return OpenBinary_forWrite_oflag(name, flag);
865*f6dc9357SAndroid Build Coastguard Worker }
866*f6dc9357SAndroid Build Coastguard Worker */
867*f6dc9357SAndroid Build Coastguard Worker
write_part(const void * data,size_t size)868*f6dc9357SAndroid Build Coastguard Worker ssize_t COutFile::write_part(const void *data, size_t size) throw()
869*f6dc9357SAndroid Build Coastguard Worker {
870*f6dc9357SAndroid Build Coastguard Worker if (size > kChunkSizeMax)
871*f6dc9357SAndroid Build Coastguard Worker size = kChunkSizeMax;
872*f6dc9357SAndroid Build Coastguard Worker return ::write(_handle, data, size);
873*f6dc9357SAndroid Build Coastguard Worker }
874*f6dc9357SAndroid Build Coastguard Worker
write_full(const void * data,size_t size,size_t & processed)875*f6dc9357SAndroid Build Coastguard Worker ssize_t COutFile::write_full(const void *data, size_t size, size_t &processed) throw()
876*f6dc9357SAndroid Build Coastguard Worker {
877*f6dc9357SAndroid Build Coastguard Worker processed = 0;
878*f6dc9357SAndroid Build Coastguard Worker do
879*f6dc9357SAndroid Build Coastguard Worker {
880*f6dc9357SAndroid Build Coastguard Worker const ssize_t res = write_part(data, size);
881*f6dc9357SAndroid Build Coastguard Worker if (res < 0)
882*f6dc9357SAndroid Build Coastguard Worker return res;
883*f6dc9357SAndroid Build Coastguard Worker if (res == 0)
884*f6dc9357SAndroid Build Coastguard Worker break;
885*f6dc9357SAndroid Build Coastguard Worker data = (const void *)((const Byte *)data + (size_t)res);
886*f6dc9357SAndroid Build Coastguard Worker processed += (size_t)res;
887*f6dc9357SAndroid Build Coastguard Worker size -= (size_t)res;
888*f6dc9357SAndroid Build Coastguard Worker }
889*f6dc9357SAndroid Build Coastguard Worker while (size);
890*f6dc9357SAndroid Build Coastguard Worker return (ssize_t)processed;
891*f6dc9357SAndroid Build Coastguard Worker }
892*f6dc9357SAndroid Build Coastguard Worker
SetLength(UInt64 length)893*f6dc9357SAndroid Build Coastguard Worker bool COutFile::SetLength(UInt64 length) throw()
894*f6dc9357SAndroid Build Coastguard Worker {
895*f6dc9357SAndroid Build Coastguard Worker const off_t len2 = (off_t)length;
896*f6dc9357SAndroid Build Coastguard Worker if ((Int64)length != len2)
897*f6dc9357SAndroid Build Coastguard Worker {
898*f6dc9357SAndroid Build Coastguard Worker SetLastError(EFBIG);
899*f6dc9357SAndroid Build Coastguard Worker return false;
900*f6dc9357SAndroid Build Coastguard Worker }
901*f6dc9357SAndroid Build Coastguard Worker // The value of the seek pointer shall not be modified by a call to ftruncate().
902*f6dc9357SAndroid Build Coastguard Worker const int iret = ftruncate(_handle, len2);
903*f6dc9357SAndroid Build Coastguard Worker return (iret == 0);
904*f6dc9357SAndroid Build Coastguard Worker }
905*f6dc9357SAndroid Build Coastguard Worker
Close()906*f6dc9357SAndroid Build Coastguard Worker bool COutFile::Close()
907*f6dc9357SAndroid Build Coastguard Worker {
908*f6dc9357SAndroid Build Coastguard Worker const bool res = CFileBase::Close();
909*f6dc9357SAndroid Build Coastguard Worker if (!res)
910*f6dc9357SAndroid Build Coastguard Worker return res;
911*f6dc9357SAndroid Build Coastguard Worker if (CTime_defined || ATime_defined || MTime_defined)
912*f6dc9357SAndroid Build Coastguard Worker {
913*f6dc9357SAndroid Build Coastguard Worker /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path,
914*f6dc9357SAndroid Build Coastguard Worker CTime_defined ? &CTime : NULL,
915*f6dc9357SAndroid Build Coastguard Worker ATime_defined ? &ATime : NULL,
916*f6dc9357SAndroid Build Coastguard Worker MTime_defined ? &MTime : NULL);
917*f6dc9357SAndroid Build Coastguard Worker }
918*f6dc9357SAndroid Build Coastguard Worker return res;
919*f6dc9357SAndroid Build Coastguard Worker }
920*f6dc9357SAndroid Build Coastguard Worker
SetTime(const CFiTime * cTime,const CFiTime * aTime,const CFiTime * mTime)921*f6dc9357SAndroid Build Coastguard Worker bool COutFile::SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw()
922*f6dc9357SAndroid Build Coastguard Worker {
923*f6dc9357SAndroid Build Coastguard Worker // On some OS (cygwin, MacOSX ...), you must close the file before updating times
924*f6dc9357SAndroid Build Coastguard Worker // return true;
925*f6dc9357SAndroid Build Coastguard Worker
926*f6dc9357SAndroid Build Coastguard Worker if (cTime) { CTime = *cTime; CTime_defined = true; } else CTime_defined = false;
927*f6dc9357SAndroid Build Coastguard Worker if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false;
928*f6dc9357SAndroid Build Coastguard Worker if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
929*f6dc9357SAndroid Build Coastguard Worker return true;
930*f6dc9357SAndroid Build Coastguard Worker
931*f6dc9357SAndroid Build Coastguard Worker /*
932*f6dc9357SAndroid Build Coastguard Worker struct timespec times[2];
933*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(cTime)
934*f6dc9357SAndroid Build Coastguard Worker if (!aTime && !mTime)
935*f6dc9357SAndroid Build Coastguard Worker return true;
936*f6dc9357SAndroid Build Coastguard Worker bool needChange;
937*f6dc9357SAndroid Build Coastguard Worker needChange = FiTime_To_timespec(aTime, times[0]);
938*f6dc9357SAndroid Build Coastguard Worker needChange |= FiTime_To_timespec(mTime, times[1]);
939*f6dc9357SAndroid Build Coastguard Worker if (!needChange)
940*f6dc9357SAndroid Build Coastguard Worker return true;
941*f6dc9357SAndroid Build Coastguard Worker return futimens(_handle, times) == 0;
942*f6dc9357SAndroid Build Coastguard Worker */
943*f6dc9357SAndroid Build Coastguard Worker }
944*f6dc9357SAndroid Build Coastguard Worker
SetMTime(const CFiTime * mTime)945*f6dc9357SAndroid Build Coastguard Worker bool COutFile::SetMTime(const CFiTime *mTime) throw()
946*f6dc9357SAndroid Build Coastguard Worker {
947*f6dc9357SAndroid Build Coastguard Worker if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
948*f6dc9357SAndroid Build Coastguard Worker return true;
949*f6dc9357SAndroid Build Coastguard Worker }
950*f6dc9357SAndroid Build Coastguard Worker
951*f6dc9357SAndroid Build Coastguard Worker }}}
952*f6dc9357SAndroid Build Coastguard Worker
953*f6dc9357SAndroid Build Coastguard Worker
954*f6dc9357SAndroid Build Coastguard Worker #endif
955