diff options
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp')
-rw-r--r-- | src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp | 318 |
1 files changed, 240 insertions, 78 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp b/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp index 76ab5ee29..ee1cc54e2 100644 --- a/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp +++ b/src/libs/7zip/unix/CPP/7zip/Common/FileStreams.cpp @@ -8,6 +8,11 @@ #include <errno.h> #endif +#ifdef SUPPORT_DEVICE_FILE +#include "../../../C/Alloc.h" +#include "../../Common/Defs.h" +#endif + #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) @@ -24,86 +29,175 @@ static inline HRESULT ConvertBoolToHRESULT(bool result) #endif } -bool CInFileStream::Open(LPCTSTR fileName) -{ -#ifdef ENV_UNIX - return File.Open(fileName,_ignoreSymbolicLink); -#else - return File.Open(fileName); -#endif -} +#ifdef SUPPORT_DEVICE_FILE -#ifdef USE_WIN_FILE -#ifndef _UNICODE -bool CInFileStream::Open(LPCWSTR fileName) +static const UInt32 kClusterSize = 1 << 18; +CInFileStream::CInFileStream(): + VirtPos(0), + PhyPos(0), + Buf(0), + BufSize(0), + SupportHardLinks(false) { -#ifdef ENV_UNIX - return File.Open(fileName,_ignoreSymbolicLink); -#else - return File.Open(fileName); -#endif } -#endif -#endif -bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) -{ -#ifdef ENV_UNIX - return File.Open(fileName,_ignoreSymbolicLink); -#else - return File.OpenShared(fileName, shareForWrite); #endif -} -#ifdef USE_WIN_FILE -#ifndef _UNICODE -bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) +CInFileStream::~CInFileStream() { - return File.OpenShared(fileName, shareForWrite); + #ifdef SUPPORT_DEVICE_FILE + MidFree(Buf); + #endif } -#endif -#endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE - + + #ifdef SUPPORT_DEVICE_FILE + if (processedSize) + *processedSize = 0; + if (size == 0) + return S_OK; + if (File.IsDeviceFile) + { + if (File.SizeDefined) + { + if (VirtPos >= File.Size) + return VirtPos == File.Size ? S_OK : E_FAIL; + UInt64 rem = File.Size - VirtPos; + if (size > rem) + size = (UInt32)rem; + } + for (;;) + { + const UInt32 mask = kClusterSize - 1; + const UInt64 mask2 = ~(UInt64)mask; + UInt64 alignedPos = VirtPos & mask2; + if (BufSize > 0 && BufStartPos == alignedPos) + { + UInt32 pos = (UInt32)VirtPos & mask; + if (pos >= BufSize) + return S_OK; + UInt32 rem = MyMin(BufSize - pos, size); + memcpy(data, Buf + pos, rem); + VirtPos += rem; + if (processedSize) + *processedSize += rem; + return S_OK; + } + + bool useBuf = false; + if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 ) + useBuf = true; + else + { + UInt64 end = VirtPos + size; + if ((end & mask) != 0) + { + end &= mask2; + if (end <= VirtPos) + useBuf = true; + else + size = (UInt32)(end - VirtPos); + } + } + if (!useBuf) + break; + if (alignedPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = realNewPosition; + } + + BufStartPos = alignedPos; + UInt32 readSize = kClusterSize; + if (File.SizeDefined) + readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize); + + if (!Buf) + { + Buf = (Byte *)MidAlloc(kClusterSize); + if (!Buf) + return E_OUTOFMEMORY; + } + bool result = File.Read1(Buf, readSize, BufSize); + if (!result) + return ConvertBoolToHRESULT(result); + + if (BufSize == 0) + return S_OK; + PhyPos += BufSize; + } + + if (VirtPos != PhyPos) + { + UInt64 realNewPosition; + bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition); + if (!result) + return ConvertBoolToHRESULT(result); + PhyPos = VirtPos = realNewPosition; + } + } + #endif + UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); - if(processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; + #ifdef SUPPORT_DEVICE_FILE + VirtPos += realProcessedSize; + PhyPos += realProcessedSize; + #endif return ConvertBoolToHRESULT(result); - + #else - - if(processedSize != NULL) + + if (processedSize) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; #endif } -#ifndef _WIN32_WCE +#ifdef UNDER_CE +STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + size_t s2 = fread(data, 1, size, stdin); + int error = ferror(stdin); + if (processedSize) + *processedSize = s2; + if (s2 <= size && error == 0) + return S_OK; + return E_FAIL; +} +#else STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 - UInt32 realProcessedSize; - BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), - data, size, (DWORD *)&realProcessedSize, NULL); - if(processedSize != NULL) + + DWORD realProcessedSize; + UInt32 sizeTemp = (1 << 20); + if (sizeTemp > size) + sizeTemp = size; + BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL); + if (processedSize) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); - + #else - if(processedSize != NULL) + if (processedSize) *processedSize = 0; ssize_t res; do @@ -113,38 +207,61 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; - + #endif } - + #endif -STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, - UInt64 *newPosition) +STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) + if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE + #ifdef SUPPORT_DEVICE_FILE + if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END)) + { + switch (seekOrigin) + { + case STREAM_SEEK_SET: break; + case STREAM_SEEK_CUR: offset += VirtPos; break; + case STREAM_SEEK_END: offset += File.Size; break; + default: return STG_E_INVALIDFUNCTION; + } + if (offset < 0) + return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; + VirtPos = offset; + if (newPosition) + *newPosition = offset; + return S_OK; + } + #endif + UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); - if(newPosition != NULL) + + #ifdef SUPPORT_DEVICE_FILE + PhyPos = VirtPos = realNewPosition; + #endif + + if (newPosition) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); - + #else - - off_t res = File.Seek(offset, seekOrigin); + + off_t res = File.Seek((off_t)offset, seekOrigin); if (res == -1) return E_FAIL; - if(newPosition != NULL) + if (newPosition) *newPosition = (UInt64)res; return S_OK; - + #endif } @@ -153,6 +270,43 @@ STDMETHODIMP CInFileStream::GetSize(UInt64 *size) return ConvertBoolToHRESULT(File.GetLength(*size)); } +#if 0 // FIXME #ifdef USE_WIN_FILE + +STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) +{ + BY_HANDLE_FILE_INFORMATION info; + if (File.GetFileInformation(&info)) + { + if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + if (cTime) *cTime = info.ftCreationTime; + if (aTime) *aTime = info.ftLastAccessTime; + if (mTime) *mTime = info.ftLastWriteTime; + if (attrib) *attrib = info.dwFileAttributes; + return S_OK; + } + return GetLastError(); +} + +STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) +{ + BY_HANDLE_FILE_INFORMATION info; + if (File.GetFileInformation(&info)) + { + props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; + props->VolID = info.dwVolumeSerialNumber; + props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow; + props->FileID_High = 0; + props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1; + props->Attrib = info.dwFileAttributes; + props->CTime = info.ftCreationTime; + props->ATime = info.ftLastAccessTime; + props->MTime = info.ftLastWriteTime; + return S_OK; + } + return GetLastError(); +} + +#endif ////////////////////////// // COutFileStream @@ -169,46 +323,46 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; - if(processedSize != NULL) + if (processedSize) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); - + #else - - if(processedSize != NULL) + + if (processedSize) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; - + #endif } - + STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) + if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); - if(newPosition != NULL) + if (newPosition) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); - + #else - - off_t res = File.Seek(offset, seekOrigin); + + off_t res = File.Seek((off_t)offset, seekOrigin); if (res == -1) return E_FAIL; - if(newPosition != NULL) + if (newPosition) *newPosition = (UInt64)res; return S_OK; - + #endif } @@ -216,7 +370,7 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; - if(!File.Seek(0, FILE_CURRENT, currentPos)) + if (!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; @@ -227,10 +381,18 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) #endif } -#ifndef _WIN32_WCE +#ifdef UNDER_CE +STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + size_t s2 = fwrite(data, 1, size, stdout); + if (processedSize) + *processedSize = s2; + return (s2 == size) ? S_OK : E_FAIL; +} +#else STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if(processedSize != NULL) + if (processedSize) *processedSize = 0; #ifdef _WIN32 @@ -247,13 +409,13 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); - if(processedSize != NULL) + if (processedSize) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else - + ssize_t res; do { @@ -262,12 +424,12 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; - if(processedSize != NULL) + if (processedSize) *processedSize = (UInt32)res; return S_OK; - + return S_OK; #endif } - + #endif |