196 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			196 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| //
 | |
| // ARCA.CPP
 | |
| //
 | |
| //  Source file for ArchiveLib 2.0
 | |
| //
 | |
| //  Copyright (c) Greenleaf Software, Inc. 1994-1996
 | |
| //  All Rights Reserved
 | |
| //
 | |
| // CONTENTS
 | |
| //
 | |
| //  ALArchive::Append()
 | |
| //  ALArchiveAppend()
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This file contains the archive Append function.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| 
 | |
| #include "arclib.h"
 | |
| #if !defined( AL_IBM )
 | |
| #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| #include "_openf.h"
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALArchive::Append()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++  C  VB  Delphi
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Append a list of objects to an existing archive.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //  int ALArchive::Append( ALEntryList AL_DLL_FAR &list )
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //
 | |
| //  int ALArchiveAppend( hALArchive this_object, hALEntryList list )
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  Declare Function ALArchiveAppend Lib "AL20LW" (ByVal this_object&, ByVal list&) As Integer
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  function ALArchiveAppend( this_object : hALArchive;
 | |
| //                            list : hALEntryList ) : Integer;
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  this_object  :  A reference or pointer to the ALArchive object that
 | |
| //                  is going to have the list of files appended to it.
 | |
| //                  As always, the C++ version of this function doesn't
 | |
| //                  need 'this_object' as an argumnent, since C++
 | |
| //                  member functions get an explicit copy of this passed
 | |
| //                  when they are called.
 | |
| //
 | |
| //  list         :  A reference to the ALEntryList that has copies of
 | |
| //                  all the storage objects to be inserted, as well
 | |
| //                  as the compression engines need to insert them.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This function is called to insert a batch of objects into an archive.
 | |
| //  You might have noticed by looking at the header file ARC.H that this
 | |
| //  is not a virtual function, which means its behavior has to be
 | |
| //  generalized enough to support both Greenleaf and PKWare archives.
 | |
| //  All the specialization is done through the virtual functions that
 | |
| //  control directory information, object positioning, and so on.
 | |
| //
 | |
| //  All of the bookwork is done in this function.  Note that in order
 | |
| //  for this to work properly, we have to read in the entire directory
 | |
| //  into memory, because we are going to append to an existing file, and
 | |
| //  we assume the directory is at the end of the archive.  So the process
 | |
| //  basically consists of first reading the directory, then compressing
 | |
| //  all the new jobs, then writing out the new combined directory.  The
 | |
| //  compresssion is done in another function, CompressJobs().
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  An ArchiveLib status, ranging from AL_SUCCESS to any number of
 | |
| //  reasons for failure.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALArchive::Append( ALEntryList AL_DLL_FAR &list )  /* Tag public function */
 | |
| {
 | |
|     ALEntryList old_list(list);
 | |
| //
 | |
| // Open the storage object for this.
 | |
| //
 | |
|     ALOpenInputFile archive( *mpArchiveStorageObject );
 | |
| //
 | |
| // I read in the current directory for this archive.  I am going to
 | |
| // write over the directory with new stuff, so I will have to write it
 | |
| // back out later.
 | |
| //
 | |
|     ReadDirectory( old_list );
 | |
|     if ( mStatus < 0 )
 | |
|         return mStatus;
 | |
| //
 | |
| // The list of new objects I am going to add needs to be scanned for
 | |
| // duplicates.  First I clear duplicate entries from the list itself.
 | |
| // Then I clear any duplicates between the current list and the
 | |
| // stuff already in the archive.
 | |
| //
 | |
|     list.UnmarkDuplicates( list, "Duplicate entry in list passed to Append()" );
 | |
|     list.UnmarkDuplicates( old_list, "Duplicate entry in list passed to Append()" );
 | |
| //
 | |
| // I get the monitor set up, for the batch of entries I am about to do.
 | |
| //
 | |
|     list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 );
 | |
|     list.mrMonitor.mlJobSoFar = 0L;
 | |
|     if ( list.mrMonitor.miMonitorType == AL_MONITOR_JOB )
 | |
|         list.mrMonitor.mlJobSize = CalculateJobSize( list );
 | |
| //
 | |
| // The new entries start at the position currently occupied by the
 | |
| // directory.  I seek to that point, then call AddJobs() to do the
 | |
| // dirty work.
 | |
| //
 | |
|     mpArchiveStorageObject->Seek( mlDirectoryOffset );
 | |
|     CompressJobs( list );
 | |
|     mlDirectoryOffset = mpArchiveStorageObject->Tell();
 | |
|     if ( mStatus < 0 ) {
 | |
|         list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
 | |
|         return mStatus;
 | |
|     }
 | |
| //
 | |
| // Now I write the old directory out, and then add in the new
 | |
| // directory entries.
 | |
| //
 | |
|     list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE, this, 0 );
 | |
|     miCount = 0;
 | |
|     PreWriteDir();
 | |
|     ALEntry *job = old_list.GetFirstEntry();
 | |
|     while ( job ) {
 | |
|         if ( job->miMark ) {
 | |
|             miCount++;
 | |
|             WriteDirEntry( *job );
 | |
|         }
 | |
|         job = job->GetNextEntry();
 | |
|     }
 | |
|     job = list.GetFirstEntry();
 | |
|     while ( job ) {
 | |
|         if ( job->miMark ) {
 | |
|             miCount++;
 | |
|             WriteDirEntry( *job );
 | |
|         }
 | |
|         job = job->GetNextEntry();
 | |
|     }
 | |
|     PostWriteDir();
 | |
| //
 | |
| // Update the monitor, check for errors, then leave.
 | |
| //
 | |
|     list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 );
 | |
|     list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 );
 | |
|     ScanStatus( list );
 | |
|     return mStatus;
 | |
| }
 | |
| 
 | |
| #if !defined( AL_NO_C )
 | |
| 
 | |
| extern "C" AL_LINKAGE int AL_FUNCTION
 | |
| ALArchiveAppend( hALArchive this_object, hALEntryList list )  /* Tag public function */
 | |
| {
 | |
|     AL_ASSERT_OBJECT( this_object, ALArchive, "ALArchiveAppend" );
 | |
|     AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveAppend" );
 | |
|     return ((ALArchive *) this_object )->Append( *( (ALEntryList *) list ) );
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 |