chxavfilestore.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:38k
- /************************************************************************
- * chxavfilestore.cpp
- * ------------------
- *
- * Synopsis:
- * simple file system abstraction for manipulating files and folders;
- * maintains 'root' (relative to true filesystem) 'current' folder
- * state
- *
- * root path is stored in full form, e.g.: c:realmedia
- * folder is stored in relative form, fully specified, e.g.:
- * = root
- * music = subfolder music
- *
- * the term 'item' (as used in this class) refers to a file or folder
- * that is in the current entry list; the entry list contains a list
- * of files and folders within the current folder
- *
- * Target:
- * Symbian OS
- *
- *
- * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
- *
- ************************************************************************/
- // Symbian includes...
- #include <coeutils.h>
- #include <eikfutil.h>
- #include <f32file.h> // TSwitch, CFileMan
- // Helix includes...
- // Include from this project...
- #include "chxavfilestore.h"
- #include "chxavdirectoryreader.h"
- #include "chxavfileutil.h"
- #include "chxavutil.h"
- #include "chxavmisc.h"
- #include "chxavstringutils.h"
- #include "hxsym_leaveutil.h"
- #include "hxsym_debug.h"
- CHXAvFileStore::CHXAvFileStore()
- : m_pFullPath(0)
- , m_bNeedRefresh(true)
- , m_pFileMan(0)
- , m_pObserver(0)
- , m_cbFileOp(0)
- , m_suspendRefreshSem(0)
- , m_bHaveOutstandingFileSystemEvent(false)
- {
- }
- CHXAvFileStore::~CHXAvFileStore()
- {
- HX_DELETE(m_pFullPath);
- HX_DELETE(m_pFileMan);
- #if defined(ASYNC_COPYMOVE)
- CancelAsyncFileOp();
- #endif
- m_apaLsSess.Close();
- }
- ////////////////////////////////////////////////////////////
- //
- void CHXAvFileStore::ConstructL(const TDesC& root,
- const TDesC& path,
- bool bAutoCreateRoot)
- {
- m_apaLsSess.Connect();
- m_fsWatcher.ConstructL();
- // set callback for receiving fs event notifications
- m_fsWatcher.SetEventActionL
- (
- MakeCommand(this, &CHXAvFileStore::OnFileSystemEvent)
- );
- #if defined(ASYNC_COPYMOVE)
- // active object to run on asynch completion of file op
- m_pFileOpCompletion =
- new (ELeave) CHXAvActiveDisp<CHXAvFileStore>(this,
- &CHXAvFileStore::OnFileOpAsyncComplete,
- &CHXAvFileStore::OnFileOpAsyncCancel);
- CActiveScheduler::Add(m_pFileOpCompletion.raw_ptr());
- #endif
- // create, fill out and activate the listbox
- SetRootL(root, bAutoCreateRoot);
- SetCurrentPathL(path);
- RefreshEntryInfoL();
- RFs& fs = CCoeEnv::Static()->FsSession();
- m_pFileMan = CFileMan::NewL(fs, this /*observer*/);
- }
- ////////////////////////////////////////////////////////////
- // paths can be provided as relative to root (e.g., /media/myfolder/foo.rm)
- // or absolute ('e:/videos/)
- //
- // this decides which and returns a fully specified path with drive
- //
- //
- TFileName* CHXAvFileStore::AllocFullPathL(const TDesC& path,
- const TDesC& name,
- CHXAvFile::NameType type)
- {
- TFileName* pPath = 0;
- TInt idxDrive = CHXAvFile::GetDriveIndex(path);
- if(-1 != idxDrive)
- {
- // path has a drive; it is absolute
- pPath = CHXAvFile::AllocFileNameL(path, name, type);
- }
- else
- {
- // path is relative
- pPath = CHXAvFile::AllocFileNameL(GetRoot(), path, CHXAvFile::ntFolder);
- CHXAvFile::AppendPath(*pPath, name, type);
- }
- return pPath;
- }
- //////////////////////////////////////////////////////////////
- // return true if fullPathChild is path to file or folder immediately
- // under current path
- bool CHXAvFileStore::IsImmediateChild(const TDesC& fullPathChild)
- {
- TPtrC ptrFolder = CHXAvFile::GetParentFolder(fullPathChild);
- return (0 == ptrFolder.CompareF(*m_pFullPath));
- }
- //////////////////////////////////////////////////////////////
- // return true if fullPathParent is a parent of the current
- //
- bool CHXAvFileStore::IsParent(const TDesC& fullPathParent)
- {
- return CHXAvFile::IsSubPath(fullPathParent, *m_pFullPath);
- }
- ////////////////////////////////////////////////////////////
- // return true if the destination path matches the
- // path for the given item within the current path
- //
- // pathDest - relative or absolute path
- // idxItem - item in current path
- //
- bool CHXAvFileStore::IsSamePathL(const TDesC& pathDest, TInt idxItem)
- {
- bool bIsSame = false;
- // form "pathdest" + "name associated with item in current path"
- TFileName* pSrcPath = AllocFullPathL(idxItem);
- AUTO_PUSH_POP_DEL(pSrcPath);
- TFileName* pDestPath = AllocFullTargetPathL(pathDest, idxItem);
- AUTO_PUSH_POP_DEL(pDestPath);
- bIsSame = ( pSrcPath->CompareF(*pDestPath) == 0 );
- return bIsSame;
- }
- ////////////////////////////////////////////////////////////
- // called when fs watcher detects an event
- void CHXAvFileStore::OnFileSystemEvent()
- {
- DPRINTF(SYMP_FILE, ("FileStore::OnFileSystemEvent(): suspend count = %ldn", m_suspendRefreshSem));
- // flag that entry list is out of data
- m_bNeedRefresh = true;
- if(m_suspendRefreshSem > 0)
- {
- // keep track of fact that we got file system event while locked; we'll defer
- // notifying observer until we become unlocked
- m_bHaveOutstandingFileSystemEvent = true;
- }
- else
- {
- m_bHaveOutstandingFileSystemEvent = false;
- m_eventHandler.Execute();
- }
-
- }
- ////////////////////////////////////////////////////////////
- // path must be fully qualified absolute root path, e.g., something like:
- //
- // 'e:realnetworksmedia'
- // 'c:media'
- //
- // * trailing slash required
- // * drive letter required
- //
- // can be called more than once
- //
- void CHXAvFileStore::SetRootL(const TDesC& path, bool bAutoCreateRoot)
- {
- RFs& fs = CCoeEnv::Static()->FsSession();
- TInt idxDrive = CHXAvFile::GetDriveIndex(path);
- if(idxDrive == -1 || !CHXAvFile::HasFolderSuffix(path))
- {
- // caller should ensure path suffix and valid drive
- HXSYM_LEAVE(KErrBadName);
- }
- TInt errExist = KErrPathNotFound;
- if( bAutoCreateRoot )
- {
- TRAP(errExist, BaflUtils::EnsurePathExistsL(fs, path));
- }
- else if(BaflUtils::PathExists(fs, path))
- {
- errExist = KErrNone;
- }
- // make sure root is valid by now
- HXSYM_LEAVE_IF_ERR(errExist); // drive doesn't exist?
- TFileName* pFullPath = new (ELeave) TFileName;
- AUTO_PUSH_POP_DEL(pFullPath);
- HXSYM_LEAVE_IF_ERR(CHXAvFile::GetFullPath(fs, path, *pFullPath));
- m_root.Set(*pFullPath, 0, 0);
- UpdateFullPathL();
- HX_ASSERT(CHXAvFile::HasFolderSuffix(m_root.FullName()));
- // watch for fs events; this resets watch path if we were watching previously
- if( m_root.FullName().Length() > 3 )
- {
- m_fsWatcher.SetWatchPathL(m_root.FullName());
- }
- else
- {
- //
- // specifying a root drive path like 'c:' fails for some reason so watch
- // everything in this case
- //
- m_fsWatcher.SetWatchPathL(KNullDesC);
- }
- m_fsWatcher.SetNotifyType(TNotifyType(ENotifyDir | ENotifyFile | ENotifyEntry));
- m_fsWatcher.StartWatching();
- m_bNeedRefresh = true;
- }
- ////////////////////////////////////////////
- // path - relative to current root path;
- // leading and trailing path delimiter is optional
- //
- //
- void CHXAvFileStore::SetCurrentPathL(const TDesC& path)
- {
- // we want to make sure it looks like '/folder/'
- m_curPath.SetLength(0);
- CHXAvFile::AppendPath(m_curPath, path, CHXAvFile::ntFolder);
- DPRINTF(SYMP_FILE, ("FileStore::SetCurrentPathL(): current path '%s'n", dbg::CharPtr(path)()));
- TInt err = EikFileUtils::CheckFolder(UpdateFullPathL());
- HXSYM_LEAVE_IF_ERR(err); // leave if path not found
-
- m_bNeedRefresh = true;
- HX_ASSERT(CHXAvFile::HasFolderPrefix(m_curPath));
- HX_ASSERT(CHXAvFile::HasFolderSuffix(m_curPath));
- }
- ////////////////////////////////////////////////////////////
- // make sure full path refers to current folder
- const TDesC& CHXAvFileStore::UpdateFullPathL()
- {
- // alloc fully qualified folder base path
- if(!m_pFullPath)
- {
- m_pFullPath = CHXAvFile::AllocFileNameL(m_root.FullName(), m_curPath, CHXAvFile::ntFolder);
- }
- else
- {
- m_pFullPath->Copy(m_root.FullName());
- CHXAvFile::AppendPath(*m_pFullPath, m_curPath, CHXAvFile::ntFolder);
- }
- return *m_pFullPath;
- }
- ////////////////////////////////////////////
- // count files (not folders) in the in the
- // current entries list
- TInt CHXAvFileStore::GetCurrentFolderFileCount() const
- {
- TInt itemCount = m_entryInfo.Nelements();
- TInt fileCount = 0;
- for(TInt idx = 0; idx < itemCount; ++idx)
- {
- if(!m_entryInfo[idx].m_entry.IsDir())
- {
- ++fileCount;
- }
- }
- return fileCount;
- }
- ////////////////////////////////////////////////////
- // add relevant file entries to list info
- //
- void CHXAvFileStore::RefreshEntryInfoHelper(const CDir* pFiles, bool bIncludeFolders)
- {
- HX_ASSERT(pFiles != 0);
- TInt count = pFiles->Count();
- for( TInt idx = 0; idx < count; ++idx )
- {
- const TEntry& entry = (*pFiles)[idx];
- // don't add special (system, hidden) files
- if(!CHXAvUtil::ShouldHideFromUser(entry)) //XXXLCM 'filter policy'
- {
- // note: entry.iName is stripped, e.g., 'folder'
- if(entry.IsDir() && bIncludeFolders)
- {
- // add directory
- CHXAvUtil::Append(m_entryInfo, CHXAvFile::FileInfo(entry, CHXAvFile::ftFolder));
- }
- else
- {
- // only add filetypes that we can play(e.g., 'file.rm')
- TFileName* pPath = CHXAvFile::AllocFileNameL(GetFullPath(),
- entry.iName);
- AUTO_PUSH_POP_DEL(pPath);
- CHXAvFile::FileType type = CHXAvFile::GetFileType(*pPath);
- if (CHXAvFile::IsNanoPlayerFileType(type)) //XXXLCM 'filter policy'
- {
- CHXAvUtil::Append(m_entryInfo, CHXAvFile::FileInfo(entry, type));
- }
- }
- }
- }
- }
- // for RefreshSuspenderL
- void CHXAvFileStore::CleanupSuspendRefresh(TAny* p)
- {
- CHXAvFileStore* pFs = reinterpret_cast<CHXAvFileStore*>(p);
- pFs->SuspendRefresh(false);
- }
- ////////////////////////////////////////////////////////////
- //
- // Call with 'true' to temporarily prevent file and dir list updates as
- // well as filesystem event notifications being forwarded. This
- // 'locks' the file and dir entry lists so that any indexes associated with
- // current lists that are held by client remain valid.
- //
- // Useful in cases where you are holding on to an index while, say,
- // waiting for user input before acting on the index.
- //
- // An alternative is to use CopyEntriesL()
- //
- void CHXAvFileStore::SuspendRefresh(bool bSuspend)
- {
- if( bSuspend )
- {
- ++m_suspendRefreshSem;
- }
- else
- {
- --m_suspendRefreshSem;
- }
- DPRINTF(SYMP_FILE, ("FileStore::SuspendRefresh('%s'): suspend count = %dn", dbg::Bool(bSuspend), m_suspendRefreshSem));
- HX_ASSERT(m_suspendRefreshSem >= 0); // calls must be balanced
-
- if(0 == m_suspendRefreshSem)
- {
- DPRINTF(SYMP_FILE, ("FileStore::SuspendRefresh(): exiting suspendn"));
- // we are no longer suspended; now we can forward deferred filesystem
- // event notifications to observes
- if( m_bHaveOutstandingFileSystemEvent )
- {
- DPRINTF(SYMP_FILE, ("FileStore::SuspendRefresh(): sending deferred file system event notificationn"));
- OnFileSystemEvent();
- }
- }
- }
- ////////////////////////////////////////////////////////////
- // fill out entry info based on current path
- //
- void CHXAvFileStore::RefreshEntryInfoL()
- {
- if( 0 == m_suspendRefreshSem )
- {
- TInt err = KErrNone;
- CHXAvDirectoryReader reader;
- if(reader.SetToPath(GetFullPath()))
- {
- m_bNeedRefresh = false;
- m_entryInfo.Resize(0);
- const bool bIncludeChildFolders = true;
- RefreshEntryInfoHelper(reader.GetFiles(), bIncludeChildFolders);
- RefreshEntryInfoHelper(reader.GetDirs(), bIncludeChildFolders);
- }
- else
- {
- // path invalid? external delete?
- err = reader.GetLastError();
- }
- HXSYM_LEAVE_IF_ERR(err);
- }
- }
- ////////////////////////////////////////////////////////////
- // path - relative to root or absolute
- // name - relative to given path
- //
- // caller must close file object
- //
- FILE* CHXAvFileStore::OpenFileL(const TDesC& path,
- const TDesC& fileName,
- const char* pMode)
- {
- HX_ASSERT(pMode);
- TFileName* pPath = AllocFullPathL(path, fileName);
- AUTO_PUSH_POP_DEL(pPath);
- CHXAvFile::EnsureClearReadOnlyAttributeL(*pPath);
- FILE* pFile = ::fopen( CHXAvStringUtils::DescToString(*pPath), pMode);
- return pFile;
- }
- ////////////////////////////////////////////////////////////
- // returns KErrDiskFull if there is not enough disk space to
- // make the copy
- //
- // Epoc copy-file APIs normally require that EFileShareReadersOnly flag was used
- // to open the source file; fopen(..., "r") apparently does not result in
- // EFileShareReadersOnly being set (probably only EFileRead);
- // here's a work-around
- //
- // call this after copyfile fails with KErrInUse
- //
- // args:
- //
- // pathDest - path relative to root or absoluted
- // fileNameDest - name relative to pathDest
- //
- TInt CHXAvFileStore::CopyFileAlternateL(const TDesC& pathDest,
- const TDesC& fileNameDest,
- const TDesC& fullPathSource,
- bool bAllowOverwrite)
- {
- TFileName* pFullPathDest = AllocFullPathL(pathDest, fileNameDest);
- AUTO_PUSH_POP_DEL(pFullPathDest);
- DPRINTF(SYMP_FILE, ("FileStore::CopyFileAlternateL(): copying '%s' -> '%s'n", dbg::CharPtr(fullPathSource)(), dbg::CharPtr(*pFullPathDest)()));
- TInt idxDestDrive = CHXAvFile::GetDriveIndex(*pFullPathDest);
- TInt err = CHXAvFile::CheckDiskSpaceForCopyL(fullPathSource, idxDestDrive);
- if(KErrNone == err)
- {
- RFile source;
- RFile target;
- // buffer for reading source file data
- const TUint k_cbCopyBuffer = 64 * 1024; // 64K buffer (mimics CFileMan copy)
- HBufC8* pCopyBuffer = HBufC8::NewL(k_cbCopyBuffer);
- AUTO_PUSH_POP_DEL(pCopyBuffer);
- CEikonEnv* pEnv = CEikonEnv::Static();
- // open source
- err = source.Open(pEnv->FsSession(), fullPathSource, EFileRead|EFileShareAny);
- if(KErrNone == err)
- {
- CleanupClosePushL(source);
- if( bAllowOverwrite && CHXAvFile::PathExists(*pFullPathDest) )
- {
- // make sure file is deleted (so create will succeed)
- HXSYM_LEAVE_IF_ERR(DeleteFileL(*pFullPathDest));
- }
- // (re-)create target; fails if file exists
- err = target.Create(pEnv->FsSession(), *pFullPathDest, EFileWrite|EFileShareExclusive);
- if(KErrNone == err)
- {
- CleanupClosePushL(target);
- m_cbFileOp = 0;
- OnFileOpStart(FileStoreOperationObserver::otCopy, fullPathSource, *pFullPathDest);
- // copy bits
- TPtr8 ptr = pCopyBuffer->Des();
- err = source.Read(ptr);
- if( KErrNone == err )
- {
- while(pCopyBuffer->Length() != 0)
- {
- err = target.Write(*pCopyBuffer);
- if( KErrNone != err )
- {
- break;
- }
- m_cbFileOp += pCopyBuffer->Length();
- // notify observer each time we copy a chunk; provide chance to cancel operation
- bool bContinue = OnFileOpTick(FileStoreOperationObserver::otCopy, fullPathSource, *pFullPathDest, m_cbFileOp);
- if( !bContinue )
- {
- // user cancel
- err = KErrCancel;
- break;
- }
- err = source.Read(ptr);
- if( KErrNone != err )
- {
- break;
- }
- }
- if( KErrNone == err )
- {
- err = target.Flush();
- }
- }
- target.Close();
- CleanupStack::PopAndDestroy(); // target
- if( KErrNone != err )
- {
- DPRINTF(SYMP_FILE, ("FileStore::CopyFileAlternateL(): failed; deleting target file (err = 0x%08xn)", err));
- // delete destination - copy was not completed
- HXSYM_LEAVE_IF_ERR(DeleteFileL(*pFullPathDest));
- }
- else
- {
- // succeded - set file attributes
- HXSYM_LEAVE_IF_ERR(m_pFileMan->Attribs(*pFullPathDest,
- KEntryAttNormal/*set*/,
- KEntryAttReadOnly/*clear*/, TTime(0)));
- }
- OnFileOpEnd(FileStoreOperationObserver::otCopy, err, fullPathSource, *pFullPathDest);
- }
- CleanupStack::PopAndDestroy(); // source
- }
- }
- return err;
- }
- ////////////////////////////////////////////////////////////
- // returns KErrDiskFull if there is not enough disk space to
- // make the copy
- //
- // args:
- //
- // pathDest - path relative to root or absolute
- // fileNameDest - name relative to pathDest
- //
- TInt CHXAvFileStore::CopyFileL(const TDesC& pathDest,
- const TDesC& fileNameDest,
- const TDesC& fullPathSource,
- bool bAllowOverwrite)
- {
- TFileName* pFullPathDest = AllocFullPathL(pathDest, fileNameDest);
- AUTO_PUSH_POP_DEL(pFullPathDest);
- TUint flag = (bAllowOverwrite ? CFileMan::EOverWrite : 0);
- DPRINTF(SYMP_FILE, ("FileStore::CopyFileL(): copying '%s' -> '%s'n", dbg::CharPtr(fullPathSource)(), dbg::CharPtr(*pFullPathDest)()));
- TInt err = KErrGeneral;
- if( 0 == pFullPathDest->CompareF(fullPathSource) )
- {
- // copy to self; nothing to do; ignore
- err = KErrNone;
- }
- else
- {
- TInt idxDestDrive = CHXAvFile::GetDriveIndex(*pFullPathDest);
- err = CHXAvFile::CheckDiskSpaceForCopyL(fullPathSource, idxDestDrive);
- if( err == KErrNone )
- {
- // fileman copy fails (KErrInUse) if file not opened with EFileShareReadersOnly
- #if defined(ASYNC_COPYMOVE)
- err = m_pFileMan->Copy(fullPathSource, *pFullPathDest, flag, m_pFileOpCompletion->Status());
- m_pFileOpCompletion->Activate();
- #else
- err = m_pFileMan->Copy(fullPathSource, *pFullPathDest, flag);
- #endif
- }
- }
- return err;
- }
- ////////////////////////////////////////////////////////////
- // folder - folder relative to current path;
- // leading path delimiter is optional
- //
- TInt CHXAvFileStore::CreateChildFolderL(const TDesC& folder, bool bAllowOverwrite)
- {
- // alloc fully qualified folder name
- TFileName* pName = CHXAvFile::AllocFileNameL(GetFullPath(), folder, CHXAvFile::ntFolder);
- AUTO_PUSH_POP_DEL(pName);
- if( bAllowOverwrite && CHXAvFile::PathExists(*pName) )
- {
- // make sure existing folder is deleted (so create will succeed)
- HXSYM_LEAVE_IF_ERR(DeleteFileL(*pName));
- }
- RFs& fs = CCoeEnv::Static()->FsSession();
- TInt err = fs.MkDir(*pName); //note: see also MkDirAll
- if(KErrNone == err)
- {
- // just in case (we should get event notification from the fs watcher)
- m_bNeedRefresh = true;
- }
- return err;
- }
- ////////////////////////////////////////////
- // folder - folder relative to current path;
- // path delimiters (prefix and suffix) are optional
- //
- void CHXAvFileStore::SwitchToChildFolderL(const TDesC& folder)
- {
- DPRINTF(SYMP_FILE, ("FileStore::SwitchToChildFolderL(): '%s'n", dbg::CharPtr(folder)()));
- TFileName* pPath = CHXAvFile::AllocFileNameL(m_curPath, folder, CHXAvFile::ntFolder);
- AUTO_PUSH_POP_DEL(pPath);
- SetCurrentPathL(*pPath);
- }
- ////////////////////////////////////////////////////////////
- // switch current path to parent folder
- void CHXAvFileStore::SwitchToParentFolderL()
- {
- DPRINTF(SYMP_FILE, ("FileStore::SwitchToParentFolderL()n"));
- HX_ASSERT(!IsAtRoot());
- TPtrC parent = CHXAvFile::GetParentFolder(m_curPath);
- SetCurrentPathL(parent);
- }
- ////////////////////////////////////////////////////////////
- //
- TInt CHXAvFileStore::DeleteFileL(const TDesC& fullPath, CHXAvFile::NameType type)
- {
- return DeleteFileL(fullPath, KNullDesC, type);
- }
- ////////////////////////////////////////////////////////////
- // delete a file or folder from disk; if successful, mark
- // current list as needing refresh
- //
- // pathDest - full or relative base path
- // name - name of file or folder to append
- // type - type of file system entry; ntUnspecified if type can safely be deduced from 'name'
- //
- TInt CHXAvFileStore::DeleteFileL(const TDesC& pathDest, const TDesC& name, CHXAvFile::NameType type)
- {
- TInt err = KErrGeneral;
- TFileName* pFullPath = AllocFullPathL(pathDest, name);
- AUTO_PUSH_POP_DEL(pFullPath);
- bool bIsFolder = false;
- if( type == CHXAvFile::ntFolder )
- {
- bIsFolder = true;
- CHXAvFile::EnsureFolderSuffix(*pFullPath);
- }
- else if( type == CHXAvFile::ntUnspecified )
- {
- bIsFolder = CHXAvFile::HasFolderSuffix(*pFullPath);
- }
- CHXAvFile::EnsureClearReadOnlyAttributeL(*pFullPath);
- if( bIsFolder )
- {
- HX_ASSERT(CHXAvFile::HasFolderSuffix(*pFullPath));
- err = m_pFileMan->RmDir(*pFullPath);
- }
- else
- {
- HX_ASSERT(!CHXAvFile::HasFolderSuffix(*pFullPath));
- err = m_pFileMan->Delete(*pFullPath);
- }
- if(KErrNone == err)
- {
- // just in case (we should get event notification from the fs watcher)
- m_bNeedRefresh = IsImmediateChild(*pFullPath) || IsParent(*pFullPath);
- }
- return err;
- }
- ////////////////////////////////////////////////////////////
- // delete a file or folder from disk; if successful, markd current
- // list as needing refresh
- //
- // idxItem - index of item in current folder path
- //
- TInt CHXAvFileStore::DeleteItemL(TInt idxItem)
- {
- TInt err = KErrGeneral;
- TFileName* pFullPath = AllocFullPathL(idxItem);
- AUTO_PUSH_POP_DEL(pFullPath);
- CHXAvFile::EnsureClearReadOnlyAttributeL(*pFullPath);
- HX_ASSERT(idxItem < m_entryInfo.Nelements());
- const TEntry& entry = m_entryInfo[idxItem].m_entry;
- if( entry.IsDir() )
- {
- HX_ASSERT(CHXAvFile::HasFolderSuffix(*pFullPath));
- err = m_pFileMan->RmDir(*pFullPath);
- }
- else
- {
- HX_ASSERT(!CHXAvFile::HasFolderSuffix(*pFullPath));
- err = m_pFileMan->Delete(*pFullPath);
- }
- if(KErrNone == err)
- {
- // just in case (we should get event notification from the fs watcher)
- m_bNeedRefresh = true;
- }
- return err;
- }
- ////////////////////////////////////////////////////////////
- // path - relative to root or absolute (if drive specified)
- // idxItem - index of item in _current_ folder path
- //
- // * call this before certain unchecking methods
- //
- // return: true if fully qualified filename formed from
- // input parameters would fit safely in a TFileName buffer
- //
- bool CHXAvFileStore::IsSafeFileNameLengthL(const TDesC& path, TInt idxItem)
- {
- TFileName* pPath = AllocFullPathL(path, KNullDesC, CHXAvFile::ntFolder);
- AUTO_PUSH_POP_DEL(pPath);
- HX_ASSERT(idxItem < m_entryInfo.Nelements());
- const TEntry& entry = m_entryInfo[idxItem].m_entry;
- TInt cchRequired = pPath->Length() + entry.iName.Length();
- if( entry.IsDir() )
- {
- cchRequired += 1; // account for folder suffix that will need to be added
- }
- return cchRequired <= KMaxFileName;
- }
- ////////////////////////////////////////////////////////////
- // see IsSafeFileNameLengthL() override
- bool CHXAvFileStore::IsSafeFileNameLengthL(const TDesC& path,
- const TDesC& name,
- CHXAvFile::NameType type)
- {
- TFileName* pPath = AllocFullPathL(path, KNullDesC, CHXAvFile::ntFolder);
- AUTO_PUSH_POP_DEL(pPath);
- TInt cchRequired = pPath->Length() + name.Length();
- if( (CHXAvFile::ntFolder == type) && !CHXAvFile::HasFolderSuffix(name) )
- {
- cchRequired += 1; // account for folder suffix that will need to be added
- }
- return cchRequired <= KMaxFileName;
- }
- ////////////////////////////////////////////////////////////
- //
- // Allocate full path (file or folder) for given item in
- // current path
- //
- // idxItem - index to an existing item (folder or file)
- //
- TFileName* CHXAvFileStore::AllocFullPathL(TInt idxItem)
- {
- HX_ASSERT(idxItem < m_entryInfo.Nelements());
- const TEntry& entry = m_entryInfo[idxItem].m_entry;
- // allocate fully qualified file or folder name
- TFileName* pPath = CHXAvFile::AllocFileNameL(GetFullPath(),
- entry.iName, (entry.IsDir() ? CHXAvFile::ntFolder : CHXAvFile::ntFile) );
- return pPath;
- }
- ////////////////////////////////////////////////////////////
- //
- // Allocate full destination path (file or folder) matching
- // the given item
- //
- // targetPath - absolute or relative target folder path
- // idxItem - index to an existing item (folder or file)
- // targetName - name of target file or folder; zero-length indicates
- // use same name as file/folder at given index in current folder
- //
- //
- TFileName* CHXAvFileStore::AllocFullTargetPathL(const TDesC& targetPath,
- TInt idxItem, const TDesC& targetName)
- {
- HX_ASSERT(idxItem < m_entryInfo.Nelements());
- const TEntry& entry = m_entryInfo[idxItem].m_entry;
- CHXAvFile::NameType type = ( entry.IsDir() ? CHXAvFile::ntFolder : CHXAvFile::ntFile );
- TFileName* pPath = 0;
- if( 0 == targetName.Length() )
- {
- // no target name, use same name
- pPath = AllocFullPathL(targetPath, entry.iName, type);
- }
- else
- {
- pPath = AllocFullPathL(targetPath, targetName, type);
- }
- return pPath;
- }
- ////////////////////////////////////////////////////////////
- //does file or folder matching name associated with item exist in target path
- //
- // path - relative to root or absolute (if drive specified)
- // idxItem - index of item in _current_ folder path
- //
- //
- bool CHXAvFileStore::NameExistsInTargetPathL(const TDesC& targetPath, TInt idxItem)
- {
- // alloc full file path matching the name associated with the given entry index
- HX_ASSERT(idxItem < m_entryInfo.Nelements());
- const TEntry& entry = m_entryInfo[idxItem].m_entry;
- return NameExistsInTargetPathL(targetPath, entry.iName);
- }
- ////////////////////////////////////////////////////////////
- // does file or folder exist with given name in path
- //
- // * use before moving/renaming an item to the target folder
- //
- // path - relative to root or absolute (if drive specified)
- // name - file or folder name (ok to have folder trailing slash)
- //
- //
- bool CHXAvFileStore::NameExistsInTargetPathL(const TDesC& targetPath, const TDesC& name)
- {
- // alloc full file path matching the name associated with the given entry index
- TFileName* pName = AllocFullPathL(targetPath, name, CHXAvFile::ntFile);
- AUTO_PUSH_POP_DEL(pName);
- // see if file with given name exists
- bool bExists = CHXAvFile::PathExists(*pName);
- if( !bExists )
- {
- // see if folder with given name exists
- CHXAvFile::EnsureFolderSuffix(*pName);
- bExists = CHXAvFile::PathExists(*pName);
- }
- return bExists;
- }
- ////////////////////////////////////////////////////////////
- // does file or folder (specified) matching name associated with item exists in target path
- //
- // return true if target path has folder or file having same name
- // as entry at given index idxItem in current path
- //
- bool CHXAvFileStore::NameExistsInTargetPathL(const TDesC& targetPath, TInt idxItem, CHXAvFile::NameType type)
- {
- HX_ASSERT(idxItem < m_entryInfo.Nelements());
- const TEntry& entry = m_entryInfo[idxItem].m_entry;
- return PathExistsL(targetPath, entry.iName, type);
- }
- ////////////////////////////////////////////////////////////
- // does path exist as file or folder (specified or dedecude based on name)
- //
- // return true if target path has file or folder having given name
- //
- bool CHXAvFileStore::PathExistsL(const TDesC& targetPath, const TDesC& name, CHXAvFile::NameType type)
- {
- TFileName* pName = AllocFullPathL(targetPath, name, type);
- AUTO_PUSH_POP_DEL(pName);
- return CHXAvFile::PathExists(*pName);
- }
- ////////////////////////////////////////////////////////////
- //
- TInt CHXAvFileStore::MoveItemL(TInt idxItem,
- const TDesC& newName,
- bool bAllowOverwrite, bool bRename)
- {
- return MoveItemL(idxItem, KNullDesC, newName, bAllowOverwrite, bRename);
- }
- ////////////////////////////////////////////////////////////
- // move item
- //
- // return:
- // KErrNone if file is moved;
- // KErrDiskFull if insufficient space on target
- //
- // idxItem - index of item in current folder path
- // targetPath - relative to root or absolute (or KNullDesC to move within current path, i.e., rename)
- // targetName - new name for file or folder;
- // for folders, trailing '' optional
- // bRename - uses underlying rename api; doesn't check disk space for copy (probably no difference from move)
- //
- TInt CHXAvFileStore::MoveItemL(TInt idxItem,
- const TDesC& targetPath,
- const TDesC& targetName,
- bool bAllowOverwrite, bool bRename)
- {
- // source path
- TFileName* pOldPath = AllocFullPathL(idxItem);
- AUTO_PUSH_POP_DEL(pOldPath);
- // target path
- TFileName* pNewPath = 0;
- if( targetPath.Length() != 0 )
- {
- pNewPath = AllocFullTargetPathL(targetPath, idxItem, targetName);
- }
- else
- {
- // use current path for target
- pNewPath = AllocFullTargetPathL(GetCurrentPath(), idxItem, targetName);
- }
- AUTO_PUSH_POP_DEL(pNewPath);
- TInt err = KErrNone;
- if( 0 != pOldPath->CompareF(*pNewPath)) // else, move to self - nothing to do
- {
- if(!bRename)
- {
- // see if we are moving across drives...
- TInt idxDestDrive = CHXAvFile::GetDriveIndex(*pNewPath);
- TInt idxSourceDrive = CHXAvFile::GetDriveIndex(*pOldPath);
- if(idxDestDrive != idxSourceDrive)
- {
- // need to check for disk space on destination drive
- err = CHXAvFile::CheckDiskSpaceForCopyL(*pOldPath, idxDestDrive);
- }
- }
- if(KErrNone == err)
- {
- DPRINTF(SYMP_FILE, ("FileStore::MoveItemL(): moving '%s' -> '%s'n", dbg::CharPtr(*pOldPath)(), dbg::CharPtr(*pNewPath)()));
- TUint flag = CFileMan::ERecurse;
- // clear ro attributes for source and dest
- CHXAvFile::EnsureClearReadOnlyAttributeL(*pOldPath);
- if(PathExistsL(*pNewPath, KNullDesC) && bAllowOverwrite)
- {
- flag |= CFileMan::EOverWrite;
- CHXAvFile::EnsureClearReadOnlyAttributeL(*pNewPath);
- }
- // folder suffixes cause errors
- CHXAvFile::TrimFolderSuffix(pOldPath);
- CHXAvFile::TrimFolderSuffix(pNewPath);
- if( bRename )
- {
- err = m_pFileMan->Rename(*pOldPath, *pNewPath, flag);
- }
- else
- {
- #if defined(ASYNC_COPYMOVE)
- err = m_pFileMan->Move(*pOldPath, *pNewPath, flag, m_pFileOpCompletion->Status());
- m_pFileOpCompletion->Activate();
- #else
- err = m_pFileMan->Move(*pOldPath, *pNewPath, flag);
- #endif
- }
- DPRINTF(SYMP_FILE_UI, ("CHXAvFileStore::MoveItemL: result = %ldn", err));
- if(KErrNone == err)
- {
- if(PathExistsL(*pOldPath, KNullDesC))
- {
- DPRINTF(SYMP_FILE_UI, ("CHXAvFileStore::MoveItemL: old path still exists! deleting old itemn"));
- // just in case - in case where we overwrite an existing folder the source
- // folder is not deleted
- HXSYM_LEAVE_IF_ERR(DeleteFileL(*pOldPath));
- }
- // just in case (we should get event notification from the fs watcher)
- m_bNeedRefresh = true;
- }
- }
- }
- return err;
- }
- //////////////////////////////////
- //
- FileStoreOperationObserver::OperationType
- FileStoreOperationObserver::TranslateFileManAction(CFileMan::TAction action)
- {
- if(action == CFileMan::ECopy)
- {
- return otCopy;
- }
- else if(action == CFileMan::EMove)
- {
- return otMove;
- }
- else if(action == CFileMan::ERename)
- {
- return otMove;
- }
- return otWhoCares;
- }
- //////////////////////////////////
- // called when fileman begins a file operation
- //
- // called on separate thread if async fileman operations are used
- //
- MFileManObserver::TControl CHXAvFileStore::NotifyFileManStarted()
- {
- DPRINTF(SYMP_FILE, ("FileStore::NotifyFileManStarted()n"));
- FileStoreOperationObserver::OperationType type = TranslateFileManAction(m_pFileMan->CurrentAction());
- if( type != FileStoreOperationObserver::otWhoCares )
- {
- TFileName source, dest;
- m_pFileMan->GetCurrentSource(source);
- m_pFileMan->GetCurrentTarget(dest);
- m_cbFileOp = 0;
- OnFileOpStart(type, source, dest);
- }
- // ECopy, EMove, EDelete, ERename, ERmDir
- return EContinue;
- }
- //////////////////////////////////
- // called when fileman completes copying a chunk of data (move, copy)
- //
- // called on separate thread if async fileman operations are used
- //
- // we can return EContinue,ERetry,EAbort,ECancel
- MFileManObserver::TControl CHXAvFileStore::NotifyFileManOperation()
- {
- DPRINTF(SYMP_FILE, ("FileStore::NotifyFileManOperation()n"));
- MFileManObserver::TControl controlAction = EContinue;
- FileStoreOperationObserver::OperationType type = TranslateFileManAction(m_pFileMan->CurrentAction());
- if( type != FileStoreOperationObserver::otWhoCares )
- {
- TFileName source, dest;
- m_pFileMan->GetCurrentSource(source);
- m_pFileMan->GetCurrentTarget(dest);
- TInt cbCopied = m_pFileMan->BytesTransferredByCopyStep();
- m_cbFileOp += cbCopied;
- bool bContinue = OnFileOpTick(type, source, dest, m_cbFileOp);
- if( !bContinue )
- {
- controlAction = ECancel;
- }
- }
- return controlAction;
- }
- //////////////////////////////////
- // called when fileman completes an operation
- //
- // called on separate thread if async fileman operations are used
- //
- MFileManObserver::TControl CHXAvFileStore::NotifyFileManEnded()
- {
- DPRINTF(SYMP_FILE, ("FileStore::NotifyFileManEnded()n"));
- FileStoreOperationObserver::OperationType type = TranslateFileManAction(m_pFileMan->CurrentAction());
- if( type != FileStoreOperationObserver::otWhoCares )
- {
- TFileName source, dest;
- m_pFileMan->GetCurrentSource(source);
- m_pFileMan->GetCurrentTarget(dest);
- //TInt cbCopied = m_pFileMan->BytesTransferredByCopyStep();
- OnFileOpEnd(type, KErrNone, source, dest);
- }
- return EContinue;
- }
- #if defined(ASYNC_COPYMOVE)
- ////////////////////////////////////////
- // called when async fileman request completes
- void CHXAvFileStore::OnFileOpAsyncComplete(TInt status)
- {
- DPRINTF(SYMP_FILE, ("FileStore::OnFileOpAsyncComplete(): status = %dn", status));
- }
- ////////////////////////////////////////
- // called when async fileman request is cancelled
- void CHXAvFileStore::OnFileOpAsyncCancel(TInt status)
- {
- DPRINTF(SYMP_FILE, ("FileStore::OnFileOpAsyncCancel(): status = %dn", status));
- }
- ////////////////////////////////////////
- // called to abort/cancel async fileman request
- void CHXAvFileStore::CancelAsyncFileOp()
- {
- DPRINTF(SYMP_FILE, ("FileStore::CancelAsyncFileOp()n"));
- if( m_pFileOpCompletion && m_pFileOpCompletion->IsActive() )
- {
- m_pFileOpCompletion->Cancel();
- }
- }
- #endif // ASYNC_COPYMOVE
- void CHXAvFileStore::OnFileOpStart(FileStoreOperationObserver::OperationType type, const TDesC& source, const TDesC& target)
- {
- DPRINTF(SYMP_FILE, ("FileStore::OnFileOpStart(): op = %d; src = '%s'; dst = '%s'n", type, dbg::CharPtr(source)(), dbg::CharPtr(target)()));
- if(m_pObserver)
- {
- m_pObserver->OnFileOpStart(type, source, target);
- }
- }
- bool CHXAvFileStore::OnFileOpTick(FileStoreOperationObserver::OperationType type, const TDesC& source, const TDesC& target, TInt64 cbCopied)
- {
- DPRINTF(SYMP_FILE, ("FileStore::OnFileOpTick(): op = %d; src = '%s'; dst = '%s'; cb = %lun", type, dbg::CharPtr(source)(), dbg::CharPtr(target)(), cbCopied.Low()));
- if(m_pObserver)
- {
- return m_pObserver->OnFileOpTick(type, source, target, m_cbFileOp);
- }
- return true;
- }
- void CHXAvFileStore::OnFileOpEnd(FileStoreOperationObserver::OperationType type, TInt err, const TDesC& source, const TDesC& target)
- {
- DPRINTF(SYMP_FILE, ("FileStore::OnFileOpEnd(): op = %d; err = %d, src = '%s'; dst = '%s'n", type, err, dbg::CharPtr(source)(), dbg::CharPtr(target)()));
- if(m_pObserver)
- {
- m_pObserver->OnFileOpEnd(type, err, source, target);
- }
- }