remotestoragefw/mountmanager/src/rsfwbootmounter.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 09:07:59 +0200
changeset 0 3ad9d5175a89
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 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:  Mounts during boot remote drives configured in CenRep
 *
*/


#include <f32file.h>	// link against efsrv.lib
#include <centralrepository.h> // link against centralrepository.lib 
#include <f32fsys.h>

// for the file server client side API   
_LIT(KRemoteFSName, "RemoteFS");
_LIT(KRemoteFs, "eremotefs");
   
   
// for the central repository API   
enum TMountEntryItemIndex
    {
    EMountEntryItemIndex, 
    EMountEntryItemName,
    EMountEntryItemDrive,
    EMountEntryItemUri,
    EMountEntryItemUserName,
    EMountEntryItemPassword,
    EMountEntryItemIap,
    EMountEntryItemInactivityTimeout,
    EMountEntryItemReserved,
    EMountEntryItemCount
    };
const TUid  KCRUidRsfwCtrl = { 0x101F9775 }; // RSFW cenrep table id
const TUint KColumnName       = EMountEntryItemName;
const TUint KColumnMask       = 0x000000ff; 
const TUint KRowMask          = 0xffffff00;
const TInt KMaxFileSystemName = 256;
const TInt KMaxDriveLetterLength = 5;
const TInt KMaxFriendlyNameLength = 20;
 

//  isRsfwFileSystem
//
//  Checks whether certain drive has rsfw file system mounted on it
//
//  
LOCAL_C TBool isRsfwFileSystemL(TInt aDrive,
                              TDriveList aDriveList,
                              RFs aFsSession) 
    {
    TBool rsfwFileSystem = EFalse;
    // check first KDriveAttRemote bit as if that is missing it is a quick way 
    // to conclude that this is not a rsfw mount
    if (aDriveList[aDrive] & KDriveAttRemote) 
        {
        TInt err;
        HBufC* filesystemName = HBufC::NewL(KMaxFileSystemName);
        TPtr itemPtr = filesystemName->Des();
        err = aFsSession.FileSystemName(itemPtr, aDrive);
        if (!err && (itemPtr.Compare(KRemoteFSName) == 0)) 
            {
            rsfwFileSystem = ETrue;
            }
        delete filesystemName;
        }
    return rsfwFileSystem;
    }
 
 
 
//  DoMountL
//
//  Do either simple mount or replace (our) existing mount
//  by doing dismount and mount
//
//  
LOCAL_C TInt DoMount(TInt aDrive, RFs aFsSession, TBool aReplaceExisting)

    {
    TInt err;
    if (aReplaceExisting) 
        {
        // ignore dismount error code
        aFsSession.DismountFileSystem(KRemoteFSName, aDrive);
        err = aFsSession.MountFileSystem(KRemoteFSName, aDrive);
        }
    else 
        {
        err = aFsSession.MountFileSystem(KRemoteFSName, aDrive);
        }
    return err;
    }
 

//  ExecuteFileServerMountL
//
//  Attempts to mount our file system to the file server
//
// 
LOCAL_C TInt ExecuteFileServerMountL(TInt aDrive,
                                    TDriveList aDriveList,
                                    RFs aFsSession)
    {
    TInt err;
    if (aDriveList[aDrive]) 
        {
        if (isRsfwFileSystemL(aDrive, aDriveList, aFsSession)) 
            {
            err = DoMount(aDrive, aFsSession, ETrue);
            }
        else 
            {
            // the drive we attempt to mount contains some other file system
            return KErrInUse;
            }
        }
    else 
        {
        // the drive we attempt to mount does not contain an existing mount
        err = DoMount(aDrive, aFsSession, EFalse);
        }
    return err;
    }


//  SetFriendlyNameL
//  
//  Sets the friendly name of the remote drive to 
//  mounted fs drivename and volumename fields
//  (to the volume name field first 11 chars)
//
//  This function assumes that we are allowed to manipulate
//  drive aDrive, in practise that ExecuteFileServerMount()
//  has been called succesfully
// 
LOCAL_C TInt SetFriendlyName(TInt aDrive,
                             TDesC& aFriendlyName,
                             RFs aFsSession)
    {
    TInt err;
    err = aFsSession.SetDriveName(aDrive, aFriendlyName);
    if (!err) 
        {
        TPtrC volumeNamePtr = aFriendlyName.Left(KMaxVolumeNameLength);
        err = aFsSession.SetVolumeLabel(volumeNamePtr, aDrive);
        }
    return err;
    }

