alex 714dd74636 Archive Library versione 2.00
git-svn-id: svn://10.65.10.50/trunk@5350 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-10-09 16:09:54 +00:00

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