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