667 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			667 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| //
 | |
| // ARC.CPP
 | |
| //
 | |
| //  Source file for ArchiveLib 2.0
 | |
| //
 | |
| //  Copyright (c) Greenleaf Software, Inc. 1994-1996
 | |
| //  All Rights Reserved
 | |
| //
 | |
| // CONTENTS
 | |
| //
 | |
| //  ALArchive::ALArchive( ALStorage * )
 | |
| //  ALArchive::operator new()
 | |
| //  ALArchive::ScanStatus()
 | |
| //  ALArchive::CalculateJobSize()
 | |
| //  ALArchive::CalculateCompressedJobSize()
 | |
| //  ALArchive::WriteArchiveData()
 | |
| //  ALArchive::ReadArchiveData()
 | |
| //  ALArchive::~ALArchive()
 | |
| //  deleteALArchive()
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This file contains the ALArchive ctor, dtor, and any functions
 | |
| //  that will *always* be linked (mostly because they are virtual.)
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| 
 | |
| #include "arclib.h"
 | |
| #if !defined( AL_IBM )
 | |
| #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::ALArchive()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Constructor for ALArchive, the base Archive class.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //  ALArchive::ALArchive( ALStorage *storage_object,
 | |
| //                        short int delete_in_dtor )
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  storage_object :  A pointer to the storage object that will contain
 | |
| //                    the archive.
 | |
| //
 | |
| //  delete_in_dtor :  When a user creates an archive, it will ordinarily
 | |
| //                    be with a storage object that will be managed by
 | |
| //                    their code.  When that's the case, we will ordinarily
 | |
| //                    expect them to be responsible for its destruction.
 | |
| //                    However, there are times when a temporary archive
 | |
| //                    might be created that isn't under the users control.
 | |
| //                    This flag controls whether the Archive destructor
 | |
| //                    will destroy the storage object as well.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  The base class ALArchive is very simple.  It has a few data members
 | |
| //  to initialize, and not much else.  The complexity in Archive classes
 | |
| //  is found in the derived classes ALGlArchive and ALPkArchive.  Both
 | |
| //  of them use this base class to initialize their storage object
 | |
| //  and the flag that indicates whether the storage object should be
 | |
| //  destroyed in the ALArchive destructor.
 | |
| //
 | |
| //  Although this is a public function, it isn't likely that there will
 | |
| //  ever be a good reason for an end user to call it.  It really isn't much
 | |
| //  good to anyone but the constructors for the archiving classes.
 | |
| //
 | |
| //  For this reason, there also isn't any reason to have a C/VB/Delphi
 | |
| //  translation routine.  Any attempt to construct an ALArchive by itself
 | |
| //  is doomed to failure anyway, since it has numerous pure virtual
 | |
| //  functions.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release, added the members to control
 | |
| //                             whether or not to strip path information.
 | |
| //
 | |
| 
 | |
| AL_PROTO
 | |
| ALArchive::ALArchive( ALStorage AL_DLL_FAR *storage_object,  /* Tag public function */
 | |
|                       short int delete_in_dtor )
 | |
|     : mfDeleteStorageObject( delete_in_dtor )
 | |
