os/persistentdata/persistentstorage/centralrepository/convtool/src/CentRepConvTool.cpp
Update contrib.
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
20 #include "CentRepConvTool.h"
24 #include "srvparams.h"
27 _LIT(KCentRepConvTool, "CentRep Conversion Tool:");
29 const TInt KNumDigitsInUID = 8;
33 CCentRepConvTool* CCentRepConvTool::NewL(const TDesC& aCmd, RFs& aFs, TBool aWaitForAck)
35 CCentRepConvTool* self = new(ELeave) CCentRepConvTool(aCmd, aFs);
36 CleanupStack::PushL(self);
37 self->ConstructL(aWaitForAck);
38 CleanupStack::Pop(self);
44 CCentRepConvTool::CCentRepConvTool(const TDesC& aCmd, RFs& aFs)
45 : iCmd(aCmd), iFs(aFs), iTextToBin(ETrue), iRepUid(KNullUid),
46 iMyDataCage(KNullDesC), iDefaultPath(KNullDesC)
51 // two phase construct
52 void CCentRepConvTool::ConstructL(TBool aWaitForAck)
54 iScrnOutput = CConsolePrint::NewL(aWaitForAck);
55 iFs.PrivatePath(iMyDataCage);
57 // set default I/O path
58 _LIT(KDefaultPathMask, "_:\\");
59 iDefaultPath.Copy(KDefaultPathMask);
60 iDefaultPath[0] = 'A' + static_cast<TInt>(RFs::GetSystemDrive());
65 CCentRepConvTool::~CCentRepConvTool()
68 delete iCentRepShrepos;
73 void CCentRepConvTool::SetOutputMode(TBool aWaitForAck)
75 iScrnOutput->SetWaitMode(aWaitForAck);
79 // Extract input and output path from cmd line, determine text to
80 // binary or binary to text, and invoke code in CentRep server classes
82 void CCentRepConvTool::ProcessCmdL()
84 _LIT(KSuccessMsg,"Output saved as: %S\r\n");
86 TPtrC inputPath(KNullDesC);
87 TPtrC outputPath(KNullDesC);
88 ParseCmdLineL(inputPath, outputPath);
90 // default input & output path is system drive root folder
92 iInputPath.Set(inputPath, NULL, NULL);
93 if (!iInputPath.DrivePresent() && !iInputPath.PathPresent())
95 iInputPath.Set(inputPath, NULL, &iDefaultPath);
98 iOutputPath.Set(outputPath, NULL, NULL);
99 if (!iOutputPath.DrivePresent() && !iOutputPath.PathPresent())
101 iOutputPath.Set(outputPath, NULL, &iDefaultPath);
104 // VerifyInputPathL must be call before VerifyOutputPathL!
108 // Get UID from input filename
109 TLex lex(iInputPath.Name());
111 lex.Val(intvalue, EHex);
112 iRepUid.iUid = intvalue;
114 TRAPD(err, DoConversionL());
117 if (err == KErrCorrupt)
119 _LIT(KCorruptError, "Input file contains corrupted entries.\r\n");
120 RDebug::Print(KCentRepConvTool);
121 RDebug::Print(KCorruptError);
122 iScrnOutput->Printf(KCorruptError);
128 iScrnOutput->Printf(KSuccessMsg, &(iOutputPath.FullName()));
132 void CCentRepConvTool::DoConversionL()
134 iCentRepShrepos = CSharedRepository::NewL(iRepUid);
138 HBufC* tempIniFileName = iInputPath.FullName().AllocLC();
139 CIniFileIn* iniFile = NULL;
140 TInt ret=CIniFileIn::NewLC(iFs,iniFile,*tempIniFileName);
141 if (ret==KErrCorrupt)
142 User::LeaveIfError(iFs.Delete(*tempIniFileName));
143 User::LeaveIfError(ret);
144 User::LeaveIfError(iCentRepShrepos->ReloadContentL(*iniFile));
145 CleanupStack::PopAndDestroy(2); // tempIniFileName, iniFile
150 CDirectFileStore* store = CDirectFileStore::OpenLC(iFs,
151 iInputPath.FullName(), EFileRead|EFileShareReadersOnly);
152 if (store->Type()[0] != KDirectFileStoreLayoutUid)
154 CleanupStack::PopAndDestroy(store);
155 User::Leave(KErrCorrupt);
158 // Get the root stream and attempt to read the index from it
159 TStreamId rootStreamId = store->Root() ;
160 RStoreReadStream rootStream ;
161 rootStream.OpenLC(*store, rootStreamId);
162 // Internalize the repository
163 #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
166 iCentRepShrepos->InternalizeCreL(rootStream
167 #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
171 CleanupStack::PopAndDestroy(&rootStream);
172 CleanupStack::PopAndDestroy(store);
174 iCentRepShrepos->DoCommitChangesToIniFileL(iOutputPath.FullName()
175 #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS
183 // Extract input path and output path from cmd line
184 void CCentRepConvTool::ParseCmdLineL(TPtrC& aInputPath, TPtrC& aOutputPath)
186 _LIT(KNoWaitSwitch, "-nowait");
187 _LIT(KOutpathSwitch, "-o");
188 _LIT(KHelpSwitch, "-h");
189 _LIT(KBadArg, "Bad input arguments: %S\r\nUsage: CentRepConv [-o output_path] [input_path\\]<repositoryUID>.txt\r\n");
190 _LIT(KHelpMsg, "Usage: CentRepConv [-o output_path] [input_path\\]<repositoryUID>.txt\r\nDefault output_path=%S\r\nDefault input_path=%S\r\n");
192 const TInt KMaxNumTokens = 8; // Arbitrary. only expect 4.
193 TPtrC tokens[KMaxNumTokens];
196 for (i = 0; !lex.Eos() && i < KMaxNumTokens; i++)
198 tokens[i].Set(lex.NextToken());
203 // Expect: [-nowait] [-o output_path] [input_path\]<rep_UID>.txt
204 for (i = 0; i < numTokens; i++)
206 if (tokens[i].CompareF(KOutpathSwitch) == 0)
208 // Got the -o switch.
209 if ((i+2) < numTokens)
211 aOutputPath.Set(tokens[i+1]);
212 aInputPath.Set(tokens[i+2]);
215 } // tokens[i] == "-o"
216 else if (tokens[i].CompareF(KNoWaitSwitch) == 0)
218 SetOutputMode(EFalse);
221 else if (tokens[i].FindF(KHelpSwitch) == 0)
223 numTokens = 0; // indicator for help message
226 else if ('-' == tokens[i][0])
228 continue; // unknown switch, assume intended for system
231 // No options. Token must be input file name.
232 aInputPath.Set(tokens[i]);
238 RDebug::Print(KCentRepConvTool);
239 RDebug::Print(KHelpMsg, &iDefaultPath, &iDefaultPath);
241 iScrnOutput->Printf(KHelpMsg, &iDefaultPath, &iDefaultPath);
242 User::Leave(KErrArgument);
245 // aOutputPath can be blank but aInputPath is mandatory.
246 if (aInputPath.Length() == 0)
248 RDebug::Print(KCentRepConvTool);
249 RDebug::Print(KBadArg, &iCmd);
251 iScrnOutput->Printf(KBadArg, &iCmd);
252 User::Leave(KErrArgument);
257 // Validate the input filenames.
258 void CCentRepConvTool::VerifyInputPathL()
260 // Check input file is .txt or .cre
261 iTextToBin = (iInputPath.Ext().CompareF(*TServerResources::iIniExt) == 0);
262 TBool binInput = !iTextToBin && (iInputPath.Ext().CompareF(*TServerResources::iCreExt) == 0);
264 if (!iTextToBin && !binInput)
266 _LIT(KBadExt, "Bad input filename: %S\r\nInput file extension must be %S or %S\r\n");
267 RDebug::Print(KCentRepConvTool);
268 RDebug::Print(KBadExt, &iCmd, TServerResources::iIniExt,
269 TServerResources::iCreExt);
271 iScrnOutput->Printf(KBadExt, &iCmd, TServerResources::iIniExt,
272 TServerResources::iCreExt);
273 User::Leave(KErrArgument);
276 // check input filename is 8 hex digits.
277 TPtrC p(iInputPath.Name());
278 TBool validName = (KNumDigitsInUID == p.Length());
283 for (TInt i = 0; validName && i<KNumDigitsInUID; i++)
285 if (lex.Peek().IsHexDigit())
298 _LIT(KBadRepUid, "Input filename in %S is not a valid UID.\r\nExpect 8 hex digits.\r\n");
299 RDebug::Print(KCentRepConvTool);
300 RDebug::Print(KBadRepUid, &iCmd);
302 iScrnOutput->Printf(KBadRepUid, &iCmd);
303 User::Leave(KErrArgument);
306 p.Set(iInputPath.FullName());
308 if ( InOthersPrivatePath(p) )
310 _LIT(KInfileCaged, "Cannot access input file %S because it is in private data cage.\r\n");
311 RDebug::Print(KCentRepConvTool);
312 RDebug::Print(KInfileCaged, &p);
314 iScrnOutput->Printf(KInfileCaged, &p);
315 User::Leave(KErrAccessDenied);
318 if (!BaflUtils::FileExists(iFs, p))
320 _LIT(KInFileNotExists, "Input file %S does not exist.\r\n");
321 RDebug::Print(KCentRepConvTool);
322 RDebug::Print(KInFileNotExists, &p);
324 iScrnOutput->Printf(KInFileNotExists, &p);
325 User::Leave(KErrNotFound);
330 // Validate the output filenames.
331 void CCentRepConvTool::VerifyOutputPathL()
333 // If output filename is not specified, fill in the missing parts.
334 TBool EmptyOutFileName = EFalse;
336 TPtrC outFileName(iOutputPath.Name());
337 if (outFileName.Length())
339 if (0 != outFileName.CompareF(iInputPath.Name()))
341 _LIT(KUnmatchFilenames, "Bad input: %S\r\nInput filename does not match output filename.\r\n");
342 RDebug::Print(KCentRepConvTool);
343 RDebug::Print(KUnmatchFilenames, &iCmd);
345 iScrnOutput->Printf(KUnmatchFilenames, &iCmd);
346 User::Leave(KErrArgument);
351 EmptyOutFileName = ETrue;
352 outFileName.Set(iInputPath.Name());
356 TPtrC correctExt(*TServerResources::iCreExt);
357 TPtrC outFileExt(iOutputPath.Ext());
360 correctExt.Set(*TServerResources::iIniExt);
363 if (outFileExt.Length())
365 // If output filename is specified, extension should match conversion.
366 if (0 != outFileExt.CompareF(correctExt))
368 _LIT(KUnmatchExt, "Bad input: %S\r\nExtension of output filename not valid.\r\n");
369 RDebug::Print(KCentRepConvTool);
370 RDebug::Print(KUnmatchExt, &iCmd);
372 iScrnOutput->Printf(KUnmatchExt, &iCmd);
373 User::Leave(KErrArgument);
378 EmptyOutFileName = ETrue;
379 outFileExt.Set(correctExt);
384 if (EmptyOutFileName)
386 const TInt KFilePlusExtLen = KNumDigitsInUID + 4; // e.g. 01234567.cre
387 TBuf<KFilePlusExtLen> newName(outFileName);
388 newName.Append(correctExt);
390 p.Set(iOutputPath.DriveAndPath());
392 newpath.Set(newName, NULL, &p);
394 p.Set(newpath.FullName());
395 iOutputPath.Set(p, NULL, NULL);
398 // Check output file is in other's private data cage
399 p.Set(iOutputPath.FullName());
400 if ( InOthersPrivatePath(p) )
402 _LIT(KOutfileInDataCage, "Cannot write output file %S because it is in private data cage.\r\n");
403 RDebug::Print(KCentRepConvTool);
404 RDebug::Print(KOutfileInDataCage, &p);
406 iScrnOutput->Printf(KOutfileInDataCage, &p);
407 User::Leave(KErrAccessDenied);
410 // Check saving output to read only drive.
411 p.Set(iOutputPath.DriveAndPath());
414 ret = BaflUtils::DiskIsReadOnly(iFs, p, isReadOnly);
419 _LIT(KWriteToReadOnly, "Bad argument: output dir %S is in read only drive.\r\n");
420 RDebug::Print(KCentRepConvTool);
421 RDebug::Print(KWriteToReadOnly, &p);
423 iScrnOutput->Printf(KWriteToReadOnly, &p);
424 User::Leave(KErrArgument);
428 ret = iFs.MkDirAll(p);
429 if (ret != KErrNone && ret != KErrAlreadyExists)
431 _LIT(KCreateOutpathFail, "Create output path %S failed, err %d.\r\n");
432 RDebug::Print(KCentRepConvTool);
433 RDebug::Print(KCreateOutpathFail, &p, ret);
435 iScrnOutput->Printf(KCreateOutpathFail, &p, ret);
441 // Open a RWriteStream on top of a CDirectFileStore. Call
442 // CSharedRepository's ExternalizeCre method to write the
444 void CCentRepConvTool::ExternalizeToCreL()
447 CDirectFileStore* store = CDirectFileStore::ReplaceLC(iFs,
448 iOutputPath.FullName(), (EFileWrite | EFileShareExclusive));
449 const TUid uid2 = KNullUid;
450 store->SetTypeL(TUidType(KDirectFileStoreLayoutUid, uid2, KServerUid3)) ;
452 // Write the stream index/dictionary as root stream within the store
453 // so we can access it when we do a restore later on
454 RStoreWriteStream rootStream ;
455 TStreamId rootStreamId = rootStream.CreateLC(*store) ;
456 iCentRepShrepos->ExternalizeCre(rootStream);
457 rootStream.CommitL();
459 CleanupStack::PopAndDestroy(&rootStream) ;
460 store->SetRootL(rootStreamId);
462 CleanupStack::PopAndDestroy(store);
466 // Check if given path is located in some other process's
468 TBool CCentRepConvTool::InOthersPrivatePath(const TDesC& aFullPathName)
470 _LIT(KPrivate, "\\private\\");
471 const TInt KPosAfterDrive = 2;
472 return aFullPathName.FindF(KPrivate) == KPosAfterDrive &&
473 aFullPathName.FindF(iMyDataCage) == KErrNotFound;