os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_fman.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "cl_std.h"
    17 
    18 #define RETURNIFERROR(a,b,t)  					\
    19 	{											\
    20 	if ((a=b)!=KErrNone)						\
    21 		{										\
    22 		if(iStatus)								\
    23 			User::RequestComplete(iStatus,a);	\
    24 		TInt _t = t;							\
    25 		if (_t)	{TRACE1(UTF::EBorder, t, MODULEUID, a);}	\
    26 		return(a);								\
    27 		}										\
    28 	}
    29 
    30 #define RETURNIFERRORD(a,b,t)  		 			\
    31 	TInt a; 									\
    32 	RETURNIFERROR(a,b,t)
    33 
    34 const TUint KRecurseFlag	=	0x40000000;
    35 const TUint KScanDownFlag	=	0x20000000;
    36 const TUint KFManBusyFlag	=	0x10000000;
    37 const TUint KOverWriteFlag	=	0x08000000;
    38 const TUint KMoveRenameFlag	=	0x04000000;
    39 const TUint KCopyFromHandle	=	0x00000001;
    40 
    41 const TInt KPathIncGran=32;
    42 
    43 const TUint KMovingFilesMask = KEntryAttMatchExclude | KEntryAttDir;
    44 
    45 TInt ShrinkNames(RFs& aFs, TFileName& aParent, TFileName& aItem, TBool aAppend);
    46 
    47 LOCAL_C HBufC8* AllocateBuffer(TInt64 aLength)
    48 	{
    49 const TInt KBigBufSize = 512 * 1024;
    50 const TInt KMediumBufSize = 32 * 1024;
    51 const TInt KSmallBufSize = 4 * 1024;
    52 	// Min result shall be of TInt size
    53 	// Hence to suppress warning
    54 	TInt big = (TInt)(Min(aLength,(TInt64)KBigBufSize));
    55 	HBufC8* bufPtr=HBufC8::New(big);
    56 	if (bufPtr==NULL)
    57 		bufPtr=HBufC8::New(KMediumBufSize);
    58 	if (bufPtr==NULL)
    59 		bufPtr=HBufC8::New(KSmallBufSize);
    60 	return(bufPtr);
    61 	}
    62 
    63 LOCAL_C TInt IncPathLength(TInt aLen)
    64 	{
    65 	return(((aLen+KPathIncGran-1)/KPathIncGran)*KPathIncGran);
    66 	}
    67 
    68 LOCAL_C TInt CreateTargetNameFromSource(TDes& aTrgName, const TDesC& aTrgMask, const TDesC& aSrcName)
    69 // Replace the wildcards with letters from the matched file.
    70 	{
    71 	TFileName destName;
    72 	TParsePtrC trg(aTrgMask);
    73 	TParsePtrC src(aSrcName);
    74 	TPtrC mask(trg.NameAndExt());
    75 	TPtrC source(src.NameAndExt());
    76 	TInt steps = 1;
    77 	TBool starCharFound = EFalse;
    78 	if(mask.LocateReverse('.')!=KErrNotFound || aTrgMask.Right(1)==_L("*"))
    79 		{
    80 		mask.Set(trg.Name());
    81 		source.Set(src.Name());
    82 		steps = 2;
    83 		}
    84 	for(TInt i = 0; i < steps;
    85 	    i++, mask.Set(trg.ExtPresent() ? trg.Ext() : _L(".*")) , source.Set(src.Ext()))
    86 		{
    87 		TInt offset = 0;
    88 		starCharFound = EFalse;
    89 		while(offset < mask.Length())
    90 			{
    91 			TChar currentChar = mask[offset];
    92 			switch(currentChar)
    93 				{
    94 				case KMatchAny:
    95 					if(offset < source.Length() && !starCharFound)
    96 						{
    97 						destName.Append(source.Mid(offset));
    98 						starCharFound = ETrue;
    99 						}
   100 					break;
   101 				case KMatchOne:
   102 					if(offset < source.Length())
   103 				    {
   104 				    destName.Append(source[offset]);
   105 				    }
   106 					break;
   107 				default:
   108 					destName.Append(currentChar);
   109 					break;
   110 				}
   111 			offset++;
   112 			}
   113 		}
   114 	if(destName.Right(1) == _L("."))
   115 		{
   116 		destName.SetLength(destName.Length()-1);
   117 		}
   118 	if(aTrgName.Length()+destName.Length() > KMaxFileName)
   119 		{
   120 		return KErrBadName;
   121 		}
   122 	aTrgName.Append(destName);
   123 	return KErrNone;
   124 	}
   125 
   126 EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManStarted()
   127 /**
   128 Inform the observer that an operation is about to start.
   129 
   130 This is done immediately before each entry is processed.
   131 
   132 @return The implementation of this function should return:
   133         MFileManObserver::EContinue, to allow processing of the current file
   134         to proceed;
   135         MFileManObserver::ECancel, to skip processing the current file and move
   136         to the next file;
   137         MFileManObserver::EAbort to abort the entire operation.
   138         The default return value is MFileManObserver::EContinue.
   139 */
   140 	{
   141 
   142 	return(EContinue);
   143 	}
   144 
   145 
   146 
   147 
   148 EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManOperation()
   149 /**
   150 Informs the observer that an operation, i.e. a copy or a move, is proceeding.
   151 
   152 Large files are copied and moved in stages.
   153 After each portion of the source file has been copied to the target, this
   154 function is called.
   155 
   156 It may be useful to call CFileMan::BytesTransferredByCopyStep() from this
   157 function to retrieve the current status of the operation.
   158 
   159 @return The implementation of this function should return:
   160         MFileManObserver::ECancel, to cancel the current operation, closing the current source
   161         and target files, the current target file is deleted.
   162         If the operation is performed on several files, cancelling one will not abort whole batch.
   163 
   164         MFileManObserver::EContinue, to continue with the operation.
   165         The default return value is MFileManObserver::EContinue.
   166 
   167 @see CFileMan
   168 */
   169 	{
   170 
   171 	return(EContinue);
   172 	}
   173 
   174 
   175 
   176 
   177 EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManEnded()
   178 /**
   179 Informs the observer that an operation is complete.
   180 
   181 This is done immediately after a directory entry has been processed.
   182 
   183 It may be useful to call CFileBase::GetLastError()
   184 and CFileBase::GetMoreInfoAboutError() from this function to retrieve
   185 information about how the operation ended.
   186 
   187 @return The implementation of this function should return:
   188         MFileManObserver::EContinue or MFileManObserver::ECancel, to proceed
   189         with processing the next entry. MFileManObserver::ECancel will not
   190         cancel processing the current entry;
   191         MFileManObserver::ERetry, to re-attempt processing the previous file;
   192         MFileManObserver::EAbort, to abort the entire operation.
   193         The default return value is MFileManObserver::EContinue.
   194 
   195 @see CFileBase
   196 */
   197 	{
   198 
   199 	return(EContinue);
   200 	}
   201 
   202 
   203 
   204 
   205 EXPORT_C CFileBase::CFileBase(RFs& aFs)
   206 /**
   207 Protected default constructor.
   208 
   209 Note that the class is intended only as an abstract base for other classes.
   210 
   211 @param aFs File server session.
   212 */
   213 	: iFs(aFs)
   214 	{
   215 	}
   216 
   217 
   218 
   219 
   220 EXPORT_C void CFileBase::ConstructL()
   221 /**
   222 Second phase constructor.
   223 */
   224 	{
   225 
   226 	iScanner=CDirScan::NewL(iFs);
   227 	User::LeaveIfError(iSynchronizer.CreateLocal(0));
   228 	}
   229 
   230 
   231 
   232 
   233 EXPORT_C CFileBase::~CFileBase()
   234 /**
   235 Destructor.
   236 
   237 Frees resources prior to destruction of the object.
   238 */
   239 	{
   240 
   241 	delete iScanner;
   242 	delete iDirList;
   243 	iSynchronizer.Close();
   244 	User::Free(iSessionPath);
   245 	}
   246 
   247 
   248 
   249 
   250 GLDEF_C void DoFManBaseOperationL(TAny* aPtr)
   251 //
   252 // File manager asynchronous thread
   253 //
   254 	{
   255 
   256 	CFileBase& fMan=*(CFileBase*)aPtr;
   257 	User::LeaveIfError(fMan.iFs.Connect());
   258 	User::LeaveIfError(fMan.iFs.SetSessionPath(*fMan.iSessionPath));
   259 	fMan.iNumberOfFilesProcessed = 0;
   260 	fMan.RunL();
   261 	}
   262 
   263 GLDEF_C TInt FManBaseThreadFunction(TAny* aPtr)
   264 //
   265 // Initialise New thread
   266 //
   267 	{
   268 
   269 	CTrapCleanup* cleanup=CTrapCleanup::New();
   270 	if (cleanup==NULL)
   271 		return(KErrNoMemory);
   272 	CFileBase& fMan=*(CFileBase*)aPtr;
   273 	fMan.iSynchronizer.Wait();
   274 	TRAPD(ret,DoFManBaseOperationL(aPtr));
   275 	if (ret==KErrNone)
   276 		ret=fMan.iLastError;
   277 	delete cleanup;
   278 	fMan.iSwitches=0;
   279 	fMan.iFs=fMan.iFsOld;
   280 	fMan.iStatus=NULL;
   281 	fMan.iFManThread.Close();
   282 	return(ret);
   283 	}
   284 
   285 
   286 
   287 
   288 EXPORT_C void CFileBase::RunInSeparateThreadL(TThreadFunction aThreadFunction)
   289 /**
   290 Creates a separate thread to run the command.
   291 
   292 @param aThreadFunction The thread function.
   293 */
   294 	{
   295 	iSwitches|=KFManBusyFlag;
   296 	User::LeaveIfError(iFManThread.Create(KNullDesC,aThreadFunction,KDefaultStackSize,NULL,this));
   297 	iFManThread.SetPriority(EPriorityMuchLess);
   298 	TFileName sessionPath;
   299 	User::LeaveIfError(iFs.SessionPath(sessionPath));
   300 	if (iSessionPath==NULL)
   301 		iSessionPath=HBufC::NewL((sessionPath.Length()));
   302 	else if (iSessionPath->Des().MaxLength()<sessionPath.Length())
   303 		iSessionPath=iSessionPath->ReAllocL(IncPathLength(sessionPath.Length()));
   304 	iSessionPath->Des()=sessionPath;
   305 	iFsOld=iFs;
   306 	iLastError=KErrNone;
   307 	iFManThread.Logon(*iStatus);
   308 	iFManThread.Resume();
   309 	}
   310 
   311 
   312 
   313 
   314 EXPORT_C void CFileBase::RunL()
   315 /**
   316 Executes a command.
   317 
   318 @capability Dependent the capabilities required by this method, of the abstract class CFileBase,
   319 					  will be dependent on and provided by the concrete-class implementation of
   320 					  the DoOperationL method
   321 
   322 */
   323 	{
   324 	if (iStatus && (iSwitches&KFManBusyFlag)==EFalse)
   325 		{
   326 		RunInSeparateThreadL(FManBaseThreadFunction);
   327 		return;
   328 		}
   329 
   330 	TBool copyFromHandle = (iSwitches & KCopyFromHandle)?(TBool)ETrue:(TBool)EFalse;
   331 
   332 	CDirScan::TScanDirection scanDir=(iSwitches&KScanDownFlag) ? CDirScan::EScanDownTree : CDirScan::EScanUpTree;
   333 
   334 	if (!copyFromHandle)
   335 		{
   336 		TRAP(iLastError,iScanner->SetScanDataL(iSrcFile.FullName(),iMatchEntry,ESortByName|EAscending,scanDir));
   337 		if (iLastError==KErrNone)
   338 			TRAP(iLastError,iScanner->NextL(iDirList));
   339 
   340 		if (iLastError!=KErrNone)
   341 			{
   342 			iErrorInfo=EInitializationFailed;
   343 			User::Leave(iLastError);
   344 			}
   345 		}
   346 
   347 	FOREVER
   348 		{
   349 		if (copyFromHandle || iDirList->Count())
   350 			{
   351 			iLastError=KErrNone;
   352 			iErrorInfo=ENoExtraInformation;
   353 			TInt action=(iObserver) ? iObserver->NotifyFileManStarted() : MFileManObserver::EContinue;
   354 			// Check if NotifyFileManStarted returned ECancel.
   355 			if ( action == MFileManObserver::ECancel)
   356 				iLastError=KErrCancel;
   357 			if (action==MFileManObserver::EContinue)
   358 				{
   359 				iNumberOfFilesProcessed++;
   360 				TRAP(iLastError,DoOperationL());
   361 				action=(iObserver) ? iObserver->NotifyFileManEnded() : MFileManObserver::EContinue;
   362 				}
   363 			else if(action==MFileManObserver::ERetry)
   364 			  {
   365 			  Panic(EFManBadValueFromObserver);
   366 			  }
   367 
   368 
   369 			switch(action)
   370 				{
   371 			case MFileManObserver::EContinue:
   372 			case MFileManObserver::ECancel:
   373 				break;
   374 			case MFileManObserver::ERetry:
   375 				continue;
   376 			case MFileManObserver::EAbort:
   377 				delete iDirList;
   378 				iDirList=NULL;
   379 				iCurrentEntry = 0;
   380 				User::Leave(KErrCancel);
   381 			default:
   382 				Panic(EFManBadValueFromObserver);
   383 				}
   384 			}
   385 		iCurrentEntry++;
   386 		if (copyFromHandle || iCurrentEntry>=iDirList->Count())
   387 			{
   388 			delete iDirList;
   389 			iDirList=NULL;
   390 			iCurrentEntry=0;
   391 
   392 			if (iSwitches&KRecurseFlag)
   393 				{
   394 				TRAPD(ret,iScanner->NextL(iDirList));
   395 				if (ret!=KErrNone && ret!=KErrPathNotFound)
   396 					{
   397 					iErrorInfo=EScanNextDirectoryFailed;
   398 					iLastError = ret;
   399 					User::Leave(iLastError);
   400 					}
   401 				}
   402 			if (iDirList==NULL)
   403 				{
   404 				CompleteOperationL();
   405 				return;
   406 				}
   407 			}
   408 		}
   409 	}
   410 
   411 
   412 
   413 
   414 EXPORT_C void CFileBase::SetObserver(MFileManObserver* anObserver)
   415 /**
   416 Sets the observer.
   417 
   418 Use this function to provide CFileMan with an MFileManObserver, or, if one
   419 already exists, to change the observer.
   420 
   421 @param anObserver File management observer.
   422 
   423 @see CFileMan
   424 @see MFileManObserver
   425 */
   426 	{
   427 
   428 	iObserver=anObserver;
   429 	}
   430 
   431 
   432 
   433 
   434 EXPORT_C const TEntry& CFileBase::CurrentEntry()
   435 /**
   436 Gets the entry currently being processed.
   437 
   438 @return Contains the current entry.
   439 */
   440 	{
   441 
   442 	__ASSERT_ALWAYS(iDirList && iCurrentEntry>=0 && iCurrentEntry<iDirList->Count(),Panic(EFManCurrentEntryInvalid));
   443 	return (*iDirList)[iCurrentEntry];
   444 	}
   445 
   446 
   447 
   448 
   449 EXPORT_C TPtrC CFileBase::AbbreviatedPath()
   450 /**
   451 Gets the abbreviated path of the file or directory currently being processed.
   452 
   453 The abbreviated path is its path relative to the top level directory
   454 specified in the operation.
   455 
   456 @return The abbreviated path.
   457 */
   458 	{
   459 
   460 	return iScanner->AbbreviatedPath();
   461 	}
   462 
   463 
   464 
   465 
   466 EXPORT_C TPtrC CFileBase::FullPath()
   467 /**
   468 Gets the full path of the file or directory currently being processed.
   469 
   470 The full path includes the drive letter, path and filename.
   471 
   472 @return The full path.
   473 */
   474 	{
   475 
   476 	return iScanner->FullPath();
   477 	}
   478 
   479 
   480 
   481 
   482 EXPORT_C TInt CFileBase::GetLastError()
   483 /**
   484 Gets the latest error code returned during a CFileMan
   485 operation.
   486 
   487 This function may be called from MFileManObserver::NotifyFileManEnded().
   488 
   489 @return KErrNone, or another error code that might have been
   490         returned by a CFileMan operation.
   491 */
   492 	{
   493 
   494 	return(iLastError);
   495 	}
   496 
   497 
   498 
   499 
   500 EXPORT_C TFileManError CFileBase::GetMoreInfoAboutError()
   501 /**
   502 Gets additional information about the latest error returned during
   503 a CFileMan operation.
   504 
   505 For example, if a rename fails, this function
   506 can be used to report whether the source or target name caused the problem.
   507 This information supplements that provided GetLastError().
   508 
   509 @return The extra information about the last CFileMan error.
   510 
   511 @see CFileMan
   512 @see CFileBase::GetLastError()
   513 */
   514 	{
   515 
   516 	return(iErrorInfo);
   517 	}
   518 
   519 
   520 
   521 
   522 EXPORT_C CFileMan* CFileMan::NewL(RFs& aFs)
   523 /**
   524 Constructs and allocates memory for a new CFileMan object.
   525 
   526 @param aFs File server session.
   527 
   528 @return Newly created CFileMan object.
   529 */
   530 	{
   531 	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL1, MODULEUID, aFs.Handle());
   532 
   533 	CFileMan* fileMan=new(ELeave) CFileMan(aFs);
   534 	CleanupStack::PushL(fileMan);
   535 	fileMan->CFileBase::ConstructL();
   536 	CleanupStack::Pop();
   537 
   538 	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL1Return, MODULEUID, fileMan);
   539 	return fileMan;
   540 	}
   541 
   542 
   543 
   544 
   545 EXPORT_C CFileMan* CFileMan::NewL(RFs& aFs,MFileManObserver* anObserver)
   546 /**
   547 Constructs and allocates memory for a new CFileMan object with an observer.
   548 
   549 @param aFs        File server session.
   550 @param anObserver File management observer.
   551 
   552 @return Newly created CFileMan object.
   553 */
   554 	{
   555 	TRACE2(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL2, MODULEUID, aFs.Handle(), anObserver);
   556 
   557 	CFileMan* fileMan=new(ELeave) CFileMan(aFs);
   558 	CleanupStack::PushL(fileMan);
   559 	fileMan->CFileBase::ConstructL();
   560 	CleanupStack::Pop();
   561 	fileMan->SetObserver(anObserver);
   562 
   563 	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL2Return, MODULEUID, fileMan);
   564 	return fileMan;
   565 	}
   566 
   567 
   568 
   569 
   570 CFileMan::CFileMan(RFs& aFs)
   571 //
   572 // Constructor and destructor
   573 //
   574 	: CFileBase(aFs)
   575 	{
   576 	}
   577 CFileMan::~CFileMan()
   578 	{
   579 	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDestructor, MODULEUID, this);
   580 
   581 	TRACE0(UTF::EBorder, UTraceModuleEfsrv::ECFileManDestructorReturn, MODULEUID);
   582 	}
   583 
   584 
   585 EXPORT_C CFileMan::TAction CFileMan::CurrentAction()
   586 /**
   587 Gets the action which CFileMan is currently carrying out.
   588 
   589 @return The action which CFileMan is carrying out.
   590 */
   591 	{
   592 	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCurrentAction, MODULEUID, this);
   593 
   594 	TAction action = ENone;
   595 
   596 	// Mapping table between internal and external action indicators.
   597 	switch(iAction)
   598 		{
   599 	case EInternalNone:
   600 		action = ENone;
   601 		break;
   602 	case EInternalAttribs:
   603 		action = EAttribs;
   604 		break;
   605 	case EInternalCopy:
   606 		action = ECopy;
   607 		break;
   608 	case EInternalCopyForMove:
   609 		action = EMove;
   610 		break;
   611 	case EInternalDelete:
   612 		action = EDelete;
   613 		break;
   614 	case EInternalRenameInvalidEntry:
   615 		action = ERenameInvalidEntry;
   616 		break;
   617 	case EInternalRenameForMove:
   618 	case EInternalRename:
   619 		action = ERename;
   620 		break;
   621 	case EInternalRmDir:
   622 		action = ERmDir;
   623 		break;
   624 	case EInternalCopyFromHandle:
   625 		action = ECopyFromHandle;
   626 		break;
   627 	default:
   628 		Panic(EFManUnknownAction);
   629 		}
   630 
   631 	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCurrentActionReturn, MODULEUID, action);
   632 	return (action);
   633 	}
   634 
   635 
   636 
   637 
   638 EXPORT_C void CFileMan::GetCurrentTarget(TFileName& aTrgName)
   639 /**
   640 Gets the name of the target file for the CFileMan operation currently
   641 being carried out.
   642 
   643 This function is relevant when copying, moving or renaming files.
   644 
   645 @param aTrgName The full path and filename of the target file for
   646                 the current CFileMan operation
   647 */
   648 	{
   649 	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentTarget, MODULEUID, this);
   650 
   651 	GetSrcAndTrg(iTmpParse, aTrgName);
   652 
   653 	TRACEMULT1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentTargetReturn, MODULEUID, aTrgName);
   654 	}
   655 
   656 
   657 
   658 
   659 EXPORT_C void CFileMan::GetCurrentSource(TFileName& aSrcName)
   660 /**
   661 Gets the name of the source file or directory for the CFileMan operation
   662 currently being carried out.
   663 
   664 The source is the file or directory which is being copied, moved or deleted.
   665 
   666 @param aSrcName The full path and filename of the source file for the current
   667                 CFileMan operation.
   668 */
   669 	{
   670 	TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentSource, MODULEUID, this);
   671 
   672     TPtrC fullPath(FullPath());
   673 	iTmpParse.Set(CurrentEntry().iName, &fullPath, NULL);
   674 	aSrcName = iTmpParse.FullName();
   675 
   676 	TRACEMULT1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentSourceReturn, MODULEUID, aSrcName);
   677 	}
   678 
   679 void CFileMan::GetSrcAndTrg(TParse& aSrcName,TFileName& aTrgName)
   680 //
   681 // Get the current target for the operation
   682 //
   683 	{
   684 	TFileName fullpath = FullPath();
   685 	TInt ret = aSrcName.Set(CurrentEntry().iName, &fullpath, NULL);
   686 	if(ret == KErrBadName)
   687 		{
   688 		// Try heap variables first
   689 		TBool done = EFalse;
   690 		TFileName* current = new TFileName;
   691 		if (current != NULL)
   692 			{
   693 			current->Copy(CurrentEntry().iName);
   694 
   695 			ret = ShrinkNames(iFs, fullpath, *current, EFalse);
   696 			if(ret == KErrNone)
   697 				{
   698 				ret = aSrcName.Set(*current, &fullpath, NULL);
   699 				done = ETrue;
   700 				}
   701 			delete current;
   702 			}
   703 
   704 		if (!done) //heap method failed
   705 			{
   706 			TFileName current = CurrentEntry().iName;
   707 			ret = ShrinkNames(iFs, fullpath, current, EFalse);
   708 			if(ret == KErrNone)
   709 				{
   710 				ret = aSrcName.Set(current, &fullpath, NULL);
   711 				}
   712 			}
   713 		}
   714 	__ASSERT_DEBUG(ret == KErrNone, Panic(EBadLength));
   715 	aTrgName=iTrgFile.DriveAndPath();
   716 	TPtrC relPath=iScanner->AbbreviatedPath();
   717 	aTrgName.Append(relPath.Right(relPath.Length()-1));
   718 	CreateTargetNameFromSource(aTrgName,iTrgFile.NameAndExt(),aSrcName.NameAndExt());
   719 	}
   720 
   721 
   722 
   723 
   724 EXPORT_C TInt CFileMan::BytesTransferredByCopyStep()
   725 /**
   726 Gets the number of bytes transferred during a copy or move operation.
   727 
   728 Large files are copied and moved in stages. After each portion of
   729 the source file has been copied to the target, the number of bytes
   730 transferred is updated. This function may be called
   731 from MFileManObserver::NotifyFileManOperation()
   732 and may be used to support the increment of progress bars.
   733 
   734 @return The number of bytes transferred.
   735 */
   736 	{
   737 	TRACE2(UTF::EBorder, UTraceModuleEfsrv::ECFileManBytesTransferredByCopyStep, MODULEUID, this, iBytesTransferred);
   738 
   739 	return(iBytesTransferred);
   740 	}
   741 
   742 
   743 
   744 
   745 LOCAL_C void MakeParseWild(TParse& aParse, TFileName& aName)
   746 //
   747 // Append _L("\\*") or _L("*") to aParse
   748 //
   749 	{
   750 	if(!aParse.IsWild())
   751 		{
   752 		aName = aParse.FullName();
   753 		if (aParse.NamePresent() || aParse.ExtPresent())
   754 			{
   755 			if (aName.Length()<=254)
   756 				aName.Append(_L("\\*"));
   757 			}
   758 		else
   759 			{
   760 			if (aName.Length()<=255)
   761 				aName.Append(_L("*"));
   762 			}
   763 		aParse.Set(aName,NULL,NULL);
   764 		}
   765 	}
   766 
   767 
   768 void CFileMan::CheckForDirectory()
   769 //
   770 // If iTrgFile is a directory set target to iTrgFile\\*
   771 //
   772 	{
   773 	TInt trg = iFs.Entry(iTrgFile.FullName(), iTmpEntry);
   774 	if (trg==KErrNone && iTmpEntry.iAtt&KEntryAttDir)
   775 		MakeParseWild(iTrgFile, iTmpName1);
   776 	TInt src = iFs.Entry(iSrcFile.FullName(), iTmpEntry);
   777 	if (src==KErrNone && iTmpEntry.iAtt&KEntryAttDir)
   778 		{
   779 		MakeParseWild(iSrcFile, iTmpName1);
   780 		if (trg==KErrNotFound && (iSwitches&KRecurseFlag))
   781 			MakeParseWild(iTrgFile, iTmpName1);
   782 		}
   783 	}
   784 
   785 void CFileMan::DoSynchronize(TInt aRetValue)
   786 //
   787 // Synchronise with fmanthread
   788 //
   789 	{
   790 
   791 	if (iStatus && aRetValue==KErrNone)
   792 		iSynchronizer.Signal(); // FManThread started
   793 	if (iStatus && aRetValue!=KErrNone)
   794 		iStatus=NULL; // FManThread failed to start
   795 	}
   796 
   797 LOCAL_C void NextInPath(const TDesC& aPath,TPtrC& anEntry,TInt& aPos)
   798 //
   799 // Returns the next entry in the path
   800 //
   801 	{
   802 
   803 	anEntry.Set(NULL,0);
   804 	if ((aPos+1)>=aPath.Length())
   805 		return;
   806 	TPtrC path(aPath.Mid(aPos+1)); // Skip delimiter
   807 	TInt delimiterPos=path.Locate(KPathDelimiter);
   808 	if (delimiterPos==KErrNotFound)
   809 		delimiterPos=aPath.Length()-(aPos+1);
   810 	if (delimiterPos<=0)
   811 		return;
   812 
   813 	if (path[delimiterPos-1]==KExtDelimiter) // return "F32." as "F32"
   814 		anEntry.Set(aPath.Mid(aPos+1,delimiterPos-1));
   815 	else
   816 		anEntry.Set(aPath.Mid(aPos+1,delimiterPos));
   817 	aPos+=delimiterPos+1;
   818 	}
   819 
   820 LOCAL_C TBool ComparePaths(const TDesC& aPath1,const TDesC& aPath2)
   821 //
   822 // Return ETrue if the paths are identical
   823 // To catch case "\\F32.\\GROUP\\" == "\\F32\\GROUP\\"
   824 //
   825 	{
   826 
   827 	TPtrC entry1(NULL,0);
   828 	TPtrC entry2(NULL,0);
   829 	TInt pos1=0;
   830 	TInt pos2=0;
   831 
   832 	do {
   833 		NextInPath(aPath1,entry1,pos1);
   834 		NextInPath(aPath2,entry2,pos2);
   835 		if (entry1.MatchF(entry2)==KErrNotFound)
   836 			return(EFalse);
   837 		} while (entry1.Length() && entry2.Length());
   838 
   839 	return(ETrue);
   840 	}
   841 
   842 EXPORT_C TBool FileNamesIdentical(const TDesC& aFileName1,const TDesC& aFileName2)
   843 //
   844 // Return ETrue if the filenames (and paths) are identical
   845 // NB "Agenda" == "AGENda."
   846 //
   847 	{
   848 
   849 	TParsePtrC file1(aFileName1);
   850 	TParsePtrC file2(aFileName2);
   851 	if (file1.Drive().MatchF(file2.Drive())==KErrNotFound)
   852 		return(EFalse);
   853 	if (file1.Name().MatchF(file2.Name())==KErrNotFound)
   854 		return(EFalse);
   855 	if (ComparePaths(file1.Path(),file2.Path())==EFalse)
   856 		return(EFalse);
   857 	if (file1.Ext().Length()==0 || file2.Ext().Length()==0)
   858 		{ // Agenda == Agenda.
   859 		if (file1.Ext().Length()==1 || file2.Ext().Length()==1)
   860 			return(ETrue);
   861 		}
   862 	if (file1.Ext().MatchF(file2.Ext())==KErrNotFound &&
   863 		file1.NameAndExt().MatchF(file2.NameAndExt())==KErrNotFound)
   864 		return(EFalse);
   865 	return(ETrue);
   866 	}
   867 
   868 
   869 
   870 
   871 EXPORT_C TInt CFileMan::Attribs(const TDesC& aName,TUint aSetMask,TUint aClearMask,const TTime& aTime,TUint aSwitches,TRequestStatus& aStatus)
   872 /**
   873 Sets or clears attributes for one or more files using two bitmasks.
   874 
   875 This is an asynchronous function.
   876 Its behaviour is the same as the synchronous overload.
   877 
   878 @param aName      Path indicating the file(s) whose attributes are to be
   879                   changed. Any path components which are not specified
   880                   here will be taken from the session path.
   881                   Use wildcards to specify more than one file.
   882 @param aSetMask   Bitmask indicating the attributes to be set.
   883 @param aClearMask Bitmask indicating the attributes to be cleared.
   884                   For more information, see KEntryAttNormal and the other
   885                   file/directory attributes.
   886 @param aTime      Contains the new modification date and time for the files, in UTC.
   887                   To preserve the file's timestamps, specify a TTime value of 0.
   888 @param aSwitches  Specify zero for no recursion;
   889                   CFileMan::ERecurse for recursion.
   890                   By default, the synchronous variant of this function operates
   891                   non-recursively.
   892 @param aStatus    The request status object. On request completion,
   893                   indicates how the request completed:
   894                   KErrNone, if successful, otherwise one of the other system-wide error
   895                   codes.
   896 
   897 @return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
   898 					is still pending; otherwise one of the other system-wide error codes
   899 
   900 @capability Dependent If aName is /Sys then Tcb capability is required.
   901 @capability Dependent If aName begins with /Private and does not match
   902 					  this process' SID then AllFiles capability is required.
   903 @capability Dependent If aName is /Resource then Tcb capability is required.
   904 
   905 */
   906 	{
   907 	TRACEMULT8(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs1, MODULEUID,
   908 		(TUint) this, aName, aSetMask, aClearMask, I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()), aSwitches, (TUint) &aStatus);
   909 
   910 	TInt r;
   911 	if (iSwitches&KFManBusyFlag)
   912 		{
   913 		r = KErrInUse;
   914 		}
   915 	else
   916 		{
   917 		iStatus=&aStatus;
   918 		r = Attribs(aName,aSetMask,aClearMask,aTime,aSwitches);
   919 		}
   920 
   921 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs1Return, MODULEUID, r);
   922 	return r;
   923 	}
   924 
   925 
   926 
   927 
   928 EXPORT_C TInt CFileMan::Attribs(const TDesC& aName,TUint aSetMask,TUint aClearMask,const TTime& aTime,TUint aSwitches)
   929 /**
   930 Sets or clears attributes for one or more files using two bitmasks
   931 
   932 This is a synchronous function.
   933 
   934 The first bitmask specifies the attributes to be set.
   935 The second specifies the attributes to be cleared.
   936 The date and time of the files' last modification can also be changed.
   937 
   938 The function can operate recursively or non-recursively.
   939 When operating non-recursively, only the matching files located in the directory
   940 specified in aName are affected. When operating recursively, all matching files
   941 in the directory hierarchy below the directory specified in aName will be affected.
   942 
   943 Notes:
   944 
   945 1. A panic is raised if any attribute is specified in both bitmasks.
   946 
   947 2. Attempting to change the attributes for an open file results in an error
   948    for that file, as retrieved by CFileBase::GetLastError().
   949 
   950 3. An attempt to set or clear the KEntryAttDir or KEntryAttVolume attribute
   951    for a file or directory will have no effect.
   952 
   953 @param aName      Path indicating the file(s) whose attributes are to be
   954                   changed. Any path components which are not specified
   955                   here will be taken from the session path.
   956                   Use wildcards to specify more than one file.
   957 @param aSetMask   Bitmask indicating the attributes to be set.
   958 @param aClearMask Bitmask indicating the attributes to be cleared.
   959                   For more information, see KEntryAttNormal and the other
   960                   file/directory attributes.
   961 @param aTime      Contains the new modification date and time for the files, in UTC.
   962                   To preserve the file's timestamps, specify a TTime value of 0.
   963 @param aSwitches  Specify zero for no recursion;
   964                   CFileMan::ERecurse for recursion.
   965                   By default, the synchronous variant of this function operates
   966                   non-recursively.
   967 
   968 @return KErrNone if successful, otherwise one of the other system-wide error codes.
   969 
   970 @capability Dependent If aName is /Sys then Tcb capability is required.
   971 @capability Dependent If aName begins with /Private and does not match
   972 					  this process' SID then AllFiles capability is required.
   973 @capability Dependent If aName is /Resource then Tcb capability is required.
   974 
   975 */
   976 	{
   977 	TRACEMULT7(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs2, MODULEUID,
   978 		(TUint) this, aName, aSetMask, aClearMask, I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()), aSwitches);
   979 
   980 	TInt ret;
   981 	if (iSwitches&KFManBusyFlag)
   982 		{
   983 		ret = KErrInUse;
   984 		}
   985 	else
   986 		{
   987 		SetFlags(aSwitches&EOverWrite,aSwitches&ERecurse,ETrue,EFalse);
   988 		RETURNIFERRORD(r,iFs.Parse(aName,iSrcFile),UTraceModuleEfsrv::ECFileManAttribs2Return);
   989 		iSetMask=aSetMask;
   990 		iClearMask=aClearMask;
   991 		iTime=aTime;
   992 		iAction = EInternalAttribs;
   993 		iMatchEntry=KEntryAttMaskSupported; // all entries
   994 		iNumberOfFilesProcessed = 0;
   995 		TRAP(r,RunL());
   996 		ret=(r==KErrNone) ? iLastError : r;
   997 		DoSynchronize(r);
   998 		}
   999 
  1000 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs2Return, MODULEUID, ret);
  1001 	return(ret);
  1002 	}
  1003 
  1004 
  1005 
  1006 
  1007 EXPORT_C TInt CFileMan::Copy(const TDesC& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
  1008 /**
  1009 Copies one or more files.
  1010 
  1011 This is an asynchronous function.
  1012 Its behaviour is the same as the synchronous overload.
  1013 
  1014 @param anOld     Path indicating the file(s) to be copied.
  1015                  Any path components which are not specified here will be
  1016                  taken from the session path.
  1017 @param aNew      Path indicating the directory into which the file(s) are to be copied.
  1018 				 Any path components which are not specified here will be
  1019                  taken from the session path
  1020 @param aSwitches Specify zero for no overwriting and no recursion;
  1021                  CFileMan::EOverWrite to overwrite files with the same name;
  1022                  CFileMan::ERecurse for recursion.
  1023                  By default, the synchronous variant of this function operates
  1024                  non-recursively and with overwriting.
  1025 @param aStatus   The request status object. On request completion,
  1026                  indicates how the request completed:
  1027                  KErrNone, if successful, otherwise one of the other system-wide error
  1028                  codes.
  1029 
  1030 @return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1031 					is still pending; otherwise one of the other system-wide error codes
  1032 
  1033 @capability AllFiles
  1034 
  1035 @capability Dependent If the path for aNew begins with /Sys then Tcb capability is required.
  1036 @capability Dependent If the path for aNew begins with /Resource then Tcb capability is required
  1037 
  1038 */
  1039 	{
  1040 	TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy1, MODULEUID,
  1041 		(TUint) this, anOld, aNew, aSwitches, (TUint) &aStatus);
  1042 
  1043 	TInt r;
  1044 	if (iSwitches&KFManBusyFlag)
  1045 		r = KErrInUse;
  1046 	else
  1047 		{
  1048 		iStatus=&aStatus;
  1049 		r = Copy(anOld,aNew,aSwitches);
  1050 		}
  1051 
  1052 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy1Return, MODULEUID, r);
  1053 	return(r);
  1054 	}
  1055 
  1056 
  1057 
  1058 
  1059 EXPORT_C TInt CFileMan::Copy(const TDesC& anOld,const TDesC& aNew,TUint aSwitches)
  1060 /**
  1061 Copies one or more files.
  1062 
  1063 This is a synchronous function.
  1064 
  1065 NB the following applies to files greater than or equal to 2GBytes in size
  1066 (2,147,483,648 bytes) :
  1067 - Only files smaller than 2GBytes will be copied; any larger files will be skipped and
  1068 processing will continue with the next file.
  1069 - If at least one file is smaller than 2GBytes, then KErrNone will be returned.
  1070 - If all files are greater than or equal to 2GBytes ,then KErrTooBig will be returned.
  1071 
  1072 One way to detect the presence of any large file(s) is to use an observer: calling
  1073 CFileBase::GetLastError() from MFileManObserver::NotifyFileManEnded() will return
  1074 KErrToBig for any file >= 2GBytes in size.
  1075 
  1076 Note: the copy operation behaves differently when MFileManObserver is used.
  1077 MFileManObserver should be used with multiple files as it enables you to capture the results of all file copy operations.
  1078 
  1079 If MFileManObserver is NOT used then only the result of the last
  1080 file copy operation is returned because the results of previous file copy operations are overwritten.
  1081 
  1082 Optionally, this function can be set to overwrite any files with the same name
  1083 which exist in the target directory. If the flag is set for no overwriting,
  1084 then any files with the same name will not be overwritten, and an error
  1085 (KErrAlreadyExists) will be returned for that file. Error codes may be retrieved
  1086 using CFileBase::GetLastError().
  1087 
  1088 If recursive operation is set, all intermediate directories will be created,
  1089 including any directories in the path specified by aNew which do not
  1090 already exist.
  1091 
  1092 If recursive operation is not set, only the matching files located in
  1093 the single directory specified in anOld are copied.
  1094 No intermediate directories will be created; if any directories in
  1095 the destination path do not exist, no files will be copied, and this function
  1096 will return KErrPathNotFound.
  1097 
  1098  Notes:
  1099  1.	This function operates on files only, therefore:
  1100  1.1	In contrast to the way CFileMan::Move() and CFileMan::Rename()
  1101  	behave, the behaviour of the copy operation does not depend on the presence
  1102  	or absence of a trailing backslash ("\") character. Therefore it is only
  1103  	possible to copy the content of the source path. It is NOT
  1104  	possible by use of a trailing backslash ("\") character to request that the
  1105  	last directory level plus its content be copied to the target path.
  1106 
  1107  	This means that the following two example copy operations will behave
  1108  	identically
  1109 
  1110  	@code
  1111  	CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1112  	...
  1113  	fm->Copy(_L("C:\\SRC\\"), _L("C:\\TRG\\"), CFileMan::ERecurse);
  1114  	fm->Copy(_L("C:\\SRC"), _L("C:\\TRG\\"), CFileMan::ERecurse);
  1115  	@endcode
  1116 
  1117  	because they will be interpreted as follows:
  1118  	@code
  1119  	fm->Copy(_L("C:\\SRC\\*"),_L("C:\\TRG\\"), CFileMan::ERecurse);
  1120  	@endcode
  1121 
  1122  1.2	If there is no file to operate on i.e. if source directory is empty, the
  1123  	function will do nothing and return error code KErrNotFound.
  1124 
  1125  2. Files can be copied across drives.
  1126 
  1127  3. Open files can be copied if they have been opened using
  1128       the EFileShareReadersOnly file share mode.
  1129 
  1130  4. Read-only, hidden and system files can be copied and
  1131    the source file's attributes are preserved in the target file.
  1132 
  1133 @param anOld     Path indicating the file(s) to be copied.
  1134                  Any path components which are not specified here will be
  1135                  taken from the session path.
  1136 @param aNew      Path indicating the directory into which the file(s) are to be copied.
  1137 				 Any path components which are not specified here will be
  1138                  taken from the session path
  1139 @param aSwitches Specify zero for no overwriting and no recursion;
  1140                  CFileMan::EOverWrite to overwrite files with the same name;
  1141                  CFileMan::ERecurse for recursion.
  1142                  By default, the synchronous variant of this function operates
  1143                  non-recursively and with overwriting.
  1144 
  1145 @return KErrNone if successful, KErrNotFound if source directory is empty, otherwise one of the other system-wide error codes.
  1146 
  1147 @see CFileBase::GetLastError()
  1148 
  1149 @capability AllFiles
  1150 
  1151 @capability Dependent If the path for anOld begins with /Sys then Tcb capability is required.
  1152 @capability Dependent If the path for anOld begins with /Resource then Tcb capability is required
  1153 
  1154 */
  1155 	{
  1156 	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2, MODULEUID, (TUint) this, anOld, aNew, aSwitches);
  1157 
  1158 	if (iSwitches&KFManBusyFlag)
  1159 		{
  1160 		TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, KErrInUse);
  1161 		return(KErrInUse);
  1162 		}
  1163 	SetFlags(aSwitches&EOverWrite,aSwitches&ERecurse,ETrue,EFalse);
  1164 	RETURNIFERRORD(r,iFs.Parse(anOld,iSrcFile),UTraceModuleEfsrv::ECFileManCopy2Return);
  1165 	RETURNIFERROR(r,iFs.Parse(aNew,_L("*"),iTrgFile),UTraceModuleEfsrv::ECFileManCopy2Return);
  1166 	CheckForDirectory();
  1167 
  1168 	if((iSwitches&KRecurseFlag) && iTrgFile.DriveAndPath().MatchF(iSrcFile.FullName()) != KErrNotFound)
  1169 		{
  1170 		TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, KErrArgument);
  1171 		return(KErrArgument);
  1172 		}
  1173 
  1174 	iAction = EInternalCopy;
  1175 	iMatchEntry=KEntryAttMaskSupported;
  1176 	iNumberOfFilesProcessed = 0;
  1177 	TRAP(r,RunL());
  1178 	TInt ret=(r==KErrNone) ? iLastError : r;
  1179 	DoSynchronize(r);
  1180 
  1181 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, ret);
  1182 	return(ret);
  1183 	}
  1184 
  1185 
  1186 
  1187 
  1188 EXPORT_C TInt CFileMan::Delete(const TDesC& aName,TUint aSwitches,TRequestStatus& aStatus)
  1189 /**
  1190 Deletes one or more files.
  1191 
  1192 This is an asynchronous function.
  1193 Its behaviour is the same as the synchronous overload.
  1194 
  1195 @param aName     Path indicating the file(s) to be deleted.
  1196                  May either be a full path, or relative to the session path.
  1197                  Use wildcards to specify more than one file.
  1198                  NOTE: if you pass KNullDesC, the empty (or null) descriptor,
  1199                  then the function interprets this to mean \\*.*
  1200 @param aSwitches Specify:
  1201                  zero for no recursion;
  1202                  CFileMan::ERecurse for recursion.
  1203                  By default, the synchronous variant of this function
  1204                  operates non-recursively.
  1205 @param aStatus   The request status object. On request completion,
  1206                  indicates how the request completed:
  1207                  KErrNone, if successful, otherwise one of the other system-wide error
  1208                  codes.
  1209 
  1210 @return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1211 					is still pending; otherwise one of the other system-wide error codes
  1212 
  1213 @capability Dependent If aName is /Sys then Tcb capability is required.
  1214 @capability Dependent If aName begins with /Private and does not match this process' SID
  1215 					  then AllFiles capability is required.
  1216 @capability Dependent If aName is /Resource then Tcb capability is required.
  1217 
  1218 @see KNullDesC
  1219 */
  1220 	{
  1221 	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete1, MODULEUID, (TUint) this, aName, aSwitches, (TUint) &aStatus);
  1222 
  1223 	TInt r;
  1224 	if (iSwitches&KFManBusyFlag)
  1225 		{
  1226 		r = KErrInUse;
  1227 		}
  1228 	else
  1229 		{
  1230 		iStatus=&aStatus;
  1231 		r = Delete(aName,aSwitches);
  1232 		}
  1233 
  1234 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete1Return, MODULEUID, r);
  1235 	return(r);
  1236 	}
  1237 
  1238 
  1239 
  1240 
  1241 EXPORT_C TInt CFileMan::Delete(const TDesC& aName,TUint aSwitches)
  1242 /**
  1243 Deletes one or more files.
  1244 
  1245 This is a synchronous function.
  1246 
  1247 This function can operate recursively or non-recursively.
  1248 When operating non-recursively, only the matching files located in
  1249 the directory specified in aName are affected.
  1250 When operating recursively, all matching files in the directory hierarchy
  1251 below the directory specified in aName will be deleted.
  1252 
  1253 Note that read-only and open files may not be deleted.
  1254 Attempting to do so will return an error for that file.
  1255 Error codes may be retrieved using CFileBase::GetLastError().
  1256 
  1257 @param aName     Path indicating the file(s) to be deleted.
  1258                  May either be a full path, or relative to the session path.
  1259                  Use wildcards to specify more than one file.
  1260                  NOTE: if you pass KNullDesC, the empty (or null) descriptor,
  1261                  then the function interprets this to mean \\*.*
  1262 @param aSwitches Specify:
  1263                  zero for no recursion;
  1264                  CFileMan::ERecurse for recursion.
  1265                  By default, the synchronous variant of this function
  1266                  operates non-recursively.
  1267 
  1268 @return KErrNone if successful, otherwise one of the other system-wide error
  1269         codes.
  1270 
  1271 @see CFileBase::GetLastError()
  1272 
  1273 @capability Dependent If aName is /Sys then Tcb capability is required.
  1274 @capability Dependent If aName begins with /Private and does not match this process' SID
  1275 					  then AllFiles capability is required.
  1276 @capability Dependent If aName is /Resource then Tcb capability is required.
  1277 
  1278 @see KNullDesC
  1279 */
  1280 	{
  1281 	TRACEMULT3(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete2, MODULEUID, (TUint) this, aName, aSwitches);
  1282 
  1283 	TInt ret;
  1284 	if (iSwitches&KFManBusyFlag)
  1285 		{
  1286 		ret = KErrInUse;
  1287 		}
  1288 	else
  1289 		{
  1290 		SetFlags(aSwitches&EOverWrite,aSwitches&ERecurse,ETrue,EFalse);
  1291 		RETURNIFERRORD(r,iFs.Parse(aName,iSrcFile),UTraceModuleEfsrv::ECFileManDelete2Return);
  1292 		iAction = EInternalDelete;
  1293 		iMatchEntry=KEntryAttHidden|KEntryAttMatchExclude|KEntryAttDir;
  1294 	//	Exclude directories and system files - include hidden files
  1295 		iNumberOfFilesProcessed = 0;
  1296 		TRAP(r,RunL());
  1297 		ret=(r==KErrNone) ? iLastError : r;
  1298 		DoSynchronize(r);
  1299 		}
  1300 
  1301 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete2Return, MODULEUID, ret);
  1302 	return(ret);
  1303 	}
  1304 
  1305 
  1306 
  1307 
  1308 EXPORT_C TInt CFileMan::Move(const TDesC& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
  1309 /**
  1310 Moves one or more files.
  1311 
  1312 This is an asynchronous function.
  1313 Its behaviour is the same as the synchronous overload.
  1314 
  1315 @param anOld     Path indicating the files to be moved. May be either
  1316                  a full path, or relative to the session path. Any path
  1317 				 components which are not specified here will be taken
  1318 				 from the session path.
  1319 @param aNew      Path indicating the directory into which the file(s) are
  1320                  to be moved. Any path components which are not specified
  1321                  here will be taken from the session path.
  1322 @param aSwitches Specify zero for no overwriting and no recursion;
  1323                  CFileMan::EOverWrite to overwrite files with the same name;
  1324                  CFileMan::ERecurse for recursion.
  1325                  By default, the synchronous variant of this function operates
  1326                  non-recursively and with overwriting.
  1327 @param aStatus   The request status object. On request completion,
  1328                  indicates how the request completed:
  1329                  KErrNone, if successful, otherwise one of the other system-wide error
  1330                  codes.
  1331 
  1332 @return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1333 					is still pending; otherwise one of the other system-wide error codes
  1334 
  1335 @capability Dependent If the path in aNew starts with /Sys then capability Tcb is required
  1336 @capability Dependent If the path in aNew starts with /Resource then capability Tcb is required
  1337 
  1338 @capability AllFiles
  1339 
  1340 @capability Dependent If the path in anOld starts with /Sys then Tcb capability is required.
  1341 @capability Dependent If the path in anOld starts with /Resource then Tcb capability is required.
  1342 
  1343 */
  1344 	{
  1345 	TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove1, MODULEUID,
  1346 		(TUint) this, anOld, aNew, aSwitches, (TUint) &aStatus);
  1347 
  1348 	TInt r;
  1349 	if (iSwitches&KFManBusyFlag)
  1350 		{
  1351 		r = KErrInUse;
  1352 		}
  1353 	else
  1354 		{
  1355 		iStatus=&aStatus;
  1356 		r = Move(anOld,aNew,aSwitches);
  1357 		}
  1358 
  1359 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove1Return, MODULEUID, r);
  1360 	return r;
  1361 	}
  1362 
  1363 
  1364 
  1365 
  1366 EXPORT_C TInt CFileMan::Move(const TDesC& anOld,const TDesC& aNew,TUint aSwitches)
  1367 /**
  1368 Moves one or more files.
  1369 
  1370 This is a synchronous function.
  1371 
  1372 Optionally, this function can be set to overwrite any files with the same name
  1373 which exist in the target directory. If the flag is set for no overwriting,
  1374 then any files with the same name will not be overwritten, and
  1375 an error (KErrAlreadyExists) will be returned for that file.
  1376 Error codes may be retrieved using CFileBase::GetLastError().
  1377 By default, when the function is operating synchronously, files are overwritten.
  1378 
  1379 When this function is operating recursively, all intermediate directories will
  1380 be created, including all directories in the destination path specified
  1381 by aNew which do not already exist.
  1382 
  1383 If recursive operation is not set, only the matching files located in
  1384 the single directory specified in anOld are moved. No intermediate directories
  1385 will be created; if any directories in the destination path do not exist,
  1386 no files will be moved, and this function will return KErrPathNotFound.
  1387 
  1388 The behaviour of the move operation is sensitive to the presence (or absence)
  1389 of a trailing backslash ("\") character on the end of the source path:
  1390 - if there is a trailing backslash ("\") character, then the operation moves
  1391   the content of the last directory level only.
  1392 - if there is no trailing backslash ("\") character, then the operation behaves
  1393   recursively by default and moves both the last directory level and all of its content.
  1394   Notice that no trailing backslash ("\") implies moving files recursively automatically.
  1395 
  1396 For example, if the directory level "b" contains the files F1,F2 and F3, then:
  1397 @code
  1398 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1399 ...
  1400 fm->Move(_L("C:\\a\\b\\"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
  1401 @endcode
  1402 
  1403 results in files F1, F2 and F3 being moved from C:\\a\\b to C:\\x\\y, leaving the
  1404 path C:\\a\\b unchanged, except that it no longer contains the files
  1405 F1, F2 and F3.
  1406 
  1407 If there is no trailing backslash character, for example:
  1408 @code
  1409 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1410 ...
  1411 fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
  1412 @endcode
  1413 
  1414 then both the directory level "b" and its contents are moved. This means that
  1415 there is no longer a directory "b" under C:\\a. Instead there is a new
  1416 directory structure C:\\x\\y\\b and the files F1, F2, and F3 now exist
  1417 under C:\\x\\y\\b. Also if "b" contains subdirectories, then these are also
  1418 moved along with "b".
  1419 
  1420 If there is no trailing backslash character and the switch is not set, i.e.
  1421 0 is passed as an argument, the operation behaves the same way as by passing
  1422 CFileMan::ERecurse flag.
  1423 
  1424 for example:
  1425 @code
  1426 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1427 ...
  1428 fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), 0);
  1429 @endcode
  1430 
  1431 The example above produces the same output as:
  1432 
  1433 @code
  1434 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1435 ...
  1436 fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
  1437 @endcode
  1438 
  1439 Notes:
  1440 
  1441 -# Read-only, hidden and system files can be moved and the source file's
  1442    attributes are preserved in the target file, but open files cannot
  1443    be moved. Attempting to move an open file will return an error for
  1444    that file, as retrieved by CFileBase::GetLastError().
  1445 
  1446 @param anOld	 Path indicating the files to be moved. May be either a full path, or
  1447 				 relative to the session path. Note that if you specify a directory level,
  1448 				 then the behaviour of the move operation is sensitive to the presence
  1449 				 (or absence) of a trailing backslash ("\") character. Any path components
  1450 				 which are not specified here will be taken from the session path. See the
  1451 				 main description for the detailed explanation.
  1452 @param aNew      Path indicating the directory into which the file(s) are to be moved.
  1453 				 Any path components which are not specified here will be taken from the session path.
  1454 @param aSwitches CFileMan::EOverWrite to overwrite files with the same name;
  1455                  CFileMan::ERecurse for recursion.
  1456                  By default, the synchronous variant of this function operates non-recursively and
  1457 				 with overwriting. And no trailing backslash ("\") character at the end of source path
  1458 				 always means CFileMan::ERecurse.
  1459 
  1460 @return KErrNone if successful, otherwise one of the other system-wide error
  1461         codes.
  1462 
  1463 @capability Dependent If the path in aNew starts with /Sys then capability Tcb is required
  1464 @capability Dependent If the path in aNew starts with /Resource then capability Tcb is required
  1465 
  1466 @capability AllFiles
  1467 
  1468 @capability Dependent If the path in anOld starts with /Sys then Tcb capability is required.
  1469 @capability Dependent If the path in anOld starts with /Resource then Tcb capability is required.
  1470 
  1471 @see CFileBase::GetLastError()
  1472 */
  1473 	{
  1474 	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2, MODULEUID,
  1475 		(TUint) this, anOld, aNew, aSwitches);
  1476 
  1477 
  1478 	if (iSwitches&KFManBusyFlag)
  1479 		{
  1480 		TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, KErrInUse);
  1481 		return(KErrInUse);
  1482 		}
  1483 
  1484 	iNumberOfFilesProcessed = 0;
  1485 
  1486 	RETURNIFERRORD(r,iFs.Parse(anOld,iSrcFile),UTraceModuleEfsrv::ECFileManMove2Return);
  1487 	RETURNIFERROR(r,iFs.Parse(aNew,_L("*"),iTrgFile),UTraceModuleEfsrv::ECFileManMove2Return);
  1488 
  1489 	TInt ret = KErrNone;
  1490 	TBool aComplete = EFalse;
  1491 	if(SrcTrgDrivesIdentical())
  1492 		{
  1493 		ret = SetupMoveOnSameDrive(aSwitches, aComplete);
  1494 		}
  1495 	else
  1496 		{
  1497 		ret = SetupMoveAcrossDrives(aSwitches);
  1498 		}
  1499 
  1500 	if(ret != KErrNone || aComplete)
  1501 		{
  1502 		if (iStatus)
  1503 			{
  1504 			User::RequestComplete(iStatus, ret);
  1505 			}
  1506 		TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, ret);
  1507 		return(ret);
  1508 		}
  1509 
  1510 	iMatchEntry = KEntryAttMaskSupported;
  1511 	if((aSwitches&ERecurse)==0 && iMovingContents)
  1512 		{
  1513 		iMatchEntry = KMovingFilesMask;
  1514 		}
  1515 
  1516 	// Do the Move or Rename Operation
  1517 	TRAP(r,RunL());
  1518 	ret = (r==KErrNone) ? iLastError : r;
  1519 	DoSynchronize(r);
  1520 
  1521 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, ret);
  1522 	return(ret);
  1523 	}
  1524 
  1525 
  1526 TBool CFileMan::SrcTrgDrivesIdentical()
  1527 //
  1528 // Returns ETrue if the source and target drives are the same
  1529 //	- Used by CFileMan::Move operations to determine whether to rename or move the files
  1530 //
  1531 	{
  1532 	return iSrcFile.Drive().MatchF(iTrgFile.Drive()) != KErrNotFound;
  1533 	}
  1534 
  1535 
  1536 TInt CFileMan::SetupDirectoryForMove(TBool& aSrcIsDir)
  1537 /**
  1538  * Sets up the target specification to include the new target directory if required.
  1539  * 
  1540  * @param aSrcIsDir	Set to ETrue if the source specifies that the directory is to be moved in its entirety,
  1541  * 					or EFalse if only the contents of the directory need to be moved.
  1542  * 
  1543  * @return KErrNone if successful, otherwise one of the system wide error codes.
  1544  */
  1545 	{
  1546 	iMovingContents = ETrue;
  1547 	aSrcIsDir = EFalse;
  1548 	
  1549 	TPtrC nameAndExt(iSrcFile.NameAndExt());
  1550 	if (nameAndExt == _L("*") || nameAndExt == _L("*.*"))
  1551 		{
  1552 		// Wildcard specification - Move the entire contents of the directory to the target
  1553 		aSrcIsDir = ETrue;
  1554 		}
  1555 	else
  1556 		{
  1557 		TInt src = iFs.Entry(iSrcFile.FullName(), iTmpEntry);
  1558 		if ((src == KErrNone && iTmpEntry.iAtt&KEntryAttDir) || (!iSrcFile.NamePresent() && iSrcFile.IsRoot()))
  1559 			{
  1560 			aSrcIsDir = ETrue;
  1561 
  1562 			// A directory is specified.
  1563 			//  - Mandatory recursion with Wildcard Copy
  1564 			//	- Target is a directory (Enforced by MakeParseWild)
  1565 
  1566 			MakeParseWild(iTrgFile, iTmpName1);
  1567 
  1568 			// Construct the target name by parsing
  1569 			// the source path for the directory name.
  1570 			TPtrC srcPath(iSrcFile.FullName());
  1571 			TInt srcPathLen = srcPath.Length() - 1;
  1572 
  1573 			iMovingContents = (srcPath[srcPathLen] == KPathDelimiter);	// Moving the directory itself, or the contents?
  1574 
  1575 			if(!iMovingContents)
  1576 				{
  1577 				// No path delimiter specified
  1578 				//	- move the whole directory (if specified)
  1579 				TInt len = srcPath.Length();
  1580 
  1581 				TInt idx = srcPath.Left(len).LocateReverse(KPathDelimiter);
  1582 
  1583 				if((idx >= 2) && (idx != KErrNotFound))
  1584 					{
  1585 					// Source path is a directory (not just the drive)
  1586 					TPtrC mid(srcPath.Left(len).Mid(1+idx));
  1587 					TInt r = iTrgFile.AddDir(mid);
  1588 					if (r != KErrNone)
  1589 						return r;
  1590 					}
  1591 				}
  1592 			}
  1593 		}
  1594 
  1595 	return KErrNone;
  1596 	}
  1597 
  1598 
  1599 TInt CFileMan::SetupTargetDirectory(TBool aOverWrite, TBool& aComplete)
  1600 	{
  1601 	aComplete = EFalse;
  1602 
  1603 	TInt trgErr = iFs.Entry(iTrgFile.DriveAndPath(), iTmpEntry);
  1604 
  1605 	TEntry srcEntry;
  1606 	TInt srcErr = iFs.Entry(iSrcFile.FullName(), srcEntry);
  1607 
  1608 	if(srcErr == KErrNone && trgErr == KErrNone)
  1609 		{
  1610         if ((srcEntry.iAtt&KEntryAttDir) != (iTmpEntry.iAtt&KEntryAttDir))
  1611         	{
  1612         	// return KErrAccessDenied if it is trying to overwrite a file to a dir or vice versa.
  1613         	return KErrAccessDenied;
  1614         	}
  1615 		}
  1616 
  1617 	if(trgErr == KErrNone)
  1618 		{
  1619 		// Already Exists - Overwrite if flags set
  1620 		if(!aOverWrite)
  1621 			{
  1622 			trgErr = KErrAlreadyExists;
  1623 			}
  1624 		else
  1625 			{
  1626 			iNumberOfFilesProcessed++;
  1627 			}
  1628 		}
  1629 	else if((trgErr == KErrNotFound) || (trgErr == KErrPathNotFound))
  1630 		{
  1631 		if(SrcTrgDrivesIdentical())
  1632 			{
  1633 			// When moving a directory on the same drive, the directory can simply be renamed...
  1634 			TParse& midDir = iTmpParse;
  1635 			midDir = iTrgFile;
  1636 			if(midDir.PopDir() == KErrNone)
  1637 				{
  1638 				// ...before renaming, ensure that all intermediate directories exist
  1639 				trgErr = iFs.MkDirAll(midDir.DriveAndPath());
  1640 				if(trgErr == KErrAlreadyExists)
  1641 					{
  1642 					trgErr = KErrNone;
  1643 					}
  1644 				}
  1645 
  1646 			if (trgErr == KErrNone)
  1647 				{
  1648 				// ...and finally rename the source directory
  1649 				trgErr = iFs.Rename(iSrcFile.FullName(),iTrgFile.DriveAndPath());
  1650 				aComplete = ETrue;
  1651 				}
  1652 			}
  1653 		else
  1654 			{
  1655 			trgErr = iFs.MkDirAll(iTrgFile.FullName());
  1656 			}
  1657 		iNumberOfFilesProcessed++;
  1658 		}
  1659 
  1660 	return(trgErr);
  1661 	}
  1662 
  1663 
  1664 TInt CFileMan::SetupMoveOnSameDrive(TUint aSwitches, TBool& aComplete)
  1665 	{
  1666 	// Moving on the same drive.
  1667 
  1668 	aComplete = EFalse;
  1669 
  1670 	TBool srcIsDir = EFalse;
  1671     TInt ret = SetupDirectoryForMove(srcIsDir);
  1672     if (ret != KErrNone)
  1673 		{
  1674         return ret;
  1675 		}
  1676 
  1677 	TBool scanDown = ETrue;
  1678 	TBool recurse = (aSwitches & ERecurse);
  1679 
  1680 	iAction = EInternalRenameForMove;
  1681 
  1682 	TFileName& srcpath = iTmpName1;
  1683 	srcpath.Copy(iSrcFile.FullName());
  1684 	if(srcpath.Length()<KMaxFileName && srcpath.Length()>1 && srcpath[srcpath.Length()-1]!=KPathDelimiter)
  1685 		{
  1686 		srcpath.Append(KPathDelimiter);
  1687 		}
  1688 
  1689 	// If the source path is a subset of the target path then Move operation is not allowed
  1690 	if((srcIsDir && recurse) || (srcIsDir && !iTrgFile.IsRoot() && !iMovingContents))
  1691 		{
  1692 		if(iTrgFile.FullName().Left(srcpath.Length()).MatchF(srcpath)==0)
  1693 			{
  1694 			aComplete = ETrue;
  1695 			return KErrInUse;
  1696 			}
  1697 		}
  1698 	// if any of the SRC folders already existing in TRG, scan upwards
  1699 	if(iMovingContents)
  1700 		{
  1701 		CDirScan* srcScanDir = NULL;
  1702 		CDirScan* trgScanDir = NULL;
  1703 		CDir* srcEntryList = NULL;
  1704 		CDir* trgEntryList = NULL;
  1705 		TInt trgCnt = 0;
  1706 		TInt srcCnt = 0;
  1707 
  1708 		TRAP(ret,(srcScanDir = CDirScan::NewL(iFs)));
  1709 		if (ret!=KErrNone)
  1710 			{
  1711 			goto CleanUp;
  1712 			}
  1713 		TRAP(ret,srcScanDir->SetScanDataL(iSrcFile.FullName(),KEntryAttMaskSupported,ESortByName));
  1714 		if (ret!=KErrNone)
  1715 			{
  1716 			goto CleanUp;
  1717 			}
  1718 		TRAP(ret,srcScanDir->NextL(srcEntryList));
  1719 		if(ret!=KErrNone)
  1720 			{
  1721 			goto CleanUp;
  1722 			}
  1723 		TRAP(ret,(trgScanDir=CDirScan::NewL(iFs)));
  1724 		if (ret!=KErrNone)
  1725 			{
  1726 			goto CleanUp;
  1727 			}
  1728 		TRAP(ret,trgScanDir->SetScanDataL(iTrgFile.FullName(),KEntryAttMaskSupported,ESortByName));
  1729 		if (ret!=KErrNone)
  1730 			{
  1731 			goto CleanUp;
  1732 			}
  1733 		TRAP(ret,trgScanDir->NextL(trgEntryList));
  1734 		if(ret!=KErrNone)
  1735 			{
  1736 			goto CleanUp;
  1737 			}
  1738 		for(trgCnt=trgEntryList->Count()-1; trgCnt>-1; trgCnt--)
  1739 			{
  1740 			for(srcCnt=srcEntryList->Count()-1; srcCnt>-1; srcCnt--)
  1741 				{
  1742 				if( (*srcEntryList)[srcCnt].iName == (*trgEntryList)[trgCnt].iName
  1743 					&& ((*srcEntryList)[srcCnt].iAtt & KEntryAttDir)
  1744 					&& ((*trgEntryList)[trgCnt].iAtt & KEntryAttDir))
  1745 					{
  1746 					// Set scan upwards
  1747 					scanDown = EFalse;
  1748 					goto CleanUp;
  1749 					}
  1750 				}// end inner for loop
  1751 			} // end outer for loop
  1752 CleanUp:
  1753 		// clean up
  1754 		if(srcEntryList!=NULL)
  1755 			delete srcEntryList;
  1756 		if(trgEntryList!=NULL)
  1757 			delete trgEntryList;
  1758 		if(srcScanDir!=NULL)
  1759 			delete srcScanDir;
  1760 		if(trgScanDir!=NULL)
  1761 			delete trgScanDir;
  1762 		}// end if(iMovingContents)
  1763 
  1764 	if(srcIsDir && !iTrgFile.IsRoot() && !iMovingContents)
  1765 		{
  1766 		ret = SetupTargetDirectory(aSwitches & EOverWrite, aComplete);
  1767 		if(ret != KErrNone || aComplete)
  1768 			{
  1769 			return(ret);
  1770 			}
  1771 		}
  1772 	if(!iMovingContents)
  1773 		{
  1774 		recurse = ETrue;
  1775 		scanDown = EFalse;
  1776 		}
  1777 	if(srcIsDir)
  1778 		{
  1779 		MakeParseWild(iSrcFile, iTmpName1);
  1780 		}
  1781 
  1782 	SetFlags(aSwitches & EOverWrite, recurse, scanDown, ETrue);
  1783 	return(KErrNone);
  1784 	}
  1785 
  1786 
  1787 TInt CFileMan::SetupMoveAcrossDrives(TUint aSwitches)
  1788 	{
  1789 	// Moving across drives.  We may need to recurse,
  1790 	// depending on the supplied source path.
  1791 
  1792 	TBool srcIsDir = EFalse;
  1793     TInt ret = SetupDirectoryForMove(srcIsDir);
  1794     if (ret != KErrNone)
  1795 		{
  1796         return ret;
  1797 		}
  1798     
  1799 	TBool recurse = (aSwitches & ERecurse);
  1800 	TBool scanDown = (recurse) ? (TBool)EFalse : (TBool)ETrue;
  1801 
  1802 	if(srcIsDir)
  1803 		{
  1804 		if(!iMovingContents)
  1805 			{
  1806 			recurse = ETrue;
  1807 			if(!iTrgFile.IsRoot())
  1808 				{
  1809 				TBool complete = EFalse;
  1810 				ret = SetupTargetDirectory(aSwitches & EOverWrite, complete);
  1811 				if(ret != KErrNone || complete)
  1812 					{
  1813 					return(ret);
  1814 					}
  1815 				}
  1816 			}
  1817 		}
  1818 
  1819 	CheckForDirectory();
  1820 	iAction = EInternalCopyForMove;
  1821 	SetFlags(aSwitches & EOverWrite, recurse, scanDown, EFalse);
  1822 	return(KErrNone);
  1823 	}
  1824 
  1825 TInt CFileMan::RenameInvalidEntry(const TDesC& /*aName*/,const TDesC& /*aNewName*/,TUint /*aSwitches*/)
  1826 //
  1827 // Start rename operation
  1828 //
  1829 	{
  1830 	return KErrNotSupported;
  1831 	}
  1832 
  1833 
  1834 
  1835 
  1836 EXPORT_C TInt CFileMan::Rename(const TDesC& aName,const TDesC& aNewName,TUint aSwitches,TRequestStatus& aStatus)
  1837 /**
  1838 Renames one or more files.
  1839 
  1840 This is an asynchronous function.
  1841 Its behaviour is the same as the synchronous overload.
  1842 
  1843 @param aName     Path specifying the file(s) to be renamed. Any path components
  1844 				 which are not specified
  1845                  here will be taken from the session path.
  1846 @param aNewName  Path specifying the new name for the files and/or
  1847                  the new directory. Any directories specified in this path
  1848                  that do not exist, will be created. Any path components
  1849 				 which are not specified here will be taken from the session path.
  1850 @param aSwitches Specify zero for no overwriting;
  1851                  CFileMan::EOverWrite to overwrite files with the same name.
  1852                  This function cannot operate recursively.
  1853 @param aStatus   The request status object. On request completion,
  1854                  indicates how the request completed:
  1855                  KErrNone, if successful, otherwise one of the other system-wide error
  1856                  codes.
  1857 
  1858 @return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  1859 					is still pending; otherwise one of the other system-wide error codes
  1860 
  1861 @capability Dependent If either aName or aNewName is /Sys then Tcb capability is required.
  1862 @capability Dependent If either aName or aNewName begins with /Private and does not match
  1863 					  this process' SID then AllFiles capability is required.
  1864 @capability Dependent If either aName or aNewName is /Resource then Tcb capability is required.
  1865 
  1866 */
  1867 	{
  1868 	TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename1, MODULEUID,
  1869 		(TUint) this, aName, aNewName, aSwitches, (TUint) &aStatus);
  1870 
  1871 	TInt r;
  1872 	if (iSwitches&KFManBusyFlag)
  1873 		{
  1874 		r = KErrInUse;
  1875 		}
  1876 	else
  1877 		{
  1878 		iStatus=&aStatus;
  1879 		r = Rename(aName,aNewName,aSwitches);
  1880 		}
  1881 
  1882 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename1Return, MODULEUID, r);
  1883 	return(r);
  1884 	}
  1885 
  1886 
  1887 
  1888 
  1889 EXPORT_C TInt CFileMan::Rename(const TDesC& aName,const TDesC& aNewName,TUint aSwitches)
  1890 /**
  1891 Renames one or more files, or a directory
  1892 
  1893 This is a synchronous function.
  1894 
  1895 The function can also be used to move files by specifying different destination
  1896 and source directories.
  1897 
  1898 Some rules for using CFileMan::Rename():
  1899 
  1900 1. General rules:
  1901 
  1902 1.1. Trailing backslash ("\") in either source path (aName) or target path (aNewName)
  1903 will be interpreted to "\*.*";
  1904 
  1905 For example, following code should behave identically:
  1906 @code
  1907 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1908 ...
  1909 fm->Rename(_L("C:\\SRC\\"), _L("C:\\TRG\\"));
  1910 fm->Rename(_L("C:\\SRC\\*.*"), _L("C:\\TRG\\"));
  1911 fm->Rename(_L("C:\\SRC\\"), _L("C:\\TRG\\*.*"));
  1912 fm->Rename(_L("C:\\SRC\\*.*"), _L("C:\\TRG\\*.*"));
  1913 @endcode
  1914 
  1915 1.2 The behaviour of the rename operation is sensitive to the presence (or absence) of
  1916 a trailing backslash ("\") character on the end of the target path (aNewName);
  1917 
  1918 For example, under all other constraints (see rules 2. and 3.),
  1919 @code
  1920 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1921 ...
  1922 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\"));
  1923 @endcode
  1924 will result in renaming "C:\\SRC" to "C:\\TRG\\SRC", while
  1925 @code
  1926 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1927 ...
  1928 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG"));
  1929 @endcode
  1930 will result in renaming "C:\\SRC" to "C:\\TRG".
  1931 
  1932 2. Renaming file(s):
  1933 
  1934 2.1 Wildcards:
  1935 
  1936 A file's name and extension are interpreted separately, for example:
  1937 
  1938 @code
  1939 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1940 ...
  1941 fm->Rename(_L("C:\\SRC\\1234.567"), _L("C:\\TRG\\AB*CD.TXT"));
  1942 @endcode
  1943 renames the source file to file "C:\\TRG\\AB34CD.TXT".
  1944 
  1945 Wildcards can be used for renaming multiple files, for example;
  1946 @code
  1947 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1948 ...
  1949 fm->Rename(_L("C:\\SRC\\*.567"), _L("C:\\TRG\\*.TXT"));
  1950 @endcode
  1951 renames all the file under "C:\\SRC\\" having extension ".567" to the files under
  1952 "C:\\TRG\\" having extension ".TXT".
  1953 
  1954 2.2 An option is provided to allow the user to overwrite any files with the same
  1955 name which may exist in the target directory; If the flag is set for no overwriting,
  1956 any files with the same name will not be overwritten, and an error (KErrAlreadyExists)
  1957 will be returned for that file, as retrieved by CFileBase::GetLastError().
  1958 
  1959 2.3 It can only operate non-recursively, so that only the matching files located
  1960 in the single directory specified by anOld may be renamed.
  1961 
  1962 2.4 Trying to rename file(s) to existing directory(ies) will fail;
  1963 
  1964 For example, giving following directory structure:
  1965 @code
  1966 C:\SRC\ITEM01
  1967 C:\SRC\ITEM02
  1968 C:\TRG\ITEM01\
  1969 C:\TRG\ITEM02\
  1970 @endcode
  1971 
  1972 Following code will fail:
  1973 @code
  1974 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1975 ...
  1976 fm->Rename(_L("C:\\SRC\\ITEM01"), _L("C:\\TRG\\ITEM01"));
  1977 fm->Rename(_L("C:\\SRC\\ITEM*"), _L("C:\\TRG\\ITEM*"));
  1978 fm->Rename(_L("C:\\SRC\\"), _L("C:\\TRG\\"));
  1979 @endcode
  1980 
  1981 3. When renamnig a directory:
  1982 
  1983 3.1. Only when the trailing backslash ("\") is missing from the source path (aName),
  1984 will the source directory be renamed, otherwise, see rule 1.1.
  1985 
  1986 For example, following code will result in moving "C:\SRC" directory including all
  1987 its contents:
  1988 @code
  1989 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  1990 ...
  1991 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG"));
  1992 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\\"));
  1993 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\\*.*"));
  1994 @endcode
  1995 
  1996 3.2. Wildcards can not be used for moving directories;
  1997 
  1998 3.3. Overwriting is not permitted;
  1999 
  2000 For example, giving directory structure as following:
  2001 @code
  2002 C:\SRC\FILE.TXT
  2003 C:\TRG\
  2004 C:\TRG\SRC\
  2005 @endcode
  2006 
  2007 following code will fail:
  2008 @code
  2009 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
  2010 ...
  2011 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG"));
  2012 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\\"));
  2013 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\\*.*"));
  2014 @endcode
  2015 
  2016 4. Notes:
  2017 
  2018 4.1. The target and source directories must be on the same drive.
  2019 
  2020 4.2. Read-only, hidden and system files can be moved and the source file's
  2021 attributes are preserved in the target file, but open files cannot
  2022 be moved. Attempting to move an open file will return an error for
  2023 that file, as retrieved by CFileBase::GetLastError().
  2024 
  2025 @param aName     Path specifying the file(s) to be renamed. Any path components
  2026 				 which are not specified
  2027                  here will be taken from the session path.
  2028 @param aNewName  Path specifying the new name for the files and/or
  2029                  the new directory. Any directories specified in this path
  2030                  that do not exist, will be created. Any path components which
  2031 				 are not specified here will be taken from the session path.
  2032 @param aSwitches Specify zero for no overwriting;
  2033                  CFileMan::EOverWrite to overwrite files with the same name.
  2034                  This function cannot operate recursively.
  2035 
  2036 @return KErrNone if successful, otherwise one of the other system-wide error
  2037         codes.
  2038 
  2039 @see CFileBase::GetLastError()
  2040 
  2041 @capability Dependent If either aName or aNewName is /Sys then Tcb capability is required.
  2042 @capability Dependent If either aName or aNewName begins with /Private and does not match
  2043 					  this process' SID then AllFiles capability is required.
  2044 @capability Dependent If either aName or aNewName is /Resource then Tcb capability is required.
  2045 
  2046 */
  2047 	{
  2048 	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename2, MODULEUID,
  2049 		(TUint) this, aName, aNewName, aSwitches);
  2050 
  2051 	TInt ret;
  2052 	if (iSwitches&KFManBusyFlag)
  2053 		{
  2054 		ret = KErrInUse;
  2055 		}
  2056 	else
  2057 		{
  2058 		SetFlags(aSwitches&EOverWrite,EFalse,ETrue,EFalse);
  2059 		RETURNIFERRORD(r,iFs.Parse(aName,iSrcFile),UTraceModuleEfsrv::ECFileManRename2Return);
  2060 		RETURNIFERROR(r,iFs.Parse(aNewName,_L("*"),iTrgFile),UTraceModuleEfsrv::ECFileManRename2Return);
  2061 
  2062 		iAction = EInternalRename;
  2063 		iMatchEntry=KEntryAttMaskSupported;
  2064 		iNumberOfFilesProcessed = 0;
  2065 		TRAP(r,RunL());
  2066 		ret=(r==KErrNone) ? iLastError : r;
  2067 		DoSynchronize(r);
  2068 		}
  2069 
  2070 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename2Return, MODULEUID, ret);
  2071 	return(ret);
  2072 	}
  2073 
  2074 
  2075 EXPORT_C TInt CFileMan::RmDir(const TDesC& aDirName,TRequestStatus& aStatus)
  2076 /**
  2077 Deletes a directory and all files and directories contained in the
  2078 directory structure below it.
  2079 
  2080 Other than being asynchronous, the behaviour of this function is the same
  2081 as is documented in its synchronous overload.
  2082 
  2083 @param aDirName Path specifying the directory to be deleted. Any path components
  2084 				which are not specified here will be taken from the session path.
  2085 @param aStatus  The request status object. On request completion, indicates how
  2086                 the request completed:
  2087                 KErrNone if successful, otherwise one of the other system-wide
  2088                 error codes.
  2089 
  2090 @return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  2091 					is still pending; otherwise one of the other system-wide error codes
  2092 
  2093 @capability Dependent If aDirName starts with /Sys then Tcb capability is required.
  2094 @capability Dependent If aDirName begins with /Private and does not match this process' SID
  2095 					  then AllFiles capability is required.
  2096 @capability Dependent If aDirName starts with /Resource then Tcb capability is required.
  2097 
  2098 */
  2099 	{
  2100 	TRACEMULT3(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir1, MODULEUID, (TUint) this, aDirName, (TUint) &aStatus);
  2101 
  2102 	TInt r;
  2103 	if (iSwitches&KFManBusyFlag)
  2104 		{
  2105 		r = KErrInUse;
  2106 		}
  2107 	else
  2108 		{
  2109 		iStatus=&aStatus;
  2110 		r = RmDir(aDirName);
  2111 		}
  2112 
  2113 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir1Return, MODULEUID, r);
  2114 	return r;
  2115 	}
  2116 
  2117 
  2118 EXPORT_C TInt CFileMan::RmDir(const TDesC& aDirName)
  2119 /**
  2120 Deletes a directory and all files and directories contained in the
  2121 directory structure below it.
  2122 
  2123 This is a synchronous function.
  2124 
  2125 The function cannot be used non-recursively. For a non-recursive
  2126 directory deletion, use RFs::RmDir().
  2127 
  2128 Note:
  2129 
  2130 1. All files in the directory hierarchy to be deleted must be closed and
  2131    none may have the read-only attribute. Otherwise, not all of the hierarchy will
  2132    be deleted, and this function will return KErrInUse.
  2133 
  2134 @param aDirName Path specifying the directory to be deleted. Any path components
  2135 				which are not specified here will be taken from the session path.
  2136 
  2137 @return KErrNone if successful, otherwise one of the other system-wide error
  2138         codes.
  2139 
  2140 @capability Dependent If aDirName starts with /Sys then Tcb capability is required.
  2141 @capability Dependent If aDirName begins with /Private and does not match this process' SID
  2142 					  then AllFiles capability is required.
  2143 @capability Dependent If aDirName starts with /Resource then Tcb capability is required.
  2144 
  2145 
  2146 */
  2147 	{
  2148 	TRACEMULT2(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir2, MODULEUID, (TUint) this, aDirName);
  2149 
  2150 	TInt ret;
  2151 	if (iSwitches&KFManBusyFlag)
  2152 		{
  2153 		ret = KErrInUse;
  2154 		}
  2155 	else
  2156 		{
  2157 		SetFlags(ETrue,ETrue,EFalse,EFalse);
  2158 		RETURNIFERRORD(r,iFs.Parse(aDirName,iTrgFile),UTraceModuleEfsrv::ECFileManRmDir2Return);
  2159 		iSrcFile.Set(iTrgFile.DriveAndPath(),NULL,NULL);
  2160 		iAction = EInternalRmDir;
  2161 		iMatchEntry=KEntryAttMaskSupported;
  2162 		iNumberOfFilesProcessed = 0;
  2163 		TRAP(r,RunL());
  2164 		DoSynchronize(r);
  2165 		ret = (r!=KErrNone) ? iLastError : KErrNone;
  2166 		}
  2167 
  2168 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir2Return, MODULEUID, ret);
  2169 	return ret;
  2170 	}
  2171 
  2172 
  2173 void CFileMan::DoOperationL()
  2174 // Call the action in progress.
  2175 	{
  2176 	switch (iAction)
  2177 		{
  2178 	case EInternalAttribs:
  2179 		DoAttribsL();
  2180 		break;
  2181 	case EInternalCopy:
  2182 	case EInternalCopyForMove:
  2183 		DoCopyOrMoveL();
  2184 		break;
  2185 	case EInternalDelete:
  2186 		DoDeleteL();
  2187 		break;
  2188 	case EInternalRenameInvalidEntry:
  2189 	case EInternalRenameForMove:
  2190 	case EInternalRename:
  2191 		DoRenameL();
  2192 		break;
  2193 	case EInternalRmDir:
  2194 		DoRmDirL();
  2195 		break;
  2196 	case EInternalCopyFromHandle:
  2197 		DoCopyFromHandleL();
  2198 		break;
  2199 	default:
  2200 		Panic(EFManUnknownAction);
  2201 		}
  2202 	}
  2203 
  2204 void CFileMan::DoAttribsL()
  2205 //
  2206 // Do attribs operation step
  2207 //
  2208 	{
  2209 	TPtrC fullPath(FullPath());
  2210 	iTmpParse.Set(CurrentEntry().iName, &fullPath, NULL);
  2211 	User::LeaveIfError(iFs.SetEntry(iTmpParse.FullName(), iTime, iSetMask, iClearMask));
  2212 	}
  2213 
  2214 void CFileMan::DoCopyOrMoveL()
  2215 //
  2216 // Do copy or move operation
  2217 //
  2218 	{
  2219 	// Following 'if' statements are to prevent incorrect recursive Move() or Copy() from "destination"
  2220 	//  to "destination", this problem occurs when the initial source directory contains destination
  2221 	//  directory.
  2222 	//  (e.g. CFileMan::Move(_L("C:\\SRC\\*.TXT"), _L("C:\\SRC\\Sub\\"), CFileMan::ERecurse);)
  2223 	// Note that CFileMan::Rename() does not suffer from this particular case, as CFileMan::Rename() API
  2224 	//  can only operate non-recursively.
  2225 	if (iSrcFile.DriveAndPath().Length() < iTrgFile.DriveAndPath().Length())
  2226 		{
  2227 		if (iTrgFile.DriveAndPath().Left(iSrcFile.DriveAndPath().Length()) == iSrcFile.DriveAndPath())
  2228 		// If source directory path contains destination directory path, including drive number, we consider
  2229 		//  this is "...\\ROOT\\" -> "...\\ROOT\\SUB\\" type of operation. Therefore skips all the items we
  2230 		//  found in "...\\ROOT\\SUB\\". We achieve this by checking current scanning directory path:
  2231 			{
  2232 			if (iTrgFile.DriveAndPath() == iScanner->FullPath().Left(iTrgFile.DriveAndPath().Length()))
  2233 				{
  2234 				return;
  2235 				}
  2236 			}
  2237 		}
  2238 
  2239 	TParse& srcName = iTmpParse;
  2240 	TFileName& trgName = iTmpName1;
  2241 	GetSrcAndTrg(srcName,trgName);
  2242 
  2243 	// Handle case when source is directory
  2244 	if (CurrentEntry().iAtt&KEntryAttDir)
  2245 		{
  2246 		if(!(iSwitches&KRecurseFlag))
  2247 			{
  2248 			User::Leave(KErrNone);
  2249 			}
  2250 		trgName.Append(KPathDelimiter);
  2251 		TInt r = iFs.MkDirAll(trgName);
  2252 		if (r!=KErrNone && r!=KErrAlreadyExists)
  2253 			User::Leave(r);
  2254 
  2255 		if(iAction == EInternalCopyForMove)
  2256 			{
  2257 			// Move operation - Attempt to delete the source directory.
  2258 			if((iMatchEntry & KMovingFilesMask) != KMovingFilesMask)
  2259 				{
  2260 				iTmpName2 = srcName.FullName();
  2261 				iTmpName2.Append(KPathDelimiter);
  2262 				TInt rdErr = iFs.RmDir(iTmpName2);
  2263 				if(rdErr != KErrNone && rdErr != KErrInUse)
  2264 					{
  2265 					User::Leave(rdErr);
  2266 					}
  2267 				}
  2268 			}
  2269 		return;
  2270 		}
  2271 
  2272 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  2273 	RFile srcFile,trgFile;
  2274 #else
  2275 	RFile64 srcFile,trgFile;
  2276 #endif
  2277 	TInt r=KErrNone;
  2278 	if (FileNamesIdentical(srcName.FullName(),trgName))
  2279 		{
  2280 		if (iSwitches & KOverWriteFlag)
  2281 			// Source and target are identical, KOverWriteFlag makes copying
  2282 			// having no effect.
  2283 			return;
  2284 		else
  2285 			User::Leave(KErrAlreadyExists);
  2286 		}
  2287 
  2288 	r=srcFile.Open(iFs, srcName.FullName(),
  2289 	                iAction==EInternalCopy ? EFileRead|EFileShareReadersOnly  // Copy access
  2290 	                                : EFileWrite|EFileWriteDirectIO|EFileShareExclusive); // Move access
  2291 	TBool isRO = EFalse;
  2292 	if(r==KErrAccessDenied && iAction==EInternalCopyForMove)
  2293 		{
  2294 		TEntry& entry = iTmpEntry;
  2295 		r = iFs.Entry(srcName.FullName(), entry);
  2296 		if(r==KErrNone && (entry.iAtt&KEntryAttReadOnly))
  2297 			{
  2298 			isRO = ETrue;
  2299 			r = iFs.SetAtt(srcName.FullName(), 0, KEntryAttReadOnly);
  2300 			if(r==KErrNone)
  2301 				{
  2302 				r = srcFile.Open(iFs, srcName.FullName(), EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  2303 				}
  2304 			}
  2305 		}
  2306 	if (r!=KErrNone)
  2307 		{
  2308 		iErrorInfo=ESrcOpenFailed;
  2309 		if(isRO)
  2310 			{
  2311 			iFs.SetAtt(srcName.FullName(), KEntryAttReadOnly, 0);
  2312 			}
  2313 		User::Leave(r);
  2314 		}
  2315 
  2316 	if ((iSwitches&KOverWriteFlag)==0)
  2317 		r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  2318 	else
  2319 		r=trgFile.Replace(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  2320 
  2321 	if (r==KErrPathNotFound && (iSwitches&KRecurseFlag))
  2322 		{
  2323 		r=iFs.MkDirAll(trgName);
  2324 		if (r==KErrNone)
  2325 			r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  2326 		}
  2327 
  2328 	if (r!=KErrNone)
  2329 		iErrorInfo=ETrgOpenFailed;
  2330 
  2331 	TInt ret=0;
  2332 	if (r == KErrNone)
  2333 		r = DoCopy(srcFile, trgFile, ret);
  2334 
  2335 	srcFile.Close();
  2336 	trgFile.Close();
  2337 	if ((r!=KErrNone && (r!=KErrAlreadyExists && iErrorInfo!=ETrgOpenFailed)) || (ret==MFileManObserver::ECancel))
  2338 		iFs.Delete(trgName);
  2339 	if(r==KErrNone && isRO)
  2340 		{
  2341 		r = iFs.SetAtt(trgName, KEntryAttReadOnly, 0);
  2342 		}
  2343 	User::LeaveIfError(r);
  2344 
  2345 	//
  2346 	// Move operation
  2347 	//
  2348 	if (iAction == EInternalCopyForMove && ret != MFileManObserver::ECancel)
  2349 		{
  2350 		r=iFs.Delete(srcName.FullName());
  2351 		if (r==KErrNone)
  2352 			return;
  2353 		iFs.Delete(trgName);
  2354 		User::Leave(r);
  2355 		}
  2356 	}
  2357 
  2358 void CFileMan::DoDeleteL()
  2359 //
  2360 // Do delete operation step
  2361 //
  2362 	{
  2363 	TFileName& pathname = iTmpName1;
  2364 	TFileName& filename = iTmpName2;
  2365 	pathname.Copy(FullPath());
  2366 	filename.Copy(CurrentEntry().iName);
  2367 	if(CurrentEntry().iName.Length() + pathname.Length() > KMaxFileName)
  2368 		{
  2369 		User::LeaveIfError(ShrinkNames(iFs, pathname, filename, EFalse));
  2370 		}
  2371 	iTmpParse.Set(filename, &pathname, NULL);
  2372 	User::LeaveIfError(iFs.Delete(iTmpParse.FullName()));
  2373 	}
  2374 
  2375 void CFileMan::DoRenameL()
  2376 //
  2377 // Do rename operation step
  2378 //
  2379 	{
  2380 	// Following 'if' statements are to prevent incorrect recursive Move() or Copy() from "destination"
  2381 	//  to "destination", this problem occurs when the initial source directory contains destination
  2382 	//  directory.
  2383 	//  (e.g. CFileMan::Move(_L("C:\\SRC\\*.TXT"), _L("C:\\SRC\\Sub\\"), CFileMan::ERecurse);)
  2384 	// Note that CFileMan::Rename() does not suffer from this particular case, as CFileMan::Rename() API
  2385 	//  can only operate non-recursively.
  2386 	if (iSrcFile.DriveAndPath().Length() < iTrgFile.DriveAndPath().Length())
  2387 		{
  2388 		if (iTrgFile.DriveAndPath().Left(iSrcFile.DriveAndPath().Length()) == iSrcFile.DriveAndPath())
  2389 		// If source directory path contains destination directory path, including drive number, we consider
  2390 		//  this is "...\\ROOT\\" -> "...\\ROOT\\SUB\\" type of operation. Therefore skips all the items we
  2391 		//  found in "...\\ROOT\\SUB\\". We achieve this by checking current scanning directory path:
  2392 			{
  2393 			if (iTrgFile.DriveAndPath() == iScanner->FullPath().Left(iTrgFile.DriveAndPath().Length()))
  2394 				{
  2395 				return;
  2396 				}
  2397 			}
  2398 		}
  2399 
  2400 	TParse& srcName = iTmpParse;
  2401 	TFileName& trgName = iTmpName1;
  2402 	GetSrcAndTrg(srcName, trgName);
  2403 
  2404 	TInt r = iFs.Rename(srcName.FullName(),trgName);
  2405 	if (r==KErrAlreadyExists && (iSwitches&KOverWriteFlag)!=0)
  2406 		{
  2407 		// Target already exists, with the overwrite flag enabled
  2408 		if((CurrentEntry().iAtt & KEntryAttDir) == 0)
  2409 			{
  2410 			// Renaming a file
  2411 			r=iFs.Replace(srcName.FullName(),trgName);
  2412 			}
  2413 		else if (iAction == EInternalRenameForMove)
  2414 			{
  2415 			trgName = srcName.FullName();
  2416 			trgName.Append(KPathDelimiter);
  2417 			r = iFs.RmDir(trgName); // remove empty directory after move
  2418 			if(r == KErrInUse)
  2419 				{
  2420 				r = KErrNone;
  2421 				}
  2422 			}
  2423 		}
  2424 
  2425 	if (r==KErrPathNotFound)
  2426 		{
  2427 		if((iSwitches&KMoveRenameFlag) && !(iSwitches&KRecurseFlag))
  2428 			User::Leave(r);
  2429 		r=iFs.MkDirAll(trgName);
  2430 		if (r==KErrNone)
  2431 			 r=iFs.Rename(srcName.FullName(),trgName);
  2432 		}
  2433 	if (r==KErrBadName)
  2434 		{
  2435 		TEntry& entry = iTmpEntry;
  2436 		TInt retcode=iFs.Entry(srcName.FullName(), entry);
  2437 		if (retcode!=KErrNone)
  2438 			iErrorInfo=ESrcOpenFailed;
  2439 		else
  2440 			iErrorInfo=ETrgOpenFailed;
  2441 		}
  2442 	User::LeaveIfError(r);
  2443 	}
  2444 
  2445 void CFileMan::DoRmDirL()
  2446 //
  2447 // Do rmdir operation step
  2448 //
  2449 	{
  2450 	TFileName& srcName = iTmpName1;
  2451 	srcName.Copy(FullPath());
  2452 	if (srcName.Length() + CurrentEntry().iName.Length() > KMaxFileName)
  2453 		{
  2454 		TFileName& current = iTmpName2;
  2455 		current.Copy(CurrentEntry().iName);
  2456 		User::LeaveIfError(ShrinkNames(iFs, srcName, current, ETrue));
  2457 		}
  2458 	else
  2459 		{
  2460 		srcName.Append(CurrentEntry().iName);
  2461 		}
  2462 
  2463 	if ((CurrentEntry().iAtt&KEntryAttDir)==0)
  2464 		User::LeaveIfError(iFs.Delete(srcName));
  2465 	else
  2466 		{
  2467 		srcName.Append(KPathDelimiter);
  2468 		User::LeaveIfError(iFs.RmDir(srcName));
  2469 		}
  2470 	}
  2471 
  2472 
  2473 void CFileMan::CompleteOperationL()
  2474 //
  2475 // Tidy up after an operation
  2476 // The last step to remove directory or to a move directory operation
  2477 // is to remove the source directory...
  2478 //
  2479 	{
  2480 	TInt r=KErrNotFound;
  2481 	if (iAction == EInternalRmDir ||
  2482 	    (iAction == EInternalCopyForMove && ((iMatchEntry & KMovingFilesMask) != KMovingFilesMask) && !iMovingContents && !iSrcFile.IsRoot()) ||
  2483 	    iAction == EInternalRenameForMove && !iMovingContents && iNumberOfFilesProcessed)
  2484 		{
  2485 		r=iFs.RmDir(iSrcFile.FullName());
  2486 		if ((r!=KErrNone && r!=KErrNotFound && iAction!=EInternalRenameForMove && r!=KErrInUse) || (iAction == EInternalRmDir && r == KErrInUse))
  2487 			{
  2488 			iLastError=r;
  2489 			User::Leave(r);
  2490 			}
  2491 		}
  2492 
  2493 	if (iLastError == KErrCancel && iNumberOfFilesProcessed==0 )
  2494 	{
  2495 		iLastError=KErrCancel;
  2496 		iErrorInfo=ENoFilesProcessed;
  2497 		User::Leave(KErrCancel);
  2498 	}
  2499 
  2500 	if (iLastError==KErrNone && r==KErrNotFound && iNumberOfFilesProcessed==0)
  2501 		{
  2502 		iLastError=KErrNotFound;
  2503 		iErrorInfo=ENoFilesProcessed;
  2504 		User::Leave(KErrNotFound);
  2505 		}
  2506 	}
  2507 
  2508 void CFileMan::SetFlags(TBool anOverWrite,TBool aRecurse,TBool aScanDownTree,TBool aMoveRename)
  2509 //
  2510 // Set or clear flags
  2511 //
  2512 	{
  2513 
  2514 	iSwitches=0;
  2515 	if (aRecurse)
  2516 		iSwitches|=KRecurseFlag;
  2517 	if (anOverWrite)
  2518 		iSwitches|=KOverWriteFlag;
  2519 	if (aScanDownTree)
  2520 		iSwitches|=KScanDownFlag;
  2521 	if (aMoveRename)
  2522 		iSwitches|=KMoveRenameFlag;
  2523 	}
  2524 
  2525 
  2526 EXPORT_C TInt CFileMan::Copy(const RFile& anOld, const TDesC& aNew, TUint aSwitches)
  2527 /**
  2528 Copies from an open file handle to a destination file name.
  2529 
  2530 This is a synchronous function.
  2531 
  2532 Optionally, this function can be set to overwrite the target file.
  2533 If the flag is set for no overwriting and the target file already exists,
  2534 then the target file will not be overwritten, and an error (KErrAlreadyExists)
  2535 will be returned.
  2536 Error codes may be retrieved using CFileBase::GetLastError().
  2537 
  2538 Notes:
  2539 
  2540 -# The file can be copied across drives.
  2541 -# Read-only, hidden and system files can be copied and
  2542    the source file's attributes are preserved in the target file.
  2543 
  2544 @param anOld     Open file handle indicating the file to be copied.
  2545 @param aNew      Path indicating the directory (and optionally the filename)
  2546 				 into which the file is to be copied.
  2547 				 Any path components which are not specified here will be
  2548                  taken from the session path
  2549 @param aSwitches Specify zero for no overwriting;
  2550                  CFileMan::EOverWrite to overwrite files with the same name;
  2551                  Any other flags are illegal
  2552                  By default, the synchronous variant of this function operates
  2553                  with overwriting.
  2554 
  2555 @return KErrNone if successful, otherwise one of the other system-wide error codes.
  2556 
  2557 @see CFileBase::GetLastError()
  2558 @see CFileMan::Move()
  2559 
  2560 @capability Dependent If the path for aNew begins with /Sys then Tcb capability is required.
  2561 @capability Dependent If the path for aNew begins with /Private and does not match
  2562 					  this process' SID then AllFiles capability is required.
  2563 @capability Dependent If the path for aNew begins with /Resource then Tcb capability is required.
  2564 */
  2565 	{
  2566 	TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy3, MODULEUID,
  2567 		(TUint) this, anOld.SubSessionHandle(), aNew, aSwitches);
  2568 
  2569 	TInt ret;
  2570 	if (iSwitches&KFManBusyFlag)
  2571 		{
  2572 		ret = KErrInUse;
  2573 		}
  2574 		// The only switch that is legal for single file copies is EOverWrite
  2575 	else if ((aSwitches & ~EOverWrite) != 0)
  2576 		{
  2577 		ret = KErrArgument;
  2578 		}
  2579 	else
  2580 		{
  2581 
  2582 		SetFlags(aSwitches & EOverWrite, EFalse, EFalse, EFalse);
  2583 
  2584 		// need to signal to CFileBase that we're copying from a handle
  2585 		// and that iSrcFile is invalid
  2586 		iSwitches|= KCopyFromHandle;
  2587 
  2588 		TInt r;
  2589 		RETURNIFERROR(r, iFs.Parse(aNew, iTrgFile),UTraceModuleEfsrv::ECFileManCopy3Return);
  2590 
  2591 		// Need to duplicate the RFile handle so that any threads owned
  2592 		// by this process can use it - i.e. the worker thread
  2593 		RETURNIFERROR(r, iSrcFileHandle.Duplicate(anOld, EOwnerProcess),UTraceModuleEfsrv::ECFileManCopy3Return);
  2594 
  2595 		iAction = EInternalCopyFromHandle;
  2596 		iNumberOfFilesProcessed = 0;
  2597 		TRAP(r,RunL());
  2598 		ret=(r==KErrNone) ? iLastError : r;
  2599 		DoSynchronize(r);
  2600 		}
  2601 
  2602 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy3Return, MODULEUID, ret);
  2603 	return(ret);
  2604 	}
  2605 
  2606 EXPORT_C TInt CFileMan::Copy(const RFile& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
  2607 /**
  2608 Copies from an open file handle to a destination file name.
  2609 
  2610 This is an asynchronous function.
  2611 Its behaviour is the same as the synchronous overload.
  2612 
  2613 @param anOld     Open file handle indicating the file to be copied.
  2614 @param aNew      Path indicating the directory (and optionally the filename)
  2615 				 into which the file is to be copied.
  2616 				 Any path components which are not specified here will be
  2617                  taken from the session path
  2618 @param aSwitches Specify zero for no overwriting;
  2619                  CFileMan::EOverWrite to overwrite files with the same name;
  2620                  Any other flags are illegal.
  2621 
  2622 @param aStatus   The request status object. On request completion,
  2623                  indicates how the request completed:
  2624                  KErrNone, if successful, otherwise one of the other system-wide error
  2625                  codes.
  2626 
  2627 @return KErrNone if the asynchronous request is made successfully; KErrInUse if an asynchronous request
  2628 					is still pending; otherwise one of the other system-wide error codes
  2629 
  2630 @see CFileBase::GetLastError()
  2631 
  2632 @capability Dependent If the path for aNew begins with /Sys then Tcb capability is required.
  2633 @capability Dependent If the path for aNew begins with /Private and does not match
  2634 					  this process' SID then AllFiles capability is required.
  2635 @capability Dependent If the path for aNew begins with /Resource then Tcb capability is required.
  2636 */
  2637 	{
  2638 	TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy4, MODULEUID,
  2639 		(TUint) this, anOld.SubSessionHandle(), aNew, aSwitches, (TUint) &aStatus);
  2640 
  2641 	TInt r;
  2642 	if (iSwitches&KFManBusyFlag)
  2643 		{
  2644 		r = KErrInUse;
  2645 		}
  2646 	else
  2647 		{
  2648 		iStatus=&aStatus;
  2649 		r = Copy(anOld,aNew,aSwitches);
  2650 		}
  2651 
  2652 	TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy4Return, MODULEUID, r);
  2653 	return(r);
  2654 	}
  2655 
  2656 void CFileMan::DoCopyFromHandleL()
  2657 //
  2658 // Copy from open file handle
  2659 //
  2660 	{
  2661 	TInt ret=0;
  2662 	TFileName& trgName = iTmpName1;
  2663 
  2664 	if (iTrgFile.NamePresent())
  2665 		{
  2666 		trgName = iTrgFile.FullName();
  2667 		}
  2668 	else
  2669 		{
  2670 		iSrcFileHandle.Name(trgName);
  2671 		if ((trgName.Length() + iTrgFile.DriveAndPath().Length()) > KMaxFileName)
  2672 			{
  2673 			iSrcFileHandle.Close();
  2674 			User::Leave(KErrBadName);
  2675 			}
  2676 		trgName.Insert(0, iTrgFile.DriveAndPath());
  2677 		}
  2678 
  2679 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  2680 	RFile trgFile;
  2681 #else
  2682 	RFile64 trgFile;
  2683 #endif
  2684 	TInt r=KErrNone;
  2685 
  2686 	if ((iSwitches&KOverWriteFlag)==0)
  2687 		r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  2688 	else
  2689 		r=trgFile.Replace(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
  2690 	if (r!=KErrNone)
  2691 		iErrorInfo = ETrgOpenFailed;
  2692 
  2693 	if (r == KErrNone)
  2694 		r = DoCopy(iSrcFileHandle, trgFile, ret);
  2695 
  2696 	// close the (duplicated) source file handle
  2697 	iSrcFileHandle.Close();
  2698 
  2699 	trgFile.Close();
  2700 	if (ret == MFileManObserver::ECancel || (r!=KErrNone && r!=KErrAlreadyExists && iErrorInfo!=ETrgOpenFailed))
  2701 		iFs.Delete(trgName);
  2702 	User::LeaveIfError(r);
  2703 	}
  2704 
  2705 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  2706 TInt CFileMan::DoCopy(const RFile& aSrcFile, RFile& aDstFile, TInt& aRet)
  2707 	{
  2708 	TInt rem;
  2709 #else
  2710 TInt CFileMan::DoCopy(const RFile64& aSrcFile, RFile64& aDstFile, TInt& aRet)
  2711 	{
  2712 	TInt64 rem;
  2713 #endif
  2714 	RETURNIFERRORD(r,aSrcFile.Size(rem),EFalse);
  2715 	RETURNIFERROR(r, aDstFile.SetSize(rem),EFalse);
  2716 
  2717 	HBufC8* bufPtr = NULL;
  2718 	bufPtr = AllocateBuffer(rem);
  2719 	if (bufPtr == NULL)
  2720 		return KErrNoMemory;
  2721 	TPtr8 copyBuf=bufPtr->Des();
  2722 
  2723 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  2724 	TInt pos=0;
  2725 #else
  2726 	TInt64 pos=0;
  2727 #endif
  2728 	aRet = MFileManObserver::EContinue;
  2729 	while(rem && aRet == MFileManObserver::EContinue)
  2730 		{
  2731 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  2732 		TInt s=Min(rem,copyBuf.MaxSize());
  2733 #else
  2734 		// Min result shall be of TInt size
  2735 		TInt s=(TInt)(Min(rem,(TInt64)copyBuf.MaxSize()));
  2736 #endif
  2737 		r=aSrcFile.Read(pos,copyBuf,s);
  2738 		if (r==KErrNone && copyBuf.Length()!=s)
  2739 			r = KErrCorrupt;
  2740 		if (r==KErrNone)
  2741 			r=aDstFile.Write(pos,copyBuf,s);
  2742 		if (r!=KErrNone)
  2743 			break;
  2744 		pos+= s;
  2745 		rem-= s;
  2746 		iBytesTransferred = s;
  2747 		aRet = (iObserver) ? iObserver->NotifyFileManOperation() : MFileManObserver::EContinue;
  2748 		if (aRet != MFileManObserver::EContinue && aRet != MFileManObserver::ECancel)
  2749 			Panic(EFManBadValueFromObserver);
  2750 		}
  2751 
  2752 	// need to flush the target file - otherwise if there is any dirty data this will be flushed
  2753 	// when the file is closed and this will set the archive attribute, resulting in the file
  2754 	// having potentially a different attribute from the source file
  2755 	if (r == KErrNone)
  2756 		r = aDstFile.Flush();
  2757 
  2758 	if (aRet != MFileManObserver::ECancel)
  2759 		{
  2760 		TTime lastMod;
  2761 		if (r == KErrNone)
  2762 			r = aSrcFile.Modified(lastMod);
  2763 		if (r == KErrNone)
  2764 			r = aDstFile.SetModified(lastMod);
  2765 
  2766 		TUint fileAttributes=0;
  2767 		if (r == KErrNone)
  2768 			r = aSrcFile.Att(fileAttributes);
  2769 		if (r == KErrNone)
  2770 			r = aDstFile.SetAtt(fileAttributes,(~fileAttributes)&KEntryAttMaskSupported);
  2771 
  2772 		if(r == KErrNone)
  2773   			r = aDstFile.Flush();
  2774 		}
  2775 
  2776 	delete bufPtr;
  2777 
  2778 	return r;
  2779 	}