// // EX18CON.CPP // // C++/DOS Example program for ArchiveLib 2.0 // // Copyright (c) Greenleaf Software, Inc. 1994 - 1996 // All Rights Reserved // // MEMBERS/FUNCTIONS DEMONSTRATED // // ALCompressedObject::ALCompressedObject() // ALCompressedObject::~ALCompressedObject() // ALCompressedObject::Extract() // ALCompressedObject::Insert() // ALStatus::GetStatusCode() // ALStatus::GetStatusString() // ALStatus::GetStatusDetail() // ALStatus::SetError(); // ALFileAttributes::PackedAttributes() // ALFileAttributes::SetFromDosAttributes() // ALFileAttributes::SetFromPackedAttributes() // ALStorage::SetTimeDate() // // DESCRIPTION // // This is another one of those example programs that ties together // a bunch of marginally related functions. It starts off by creating // a data file on disk, and writing some fixed patterns out to it. Next, // the data file gets inserted into a compressed object, also on disk. // Then the weird part: If a random number hits, I randomly change a // byte in the compressed object. Finally, I extract the original data // file from the compressed object, for better or worse. // // After this is all done, I have three TMP files on the disk. In an // imitation of what you might do in a real debugging situation, I check // to see if the input and output match. If they do match, I just go // ahead and delete them, all is well. If they don't match, I want to // hang on to the files. Not only do I hang on to the files, I give // them a funny time date stamp, and set them to be read-only. // // REVISION HISTORY // // February 1, 1996 2.0A : Second release // // #include #include #include #include "al.h" main() { ALFile DataFile; ALFile CompressedFile; ALFile OutputFile; cout << "Archive Library 2.0\nEX18CON.CPP\n\n"; cout << "This is another one of those example programs that ties together\n"; cout << "a bunch of marginally related functions. It starts off by creating\n"; cout << "a data file on disk, and writing some fixed patterns out to it. Next,\n"; cout << "the data file gets inserted into a compressed object, also on disk.\n"; cout << "Then the weird part: If a random number hits, I randomly change a\n"; cout << "byte in the compressed object. Finally, I extract the original data\n"; cout << "file from the compressed object, for better or worse.\n\n"; getch(); #if defined( AL_ZIP ) ALPkCompressor Compressor( 3 ); ALPkDecompressor Decompressor; #else ALGlCompressor Compressor( AL_GREENLEAF_LEVEL_4 ); ALGlDecompressor Decompressor; #endif ALCompressedObject *CompressedObject; // // Here is where I create the input data file and the compressed object. // This is all fairly realistic, you could write code that looks a lot // like this. // CompressedObject = new ALCompressedObject( CompressedFile, &Compressor, &Decompressor ); DataFile.Create(); // Temporary file for ( int i = 0 ; i < 64 ; i++ ) for ( int j = i; j < 64 ; j++ ) DataFile.WriteChar( j ); DataFile.Close(); CompressedObject->Insert( DataFile ); // // If the one in four chance hits, I change a single byte in the compressed // file. This will almost always cause an expansion error, although it // is possible to create a benign change (like the 1/256 chance that you // write over the old byte with a new byte that is the same!) // srand( (unsigned) time( NULL ) ); if ( (rand() & 3) == 0 ) { cout << "Mangling the compressed file!\n"; CompressedFile.Open(); CompressedFile.Seek( 32 + ( rand() & 31 )); CompressedFile.WriteChar( rand() & 0xff ); CompressedFile.Close(); } // // Now I try to extract the output file. Once I have done that, I perform // a compare to the original to see how things went. Note that there is // a tricky bit here. The only time ALFile objects will get new time/date // and attribute stamps is if they are closed immediately after having been // created. The CompressedObject->Extract() call will create the file, // then close it. Once it is closed, the flag indicating that it was just // created will be cleared, so I won't be able to set the time stamp. But, // if *I* create it here, the Extract() function will leave it open after // performing its magic. After it returns, I have to close the file, // but I can mung the time/date stamp first. // OutputFile.Create(); //I need to do this in order to set the time and atts CompressedObject->Extract( OutputFile ); OutputFile.Seek( 0L ); int status = DataFile.Compare( OutputFile ); cout << "Compare returned : " << status << "\n"; // // If the comparison passed, I just delete all of the TMP files created // here. (Note that they all have TMP names because I didn't give them // any names in their constructors.) // if ( status >= 0 ) { DataFile.Delete(); CompressedFile.Delete(); OutputFile.Close(); OutputFile.Delete(); } else { // // If the comparison failed, I am going to set their time/date stamps and // their attributes, using one of two methods. Note that the Close() // routine will only set their attributes if the files have a valid // time/date stamp. Since they are newly created, they don't have one // yet. So I have to cook one up here. // cout << "Object " << ( OutputFile.mTimeDate.Valid() ? "has" : "does not have" ) << " a valid time stamp\n"; struct tm* tblock; time_t t; t = time( 0 ); tblock = localtime( &t ); if ( tblock->tm_sec > 30 ) { tblock->tm_year--; OutputFile.mTimeDate.SetTimeDate( tblock ); cout << "Setting time stamp using tblock\n"; } else { cout << "Setting time stamp using a long\n"; OutputFile.mTimeDate.SetTimeDate( 20L*365L*24L*60L*60L + 5L*24L*60L*60L + 12L*60L*60L ); // Might be 1/1/1990 } short unsigned int atts = OutputFile.mAttributes.PackedAttributes(); atts = (short unsigned int)( atts | 1 ); OutputFile.mAttributes.SetFromPackedAttributes( atts ); //Make it Read Only OutputFile.Close(); CompressedObject->mStatus.SetError( status, DataFile.mStatus.GetStatusDetail() ); } cout << "Compressed object status code: " << CompressedObject->mStatus.GetStatusCode() << "\n"; cout << "Compressed object status string: " << CompressedObject->mStatus.GetStatusString() << "\n"; cout << "Compressed object status detail: " << CompressedObject->mStatus.GetStatusDetail() << "\n"; delete CompressedObject; return status; }