794 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			794 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//
 | 
						|
// GLARC.CPP
 | 
						|
//
 | 
						|
//  Source file for ArchiveLib 2.0
 | 
						|
//
 | 
						|
//  Copyright (c) Greenleaf Software, Inc. 1994-1996
 | 
						|
//  All Rights Reserved
 | 
						|
//
 | 
						|
// CONTENTS
 | 
						|
//
 | 
						|
//  ALGlArchive::operator new()
 | 
						|
//  ALGlArchive::ALGlArchive()
 | 
						|
//  newALGlArchiveFromStorage()
 | 
						|
//  ALGlArchive::~ALGlArchive()
 | 
						|
//  ALGlArchive::PreWriteDir()
 | 
						|
//  ALGlArchive::PostWriteDir()
 | 
						|
//  ALGlArchive::WriteDirEntry()
 | 
						|
//  ALGlArchive::ReadDirectory()
 | 
						|
//  ALGlArchive::PreCreate()
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This file contains all of the source code for the base class,
 | 
						|
//  ALGlArchive. The details on how things get inserted and extracted from an
 | 
						|
//  archive will all be found here.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//  May 23, 1994  1.0A  : First release
 | 
						|
//
 | 
						|
//  July 7, 1994  1.0B  : Minor change to handle a snag with the sun
 | 
						|
//                        compilers.
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
#include "arclib.h"
 | 
						|
#if !defined( AL_IBM )
 | 
						|
#pragma hdrstop
 | 
						|
#endif
 | 
						|
 | 
						|
#include "glarc.h"
 | 
						|
#include "_openf.h"
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALGlArchive::operator new()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Memory allocator used when ArchiveLib resides in a 16 bit DLL.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  void * ALGlArchive::operator new( size_t size )
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  size  :  The number of bytes that the compiler has decided will be
 | 
						|
//           necessary to construct a new ALGlArchive object.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  When using a DLL, it is easy to get into a dangerous situation when
 | 
						|
//  creating objects whose ctor and dtor are both in the DLL.  The problem
 | 
						|
//  arises because when you create an object using new, the memory for
 | 
						|
//  the object will be allocated from the EXE.  However, when you destroy
 | 
						|
//  the object using delete, the memory is freed inside the DLL.  Since
 | 
						|
//  the DLL doesn't really own that memory, bad things can happen.
 | 
						|
//
 | 
						|
//  But, you say, won't the space just go back to the Windows heap regardless
 | 
						|
//  of who tries to free it?  Maybe, but maybe not.  If the DLL is using
 | 
						|
//  a subsegment allocation scheme, it might do some sort of local free
 | 
						|
//  before returning the space to the windows heap.  That is the point where
 | 
						|
//  you could conceivably cook your heap.
 | 
						|
//
 | 
						|
//  By providing our own version of operator new inside this class, we
 | 
						|
//  ensure that all memory allocation for the class will be done from
 | 
						|
//  inside the DLL, not the EXE calling the DLL.
 | 
						|
//
 | 
						|
//  This function will be called whenever you dynamically create a new
 | 
						|
//  ALGlArchive object (using the new operator.)
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  A pointer to some memory that should have been pulled out of the
 | 
						|
//  heap for the DLL.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
#if defined( AL_BUILDING_DLL )
 | 
						|
 | 
						|
void AL_DLL_FAR * AL_PROTO
 | 
						|
