--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/fzip/fzip.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,393 @@
+// fzip.cpp
+//
+// Copyright (c) 2008 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+
+#include <zipfile.h>
+#include <ezgzip.h>
+#include "fzip.h"
+
+_LIT(KGzExtension, ".gz");
+
+CCommandBase* CCmdZip::NewLC()
+ {
+ CCmdZip* self = new (ELeave) CCmdZip();
+ CleanupStack::PushL(self);
+ self->BaseConstructL();
+ return self;
+ }
+
+CCmdZip::~CCmdZip()
+ {
+ if (iFileToZip.Count() > 0)
+ iFileToZip.Close();
+ }
+
+CCmdZip::CCmdZip() : CCommandBase(CCommandBase::EManualComplete)
+ {
+ }
+
+const TDesC& CCmdZip::Name() const
+ {
+ _LIT(KName, "fzip");
+ return KName;
+ }
+
+void CCmdZip::DoRunL()
+ {
+ FsL();
+ if (iUnzip)
+ {
+ if (!iOptions.IsPresent(&iUnzipPath))
+ {
+ iUnzipPath = Env().Pwd();
+ }
+
+ if (iVerbose)
+ {
+ // command-line sanity checks
+ if (iFileToZip.Count() > 0)
+ {
+ PrintWarning(_L("Ignoring \'-f\' file option."));
+ }
+ if (iRecurse)
+ {
+ PrintWarning(_L("Ignoring \'-r\' recurse option."));
+ }
+ }
+ TRAPL(ExpandArchiveL(), _L("Couldn't expand archive"));
+ }
+ else
+ {
+ if (iVerbose)
+ {
+ // command-line sanity checks
+ if (iUnzipPath.Length() > 0)
+ {
+ PrintWarning(_L("Ignoring '-d' directory option."));
+ }
+ }
+ if (iFileToZip.Count() == 0)
+ {
+ PrintError(KErrArgument, _L("Use '-f' to specify source files."));
+ User::Leave(KErrArgument);
+ }
+ TRAPD(err, CreateArchiveL());
+ if (err != KErrNone)
+ {
+ PrintError(err, _L("Couldn't create archive"));
+ Fs().Delete(iArchive); // ignore error
+ User::Leave(err);
+ }
+ }
+ if (iVerbose)
+ {
+ Printf(_L("Done\r\n"));
+ }
+ Complete(KErrNone);
+ }
+
+void CCmdZip::ArgumentsL(RCommandArgumentList& aArguments)
+ {
+ _LIT(KArg1, "archive");
+ aArguments.AppendFileNameL(iArchive, KArg1);
+ }
+
+void CCmdZip::OptionsL(RCommandOptionList& aOptions)
+ {
+ _LIT(KOptVerbose, "verbose");
+ aOptions.AppendBoolL(iVerbose, KOptVerbose);
+
+ _LIT(KOptUnzip, "unzip");
+ aOptions.AppendBoolL(iUnzip, KOptUnzip);
+
+ _LIT(KOptDirectory, "directory");
+ aOptions.AppendFileNameL(iUnzipPath, KOptDirectory);
+
+ _LIT(KOptRecurse, "recurse");
+ aOptions.AppendBoolL(iRecurse, KOptRecurse);
+
+ _LIT(KOptSource, "file");
+ aOptions.AppendFileNameL(iFileToZip, KOptSource);
+
+ _LIT(KOptCompressionType, "compression-type");
+ aOptions.AppendEnumL((TInt&)iCompressionType, KOptCompressionType);
+ }
+
+
+//
+// COMPRESSION FUNCTIONS
+//
+
+//
+// CCmdZip::CreateArchiveL
+// determine which zip format to use and go ahead & create the archive
+//
+void CCmdZip::CreateArchiveL()
+ {
+ if (iCompressionType == EGZip)
+ {
+ CreateGzArchiveL();
+ }
+ else
+ {
+ CreateZipArchiveL();
+ }
+ }
+
+//
+// CCmdZip::CreateGzArchiveL
+// create an archive, zipping up all the specified files
+//
+void CCmdZip::CreateGzArchiveL()
+ {
+ if (iRecurse)
+ {
+ LeaveIfErr(KErrArgument, _L("GNU Zip format does not support recursion"));
+ }
+
+ if (iFileToZip.Count() > 1)
+ {
+ LeaveIfErr(KErrArgument, _L("GNU Zip format can only handle a single file"));
+ }
+
+ if (iArchive.Length() == 0)
+ {
+ iArchive = iFileToZip[0];
+ iArchive.Append(KGzExtension);
+ }
+
+ RFile input;
+ if (iVerbose)
+ {
+ Printf(_L("Creating '%S'\r\n"), &iArchive);
+ }
+
+ // open the input file
+ User::LeaveIfError(input.Open(Fs(), iFileToZip[0], EFileStream | EFileRead | EFileShareAny));
+ CleanupClosePushL(input);
+
+ CEZFileToGZip* zip = CEZFileToGZip::NewLC(Fs(), iArchive, input);
+ while (zip->DeflateL())
+ {
+ // do nothing
+ }
+ if (iVerbose)
+ {
+ Printf(_L("Deflating '%S'\r\n"), &iFileToZip[0]);
+ }
+
+ CleanupStack::PopAndDestroy(2); // zip, input
+ }
+
+//
+// CCmdZip::CreateZipArchiveL
+// zip format archive creation
+//
+void CCmdZip::CreateZipArchiveL()
+ {
+ CZipItUp* zipArchive = CZipItUp::NewLC(Fs(), iArchive);
+ for (TInt ii = 0 ; ii < iFileToZip.Count() ; ii++)
+ {
+ TFileName2& fileName = iFileToZip[ii];
+ fileName.SetTypeL(Fs());
+ AddFileL(*zipArchive, fileName);
+ }
+ zipArchive->CreateZipL();
+ if (iVerbose)
+ {
+ Printf(_L("Created '%S'\r\n"), &iArchive);
+ }
+ CleanupStack::PopAndDestroy(); // zipArchive
+ }
+
+//
+// CCmdZip::AddFileL
+// examines a file for wildcards, directories/recursion etc
+// if it finds an actual file, it'll add it to the zip archive
+// recursive function
+//
+void CCmdZip::AddFileL(CZipItUp& aZipArchive, const TFileName2& aFile)
+ {
+ if (aFile.IsDir())
+ {
+ CDir* dir;
+ LeaveIfErr(Fs().GetDir(aFile, KEntryAttMatchMask, EDirsLast, dir), _L("Unable to read directory '%S'"), &aFile);
+ CleanupStack::PushL(dir);
+ for (TInt ii = 0 ; ii < dir->Count() ; ii++)
+ {
+ const TEntry& entry = (*dir)[ii];
+ TFileName2* newFile = new(ELeave) TFileName2(entry.iName);
+ CleanupStack::PushL(newFile);
+ newFile->MakeAbsoluteL(aFile.DriveAndPath());
+ newFile->SetTypeL(Fs());
+ if (newFile->IsDir())
+ {
+ if (iRecurse)
+ {
+ AddFileL(aZipArchive, *newFile);
+ }
+ }
+ else
+ {
+ AddFileL(aZipArchive, *newFile);
+ }
+ CleanupStack::PopAndDestroy(newFile);
+ }
+ CleanupStack::PopAndDestroy(dir);
+ }
+ else
+ {
+ if (iVerbose)
+ {
+ Printf(_L("Adding '%S'\r\n"), &aFile);
+ }
+ aZipArchive.AddFileL(aFile);
+ }
+ }
+
+
+//
+// DECOMPRESSION FUNCTIONS
+//
+
+//
+// CCmdZip::ExpandArchiveL
+// determine which zip format to use and go ahead & expand the archive
+//
+void CCmdZip::ExpandArchiveL()
+ {
+ if (iCompressionType == EGZip)
+ {
+ ExpandGzArchiveL();
+ }
+ else
+ {
+ ExpandZipArchiveL();
+ }
+ }
+
+//
+// CCmdZip::ExpandGzArchiveL
+// unzip an existing gzip compressed file
+//
+void CCmdZip::ExpandGzArchiveL()
+ {
+ // open the destination file, determine where it goes
+ RFile newFile;
+ TFileName2 dest(iUnzipPath);
+ if (iVerbose)
+ {
+ Printf(_L("Opening\t\t\'%S\'\r\n"), &iArchive);
+ }
+ if (iArchive.Ext().CompareF(KGzExtension) != 0)
+ {
+ LeaveIfErr(KErrArgument, _L("Compressed file must have '.gz' extension."));
+ }
+ dest.AppendComponentL(iArchive.Name());
+ TInt err = Fs().MkDirAll(dest);
+ if ((err != KErrNone) && (err != KErrAlreadyExists))
+ {
+ LeaveIfErr(err, _L("Couldn't create path '%S'"), &dest);
+ }
+ User::LeaveIfError(newFile.Replace(Fs(), dest, EFileStream | EFileRead | EFileShareAny));
+ CleanupClosePushL(newFile);
+
+ // inflate the compressed file
+ CEZGZipToFile* zip = CEZGZipToFile::NewLC(Fs(), iArchive, newFile);
+ while (zip->InflateL())
+ {
+ // do nothing
+ }
+ if (iVerbose)
+ {
+ Printf(_L("Inflating '%S'\r\n"), &dest);
+ }
+ CleanupStack::PopAndDestroy(2); // zip, newFile
+ }
+
+//
+// CCmdZip::ExpandZipArchiveL
+// Unzip an existing archive iterating through each member file contained within the archive
+//
+void CCmdZip::ExpandZipArchiveL()
+ {
+ if (iVerbose)
+ {
+ Printf(_L("Opening\t\t\'%S\'\r\n"), &iArchive);
+ }
+ CZipFile* zip = CZipFile::NewL(Fs(), iArchive);
+ CleanupStack::PushL(zip);
+ CZipFileMemberIterator* zipIterator = zip->GetMembersL();
+ CleanupStack::PushL(zipIterator);
+ CZipFileMember* zipMember = zipIterator->NextL();
+ while (zipMember)
+ {
+ CleanupStack::PushL(zipMember);
+ ExtractZipFileL(*zip, *zipMember);
+ CleanupStack::PopAndDestroy(zipMember);
+ zipMember = zipIterator->NextL();
+ }
+ CleanupStack::PopAndDestroy(2); // zipIterator, zip
+ }
+
+//
+// CCmdZip::ExtractZipFileL
+// extracts a single file from within the zip archive
+//
+void CCmdZip::ExtractZipFileL(CZipFile& aZip, const CZipFileMember& aMember)
+ {
+ // prep. the stream
+ RZipFileMemberReaderStream* readStream;
+ aZip.GetInputStreamL(&aMember, readStream);
+ CleanupStack::PushL(readStream);
+ // prep. the destination file.
+ // note if iUnzipPath is not specified, it'll stuff the extracted file in the current directory from which fzip.exe runs
+ RFile newFile;
+ TFileName2 dest(iUnzipPath);
+ dest.AppendComponentL(*aMember.Name());
+ TInt err = Fs().MkDirAll(dest);
+ if ((err != KErrNone) && (err != KErrAlreadyExists))
+ {
+ User::Leave(err);
+ }
+ User::LeaveIfError(newFile.Replace(Fs(), dest, EFileShareExclusive));
+ CleanupClosePushL(newFile);
+ if (iVerbose)
+ {
+ Printf(_L("Inflating '%S'\r\n\tcrc: 0x%x\r\n\tcompressed size: %d\r\n\tuncompressed size: %d\r\n"), &dest, aMember.CRC32(), aMember.CompressedSize(), aMember.UncompressedSize());
+ }
+
+ // stream from the zip archive member into the destination file
+ TInt bytesRead = 0;
+ TInt length = KDefaultZipBufferLength; // 32Kb
+ if (aMember.UncompressedSize() < KDefaultZipBufferLength)
+ {
+ length = aMember.UncompressedSize();
+ }
+ HBufC8* data = HBufC8::NewLC(length);
+ TPtr8 ptr = data->Des();
+ do
+ {
+ User::LeaveIfError(readStream->Read(ptr, length));
+ User::LeaveIfError(newFile.Write(ptr));
+ bytesRead += length;
+ if ((aMember.UncompressedSize() - bytesRead) < KDefaultZipBufferLength)
+ {
+ length = aMember.UncompressedSize() - bytesRead;
+ }
+ } while (length > 0);
+
+ // cleanup
+ CleanupStack::PopAndDestroy(3); // data, newfile, readstream
+ }
+
+
+EXE_BOILER_PLATE(CCmdZip)