os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_fman.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_fman.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,2779 @@
     1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "cl_std.h"
    1.20 +
    1.21 +#define RETURNIFERROR(a,b,t)  					\
    1.22 +	{											\
    1.23 +	if ((a=b)!=KErrNone)						\
    1.24 +		{										\
    1.25 +		if(iStatus)								\
    1.26 +			User::RequestComplete(iStatus,a);	\
    1.27 +		TInt _t = t;							\
    1.28 +		if (_t)	{TRACE1(UTF::EBorder, t, MODULEUID, a);}	\
    1.29 +		return(a);								\
    1.30 +		}										\
    1.31 +	}
    1.32 +
    1.33 +#define RETURNIFERRORD(a,b,t)  		 			\
    1.34 +	TInt a; 									\
    1.35 +	RETURNIFERROR(a,b,t)
    1.36 +
    1.37 +const TUint KRecurseFlag	=	0x40000000;
    1.38 +const TUint KScanDownFlag	=	0x20000000;
    1.39 +const TUint KFManBusyFlag	=	0x10000000;
    1.40 +const TUint KOverWriteFlag	=	0x08000000;
    1.41 +const TUint KMoveRenameFlag	=	0x04000000;
    1.42 +const TUint KCopyFromHandle	=	0x00000001;
    1.43 +
    1.44 +const TInt KPathIncGran=32;
    1.45 +
    1.46 +const TUint KMovingFilesMask = KEntryAttMatchExclude | KEntryAttDir;
    1.47 +
    1.48 +TInt ShrinkNames(RFs& aFs, TFileName& aParent, TFileName& aItem, TBool aAppend);
    1.49 +
    1.50 +LOCAL_C HBufC8* AllocateBuffer(TInt64 aLength)
    1.51 +	{
    1.52 +const TInt KBigBufSize = 512 * 1024;
    1.53 +const TInt KMediumBufSize = 32 * 1024;
    1.54 +const TInt KSmallBufSize = 4 * 1024;
    1.55 +	// Min result shall be of TInt size
    1.56 +	// Hence to suppress warning
    1.57 +	TInt big = (TInt)(Min(aLength,(TInt64)KBigBufSize));
    1.58 +	HBufC8* bufPtr=HBufC8::New(big);
    1.59 +	if (bufPtr==NULL)
    1.60 +		bufPtr=HBufC8::New(KMediumBufSize);
    1.61 +	if (bufPtr==NULL)
    1.62 +		bufPtr=HBufC8::New(KSmallBufSize);
    1.63 +	return(bufPtr);
    1.64 +	}
    1.65 +
    1.66 +LOCAL_C TInt IncPathLength(TInt aLen)
    1.67 +	{
    1.68 +	return(((aLen+KPathIncGran-1)/KPathIncGran)*KPathIncGran);
    1.69 +	}
    1.70 +
    1.71 +LOCAL_C TInt CreateTargetNameFromSource(TDes& aTrgName, const TDesC& aTrgMask, const TDesC& aSrcName)
    1.72 +// Replace the wildcards with letters from the matched file.
    1.73 +	{
    1.74 +	TFileName destName;
    1.75 +	TParsePtrC trg(aTrgMask);
    1.76 +	TParsePtrC src(aSrcName);
    1.77 +	TPtrC mask(trg.NameAndExt());
    1.78 +	TPtrC source(src.NameAndExt());
    1.79 +	TInt steps = 1;
    1.80 +	TBool starCharFound = EFalse;
    1.81 +	if(mask.LocateReverse('.')!=KErrNotFound || aTrgMask.Right(1)==_L("*"))
    1.82 +		{
    1.83 +		mask.Set(trg.Name());
    1.84 +		source.Set(src.Name());
    1.85 +		steps = 2;
    1.86 +		}
    1.87 +	for(TInt i = 0; i < steps;
    1.88 +	    i++, mask.Set(trg.ExtPresent() ? trg.Ext() : _L(".*")) , source.Set(src.Ext()))
    1.89 +		{
    1.90 +		TInt offset = 0;
    1.91 +		starCharFound = EFalse;
    1.92 +		while(offset < mask.Length())
    1.93 +			{
    1.94 +			TChar currentChar = mask[offset];
    1.95 +			switch(currentChar)
    1.96 +				{
    1.97 +				case KMatchAny:
    1.98 +					if(offset < source.Length() && !starCharFound)
    1.99 +						{
   1.100 +						destName.Append(source.Mid(offset));
   1.101 +						starCharFound = ETrue;
   1.102 +						}
   1.103 +					break;
   1.104 +				case KMatchOne:
   1.105 +					if(offset < source.Length())
   1.106 +				    {
   1.107 +				    destName.Append(source[offset]);
   1.108 +				    }
   1.109 +					break;
   1.110 +				default:
   1.111 +					destName.Append(currentChar);
   1.112 +					break;
   1.113 +				}
   1.114 +			offset++;
   1.115 +			}
   1.116 +		}
   1.117 +	if(destName.Right(1) == _L("."))
   1.118 +		{
   1.119 +		destName.SetLength(destName.Length()-1);
   1.120 +		}
   1.121 +	if(aTrgName.Length()+destName.Length() > KMaxFileName)
   1.122 +		{
   1.123 +		return KErrBadName;
   1.124 +		}
   1.125 +	aTrgName.Append(destName);
   1.126 +	return KErrNone;
   1.127 +	}
   1.128 +
   1.129 +EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManStarted()
   1.130 +/**
   1.131 +Inform the observer that an operation is about to start.
   1.132 +
   1.133 +This is done immediately before each entry is processed.
   1.134 +
   1.135 +@return The implementation of this function should return:
   1.136 +        MFileManObserver::EContinue, to allow processing of the current file
   1.137 +        to proceed;
   1.138 +        MFileManObserver::ECancel, to skip processing the current file and move
   1.139 +        to the next file;
   1.140 +        MFileManObserver::EAbort to abort the entire operation.
   1.141 +        The default return value is MFileManObserver::EContinue.
   1.142 +*/
   1.143 +	{
   1.144 +
   1.145 +	return(EContinue);
   1.146 +	}
   1.147 +
   1.148 +
   1.149 +
   1.150 +
   1.151 +EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManOperation()
   1.152 +/**
   1.153 +Informs the observer that an operation, i.e. a copy or a move, is proceeding.
   1.154 +
   1.155 +Large files are copied and moved in stages.
   1.156 +After each portion of the source file has been copied to the target, this
   1.157 +function is called.
   1.158 +
   1.159 +It may be useful to call CFileMan::BytesTransferredByCopyStep() from this
   1.160 +function to retrieve the current status of the operation.
   1.161 +
   1.162 +@return The implementation of this function should return:
   1.163 +        MFileManObserver::ECancel, to cancel the current operation, closing the current source
   1.164 +        and target files, the current target file is deleted.
   1.165 +        If the operation is performed on several files, cancelling one will not abort whole batch.
   1.166 +
   1.167 +        MFileManObserver::EContinue, to continue with the operation.
   1.168 +        The default return value is MFileManObserver::EContinue.
   1.169 +
   1.170 +@see CFileMan
   1.171 +*/
   1.172 +	{
   1.173 +
   1.174 +	return(EContinue);
   1.175 +	}
   1.176 +
   1.177 +
   1.178 +
   1.179 +
   1.180 +EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManEnded()
   1.181 +/**
   1.182 +Informs the observer that an operation is complete.
   1.183 +
   1.184 +This is done immediately after a directory entry has been processed.
   1.185 +
   1.186 +It may be useful to call CFileBase::GetLastError()
   1.187 +and CFileBase::GetMoreInfoAboutError() from this function to retrieve
   1.188 +information about how the operation ended.
   1.189 +
   1.190 +@return The implementation of this function should return:
   1.191 +        MFileManObserver::EContinue or MFileManObserver::ECancel, to proceed
   1.192 +        with processing the next entry. MFileManObserver::ECancel will not
   1.193 +        cancel processing the current entry;
   1.194 +        MFileManObserver::ERetry, to re-attempt processing the previous file;
   1.195 +        MFileManObserver::EAbort, to abort the entire operation.
   1.196 +        The default return value is MFileManObserver::EContinue.
   1.197 +
   1.198 +@see CFileBase
   1.199 +*/
   1.200 +	{
   1.201 +
   1.202 +	return(EContinue);
   1.203 +	}
   1.204 +
   1.205 +
   1.206 +
   1.207 +
   1.208 +EXPORT_C CFileBase::CFileBase(RFs& aFs)
   1.209 +/**
   1.210 +Protected default constructor.
   1.211 +
   1.212 +Note that the class is intended only as an abstract base for other classes.
   1.213 +
   1.214 +@param aFs File server session.
   1.215 +*/
   1.216 +	: iFs(aFs)
   1.217 +	{
   1.218 +	}
   1.219 +
   1.220 +
   1.221 +
   1.222 +
   1.223 +EXPORT_C void CFileBase::ConstructL()
   1.224 +/**
   1.225 +Second phase constructor.
   1.226 +*/
   1.227 +	{
   1.228 +
   1.229 +	iScanner=CDirScan::NewL(iFs);
   1.230 +	User::LeaveIfError(iSynchronizer.CreateLocal(0));
   1.231 +	}
   1.232 +
   1.233 +
   1.234 +
   1.235 +
   1.236 +EXPORT_C CFileBase::~CFileBase()
   1.237 +/**
   1.238 +Destructor.
   1.239 +
   1.240 +Frees resources prior to destruction of the object.
   1.241 +*/
   1.242 +	{
   1.243 +
   1.244 +	delete iScanner;
   1.245 +	delete iDirList;
   1.246 +	iSynchronizer.Close();
   1.247 +	User::Free(iSessionPath);
   1.248 +	}
   1.249 +
   1.250 +
   1.251 +
   1.252 +
   1.253 +GLDEF_C void DoFManBaseOperationL(TAny* aPtr)
   1.254 +//
   1.255 +// File manager asynchronous thread
   1.256 +//
   1.257 +	{
   1.258 +
   1.259 +	CFileBase& fMan=*(CFileBase*)aPtr;
   1.260 +	User::LeaveIfError(fMan.iFs.Connect());
   1.261 +	User::LeaveIfError(fMan.iFs.SetSessionPath(*fMan.iSessionPath));
   1.262 +	fMan.iNumberOfFilesProcessed = 0;
   1.263 +	fMan.RunL();
   1.264 +	}
   1.265 +
   1.266 +GLDEF_C TInt FManBaseThreadFunction(TAny* aPtr)
   1.267 +//
   1.268 +// Initialise New thread
   1.269 +//
   1.270 +	{
   1.271 +
   1.272 +	CTrapCleanup* cleanup=CTrapCleanup::New();
   1.273 +	if (cleanup==NULL)
   1.274 +		return(KErrNoMemory);
   1.275 +	CFileBase& fMan=*(CFileBase*)aPtr;
   1.276 +	fMan.iSynchronizer.Wait();
   1.277 +	TRAPD(ret,DoFManBaseOperationL(aPtr));
   1.278 +	if (ret==KErrNone)
   1.279 +		ret=fMan.iLastError;
   1.280 +	delete cleanup;
   1.281 +	fMan.iSwitches=0;
   1.282 +	fMan.iFs=fMan.iFsOld;
   1.283 +	fMan.iStatus=NULL;
   1.284 +	fMan.iFManThread.Close();
   1.285 +	return(ret);
   1.286 +	}
   1.287 +
   1.288 +
   1.289 +
   1.290 +
   1.291 +EXPORT_C void CFileBase::RunInSeparateThreadL(TThreadFunction aThreadFunction)
   1.292 +/**
   1.293 +Creates a separate thread to run the command.
   1.294 +
   1.295 +@param aThreadFunction The thread function.
   1.296 +*/
   1.297 +	{
   1.298 +	iSwitches|=KFManBusyFlag;
   1.299 +	User::LeaveIfError(iFManThread.Create(KNullDesC,aThreadFunction,KDefaultStackSize,NULL,this));
   1.300 +	iFManThread.SetPriority(EPriorityMuchLess);
   1.301 +	TFileName sessionPath;
   1.302 +	User::LeaveIfError(iFs.SessionPath(sessionPath));
   1.303 +	if (iSessionPath==NULL)
   1.304 +		iSessionPath=HBufC::NewL((sessionPath.Length()));
   1.305 +	else if (iSessionPath->Des().MaxLength()<sessionPath.Length())
   1.306 +		iSessionPath=iSessionPath->ReAllocL(IncPathLength(sessionPath.Length()));
   1.307 +	iSessionPath->Des()=sessionPath;
   1.308 +	iFsOld=iFs;
   1.309 +	iLastError=KErrNone;
   1.310 +	iFManThread.Logon(*iStatus);
   1.311 +	iFManThread.Resume();
   1.312 +	}
   1.313 +
   1.314 +
   1.315 +
   1.316 +
   1.317 +EXPORT_C void CFileBase::RunL()
   1.318 +/**
   1.319 +Executes a command.
   1.320 +
   1.321 +@capability Dependent the capabilities required by this method, of the abstract class CFileBase,
   1.322 +					  will be dependent on and provided by the concrete-class implementation of
   1.323 +					  the DoOperationL method
   1.324 +
   1.325 +*/
   1.326 +	{
   1.327 +	if (iStatus && (iSwitches&KFManBusyFlag)==EFalse)
   1.328 +		{
   1.329 +		RunInSeparateThreadL(FManBaseThreadFunction);
   1.330 +		return;
   1.331 +		}
   1.332 +
   1.333 +	TBool copyFromHandle = (iSwitches & KCopyFromHandle)?(TBool)ETrue:(TBool)EFalse;
   1.334 +
   1.335 +	CDirScan::TScanDirection scanDir=(iSwitches&KScanDownFlag) ? CDirScan::EScanDownTree : CDirScan::EScanUpTree;
   1.336 +
   1.337 +	if (!copyFromHandle)
   1.338 +		{
   1.339 +		TRAP(iLastError,iScanner->SetScanDataL(iSrcFile.FullName(),iMatchEntry,ESortByName|EAscending,scanDir));
   1.340 +		if (iLastError==KErrNone)
   1.341 +			TRAP(iLastError,iScanner->NextL(iDirList));
   1.342 +
   1.343 +		if (iLastError!=KErrNone)
   1.344 +			{
   1.345 +			iErrorInfo=EInitializationFailed;
   1.346 +			User::Leave(iLastError);
   1.347 +			}
   1.348 +		}
   1.349 +
   1.350 +	FOREVER
   1.351 +		{
   1.352 +		if (copyFromHandle || iDirList->Count())
   1.353 +			{
   1.354 +			iLastError=KErrNone;
   1.355 +			iErrorInfo=ENoExtraInformation;
   1.356 +			TInt action=(iObserver) ? iObserver->NotifyFileManStarted() : MFileManObserver::EContinue;
   1.357 +			// Check if NotifyFileManStarted returned ECancel.
   1.358 +			if ( action == MFileManObserver::ECancel)
   1.359 +				iLastError=KErrCancel;
   1.360 +			if (action==MFileManObserver::EContinue)
   1.361 +				{
   1.362 +				iNumberOfFilesProcessed++;
   1.363 +				TRAP(iLastError,DoOperationL());
   1.364 +				action=(iObserver) ? iObserver->NotifyFileManEnded() : MFileManObserver::EContinue;
   1.365 +				}
   1.366 +			else if(action==MFileManObserver::ERetry)
   1.367 +			  {
   1.368 +			  Panic(EFManBadValueFromObserver);
   1.369 +			  }
   1.370 +
   1.371 +
   1.372 +			switch(action)
   1.373 +				{
   1.374 +			case MFileManObserver::EContinue:
   1.375 +			case MFileManObserver::ECancel:
   1.376 +				break;
   1.377 +			case MFileManObserver::ERetry:
   1.378 +				continue;
   1.379 +			case MFileManObserver::EAbort:
   1.380 +				delete iDirList;
   1.381 +				iDirList=NULL;
   1.382 +				iCurrentEntry = 0;
   1.383 +				User::Leave(KErrCancel);
   1.384 +			default:
   1.385 +				Panic(EFManBadValueFromObserver);
   1.386 +				}
   1.387 +			}
   1.388 +		iCurrentEntry++;
   1.389 +		if (copyFromHandle || iCurrentEntry>=iDirList->Count())
   1.390 +			{
   1.391 +			delete iDirList;
   1.392 +			iDirList=NULL;
   1.393 +			iCurrentEntry=0;
   1.394 +
   1.395 +			if (iSwitches&KRecurseFlag)
   1.396 +				{
   1.397 +				TRAPD(ret,iScanner->NextL(iDirList));
   1.398 +				if (ret!=KErrNone && ret!=KErrPathNotFound)
   1.399 +					{
   1.400 +					iErrorInfo=EScanNextDirectoryFailed;
   1.401 +					iLastError = ret;
   1.402 +					User::Leave(iLastError);
   1.403 +					}
   1.404 +				}
   1.405 +			if (iDirList==NULL)
   1.406 +				{
   1.407 +				CompleteOperationL();
   1.408 +				return;
   1.409 +				}
   1.410 +			}
   1.411 +		}
   1.412 +	}
   1.413 +
   1.414 +
   1.415 +
   1.416 +
   1.417 +EXPORT_C void CFileBase::SetObserver(MFileManObserver* anObserver)
   1.418 +/**
   1.419 +Sets the observer.
   1.420 +
   1.421 +Use this function to provide CFileMan with an MFileManObserver, or, if one
   1.422 +already exists, to change the observer.
   1.423 +
   1.424 +@param anObserver File management observer.
   1.425 +
   1.426 +@see CFileMan
   1.427 +@see MFileManObserver
   1.428 +*/
   1.429 +	{
   1.430 +
   1.431 +	iObserver=anObserver;
   1.432 +	}
   1.433 +
   1.434 +
   1.435 +
   1.436 +
   1.437 +EXPORT_C const TEntry& CFileBase::CurrentEntry()
   1.438 +/**
   1.439 +Gets the entry currently being processed.
   1.440 +
   1.441 +@return Contains the current entry.
   1.442 +*/
   1.443 +	{
   1.444 +
   1.445 +	__ASSERT_ALWAYS(iDirList && iCurrentEntry>=0 && iCurrentEntry<iDirList->Count(),Panic(EFManCurrentEntryInvalid));
   1.446 +	return (*iDirList)[iCurrentEntry];
   1.447 +	}
   1.448 +
   1.449 +
   1.450 +
   1.451 +
   1.452 +EXPORT_C TPtrC CFileBase::AbbreviatedPath()
   1.453 +/**
   1.454 +Gets the abbreviated path of the file or directory currently being processed.
   1.455 +
   1.456 +The abbreviated path is its path relative to the top level directory
   1.457 +specified in the operation.
   1.458 +
   1.459 +@return The abbreviated path.
   1.460 +*/
   1.461 +	{
   1.462 +
   1.463 +	return iScanner->AbbreviatedPath();
   1.464 +	}
   1.465 +
   1.466 +
   1.467 +
   1.468 +
   1.469 +EXPORT_C TPtrC CFileBase::FullPath()
   1.470 +/**
   1.471 +Gets the full path of the file or directory currently being processed.
   1.472 +
   1.473 +The full path includes the drive letter, path and filename.
   1.474 +
   1.475 +@return The full path.
   1.476 +*/
   1.477 +	{
   1.478 +
   1.479 +	return iScanner->FullPath();
   1.480 +	}
   1.481 +
   1.482 +
   1.483 +
   1.484 +
   1.485 +EXPORT_C TInt CFileBase::GetLastError()
   1.486 +/**
   1.487 +Gets the latest error code returned during a CFileMan
   1.488 +operation.
   1.489 +
   1.490 +This function may be called from MFileManObserver::NotifyFileManEnded().
   1.491 +
   1.492 +@return KErrNone, or another error code that might have been
   1.493 +        returned by a CFileMan operation.
   1.494 +*/
   1.495 +	{
   1.496 +
   1.497 +	return(iLastError);
   1.498 +	}
   1.499 +
   1.500 +
   1.501 +
   1.502 +
   1.503 +EXPORT_C TFileManError CFileBase::GetMoreInfoAboutError()
   1.504 +/**
   1.505 +Gets additional information about the latest error returned during
   1.506 +a CFileMan operation.
   1.507 +
   1.508 +For example, if a rename fails, this function
   1.509 +can be used to report whether the source or target name caused the problem.
   1.510 +This information supplements that provided GetLastError().
   1.511 +
   1.512 +@return The extra information about the last CFileMan error.
   1.513 +
   1.514 +@see CFileMan
   1.515 +@see CFileBase::GetLastError()
   1.516 +*/
   1.517 +	{
   1.518 +
   1.519 +	return(iErrorInfo);
   1.520 +	}
   1.521 +
   1.522 +
   1.523 +
   1.524 +
   1.525 +EXPORT_C CFileMan* CFileMan::NewL(RFs& aFs)
   1.526 +/**
   1.527 +Constructs and allocates memory for a new CFileMan object.
   1.528 +
   1.529 +@param aFs File server session.
   1.530 +
   1.531 +@return Newly created CFileMan object.
   1.532 +*/
   1.533 +	{
   1.534 +	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL1, MODULEUID, aFs.Handle());
   1.535 +
   1.536 +	CFileMan* fileMan=new(ELeave) CFileMan(aFs);
   1.537 +	CleanupStack::PushL(fileMan);
   1.538 +	fileMan->CFileBase::ConstructL();
   1.539 +	CleanupStack::Pop();
   1.540 +
   1.541 +	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL1Return, MODULEUID, fileMan);
   1.542 +	return fileMan;
   1.543 +	}
   1.544 +
   1.545 +
   1.546 +
   1.547 +
   1.548 +EXPORT_C CFileMan* CFileMan::NewL(RFs& aFs,MFileManObserver* anObserver)
   1.549 +/**
   1.550 +Constructs and allocates memory for a new CFileMan object with an observer.
   1.551 +
   1.552 +@param aFs        File server session.
   1.553 +@param anObserver File management observer.
   1.554 +
   1.555 +@return Newly created CFileMan object.
   1.556 +*/
   1.557 +	{
   1.558 +	TRACE2(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL2, MODULEUID, aFs.Handle(), anObserver);
   1.559 +
   1.560 +	CFileMan* fileMan=new(ELeave) CFileMan(aFs);
   1.561 +	CleanupStack::PushL(fileMan);
   1.562 +	fileMan->CFileBase::ConstructL();
   1.563 +	CleanupStack::Pop();
   1.564 +	fileMan->SetObserver(anObserver);
   1.565 +
   1.566 +	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL2Return, MODULEUID, fileMan);
   1.567 +	return fileMan;
   1.568 +	}
   1.569 +
   1.570 +
   1.571 +
   1.572 +
   1.573 +CFileMan::CFileMan(RFs& aFs)
   1.574 +//
   1.575 +// Constructor and destructor
   1.576 +//
   1.577 +	: CFileBase(aFs)
   1.578 +	{
   1.579 +	}
   1.580 +CFileMan::~CFileMan()
   1.581 +	{
   1.582 +	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDestructor, MODULEUID, this);
   1.583 +
   1.584 +	TRACE0(UTF::EBorder, UTraceModuleEfsrv::ECFileManDestructorReturn, MODULEUID);
   1.585 +	}
   1.586 +
   1.587 +
   1.588 +EXPORT_C CFileMan::TAction CFileMan::CurrentAction()
   1.589 +/**
   1.590 +Gets the action which CFileMan is currently carrying out.
   1.591 +
   1.592 +@return The action which CFileMan is carrying out.
   1.593 +*/
   1.594 +	{
   1.595 +	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCurrentAction, MODULEUID, this);
   1.596 +
   1.597 +	TAction action = ENone;
   1.598 +
   1.599 +	// Mapping table between internal and external action indicators.
   1.600 +	switch(iAction)
   1.601 +		{
   1.602 +	case EInternalNone:
   1.603 +		action = ENone;
   1.604 +		break;
   1.605 +	case EInternalAttribs:
   1.606 +		action = EAttribs;
   1.607 +		break;
   1.608 +	case EInternalCopy:
   1.609 +		action = ECopy;
   1.610 +		break;
   1.611 +	case EInternalCopyForMove:
   1.612 +		action = EMove;
   1.613 +		break;
   1.614 +	case EInternalDelete:
   1.615 +		action = EDelete;
   1.616 +		break;
   1.617 +	case EInternalRenameInvalidEntry:
   1.618 +		action = ERenameInvalidEntry;
   1.619 +		break;
   1.620 +	case EInternalRenameForMove:
   1.621 +	case EInternalRename:
   1.622 +		action = ERename;
   1.623 +		break;
   1.624 +	case EInternalRmDir:
   1.625 +		action = ERmDir;
   1.626 +		break;
   1.627 +	case EInternalCopyFromHandle:
   1.628 +		action = ECopyFromHandle;
   1.629 +		break;
   1.630 +	default:
   1.631 +		Panic(EFManUnknownAction);
   1.632 +		}
   1.633 +
   1.634 +	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCurrentActionReturn, MODULEUID, action);
   1.635 +	return (action);
   1.636 +	}
   1.637 +
   1.638 +
   1.639 +
   1.640 +
   1.641 +EXPORT_C void CFileMan::GetCurrentTarget(TFileName& aTrgName)
   1.642 +/**
   1.643 +Gets the name of the target file for the CFileMan operation currently
   1.644 +being carried out.
   1.645 +
   1.646 +This function is relevant when copying, moving or renaming files.
   1.647 +
   1.648 +@param aTrgName The full path and filename of the target file for
   1.649 +                the current CFileMan operation
   1.650 +*/
   1.651 +	{
   1.652 +	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentTarget, MODULEUID, this);
   1.653 +
   1.654 +	GetSrcAndTrg(iTmpParse, aTrgName);
   1.655 +
   1.656 +	TRACEMULT1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentTargetReturn, MODULEUID, aTrgName);
   1.657 +	}
   1.658 +
   1.659 +
   1.660 +
   1.661 +
   1.662 +EXPORT_C void CFileMan::GetCurrentSource(TFileName& aSrcName)
   1.663 +/**
   1.664 +Gets the name of the source file or directory for the CFileMan operation
   1.665 +currently being carried out.
   1.666 +
   1.667 +The source is the file or directory which is being copied, moved or deleted.
   1.668 +
   1.669 +@param aSrcName The full path and filename of the source file for the current
   1.670 +                CFileMan operation.
   1.671 +*/
   1.672 +	{
   1.673 +	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentSource, MODULEUID, this);
   1.674 +
   1.675 +    TPtrC fullPath(FullPath());
   1.676 +	iTmpParse.Set(CurrentEntry().iName, &fullPath, NULL);
   1.677 +	aSrcName = iTmpParse.FullName();
   1.678 +
   1.679 +	TRACEMULT1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentSourceReturn, MODULEUID, aSrcName);
   1.680 +	}
   1.681 +
   1.682 +void CFileMan::GetSrcAndTrg(TParse& aSrcName,TFileName& aTrgName)
   1.683 +//
   1.684 +// Get the current target for the operation
   1.685 +//
   1.686 +	{
   1.687 +	TFileName fullpath = FullPath();
   1.688 +	TInt ret = aSrcName.Set(CurrentEntry().iName, &fullpath, NULL);
   1.689 +	if(ret == KErrBadName)
   1.690 +		{
   1.691 +		// Try heap variables first
   1.692 +		TBool done = EFalse;
   1.693 +		TFileName* current = new TFileName;
   1.694 +		if (current != NULL)
   1.695 +			{
   1.696 +			current->Copy(CurrentEntry().iName);
   1.697 +
   1.698 +			ret = ShrinkNames(iFs, fullpath, *current, EFalse);
   1.699 +			if(ret == KErrNone)
   1.700 +				{
   1.701 +				ret = aSrcName.Set(*current, &fullpath, NULL);
   1.702 +				done = ETrue;
   1.703 +				}
   1.704 +			delete current;
   1.705 +			}
   1.706 +
   1.707 +		if (!done) //heap method failed
   1.708 +			{
   1.709 +			TFileName current = CurrentEntry().iName;
   1.710 +			ret = ShrinkNames(iFs, fullpath, current, EFalse);
   1.711 +			if(ret == KErrNone)
   1.712 +				{
   1.713 +				ret = aSrcName.Set(current, &fullpath, NULL);
   1.714 +				}
   1.715 +			}
   1.716 +		}
   1.717 +	__ASSERT_DEBUG(ret == KErrNone, Panic(EBadLength));
   1.718 +	aTrgName=iTrgFile.DriveAndPath();
   1.719 +	TPtrC relPath=iScanner->AbbreviatedPath();
   1.720 +	aTrgName.Append(relPath.Right(relPath.Length()-1));
   1.721 +	CreateTargetNameFromSource(aTrgName,iTrgFile.NameAndExt(),aSrcName.NameAndExt());
   1.722 +	}
   1.723 +
   1.724 +
   1.725 +
   1.726 +
   1.727 +EXPORT_C TInt CFileMan::BytesTransferredByCopyStep()
   1.728 +/**
   1.729 +Gets the number of bytes transferred during a copy or move operation.
   1.730 +
   1.731 +Large files are copied and moved in stages. After each portion of
   1.732 +the source file has been copied to the target, the number of bytes
   1.733 +transferred is updated. This function may be called
   1.734 +from MFileManObserver::NotifyFileManOperation()
   1.735 +and may be used to support the increment of progress bars.
   1.736 +
   1.737 +@return The number of bytes transferred.
   1.738 +*/
   1.739 +	{
   1.740 +	TRACE2(UTF::EBorder, UTraceModuleEfsrv::ECFileManBytesTransferredByCopyStep, MODULEUID, this, iBytesTransferred);
   1.741 +
   1.742 +	return(iBytesTransferred);
   1.743 +	}
   1.744 +
   1.745 +
   1.746 +
   1.747 +
   1.748 +LOCAL_C void MakeParseWild(TParse& aParse, TFileName& aName)
   1.749 +//
   1.750 +// Append _L("\\*") or _L("*") to aParse
   1.751 +//
   1.752 +	{
   1.753 +	if(!aParse.IsWild())
   1.754 +		{
   1.755 +		aName = aParse.FullName();
   1.756 +		if (aParse.NamePresent() || aParse.ExtPresent())
   1.757 +			{
   1.758 +			if (aName.Length()<=254)
   1.759 +				aName.Append(_L("\\*"));
   1.760 +			}
   1.761 +		else
   1.762 +			{
   1.763 +			if (aName.Length()<=255)
   1.764 +				aName.Append(_L("*"));
   1.765 +			}
   1.766 +		aParse.Set(aName,NULL,NULL);
   1.767 +		}
   1.768 +	}
   1.769 +
   1.770 +
   1.771 +void CFileMan::CheckForDirectory()
   1.772 +//
   1.773 +// If iTrgFile is a directory set target to iTrgFile\\*
   1.774 +//
   1.775 +	{
   1.776 +	TInt trg = iFs.Entry(iTrgFile.FullName(), iTmpEntry);
   1.777 +	if (trg==KErrNone && iTmpEntry.iAtt&KEntryAttDir)
   1.778 +		MakeParseWild(iTrgFile, iTmpName1);
   1.779 +	TInt src = iFs.Entry(iSrcFile.FullName(), iTmpEntry);
   1.780 +	if (src==KErrNone && iTmpEntry.iAtt&KEntryAttDir)
   1.781 +		{
   1.782 +		MakeParseWild(iSrcFile, iTmpName1);
   1.783 +		if (trg==KErrNotFound && (iSwitches&KRecurseFlag))
   1.784 +			MakeParseWild(iTrgFile, iTmpName1);
   1.785 +		}
   1.786 +	}
   1.787 +
   1.788 +void CFileMan::DoSynchronize(TInt aRetValue)
   1.789 +//
   1.790 +// Synchronise with fmanthread
   1.791 +//
   1.792 +	{
   1.793 +
   1.794 +	if (iStatus && aRetValue==KErrNone)
   1.795 +		iSynchronizer.Signal(); // FManThread started
   1.796 +	if (iStatus && aRetValue!=KErrNone)
   1.797 +		iStatus=NULL; // FManThread failed to start
   1.798 +	}
   1.799 +
   1.800 +LOCAL_C void NextInPath(const TDesC& aPath,TPtrC& anEntry,TInt& aPos)
   1.801 +//
   1.802 +// Returns the next entry in the path
   1.803 +//
   1.804 +	{
   1.805 +
   1.806 +	anEntry.Set(NULL,0);
   1.807 +	if ((aPos+1)>=aPath.Length())
   1.808 +		return;
   1.809 +	TPtrC path(aPath.Mid(aPos+1)); // Skip delimiter
   1.810 +	TInt delimiterPos=path.Locate(KPathDelimiter);
   1.811 +	if (delimiterPos==KErrNotFound)
   1.812 +		delimiterPos=aPath.Length()-(aPos+1);
   1.813 +	if (delimiterPos<=0)
   1.814 +		return;
   1.815 +
   1.816 +	if (path[delimiterPos-1]==KExtDelimiter) // return "F32." as "F32"
   1.817 +		anEntry.Set(aPath.Mid(aPos+1,delimiterPos-1));
   1.818 +	else
   1.819 +		anEntry.Set(aPath.Mid(aPos+1,delimiterPos));
   1.820 +	aPos+=delimiterPos+1;
   1.821 +	}
   1.822 +
   1.823 +LOCAL_C TBool ComparePaths(const TDesC& aPath1,const TDesC& aPath2)
   1.824 +//
   1.825 +// Return ETrue if the paths are identical
   1.826 +// To catch case "\\F32.\\GROUP\\" == "\\F32\\GROUP\\"
   1.827 +//
   1.828 +	{
   1.829 +
   1.830 +	TPtrC entry1(NULL,0);
   1.831 +	TPtrC entry2(NULL,0);
   1.832 +	TInt pos1=0;
   1.833 +	TInt pos2=0;
   1.834 +
   1.835 +	do {
   1.836 +		NextInPath(aPath1,entry1,pos1);
   1.837 +		NextInPath(aPath2,entry2,pos2);
   1.838 +		if (entry1.MatchF(entry2)==KErrNotFound)
   1.839 +			return(EFalse);
   1.840 +		} while (entry1.Length() && entry2.Length());
   1.841 +
   1.842 +	return(ETrue);
   1.843 +	}
   1.844 +
   1.845 +EXPORT_C TBool FileNamesIdentical(const TDesC& aFileName1,const TDesC& aFileName2)
   1.846 +//
   1.847 +// Return ETrue if the filenames (and paths) are identical
   1.848 +// NB "Agenda" == "AGENda."
   1.849 +//
   1.850 +	{
   1.851 +
   1.852 +	TParsePtrC file1(aFileName1);
   1.853 +	TParsePtrC file2(aFileName2);
   1.854 +	if (file1.Drive().MatchF(file2.Drive())==KErrNotFound)
   1.855 +		return(EFalse);
   1.856 +	if (file1.Name().MatchF(file2.Name())==KErrNotFound)
   1.857 +		return(EFalse);
   1.858 +	if (ComparePaths(file1.Path(),file2.Path())==EFalse)
   1.859 +		return(EFalse);
   1.860 +	if (file1.Ext().Length()==0 || file2.Ext().Length()==0)
   1.861 +		{ // Agenda == Agenda.
   1.862 +		if (file1.Ext().Length()==1 || file2.Ext().Length()==1)
   1.863 +			return(ETrue);
   1.864 +		}
   1.865 +	if (file1.Ext().MatchF(file2.Ext())==KErrNotFound &&
   1.866 +		file1.NameAndExt().MatchF(file2.NameAndExt())==KErrNotFound)
   1.867 +		return(EFalse);
   1.868 +	return(ETrue);
   1.869 +	}
   1.870 +
   1.871 +
   1.872 +
   1.873 +
   1.874 +EXPORT_C TInt CFileMan::Attribs(const TDesC& aName,TUint aSetMask,TUint aClearMask,const TTime& aTime,TUint aSwitches,TRequestStatus& aStatus)
   1.875 +/**
   1.876 +Sets or clears attributes for one or more files using two bitmasks.
   1.877 +
   1.878 +This is an asynchronous function.
   1.879 +Its behaviour is the same as the synchronous overload.
   1.880 +
   1.881 +@param aName      Path indicating the file(s) whose attributes are to be
   1.882 +                  changed. Any path components which are not specified
   1.883 +                  here will be taken from the session path.
   1.884 +                  Use wildcards to specify more than one file.
   1.885 +@param aSetMask   Bitmask indicating the attributes to be set.
   1.886 +@param aClearMask Bitmask indicating the attributes to be cleared.
   1.887 +                  For more information, see KEntryAttNormal and the other
   1.888 +                  file/directory attributes.
   1.889 +@param aTime      Contains the new modification date and time for the files, in UTC.
   1.890 +                  To preserve the file's timestamps, specify a TTime value of 0.
   1.891 +@param aSwitches  Specify zero for no recursion;
   1.892 +                  CFileMan::ERecurse for recursion.
   1.893 +                  By default, the synchronous variant of this function operates
   1.894 +                  non-recursively.
   1.895 +@param aStatus    The request status object. On request completion,
   1.896 +                  indicates how the request completed:
   1.897 +                  KErrNone, if successful, otherwise one of the other system-wide error
   1.898 +                  codes.
   1.899 +
   1.900 +@return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
   1.901 +					is still pending; otherwise one of the other system-wide error codes
   1.902 +
   1.903 +@capability Dependent If aName is /Sys then Tcb capability is required.
   1.904 +@capability Dependent If aName begins with /Private and does not match
   1.905 +					  this process' SID then AllFiles capability is required.
   1.906 +@capability Dependent If aName is /Resource then Tcb capability is required.
   1.907 +
   1.908 +*/
   1.909 +	{
   1.910 +	TRACEMULT8(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs1, MODULEUID,
   1.911 +		(TUint) this, aName, aSetMask, aClearMask, I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()), aSwitches, (TUint) &aStatus);
   1.912 +
   1.913 +	TInt r;
   1.914 +	if (iSwitches&KFManBusyFlag)
   1.915 +		{
   1.916 +		r = KErrInUse;
   1.917 +		}
   1.918 +	else
   1.919 +		{
   1.920 +		iStatus=&aStatus;
   1.921 +		r = Attribs(aName,aSetMask,aClearMask,aTime,aSwitches);
   1.922 +		}
   1.923 +
   1.924 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs1Return, MODULEUID, r);
   1.925 +	return r;
   1.926 +	}
   1.927 +
   1.928 +
   1.929 +
   1.930 +
   1.931 +EXPORT_C TInt CFileMan::Attribs(const TDesC& aName,TUint aSetMask,TUint aClearMask,const TTime& aTime,TUint aSwitches)
   1.932 +/**
   1.933 +Sets or clears attributes for one or more files using two bitmasks
   1.934 +
   1.935 +This is a synchronous function.
   1.936 +
   1.937 +The first bitmask specifies the attributes to be set.
   1.938 +The second specifies the attributes to be cleared.
   1.939 +The date and time of the files' last modification can also be changed.
   1.940 +
   1.941 +The function can operate recursively or non-recursively.
   1.942 +When operating non-recursively, only the matching files located in the directory
   1.943 +specified in aName are affected. When operating recursively, all matching files
   1.944 +in the directory hierarchy below the directory specified in aName will be affected.
   1.945 +
   1.946 +Notes:
   1.947 +
   1.948 +1. A panic is raised if any attribute is specified in both bitmasks.
   1.949 +
   1.950 +2. Attempting to change the attributes for an open file results in an error
   1.951 +   for that file, as retrieved by CFileBase::GetLastError().
   1.952 +
   1.953 +3. An attempt to set or clear the KEntryAttDir or KEntryAttVolume attribute
   1.954 +   for a file or directory will have no effect.
   1.955 +
   1.956 +@param aName      Path indicating the file(s) whose attributes are to be
   1.957 +                  changed. Any path components which are not specified
   1.958 +                  here will be taken from the session path.
   1.959 +                  Use wildcards to specify more than one file.
   1.960 +@param aSetMask   Bitmask indicating the attributes to be set.
   1.961 +@param aClearMask Bitmask indicating the attributes to be cleared.
   1.962 +                  For more information, see KEntryAttNormal and the other
   1.963 +                  file/directory attributes.
   1.964 +@param aTime      Contains the new modification date and time for the files, in UTC.
   1.965 +                  To preserve the file's timestamps, specify a TTime value of 0.
   1.966 +@param aSwitches  Specify zero for no recursion;
   1.967 +                  CFileMan::ERecurse for recursion.
   1.968 +                  By default, the synchronous variant of this function operates
   1.969 +                  non-recursively.
   1.970 +
   1.971 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
   1.972 +
   1.973 +@capability Dependent If aName is /Sys then Tcb capability is required.
   1.974 +@capability Dependent If aName begins with /Private and does not match
   1.975 +					  this process' SID then AllFiles capability is required.
   1.976 +@capability Dependent If aName is /Resource then Tcb capability is required.
   1.977 +
   1.978 +*/
   1.979 +	{
   1.980 +	TRACEMULT7(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs2, MODULEUID,
   1.981 +		(TUint) this, aName, aSetMask, aClearMask, I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()), aSwitches);
   1.982 +
   1.983 +	TInt ret;
   1.984 +	if (iSwitches&KFManBusyFlag)
   1.985 +		{
   1.986 +		ret = KErrInUse;
   1.987 +		}
   1.988 +	else
   1.989 +		{
   1.990 +		SetFlags(aSwitches&EOverWrite,aSwitches&ERecurse,ETrue,EFalse);
   1.991 +		RETURNIFERRORD(r,iFs.Parse(aName,iSrcFile),UTraceModuleEfsrv::ECFileManAttribs2Return);
   1.992 +		iSetMask=aSetMask;
   1.993 +		iClearMask=aClearMask;
   1.994 +		iTime=aTime;
   1.995 +		iAction = EInternalAttribs;
   1.996 +		iMatchEntry=KEntryAttMaskSupported; // all entries
   1.997 +		iNumberOfFilesProcessed = 0;
   1.998 +		TRAP(r,RunL());
   1.999 +		ret=(r==KErrNone) ? iLastError : r;
  1.1000 +		DoSynchronize(r);
  1.1001 +		}
  1.1002 +
  1.1003 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs2Return, MODULEUID, ret);
  1.1004 +	return(ret);
  1.1005 +	}
  1.1006 +
  1.1007 +
  1.1008 +
  1.1009 +
  1.1010 +EXPORT_C TInt CFileMan::Copy(const TDesC& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
  1.1011 +/**
  1.1012 +Copies one or more files.
  1.1013 +
  1.1014 +This is an asynchronous function.
  1.1015 +Its behaviour is the same as the synchronous overload.
  1.1016 +
  1.1017 +@param anOld     Path indicating the file(s) to be copied.
  1.1018 +                 Any path components which are not specified here will be
  1.1019 +                 taken from the session path.
  1.1020 +@param aNew      Path indicating the directory into which the file(s) are to be copied.
  1.1021 +				 Any path components which are not specified here will be
  1.1022 +                 taken from the session path
  1.1023 +@param aSwitches Specify zero for no overwriting and no recursion;
  1.1024 +                 CFileMan::EOverWrite to overwrite files with the same name;
  1.1025 +                 CFileMan::ERecurse for recursion.
  1.1026 +                 By default, the synchronous variant of this function operates
  1.1027 +                 non-recursively and with overwriting.
  1.1028 +@param aStatus   The request status object. On request completion,
  1.1029 +                 indicates how the request completed:
  1.1030 +                 KErrNone, if successful, otherwise one of the other system-wide error
  1.1031 +                 codes.
  1.1032 +
  1.1033 +@return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1.1034 +					is still pending; otherwise one of the other system-wide error codes
  1.1035 +
  1.1036 +@capability AllFiles
  1.1037 +
  1.1038 +@capability Dependent If the path for aNew begins with /Sys then Tcb capability is required.
  1.1039 +@capability Dependent If the path for aNew begins with /Resource then Tcb capability is required
  1.1040 +
  1.1041 +*/
  1.1042 +	{
  1.1043 +	TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy1, MODULEUID,
  1.1044 +		(TUint) this, anOld, aNew, aSwitches, (TUint) &aStatus);
  1.1045 +
  1.1046 +	TInt r;
  1.1047 +	if (iSwitches&KFManBusyFlag)
  1.1048 +		r = KErrInUse;
  1.1049 +	else
  1.1050 +		{
  1.1051 +		iStatus=&aStatus;
  1.1052 +		r = Copy(anOld,aNew,aSwitches);
  1.1053 +		}
  1.1054 +
  1.1055 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy1Return, MODULEUID, r);
  1.1056 +	return(r);
  1.1057 +	}
  1.1058 +
  1.1059 +
  1.1060 +
  1.1061 +
  1.1062 +EXPORT_C TInt CFileMan::Copy(const TDesC& anOld,const TDesC& aNew,TUint aSwitches)
  1.1063 +/**
  1.1064 +Copies one or more files.
  1.1065 +
  1.1066 +This is a synchronous function.
  1.1067 +
  1.1068 +NB the following applies to files greater than or equal to 2GBytes in size
  1.1069 +(2,147,483,648 bytes) :
  1.1070 +- Only files smaller than 2GBytes will be copied; any larger files will be skipped and
  1.1071 +processing will continue with the next file.
  1.1072 +- If at least one file is smaller than 2GBytes, then KErrNone will be returned.
  1.1073 +- If all files are greater than or equal to 2GBytes ,then KErrTooBig will be returned.
  1.1074 +
  1.1075 +One way to detect the presence of any large file(s) is to use an observer: calling
  1.1076 +CFileBase::GetLastError() from MFileManObserver::NotifyFileManEnded() will return
  1.1077 +KErrToBig for any file >= 2GBytes in size.
  1.1078 +
  1.1079 +Note: the copy operation behaves differently when MFileManObserver is used.
  1.1080 +MFileManObserver should be used with multiple files as it enables you to capture the results of all file copy operations.
  1.1081 +
  1.1082 +If MFileManObserver is NOT used then only the result of the last
  1.1083 +file copy operation is returned because the results of previous file copy operations are overwritten.
  1.1084 +
  1.1085 +Optionally, this function can be set to overwrite any files with the same name
  1.1086 +which exist in the target directory. If the flag is set for no overwriting,
  1.1087 +then any files with the same name will not be overwritten, and an error
  1.1088 +(KErrAlreadyExists) will be returned for that file. Error codes may be retrieved
  1.1089 +using CFileBase::GetLastError().
  1.1090 +
  1.1091 +If recursive operation is set, all intermediate directories will be created,
  1.1092 +including any directories in the path specified by aNew which do not
  1.1093 +already exist.
  1.1094 +
  1.1095 +If recursive operation is not set, only the matching files located in
  1.1096 +the single directory specified in anOld are copied.
  1.1097 +No intermediate directories will be created; if any directories in
  1.1098 +the destination path do not exist, no files will be copied, and this function
  1.1099 +will return KErrPathNotFound.
  1.1100 +
  1.1101 + Notes:
  1.1102 + 1.	This function operates on files only, therefore:
  1.1103 + 1.1	In contrast to the way CFileMan::Move() and CFileMan::Rename()
  1.1104 + 	behave, the behaviour of the copy operation does not depend on the presence
  1.1105 + 	or absence of a trailing backslash ("\") character. Therefore it is only
  1.1106 + 	possible to copy the content of the source path. It is NOT
  1.1107 + 	possible by use of a trailing backslash ("\") character to request that the
  1.1108 + 	last directory level plus its content be copied to the target path.
  1.1109 +
  1.1110 + 	This means that the following two example copy operations will behave
  1.1111 + 	identically
  1.1112 +
  1.1113 + 	@code
  1.1114 + 	CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1115 + 	...
  1.1116 + 	fm->Copy(_L("C:\\SRC\\"), _L("C:\\TRG\\"), CFileMan::ERecurse);
  1.1117 + 	fm->Copy(_L("C:\\SRC"), _L("C:\\TRG\\"), CFileMan::ERecurse);
  1.1118 + 	@endcode
  1.1119 +
  1.1120 + 	because they will be interpreted as follows:
  1.1121 + 	@code
  1.1122 + 	fm->Copy(_L("C:\\SRC\\*"),_L("C:\\TRG\\"), CFileMan::ERecurse);
  1.1123 + 	@endcode
  1.1124 +
  1.1125 + 1.2	If there is no file to operate on i.e. if source directory is empty, the
  1.1126 + 	function will do nothing and return error code KErrNotFound.
  1.1127 +
  1.1128 + 2. Files can be copied across drives.
  1.1129 +
  1.1130 + 3. Open files can be copied if they have been opened using
  1.1131 +      the EFileShareReadersOnly file share mode.
  1.1132 +
  1.1133 + 4. Read-only, hidden and system files can be copied and
  1.1134 +   the source file's attributes are preserved in the target file.
  1.1135 +
  1.1136 +@param anOld     Path indicating the file(s) to be copied.
  1.1137 +                 Any path components which are not specified here will be
  1.1138 +                 taken from the session path.
  1.1139 +@param aNew      Path indicating the directory into which the file(s) are to be copied.
  1.1140 +				 Any path components which are not specified here will be
  1.1141 +                 taken from the session path
  1.1142 +@param aSwitches Specify zero for no overwriting and no recursion;
  1.1143 +                 CFileMan::EOverWrite to overwrite files with the same name;
  1.1144 +                 CFileMan::ERecurse for recursion.
  1.1145 +                 By default, the synchronous variant of this function operates
  1.1146 +                 non-recursively and with overwriting.
  1.1147 +
  1.1148 +@return KErrNone if successful, KErrNotFound if source directory is empty, otherwise one of the other system-wide error codes.
  1.1149 +
  1.1150 +@see CFileBase::GetLastError()
  1.1151 +
  1.1152 +@capability AllFiles
  1.1153 +
  1.1154 +@capability Dependent If the path for anOld begins with /Sys then Tcb capability is required.
  1.1155 +@capability Dependent If the path for anOld begins with /Resource then Tcb capability is required
  1.1156 +
  1.1157 +*/
  1.1158 +	{
  1.1159 +	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2, MODULEUID, (TUint) this, anOld, aNew, aSwitches);
  1.1160 +
  1.1161 +	if (iSwitches&KFManBusyFlag)
  1.1162 +		{
  1.1163 +		TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, KErrInUse);
  1.1164 +		return(KErrInUse);
  1.1165 +		}
  1.1166 +	SetFlags(aSwitches&EOverWrite,aSwitches&ERecurse,ETrue,EFalse);
  1.1167 +	RETURNIFERRORD(r,iFs.Parse(anOld,iSrcFile),UTraceModuleEfsrv::ECFileManCopy2Return);
  1.1168 +	RETURNIFERROR(r,iFs.Parse(aNew,_L("*"),iTrgFile),UTraceModuleEfsrv::ECFileManCopy2Return);
  1.1169 +	CheckForDirectory();
  1.1170 +
  1.1171 +	if((iSwitches&KRecurseFlag) && iTrgFile.DriveAndPath().MatchF(iSrcFile.FullName()) != KErrNotFound)
  1.1172 +		{
  1.1173 +		TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, KErrArgument);
  1.1174 +		return(KErrArgument);
  1.1175 +		}
  1.1176 +
  1.1177 +	iAction = EInternalCopy;
  1.1178 +	iMatchEntry=KEntryAttMaskSupported;
  1.1179 +	iNumberOfFilesProcessed = 0;
  1.1180 +	TRAP(r,RunL());
  1.1181 +	TInt ret=(r==KErrNone) ? iLastError : r;
  1.1182 +	DoSynchronize(r);
  1.1183 +
  1.1184 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, ret);
  1.1185 +	return(ret);
  1.1186 +	}
  1.1187 +
  1.1188 +
  1.1189 +
  1.1190 +
  1.1191 +EXPORT_C TInt CFileMan::Delete(const TDesC& aName,TUint aSwitches,TRequestStatus& aStatus)
  1.1192 +/**
  1.1193 +Deletes one or more files.
  1.1194 +
  1.1195 +This is an asynchronous function.
  1.1196 +Its behaviour is the same as the synchronous overload.
  1.1197 +
  1.1198 +@param aName     Path indicating the file(s) to be deleted.
  1.1199 +                 May either be a full path, or relative to the session path.
  1.1200 +                 Use wildcards to specify more than one file.
  1.1201 +                 NOTE: if you pass KNullDesC, the empty (or null) descriptor,
  1.1202 +                 then the function interprets this to mean \\*.*
  1.1203 +@param aSwitches Specify:
  1.1204 +                 zero for no recursion;
  1.1205 +                 CFileMan::ERecurse for recursion.
  1.1206 +                 By default, the synchronous variant of this function
  1.1207 +                 operates non-recursively.
  1.1208 +@param aStatus   The request status object. On request completion,
  1.1209 +                 indicates how the request completed:
  1.1210 +                 KErrNone, if successful, otherwise one of the other system-wide error
  1.1211 +                 codes.
  1.1212 +
  1.1213 +@return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1.1214 +					is still pending; otherwise one of the other system-wide error codes
  1.1215 +
  1.1216 +@capability Dependent If aName is /Sys then Tcb capability is required.
  1.1217 +@capability Dependent If aName begins with /Private and does not match this process' SID
  1.1218 +					  then AllFiles capability is required.
  1.1219 +@capability Dependent If aName is /Resource then Tcb capability is required.
  1.1220 +
  1.1221 +@see KNullDesC
  1.1222 +*/
  1.1223 +	{
  1.1224 +	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete1, MODULEUID, (TUint) this, aName, aSwitches, (TUint) &aStatus);
  1.1225 +
  1.1226 +	TInt r;
  1.1227 +	if (iSwitches&KFManBusyFlag)
  1.1228 +		{
  1.1229 +		r = KErrInUse;
  1.1230 +		}
  1.1231 +	else
  1.1232 +		{
  1.1233 +		iStatus=&aStatus;
  1.1234 +		r = Delete(aName,aSwitches);
  1.1235 +		}
  1.1236 +
  1.1237 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete1Return, MODULEUID, r);
  1.1238 +	return(r);
  1.1239 +	}
  1.1240 +
  1.1241 +
  1.1242 +
  1.1243 +
  1.1244 +EXPORT_C TInt CFileMan::Delete(const TDesC& aName,TUint aSwitches)
  1.1245 +/**
  1.1246 +Deletes one or more files.
  1.1247 +
  1.1248 +This is a synchronous function.
  1.1249 +
  1.1250 +This function can operate recursively or non-recursively.
  1.1251 +When operating non-recursively, only the matching files located in
  1.1252 +the directory specified in aName are affected.
  1.1253 +When operating recursively, all matching files in the directory hierarchy
  1.1254 +below the directory specified in aName will be deleted.
  1.1255 +
  1.1256 +Note that read-only and open files may not be deleted.
  1.1257 +Attempting to do so will return an error for that file.
  1.1258 +Error codes may be retrieved using CFileBase::GetLastError().
  1.1259 +
  1.1260 +@param aName     Path indicating the file(s) to be deleted.
  1.1261 +                 May either be a full path, or relative to the session path.
  1.1262 +                 Use wildcards to specify more than one file.
  1.1263 +                 NOTE: if you pass KNullDesC, the empty (or null) descriptor,
  1.1264 +                 then the function interprets this to mean \\*.*
  1.1265 +@param aSwitches Specify:
  1.1266 +                 zero for no recursion;
  1.1267 +                 CFileMan::ERecurse for recursion.
  1.1268 +                 By default, the synchronous variant of this function
  1.1269 +                 operates non-recursively.
  1.1270 +
  1.1271 +@return KErrNone if successful, otherwise one of the other system-wide error
  1.1272 +        codes.
  1.1273 +
  1.1274 +@see CFileBase::GetLastError()
  1.1275 +
  1.1276 +@capability Dependent If aName is /Sys then Tcb capability is required.
  1.1277 +@capability Dependent If aName begins with /Private and does not match this process' SID
  1.1278 +					  then AllFiles capability is required.
  1.1279 +@capability Dependent If aName is /Resource then Tcb capability is required.
  1.1280 +
  1.1281 +@see KNullDesC
  1.1282 +*/
  1.1283 +	{
  1.1284 +	TRACEMULT3(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete2, MODULEUID, (TUint) this, aName, aSwitches);
  1.1285 +
  1.1286 +	TInt ret;
  1.1287 +	if (iSwitches&KFManBusyFlag)
  1.1288 +		{
  1.1289 +		ret = KErrInUse;
  1.1290 +		}
  1.1291 +	else
  1.1292 +		{
  1.1293 +		SetFlags(aSwitches&EOverWrite,aSwitches&ERecurse,ETrue,EFalse);
  1.1294 +		RETURNIFERRORD(r,iFs.Parse(aName,iSrcFile),UTraceModuleEfsrv::ECFileManDelete2Return);
  1.1295 +		iAction = EInternalDelete;
  1.1296 +		iMatchEntry=KEntryAttHidden|KEntryAttMatchExclude|KEntryAttDir;
  1.1297 +	//	Exclude directories and system files - include hidden files
  1.1298 +		iNumberOfFilesProcessed = 0;
  1.1299 +		TRAP(r,RunL());
  1.1300 +		ret=(r==KErrNone) ? iLastError : r;
  1.1301 +		DoSynchronize(r);
  1.1302 +		}
  1.1303 +
  1.1304 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete2Return, MODULEUID, ret);
  1.1305 +	return(ret);
  1.1306 +	}
  1.1307 +
  1.1308 +
  1.1309 +
  1.1310 +
  1.1311 +EXPORT_C TInt CFileMan::Move(const TDesC& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
  1.1312 +/**
  1.1313 +Moves one or more files.
  1.1314 +
  1.1315 +This is an asynchronous function.
  1.1316 +Its behaviour is the same as the synchronous overload.
  1.1317 +
  1.1318 +@param anOld     Path indicating the files to be moved. May be either
  1.1319 +                 a full path, or relative to the session path. Any path
  1.1320 +				 components which are not specified here will be taken
  1.1321 +				 from the session path.
  1.1322 +@param aNew      Path indicating the directory into which the file(s) are
  1.1323 +                 to be moved. Any path components which are not specified
  1.1324 +                 here will be taken from the session path.
  1.1325 +@param aSwitches Specify zero for no overwriting and no recursion;
  1.1326 +                 CFileMan::EOverWrite to overwrite files with the same name;
  1.1327 +                 CFileMan::ERecurse for recursion.
  1.1328 +                 By default, the synchronous variant of this function operates
  1.1329 +                 non-recursively and with overwriting.
  1.1330 +@param aStatus   The request status object. On request completion,
  1.1331 +                 indicates how the request completed:
  1.1332 +                 KErrNone, if successful, otherwise one of the other system-wide error
  1.1333 +                 codes.
  1.1334 +
  1.1335 +@return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1.1336 +					is still pending; otherwise one of the other system-wide error codes
  1.1337 +
  1.1338 +@capability Dependent If the path in aNew starts with /Sys then capability Tcb is required
  1.1339 +@capability Dependent If the path in aNew starts with /Resource then capability Tcb is required
  1.1340 +
  1.1341 +@capability AllFiles
  1.1342 +
  1.1343 +@capability Dependent If the path in anOld starts with /Sys then Tcb capability is required.
  1.1344 +@capability Dependent If the path in anOld starts with /Resource then Tcb capability is required.
  1.1345 +
  1.1346 +*/
  1.1347 +	{
  1.1348 +	TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove1, MODULEUID,
  1.1349 +		(TUint) this, anOld, aNew, aSwitches, (TUint) &aStatus);
  1.1350 +
  1.1351 +	TInt r;
  1.1352 +	if (iSwitches&KFManBusyFlag)
  1.1353 +		{
  1.1354 +		r = KErrInUse;
  1.1355 +		}
  1.1356 +	else
  1.1357 +		{
  1.1358 +		iStatus=&aStatus;
  1.1359 +		r = Move(anOld,aNew,aSwitches);
  1.1360 +		}
  1.1361 +
  1.1362 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove1Return, MODULEUID, r);
  1.1363 +	return r;
  1.1364 +	}
  1.1365 +
  1.1366 +
  1.1367 +
  1.1368 +
  1.1369 +EXPORT_C TInt CFileMan::Move(const TDesC& anOld,const TDesC& aNew,TUint aSwitches)
  1.1370 +/**
  1.1371 +Moves one or more files.
  1.1372 +
  1.1373 +This is a synchronous function.
  1.1374 +
  1.1375 +Optionally, this function can be set to overwrite any files with the same name
  1.1376 +which exist in the target directory. If the flag is set for no overwriting,
  1.1377 +then any files with the same name will not be overwritten, and
  1.1378 +an error (KErrAlreadyExists) will be returned for that file.
  1.1379 +Error codes may be retrieved using CFileBase::GetLastError().
  1.1380 +By default, when the function is operating synchronously, files are overwritten.
  1.1381 +
  1.1382 +When this function is operating recursively, all intermediate directories will
  1.1383 +be created, including all directories in the destination path specified
  1.1384 +by aNew which do not already exist.
  1.1385 +
  1.1386 +If recursive operation is not set, only the matching files located in
  1.1387 +the single directory specified in anOld are moved. No intermediate directories
  1.1388 +will be created; if any directories in the destination path do not exist,
  1.1389 +no files will be moved, and this function will return KErrPathNotFound.
  1.1390 +
  1.1391 +The behaviour of the move operation is sensitive to the presence (or absence)
  1.1392 +of a trailing backslash ("\") character on the end of the source path:
  1.1393 +- if there is a trailing backslash ("\") character, then the operation moves
  1.1394 +  the content of the last directory level only.
  1.1395 +- if there is no trailing backslash ("\") character, then the operation behaves
  1.1396 +  recursively by default and moves both the last directory level and all of its content.
  1.1397 +  Notice that no trailing backslash ("\") implies moving files recursively automatically.
  1.1398 +
  1.1399 +For example, if the directory level "b" contains the files F1,F2 and F3, then:
  1.1400 +@code
  1.1401 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1402 +...
  1.1403 +fm->Move(_L("C:\\a\\b\\"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
  1.1404 +@endcode
  1.1405 +
  1.1406 +results in files F1, F2 and F3 being moved from C:\\a\\b to C:\\x\\y, leaving the
  1.1407 +path C:\\a\\b unchanged, except that it no longer contains the files
  1.1408 +F1, F2 and F3.
  1.1409 +
  1.1410 +If there is no trailing backslash character, for example:
  1.1411 +@code
  1.1412 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1413 +...
  1.1414 +fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
  1.1415 +@endcode
  1.1416 +
  1.1417 +then both the directory level "b" and its contents are moved. This means that
  1.1418 +there is no longer a directory "b" under C:\\a. Instead there is a new
  1.1419 +directory structure C:\\x\\y\\b and the files F1, F2, and F3 now exist
  1.1420 +under C:\\x\\y\\b. Also if "b" contains subdirectories, then these are also
  1.1421 +moved along with "b".
  1.1422 +
  1.1423 +If there is no trailing backslash character and the switch is not set, i.e.
  1.1424 +0 is passed as an argument, the operation behaves the same way as by passing
  1.1425 +CFileMan::ERecurse flag.
  1.1426 +
  1.1427 +for example:
  1.1428 +@code
  1.1429 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1430 +...
  1.1431 +fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), 0);
  1.1432 +@endcode
  1.1433 +
  1.1434 +The example above produces the same output as:
  1.1435 +
  1.1436 +@code
  1.1437 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1438 +...
  1.1439 +fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
  1.1440 +@endcode
  1.1441 +
  1.1442 +Notes:
  1.1443 +
  1.1444 +-# Read-only, hidden and system files can be moved and the source file's
  1.1445 +   attributes are preserved in the target file, but open files cannot
  1.1446 +   be moved. Attempting to move an open file will return an error for
  1.1447 +   that file, as retrieved by CFileBase::GetLastError().
  1.1448 +
  1.1449 +@param anOld	 Path indicating the files to be moved. May be either a full path, or
  1.1450 +				 relative to the session path. Note that if you specify a directory level,
  1.1451 +				 then the behaviour of the move operation is sensitive to the presence
  1.1452 +				 (or absence) of a trailing backslash ("\") character. Any path components
  1.1453 +				 which are not specified here will be taken from the session path. See the
  1.1454 +				 main description for the detailed explanation.
  1.1455 +@param aNew      Path indicating the directory into which the file(s) are to be moved.
  1.1456 +				 Any path components which are not specified here will be taken from the session path.
  1.1457 +@param aSwitches CFileMan::EOverWrite to overwrite files with the same name;
  1.1458 +                 CFileMan::ERecurse for recursion.
  1.1459 +                 By default, the synchronous variant of this function operates non-recursively and
  1.1460 +				 with overwriting. And no trailing backslash ("\") character at the end of source path
  1.1461 +				 always means CFileMan::ERecurse.
  1.1462 +
  1.1463 +@return KErrNone if successful, otherwise one of the other system-wide error
  1.1464 +        codes.
  1.1465 +
  1.1466 +@capability Dependent If the path in aNew starts with /Sys then capability Tcb is required
  1.1467 +@capability Dependent If the path in aNew starts with /Resource then capability Tcb is required
  1.1468 +
  1.1469 +@capability AllFiles
  1.1470 +
  1.1471 +@capability Dependent If the path in anOld starts with /Sys then Tcb capability is required.
  1.1472 +@capability Dependent If the path in anOld starts with /Resource then Tcb capability is required.
  1.1473 +
  1.1474 +@see CFileBase::GetLastError()
  1.1475 +*/
  1.1476 +	{
  1.1477 +	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2, MODULEUID,
  1.1478 +		(TUint) this, anOld, aNew, aSwitches);
  1.1479 +
  1.1480 +
  1.1481 +	if (iSwitches&KFManBusyFlag)
  1.1482 +		{
  1.1483 +		TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, KErrInUse);
  1.1484 +		return(KErrInUse);
  1.1485 +		}
  1.1486 +
  1.1487 +	iNumberOfFilesProcessed = 0;
  1.1488 +
  1.1489 +	RETURNIFERRORD(r,iFs.Parse(anOld,iSrcFile),UTraceModuleEfsrv::ECFileManMove2Return);
  1.1490 +	RETURNIFERROR(r,iFs.Parse(aNew,_L("*"),iTrgFile),UTraceModuleEfsrv::ECFileManMove2Return);
  1.1491 +
  1.1492 +	TInt ret = KErrNone;
  1.1493 +	TBool aComplete = EFalse;
  1.1494 +	if(SrcTrgDrivesIdentical())
  1.1495 +		{
  1.1496 +		ret = SetupMoveOnSameDrive(aSwitches, aComplete);
  1.1497 +		}
  1.1498 +	else
  1.1499 +		{
  1.1500 +		ret = SetupMoveAcrossDrives(aSwitches);
  1.1501 +		}
  1.1502 +
  1.1503 +	if(ret != KErrNone || aComplete)
  1.1504 +		{
  1.1505 +		if (iStatus)
  1.1506 +			{
  1.1507 +			User::RequestComplete(iStatus, ret);
  1.1508 +			}
  1.1509 +		TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, ret);
  1.1510 +		return(ret);
  1.1511 +		}
  1.1512 +
  1.1513 +	iMatchEntry = KEntryAttMaskSupported;
  1.1514 +	if((aSwitches&ERecurse)==0 && iMovingContents)
  1.1515 +		{
  1.1516 +		iMatchEntry = KMovingFilesMask;
  1.1517 +		}
  1.1518 +
  1.1519 +	// Do the Move or Rename Operation
  1.1520 +	TRAP(r,RunL());
  1.1521 +	ret = (r==KErrNone) ? iLastError : r;
  1.1522 +	DoSynchronize(r);
  1.1523 +
  1.1524 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, ret);
  1.1525 +	return(ret);
  1.1526 +	}
  1.1527 +
  1.1528 +
  1.1529 +TBool CFileMan::SrcTrgDrivesIdentical()
  1.1530 +//
  1.1531 +// Returns ETrue if the source and target drives are the same
  1.1532 +//	- Used by CFileMan::Move operations to determine whether to rename or move the files
  1.1533 +//
  1.1534 +	{
  1.1535 +	return iSrcFile.Drive().MatchF(iTrgFile.Drive()) != KErrNotFound;
  1.1536 +	}
  1.1537 +
  1.1538 +
  1.1539 +TInt CFileMan::SetupDirectoryForMove(TBool& aSrcIsDir)
  1.1540 +/**
  1.1541 + * Sets up the target specification to include the new target directory if required.
  1.1542 + * 
  1.1543 + * @param aSrcIsDir	Set to ETrue if the source specifies that the directory is to be moved in its entirety,
  1.1544 + * 					or EFalse if only the contents of the directory need to be moved.
  1.1545 + * 
  1.1546 + * @return KErrNone if successful, otherwise one of the system wide error codes.
  1.1547 + */
  1.1548 +	{
  1.1549 +	iMovingContents = ETrue;
  1.1550 +	aSrcIsDir = EFalse;
  1.1551 +	
  1.1552 +	TPtrC nameAndExt(iSrcFile.NameAndExt());
  1.1553 +	if (nameAndExt == _L("*") || nameAndExt == _L("*.*"))
  1.1554 +		{
  1.1555 +		// Wildcard specification - Move the entire contents of the directory to the target
  1.1556 +		aSrcIsDir = ETrue;
  1.1557 +		}
  1.1558 +	else
  1.1559 +		{
  1.1560 +		TInt src = iFs.Entry(iSrcFile.FullName(), iTmpEntry);
  1.1561 +		if ((src == KErrNone && iTmpEntry.iAtt&KEntryAttDir) || (!iSrcFile.NamePresent() && iSrcFile.IsRoot()))
  1.1562 +			{
  1.1563 +			aSrcIsDir = ETrue;
  1.1564 +
  1.1565 +			// A directory is specified.
  1.1566 +			//  - Mandatory recursion with Wildcard Copy
  1.1567 +			//	- Target is a directory (Enforced by MakeParseWild)
  1.1568 +
  1.1569 +			MakeParseWild(iTrgFile, iTmpName1);
  1.1570 +
  1.1571 +			// Construct the target name by parsing
  1.1572 +			// the source path for the directory name.
  1.1573 +			TPtrC srcPath(iSrcFile.FullName());
  1.1574 +			TInt srcPathLen = srcPath.Length() - 1;
  1.1575 +
  1.1576 +			iMovingContents = (srcPath[srcPathLen] == KPathDelimiter);	// Moving the directory itself, or the contents?
  1.1577 +
  1.1578 +			if(!iMovingContents)
  1.1579 +				{
  1.1580 +				// No path delimiter specified
  1.1581 +				//	- move the whole directory (if specified)
  1.1582 +				TInt len = srcPath.Length();
  1.1583 +
  1.1584 +				TInt idx = srcPath.Left(len).LocateReverse(KPathDelimiter);
  1.1585 +
  1.1586 +				if((idx >= 2) && (idx != KErrNotFound))
  1.1587 +					{
  1.1588 +					// Source path is a directory (not just the drive)
  1.1589 +					TPtrC mid(srcPath.Left(len).Mid(1+idx));
  1.1590 +					TInt r = iTrgFile.AddDir(mid);
  1.1591 +					if (r != KErrNone)
  1.1592 +						return r;
  1.1593 +					}
  1.1594 +				}
  1.1595 +			}
  1.1596 +		}
  1.1597 +
  1.1598 +	return KErrNone;
  1.1599 +	}
  1.1600 +
  1.1601 +
  1.1602 +TInt CFileMan::SetupTargetDirectory(TBool aOverWrite, TBool& aComplete)
  1.1603 +	{
  1.1604 +	aComplete = EFalse;
  1.1605 +
  1.1606 +	TInt trgErr = iFs.Entry(iTrgFile.DriveAndPath(), iTmpEntry);
  1.1607 +
  1.1608 +	TEntry srcEntry;
  1.1609 +	TInt srcErr = iFs.Entry(iSrcFile.FullName(), srcEntry);
  1.1610 +
  1.1611 +	if(srcErr == KErrNone && trgErr == KErrNone)
  1.1612 +		{
  1.1613 +        if ((srcEntry.iAtt&KEntryAttDir) != (iTmpEntry.iAtt&KEntryAttDir))
  1.1614 +        	{
  1.1615 +        	// return KErrAccessDenied if it is trying to overwrite a file to a dir or vice versa.
  1.1616 +        	return KErrAccessDenied;
  1.1617 +        	}
  1.1618 +		}
  1.1619 +
  1.1620 +	if(trgErr == KErrNone)
  1.1621 +		{
  1.1622 +		// Already Exists - Overwrite if flags set
  1.1623 +		if(!aOverWrite)
  1.1624 +			{
  1.1625 +			trgErr = KErrAlreadyExists;
  1.1626 +			}
  1.1627 +		else
  1.1628 +			{
  1.1629 +			iNumberOfFilesProcessed++;
  1.1630 +			}
  1.1631 +		}
  1.1632 +	else if((trgErr == KErrNotFound) || (trgErr == KErrPathNotFound))
  1.1633 +		{
  1.1634 +		if(SrcTrgDrivesIdentical())
  1.1635 +			{
  1.1636 +			// When moving a directory on the same drive, the directory can simply be renamed...
  1.1637 +			TParse& midDir = iTmpParse;
  1.1638 +			midDir = iTrgFile;
  1.1639 +			if(midDir.PopDir() == KErrNone)
  1.1640 +				{
  1.1641 +				// ...before renaming, ensure that all intermediate directories exist
  1.1642 +				trgErr = iFs.MkDirAll(midDir.DriveAndPath());
  1.1643 +				if(trgErr == KErrAlreadyExists)
  1.1644 +					{
  1.1645 +					trgErr = KErrNone;
  1.1646 +					}
  1.1647 +				}
  1.1648 +
  1.1649 +			if (trgErr == KErrNone)
  1.1650 +				{
  1.1651 +				// ...and finally rename the source directory
  1.1652 +				trgErr = iFs.Rename(iSrcFile.FullName(),iTrgFile.DriveAndPath());
  1.1653 +				aComplete = ETrue;
  1.1654 +				}
  1.1655 +			}
  1.1656 +		else
  1.1657 +			{
  1.1658 +			trgErr = iFs.MkDirAll(iTrgFile.FullName());
  1.1659 +			}
  1.1660 +		iNumberOfFilesProcessed++;
  1.1661 +		}
  1.1662 +
  1.1663 +	return(trgErr);
  1.1664 +	}
  1.1665 +
  1.1666 +
  1.1667 +TInt CFileMan::SetupMoveOnSameDrive(TUint aSwitches, TBool& aComplete)
  1.1668 +	{
  1.1669 +	// Moving on the same drive.
  1.1670 +
  1.1671 +	aComplete = EFalse;
  1.1672 +
  1.1673 +	TBool srcIsDir = EFalse;
  1.1674 +    TInt ret = SetupDirectoryForMove(srcIsDir);
  1.1675 +    if (ret != KErrNone)
  1.1676 +		{
  1.1677 +        return ret;
  1.1678 +		}
  1.1679 +
  1.1680 +	TBool scanDown = ETrue;
  1.1681 +	TBool recurse = (aSwitches & ERecurse);
  1.1682 +
  1.1683 +	iAction = EInternalRenameForMove;
  1.1684 +
  1.1685 +	TFileName& srcpath = iTmpName1;
  1.1686 +	srcpath.Copy(iSrcFile.FullName());
  1.1687 +	if(srcpath.Length()<KMaxFileName && srcpath.Length()>1 && srcpath[srcpath.Length()-1]!=KPathDelimiter)
  1.1688 +		{
  1.1689 +		srcpath.Append(KPathDelimiter);
  1.1690 +		}
  1.1691 +
  1.1692 +	// If the source path is a subset of the target path then Move operation is not allowed
  1.1693 +	if((srcIsDir && recurse) || (srcIsDir && !iTrgFile.IsRoot() && !iMovingContents))
  1.1694 +		{
  1.1695 +		if(iTrgFile.FullName().Left(srcpath.Length()).MatchF(srcpath)==0)
  1.1696 +			{
  1.1697 +			aComplete = ETrue;
  1.1698 +			return KErrInUse;
  1.1699 +			}
  1.1700 +		}
  1.1701 +	// if any of the SRC folders already existing in TRG, scan upwards
  1.1702 +	if(iMovingContents)
  1.1703 +		{
  1.1704 +		CDirScan* srcScanDir = NULL;
  1.1705 +		CDirScan* trgScanDir = NULL;
  1.1706 +		CDir* srcEntryList = NULL;
  1.1707 +		CDir* trgEntryList = NULL;
  1.1708 +		TInt trgCnt = 0;
  1.1709 +		TInt srcCnt = 0;
  1.1710 +
  1.1711 +		TRAP(ret,(srcScanDir = CDirScan::NewL(iFs)));
  1.1712 +		if (ret!=KErrNone)
  1.1713 +			{
  1.1714 +			goto CleanUp;
  1.1715 +			}
  1.1716 +		TRAP(ret,srcScanDir->SetScanDataL(iSrcFile.FullName(),KEntryAttMaskSupported,ESortByName));
  1.1717 +		if (ret!=KErrNone)
  1.1718 +			{
  1.1719 +			goto CleanUp;
  1.1720 +			}
  1.1721 +		TRAP(ret,srcScanDir->NextL(srcEntryList));
  1.1722 +		if(ret!=KErrNone)
  1.1723 +			{
  1.1724 +			goto CleanUp;
  1.1725 +			}
  1.1726 +		TRAP(ret,(trgScanDir=CDirScan::NewL(iFs)));
  1.1727 +		if (ret!=KErrNone)
  1.1728 +			{
  1.1729 +			goto CleanUp;
  1.1730 +			}
  1.1731 +		TRAP(ret,trgScanDir->SetScanDataL(iTrgFile.FullName(),KEntryAttMaskSupported,ESortByName));
  1.1732 +		if (ret!=KErrNone)
  1.1733 +			{
  1.1734 +			goto CleanUp;
  1.1735 +			}
  1.1736 +		TRAP(ret,trgScanDir->NextL(trgEntryList));
  1.1737 +		if(ret!=KErrNone)
  1.1738 +			{
  1.1739 +			goto CleanUp;
  1.1740 +			}
  1.1741 +		for(trgCnt=trgEntryList->Count()-1; trgCnt>-1; trgCnt--)
  1.1742 +			{
  1.1743 +			for(srcCnt=srcEntryList->Count()-1; srcCnt>-1; srcCnt--)
  1.1744 +				{
  1.1745 +				if( (*srcEntryList)[srcCnt].iName == (*trgEntryList)[trgCnt].iName
  1.1746 +					&& ((*srcEntryList)[srcCnt].iAtt & KEntryAttDir)
  1.1747 +					&& ((*trgEntryList)[trgCnt].iAtt & KEntryAttDir))
  1.1748 +					{
  1.1749 +					// Set scan upwards
  1.1750 +					scanDown = EFalse;
  1.1751 +					goto CleanUp;
  1.1752 +					}
  1.1753 +				}// end inner for loop
  1.1754 +			} // end outer for loop
  1.1755 +CleanUp:
  1.1756 +		// clean up
  1.1757 +		if(srcEntryList!=NULL)
  1.1758 +			delete srcEntryList;
  1.1759 +		if(trgEntryList!=NULL)
  1.1760 +			delete trgEntryList;
  1.1761 +		if(srcScanDir!=NULL)
  1.1762 +			delete srcScanDir;
  1.1763 +		if(trgScanDir!=NULL)
  1.1764 +			delete trgScanDir;
  1.1765 +		}// end if(iMovingContents)
  1.1766 +
  1.1767 +	if(srcIsDir && !iTrgFile.IsRoot() && !iMovingContents)
  1.1768 +		{
  1.1769 +		ret = SetupTargetDirectory(aSwitches & EOverWrite, aComplete);
  1.1770 +		if(ret != KErrNone || aComplete)
  1.1771 +			{
  1.1772 +			return(ret);
  1.1773 +			}
  1.1774 +		}
  1.1775 +	if(!iMovingContents)
  1.1776 +		{
  1.1777 +		recurse = ETrue;
  1.1778 +		scanDown = EFalse;
  1.1779 +		}
  1.1780 +	if(srcIsDir)
  1.1781 +		{
  1.1782 +		MakeParseWild(iSrcFile, iTmpName1);
  1.1783 +		}
  1.1784 +
  1.1785 +	SetFlags(aSwitches & EOverWrite, recurse, scanDown, ETrue);
  1.1786 +	return(KErrNone);
  1.1787 +	}
  1.1788 +
  1.1789 +
  1.1790 +TInt CFileMan::SetupMoveAcrossDrives(TUint aSwitches)
  1.1791 +	{
  1.1792 +	// Moving across drives.  We may need to recurse,
  1.1793 +	// depending on the supplied source path.
  1.1794 +
  1.1795 +	TBool srcIsDir = EFalse;
  1.1796 +    TInt ret = SetupDirectoryForMove(srcIsDir);
  1.1797 +    if (ret != KErrNone)
  1.1798 +		{
  1.1799 +        return ret;
  1.1800 +		}
  1.1801 +    
  1.1802 +	TBool recurse = (aSwitches & ERecurse);
  1.1803 +	TBool scanDown = (recurse) ? (TBool)EFalse : (TBool)ETrue;
  1.1804 +
  1.1805 +	if(srcIsDir)
  1.1806 +		{
  1.1807 +		if(!iMovingContents)
  1.1808 +			{
  1.1809 +			recurse = ETrue;
  1.1810 +			if(!iTrgFile.IsRoot())
  1.1811 +				{
  1.1812 +				TBool complete = EFalse;
  1.1813 +				ret = SetupTargetDirectory(aSwitches & EOverWrite, complete);
  1.1814 +				if(ret != KErrNone || complete)
  1.1815 +					{
  1.1816 +					return(ret);
  1.1817 +					}
  1.1818 +				}
  1.1819 +			}
  1.1820 +		}
  1.1821 +
  1.1822 +	CheckForDirectory();
  1.1823 +	iAction = EInternalCopyForMove;
  1.1824 +	SetFlags(aSwitches & EOverWrite, recurse, scanDown, EFalse);
  1.1825 +	return(KErrNone);
  1.1826 +	}
  1.1827 +
  1.1828 +TInt CFileMan::RenameInvalidEntry(const TDesC& /*aName*/,const TDesC& /*aNewName*/,TUint /*aSwitches*/)
  1.1829 +//
  1.1830 +// Start rename operation
  1.1831 +//
  1.1832 +	{
  1.1833 +	return KErrNotSupported;
  1.1834 +	}
  1.1835 +
  1.1836 +
  1.1837 +
  1.1838 +
  1.1839 +EXPORT_C TInt CFileMan::Rename(const TDesC& aName,const TDesC& aNewName,TUint aSwitches,TRequestStatus& aStatus)
  1.1840 +/**
  1.1841 +Renames one or more files.
  1.1842 +
  1.1843 +This is an asynchronous function.
  1.1844 +Its behaviour is the same as the synchronous overload.
  1.1845 +
  1.1846 +@param aName     Path specifying the file(s) to be renamed. Any path components
  1.1847 +				 which are not specified
  1.1848 +                 here will be taken from the session path.
  1.1849 +@param aNewName  Path specifying the new name for the files and/or
  1.1850 +                 the new directory. Any directories specified in this path
  1.1851 +                 that do not exist, will be created. Any path components
  1.1852 +				 which are not specified here will be taken from the session path.
  1.1853 +@param aSwitches Specify zero for no overwriting;
  1.1854 +                 CFileMan::EOverWrite to overwrite files with the same name.
  1.1855 +                 This function cannot operate recursively.
  1.1856 +@param aStatus   The request status object. On request completion,
  1.1857 +                 indicates how the request completed:
  1.1858 +                 KErrNone, if successful, otherwise one of the other system-wide error
  1.1859 +                 codes.
  1.1860 +
  1.1861 +@return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1.1862 +					is still pending; otherwise one of the other system-wide error codes
  1.1863 +
  1.1864 +@capability Dependent If either aName or aNewName is /Sys then Tcb capability is required.
  1.1865 +@capability Dependent If either aName or aNewName begins with /Private and does not match
  1.1866 +					  this process' SID then AllFiles capability is required.
  1.1867 +@capability Dependent If either aName or aNewName is /Resource then Tcb capability is required.
  1.1868 +
  1.1869 +*/
  1.1870 +	{
  1.1871 +	TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename1, MODULEUID,
  1.1872 +		(TUint) this, aName, aNewName, aSwitches, (TUint) &aStatus);
  1.1873 +
  1.1874 +	TInt r;
  1.1875 +	if (iSwitches&KFManBusyFlag)
  1.1876 +		{
  1.1877 +		r = KErrInUse;
  1.1878 +		}
  1.1879 +	else
  1.1880 +		{
  1.1881 +		iStatus=&aStatus;
  1.1882 +		r = Rename(aName,aNewName,aSwitches);
  1.1883 +		}
  1.1884 +
  1.1885 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename1Return, MODULEUID, r);
  1.1886 +	return(r);
  1.1887 +	}
  1.1888 +
  1.1889 +
  1.1890 +
  1.1891 +
  1.1892 +EXPORT_C TInt CFileMan::Rename(const TDesC& aName,const TDesC& aNewName,TUint aSwitches)
  1.1893 +/**
  1.1894 +Renames one or more files, or a directory
  1.1895 +
  1.1896 +This is a synchronous function.
  1.1897 +
  1.1898 +The function can also be used to move files by specifying different destination
  1.1899 +and source directories.
  1.1900 +
  1.1901 +Some rules for using CFileMan::Rename():
  1.1902 +
  1.1903 +1. General rules:
  1.1904 +
  1.1905 +1.1. Trailing backslash ("\") in either source path (aName) or target path (aNewName)
  1.1906 +will be interpreted to "\*.*";
  1.1907 +
  1.1908 +For example, following code should behave identically:
  1.1909 +@code
  1.1910 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1911 +...
  1.1912 +fm->Rename(_L("C:\\SRC\\"), _L("C:\\TRG\\"));
  1.1913 +fm->Rename(_L("C:\\SRC\\*.*"), _L("C:\\TRG\\"));
  1.1914 +fm->Rename(_L("C:\\SRC\\"), _L("C:\\TRG\\*.*"));
  1.1915 +fm->Rename(_L("C:\\SRC\\*.*"), _L("C:\\TRG\\*.*"));
  1.1916 +@endcode
  1.1917 +
  1.1918 +1.2 The behaviour of the rename operation is sensitive to the presence (or absence) of
  1.1919 +a trailing backslash ("\") character on the end of the target path (aNewName);
  1.1920 +
  1.1921 +For example, under all other constraints (see rules 2. and 3.),
  1.1922 +@code
  1.1923 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1924 +...
  1.1925 +fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\"));
  1.1926 +@endcode
  1.1927 +will result in renaming "C:\\SRC" to "C:\\TRG\\SRC", while
  1.1928 +@code
  1.1929 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1930 +...
  1.1931 +fm->Rename(_L("C:\\SRC"), _L("C:\\TRG"));
  1.1932 +@endcode
  1.1933 +will result in renaming "C:\\SRC" to "C:\\TRG".
  1.1934 +
  1.1935 +2. Renaming file(s):
  1.1936 +
  1.1937 +2.1 Wildcards:
  1.1938 +
  1.1939 +A file's name and extension are interpreted separately, for example:
  1.1940 +
  1.1941 +@code
  1.1942 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1943 +...
  1.1944 +fm->Rename(_L("C:\\SRC\\1234.567"), _L("C:\\TRG\\AB*CD.TXT"));
  1.1945 +@endcode
  1.1946 +renames the source file to file "C:\\TRG\\AB34CD.TXT".
  1.1947 +
  1.1948 +Wildcards can be used for renaming multiple files, for example;
  1.1949 +@code
  1.1950 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1951 +...
  1.1952 +fm->Rename(_L("C:\\SRC\\*.567"), _L("C:\\TRG\\*.TXT"));
  1.1953 +@endcode
  1.1954 +renames all the file under "C:\\SRC\\" having extension ".567" to the files under
  1.1955 +"C:\\TRG\\" having extension ".TXT".
  1.1956 +
  1.1957 +2.2 An option is provided to allow the user to overwrite any files with the same
  1.1958 +name which may exist in the target directory; If the flag is set for no overwriting,
  1.1959 +any files with the same name will not be overwritten, and an error (KErrAlreadyExists)
  1.1960 +will be returned for that file, as retrieved by CFileBase::GetLastError().
  1.1961 +
  1.1962 +2.3 It can only operate non-recursively, so that only the matching files located
  1.1963 +in the single directory specified by anOld may be renamed.
  1.1964 +
  1.1965 +2.4 Trying to rename file(s) to existing directory(ies) will fail;
  1.1966 +
  1.1967 +For example, giving following directory structure:
  1.1968 +@code
  1.1969 +C:\SRC\ITEM01
  1.1970 +C:\SRC\ITEM02
  1.1971 +C:\TRG\ITEM01\
  1.1972 +C:\TRG\ITEM02\
  1.1973 +@endcode
  1.1974 +
  1.1975 +Following code will fail:
  1.1976 +@code
  1.1977 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1978 +...
  1.1979 +fm->Rename(_L("C:\\SRC\\ITEM01"), _L("C:\\TRG\\ITEM01"));
  1.1980 +fm->Rename(_L("C:\\SRC\\ITEM*"), _L("C:\\TRG\\ITEM*"));
  1.1981 +fm->Rename(_L("C:\\SRC\\"), _L("C:\\TRG\\"));
  1.1982 +@endcode
  1.1983 +
  1.1984 +3. When renamnig a directory:
  1.1985 +
  1.1986 +3.1. Only when the trailing backslash ("\") is missing from the source path (aName),
  1.1987 +will the source directory be renamed, otherwise, see rule 1.1.
  1.1988 +
  1.1989 +For example, following code will result in moving "C:\SRC" directory including all
  1.1990 +its contents:
  1.1991 +@code
  1.1992 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.1993 +...
  1.1994 +fm->Rename(_L("C:\\SRC"), _L("C:\\TRG"));
  1.1995 +fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\\"));
  1.1996 +fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\\*.*"));
  1.1997 +@endcode
  1.1998 +
  1.1999 +3.2. Wildcards can not be used for moving directories;
  1.2000 +
  1.2001 +3.3. Overwriting is not permitted;
  1.2002 +
  1.2003 +For example, giving directory structure as following:
  1.2004 +@code
  1.2005 +C:\SRC\FILE.TXT
  1.2006 +C:\TRG\
  1.2007 +C:\TRG\SRC\
  1.2008 +@endcode
  1.2009 +
  1.2010 +following code will fail:
  1.2011 +@code
  1.2012 +CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1.2013 +...
  1.2014 +fm->Rename(_L("C:\\SRC"), _L("C:\\TRG"));
  1.2015 +fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\\"));
  1.2016 +fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\\*.*"));
  1.2017 +@endcode
  1.2018 +
  1.2019 +4. Notes:
  1.2020 +
  1.2021 +4.1. The target and source directories must be on the same drive.
  1.2022 +
  1.2023 +4.2. Read-only, hidden and system files can be moved and the source file's
  1.2024 +attributes are preserved in the target file, but open files cannot
  1.2025 +be moved. Attempting to move an open file will return an error for
  1.2026 +that file, as retrieved by CFileBase::GetLastError().
  1.2027 +
  1.2028 +@param aName     Path specifying the file(s) to be renamed. Any path components
  1.2029 +				 which are not specified
  1.2030 +                 here will be taken from the session path.
  1.2031 +@param aNewName  Path specifying the new name for the files and/or
  1.2032 +                 the new directory. Any directories specified in this path
  1.2033 +                 that do not exist, will be created. Any path components which
  1.2034 +				 are not specified here will be taken from the session path.
  1.2035 +@param aSwitches Specify zero for no overwriting;
  1.2036 +                 CFileMan::EOverWrite to overwrite files with the same name.
  1.2037 +                 This function cannot operate recursively.
  1.2038 +
  1.2039 +@return KErrNone if successful, otherwise one of the other system-wide error
  1.2040 +        codes.
  1.2041 +
  1.2042 +@see CFileBase::GetLastError()
  1.2043 +
  1.2044 +@capability Dependent If either aName or aNewName is /Sys then Tcb capability is required.
  1.2045 +@capability Dependent If either aName or aNewName begins with /Private and does not match
  1.2046 +					  this process' SID then AllFiles capability is required.
  1.2047 +@capability Dependent If either aName or aNewName is /Resource then Tcb capability is required.
  1.2048 +
  1.2049 +*/
  1.2050 +	{
  1.2051 +	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename2, MODULEUID,
  1.2052 +		(TUint) this, aName, aNewName, aSwitches);
  1.2053 +
  1.2054 +	TInt ret;
  1.2055 +	if (iSwitches&KFManBusyFlag)
  1.2056 +		{
  1.2057 +		ret = KErrInUse;
  1.2058 +		}
  1.2059 +	else
  1.2060 +		{
  1.2061 +		SetFlags(aSwitches&EOverWrite,EFalse,ETrue,EFalse);
  1.2062 +		RETURNIFERRORD(r,iFs.Parse(aName,iSrcFile),UTraceModuleEfsrv::ECFileManRename2Return);
  1.2063 +		RETURNIFERROR(r,iFs.Parse(aNewName,_L("*"),iTrgFile),UTraceModuleEfsrv::ECFileManRename2Return);
  1.2064 +
  1.2065 +		iAction = EInternalRename;
  1.2066 +		iMatchEntry=KEntryAttMaskSupported;
  1.2067 +		iNumberOfFilesProcessed = 0;
  1.2068 +		TRAP(r,RunL());
  1.2069 +		ret=(r==KErrNone) ? iLastError : r;
  1.2070 +		DoSynchronize(r);
  1.2071 +		}
  1.2072 +
  1.2073 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename2Return, MODULEUID, ret);
  1.2074 +	return(ret);
  1.2075 +	}
  1.2076 +
  1.2077 +
  1.2078 +EXPORT_C TInt CFileMan::RmDir(const TDesC& aDirName,TRequestStatus& aStatus)
  1.2079 +/**
  1.2080 +Deletes a directory and all files and directories contained in the
  1.2081 +directory structure below it.
  1.2082 +
  1.2083 +Other than being asynchronous, the behaviour of this function is the same
  1.2084 +as is documented in its synchronous overload.
  1.2085 +
  1.2086 +@param aDirName Path specifying the directory to be deleted. Any path components
  1.2087 +				which are not specified here will be taken from the session path.
  1.2088 +@param aStatus  The request status object. On request completion, indicates how
  1.2089 +                the request completed:
  1.2090 +                KErrNone if successful, otherwise one of the other system-wide
  1.2091 +                error codes.
  1.2092 +
  1.2093 +@return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1.2094 +					is still pending; otherwise one of the other system-wide error codes
  1.2095 +
  1.2096 +@capability Dependent If aDirName starts with /Sys then Tcb capability is required.
  1.2097 +@capability Dependent If aDirName begins with /Private and does not match this process' SID
  1.2098 +					  then AllFiles capability is required.
  1.2099 +@capability Dependent If aDirName starts with /Resource then Tcb capability is required.
  1.2100 +
  1.2101 +*/
  1.2102 +	{
  1.2103 +	TRACEMULT3(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir1, MODULEUID, (TUint) this, aDirName, (TUint) &aStatus);
  1.2104 +
  1.2105 +	TInt r;
  1.2106 +	if (iSwitches&KFManBusyFlag)
  1.2107 +		{
  1.2108 +		r = KErrInUse;
  1.2109 +		}
  1.2110 +	else
  1.2111 +		{
  1.2112 +		iStatus=&aStatus;
  1.2113 +		r = RmDir(aDirName);
  1.2114 +		}
  1.2115 +
  1.2116 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir1Return, MODULEUID, r);
  1.2117 +	return r;
  1.2118 +	}
  1.2119 +
  1.2120 +
  1.2121 +EXPORT_C TInt CFileMan::RmDir(const TDesC& aDirName)
  1.2122 +/**
  1.2123 +Deletes a directory and all files and directories contained in the
  1.2124 +directory structure below it.
  1.2125 +
  1.2126 +This is a synchronous function.
  1.2127 +
  1.2128 +The function cannot be used non-recursively. For a non-recursive
  1.2129 +directory deletion, use RFs::RmDir().
  1.2130 +
  1.2131 +Note:
  1.2132 +
  1.2133 +1. All files in the directory hierarchy to be deleted must be closed and
  1.2134 +   none may have the read-only attribute. Otherwise, not all of the hierarchy will
  1.2135 +   be deleted, and this function will return KErrInUse.
  1.2136 +
  1.2137 +@param aDirName Path specifying the directory to be deleted. Any path components
  1.2138 +				which are not specified here will be taken from the session path.
  1.2139 +
  1.2140 +@return KErrNone if successful, otherwise one of the other system-wide error
  1.2141 +        codes.
  1.2142 +
  1.2143 +@capability Dependent If aDirName starts with /Sys then Tcb capability is required.
  1.2144 +@capability Dependent If aDirName begins with /Private and does not match this process' SID
  1.2145 +					  then AllFiles capability is required.
  1.2146 +@capability Dependent If aDirName starts with /Resource then Tcb capability is required.
  1.2147 +
  1.2148 +
  1.2149 +*/
  1.2150 +	{
  1.2151 +	TRACEMULT2(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir2, MODULEUID, (TUint) this, aDirName);
  1.2152 +
  1.2153 +	TInt ret;
  1.2154 +	if (iSwitches&KFManBusyFlag)
  1.2155 +		{
  1.2156 +		ret = KErrInUse;
  1.2157 +		}
  1.2158 +	else
  1.2159 +		{
  1.2160 +		SetFlags(ETrue,ETrue,EFalse,EFalse);
  1.2161 +		RETURNIFERRORD(r,iFs.Parse(aDirName,iTrgFile),UTraceModuleEfsrv::ECFileManRmDir2Return);
  1.2162 +		iSrcFile.Set(iTrgFile.DriveAndPath(),NULL,NULL);
  1.2163 +		iAction = EInternalRmDir;
  1.2164 +		iMatchEntry=KEntryAttMaskSupported;
  1.2165 +		iNumberOfFilesProcessed = 0;
  1.2166 +		TRAP(r,RunL());
  1.2167 +		DoSynchronize(r);
  1.2168 +		ret = (r!=KErrNone) ? iLastError : KErrNone;
  1.2169 +		}
  1.2170 +
  1.2171 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir2Return, MODULEUID, ret);
  1.2172 +	return ret;
  1.2173 +	}
  1.2174 +
  1.2175 +
  1.2176 +void CFileMan::DoOperationL()
  1.2177 +// Call the action in progress.
  1.2178 +	{
  1.2179 +	switch (iAction)
  1.2180 +		{
  1.2181 +	case EInternalAttribs:
  1.2182 +		DoAttribsL();
  1.2183 +		break;
  1.2184 +	case EInternalCopy:
  1.2185 +	case EInternalCopyForMove:
  1.2186 +		DoCopyOrMoveL();
  1.2187 +		break;
  1.2188 +	case EInternalDelete:
  1.2189 +		DoDeleteL();
  1.2190 +		break;
  1.2191 +	case EInternalRenameInvalidEntry:
  1.2192 +	case EInternalRenameForMove:
  1.2193 +	case EInternalRename:
  1.2194 +		DoRenameL();
  1.2195 +		break;
  1.2196 +	case EInternalRmDir:
  1.2197 +		DoRmDirL();
  1.2198 +		break;
  1.2199 +	case EInternalCopyFromHandle:
  1.2200 +		DoCopyFromHandleL();
  1.2201 +		break;
  1.2202 +	default:
  1.2203 +		Panic(EFManUnknownAction);
  1.2204 +		}
  1.2205 +	}
  1.2206 +
  1.2207 +void CFileMan::DoAttribsL()
  1.2208 +//
  1.2209 +// Do attribs operation step
  1.2210 +//
  1.2211 +	{
  1.2212 +	TPtrC fullPath(FullPath());
  1.2213 +	iTmpParse.Set(CurrentEntry().iName, &fullPath, NULL);
  1.2214 +	User::LeaveIfError(iFs.SetEntry(iTmpParse.FullName(), iTime, iSetMask, iClearMask));
  1.2215 +	}
  1.2216 +
  1.2217 +void CFileMan::DoCopyOrMoveL()
  1.2218 +//
  1.2219 +// Do copy or move operation
  1.2220 +//
  1.2221 +	{
  1.2222 +	// Following 'if' statements are to prevent incorrect recursive Move() or Copy() from "destination"
  1.2223 +	//  to "destination", this problem occurs when the initial source directory contains destination
  1.2224 +	//  directory.
  1.2225 +	//  (e.g. CFileMan::Move(_L("C:\\SRC\\*.TXT"), _L("C:\\SRC\\Sub\\"), CFileMan::ERecurse);)
  1.2226 +	// Note that CFileMan::Rename() does not suffer from this particular case, as CFileMan::Rename() API
  1.2227 +	//  can only operate non-recursively.
  1.2228 +	if (iSrcFile.DriveAndPath().Length() < iTrgFile.DriveAndPath().Length())
  1.2229 +		{
  1.2230 +		if (iTrgFile.DriveAndPath().Left(iSrcFile.DriveAndPath().Length()) == iSrcFile.DriveAndPath())
  1.2231 +		// If source directory path contains destination directory path, including drive number, we consider
  1.2232 +		//  this is "...\\ROOT\\" -> "...\\ROOT\\SUB\\" type of operation. Therefore skips all the items we
  1.2233 +		//  found in "...\\ROOT\\SUB\\". We achieve this by checking current scanning directory path:
  1.2234 +			{
  1.2235 +			if (iTrgFile.DriveAndPath() == iScanner->FullPath().Left(iTrgFile.DriveAndPath().Length()))
  1.2236 +				{
  1.2237 +				return;
  1.2238 +				}
  1.2239 +			}
  1.2240 +		}
  1.2241 +
  1.2242 +	TParse& srcName = iTmpParse;
  1.2243 +	TFileName& trgName = iTmpName1;
  1.2244 +	GetSrcAndTrg(srcName,trgName);
  1.2245 +
  1.2246 +	// Handle case when source is directory
  1.2247 +	if (CurrentEntry().iAtt&KEntryAttDir)
  1.2248 +		{
  1.2249 +		if(!(iSwitches&KRecurseFlag))
  1.2250 +			{
  1.2251 +			User::Leave(KErrNone);
  1.2252 +			}
  1.2253 +		trgName.Append(KPathDelimiter);
  1.2254 +		TInt r = iFs.MkDirAll(trgName);
  1.2255 +		if (r!=KErrNone && r!=KErrAlreadyExists)
  1.2256 +			User::Leave(r);
  1.2257 +
  1.2258 +		if(iAction == EInternalCopyForMove)
  1.2259 +			{
  1.2260 +			// Move operation - Attempt to delete the source directory.
  1.2261 +			if((iMatchEntry & KMovingFilesMask) != KMovingFilesMask)
  1.2262 +				{
  1.2263 +				iTmpName2 = srcName.FullName();
  1.2264 +				iTmpName2.Append(KPathDelimiter);
  1.2265 +				TInt rdErr = iFs.RmDir(iTmpName2);
  1.2266 +				if(rdErr != KErrNone && rdErr != KErrInUse)
  1.2267 +					{
  1.2268 +					User::Leave(rdErr);
  1.2269 +					}
  1.2270 +				}
  1.2271 +			}
  1.2272 +		return;
  1.2273 +		}
  1.2274 +
  1.2275 +#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  1.2276 +	RFile srcFile,trgFile;
  1.2277 +#else
  1.2278 +	RFile64 srcFile,trgFile;
  1.2279 +#endif
  1.2280 +	TInt r=KErrNone;
  1.2281 +	if (FileNamesIdentical(srcName.FullName(),trgName))
  1.2282 +		{
  1.2283 +		if (iSwitches & KOverWriteFlag)
  1.2284 +			// Source and target are identical, KOverWriteFlag makes copying
  1.2285 +			// having no effect.
  1.2286 +			return;
  1.2287 +		else
  1.2288 +			User::Leave(KErrAlreadyExists);
  1.2289 +		}
  1.2290 +
  1.2291 +	r=srcFile.Open(iFs, srcName.FullName(),
  1.2292 +	                iAction==EInternalCopy ? EFileRead|EFileShareReadersOnly  // Copy access
  1.2293 +	                                : EFileWrite|EFileWriteDirectIO|EFileShareExclusive); // Move access
  1.2294 +	TBool isRO = EFalse;
  1.2295 +	if(r==KErrAccessDenied && iAction==EInternalCopyForMove)
  1.2296 +		{
  1.2297 +		TEntry& entry = iTmpEntry;
  1.2298 +		r = iFs.Entry(srcName.FullName(), entry);
  1.2299 +		if(r==KErrNone && (entry.iAtt&KEntryAttReadOnly))
  1.2300 +			{
  1.2301 +			isRO = ETrue;
  1.2302 +			r = iFs.SetAtt(srcName.FullName(), 0, KEntryAttReadOnly);
  1.2303 +			if(r==KErrNone)
  1.2304 +				{
  1.2305 +				r = srcFile.Open(iFs, srcName.FullName(), EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  1.2306 +				}
  1.2307 +			}
  1.2308 +		}
  1.2309 +	if (r!=KErrNone)
  1.2310 +		{
  1.2311 +		iErrorInfo=ESrcOpenFailed;
  1.2312 +		if(isRO)
  1.2313 +			{
  1.2314 +			iFs.SetAtt(srcName.FullName(), KEntryAttReadOnly, 0);
  1.2315 +			}
  1.2316 +		User::Leave(r);
  1.2317 +		}
  1.2318 +
  1.2319 +	if ((iSwitches&KOverWriteFlag)==0)
  1.2320 +		r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  1.2321 +	else
  1.2322 +		r=trgFile.Replace(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  1.2323 +
  1.2324 +	if (r==KErrPathNotFound && (iSwitches&KRecurseFlag))
  1.2325 +		{
  1.2326 +		r=iFs.MkDirAll(trgName);
  1.2327 +		if (r==KErrNone)
  1.2328 +			r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  1.2329 +		}
  1.2330 +
  1.2331 +	if (r!=KErrNone)
  1.2332 +		iErrorInfo=ETrgOpenFailed;
  1.2333 +
  1.2334 +	TInt ret=0;
  1.2335 +	if (r == KErrNone)
  1.2336 +		r = DoCopy(srcFile, trgFile, ret);
  1.2337 +
  1.2338 +	srcFile.Close();
  1.2339 +	trgFile.Close();
  1.2340 +	if ((r!=KErrNone && (r!=KErrAlreadyExists && iErrorInfo!=ETrgOpenFailed)) || (ret==MFileManObserver::ECancel))
  1.2341 +		iFs.Delete(trgName);
  1.2342 +	if(r==KErrNone && isRO)
  1.2343 +		{
  1.2344 +		r = iFs.SetAtt(trgName, KEntryAttReadOnly, 0);
  1.2345 +		}
  1.2346 +	User::LeaveIfError(r);
  1.2347 +
  1.2348 +	//
  1.2349 +	// Move operation
  1.2350 +	//
  1.2351 +	if (iAction == EInternalCopyForMove && ret != MFileManObserver::ECancel)
  1.2352 +		{
  1.2353 +		r=iFs.Delete(srcName.FullName());
  1.2354 +		if (r==KErrNone)
  1.2355 +			return;
  1.2356 +		iFs.Delete(trgName);
  1.2357 +		User::Leave(r);
  1.2358 +		}
  1.2359 +	}
  1.2360 +
  1.2361 +void CFileMan::DoDeleteL()
  1.2362 +//
  1.2363 +// Do delete operation step
  1.2364 +//
  1.2365 +	{
  1.2366 +	TFileName& pathname = iTmpName1;
  1.2367 +	TFileName& filename = iTmpName2;
  1.2368 +	pathname.Copy(FullPath());
  1.2369 +	filename.Copy(CurrentEntry().iName);
  1.2370 +	if(CurrentEntry().iName.Length() + pathname.Length() > KMaxFileName)
  1.2371 +		{
  1.2372 +		User::LeaveIfError(ShrinkNames(iFs, pathname, filename, EFalse));
  1.2373 +		}
  1.2374 +	iTmpParse.Set(filename, &pathname, NULL);
  1.2375 +	User::LeaveIfError(iFs.Delete(iTmpParse.FullName()));
  1.2376 +	}
  1.2377 +
  1.2378 +void CFileMan::DoRenameL()
  1.2379 +//
  1.2380 +// Do rename operation step
  1.2381 +//
  1.2382 +	{
  1.2383 +	// Following 'if' statements are to prevent incorrect recursive Move() or Copy() from "destination"
  1.2384 +	//  to "destination", this problem occurs when the initial source directory contains destination
  1.2385 +	//  directory.
  1.2386 +	//  (e.g. CFileMan::Move(_L("C:\\SRC\\*.TXT"), _L("C:\\SRC\\Sub\\"), CFileMan::ERecurse);)
  1.2387 +	// Note that CFileMan::Rename() does not suffer from this particular case, as CFileMan::Rename() API
  1.2388 +	//  can only operate non-recursively.
  1.2389 +	if (iSrcFile.DriveAndPath().Length() < iTrgFile.DriveAndPath().Length())
  1.2390 +		{
  1.2391 +		if (iTrgFile.DriveAndPath().Left(iSrcFile.DriveAndPath().Length()) == iSrcFile.DriveAndPath())
  1.2392 +		// If source directory path contains destination directory path, including drive number, we consider
  1.2393 +		//  this is "...\\ROOT\\" -> "...\\ROOT\\SUB\\" type of operation. Therefore skips all the items we
  1.2394 +		//  found in "...\\ROOT\\SUB\\". We achieve this by checking current scanning directory path:
  1.2395 +			{
  1.2396 +			if (iTrgFile.DriveAndPath() == iScanner->FullPath().Left(iTrgFile.DriveAndPath().Length()))
  1.2397 +				{
  1.2398 +				return;
  1.2399 +				}
  1.2400 +			}
  1.2401 +		}
  1.2402 +
  1.2403 +	TParse& srcName = iTmpParse;
  1.2404 +	TFileName& trgName = iTmpName1;
  1.2405 +	GetSrcAndTrg(srcName, trgName);
  1.2406 +
  1.2407 +	TInt r = iFs.Rename(srcName.FullName(),trgName);
  1.2408 +	if (r==KErrAlreadyExists && (iSwitches&KOverWriteFlag)!=0)
  1.2409 +		{
  1.2410 +		// Target already exists, with the overwrite flag enabled
  1.2411 +		if((CurrentEntry().iAtt & KEntryAttDir) == 0)
  1.2412 +			{
  1.2413 +			// Renaming a file
  1.2414 +			r=iFs.Replace(srcName.FullName(),trgName);
  1.2415 +			}
  1.2416 +		else if (iAction == EInternalRenameForMove)
  1.2417 +			{
  1.2418 +			trgName = srcName.FullName();
  1.2419 +			trgName.Append(KPathDelimiter);
  1.2420 +			r = iFs.RmDir(trgName); // remove empty directory after move
  1.2421 +			if(r == KErrInUse)
  1.2422 +				{
  1.2423 +				r = KErrNone;
  1.2424 +				}
  1.2425 +			}
  1.2426 +		}
  1.2427 +
  1.2428 +	if (r==KErrPathNotFound)
  1.2429 +		{
  1.2430 +		if((iSwitches&KMoveRenameFlag) && !(iSwitches&KRecurseFlag))
  1.2431 +			User::Leave(r);
  1.2432 +		r=iFs.MkDirAll(trgName);
  1.2433 +		if (r==KErrNone)
  1.2434 +			 r=iFs.Rename(srcName.FullName(),trgName);
  1.2435 +		}
  1.2436 +	if (r==KErrBadName)
  1.2437 +		{
  1.2438 +		TEntry& entry = iTmpEntry;
  1.2439 +		TInt retcode=iFs.Entry(srcName.FullName(), entry);
  1.2440 +		if (retcode!=KErrNone)
  1.2441 +			iErrorInfo=ESrcOpenFailed;
  1.2442 +		else
  1.2443 +			iErrorInfo=ETrgOpenFailed;
  1.2444 +		}
  1.2445 +	User::LeaveIfError(r);
  1.2446 +	}
  1.2447 +
  1.2448 +void CFileMan::DoRmDirL()
  1.2449 +//
  1.2450 +// Do rmdir operation step
  1.2451 +//
  1.2452 +	{
  1.2453 +	TFileName& srcName = iTmpName1;
  1.2454 +	srcName.Copy(FullPath());
  1.2455 +	if (srcName.Length() + CurrentEntry().iName.Length() > KMaxFileName)
  1.2456 +		{
  1.2457 +		TFileName& current = iTmpName2;
  1.2458 +		current.Copy(CurrentEntry().iName);
  1.2459 +		User::LeaveIfError(ShrinkNames(iFs, srcName, current, ETrue));
  1.2460 +		}
  1.2461 +	else
  1.2462 +		{
  1.2463 +		srcName.Append(CurrentEntry().iName);
  1.2464 +		}
  1.2465 +
  1.2466 +	if ((CurrentEntry().iAtt&KEntryAttDir)==0)
  1.2467 +		User::LeaveIfError(iFs.Delete(srcName));
  1.2468 +	else
  1.2469 +		{
  1.2470 +		srcName.Append(KPathDelimiter);
  1.2471 +		User::LeaveIfError(iFs.RmDir(srcName));
  1.2472 +		}
  1.2473 +	}
  1.2474 +
  1.2475 +
  1.2476 +void CFileMan::CompleteOperationL()
  1.2477 +//
  1.2478 +// Tidy up after an operation
  1.2479 +// The last step to remove directory or to a move directory operation
  1.2480 +// is to remove the source directory...
  1.2481 +//
  1.2482 +	{
  1.2483 +	TInt r=KErrNotFound;
  1.2484 +	if (iAction == EInternalRmDir ||
  1.2485 +	    (iAction == EInternalCopyForMove && ((iMatchEntry & KMovingFilesMask) != KMovingFilesMask) && !iMovingContents && !iSrcFile.IsRoot()) ||
  1.2486 +	    iAction == EInternalRenameForMove && !iMovingContents && iNumberOfFilesProcessed)
  1.2487 +		{
  1.2488 +		r=iFs.RmDir(iSrcFile.FullName());
  1.2489 +		if ((r!=KErrNone && r!=KErrNotFound && iAction!=EInternalRenameForMove && r!=KErrInUse) || (iAction == EInternalRmDir && r == KErrInUse))
  1.2490 +			{
  1.2491 +			iLastError=r;
  1.2492 +			User::Leave(r);
  1.2493 +			}
  1.2494 +		}
  1.2495 +
  1.2496 +	if (iLastError == KErrCancel && iNumberOfFilesProcessed==0 )
  1.2497 +	{
  1.2498 +		iLastError=KErrCancel;
  1.2499 +		iErrorInfo=ENoFilesProcessed;
  1.2500 +		User::Leave(KErrCancel);
  1.2501 +	}
  1.2502 +
  1.2503 +	if (iLastError==KErrNone && r==KErrNotFound && iNumberOfFilesProcessed==0)
  1.2504 +		{
  1.2505 +		iLastError=KErrNotFound;
  1.2506 +		iErrorInfo=ENoFilesProcessed;
  1.2507 +		User::Leave(KErrNotFound);
  1.2508 +		}
  1.2509 +	}
  1.2510 +
  1.2511 +void CFileMan::SetFlags(TBool anOverWrite,TBool aRecurse,TBool aScanDownTree,TBool aMoveRename)
  1.2512 +//
  1.2513 +// Set or clear flags
  1.2514 +//
  1.2515 +	{
  1.2516 +
  1.2517 +	iSwitches=0;
  1.2518 +	if (aRecurse)
  1.2519 +		iSwitches|=KRecurseFlag;
  1.2520 +	if (anOverWrite)
  1.2521 +		iSwitches|=KOverWriteFlag;
  1.2522 +	if (aScanDownTree)
  1.2523 +		iSwitches|=KScanDownFlag;
  1.2524 +	if (aMoveRename)
  1.2525 +		iSwitches|=KMoveRenameFlag;
  1.2526 +	}
  1.2527 +
  1.2528 +
  1.2529 +EXPORT_C TInt CFileMan::Copy(const RFile& anOld, const TDesC& aNew, TUint aSwitches)
  1.2530 +/**
  1.2531 +Copies from an open file handle to a destination file name.
  1.2532 +
  1.2533 +This is a synchronous function.
  1.2534 +
  1.2535 +Optionally, this function can be set to overwrite the target file.
  1.2536 +If the flag is set for no overwriting and the target file already exists,
  1.2537 +then the target file will not be overwritten, and an error (KErrAlreadyExists)
  1.2538 +will be returned.
  1.2539 +Error codes may be retrieved using CFileBase::GetLastError().
  1.2540 +
  1.2541 +Notes:
  1.2542 +
  1.2543 +-# The file can be copied across drives.
  1.2544 +-# Read-only, hidden and system files can be copied and
  1.2545 +   the source file's attributes are preserved in the target file.
  1.2546 +
  1.2547 +@param anOld     Open file handle indicating the file to be copied.
  1.2548 +@param aNew      Path indicating the directory (and optionally the filename)
  1.2549 +				 into which the file is to be copied.
  1.2550 +				 Any path components which are not specified here will be
  1.2551 +                 taken from the session path
  1.2552 +@param aSwitches Specify zero for no overwriting;
  1.2553 +                 CFileMan::EOverWrite to overwrite files with the same name;
  1.2554 +                 Any other flags are illegal
  1.2555 +                 By default, the synchronous variant of this function operates
  1.2556 +                 with overwriting.
  1.2557 +
  1.2558 +@return KErrNone if successful, otherwise one of the other system-wide error codes.
  1.2559 +
  1.2560 +@see CFileBase::GetLastError()
  1.2561 +@see CFileMan::Move()
  1.2562 +
  1.2563 +@capability Dependent If the path for aNew begins with /Sys then Tcb capability is required.
  1.2564 +@capability Dependent If the path for aNew begins with /Private and does not match
  1.2565 +					  this process' SID then AllFiles capability is required.
  1.2566 +@capability Dependent If the path for aNew begins with /Resource then Tcb capability is required.
  1.2567 +*/
  1.2568 +	{
  1.2569 +	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy3, MODULEUID,
  1.2570 +		(TUint) this, anOld.SubSessionHandle(), aNew, aSwitches);
  1.2571 +
  1.2572 +	TInt ret;
  1.2573 +	if (iSwitches&KFManBusyFlag)
  1.2574 +		{
  1.2575 +		ret = KErrInUse;
  1.2576 +		}
  1.2577 +		// The only switch that is legal for single file copies is EOverWrite
  1.2578 +	else if ((aSwitches & ~EOverWrite) != 0)
  1.2579 +		{
  1.2580 +		ret = KErrArgument;
  1.2581 +		}
  1.2582 +	else
  1.2583 +		{
  1.2584 +
  1.2585 +		SetFlags(aSwitches & EOverWrite, EFalse, EFalse, EFalse);
  1.2586 +
  1.2587 +		// need to signal to CFileBase that we're copying from a handle
  1.2588 +		// and that iSrcFile is invalid
  1.2589 +		iSwitches|= KCopyFromHandle;
  1.2590 +
  1.2591 +		TInt r;
  1.2592 +		RETURNIFERROR(r, iFs.Parse(aNew, iTrgFile),UTraceModuleEfsrv::ECFileManCopy3Return);
  1.2593 +
  1.2594 +		// Need to duplicate the RFile handle so that any threads owned
  1.2595 +		// by this process can use it - i.e. the worker thread
  1.2596 +		RETURNIFERROR(r, iSrcFileHandle.Duplicate(anOld, EOwnerProcess),UTraceModuleEfsrv::ECFileManCopy3Return);
  1.2597 +
  1.2598 +		iAction = EInternalCopyFromHandle;
  1.2599 +		iNumberOfFilesProcessed = 0;
  1.2600 +		TRAP(r,RunL());
  1.2601 +		ret=(r==KErrNone) ? iLastError : r;
  1.2602 +		DoSynchronize(r);
  1.2603 +		}
  1.2604 +
  1.2605 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy3Return, MODULEUID, ret);
  1.2606 +	return(ret);
  1.2607 +	}
  1.2608 +
  1.2609 +EXPORT_C TInt CFileMan::Copy(const RFile& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
  1.2610 +/**
  1.2611 +Copies from an open file handle to a destination file name.
  1.2612 +
  1.2613 +This is an asynchronous function.
  1.2614 +Its behaviour is the same as the synchronous overload.
  1.2615 +
  1.2616 +@param anOld     Open file handle indicating the file to be copied.
  1.2617 +@param aNew      Path indicating the directory (and optionally the filename)
  1.2618 +				 into which the file is to be copied.
  1.2619 +				 Any path components which are not specified here will be
  1.2620 +                 taken from the session path
  1.2621 +@param aSwitches Specify zero for no overwriting;
  1.2622 +                 CFileMan::EOverWrite to overwrite files with the same name;
  1.2623 +                 Any other flags are illegal.
  1.2624 +
  1.2625 +@param aStatus   The request status object. On request completion,
  1.2626 +                 indicates how the request completed:
  1.2627 +                 KErrNone, if successful, otherwise one of the other system-wide error
  1.2628 +                 codes.
  1.2629 +
  1.2630 +@return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1.2631 +					is still pending; otherwise one of the other system-wide error codes
  1.2632 +
  1.2633 +@see CFileBase::GetLastError()
  1.2634 +
  1.2635 +@capability Dependent If the path for aNew begins with /Sys then Tcb capability is required.
  1.2636 +@capability Dependent If the path for aNew begins with /Private and does not match
  1.2637 +					  this process' SID then AllFiles capability is required.
  1.2638 +@capability Dependent If the path for aNew begins with /Resource then Tcb capability is required.
  1.2639 +*/
  1.2640 +	{
  1.2641 +	TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy4, MODULEUID,
  1.2642 +		(TUint) this, anOld.SubSessionHandle(), aNew, aSwitches, (TUint) &aStatus);
  1.2643 +
  1.2644 +	TInt r;
  1.2645 +	if (iSwitches&KFManBusyFlag)
  1.2646 +		{
  1.2647 +		r = KErrInUse;
  1.2648 +		}
  1.2649 +	else
  1.2650 +		{
  1.2651 +		iStatus=&aStatus;
  1.2652 +		r = Copy(anOld,aNew,aSwitches);
  1.2653 +		}
  1.2654 +
  1.2655 +	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy4Return, MODULEUID, r);
  1.2656 +	return(r);
  1.2657 +	}
  1.2658 +
  1.2659 +void CFileMan::DoCopyFromHandleL()
  1.2660 +//
  1.2661 +// Copy from open file handle
  1.2662 +//
  1.2663 +	{
  1.2664 +	TInt ret=0;
  1.2665 +	TFileName& trgName = iTmpName1;
  1.2666 +
  1.2667 +	if (iTrgFile.NamePresent())
  1.2668 +		{
  1.2669 +		trgName = iTrgFile.FullName();
  1.2670 +		}
  1.2671 +	else
  1.2672 +		{
  1.2673 +		iSrcFileHandle.Name(trgName);
  1.2674 +		if ((trgName.Length() + iTrgFile.DriveAndPath().Length()) > KMaxFileName)
  1.2675 +			{
  1.2676 +			iSrcFileHandle.Close();
  1.2677 +			User::Leave(KErrBadName);
  1.2678 +			}
  1.2679 +		trgName.Insert(0, iTrgFile.DriveAndPath());
  1.2680 +		}
  1.2681 +
  1.2682 +#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  1.2683 +	RFile trgFile;
  1.2684 +#else
  1.2685 +	RFile64 trgFile;
  1.2686 +#endif
  1.2687 +	TInt r=KErrNone;
  1.2688 +
  1.2689 +	if ((iSwitches&KOverWriteFlag)==0)
  1.2690 +		r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  1.2691 +	else
  1.2692 +		r=trgFile.Replace(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  1.2693 +	if (r!=KErrNone)
  1.2694 +		iErrorInfo = ETrgOpenFailed;
  1.2695 +
  1.2696 +	if (r == KErrNone)
  1.2697 +		r = DoCopy(iSrcFileHandle, trgFile, ret);
  1.2698 +
  1.2699 +	// close the (duplicated) source file handle
  1.2700 +	iSrcFileHandle.Close();
  1.2701 +
  1.2702 +	trgFile.Close();
  1.2703 +	if (ret == MFileManObserver::ECancel || (r!=KErrNone && r!=KErrAlreadyExists && iErrorInfo!=ETrgOpenFailed))
  1.2704 +		iFs.Delete(trgName);
  1.2705 +	User::LeaveIfError(r);
  1.2706 +	}
  1.2707 +
  1.2708 +#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  1.2709 +TInt CFileMan::DoCopy(const RFile& aSrcFile, RFile& aDstFile, TInt& aRet)
  1.2710 +	{
  1.2711 +	TInt rem;
  1.2712 +#else
  1.2713 +TInt CFileMan::DoCopy(const RFile64& aSrcFile, RFile64& aDstFile, TInt& aRet)
  1.2714 +	{
  1.2715 +	TInt64 rem;
  1.2716 +#endif
  1.2717 +	RETURNIFERRORD(r,aSrcFile.Size(rem),EFalse);
  1.2718 +	RETURNIFERROR(r, aDstFile.SetSize(rem),EFalse);
  1.2719 +
  1.2720 +	HBufC8* bufPtr = NULL;
  1.2721 +	bufPtr = AllocateBuffer(rem);
  1.2722 +	if (bufPtr == NULL)
  1.2723 +		return KErrNoMemory;
  1.2724 +	TPtr8 copyBuf=bufPtr->Des();
  1.2725 +
  1.2726 +#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  1.2727 +	TInt pos=0;
  1.2728 +#else
  1.2729 +	TInt64 pos=0;
  1.2730 +#endif
  1.2731 +	aRet = MFileManObserver::EContinue;
  1.2732 +	while(rem && aRet == MFileManObserver::EContinue)
  1.2733 +		{
  1.2734 +#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  1.2735 +		TInt s=Min(rem,copyBuf.MaxSize());
  1.2736 +#else
  1.2737 +		// Min result shall be of TInt size
  1.2738 +		TInt s=(TInt)(Min(rem,(TInt64)copyBuf.MaxSize()));
  1.2739 +#endif
  1.2740 +		r=aSrcFile.Read(pos,copyBuf,s);
  1.2741 +		if (r==KErrNone && copyBuf.Length()!=s)
  1.2742 +			r = KErrCorrupt;
  1.2743 +		if (r==KErrNone)
  1.2744 +			r=aDstFile.Write(pos,copyBuf,s);
  1.2745 +		if (r!=KErrNone)
  1.2746 +			break;
  1.2747 +		pos+= s;
  1.2748 +		rem-= s;
  1.2749 +		iBytesTransferred = s;
  1.2750 +		aRet = (iObserver) ? iObserver->NotifyFileManOperation() : MFileManObserver::EContinue;
  1.2751 +		if (aRet != MFileManObserver::EContinue && aRet != MFileManObserver::ECancel)
  1.2752 +			Panic(EFManBadValueFromObserver);
  1.2753 +		}
  1.2754 +
  1.2755 +	// need to flush the target file - otherwise if there is any dirty data this will be flushed
  1.2756 +	// when the file is closed and this will set the archive attribute, resulting in the file
  1.2757 +	// having potentially a different attribute from the source file
  1.2758 +	if (r == KErrNone)
  1.2759 +		r = aDstFile.Flush();
  1.2760 +
  1.2761 +	if (aRet != MFileManObserver::ECancel)
  1.2762 +		{
  1.2763 +		TTime lastMod;
  1.2764 +		if (r == KErrNone)
  1.2765 +			r = aSrcFile.Modified(lastMod);
  1.2766 +		if (r == KErrNone)
  1.2767 +			r = aDstFile.SetModified(lastMod);
  1.2768 +
  1.2769 +		TUint fileAttributes=0;
  1.2770 +		if (r == KErrNone)
  1.2771 +			r = aSrcFile.Att(fileAttributes);
  1.2772 +		if (r == KErrNone)
  1.2773 +			r = aDstFile.SetAtt(fileAttributes,(~fileAttributes)&KEntryAttMaskSupported);
  1.2774 +
  1.2775 +		if(r == KErrNone)
  1.2776 +  			r = aDstFile.Flush();
  1.2777 +		}
  1.2778 +
  1.2779 +	delete bufPtr;
  1.2780 +
  1.2781 +	return r;
  1.2782 +	}