Skip to content
Permalink
Browse files Browse the repository at this point in the history
5.6.1.4: Use in-memory archive instead of file IO
  • Loading branch information
Varun Khaneja authored and aawc committed Jan 4, 2018
1 parent 637fc84 commit 0ff832d
Show file tree
Hide file tree
Showing 22 changed files with 233 additions and 31 deletions.
2 changes: 1 addition & 1 deletion arccmt.cpp
Expand Up @@ -120,7 +120,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
// 4x memory for OEM to UTF-8 output here.
OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
#endif
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtLength);
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
CmtData->Alloc(wcslen(CmtData->Addr(0)));
}
#endif
Expand Down
75 changes: 68 additions & 7 deletions archive.cpp
Expand Up @@ -3,6 +3,10 @@
#include "arccmt.cpp"


#ifdef USE_ARCMEM
#include "arcmem.cpp"
#endif

Archive::Archive(RAROptions *InitCmd)
{
Cmd=NULL; // Just in case we'll have an exception in 'new' below.
Expand Down Expand Up @@ -48,6 +52,10 @@ Archive::Archive(RAROptions *InitCmd)

SilentOpen=false;

#ifdef USE_QOPEN
ProhibitQOpen=false;
#endif

}


Expand Down Expand Up @@ -294,39 +302,92 @@ uint Archive::FullHeaderSize(size_t Size)



#ifdef USE_QOPEN
bool Archive::Open(const wchar *Name,uint Mode)
{
#ifdef USE_QOPEN
// Important if we reuse Archive object and it has virtual QOpen
// file position not matching real. For example, for 'l -v volname'.
QOpen.Unload();
#endif

#ifdef USE_ARCMEM
if (Cmd->ArcInMem)
{
wcsncpyz(FileName,Name,ASIZE(FileName));
ArcMem.Load(Cmd->ArcMemData,Cmd->ArcMemSize);
Cmd->SetArcInMem(NULL,0); // Return in memory data for first volume only, not for next volumes.
return true;
}
#endif

return File::Open(Name,Mode);
}



bool Archive::Close()
{
#ifdef USE_ARCMEM
if (ArcMem.Unload())
return true;
#endif
return File::Close();
}



int Archive::Read(void *Data,size_t Size)
{
size_t Result;
if (QOpen.Read(Data,Size,Result))
return (int)Result;
#ifdef USE_QOPEN
size_t QResult;
if (QOpen.Read(Data,Size,QResult))
return (int)QResult;
#endif
#ifdef USE_ARCMEM
size_t AResult;
if (ArcMem.Read(Data,Size,AResult))
return (int)AResult;
#endif
return File::Read(Data,Size);
}


void Archive::Seek(int64 Offset,int Method)
{
if (!QOpen.Seek(Offset,Method))
File::Seek(Offset,Method);
#ifdef USE_QOPEN
if (QOpen.Seek(Offset,Method))
return;
#endif
#ifdef USE_ARCMEM
if (ArcMem.Seek(Offset,Method))
return;
#endif
File::Seek(Offset,Method);
}


int64 Archive::Tell()
{
#ifdef USE_QOPEN
int64 QPos;
if (QOpen.Tell(&QPos))
return QPos;
#endif
#ifdef USE_ARCMEM
int64 APos;
if (ArcMem.Tell(&APos))
return APos;
#endif
return File::Tell();
}
#endif



bool Archive::IsOpened()
{
#ifdef USE_ARCMEM
if (ArcMem.IsLoaded())
return true;
#endif
return File::IsOpened();
};
9 changes: 8 additions & 1 deletion archive.hpp
Expand Up @@ -55,6 +55,10 @@ class Archive:public File
bool SilentOpen;
#ifdef USE_QOPEN
QuickOpen QOpen;
bool ProhibitQOpen;
#endif
#ifdef USE_ARCMEM
ArcMemory ArcMem;
#endif
public:
Archive(RAROptions *InitCmd=NULL);
Expand Down Expand Up @@ -89,12 +93,15 @@ class Archive:public File
#if 0
void GetRecoveryInfo(bool Required,int64 *Size,int *Percent);
#endif
#ifdef USE_QOPEN
bool Open(const wchar *Name,uint Mode=FMF_READ);
bool Close();
int Read(void *Data,size_t Size);
void Seek(int64 Offset,int Method);
int64 Tell();
bool IsOpened();
#ifdef USE_QOPEN
void QOpenUnload() {QOpen.Unload();}
void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;}
#endif

