11 #ifdef SUPPORT_DEVICE_FILE
\r
12 #include "../../../C/Alloc.h"
\r
13 #include "../../Common/Defs.h"
\r
16 #include "FileStreams.h"
\r
18 static inline HRESULT ConvertBoolToHRESULT(bool result)
\r
23 DWORD lastError = ::GetLastError();
\r
26 return HRESULT_FROM_WIN32(lastError);
\r
28 return result ? S_OK: E_FAIL;
\r
32 bool CInFileStream::Open(LPCTSTR fileName)
\r
34 return File.Open(fileName);
\r
39 bool CInFileStream::Open(LPCWSTR fileName)
\r
41 return File.Open(fileName);
\r
46 bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite)
\r
48 return File.OpenShared(fileName, shareForWrite);
\r
53 bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite)
\r
55 return File.OpenShared(fileName, shareForWrite);
\r
60 #ifdef SUPPORT_DEVICE_FILE
\r
62 static const UInt32 kClusterSize = 1 << 18;
\r
63 CInFileStream::CInFileStream():
\r
73 CInFileStream::~CInFileStream()
\r
75 #ifdef SUPPORT_DEVICE_FILE
\r
80 STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
\r
84 #ifdef SUPPORT_DEVICE_FILE
\r
85 if (processedSize != NULL)
\r
89 if (File.IsDeviceFile)
\r
91 if (File.LengthDefined)
\r
93 if (VirtPos >= File.Length)
\r
94 return VirtPos == File.Length ? S_OK : E_FAIL;
\r
95 UInt64 rem = File.Length - VirtPos;
\r
101 const UInt32 mask = kClusterSize - 1;
\r
102 UInt64 mask2 = ~(UInt64)mask;
\r
103 UInt64 alignedPos = VirtPos & mask2;
\r
104 if (BufferSize > 0 && BufferStartPos == alignedPos)
\r
106 UInt32 pos = (UInt32)VirtPos & mask;
\r
107 if (pos >= BufferSize)
\r
109 UInt32 rem = MyMin(BufferSize - pos, size);
\r
110 memcpy(data, Buffer + pos, rem);
\r
112 if (processedSize != NULL)
\r
113 *processedSize += rem;
\r
117 bool useBuffer = false;
\r
118 if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )
\r
122 UInt64 end = VirtPos + size;
\r
123 if ((end & mask) != 0)
\r
126 if (end <= VirtPos)
\r
129 size = (UInt32)(end - VirtPos);
\r
134 if (alignedPos != PhyPos)
\r
136 UInt64 realNewPosition;
\r
137 bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition);
\r
139 return ConvertBoolToHRESULT(result);
\r
140 PhyPos = realNewPosition;
\r
143 BufferStartPos = alignedPos;
\r
144 UInt32 readSize = kClusterSize;
\r
145 if (File.LengthDefined)
\r
146 readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize);
\r
150 Buffer = (Byte *)MidAlloc(kClusterSize);
\r
152 return E_OUTOFMEMORY;
\r
154 bool result = File.Read1(Buffer, readSize, BufferSize);
\r
156 return ConvertBoolToHRESULT(result);
\r
158 if (BufferSize == 0)
\r
160 PhyPos += BufferSize;
\r
163 if (VirtPos != PhyPos)
\r
165 UInt64 realNewPosition;
\r
166 bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition);
\r
168 return ConvertBoolToHRESULT(result);
\r
169 PhyPos = VirtPos = realNewPosition;
\r
174 UInt32 realProcessedSize;
\r
175 bool result = File.ReadPart(data, size, realProcessedSize);
\r
176 if (processedSize != NULL)
\r
177 *processedSize = realProcessedSize;
\r
178 #ifdef SUPPORT_DEVICE_FILE
\r
179 VirtPos += realProcessedSize;
\r
180 PhyPos += realProcessedSize;
\r
182 return ConvertBoolToHRESULT(result);
\r
186 if (processedSize != NULL)
\r
187 *processedSize = 0;
\r
188 ssize_t res = File.Read(data, (size_t)size);
\r
191 if (processedSize != NULL)
\r
192 *processedSize = (UInt32)res;
\r
199 STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
\r
201 size_t s2 = fread(data, 1, size, stdout);
\r
202 if (processedSize != 0)
\r
203 *processedSize = s2;
\r
204 return (s2 = size) ? S_OK : E_FAIL;
\r
207 STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
\r
211 DWORD realProcessedSize;
\r
212 UInt32 sizeTemp = (1 << 20);
\r
213 if (sizeTemp > size)
\r
215 BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);
\r
216 if (processedSize != NULL)
\r
217 *processedSize = realProcessedSize;
\r
218 if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
\r
220 return ConvertBoolToHRESULT(res != FALSE);
\r
224 if (processedSize != NULL)
\r
225 *processedSize = 0;
\r
229 res = read(0, data, (size_t)size);
\r
231 while (res < 0 && (errno == EINTR));
\r
234 if (processedSize != NULL)
\r
235 *processedSize = (UInt32)res;
\r
243 STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,
\r
244 UInt64 *newPosition)
\r
246 if (seekOrigin >= 3)
\r
247 return STG_E_INVALIDFUNCTION;
\r
249 #ifdef USE_WIN_FILE
\r
251 #ifdef SUPPORT_DEVICE_FILE
\r
252 if (File.IsDeviceFile)
\r
254 UInt64 newVirtPos = offset;
\r
257 case STREAM_SEEK_SET: break;
\r
258 case STREAM_SEEK_CUR: newVirtPos += VirtPos; break;
\r
259 case STREAM_SEEK_END: newVirtPos += File.Length; break;
\r
260 default: return STG_E_INVALIDFUNCTION;
\r
262 VirtPos = newVirtPos;
\r
264 *newPosition = newVirtPos;
\r
269 UInt64 realNewPosition;
\r
270 bool result = File.Seek(offset, seekOrigin, realNewPosition);
\r
272 #ifdef SUPPORT_DEVICE_FILE
\r
273 PhyPos = VirtPos = realNewPosition;
\r
276 if (newPosition != NULL)
\r
277 *newPosition = realNewPosition;
\r
278 return ConvertBoolToHRESULT(result);
\r
282 off_t res = File.Seek(offset, seekOrigin);
\r
285 if (newPosition != NULL)
\r
286 *newPosition = (UInt64)res;
\r
292 STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
\r
294 return ConvertBoolToHRESULT(File.GetLength(*size));
\r
298 //////////////////////////
\r
301 HRESULT COutFileStream::Close()
\r
303 return ConvertBoolToHRESULT(File.Close());
\r
306 STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
\r
308 #ifdef USE_WIN_FILE
\r
310 UInt32 realProcessedSize;
\r
311 bool result = File.WritePart(data, size, realProcessedSize);
\r
312 ProcessedSize += realProcessedSize;
\r
313 if (processedSize != NULL)
\r
314 *processedSize = realProcessedSize;
\r
315 return ConvertBoolToHRESULT(result);
\r
319 if (processedSize != NULL)
\r
320 *processedSize = 0;
\r
321 ssize_t res = File.Write(data, (size_t)size);
\r
324 if (processedSize != NULL)
\r
325 *processedSize = (UInt32)res;
\r
326 ProcessedSize += res;
\r
332 STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
\r
334 if (seekOrigin >= 3)
\r
335 return STG_E_INVALIDFUNCTION;
\r
336 #ifdef USE_WIN_FILE
\r
338 UInt64 realNewPosition;
\r
339 bool result = File.Seek(offset, seekOrigin, realNewPosition);
\r
340 if (newPosition != NULL)
\r
341 *newPosition = realNewPosition;
\r
342 return ConvertBoolToHRESULT(result);
\r
346 off_t res = File.Seek(offset, seekOrigin);
\r
349 if (newPosition != NULL)
\r
350 *newPosition = (UInt64)res;
\r
356 STDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
\r
358 #ifdef USE_WIN_FILE
\r
360 if (!File.Seek(0, FILE_CURRENT, currentPos))
\r
362 bool result = File.SetLength(newSize);
\r
363 UInt64 currentPos2;
\r
364 result = result && File.Seek(currentPos, currentPos2);
\r
365 return result ? S_OK : E_FAIL;
\r
372 STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
\r
374 size_t s2 = fwrite(data, 1, size, stdout);
\r
375 if (processedSize != 0)
\r
376 *processedSize = s2;
\r
377 return (s2 = size) ? S_OK : E_FAIL;
\r
380 STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
\r
382 if (processedSize != NULL)
\r
383 *processedSize = 0;
\r
386 UInt32 realProcessedSize;
\r
390 // Seems that Windows doesn't like big amounts writing to stdout.
\r
391 // So we limit portions by 32KB.
\r
392 UInt32 sizeTemp = (1 << 15);
\r
393 if (sizeTemp > size)
\r
395 res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
\r
396 data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
\r
397 size -= realProcessedSize;
\r
398 data = (const void *)((const Byte *)data + realProcessedSize);
\r
399 if (processedSize != NULL)
\r
400 *processedSize += realProcessedSize;
\r
402 return ConvertBoolToHRESULT(res != FALSE);
\r
409 res = write(1, data, (size_t)size);
\r
411 while (res < 0 && (errno == EINTR));
\r
414 if (processedSize != NULL)
\r
415 *processedSize = (UInt32)res;
\r