home *** CD-ROM | disk | FTP | other *** search
- // LZH file spliter. Uses best fit approach in C++. By Bill Ataras.
- //
- // This code is hereby public domain.
- //
- // I am an ASP member. I have two other products:
- //
- // 1. DFL (Duplicate File Locator). Does everything. Archives, CRCs,
- // system security scanning.
- // 2. PowerInstall. Excellent installation utility. Runs in 5 languages:
- // English, French, German, Italian and Spanish. A 6th, user-definable
- // language is available too. Also converts self-extracting archives to
- // self-extracting-installing archives with a windowed interface.
- // Both the installation and the self-extractor-installer interface can
- // auto-detect the customer's Dos country code and interface with him in
- // the proper language. This utility is used by Hewlett-Packard for
- // international distribution of Autocad plotter drivers. Also used by
- // Delta Airlines.
- //
- // For a fully-functional shareware copy of either of these programs, send $5
- // ($10 outside North America) per program to:
- //
- // William S. Ataras III
- // 1125 Balclutha Dr. #K108
- // Foster City, Ca. 94404
- //
- // Compuserve address: 70400,3542
- //
- // Thank you.
- //
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <io.h>
- #include <fcntl.h>
- #include <conio.h>
- #include <string.h>
- #include <share.h>
- #include <sys\stat.h>
-
-
- /*****************************************************************************
-
- Defines
-
- *****************************************************************************/
-
- #define BUFLEN 0x8000
- #define TRUE 1
- #define FALSE 0
-
-
- /*****************************************************************************
-
- Prototypes
-
- *****************************************************************************/
-
-
- /*****************************************************************************
-
- Data and variables
-
- *****************************************************************************/
-
- struct HEADER1
- {
- int garbage1;
- char garbage2 [ 5 ];
- long CompLen;
- long garbage3;
- char garbage4 [ 6 ];
- char NameLen;
- };
-
- struct HEADER2
- {
- char garbage1 [ 5 ];
- };
-
- struct LZHCHILD
- {
- long StartPos;
- int Handle, Opened;
-
- public:
-
- LZHCHILD *Next;
- long TotLen;
- int IsUsed;
-
- LZHCHILD ( int );
-
- void Copy ( int );
- };
-
-
- class LZHFILE
-
- {
- LZHCHILD *First;
- long ThisLen;
- int Handle,
- Reading;
- char *Name;
-
- public:
-
- int Opened;
-
- LZHFILE ( char *, int ); // Open and read LZH file
- ~LZHFILE (); // Close LZH file
-
- long Length () {return(ThisLen);}; // Get current filelength
- LZHCHILD *FindLE ( long ); // Next file <=
- int AnyGE ( long Len )
- {if(First&&First->TotLen>=Len) // Any files >= length ?
- return(1);return(0);};
- void Add ( LZHCHILD * ); // Write given file
- int AnyLeft (); // Any files left ?
- };
-
- char *Buffer = NULL;
-
- /*****************************************************************************
-
- CODE !
-
- *****************************************************************************/
-
-
- /*****************************************************************************
-
- Function : main
-
- Description : Main routine for LZH file spliter.
-
- Parameters : Command line:
-
- LZH filename.
- Size to split into.
-
- Returns : Nothing.
-
- *****************************************************************************/
-
- void main ( int argc, char **argv )
-
- {
- if ( argc < 3 )
- {
- puts ( "Usage: LZHSPLIT lzhfile fitlength" );
- puts ( "By: Bill Ataras" );
- puts ( "CIS: 70400,3542" );
- return;
- }
-
- Buffer = (char*)malloc ( BUFLEN );
-
- char Newfile [ 128 ];
- char *ch;
-
- strcpy ( Newfile, argv [ 1 ] );
- ch = strrchr ( Newfile, '.' );
-
- if ( !ch || strchr ( ch, '\\' ) ) strcat ( Newfile, ".LZH" );
-
- LZHFILE *Infile = new LZHFILE ( Newfile, 0 ); // Open for read
-
- if ( !Infile || !Buffer )
- {
- puts ( "Out of memory");
- return;
- }
-
- if ( !Infile->Opened )
- {
- delete Infile;
- printf ( "Can't open %s\n", Newfile );
- return;
- }
-
- char Outname [ 13 ];
- int Outcnt = 1;
- long Outlen = atol ( argv [ 2 ] );
- LZHCHILD *File = NULL;
-
- if ( Infile->AnyGE ( Outlen ) )
- {
- delete Infile;
- printf ( "There is a file in %s that is bigger than %ld\n",
- Newfile, Outlen );
- return;
- }
-
- while ( Infile->AnyLeft () )
- {
- sprintf ( Outname, "SPLIT%03d.LZH", Outcnt++ );
-
- LZHFILE *Outfile = new LZHFILE ( Outname, 1 ); // Create for write
-
- if ( !Outfile->Opened )
- {
- printf ( "Can't open %s\n", Outname );
- break;
- }
-
- printf ( "Writing %s -> ", Outname );
-
- while ( Outlen > Outfile->Length () && // Bytes left ?
- NULL != ( File = Infile->FindLE (Outlen-Outfile->Length()) ) )
- Outfile->Add ( File ); // Add file
-
- if ( Outfile->Length() > 1 )
- printf ( "%6ld bytes\n", Outfile->Length() );
- else
- printf ( "\r " );
-
- delete Outfile; // Done with this file
- }
-
- delete Infile;
-
- puts ( "Done." );
- }
-
- LZHCHILD::LZHCHILD ( int Fl )
-
- {
- HEADER1 h1;
- HEADER2 h2;
-
- Handle = Fl;
- Opened = FALSE;
- StartPos = tell ( Fl );
-
- if ( read ( Fl, &h1, sizeof ( h1 ) ) != sizeof ( h1 ) ) return;
- lseek ( Fl, h1.NameLen, SEEK_CUR );
- if ( read ( Fl, &h2, sizeof ( h2 ) ) != sizeof ( h2 ) ) return;
-
- lseek ( Fl, h1.CompLen, SEEK_CUR ); // Skip file data
-
- TotLen = h1.CompLen + sizeof ( h1 ) + sizeof ( h2 ) + h1.NameLen;
- Next = NULL;
- Opened = TRUE;
- IsUsed = FALSE;
- }
-
- void LZHCHILD::Copy ( int Fl )
-
- {
- lseek ( Handle, StartPos, SEEK_SET );
-
- long Tot = 0L;
-
- while ( Tot < TotLen )
- {
- unsigned Len = read ( Handle, Buffer, (long)BUFLEN<TotLen-Tot?BUFLEN:TotLen-Tot );
- write ( Fl, Buffer, Len );
- Tot += Len;
- }
-
- IsUsed = TRUE;
- }
-
-
- LZHFILE::LZHFILE ( char *File, int Create )
-
- {
- if ( Create )
- Handle = sopen ( File, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, SH_DENYWR, S_IWRITE );
- else
- Handle = sopen ( File, O_BINARY|O_RDONLY, SH_DENYWR, S_IREAD );
-
- if ( Handle < 0 )
- {
- Opened = FALSE;
- return;
- }
-
- Name = strdup ( File ); // Save name
-
- Reading = !Create;
- Opened = TRUE;
- First = NULL;
- ThisLen = Reading ? 0L : filelength ( Handle );
-
- if ( !Reading ) return;
-
- First = new LZHCHILD ( Handle );
-
- if ( !First || !First->Opened )
- {
- Opened = FALSE;
- return;
- }
-
- while ( TRUE ) // Read LZH file
- {
- LZHCHILD *Child = new LZHCHILD ( Handle );
-
- if ( !Child || !Child->Opened ) break;
-
- LZHCHILD *Find, *Prev = NULL;
-
- for ( Find = First; Find; Find = Find->Next )
- {
- if ( Child->TotLen > Find->TotLen ) // Add in descending order
- if ( Prev )
- {
- Prev->Next = Child;
- Child->Next = Find;
- break;
- }
- else
- {
- Child->Next = First;
- First = Child;
- break;
- }
-
- Prev = Find;
- }
-
- if ( !Find ) Prev->Next = Child;
- }
- }
-
- LZHFILE::~LZHFILE ()
-
- {
- if ( Reading )
- {
- LZHCHILD *Child, *Tmp;
-
- for ( Child = First; Child; ) // Kill Children
- {
- Tmp = Child;
- Child = Child->Next;
- delete Tmp;
- }
-
- close ( Handle );
- return;
- }
-
- if ( Length () )
- {
- lseek ( Handle, 0L, SEEK_END );
- char End = 0;
- write ( Handle, &End, 1 );
- close ( Handle );
- return;
- }
-
- close ( Handle );
- unlink ( Name );
- }
-
- LZHCHILD *LZHFILE::FindLE ( long Len )
-
- {
- LZHCHILD *Find;
-
- for ( Find = First;
- Find && ( Find->TotLen > Len || Find->IsUsed );
- Find = Find->Next );
-
- return ( Find );
- }
-
- void LZHFILE::Add ( LZHCHILD *Child )
-
- {
- if ( Reading ) return;
-
- Child->Copy ( Handle );
- ThisLen = filelength ( Handle ) + 1;
- }
-
- int LZHFILE::AnyLeft ()
-
- {
- LZHCHILD *Find;
-
- for ( Find = First; Find && Find->IsUsed; Find = Find->Next );
-
- return ( !(Find == NULL) );
- }
-