BaseBlock ShortBlock;
Expand Down
62 changes: 62 additions & 0 deletions arcmem.cpp
@@ -0,0 +1,62 @@
ArcMemory::ArcMemory()
{
Loaded=false;
SeekPos=0;
}


void ArcMemory::Load(const byte *Data,size_t Size)
{
ArcData.Alloc(Size);
memcpy(&ArcData[0],Data,Size);
Loaded=true;
SeekPos=0;
}


bool ArcMemory::Unload()
{
if (!Loaded)
return false;
Loaded=false;
return true;
}


bool ArcMemory::Read(void *Data,size_t Size,size_t &Result)
{
if (!Loaded)
return false;
Result=(size_t)Min(Size,ArcData.Size()-SeekPos);
memcpy(Data,&ArcData[(size_t)SeekPos],Result);
SeekPos+=Result;
return true;
}


bool ArcMemory::Seek(int64 Offset,int Method)
{
if (!Loaded)
return false;
if (Method==SEEK_SET)
SeekPos=Min(Offset,ArcData.Size());
else
if (Method==SEEK_CUR || Method==SEEK_END)
{
if (Method==SEEK_END)
SeekPos=ArcData.Size();
SeekPos+=(uint64)Offset;
if (SeekPos>ArcData.Size())
SeekPos=Offset<0 ? 0 : ArcData.Size();
}
return true;
}


bool ArcMemory::Tell(int64 *Pos)
{
if (!Loaded)
return false;
*Pos=SeekPos;
return true;
}
22 changes: 22 additions & 0 deletions arcmem.hpp
@@ -0,0 +1,22 @@
#ifndef _RAR_ARCMEM_
#define _RAR_ARCMEM_

// Memory interface for software fuzzers.

class ArcMemory
{
private:
bool Loaded;
Array<byte> ArcData;
uint64 SeekPos;
public:
ArcMemory();
void Load(const byte *Data,size_t Size);
bool Unload();
bool IsLoaded() {return Loaded;}
bool Read(void *Data,size_t Size,size_t &Result);
bool Seek(int64 Offset,int Method);
bool Tell(int64 *Pos);
};

#endif
4 changes: 2 additions & 2 deletions arcread.cpp
Expand Up @@ -757,7 +757,7 @@ size_t Archive::ReadHeader50()
ProcessExtra50(&Raw,(size_t)ExtraSize,&MainHead);

#ifdef USE_QOPEN
if (MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE)
if (!ProhibitQOpen && MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE)
{
// We seek to QO block in the end of archive when processing
// QOpen.Load, so we need to preserve current block positions
Expand Down Expand Up @@ -1091,7 +1091,7 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)

