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
 | 
						|
 |