sl@0: // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include <e32def.h> sl@0: #include <e32property.h> sl@0: #include <s32file.h> sl@0: #include <connect/sbdefs.h> sl@0: #include "srvres.h" sl@0: #include "cachemgr.h" sl@0: #include "srvparams.h" sl@0: #include "shrepos.h" sl@0: #include "sessnotf.h" sl@0: #include "backup.h" sl@0: sl@0: #define UNUSED_VAR(a) a = a sl@0: sl@0: _LIT (KBackupFileName, "BACKUP") ; sl@0: _LIT (KRestoreFileName, "RESTORE") ; sl@0: _LIT(KBackupFileExt, ".bak"); sl@0: _LIT(KRestoreFileExt, ".rst"); sl@0: sl@0: sl@0: TRepositoryBackupState CRepositoryBackupClient::iBackupStatus ; sl@0: sl@0: sl@0: // sl@0: // Backup stream index class - Used to hold association between a UID (in sl@0: // our case the UID of a repository) and a stream ID - Can't use CStreamDictionary sl@0: // because that only lets you retrieve stream IDs by a (previously known) UID rather sl@0: // than iterate through its contentsretrieving UID/StreamID pairs... sl@0: // sl@0: sl@0: sl@0: // sl@0: // CRepositoryBackupStreamIndex::AddL sl@0: // sl@0: // Add a new repository UID and stream ID pair to the index sl@0: void CRepositoryBackupStreamIndex::AddL(TUid aUid, TStreamId aSettingStreamId, TStreamId aDeletedSettingsStreamId, TStreamId aInstalledSettingsStreamId) sl@0: { sl@0: TRepositoryBackupStreamIndexElement newIndexElement; sl@0: newIndexElement.Set(aUid,aSettingStreamId, aDeletedSettingsStreamId, aInstalledSettingsStreamId) ; sl@0: iStreamIndex.AppendL(newIndexElement); sl@0: } sl@0: sl@0: sl@0: // sl@0: // CRepositoryBackupStreamIndex::GetNext sl@0: // sl@0: // Iterate through the index retrieving the next Reposirory UID and Stream ID sl@0: // pair. sl@0: // sl@0: TInt CRepositoryBackupStreamIndex::GetNext(TUid& aUid, TStreamId& aSettingsStreamId, TStreamId& aDeletedSettingsStreamId, TStreamId& aInstalledSettingsStreamId) sl@0: { sl@0: TInt error = KErrNone ; sl@0: if (iIndex < iStreamIndex.Count()) sl@0: { sl@0: iStreamIndex[iIndex++].Get(aUid, aSettingsStreamId, aDeletedSettingsStreamId, aInstalledSettingsStreamId) ; sl@0: } sl@0: else sl@0: { sl@0: error = KErrNotFound ; sl@0: } sl@0: return error ; sl@0: } sl@0: sl@0: sl@0: // sl@0: // Backup client class. sl@0: // sl@0: // Has Active object functionality to monitor the state of the publish and subscribe sl@0: // flags associated with backup and restore and also implements MActiveBackupDataClient sl@0: // to perform active backup according to the "proxy data holder" model. sl@0: // sl@0: sl@0: sl@0: sl@0: // sl@0: // Usual 2 phase construction factory NewL NewLC classes sl@0: // sl@0: CRepositoryBackupClient* CRepositoryBackupClient::NewLC(RFs& aFs) sl@0: { sl@0: CRepositoryBackupClient* me = new(ELeave)CRepositoryBackupClient(aFs); sl@0: CleanupStack::PushL(me) ; sl@0: me->ConstructL() ; sl@0: return me ; sl@0: } sl@0: sl@0: sl@0: CRepositoryBackupClient* CRepositoryBackupClient::NewL(RFs& aFs) sl@0: { sl@0: CRepositoryBackupClient* me = CRepositoryBackupClient::NewLC(aFs) ; sl@0: CleanupStack::Pop(me) ; sl@0: return me ; sl@0: } sl@0: sl@0: sl@0: sl@0: // sl@0: // Constructor - doesn't really do anything! sl@0: // sl@0: CRepositoryBackupClient::CRepositoryBackupClient(RFs& aFs) : CActive(EPriorityStandard), iFs(aFs), iRomScanDone(EFalse) sl@0: { sl@0: } sl@0: sl@0: sl@0: // sl@0: // Phase 2 constructor sl@0: // sl@0: void CRepositoryBackupClient::ConstructL() sl@0: { sl@0: // Create repository object sl@0: iRepository = new(ELeave) CServerRepository; sl@0: sl@0: // Notifier needed to open repositories. sl@0: iNotifier = new(ELeave)CSessionNotifier ; sl@0: sl@0: // Attach to Backup/Restore Pub/Sub property. sl@0: User::LeaveIfError(iBackupRestoreProperty.Attach(KUidSystemCategory, KUidBackupRestoreKey)) ; sl@0: sl@0: // Add ourself to the active scheduler sl@0: CActiveScheduler::Add(this) ; sl@0: sl@0: // Initialise backup/restore status sl@0: iBackupStatus = ENoBackupActivty ; sl@0: sl@0: // Set active and request notification of changes to backup/restore sl@0: // Pub/Sub property. sl@0: StartL() ; sl@0: } sl@0: sl@0: sl@0: sl@0: // sl@0: // Destructor sl@0: // sl@0: CRepositoryBackupClient::~CRepositoryBackupClient() sl@0: { sl@0: Cancel(); sl@0: sl@0: iBackupRestoreProperty.Close() ; sl@0: sl@0: if (iRepository) sl@0: { sl@0: iRepository->Close(); sl@0: delete(iRepository); sl@0: } sl@0: sl@0: if (iNotifier) sl@0: delete(iNotifier) ; sl@0: sl@0: if (iActiveBackupClient) sl@0: delete(iActiveBackupClient) ; sl@0: sl@0: iRestoredRepositoriesArray.ResetAndDestroy(); sl@0: iRestoredRepositoriesArray.Close(); sl@0: sl@0: iFile.Close(); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: // sl@0: // DoCancel - mandatory for active objects. sl@0: // sl@0: void CRepositoryBackupClient::DoCancel() sl@0: { sl@0: iBackupRestoreProperty.Cancel() ; sl@0: } sl@0: sl@0: sl@0: sl@0: // sl@0: // RunError sl@0: // sl@0: TInt CRepositoryBackupClient::RunError(TInt aError) sl@0: { sl@0: iRestoredRepositoriesArray.ResetAndDestroy(); sl@0: UNUSED_VAR(aError); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: // sl@0: // Test BUR Pub/Sub property set status, and notify BUR that we're sl@0: // ready to go as appropriate. sl@0: // sl@0: void CRepositoryBackupClient::TestBURstatusL(void) sl@0: { sl@0: TInt BURstatus ; sl@0: TRepositoryBackupState lastBackupStatus = ENoBackupActivty; sl@0: if (iBackupRestoreProperty.Get(BURstatus) != KErrNotFound) sl@0: { sl@0: BURstatus &= KBURPartTypeMask ; sl@0: switch (BURstatus) sl@0: { sl@0: case EBURUnset: // State not yet set. Treat as no backup/restore in progress. sl@0: case EBURNormal: sl@0: // No backup or restore in progress. Probably sl@0: // means we've just completed an operation? sl@0: sl@0: lastBackupStatus = iBackupStatus; sl@0: iBackupStatus = ENoBackupActivty ; sl@0: sl@0: // Back to normal, so enable cache sl@0: TServerResources::iCacheManager->EnableCache(); sl@0: // delete the CActiveBackupClient sl@0: if (iActiveBackupClient) sl@0: { sl@0: delete iActiveBackupClient ; sl@0: iActiveBackupClient = NULL ; sl@0: } sl@0: sl@0: // Notify the changed keys if a restoration was just completed sl@0: if((lastBackupStatus == ERestoreInProgress)) sl@0: { sl@0: for(TInt i = 0; i < iRestoredRepositoriesArray.Count(); i++) sl@0: { sl@0: iRepository->OpenL(iRestoredRepositoriesArray[i]->Uid(), *iNotifier, EFalse); sl@0: iRepository->RestoreNotify(*iRestoredRepositoriesArray[i]); sl@0: iRepository->Close(); sl@0: } sl@0: iRestoredRepositoriesArray.ResetAndDestroy(); sl@0: } sl@0: sl@0: break ; sl@0: sl@0: case EBURBackupFull : sl@0: case EBURBackupPartial : sl@0: // We don't distinguish between full and partial backups sl@0: // as the Backup engine will give us UIDs for all the sl@0: // repository data owners that want their stuff backed up sl@0: // anyway. sl@0: sl@0: // We don't want cache activity during backup sl@0: TServerResources::iCacheManager->DisableCache(); sl@0: sl@0: // Any (and all!) repositories which have been opened in the sl@0: // course of system boot and normal operation will have been sl@0: // added to TServerResources::iOwnerIdLookUpTable as they were sl@0: // opened but there may well be repositories which need backing sl@0: // up and haven't yet been opened so we need to make sure that sl@0: // the lookup table is complete. sl@0: CompleteOwnerIdLookupTableL(); sl@0: sl@0: // Register with BUR engine sl@0: if (!iActiveBackupClient) sl@0: { sl@0: iActiveBackupClient = CActiveBackupClient::NewL(this) ; sl@0: } sl@0: iActiveBackupClient->ConfirmReadyForBURL(KErrNone); sl@0: iBackupStatus = EBackupInProgress ; sl@0: break ; sl@0: sl@0: case EBURRestoreFull : sl@0: case EBURRestorePartial : sl@0: // We don't distinguish between full and partial restore sl@0: // either! sl@0: sl@0: // We don't want cache activity during restore either! sl@0: TServerResources::iCacheManager->DisableCache(); sl@0: sl@0: // Register with BUR engine sl@0: if (!iActiveBackupClient) sl@0: { sl@0: iActiveBackupClient = CActiveBackupClient::NewL(this) ; sl@0: } sl@0: iActiveBackupClient->ConfirmReadyForBURL(KErrNone); sl@0: iBackupStatus = ERestoreInProgress ; sl@0: break ; sl@0: sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: // sl@0: // Request notification of changes in BUR Pub/Sub status sl@0: // sl@0: void CRepositoryBackupClient::StartL() sl@0: { sl@0: if (!IsActive()) sl@0: { sl@0: TestBURstatusL(); sl@0: NotifyChange(); sl@0: } sl@0: } sl@0: sl@0: sl@0: // sl@0: // Request notification of changes in BUR Pub/Sub status sl@0: // sl@0: void CRepositoryBackupClient::NotifyChange() sl@0: { sl@0: // Watch for changes in the property state. sl@0: iBackupRestoreProperty.Subscribe(iStatus) ; sl@0: SetActive(); sl@0: } sl@0: sl@0: sl@0: // sl@0: // Handle changes of backup state through publish/subscribe sl@0: // sl@0: void CRepositoryBackupClient::RunL() sl@0: { sl@0: NotifyChange() ; sl@0: TestBURstatusL(); sl@0: } sl@0: sl@0: sl@0: // sl@0: // We can't estimate data size without A) having the SID of the data owner who's data sl@0: // is to be backed up and B) going through the whole process of preparing the backup. sl@0: // sl@0: // The only sensible thing we can do is return an arbitrary value! sl@0: // sl@0: TUint CRepositoryBackupClient::GetExpectedDataSize(TDriveNumber /* aDrive */) sl@0: { sl@0: return KArbitraryNumber ; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: // sl@0: // Called by BUR engine to request a chunk of backup data. sl@0: // sl@0: void CRepositoryBackupClient::GetBackupDataSectionL(TPtr8& aBuffer, TBool& aFinished) sl@0: { sl@0: const TInt chunkSize = aBuffer.MaxSize() ; sl@0: sl@0: aFinished = EFalse ; sl@0: sl@0: // Pass a chunk of our prepared backup data in aBuffer sl@0: User::LeaveIfError(iFile.Read(aBuffer, chunkSize)) ; sl@0: TInt bytesRead = aBuffer.Length() ; sl@0: sl@0: // Check to see if this was the last chunk of data. sl@0: if (bytesRead < chunkSize) sl@0: { sl@0: // Set "finished" flag so that BUR knows we're through... sl@0: aFinished = ETrue ; sl@0: sl@0: // ...and then tidy up by closing and deleting the backup file. sl@0: iFile.Close() ; sl@0: TParse backupFilePath ; sl@0: User::LeaveIfError(backupFilePath.Set(KBackupFileName, TServerResources::iBURDirectory, &KBackupFileExt)); sl@0: TInt fileDeleteErr=iFs.Delete(backupFilePath.FullName()) ; sl@0: #ifdef _DEBUG sl@0: if (fileDeleteErr != KErrNone) sl@0: { sl@0: RDebug::Print(_L("CRepositoryBackupClient::GetBackupDataSectionL - Failed to delete file. Error = %d"), fileDeleteErr); sl@0: } sl@0: #else sl@0: UNUSED_VAR(fileDeleteErr); sl@0: #endif sl@0: sl@0: } sl@0: } sl@0: sl@0: // sl@0: // CRepositoryBackupClient::RestoreComplete sl@0: // sl@0: // Called when a Complete set of backup data has been received and written sl@0: // to a file. We now need to open the file as a stream store, get the sl@0: // index (list of repository UID and corresponding stream ID pairs, and then sl@0: // reconstruct and save each repository in turn. sl@0: // sl@0: void CRepositoryBackupClient::RestoreComplete(TDriveNumber /* aDrive */) sl@0: { sl@0: } sl@0: sl@0: sl@0: void CRepositoryBackupClient::RestoreRepositoryAndListL(TUid repositoryUid, CDirectFileStore* store, TStreamId settingsStreamId, TStreamId deletedSettingsStreamId, TInt& repIndex) sl@0: { sl@0: // Add the restored repository to the restored repositories list. sl@0: // Pass its changed-keys list to further restoring functions to add entries for post-restoration notification. sl@0: repIndex = AddRestoredRepositoryL(repositoryUid); sl@0: iRepository->RestoreRepositoryContentsL(*store, settingsStreamId, deletedSettingsStreamId, *iRestoredRepositoriesArray[repIndex]); sl@0: iRepository->CommitChangesL(); sl@0: } sl@0: sl@0: sl@0: // sl@0: // CRepositoryBackupClient::RestoreCompleteL sl@0: // sl@0: // Does the actual work of reconstructing repositories from backup data sl@0: // sl@0: // sl@0: void CRepositoryBackupClient::RestoreCompleteL() sl@0: { sl@0: // All restore data recived so we can now recreate the repositories from the sl@0: // backup store sl@0: // Attempt to open the restore file as a CDirectFileStore sl@0: TParse restoreFilePath ; sl@0: User::LeaveIfError(restoreFilePath.Set(KRestoreFileName, TServerResources::iBURDirectory, &KRestoreFileExt)); sl@0: CDirectFileStore* store = CDirectFileStore::OpenLC (iFs,restoreFilePath.FullName(), EFileRead|EFileShareReadersOnly); sl@0: if (store->Type()[0] != KDirectFileStoreLayoutUid) sl@0: { sl@0: // store wasn't quite what we were expecting - can't return an error, can't leave sl@0: // so all we can do is close the file, tidy up as best we can, and bail out!!!! sl@0: CleanupStack::PopAndDestroy(store); sl@0: // If a debug build - record error sl@0: TInt fileDeleteErr=iFs.Delete(restoreFilePath.FullName()) ; sl@0: #ifdef _DEBUG sl@0: if (fileDeleteErr != KErrNone) sl@0: { sl@0: RDebug::Print(_L("CRepositoryBackupClient::RestoreCompleteL - Failed to delete file. Error = %d"), fileDeleteErr); sl@0: } sl@0: #else sl@0: UNUSED_VAR(fileDeleteErr); sl@0: #endif sl@0: sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: sl@0: sl@0: // Get the root stream and attempt to read a backup file header from it sl@0: TStreamId rootStreamId = store->Root() ; sl@0: RStoreReadStream rootStream ; sl@0: RStoreReadStream indexStream ; sl@0: rootStream.OpenLC(*store, rootStreamId); sl@0: TRepositoryBackupStreamHeader header ; sl@0: TRAPD(err, header.InternalizeL(rootStream)) ; sl@0: sl@0: // Check for a valid header by checking that the UID matches the UID sl@0: // of Central Repository and that the version number is sane. sl@0: if (err == KErrNotSupported) sl@0: { sl@0: // Not a valid header - assume it's an old style backup stream, sl@0: // set extensions supported to none, set index stream to be sl@0: // root stream and reset read pointer to beginning. sl@0: iBackupExtensionsSupported = ENoBackupExtensions ; sl@0: sl@0: CleanupStack::PopAndDestroy(&rootStream) ; sl@0: CleanupStack::PopAndDestroy(store) ; sl@0: sl@0: // Try re-opening as old-style backup stream with index sl@0: // as root stream. sl@0: CDirectFileStore* store = CDirectFileStore::OpenLC (iFs,restoreFilePath.FullName(), EFileRead|EFileShareReadersOnly); sl@0: indexStream.OpenLC(*store, rootStreamId) ; sl@0: } sl@0: else sl@0: { sl@0: // Got a valid header. Check for extensions supported by this sl@0: // stream and get stream to read index from sl@0: CleanupStack::PopAndDestroy(&rootStream) ; sl@0: iBackupExtensionsSupported = header.getBackupExtensionsSupported(); sl@0: TStreamId indexStreamId = header.getIndexStreamId() ; sl@0: indexStream.OpenLC (*store, indexStreamId) ; sl@0: } sl@0: sl@0: CRepositoryBackupStreamIndex *restoreStreamIndex = CRepositoryBackupStreamIndex::NewLC(); sl@0: restoreStreamIndex->InternalizeL(indexStream, iBackupExtensionsSupported); sl@0: sl@0: sl@0: // Iterate through index and attempt restore of each repository stream sl@0: // we find in it. sl@0: restoreStreamIndex->Reset(); sl@0: TUid repositoryUid; sl@0: TStreamId settingsStreamId(KNullStreamIdValue); sl@0: TStreamId deletedSettingsStreamId(KNullStreamIdValue); sl@0: TStreamId installedSettingsStreamId(KNullStreamIdValue); sl@0: sl@0: while (restoreStreamIndex->GetNext(repositoryUid, settingsStreamId, deletedSettingsStreamId, installedSettingsStreamId) == KErrNone) sl@0: { sl@0: iRepository->OpenL(repositoryUid, *iNotifier, EFalse); sl@0: iRepository->FailAllTransactions(); sl@0: TInt repIndex; sl@0: TRAPD(err, RestoreRepositoryAndListL(repositoryUid, store, settingsStreamId, deletedSettingsStreamId, repIndex)); sl@0: iRepository->Close(); sl@0: User::LeaveIfError(err); sl@0: // If the backup contains an installed repository containing default values for the settings, read them in sl@0: if (installedSettingsStreamId != KNullStreamId) sl@0: { sl@0: // create an empty repository in install directory, and restore the data from backup file sl@0: iRepository->RestoreInstallRepositoryL(repositoryUid, *store, installedSettingsStreamId, *iRestoredRepositoriesArray[repIndex]); sl@0: // remove the .ini install file (if exists) because it will clash with the restored file sl@0: TServerResources::DeleteCentrepFileL(repositoryUid, EInstall, EIni); sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(restoreStreamIndex) ; sl@0: CleanupStack::PopAndDestroy(&indexStream); sl@0: CleanupStack::PopAndDestroy(store); sl@0: // If a debug build - record error sl@0: TInt fileDeleteErr=iFs.Delete(restoreFilePath.FullName()); sl@0: #ifdef _DEBUG sl@0: if (fileDeleteErr != KErrNone) sl@0: { sl@0: RDebug::Print(_L("CRepositoryBackupClient::RestoreCompleteL (2nd) - Failed to delete file. Error = %d"), fileDeleteErr); sl@0: } sl@0: #else sl@0: UNUSED_VAR(fileDeleteErr); sl@0: #endif sl@0: sl@0: } sl@0: sl@0: // sl@0: // CRepositoryBackupClient::CompleteOwnerIdLookupTableL sl@0: // sl@0: // Open each repository in TServerResources::iDataDirectory. sl@0: // Save the Rep UID and Owner Id of the rep to be used by sl@0: // InitialiseGetProxyBackupDataL. sl@0: void CRepositoryBackupClient::CompleteOwnerIdLookupTableL() sl@0: { sl@0: sl@0: // Read contents of persist, install, and ROM directories and sl@0: // use them to build a list of repository candidates. sl@0: RArray <TUint32> repositoryList ; sl@0: CleanupClosePushL(repositoryList) ; sl@0: sl@0: for (TBackupDirectoryScan scanDir = EScanRom; scanDir <= EScanPersist; scanDir = (TBackupDirectoryScan)(scanDir+1)) sl@0: { sl@0: TPtrC directoryName ; sl@0: switch (scanDir) sl@0: { sl@0: case EScanRom : sl@0: if (TServerResources::iRomDirectory) sl@0: { sl@0: directoryName.Set(TServerResources::iRomDirectory->Des()) ; sl@0: } sl@0: else sl@0: { sl@0: // if ROM directory doesn't exist or there are no files, skip scanning sl@0: continue; sl@0: } sl@0: break ; sl@0: sl@0: case EScanInstall : sl@0: directoryName.Set(TServerResources::iInstallDirectory->Des()) ; sl@0: break ; sl@0: sl@0: case EScanPersist : sl@0: directoryName.Set(TServerResources::iDataDirectory->Des()) ; sl@0: break ; sl@0: } sl@0: sl@0: RDir dir; sl@0: CleanupClosePushL(dir); sl@0: User::LeaveIfError(dir.Open(iFs, directoryName, KEntryAttNormal)); sl@0: sl@0: TEntryArray dirEntries; sl@0: TInt readError = KErrNone; sl@0: sl@0: while (readError != KErrEof) sl@0: { sl@0: readError = dir.Read(dirEntries); sl@0: sl@0: if(readError != KErrNone && readError != KErrEof) sl@0: { sl@0: User::Leave(readError); sl@0: } sl@0: else sl@0: { sl@0: const TInt dirCount = dirEntries.Count(); sl@0: for (TInt i=0; i<dirCount; i++) sl@0: { sl@0: // Attempt to extract a repository UID from directory entry sl@0: TUid uid; sl@0: TInt insertionError; sl@0: if (KErrNone == TServerResources::GetUid(const_cast<TEntry&>(dirEntries[i]), uid)) sl@0: { sl@0: insertionError=repositoryList.InsertInUnsignedKeyOrder(uid.iUid) ; sl@0: // Should leave in all cases other than KErrNone or KErrAlreadyExists sl@0: if((insertionError != KErrNone) && (insertionError != KErrAlreadyExists )) sl@0: { sl@0: User::Leave(insertionError); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(&dir); sl@0: } sl@0: sl@0: // Open all repositories in turn. Save repository UID and owner ID sl@0: // in lookup table. sl@0: for(TInt i = 0; i<repositoryList.Count(); i++) sl@0: { sl@0: // Look to see if this repository already has an entry in the owner ID lookup table sl@0: if ( TServerResources::FindOwnerIdLookupMapping(repositoryList[i]) == KErrNotFound) sl@0: { sl@0: // Need to TRAP here as otherwise if ANY repository fails to open sl@0: // (e.g. due to corruption) it would cause the entire backup to sl@0: // fail sl@0: TRAPD(err, iRepository->OpenL(TUid::Uid(repositoryList[i]), *iNotifier)); sl@0: if (err == KErrNoMemory) sl@0: { sl@0: User::Leave(err) ; sl@0: } sl@0: sl@0: else if (err == KErrNone) sl@0: { sl@0: // The act of opening a repository will cause it to add itself to the sl@0: // Repository/Owner UID mapping table so we don't need to do anything sl@0: // and can close it immediately! sl@0: iRepository->Close(); sl@0: } sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy() ; // repositoryList sl@0: } sl@0: sl@0: // CRepositoryBackupClient::InitialiseGetProxyBackupDataL sl@0: // sl@0: // Prepare data to be backed up. We get the Sid/Uid of the entity whos data sl@0: // is to be backed up. What we do is to open each repository in turn (identified sl@0: // by directory listing), check its owner, and if it matches the Sid/Uid we've sl@0: // been given by secure backup externalise it to a stream within a file store. sl@0: // sl@0: void CRepositoryBackupClient::InitialiseGetProxyBackupDataL(TSecureId aSID, TDriveNumber /* aDrive */) sl@0: { sl@0: // Prepare data for backup. sl@0: sl@0: // Create file store sl@0: TParse backupFilePath ; sl@0: User::LeaveIfError(backupFilePath.Set(KBackupFileName, TServerResources::iBURDirectory, &KBackupFileExt)); sl@0: CDirectFileStore* store = CDirectFileStore::ReplaceLC(iFs, backupFilePath.FullName(), sl@0: (EFileWrite | EFileShareExclusive)); sl@0: const TUid uid2 = KNullUid ; sl@0: store->SetTypeL(TUidType(KDirectFileStoreLayoutUid, uid2, KServerUid3)) ; sl@0: sl@0: // Create a Backup Stream index sl@0: CRepositoryBackupStreamIndex* backupStreamIndex = CRepositoryBackupStreamIndex::NewLC(); sl@0: sl@0: // Find the reps owned by aSID sl@0: for(TInt i = 0; i < TServerResources::iOwnerIdLookUpTable.Count(); ++i) sl@0: { sl@0: const TOwnerIdMapping& lookupTableEntry = TServerResources::iOwnerIdLookUpTable[i]; sl@0: sl@0: if ( lookupTableEntry.iOwner == aSID ) sl@0: { sl@0: TStreamId settingStreamId(KNullStreamIdValue); sl@0: TStreamId deletedSettingsStreamId(KNullStreamIdValue); sl@0: TStreamId installedSettingStreamId(KNullStreamIdValue); sl@0: // Found one match, open the repository and externalise content. sl@0: TUid uid = TUid::Uid(lookupTableEntry.iRepUid); sl@0: TRAPD(err,iRepository->OpenL(uid, *iNotifier)); sl@0: if (err == KErrNoMemory) sl@0: { sl@0: User::Leave(err) ; sl@0: } sl@0: else if (err == KErrNone) sl@0: { sl@0: iRepository->FailAllTransactions(); sl@0: // externalise repository contents sl@0: iRepository->StoreRepositoryContentsL(*store, settingStreamId, deletedSettingsStreamId); sl@0: // Close repository. sl@0: iRepository->Close(); sl@0: } sl@0: sl@0: TBool installExists=TServerResources::InstallFileExistsL(uid); sl@0: if(installExists) sl@0: { sl@0: // load existing repository from install directory (default values installed post-build by SWI) sl@0: // and externalise installed repository contents sl@0: TRAPD(err, iRepository->BackupInstallRepositoryL(uid, *store, installedSettingStreamId)); sl@0: // We trap and discard most errors to be able to continue backing up other repositories in the list sl@0: if (err == KErrNoMemory) sl@0: { sl@0: User::Leave(err) ; sl@0: } sl@0: else if (err != KErrNone) sl@0: { sl@0: // If for any reason we haven't been able to back up the install repository, sl@0: // we create an empty stream to preserve the format sl@0: installedSettingStreamId = KNullStreamIdValue; sl@0: } sl@0: } sl@0: // Add all to store index sl@0: backupStreamIndex->AddL(uid, settingStreamId, deletedSettingsStreamId, installedSettingStreamId) ; sl@0: sl@0: } sl@0: } sl@0: // Write the stream index/dictionary as root stream within the store sl@0: // so we can access it when we do a restore later on sl@0: RStoreWriteStream indexStream ; sl@0: TStreamId indexStreamId = indexStream.CreateLC(*store) ; sl@0: backupStreamIndex->ExternalizeL(indexStream) ; sl@0: indexStream.CommitL() ; sl@0: CleanupStack::PopAndDestroy(&indexStream) ; sl@0: CleanupStack::PopAndDestroy (backupStreamIndex) ; sl@0: sl@0: // Create the Header and write it as the root stream within the store sl@0: // so we can access it when we do a restore later on sl@0: TRepositoryBackupStreamHeader header (indexStreamId) ; sl@0: RStoreWriteStream rootStream ; sl@0: TStreamId rootStreamId = rootStream.CreateLC(*store) ; sl@0: header.ExternalizeL(rootStream) ; sl@0: rootStream.CommitL() ; sl@0: sl@0: CleanupStack::PopAndDestroy(&rootStream) ; sl@0: store->SetRootL(rootStreamId); sl@0: store->CommitL(); sl@0: CleanupStack::PopAndDestroy(store) ; sl@0: sl@0: // Attempt to open file containing store ready to read back and send to sl@0: // BUR engine as a stream of bytes. sl@0: User::LeaveIfError(iFile.Open(iFs, backupFilePath.FullName(), (EFileRead | EFileShareExclusive))) ; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: // sl@0: // CRepositoryBackupClient::InitialiseRestoreProxyBaseDataL sl@0: // sl@0: // Called when secure backup is about to start sending restore data. sl@0: // sl@0: void CRepositoryBackupClient::InitialiseRestoreProxyBaseDataL(TSecureId aSID, TDriveNumber /* aDrive*/) sl@0: { sl@0: // prepare for restore - Don't think we need to do anything here except prepare sl@0: // data structures to receive incoming data sl@0: sl@0: // Save SID so we can check that it corresponds with the owner information sl@0: // in the restored data. sl@0: iSid = aSID ; sl@0: sl@0: // Open file to receive restored data sl@0: TParse restoreFilePath ; sl@0: User::LeaveIfError(restoreFilePath.Set(KRestoreFileName, TServerResources::iBURDirectory, &KRestoreFileExt)); sl@0: User::LeaveIfError(iFile.Replace (iFs, restoreFilePath.FullName(), (EFileWrite | EFileShareExclusive))); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: // sl@0: // CRepositoryBackupClient::RestoreBaseDataSectionL sl@0: // sl@0: // Called when secure backup has a chunk of restore data for us. Last data sl@0: // segment identified by aFinished. sl@0: // sl@0: void CRepositoryBackupClient::RestoreBaseDataSectionL(TDesC8& aBuffer, TBool aFinished) sl@0: { sl@0: // Receive a chunk of restore data in aBuffer sl@0: User::LeaveIfError(iFile.Write (aBuffer)) ; sl@0: if (aFinished) sl@0: { sl@0: iFile.Close() ; sl@0: sl@0: // All restore data recived so we can now recreate the repositories from the sl@0: // backup store sl@0: RestoreCompleteL(); sl@0: } sl@0: } sl@0: sl@0: void CRepositoryBackupClient::TerminateMultiStageOperation() sl@0: { sl@0: // Backup/Restore operation aborted! sl@0: // Tidy up all temporary data. sl@0: HBufC* burFileName = HBufC::New(KMaxFileName); sl@0: if(burFileName==NULL) sl@0: { sl@0: return; sl@0: } sl@0: TPtr burFileNamePtr(burFileName->Des()); sl@0: iFile.FullName(burFileNamePtr); //get the full name of the temporary file sl@0: iFile.Close(); // close the file sl@0: // If a debug build - record error sl@0: TInt fileDeleteErr=iFs.Delete(burFileNamePtr); sl@0: #ifdef _DEBUG sl@0: if (fileDeleteErr != KErrNone) sl@0: { sl@0: RDebug::Print(_L("CRepositoryBackupClient::TerminateMultiStageOperation - Failed to delete file. Error = %d"), fileDeleteErr); sl@0: } sl@0: #else sl@0: UNUSED_VAR(fileDeleteErr); sl@0: #endif sl@0: sl@0: delete burFileName; sl@0: } sl@0: sl@0: sl@0: // sl@0: // CRepositoryBackupClient::GetDataChecksum sl@0: // sl@0: // Not required and we don't implement it. sl@0: // sl@0: TUint CRepositoryBackupClient::GetDataChecksum(TDriveNumber /* aDrive */) sl@0: { sl@0: return KArbitraryNumber; sl@0: } sl@0: sl@0: // sl@0: // CRepositoryBackupClient::GetSnapshotDataL sl@0: // sl@0: // Only required for incremental backup (which we don't support sl@0: // sl@0: void CRepositoryBackupClient::GetSnapshotDataL(TDriveNumber /* aDrive */, TPtr8& /* aBuffer */, TBool& /* aFinished */) sl@0: { sl@0: User::Leave(KErrNotSupported) ; sl@0: } sl@0: sl@0: // sl@0: // CRepositoryBackupClient::InitialiseGetBackupDataL sl@0: // sl@0: // Used by "normal" active backup to prepare data - we use sl@0: // InitialiseRestoreProxyBaseDataL so this shouldn't be called! sl@0: // sl@0: void CRepositoryBackupClient::InitialiseGetBackupDataL(TDriveNumber /* aDrive */) sl@0: { sl@0: User::Leave(KErrNotSupported) ; sl@0: } sl@0: sl@0: sl@0: sl@0: void CRepositoryBackupClient::InitialiseRestoreBaseDataL(TDriveNumber /* aDrive */) sl@0: { sl@0: // Check this! I Don't think this method should get called as we're a proxy sl@0: // and so implement InitialiseGetProxyBackupDataL!! sl@0: User::Leave(KErrNotSupported) ; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: void CRepositoryBackupClient::InitialiseRestoreIncrementDataL(TDriveNumber /* aDrive */) sl@0: { sl@0: // Check this! I Don't think this method should get called as we're a proxy sl@0: // so don't do incremental backup!! sl@0: User::Leave(KErrNotSupported) ; sl@0: } sl@0: sl@0: sl@0: sl@0: void CRepositoryBackupClient::RestoreIncrementDataSectionL(TDesC8& /* aBuffer */, TBool /* aFinished */) sl@0: { sl@0: // Check this! I Don't think this method should get called as we're a proxy sl@0: // so don't do incremental backup!! sl@0: User::Leave(KErrNotSupported) ; sl@0: } sl@0: sl@0: sl@0: // sl@0: // Incremental backup isn't supported for the proxy data holder model so this sl@0: // method should never be called. sl@0: // sl@0: // Not acceptable to leave even though it's an ...L function which we don't implement sl@0: void CRepositoryBackupClient::AllSnapshotsSuppliedL() sl@0: { sl@0: ; sl@0: } sl@0: sl@0: sl@0: sl@0: // sl@0: // Incremental backup not supported sl@0: // sl@0: void CRepositoryBackupClient::ReceiveSnapshotDataL(TDriveNumber /* aDrive */, TDesC8& /* aBuffer */, TBool /* aLastSection */) sl@0: { sl@0: User::Leave(KErrNotSupported) ; sl@0: } sl@0: sl@0: /** sl@0: Adds a new entry to the restored repository list with the specified repository uid. sl@0: sl@0: Creates an object of the CRestoredRepository and inserts it to the list. sl@0: If a repository of the specified uid is already on the list, the created object will sl@0: be deleted and no repeated entry will be inserted to the list. sl@0: sl@0: @param aUid The uid of the repository to be added to this array. sl@0: @return The index of the new or existing entry within the list. sl@0: */ sl@0: TInt CRepositoryBackupClient::AddRestoredRepositoryL(TUid aUid) sl@0: { sl@0: CRestoredRepository* rstRepos = new(ELeave) CRestoredRepository(aUid); sl@0: CleanupStack::PushL(rstRepos); sl@0: TInt err = iRestoredRepositoriesArray.InsertInOrder(rstRepos, TLinearOrder<CRestoredRepository>(CRestoredRepository::CompareUids)); sl@0: if(err != KErrNone && err != KErrAlreadyExists) sl@0: User::Leave(err); sl@0: TInt index = iRestoredRepositoriesArray.FindInOrderL(rstRepos, TLinearOrder<CRestoredRepository>(CRestoredRepository::CompareUids)); sl@0: CleanupStack::Pop(); sl@0: sl@0: if(err == KErrAlreadyExists) sl@0: { sl@0: delete rstRepos; sl@0: } sl@0: return index; sl@0: }