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