ALGlArchive::operator new( size_t size )  /* Tag internal function */
 | 
						|
{
 | 
						|
    return ::new char[ size ];
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALGlArchive::ALGlArchive()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++  C  VB  Delphi
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  The Greenleaf Archive constructors.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  ALGlArchive::ALGlArchive( ALStorage &storage_object );
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  hALArchive newALGlArchiveFromStorage( hALStorage storage );
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  Declare Function newALGlArchiveFromStorage Lib "AL20LW"
 | 
						|
//    (ByVal storage&) As Long
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  function newALGlArchiveFromStorage( storage : hALStorage ) : hALArchive;
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  storage_object   : A pointer to the storage object that will/does
 | 
						|
//                     hold the archive.
 | 
						|
//
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This function creates a new ALGlArchive object, using a storage object
 | 
						|
//  as the underlying physical container.  GlArchives are siblings to
 | 
						|
//  Pk archives.  While they both use the same base class, and support many
 | 
						|
//  functions in common, they are essentially incompatible.
 | 
						|
//
 | 
						|
//  You call this constructor to manipulate any archive, including ones
 | 
						|
//  that haven't even been created yet.
 | 
						|
//
 | 
						|
//  Recall that the base class, ALArchive, has a single argument to *its*
 | 
						|
//  constructor that determines whether or not it destroys the underlying
 | 
						|
//  storage object in its destructor.  Since we are using user-specified
 | 
						|
//  storage in this case, we pass a 0, indicating that we don't want the
 | 
						|
//  destructor to destroy the underlying storage object.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  When called from C/VB/Delphi, the translation function returns a handle
 | 
						|
//  to a newly created archive object.  When called using the new operator
 | 
						|
//  in C++, this function returns a pointer to a newly created archive
 | 
						|
//  object.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
AL_PROTO
 | 
						|
ALGlArchive::ALGlArchive( ALStorage AL_DLL_FAR &storage_object )  /* Tag public function */
 | 
						|
    : ALArchive( &storage_object, 0)
 | 
						|
{
 | 
						|
    miVersion = 0x100;
 | 
						|
}
 | 
						|
 | 
						|
#if !defined( AL_NO_C )
 | 
						|
 | 
						|
extern "C" AL_LINKAGE hALArchive AL_FUNCTION
 | 
						|
newALGlArchiveFromStorage( hALStorage storage ) /* Tag public function */
 | 
						|
{
 | 
						|
    AL_ASSERT( ( (ALStorage *) storage)->GoodTag(),
 | 
						|
               "storage argument is not a valid ALStorageObject" );
 | 
						|
    ALArchive *archive;
 | 
						|
    archive = new ALGlArchive( *(ALStorage *) storage );
 | 
						|
    return (hALArchive) archive;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALGlArchive::~ALGlArchive()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Destructor for the Greenleaf Archive.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  ALGlArchive::~ALGlArchive()
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, use deleteALArchive();
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, use deleteALArchive();
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, use deleteALArchive();
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This is a virtual destructor for the derived class ALGlArchive.  It
 | 
						|
//  has absolutely nothing to do, since all of the important work is done
 | 
						|
//  by the base class destructor, ALArchive::~ALArchive().  Note that
 | 
						|
//  there is no translation function for C/VB/Delphi to call this function
 | 
						|
//  directly.  Instead, they will get here by way of a virtual function
 | 
						|
//  call to the base class destructor.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Nothing.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
AL_PROTO
 | 
						|
ALGlArchive::~ALGlArchive()  /* Tag public function */
 | 
						|
{
 | 
						|
    AL_ASSERT( GoodTag(), "~ALGlArchive(): Attempting to delete invalid ALGlArchive" );
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALGlArchive::PreWriteDir()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Write out the archive data that precedes the directory.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  void ALGlArchive::PreWriteDir()
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal function.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal function.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal function.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  The base class, ALArchive, is responsible for all the work done when
 | 
						|
//  creating an archive.  However, since Greenleaf and PKWare archives
 | 
						|
//  are fairly different, the base class relies on a few virtual functions
 | 
						|
//  to perform archive specific chores.
 | 
						|
//
 | 
						|
//  PreWriteDir() is one of those functions.  It is called after the
 | 
						|
//  file pointer has been positioned to write the directory out, but
 | 
						|
//  before any directory entries have been written.
 | 
						|
//
 | 
						|
//  Greenleaf archives store three items directly ahead of the
 | 
						|
//  directory: the archive version, any customized archive data, and
 | 
						|
//  the archive comment.  This routine just writes all those out, then
 | 
						|
//  returns to the calling routine.  The caller is presumably the
 | 
						|
//  write directory code in ALArchive, and it should continue by writing
 | 
						|
//  out all of its directory entries.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Nothing.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
void AL_PROTO
 | 
						|
ALGlArchive::PreWriteDir()  /* Tag protected function */
 | 
						|
{
 | 
						|
    mpArchiveStorageObject->WriteGlShort( miVersion );
 | 
						|
    WriteArchiveData();
 | 
						|
    mpArchiveStorageObject->WriteString( mComment );
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALGlArchive::PostWriteDir()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Write out the archive data that follows the directory.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  void ALGlArchive::PostWriteDir()
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal function.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal function.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal function.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  The base class, ALArchive, is responsible for all the work done when
 | 
						|
//  creating an archive.  However, since Greenleaf and PKWare archives
 | 
						|
//  are fairly different, the base class relies on a few virtual functions
 | 
						|
//  to perform archive specific chores.
 | 
						|
//
 | 
						|
//  PostWriteDir() is one of those functions.  It is called after the
 | 
						|
//  directory entires for the archive have all been written out.
 | 
						|
//
 | 
						|
//  Greenleaf archives store three items directly ahead of the
 | 
						|
//  directory: the archive version, any customized archive data, and
 | 
						|
//  the archive comment.  This routine just writes all those out, then
 | 
						|
//  returns to the calling routine.  The caller is presumably the
 | 
						|
//  write directory code in ALArchive, and it should continue by writing
 | 
						|
//  out all of its directory entries.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Nothing.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
void AL_PROTO
 | 
						|
ALGlArchive::PostWriteDir()  /* Tag protected function */
 | 
						|
{
 | 
						|
    long keeper = mpArchiveStorageObject->Tell();
 | 
						|
    mpArchiveStorageObject->WriteString( "" );
 | 
						|
    mpArchiveStorageObject->Seek( 0L );
 | 
						|
    mpArchiveStorageObject->WriteGlLong( mlDirectoryOffset );
 | 
						|
 | 
						|
    mpArchiveStorageObject->Seek( keeper );
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALGlArchive::WriteDirEntry()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Write an individual object entry to the archive directory.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  void ALGlArchive::WriteDirEntry( ALEntry &entry );
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal support function.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal support function.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal support function.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  entry  :  A reference to an entry.  This should correspond to an actual
 | 
						|
//            object that is present in the archive.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  The base class function, ALArchive::WriteDirectory(), sits in a loop
 | 
						|
//  writing out directory entries, one after the other.  Since it is in
 | 
						|
//  the base class, you can't expect it to know the exact format for an
 | 
						|
//  entry.  So instead, it relies on this virtual function in derived
 | 
						|
//  classes to do the job.
 | 
						|
//
 | 
						|
//  This function takes care of writing out a directory entry in the format
 | 
						|
//  Greenleaf archives use.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Nothing.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
void AL_PROTO
 | 
						|
ALGlArchive::WriteDirEntry( ALEntry AL_DLL_FAR &entry )  /* Tag protected function */
 | 
						|
{
 | 
						|
    mpArchiveStorageObject->WriteString( entry.mpStorageObject->mName.GetSafeName() );
 | 
						|
    if ( entry.mpCompressor ) {
 | 
						|
        mpArchiveStorageObject->WriteChar( entry.mpCompressor->miCompressionType );
 | 
						|
        entry.mpCompressor->WriteEngineData( mpArchiveStorageObject );
 | 
						|
    } else if ( entry.mpDecompressor ) {
 | 
						|
        mpArchiveStorageObject->WriteChar( entry.mpDecompressor->miCompressionType );
 | 
						|
        entry.mpDecompressor->WriteEngineData( mpArchiveStorageObject );
 | 
						|
    } else {
 | 
						|
        mStatus.SetError( AL_UNKNOWN_COMPRESSION_TYPE,
 | 
						|
                          "No compressor or decompressor for archive"
 | 
						|
                          " entry %s",
 | 
						|
                          entry.mpStorageObject->mName.GetSafeName() );
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    mpArchiveStorageObject->WriteChar( entry.mpStorageObject->miStorageObjectType );
 | 
						|
    entry.mpStorageObject->WriteStorageObjectData( mpArchiveStorageObject );
 | 
						|
 | 
						|
    mpArchiveStorageObject->WriteGlLong( entry.mpStorageObject->GetSize() );
 | 
						|
    mpArchiveStorageObject->WriteGlLong( entry.GetCompressedSize() );
 | 
						|
    mpArchiveStorageObject->WriteGlLong( entry.GetCrc32() );
 | 
						|
    mpArchiveStorageObject->WriteGlLong( entry.mlCompressedObjectPosition );
 | 
						|
    mpArchiveStorageObject->WriteString( entry.GetComment() );
 | 
						|
    mpArchiveStorageObject->WriteGlLong( entry.mpStorageObject->mTimeDate.GetUnixTime() );
 | 
						|
    mpArchiveStorageObject->WriteGlShort( entry.mpStorageObject->mAttributes.PackedAttributes() );
 | 
						|
    if ( mpArchiveStorageObject->mStatus < 0 )
 | 
						|
        mStatus = mpArchiveStorageObject->mStatus;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALGlArchive::ReadDirectory()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Read in the directory for a GL format archive.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  int ALGlArchive::ReadDirectory( ALEntryList &list )
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal function.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal function.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal function.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  list  : An ALEntryList object that is going to receive all the
 | 
						|
//          new ALEntry objects created from reading the directory.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  During the process of creating ArchiveLib 2.0, the WriteDirectory()
 | 
						|
//  function was moved up into the base class.  The addition of three
 | 
						|
//  virtual helper functions takes care of all the specialized aspects
 | 
						|
//  needed to make it happen.
 | 
						|
//
 | 
						|
//  Well, I haven't gotten around to that for the ReadDirectory function.
 | 
						|
//  Maybe in the final release of 2.0, but more likely in the release
 | 
						|
//  of ArchiveLib 3.0.  It's not a critical issue, it just helps break
 | 
						|
//  the code down into smaller pieces, and is somewhat more efficient by
 | 
						|
//  sharing common code.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  AL_SUCCESS or < AL_SUCCESS if things don't work.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALGlArchive::ReadDirectory( ALEntryList AL_DLL_FAR &list )  /* Tag protected function */
 | 
						|
{
 | 
						|
    list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_READ, this, 0 );
 | 
						|
    ALOpenInputFile archive( *mpArchiveStorageObject );
 | 
						|
    if ( mpArchiveStorageObject->mStatus < 0 )
 | 
						|
        return mStatus = mpArchiveStorageObject->mStatus;
 | 
						|
//
 | 
						|
// First I seek to the start of the directory (offset found at 0), and
 | 
						|
// read in the version.  This function only supports the directory
 | 
						|
// structure defined in version 0x100.
 | 
						|
//
 | 
						|
    mpArchiveStorageObject->Seek( 0 );
 | 
						|
    mpArchiveStorageObject->ReadGlLong( mlDirectoryOffset );
 | 
						|
    mpArchiveStorageObject->Seek( mlDirectoryOffset );
 | 
						|
    mpArchiveStorageObject->ReadGlShort( miVersion );
 | 
						|
    if ( miVersion != 0x100 )
 | 
						|
        return mStatus.SetError( AL_INVALID_ARCHIVE,
 | 
						|
                                 "%s is not a valid archive file",
 | 
						|
                                 mpArchiveStorageObject->mName.GetSafeName() );
 | 
						|
//
 | 
						|
// Read in any customized archive data defined by a derived class.
 | 
						|
//
 | 
						|
    ReadArchiveData();
 | 
						|
//
 | 
						|
// Read in the comment, deleting the old one if necessary.
 | 
						|
//
 | 
						|
    mpArchiveStorageObject->ReadString( mComment );
 | 
						|
//
 | 
						|
// Now, the big loop.  I have to read in each entry, one at a time, and
 | 
						|
// add it to the list.  If I broke this out into a separate routine it
 | 
						|
// would make the whole thing a lot more manageable.
 | 
						|
//
 | 
						|
    for ( ; ; ) {
 | 
						|
        if ( mpArchiveStorageObject->mStatus < 0 )
 | 
						|
            return mStatus = mpArchiveStorageObject->mStatus;
 | 
						|
        ALName name;
 | 
						|
        mpArchiveStorageObject->ReadString( name );
 | 
						|
//
 | 
						|
// The directory ends with a blank name.
 | 
						|
//
 | 
						|
        if ( strlen( name ) == 0 )
 | 
						|
            break;
 | 
						|
//
 | 
						|
// Derived classes are responsible for providing a version of
 | 
						|
// CreateCompressionEngine() that will convert the engine_type
 | 
						|
// integer into a created compression engine.  The derived class is
 | 
						|
// then also responsible for reading in the engine data from the archive.
 | 
						|
//
 | 
						|
        int engine_type = mpArchiveStorageObject->ReadChar();
 | 
						|
        ALCompressor *compressor = 0;
 | 
						|
        ALDecompressor *decompressor = list.mToolKit.CreateDecompressor( engine_type );
 | 
						|
        if ( decompressor )
 | 
						|
            decompressor->ReadEngineData( mpArchiveStorageObject );
 | 
						|
        else {
 | 
						|
            compressor = list.mToolKit.CreateCompressor( engine_type );
 | 
						|
            if ( compressor )
 | 
						|
                compressor->ReadEngineData( mpArchiveStorageObject );
 | 
						|
            else {
 | 
						|
                ALName temp;
 | 
						|
                mpArchiveStorageObject->ReadString( temp );
 | 
						|
//
 | 
						|
// I used to treat this as an error, now I don't.  The error will come about
 | 
						|
// when you actually try to decompress the object.
 | 
						|
//
 | 
						|
#if 0
 | 
						|
                return mStatus.SetError( AL_CANT_CREATE_ENGINE,
 | 
						|
                                         "Failure creating compression engine for object %s",
 | 
						|
                                         (const char *) name );
 | 
						|
#endif
 | 
						|
            }
 | 
						|
        }
 | 
						|
//
 | 
						|
// Now we go through a nearly identical process to create the storage object.
 | 
						|
// The derived class is responsible for writing a CreateStorageObject()
 | 
						|
// function that converts an object_type integer to a created storage
 | 
						|
// object.  The derived class also has to read in the storage object
 | 
						|
// data.
 | 
						|
//
 | 
						|
        int object_type = mpArchiveStorageObject->ReadChar();
 | 
						|
        ALStorage *storage_object = list.mToolKit.CreateStorageObject( name, object_type );
 | 
						|
        if ( storage_object )
 | 
						|
            storage_object->ReadStorageObjectData( mpArchiveStorageObject );
 | 
						|
        else {
 | 
						|
            ALName temp;
 | 
						|
            mpArchiveStorageObject->ReadString( temp );
 | 
						|
//
 | 
						|
// I used to treat this as an error, now I don't.  The error will come about
 | 
						|
// when you actually try to compress the object.
 | 
						|
//
 | 
						|
#if 0
 | 
						|
            return mStatus.SetError( AL_CANT_CREATE_STORAGE_OBJECT,
 | 
						|
                                     "Failure creating storage object for object %s",
 | 
						|
                                     (const char *) name );
 | 
						|
#endif
 | 
						|
        }
 | 
						|
//
 | 
						|
// The rest of the stuff in the entry is pretty straightforward.
 | 
						|
//
 | 
						|
        mpArchiveStorageObject->ReadGlLong( storage_object->mlSize );
 | 
						|
        ALEntry *job = new ALEntry( list, storage_object, compressor, decompressor );
 | 
						|
        mpArchiveStorageObject->ReadGlLong( job->mlCompressedSize );
 | 
						|
        mpArchiveStorageObject->ReadGlLong( job->mlCrc32 );
 | 
						|
        mpArchiveStorageObject->ReadGlLong( job->mlCompressedObjectPosition );
 | 
						|
        ALName comment;
 | 
						|
        mpArchiveStorageObject->ReadString( comment );
 | 
						|
        job->SetComment( comment );
 | 
						|
        long unix_time;
 | 
						|
        mpArchiveStorageObject->ReadGlLong( unix_time );
 | 
						|
        storage_object->mTimeDate.SetTimeDate( unix_time );
 | 
						|
        short int packed_attributes;
 | 
						|
        mpArchiveStorageObject->ReadGlShort( packed_attributes );
 | 
						|
        storage_object->mAttributes.SetFromPackedAttributes( packed_attributes );
 | 
						|
    }
 | 
						|
    list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_READ, this, 0 );
 | 
						|
    return mStatus;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALEntryList::ClearError()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Reset the error status for an entry list.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "glarc.h"
 | 
						|
//
 | 
						|
//  void ALGlArchive::PreCreate()
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal support function.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal support function.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, internal support function.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//   The Create() function is found in the base class.  It takes care of
 | 
						|
//   sticking a bunch of compressed objects into an archive.  It gets
 | 
						|
//   ready to do this, then class this function first.
 | 
						|
//
 | 
						|
//   Since this is a virtual function, the derived class can put any
 | 
						|
//   specialized behavior here.  For Greenleaf archives, the only
 | 
						|
//   specialized behavior needed is to save enough space for a long
 | 
						|
//   in the file.  After the archive is created, the long at offset 0
 | 
						|
//   will get a pointer to the start of the directory.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Nothing.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
void AL_PROTO
 | 
						|
ALGlArchive::PreCreate()  /* Tag protected function */
 | 
						|
{
 | 
						|
//
 | 
						|
// The first four bytes in the archive are a long that points to the
 | 
						|
// first byte of the directory.  I don't know where the directory is
 | 
						|
// going to be, so I just reserve space at this time with a dummy value.
 | 
						|
//
 | 
						|
    mpArchiveStorageObject->WriteGlLong( 0x12345678L );
 | 
						|
}
 | 
						|
 |