diff -r 000000000000 -r 08ec8eefde2f persistentstorage/centralrepository/common/src/heaprepos.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/centralrepository/common/src/heaprepos.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,443 @@ +// Copyright (c) 2008-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: +// simrepos.cpp +// +// + +#include "heaprepos.h" + +CHeapRepository* CHeapRepository::NewL(TUid aUid) + { + CHeapRepository* repos=new (ELeave) CHeapRepository(aUid); + return repos; + } + +CHeapRepository::CHeapRepository(TUid aUid) + :iSettings(),iUid(aUid),iSinglePolicies(KGranularity) + { + } + +CHeapRepository::~CHeapRepository() + { + iSinglePolicies.ResetAndDestroy(); + iRangePolicies.Close(); + iDeletedSettings.Close(); + iSettings.Close(); + iRangeMeta.Close(); + } + +/** +Stores the repository in-memory content to the related repository file on drive C. +If the operation fails, the in-memory content won't match the content of +the repository file (which will be kept as it was before the CommitChangesL() call). +In order to keep the consistency, the in-memory repository content is deleted now +and restored later, on the next repository operation. +*/ +TInt CHeapRepository::CommitChanges(RFs& aFs,TUint8 aPersistVersion,const TDesC& aTargetFilePath) + { + TRAPD(error, DoCommitChangesL(aFs,aPersistVersion,aTargetFilePath)); + if (error != KErrNone) + { + //If the commit fails reset the repository as it is in an inconsistent state + ResetContent(); + } + return error; + } + +void CHeapRepository::SetMetaDataOnRead(TServerSetting& aSetting, TBool aSingleMetaFound) + { + TInt isMetaFlagSet = aSetting.Meta() & KMetaDefaultValue; + + if(!aSingleMetaFound) + // No single metadata set for this key + { + // First check for a matching "range" default metadata + // setting + TSettingsDefaultMeta* defaultMeta = iRangeMeta.Find(aSetting.Key()); + if (defaultMeta) + { + if (isMetaFlagSet) + //sets a default meta data + //also sets the flag back to indicate that it is a default setting from ROM + //or previous install so it can be replaced later with a new one. + aSetting.SetMeta(defaultMeta->GetDefaultMetadata() | KMetaDefaultValue); + else + aSetting.SetMeta(defaultMeta->GetDefaultMetadata()); + } + else + { + // Range value not found, try for a repository default + if (isMetaFlagSet) + aSetting.SetMeta(iDefaultMeta | KMetaDefaultValue) ; + else + aSetting.SetMeta(iDefaultMeta) ; + } + } + +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS +#ifdef CENTREP_CONV_TOOL + if (aSingleMetaFound && aSetting.IsClean() && !aSetting.IsIndividualMeta()) + aSingleMetaFound=EFalse; +#endif + aSetting.SetIndividualMeta(aSingleMetaFound); +#endif + } + +TInt CHeapRepository::Create(TServerSetting& aSetting, TSettingsAccessPolicy* &aPolicy, TBool aSingleMetaFound) + { + if(iSettings.Find(aSetting.Key())) + return KErrAlreadyExists; + + SetMetaDataOnRead( aSetting, aSingleMetaFound); + aSetting.SetAccessPolicy(aPolicy); + + return iSettings.OrderedInsert(aSetting); + } + +// Comparison relation to allow single policies to be inserted in order +TInt CHeapRepository::CompareKeyIds(const TSettingsAccessPolicy& aSinglePolicy, const TSettingsAccessPolicy& aSinglePolicyIndexItem) + { + if(aSinglePolicy.iLowKey==aSinglePolicyIndexItem.iLowKey) + return 0; + return (aSinglePolicy.iLowKey < aSinglePolicyIndexItem.iLowKey)?-1:1; + } + +// Identity relation to allow single policy for a given key to be found +TBool CHeapRepository::SinglePolicyMatchOnKey(const TSettingsAccessPolicy& aSinglePolicy, const TSettingsAccessPolicy& aSinglePolicyIndexItem) + { + return aSinglePolicy.iLowKey==aSinglePolicyIndexItem.iLowKey; + } + +// returns the read security policy used if there is no per-setting policy at aId +const TSecurityPolicy& CHeapRepository::GetFallbackReadAccessPolicy(TUint32 aId) + { + return *(GetFallbackAccessPolicy(aId)->GetReadAccessPolicy()); + } + +// returns the write security policy used if there is no per-setting policy at aId +const TSecurityPolicy& CHeapRepository::GetFallbackWriteAccessPolicy(TUint32 aId) + { + return *(GetFallbackAccessPolicy(aId)->GetWriteAccessPolicy()); + } + +// Get pointer to security policy that applies to a given setting +TSettingsAccessPolicy* CHeapRepository::GetFallbackAccessPolicy(TUint32 aId +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + ,TBool aSkipSingle +#endif + ) + { +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + if (!aSkipSingle) + { +#endif + // Check for single policy + TSettingsAccessPolicy policy(aId); + TIdentityRelation identity(SinglePolicyMatchOnKey); + TInt index = iSinglePolicies.Find(&policy, identity); + if(KErrNotFound != index) + return iSinglePolicies[index]; +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + } +#endif + + // check if the aId falls into any range specified in the ini file + TSettingsAccessPolicy* rangePolicy = iRangePolicies.Find(aId); + if(rangePolicy) + return rangePolicy; + + // If no single policy or range policy, return default policy + return &iDefaultPolicy; + } + +// this function saves idividual meta as well +TInt CHeapRepository::ReadSettingSavePolicyL(CIniFileIn& aFile,TServerSetting& aSetting, TSettingsAccessPolicy* &aPolicy, TBool& aSingleMetaFound) + { + TBool singleReadPolicyFound; + TBool singleWritePolicyFound; + TSecurityPolicy singleReadPolicy; + TSecurityPolicy singleWritePolicy; + + TInt err=aFile.ReadSettingL(aSetting,singleReadPolicy, singleWritePolicy, singleReadPolicyFound, singleWritePolicyFound, aSingleMetaFound); + if(err!=KErrNone) + return err; + + // Set up single policies + if(!singleReadPolicyFound) + singleReadPolicy=GetDefaultReadAccessPolicy(); + if(!singleWritePolicyFound) + singleWritePolicy=GetDefaultWriteAccessPolicy(); + + aSetting.PushL(); + if(singleReadPolicyFound || singleWritePolicyFound) + { + aPolicy=new (ELeave) TSettingsAccessPolicy(singleReadPolicy,singleWritePolicy,aSetting.Key()); + CleanupStack::PushL(aPolicy); +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + //reused single setting high key and mask to indicate whether read or write has been specified + //or they are just a default policy + if (singleReadPolicyFound) + aPolicy->iHighKey=1; + if (singleWritePolicyFound) + aPolicy->iKeyMask=1; +#endif + TLinearOrder order(&CHeapRepository::CompareKeyIds); + iSinglePolicies.InsertInOrderL(aPolicy,order); + CleanupStack::Pop(aPolicy); + } + else + { + // check if the aId falls into any range specified in the ini file + // otherwise set policy to default policy + TSettingsAccessPolicy* rangePolicy = iRangePolicies.Find(aSetting.Key()); + if(rangePolicy) + aPolicy=rangePolicy; + else + aPolicy=&iDefaultPolicy; + } + + aSetting.Pop(); + return err; + } + +#ifdef CENTREP_CONV_TOOL +void CHeapRepository::DoCommitChangesToIniFileL(RFs& aFs,const TDesC& aOutFileName +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + ,TUint32 aCreVersion +#endif + ) + { + CIniFileOut* out = CIniFileOut::NewLC(aFs,aOutFileName); + + out->WriteHeaderL(); + out->WriteOwnerSectionL(iOwner); + out->WriteTimeStampL(iTimeStamp); + out->WriteMetaDataL(iDefaultMeta, iRangeMeta); +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + out->WritePlatSecL(GetDefaultAccessPolicy(), iRangePolicies,aCreVersion); +#else + out->WritePlatSecL(GetDefaultReadAccessPolicy(), GetDefaultWriteAccessPolicy(), iRangePolicies); +#endif + + + out->WriteMainSectionHeaderL(); + for(TInt i=0; iWriteSettingL(setting, *setting.AccessPolicy() +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + ,aCreVersion +#endif + ); + } + else + { + out->WriteSettingL(setting +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + ,aCreVersion +#endif + ); + } + } + + out->CommitL(); + CleanupStack::PopAndDestroy(out);//out + } +#endif + +void CHeapRepository::DoCommitChangesL(RFs& aFs,TUint8 aPersistVersion,const TDesC& aTargetFilePath) + { + CCreGenerator::CommitChangesToCreL(aFs,aPersistVersion,*this, aTargetFilePath); + } + +/** +The method reloads the repository content from a repository file. +The current repository must be emptied (or must be empty already) before the call is made. +@param aIniFile A reference to CIniFileIn object, which will be used to load + the repository content. +@leave System-wide error codes. +@leave KErrGeneral It's probably a programmer's error - current CHeapRepository + object is partially initialised. +@leave KErrCorrupt Corrupted repository file. +*/ +void CHeapRepository::ReloadContentL(CIniFileIn& aIniFile) + { + // Preconditions - CHeapRepository object should be an empty one. + if(!IsEmpty()) + { + User::Leave(KErrGeneral); + } + TInt err = ReloadContentExceptSettingsL(aIniFile); + if(err == KErrCorrupt) + { + User::Leave(err); + } + CleanupClosePushL(iRangeMeta); + CleanupClosePushL(iRangePolicies); + + // Settings + TServerSetting setting; + TSettingsAccessPolicy* policy; + TBool singleMetaFound; + TCleanupItem tc(SinglePoliciesCleanup, &iSinglePolicies); + CleanupStack::PushL(tc); + CleanupClosePushL(iSettings); + while((err = ReadSettingSavePolicyL(aIniFile, setting, policy, singleMetaFound)) == KErrNone) + { + setting.PushL(); + if(iSettings.IsDefault()) + { + setting.SetClean(); + } + User::LeaveIfError(Create(setting, policy, singleMetaFound)); + setting.Pop(); + } + if(err == KErrNotFound) + { + err = KErrNone; + } + User::LeaveIfError(err); + CleanupStack::Pop(4,&iRangeMeta); + } + +/** +Resets current repository data - actually all of them, which may be loaded from +the related ini file. +The iUid data member value is kept as it was at the moment of creation of +CHeapRepository object. +*/ +void CHeapRepository::ResetContent() + { + iSettings.Reset(); + iOwner = KNullUid; + iTimeStamp = TTime(0); + + for (TInt i=0;i*>(aPtr)->ResetAndDestroy(); + } + +TInt CHeapRepository::ReloadContentExceptSettingsL(CIniFileIn& aIniFile) + { + // Look for an "owner" section + TUint32 uidValue(KNullUid.iUid); + TInt err = aIniFile.ReadOwnerSectionL(uidValue); + if(err == KErrCorrupt) + { + return err; + } + iOwner.iUid = uidValue; + // Timestamp + TTime timeStamp (0); + err = aIniFile.ReadTimeStampSectionL(timeStamp); + if(err == KErrCorrupt) + { + return err; + } + iTimeStamp=timeStamp; + + // Metadata + err = aIniFile.ReadDefaultMetaSecSectionL(iDefaultMeta, iRangeMeta); + // Even if err == KErrCorrupt, some items might have already been placed in the array + CleanupClosePushL(iRangeMeta); + if(err == KErrCorrupt) + { + CleanupStack::PopAndDestroy(&iRangeMeta); + return err; + } + + // Default read/write policies + TBool gotDefaultReadPolicy; + TBool gotDefaultWritePolicy; + TSecurityPolicy defaultReadPolicy; + TSecurityPolicy defaultWritePolicy; + err = aIniFile.ReadPlatSecSectionL(defaultReadPolicy, gotDefaultReadPolicy, + defaultWritePolicy, gotDefaultWritePolicy, + iRangePolicies); + // Even if err == KErrCorrupt, some items might have already been placed in the array + CleanupClosePushL(iRangePolicies); + if(err == KErrCorrupt) + { + CleanupStack::PopAndDestroy(2,&iRangeMeta); + return err; + } + + iDefaultPolicy = TSettingsAccessPolicy(defaultReadPolicy,defaultWritePolicy, KUnspecifiedKey); +#ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS + if (gotDefaultReadPolicy) + iDefaultPolicy.iHighKey=1; + if (gotDefaultWritePolicy) + iDefaultPolicy.iKeyMask=1; +#endif + CleanupStack::Pop(2,&iRangeMeta); + return KErrNone; + } + +TBool CHeapRepository::IsEmpty() + { + if(iSettings.Count() != 0 || iRangeMeta.Count() != 0 || + iSinglePolicies.Count() != 0 || iRangePolicies.Count() != 0) + { + return EFalse; + } + return ETrue; + }