VirtualBox

Changeset 69943 in vbox


Ignore:
Timestamp:
Dec 5, 2017 11:40:52 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119441
Message:

iprt/ntfsvfs.cpp: Implemented file reading.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp

    r69938 r69943  
    296296
    297297/**
    298  * Pointer to a shared NTFS directory object.
     298 * Shared NTFS directory object.
    299299 */
    300300typedef struct RTFSNTFSDIRSHRD
     
    341341typedef RTFSNTFSDIR *PRTFSNTFSDIR;
    342342
     343
     344/**
     345 * Shared NTFS file object.
     346 */
     347typedef struct RTFSNTFSFILESHRD
     348{
     349    /** Reference counter. */
     350    uint32_t volatile       cRefs;
     351    /** Pointer to the data attribute (core is referenced thru this). */
     352    PRTFSNTFSATTR           pData;
     353} RTFSNTFSFILESHRD;
     354/** Pointer to shared data for a file or data stream. */
     355typedef RTFSNTFSFILESHRD *PRTFSNTFSFILESHRD;
     356
     357
     358/**
     359 * Open NTFS file instance.
     360 */
     361typedef struct RTFSNTFSFILE
     362{
     363    /** Pointer to the shared file data (referenced). */
     364    PRTFSNTFSFILESHRD       pShared;
     365    /** Current file offset. */
     366    uint64_t                offFile;
     367} RTFSNTFSFILE;
     368/** Pointer to an NTFS open file instance. */
     369typedef RTFSNTFSFILE *PRTFSNTFSFILE;
    343370
    344371/**
     
    19872014        pObjInfo->cbAllocated = RT_LE2H_U64(pAttr->pAttrHdr->u.NonRes.cbAllocated);
    19882015
    1989 
    19902016    /*
    19912017     * See if we can find a filename record before we try convert the file attributes to mode.
     
    20122038    return VINF_SUCCESS;
    20132039}
     2040
     2041
     2042
     2043
     2044/*
     2045 *
     2046 * File operations.
     2047 * File operations.
     2048 * File operations.
     2049 *
     2050 */
     2051
     2052/**
     2053 * Releases a reference to a shared NTFS file structure.
     2054 *
     2055 * @returns New reference count.
     2056 * @param   pShared             The shared NTFS file structure.
     2057 */
     2058static uint32_t rtFsNtfsFileShrd_Release(PRTFSNTFSFILESHRD pShared)
     2059{
     2060    uint32_t cRefs = ASMAtomicDecU32(&pShared->cRefs);
     2061    Assert(cRefs < 64);
     2062    if (cRefs == 0)
     2063    {
     2064        LogFlow(("rtFsNtfsFileShrd_Release(%p): Destroying it\n", pShared));
     2065        Assert(pShared->pData->uObj.pSharedFile == pShared);
     2066        pShared->pData->uObj.pSharedFile = NULL;
     2067        rtFsNtfsCore_Release(pShared->pData->pCore);
     2068        pShared->pData = NULL;
     2069        RTMemFree(pShared);
     2070    }
     2071    return cRefs;
     2072}
     2073
     2074
     2075/**
     2076 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
     2077 */
     2078static DECLCALLBACK(int) rtFsNtfsFile_Close(void *pvThis)
     2079{
     2080    PRTFSNTFSFILE pThis = (PRTFSNTFSFILE)pvThis;
     2081    LogFlow(("rtFsNtfsFile_Close(%p/%p)\n", pThis, pThis->pShared));
     2082
     2083    PRTFSNTFSFILESHRD pShared = pThis->pShared;
     2084    pThis->pShared = NULL;
     2085    if (pShared)
     2086        rtFsNtfsFileShrd_Release(pShared);
     2087    return VINF_SUCCESS;
     2088}
     2089
     2090
     2091/**
     2092 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     2093 */
     2094static DECLCALLBACK(int) rtFsNtfsFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     2095{
     2096    PRTFSNTFSFILE       pThis   = (PRTFSNTFSFILE)pvThis;
     2097    PRTFSNTFSATTR       pDataAttr = pThis->pShared->pData;
     2098    return rtFsNtfsCore_QueryInfo(pDataAttr->pCore, pDataAttr, pObjInfo, enmAddAttr);
     2099}
     2100
     2101
     2102/**
     2103 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
     2104 */
     2105static DECLCALLBACK(int) rtFsNtfsFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
     2106{
     2107    PRTFSNTFSFILE pThis = (PRTFSNTFSFILE)pvThis;
     2108    AssertReturn(pSgBuf->cSegs == 1, VERR_INTERNAL_ERROR_3);
     2109    RT_NOREF(fBlocking);
     2110
     2111    if (off == -1)
     2112        off = pThis->offFile;
     2113    else
     2114        AssertReturn(off >= 0, VERR_INTERNAL_ERROR_3);
     2115
     2116    int rc;
     2117    size_t cbRead = pSgBuf->paSegs[0].cbSeg;
     2118    if (!pcbRead)
     2119    {
     2120        rc = rtFsNtfsAttr_Read(pThis->pShared->pData, off, pSgBuf->paSegs[0].pvSeg, cbRead);
     2121        if (RT_SUCCESS(rc))
     2122            pThis->offFile = off + cbRead;
     2123        Log6(("rtFsNtfsFile_Read: off=%#RX64 cbSeg=%#x -> %Rrc\n", off, pSgBuf->paSegs[0].cbSeg, rc));
     2124    }
     2125    else
     2126    {
     2127        PRTFSNTFSATTR pDataAttr = pThis->pShared->pData;
     2128        if ((uint64_t)off >= pDataAttr->cbValue)
     2129        {
     2130            *pcbRead = 0;
     2131            rc = VINF_EOF;
     2132        }
     2133        else
     2134        {
     2135            if ((uint64_t)off + cbRead <= pDataAttr->cbValue)
     2136                rc = rtFsNtfsAttr_Read(pThis->pShared->pData, off, pSgBuf->paSegs[0].pvSeg, cbRead);
     2137            else
     2138            {
     2139                /* Return VINF_EOF if beyond end-of-file. */
     2140                cbRead = (size_t)(pDataAttr->cbValue - (uint64_t)off);
     2141                rc = rtFsNtfsAttr_Read(pThis->pShared->pData, off, pSgBuf->paSegs[0].pvSeg, cbRead);
     2142                if (RT_SUCCESS(rc))
     2143                    rc = VINF_EOF;
     2144            }
     2145            if (RT_SUCCESS(rc))
     2146            {
     2147                pThis->offFile = off + cbRead;
     2148                *pcbRead = cbRead;
     2149            }
     2150            else
     2151                *pcbRead = 0;
     2152        }
     2153        Log6(("rtFsNtfsFile_Read: off=%#RX64 cbSeg=%#x -> %Rrc *pcbRead=%#x\n", off, pSgBuf->paSegs[0].cbSeg, rc, *pcbRead));
     2154    }
     2155
     2156    return rc;
     2157}
     2158
     2159
     2160/**
     2161 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
     2162 */
     2163static DECLCALLBACK(int) rtFsNtfsFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
     2164{
     2165    RT_NOREF(pvThis, off, pSgBuf, fBlocking, pcbWritten);
     2166    return VERR_WRITE_PROTECT;
     2167}
     2168
     2169
     2170/**
     2171 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
     2172 */
     2173static DECLCALLBACK(int) rtFsNtfsFile_Flush(void *pvThis)
     2174{
     2175    RT_NOREF(pvThis);
     2176    return VINF_SUCCESS;
     2177}
     2178
     2179
     2180/**
     2181 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
     2182 */
     2183static DECLCALLBACK(int) rtFsNtfsFile_Tell(void *pvThis, PRTFOFF poffActual)
     2184{
     2185    PRTFSNTFSFILE pThis = (PRTFSNTFSFILE)pvThis;
     2186    *poffActual = pThis->offFile;
     2187    return VINF_SUCCESS;
     2188}
     2189
     2190
     2191/**
     2192 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
     2193 */
     2194static DECLCALLBACK(int) rtFsNtfsFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
     2195{
     2196    RT_NOREF(pvThis, fMode, fMask);
     2197    return VERR_WRITE_PROTECT;
     2198}
     2199
     2200
     2201/**
     2202 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
     2203 */
     2204static DECLCALLBACK(int) rtFsNtfsFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     2205                                                 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
     2206{
     2207    RT_NOREF(pvThis, pAccessTime, pModificationTime, pChangeTime, pBirthTime);
     2208    return VERR_WRITE_PROTECT;
     2209}
     2210
     2211
     2212/**
     2213 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
     2214 */
     2215static DECLCALLBACK(int) rtFsNtfsFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
     2216{
     2217    RT_NOREF(pvThis, uid, gid);
     2218    return VERR_WRITE_PROTECT;
     2219}
     2220
     2221
     2222/**
     2223 * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
     2224 */
     2225static DECLCALLBACK(int) rtFsNtfsFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
     2226{
     2227    PRTFSNTFSFILE pThis = (PRTFSNTFSFILE)pvThis;
     2228    RTFOFF offNew;
     2229    switch (uMethod)
     2230    {
     2231        case RTFILE_SEEK_BEGIN:
     2232            offNew = offSeek;
     2233            break;
     2234        case RTFILE_SEEK_END:
     2235            offNew = (RTFOFF)pThis->pShared->pData->cbValue + offSeek;
     2236            break;
     2237        case RTFILE_SEEK_CURRENT:
     2238            offNew = (RTFOFF)pThis->offFile + offSeek;
     2239            break;
     2240        default:
     2241            return VERR_INVALID_PARAMETER;
     2242    }
     2243    if (offNew >= 0)
     2244    {
     2245        pThis->offFile = offNew;
     2246        *poffActual    = offNew;
     2247        return VINF_SUCCESS;
     2248    }
     2249    return VERR_NEGATIVE_SEEK;
     2250}
     2251
     2252
     2253/**
     2254 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
     2255 */
     2256static DECLCALLBACK(int) rtFsNtfsFile_QuerySize(void *pvThis, uint64_t *pcbFile)
     2257{
     2258    PRTFSNTFSFILE pThis = (PRTFSNTFSFILE)pvThis;
     2259    *pcbFile = pThis->pShared->pData->cbValue;
     2260    return VINF_SUCCESS;
     2261}
     2262
     2263
     2264/**
     2265 * NTFS FS file operations.
     2266 */
     2267DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_rtFsNtfsFileOps =
     2268{
     2269    { /* Stream */
     2270        { /* Obj */
     2271            RTVFSOBJOPS_VERSION,
     2272            RTVFSOBJTYPE_FILE,
     2273            "NTFS File",
     2274            rtFsNtfsFile_Close,
     2275            rtFsNtfsFile_QueryInfo,
     2276            RTVFSOBJOPS_VERSION
     2277        },
     2278        RTVFSIOSTREAMOPS_VERSION,
     2279        RTVFSIOSTREAMOPS_FEAT_NO_SG,
     2280        rtFsNtfsFile_Read,
     2281        rtFsNtfsFile_Write,
     2282        rtFsNtfsFile_Flush,
     2283        NULL /*PollOne*/,
     2284        rtFsNtfsFile_Tell,
     2285        NULL /*pfnSkip*/,
     2286        NULL /*pfnZeroFill*/,
     2287        RTVFSIOSTREAMOPS_VERSION,
     2288    },
     2289    RTVFSFILEOPS_VERSION,
     2290    0,
     2291    { /* ObjSet */
     2292        RTVFSOBJSETOPS_VERSION,
     2293        RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
     2294        rtFsNtfsFile_SetMode,
     2295        rtFsNtfsFile_SetTimes,
     2296        rtFsNtfsFile_SetOwner,
     2297        RTVFSOBJSETOPS_VERSION
     2298    },
     2299    rtFsNtfsFile_Seek,
     2300    rtFsNtfsFile_QuerySize,
     2301    RTVFSFILEOPS_VERSION
     2302};
     2303
     2304
     2305static int rtFsNtfsVol_NewFile(PRTFSNTFSVOL pThis, uint64_t fOpen, PCNTFSIDXENTRYHDR pEntryHdr, const char *pszStreamName,
     2306                               PRTVFSFILE phVfsFile, PRTERRINFO pErrInfo, const char *pszWhat)
     2307{
     2308    /*
     2309     * Get the core structure for the MFT record and check that it's a directory we've got.
     2310     */
     2311    PRTFSNTFSCORE pCore;
     2312    int rc = rtFsNtfsVol_QueryCoreForMftRef(pThis, &pEntryHdr->u.FileMftRec, false /*fRelaxedUsa*/, &pCore, pErrInfo);
     2313    if (RT_SUCCESS(rc))
     2314    {
     2315        if (!(pCore->pMftRec->pFileRec->fFlags & NTFSRECFILE_F_DIRECTORY))
     2316        {
     2317            /*
     2318             * Locate the data attribute.
     2319             */
     2320            PRTFSNTFSATTR pDataAttr;
     2321            if (pszStreamName == NULL)
     2322            {
     2323                pDataAttr = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_DATA);
     2324                if (pDataAttr)
     2325                    rc = VINF_SUCCESS;
     2326                else
     2327                    rc = RTERRINFO_LOG_SET_F(pErrInfo, VERR_NOT_A_FILE, "%s: no unamed data stream", pszWhat);
     2328            }
     2329            else
     2330            {
     2331                NOREF(pszStreamName);
     2332                rc = RTERRINFO_LOG_SET_F(pErrInfo, VERR_NOT_IMPLEMENTED, "%s: named data streams not implemented yet", pszWhat);
     2333                pDataAttr = NULL;
     2334            }
     2335            if (RT_SUCCESS(rc))
     2336            {
     2337                /*
     2338                 * Get a referenced shared file structure, creating it if necessary.
     2339                 */
     2340                PRTFSNTFSFILESHRD pShared = pDataAttr->uObj.pSharedFile;
     2341                if (pShared)
     2342                {
     2343                    uint32_t cRefs = ASMAtomicIncU32(&pShared->cRefs);
     2344                    Assert(cRefs > 1); NOREF(cRefs);
     2345                }
     2346                else
     2347                {
     2348                    pShared = (PRTFSNTFSFILESHRD)RTMemAllocZ(sizeof(*pShared));
     2349                    if (pShared)
     2350                    {
     2351                        pShared->cRefs = 1;
     2352                        pShared->pData = pDataAttr;
     2353                        rtFsNtfsCore_Retain(pCore);
     2354                        pDataAttr->uObj.pSharedFile = pShared;
     2355                    }
     2356                }
     2357                if (pShared)
     2358                {
     2359                    /*
     2360                     * Create the open file instance.
     2361                     */
     2362                    PRTFSNTFSFILE pNewFile;
     2363                    rc = RTVfsNewFile(&g_rtFsNtfsFileOps, sizeof(*pNewFile), fOpen, pThis->hVfsSelf, NIL_RTVFSLOCK,
     2364                                      phVfsFile, (void **)&pNewFile);
     2365                    if (RT_SUCCESS(rc))
     2366                    {
     2367                        pNewFile->offFile = 0;
     2368                        pNewFile->pShared = pShared;
     2369                        return VINF_SUCCESS;
     2370                    }
     2371
     2372                    rtFsNtfsFileShrd_Release(pShared);
     2373                }
     2374                else
     2375                    rc = VERR_NO_MEMORY;
     2376            }
     2377        }
     2378        else
     2379            rc = RTERRINFO_LOG_SET_F(pErrInfo, VERR_NOT_A_FILE, "%s: fFlags=%#x", pszWhat, pCore->pMftRec->pFileRec->fFlags);
     2380        rtFsNtfsCore_Release(pCore);
     2381    }
     2382    return rc;
     2383}
     2384
    20142385
    20152386
     
    31863557                if (fFlags & RTVFSOBJ_F_OPEN_FILE)
    31873558                {
    3188                     //RTVFSFILE hVfsFile;
    3189                     //rc = rtFsIsoFile_New9660(pVol, pShared, pDirRec, cDirRecs,
    3190                     //                         offDirRec, fOpen, uVersion, &hVfsFile);
    3191                     //if (RT_SUCCESS(rc))
    3192                     //{
    3193                     //    *phVfsObj = RTVfsObjFromFile(hVfsFile);
    3194                     //    RTVfsFileRelease(hVfsFile);
    3195                     //    AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
    3196                     //}
    3197                     rc = VERR_NOT_IMPLEMENTED;
     3559                    RTVFSFILE hVfsFile;
     3560                    rc = rtFsNtfsVol_NewFile(pVol, fOpen, pEntryHdr, NULL /*pszStreamName*/, &hVfsFile, NULL, pszEntry);
     3561                    if (RT_SUCCESS(rc))
     3562                    {
     3563                        *phVfsObj = RTVfsObjFromFile(hVfsFile);
     3564                        RTVfsFileRelease(hVfsFile);
     3565                        AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
     3566                    }
    31983567                }
    31993568                else
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette