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