diff -r 000000000000 -r 3ad9d5175a89 remotestoragefw/mountmanager/src/rsfwmountmanimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/remotestoragefw/mountmanager/src/rsfwmountmanimpl.cpp Thu Dec 17 09:07:59 2009 +0200 @@ -0,0 +1,755 @@ +/* +* Copyright (c) 2002-2004 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: Mount manager + * +*/ + + +// INCLUDE FILES +#include +#include // KMaxVolumeNameLength +#include +#include + +#include "rsfwinterface.h" +#include "rsfwmountmanimpl.h" + + +// CONSTANTS +const TUint8 KDefaultDriveLetter = 'J'; + // system default if no other specified; + // remote drives should use letters from J: to Y: + + +// ============================ MEMBER FUNCTIONS ============================== + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::CRsfwMountManImpl +// Constructor +// ---------------------------------------------------------------------------- +// +CRsfwMountManImpl::CRsfwMountManImpl() + { + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::NewL +// ---------------------------------------------------------------------------- +// +CRsfwMountManImpl* CRsfwMountManImpl::NewL(TUint aDefaultFlags, + MRsfwMountManObserver* aMountManObserver) + { + CRsfwMountManImpl* self = new (ELeave) CRsfwMountManImpl(); + CleanupStack::PushL(self); + self->ConstructL(aDefaultFlags, aMountManObserver); + CleanupStack::Pop(self); + return self; + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::~CRsfwMountManImpl +// ---------------------------------------------------------------------------- +// +CRsfwMountManImpl::~CRsfwMountManImpl() + { + iFs.Close(); + if (iRsfwControlConnected) + { + iRsfwControl.Close(); + } + delete iMountStore; + + iBlackList.Close(); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::GetMountNamesL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::GetMountNamesL(CDesC16Array* aNames) + { + iMountStore->GetNamesL(aNames); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::MountEntry +// ---------------------------------------------------------------------------- +// +const CRsfwMountEntry* CRsfwMountManImpl::MountEntryL(const TDesC& aName) + { + return iMountStore->LookupEntryByNameL(aName); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::MountEntry +// ---------------------------------------------------------------------------- +// +const CRsfwMountEntry* CRsfwMountManImpl::MountEntryL(TChar aDriveLetter) + { + return iMountStore->LookupEntryByDriveL(aDriveLetter); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::AddMountEntryL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::AddMountEntryL(CRsfwMountEntry* aMountEntry) + { + // Take ownership + CleanupStack::PushL(aMountEntry); + + // Look for existing configuration with the same friendly name + // overwriting not allowed + const HBufC* driveName = aMountEntry->Item(EMountEntryItemName); + const CRsfwMountEntry* entry = MountEntryL(*driveName); + if (entry) + { + User::Leave(KErrInUse); + } + // Also look for existing configuration with the same drive letter + // overwriting not allowed + TChar driveLetter = DriveLetterFromMountEntry(*aMountEntry); + if (driveLetter != '?') + { + entry = MountEntryL(driveLetter); + if (entry) + { + User::Leave(KErrInUse); + } + } + else + { + driveLetter = FreeDriveLetterL(driveLetter); + TBuf<1> driveLetterBuf; + driveLetterBuf.Append(driveLetter); + // Replace '?' with the allocated drive letter + aMountEntry->SetItemL(EMountEntryItemDrive, driveLetterBuf); + } + + // find the number of remote drives in use + // if 9 already new ones are not allowed + TDriveList fsDriveList; + User::LeaveIfError(iFs.DriveList(fsDriveList, KDriveAttRemote)); + TInt i; + TInt remoteDrives = 0; + for (i = EDriveA; i <= EDriveZ; i++) + { + if (fsDriveList[i] & KDriveAttRemote) + { + remoteDrives++; + } + } + + if (remoteDrives == KMaxRemoteDrives) + { + User::Leave(KErrInUse); + } + + // Save the friendly name (not guaranteed to survive CMountStore::AddEntryL + HBufC* name = NULL; + if (aMountEntry->Item(EMountEntryItemName)) + { + name = aMountEntry->Item(EMountEntryItemName)->AllocL(); + } + + // Release ownership + CleanupStack::Pop(aMountEntry); + // Add mount configuration repository entry + TRAPD(err, AddEntryL(aMountEntry)); + CleanupStack::PushL(name); + User::LeaveIfError(err); + + // Add mount in File Server + if (name) + { + User::LeaveIfError(MountFileSystem(*name, driveLetter)); + } + else + { + _LIT(KRsfwNoName, "remotedrive"); + User::LeaveIfError(MountFileSystem(KRsfwNoName, driveLetter)); + } + + // finally set mountconnection state to disconnected + // this will make in Remote File Engine what is called "disconnected dormant mount" + SetMountConnectionState(driveLetter, KMountNotConnected); + + CleanupStack::PopAndDestroy(name); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::DeleteMountEntryL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::DeleteMountEntryL(const TDesC& aName) + { + const CRsfwMountEntry* mountEntry = iMountStore->LookupEntryByNameL(aName); + if (mountEntry) + { + TChar driveLetter = DriveLetterFromMountEntry(*mountEntry); + if (driveLetter != '?') + { + DeleteMountEntryL(driveLetter); + } + } + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::DeleteMountEntryL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::DeleteMountEntryL(TChar aDriveLetter) + { + const CRsfwMountEntry* mountEntry = + iMountStore->LookupEntryByDriveL(aDriveLetter); + if (mountEntry) + { + // Remove entry from configuration repository + iMountStore->RemoveEntryL(aDriveLetter); + // Dismount from file server and Remote File Engine + ExecuteUnmount(aDriveLetter); + } + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::EditMountEntryL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::EditMountEntryL(CRsfwMountEntry* aMountEntry) + { + // take ownership + CleanupStack::PushL(aMountEntry); + + // look for the drive based on the letter + TChar driveLetter = DriveLetterFromMountEntry(*aMountEntry); + const CRsfwMountEntry* entryByDrive = MountEntryL(driveLetter); + if ( !entryByDrive ) + { + User::Leave(KErrNotFound); + } + + // check whether the name has changed + TBool nameChanged = EFalse; + const HBufC* newName = aMountEntry->Item(EMountEntryItemName); + const HBufC* oldName = entryByDrive->Item(EMountEntryItemName); + if ( newName->Compare(*oldName) != KErrNone ) + { + nameChanged = ETrue; + } + + // check whether URI has changed + TBool uriChanged = EFalse; + const HBufC* newUri = aMountEntry->Item(EMountEntryItemUri); + const HBufC* oldUri = entryByDrive->Item(EMountEntryItemUri); + if ( newUri->Compare(*oldUri) != KErrNone ) + { + uriChanged = ETrue; + } + + // if the name has changed -> check whether it is not used by the other mount entry + if ( nameChanged ) + { + const CRsfwMountEntry* entryByName = MountEntryL(*newName); + if ( entryByName && entryByDrive != entryByName ) + { + User::Leave(KErrInUse); + } + } + + // release ownership and call MountStore API + CleanupStack::Pop(aMountEntry); + AddEntryL(aMountEntry); + + // if URI has changed we have to unmount the drive from RFE in order + // to clear the cache and mount it again + // note there is no need to make unmounting from File System + if ( uriChanged ) + { + TInt err; + User::LeaveIfError(GetRsfwControlConnection()); + err = iRsfwControl.DismountByDriveLetter(driveLetter); + if ((err != KErrNone) && (err != KErrNotFound)) + { + User::Leave(err); + } + User::LeaveIfError(iRsfwControl.SetMountConnectionState(driveLetter, KMountNotConnected)); + } + + // if the name has changed -> change label in File System + if ( nameChanged ) + { + User::LeaveIfError(SetDriveNameToFileSystem(driveLetter, *newName)); + } + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::MountL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::MountL(TChar& aDriveLetter) + { + TInt driveNumber; + User::LeaveIfError(iFs.CharToDrive(aDriveLetter, driveNumber)); + User::LeaveIfError(GetRsfwControlConnection()); + User::LeaveIfError(iRsfwControl.Mount(driveNumber)); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::MountL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::MountBlindL(TChar& aDriveLetter) + { + TInt driveNumber; + User::LeaveIfError(iFs.CharToDrive(aDriveLetter, driveNumber)); + User::LeaveIfError(GetRsfwControlConnection()); + User::LeaveIfError(iRsfwControl.MountBlind(driveNumber)); + } + + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::SetMountConnectionState +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::SetMountConnectionState(TChar aDriveLetter, + TUint aConnectionState) + { + TInt err = GetRsfwControlConnection(); + if (err != KErrNone) + { + return err; + } + + err = iRsfwControl.SetMountConnectionState(aDriveLetter, aConnectionState); + return err; + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::IsAppOnBlackList +// ---------------------------------------------------------------------------- +// +TBool CRsfwMountManImpl::IsAppOnBlackList(TUid aUid) + { + TInt i; + for ( i = 0; i < iBlackList.Count(); i++ ) + { + if ( aUid == iBlackList[i] ) + { + return ETrue; + } + } + return EFalse; + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::GetAllDrivesL +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::GetAllDrivesL(TDriveList& aDriveList) + { + GetFsDriveListL(aDriveList, EFalse); + return aDriveList.Length(); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::GetRemoteMountList +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::GetRemoteMountListL(TDriveList& aDriveList) + { + GetFsDriveListL(aDriveList, ETrue); + return aDriveList.Length(); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::GetMountInfo +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::GetMountInfo(TChar aDriveLetter, + TRsfwMountInfo& aMountInfo) + { + TInt err = GetRsfwControlConnection(); + if (err == KErrNone) + { + err = iRsfwControl.GetMountInfo(aDriveLetter, aMountInfo); + } + return err; + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::GetRsfwControlConnection +// Set a Remote File Engine control connection unless +// we already have a connection +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::GetRsfwControlConnection() + { + TInt err = KErrNone; + if (!iRsfwControlConnected) + { + err = iRsfwControl.Connect(); + if (!err) + { + iRsfwControlConnected = ETrue; + } + } + return err; + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::MountFileSystem +// Install ERemoteFS file system plugin (if not already done) and +// mount a filesystem designated with the given drive letter +// on that file system +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::MountFileSystem(const TDesC& /*aDriveName*/, + TChar aDriveLetter) + { + return SyncWithMounterExe(ETrue, aDriveLetter); + } + + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::RemoteDriveCount +// Get the number of remote mounts as seen by the File Server +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::RemoteMountCountL() + { + // Check if how many mounts there are (also dormant mounts are counted) + TDriveList driveList; + return GetRemoteMountListL(driveList); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::DoUnmountL +// Do conditional unmounting by consulting the user +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::DoUnmountL(TChar aDriveLetter, TUint /* aFlags */) + { + TInt err = ExecuteUnmount(aDriveLetter); + User::LeaveIfError(err); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::ExecuteUnmount +// Do unconditional unmounting +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::ExecuteUnmount(TChar aDriveLetter) + { + TInt err = GetRsfwControlConnection(); + if (err != KErrNone) + { + return err; + } + + // Drop the mount both from the File Server and from Remote File Engine + TInt errFs = KErrNone; + TInt driveNumber; + err = iFs.CharToDrive(aDriveLetter, driveNumber); + if (err != KErrNone) + { + return err; + } + TDriveInfo driveInfo; + err = iFs.Drive(driveInfo, driveNumber); + if (err != KErrNone) + { + return err; + } + if (driveInfo.iDriveAtt & KDriveAttRemote) + { + // The mount is known by the File Server + errFs = iFs.DismountFileSystem(KRemoteFSName, driveNumber); + if (errFs == KErrPermissionDenied) + { + // Client does not have sufficient capabilities to do the operation + // execute mount with the boot mounter application + SyncWithMounterExe(ETrue, aDriveLetter); + } + } + + // We also request dismount from the RFE because + // The File Server (eremotefs) does not pass the + // dismount request to the RFE. + err = iRsfwControl.DismountByDriveLetter(aDriveLetter); + if (errFs != KErrNone) + { + // give priority to the File Server error + err = errFs; + } + return err; + } + + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::ConstructL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::ConstructL(TUint aDefaultFlags, + MRsfwMountManObserver* aMountManObserver) + { + iDefaultFlags = aDefaultFlags; + + User::LeaveIfError(iFs.Connect()); + iRsfwControlConnected = EFalse; + iMountManObserver = aMountManObserver; + iMountStore = CRsfwMountStore::NewL(this); + LoadBlackListL(); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::FreeDriveLetterL +// Find a drive letter that has not yet been allocated by the File Server or +// defined in the mount configuration data base +// If the suggested drive letter (given as an input parameter) +// is already occupied, an adjacent letter in the alphabet is returned. +// Letter '?' as an input parameter is equal to KDefaultDriveLetter. +// Leave with KErrInUse if there are no free drive slots +// ---------------------------------------------------------------------------- +// +TChar CRsfwMountManImpl::FreeDriveLetterL(TChar aDriveLetter) + { + if (aDriveLetter == '?') + { + // Use the system default drive letter if none is specified + aDriveLetter = KDefaultDriveLetter; + } + else if ((aDriveLetter < 'A') || (aDriveLetter > 'Z')) + { + aDriveLetter.UpperCase(); + } + + TInt driveNumber; + User::LeaveIfError(iFs.CharToDrive(aDriveLetter, driveNumber)); + + // Try to find a free drive around the given drive + + // Get drives that are already mounted in the File Server + TDriveList fsDriveList; + User::LeaveIfError(iFs.DriveList(fsDriveList, KDriveAttAll)); + // scan first upwards, then downwards from the requested drive + // (or default drive letter) until a free and legal drive letter is found + // remote drives should use letters from J: to Y: + TInt i; + for (i = driveNumber; i <= EDriveY; i++) + { + if (fsDriveList[i] == 0) + { + User::LeaveIfError(iFs.DriveToChar(i, aDriveLetter)); + return aDriveLetter; + } + } + for (i = driveNumber - 1; i >= EDriveJ; i--) + { + if (fsDriveList[i] == 0) + { + User::LeaveIfError(iFs.DriveToChar(i, aDriveLetter)); + return aDriveLetter; + } + } + + // no free drive letters for remote drives + User::Leave(KErrInUse); + return 0; + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::DriveLetterFromMountEntry +// Build a TRsfwMountConfig +// ---------------------------------------------------------------------------- +// +TChar CRsfwMountManImpl::DriveLetterFromMountEntry(const CRsfwMountEntry& aMountEntry) + { + const HBufC* drive = aMountEntry.Item(EMountEntryItemDrive); + if (drive && drive->Length()) + { + return (*drive)[0]; + } + else + { + return '?'; + } + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::AddEntryL +// Add an entry in the mount configurarion store +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::AddEntryL(CRsfwMountEntry* aMountEntry) + { + iMountStore->AddEntryL(aMountEntry); + } + + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::HandleMountStoreEvent +// Handle a mount store change notification +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::HandleMountStoreEvent(TMountStoreEvent aEvent, + TInt aStatus, + TAny* aArg) + { + if (iMountManObserver) + { + if (aEvent == EMountStoreEventMountConfigurationChanged) + { + TRAP_IGNORE(iMountManObserver->HandleMountManEventL( + EMountManEventMountConfigurationChanged, + aStatus, + aArg)); + } + } + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::SyncWithMounterExe +// Uses boot mounter exe to mount or unmount remote drives in File Server +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::SyncWithMounterExe(TBool aSetDrive, TChar aDrive) + { + TInt err; + RProcess mounter; + TRequestStatus status; + TBuf<5> parameter; + if (!aSetDrive) + { + err = mounter.Create(KRsfwMounterExe, _L("")); + } + else + { + parameter.Append(aDrive); + err = mounter.Create(KRsfwMounterExe, parameter); + } + + if (err == KErrNone) + { + mounter.Resume(); + mounter.Logon(status); + User::WaitForRequest(status); + mounter.Close(); + err = status.Int(); + } + return err; + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::GetFsDriveList +// +// Returns drive letters. Letters for remote drives in order defined in CenRep +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::GetFsDriveListL(TDriveList& aDriveList, TBool aRemoteOnly) + { + TDriveList driveList; + // get local drives + User::LeaveIfError(iFs.DriveList(driveList)); + + // local drives are assumed to be from C:\ to R:\ + // these will go to the front of the list + if (!aRemoteOnly) + { + for (int i = EDriveC; i <= EDriveZ; i++) + { + if ( (driveList[i]) && (!(driveList[i] & KDriveAttRemote)) ) + { + TChar driveLetter; + User::LeaveIfError(iFs.DriveToChar(i, driveLetter)); + aDriveList.Append(driveLetter); + } + } + } + + GetRemoteDriveListL(driveList); + + for (int i = 0; i < driveList.Length(); i++) + { + aDriveList.Append(driveList[i]); + } + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::GetRemoteDriveList +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::GetRemoteDriveListL(TDriveList& aDriveList) + { + iMountStore->GetDriveLettersL(aDriveList); + return aDriveList.Length(); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::SetDriveNameToFileSystem +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::SetDriveNameToFileSystem(TChar aDriveLetter, + const TDesC& /*aDriveName*/) + { + return SyncWithMounterExe(ETrue, aDriveLetter); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::RefreshDirectoryL +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::RefreshDirectory(const TDesC& aPath) + { + TInt err; + err = GetRsfwControlConnection(); + if (err != KErrNone) + { + return err; + } + return iRsfwControl.RefreshDirectory(aPath); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::LoadBlackListL +// ---------------------------------------------------------------------------- +// +void CRsfwMountManImpl::LoadBlackListL() + { + +// const TUid app1 = TUid::Uid(0x00000000); +// const TUid app2 = TUid::Uid(0x00000001); +// const TUid app3 = TUid::Uid(0x00000002); + + iBlackList.Reset(); +// iBlackList.AppendL(app1); +// iBlackList.AppendL(app2); +// iBlackList.AppendL(app3); + } + +// ---------------------------------------------------------------------------- +// CRsfwMountManImpl::LoadBlackListL +// ---------------------------------------------------------------------------- +// +TInt CRsfwMountManImpl::CancelRemoteTransfer(const TDesC& aFile) + { + TInt err; + err = GetRsfwControlConnection(); + if (err != KErrNone) + { + return err; + } + return iRsfwControl.CancelRemoteTransfer(aFile); + } + +// End of File