VirtualBox

Changeset 34029 in vbox


Ignore:
Timestamp:
Nov 12, 2010 2:21:59 PM (14 years ago)
Author:
vboxsync
Message:

iprt/vfs/tar: more code.

Location:
trunk
Files:
5 edited

Legend:

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

    r34002 r34029  
    4040 */
    4141
     42
     43/** @name VFS Lock Abstraction
     44 * @todo This should be moved somewhere else as it is of general use.
     45 * @{ */
     46
     47/**
     48 * VFS lock types.
     49 */
     50typedef enum RTVFSLOCKTYPE
     51{
     52    /** Invalid lock type. */
     53    RTVFSLOCKTYPE_INVALID = 0,
     54    /** Read write semaphore. */
     55    RTVFSLOCKTYPE_RW,
     56    /** Fast mutex semaphore (critical section in ring-3). */
     57    RTVFSLOCKTYPE_FASTMUTEX,
     58    /** Full fledged mutex semaphore. */
     59    RTVFSLOCKTYPE_MUTEX,
     60    /** The end of valid lock types. */
     61    RTVFSLOCKTYPE_END,
     62    /** The customary 32-bit type hack. */
     63    RTVFSLOCKTYPE_32BIT_HACK = 0x7fffffff
     64} RTVFSLOCKTYPE;
     65
     66/** VFS lock handle. */
     67typedef struct RTVFSLOCKINTERNAL   *RTVFSLOCK;
     68/** Pointer to a VFS lock handle. */
     69typedef RTVFSLOCK                  *PRTVFSLOCK;
     70/** Nil VFS lock handle. */
     71#define NIL_RTVFSLOCK               ((RTVFSLOCK)~(uintptr_t)0)
     72
     73/** Special handle value for creating a new read/write semaphore based lock. */
     74#define RTVFSLOCK_CREATE_RW         ((RTVFSLOCK)~(uintptr_t)1)
     75/** Special handle value for creating a new fast mutex semaphore based lock. */
     76#define RTVFSLOCK_CREATE_FASTMUTEX  ((RTVFSLOCK)~(uintptr_t)2)
     77/** Special handle value for creating a new mutex semaphore based lock. */
     78#define RTVFSLOCK_CREATE_MUTEX      ((RTVFSLOCK)~(uintptr_t)3)
     79
     80/**
     81 * Retains a reference to the VFS lock handle.
     82 *
     83 * @returns New reference count on success, UINT32_MAX on failure.
     84 * @param   hLock           The VFS lock handle.
     85 */
     86RTDECL(uint32_t) RTVfsLockRetain(RTVFSLOCK hLock);
     87
     88/**
     89 * Releases a reference to the VFS lock handle.
     90 *
     91 * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
     92 * @param   hLock           The VFS lock handle.
     93 */
     94RTDECL(uint32_t) RTVfsLockRelease(RTVFSLOCK hLock);
     95
     96/**
     97 * Gets the lock type.
     98 *
     99 * @returns The lock type on success, RTVFSLOCKTYPE_INVALID if the handle is
     100 *          not valid.
     101 * @param   hLock               The lock handle.
     102 */
     103RTDECL(RTVFSLOCKTYPE) RTVfsLockGetType(RTVFSLOCK hLock);
     104
     105
     106
     107RTDECL(void) RTVfsLockAcquireReadSlow(RTVFSLOCK hLock);
     108RTDECL(void) RTVfsLockReleaseReadSlow(RTVFSLOCK hLock);
     109RTDECL(void) RTVfsLockAcquireWriteSlow(RTVFSLOCK hLock);
     110RTDECL(void) RTVfsLockReleaseWriteSlow(RTVFSLOCK hLock);
     111/** @}  */
     112
     113/**
     114 * Acquire a read lock.
     115 *
     116 * @param   hLock               The lock handle, can be NIL.
     117 */
     118DECLINLINE(void) RTVfsLockAcquireRead(RTVFSLOCK hLock)
     119{
     120    if (hLock != NIL_RTVFSLOCK)
     121        RTVfsLockAcquireReadSlow(hLock);
     122}
     123
     124
     125/**
     126 * Release a read lock.
     127 *
     128 * @param   hLock               The lock handle, can be NIL.
     129 */
     130DECLINLINE(void) RTVfsLockReleaseRead(RTVFSLOCK hLock)
     131{
     132    if (hLock != NIL_RTVFSLOCK)
     133        RTVfsLockReleaseReadSlow(hLock);
     134}
     135
     136
     137/**
     138 * Acquire a write lock.
     139 *
     140 * @param   hLock               The lock handle, can be NIL.
     141 */
     142DECLINLINE(void) RTVfsLockAcquireWrite(RTVFSLOCK hLock)
     143{
     144    if (hLock != NIL_RTVFSLOCK)
     145        RTVfsLockAcquireWriteSlow(hLock);
     146}
     147
     148
     149/**
     150 * Release a write lock.
     151 *
     152 * @param   hLock               The lock handle, can be NIL.
     153 */
     154DECLINLINE(void) RTVfsLockReleaseWrite(RTVFSLOCK hLock)
     155{
     156    if (hLock != NIL_RTVFSLOCK)
     157        RTVfsLockReleaseWriteSlow(hLock);
     158}
     159
     160/** @}  */
     161
    42162/**
    43163 * The VFS operations.
     
    141261/** The RTVFSOBJOPS structure version. */
    142262#define RTVFSOBJOPS_VERSION         RT_MAKE_U32_FROM_U8(0xff,0x1f,1,0)
     263
     264
     265/**
     266 * Creates a new VFS base object handle.
     267 *
     268 * @returns IPRT status code
     269 * @param   pObjOps             The base object operations.
     270 * @param   cbInstance          The size of the instance data.
     271 * @param   hVfs                The VFS handle to associate this base object
     272 *                              with.  NIL_VFS is ok.
     273 * @param   hLock               Handle to a custom lock to be used with the new
     274 *                              object.  The reference is consumed.  NIL and
     275 *                              special lock handles are fine.
     276 * @param   phVfsFss            Where to return the new handle.
     277 * @param   ppvInstance         Where to return the pointer to the instance data
     278 *                              (size is @a cbInstance).
     279 */
     280RTDECL(int) RTVfsNewBaseObj(PCRTVFSOBJOPS pObjOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
     281                            PRTVFSOBJ phVfsObj, void **ppvInstance);
    143282
    144283
     
    255394 * @param   cbInstance          The size of the instance data.
    256395 * @param   hVfs                The VFS handle to associate this filesystem
    257  *                              steram with.  NIL_VFS is ok.
    258  * @param   hSemRW              The read-write semaphore to use to protect the
    259  *                              handle if this differs from the one the VFS
    260  *                              uses.  NIL_RTSEMRW is ok if no locking is
    261  *                              desired.
     396 *                              stream with.  NIL_VFS is ok.
     397 * @param   hLock               Handle to a custom lock to be used with the new
     398 *                              object.  The reference is consumed.  NIL and
     399 *                              special lock handles are fine.
    262400 * @param   phVfsFss            Where to return the new handle.
    263401 * @param   ppvInstance         Where to return the pointer to the instance data
    264402 *                              (size is @a cbInstance).
    265403 */
    266 RTDECL(int) RTVfsNewFsStream(PCRTVFSFSSTREAMOPS pFsStreamOps, size_t cbInstance, RTVFS hVfs, RTSEMRW hSemRW,
     404RTDECL(int) RTVfsNewFsStream(PCRTVFSFSSTREAMOPS pFsStreamOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
    267405                             PRTVFSFSSTREAM phVfsFss, void **ppvInstance);
    268406
     
    450588/** The RTVFSSYMLINKOPS structure version. */
    451589#define RTVFSSYMLINKOPS_VERSION     RT_MAKE_U32_FROM_U8(0xff,0x5f,1,0)
     590
     591
     592/**
     593 * Creates a new VFS symlink handle.
     594 *
     595 * @returns IPRT status code
     596 * @param   pSymlinkOps         The symlink operations.
     597 * @param   cbInstance          The size of the instance data.
     598 * @param   hVfs                The VFS handle to associate this symlink object
     599 *                              with.  NIL_VFS is ok.
     600 * @param   hLock               Handle to a custom lock to be used with the new
     601 *                              object.  The reference is consumed.  NIL and
     602 *                              special lock handles are fine.
     603 * @param   phVfsSym            Where to return the new handle.
     604 * @param   ppvInstance         Where to return the pointer to the instance data
     605 *                              (size is @a cbInstance).
     606 */
     607RTDECL(int) RTVfsNewSymlink(PCRTVFSSYMLINKOPS pSymlinkOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
     608                            PRTVFSSYMLINK phVfsSym, void **ppvInstance);
    452609
    453610
     
    576733 * @param   hVfs                The VFS handle to associate this I/O stream
    577734 *                              with.  NIL_VFS is ok.
    578  * @param   hSemRW              The read-write semaphore to use to protect the
    579  *                              handle if this differs from the one the VFS
    580  *                              uses.  NIL_RTSEMRW is ok if no locking is
    581  *                              desired.
     735 * @param   hLock               Handle to a custom lock to be used with the new
     736 *                              object.  The reference is consumed.  NIL and
     737 *                              special lock handles are fine.
    582738 * @param   phVfsIos            Where to return the new handle.
    583739 * @param   ppvInstance         Where to return the pointer to the instance data
    584740 *                              (size is @a cbInstance).
    585741 */
    586 RTDECL(int) RTVfsNewIoStream(PCRTVFSIOSTREAMOPS pIoStreamOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTSEMRW hSemRW,
     742RTDECL(int) RTVfsNewIoStream(PCRTVFSIOSTREAMOPS pIoStreamOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTVFSLOCK hLock,
    587743                             PRTVFSIOSTREAM phVfsIos, void **ppvInstance);
    588744
     
    647803 * @param   hVfs                The VFS handle to associate this file with.
    648804 *                              NIL_VFS is ok.
     805 * @param   hLock               Handle to a custom lock to be used with the new
     806 *                              object.  The reference is consumed.  NIL and
     807 *                              special lock handles are fine.
    649808 * @param   phVfsFile           Where to return the new handle.
    650809 * @param   ppvInstance         Where to return the pointer to the instance data
    651810 *                              (size is @a cbInstance).
    652811 */
    653 RTDECL(int) RTVfsNewFile(PCRTVFSFILEOPS pFileOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs,
     812RTDECL(int) RTVfsNewFile(PCRTVFSFILEOPS pFileOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTVFSLOCK hLock,
    654813                         PRTVFSFILE phVfsFile, void **ppvInstance);
    655814
  • trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp

    r34014 r34029  
    7171
    7272/** Asserts that the VFS base object vtable is valid. */
    73 #define RTVFSOBJ_ASSERT_OPS(pObj, enmTypeArg) \
     73#define RTVFSOBJ_ASSERT_OPS(a_pObjOps, a_enmType) \
    7474    do \
    7575    { \
    76         Assert((pObj)->uVersion == RTVFSOBJOPS_VERSION); \
    77         Assert((pObj)->enmType == (enmTypeArg) || (enmTypeArg) == RTVFSOBJTYPE_INVALID); \
    78         AssertPtr((pObj)->pszName); \
    79         Assert(*(pObj)->pszName); \
    80         AssertPtr((pObj)->pfnClose); \
    81         AssertPtr((pObj)->pfnQueryInfo); \
    82         Assert((pObj)->uEndMarker == RTVFSOBJOPS_VERSION); \
     76        Assert((a_pObjOps)->uVersion == RTVFSOBJOPS_VERSION); \
     77        Assert((a_pObjOps)->enmType == (a_enmType) || (a_enmType) == RTVFSOBJTYPE_INVALID); \
     78        AssertPtr((a_pObjOps)->pszName); \
     79        Assert(*(a_pObjOps)->pszName); \
     80        AssertPtr((a_pObjOps)->pfnClose); \
     81        AssertPtr((a_pObjOps)->pfnQueryInfo); \
     82        Assert((a_pObjOps)->uEndMarker == RTVFSOBJOPS_VERSION); \
    8383    } while (0)
    8484
     85/** Asserts that the VFS set object vtable is valid. */
     86#define RTVFSOBJSET_ASSERT_OPS(a_pSetOps, a_offObjOps) \
     87    do \
     88    { \
     89        Assert((a_pSetOps)->uVersion == RTVFSOBJSETOPS_VERSION); \
     90        Assert((a_pSetOps)->offObjOps == (a_offObjOps)); \
     91        AssertPtr((a_pSetOps)->pfnSetMode); \
     92        AssertPtr((a_pSetOps)->pfnSetTimes); \
     93        AssertPtr((a_pSetOps)->pfnSetOwner); \
     94        Assert((a_pSetOps)->uEndMarker == RTVFSOBJSETOPS_VERSION); \
     95    } while (0)
     96
    8597/** Asserts that the VFS I/O stream vtable is valid. */
    86 #define RTVFSIOSTREAM_ASSERT_OPS(pIoStreamOps, enmTypeArg) \
     98#define RTVFSIOSTREAM_ASSERT_OPS(pIoStreamOps, a_enmType) \
    8799    do { \
    88         RTVFSOBJ_ASSERT_OPS(&(pIoStreamOps)->Obj, enmTypeArg); \
     100        RTVFSOBJ_ASSERT_OPS(&(pIoStreamOps)->Obj, a_enmType); \
    89101        Assert((pIoStreamOps)->uVersion == RTVFSIOSTREAMOPS_VERSION); \
    90102        Assert(!(pIoStreamOps)->fReserved); \
     
    99111    } while (0)
    100112
     113/** Asserts that the VFS symlink vtable is valid. */
     114#define RTVFSSYMLINK_ASSERT_OPS(pSymlinkOps, a_enmType) \
     115    do { \
     116        RTVFSOBJ_ASSERT_OPS(&(pSymlinkOps)->Obj, a_enmType); \
     117        RTVFSOBJSET_ASSERT_OPS(&(pSymlinkOps)->ObjSet, \
     118            RT_OFFSETOF(RTVFSSYMLINKOPS, Obj) - RT_OFFSETOF(RTVFSSYMLINKOPS, ObjSet)); \
     119        Assert((pSymlinkOps)->uVersion == RTVFSSYMLINKOPS_VERSION); \
     120        Assert(!(pSymlinkOps)->fReserved); \
     121        AssertPtr((pSymlinkOps)->pfnRead); \
     122        Assert((pSymlinkOps)->uEndMarker == RTVFSSYMLINKOPS_VERSION); \
     123    } while (0)
     124
     125
     126/** Validates a VFS handle and returns @a rcRet if it's invalid. */
     127#define RTVFS_ASSERT_VALID_HANDLE_OR_NIL_RETURN(hVfs, rcRet) \
     128    do { \
     129        if ((hVfs) != NIL_RTVFS) \
     130        { \
     131            AssertPtrReturn((hVfs), (rcRet)); \
     132            AssertReturn((hVfs)->uMagic == RTVFS_MAGIC, (rcRet)); \
     133        } \
     134    } while (0)
    101135
    102136
     
    105139*******************************************************************************/
    106140/** @todo Move all this stuff to internal/vfs.h */
     141
     142
     143/**
     144 * The VFS internal lock data.
     145 */
     146typedef struct RTVFSLOCKINTERNAL
     147{
     148    /** The number of references to the this lock. */
     149    uint32_t volatile       cRefs;
     150    /** The lock type. */
     151    RTVFSLOCKTYPE           enmType;
     152    /** Type specific data. */
     153    union
     154    {
     155        /** Read/Write semaphore handle. */
     156        RTSEMRW             hSemRW;
     157        /** Fast mutex semaphore handle. */
     158        RTSEMFASTMUTEX      hFastMtx;
     159        /** Regular mutex semaphore handle. */
     160        RTSEMMUTEX          hMtx;
     161    } u;
     162} RTVFSLOCKINTERNAL;
     163
    107164
    108165/**
     
    122179    /** The vtable. */
    123180    PCRTVFSOBJOPS           pOps;
    124     /** Read-write semaphore protecting all access to the VFS
    125      * Only valid RTVFS_C_THREAD_SAFE is set, otherwise it is NIL_RTSEMRW. */
    126     RTSEMRW                 hSemRW;
     181    /** The lock protecting all access to the VFS.
     182     * Only valid RTVFS_C_THREAD_SAFE is set, otherwise it is NIL_RTVFSLOCK. */
     183    RTVFSLOCK               hLock;
    127184    /** Reference back to the VFS containing this object. */
    128185    RTVFS                   hVfs;
     
    279336
    280337
     338
     339/*
     340 *
     341 *  V F S   L o c k   A b s t r a c t i o n
     342 *  V F S   L o c k   A b s t r a c t i o n
     343 *  V F S   L o c k   A b s t r a c t i o n
     344 *
     345 *
     346 */
     347
     348
     349RTDECL(uint32_t) RTVfsLockRetain(RTVFSLOCK hLock)
     350{
     351    RTVFSLOCKINTERNAL *pThis = hLock;
     352    AssertPtrReturn(pThis, UINT32_MAX);
     353    AssertPtrReturn(pThis->enmType > RTVFSLOCKTYPE_INVALID && pThis->enmType < RTVFSLOCKTYPE_END, UINT32_MAX);
     354
     355    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
     356    AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p %d\n", cRefs, pThis, pThis->enmType));
     357    return cRefs;
     358}
     359
     360
     361/**
     362 * Destroys a VFS lock handle.
     363 *
     364 * @param   pThis               The lock to destroy.
     365 */
     366static void rtVfsLockDestroy(RTVFSLOCKINTERNAL *pThis)
     367{
     368    switch (pThis->enmType)
     369    {
     370        case RTVFSLOCKTYPE_RW:
     371            RTSemRWDestroy(pThis->u.hSemRW);
     372            pThis->u.hSemRW = NIL_RTSEMRW;
     373            break;
     374
     375        case RTVFSLOCKTYPE_FASTMUTEX:
     376            RTSemFastMutexDestroy(pThis->u.hFastMtx);
     377            pThis->u.hFastMtx = NIL_RTSEMFASTMUTEX;
     378            break;
     379
     380        case RTVFSLOCKTYPE_MUTEX:
     381            RTSemMutexDestroy(pThis->u.hMtx);
     382            pThis->u.hFastMtx = NIL_RTSEMMUTEX;
     383            break;
     384
     385        default:
     386            AssertMsgFailedReturnVoid(("%p %d\n", pThis, pThis->enmType));
     387    }
     388
     389    pThis->enmType = RTVFSLOCKTYPE_INVALID;
     390    RTMemFree(pThis);
     391}
     392
     393
     394RTDECL(uint32_t) RTVfsLockRelease(RTVFSLOCK hLock)
     395{
     396    RTVFSLOCKINTERNAL *pThis = hLock;
     397    AssertPtrReturn(pThis, UINT32_MAX);
     398    AssertPtrReturn(pThis->enmType > RTVFSLOCKTYPE_INVALID && pThis->enmType < RTVFSLOCKTYPE_END, UINT32_MAX);
     399
     400    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
     401    AssertMsg(cRefs < _1M, ("%#x %p %d\n", cRefs, pThis, pThis->enmType));
     402    if (cRefs == 0)
     403        rtVfsLockDestroy(pThis);
     404    return cRefs;
     405}
     406
     407
     408/**
     409 * Creates a read/write lock.
     410 *
     411 * @returns IPRT status code
     412 * @param   phLock              Where to return the lock handle.
     413 */
     414static int rtVfsLockCreateRW(PRTVFSLOCK phLock)
     415{
     416    RTVFSLOCKINTERNAL *pThis = (RTVFSLOCKINTERNAL *)RTMemAlloc(sizeof(*pThis));
     417    if (!pThis)
     418        return VERR_NO_MEMORY;
     419
     420    pThis->cRefs    = 1;
     421    pThis->enmType  = RTVFSLOCKTYPE_RW;
     422
     423    int rc = RTSemRWCreate(&pThis->u.hSemRW);
     424    if (RT_FAILURE(rc))
     425    {
     426        RTMemFree(pThis);
     427        return rc;
     428    }
     429
     430    *phLock = pThis;
     431    return VINF_SUCCESS;
     432}
     433
     434
     435/**
     436 * Creates a fast mutex lock.
     437 *
     438 * @returns IPRT status code
     439 * @param   phLock              Where to return the lock handle.
     440 */
     441static int rtVfsLockCreateFastMutex(PRTVFSLOCK phLock)
     442{
     443    RTVFSLOCKINTERNAL *pThis = (RTVFSLOCKINTERNAL *)RTMemAlloc(sizeof(*pThis));
     444    if (!pThis)
     445        return VERR_NO_MEMORY;
     446
     447    pThis->cRefs    = 1;
     448    pThis->enmType  = RTVFSLOCKTYPE_FASTMUTEX;
     449
     450    int rc = RTSemFastMutexCreate(&pThis->u.hFastMtx);
     451    if (RT_FAILURE(rc))
     452    {
     453        RTMemFree(pThis);
     454        return rc;
     455    }
     456
     457    *phLock = pThis;
     458    return VINF_SUCCESS;
     459
     460}
     461
     462
     463/**
     464 * Creates a mutex lock.
     465 *
     466 * @returns IPRT status code
     467 * @param   phLock              Where to return the lock handle.
     468 */
     469static int rtVfsLockCreateMutex(PRTVFSLOCK phLock)
     470{
     471    RTVFSLOCKINTERNAL *pThis = (RTVFSLOCKINTERNAL *)RTMemAlloc(sizeof(*pThis));
     472    if (!pThis)
     473        return VERR_NO_MEMORY;
     474
     475    pThis->cRefs    = 1;
     476    pThis->enmType  = RTVFSLOCKTYPE_MUTEX;
     477
     478    int rc = RTSemMutexCreate(&pThis->u.hMtx);
     479    if (RT_FAILURE(rc))
     480    {
     481        RTMemFree(pThis);
     482        return rc;
     483    }
     484
     485    *phLock = pThis;
     486    return VINF_SUCCESS;
     487}
     488
     489
     490/**
     491 * Acquires the lock for reading.
     492 *
     493 * @param   hLock               Non-nil lock handle.
     494 * @internal
     495 */
     496RTDECL(void) RTVfsLockAcquireReadSlow(RTVFSLOCK hLock)
     497{
     498    RTVFSLOCKINTERNAL *pThis = hLock;
     499    int                rc;
     500
     501    AssertPtr(pThis);
     502    switch (pThis->enmType)
     503    {
     504        case RTVFSLOCKTYPE_RW:
     505            rc = RTSemRWRequestRead(pThis->u.hSemRW, RT_INDEFINITE_WAIT);
     506            AssertRC(rc);
     507            break;
     508
     509        case RTVFSLOCKTYPE_FASTMUTEX:
     510            rc = RTSemFastMutexRequest(pThis->u.hFastMtx);
     511            AssertRC(rc);
     512            break;
     513
     514        case RTVFSLOCKTYPE_MUTEX:
     515            rc = RTSemMutexRequest(pThis->u.hMtx, RT_INDEFINITE_WAIT);
     516            AssertRC(rc);
     517            break;
     518        default:
     519            AssertFailed();
     520    }
     521}
     522
     523
     524/**
     525 * Release a lock held for reading.
     526 *
     527 * @param   hLock               Non-nil lock handle.
     528 * @internal
     529 */
     530RTDECL(void) RTVfsLockReleaseReadSlow(RTVFSLOCK hLock)
     531{
     532    RTVFSLOCKINTERNAL *pThis = hLock;
     533    int                rc;
     534
     535    AssertPtr(pThis);
     536    switch (pThis->enmType)
     537    {
     538        case RTVFSLOCKTYPE_RW:
     539            rc = RTSemRWReleaseRead(pThis->u.hSemRW);
     540            AssertRC(rc);
     541            break;
     542
     543        case RTVFSLOCKTYPE_FASTMUTEX:
     544            rc = RTSemFastMutexRelease(pThis->u.hFastMtx);
     545            AssertRC(rc);
     546            break;
     547
     548        case RTVFSLOCKTYPE_MUTEX:
     549            rc = RTSemMutexRelease(pThis->u.hMtx);
     550            AssertRC(rc);
     551            break;
     552        default:
     553            AssertFailed();
     554    }
     555}
     556
     557
     558/**
     559 * Acquires the lock for writing.
     560 *
     561 * @param   hLock               Non-nil lock handle.
     562 * @internal
     563 */
     564RTDECL(void) RTVfsLockAcquireWriteSlow(RTVFSLOCK hLock)
     565{
     566    RTVFSLOCKINTERNAL *pThis = hLock;
     567    int                rc;
     568
     569    AssertPtr(pThis);
     570    switch (pThis->enmType)
     571    {
     572        case RTVFSLOCKTYPE_RW:
     573            rc = RTSemRWRequestWrite(pThis->u.hSemRW, RT_INDEFINITE_WAIT);
     574            AssertRC(rc);
     575            break;
     576
     577        case RTVFSLOCKTYPE_FASTMUTEX:
     578            rc = RTSemFastMutexRequest(pThis->u.hFastMtx);
     579            AssertRC(rc);
     580            break;
     581
     582        case RTVFSLOCKTYPE_MUTEX:
     583            rc = RTSemMutexRequest(pThis->u.hMtx, RT_INDEFINITE_WAIT);
     584            AssertRC(rc);
     585            break;
     586        default:
     587            AssertFailed();
     588    }
     589}
     590
     591
     592/**
     593 * Release a lock held for writing.
     594 *
     595 * @param   hLock               Non-nil lock handle.
     596 * @internal
     597 */
     598RTDECL(void) RTVfsLockReleaseWriteSlow(RTVFSLOCK hLock)
     599{
     600    RTVFSLOCKINTERNAL *pThis = hLock;
     601    int                rc;
     602
     603    AssertPtr(pThis);
     604    switch (pThis->enmType)
     605    {
     606        case RTVFSLOCKTYPE_RW:
     607            rc = RTSemRWReleaseWrite(pThis->u.hSemRW);
     608            AssertRC(rc);
     609            break;
     610
     611        case RTVFSLOCKTYPE_FASTMUTEX:
     612            rc = RTSemFastMutexRelease(pThis->u.hFastMtx);
     613            AssertRC(rc);
     614            break;
     615
     616        case RTVFSLOCKTYPE_MUTEX:
     617            rc = RTSemMutexRelease(pThis->u.hMtx);
     618            AssertRC(rc);
     619            break;
     620        default:
     621            AssertFailed();
     622    }
     623}
     624
     625
     626
    281627/*
    282628 *
     
    288634
    289635/**
     636 * Internal object retainer that asserts sanity in strict builds.
     637 *
     638 * @param   pThis               The base object handle data.
     639 */
     640DECLINLINE(void) rtVfsObjRetainVoid(RTVFSOBJINTERNAL *pThis)
     641{
     642    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
     643    AssertMsg(cRefs > 1 && cRefs < _1M,
     644              ("%#x %p ops=%p %s (%d)\n", cRefs, pThis, pThis->pOps, pThis->pOps->pszName, pThis->pOps->enmType));
     645    NOREF(cRefs);
     646}
     647
     648
     649/**
     650 * Initializes the base object part of a new object.
     651 *
     652 * @returns IPRT status code.
     653 * @param   pThis               Pointer to the base object part.
     654 * @param   pObjOps             The base object vtable.
     655 * @param   hVfs                The VFS handle to associate with.
     656 * @param   hLock               The lock handle, pseudo handle or nil.
     657 * @param   pvThis              Pointer to the private data.
     658 */
     659static int rtVfsObjInitNewObject(RTVFSOBJINTERNAL *pThis, PCRTVFSOBJOPS pObjOps, RTVFS hVfs, RTVFSLOCK hLock, void *pvThis)
     660{
     661    /*
     662     * Deal with the lock first as that's the most complicated matter.
     663     */
     664    if (hLock != NIL_RTVFSLOCK)
     665    {
     666        int rc;
     667        if (hLock == RTVFSLOCK_CREATE_RW)
     668        {
     669            rc = rtVfsLockCreateRW(&hLock);
     670            AssertRCReturn(rc, rc);
     671        }
     672        else if (hLock == RTVFSLOCK_CREATE_FASTMUTEX)
     673        {
     674            rc = rtVfsLockCreateFastMutex(&hLock);
     675            AssertRCReturn(rc, rc);
     676        }
     677        else if (hLock == RTVFSLOCK_CREATE_MUTEX)
     678        {
     679            rc = rtVfsLockCreateMutex(&hLock);
     680            AssertRCReturn(rc, rc);
     681        }
     682        else
     683        {
     684            /*
     685             * The caller specified a lock, we consume the this reference.
     686             */
     687            AssertPtrReturn(hLock, VERR_INVALID_HANDLE);
     688            AssertPtrReturn(hLock->enmType > RTVFSLOCKTYPE_INVALID && hLock->enmType < RTVFSLOCKTYPE_END, VERR_INVALID_HANDLE);
     689            AssertPtrReturn(hLock->cRefs > 0, VERR_INVALID_HANDLE);
     690        }
     691    }
     692    else if (hVfs != NIL_RTVFS)
     693    {
     694        /*
     695         * Retain a reference to the VFS lock, if there is one.
     696         */
     697        hLock = hVfs->Base.hLock;
     698        if (hLock != NIL_RTVFSLOCK)
     699        {
     700            uint32_t cRefs = RTVfsLockRetain(hLock);
     701            if (RT_UNLIKELY(cRefs == UINT32_MAX))
     702                return VERR_INVALID_HANDLE;
     703        }
     704    }
     705
     706
     707    /*
     708     * Do the actual initializing.
     709     */
     710    pThis->uMagic  = RTVFSOBJ_MAGIC;
     711    pThis->pvThis  = pvThis;
     712    pThis->pOps    = pObjOps;
     713    pThis->cRefs   = 1;
     714    pThis->hVfs    = hVfs;
     715    pThis->hLock   = hLock;
     716    if (hVfs != NIL_RTVFS)
     717        rtVfsObjRetainVoid(&hVfs->Base);
     718
     719    return VINF_SUCCESS;
     720}
     721
     722
     723RTDECL(int) RTVfsNewBaseObj(PCRTVFSOBJOPS pObjOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
     724                            PRTVFSOBJ phVfsObj, void **ppvInstance)
     725{
     726    /*
     727     * Validate the input, be extra strict in strict builds.
     728     */
     729    AssertPtr(pObjOps);
     730    AssertReturn(pObjOps->uVersion   == RTVFSOBJOPS_VERSION, VERR_VERSION_MISMATCH);
     731    AssertReturn(pObjOps->uEndMarker == RTVFSOBJOPS_VERSION, VERR_VERSION_MISMATCH);
     732    RTVFSOBJ_ASSERT_OPS(pObjOps, RTVFSOBJTYPE_BASE);
     733    Assert(cbInstance > 0);
     734    AssertPtr(ppvInstance);
     735    AssertPtr(phVfsObj);
     736    RTVFS_ASSERT_VALID_HANDLE_OR_NIL_RETURN(hVfs, VERR_INVALID_HANDLE);
     737
     738    /*
     739     * Allocate the handle + instance data.
     740     */
     741    size_t const cbThis = RT_ALIGN_Z(sizeof(RTVFSOBJINTERNAL), RTVFS_INST_ALIGNMENT)
     742                        + RT_ALIGN_Z(cbInstance, RTVFS_INST_ALIGNMENT);
     743    RTVFSOBJINTERNAL *pThis = (RTVFSOBJINTERNAL *)RTMemAllocZ(cbThis);
     744    if (!pThis)
     745        return VERR_NO_MEMORY;
     746
     747    int rc = rtVfsObjInitNewObject(pThis, pObjOps, hVfs, hLock,
     748                                   (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT));
     749    if (RT_FAILURE(rc))
     750    {
     751        RTMemFree(pThis);
     752        return rc;
     753    }
     754
     755    *phVfsObj    = pThis;
     756    *ppvInstance = pThis->pvThis;
     757    return VINF_SUCCESS;
     758}
     759
     760
     761/**
    290762 * Write locks the object.
    291763 *
     
    294766DECLINLINE(void) rtVfsObjWriteLock(RTVFSOBJINTERNAL *pThis)
    295767{
    296     if (pThis->hSemRW != NIL_RTSEMRW)
    297     {
    298         int rc = RTSemRWRequestWrite(pThis->hSemRW, RT_INDEFINITE_WAIT);
    299         AssertRC(rc);
    300     }
     768    RTVfsLockAcquireWrite(pThis->hLock);
    301769}
    302770
     
    309777DECLINLINE(void) rtVfsObjWriteUnlock(RTVFSOBJINTERNAL *pThis)
    310778{
    311     if (pThis->hSemRW != NIL_RTSEMRW)
    312     {
    313         int rc = RTSemRWReleaseWrite(pThis->hSemRW);
    314         AssertRC(rc);
    315     }
     779    RTVfsLockReleaseWrite(pThis->hLock);
    316780}
    317781
     
    323787DECLINLINE(void) rtVfsObjReadLock(RTVFSOBJINTERNAL *pThis)
    324788{
    325     if (pThis->hSemRW != NIL_RTSEMRW)
    326     {
    327         int rc = RTSemRWRequestRead(pThis->hSemRW, RT_INDEFINITE_WAIT);
    328         AssertRC(rc);
    329     }
     789    RTVfsLockAcquireRead(pThis->hLock);
    330790}
    331791
     
    338798DECLINLINE(void) rtVfsObjReadUnlock(RTVFSOBJINTERNAL *pThis)
    339799{
    340     if (pThis->hSemRW != NIL_RTSEMRW)
    341     {
    342         int rc = RTSemRWReleaseRead(pThis->hSemRW);
    343         AssertRC(rc);
    344     }
     800    RTVfsLockReleaseRead(pThis->hLock);
    345801}
    346802
     
    359815              ("%#x %p ops=%p %s (%d)\n", cRefs, pThis, pThis->pOps, pThis->pOps->pszName, pThis->pOps->enmType));
    360816    return cRefs;
    361 }
    362 
    363 
    364 /**
    365  * Internal object retainer that asserts sanity in strict builds.
    366  *
    367  * @param   pThis               The base object handle data.
    368  */
    369 DECLINLINE(void) rtVfsObjRetainVoid(RTVFSOBJINTERNAL *pThis)
    370 {
    371     uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
    372     AssertMsg(cRefs > 1 && cRefs < _1M,
    373               ("%#x %p ops=%p %s (%d)\n", cRefs, pThis, pThis->pOps, pThis->pOps->pszName, pThis->pOps->enmType));
    374     NOREF(cRefs);
    375817}
    376818
     
    11221564
    11231565
    1124 RTDECL(int) RTVfsNewFsStream(PCRTVFSFSSTREAMOPS pFsStreamOps, size_t cbInstance, RTVFS hVfs, RTSEMRW hSemRW,
     1566RTDECL(int) RTVfsNewFsStream(PCRTVFSFSSTREAMOPS pFsStreamOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
    11251567                             PRTVFSFSSTREAM phVfsFss, void **ppvInstance)
    11261568{
     
    11371579    AssertPtr(ppvInstance);
    11381580    AssertPtr(phVfsFss);
    1139 
    1140     RTVFSINTERNAL *pVfs = NULL;
    1141     if (hVfs != NIL_RTVFS)
    1142     {
    1143         pVfs = hVfs;
    1144         AssertPtrReturn(pVfs, VERR_INVALID_HANDLE);
    1145         AssertReturn(pVfs->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE);
    1146     }
     1581    RTVFS_ASSERT_VALID_HANDLE_OR_NIL_RETURN(hVfs, VERR_INVALID_HANDLE);
    11471582
    11481583    /*
     
    11551590        return VERR_NO_MEMORY;
    11561591
    1157     pThis->uMagic       = RTVFSFSSTREAM_MAGIC;
    1158     pThis->fFlags       = RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE;
    1159     pThis->pOps         = pFsStreamOps;
    1160     pThis->Base.uMagic  = RTVFSOBJ_MAGIC;
    1161     pThis->Base.pvThis  = (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT);
    1162     pThis->Base.pOps    = &pFsStreamOps->Obj;
    1163     pThis->Base.hSemRW  = hSemRW != NIL_RTSEMRW ? hSemRW : pVfs ? pVfs->Base.hSemRW : NIL_RTSEMRW;
    1164     pThis->Base.hVfs    = hVfs;
    1165     pThis->Base.cRefs   = 1;
    1166     if (hVfs != NIL_RTVFS)
    1167         rtVfsObjRetainVoid(&pVfs->Base);
    1168 
    1169     *phVfsFss    = pThis;
    1170     *ppvInstance = pThis->Base.pvThis;
     1592    int rc = rtVfsObjInitNewObject(&pThis->Base, &pFsStreamOps->Obj, hVfs, hLock,
     1593                                   (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT));
     1594
     1595    if (RT_FAILURE(rc))
     1596    {
     1597        RTMemFree(pThis);
     1598        return rc;
     1599    }
     1600
     1601    pThis->uMagic = RTVFSFSSTREAM_MAGIC;
     1602    pThis->fFlags = RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE;
     1603    pThis->pOps   = pFsStreamOps;
     1604
     1605    *phVfsFss     = pThis;
     1606    *ppvInstance  = pThis->Base.pvThis;
    11711607    return VINF_SUCCESS;
    11721608}
     
    12561692 */
    12571693
     1694RTDECL(int) RTVfsNewSymlink(PCRTVFSSYMLINKOPS pSymlinkOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
     1695                            PRTVFSSYMLINK phVfsSym, void **ppvInstance)
     1696{
     1697    /*
     1698     * Validate the input, be extra strict in strict builds.
     1699     */
     1700    AssertPtr(pSymlinkOps);
     1701    AssertReturn(pSymlinkOps->uVersion   == RTVFSSYMLINKOPS_VERSION, VERR_VERSION_MISMATCH);
     1702    AssertReturn(pSymlinkOps->uEndMarker == RTVFSSYMLINKOPS_VERSION, VERR_VERSION_MISMATCH);
     1703    Assert(!pSymlinkOps->fReserved);
     1704    RTVFSSYMLINK_ASSERT_OPS(pSymlinkOps, RTVFSOBJTYPE_SYMLINK);
     1705    Assert(cbInstance > 0);
     1706    AssertPtr(ppvInstance);
     1707    AssertPtr(phVfsSym);
     1708    RTVFS_ASSERT_VALID_HANDLE_OR_NIL_RETURN(hVfs, VERR_INVALID_HANDLE);
     1709
     1710    /*
     1711     * Allocate the handle + instance data.
     1712     */
     1713    size_t const cbThis = RT_ALIGN_Z(sizeof(RTVFSSYMLINKINTERNAL), RTVFS_INST_ALIGNMENT)
     1714                        + RT_ALIGN_Z(cbInstance, RTVFS_INST_ALIGNMENT);
     1715    RTVFSSYMLINKINTERNAL *pThis = (RTVFSSYMLINKINTERNAL *)RTMemAllocZ(cbThis);
     1716    if (!pThis)
     1717        return VERR_NO_MEMORY;
     1718
     1719    int rc = rtVfsObjInitNewObject(&pThis->Base, &pSymlinkOps->Obj, hVfs, hLock,
     1720                                   (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT));
     1721    if (RT_FAILURE(rc))
     1722    {
     1723        RTMemFree(pThis);
     1724        return rc;
     1725    }
     1726
     1727    pThis->uMagic = RTVFSSYMLINK_MAGIC;
     1728    pThis->pOps   = pSymlinkOps;
     1729
     1730    *phVfsSym     = pThis;
     1731    *ppvInstance  = pThis->Base.pvThis;
     1732    return VINF_SUCCESS;
     1733}
     1734
     1735
    12581736RTDECL(uint32_t)    RTVfsSymlinkRetain(RTVFSSYMLINK hVfsSym)
    12591737{
     
    12971775 */
    12981776
    1299 RTDECL(int) RTVfsNewIoStream(PCRTVFSIOSTREAMOPS pIoStreamOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTSEMRW hSemRW,
     1777RTDECL(int) RTVfsNewIoStream(PCRTVFSIOSTREAMOPS pIoStreamOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTVFSLOCK hLock,
    13001778                             PRTVFSIOSTREAM phVfsIos, void **ppvInstance)
    13011779{
     
    13121790    AssertPtr(ppvInstance);
    13131791    AssertPtr(phVfsIos);
    1314 
    1315     RTVFSINTERNAL *pVfs = NULL;
    1316     if (hVfs != NIL_RTVFS)
    1317     {
    1318         pVfs = hVfs;
    1319         AssertPtrReturn(pVfs, VERR_INVALID_HANDLE);
    1320         AssertReturn(pVfs->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE);
    1321     }
     1792    RTVFS_ASSERT_VALID_HANDLE_OR_NIL_RETURN(hVfs, VERR_INVALID_HANDLE);
    13221793
    13231794    /*
     
    13301801        return VERR_NO_MEMORY;
    13311802
    1332     pThis->uMagic       = RTVFSIOSTREAM_MAGIC;
    1333     pThis->fFlags       = fOpen;
    1334     pThis->pOps         = pIoStreamOps;
    1335     pThis->Base.uMagic  = RTVFSOBJ_MAGIC;
    1336     pThis->Base.pvThis  = (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT);
    1337     pThis->Base.pOps    = &pIoStreamOps->Obj;
    1338     pThis->Base.hSemRW  = hSemRW != NIL_RTSEMRW ? hSemRW : pVfs ? pVfs->Base.hSemRW : NIL_RTSEMRW;
    1339     pThis->Base.hVfs    = hVfs;
    1340     pThis->Base.cRefs   = 1;
    1341     if (hVfs != NIL_RTVFS)
    1342         rtVfsObjRetainVoid(&pVfs->Base);
    1343 
    1344     *phVfsIos    = pThis;
    1345     *ppvInstance = pThis->Base.pvThis;
     1803    int rc = rtVfsObjInitNewObject(&pThis->Base, &pIoStreamOps->Obj, hVfs, hLock,
     1804                                   (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT));
     1805    if (RT_FAILURE(rc))
     1806    {
     1807        RTMemFree(pThis);
     1808        return rc;
     1809    }
     1810
     1811    pThis->uMagic = RTVFSIOSTREAM_MAGIC;
     1812    pThis->fFlags = fOpen;
     1813    pThis->pOps   = pIoStreamOps;
     1814
     1815    *phVfsIos     = pThis;
     1816    *ppvInstance  = pThis->Base.pvThis;
    13461817    return VINF_SUCCESS;
    13471818}
     
    16042075 */
    16052076
    1606 RTDECL(int) RTVfsNewFile(PCRTVFSFILEOPS pFileOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs,
     2077RTDECL(int) RTVfsNewFile(PCRTVFSFILEOPS pFileOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTVFSLOCK hLock,
    16072078                         PRTVFSFILE phVfsFile, void **ppvInstance)
    16082079{
     
    16192090    AssertPtr(ppvInstance);
    16202091    AssertPtr(phVfsFile);
    1621 
    1622     RTVFSINTERNAL *pVfs = NULL;
    1623     if (hVfs != NIL_RTVFS)
    1624     {
    1625         pVfs = hVfs;
    1626         AssertPtrReturn(pVfs, VERR_INVALID_HANDLE);
    1627         AssertReturn(pVfs->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE);
    1628     }
     2092    RTVFS_ASSERT_VALID_HANDLE_OR_NIL_RETURN(hVfs, VERR_INVALID_HANDLE);
    16292093
    16302094    /*
     
    16372101        return VERR_NO_MEMORY;
    16382102
    1639     pThis->uMagic               = RTVFSFILE_MAGIC;
    1640     pThis->fReserved            = 0;
    1641     pThis->pOps                 = pFileOps;
    1642     pThis->Stream.uMagic        = RTVFSIOSTREAM_MAGIC;
    1643     pThis->Stream.fFlags        = fOpen;
    1644     pThis->Stream.pOps          = &pFileOps->Stream;
    1645     pThis->Stream.Base.pvThis   = (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT);
    1646     pThis->Stream.Base.pOps     = &pFileOps->Stream.Obj;
    1647     pThis->Stream.Base.hSemRW   = pVfs ? pVfs->Base.hSemRW : NIL_RTSEMRW;
    1648     pThis->Stream.Base.hVfs     = hVfs;
    1649     pThis->Stream.Base.cRefs    = 1;
    1650     if (hVfs != NIL_RTVFS)
    1651         rtVfsObjRetainVoid(&pVfs->Base);
     2103    int rc = rtVfsObjInitNewObject(&pThis->Stream.Base, &pFileOps->Stream.Obj, hVfs, hLock,
     2104                                   (char *)pThis + RT_ALIGN_Z(sizeof(*pThis), RTVFS_INST_ALIGNMENT));
     2105    if (RT_FAILURE(rc))
     2106    {
     2107        RTMemFree(pThis);
     2108        return rc;
     2109    }
     2110
     2111    pThis->uMagic        = RTVFSFILE_MAGIC;
     2112    pThis->fReserved     = 0;
     2113    pThis->pOps          = pFileOps;
     2114    pThis->Stream.uMagic = RTVFSIOSTREAM_MAGIC;
     2115    pThis->Stream.fFlags = fOpen;
     2116    pThis->Stream.pOps   = &pFileOps->Stream;
    16522117
    16532118    *phVfsFile   = pThis;
  • trunk/src/VBox/Runtime/common/vfs/vfsstdfile.cpp

    r34014 r34029  
    436436    PRTVFSSTDFILE   pThis;
    437437    RTVFSFILE       hVfsFile;
    438     rc = RTVfsNewFile(&g_rtVfsStdFileOps, sizeof(RTVFSSTDFILE), fOpen, NIL_RTVFS, &hVfsFile, (void **)&pThis);
     438    rc = RTVfsNewFile(&g_rtVfsStdFileOps, sizeof(RTVFSSTDFILE), fOpen, NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pThis);
    439439    if (RT_FAILURE(rc))
    440440        return rc;
  • trunk/src/VBox/Runtime/common/zip/tar.h

    r34002 r34029  
    9393    char            ab[512];
    9494    /** The standard header. */
    95     RTZIPTARHDRPOSIX   Hdr;
     95    RTZIPTARHDRPOSIX Posix;
    9696} RTZIPTARHDR;
    9797AssertCompileSize(RTZIPTARHDR, 512);
  • trunk/src/VBox/Runtime/common/zip/tarvfs.cpp

    r34002 r34029  
    3535#include <iprt/err.h>
    3636#include <iprt/poll.h>
     37#include <iprt/file.h>
    3738#include <iprt/string.h>
    3839#include <iprt/vfs.h>
     
    111112
    112113
     114/**
     115 * Checks if the TAR header includes a posix user name field.
     116 *
     117 * @returns true / false.
     118 * @param   pTar                The TAR header.
     119 */
    113120DECLINLINE(bool) rtZipTarHdrHasPosixUserName(PCRTZIPTARHDR pTar)
    114121{
     
    117124
    118125
     126/**
     127 * Checks if the TAR header includes a posix group name field.
     128 *
     129 * @returns true / false.
     130 * @param   pTar                The TAR header.
     131 */
    119132DECLINLINE(bool) rtZipTarHdrHasPosixGroupName(PCRTZIPTARHDR pTar)
    120133{
    121134    return true;
     135}
     136
     137
     138/**
     139 * Checks if the TAR header includes a posix compatible path prefix field.
     140 *
     141 * @returns true / false.
     142 * @param   pTar                The TAR header.
     143 */
     144DECLINLINE(bool) rtZipTarHdrHasPrefix(PCRTZIPTARHDR pTar)
     145{
     146    return true;
     147}
     148
     149
     150/**
     151 * Validates the TAR header.
     152 *
     153 * @returns VINF_SUCCESS if valid, appropriate VERR_TAR_XXX if not.
     154 * @param   pTar                The TAR header.
     155 */
     156static int rtZipTarHdrValidate(PCRTZIPTARHDR pTar)
     157{
     158    return VINF_SUCCESS;
     159}
     160
     161
     162/**
     163 * Translate a TAR header to an IPRT object info structure with additional UNIX
     164 * attributes.
     165 *
     166 * @returns VINF_SUCCESS if valid, appropriate VERR_TAR_XXX if not.
     167 * @param   pTar                The TAR header (input).
     168 * @param   pObjInfo            The object info structure (output).
     169 */
     170static int rtZipTarHdrToFsObjInfo(PCRTZIPTARHDR pTar, PRTFSOBJINFO pObjInfo)
     171{
     172    RT_ZERO(*pObjInfo);
     173
     174    return VINF_SUCCESS;
    122175}
    123176
     
    168221            pObjInfo->Attr.u.UnixOwner.szName[0] = '\0';
    169222            if (rtZipTarHdrHasPosixUserName(&pThis->Hdr))
    170                 RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName), pThis->Hdr.Hdr.uname);
     223                RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName), pThis->Hdr.Posix.uname);
    171224            break;
    172225
     
    177230            pObjInfo->Attr.u.UnixGroup.szName[0] = '\0';
    178231            if (rtZipTarHdrHasPosixGroupName(&pThis->Hdr))
    179                 RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName), pThis->Hdr.Hdr.gname);
     232                RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName), pThis->Hdr.Posix.gname);
    180233            break;
    181234
     
    194247
    195248
    196 
    197 /**
    198  * Tar filesystem stream operations.
    199  */
    200 static const RTVFSOBJOPS g_rtZipTarFsStrmOps =
     249/**
     250 * Tar filesystem base object operations.
     251 */
     252static const RTVFSOBJOPS g_rtZipTarFssBaseObjOps =
    201253{
    202254    RTVFSOBJOPS_VERSION,
     
    369421
    370422/**
    371  * Standard file operations.
     423 * Tar I/O stream operations.
    372424 */
    373425static const RTVFSIOSTREAMOPS g_rtZipTarFssIosOps =
     
    397449 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
    398450 */
     451static DECLCALLBACK(int) rtZipTarFssSym_Close(void *pvThis)
     452{
     453    PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;
     454    return rtZipTarFssBaseObj_Close(pThis);
     455}
     456
     457
     458/**
     459 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     460 */
     461static DECLCALLBACK(int) rtZipTarFssSym_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     462{
     463    PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;
     464    return rtZipTarFssBaseObj_QueryInfo(pThis, pObjInfo, enmAddAttr);
     465}
     466
     467/**
     468 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
     469 */
     470static DECLCALLBACK(int) rtZipTarFssSym_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
     471{
     472    NOREF(pvThis); NOREF(fMode); NOREF(fMask);
     473    return VERR_ACCESS_DENIED;
     474}
     475
     476
     477/**
     478 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
     479 */
     480static DECLCALLBACK(int) rtZipTarFssSym_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     481                                                 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
     482{
     483    NOREF(pvThis); NOREF(pAccessTime); NOREF(pModificationTime); NOREF(pChangeTime); NOREF(pBirthTime);
     484    return VERR_ACCESS_DENIED;
     485}
     486
     487
     488/**
     489 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
     490 */
     491static DECLCALLBACK(int) rtZipTarFssSym_SetOwner(void *pvThis, RTUID uid, RTGID gid)
     492{
     493    NOREF(pvThis); NOREF(uid); NOREF(gid);
     494    return VERR_ACCESS_DENIED;
     495}
     496
     497
     498/**
     499 * @interface_method_impl{RTVFSSYMLINKOPS,pfnRead}
     500 */
     501static DECLCALLBACK(int) rtZipTarFssSym_Read(void *pvThis, char *pszTarget, size_t cbTarget)
     502{
     503    PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis;
     504    return RTStrCopy(pszTarget, cbTarget, pThis->Hdr.Posix.linkname);
     505}
     506
     507
     508/**
     509 * Tar symbolic (and hardlink) operations.
     510 */
     511static const RTVFSSYMLINKOPS g_rtZipTarFssSymOps =
     512{
     513    { /* Obj */
     514        RTVFSOBJOPS_VERSION,
     515        RTVFSOBJTYPE_IO_STREAM,
     516        "TarFsStream::Symlink",
     517        rtZipTarFssIos_Close,
     518        rtZipTarFssIos_QueryInfo,
     519        RTVFSOBJOPS_VERSION
     520    },
     521    RTVFSSYMLINKOPS_VERSION,
     522    0,
     523    { /* ObjSet */
     524        RTVFSOBJSETOPS_VERSION,
     525        RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
     526        rtZipTarFssSym_SetMode,
     527        rtZipTarFssSym_SetTimes,
     528        rtZipTarFssSym_SetOwner,
     529        RTVFSOBJSETOPS_VERSION
     530    },
     531    rtZipTarFssSym_Read,
     532    RTVFSSYMLINKOPS_VERSION
     533};
     534
     535
     536/**
     537 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
     538 */
    399539static DECLCALLBACK(int) rtZipTarFss_Close(void *pvThis)
    400540{
     
    493633        return pThis->rcFatal = VERR_TAR_UNEXPECTED_EOS;
    494634
    495     /*
    496      * Validate the header.
    497      */
    498     /** @todo continue here... */
     635    pThis->offNextHdr = off + sizeof(Hdr);
     636
     637    /*
     638     * Validate the header and convert to binary object info.
     639     */
     640/** @todo look for the two all zero headers terminating the stream... */
     641    rc = rtZipTarHdrValidate(&Hdr);
     642    if (RT_FAILURE(rc))
     643        return pThis->rcFatal = rc;
     644
     645    RTFSOBJINFO Info;
     646    rc = rtZipTarHdrToFsObjInfo(&Hdr, &Info);
     647    if (RT_FAILURE(rc))
     648        return pThis->rcFatal = rc;
    499649
    500650    /*
    501651     * Create an object of the appropriate type.
    502652     */
    503 
    504 
    505     return VERR_NOT_IMPLEMENTED;
     653    RTVFSOBJTYPE    enmType;
     654    RTVFSOBJ        hVfsObj;
     655    switch (Hdr.Posix.typeflag)
     656    {
     657        /*
     658         * Files are represented by a VFS I/O stream.
     659         */
     660        case RTZIPTAR_TF_NORMAL:
     661        case RTZIPTAR_TF_OLDNORMAL:
     662        case RTZIPTAR_TF_CONTIG:
     663        {
     664            RTVFSIOSTREAM       hVfsIos;
     665            PRTZIPTARIOSTREAM   pIosData;
     666            rc = RTVfsNewIoStream(&g_rtZipTarFssIosOps,
     667                                  sizeof(*pIosData),
     668                                  RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
     669                                  NIL_RTVFS,
     670                                  NIL_RTVFSLOCK,
     671                                  &hVfsIos,
     672                                  (void **)&pIosData);
     673            if (RT_FAILURE(rc))
     674                return pThis->rcFatal = rc;
     675
     676            pIosData->BaseObj.offHdr  = off;
     677            pIosData->BaseObj.Hdr     = Hdr;
     678            pIosData->BaseObj.ObjInfo = Info;
     679            pIosData->cbFile          = Info.cbObject;
     680            pIosData->offFile         = 0;
     681            pIosData->cbPadding       = 512 - (uint32_t)(Info.cbObject % 512);
     682            pIosData->fEndOfStream    = false;
     683            pIosData->hVfsIos         = pThis->hVfsIos;
     684            RTVfsIoStrmRetain(pThis->hVfsIos);
     685
     686            pThis->pCurIosData = pIosData;
     687            pThis->offNextHdr += pIosData->cbFile + pIosData->cbPadding;
     688
     689            enmType = RTVFSOBJTYPE_IO_STREAM;
     690            hVfsObj = RTVfsObjFromIoStream(hVfsIos);
     691            RTVfsIoStrmRelease(hVfsIos);
     692            break;
     693        }
     694
     695        /*
     696         * We represent hard links using a symbolic link object.  This fits
     697         * best with the way TAR stores it and there is currently no better
     698         * fitting VFS type alternative.
     699         */
     700        case RTZIPTAR_TF_LINK:
     701        case RTZIPTAR_TF_SYMLINK:
     702        {
     703            RTVFSSYMLINK        hVfsSym;
     704            PRTZIPTARBASEOBJ    pBaseObjData;
     705            rc = RTVfsNewSymlink(&g_rtZipTarFssSymOps,
     706                                 sizeof(*pBaseObjData),
     707                                 NIL_RTVFS,
     708                                 NIL_RTVFSLOCK,
     709                                 &hVfsSym,
     710                                 (void **)&pBaseObjData);
     711            if (RT_FAILURE(rc))
     712                return pThis->rcFatal = rc;
     713
     714            pBaseObjData->offHdr  = off;
     715            pBaseObjData->Hdr     = Hdr;
     716            pBaseObjData->ObjInfo = Info;
     717
     718            enmType = RTVFSOBJTYPE_SYMLINK;
     719            hVfsObj = RTVfsObjFromSymlink(hVfsSym);
     720            RTVfsSymlinkRelease(hVfsSym);
     721            break;
     722        }
     723
     724        /*
     725         * All other objects are repesented using a VFS base object since they
     726         * carry no data streams (unless some tar extension implements extended
     727         * attributes / alternative streams).
     728         */
     729        case RTZIPTAR_TF_CHR:
     730        case RTZIPTAR_TF_BLK:
     731        case RTZIPTAR_TF_DIR:
     732        case RTZIPTAR_TF_FIFO:
     733        {
     734            PRTZIPTARBASEOBJ pBaseObjData;
     735            rc = RTVfsNewBaseObj(&g_rtZipTarFssBaseObjOps,
     736                                 sizeof(*pBaseObjData),
     737                                 NIL_RTVFS,
     738                                 NIL_RTVFSLOCK,
     739                                 &hVfsObj,
     740                                 (void **)&pBaseObjData);
     741            if (RT_FAILURE(rc))
     742                return pThis->rcFatal = rc;
     743
     744            pBaseObjData->offHdr  = off;
     745            pBaseObjData->Hdr     = Hdr;
     746            pBaseObjData->ObjInfo = Info;
     747
     748            enmType = RTVFSOBJTYPE_BASE;
     749            break;
     750        }
     751
     752        default:
     753            AssertFailed();
     754            return pThis->rcFatal = VERR_INTERNAL_ERROR_5;
     755    }
     756    pThis->hVfsCurObj = hVfsObj;
     757
     758    /*
     759     * Set the return data and we're done.
     760     */
     761    if (ppszName)
     762    {
     763        if (rtZipTarHdrHasPrefix(&Hdr))
     764        {
     765            *ppszName = NULL;
     766            rc = RTStrAAppendExN(ppszName, 2, Hdr.Posix.prefix, Hdr.Posix.name);
     767        }
     768        else
     769            rc = RTStrDupEx(ppszName, Hdr.Posix.name);
     770        if (RT_FAILURE(rc))
     771            return rc;
     772    }
     773
     774    if (phVfsObj)
     775    {
     776        RTVfsObjRetain(hVfsObj);
     777        *phVfsObj = hVfsObj;
     778    }
     779
     780    if (penmType)
     781        *penmType = enmType;
     782
     783    return VINF_SUCCESS;
    506784}
    507785
     
    548826    PRTZIPTARFSSTREAM pThis;
    549827    RTVFSFSSTREAM     hVfsFss;
    550     int rc = RTVfsNewFsStream(&rtZipTarFssOps, sizeof(*pThis), NIL_RTVFS, NIL_RTSEMRW, &hVfsFss, (void **)&pThis);
     828    int rc = RTVfsNewFsStream(&rtZipTarFssOps, sizeof(*pThis), NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFss, (void **)&pThis);
    551829    if (RT_SUCCESS(rc))
    552830    {
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