userlibandfileserver/fileserver/sfsrv/cl_fman.cpp
changeset 9 96e5fb8b040d
child 28 5b5d147c7838
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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 	}