Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Common/FileStreams.cpp')
-rwxr-xr-xCPP/7zip/Common/FileStreams.cpp189
1 files changed, 167 insertions, 22 deletions
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp
index eb7ad3a2..f7c01d2c 100755
--- a/CPP/7zip/Common/FileStreams.cpp
+++ b/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)
@@ -52,24 +57,138 @@ bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite)
#endif
#endif
+#ifdef SUPPORT_DEVICE_FILE
+
+static const UInt32 kClusterSize = 1 << 18;
+CInFileStream::CInFileStream():
+ VirtPos(0),
+ PhyPos(0),
+ Buffer(0),
+ BufferSize(0)
+{
+}
+
+#endif
+
+CInFileStream::~CInFileStream()
+{
+ #ifdef SUPPORT_DEVICE_FILE
+ MidFree(Buffer);
+ #endif
+}
+
STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
#ifdef USE_WIN_FILE
+ #ifdef SUPPORT_DEVICE_FILE
+ if (processedSize != NULL)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ if (File.IsDeviceFile)
+ {
+ if (File.LengthDefined)
+ {
+ if (VirtPos >= File.Length)
+ return VirtPos == File.Length ? S_OK : E_FAIL;
+ UInt64 rem = File.Length - VirtPos;
+ if (size > rem)
+ size = (UInt32)rem;
+ }
+ for (;;)
+ {
+ const UInt32 mask = kClusterSize - 1;
+ UInt64 mask2 = ~(UInt64)mask;
+ UInt64 alignedPos = VirtPos & mask2;
+ if (BufferSize > 0 && BufferStartPos == alignedPos)
+ {
+ UInt32 pos = (UInt32)VirtPos & mask;
+ if (pos >= BufferSize)
+ return S_OK;
+ UInt32 rem = MyMin(BufferSize - pos, size);
+ memcpy(data, Buffer + pos, rem);
+ VirtPos += rem;
+ if (processedSize != NULL)
+ *processedSize += rem;
+ return S_OK;
+ }
+
+ bool useBuffer = false;
+ if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )
+ useBuffer = true;
+ else
+ {
+ UInt64 end = VirtPos + size;
+ if ((end & mask) != 0)
+ {
+ end &= mask2;
+ if (end <= VirtPos)
+ useBuffer = true;
+ else
+ size = (UInt32)(end - VirtPos);
+ }
+ }
+ if (!useBuffer)
+ break;
+ if (alignedPos != PhyPos)
+ {
+ UInt64 realNewPosition;
+ bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition);
+ if (!result)
+ return ConvertBoolToHRESULT(result);
+ PhyPos = realNewPosition;
+ }
+
+ BufferStartPos = alignedPos;
+ UInt32 readSize = kClusterSize;
+ if (File.LengthDefined)
+ readSize = (UInt32)MyMin(File.Length - PhyPos, (UInt64)kClusterSize);
+
+ if (Buffer == 0)
+ {
+ Buffer = (Byte *)MidAlloc(kClusterSize);
+ if (Buffer == 0)
+ return E_OUTOFMEMORY;
+ }
+ bool result = File.Read1(Buffer, readSize, BufferSize);
+ if (!result)
+ return ConvertBoolToHRESULT(result);
+
+ if (BufferSize == 0)
+ return S_OK;
+ PhyPos += BufferSize;
+ }
+
+ 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 != NULL)
*processedSize = realProcessedSize;
+ #ifdef SUPPORT_DEVICE_FILE
+ VirtPos += realProcessedSize;
+ PhyPos += realProcessedSize;
+ #endif
return ConvertBoolToHRESULT(result);
#else
- if(processedSize != NULL)
+ if (processedSize != NULL)
*processedSize = 0;
ssize_t res = File.Read(data, (size_t)size);
if (res == -1)
return E_FAIL;
- if(processedSize != NULL)
+ if (processedSize != NULL)
*processedSize = (UInt32)res;
return S_OK;
@@ -80,10 +199,13 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
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 != NULL)
*processedSize = realProcessedSize;
if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
return S_OK;
@@ -91,7 +213,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi
#else
- if(processedSize != NULL)
+ if (processedSize != NULL)
*processedSize = 0;
ssize_t res;
do
@@ -101,7 +223,7 @@ 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 != NULL)
*processedSize = (UInt32)res;
return S_OK;
@@ -113,14 +235,37 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi
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)
+ {
+ UInt64 newVirtPos = offset;
+ switch(seekOrigin)
+ {
+ case STREAM_SEEK_SET: break;
+ case STREAM_SEEK_CUR: newVirtPos += VirtPos; break;
+ case STREAM_SEEK_END: newVirtPos += File.Length; break;
+ default: return STG_E_INVALIDFUNCTION;
+ }
+ VirtPos = newVirtPos;
+ if (newPosition)
+ *newPosition = newVirtPos;
+ 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 != NULL)
*newPosition = realNewPosition;
return ConvertBoolToHRESULT(result);
@@ -129,7 +274,7 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin,
off_t res = File.Seek(offset, seekOrigin);
if (res == -1)
return E_FAIL;
- if(newPosition != NULL)
+ if (newPosition != NULL)
*newPosition = (UInt64)res;
return S_OK;
@@ -157,18 +302,18 @@ 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 != NULL)
*processedSize = realProcessedSize;
return ConvertBoolToHRESULT(result);
#else
- if(processedSize != NULL)
+ if (processedSize != NULL)
*processedSize = 0;
ssize_t res = File.Write(data, (size_t)size);
if (res == -1)
return E_FAIL;
- if(processedSize != NULL)
+ if (processedSize != NULL)
*processedSize = (UInt32)res;
ProcessedSize += res;
return S_OK;
@@ -178,13 +323,13 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces
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 != NULL)
*newPosition = realNewPosition;
return ConvertBoolToHRESULT(result);
@@ -193,7 +338,7 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo
off_t res = File.Seek(offset, seekOrigin);
if (res == -1)
return E_FAIL;
- if(newPosition != NULL)
+ if (newPosition != NULL)
*newPosition = (UInt64)res;
return S_OK;
@@ -204,7 +349,7 @@ STDMETHODIMP COutFileStream::SetSize(Int64 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;
@@ -218,7 +363,7 @@ STDMETHODIMP COutFileStream::SetSize(Int64 newSize)
#ifndef _WIN32_WCE
STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- if(processedSize != NULL)
+ if (processedSize != NULL)
*processedSize = 0;
#ifdef _WIN32
@@ -235,7 +380,7 @@ 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 != NULL)
*processedSize += realProcessedSize;
}
return ConvertBoolToHRESULT(res != FALSE);
@@ -250,7 +395,7 @@ 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 != NULL)
*processedSize = (UInt32)res;
return S_OK;