diff -r c32dc0be5eb4 -r 6b4fc789785b remotestoragefw/remotefileengine/src/rsfwfileengine.cpp --- a/remotestoragefw/remotefileengine/src/rsfwfileengine.cpp Mon Jan 18 21:00:57 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1763 +0,0 @@ -/* -* Copyright (c) 2003-2006 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: Operation independent remote file handling functions -* -*/ - - -#include -#include - -#include "rsfwfileentry.h" -#include "rsfwfiletable.h" -#include "rsfwvolumetable.h" -#include "rsfwvolume.h" -#include "rsfwrfestatemachine.h" -#include "rsfwinterface.h" -#include "rsfwcontrol.h" -#include "rsfwremoteaccess.h" -#include "rsfwfileengine.h" -#include "rsfwrfeserver.h" -#include "rsfwlockmanager.h" -#include "mdebug.h" -#include "rsfwdirent.h" -#include "rsfwdirentattr.h" -#include "rsfwinterface.h" - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::NewL -// ---------------------------------------------------------------------------- -// -CRsfwFileEngine* CRsfwFileEngine::NewL(CRsfwVolume* aVolume) - { - CRsfwFileEngine* self = CRsfwFileEngine::NewLC(aVolume); - CleanupStack::Pop(self); - return self; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::NewLC -// ---------------------------------------------------------------------------- -// -CRsfwFileEngine* CRsfwFileEngine::NewLC(CRsfwVolume* aVolume) - { - DEBUGSTRING(("CRsfwFileEngine::NewLC")); - CRsfwFileEngine* self = new (ELeave) CRsfwFileEngine(); - DEBUGSTRING(("CRsfwFileEngine: in NewLC 0x%x", self)); - CleanupStack::PushL(self); - self->ConstructL(aVolume); - return self; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::ConstructL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::ConstructL(CRsfwVolume* aVolume) - { - iRemoteAccess = NULL; - iRootFid = NULL; - iRootFep = NULL; - iVolume = aVolume; - iFs = CRsfwRfeServer::Env()->iFs; - iConnectionState = KMountNotConnected; - __ASSERT_ALWAYS(iVolume != NULL, User::Panic(KRfeServer, EConstructingServerStructs)); - iInactivityTimeout = - iVolume->iMountInfo.iMountConfig.iInactivityTimeout * 1000000; - PrepareCacheL(); - // Create file table - iFileTable = CRsfwFileTable::NewL(aVolume, iCacheRoot); - __ASSERT_ALWAYS(iVolume->iVolumeTable != NULL, User::Panic(KRfeServer, - EConstructingServerStructs)); - SetupRootL(iVolume->iVolumeTable->iPermanence); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::~CRsfwFileEngine -// ---------------------------------------------------------------------------- -// -CRsfwFileEngine::~CRsfwFileEngine() - { - DEBUGSTRING(("CRsfwFileEngine destructor")); - delete iFileTable; - delete iRemoteAccess; - delete iLockManager; - StopInactivityTimer(); - delete iInactivityTimer; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::DispatchL -// we should only come here with some synchronous requests -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::DispatchL(TRfeInArgs& aIn, TRfeOutArgs& aOut) - { - - switch(aIn.iOpCode) - { - case EFsIoctl: - DEBUGSTRING(("IOCTL")); - DoIoctlL(static_cast(aIn), - aOut); - break; - - case EFsRoot: - DEBUGSTRING(("ROOT")); - DoRootL(static_cast(aIn), - static_cast(aOut)); - break; - - case ESetAttr: - DEBUGSTRING(("SETATTR")); - DoSetAttrL(static_cast(aIn), - aOut); - break; - - default: - DEBUGSTRING(("WHAT??? - %d", aIn.iOpCode)); - User::Leave(KErrArgument); - break; - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::FullNameLC -// ---------------------------------------------------------------------------- -// -HBufC* CRsfwFileEngine::FullNameLC(CRsfwFileEntry& aFe) - { - HBufC* fn = aFe.FullNameLC(); - return fn; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::FullNameL -// ---------------------------------------------------------------------------- -// -HBufC* CRsfwFileEngine::FullNameL(CRsfwFileEntry& aFe) - { - HBufC* fn = FullNameLC(aFe); - CleanupStack::Pop(fn); - return fn; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::SetupAttributes -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::SetupAttributes(CRsfwFileEntry& aFe) - { - DEBUGSTRING(("CRsfwFileEngine::SetupAttributes")); - // Construct the attributes for a newly created file or directory, - // or a file that that was locally modified and just written to the server, - // based on local knowledge of time and file size. - // We assume that either the file is cached or it is an empty file. - // We do not touch the local or protection attributes. - - TUint att; - - // Assume that the file type has already been setup - if (aFe.Type() == KNodeTypeDir) - { - att = KEntryAttDir; - } - else - { - att = 0; - } - - TTime time; - if (aFe.IsCached()) - { - TDesC* cacheNamep = aFe.CacheFileName(); - RFile f; - if (f.Open(iFs, *cacheNamep, EFileShareAny) == KErrNone) - { - // attribute bits - TUint a; - f.Att(a); - - att |= a & KEntryAttReadOnly; - - if (aFe.Type() == KNodeTypeDir) - { - aFe.SetSize(0); - } - else - { - if (aFe.IsFullyCached()) - { - // size - TInt siz; - f.Size(siz); - DEBUGSTRING(("File is fully cached, setting size to %d", siz)); - aFe.SetSize(siz); - aFe.SetCachedSize(siz); - } - else - { - DEBUGSTRING(("File is not fully cached, not touching the size")); - // file is not fully cached - // the size cannot be set from the local cache container - } - } - // modification time - f.Modified(time); - - f.Close(); - aFe.iUseCachedData = ETrue; - } - else - { - // No cache - aFe.SetSize(0); - time.HomeTime(); - } - - } - else - { - // No cache - aFe.SetSize(0); - time.HomeTime(); - } - - aFe.SetAtt(att); - - aFe.SetModified(time); - aFe.SetAttribValidationTime(); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::MakeDirectoryEntry -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::MakeDirectoryEntry(CRsfwFileEntry& aFe, TDirEnt& aDirEnt) - { - DEBUGSTRING(("CRsfwFileEngine::MakeDirectoryEntry")); - DEBUGSTRING16(("name %S, att %d, size %d", aFe.Name(), aFe.Att(), aFe.Size()));; - aDirEnt.Clear(); - aDirEnt.iName.Copy(*aFe.Name()); - aDirEnt.iAttr.iAtt = aFe.Att(); - aDirEnt.iAttr.iSize = aFe.Size(); - aDirEnt.iAttr.iModified = aFe.Modified(); - aDirEnt.iAttr.iUid3 = aFe.iUid; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::UpdateDirectoryContainerL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::UpdateDirectoryContainerL(CRsfwFileEntry& aFe) - { - // Construct the directory container based on - // file table information - DEBUGSTRING16(("Update directory container of %d (%S)", aFe.Fid().iNodeId, aFe.Name())); - - TDesC* cacheNamep = aFe.CacheFileName(); - if (!cacheNamep) - { - // There was no prior cache. - DEBUGSTRING(("Cache missing!")); - User::Leave(KErrGeneral); - } - - RFile f; - CleanupClosePushL(f); - User::LeaveIfError(f.Replace(iFs, - *cacheNamep, - EFileShareAny | EFileWrite)); - RFileWriteStream fStream(f); - CleanupClosePushL(fStream); - - RPointerArray* kidsp = aFe.Kids(); - TInt i; - if (!(iVolume->iVolumeTable->EnsureCacheCanBeAddedL( - sizeof(TEntry) * kidsp->Count()))) - { // pessimistic estimate - User::Leave(KErrDiskFull); - } - for (i = 0; i < kidsp->Count(); i++) - { - CRsfwFileEntry* kidFep = (*kidsp)[i]; - TDirEnt dirEnt; - MakeDirectoryEntry(*kidFep, dirEnt); - dirEnt.ExternalizeL(fStream); - } - CleanupStack::PopAndDestroy(2, &f); // f - - aFe.ResetLocallyDirty(); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::DataChanged -// ---------------------------------------------------------------------------- -// -TInt CRsfwFileEngine::DataChanged(const CRsfwDirEntAttr& aOldAttr, - const CRsfwDirEntAttr& aNewAttr) - { - // Based on attributes or metadata in general, - // tell whether the actual data, if cached, - // should be updated - if (aOldAttr.Att() == KEntryAttDir) - { - // use Last Modified (a weak entity tag) - if (aOldAttr.Modified() == aNewAttr.Modified()) - { - return EFalse; - } - else - { - return ETrue; - } - } - else - { - // use ETags if available - // a strong entity tag - if (aOldAttr.ETag() && aNewAttr.ETag()) - { - if (*aOldAttr.ETag() == *aNewAttr.ETag()) - { - return EFalse; - } - else - { - return ETrue; - } - } - - // use Last Modified (a weak entity tag) - // we assume it's file and compare also iSize... - if ((aOldAttr.Modified() == aNewAttr.Modified()) && - (aOldAttr.Size() == aNewAttr.Size())) - { - return EFalse; - } - else - { - return ETrue; - } - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::UseCachedData -// ---------------------------------------------------------------------------- -// -TBool CRsfwFileEngine::UseCachedData(CRsfwFileEntry& aFe) - { - if (!Disconnected()) - { - return aFe.UseCachedData(); - } - else - { - return ETrue; - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::UseCachedAttributes -// ---------------------------------------------------------------------------- -// -TBool CRsfwFileEngine::UseCachedAttributes(CRsfwFileEntry& aFe) - { - if (!Disconnected()) - { - if (aFe.Type() == KNodeTypeDir) - { - return iFileTable->Volume()->iVolumeTable-> - IsCachedAttrStillValid(aFe.iAttribValidation); - } - else - { // file - return iFileTable->Volume()->iVolumeTable-> - IsCachedDataStillValid(aFe.iAttribValidation); - - } - } - else - { - return ETrue; - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::GetAttributesL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::GetAttributesL(CRsfwFileEntry& aFe, - CRsfwDirEntAttr*& aAttr, - TUint aNodeType, - CRsfwRfeStateMachine* aCaller) - { - // Gets attributes for File Entry aFe. - // Uses either cached attributes (if they are still deemed to be valid), or - // fetches the attributes from the server*/ - DEBUGSTRING(("GetAttributesL")); - if ((aFe.Type() == aNodeType) && UseCachedAttributes(aFe)) - { - // Nothing to do - - if (aFe.IsOpenedForWriting()) - { - // update attributes when we are writing to the file - DEBUGSTRING(("volatile attributes")); - SetupAttributes(aFe); - } - else - { - DEBUGSTRING(("using cached attributes")); - } - aCaller->HandleRemoteAccessResponse(0, KErrNone); // "file exists" - } - else - { - // Refresh attributes - UpdateAttributesL(aFe, aAttr, aNodeType, aCaller); - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::UpdateAttributesL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::UpdateAttributesL(CRsfwFileEntry& aFe, - CRsfwDirEntAttr*& aAttr, - TUint aNodeType, - MRsfwRemoteAccessResponseHandler* aCaller) - { - // UpdateAttributes doesn't attempt to use cached attributes - HBufC* path = FullNameLC(aFe); - TPtr p = path->Des(); - DEBUGSTRING16(("UpdateAttributesL of '%S'", &p)); - - - UpdateAttributesL(*path, aAttr, aNodeType, aCaller); - - CleanupStack::PopAndDestroy(path); // path - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::UpdateAttributesL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::UpdateAttributesL(TDesC& aPath, - TDesC& aName, - CRsfwDirEntAttr*& aAttr, - TUint aNodeType, - MRsfwRemoteAccessResponseHandler* aCaller) - { - HBufC* pn = HBufC::NewLC(KMaxPath); - TPtr pnPtr = pn->Des(); - - if (aPath.Length()) - { - pnPtr.Copy(aPath); - pnPtr.Append('/'); - } - pnPtr.Append(aName); - - DEBUGSTRING16(("UpdateKidAttributes of '%S'", &pnPtr)); - - UpdateAttributesL(pnPtr, aAttr, aNodeType, aCaller); - - CleanupStack::PopAndDestroy(pn); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::UpdateAttributesL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::UpdateAttributesL(TDesC& aFullPath, - CRsfwDirEntAttr*& aAttr, - TUint aNodeType, - MRsfwRemoteAccessResponseHandler* aCaller) - { - - // If we have "recently" found out that this file/dir does NOT exist - // we cache even this negative result. Time limit is cache expiry for - // directory attributes - if ((aFullPath.Length() > 0) && // do not compare root folder (always exists) - (iLastFailedLookup == aFullPath) && - (iFileTable->Volume()->iVolumeTable-> - IsCachedAttrStillValid(iLookupTime))) - { - if (aNodeType == KNodeTypeDir) - { - aCaller->HandleRemoteAccessResponse(0, KErrPathNotFound); - } - else if (aNodeType == KNodeTypeFile) - { - aCaller->HandleRemoteAccessResponse(0, KErrNotFound); - } - return; - - } - - if (!Disconnected()) - { - if (aNodeType == KNodeTypeDir) - { - RemoteAccessL()->GetDirectoryAttributesL(aFullPath, aAttr, aCaller); - } - else if (aNodeType == KNodeTypeFile) - { - RemoteAccessL()->GetFileAttributesL(aFullPath, aAttr, aCaller); - } - } - else - { - User::Leave(KErrNotFound); - } - - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::CreateContainerFileL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::CreateContainerFileL(CRsfwFileEntry& aFe) - { - // Create a container file for the Fid. - // If the cache file already exists, it will be deleted - - RFile f; - HBufC* cachePath = HBufC::NewMaxLC(KMaxPath); - TPtr pathPtr = cachePath->Des(); - BuildContainerPathL(aFe, pathPtr); - - TInt err = f.Replace(iFs, *cachePath, EFileShareAny | EFileWrite); - f.Close(); - if (err != KErrNone) - { - DEBUGSTRING(("Error when creating container file! err=%d", err)); - User::Leave(KErrGeneral); - } - aFe.SetCacheFileName(cachePath); - CleanupStack::PopAndDestroy(cachePath); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::FetchAndCacheL -// ---------------------------------------------------------------------------- -// -TUint CRsfwFileEngine::FetchAndCacheL(CRsfwFileEntry& aFe, - TInt aFirstByte, - TInt* aLength, - RPointerArray* aDirEntsp, - CRsfwRfeStateMachine* aCaller) - { - // Fetch a file from the remote store and decrypt it if necessary. - // The assumption is that the file has not yet been fetched - // or has been cached up to the byte indicated by (aFe.iCachedSize - 1) - // and filling the cache will continue linearly - // i.e. aFirstByte = 0 || aFirstByte = aFe.iCachedSize - // Access modules can fetch more than requested, so aLastByte might change. - - DEBUGSTRING(("Fetch fid %d, bytes %d - %d", - aFe.Fid().iNodeId, - aFirstByte, - aFirstByte + *aLength)); - - TUint transactionId = 0; - RFile f; - HBufC* fullName = NULL; - HBufC* cacheName = HBufC::NewMaxLC(KMaxPath); - TPtr cachePtr = cacheName->Des(); - TInt err; - - TInt usedCache = iVolume->iVolumeTable->TotalCachedSize(); - - // This much will be added to the cache by this fetch - if (!iVolume->iVolumeTable->EnsureCacheCanBeAddedL(*aLength)) - { - User::Leave(KErrDiskFull); - } - - if (!Disconnected()) - { - if (aFe.CacheFileName()) - { - // modify an existing cachefile ... - cachePtr = *(aFe.CacheFileName()); - - if (aFe.Type() == KNodeTypeFile) - { - // If the cache file exists, - // we will just continue filling it... - err = f.Open(iFs, *cacheName, EFileShareAny | EFileWrite); - if (err) - { - User::LeaveIfError(f.Replace(iFs, - *cacheName, - EFileShareAny | EFileWrite)); - } - } - else - { - User::LeaveIfError(f.Replace(iFs, - *cacheName, - EFileShareAny | EFileWrite)); - } - } - else - { - // create a new cache file - CreateContainerFileL(aFe, cachePtr, f); - } - - CleanupClosePushL(f); - fullName = FullNameLC(aFe); - if (aFe.Type() == KNodeTypeDir) - { - transactionId = GetDirectoryL(aFe, - *fullName, - f, - aDirEntsp, - aCaller); - } - else if (aFe.Type() == KNodeTypeFile) - { - f.Close(); - transactionId = RemoteAccessL()->GetFileL(*fullName, - *cacheName, - aFirstByte, - aLength, - 0, - aCaller); - } - - // fullName, f (duplicate close in the case of files) - CleanupStack::PopAndDestroy(2, &f); - } - CleanupStack::PopAndDestroy(cacheName); - return transactionId; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::RequestConnectionStateL -// ---------------------------------------------------------------------------- -// -TUint CRsfwFileEngine::RequestConnectionStateL(TUint aConnectionState, - CRsfwRfeStateMachine* aCaller) - { - DEBUGSTRING16(("CRsfwFileEngine::RequestConnectionStateL %d", aConnectionState)); - DEBUGSTRING16(("current connection state is %d", iConnectionState)); - TUint transactionId = 0; - if (aConnectionState != iConnectionState) - { - switch (aConnectionState) - { - case KMountNotConnected: - DisconnectL(); - break; - case KMountStronglyConnected: - transactionId = ConnectL(ETrue, aCaller); - break; - - default: - break; - } - } - // else does not do anything (if iConnectionState == aConnectionState) - return transactionId; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::EnteredConnectionStateL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::EnteredConnectionStateL(TUint aConnectionState, - TBool aRequested) - { - DEBUGSTRING16(("CRsfwFileEngine::EnteredConnectionStateL %d", aConnectionState)); - DEBUGSTRING16(("current connection state is %d", iConnectionState)); - if (aConnectionState != iConnectionState) - { - iConnectionState = aConnectionState; - iVolume->ConnectionStateChanged(iConnectionState); - - switch (aConnectionState) - { - case KMountNotConnected: - if (!aRequested) - { - iRemoteAccess->Cancel(0); - } - break; - - case KMountStronglyConnected: - if (aRequested) - { - if (iLockManager) - { - iLockManager->PopulateExternalLockTokenCacheL(iRootFep); - } - } - break; - - default: - break; - } - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::ConnectionState -// ---------------------------------------------------------------------------- -// -TUint CRsfwFileEngine::ConnectionState() - { - return iConnectionState; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::LockManager -// ---------------------------------------------------------------------------- -// -CRsfwLockManager* CRsfwFileEngine::LockManager() - { - return iLockManager; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::SetPermanenceL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::SetPermanenceL(TBool aPermanence) - { - iFileTable->SetPermanenceL(aPermanence); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::Disconnected -// ---------------------------------------------------------------------------- -// -TBool CRsfwFileEngine::Disconnected() - { - return (iConnectionState == KMountNotConnected); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::WriteDisconnected -// ---------------------------------------------------------------------------- -// -TBool CRsfwFileEngine::WriteDisconnected() - { - // This also encompasses disconnected mode - return (iConnectionState != KMountStronglyConnected); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::AddToCacheL -// ---------------------------------------------------------------------------- -// -TInt CRsfwFileEngine::AddToCacheL(CRsfwFileEntry& aFe, - RPointerArray* aDirEnts, - CRsfwFileEngine *aFileEngine, - TUint cachedSize) - { - // returns the size of the cached data - RFs fs = CRsfwRfeServer::Env()->iFs; - TInt err; - TInt kidsCount = 0; - TInt containerSize = cachedSize; - // holds true for files, will be overwritten for directories - - if (aFe.Type() == KNodeTypeDir) - { - // *********** originally from CRsfwFileEngine::GetDirectoryL() - // ********************************************************** - // Unmark and mark kids only when getdirectory returns KErrNone - // otherwise (i.e. KErrUpdateNotRequired) let's just keep - // the cached kids... - aFe.UnmarkKids(); - - RApaLsSession lsSession; - User::LeaveIfError(lsSession.Connect()); - CleanupClosePushL(lsSession); - - RFileWriteStream fStream; - // Dump to the local cache - User::LeaveIfError( - fStream.Open(fs, - *(aFe.CacheFileName()), - EFileWrite | EFileShareAny)); - CleanupClosePushL(fStream); - - containerSize = fStream.Sink()->SizeL(); - TInt i; - TLex lex; - for (i = 0; i < aDirEnts->Count(); i++) - { - CRsfwDirEnt* d = (*aDirEnts)[i]; - TUid appUid; - // For each TDirEnt we just read... - // ... if the server returned content-type - if (d->Attr()->MimeType() && d->Attr()->MimeType()->Length()) - { - err = lsSession.AppForDataType(*(d->Attr()->MimeType()), - appUid); - if (err == KErrNone) - { - d->Attr()->SetUid(appUid); - } - } - - d->Attr()->SetAttFlags(KEntryAttRemote); - CRsfwFileEntry* kidFep = aFe.FindKidByName(*d->Name()); - if (kidFep) - { - // We already know this kid - // However we must check whether the kid has been modified - CRsfwDirEntAttr* oldAttr = CRsfwDirEntAttr::NewLC(); - kidFep->GetAttributesL(*oldAttr); - if (DataChanged(*oldAttr, *d->Attr())) - { - kidFep->RemoveCacheFile(); - } - CleanupStack::PopAndDestroy(oldAttr); - if (kidFep->IsFullyCached()) - { - // Mark the kid as cached - d->Attr()->ResetAttFlags(KEntryAttRemote); - } - // as this entry is "used", move it to the back of metadata LRU list - iVolume->iVolumeTable->MoveToTheBackOfMetadataLRUPriorityListL(kidFep); - } - - // As a side effect, - // insert this kid into the file table and - // set its attributes - if (!kidFep) - { - if (!iVolume->iVolumeTable->EnsureMetadataCanBeAddedL(&aFe)) - { - User::Leave(KErrNoMemory); - } - kidFep = CRsfwFileEntry::NewL(*d->Name(), &aFe); - // Attach the new kid - aFileEngine->iFileTable->AddL(kidFep); - aFe.AddKid(*kidFep); - } - - kidFep->Mark(); - - // set attributes if getting directory listing also supports getting file attributes - if (DirectoryListingContainsFileMetadata()) - { - kidFep->SetAttributesL(*d->Attr(), ETrue); - } - else - { - kidFep->SetAttributesL(*d->Attr(), EFalse); - } - - TDirEnt dirEnt; - MakeDirectoryEntry(*kidFep, dirEnt); - dirEnt.ExternalizeL(fStream); - kidsCount++; - } - - aFe.DropUnmarkedKidsL(); - - containerSize = fStream.Sink()->SizeL(); - // assumes that this fetch will write the whole directory, - - // i.e. there is no partial fetching for the directories - if(!iFileTable->Volume()->iVolumeTable-> - EnsureCacheCanBeAddedL(containerSize)) - { - User::Leave(KErrDiskFull); - } - fStream.CommitL(); - - CleanupStack::PopAndDestroy(2, &lsSession); // fStream, lsSession - - // if the directory appeared to be childless add it to metadata LRU list - if ( aDirEnts->Count() == 0 ) - { - iVolume->iVolumeTable->AddToMetadataLRUPriorityListL(&aFe, ECachePriorityNormal); - } - - }// if directory - - // assumes the files are cached in continuos chunks, - // i.e. always cached up to the last byte fetched - aFe.SetCachedSize(containerSize); - - aFe.SetCached(ETrue); - - // We have to update locally dirty bit for the parent container - if (aFe.Parent()) - { - aFe.Parent()->SetLocallyDirty(); - } - // But the object itself cannot be remotely dirty any more - aFe.ResetRemotelyDirty(); - - // *** from CRsfwFileEngine::DoFetch *** - if (aFe.Type() == KNodeTypeDir) - { - // the reason why kidsCount may be different than aFe.Kids.Count is that for big directories - // some kids could have been removed when adding the others to memory. this is due to memory management cap. - // however this should not happen so often - aFe.KidsCount() == kidsCount ? aFe.iUseCachedData = ETrue : aFe.iUseCachedData = EFalse; - } - else - { - aFe.iUseCachedData = ETrue; - } - - return containerSize; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::RemoteAccessL -// ---------------------------------------------------------------------------- -// -CRsfwRemoteAccess* CRsfwFileEngine::RemoteAccessL() - { - DEBUGSTRING(("CRsfwFileEngine::RemoteAccessL")); - if (!iRemoteAccess) - { - User::Leave(KErrNotReady); - } - - // Prevent the inactivity timer from triggering - // in the middle of a remote access operation - StopInactivityTimer(); - - return iRemoteAccess; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::OperationCompleted -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::OperationCompleted() - { - DEBUGSTRING(("File engine operation completed")); - if (iVolume->iVolumeTable->iPermanence) - { - iFileTable->SaveMetaDataDelta(); - } - - if (iLockManager && (iLockManager->LockedCount() == 0)) - { - // Start timer only if we don't have files open for writing - StartInactivityTimer(); - } - - iVolume->OperationCompleted(); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::CancelTransaction -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::CancelTransaction(TUint iTransactionId) - { - DEBUGSTRING(("CRsfwFileEngine::CancelTransactionL")); - if (iRemoteAccess) - { - iRemoteAccess->Cancel(iTransactionId); - } - - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::CancelTransaction -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::CancelTransactionL(TDesC& aPathName) - { - DEBUGSTRING(("CRsfwFileEngine::CancelTransactionL")); - TPtrC testPtr; - testPtr.Set(aPathName.Right(aPathName.Length() - 3)); - HBufC* cancelPath = HBufC::NewLC(KMaxPath); - TPtr cancelPathPtr = cancelPath->Des(); - // change '\\' to '/' so the path matches - TLex parser(testPtr); - TChar theChar; - - for (int i = 0; i < testPtr.Length(); i++) - { - theChar = parser.Get(); - if (theChar == 0) - { - break; - } - // assumes that the input string always has "\\" and not just "\" - // this is true as the input is a file path - if (theChar != '\\') - { - cancelPathPtr.Append(theChar); - } - else - { - cancelPathPtr.Append('/'); - } - } - - if (iRemoteAccess) - { - iRemoteAccess->Cancel(*cancelPath); - } - - CleanupStack::PopAndDestroy(cancelPath); - - } - - - - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::SetFailedLookup -// Caches the last failed lookup result -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::SetFailedLookup(TDesC& aPath, TDesC& aKidName) - { - iLastFailedLookup = aPath; - iLastFailedLookup.Append('/'); - iLastFailedLookup.Append(aKidName); - iLookupTime.HomeTime(); - DEBUGSTRING16(("SetFailedLookup: %S", &iLastFailedLookup)); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::ResetFailedLookup -// Clears the last failed lookup result -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::ResetFailedLookup() - { - DEBUGSTRING16(("ResetFailedLookup: %S", &iLastFailedLookup)); - iLastFailedLookup.Zero(); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::Volume -// ---------------------------------------------------------------------------- -// -CRsfwVolume* CRsfwFileEngine::Volume() - { - return iVolume; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::PrepareCacheL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::PrepareCacheL() - { - // make sure the file cache (of this volume) exists - iCacheRoot.Copy(CRsfwRfeServer::Env()->iCacheRoot); - iCacheRoot.Append('C'); - iCacheRoot.AppendNum(iVolume->iMountInfo.iMountStatus.iVolumeId); - iCacheRoot.Append('\\'); - - if (! BaflUtils::FileExists(iFs, iCacheRoot)) - { - // There was no prior cache directory - TInt err = iFs.MkDirAll(iCacheRoot); - DEBUGSTRING(("Cache directory created with err=%d", err)); - User::LeaveIfError(err); - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::GetDirectoryL -// ---------------------------------------------------------------------------- -// -TUint CRsfwFileEngine::GetDirectoryL(CRsfwFileEntry& /*aFe*/, - TDesC& aFullName, - RFile& /*aF*/, - RPointerArray* aDirEntsp, - MRsfwRemoteAccessResponseHandler* aCaller) - { - return RemoteAccessL()->GetDirectoryL(aFullName, *aDirEntsp, aCaller); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::BuildContainerPathL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::BuildContainerPathL(CRsfwFileEntry& aFe, TDes& aPath) - { - if (aPath.MaxLength() < (aPath.Length() + iCacheRoot.Length())) - { - aPath.Copy(iCacheRoot); - } - else - { - User::Leave(KErrOverflow); - } - - ApplyMultiDirCacheL(aPath); - // This filename tagging based on container type is just for convenience - if (aFe.Type() == KNodeTypeFile) - { - aPath.Append('F'); - } - else - { - aPath.Append('D'); - } - aPath.AppendNum((TInt)aFe.Fid().iNodeId); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::ApplyMultiDirCachePathL -// Due to Symbian performance problems with huge directories, items will not -// be stored in one directory in the cache. -// Now instead one dir like: -// C:\system\data\rsfw_cache\C16 -// there will be dirs like: -// C:\system\data\rsfw_cache\C16\M0 -// C:\system\data\rsfw_cache\C16\M1 -// ... and so on -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::ApplyMultiDirCacheL(TDes& aPath) - { - // maximum number of items in a single dir in the cache - const TInt KRsfwMaxItemsInDir = 100; - TInt i; - // this loop will surely break (or leave) at some point - for ( i = 0; ; i++ ) - { - // create path like "C:\system\data\rsfw_cache\C16\M0" - HBufC* trypath = HBufC::NewMaxL(KMaxPath); - TPtr pathPtr = trypath->Des(); - pathPtr.Copy(aPath); - pathPtr.Append('M'); - pathPtr.AppendNum(i); - pathPtr.Append('\\'); - - // check whether dir exists and if so, how many items it contains - CDir* dir = NULL; - // note that KEntryAttDir att means files & directories - TInt err = iFs.GetDir(*trypath, KEntryAttDir, ESortNone, dir); - if ( err == KErrNone ) - { - // count the items - TInt count = dir->Count(); - delete dir; - dir = NULL; - - //limit is not exceeded -> return the path - if ( count < KRsfwMaxItemsInDir ) - { - aPath.Copy(pathPtr); - delete trypath; - break; - } - // limit exceeded -> let's try the next dir - else - { - delete trypath; - continue; - } - } - else if ( err == KErrPathNotFound ) - { - // create dir and return the path to empty dir - err = iFs.MkDir(*trypath); - if (!err) - { - aPath.Copy(pathPtr); - delete trypath; - } - else - { - delete trypath; - DEBUGSTRING(("Error when creating cache dir! err=%d", err)); - User::Leave(KErrGeneral); - } - - break; - } - else - { - delete trypath; - DEBUGSTRING(("Cache directory cannot be created! err=%d", err)); - User::Leave(KErrGeneral); - } - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::CreateContainerFileL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::CreateContainerFileL(CRsfwFileEntry& aFe, - TDes& aPath, - RFile& aF) - { - // Create a container file for the Fid. - // If the cache file already exists, it will be deleted - - BuildContainerPathL(aFe, aPath); - - TInt err = aF.Replace(iFs, aPath, EFileShareAny | EFileWrite); - if (err != KErrNone) - { - User::Leave(KErrGeneral); - } - aF.Close(); - - aFe.SetCacheFileName(&aPath); - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::DoIoctlL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::DoIoctlL(TRfeIoctlInArgs& aIn, TRfeOutArgs& /* aOut */) - { - TFid fidp = aIn.iFid; - TInt cmd = aIn.iCmd; - - TInt err = KErrNone; - - DEBUGSTRING(("ioctl fid %d - command=%d, data=%d", - fidp.iNodeId, - cmd, - aIn.iData32[0])); - - CRsfwFileEntry* fep = iFileTable->Lookup(fidp); - if (fep) - { - switch (cmd) - { - case ERemoteFsIoctlRefresh: - - - if (fep->Type() == KNodeTypeFile) - { - - fep->SetCacheFileName(NULL); - fep->SetCached(EFalse); - - // There is a change in the parent's container - fep->Parent()->SetLocallyDirty(); - } - break; - - case ERemoteFsHighCachePriority: - default: - err = KErrArgument; - break; - } - } - else - { - err = KErrNotFound; - } - - if (err != KErrNone) - { - User::Leave(err); - } - - return; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::DoRootL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::DoRootL(TRfeRootInArgs& /* aIn */, TRfeRootOutArgs& aOut) - { - SetupRootL(iVolume->iVolumeTable->iPermanence); - aOut.iFid.iVolumeId = iRootFid->iVolumeId; - aOut.iFid.iNodeId = iRootFid->iNodeId; - return; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::DoSetAttrL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::DoSetAttrL(TRfeSetAttrInArgs& aIn, TRfeOutArgs& /* aOut */) - // We cannot really set anything but this is the way to implement this - // note that if this is implemented, it should really be a state machine - { - TInt err = KErrNone; - TFid fidp = aIn.iFid; -#ifdef _DEBUG - TDirEntAttr* attrp = &(aIn.iAttr); -#endif - - DEBUGSTRING(("setting attributes of fid %d, attr=0x%x, size=%d, time=", - fidp.iNodeId, - attrp->iAtt, - attrp->iSize)); - DEBUGTIME((attrp->iModified)); - - // Get the file or directory to setattr - CRsfwFileEntry* fep = iFileTable->Lookup(fidp); - if (fep) - { - err = KErrNotSupported; - } - else - { - err = KErrNotFound; - } - - User::Leave(err); - return; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::SetupRootL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::SetupRootL(TBool aPermanence) - { - _LIT(KRootPath, "."); // dummy - - if (!iRootFid) - { - CRsfwFileEntry* root = NULL; - TInt err; - if (aPermanence) - { - TRAP(err, root = iFileTable->LoadMetaDataL()); - } - if (err == KErrCorrupt) - { - DEBUGSTRING(("Metadata corrupted! Recreating cache file...")); - // corrupted cache file, recreate filetable and cache file - delete iFileTable; - iFileTable = NULL; - CleanupCorruptedCacheL(); - PrepareCacheL(); - iFileTable = CRsfwFileTable::NewL(iVolume, iCacheRoot); - } - if (!aPermanence || (err != KErrNone)) - { - root = CRsfwFileEntry::NewL(KRootPath, NULL); - // Insert root into the file table - iFileTable->AddL(root); - root->SetType(KNodeTypeDir); - } - if (aPermanence) - { - iFileTable->SaveMetaDataDelta(); - } - iRootFep = root; - iRootFid = &(root->Fid()); - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::CleanupCorruptedCacheL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::CleanupCorruptedCacheL() - { - // delete everything from the cache - TFileName cachepath; - cachepath.Copy(iCacheRoot); - CFileMan* fileMan = CFileMan::NewL(iFs); - fileMan->Delete(cachepath, CFileMan::ERecurse); - delete fileMan; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::ConnectL -// ---------------------------------------------------------------------------- -// -TUint CRsfwFileEngine::ConnectL(TBool aRestart, CRsfwRfeStateMachine* aCaller) - { - // Assume parameter format: - // protocol://username:password@server:port/rootdir or - // The ":password", ":port", and "[/]rootdir" can be omitted. - // If the length of password parameter is bigger than 1, - // it overrides the one in uri, if any. - // Characters can be quoted with % format - TUint transactionId = 0; - - if (iRemoteAccess) - { - // We already have a remote accessor - if (aRestart) - { - // Restarting - delete iLockManager; - iLockManager = NULL; - delete iRemoteAccess; - iRemoteAccess = NULL; - } - else - { - User::Leave(KErrAlreadyExists); - } - } - - DEBUGSTRING16(("ConnectL(): '%S'", - &iVolume->iMountInfo.iMountConfig.iUri)); - - TUriParser uriParser; - User::LeaveIfError(uriParser.Parse(iVolume->iMountInfo.iMountConfig.iUri)); - - TPtrC userName; - TPtrC password; - TPtrC friendlyName; - - if (uriParser.IsPresent(EUriUserinfo)) - { - TPtrC userInfo(uriParser.Extract(EUriUserinfo)); - // Split the user info into user name and password (seprated by ':') - TInt pos = userInfo.Locate(':'); - if (pos != KErrNotFound) - { - password.Set(userInfo.Mid(pos + 1)); - userName.Set(userInfo.Left(pos)); - } - else - { - userName.Set(userInfo); - } - } - - HBufC* userNameBuf = NULL; - if (!userName.Length() && - iVolume->iMountInfo.iMountConfig.iUserName.Length()) - { - // separate user name overwrites the username embedded in the URI - userName.Set(iVolume->iMountInfo.iMountConfig.iUserName); - } - - HBufC* passwordBuf = NULL; - if (!password.Length() && - (iVolume->iMountInfo.iMountConfig.iPassword.Length() > 1)) - { - // separate password overwrites the password embedded in the URI - password.Set(iVolume->iMountInfo.iMountConfig.iPassword); - } - - friendlyName.Set(iVolume->iMountInfo.iMountConfig.iName); - - TPtrC scheme(uriParser.Extract(EUriScheme)); - HBufC8* protocol = HBufC8::NewLC(scheme.Length()); - TPtr8 protocolPtr = protocol->Des(); - protocolPtr.Copy(scheme); - iRemoteAccess = CRsfwRemoteAccess::NewL(protocolPtr); - CleanupStack::PopAndDestroy(protocol); - - // user name and password are conveyed separately from the URI - CUri* uri = CUri::NewLC(uriParser); - uri->RemoveComponentL(EUriUserinfo); - - // leaves if error - iRemoteAccess->SetupL(this); - transactionId = iRemoteAccess-> - OpenL(uri->Uri(), - friendlyName, - userName, - password, - iVolume->iMountInfo.iMountConfig.iAuxData, - aCaller); - - CleanupStack::PopAndDestroy(uri); - if (passwordBuf) - { - CleanupStack::PopAndDestroy(passwordBuf); - } - if (userNameBuf) - { - CleanupStack::PopAndDestroy(userNameBuf); - } - - // lock manager can be created before we know whether connecting was - // succesful - however it must be deleted upon unsuccesful connect - if (!iLockManager) - { - iLockManager = CRsfwLockManager::NewL(iRemoteAccess); - } - - if ((iInactivityTimeout > 0) && !iInactivityTimer) - { - iInactivityTimer = CPeriodic::NewL(CActive::EPriorityLow); - } - return transactionId; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::DisconnectL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::DisconnectL() - { - DEBUGSTRING(("CRsfwFileEngine::DisconnectL")); - if (iRemoteAccess) - { - iRemoteAccess->Cancel(0); - delete iRemoteAccess; - iRemoteAccess = NULL; - } - - if (iLockManager) - { - delete iLockManager; - iLockManager = NULL; - } - - - // Set open file count to zero - // If there are open files, after disconnecting we do not necessarily - // get close events. - // Note that this variable is not "dirty bit" (file has currently - // uncommitted modifications), so it is safe to set it to zero - TInt openfiles = iFileTable->OpenFileCount(); - iFileTable->UpdateOpenFileCount(-openfiles); - - EnteredConnectionStateL(KMountNotConnected, ETrue); - - // publish connection status when disconnecting - iVolume->iVolumeTable->PublishConnectionStatus(iVolume); - - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::StartInactivityTimer -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::StartInactivityTimer() - { - if (iInactivityTimer) - { - DEBUGSTRING(("inactivity timer started (%d us)", - iInactivityTimeout)); - iInactivityTimer->Cancel(); - TCallBack callBack(CRsfwFileEngine::InactivityTimerExpired, this); - iInactivityTimer->Start(iInactivityTimeout, - iInactivityTimeout, - callBack); - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::StopInactivityTimer -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::StopInactivityTimer() - { - DEBUGSTRING(("CRsfwFileEngine::StopInactivityTimer")); - if (iInactivityTimer) - { - DEBUGSTRING(("inactivity timer stopped")); - iInactivityTimer->Cancel(); - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::InactivityTimerExpired -// ---------------------------------------------------------------------------- -// -TInt CRsfwFileEngine::InactivityTimerExpired(TAny* aArg) - { - DEBUGSTRING(("CRsfwFileEngine::InactivityTimerExpired")); - CRsfwFileEngine* fileEngine = static_cast(aArg); - if (fileEngine->iFileTable->OpenFileCount() == 0) - { - fileEngine->StopInactivityTimer(); - TRAP_IGNORE(fileEngine->DisconnectL()); - // "Simulate" operation completion (which may result in RFE shutdown) - fileEngine->OperationCompleted(); - } - else - { - // if there are open files on this volume, just restart the inactivity timer - fileEngine->StartInactivityTimer(); - } - - return 0; - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::HandleRemoteAccessEventL -// ---------------------------------------------------------------------------- -// -void CRsfwFileEngine::HandleRemoteAccessEventL(TInt aEventType, - TInt aEvent, - TAny* /* aArg */) - { - DEBUGSTRING(("Handle remote access event: %d/%d in connection state %d", - aEventType, - aEvent, - iConnectionState)); - switch (aEventType) - { - case ERsfwRemoteAccessObserverEventConnection: - switch (aEvent) - { - case ERsfwRemoteAccessObserverEventConnectionDisconnected: - EnteredConnectionStateL(KMountNotConnected, EFalse); - break; - - case ERsfwRemoteAccessObserverEventConnectionWeaklyConnected: -#if 0 - // This event does not appear - EnteredConnectionStateL(KMountWeaklyConnected, EFalse); -#endif - break; - - case ERsfwRemoteAccessObserverEventConnectionStronglyConnected: -#if 0 - // This event does not appear - EnteredConnectionStateL(KMountStronglyConnected, EFalse); -#endif - break; - - default: - break; - } - break; - - default: - break; - } - } - -// ---------------------------------------------------------------------------- -// CRsfwFileEngine::PurgeFromCacheL -// ---------------------------------------------------------------------------- -// -TInt CRsfwFileEngine::PurgeFromCache(const TDesC& aPath) - { - // get the fid of the entry for which the cached data is removed - CRsfwFileEntry* targetFid = FetchFep(aPath); - if (!targetFid) - { - return KErrPathNotFound; - } - // only directories can be refreshed currently - if (targetFid->Type() != KNodeTypeDir) - { - return KErrArgument; - } - targetFid->SetCached(EFalse); - return KErrNone; - } - -CRsfwFileEntry* CRsfwFileEngine::FetchFep(const TDesC& aPath) - { - DEBUGSTRING16(("CRsfwFileEngine::FetchFep for file %S", &aPath)); - if (aPath.Length() <= 1) - { - DEBUGSTRING(("returning rootFep")); - return iRootFep; - } - else - { - TInt delimiterPos = aPath.LocateReverse(KPathDelimiter); - if (delimiterPos == (aPath.Length() - 1)) - { - // The path ends with a slash, - //i.e. this is a directory - continue parsing - TPtrC nextdelimiter; - nextdelimiter.Set(aPath.Left(delimiterPos)); - delimiterPos = nextdelimiter.LocateReverse(KPathDelimiter); - } - TPtrC entry(aPath.Right(aPath.Length() - (delimiterPos + 1))); - TPtrC path(aPath.Left(delimiterPos + 1)); - - // strip a trailing backslash if found - delimiterPos = entry.LocateReverse(KPathDelimiter); - if (delimiterPos == (entry.Length() - 1)) - { - TPtrC stripped(entry.Left(entry.Length() - 1)); - return (FetchFep(path)->FindKidByName(stripped)); - } - else - { - return (FetchFep(path)->FindKidByName(entry)); - } - - } - - } - -HBufC8* CRsfwFileEngine::GetContentType(TDesC& aName) - { - TInt err; - RApaLsSession lsSession; - err = lsSession.Connect(); - if (err) - { - return NULL; - } - - RFs fsSession; - err = fsSession.Connect(); - if (err) - { - lsSession.Close(); - return NULL; - } - fsSession.ShareProtected(); - TDataRecognitionResult dataType; - RFile theFile; - // the mode must mach the mode that is used in the file system plugin - // (EFileWrite|EFileShareAny) - err = theFile.Open(fsSession, aName, EFileWrite|EFileShareAny); - if (err) - { - lsSession.Close(); - fsSession.Close(); - return NULL; - } - err = lsSession.RecognizeData(theFile, dataType); - lsSession.Close(); - theFile.Close(); - fsSession.Close(); - if (err) - { - return NULL; - } - - return dataType.iDataType.Des8().Alloc(); - } - - // The purpose of these functions is to give capability info - // for the access protocol plugin used. - - // Currently this information is hard coded and takes into account webdav and upnp - // access modules. New function should be added to the access plugin api to get - // this information from the protocol module - - // whether getting the directory listing also gives reliable file metadata -TBool CRsfwFileEngine::DirectoryListingContainsFileMetadata() - { - _LIT(KUPnP, "upnp"); - if (iVolume->MountInfo()->iMountConfig.iUri.Left(4) == KUPnP) - { - return EFalse; - } - else - { - return ETrue; - } - - } -