1 // FileStreams.cpp
2 
3 #include "StdAfx.h"
4 
5 #ifndef _WIN32
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #endif
10 
11 #include "FileStreams.h"
12 
ConvertBoolToHRESULT(bool result)13 static inline HRESULT ConvertBoolToHRESULT(bool result)
14 {
15   // return result ? S_OK: E_FAIL;
16   #ifdef _WIN32
17   return result ? S_OK: (::GetLastError());
18   #else
19   return result ? S_OK: E_FAIL;
20   #endif
21 }
22 
Open(LPCTSTR fileName)23 bool CInFileStream::Open(LPCTSTR fileName)
24 {
25   return File.Open(fileName);
26 }
27 
28 #ifdef _WIN32
29 #ifndef _UNICODE
Open(LPCWSTR fileName)30 bool CInFileStream::Open(LPCWSTR fileName)
31 {
32   return File.Open(fileName);
33 }
34 #endif
35 #endif
36 
Read(void * data,UInt32 size,UInt32 * processedSize)37 STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
38 {
39   #ifdef _WIN32
40 
41   UInt32 realProcessedSize;
42   bool result = File.Read(data, size, realProcessedSize);
43   if(processedSize != NULL)
44     *processedSize = realProcessedSize;
45   return ConvertBoolToHRESULT(result);
46 
47   #else
48 
49   if(processedSize != NULL)
50     *processedSize = 0;
51   ssize_t res = File.Read(data, (size_t)size);
52   if (res == -1)
53     return E_FAIL;
54   if(processedSize != NULL)
55     *processedSize = (UInt32)res;
56   return S_OK;
57 
58   #endif
59 }
60 
ReadPart(void * data,UInt32 size,UInt32 * processedSize)61 STDMETHODIMP CInFileStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
62 {
63   return Read(data, size, processedSize);
64 }
65 
66 #ifndef _WIN32_WCE
Read(void * data,UInt32 size,UInt32 * processedSize)67 STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
68 {
69   #ifdef _WIN32
70   UInt32 realProcessedSize;
71   BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE),
72       data, size, (DWORD *)&realProcessedSize, NULL);
73   if(processedSize != NULL)
74     *processedSize = realProcessedSize;
75   if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
76     return S_OK;
77   return ConvertBoolToHRESULT(res != FALSE);
78 
79   #else
80 
81   if(processedSize != NULL)
82     *processedSize = 0;
83   ssize_t res;
84   do
85   {
86     res = read(0, data, (size_t)size);
87   }
88   while (res < 0 && (errno == EINTR));
89   if (res == -1)
90     return E_FAIL;
91   if(processedSize != NULL)
92     *processedSize = (UInt32)res;
93   return S_OK;
94 
95   #endif
96 }
97 
ReadPart(void * data,UInt32 size,UInt32 * processedSize)98 STDMETHODIMP CStdInFileStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
99 {
100   return Read(data, size, processedSize);
101 }
102 #endif
103 
Seek(Int64 offset,UInt32 seekOrigin,UInt64 * newPosition)104 STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,
105     UInt64 *newPosition)
106 {
107   if(seekOrigin >= 3)
108     return STG_E_INVALIDFUNCTION;
109 
110   #ifdef _WIN32
111 
112   UInt64 realNewPosition;
113   bool result = File.Seek(offset, seekOrigin, realNewPosition);
114   if(newPosition != NULL)
115     *newPosition = realNewPosition;
116   return ConvertBoolToHRESULT(result);
117 
118   #else
119 
120   off_t res = File.Seek(offset, seekOrigin);
121   if (res == -1)
122     return E_FAIL;
123   if(newPosition != NULL)
124     *newPosition = (UInt64)res;
125   return S_OK;
126 
127   #endif
128 }
129 
GetSize(UInt64 * size)130 STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
131 {
132   return ConvertBoolToHRESULT(File.GetLength(*size));
133 }
134 
135 
136 //////////////////////////
137 // COutFileStream
138 
Create(LPCTSTR fileName,bool createAlways)139 bool COutFileStream::Create(LPCTSTR fileName, bool createAlways)
140 {
141   return File.Create(fileName, createAlways);
142 }
143 
144 #ifdef _WIN32
145 #ifndef _UNICODE
Create(LPCWSTR fileName,bool createAlways)146 bool COutFileStream::Create(LPCWSTR fileName, bool createAlways)
147 {
148   return File.Create(fileName, createAlways);
149 }
150 #endif
151 #endif
152 
Write(const void * data,UInt32 size,UInt32 * processedSize)153 STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
154 {
155   #ifdef _WIN32
156 
157   UInt32 realProcessedSize;
158   bool result = File.Write(data, size, realProcessedSize);
159   if(processedSize != NULL)
160     *processedSize = realProcessedSize;
161   return ConvertBoolToHRESULT(result);
162 
163   #else
164 
165   if(processedSize != NULL)
166     *processedSize = 0;
167   ssize_t res = File.Write(data, (size_t)size);
168   if (res == -1)
169     return E_FAIL;
170   if(processedSize != NULL)
171     *processedSize = (UInt32)res;
172   return S_OK;
173 
174   #endif
175 }
176 
WritePart(const void * data,UInt32 size,UInt32 * processedSize)177 STDMETHODIMP COutFileStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
178 {
179   return Write(data, size, processedSize);
180 }
181 
182 
Seek(Int64 offset,UInt32 seekOrigin,UInt64 * newPosition)183 STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin,
184     UInt64 *newPosition)
185 {
186   if(seekOrigin >= 3)
187     return STG_E_INVALIDFUNCTION;
188   #ifdef _WIN32
189 
190   UInt64 realNewPosition;
191   bool result = File.Seek(offset, seekOrigin, realNewPosition);
192   if(newPosition != NULL)
193     *newPosition = realNewPosition;
194   return ConvertBoolToHRESULT(result);
195 
196   #else
197 
198   off_t res = File.Seek(offset, seekOrigin);
199   if (res == -1)
200     return E_FAIL;
201   if(newPosition != NULL)
202     *newPosition = (UInt64)res;
203   return S_OK;
204 
205   #endif
206 }
207 
SetSize(Int64 newSize)208 STDMETHODIMP COutFileStream::SetSize(Int64 newSize)
209 {
210   #ifdef _WIN32
211   UInt64 currentPos;
212   if(!File.Seek(0, FILE_CURRENT, currentPos))
213     return E_FAIL;
214   bool result = File.SetLength(newSize);
215   UInt64 currentPos2;
216   result = result && File.Seek(currentPos, currentPos2);
217   return result ? S_OK : E_FAIL;
218   #else
219   return E_FAIL;
220   #endif
221 }
222 
223 #ifndef _WIN32_WCE
Write(const void * data,UInt32 size,UInt32 * processedSize)224 STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
225 {
226   if(processedSize != NULL)
227     *processedSize = 0;
228 
229   #ifdef _WIN32
230   UInt32 realProcessedSize;
231   BOOL res = TRUE;
232   while (size > 0)
233   {
234     // Seems that Windows doesn't like big amounts writing to stdout.
235     // So we limit portions by 32KB.
236     UInt32 sizeTemp = (1 << 15);
237     if (sizeTemp > size)
238       sizeTemp = size;
239     res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
240         data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
241     if (realProcessedSize == 0)
242       break;
243     size -= realProcessedSize;
244     data = (const void *)((const Byte *)data + realProcessedSize);
245     if(processedSize != NULL)
246       *processedSize += realProcessedSize;
247   }
248   return ConvertBoolToHRESULT(res != FALSE);
249 
250   #else
251 
252   ssize_t res;
253   do
254   {
255     res = write(1, data, (size_t)size);
256   }
257   while (res < 0 && (errno == EINTR));
258   if (res == -1)
259     return E_FAIL;
260   if(processedSize != NULL)
261     *processedSize = (UInt32)res;
262   return S_OK;
263 
264   return S_OK;
265   #endif
266 }
267 
WritePart(const void * data,UInt32 size,UInt32 * processedSize)268 STDMETHODIMP CStdOutFileStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
269 {
270   return Write(data, size, processedSize);
271 }
272 #endif
273