diff -r 000000000000 -r bde4ae8d615e os/persistentdata/persistentstorage/centralrepository/convtool/src/CentRepConvTool.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/persistentdata/persistentstorage/centralrepository/convtool/src/CentRepConvTool.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,474 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include +#include +#include "CentRepConvTool.h" +#include "shrepos.h" +#include "inifile.h" +#include "srvres.h" +#include "srvparams.h" + + +_LIT(KCentRepConvTool, "CentRep Conversion Tool:"); + +const TInt KNumDigitsInUID = 8; + +// +// factory method +CCentRepConvTool* CCentRepConvTool::NewL(const TDesC& aCmd, RFs& aFs, TBool aWaitForAck) + { + CCentRepConvTool* self = new(ELeave) CCentRepConvTool(aCmd, aFs); + CleanupStack::PushL(self); + self->ConstructL(aWaitForAck); + CleanupStack::Pop(self); + return self; + } + +// +// Constructor +CCentRepConvTool::CCentRepConvTool(const TDesC& aCmd, RFs& aFs) + : iCmd(aCmd), iFs(aFs), iTextToBin(ETrue), iRepUid(KNullUid), + iMyDataCage(KNullDesC), iDefaultPath(KNullDesC) + { + } + +// +// two phase construct +void CCentRepConvTool::ConstructL(TBool aWaitForAck) + { + iScrnOutput = CConsolePrint::NewL(aWaitForAck); + iFs.PrivatePath(iMyDataCage); + + // set default I/O path + _LIT(KDefaultPathMask, "_:\\"); + iDefaultPath.Copy(KDefaultPathMask); + iDefaultPath[0] = 'A' + static_cast(RFs::GetSystemDrive()); + } + +// +// destructor +CCentRepConvTool::~CCentRepConvTool() + { + delete iScrnOutput; + delete iCentRepShrepos; + } + +// +// setter +void CCentRepConvTool::SetOutputMode(TBool aWaitForAck) + { + iScrnOutput->SetWaitMode(aWaitForAck); + } + +// +// Extract input and output path from cmd line, determine text to +// binary or binary to text, and invoke code in CentRep server classes +// to do conversion. +void CCentRepConvTool::ProcessCmdL() + { + _LIT(KSuccessMsg,"Output saved as: %S\r\n"); + + TPtrC inputPath(KNullDesC); + TPtrC outputPath(KNullDesC); + ParseCmdLineL(inputPath, outputPath); + + // default input & output path is system drive root folder + + iInputPath.Set(inputPath, NULL, NULL); + if (!iInputPath.DrivePresent() && !iInputPath.PathPresent()) + { + iInputPath.Set(inputPath, NULL, &iDefaultPath); + } + + iOutputPath.Set(outputPath, NULL, NULL); + if (!iOutputPath.DrivePresent() && !iOutputPath.PathPresent()) + { + iOutputPath.Set(outputPath, NULL, &iDefaultPath); + } + + // VerifyInputPathL must be call before VerifyOutputPathL! + VerifyInputPathL(); + VerifyOutputPathL(); + + // Get UID from input filename + TLex lex(iInputPath.Name()); + TUint32 intvalue; + lex.Val(intvalue, EHex); + iRepUid.iUid = intvalue; + + TRAPD(err, DoConversionL()); + if (err != KErrNone) + { + if (err == KErrCorrupt) + { + _LIT(KCorruptError, "Input file contains corrupted entries.\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KCorruptError); + iScrnOutput->Printf(KCorruptError); + } + User::Leave(err); + } + + // Success + iScrnOutput->Printf(KSuccessMsg, &(iOutputPath.FullName())); + } + +// +void CCentRepConvTool::DoConversionL() + { + iCentRepShrepos = CSharedRepository::NewL(iRepUid); + + if (iTextToBin) + { + HBufC* tempIniFileName = iInputPath.FullName().AllocLC(); + CIniFileIn* iniFile = NULL; + TInt ret=CIniFileIn::NewLC(iFs,iniFile,*tempIniFileName); + if (ret==KErrCorrupt) + User::LeaveIfError(iFs.Delete(*tempIniFileName)); + User::LeaveIfError(ret); + User::LeaveIfError(iCentRepShrepos->ReloadContentL(*iniFile)); + CleanupStack::PopAndDestroy(2); // tempIniFileName, iniFile + ExternalizeToCreL(); + } + else + { + CDirectFileStore* store = CDirectFileStore::OpenLC(iFs, + iInputPath.FullName(), EFileRead|EFileShareReadersOnly); + if (store->Type()[0] != KDirectFileStoreLayoutUid) + { + CleanupStack::PopAndDestroy(store); + User::Leave(KErrCorrupt); + } + + // Get the root stream and attempt to read the index from it + TStreamId rootStreamId = store->Root() ; + RStoreReadStream rootStream ; + rootStream.OpenLC(*store, rootStreamId); + // Internalize the repository +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + TUint8 creVersion; +#endif + iCentRepShrepos->InternalizeCreL(rootStream +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + ,creVersion +#endif + ); + CleanupStack::PopAndDestroy(&rootStream); + CleanupStack::PopAndDestroy(store); + + iCentRepShrepos->DoCommitChangesToIniFileL(iOutputPath.FullName() +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + ,creVersion +#endif + ); + } + } + +// +// Extract input path and output path from cmd line +void CCentRepConvTool::ParseCmdLineL(TPtrC& aInputPath, TPtrC& aOutputPath) + { + _LIT(KNoWaitSwitch, "-nowait"); + _LIT(KOutpathSwitch, "-o"); + _LIT(KHelpSwitch, "-h"); + _LIT(KBadArg, "Bad input arguments: %S\r\nUsage: CentRepConv [-o output_path] [input_path\\].txt\r\n"); + _LIT(KHelpMsg, "Usage: CentRepConv [-o output_path] [input_path\\].txt\r\nDefault output_path=%S\r\nDefault input_path=%S\r\n"); + + const TInt KMaxNumTokens = 8; // Arbitrary. only expect 4. + TPtrC tokens[KMaxNumTokens]; + TLex lex(iCmd); + TInt i; + for (i = 0; !lex.Eos() && i < KMaxNumTokens; i++) + { + tokens[i].Set(lex.NextToken()); + } + + TInt numTokens = i; + + // Expect: [-nowait] [-o output_path] [input_path\].txt + for (i = 0; i < numTokens; i++) + { + if (tokens[i].CompareF(KOutpathSwitch) == 0) + { + // Got the -o switch. + if ((i+2) < numTokens) + { + aOutputPath.Set(tokens[i+1]); + aInputPath.Set(tokens[i+2]); + } + break; + } // tokens[i] == "-o" + else if (tokens[i].CompareF(KNoWaitSwitch) == 0) + { + SetOutputMode(EFalse); + continue; + } + else if (tokens[i].FindF(KHelpSwitch) == 0) + { + numTokens = 0; // indicator for help message + break; + } + else if ('-' == tokens[i][0]) + { + continue; // unknown switch, assume intended for system + } + + // No options. Token must be input file name. + aInputPath.Set(tokens[i]); + break; + } // for + + if (0 == numTokens) + { + RDebug::Print(KCentRepConvTool); + RDebug::Print(KHelpMsg, &iDefaultPath, &iDefaultPath); + + iScrnOutput->Printf(KHelpMsg, &iDefaultPath, &iDefaultPath); + User::Leave(KErrArgument); + } + + // aOutputPath can be blank but aInputPath is mandatory. + if (aInputPath.Length() == 0) + { + RDebug::Print(KCentRepConvTool); + RDebug::Print(KBadArg, &iCmd); + + iScrnOutput->Printf(KBadArg, &iCmd); + User::Leave(KErrArgument); + } + } + +// +// Validate the input filenames. +void CCentRepConvTool::VerifyInputPathL() + { + // Check input file is .txt or .cre + iTextToBin = (iInputPath.Ext().CompareF(*TServerResources::iIniExt) == 0); + TBool binInput = !iTextToBin && (iInputPath.Ext().CompareF(*TServerResources::iCreExt) == 0); + + if (!iTextToBin && !binInput) + { + _LIT(KBadExt, "Bad input filename: %S\r\nInput file extension must be %S or %S\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KBadExt, &iCmd, TServerResources::iIniExt, + TServerResources::iCreExt); + + iScrnOutput->Printf(KBadExt, &iCmd, TServerResources::iIniExt, + TServerResources::iCreExt); + User::Leave(KErrArgument); + } + + // check input filename is 8 hex digits. + TPtrC p(iInputPath.Name()); + TBool validName = (KNumDigitsInUID == p.Length()); + + if (validName) + { + TLex lex(p); + for (TInt i = 0; validName && iPrintf(KBadRepUid, &iCmd); + User::Leave(KErrArgument); + } + + p.Set(iInputPath.FullName()); + + if ( InOthersPrivatePath(p) ) + { + _LIT(KInfileCaged, "Cannot access input file %S because it is in private data cage.\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KInfileCaged, &p); + + iScrnOutput->Printf(KInfileCaged, &p); + User::Leave(KErrAccessDenied); + } + + if (!BaflUtils::FileExists(iFs, p)) + { + _LIT(KInFileNotExists, "Input file %S does not exist.\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KInFileNotExists, &p); + + iScrnOutput->Printf(KInFileNotExists, &p); + User::Leave(KErrNotFound); + } + } + +// +// Validate the output filenames. +void CCentRepConvTool::VerifyOutputPathL() +{ + // If output filename is not specified, fill in the missing parts. + TBool EmptyOutFileName = EFalse; + + TPtrC outFileName(iOutputPath.Name()); + if (outFileName.Length()) + { + if (0 != outFileName.CompareF(iInputPath.Name())) + { + _LIT(KUnmatchFilenames, "Bad input: %S\r\nInput filename does not match output filename.\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KUnmatchFilenames, &iCmd); + + iScrnOutput->Printf(KUnmatchFilenames, &iCmd); + User::Leave(KErrArgument); + } + } + else + { + EmptyOutFileName = ETrue; + outFileName.Set(iInputPath.Name()); + } + + + TPtrC correctExt(*TServerResources::iCreExt); + TPtrC outFileExt(iOutputPath.Ext()); + if (!iTextToBin) + { + correctExt.Set(*TServerResources::iIniExt); + } + + if (outFileExt.Length()) + { + // If output filename is specified, extension should match conversion. + if (0 != outFileExt.CompareF(correctExt)) + { + _LIT(KUnmatchExt, "Bad input: %S\r\nExtension of output filename not valid.\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KUnmatchExt, &iCmd); + + iScrnOutput->Printf(KUnmatchExt, &iCmd); + User::Leave(KErrArgument); + } + } + else + { + EmptyOutFileName = ETrue; + outFileExt.Set(correctExt); + } + + TPtrC p; + + if (EmptyOutFileName) + { + const TInt KFilePlusExtLen = KNumDigitsInUID + 4; // e.g. 01234567.cre + TBuf newName(outFileName); + newName.Append(correctExt); + + p.Set(iOutputPath.DriveAndPath()); + TParse newpath; + newpath.Set(newName, NULL, &p); + + p.Set(newpath.FullName()); + iOutputPath.Set(p, NULL, NULL); + } + + // Check output file is in other's private data cage + p.Set(iOutputPath.FullName()); + if ( InOthersPrivatePath(p) ) + { + _LIT(KOutfileInDataCage, "Cannot write output file %S because it is in private data cage.\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KOutfileInDataCage, &p); + + iScrnOutput->Printf(KOutfileInDataCage, &p); + User::Leave(KErrAccessDenied); + } + + // Check saving output to read only drive. + p.Set(iOutputPath.DriveAndPath()); + TBool isReadOnly; + TInt ret; + ret = BaflUtils::DiskIsReadOnly(iFs, p, isReadOnly); + if (ret == KErrNone) + { + if (isReadOnly) + { + _LIT(KWriteToReadOnly, "Bad argument: output dir %S is in read only drive.\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KWriteToReadOnly, &p); + + iScrnOutput->Printf(KWriteToReadOnly, &p); + User::Leave(KErrArgument); + } + } + + ret = iFs.MkDirAll(p); + if (ret != KErrNone && ret != KErrAlreadyExists) + { + _LIT(KCreateOutpathFail, "Create output path %S failed, err %d.\r\n"); + RDebug::Print(KCentRepConvTool); + RDebug::Print(KCreateOutpathFail, &p, ret); + + iScrnOutput->Printf(KCreateOutpathFail, &p, ret); + User::Leave(ret); + } + } + +// +// Open a RWriteStream on top of a CDirectFileStore. Call +// CSharedRepository's ExternalizeCre method to write the +// settings to file. +void CCentRepConvTool::ExternalizeToCreL() + { + // Create file store + CDirectFileStore* store = CDirectFileStore::ReplaceLC(iFs, + iOutputPath.FullName(), (EFileWrite | EFileShareExclusive)); + const TUid uid2 = KNullUid; + store->SetTypeL(TUidType(KDirectFileStoreLayoutUid, uid2, KServerUid3)) ; + + // Write the stream index/dictionary as root stream within the store + // so we can access it when we do a restore later on + RStoreWriteStream rootStream ; + TStreamId rootStreamId = rootStream.CreateLC(*store) ; + iCentRepShrepos->ExternalizeCre(rootStream); + rootStream.CommitL(); + + CleanupStack::PopAndDestroy(&rootStream) ; + store->SetRootL(rootStreamId); + store->CommitL(); + CleanupStack::PopAndDestroy(store); + } + +// +// Check if given path is located in some other process's +// private data cage +TBool CCentRepConvTool::InOthersPrivatePath(const TDesC& aFullPathName) + { + _LIT(KPrivate, "\\private\\"); + const TInt KPosAfterDrive = 2; + return aFullPathName.FindF(KPrivate) == KPosAfterDrive && + aFullPathName.FindF(iMyDataCage) == KErrNotFound; + }