// ----------------------------------------------------------------------------
// SyncConfiguredRemoteDrivesL
// adds RSFW File Server plug-in 
// and synchronizes Central Repository's view of configured remote drives 
// with File Server's view (mounts the remote drives configured in CR and
// unmounts those remote drives that are not anymore configured)   
// ----------------------------------------------------------------------------
//  
LOCAL_C void SyncConfiguredRemoteDrivesL()
    {  
    TInt err = 0;
    TInt row = 0;
    TInt driveNumber = 0;
    RFs fs;
    TChar paramLetter(90);
    TBool paramSet = EFalse;
    
    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);
    
    // it is possible to manipulate only one drive letter, and give that as an argument
    TInt clinelength = User::CommandLineLength();
    if (clinelength > 0) 
        {
        HBufC* cl = HBufC::NewL(clinelength);
        TPtr linePtr = cl->Des();
        User::CommandLine(linePtr);
        TLex lex(linePtr);
        paramLetter = lex.Get();
        paramSet = ETrue;
        delete cl;
        }
    
 	// add our file system plugin to the file server
    err = fs.AddFileSystem(KRemoteFs);
    if ((err != KErrNone) && (err != KErrAlreadyExists)) 
    	{
    	User::Leave(err);
    	}
    	
    // Get a list of drives in the File Server
    TDriveList drives;
    User::LeaveIfError(fs.DriveList(drives, KDriveAttAll));  
    // 	(drives[i] & KDriveAttRemote) now tells whether i:th drive is remote
    
    // Get a list of remote drives in the central repository table
    
    // connect
   	CRepository* cenrep;
    cenrep = CRepository::NewL(KCRUidRsfwCtrl);
    CleanupStack::PushL(cenrep);
    
     // find all entries by name
    RArray<TUint32> nameIds;
    CleanupClosePushL(nameIds);
    err = cenrep->FindL(KColumnName, KColumnMask, nameIds);
    if (!err)
    	{
    	// for each remote drive entry, represented by a record in central repository, do the following:
    	// 1) get drive letter from central repository
    	// 2) based on drive letter acquire corresponding drive number from the File Server
    	// 3) check whether in the File Server there is already mounted a drive with given number
    	//    3.1) if there is NOT, then mount the drive
    	//    3.2) if there is and it appears to be remote, then do re-mounting
    	//    3.3) if there is and it appears NOT to be remote, then this means error
    	// 4) still for the same record from central repository, get the name of the drive
    	// 5) use this name as the volume label in the File Server
    	for (row = 0; row < nameIds.Count(); row++)
        	{
        	TUint rowId = (nameIds[row] & KRowMask);
        	// don't touch zero row as it DOES NOT contain info about mounted drives
        	if (rowId > 0) 
        	    {
        	    TInt i;
            	// mount it to the file server
            	
            	// get drive number
            	TBuf<KMaxDriveLetterLength> driveLetter;
            	i = EMountEntryItemDrive;
            	User::LeaveIfError(cenrep->Get(rowId | i, driveLetter));
            	
            	// driveNumber needed in any case, so that we can mark this as existing drive
            	if (driveLetter.Length() > 0) 
            	    {
            	    User::LeaveIfError(fs.CharToDrive((driveLetter)[0], driveNumber));
            	    }
            	 else 
            	    {
            	    User::Leave(KErrBadName);
            	    }
            	
            	// proceed this drive if we didn't get any drive
            	// letter as a parameter or we got this one
                if ((!paramSet) || (paramLetter ==  driveLetter[0]))
                    {
                    // get friendly name
            	    TBuf<KMaxFriendlyNameLength> friendlyName;
            	    i = EMountEntryItemName;
            	    User::LeaveIfError(cenrep->Get(rowId | i, friendlyName));
            	
            	    if (friendlyName.Length() > 0) 
            	        {
            		    User::LeaveIfError(ExecuteFileServerMountL(driveNumber, drives, fs));
            		    User::LeaveIfError(SetFriendlyName(driveNumber, friendlyName,fs));		
            		    }
            	
            	    else
            		    {
            		    User::Leave(KErrBadName);
            		    }
                    }
                    
            	// do not unmount this drive as it is still in the CenRep table
            	// after this loop non-zero drives are used to see 
            	// which remote drives should be unmounted	
            	drives[driveNumber] = 0; 
        	    }
            } // loop
    	}
    	
    	// If drives now contain some remote drives, this means that they are not 
    	// anymore configured in CenRep and should be unmounted. 
       	for (int i = 0; i < EDriveZ; i++) 
       		{
       		if (isRsfwFileSystemL(i, drives, fs))
       			{
       			fs.DismountFileSystem(KRemoteFSName, i);
       			}
       		}
    
    CleanupStack::PopAndDestroy(3, &fs);   // fs, cenrep, nameIds
    
    }
    
// ----------------------------------------------------------------------------
// E32Main
// 
// ----------------------------------------------------------------------------
//   
GLDEF_C TInt E32Main() 
    {
    CTrapCleanup* cleanupStack = CTrapCleanup::New();
    TRAPD(err, SyncConfiguredRemoteDrivesL());
    delete cleanupStack;
    return err;
    }


// End of file