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