wchar VerText[20];
swprintf(VerText,ASIZE(VerText),L";%u",Version);
wcsncatz(FileHead.FileName,VerText,ASIZE(FileHead.FileName));
wcsncatz(hd->FileName,VerText,ASIZE(hd->FileName));
}
}
break;
Expand Down
8 changes: 4 additions & 4 deletions cmddata.cpp
Expand Up @@ -97,7 +97,7 @@ void CommandData::ParseArg(wchar *Arg)
else
if (*Command==0)
{
wcsncpy(Command,Arg,ASIZE(Command));
wcsncpyz(Command,Arg,ASIZE(Command));


*Command=toupperw(*Command);
Expand Down Expand Up @@ -1194,8 +1194,8 @@ int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchTy
{
if (MatchedArg!=NULL && MatchedArgSize>0)
*MatchedArg=0;
if (wcslen(FileHead.FileName)>=NM)
return 0;
// if (wcslen(FileHead.FileName)>=NM)
// return 0;
bool Dir=FileHead.Dir;
if (ExclCheck(FileHead.FileName,Dir,false,true))
return 0;
Expand Down Expand Up @@ -1249,7 +1249,7 @@ void CommandData::ProcessCommand()
wcsncpyz(ArcName,Name,ASIZE(ArcName));
}

if (wcschr(L"AFUMD",*Command)==NULL)
if (wcschr(L"AFUMD",*Command)==NULL && !ArcInMem)
{
if (GenerateArcName)
GenerateArchiveName(ArcName,ASIZE(ArcName),GenerateMask,false);
Expand Down
9 changes: 9 additions & 0 deletions compress.hpp
Expand Up @@ -6,7 +6,16 @@
class PackDef
{
public:
// Maximum LZ match length we can encode even for short distances.
static const uint MAX_LZ_MATCH = 0x1001;

// We increment LZ match length for longer distances, because shortest
// matches are not allowed for them. Maximum length increment is 3
// for distances larger than 256KB (0x40000). Here we define the maximum
// incremented LZ match. Normally packer does not use it, but we must be
// ready to process it in corrupt archives.
static const uint MAX_INC_LZ_MATCH = MAX_LZ_MATCH + 3;

static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
static const uint LOW_DIST_REP_COUNT = 16;

Expand Down
4 changes: 2 additions & 2 deletions file.hpp
Expand Up @@ -78,7 +78,7 @@ class File
bool Create(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
void TCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
bool WCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD);
bool Close();
virtual bool Close();
bool Delete();
bool Rename(const wchar *NewName);
bool Write(const void *Data,size_t Size);
Expand All @@ -96,7 +96,7 @@ class File
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
void GetOpenFileTime(RarTime *ft);
bool IsOpened() {return hFile!=FILE_BAD_HANDLE;};
virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;};
int64 FileLength();
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
FILE_HANDLETYPE GetHandleType() {return HandleType;}
Expand Down
2 changes: 1 addition & 1 deletion makefile
Expand Up @@ -3,7 +3,7 @@

# Linux using GCC
CXX=c++
CXXFLAGS=-O2
CXXFLAGS=-O2 -Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else
LIBFLAGS=-fPIC
DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP
STRIP=strip
Expand Down
16 changes: 15 additions & 1 deletion options.hpp
Expand Up @@ -89,10 +89,24 @@ class RAROptions
bool InclAttrSet;
size_t WinSize;
wchar TempPath[NM];
#ifdef USE_QOPEN
wchar SFXModule[NM];

#ifdef USE_QOPEN
QOPEN_MODE QOpenMode;
#endif

bool ArcInMem;
#ifdef USE_ARCMEM
void SetArcInMem(byte *Data,size_t Size)
{
ArcMemData=Data;
ArcMemSize=Size;
ArcInMem=Data!=NULL && Size>0;
}
byte *ArcMemData;
size_t ArcMemSize;
#endif

bool ConfigDisabled; // Switch -cfg-.
wchar ExtrPath[NM];
wchar CommentFile[NM];
Expand Down
17 changes: 15 additions & 2 deletions qopen.cpp
Expand Up @@ -61,14 +61,27 @@ void QuickOpen::Close()

void QuickOpen::Load(uint64 BlockPos)
{
if (!Loaded) // If loading the first time, perform additional intialization.
if (!Loaded)
{
// If loading for the first time, perform additional intialization.
SeekPos=Arc->Tell();
UnsyncSeekPos=false;

SaveFilePos SavePos(*Arc);
Arc->Seek(BlockPos,SEEK_SET);
if (Arc->ReadHeader()==0 || Arc->GetHeaderType()!=HEAD_SERVICE ||

// If BlockPos points to original main header, we'll have the infinite
// recursion, because ReadHeader() for main header will attempt to load
// QOpen and call QuickOpen::Load again. If BlockPos points to long chain
// of other main headers, we'll have multiple recursive calls of this
// function wasting resources. So we prohibit QOpen temporarily to
// prevent this. ReadHeader() calls QOpen.Init and sets MainHead Locator
// and QOpenOffset fields, so we cannot use them to prohibit QOpen.
Arc->SetProhibitQOpen(true);
size_t ReadSize=Arc->ReadHeader();
Arc->SetProhibitQOpen(false);

if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE ||
!Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN))
return;
QLHeaderPos=Arc->CurBlockPos;
Expand Down

0 comments on commit 0ff832d

Please sign in to comment.