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