VirtualBox

Changeset 33859 in vbox


Ignore:
Timestamp:
Nov 8, 2010 4:15:07 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
67505
Message:

iprt/vfs: more code.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/vfs.h

    r33822 r33859  
    120120                                       char *pszMountPoint, size_t cbMountPoint);
    121121
     122
    122123/** @defgroup grp_vfs_dir           VFS Directory API
    123124 * @{
    124125 */
     126
     127/**
     128 * Retains a reference to the VFS directory handle.
     129 *
     130 * @returns New reference count on success, UINT32_MAX on failure.
     131 * @param   hVfsDir         The VFS directory handle.
     132 */
     133RTDECL(uint32_t)    RTVfsDirRetain(RTVFSDIR hVfsDir);
     134
     135/**
     136 * Releases a reference to the VFS directory handle.
     137 *
     138 * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
     139 * @param   hVfsIos         The VFS directory handle.
     140 */
     141RTDECL(uint32_t)    RTVfsDirRelease(RTVFSDIR hVfsDir);
     142
    125143/** @}  */
    126144
    127145
    128 /** @defgroup grp_vfs_iostream      VFS I/O Stream
     146/** @defgroup grp_vfs_iostream      VFS Symbolic Link API
     147 * @{
     148 */
     149
     150/**
     151 * Read the symbolic link target.
     152 *
     153 * @returns IPRT status code.
     154 * @param   hVfsSym         The VFS symbolic link handle.
     155 * @param   pszTarget       The target buffer.
     156 * @param   cbTarget        The size of the target buffer.
     157 * @sa      RTSymlinkRead
     158 */
     159RTDECL(int)         RTVfsSymlinkRead(RTVFSSYMLINK hVfsSym, char *pszTarget, size_t cbTarget);
     160
     161/** @}  */
     162
     163
     164
     165/** @defgroup grp_vfs_iostream      VFS I/O Stream API
    129166 * @{
    130167 */
     
    264301 */
    265302RTDECL(RTFOFF)      RTVfsIoStrmTell(RTVFSIOSTREAM hVfsIos);
     303
     304/**
     305 * Skips @a cb ahead in the stream.
     306 *
     307 * @returns IPRT status code.
     308 * @param   hVfsIos         The VFS I/O stream handle.
     309 * @param   cb              The number bytes to skip.
     310 */
     311RTDECL(int)         RTVfsIoStrmSkip(RTVFSIOSTREAM hVfsIos, RTFOFF cb);
     312
     313/**
     314 * Fills the stream with @a cb zeros.
     315 *
     316 * @returns IPRT status code.
     317 * @param   hVfsIos         The VFS I/O stream handle.
     318 * @param   cb              The number of zero bytes to insert.
     319 */
     320RTDECL(int)         RTVfsIoStrmZeroFill(RTVFSIOSTREAM hVfsIos, RTFOFF cb);
    266321/** @} */
    267322
  • trunk/include/iprt/vfslowlevel.h

    r33822 r33859  
    2828
    2929#include <iprt/vfs.h>
     30#include <iprt/param.h>
    3031
    3132
     
    8788} RTVFSOPS;
    8889/** Pointer to constant VFS operations. */
    89 typedef RTVFSOPS const PCRTVFSOPS;
     90typedef RTVFSOPS const *PCRTVFSOPS;
    9091
    9192/** The RTVFSOPS structure version. */
     
    112113    /** File. */
    113114    RTVFSOBJTYPE_FILE,
     115    /** Symbolic link. */
     116    RTVFSOBJTYPE_SYMLINK,
    114117    /** End of valid object types. */
    115118    RTVFSOBJTYPE_END,
     
    242245
    243246    /**
     247     * Opens a directory entry for traversal purposes.
     248     *
     249     * Method which sole purpose is helping the path traversal.  Only one of
     250     * the three output variables will be set, the others will left untouched
     251     * (caller sets them to NIL).
     252     *
     253     * @returns IPRT status code.
     254     * @retval  VERR_PATH_NOT_FOUND if @a pszEntry was not found.
     255     * @param   pvThis          The implementation specific directory data.
     256     * @param   pszEntry        The name of the directory entry to remove.
     257     * @param   phVfsDir        If not NULL and it is a directory, open it and
     258     *                          return the handle here.
     259     * @param   phVfsSymlink    If not NULL and it is a symbolic link, open it
     260     *                          and return the handle here.
     261     * @param   phVfsMounted    If not NULL and it is a mounted VFS directory,
     262     *                          reference it and return the handle here.
     263     * @todo    Should com dir, symlinks and mount points using some common
     264     *          ancestor "class".
     265     */
     266    DECLCALLBACKMEMBER(int, pfnTraversalOpen)(void *pvThis, const char *pszEntry, PRTVFSDIR phVfsDir,
     267                                              PRTVFSSYMLINK phVfsSymlink, PRTVFS phVfsMounted);
     268
     269    /**
    244270     * Open or create a file.
    245271     *
     
    347373/** The RTVFSDIROPS structure version. */
    348374#define RTVFSDIROPS_VERSION         RT_MAKE_U32_FROM_U8(0xff,0x3f,1,0)
     375
     376
     377/**
     378 * The symbolic link operations.
     379 *
     380 * @extends RTVFSOBJOPS
     381 * @extends RTVFSOBJSETOPS
     382 */
     383typedef struct RTVFSSYMLINKOPS
     384{
     385    /** The basic object operation.  */
     386    RTVFSOBJOPS             Obj;
     387    /** The structure version (RTVFSSYMLINKOPS_VERSION). */
     388    uint32_t                uVersion;
     389    /** Reserved field, MBZ. */
     390    uint32_t                fReserved;
     391    /** The object setter operations. */
     392    RTVFSOBJSETOPS          ObjSet;
     393
     394    /**
     395     * Read the symbolic link target.
     396     *
     397     * @returns IPRT status code.
     398     * @param   pvThis      The implementation specific symbolic link data.
     399     * @param   pszTarget   The target buffer.
     400     * @param   cbTarget    The size of the target buffer.
     401     * @sa      RTSymlinkRead
     402     */
     403    DECLCALLBACKMEMBER(int, pfnRead)(void *pvThis, char *pszTarget, size_t cbTarget);
     404
     405    /** Marks the end of the structure (RTVFSSYMLINKOPS_VERSION). */
     406    uintptr_t               uEndMarker;
     407} RTVFSSYMLINKOPS;
     408/** Pointer to const symbolic link operations. */
     409typedef RTVFSSYMLINKOPS const *PCRTVFSSYMLINKOPS;
     410/** The RTVFSSYMLINKOPS structure version. */
     411#define RTVFSSYMLINKOPS_VERSION     RT_MAKE_U32_FROM_U8(0xff,0x4f,1,0)
    349412
    350413
     
    432495    DECLCALLBACKMEMBER(int, pfnTell)(void *pvThis, PRTFOFF poffActual);
    433496
     497    /**
     498     * Skips @a cb ahead in the stream.
     499     *
     500     * @returns IPRT status code.
     501     * @param   pvThis      The implementation specific file data.
     502     * @param   cb          The number bytes to skip.
     503     * @remarks This is optional and can be NULL.
     504     */
     505    DECLCALLBACKMEMBER(int, pfnSkip)(void *pvThis, RTFOFF cb);
     506
     507    /**
     508     * Fills the stream with @a cb zeros.
     509     *
     510     * @returns IPRT status code.
     511     * @param   pvThis      The implementation specific file data.
     512     * @param   cb          The number of zero bytes to insert.
     513     * @remarks This is optional and can be NULL.
     514     */
     515    DECLCALLBACKMEMBER(int, pfnZeroFill)(void *pvThis, RTFOFF cb);
     516
    434517    /** Marks the end of the structure (RTVFSIOSTREAMOPS_VERSION). */
    435518    uintptr_t               uEndMarker;
     
    439522
    440523/** The RTVFSIOSTREAMOPS structure version. */
    441 #define RTVFSIOSTREAMOPS_VERSION    RT_MAKE_U32_FROM_U8(0xff,0x4f,1,0)
     524#define RTVFSIOSTREAMOPS_VERSION    RT_MAKE_U32_FROM_U8(0xff,0x5f,1,0)
    442525
    443526
     
    490573
    491574/** The RTVFSFILEOPS structure version. */
    492 #define RTVFSFILEOPS_VERSION        RT_MAKE_U32_FROM_U8(0xff,0x5f,1,0)
     575#define RTVFSFILEOPS_VERSION        RT_MAKE_U32_FROM_U8(0xff,0x6f,1,0)
    493576
    494577/**
     
    509592
    510593
     594/** @defgroup grp_rt_vfs_ll_util        VFS Utility APIs
     595 * @{ */
     596
     597/**
     598 * Parsed path.
     599 */
     600typedef struct RTVFSPARSEDPATH
     601{
     602    /** The length of the path in szCopy. */
     603    uint16_t        cch;
     604    /** The number of path components. */
     605    uint16_t        cComponents;
     606    /** Set if the path ends with slash, indicating that it's a directory
     607     * reference and not a file reference.  The slash has been removed from
     608     * the copy. */
     609    bool            fDirSlash;
     610    /** The offset where each path component starts, i.e. the char after the
     611     * slash.  The array has cComponents + 1 entries, where the final one is
     612     * cch + 1 so that one can always terminate the current component by
     613     * szPath[aoffComponent[i] - 1] = '\0'. */
     614    uint16_t        aoffComponents[RTPATH_MAX / 2 + 1];
     615    /** A normalized copy of the path.
     616     * Reserve some extra space so we can be more relaxed about overflow
     617     * checks and terminator paddings, especially when recursing. */
     618    char            szPath[RTPATH_MAX];
     619} RTVFSPARSEDPATH;
     620/** Pointer to a parsed path. */
     621typedef RTVFSPARSEDPATH *PRTVFSPARSEDPATH;
     622
     623/** The max accepted path length.
     624 * This must be a few chars shorter than RTVFSPARSEDPATH::szPath because we
     625 * use two terminators and wish be a little bit lazy with checking. */
     626#define RTVFSPARSEDPATH_MAX     (RTPATH_MAX - 4U)
     627
     628/**
     629 * Appends @a pszPath (relative) to the already parsed path @a pPath.
     630 *
     631 * @retval  VINF_SUCCESS
     632 * @retval  VERR_FILENAME_TOO_LONG
     633 * @retval  VERR_INTERNAL_ERROR_4
     634 * @param   pPath               The parsed path to append @a pszPath onto.
     635 *                              This is both input and output.
     636 * @param   pszPath             The path to append.  This must be relative.
     637 * @param   piRestartComp       The component to restart parsing at.  This is
     638 *                              input/output.  The input does not have to be
     639 *                              within the valid range.  Optional.
     640 */
     641RTDECL(int) RTVfsParsePathAppend(PRTVFSPARSEDPATH pPath, const char *pszPath, uint16_t *piRestartComp);
     642
     643/**
     644 * Parses a path.
     645 *
     646 * @retval  VINF_SUCCESS
     647 * @retval  VERR_FILENAME_TOO_LONG
     648 * @param   pPath               Where to store the parsed path.
     649 * @param   pszPath             The path to parse.  Absolute or relative to @a
     650 *                              pszCwd.
     651 * @param   pszCwd              The current working directory.  Must be
     652 *                              absolute.
     653 */
     654RTDECL(int) RTVfsParsePath(PRTVFSPARSEDPATH pPath, const char *pszPath, const char *pszCwd);
     655
     656/**
     657 * Same as RTVfsParsePath except that it allocates a temporary buffer.
     658 *
     659 * @retval  VINF_SUCCESS
     660 * @retval  VERR_NO_TMP_MEMORY
     661 * @retval  VERR_FILENAME_TOO_LONG
     662 * @param   pszPath             The path to parse.  Absolute or relative to @a
     663 *                              pszCwd.
     664 * @param   pszCwd              The current working directory.  Must be
     665 *                              absolute.
     666 * @param   ppPath              Where to store the pointer to the allocated
     667 *                              buffer containing the parsed path.  This must
     668 *                              be freed by calling RTVfsParsePathFree.  NULL
     669 *                              will be stored on failured.
     670 */
     671RTDECL(int) RTVfsParsePathA(const char *pszPath, const char *pszCwd, PRTVFSPARSEDPATH *ppPath);
     672
     673/**
     674 * Frees a buffer returned by RTVfsParsePathA.
     675 *
     676 * @param   pPath               The parsed path buffer to free.  NULL is fine.
     677 */
     678RTDECL(void) RTVfsParsePathFree(PRTVFSPARSEDPATH pPath);
     679
     680/** @}  */
     681
    511682/** @} */
    512683
  • trunk/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp

    r33832 r33859  
    917917     * Check each component.  No parent references or double slashes.
    918918     */
    919     pInfo->fDirSlash = false;
     919    pInfo->cComponents = 0;
     920    pInfo->fDirSlash   = false;
    920921    while (pszSrc[0])
    921922    {
  • 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.

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