#include "arclib.h"
#pragma hdrstop
#include "_openf.h"
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALArchiveBase::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
AL_PROTO ALArchiveBase::ALArchiveBase( ALStorage AL_DLL_FAR *storage_object,
short int delete_in_dtor )
: miDeleteStorageObject( delete_in_dtor )
{
mpArchiveStorageObject = storage_object;
mszComment = 0;
mlDirectoryOffset = -1L;
miVersion = -1;
}
AL_PROTO ALArchiveBase::~ALArchiveBase()
{
AL_ASSERT( GoodTag(), "~Archive(): Attempting to delete invalid ALArchiveBase" );
if ( mszComment )
delete[] mszComment;
if ( mpArchiveStorageObject && miDeleteStorageObject )
delete mpArchiveStorageObject;
AL_ASSERT( GoodTag(), "~Archive::Attempting to delete invalid ALArchiveBase" );
}
int AL_PROTO ALArchiveBase::SetComment( char AL_DLL_FAR * comment )
{
if ( mszComment )
delete[] mszComment;
if ( comment == 0 )
mszComment = 0;
else {
mszComment = new char[ strlen( comment ) + 1 ];
if ( mszComment )
strcpy( mszComment, comment );
else
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Failed to allocate memory for "
"comment in archive %s",
mpArchiveStorageObject->mName.GetName() );
}
return mStatus;
}
int AL_PROTO ALArchiveBase::WriteDirectory( ALEntryList AL_DLL_FAR &list )
{
ALOpenInputFile archive( *mpArchiveStorageObject );
mpArchiveStorageObject->Seek( mlDirectoryOffset );
mpArchiveStorageObject->WritePortableShort( miVersion );
WriteArchiveData();
mpArchiveStorageObject->WriteString( mszComment );
AddDirectoryEntries( list );
return mStatus;
}
void AL_PROTO ALArchiveBase::ScanStatus( ALEntryList AL_DLL_FAR &list )
{
if ( mStatus < AL_SUCCESS )
return;
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->mpStorageObject->mStatus < AL_SUCCESS ) {
mStatus.SetError( job->mpStorageObject->mStatus,
"%s: %s",
job->mpStorageObject->mName.GetSafeName(),
job->mpStorageObject->mStatus.GetStatusDetail() );
return;
}
job = job->GetNextEntry();
}
}
int AL_PROTO ALArchiveBase::Extract( ALEntryList AL_DLL_FAR &list )
{
ALOpenInputFile archive( *mpArchiveStorageObject );
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 );
list.UnmarkDuplicates( list, "Duplicate entry in list passed to Extract()" );
list.mrMonitor.mlJobSoFar = 0L;
if ( list.mrMonitor.miMonitorType == AL_MONITOR_JOB )
list.mrMonitor.mlJobSize = CalculateCompressedJobSize( list );
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->miMark ) {
list.mrMonitor.ArchiveOperation( AL_EXTRACTION_OPEN, this, job );
mpArchiveStorageObject->Seek( job->mlCompressedObjectPosition );
list.mrMonitor.mlObjectStart = job->mlCompressedObjectPosition;
list.mrMonitor.mlObjectSize = job->mlCompressedSize;
mpArchiveStorageObject->mpMonitor = &list.mrMonitor;
job->mpCompressionEngine->Decompress( *mpArchiveStorageObject,
*job->mpStorageObject,
job->mlCompressedSize );
if ( job->mpStorageObject->GetCrc32() != job->GetCrc32() )
job->mpStorageObject->mStatus.SetError(
AL_CRC_ERROR,
"CRC32 was supposed to be %08lx, was %08lx",
job->GetCrc32(),
job->mpStorageObject->GetCrc32() );
list.mrMonitor.mlJobSoFar += job->mlCompressedSize;
mpArchiveStorageObject->YieldTime();
mpArchiveStorageObject->mpMonitor = 0;
list.mrMonitor.ArchiveOperation( AL_EXTRACTION_CLOSE, this, job );
job->mpStorageObject->mpMonitor = 0;
}
job = job->GetNextEntry();
}
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
ScanStatus( list );
return mStatus;
}
int AL_PROTO ALArchiveBase::AddJobs( ALEntryList AL_DLL_FAR &list )
{
list.mrMonitor.mlObjectStart = 0L; ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->miMark ) {
job->mlCompressedObjectPosition = mpArchiveStorageObject->Tell();
list.mrMonitor.ArchiveOperation( AL_INSERTION_OPEN, this, job );
list.mrMonitor.mlObjectSize = -1L; job->mpStorageObject->mpMonitor = &list.mrMonitor;
job->mpCompressionEngine->Compress( *job->mpStorageObject,
*mpArchiveStorageObject );
job->mlCrc32 = job->mpStorageObject->GetCrc32();
job->mpStorageObject->mpMonitor = 0;
if ( job->mpCompressionEngine->mStatus < 0 )
return mStatus = job->mpCompressionEngine->mStatus;
job->mlCompressedSize = mpArchiveStorageObject->Tell() -
job->mlCompressedObjectPosition;
list.mrMonitor.mlJobSoFar += job->mpStorageObject->GetSize();
list.mrMonitor.ArchiveOperation( AL_INSERTION_CLOSE, this, job );
}
job = job->GetNextEntry();
if ( mStatus < 0 )
break;
}
return mStatus;
}
int AL_PROTO ALArchiveBase::AddDirectoryEntries( ALEntryList AL_DLL_FAR &list )
{
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->miMark ) {
mpArchiveStorageObject->WriteString( job->mpStorageObject->mName.GetSafeName() );
mpArchiveStorageObject->WriteChar( job->mpCompressionEngine->miCompressionType );
job->mpCompressionEngine->WriteEngineData( mpArchiveStorageObject );
mpArchiveStorageObject->WriteChar( job->mpStorageObject->miStorageObjectType );
job->mpStorageObject->WriteStorageObjectData( mpArchiveStorageObject );
mpArchiveStorageObject->WritePortableLong( job->mpStorageObject->GetSize() );
mpArchiveStorageObject->WritePortableLong( job->GetCompressedSize() );
mpArchiveStorageObject->WritePortableLong( job->GetCrc32() );
mpArchiveStorageObject->WritePortableLong( job->mlCompressedObjectPosition );
mpArchiveStorageObject->WriteString( job->GetComment() );
mpArchiveStorageObject->WritePortableLong( job->mpStorageObject->mTimeDate.GetUnixTime() );
mpArchiveStorageObject->WritePortableShort( job->mpStorageObject->mAttributes.PackedAttributes() );
if ( mpArchiveStorageObject->mStatus < 0 )
return mStatus = mpArchiveStorageObject->mStatus;
}
job = job->GetNextEntry();
}
mpArchiveStorageObject->WriteString( "" );
mpArchiveStorageObject->Seek( mpArchiveStorageObject->Tell() - 2 );
return AL_SUCCESS;
}
long AL_PROTO ALArchiveBase::CalculateJobSize( ALEntryList AL_DLL_FAR &list )
{
long total = 0;
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->miMark ) {
long obj_size;
if ( ( obj_size = job->mpStorageObject->GetSize() ) == -1 ) {
job->mpStorageObject->Open();
obj_size = job->mpStorageObject->GetSize();
job->mpStorageObject->Close();
if ( obj_size == -1 )
return -1;
}
total += obj_size;
}
job = job->GetNextEntry();
}
return total;
}
long AL_PROTO ALArchiveBase::CalculateCompressedJobSize( ALEntryList AL_DLL_FAR &list )
{
long total = 0;
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->miMark ) {
if ( job->mlCompressedSize == -1 )
return -1;
else
total += job->mlCompressedSize;
}
job = job->GetNextEntry();
}
return total;
}
int AL_PROTO ALArchiveBase::Create( ALEntryList AL_DLL_FAR &list )
{
ALOpenOutputFile archive( *mpArchiveStorageObject );
miVersion = 0x100;
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 );
if ( mpArchiveStorageObject->mStatus < 0 )
return mStatus = mpArchiveStorageObject->mStatus;
list.UnmarkDuplicates( list,
"Duplicate entry in list passed to Create()" );
mpArchiveStorageObject->WritePortableLong( 0x12345678L );
list.mrMonitor.mlJobSoFar = 0L;
if ( list.mrMonitor.miMonitorType == AL_MONITOR_JOB )
list.mrMonitor.mlJobSize = CalculateJobSize( list );
AddJobs( list );
mlDirectoryOffset = mpArchiveStorageObject->Tell();
mpArchiveStorageObject->Seek( 0L );
mpArchiveStorageObject->WritePortableLong( mlDirectoryOffset );
if ( mpArchiveStorageObject->mStatus < 0 ) {
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
return mStatus = mpArchiveStorageObject->mStatus;
}
list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE, this, 0 );
WriteDirectory( list );
list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 );
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
ScanStatus( list );
return mStatus;
}
int AL_PROTO ALArchiveBase::CopyJobs( ALArchiveBase AL_DLL_FAR &source_archive,
ALEntryList AL_DLL_FAR &source_list )
{
ALOpenInputFile input( *(source_archive.mpArchiveStorageObject) );
ALEntry *job = source_list.GetFirstEntry();
while ( job ) {
if ( job->miMark ) {
source_archive.mpArchiveStorageObject->Seek( job->mlCompressedObjectPosition );
source_list.mrMonitor.mlObjectStart = job->mlCompressedObjectPosition;
source_list.mrMonitor.mlObjectSize = job->mlCompressedSize;
source_list.mrMonitor.ArchiveOperation( AL_COPY_OPEN, this, job );
source_archive.mpArchiveStorageObject->mpMonitor = &source_list.mrMonitor;
job->mlCompressedObjectPosition = mpArchiveStorageObject->Tell();
for ( long i = 0 ; i < job->mlCompressedSize ; i++ ) {
int c = source_archive.mpArchiveStorageObject->ReadChar();
mpArchiveStorageObject->WriteChar( c );
}
source_list.mrMonitor.ArchiveOperation( AL_COPY_CLOSE, this, job );
source_archive.mpArchiveStorageObject->YieldTime();
source_list.mrMonitor.mlJobSoFar += job->mlCompressedSize;
source_archive.mpArchiveStorageObject->mpMonitor = 0;
if ( source_archive.mpArchiveStorageObject->mStatus < 0 )
return mStatus = source_archive.mpArchiveStorageObject->mStatus;
if ( mpArchiveStorageObject->mStatus < 0 )
return mStatus = mpArchiveStorageObject->mStatus;
}
job = job->GetNextEntry();
if ( mStatus < 0 )
break;
}
return mStatus;
}
int AL_PROTO ALArchiveBase::Create( ALArchiveBase AL_DLL_FAR &source_archive,
ALEntryList AL_DLL_FAR &source_list )
{
ALOpenOutputFile archive( *mpArchiveStorageObject );
miVersion = 0x100;
if ( mpArchiveStorageObject->mStatus < 0 )
return mStatus = mpArchiveStorageObject->mStatus;
source_list.UnmarkDuplicates( source_list, "Duplicate entry in list passed to Create()" );
source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 );
source_list.mrMonitor.mlJobSoFar = 0L;
source_list.mrMonitor.mlJobSize = 0L;
for ( ALEntry *job = source_list.GetFirstEntry();
job != 0;
job = job->GetNextEntry() ) {
if ( job->GetMark() )
source_list.mrMonitor.mlJobSize += job->mlCompressedSize;
}
mpArchiveStorageObject->WritePortableLong( 0x12345678L );
CopyJobs( source_archive, source_list );
mlDirectoryOffset = mpArchiveStorageObject->Tell();
mpArchiveStorageObject->Seek( 0L );
mpArchiveStorageObject->WritePortableLong( mlDirectoryOffset );
if ( mpArchiveStorageObject->mStatus < 0 ) {
source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
return mStatus = mpArchiveStorageObject->mStatus;
}
source_list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE,this, 0 );
WriteDirectory( source_list );
source_list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 );
source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
ScanStatus( source_list );
return mStatus;
}
int AL_PROTO ALArchiveBase::Append( ALEntryList AL_DLL_FAR &list )
{
ALEntryList old_list;
ALOpenInputFile archive( *mpArchiveStorageObject );
ReadDirectory( old_list );
if ( mStatus < 0 )
return mStatus;
list.UnmarkDuplicates( list, "Duplicate entry in list passed to Append()" );
list.UnmarkDuplicates( old_list, "Duplicate entry in list passed to Append()" );
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 );
list.mrMonitor.mlJobSoFar = 0L;
if ( list.mrMonitor.miMonitorType == AL_MONITOR_JOB )
list.mrMonitor.mlJobSize = CalculateJobSize( list );
mpArchiveStorageObject->Seek( mlDirectoryOffset );
AddJobs( list );
if ( mStatus < 0 ) {
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
return mStatus;
}
mlDirectoryOffset = mpArchiveStorageObject->Tell();
mpArchiveStorageObject->Seek( 0L );
mpArchiveStorageObject->WritePortableLong( mlDirectoryOffset );
if ( mpArchiveStorageObject->mStatus < 0 ) {
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
return mStatus = mpArchiveStorageObject->mStatus;
}
list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE, this, 0 );
WriteDirectory( old_list );
AddDirectoryEntries( list );
list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 );
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
ScanStatus( list );
return mStatus;
}
int AL_PROTO ALArchiveBase::Append( ALArchiveBase AL_DLL_FAR &source_archive,
ALEntryList AL_DLL_FAR &source_list )
{
ALEntryList old_list;
ALOpenInputFile archive( *mpArchiveStorageObject );
source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 );
ReadDirectory( old_list );
if ( mStatus < 0 ) {
source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
return mStatus;
}
source_list.UnmarkDuplicates( source_list, "Duplicate entry in list passed to Append()" );
source_list.UnmarkDuplicates( old_list, "Duplicate entry in list passed to Append()" );
mpArchiveStorageObject->Seek( mlDirectoryOffset );
source_list.mrMonitor.mlJobSoFar = 0L;
source_list.mrMonitor.mlJobSize = 0L;
for ( ALEntry *job = source_list.GetFirstEntry();
job != 0;
job = job->GetNextEntry() ) {
if ( job->GetMark() )
source_list.mrMonitor.mlJobSize += job->mlCompressedSize;
}
CopyJobs( source_archive, source_list );
if ( mStatus < 0 ) {
source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
return mStatus;
}
mlDirectoryOffset = mpArchiveStorageObject->Tell();
mpArchiveStorageObject->Seek( 0L );
mpArchiveStorageObject->WritePortableLong( mlDirectoryOffset );
if ( mpArchiveStorageObject->mStatus < 0 ) {
source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
return mStatus = mpArchiveStorageObject->mStatus;
}
source_list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE, this, 0 );
WriteDirectory( old_list );
AddDirectoryEntries( source_list );
source_list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 );
source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
ScanStatus( source_list );
return mStatus;
}
int AL_PROTO ALArchiveBase::ReadDirectory( ALEntryList AL_DLL_FAR &list )
{
list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_READ, this, 0 );
ALOpenInputFile archive( *mpArchiveStorageObject );
if ( mpArchiveStorageObject->mStatus < 0 )
return mStatus = mpArchiveStorageObject->mStatus;
mpArchiveStorageObject->Seek( 0 );
mpArchiveStorageObject->ReadPortableLong( mlDirectoryOffset );
mpArchiveStorageObject->Seek( mlDirectoryOffset );
mpArchiveStorageObject->ReadPortableShort( miVersion );
if ( miVersion != 0x100 )
return mStatus.SetError( AL_INVALID_ARCHIVE,
"%s is not a valid archive file",
mpArchiveStorageObject->mName.GetSafeName() );
ReadArchiveData();
if ( mszComment )
delete[] mszComment;
mszComment = mpArchiveStorageObject->ReadString();
for ( ; ; ) {
if ( mpArchiveStorageObject->mStatus < 0 )
return mStatus = mpArchiveStorageObject->mStatus;
char *name = mpArchiveStorageObject->ReadString();
if ( name == 0 )
break;
if ( strlen( name ) == 0 ) {
delete[] name;
break;
}
int engine_type = mpArchiveStorageObject->ReadChar();
ALCompressionEngine *engine = CreateCompressionEngine( engine_type );
if ( engine )
engine->ReadEngineData( mpArchiveStorageObject );
else {
char *temp = mpArchiveStorageObject->ReadString();
if ( temp )
delete[] temp;
return mStatus.SetError( AL_CANT_CREATE_ENGINE,
"Failure creating compression engine for object %s",
name );
}
int object_type = mpArchiveStorageObject->ReadChar();
ALStorage *storage_object = CreateStorageObject( name, object_type );
delete[] name; name = 0;
if ( storage_object )
storage_object->ReadStorageObjectData( mpArchiveStorageObject );
else {
char *temp = mpArchiveStorageObject->ReadString();
if ( temp )
delete[] temp;
return mStatus.SetError( AL_CANT_CREATE_STORAGE_OBJECT,
"Failure creating storage object for object %s",
name );
}
mpArchiveStorageObject->ReadPortableLong( storage_object->mlSize );
ALEntry *job = new ALEntry( list, storage_object, engine );
mpArchiveStorageObject->ReadPortableLong( job->mlCompressedSize );
mpArchiveStorageObject->ReadPortableLong( job->mlCrc32 );
mpArchiveStorageObject->ReadPortableLong( job->mlCompressedObjectPosition );
char *comment = mpArchiveStorageObject->ReadString();
job->SetComment( comment );
if ( comment )
delete[] comment;
long unix_time;
mpArchiveStorageObject->ReadPortableLong( unix_time );
storage_object->mTimeDate.SetTimeDate( unix_time );
short int packed_attributes;
mpArchiveStorageObject->ReadPortableShort( packed_attributes );
storage_object->mAttributes.SetFromPackedAttributes( packed_attributes );
}
list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_READ, this, 0 );
return mStatus;
}
int AL_PROTO ALArchiveBase::WriteArchiveData()
{
return mpArchiveStorageObject->WritePortableShort( 0 );
}
int AL_PROTO ALArchiveBase::ReadArchiveData()
{
short temp;
mpArchiveStorageObject->ReadPortableShort( temp );
AL_ASSERT( temp == 0, "ReadArchiveData(): archive data != 0" );
return mpArchiveStorageObject->mStatus;
}
int AL_PROTO ALArchiveBase::Delete( ALEntryList AL_DLL_FAR &list,
ALArchiveBase AL_DLL_FAR &destination )
{
destination.SetComment( mszComment );
list.ToggleMarks();
destination.Create( *this, list );
list.ToggleMarks();
ALName temp = mpArchiveStorageObject->mName;
mpArchiveStorageObject->RenameToBackup();
destination.mpArchiveStorageObject->Rename( (const char *) temp );
if ( destination.mStatus < 0 )
return mStatus = destination.mStatus;
return mStatus;
}
#if defined( AL_WINDOWS_GUI )
int AL_PROTO ALArchiveBase::FillListBox( HWND hDlg, int list_box )
{
ALEntryList list;
HWND window;
ReadDirectory( list );
if ( list_box != -1 )
window = GetDlgItem( hDlg, (short int) list_box );
else
window = hDlg;
int count;
if ( ( count = list.FillListBox( window ) ) == 0 ) {
if ( mStatus < 0 ) {
SendMessage( window, LB_RESETCONTENT, 0, 0 );
SendMessage( window,
LB_ADDSTRING,
0,
(LPARAM)( (LPSTR) "Error!" ) );
}
}
return count;
}
#endif