714dd74636
git-svn-id: svn://10.65.10.50/trunk@5350 c028cbd2-c16b-5b4b-a496-9718f37d4682
203 lines
6.6 KiB
C++
Executable File
203 lines
6.6 KiB
C++
Executable File
//
|
|
// ARCE.CPP
|
|
//
|
|
// Source file for ArchiveLib 2.0
|
|
//
|
|
// Copyright (c) Greenleaf Software, Inc. 1994-1996
|
|
// All Rights Reserved
|
|
//
|
|
// CONTENTS
|
|
//
|
|
// ALArchive::Extract()
|
|
// ALArchiveExtract()
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// February 14, 1996 2.0A : New release
|
|
|
|
#include "arclib.h"
|
|
#if !defined( AL_IBM )
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#include "_openf.h"
|
|
|
|
//
|
|
// NAME
|
|
//
|
|
// ALArchive::Extract()
|
|
//
|
|
// PLATFORMS/ENVIRONMENTS
|
|
//
|
|
// Console Windows PM
|
|
// C++ C VB Delphi
|
|
//
|
|
// SHORT DESCRIPTION
|
|
//
|
|
// Extract objects from an archive.
|
|
//
|
|
// C++ SYNOPSIS
|
|
//
|
|
// #include "arclib.h"
|
|
//
|
|
// int ALArchive::Extract( ALEntryList AL_DLL_FAR &list )
|
|
//
|
|
// C SYNOPSIS
|
|
//
|
|
// #include "arclib.h"
|
|
//
|
|
// int ALArchiveExtract( hALArchive this_object,
|
|
// hALEntryList list );
|
|
//
|
|
// VB SYNOPSIS
|
|
//
|
|
// Declare Function ALArchiveExtract Lib "AL20LW"
|
|
// (ByVal this_object&, ByVal list&) As Integer
|
|
//
|
|
// DELPHI SYNOPSIS
|
|
//
|
|
// function ALArchiveExtract( this_object : hALArchive;
|
|
// list : hALEntryList ) : Integer;
|
|
//
|
|
// ARGUMENTS
|
|
//
|
|
// this_object : A reference or pointer to the ALArchive object that
|
|
// contains the storage objects to be extracted. In C++,
|
|
// we bypass this argument, since the implicit 'this'
|
|
// pointer takes care of the same thing nicely.
|
|
//
|
|
// list : An ALEntry list. All of the marked objects in the
|
|
// list will be extracted. Note that all the information
|
|
// in the list needs to be correct, e.g. file offset, CRC,
|
|
// etc. If you did a ReadDir(), that probably took care
|
|
// of it for you. Plus, the list needs to have good
|
|
// decompressors ready to go.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This routine just has to step through an entry list, and extract
|
|
// every marked object. Note that this isn't a virtual function, so
|
|
// it needs has to be able to generalize between PK and GL archives.
|
|
// It does so with the help of virtual functions like PreCompress()
|
|
// that set things up for a specific archive type.
|
|
//
|
|
// One big obstacle to extraction is the ability to set up a good
|
|
// decompressor. When reading in the archive list, ArchiveLib will
|
|
// attempt to set up a decompressor that will work with your compression
|
|
// method. As long as that decompressor has been added to the toolkit
|
|
// used to construct the list, you should be okay.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// The status of the Archive. This will be AL_SUCCESS if things went
|
|
// well, but might be < 0 if something bad happened.
|
|
//
|
|
// EXAMPLE
|
|
//
|
|
// SEE ALSO
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// February 14, 1996 2.0A : New release
|
|
//
|
|
|
|
|
|
int AL_PROTO
|
|
ALArchive::Extract( ALEntryList AL_DLL_FAR &list ) /* Tag public function */
|
|
{
|
|
//
|
|
// Open the input storage object, if not already open. Let the monitor
|
|
// know about it.
|
|
//
|
|
ALOpenInputFile archive( *mpArchiveStorageObject );
|
|
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 );
|
|
//
|
|
// Get rid of any duplicate entries, and set up the monitor sizes.
|
|
//
|
|
// Maybe it's okay? The one thing that unmarking duplicates
|
|
// screws up is a bunch of files with blank names. The blank
|
|
// name causes a temporary file to be created with a unique name,
|
|
// but not until the file is created!
|
|
//
|
|
// 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 );
|
|
//
|
|
// This loop iterates through the entire ALEntryList. We only care about
|
|
// ALEntry objects that have their mark set.
|
|
//
|
|
ALEntry *job = list.GetFirstEntry();
|
|
while ( job ) {
|
|
if ( mfStripPathOnExtract )
|
|
job->mpStorageObject->mName.StripPath();
|
|
if ( job->miMark ) {
|
|
//
|
|
// Go to the correct input position in this, and set up the monitor for
|
|
// this particular object.
|
|
//
|
|
list.mrMonitor.ArchiveOperation( AL_EXTRACTION_OPEN, this, job );
|
|
mpArchiveStorageObject->Seek( job->mlCompressedObjectPosition );
|
|
PreDecompress( *job );
|
|
list.mrMonitor.mlObjectStart = mpArchiveStorageObject->Tell();
|
|
list.mrMonitor.mlObjectSize = job->mlCompressedSize;
|
|
mpArchiveStorageObject->mpMonitor = &list.mrMonitor;
|
|
//
|
|
// Extract it, then check the CRC.
|
|
//
|
|
if ( !job->mpDecompressor )
|
|
return mStatus.SetError(
|
|
AL_CANT_CREATE_ENGINE,
|
|
"Attempt to decompress without a decompressor" );
|
|
job->mpStorageObject->Create( job->mpStorageObject->mlSize );
|
|
job->mpDecompressor->Decompress( *mpArchiveStorageObject,
|
|
*job->mpStorageObject,
|
|
job->mlCompressedSize );
|
|
job->mpStorageObject->Close();
|
|
PostDecompress( *job );
|
|
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() );
|
|
//
|
|
// Update the monitor data, and yield some time. Note that I turn off
|
|
// the monitor at this point so it doesn't jump around while I seek to the
|
|
// next position in the archive.
|
|
//
|
|
//
|
|
// The following two lines were reversed in 2.0. Updating JobSoFar
|
|
// before individual file stats were done causes a big jump ahead
|
|
// in total progress, but it isn't warranted.
|
|
//
|
|
mpArchiveStorageObject->YieldTime();
|
|
list.mrMonitor.mlJobSoFar += job->mlCompressedSize;
|
|
mpArchiveStorageObject->mpMonitor = 0;
|
|
list.mrMonitor.ArchiveOperation( AL_EXTRACTION_CLOSE, this, job );
|
|
job->mpStorageObject->mpMonitor = 0;
|
|
}
|
|
job = job->GetNextEntry();
|
|
}
|
|
//
|
|
// Update the monitor, then scan the list for status errors.
|
|
//
|
|
list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
|
|
ScanStatus( list );
|
|
return mStatus;
|
|
}
|
|
|
|
#if !defined( AL_NO_C )
|
|
|
|
extern "C" AL_LINKAGE int AL_FUNCTION
|
|
ALArchiveExtract( hALArchive this_object, /* Tag public function */
|
|
hALEntryList list )
|
|
{
|
|
AL_ASSERT_OBJECT( this_object, ALArchive, "ALArchiveExtract" );
|
|
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveExtract" );
|
|
return ((ALArchive *) this_object )->Extract( *( (ALEntryList *) list ) );
|
|
}
|
|
|
|
#endif
|
|
|