--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filebrowser/src/FBFileOps.cpp Wed Sep 01 12:30:35 2010 +0100
@@ -0,0 +1,1162 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+// INCLUDE FILES
+#include "FBFileOps.h"
+#include "FBFileUtils.h"
+#include "FBModel.h"
+#include "FBTraces.h"
+
+#ifndef FILEBROWSER_LITE
+ #include "FBFileOpClient.h"
+#endif
+
+#include <f32file.h>
+#include <bautils.h>
+#include <eikenv.h>
+#include <babackup.h>
+
+const TInt KSecureBackupStartDelay = 750000;
+const TInt KSecureBackupLoopDelay = 100000;
+const TInt KSecureBackupEndDelay = 200000;
+const TInt KMaxFileLockAttempts = 3;
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+CFileBrowserFileOps* CFileBrowserFileOps::NewL(CFileBrowserModel* aModel)
+ {
+ CFileBrowserFileOps* self = new(ELeave) CFileBrowserFileOps(aModel);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+CFileBrowserFileOps::CFileBrowserFileOps(CFileBrowserModel* aModel) : iModel(aModel)
+ {
+ }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileOps::ConstructL()
+ {
+ iRecursiveState = EFileOpInvalid;
+ iSecureBackUpActive = EFalse;
+ iFileCommandActivatedSecureBackup = EFalse;
+
+ User::LeaveIfError(iFs.Connect());
+ iFileMan = CFileMan::NewL( iFs, this );
+ }
+
+// --------------------------------------------------------------------------------------------
+
+CFileBrowserFileOps::~CFileBrowserFileOps()
+ {
+ if (iSBEClient)
+ delete iSBEClient;
+
+ #ifndef FILEBROWSER_LITE
+ if (iFileOpClient)
+ delete iFileOpClient;
+ #endif
+
+ delete iFileMan;
+ iFs.Close();
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::ActivateSecureBackUpViaFileOp()
+ {
+ iFileManObserverResult = MFileManObserver::EContinue;
+ // if already activate by a file command, return ok
+ if (iFileCommandActivatedSecureBackup)
+ return KErrNone;
+ else
+ {
+ // if secure backup is already active, disable it first, because it may in wrong state
+ if (iSecureBackUpActive)
+ DeActivateSecureBackUp();
+ }
+
+ // try to activate full secure backup
+ TInt err = ActivateSecureBackUp(conn::EBURBackupFull, conn::EBackupBase);
+
+ if (err == KErrNone)
+ iFileCommandActivatedSecureBackup = ETrue;
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DeActivateSecureBackUpViaFileOp()
+ {
+ TInt err(KErrGeneral);
+ iFileManObserverResult = MFileManObserver::EContinue;
+
+ // if activate by a file command, try to reactivate it
+ if (iFileCommandActivatedSecureBackup)
+ {
+ err = DeActivateSecureBackUp();
+
+ // even if it fails, forget the state
+ iFileCommandActivatedSecureBackup = EFalse;
+ }
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::ActivateSecureBackUp(conn::TBURPartType aPartType, conn::TBackupIncType aBackupIncType)
+ {
+ iFileManObserverResult = MFileManObserver::EContinue;
+ // check for invalid parameters
+ if (aPartType == conn::EBURNormal || aBackupIncType == conn::ENoBackup)
+ User::Panic(_L("Inv.Usage.SE"), 532);
+
+ TInt err(KErrNone);
+
+ if (!iSBEClient)
+ {
+ TRAP(err, iSBEClient = conn::CSBEClient::NewL());
+ if (err != KErrNone)
+ return err;
+ }
+
+ TDriveList driveList;
+ err = iFs.DriveList(driveList);
+
+ if (err == KErrNone)
+ {
+ // make sure that the application has a system status to prevent getting shut down events
+ iModel->EikonEnv()->SetSystem(ETrue);
+
+ // activating secure back up removes locks from files which respect this fuctionality
+ TRAP(err, iSBEClient->SetBURModeL(driveList, aPartType, aBackupIncType));
+
+ if (err == KErrNone)
+ {
+ iSecureBackUpActive = ETrue;
+ User::After(KSecureBackupStartDelay); // a short delay to wait to activate
+ }
+ }
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DeActivateSecureBackUp()
+ {
+ TInt err(KErrNone);
+
+ if (!iSBEClient)
+ {
+ TRAP(err, iSBEClient = conn::CSBEClient::NewL());
+ if (err != KErrNone)
+ return err;
+
+ // make sure that the application has a system status
+ iModel->EikonEnv()->SetSystem(ETrue);
+ }
+
+ TDriveList driveList;
+ err = iFs.DriveList(driveList);
+
+ if (err == KErrNone)
+ {
+ // deactivate secure backup
+ TRAP(err, iSBEClient->SetBURModeL(driveList, conn::EBURNormal, conn::ENoBackup));
+
+ User::After(KSecureBackupEndDelay); // a short delay to wait to deactivate
+
+ // system status not needed anymore
+ iModel->EikonEnv()->SetSystem(EFalse);
+ }
+
+ iSecureBackUpActive = EFalse;
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFindEntries(const TDesC& aFileName, const TDesC& aPath)
+ {
+ TFindFile fileFinder(iFs);
+ CDir* dir;
+ TInt err = fileFinder.FindWildByPath(aFileName, &aPath, dir);
+
+ while (err == KErrNone && iFileManObserverResult != MFileManObserver::ECancel)
+ {
+ for (TInt i=0; i<dir->Count(); i++)
+ {
+ TEntry entry = (*dir)[i];
+
+ if (entry.iName.Length() && aPath.Length())
+ {
+ // parse the entry
+ TParse parsedName;
+ parsedName.Set(entry.iName, &fileFinder.File(), NULL);
+
+ if (parsedName.Drive().Length() && aPath.Length() && parsedName.Drive()[0] == aPath[0])
+ {
+ // get full source path
+ TFileName fullSourcePath = parsedName.FullName();
+ if (entry.IsDir())
+ fullSourcePath.Append(_L("\\"));
+
+ // call the file operation command
+ switch(iRecursiveState)
+ {
+ case EFileOpAttribs:
+ {
+ // the same attribs command can be given for both directories and files
+ FileOpAttribs(fullSourcePath, iUint1, iUint2, iTime1, iUint3);
+ }
+ break;
+
+ case EFileOpCopy:
+ {
+ // calculate length of new entries added to the original source path
+ TUint newEntriesLength = fullSourcePath.Length() - iBuf1.Length();
+
+ // get pointer description to the rightmost data
+ TPtr16 newEntriesPtr = fullSourcePath.RightTPtr(newEntriesLength);
+
+ // generate target path
+ TFileName fullTargetPath = iBuf2;
+ fullTargetPath.Append(newEntriesPtr);
+
+ if (entry.IsDir())
+ {
+ // if it is a directory entry, just create it based on the entry's attributes
+ FileOpMkDirAll(fullTargetPath, entry.iAtt);
+ }
+ else
+ {
+ // otherwise copy the file
+ FileOpCopy(fullSourcePath, fullTargetPath, iUint1);
+ }
+ }
+ break;
+
+ case EFileOpDelete:
+ {
+ if (entry.IsDir())
+ {
+ // for directories call rmdir
+ FileOpRmDir(fullSourcePath, iUint1);
+ }
+ else
+ {
+ // for files call the normal file deletion operation
+ FileOpDeleteFile(fullSourcePath, iUint1);
+ }
+ }
+ break;
+
+ default:
+ User::Panic (_L("FileOpRecurs"), 775);
+ break;
+ }
+ }
+ }
+ if ( iFileManObserverResult == MFileManObserver::ECancel ) break;
+ }
+
+ delete dir;
+ dir = NULL;
+ if ( iFileManObserverResult != MFileManObserver::ECancel )
+ {
+ err = fileFinder.FindWild(dir);
+ }
+ }
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFindEntriesRecursiveL(const TDesC& aFileName, const TDesC& aPath)
+ {
+ TInt err(KErrNone);
+
+ // it is logical to scan upwards when deleting and changing attributes
+ CDirScan::TScanDirection scanDirection = CDirScan::EScanUpTree;
+
+ // when copying files, it is more logical to move downwards
+ if (iRecursiveState == EFileOpCopy)
+ scanDirection = CDirScan::EScanDownTree;
+
+
+ CDirScan* scan = CDirScan::NewLC(iFs);
+ scan->SetScanDataL(aPath, KEntryAttDir|KEntryAttMatchMask, ESortByName | EAscending | EDirsFirst, scanDirection);
+ CDir* dir = NULL;
+
+ for(;;)
+ {
+ TRAP(err, scan->NextL(dir));
+ if (!dir || (err != KErrNone))
+ break;
+
+ for (TInt i=0; i<dir->Count(); i++)
+ {
+ TEntry entry = (*dir)[i];
+
+ if (entry.IsDir())
+ {
+ TFileName path(scan->FullPath());
+
+ if (path.Length())
+ {
+ path.Append(entry.iName);
+ path.Append(_L("\\"));
+ // test path.Left(iBuf2.Length()).Compare(iBuf2) - to prevent never ending recursive copy (in case of copy folder under itself)
+ if( iRecursiveState == EFileOpCopy && path.Left(iBuf2.Length()).Compare(iBuf2) )
+ {
+ DoFindEntries(aFileName, path);
+ }
+ }
+ }
+ if ( iFileManObserverResult == MFileManObserver::ECancel )
+ {
+ break;
+ }
+ }
+ delete(dir);
+ if ( iFileManObserverResult == MFileManObserver::ECancel )
+ {
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(scan);
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::Copy(const TFileEntry& aSourceEntry, const TDesC& aTargetFullName, TUint aSwitch, TBool aDeleteSource)
+ {
+ iOperationError = KErrNone;
+ iFileManObserverResult = MFileManObserver::EContinue;
+
+ TFileName sourcePath = aSourceEntry.iPath;
+ sourcePath.Append(aSourceEntry.iEntry.iName);
+
+ TInt err(KErrNone);
+
+ if (aSourceEntry.iEntry.IsDir() && (aSwitch & CFileMan::ERecurse))
+ {
+ // find all files recursively and run the operation for them
+ iRecursiveState = EFileOpCopy;
+ sourcePath.Append(_L("\\"));
+
+ TFileName targetPath = aTargetFullName;
+ targetPath.Append(_L("\\"));
+
+ // remove the recursion flag because we will implement our own recursion
+ TUint newSwitch(aSwitch);
+ newSwitch &= ~CFileMan::ERecurse;
+
+ iBuf1.Copy(sourcePath);
+ iBuf2.Copy(targetPath);
+ iUint1 = newSwitch;
+
+ // create initial directory - if it does not succeed, do not even try to continue
+ err = FileOpMkDirAll(targetPath, aSourceEntry.iEntry.iAtt);
+
+ if (iOperationError == KErrNone)
+ {
+ TRAP(err, DoFindEntries(_L("*"), sourcePath)); // entries under current directory entry
+ if ( iFileManObserverResult != MFileManObserver::ECancel )
+ {
+ TRAP(err, DoFindEntriesRecursiveL(_L("*"), sourcePath)); // recursively under directories of current directory entry
+ }
+ }
+ }
+
+ else if (aSourceEntry.iEntry.IsDir())
+ {
+ TFileName targetPath = aTargetFullName;
+ targetPath.Append(_L("\\"));
+
+ // just create a directory based on the file attributes of the source directory
+ err = FileOpMkDirAll(targetPath, aSourceEntry.iEntry.iAtt);
+ }
+
+ else
+ {
+ // remove a recursion flag if present (this should never happen, but some extra error checking)
+ if (aSwitch & CFileMan::ERecurse)
+ aSwitch &= ~CFileMan::ERecurse;
+
+ // do the operation for a file entry
+ err = FileOpCopy(sourcePath, aTargetFullName, aSwitch);
+ }
+
+
+ // delete source if needed and copy succeeded without any errors (== move operation)
+ if ( aDeleteSource && iOperationError == KErrNone &&
+ iFileManObserverResult != MFileManObserver::ECancel )
+ {
+ err = Delete(aSourceEntry, aSwitch);
+ }
+
+ if ( !iOperationError && iFileManObserverResult == MFileManObserver::ECancel )
+ {
+ iOperationError = KErrCancel;
+ }
+
+ return iOperationError;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::FileOpCopy(const TDesC& aSourceFullName, const TDesC& aTargetFullName, TUint aSwitch)
+ {
+ TInt err = DoFileOpCopy(aSourceFullName, aTargetFullName, aSwitch);
+
+ // if locked, unlock the file and retry
+ if (iModel->Settings().iRemoveFileLocks && err == KErrInUse)
+ {
+ // try to remove the file lock by activating secure backup mode
+ if (ActivateSecureBackUpViaFileOp() == KErrNone)
+ {
+ // try the operation several times
+ for (TInt i=0; i<KMaxFileLockAttempts; i++)
+ {
+ err = DoFileOpCopy(aSourceFullName, aTargetFullName, aSwitch);
+
+ if (err != KErrInUse)
+ break;
+ else
+ User::After(KSecureBackupLoopDelay);
+ }
+ }
+ }
+
+ // if access denied, then try to remove the target path and try again
+ if (iModel->Settings().iIgnoreProtectionsAtts && err == KErrAccessDenied && BaflUtils::FileExists(iFs, aTargetFullName))
+ {
+ if (FileOpDeleteFile(aTargetFullName, 0) == KErrNone)
+ {
+ err = DoFileOpCopy(aSourceFullName, aTargetFullName, aSwitch);
+ }
+ }
+
+ // if the file already exists, it is not an error
+ if (err == KErrAlreadyExists)
+ err = KErrNone;
+
+
+ // if copying from a ROM drive, remove the writing protection flag
+ if (iModel->Settings().iRemoveROMWriteProrection && err == KErrNone && aSourceFullName.Length() > 3 && (aSourceFullName[0]=='z' || aSourceFullName[0]=='Z'))
+ {
+ FileOpAttribs(aTargetFullName, 0, KEntryAttReadOnly, 0, 0);
+ }
+
+
+ // remember the "lowest" error
+ if (err < iOperationError)
+ iOperationError = err;
+
+ LOGSTRING4("FileBrowser: FileOpCopy %S -> %S, err=%d", &aSourceFullName, &aTargetFullName, err);
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFileOpCopy(const TDesC& aSourceFullName, const TDesC& aTargetFullName, TUint aSwitch)
+ {
+ #ifndef FILEBROWSER_LITE
+ if (iModel->Settings().iBypassPlatformSecurity)
+ {
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->Copy(aSourceFullName, aTargetFullName, aSwitch);
+ }
+ else
+ {
+ #endif
+ CAsyncWaiter* waiter = CAsyncWaiter::NewLC();
+ TInt result = iFileMan->Copy( aSourceFullName, aTargetFullName, aSwitch, waiter->iStatus );
+ waiter->StartAndWait();
+ if ( !result ) result = waiter->Result();
+ CleanupStack::PopAndDestroy( waiter );
+ return result;
+ #ifndef FILEBROWSER_LITE
+ }
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::Rename(const TFileEntry& aSourceEntry, const TDesC& aNew, TUint aSwitch)
+ {
+ iOperationError = KErrNone;
+ iFileManObserverResult = MFileManObserver::EContinue;
+
+ TFileName sourcePath = aSourceEntry.iPath;
+ sourcePath.Append(aSourceEntry.iEntry.iName);
+
+ if (aSourceEntry.iEntry.IsDir())
+ {
+ // do the operation for a directory entry
+ FileOpRename(sourcePath, aNew, aSwitch);
+ }
+ else
+ {
+ // do the operation for a file
+ FileOpRename(sourcePath, aNew, aSwitch);
+ }
+
+ return iOperationError;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::FileOpRename(const TDesC& aName, const TDesC& aNew, TUint aSwitch)
+ {
+ TBool setBackROFlag(EFalse);
+
+ TInt err = DoFileOpRename(aName, aNew, aSwitch);
+
+ // if locked, unlock the file and retry
+ if (iModel->Settings().iRemoveFileLocks && err == KErrInUse)
+ {
+ // try to remove the file lock by activating secure backup mode
+ if (ActivateSecureBackUpViaFileOp() == KErrNone)
+ {
+ // try the operation several times
+ for (TInt i=0; i<KMaxFileLockAttempts; i++)
+ {
+ err = DoFileOpRename(aName, aNew, aSwitch);
+
+ if (err != KErrInUse)
+ break;
+ else
+ User::After(KSecureBackupLoopDelay);
+ }
+ }
+ }
+
+ // if write protected, remove protection and retry
+ else if (iModel->Settings().iIgnoreProtectionsAtts && err == KErrAccessDenied)
+ {
+ // remove write protection and try again
+ if (FileOpAttribs(aName, 0, KEntryAttReadOnly, 0, 0) == KErrNone)
+ {
+ err = DoFileOpRename(aName, aNew, aSwitch);
+
+ setBackROFlag = ETrue;
+ }
+ }
+
+ // if still access denied, then try to remove the target path and try again
+ if (iModel->Settings().iIgnoreProtectionsAtts && err == KErrAccessDenied && BaflUtils::FileExists(iFs, aNew))
+ {
+ if (FileOpDeleteFile(aNew, 0) == KErrNone)
+ {
+ err = DoFileOpRename(aName, aNew, aSwitch);
+ }
+ }
+
+ // set back the read only flag
+ if (setBackROFlag)
+ FileOpAttribs(aName, KEntryAttReadOnly, 0, 0, 0);
+
+
+ // remember the "lowest" error
+ if (err < iOperationError)
+ iOperationError = err;
+
+ LOGSTRING3("FileBrowser: FileOpRename %S, err=%d", &aName, err);
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFileOpRename(const TDesC& aName, const TDesC& aNew, TUint aSwitch)
+ {
+ #ifndef FILEBROWSER_LITE
+ if (iModel->Settings().iBypassPlatformSecurity)
+ {
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->Rename(aName, aNew, aSwitch);
+ }
+ else
+ {
+ #endif
+ return iFileMan->Rename(aName, aNew, aSwitch);
+ #ifndef FILEBROWSER_LITE
+ }
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::Attribs(const TFileEntry& aSourceEntry, TUint aSetMask, TUint aClearMask, const TTime& aTime, TUint aSwitch)
+ {
+ iOperationError = KErrNone;
+ iFileManObserverResult = MFileManObserver::EContinue;
+
+ TFileName sourcePath = aSourceEntry.iPath;
+ sourcePath.Append(aSourceEntry.iEntry.iName);
+
+ TInt err(KErrNone);
+
+ if (aSourceEntry.iEntry.IsDir() && (aSwitch & CFileMan::ERecurse))
+ {
+ // do the operation for a current directory entry
+ err = FileOpAttribs(sourcePath, aSetMask, aClearMask, aTime, 0);
+
+ // find all files recursively and run the operation for them
+ iRecursiveState = EFileOpAttribs;
+ sourcePath.Append(_L("\\"));
+
+ iBuf1.Copy(sourcePath);
+ iUint1 = aSetMask;
+ iUint2 = aClearMask;
+ iTime1 = aTime;
+ iUint3 = 0;
+
+ TRAP(err, DoFindEntriesRecursiveL(_L("*"), sourcePath)); // recursively under directories of current directory entry
+ TRAP(err, DoFindEntries(_L("*"), sourcePath)); // entries under current directory entry
+ }
+
+ else if (aSourceEntry.iEntry.IsDir())
+ {
+ //sourcePath.Append(_L("\\")); // <-- do not apply!
+
+ // do the operation for a directory entry
+ err = FileOpAttribs(sourcePath, aSetMask, aClearMask, aTime, 0);
+ }
+
+ else
+ {
+ // do the operation for a file entry
+ err = FileOpAttribs(sourcePath, aSetMask, aClearMask, aTime, 0);
+ }
+
+ return iOperationError;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::FileOpAttribs(const TDesC& aName, TUint aSetMask, TUint aClearMask, const TTime& aTime, TUint aSwitch)
+ {
+ TInt err = DoFileOpAttribs(aName, aSetMask, aClearMask, aTime, aSwitch);
+
+ // if locked, unlock the file and retry
+ if (iModel->Settings().iRemoveFileLocks && err == KErrInUse)
+ {
+ // try to remove the file lock by activating secure backup mode
+ if (ActivateSecureBackUpViaFileOp() == KErrNone)
+ {
+ // try the operation several times
+ for (TInt i=0; i<KMaxFileLockAttempts; i++)
+ {
+ err = DoFileOpAttribs(aName, aSetMask, aClearMask, aTime, aSwitch);
+
+ if (err != KErrInUse)
+ break;
+ else
+ User::After(KSecureBackupLoopDelay);
+ }
+ }
+ }
+
+ // remember the "lowest" error
+ if (err < iOperationError)
+ iOperationError = err;
+
+ LOGSTRING3("FileBrowser: FileOpAttribs %S, err=%d", &aName, err);
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFileOpAttribs(const TDesC& aName, TUint aSetMask, TUint aClearMask, const TTime& aTime, TUint aSwitch)
+ {
+ #ifndef FILEBROWSER_LITE
+ if (iModel->Settings().iBypassPlatformSecurity)
+ {
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->Attribs(aName, aSetMask, aClearMask, aTime, aSwitch);
+ }
+ else
+ {
+ #endif
+ return iFileMan->Attribs(aName, aSetMask, aClearMask, aTime, aSwitch);
+ #ifndef FILEBROWSER_LITE
+ }
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::Delete(const TFileEntry& aSourceEntry, TUint aSwitch)
+ {
+ iOperationError = KErrNone;
+ iFileManObserverResult = MFileManObserver::EContinue;
+
+ TFileName sourcePath = aSourceEntry.iPath;
+ sourcePath.Append(aSourceEntry.iEntry.iName);
+
+ TInt err(KErrNone);
+
+ if (aSourceEntry.iEntry.IsDir() && (aSwitch & CFileMan::ERecurse))
+ {
+ // find all files recursively and run the operation for them
+ iRecursiveState = EFileOpDelete;
+ sourcePath.Append(_L("\\"));
+
+ iBuf1.Copy(sourcePath);
+ iUint1 = 0;
+
+ TRAP(err, DoFindEntriesRecursiveL(_L("*"), sourcePath)); // recursively under directories of current directory entry
+ if ( iFileManObserverResult != MFileManObserver::ECancel )
+ {
+ TRAP(err, DoFindEntries(_L("*"), sourcePath)); // entries under current directory entry
+ }
+
+ if ( iFileManObserverResult != MFileManObserver::ECancel )
+ {
+ // do the operation for a current directory entry as well
+ err = FileOpRmDir(sourcePath, 0);
+ }
+ }
+
+ else if (aSourceEntry.iEntry.IsDir())
+ {
+ sourcePath.Append(_L("\\"));
+
+ // do the operation for a directory entry
+ err = FileOpRmDir(sourcePath, 0);
+ }
+
+ else
+ {
+ // do the operation for a file entry
+ err = FileOpDeleteFile(sourcePath, 0);
+ }
+ if ( !iOperationError && iFileManObserverResult == MFileManObserver::ECancel )
+ {
+ iOperationError = KErrCancel;
+ }
+ return iOperationError;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::FileOpDeleteFile(const TDesC& aName, TUint aSwitch)
+ {
+ TInt err = DoFileOpDeleteFile(aName, aSwitch);
+
+ // if locked, unlock the file and retry
+ if (iModel->Settings().iRemoveFileLocks && err == KErrInUse)
+ {
+ // try to remove the file lock by activating secure backup mode
+ if (ActivateSecureBackUpViaFileOp() == KErrNone)
+ {
+ // try the operation several times
+ for (TInt i=0; i<KMaxFileLockAttempts; i++)
+ {
+ err = DoFileOpDeleteFile(aName, aSwitch);
+
+ if (err != KErrInUse)
+ break;
+ else
+ User::After(KSecureBackupLoopDelay);
+ }
+ }
+ }
+
+ // if write protected or system file, remove protections and retry
+ else if (iModel->Settings().iIgnoreProtectionsAtts && (err == KErrAccessDenied || err == KErrNotFound))
+ {
+ // remove protections and try again
+ if (FileOpAttribs(aName, 0, KEntryAttReadOnly|KEntryAttSystem|KEntryAttHidden, 0, 0) == KErrNone)
+ {
+ err = DoFileOpDeleteFile(aName, aSwitch);
+ }
+ }
+
+ // remember the "lowest" error
+ if (err < iOperationError)
+ iOperationError = err;
+
+ LOGSTRING3("FileBrowser: FileOpDeleteFile %S, err=%d", &aName, err);
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFileOpDeleteFile(const TDesC& aName, TUint aSwitch)
+ {
+ #ifndef FILEBROWSER_LITE
+ if (iModel->Settings().iBypassPlatformSecurity)
+ {
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->Delete(aName, aSwitch);
+ }
+ else
+ {
+ #endif
+ CAsyncWaiter* waiter = CAsyncWaiter::NewLC();
+ TInt result = iFileMan->Delete( aName, aSwitch, waiter->iStatus );
+ waiter->StartAndWait();
+ if ( iFileManObserverResult == MFileManObserver::ECancel ) result = KErrCancel;
+ if ( !result ) result = waiter->Result();
+ CleanupStack::PopAndDestroy( waiter );
+ return result;
+ #ifndef FILEBROWSER_LITE
+ }
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::FileOpRmDir(const TDesC& aName, TUint aSwitch)
+ {
+ TInt err = DoFileOpRmDir(aName, aSwitch);
+
+ // if write protected or system directory, remove protections and retry
+ if (iModel->Settings().iIgnoreProtectionsAtts && (err == KErrAccessDenied || err == KErrInUse))
+ {
+ // remove protections and try again
+ if (FileOpAttribs(aName.Left(aName.Length()-1), 0, KEntryAttReadOnly|KEntryAttSystem|KEntryAttHidden, 0, 0) == KErrNone)
+ {
+ err = DoFileOpRmDir(aName, aSwitch);
+ }
+ }
+
+ // remember the "lowest" error
+ if (err < iOperationError)
+ iOperationError = err;
+
+ LOGSTRING3("FileBrowser: FileOpRmDir %S, err=%d", &aName, err);
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFileOpRmDir(const TDesC& aDirName, TUint aSwitch)
+ {
+ #ifndef FILEBROWSER_LITE
+ if (iModel->Settings().iBypassPlatformSecurity)
+ {
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->RmDir(aDirName, aSwitch);
+ }
+ else
+ {
+ #endif
+ if ( aSwitch & CFileMan::ERecurse )
+ {
+ CAsyncWaiter* waiter = CAsyncWaiter::NewLC();
+ TInt result = iFileMan->RmDir( aDirName, waiter->iStatus );
+ waiter->StartAndWait();
+ if ( iFileManObserverResult == MFileManObserver::ECancel ) result = KErrCancel;
+ if ( !result ) result = waiter->Result();
+ CleanupStack::PopAndDestroy( waiter);
+ return result;
+ }
+ else
+ return iFs.RmDir(aDirName);
+ #ifndef FILEBROWSER_LITE
+ }
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::MkDirAll(const TDesC& aPath, TInt aSetAtts, TBool aQuickOperation)
+ {
+ iFileManObserverResult = MFileManObserver::EContinue;
+ if (aQuickOperation)
+ return DoFileOpMkDirAll(aPath);
+ else
+ return FileOpMkDirAll(aPath, aSetAtts);
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::FileOpMkDirAll(const TDesC& aPath, TInt aSetAtts)
+ {
+ TInt err = DoFileOpMkDirAll(aPath);
+
+ // if the directory already exists, it is not an error
+ if (err == KErrAlreadyExists)
+ err = KErrNone;
+
+
+ // set attributes for directory just created
+ if (aSetAtts > 0 && err == KErrNone && aPath.Length() > 3)
+ {
+ // a path has a trailing backslash so it needs to be removed before the call
+ err = FileOpAttribs(aPath.Left(aPath.Length()-1), aSetAtts, 0, 0, 0);
+ }
+
+
+ // remember the "lowest" error
+ if (err < iOperationError)
+ iOperationError = err;
+
+ LOGSTRING3("FileBrowser: FileOpMkDirAll %S, err=%d", &aPath, err);
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFileOpMkDirAll(const TDesC& aPath)
+ {
+ #ifndef FILEBROWSER_LITE
+ if (iModel->Settings().iBypassPlatformSecurity)
+ {
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->MkDirAll(aPath);
+ }
+ else
+ {
+ #endif
+ return iFs.MkDirAll(aPath);
+ #ifndef FILEBROWSER_LITE
+ }
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::CreateEmptyFile(const TDesC& aName)
+ {
+ return DoFileOpCreateEmptyFile(aName);
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::FileOpCreateEmptyFile(const TDesC& aName)
+ {
+ TInt err = DoFileOpCreateEmptyFile(aName);
+
+ // remember the "lowest" error
+ if (err < iOperationError)
+ iOperationError = err;
+
+ LOGSTRING3("FileBrowser: FileOpCreateEmptyFile %S, err=%d", &aName, err);
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DoFileOpCreateEmptyFile(const TDesC& aName)
+ {
+ #ifndef FILEBROWSER_LITE
+ if (iModel->Settings().iBypassPlatformSecurity)
+ {
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->CreateEmptyFile(aName);
+ }
+ else
+ {
+ #endif
+ TInt err(KErrNone);
+
+ RFile newFile;
+ err = newFile.Create(iFs, aName, EFileShareExclusive);
+ if (err == KErrNone)
+ err = newFile.Flush();
+ newFile.Close();
+
+ return err;
+ #ifndef FILEBROWSER_LITE
+ }
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::DriveSnapShot(TChar aSourceDriveLetter, TChar aTargetDriveLetter)
+ {
+ TInt err(KErrNone);
+ iFileManObserverResult = MFileManObserver::EContinue;
+
+ // remember old settings and force them to be true for this operation
+ TBool currentRemoveFileLocksValue = iModel->Settings().iRemoveFileLocks;
+ TBool currentIgnoreProtectionAttsValue = iModel->Settings().iIgnoreProtectionsAtts;
+ TBool currentRemoveROMWriteProrection = iModel->Settings().iRemoveROMWriteProrection;
+ iModel->Settings().iRemoveFileLocks = ETrue;
+ iModel->Settings().iIgnoreProtectionsAtts = ETrue;
+ iModel->Settings().iRemoveROMWriteProrection = ETrue;
+
+
+ TFileName sourceDir;
+ sourceDir.Append(aSourceDriveLetter);
+ sourceDir.Append(_L(":"));
+
+ _LIT(KTargetDir, "%c:\\SnapShot_%c_drive");
+ TFileName targetDir;
+ targetDir.Format(KTargetDir, TUint(aTargetDriveLetter), TUint(aSourceDriveLetter));
+
+ // remove any existing content, first get TEntry
+ TEntry entry;
+ err = iFs.Entry(targetDir, entry);
+
+ // entry directory exists, delete it
+ if (err == KErrNone && entry.IsDir())
+ {
+ TFileName targetRoot;
+ targetRoot.Append(aTargetDriveLetter);
+ targetRoot.Append(_L(":\\"));
+
+ TFileEntry targetEntry;
+ targetEntry.iPath = targetRoot;
+ targetEntry.iEntry = entry;
+
+ err = Delete(targetEntry, CFileMan::ERecurse);
+ }
+
+ // do not care if removing succeeded or not, just continue with copying
+ TEntry fakeEntry;
+ fakeEntry.iAtt |= KEntryAttDir;
+
+ TFileEntry sourceEntry;
+ sourceEntry.iPath = sourceDir;
+ sourceEntry.iEntry = fakeEntry;
+
+ err = Copy(sourceEntry, targetDir, CFileMan::ERecurse|CFileMan::EOverWrite);
+
+
+ // restore back settings
+ iModel->Settings().iRemoveFileLocks = currentRemoveFileLocksValue;
+ iModel->Settings().iIgnoreProtectionsAtts = currentIgnoreProtectionAttsValue;
+ iModel->Settings().iRemoveROMWriteProrection = currentRemoveROMWriteProrection;
+
+
+ return iOperationError;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::EraseMBR(TUint aDriveNumber)
+ {
+ #ifndef FILEBROWSER_LITE
+
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->EraseMBR(aDriveNumber);
+
+ #else
+ return KErrNotSupported;
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt CFileBrowserFileOps::PartitionDrive(TUint aDriveNumber, TUint aNumberOfPartitions)
+ {
+ #ifndef FILEBROWSER_LITE
+
+ if (!iFileOpClient)
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ return iFileOpClient->PartitionDrive(aDriveNumber, aNumberOfPartitions);
+
+ #else
+ return KErrNotSupported
+ #endif
+ }
+
+// --------------------------------------------------------------------------------------------
+
+MFileManObserver::TControl CFileBrowserFileOps::NotifyFileManStarted()
+ {
+ return iFileManObserverResult;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+MFileManObserver::TControl CFileBrowserFileOps::NotifyFileManOperation()
+ {
+ return iFileManObserverResult;
+ }
+// --------------------------------------------------------------------------------------------
+
+MFileManObserver::TControl CFileBrowserFileOps::NotifyFileManEnded()
+ {
+ return iFileManObserverResult;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+void CFileBrowserFileOps::CancelOp()
+ {
+#ifndef FILEBROWSER_LITE
+
+ if ( iModel->Settings().iBypassPlatformSecurity )
+ {
+ if ( !iFileOpClient )
+ iFileOpClient = CFBFileOpClient::NewL();
+
+ iFileOpClient->CancelOp();
+ }
+
+ // we need this information even when using iFileOpClient
+ // to be able to not execute aggregate operations
+ iFileManObserverResult = MFileManObserver::ECancel;
+
+#else
+ iFileManObserverResult = MFileManObserver::ECancel;
+#endif
+ }
+
+// End of File