| {
 | |
|     mfStripPathOnInsert = 0;
 | |
|     mfStripPathOnExtract = 0;
 | |
|     mpArchiveStorageObject = storage_object;
 | |
|     mlDirectoryOffset = -1L;
 | |
|     miVersion = -1;
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::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"
 | |
| //
 | |
| //  void * ALArchive::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 ALArchive 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.
 | |
| //
 | |
| //  Incidentally, I suspect that this function never gets called.  If an
 | |
| //  object of a derived archive class is being created, it should use
 | |
| //  its own new operator, rendering this one useless.
 | |
| //
 | |
| // 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
 | |
| ALArchive::operator new( size_t size )  /* Tag internal function */
 | |
| {
 | |
|     return ::new char[ size ];
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::ScanStatus()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Scan the list of entries for errors after an archiving operation
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //  void ALArchive::ScanStatus( ALEntryList &list )
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  list  :  The list of entries that have just been processed, in one of
 | |
| //           the exciting functions, such as Create(), Delete(), etc.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  After an archive operation, I use this function to update the
 | |
| //  status member of the archive.  If the archive doesn't already
 | |
| //  have an error, I check through all the storage objects and
 | |
| //  compression engines to see if any of them hosed up.  Any error
 | |
| //  of any sort by any of them is copied into the archive status.
 | |
| //  The whole point of this is to ensure that if
 | |
| //  ALArchive.mStatus == AL_SUCCESS, it means everything worked.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  None.  This function sort of has a return, it will update
 | |
| //  the member mStatus with an error code if one is found.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| //
 | |
| 
 | |
| void AL_PROTO
 | |
| ALArchive::ScanStatus( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
 | |
| {
 | |
|     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();
 | |
|     }
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::CalculateJobSize()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Calculate the total number of bytes in a job.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //  long ALArchive::CalculateJobSize( ALEntryList &list )
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  list  :  The list of entries in the job.  The calculation function
 | |
| //           will iterator through this list.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  If a monitor is running in AL_MONITOR_JOB mode, we need to add up
 | |
| //  the sizes of all the storage objects we are going to process, so
 | |
| //  that we can accurately track our progress from 0 to 100%.  In many
 | |
| //  cases, the sizes of all the files will not yet be known, which means
 | |
| //  this routine will have to open the files up and check the values.
 | |
| //  That is why we only call this routine when we have to.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  This function is used to calculate the total number of bytes that
 | |
| //  are going to have to be moved when performing a Create() or Append()
 | |
| //  operation.  We need that info in order to set up a monitor properly
 | |
| //  when its mode is AL_MONITOR_JOB.  Naturally, we don't really care
 | |
| //  about the total size when the monitor is in AL_MONITOR_OBJECTS mode.
 | |
| //  Anyway, it returns the total unocmpressed size of all the objects added up.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| //
 | |
| 
 | |
| long AL_PROTO
 | |
| ALArchive::CalculateJobSize( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
 | |
| {
 | |
|     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;
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::CalculateCompressedJobSize()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Calculate the total number of bytes in a job.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //  long ALArchive::CalculateCompressedJobSize( ALEntryList &list )
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  list  :  The list of entries in the job.  The calculation function
 | |
| //           will iterator through this list.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  When we are monitoring an Extract() command, the monitor object
 | |
| //  gets attached to the Archive, not to the objects that are getting
 | |
| //  sucked out of it.  This means that progress is being measured
 | |
| //  against the compressed objects, not the true size objects.  So
 | |
| //  before I start the extract, I call this function to see just how
 | |
| //  much compressed space is taken up by the compressed objects in
 | |
| //  the archive.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  The total size of a bunch of compressed objects, not the uncompressed
 | |
| //  size.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| //
 | |
| 
 | |
| long AL_PROTO
 | |
| ALArchive::CalculateCompressedJobSize( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
 | |
| {
 | |
|     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;
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::WriteArchiveData()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Write out any customized archive data.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //  int ALArchive::WriteArchiveData()
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  Derived classes can write out customized archive data, for whatever
 | |
| //  reasons they deem necessary.  Our base class has nothing that it
 | |
| //  needs to save, so it just writes out a zero length string, which takes
 | |
| //  two bytes to save.  Instead of using WriteString like I ought to, for
 | |
| //  some reason I write the 0 out directly.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  AL_SUCCESS if everything writes out okay, or < AL_SUCCESS for trouble.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALArchive::WriteArchiveData()  /* Tag protected function */
 | |
| {
 | |
|     return mpArchiveStorageObject->WriteGlShort( 0 );
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::ReadArchiveData()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Read in any customized archive data.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  int ALArchive::ReadArchiveData()
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  The base class doesn't store anything in the archive specific
 | |
| //  data area.  That means that when I am reading the archive specific
 | |
| //  data in, I should see a zero length string, which is the same thing
 | |
| //  as a single short of value 0.  I read it in and verify it here.
 | |
| //
 | |
| //  Note that derived classes are free to override this function, but
 | |
| //  nothing we ship with ArchiveLib does so.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  AL_SUCCESS if things went well, < AL_SUCCESS it things go sour.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALArchive::ReadArchiveData()  /* Tag protected function */
 | |
| {
 | |
|     short temp;
 | |
|     mpArchiveStorageObject->ReadGlShort( temp );
 | |
|     AL_ASSERT( temp == 0, "ReadArchiveData(): archive data != 0" );
 | |
|     return mpArchiveStorageObject->mStatus;
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::~ALArchive()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++  C  VB  Delphi
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  The base class destructor for ALArchive.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //   ALArchive::~ALArchive()
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //  void deleteALArchive( hALArchive this_object );
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  Declare Sub deleteALArchive Lib "AL20LW" (ByVal this_object&)
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  procedure deleteALArchive( this_object : hALArchive );
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  this_object  :  A reference or pointer to the ALArchive object that
 | |
| //                  is going to be destroyed.  The C++ version of this
 | |
| //                  function doesn't have an argument, because it knows
 | |
| //                  implicitly who to destroy.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  The destructor for the base class doesn't have to do too much work.
 | |
| //  All it has to do is destroy the storage object, if that service was
 | |
| //  requested when the object was constructed.
 | |
| //
 | |
| //  It's a little deceptive to show the C/VB/Delphi translation here
 | |
| //  as well.  Since the archive being destroyed will always be in a base
 | |
| //  class, the virtual function call will direct a call to deleteALArchive
 | |
| //  down to the derived class destructor before coming back up here.  But
 | |
| //  I don't really have a better place to put it.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| //
 | |
| 
 | |
| AL_PROTO
 | |
| ALArchive::~ALArchive()  /* Tag public function */
 | |
| {
 | |
|     AL_ASSERT( GoodTag(), "~ALArchive(): Attempting to delete invalid ALArchive" );
 | |
|     if ( mpArchiveStorageObject && mfDeleteStorageObject )
 | |
|         delete mpArchiveStorageObject;
 | |
|     AL_ASSERT( GoodTag(), "~ALArchive::Attempting to delete invalid ALArchive" );
 | |
| }
 | |
| 
 | |
| #if !defined( AL_NO_C )
 | |
| 
 | |
| extern "C" AL_LINKAGE void AL_FUNCTION
 | |
| deleteALArchive( hALArchive this_object )  /* Tag public function */
 | |
| {
 | |
|     AL_ASSERT_OBJECT( this_object, ALArchive, "deleteALArchive()" );
 | |
|     delete (ALArchive *) this_object;
 | |
| }
 | |
| 
 | |
| #endif
 |