--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/centralrepository/convtool/src/CentRepConvTool.cpp Fri Jan 22 11:06:30 2010 +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 <e32const.h>
+#include <e32debug.h>
+#include <bautils.h>
+#include <s32file.h>
+#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<TInt>(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\\]<repositoryUID>.txt\r\n");
+ _LIT(KHelpMsg, "Usage: CentRepConv [-o output_path] [input_path\\]<repositoryUID>.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\]<rep_UID>.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 && i<KNumDigitsInUID; i++)
+ {
+ if (lex.Peek().IsHexDigit())
+ {
+ lex.Inc();
+ }
+ else
+ {
+ validName = EFalse;
+ }
+ } // for
+ } // if validName
+
+ if (!validName)
+ {
+ _LIT(KBadRepUid, "Input filename in %S is not a valid UID.\r\nExpect 8 hex digits.\r\n");
+ RDebug::Print(KCentRepConvTool);
+ RDebug::Print(KBadRepUid, &iCmd);
+
+ iScrnOutput->Printf(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<KFilePlusExtLen> 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;
+ }