chxavfilestore.cpp

来自「著名的 helix realplayer 基于手机 symbian 系统的 播放」· C++ 代码 · 共 1,202 行 · 第 1/3 页

CPP
1,202
字号
// 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%08x\n)", 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) )

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?