VirtualBox

Ignore:
Timestamp:
Nov 8, 2010 4:15:07 PM (14 years ago)
Author:
vboxsync
Message:

iprt/vfs: more code.

Location:
trunk/src/VBox/Runtime/common/vfs
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp

    r33822 r33859  
    3636#include <iprt/file.h>
    3737#include <iprt/mem.h>
     38#include <iprt/param.h>
     39#include <iprt/path.h>
     40#include <iprt/semaphore.h>
     41
     42#include "internal/file.h"
     43#include "internal/magics.h"
     44//#include "internal/vfs.h"
    3845
    3946
     
    4350#define RTVFS_MAGIC                 UINT32_C(0x11112222)
    4451#define RTVFS_MAGIC_DEAD            (~RTVFS_MAGIC)
     52#define RTVFSDIR_MAGIC              UINT32_C(0x77778888)
     53#define RTVFSDIR_MAGIC_DEAD         (~RTVFSDIR_MAGIC)
     54#define RTVFSFILE_MAGIC             UINT32_C(0x55556666)
     55#define RTVFSFILE_MAGIC_DEAD        (~RTVFSFILE_MAGIC)
    4556#define RTVFSIOSTREAM_MAGIC         UINT32_C(0x33334444)
    4657#define RTVFSIOSTREAM_MAGIC_DEAD    (~RTVFSIOSTREAM_MAGIC)
    47 #define RTVFSFILE_MAGIC             UINT32_C(0x55556666)
    48 #define RTVFSFILE_MAGIC_DEAD        (~RTVFSFILE_MAGIC)
     58#define RTVFSSYMLINK_MAGIC          UINT32_C(0x9999aaaa)
     59#define RTVFSSYMLINK_MAGIC_DEAD     (~RTVFSSYMLINK_MAGIC)
    4960
    5061/** The instance data alignment. */
    5162#define RTVFS_INST_ALIGNMENT        16U
     63
     64/** The max number of symbolic links to resolve in a path. */
     65#define RTVFS_MAX_LINKS             20U
     66
     67
     68/** Takes a write lock. */
     69#define RTVFS_WRITE_LOCK(hSemRW)  \
     70    do { \
     71        if ((hSemRW) != NIL_RTSEMRW) \
     72        { \
     73            int rcSemEnter = RTSemRWRequestWrite(hSemRW, RT_INDEFINITE_WAIT); \
     74            AssertRC(rcSemEnter); \
     75        } \
     76    } while (0)
     77
     78/** Releases a write lock. */
     79#define RTVFS_WRITE_UNLOCK(hSemRW)  \
     80    do { \
     81        if ((hSemRW) != NIL_RTSEMRW) \
     82        { \
     83            int rcSemLeave = RTSemRWReleaseWrite(hSemRW); \
     84            AssertRC(rcSemLeave); \
     85        } \
     86    } while (0)
     87
     88/** Takes a read lock. */
     89#define RTVFS_READ_LOCK(hSemRW)  \
     90    do { \
     91        if ((hSemRW) != NIL_RTSEMRW) \
     92        { \
     93            int rcSemEnter = RTSemRWRequestRead(hSemRW, RT_INDEFINITE_WAIT); \
     94            AssertRC(rcSemEnter); \
     95        } \
     96    } while (0)
     97
     98/** Releases a read lock. */
     99#define RTVFS_READ_UNLOCK(hSemRW)  \
     100    do { \
     101        if ((hSemRW) != NIL_RTSEMRW) \
     102        { \
     103            int rcSemLeave = RTSemRWReleaseRead(hSemRW); \
     104            AssertRC(rcSemLeave); \
     105        } \
     106    } while (0)
    52107
    53108
     
    104159
    105160/**
     161 * The VFS symbolic link handle data.
     162 */
     163typedef struct RTVFSSYMLINKINTERNAL
     164{
     165    /** The VFS magic (RTVFSSYMLINK_MAGIC). */
     166    uint32_t                uMagic;
     167    /** Reserved for flags or something. */
     168    uint32_t                fReserved;
     169    /** Pointer to the instance data. */
     170    void                   *pvThis;
     171    /** The vtable. */
     172    PCRTVFSSYMLINKOPS       pOps;
     173    /** The VFS RW sem if serialized. */
     174    RTSEMRW                 hSemRW;
     175    /** Reference back to the VFS containing this symbolic link. */
     176    RTVFS                   hVfs;
     177    /** The number of references to this symbolic link handle. */
     178    uint32_t volatile       cRefs;
     179} RTVFSSYMLINKINTERNAL;
     180
     181
     182/**
    106183 * The VFS I/O stream handle data.
    107184 *
     
    145222
    146223
     224
    147225/**
    148226 * Internal object retainer that asserts sanity in strict builds.
     
    183261}
    184262
     263
     264/*
     265 *
     266 *  U T I L   U T I L   U T I L
     267 *  U T I L   U T I L   U T I L
     268 *  U T I L   U T I L   U T I L
     269 *
     270 */
     271
     272
     273
     274/**
     275 * Removes dots from the path.
     276 *
     277 * @returns The new @a pszDst value.
     278 * @param   pPath               The path parsing buffer.
     279 * @param   pszDst              The current szPath position.  This will be
     280 *                              updated and returned.
     281 * @param   fTheEnd             Indicates whether we're at the end of the path
     282 *                              or not.
     283 * @param   piRestartComp       The component to restart parsing at.
     284 */
     285static char *rtVfsParsePathHandleDots(PRTVFSPARSEDPATH pPath, char *pszDst, bool fTheEnd, uint16_t *piRestartComp)
     286{
     287    if (pszDst[-1] != '.')
     288        return pszDst;
     289
     290    if (pszDst[-2] == '/')
     291    {
     292        pPath->cComponents--;
     293        pszDst = &pPath->szPath[pPath->aoffComponents[pPath->cComponents]];
     294    }
     295    else if (pszDst[-2] == '.' && pszDst[-3] == '/')
     296    {
     297        pPath->cComponents -= pPath->cComponents > 1 ? 2 : 1;
     298        pszDst = &pPath->szPath[pPath->aoffComponents[pPath->cComponents]];
     299        if (piRestartComp && *piRestartComp + 1 >= pPath->cComponents)
     300            *piRestartComp = pPath->cComponents > 0 ? pPath->cComponents - 1 : 0;
     301    }
     302    else
     303        return pszDst;
     304
     305    /*
     306     * Drop the trailing slash if we're at the end of the source path.
     307     */
     308    if (fTheEnd && pPath->cComponents == 0)
     309        pszDst--;
     310    return pszDst;
     311}
     312
     313
     314RTDECL(int) RTVfsParsePathAppend(PRTVFSPARSEDPATH pPath, const char *pszPath, uint16_t *piRestartComp)
     315{
     316    AssertReturn(*pszPath != '/', VERR_INTERNAL_ERROR_4);
     317
     318    /* In case *piRestartComp was set higher than the number of components
     319       before making the call to this function. */
     320    if (piRestartComp && *piRestartComp + 1 >= pPath->cComponents)
     321        *piRestartComp = pPath->cComponents > 0 ? pPath->cComponents - 1 : 0;
     322
     323    /*
     324     * Append a slash to the destination path if necessary.
     325     */
     326    char *pszDst = &pPath->szPath[pPath->cch];
     327    if (pPath->cComponents > 0)
     328    {
     329        *pszDst++ = '/';
     330        if (pszDst - &pPath->szPath[0] >= RTVFSPARSEDPATH_MAX)
     331            return VERR_FILENAME_TOO_LONG;
     332    }
     333    Assert(pszDst[-1] == '/');
     334
     335    /*
     336     * Parse and append the relative path.
     337     */
     338    const char *pszSrc = pszPath;
     339    pPath->fDirSlash   = false;
     340    while (pszSrc[0])
     341    {
     342        /* Skip unncessary slashes. */
     343        while (pszSrc[0] == '/')
     344            pszSrc++;
     345
     346        /* Copy until we encounter the next slash. */
     347        pPath->aoffComponents[pPath->cComponents++] = pszDst - &pPath->szPath[0];
     348        while (pszSrc[0])
     349        {
     350            if (pszSrc[0] == '/')
     351            {
     352                pszSrc++;
     353                if (pszSrc[0])
     354                    *pszDst++ = '/';
     355                else
     356                    pPath->fDirSlash = true;
     357                pszDst = rtVfsParsePathHandleDots(pPath, pszDst, pszSrc[0] == '\0', piRestartComp);
     358                break;
     359            }
     360
     361            *pszDst++ = *pszSrc++;
     362            if (pszDst - &pPath->szPath[0] >= RTVFSPARSEDPATH_MAX)
     363                return VERR_FILENAME_TOO_LONG;
     364        }
     365    }
     366    pszDst = rtVfsParsePathHandleDots(pPath, pszDst, true /*fTheEnd*/, piRestartComp);
     367
     368    /* Terminate the string and enter its length. */
     369    pszDst[0] = '\0';
     370    pszDst[1] = '\0';                   /* for aoffComponents */
     371    pPath->cch = (uint16_t)(pszDst - &pPath->szPath[0]);
     372    pPath->aoffComponents[pPath->cComponents] = pPath->cch + 1;
     373
     374    return VINF_SUCCESS;
     375}
     376
     377
     378RTDECL(int) RTVfsParsePath(PRTVFSPARSEDPATH pPath, const char *pszPath, const char *pszCwd)
     379{
     380    if (*pszPath != '/')
     381    {
     382        /*
     383         * Relative, recurse and parse pszCwd first.
     384         */
     385        int rc = RTVfsParsePath(pPath, pszCwd, NULL /*crash if pszCwd is not absolute*/);
     386        if (RT_FAILURE(rc))
     387            return rc;
     388    }
     389    else
     390    {
     391        /*
     392         * Make pszPath relative, i.e. set up pPath for the root and skip
     393         * leading slashes in pszPath before appending it.
     394         */
     395        pPath->cch               = 1;
     396        pPath->cComponents       = 0;
     397        pPath->fDirSlash         = false;
     398        pPath->aoffComponents[0] = 1;
     399        pPath->aoffComponents[1] = 2;
     400        pPath->szPath[0]         = '/';
     401        pPath->szPath[1]         = '\0';
     402        pPath->szPath[2]         = '\0';
     403        while (pszPath[0] == '/')
     404            pszPath++;
     405        if (!pszPath[0])
     406            return VINF_SUCCESS;
     407    }
     408    return RTVfsParsePathAppend(pPath, pszPath, NULL);
     409}
     410
     411
     412
     413RTDECL(int) RTVfsParsePathA(const char *pszPath, const char *pszCwd, PRTVFSPARSEDPATH *ppPath)
     414{
     415    /*
     416     * Allocate the output buffer and hand the problem to rtVfsParsePath.
     417     */
     418    int rc;
     419    PRTVFSPARSEDPATH pPath = (PRTVFSPARSEDPATH)RTMemTmpAlloc(sizeof(RTVFSPARSEDPATH));
     420    if (pPath)
     421    {
     422        rc = RTVfsParsePath(pPath, pszPath, pszCwd);
     423        if (RT_FAILURE(rc))
     424        {
     425            RTMemTmpFree(pPath);
     426            pPath = NULL;
     427        }
     428    }
     429    else
     430        rc = VERR_NO_TMP_MEMORY;
     431    *ppPath = pPath;                    /* always set it */
     432    return rc;
     433}
     434
     435
     436RTDECL(void) RTVfsParsePathFree(PRTVFSPARSEDPATH pPath)
     437{
     438    if (pPath)
     439    {
     440        pPath->cch               = UINT16_MAX;
     441        pPath->cComponents       = UINT16_MAX;
     442        pPath->aoffComponents[0] = UINT16_MAX;
     443        pPath->aoffComponents[1] = UINT16_MAX;
     444        RTMemTmpFree(pPath);
     445    }
     446}
     447
     448
     449/**
     450 * Handles a symbolic link, adding it to
     451 *
     452 * @returns IPRT status code.
     453 * @param   pPath               The parsed path to update.
     454 * @param   piComponent         The component iterator to update.
     455 * @param   hSymlink            The symbolic link to process.
     456 */
     457static int rtVfsTraverseHandleSymlink(PRTVFSPARSEDPATH pPath, uint16_t *piComponent, RTVFSSYMLINK hSymlink)
     458{
     459    /*
     460     * Read the link.
     461     */
     462    char szPath[RTPATH_MAX];
     463    int rc = RTVfsSymlinkRead(hSymlink, szPath, sizeof(szPath) - 1);
     464    if (RT_SUCCESS(rc))
     465    {
     466        szPath[sizeof(szPath) - 1] = '\0';
     467        if (szPath[0] == '/')
     468        {
     469            /*
     470             * Absolute symlink.
     471             */
     472            rc = RTVfsParsePath(pPath, szPath, NULL);
     473            if (RT_SUCCESS(rc))
     474            {
     475                *piComponent = 0;
     476                return VINF_SUCCESS;
     477            }
     478        }
     479        else
     480        {
     481            /*
     482             * Relative symlink, must replace the current component with the
     483             * link value.  We do that by using the remainder of the symlink
     484             * buffer as temporary storage.
     485             */
     486            uint16_t iComponent = *piComponent;
     487            if (iComponent + 1 < pPath->cComponents)
     488                rc = RTPathAppend(szPath, sizeof(szPath), &pPath->szPath[pPath->aoffComponents[iComponent + 1]]);
     489            if (RT_SUCCESS(rc))
     490            {
     491                pPath->cch = pPath->aoffComponents[iComponent] - (iComponent > 0);
     492                pPath->aoffComponents[iComponent + 1] = pPath->cch + 1;
     493                pPath->szPath[pPath->cch]     = '\0';
     494                pPath->szPath[pPath->cch + 1] = '\0';
     495
     496                rc = RTVfsParsePathAppend(pPath, szPath, &iComponent);
     497                if (RT_SUCCESS(rc))
     498                {
     499                    *piComponent = iComponent;
     500                    return VINF_SUCCESS;
     501                }
     502            }
     503        }
     504    }
     505    return rc == VERR_BUFFER_OVERFLOW ? VERR_FILENAME_TOO_LONG : rc;
     506}
     507
     508
     509/**
     510 * Internal worker for various open functions as well as RTVfsTraverseToParent.
     511 *
     512 * @returns IPRT status code.
     513 * @param   pThis           The VFS.
     514 * @param   pPath           The parsed path.  This may be changed as symbolic
     515 *                          links are processed during the path traversal.
     516 * @param   fFollowSymlink  Whether to follow the final component if it is a
     517 *                          symbolic link.
     518 * @param   ppVfsParentDir  Where to return the parent directory handle
     519 *                          (referenced).
     520 */
     521static int rtVfsTraverseToParent(RTVFSINTERNAL *pThis, PRTVFSPARSEDPATH pPath, bool fFollowSymlink,
     522                                 RTVFSDIRINTERNAL **ppVfsParentDir)
     523{
     524    /*
     525     * Assert sanity.
     526     */
     527    AssertPtr(pThis);
     528    Assert(pThis->uMagic == RTVFS_MAGIC);
     529    Assert(pThis->cRefs > 0);
     530    AssertPtr(pPath);
     531    AssertPtr(ppVfsParentDir);
     532    AssertReturn(pPath->cComponents > 0, VERR_INTERNAL_ERROR_3);
     533
     534    /*
     535     * Open the root directory.
     536     */
     537    /** @todo Union mounts, traversal optimization methods, races, ++ */
     538    RTVFSDIRINTERNAL *pCurDir;
     539    RTVFS_READ_LOCK(pThis->hSemRW);
     540    int rc = pThis->pOps->pfnOpenRoot(pThis->pvThis, &pCurDir);
     541    RTVFS_READ_UNLOCK(pThis->hSemRW);
     542    if (RT_FAILURE(rc))
     543        return rc;
     544    Assert(pCurDir->uMagic == RTVFSDIR_MAGIC);
     545
     546    /*
     547     * The traversal loop.
     548     */
     549    unsigned cLinks     = 0;
     550    uint16_t iComponent = 0;
     551    for (;;)
     552    {
     553        /*
     554         * Are we done yet?
     555         */
     556        bool fFinal = iComponent + 1 >= pPath->cComponents;
     557        if (fFinal && !fFollowSymlink)
     558        {
     559            *ppVfsParentDir = pCurDir;
     560            return VINF_SUCCESS;
     561        }
     562
     563        /*
     564         * Try open the next entry.
     565         */
     566        const char     *pszEntry    = &pPath->szPath[pPath->aoffComponents[iComponent]];
     567        char           *pszEntryEnd = &pPath->szPath[pPath->aoffComponents[iComponent + 1] - 1];
     568        *pszEntryEnd = '\0';
     569        RTVFSDIR        hDir     = NIL_RTVFSDIR;
     570        RTVFSSYMLINK    hSymlink = NIL_RTVFSSYMLINK;
     571        RTVFS           hVfsMnt  = NIL_RTVFS;
     572        if (fFinal)
     573        {
     574            RTVFS_READ_LOCK(pCurDir->hSemRW);
     575            rc = pCurDir->pOps->pfnTraversalOpen(pCurDir->pvThis, pszEntry, NULL, &hSymlink, NULL);
     576            RTVFS_READ_UNLOCK(pCurDir->hSemRW);
     577            *pszEntryEnd = '\0';
     578            if (rc == VERR_PATH_NOT_FOUND)
     579                rc = VINF_SUCCESS;
     580            if (RT_FAILURE(rc))
     581                break;
     582
     583            if (hSymlink == NIL_RTVFSSYMLINK)
     584            {
     585                *ppVfsParentDir = pCurDir;
     586                return VINF_SUCCESS;
     587            }
     588        }
     589        else
     590        {
     591            RTVFS_READ_LOCK(pCurDir->hSemRW);
     592            rc = pCurDir->pOps->pfnTraversalOpen(pCurDir->pvThis, pszEntry, &hDir, &hSymlink, &hVfsMnt);
     593            RTVFS_READ_UNLOCK(pCurDir->hSemRW);
     594            *pszEntryEnd = '/';
     595            if (RT_FAILURE(rc))
     596                break;
     597
     598            if (   hDir     == NIL_RTVFSDIR
     599                && hSymlink == NIL_RTVFSSYMLINK
     600                && hVfsMnt  == NIL_RTVFS)
     601            {
     602                rc = VERR_NOT_A_DIRECTORY;
     603                break;
     604            }
     605        }
     606        Assert(   (hDir != NIL_RTVFSDIR && hSymlink == NIL_RTVFSSYMLINK && hVfsMnt == NIL_RTVFS)
     607               || (hDir == NIL_RTVFSDIR && hSymlink != NIL_RTVFSSYMLINK && hVfsMnt == NIL_RTVFS)
     608               || (hDir == NIL_RTVFSDIR && hSymlink == NIL_RTVFSSYMLINK && hVfsMnt != NIL_RTVFS));
     609
     610        if (hDir != NIL_RTVFSDIR)
     611        {
     612            /*
     613             * Directory - advance down the path.
     614             */
     615            AssertPtr(hDir);
     616            Assert(hDir->uMagic == RTVFSDIR_MAGIC);
     617            RTVfsDirRelease(pCurDir);
     618            pCurDir = hDir;
     619            iComponent++;
     620        }
     621        else if (hSymlink != NIL_RTVFSSYMLINK)
     622        {
     623            /*
     624             * Symbolic link - deal with it and retry the current component.
     625             */
     626            AssertPtr(hSymlink);
     627            Assert(hSymlink->uMagic == RTVFSSYMLINK_MAGIC);
     628            cLinks++;
     629            if (cLinks >= RTVFS_MAX_LINKS)
     630            {
     631                rc = VERR_TOO_MANY_SYMLINKS;
     632                break;
     633            }
     634            uint16_t iRestartComp = iComponent;
     635            rc = rtVfsTraverseHandleSymlink(pPath, &iRestartComp, hSymlink);
     636            if (RT_FAILURE(rc))
     637                break;
     638            if (iRestartComp != iComponent)
     639            {
     640                /* Must restart from the root (optimize this). */
     641                RTVfsDirRelease(pCurDir);
     642                RTVFS_READ_LOCK(pThis->hSemRW);
     643                rc = pThis->pOps->pfnOpenRoot(pThis->pvThis, &pCurDir);
     644                RTVFS_READ_UNLOCK(pThis->hSemRW);
     645                if (RT_FAILURE(rc))
     646                {
     647                    pCurDir = NULL;
     648                    break;
     649                }
     650                iComponent = 0;
     651            }
     652        }
     653        else
     654        {
     655            /*
     656             * Mount point - deal with it and retry the current component.
     657             */
     658            RTVfsDirRelease(pCurDir);
     659            RTVFS_READ_LOCK(hVfsMnt->hSemRW);
     660            rc = pThis->pOps->pfnOpenRoot(hVfsMnt->pvThis, &pCurDir);
     661            RTVFS_READ_UNLOCK(hVfsMnt->hSemRW);
     662            if (RT_FAILURE(rc))
     663            {
     664                pCurDir = NULL;
     665                break;
     666            }
     667            iComponent = 0;
     668            /** @todo union mounts. */
     669        }
     670    }
     671
     672    if (pCurDir)
     673        RTVfsDirRelease(pCurDir);
     674
     675    return rc;
     676}
     677
     678
     679
     680/*
     681 *
     682 *  D I R   D I R   D I R
     683 *  D I R   D I R   D I R
     684 *  D I R   D I R   D I R
     685 *
     686 */
     687
     688RTDECL(uint32_t)    RTVfsDirRetain(RTVFSDIR hVfsDir)
     689{
     690    RTVFSDIRINTERNAL *pThis = hVfsDir;
     691    AssertPtrReturn(pThis, UINT32_MAX);
     692    AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, UINT32_MAX);
     693    return rtVfsRetain(&pThis->cRefs);
     694}
     695
     696
     697RTDECL(uint32_t)    RTVfsDirRelease(RTVFSDIR hVfsDir)
     698{
     699    RTVFSDIRINTERNAL *pThis = hVfsDir;
     700    AssertPtrReturn(pThis, UINT32_MAX);
     701    AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, UINT32_MAX);
     702
     703    uint32_t cRefs = rtVfsRelease(&pThis->cRefs);
     704    if (!cRefs)
     705    {
     706        RTVFS_WRITE_LOCK(pThis->hSemRW);
     707        ASMAtomicWriteU32(&pThis->uMagic, RTVFSDIR_MAGIC_DEAD);
     708        RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     709        pThis->pOps->Obj.pfnClose(pThis->pvThis);
     710        RTMemFree(pThis);
     711    }
     712
     713    return cRefs;
     714}
     715
     716
     717
     718/*
     719 *
     720 *  S Y M B O L I C   L I N K
     721 *  S Y M B O L I C   L I N K
     722 *  S Y M B O L I C   L I N K
     723 *
     724 */
     725
     726RTDECL(uint32_t)    RTVfsSymlinkRetain(RTVFSSYMLINK hVfsSym)
     727{
     728    RTVFSSYMLINKINTERNAL *pThis = hVfsSym;
     729    AssertPtrReturn(pThis, UINT32_MAX);
     730    AssertReturn(pThis->uMagic == RTVFSSYMLINK_MAGIC, UINT32_MAX);
     731    return rtVfsRetain(&pThis->cRefs);
     732}
     733
     734
     735RTDECL(uint32_t)    RTVfsSymlinkRelease(RTVFSSYMLINK hVfsSym)
     736{
     737    RTVFSSYMLINKINTERNAL *pThis = hVfsSym;
     738    AssertPtrReturn(pThis, UINT32_MAX);
     739    AssertReturn(pThis->uMagic == RTVFSSYMLINK_MAGIC, UINT32_MAX);
     740
     741    uint32_t cRefs = rtVfsRelease(&pThis->cRefs);
     742    if (!cRefs)
     743    {
     744        RTVFS_WRITE_LOCK(pThis->hSemRW);
     745        ASMAtomicWriteU32(&pThis->uMagic, RTVFSSYMLINK_MAGIC_DEAD);
     746        RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     747        pThis->pOps->Obj.pfnClose(pThis->pvThis);
     748        RTMemFree(pThis);
     749    }
     750
     751    return cRefs;
     752}
     753
     754
     755RTDECL(int)         RTVfsSymlinkRead(RTVFSSYMLINK hVfsSym, char *pszTarget, size_t cbTarget)
     756{
     757    RTVFSSYMLINKINTERNAL *pThis = hVfsSym;
     758    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     759    AssertReturn(pThis->uMagic == RTVFSSYMLINK_MAGIC, VERR_INVALID_HANDLE);
     760
     761    RTVFS_WRITE_LOCK(pThis->hSemRW);
     762    int rc = pThis->pOps->pfnRead(pThis->pvThis, pszTarget, cbTarget);
     763    RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     764
     765    return rc;
     766}
     767
     768
     769
     770/*
     771 *
     772 *  I / O   S T R E A M     I / O   S T R E A M     I / O   S T R E A M
     773 *  I / O   S T R E A M     I / O   S T R E A M     I / O   S T R E A M
     774 *  I / O   S T R E A M     I / O   S T R E A M     I / O   S T R E A M
     775 *
     776 */
    185777
    186778RTDECL(uint32_t)    RTVfsIoStrmRetain(RTVFSIOSTREAM hVfsIos)
     
    209801         * need to get to the real one before handing it to RTMemFree.
    210802         */
     803        RTVFS_WRITE_LOCK(pThis->hSemRW);
    211804        ASMAtomicWriteU32(&pThis->uMagic, RTVFSIOSTREAM_MAGIC_DEAD);
     805        RTVFS_WRITE_UNLOCK(pThis->hSemRW);
    212806        pThis->pOps->Obj.pfnClose(pThis->pvThis);
    213807
     
    262856    AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE);
    263857
    264     return pThis->pOps->Obj.pfnQueryInfo(pThis->pvThis, pObjInfo, enmAddAttr);
     858    RTVFS_READ_LOCK(pThis->hSemRW);
     859    int rc = pThis->pOps->Obj.pfnQueryInfo(pThis->pvThis, pObjInfo, enmAddAttr);
     860    RTVFS_READ_UNLOCK(pThis->hSemRW);
     861    return rc;
    265862}
    266863
     
    275872    RTSGBUF SgBuf;
    276873    RTSgBufInit(&SgBuf, &Seg, 1);
    277     return pThis->pOps->pfnRead(pThis->pvThis, -1 /*off*/, &SgBuf, pcbRead == NULL /*fBlocking*/, pcbRead);
     874
     875    RTVFS_WRITE_LOCK(pThis->hSemRW);
     876    int rc = pThis->pOps->pfnRead(pThis->pvThis, -1 /*off*/, &SgBuf, pcbRead == NULL /*fBlocking*/, pcbRead);
     877    RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     878    return rc;
    278879}
    279880
     
    288889    RTSGBUF SgBuf;
    289890    RTSgBufInit(&SgBuf, &Seg, 1);
    290     return pThis->pOps->pfnWrite(pThis->pvThis, -1 /*off*/, &SgBuf, pcbWritten == NULL /*fBlocking*/, pcbWritten);
     891
     892    RTVFS_WRITE_LOCK(pThis->hSemRW);
     893    int rc = pThis->pOps->pfnWrite(pThis->pvThis, -1 /*off*/, &SgBuf, pcbWritten == NULL /*fBlocking*/, pcbWritten);
     894    RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     895    return rc;
    291896}
    292897
     
    300905    AssertReturn(fBlocking || VALID_PTR(pcbRead), VERR_INVALID_PARAMETER);
    301906
    302     return pThis->pOps->pfnRead(pThis->pvThis, -1 /*off*/, pSgBuf, fBlocking, pcbRead);
     907    RTVFS_WRITE_LOCK(pThis->hSemRW);
     908    int rc = pThis->pOps->pfnRead(pThis->pvThis, -1 /*off*/, pSgBuf, fBlocking, pcbRead);
     909    RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     910    return rc;
    303911}
    304912
     
    312920    AssertReturn(fBlocking || VALID_PTR(pcbWritten), VERR_INVALID_PARAMETER);
    313921
    314     return pThis->pOps->pfnWrite(pThis->pvThis, -1 /*off*/, pSgBuf, fBlocking, pcbWritten);
     922    RTVFS_WRITE_LOCK(pThis->hSemRW);
     923    int rc = pThis->pOps->pfnWrite(pThis->pvThis, -1 /*off*/, pSgBuf, fBlocking, pcbWritten);
     924    RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     925    return rc;
    315926}
    316927
     
    322933    AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE);
    323934
    324     return pThis->pOps->pfnFlush(pThis->pvThis);
     935    RTVFS_WRITE_LOCK(pThis->hSemRW);
     936    int rc = pThis->pOps->pfnFlush(pThis->pvThis);
     937    RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     938    return rc;
    325939}
    326940
     
    333947    AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, VERR_INVALID_HANDLE);
    334948
    335     return pThis->pOps->pfnPollOne(pThis->pvThis, fEvents, cMillies, fIntr, pfRetEvents);
     949    RTVFS_WRITE_LOCK(pThis->hSemRW);
     950    int rc = pThis->pOps->pfnPollOne(pThis->pvThis, fEvents, cMillies, fIntr, pfRetEvents);
     951    RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     952    return rc;
    336953}
    337954
     
    344961
    345962    RTFOFF off;
     963    RTVFS_READ_LOCK(pThis->hSemRW);
    346964    int rc = pThis->pOps->pfnTell(pThis->pvThis, &off);
     965    RTVFS_READ_UNLOCK(pThis->hSemRW);
    347966    if (RT_FAILURE(rc))
    348967        off = rc;
     
    351970
    352971
     972RTDECL(int)         RTVfsIoStrmSkip(RTVFSIOSTREAM hVfsIos, RTFOFF cb)
     973{
     974    RTVFSIOSTREAMINTERNAL *pThis = hVfsIos;
     975    AssertPtrReturn(pThis, -1);
     976    AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, -1);
     977    AssertReturn(cb >= 0, VERR_INVALID_PARAMETER);
     978
     979    int rc;
     980    if (pThis->pOps->pfnSkip)
     981    {
     982        RTVFS_WRITE_LOCK(pThis->hSemRW);
     983        rc = pThis->pOps->pfnSkip(pThis->pvThis, cb);
     984        RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     985    }
     986    else
     987    {
     988        void *pvBuf = RTMemTmpAlloc(_64K);
     989        if (pvBuf)
     990        {
     991            rc = VINF_SUCCESS;
     992            while (cb > 0)
     993            {
     994                size_t cbToRead = RT_MIN(cb, _64K);
     995                RTVFS_WRITE_LOCK(pThis->hSemRW);
     996                rc = RTVfsIoStrmRead(hVfsIos, pvBuf, cbToRead, NULL);
     997                RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     998                if (RT_FAILURE(rc))
     999                    break;
     1000                cb -= cbToRead;
     1001            }
     1002
     1003            RTMemTmpFree(pvBuf);
     1004        }
     1005        else
     1006            rc = VERR_NO_TMP_MEMORY;
     1007    }
     1008    return rc;
     1009}
     1010
     1011
     1012RTDECL(int)         RTVfsIoStrmZeroFill(RTVFSIOSTREAM hVfsIos, RTFOFF cb)
     1013{
     1014    RTVFSIOSTREAMINTERNAL *pThis = hVfsIos;
     1015    AssertPtrReturn(pThis, -1);
     1016    AssertReturn(pThis->uMagic == RTVFSIOSTREAM_MAGIC, -1);
     1017
     1018    int rc;
     1019    if (pThis->pOps->pfnSkip)
     1020    {
     1021        RTVFS_WRITE_LOCK(pThis->hSemRW);
     1022        rc = pThis->pOps->pfnZeroFill(pThis->pvThis, cb);
     1023        RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     1024    }
     1025    else
     1026    {
     1027        void *pvBuf = RTMemTmpAllocZ(_64K);
     1028        if (pvBuf)
     1029        {
     1030            rc = VINF_SUCCESS;
     1031            while (cb > 0)
     1032            {
     1033                size_t cbToWrite = RT_MIN(cb, _64K);
     1034                RTVFS_WRITE_LOCK(pThis->hSemRW);
     1035                rc = RTVfsIoStrmWrite(hVfsIos, pvBuf, cbToWrite, NULL);
     1036                RTVFS_WRITE_UNLOCK(pThis->hSemRW);
     1037                if (RT_FAILURE(rc))
     1038                    break;
     1039                cb -= cbToWrite;
     1040            }
     1041
     1042            RTMemTmpFree(pvBuf);
     1043        }
     1044        else
     1045            rc = VERR_NO_TMP_MEMORY;
     1046    }
     1047    return rc;
     1048}
     1049
     1050
     1051
     1052
     1053
     1054
     1055/*
     1056 *
     1057 *  F I L E   F I L E   F I L E
     1058 *  F I L E   F I L E   F I L E
     1059 *  F I L E   F I L E   F I L E
     1060 *
     1061 */
    3531062
    3541063RTDECL(int) RTVfsNewFile(PCRTVFSFILEOPS pFileOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs,
     
    4031112
    4041113
     1114RTDECL(int)         RTVfsFileOpen(RTVFS hVfs, const char *pszFilename, uint32_t fOpen, PRTVFSFILE phVfsFile)
     1115{
     1116    /*
     1117     * Validate input.
     1118     */
     1119    RTVFSINTERNAL *pThis = hVfs;
     1120    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1121    AssertReturn(pThis->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE);
     1122    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
     1123    AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER);
     1124
     1125    int rc = rtFileRecalcAndValidateFlags(&fOpen);
     1126    if (RT_FAILURE(rc))
     1127        return rc;
     1128
     1129    /*
     1130     * Parse the path, assume current directory is root since we've got no
     1131     * caller context here.
     1132     */
     1133    PRTVFSPARSEDPATH pPath;
     1134    rc = RTVfsParsePathA(pszFilename, "/", &pPath);
     1135    if (RT_SUCCESS(rc))
     1136    {
     1137        if (!pPath->fDirSlash)
     1138        {
     1139            /*
     1140             * Tranverse the path, resolving the parent node and any symlinks
     1141             * in the final element, and ask the directory to open the file.
     1142             */
     1143            RTVFSDIRINTERNAL *pVfsParentDir;
     1144            rc = rtVfsTraverseToParent(pThis, pPath, true /*fFollowSymlink*/, &pVfsParentDir);
     1145            if (RT_SUCCESS(rc))
     1146            {
     1147                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
     1148
     1149                /** @todo there is a symlink creation race here. */
     1150                RTVFS_WRITE_LOCK(pVfsParentDir->hSemRW);
     1151                rc = pVfsParentDir->pOps->pfnOpenFile(pVfsParentDir->pvThis, pszEntryName, fOpen, phVfsFile);
     1152                RTVFS_WRITE_UNLOCK(pVfsParentDir->hSemRW);
     1153
     1154                RTVfsDirRelease(pVfsParentDir);
     1155
     1156                if (RT_SUCCESS(rc))
     1157                {
     1158                    AssertPtr(*phVfsFile);
     1159                    Assert((*phVfsFile)->uMagic == RTVFSFILE_MAGIC);
     1160                }
     1161            }
     1162        }
     1163        else
     1164            rc = VERR_INVALID_PARAMETER;
     1165        RTVfsParsePathFree(pPath);
     1166    }
     1167    return rc;
     1168}
     1169
     1170
    4051171RTDECL(uint32_t)    RTVfsFileRetain(RTVFSFILE hVfsFile)
    4061172{
     
    4211187    if (!cRefs)
    4221188    {
     1189        RTVFS_WRITE_LOCK(pThis->Stream.hSemRW);
    4231190        ASMAtomicWriteU32(&pThis->uMagic, RTVFSFILE_MAGIC_DEAD);
    4241191        ASMAtomicWriteU32(&pThis->Stream.uMagic, RTVFSIOSTREAM_MAGIC_DEAD);
     1192        RTVFS_WRITE_UNLOCK(pThis->Stream.hSemRW);
     1193
    4251194        pThis->pOps->Stream.Obj.pfnClose(pThis->Stream.pvThis);
    4261195        RTMemFree(pThis);
  • trunk/src/VBox/Runtime/common/vfs/vfsstdfile.cpp

    r33821 r33859  
    243243
    244244/**
     245 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnSkip}
     246 */
     247static DECLCALLBACK(int) rtVfsStdFile_Skip(void *pvThis, RTFOFF cb)
     248{
     249    PRTVFSSTDFILE pThis = (PRTVFSSTDFILE)pvThis;
     250    uint64_t offIgnore;
     251    return RTFileSeek(pThis->hFile, cb, RTFILE_SEEK_CURRENT, &offIgnore);
     252}
     253
     254
     255/**
    245256 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
    246257 */
     
    339350        rtVfsStdFile_PollOne,
    340351        rtVfsStdFile_Tell,
     352        rtVfsStdFile_Skip,
     353        NULL /*ZeroFill*/,
    341354        RTVFSIOSTREAMOPS_VERSION,
    342355    },
Note: See TracChangeset for help on using the changeset viewer.

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