Update contrib.
1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
18 #define RETURNIFERROR(a,b,t) \
20 if ((a=b)!=KErrNone) \
23 User::RequestComplete(iStatus,a); \
25 if (_t) {TRACE1(UTF::EBorder, t, MODULEUID, a);} \
30 #define RETURNIFERRORD(a,b,t) \
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;
41 const TInt KPathIncGran=32;
43 const TUint KMovingFilesMask = KEntryAttMatchExclude | KEntryAttDir;
45 TInt ShrinkNames(RFs& aFs, TFileName& aParent, TFileName& aItem, TBool aAppend);
47 LOCAL_C HBufC8* AllocateBuffer(TInt64 aLength)
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);
57 bufPtr=HBufC8::New(KMediumBufSize);
59 bufPtr=HBufC8::New(KSmallBufSize);
63 LOCAL_C TInt IncPathLength(TInt aLen)
65 return(((aLen+KPathIncGran-1)/KPathIncGran)*KPathIncGran);
68 LOCAL_C TInt CreateTargetNameFromSource(TDes& aTrgName, const TDesC& aTrgMask, const TDesC& aSrcName)
69 // Replace the wildcards with letters from the matched file.
72 TParsePtrC trg(aTrgMask);
73 TParsePtrC src(aSrcName);
74 TPtrC mask(trg.NameAndExt());
75 TPtrC source(src.NameAndExt());
77 TBool starCharFound = EFalse;
78 if(mask.LocateReverse('.')!=KErrNotFound || aTrgMask.Right(1)==_L("*"))
81 source.Set(src.Name());
84 for(TInt i = 0; i < steps;
85 i++, mask.Set(trg.ExtPresent() ? trg.Ext() : _L(".*")) , source.Set(src.Ext()))
88 starCharFound = EFalse;
89 while(offset < mask.Length())
91 TChar currentChar = mask[offset];
95 if(offset < source.Length() && !starCharFound)
97 destName.Append(source.Mid(offset));
98 starCharFound = ETrue;
102 if(offset < source.Length())
104 destName.Append(source[offset]);
108 destName.Append(currentChar);
114 if(destName.Right(1) == _L("."))
116 destName.SetLength(destName.Length()-1);
118 if(aTrgName.Length()+destName.Length() > KMaxFileName)
122 aTrgName.Append(destName);
126 EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManStarted()
128 Inform the observer that an operation is about to start.
130 This is done immediately before each entry is processed.
132 @return The implementation of this function should return:
133 MFileManObserver::EContinue, to allow processing of the current file
135 MFileManObserver::ECancel, to skip processing the current file and move
137 MFileManObserver::EAbort to abort the entire operation.
138 The default return value is MFileManObserver::EContinue.
148 EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManOperation()
150 Informs the observer that an operation, i.e. a copy or a move, is proceeding.
152 Large files are copied and moved in stages.
153 After each portion of the source file has been copied to the target, this
156 It may be useful to call CFileMan::BytesTransferredByCopyStep() from this
157 function to retrieve the current status of the operation.
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.
164 MFileManObserver::EContinue, to continue with the operation.
165 The default return value is MFileManObserver::EContinue.
177 EXPORT_C MFileManObserver::TControl MFileManObserver::NotifyFileManEnded()
179 Informs the observer that an operation is complete.
181 This is done immediately after a directory entry has been processed.
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.
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.
205 EXPORT_C CFileBase::CFileBase(RFs& aFs)
207 Protected default constructor.
209 Note that the class is intended only as an abstract base for other classes.
211 @param aFs File server session.
220 EXPORT_C void CFileBase::ConstructL()
222 Second phase constructor.
226 iScanner=CDirScan::NewL(iFs);
227 User::LeaveIfError(iSynchronizer.CreateLocal(0));
233 EXPORT_C CFileBase::~CFileBase()
237 Frees resources prior to destruction of the object.
243 iSynchronizer.Close();
244 User::Free(iSessionPath);
250 GLDEF_C void DoFManBaseOperationL(TAny* aPtr)
252 // File manager asynchronous thread
256 CFileBase& fMan=*(CFileBase*)aPtr;
257 User::LeaveIfError(fMan.iFs.Connect());
258 User::LeaveIfError(fMan.iFs.SetSessionPath(*fMan.iSessionPath));
259 fMan.iNumberOfFilesProcessed = 0;
263 GLDEF_C TInt FManBaseThreadFunction(TAny* aPtr)
265 // Initialise New thread
269 CTrapCleanup* cleanup=CTrapCleanup::New();
271 return(KErrNoMemory);
272 CFileBase& fMan=*(CFileBase*)aPtr;
273 fMan.iSynchronizer.Wait();
274 TRAPD(ret,DoFManBaseOperationL(aPtr));
279 fMan.iFs=fMan.iFsOld;
281 fMan.iFManThread.Close();
288 EXPORT_C void CFileBase::RunInSeparateThreadL(TThreadFunction aThreadFunction)
290 Creates a separate thread to run the command.
292 @param aThreadFunction The thread function.
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;
307 iFManThread.Logon(*iStatus);
308 iFManThread.Resume();
314 EXPORT_C void CFileBase::RunL()
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
324 if (iStatus && (iSwitches&KFManBusyFlag)==EFalse)
326 RunInSeparateThreadL(FManBaseThreadFunction);
330 TBool copyFromHandle = (iSwitches & KCopyFromHandle)?(TBool)ETrue:(TBool)EFalse;
332 CDirScan::TScanDirection scanDir=(iSwitches&KScanDownFlag) ? CDirScan::EScanDownTree : CDirScan::EScanUpTree;
336 TRAP(iLastError,iScanner->SetScanDataL(iSrcFile.FullName(),iMatchEntry,ESortByName|EAscending,scanDir));
337 if (iLastError==KErrNone)
338 TRAP(iLastError,iScanner->NextL(iDirList));
340 if (iLastError!=KErrNone)
342 iErrorInfo=EInitializationFailed;
343 User::Leave(iLastError);
349 if (copyFromHandle || iDirList->Count())
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)
359 iNumberOfFilesProcessed++;
360 TRAP(iLastError,DoOperationL());
361 action=(iObserver) ? iObserver->NotifyFileManEnded() : MFileManObserver::EContinue;
363 else if(action==MFileManObserver::ERetry)
365 Panic(EFManBadValueFromObserver);
371 case MFileManObserver::EContinue:
372 case MFileManObserver::ECancel:
374 case MFileManObserver::ERetry:
376 case MFileManObserver::EAbort:
380 User::Leave(KErrCancel);
382 Panic(EFManBadValueFromObserver);
386 if (copyFromHandle || iCurrentEntry>=iDirList->Count())
392 if (iSwitches&KRecurseFlag)
394 TRAPD(ret,iScanner->NextL(iDirList));
395 if (ret!=KErrNone && ret!=KErrPathNotFound)
397 iErrorInfo=EScanNextDirectoryFailed;
399 User::Leave(iLastError);
404 CompleteOperationL();
414 EXPORT_C void CFileBase::SetObserver(MFileManObserver* anObserver)
418 Use this function to provide CFileMan with an MFileManObserver, or, if one
419 already exists, to change the observer.
421 @param anObserver File management observer.
424 @see MFileManObserver
428 iObserver=anObserver;
434 EXPORT_C const TEntry& CFileBase::CurrentEntry()
436 Gets the entry currently being processed.
438 @return Contains the current entry.
442 __ASSERT_ALWAYS(iDirList && iCurrentEntry>=0 && iCurrentEntry<iDirList->Count(),Panic(EFManCurrentEntryInvalid));
443 return (*iDirList)[iCurrentEntry];
449 EXPORT_C TPtrC CFileBase::AbbreviatedPath()
451 Gets the abbreviated path of the file or directory currently being processed.
453 The abbreviated path is its path relative to the top level directory
454 specified in the operation.
456 @return The abbreviated path.
460 return iScanner->AbbreviatedPath();
466 EXPORT_C TPtrC CFileBase::FullPath()
468 Gets the full path of the file or directory currently being processed.
470 The full path includes the drive letter, path and filename.
472 @return The full path.
476 return iScanner->FullPath();
482 EXPORT_C TInt CFileBase::GetLastError()
484 Gets the latest error code returned during a CFileMan
487 This function may be called from MFileManObserver::NotifyFileManEnded().
489 @return KErrNone, or another error code that might have been
490 returned by a CFileMan operation.
500 EXPORT_C TFileManError CFileBase::GetMoreInfoAboutError()
502 Gets additional information about the latest error returned during
503 a CFileMan operation.
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().
509 @return The extra information about the last CFileMan error.
512 @see CFileBase::GetLastError()
522 EXPORT_C CFileMan* CFileMan::NewL(RFs& aFs)
524 Constructs and allocates memory for a new CFileMan object.
526 @param aFs File server session.
528 @return Newly created CFileMan object.
531 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL1, MODULEUID, aFs.Handle());
533 CFileMan* fileMan=new(ELeave) CFileMan(aFs);
534 CleanupStack::PushL(fileMan);
535 fileMan->CFileBase::ConstructL();
538 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL1Return, MODULEUID, fileMan);
545 EXPORT_C CFileMan* CFileMan::NewL(RFs& aFs,MFileManObserver* anObserver)
547 Constructs and allocates memory for a new CFileMan object with an observer.
549 @param aFs File server session.
550 @param anObserver File management observer.
552 @return Newly created CFileMan object.
555 TRACE2(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL2, MODULEUID, aFs.Handle(), anObserver);
557 CFileMan* fileMan=new(ELeave) CFileMan(aFs);
558 CleanupStack::PushL(fileMan);
559 fileMan->CFileBase::ConstructL();
561 fileMan->SetObserver(anObserver);
563 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManNewL2Return, MODULEUID, fileMan);
570 CFileMan::CFileMan(RFs& aFs)
572 // Constructor and destructor
577 CFileMan::~CFileMan()
579 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDestructor, MODULEUID, this);
581 TRACE0(UTF::EBorder, UTraceModuleEfsrv::ECFileManDestructorReturn, MODULEUID);
585 EXPORT_C CFileMan::TAction CFileMan::CurrentAction()
587 Gets the action which CFileMan is currently carrying out.
589 @return The action which CFileMan is carrying out.
592 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCurrentAction, MODULEUID, this);
594 TAction action = ENone;
596 // Mapping table between internal and external action indicators.
602 case EInternalAttribs:
608 case EInternalCopyForMove:
611 case EInternalDelete:
614 case EInternalRenameInvalidEntry:
615 action = ERenameInvalidEntry;
617 case EInternalRenameForMove:
618 case EInternalRename:
624 case EInternalCopyFromHandle:
625 action = ECopyFromHandle;
628 Panic(EFManUnknownAction);
631 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCurrentActionReturn, MODULEUID, action);
638 EXPORT_C void CFileMan::GetCurrentTarget(TFileName& aTrgName)
640 Gets the name of the target file for the CFileMan operation currently
643 This function is relevant when copying, moving or renaming files.
645 @param aTrgName The full path and filename of the target file for
646 the current CFileMan operation
649 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentTarget, MODULEUID, this);
651 GetSrcAndTrg(iTmpParse, aTrgName);
653 TRACEMULT1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentTargetReturn, MODULEUID, aTrgName);
659 EXPORT_C void CFileMan::GetCurrentSource(TFileName& aSrcName)
661 Gets the name of the source file or directory for the CFileMan operation
662 currently being carried out.
664 The source is the file or directory which is being copied, moved or deleted.
666 @param aSrcName The full path and filename of the source file for the current
670 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentSource, MODULEUID, this);
672 TPtrC fullPath(FullPath());
673 iTmpParse.Set(CurrentEntry().iName, &fullPath, NULL);
674 aSrcName = iTmpParse.FullName();
676 TRACEMULT1(UTF::EBorder, UTraceModuleEfsrv::ECFileManGetCurrentSourceReturn, MODULEUID, aSrcName);
679 void CFileMan::GetSrcAndTrg(TParse& aSrcName,TFileName& aTrgName)
681 // Get the current target for the operation
684 TFileName fullpath = FullPath();
685 TInt ret = aSrcName.Set(CurrentEntry().iName, &fullpath, NULL);
686 if(ret == KErrBadName)
688 // Try heap variables first
690 TFileName* current = new TFileName;
693 current->Copy(CurrentEntry().iName);
695 ret = ShrinkNames(iFs, fullpath, *current, EFalse);
698 ret = aSrcName.Set(*current, &fullpath, NULL);
704 if (!done) //heap method failed
706 TFileName current = CurrentEntry().iName;
707 ret = ShrinkNames(iFs, fullpath, current, EFalse);
710 ret = aSrcName.Set(current, &fullpath, NULL);
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());
724 EXPORT_C TInt CFileMan::BytesTransferredByCopyStep()
726 Gets the number of bytes transferred during a copy or move operation.
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.
734 @return The number of bytes transferred.
737 TRACE2(UTF::EBorder, UTraceModuleEfsrv::ECFileManBytesTransferredByCopyStep, MODULEUID, this, iBytesTransferred);
739 return(iBytesTransferred);
745 LOCAL_C void MakeParseWild(TParse& aParse, TFileName& aName)
747 // Append _L("\\*") or _L("*") to aParse
752 aName = aParse.FullName();
753 if (aParse.NamePresent() || aParse.ExtPresent())
755 if (aName.Length()<=254)
756 aName.Append(_L("\\*"));
760 if (aName.Length()<=255)
761 aName.Append(_L("*"));
763 aParse.Set(aName,NULL,NULL);
768 void CFileMan::CheckForDirectory()
770 // If iTrgFile is a directory set target to iTrgFile\\*
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)
779 MakeParseWild(iSrcFile, iTmpName1);
780 if (trg==KErrNotFound && (iSwitches&KRecurseFlag))
781 MakeParseWild(iTrgFile, iTmpName1);
785 void CFileMan::DoSynchronize(TInt aRetValue)
787 // Synchronise with fmanthread
791 if (iStatus && aRetValue==KErrNone)
792 iSynchronizer.Signal(); // FManThread started
793 if (iStatus && aRetValue!=KErrNone)
794 iStatus=NULL; // FManThread failed to start
797 LOCAL_C void NextInPath(const TDesC& aPath,TPtrC& anEntry,TInt& aPos)
799 // Returns the next entry in the path
804 if ((aPos+1)>=aPath.Length())
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);
813 if (path[delimiterPos-1]==KExtDelimiter) // return "F32." as "F32"
814 anEntry.Set(aPath.Mid(aPos+1,delimiterPos-1));
816 anEntry.Set(aPath.Mid(aPos+1,delimiterPos));
817 aPos+=delimiterPos+1;
820 LOCAL_C TBool ComparePaths(const TDesC& aPath1,const TDesC& aPath2)
822 // Return ETrue if the paths are identical
823 // To catch case "\\F32.\\GROUP\\" == "\\F32\\GROUP\\"
827 TPtrC entry1(NULL,0);
828 TPtrC entry2(NULL,0);
833 NextInPath(aPath1,entry1,pos1);
834 NextInPath(aPath2,entry2,pos2);
835 if (entry1.MatchF(entry2)==KErrNotFound)
837 } while (entry1.Length() && entry2.Length());
842 EXPORT_C TBool FileNamesIdentical(const TDesC& aFileName1,const TDesC& aFileName2)
844 // Return ETrue if the filenames (and paths) are identical
845 // NB "Agenda" == "AGENda."
849 TParsePtrC file1(aFileName1);
850 TParsePtrC file2(aFileName2);
851 if (file1.Drive().MatchF(file2.Drive())==KErrNotFound)
853 if (file1.Name().MatchF(file2.Name())==KErrNotFound)
855 if (ComparePaths(file1.Path(),file2.Path())==EFalse)
857 if (file1.Ext().Length()==0 || file2.Ext().Length()==0)
858 { // Agenda == Agenda.
859 if (file1.Ext().Length()==1 || file2.Ext().Length()==1)
862 if (file1.Ext().MatchF(file2.Ext())==KErrNotFound &&
863 file1.NameAndExt().MatchF(file2.NameAndExt())==KErrNotFound)
871 EXPORT_C TInt CFileMan::Attribs(const TDesC& aName,TUint aSetMask,TUint aClearMask,const TTime& aTime,TUint aSwitches,TRequestStatus& aStatus)
873 Sets or clears attributes for one or more files using two bitmasks.
875 This is an asynchronous function.
876 Its behaviour is the same as the synchronous overload.
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
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
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
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.
907 TRACEMULT8(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs1, MODULEUID,
908 (TUint) this, aName, aSetMask, aClearMask, I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()), aSwitches, (TUint) &aStatus);
911 if (iSwitches&KFManBusyFlag)
918 r = Attribs(aName,aSetMask,aClearMask,aTime,aSwitches);
921 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs1Return, MODULEUID, r);
928 EXPORT_C TInt CFileMan::Attribs(const TDesC& aName,TUint aSetMask,TUint aClearMask,const TTime& aTime,TUint aSwitches)
930 Sets or clears attributes for one or more files using two bitmasks
932 This is a synchronous function.
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.
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.
945 1. A panic is raised if any attribute is specified in both bitmasks.
947 2. Attempting to change the attributes for an open file results in an error
948 for that file, as retrieved by CFileBase::GetLastError().
950 3. An attempt to set or clear the KEntryAttDir or KEntryAttVolume attribute
951 for a file or directory will have no effect.
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
968 @return KErrNone if successful, otherwise one of the other system-wide error codes.
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.
977 TRACEMULT7(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs2, MODULEUID,
978 (TUint) this, aName, aSetMask, aClearMask, I64LOW(aTime.Int64()), I64HIGH(aTime.Int64()), aSwitches);
981 if (iSwitches&KFManBusyFlag)
987 SetFlags(aSwitches&EOverWrite,aSwitches&ERecurse,ETrue,EFalse);
988 RETURNIFERRORD(r,iFs.Parse(aName,iSrcFile),UTraceModuleEfsrv::ECFileManAttribs2Return);
990 iClearMask=aClearMask;
992 iAction = EInternalAttribs;
993 iMatchEntry=KEntryAttMaskSupported; // all entries
994 iNumberOfFilesProcessed = 0;
996 ret=(r==KErrNone) ? iLastError : r;
1000 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManAttribs2Return, MODULEUID, ret);
1007 EXPORT_C TInt CFileMan::Copy(const TDesC& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
1009 Copies one or more files.
1011 This is an asynchronous function.
1012 Its behaviour is the same as the synchronous overload.
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
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
1033 @capability AllFiles
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
1040 TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy1, MODULEUID,
1041 (TUint) this, anOld, aNew, aSwitches, (TUint) &aStatus);
1044 if (iSwitches&KFManBusyFlag)
1049 r = Copy(anOld,aNew,aSwitches);
1052 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy1Return, MODULEUID, r);
1059 EXPORT_C TInt CFileMan::Copy(const TDesC& anOld,const TDesC& aNew,TUint aSwitches)
1061 Copies one or more files.
1063 This is a synchronous function.
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.
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.
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.
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.
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().
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
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.
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.
1107 This means that the following two example copy operations will behave
1111 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1113 fm->Copy(_L("C:\\SRC\\"), _L("C:\\TRG\\"), CFileMan::ERecurse);
1114 fm->Copy(_L("C:\\SRC"), _L("C:\\TRG\\"), CFileMan::ERecurse);
1117 because they will be interpreted as follows:
1119 fm->Copy(_L("C:\\SRC\\*"),_L("C:\\TRG\\"), CFileMan::ERecurse);
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.
1125 2. Files can be copied across drives.
1127 3. Open files can be copied if they have been opened using
1128 the EFileShareReadersOnly file share mode.
1130 4. Read-only, hidden and system files can be copied and
1131 the source file's attributes are preserved in the target file.
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.
1145 @return KErrNone if successful, KErrNotFound if source directory is empty, otherwise one of the other system-wide error codes.
1147 @see CFileBase::GetLastError()
1149 @capability AllFiles
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
1156 TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2, MODULEUID, (TUint) this, anOld, aNew, aSwitches);
1158 if (iSwitches&KFManBusyFlag)
1160 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, KErrInUse);
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();
1168 if((iSwitches&KRecurseFlag) && iTrgFile.DriveAndPath().MatchF(iSrcFile.FullName()) != KErrNotFound)
1170 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, KErrArgument);
1171 return(KErrArgument);
1174 iAction = EInternalCopy;
1175 iMatchEntry=KEntryAttMaskSupported;
1176 iNumberOfFilesProcessed = 0;
1178 TInt ret=(r==KErrNone) ? iLastError : r;
1181 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy2Return, MODULEUID, ret);
1188 EXPORT_C TInt CFileMan::Delete(const TDesC& aName,TUint aSwitches,TRequestStatus& aStatus)
1190 Deletes one or more files.
1192 This is an asynchronous function.
1193 Its behaviour is the same as the synchronous overload.
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
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
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.
1221 TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete1, MODULEUID, (TUint) this, aName, aSwitches, (TUint) &aStatus);
1224 if (iSwitches&KFManBusyFlag)
1231 r = Delete(aName,aSwitches);
1234 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete1Return, MODULEUID, r);
1241 EXPORT_C TInt CFileMan::Delete(const TDesC& aName,TUint aSwitches)
1243 Deletes one or more files.
1245 This is a synchronous function.
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.
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().
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.
1268 @return KErrNone if successful, otherwise one of the other system-wide error
1271 @see CFileBase::GetLastError()
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.
1281 TRACEMULT3(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete2, MODULEUID, (TUint) this, aName, aSwitches);
1284 if (iSwitches&KFManBusyFlag)
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;
1297 ret=(r==KErrNone) ? iLastError : r;
1301 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManDelete2Return, MODULEUID, ret);
1308 EXPORT_C TInt CFileMan::Move(const TDesC& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
1310 Moves one or more files.
1312 This is an asynchronous function.
1313 Its behaviour is the same as the synchronous overload.
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
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
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
1338 @capability AllFiles
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.
1345 TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove1, MODULEUID,
1346 (TUint) this, anOld, aNew, aSwitches, (TUint) &aStatus);
1349 if (iSwitches&KFManBusyFlag)
1356 r = Move(anOld,aNew,aSwitches);
1359 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove1Return, MODULEUID, r);
1366 EXPORT_C TInt CFileMan::Move(const TDesC& anOld,const TDesC& aNew,TUint aSwitches)
1368 Moves one or more files.
1370 This is a synchronous function.
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.
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.
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.
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.
1396 For example, if the directory level "b" contains the files F1,F2 and F3, then:
1398 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1400 fm->Move(_L("C:\\a\\b\\"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
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
1407 If there is no trailing backslash character, for example:
1409 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1411 fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
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".
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.
1426 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1428 fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), 0);
1431 The example above produces the same output as:
1434 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1436 fm->Move(_L("C:\\a\\b"), _L("C:\\x\\y\\"), CFileMan::ERecurse);
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().
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.
1460 @return KErrNone if successful, otherwise one of the other system-wide error
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
1466 @capability AllFiles
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.
1471 @see CFileBase::GetLastError()
1474 TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2, MODULEUID,
1475 (TUint) this, anOld, aNew, aSwitches);
1478 if (iSwitches&KFManBusyFlag)
1480 TRACE1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, KErrInUse);
1484 iNumberOfFilesProcessed = 0;
1486 RETURNIFERRORD(r,iFs.Parse(anOld,iSrcFile),UTraceModuleEfsrv::ECFileManMove2Return);
1487 RETURNIFERROR(r,iFs.Parse(aNew,_L("*"),iTrgFile),UTraceModuleEfsrv::ECFileManMove2Return);
1489 TInt ret = KErrNone;
1490 TBool aComplete = EFalse;
1491 if(SrcTrgDrivesIdentical())
1493 ret = SetupMoveOnSameDrive(aSwitches, aComplete);
1497 ret = SetupMoveAcrossDrives(aSwitches);
1500 if(ret != KErrNone || aComplete)
1504 User::RequestComplete(iStatus, ret);
1506 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, ret);
1510 iMatchEntry = KEntryAttMaskSupported;
1511 if((aSwitches&ERecurse)==0 && iMovingContents)
1513 iMatchEntry = KMovingFilesMask;
1516 // Do the Move or Rename Operation
1518 ret = (r==KErrNone) ? iLastError : r;
1521 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManMove2Return, MODULEUID, ret);
1526 TBool CFileMan::SrcTrgDrivesIdentical()
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
1532 return iSrcFile.Drive().MatchF(iTrgFile.Drive()) != KErrNotFound;
1536 TInt CFileMan::SetupDirectoryForMove(TBool& aSrcIsDir)
1538 * Sets up the target specification to include the new target directory if required.
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.
1543 * @return KErrNone if successful, otherwise one of the system wide error codes.
1546 iMovingContents = ETrue;
1549 TPtrC nameAndExt(iSrcFile.NameAndExt());
1550 if (nameAndExt == _L("*") || nameAndExt == _L("*.*"))
1552 // Wildcard specification - Move the entire contents of the directory to the target
1557 TInt src = iFs.Entry(iSrcFile.FullName(), iTmpEntry);
1558 if ((src == KErrNone && iTmpEntry.iAtt&KEntryAttDir) || (!iSrcFile.NamePresent() && iSrcFile.IsRoot()))
1562 // A directory is specified.
1563 // - Mandatory recursion with Wildcard Copy
1564 // - Target is a directory (Enforced by MakeParseWild)
1566 MakeParseWild(iTrgFile, iTmpName1);
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;
1573 iMovingContents = (srcPath[srcPathLen] == KPathDelimiter); // Moving the directory itself, or the contents?
1575 if(!iMovingContents)
1577 // No path delimiter specified
1578 // - move the whole directory (if specified)
1579 TInt len = srcPath.Length();
1581 TInt idx = srcPath.Left(len).LocateReverse(KPathDelimiter);
1583 if((idx >= 2) && (idx != KErrNotFound))
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);
1599 TInt CFileMan::SetupTargetDirectory(TBool aOverWrite, TBool& aComplete)
1603 TInt trgErr = iFs.Entry(iTrgFile.DriveAndPath(), iTmpEntry);
1606 TInt srcErr = iFs.Entry(iSrcFile.FullName(), srcEntry);
1608 if(srcErr == KErrNone && trgErr == KErrNone)
1610 if ((srcEntry.iAtt&KEntryAttDir) != (iTmpEntry.iAtt&KEntryAttDir))
1612 // return KErrAccessDenied if it is trying to overwrite a file to a dir or vice versa.
1613 return KErrAccessDenied;
1617 if(trgErr == KErrNone)
1619 // Already Exists - Overwrite if flags set
1622 trgErr = KErrAlreadyExists;
1626 iNumberOfFilesProcessed++;
1629 else if((trgErr == KErrNotFound) || (trgErr == KErrPathNotFound))
1631 if(SrcTrgDrivesIdentical())
1633 // When moving a directory on the same drive, the directory can simply be renamed...
1634 TParse& midDir = iTmpParse;
1636 if(midDir.PopDir() == KErrNone)
1638 // ...before renaming, ensure that all intermediate directories exist
1639 trgErr = iFs.MkDirAll(midDir.DriveAndPath());
1640 if(trgErr == KErrAlreadyExists)
1646 if (trgErr == KErrNone)
1648 // ...and finally rename the source directory
1649 trgErr = iFs.Rename(iSrcFile.FullName(),iTrgFile.DriveAndPath());
1655 trgErr = iFs.MkDirAll(iTrgFile.FullName());
1657 iNumberOfFilesProcessed++;
1664 TInt CFileMan::SetupMoveOnSameDrive(TUint aSwitches, TBool& aComplete)
1666 // Moving on the same drive.
1670 TBool srcIsDir = EFalse;
1671 TInt ret = SetupDirectoryForMove(srcIsDir);
1672 if (ret != KErrNone)
1677 TBool scanDown = ETrue;
1678 TBool recurse = (aSwitches & ERecurse);
1680 iAction = EInternalRenameForMove;
1682 TFileName& srcpath = iTmpName1;
1683 srcpath.Copy(iSrcFile.FullName());
1684 if(srcpath.Length()<KMaxFileName && srcpath.Length()>1 && srcpath[srcpath.Length()-1]!=KPathDelimiter)
1686 srcpath.Append(KPathDelimiter);
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))
1692 if(iTrgFile.FullName().Left(srcpath.Length()).MatchF(srcpath)==0)
1698 // if any of the SRC folders already existing in TRG, scan upwards
1701 CDirScan* srcScanDir = NULL;
1702 CDirScan* trgScanDir = NULL;
1703 CDir* srcEntryList = NULL;
1704 CDir* trgEntryList = NULL;
1708 TRAP(ret,(srcScanDir = CDirScan::NewL(iFs)));
1713 TRAP(ret,srcScanDir->SetScanDataL(iSrcFile.FullName(),KEntryAttMaskSupported,ESortByName));
1718 TRAP(ret,srcScanDir->NextL(srcEntryList));
1723 TRAP(ret,(trgScanDir=CDirScan::NewL(iFs)));
1728 TRAP(ret,trgScanDir->SetScanDataL(iTrgFile.FullName(),KEntryAttMaskSupported,ESortByName));
1733 TRAP(ret,trgScanDir->NextL(trgEntryList));
1738 for(trgCnt=trgEntryList->Count()-1; trgCnt>-1; trgCnt--)
1740 for(srcCnt=srcEntryList->Count()-1; srcCnt>-1; srcCnt--)
1742 if( (*srcEntryList)[srcCnt].iName == (*trgEntryList)[trgCnt].iName
1743 && ((*srcEntryList)[srcCnt].iAtt & KEntryAttDir)
1744 && ((*trgEntryList)[trgCnt].iAtt & KEntryAttDir))
1750 }// end inner for loop
1751 } // end outer for loop
1754 if(srcEntryList!=NULL)
1755 delete srcEntryList;
1756 if(trgEntryList!=NULL)
1757 delete trgEntryList;
1758 if(srcScanDir!=NULL)
1760 if(trgScanDir!=NULL)
1762 }// end if(iMovingContents)
1764 if(srcIsDir && !iTrgFile.IsRoot() && !iMovingContents)
1766 ret = SetupTargetDirectory(aSwitches & EOverWrite, aComplete);
1767 if(ret != KErrNone || aComplete)
1772 if(!iMovingContents)
1779 MakeParseWild(iSrcFile, iTmpName1);
1782 SetFlags(aSwitches & EOverWrite, recurse, scanDown, ETrue);
1787 TInt CFileMan::SetupMoveAcrossDrives(TUint aSwitches)
1789 // Moving across drives. We may need to recurse,
1790 // depending on the supplied source path.
1792 TBool srcIsDir = EFalse;
1793 TInt ret = SetupDirectoryForMove(srcIsDir);
1794 if (ret != KErrNone)
1799 TBool recurse = (aSwitches & ERecurse);
1800 TBool scanDown = (recurse) ? (TBool)EFalse : (TBool)ETrue;
1804 if(!iMovingContents)
1807 if(!iTrgFile.IsRoot())
1809 TBool complete = EFalse;
1810 ret = SetupTargetDirectory(aSwitches & EOverWrite, complete);
1811 if(ret != KErrNone || complete)
1819 CheckForDirectory();
1820 iAction = EInternalCopyForMove;
1821 SetFlags(aSwitches & EOverWrite, recurse, scanDown, EFalse);
1825 TInt CFileMan::RenameInvalidEntry(const TDesC& /*aName*/,const TDesC& /*aNewName*/,TUint /*aSwitches*/)
1827 // Start rename operation
1830 return KErrNotSupported;
1836 EXPORT_C TInt CFileMan::Rename(const TDesC& aName,const TDesC& aNewName,TUint aSwitches,TRequestStatus& aStatus)
1838 Renames one or more files.
1840 This is an asynchronous function.
1841 Its behaviour is the same as the synchronous overload.
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
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
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.
1868 TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename1, MODULEUID,
1869 (TUint) this, aName, aNewName, aSwitches, (TUint) &aStatus);
1872 if (iSwitches&KFManBusyFlag)
1879 r = Rename(aName,aNewName,aSwitches);
1882 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename1Return, MODULEUID, r);
1889 EXPORT_C TInt CFileMan::Rename(const TDesC& aName,const TDesC& aNewName,TUint aSwitches)
1891 Renames one or more files, or a directory
1893 This is a synchronous function.
1895 The function can also be used to move files by specifying different destination
1896 and source directories.
1898 Some rules for using CFileMan::Rename():
1902 1.1. Trailing backslash ("\") in either source path (aName) or target path (aNewName)
1903 will be interpreted to "\*.*";
1905 For example, following code should behave identically:
1907 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
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\\*.*"));
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);
1918 For example, under all other constraints (see rules 2. and 3.),
1920 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1922 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG\"));
1924 will result in renaming "C:\\SRC" to "C:\\TRG\\SRC", while
1926 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1928 fm->Rename(_L("C:\\SRC"), _L("C:\\TRG"));
1930 will result in renaming "C:\\SRC" to "C:\\TRG".
1932 2. Renaming file(s):
1936 A file's name and extension are interpreted separately, for example:
1939 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1941 fm->Rename(_L("C:\\SRC\\1234.567"), _L("C:\\TRG\\AB*CD.TXT"));
1943 renames the source file to file "C:\\TRG\\AB34CD.TXT".
1945 Wildcards can be used for renaming multiple files, for example;
1947 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
1949 fm->Rename(_L("C:\\SRC\\*.567"), _L("C:\\TRG\\*.TXT"));
1951 renames all the file under "C:\\SRC\\" having extension ".567" to the files under
1952 "C:\\TRG\\" having extension ".TXT".
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().
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.
1962 2.4 Trying to rename file(s) to existing directory(ies) will fail;
1964 For example, giving following directory structure:
1972 Following code will fail:
1974 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
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\\"));
1981 3. When renamnig a directory:
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.
1986 For example, following code will result in moving "C:\SRC" directory including all
1989 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
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\\*.*"));
1996 3.2. Wildcards can not be used for moving directories;
1998 3.3. Overwriting is not permitted;
2000 For example, giving directory structure as following:
2007 following code will fail:
2009 CFileMan* fm(CFileMan::NewL(iFs)); // Where iFs is an RFs handle
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\\*.*"));
2018 4.1. The target and source directories must be on the same drive.
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().
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.
2036 @return KErrNone if successful, otherwise one of the other system-wide error
2039 @see CFileBase::GetLastError()
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.
2048 TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename2, MODULEUID,
2049 (TUint) this, aName, aNewName, aSwitches);
2052 if (iSwitches&KFManBusyFlag)
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);
2062 iAction = EInternalRename;
2063 iMatchEntry=KEntryAttMaskSupported;
2064 iNumberOfFilesProcessed = 0;
2066 ret=(r==KErrNone) ? iLastError : r;
2070 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRename2Return, MODULEUID, ret);
2075 EXPORT_C TInt CFileMan::RmDir(const TDesC& aDirName,TRequestStatus& aStatus)
2077 Deletes a directory and all files and directories contained in the
2078 directory structure below it.
2080 Other than being asynchronous, the behaviour of this function is the same
2081 as is documented in its synchronous overload.
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
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
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.
2100 TRACEMULT3(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir1, MODULEUID, (TUint) this, aDirName, (TUint) &aStatus);
2103 if (iSwitches&KFManBusyFlag)
2110 r = RmDir(aDirName);
2113 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir1Return, MODULEUID, r);
2118 EXPORT_C TInt CFileMan::RmDir(const TDesC& aDirName)
2120 Deletes a directory and all files and directories contained in the
2121 directory structure below it.
2123 This is a synchronous function.
2125 The function cannot be used non-recursively. For a non-recursive
2126 directory deletion, use RFs::RmDir().
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.
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.
2137 @return KErrNone if successful, otherwise one of the other system-wide error
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.
2148 TRACEMULT2(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir2, MODULEUID, (TUint) this, aDirName);
2151 if (iSwitches&KFManBusyFlag)
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;
2165 ret = (r!=KErrNone) ? iLastError : KErrNone;
2168 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManRmDir2Return, MODULEUID, ret);
2173 void CFileMan::DoOperationL()
2174 // Call the action in progress.
2178 case EInternalAttribs:
2182 case EInternalCopyForMove:
2185 case EInternalDelete:
2188 case EInternalRenameInvalidEntry:
2189 case EInternalRenameForMove:
2190 case EInternalRename:
2193 case EInternalRmDir:
2196 case EInternalCopyFromHandle:
2197 DoCopyFromHandleL();
2200 Panic(EFManUnknownAction);
2204 void CFileMan::DoAttribsL()
2206 // Do attribs operation step
2209 TPtrC fullPath(FullPath());
2210 iTmpParse.Set(CurrentEntry().iName, &fullPath, NULL);
2211 User::LeaveIfError(iFs.SetEntry(iTmpParse.FullName(), iTime, iSetMask, iClearMask));
2214 void CFileMan::DoCopyOrMoveL()
2216 // Do copy or move operation
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
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())
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:
2232 if (iTrgFile.DriveAndPath() == iScanner->FullPath().Left(iTrgFile.DriveAndPath().Length()))
2239 TParse& srcName = iTmpParse;
2240 TFileName& trgName = iTmpName1;
2241 GetSrcAndTrg(srcName,trgName);
2243 // Handle case when source is directory
2244 if (CurrentEntry().iAtt&KEntryAttDir)
2246 if(!(iSwitches&KRecurseFlag))
2248 User::Leave(KErrNone);
2250 trgName.Append(KPathDelimiter);
2251 TInt r = iFs.MkDirAll(trgName);
2252 if (r!=KErrNone && r!=KErrAlreadyExists)
2255 if(iAction == EInternalCopyForMove)
2257 // Move operation - Attempt to delete the source directory.
2258 if((iMatchEntry & KMovingFilesMask) != KMovingFilesMask)
2260 iTmpName2 = srcName.FullName();
2261 iTmpName2.Append(KPathDelimiter);
2262 TInt rdErr = iFs.RmDir(iTmpName2);
2263 if(rdErr != KErrNone && rdErr != KErrInUse)
2272 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
2273 RFile srcFile,trgFile;
2275 RFile64 srcFile,trgFile;
2278 if (FileNamesIdentical(srcName.FullName(),trgName))
2280 if (iSwitches & KOverWriteFlag)
2281 // Source and target are identical, KOverWriteFlag makes copying
2282 // having no effect.
2285 User::Leave(KErrAlreadyExists);
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)
2294 TEntry& entry = iTmpEntry;
2295 r = iFs.Entry(srcName.FullName(), entry);
2296 if(r==KErrNone && (entry.iAtt&KEntryAttReadOnly))
2299 r = iFs.SetAtt(srcName.FullName(), 0, KEntryAttReadOnly);
2302 r = srcFile.Open(iFs, srcName.FullName(), EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
2308 iErrorInfo=ESrcOpenFailed;
2311 iFs.SetAtt(srcName.FullName(), KEntryAttReadOnly, 0);
2316 if ((iSwitches&KOverWriteFlag)==0)
2317 r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
2319 r=trgFile.Replace(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
2321 if (r==KErrPathNotFound && (iSwitches&KRecurseFlag))
2323 r=iFs.MkDirAll(trgName);
2325 r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
2329 iErrorInfo=ETrgOpenFailed;
2333 r = DoCopy(srcFile, trgFile, ret);
2337 if ((r!=KErrNone && (r!=KErrAlreadyExists && iErrorInfo!=ETrgOpenFailed)) || (ret==MFileManObserver::ECancel))
2338 iFs.Delete(trgName);
2339 if(r==KErrNone && isRO)
2341 r = iFs.SetAtt(trgName, KEntryAttReadOnly, 0);
2343 User::LeaveIfError(r);
2348 if (iAction == EInternalCopyForMove && ret != MFileManObserver::ECancel)
2350 r=iFs.Delete(srcName.FullName());
2353 iFs.Delete(trgName);
2358 void CFileMan::DoDeleteL()
2360 // Do delete operation step
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)
2369 User::LeaveIfError(ShrinkNames(iFs, pathname, filename, EFalse));
2371 iTmpParse.Set(filename, &pathname, NULL);
2372 User::LeaveIfError(iFs.Delete(iTmpParse.FullName()));
2375 void CFileMan::DoRenameL()
2377 // Do rename operation step
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
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())
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:
2393 if (iTrgFile.DriveAndPath() == iScanner->FullPath().Left(iTrgFile.DriveAndPath().Length()))
2400 TParse& srcName = iTmpParse;
2401 TFileName& trgName = iTmpName1;
2402 GetSrcAndTrg(srcName, trgName);
2404 TInt r = iFs.Rename(srcName.FullName(),trgName);
2405 if (r==KErrAlreadyExists && (iSwitches&KOverWriteFlag)!=0)
2407 // Target already exists, with the overwrite flag enabled
2408 if((CurrentEntry().iAtt & KEntryAttDir) == 0)
2411 r=iFs.Replace(srcName.FullName(),trgName);
2413 else if (iAction == EInternalRenameForMove)
2415 trgName = srcName.FullName();
2416 trgName.Append(KPathDelimiter);
2417 r = iFs.RmDir(trgName); // remove empty directory after move
2425 if (r==KErrPathNotFound)
2427 if((iSwitches&KMoveRenameFlag) && !(iSwitches&KRecurseFlag))
2429 r=iFs.MkDirAll(trgName);
2431 r=iFs.Rename(srcName.FullName(),trgName);
2435 TEntry& entry = iTmpEntry;
2436 TInt retcode=iFs.Entry(srcName.FullName(), entry);
2437 if (retcode!=KErrNone)
2438 iErrorInfo=ESrcOpenFailed;
2440 iErrorInfo=ETrgOpenFailed;
2442 User::LeaveIfError(r);
2445 void CFileMan::DoRmDirL()
2447 // Do rmdir operation step
2450 TFileName& srcName = iTmpName1;
2451 srcName.Copy(FullPath());
2452 if (srcName.Length() + CurrentEntry().iName.Length() > KMaxFileName)
2454 TFileName& current = iTmpName2;
2455 current.Copy(CurrentEntry().iName);
2456 User::LeaveIfError(ShrinkNames(iFs, srcName, current, ETrue));
2460 srcName.Append(CurrentEntry().iName);
2463 if ((CurrentEntry().iAtt&KEntryAttDir)==0)
2464 User::LeaveIfError(iFs.Delete(srcName));
2467 srcName.Append(KPathDelimiter);
2468 User::LeaveIfError(iFs.RmDir(srcName));
2473 void CFileMan::CompleteOperationL()
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...
2480 TInt r=KErrNotFound;
2481 if (iAction == EInternalRmDir ||
2482 (iAction == EInternalCopyForMove && ((iMatchEntry & KMovingFilesMask) != KMovingFilesMask) && !iMovingContents && !iSrcFile.IsRoot()) ||
2483 iAction == EInternalRenameForMove && !iMovingContents && iNumberOfFilesProcessed)
2485 r=iFs.RmDir(iSrcFile.FullName());
2486 if ((r!=KErrNone && r!=KErrNotFound && iAction!=EInternalRenameForMove && r!=KErrInUse) || (iAction == EInternalRmDir && r == KErrInUse))
2493 if (iLastError == KErrCancel && iNumberOfFilesProcessed==0 )
2495 iLastError=KErrCancel;
2496 iErrorInfo=ENoFilesProcessed;
2497 User::Leave(KErrCancel);
2500 if (iLastError==KErrNone && r==KErrNotFound && iNumberOfFilesProcessed==0)
2502 iLastError=KErrNotFound;
2503 iErrorInfo=ENoFilesProcessed;
2504 User::Leave(KErrNotFound);
2508 void CFileMan::SetFlags(TBool anOverWrite,TBool aRecurse,TBool aScanDownTree,TBool aMoveRename)
2510 // Set or clear flags
2516 iSwitches|=KRecurseFlag;
2518 iSwitches|=KOverWriteFlag;
2520 iSwitches|=KScanDownFlag;
2522 iSwitches|=KMoveRenameFlag;
2526 EXPORT_C TInt CFileMan::Copy(const RFile& anOld, const TDesC& aNew, TUint aSwitches)
2528 Copies from an open file handle to a destination file name.
2530 This is a synchronous function.
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)
2536 Error codes may be retrieved using CFileBase::GetLastError().
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.
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
2555 @return KErrNone if successful, otherwise one of the other system-wide error codes.
2557 @see CFileBase::GetLastError()
2558 @see CFileMan::Move()
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.
2566 TRACEMULT4(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy3, MODULEUID,
2567 (TUint) this, anOld.SubSessionHandle(), aNew, aSwitches);
2570 if (iSwitches&KFManBusyFlag)
2574 // The only switch that is legal for single file copies is EOverWrite
2575 else if ((aSwitches & ~EOverWrite) != 0)
2582 SetFlags(aSwitches & EOverWrite, EFalse, EFalse, EFalse);
2584 // need to signal to CFileBase that we're copying from a handle
2585 // and that iSrcFile is invalid
2586 iSwitches|= KCopyFromHandle;
2589 RETURNIFERROR(r, iFs.Parse(aNew, iTrgFile),UTraceModuleEfsrv::ECFileManCopy3Return);
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);
2595 iAction = EInternalCopyFromHandle;
2596 iNumberOfFilesProcessed = 0;
2598 ret=(r==KErrNone) ? iLastError : r;
2602 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy3Return, MODULEUID, ret);
2606 EXPORT_C TInt CFileMan::Copy(const RFile& anOld,const TDesC& aNew,TUint aSwitches,TRequestStatus& aStatus)
2608 Copies from an open file handle to a destination file name.
2610 This is an asynchronous function.
2611 Its behaviour is the same as the synchronous overload.
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.
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
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
2630 @see CFileBase::GetLastError()
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.
2638 TRACEMULT5(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy4, MODULEUID,
2639 (TUint) this, anOld.SubSessionHandle(), aNew, aSwitches, (TUint) &aStatus);
2642 if (iSwitches&KFManBusyFlag)
2649 r = Copy(anOld,aNew,aSwitches);
2652 TRACERET1(UTF::EBorder, UTraceModuleEfsrv::ECFileManCopy4Return, MODULEUID, r);
2656 void CFileMan::DoCopyFromHandleL()
2658 // Copy from open file handle
2662 TFileName& trgName = iTmpName1;
2664 if (iTrgFile.NamePresent())
2666 trgName = iTrgFile.FullName();
2670 iSrcFileHandle.Name(trgName);
2671 if ((trgName.Length() + iTrgFile.DriveAndPath().Length()) > KMaxFileName)
2673 iSrcFileHandle.Close();
2674 User::Leave(KErrBadName);
2676 trgName.Insert(0, iTrgFile.DriveAndPath());
2679 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
2686 if ((iSwitches&KOverWriteFlag)==0)
2687 r=trgFile.Create(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
2689 r=trgFile.Replace(iFs,trgName,EFileWrite|EFileWriteDirectIO|EFileShareExclusive);
2691 iErrorInfo = ETrgOpenFailed;
2694 r = DoCopy(iSrcFileHandle, trgFile, ret);
2696 // close the (duplicated) source file handle
2697 iSrcFileHandle.Close();
2700 if (ret == MFileManObserver::ECancel || (r!=KErrNone && r!=KErrAlreadyExists && iErrorInfo!=ETrgOpenFailed))
2701 iFs.Delete(trgName);
2702 User::LeaveIfError(r);
2705 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
2706 TInt CFileMan::DoCopy(const RFile& aSrcFile, RFile& aDstFile, TInt& aRet)
2710 TInt CFileMan::DoCopy(const RFile64& aSrcFile, RFile64& aDstFile, TInt& aRet)
2714 RETURNIFERRORD(r,aSrcFile.Size(rem),EFalse);
2715 RETURNIFERROR(r, aDstFile.SetSize(rem),EFalse);
2717 HBufC8* bufPtr = NULL;
2718 bufPtr = AllocateBuffer(rem);
2720 return KErrNoMemory;
2721 TPtr8 copyBuf=bufPtr->Des();
2723 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
2728 aRet = MFileManObserver::EContinue;
2729 while(rem && aRet == MFileManObserver::EContinue)
2731 #ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
2732 TInt s=Min(rem,copyBuf.MaxSize());
2734 // Min result shall be of TInt size
2735 TInt s=(TInt)(Min(rem,(TInt64)copyBuf.MaxSize()));
2737 r=aSrcFile.Read(pos,copyBuf,s);
2738 if (r==KErrNone && copyBuf.Length()!=s)
2741 r=aDstFile.Write(pos,copyBuf,s);
2746 iBytesTransferred = s;
2747 aRet = (iObserver) ? iObserver->NotifyFileManOperation() : MFileManObserver::EContinue;
2748 if (aRet != MFileManObserver::EContinue && aRet != MFileManObserver::ECancel)
2749 Panic(EFManBadValueFromObserver);
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
2756 r = aDstFile.Flush();
2758 if (aRet != MFileManObserver::ECancel)
2762 r = aSrcFile.Modified(lastMod);
2764 r = aDstFile.SetModified(lastMod);
2766 TUint fileAttributes=0;
2768 r = aSrcFile.Att(fileAttributes);
2770 r = aDstFile.SetAtt(fileAttributes,(~fileAttributes)&KEntryAttMaskSupported);
2773 r = aDstFile.Flush();