VirtualBox

Changeset 66601 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Apr 18, 2017 10:38:18 AM (8 years ago)
Author:
vboxsync
Message:

iprt,vfs: Added a generic 'open' provider and sketched out a few directory related APIs.

Location:
trunk/src/VBox/Runtime/common
Files:
5 edited

Legend:

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

    r66576 r66601  
    11981198
    11991199
     1200/** @todo Replace RTVfsParsePath with RTPathParse and friends?  */
    12001201RTDECL(int) RTVfsParsePath(PRTVFSPARSEDPATH pPath, const char *pszPath, const char *pszCwd)
    12011202{
     
    13411342 *                          (referenced).
    13421343 */
    1343 static int rtVfsTraverseToParent(RTVFSINTERNAL *pThis, PRTVFSPARSEDPATH pPath, bool fFollowSymlink,
    1344                                  RTVFSDIRINTERNAL **ppVfsParentDir)
     1344static int rtVfsDirTraverseToParent(RTVFSDIRINTERNAL *pThis, PRTVFSPARSEDPATH pPath, bool fFollowSymlink,
     1345                                    RTVFSDIRINTERNAL **ppVfsParentDir)
    13451346{
    13461347    /*
     
    13481349     */
    13491350    AssertPtr(pThis);
    1350     Assert(pThis->uMagic == RTVFS_MAGIC);
     1351    Assert(pThis->uMagic == RTVFSDIR_MAGIC);
    13511352    Assert(pThis->Base.cRefs > 0);
    13521353    AssertPtr(pPath);
     
    13561357
    13571358    /*
    1358      * Open the root directory.
    1359      */
    1360     /** @todo Union mounts, traversal optimization methods, races, ++ */
    1361     RTVFSDIRINTERNAL *pCurDir;
    1362     RTVfsLockAcquireRead(pThis->Base.hLock);
    1363     int rc = pThis->pOps->pfnOpenRoot(pThis->Base.pvThis, &pCurDir);
    1364     RTVfsLockReleaseRead(pThis->Base.hLock);
    1365     if (RT_FAILURE(rc))
    1366         return rc;
    1367     Assert(pCurDir->uMagic == RTVFSDIR_MAGIC);
     1359     * Start with the pThis directory.
     1360     */
     1361    if (RTVfsDirRetain(pThis) == UINT32_MAX)
     1362        return VERR_INVALID_HANDLE;
     1363    RTVFSDIRINTERNAL *pCurDir = pThis;
    13681364
    13691365    /*
    13701366     * The traversal loop.
    13711367     */
     1368    int      rc         = VINF_SUCCESS;
    13721369    unsigned cLinks     = 0;
    13731370    uint16_t iComponent = 0;
     
    14611458            if (iRestartComp != iComponent)
    14621459            {
    1463                 /* Must restart from the root (optimize this). */
     1460                /* Must restart from the root. */
    14641461                RTVfsDirRelease(pCurDir);
    1465                 RTVfsLockAcquireRead(pThis->Base.hLock);
    1466                 rc = pThis->pOps->pfnOpenRoot(pThis->Base.pvThis, &pCurDir);
    1467                 RTVfsLockReleaseRead(pThis->Base.hLock);
    1468                 if (RT_FAILURE(rc))
     1462                if (RTVfsDirRetain(pThis) == UINT32_MAX)
    14691463                {
     1464                    rc = VERR_INVALID_HANDLE;
    14701465                    pCurDir = NULL;
    14711466                    break;
    14721467                }
     1468                pCurDir = pThis;
    14731469                iComponent = 0;
    14741470            }
     
    14811477            RTVfsDirRelease(pCurDir);
    14821478            RTVfsLockAcquireRead(hVfsMnt->Base.hLock);
    1483             rc = pThis->pOps->pfnOpenRoot(hVfsMnt->Base.pvThis, &pCurDir);
     1479            rc = hVfsMnt->pOps->pfnOpenRoot(hVfsMnt->Base.pvThis, &pCurDir);
    14841480            RTVfsLockReleaseRead(hVfsMnt->Base.hLock);
    14851481            if (RT_FAILURE(rc))
     
    15001496
    15011497
     1498/**
     1499 * Internal worker for various open functions as well as RTVfsTraverseToParent.
     1500 *
     1501 * @returns IPRT status code.
     1502 * @param   pThis           The VFS.
     1503 * @param   pPath           The parsed path.  This may be changed as symbolic
     1504 *                          links are processed during the path traversal.
     1505 * @param   fFollowSymlink  Whether to follow the final component if it is a
     1506 *                          symbolic link.
     1507 * @param   ppVfsParentDir  Where to return the parent directory handle
     1508 *                          (referenced).
     1509 */
     1510static int rtVfsTraverseToParent(RTVFSINTERNAL *pThis, PRTVFSPARSEDPATH pPath, bool fFollowSymlink,
     1511                                 RTVFSDIRINTERNAL **ppVfsParentDir)
     1512{
     1513    /*
     1514     * Assert sanity.
     1515     */
     1516    AssertPtr(pThis);
     1517    Assert(pThis->uMagic == RTVFS_MAGIC);
     1518    Assert(pThis->Base.cRefs > 0);
     1519    AssertPtr(pPath);
     1520    AssertPtr(ppVfsParentDir);
     1521    *ppVfsParentDir = NULL;
     1522    AssertReturn(pPath->cComponents > 0, VERR_INTERNAL_ERROR_3);
     1523
     1524    /*
     1525     * Open the root directory and join paths with the directory traversal.
     1526     */
     1527    /** @todo Union mounts, traversal optimization methods, races, ++ */
     1528    RTVFSDIRINTERNAL *pRootDir;
     1529    RTVfsLockAcquireRead(pThis->Base.hLock);
     1530    int rc = pThis->pOps->pfnOpenRoot(pThis->Base.pvThis, &pRootDir);
     1531    RTVfsLockReleaseRead(pThis->Base.hLock);
     1532    if (RT_SUCCESS(rc))
     1533    {
     1534        rc = rtVfsDirTraverseToParent(pRootDir, pPath, fFollowSymlink, ppVfsParentDir);
     1535        RTVfsDirRelease(pRootDir);
     1536    }
     1537    return rc;
     1538}
     1539
     1540
    15021541RTDECL(int) RTVfsUtilDummyPollOne(uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, uint32_t *pfRetEvents)
    15031542{
     
    16251664
    16261665
    1627 RTDECL(uint32_t)    RTVfsRetain(RTVFS hVfs)
     1666RTDECL(uint32_t) RTVfsRetain(RTVFS hVfs)
    16281667{
    16291668    RTVFSINTERNAL *pThis = hVfs;
     
    16341673
    16351674
    1636 RTDECL(uint32_t)    RTVfsRelease(RTVFS hVfs)
     1675RTDECL(uint32_t) RTVfsRelease(RTVFS hVfs)
    16371676{
    16381677    RTVFSINTERNAL *pThis = hVfs;
     
    16451684
    16461685
    1647 RTDECL(int)         RTVfsIsRangeInUse(RTVFS hVfs, uint64_t off, size_t cb, bool *pfUsed)
     1686RTDECL(int) RTVfsOpenRoot(RTVFS hVfs, PRTVFSDIR phDir)
    16481687{
    16491688    RTVFSINTERNAL *pThis = hVfs;
    16501689    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    16511690    AssertReturn(pThis->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE);
     1691    AssertPtrReturn(phDir, VERR_INVALID_POINTER);
     1692    *phDir = NIL_RTVFSDIR;
    16521693
    16531694    if (!pThis->pOps->pfnIsRangeInUse)
    16541695        return VERR_NOT_SUPPORTED;
    1655     RTVfsLockAcquireWrite(pThis->Base.hLock);
     1696    RTVfsLockAcquireRead(pThis->Base.hLock);
     1697    int rc = pThis->pOps->pfnOpenRoot(pThis->Base.pvThis, phDir);
     1698    RTVfsLockReleaseRead(pThis->Base.hLock);
     1699
     1700    return rc;
     1701}
     1702
     1703
     1704
     1705RTDECL(int) RTVfsIsRangeInUse(RTVFS hVfs, uint64_t off, size_t cb, bool *pfUsed)
     1706{
     1707    RTVFSINTERNAL *pThis = hVfs;
     1708    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1709    AssertReturn(pThis->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE);
     1710
     1711    if (!pThis->pOps->pfnIsRangeInUse)
     1712        return VERR_NOT_SUPPORTED;
     1713    RTVfsLockAcquireRead(pThis->Base.hLock);
    16561714    int rc = pThis->pOps->pfnIsRangeInUse(pThis->Base.pvThis, off, cb, pfUsed);
    1657     RTVfsLockReleaseWrite(pThis->Base.hLock);
    1658 
    1659     return rc;
    1660 }
     1715    RTVfsLockReleaseRead(pThis->Base.hLock);
     1716
     1717    return rc;
     1718}
     1719
     1720
    16611721
    16621722
     
    17731833 */
    17741834
    1775 RTDECL(uint32_t)    RTVfsDirRetain(RTVFSDIR hVfsDir)
     1835RTDECL(uint32_t) RTVfsDirRetain(RTVFSDIR hVfsDir)
    17761836{
    17771837    RTVFSDIRINTERNAL *pThis = hVfsDir;
     
    17821842
    17831843
    1784 RTDECL(uint32_t)    RTVfsDirRelease(RTVFSDIR hVfsDir)
     1844RTDECL(uint32_t) RTVfsDirRelease(RTVFSDIR hVfsDir)
    17851845{
    17861846    RTVFSDIRINTERNAL *pThis = hVfsDir;
     
    17921852}
    17931853
     1854
     1855RTDECL(int) RTVfsDirOpen(RTVFS hVfs, const char *pszPath, uint32_t fFlags, PRTVFSDIR phVfsDir)
     1856{
     1857    /*
     1858     * Validate input.
     1859     */
     1860    RTVFSINTERNAL *pThis = hVfs;
     1861    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1862    AssertReturn(pThis->uMagic == RTVFS_MAGIC, VERR_INVALID_HANDLE);
     1863    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     1864    AssertPtrReturn(phVfsDir, VERR_INVALID_POINTER);
     1865    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
     1866
     1867    /*
     1868     * Parse the path, assume current directory is root since we've got no
     1869     * caller context here.
     1870     */
     1871    PRTVFSPARSEDPATH pPath;
     1872    int rc = RTVfsParsePathA(pszPath, "/", &pPath);
     1873    if (RT_SUCCESS(rc))
     1874    {
     1875        /*
     1876         * Tranverse the path, resolving the parent node and any symlinks
     1877         * in the final element, and ask the directory to open the subdir.
     1878         */
     1879        RTVFSDIRINTERNAL *pVfsParentDir;
     1880        rc = rtVfsTraverseToParent(pThis, pPath, true /*fFollowSymlink*/, &pVfsParentDir);
     1881        if (RT_SUCCESS(rc))
     1882        {
     1883            const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
     1884
     1885            /** @todo there is a symlink creation race here. */
     1886            RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
     1887            rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
     1888            RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
     1889
     1890            RTVfsDirRelease(pVfsParentDir);
     1891
     1892            if (RT_SUCCESS(rc))
     1893            {
     1894                AssertPtr(*phVfsDir);
     1895                Assert((*phVfsDir)->uMagic == RTVFSDIR_MAGIC);
     1896            }
     1897        }
     1898        RTVfsParsePathFree(pPath);
     1899    }
     1900    return rc;
     1901}
     1902
     1903
     1904RTDECL(int) RTVfsDirOpenDir(RTVFSDIR hVfsDir, const char *pszPath, uint32_t fFlags, PRTVFSDIR phVfsDir)
     1905{
     1906    /*
     1907     * Validate input.
     1908     */
     1909    RTVFSDIRINTERNAL *pThis = hVfsDir;
     1910    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1911    AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, VERR_INVALID_HANDLE);
     1912    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     1913    AssertPtrReturn(phVfsDir, VERR_INVALID_POINTER);
     1914    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
     1915
     1916    /*
     1917     * Parse the path, it's always relative to the given directory.
     1918     */
     1919    PRTVFSPARSEDPATH pPath;
     1920    int rc = RTVfsParsePathA(pszPath, "/", &pPath);
     1921    if (RT_SUCCESS(rc))
     1922    {
     1923        /*
     1924         * Tranverse the path, resolving the parent node and any symlinks
     1925         * in the final element, and ask the directory to open the subdir.
     1926         */
     1927        RTVFSDIRINTERNAL *pVfsParentDir;
     1928        rc = rtVfsDirTraverseToParent(pThis, pPath, true /*fFollowSymlink*/, &pVfsParentDir);
     1929        if (RT_SUCCESS(rc))
     1930        {
     1931            const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
     1932
     1933            /** @todo there is a symlink creation race here. */
     1934            RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
     1935            rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
     1936            RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
     1937
     1938            RTVfsDirRelease(pVfsParentDir);
     1939
     1940            if (RT_SUCCESS(rc))
     1941            {
     1942                AssertPtr(*phVfsDir);
     1943                Assert((*phVfsDir)->uMagic == RTVFSDIR_MAGIC);
     1944            }
     1945        }
     1946        RTVfsParsePathFree(pPath);
     1947    }
     1948    return rc;
     1949}
     1950
     1951
     1952RTDECL(int) RTVfsDirOpenFile(RTVFSDIR hVfsDir, const char *pszPath, uint64_t fOpen, PRTVFSFILE phVfsFile)
     1953{
     1954    /*
     1955     * Validate input.
     1956     */
     1957    RTVFSDIRINTERNAL *pThis = hVfsDir;
     1958    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     1959    AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, VERR_INVALID_HANDLE);
     1960    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     1961    AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER);
     1962
     1963    int rc = rtFileRecalcAndValidateFlags(&fOpen);
     1964    if (RT_FAILURE(rc))
     1965        return rc;
     1966
     1967    /*
     1968     * Parse the path, assume current directory is root since we've got no
     1969     * caller context here.
     1970     */
     1971    PRTVFSPARSEDPATH pPath;
     1972    rc = RTVfsParsePathA(pszPath, "/", &pPath);
     1973    if (RT_SUCCESS(rc))
     1974    {
     1975        if (!pPath->fDirSlash)
     1976        {
     1977            /*
     1978             * Tranverse the path, resolving the parent node and any symlinks
     1979             * in the final element, and ask the directory to open the file.
     1980             */
     1981            RTVFSDIRINTERNAL *pVfsParentDir;
     1982            rc = rtVfsDirTraverseToParent(pThis, pPath, true /*fFollowSymlink*/, &pVfsParentDir);
     1983            if (RT_SUCCESS(rc))
     1984            {
     1985                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
     1986
     1987                /** @todo there is a symlink creation race here. */
     1988                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
     1989                rc = pVfsParentDir->pOps->pfnOpenFile(pVfsParentDir->Base.pvThis, pszEntryName, fOpen, phVfsFile);
     1990                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
     1991
     1992                RTVfsDirRelease(pVfsParentDir);
     1993
     1994                if (RT_SUCCESS(rc))
     1995                {
     1996                    AssertPtr(*phVfsFile);
     1997                    Assert((*phVfsFile)->uMagic == RTVFSFILE_MAGIC);
     1998                }
     1999            }
     2000        }
     2001        else
     2002            rc = VERR_INVALID_PARAMETER;
     2003        RTVfsParsePathFree(pPath);
     2004    }
     2005    return rc;
     2006}
    17942007
    17952008
     
    24332646
    24342647
    2435 RTDECL(int)         RTVfsFileOpen(RTVFS hVfs, const char *pszFilename, uint64_t fOpen, PRTVFSFILE phVfsFile)
     2648RTDECL(int) RTVfsFileOpen(RTVFS hVfs, const char *pszFilename, uint64_t fOpen, PRTVFSFILE phVfsFile)
    24362649{
    24372650    /*
  • trunk/src/VBox/Runtime/common/vfs/vfschain.cpp

    r66594 r66601  
    4848
    4949
     50/*********************************************************************************************************************************
     51*   Internal Functions                                                                                                           *
     52*********************************************************************************************************************************/
     53static PCRTVFSCHAINELEMENTREG rtVfsChainFindProviderLocked(const char *pszProvider);
     54
    5055
    5156/*********************************************************************************************************************************
     
    6166
    6267
     68RTDECL(int) RTVfsChainValidateOpenFileOrIoStream(PRTVFSCHAINSPEC pSpec, PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError)
     69{
     70    if (pElement->cArgs < 1)
     71        return VERR_VFS_CHAIN_AT_LEAST_ONE_ARG;
     72    if (pElement->cArgs > 4)
     73        return VERR_VFS_CHAIN_AT_MOST_FOUR_ARGS;
     74    if (!*pElement->paArgs[0].psz)
     75        return VERR_VFS_CHAIN_EMPTY_ARG;
     76
     77    /*
     78     * Calculate the flags, storing them in the first argument.
     79     */
     80    const char *pszAccess = pElement->cArgs >= 2 ? pElement->paArgs[1].psz : "";
     81    if (!*pszAccess)
     82        pszAccess = (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READWRITE ? "rw"
     83                  : (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ      ? "r"
     84                  : (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_WRITE     ? "w"
     85                  :                                                                   "rw";
     86
     87    const char *pszDisp = pElement->cArgs >= 3 ? pElement->paArgs[2].psz : "";
     88    if (!*pszDisp)
     89        pszDisp = strchr(pszAccess, 'w') != NULL ? "open-create" : "open";
     90
     91    const char *pszSharing = pElement->cArgs >= 4 ? pElement->paArgs[3].psz : "";
     92
     93    int rc = RTFileModeToFlagsEx(pszAccess, pszDisp, pszSharing, &pElement->uProvider);
     94    if (RT_SUCCESS(rc))
     95        return VINF_SUCCESS;
     96
     97    /*
     98     * Now try figure out which argument offended us.
     99     */
     100    AssertReturn(pElement->cArgs > 1, VERR_VFS_CHAIN_IPE);
     101    if (   pElement->cArgs == 2
     102        || RT_FAILURE(RTFileModeToFlagsEx(pszAccess, "open-create", "", &pElement->uProvider)))
     103        *poffError = pElement->paArgs[1].offSpec;
     104    else if (   pElement->cArgs == 3
     105             || RT_FAILURE(RTFileModeToFlagsEx(pszAccess, pszDisp, "", &pElement->uProvider)))
     106        *poffError = pElement->paArgs[2].offSpec;
     107    else
     108        *poffError = pElement->paArgs[3].offSpec;
     109    return VERR_VFS_CHAIN_INVALID_ARGUMENT;
     110}
     111
     112
     113/**
     114 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnValidate}
     115 */
     116static DECLCALLBACK(int) rtVfsChainOpen_Validate(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec,
     117                                                 PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError)
     118{
     119    RT_NOREF(pProviderReg);
     120
     121    /*
     122     * Basic checks.
     123     */
     124    if (   pElement->enmType != RTVFSOBJTYPE_DIR
     125        && pElement->enmType != RTVFSOBJTYPE_FILE
     126        && pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
     127        return VERR_VFS_CHAIN_ONLY_FILE_OR_IOS_OR_DIR;
     128    if (   pElement->enmTypeIn != RTVFSOBJTYPE_DIR
     129        && pElement->enmTypeIn != RTVFSOBJTYPE_FS_STREAM
     130        && pElement->enmTypeIn != RTVFSOBJTYPE_VFS)
     131    {
     132        if (pElement->enmTypeIn == RTVFSOBJTYPE_INVALID)
     133        {
     134            /*
     135             * First element: Ttransform into 'stdfile' or 'stddir' if registered.
     136             */
     137            const char            *pszNewProvider = pElement->enmType == RTVFSOBJTYPE_DIR ? "stddir" : "stdfile";
     138            PCRTVFSCHAINELEMENTREG pNewProvider   = rtVfsChainFindProviderLocked(pszNewProvider);
     139            if (pNewProvider)
     140            {
     141                pElement->pProvider = pNewProvider;
     142                return pNewProvider->pfnValidate(pNewProvider, pSpec, pElement, poffError);
     143            }
     144            return VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT;
     145        }
     146        return VERR_VFS_CHAIN_TAKES_DIR_OR_FSS_OR_VFS;
     147    }
     148
     149    /*
     150     * Make common cause with 'stdfile' if we're opening a file or I/O stream.
     151     * If the input is a FSS, we have to make sure it's a read-only operation.
     152     */
     153    if (   pElement->enmType != RTVFSOBJTYPE_FILE
     154        && pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
     155    {
     156        int rc = RTVfsChainValidateOpenFileOrIoStream(pSpec, pElement, poffError);
     157        if (RT_SUCCESS(rc))
     158        {
     159            if (pElement->enmTypeIn != RTVFSOBJTYPE_FS_STREAM)
     160                return VINF_SUCCESS;
     161            if (   !(pElement->uProvider & RTFILE_O_WRITE)
     162                &&  (pElement->uProvider & RTFILE_O_ACTION_MASK) ==  RTFILE_O_OPEN)
     163                return VINF_SUCCESS;
     164            *poffError = pElement->cArgs > 1 ? pElement->paArgs[1].offSpec : pElement->offSpec;
     165            return VERR_VFS_CHAIN_INVALID_ARGUMENT;
     166        }
     167    }
     168
     169    /*
     170     * Directory checks.  Path argument only, optional. If not given the root directory of a VFS or the
     171     */
     172    if (pElement->cArgs > 1)
     173        return VERR_VFS_CHAIN_AT_MOST_ONE_ARG;
     174    return VINF_SUCCESS;
     175}
     176
     177
     178/**
     179 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate}
     180 */
     181static DECLCALLBACK(int) rtVfsChainOpen_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec,
     182                                                    PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj,
     183                                                    PRTVFSOBJ phVfsObj, uint32_t *poffError)
     184{
     185    RT_NOREF(pProviderReg, pSpec, pElement, poffError);
     186    AssertReturn(hPrevVfsObj != NIL_RTVFSOBJ, VERR_VFS_CHAIN_IPE);
     187
     188    /*
     189     * File system stream: Seek thru the stream looking for the object to open.
     190     */
     191    RTVFSFSSTREAM hVfsFssIn = RTVfsObjToFsStream(hPrevVfsObj);
     192    if (hVfsFssIn != NIL_RTVFSFSSTREAM)
     193    {
     194        return VERR_NOT_IMPLEMENTED;
     195    }
     196
     197    /*
     198     * VFS: Use RTVfsFileOpen or RTVfsDirOpen.
     199     */
     200    RTVFS hVfsIn = RTVfsObjToVfs(hPrevVfsObj);
     201    if (hVfsIn != NIL_RTVFS)
     202    {
     203        if (   pElement->enmType == RTVFSOBJTYPE_FILE
     204            || pElement->enmType == RTVFSOBJTYPE_IO_STREAM)
     205        {
     206            RTVFSFILE hVfsFile = NIL_RTVFSFILE;
     207            int rc = RTVfsFileOpen(hVfsIn, pElement->paArgs[0].psz, pElement->uProvider, &hVfsFile);
     208            if (RT_SUCCESS(rc))
     209            {
     210                *phVfsObj = RTVfsObjFromFile(hVfsFile);
     211                RTVfsFileRelease(hVfsFile);
     212                if (*phVfsObj != NIL_RTVFSOBJ)
     213                    return VINF_SUCCESS;
     214                rc = VERR_VFS_CHAIN_CAST_FAILED;
     215            }
     216            return rc;
     217        }
     218        if (pElement->enmType == RTVFSOBJTYPE_DIR)
     219        {
     220            RTVFSDIR hVfsDir = NIL_RTVFSDIR;
     221            int rc = RTVfsDirOpen(hVfsIn, pElement->paArgs[0].psz, (uint32_t)pElement->uProvider, &hVfsDir);
     222            if (RT_SUCCESS(rc))
     223            {
     224                *phVfsObj = RTVfsObjFromDir(hVfsDir);
     225                RTVfsDirRelease(hVfsDir);
     226                if (*phVfsObj != NIL_RTVFSOBJ)
     227                    return VINF_SUCCESS;
     228                rc = VERR_VFS_CHAIN_CAST_FAILED;
     229            }
     230            return rc;
     231        }
     232        return VERR_VFS_CHAIN_IPE;
     233    }
     234
     235    /*
     236     * Directory: Similar to above, just relative to a directory.
     237     */
     238    RTVFSDIR hVfsDirIn = RTVfsObjToDir(hPrevVfsObj);
     239    if (hVfsDirIn != NIL_RTVFSDIR)
     240    {
     241        if (   pElement->enmType == RTVFSOBJTYPE_FILE
     242            || pElement->enmType == RTVFSOBJTYPE_IO_STREAM)
     243        {
     244            RTVFSFILE hVfsFile = NIL_RTVFSFILE;
     245            int rc = RTVfsDirOpenFile(hVfsDirIn, pElement->paArgs[0].psz, pElement->uProvider, &hVfsFile);
     246            if (RT_SUCCESS(rc))
     247            {
     248                *phVfsObj = RTVfsObjFromFile(hVfsFile);
     249                RTVfsFileRelease(hVfsFile);
     250                if (*phVfsObj != NIL_RTVFSOBJ)
     251                    return VINF_SUCCESS;
     252                rc = VERR_VFS_CHAIN_CAST_FAILED;
     253            }
     254            return rc;
     255        }
     256        if (pElement->enmType == RTVFSOBJTYPE_DIR)
     257        {
     258            RTVFSDIR hVfsDir = NIL_RTVFSDIR;
     259            int rc = RTVfsDirOpenDir(hVfsDirIn, pElement->paArgs[0].psz, pElement->uProvider, &hVfsDir);
     260            if (RT_SUCCESS(rc))
     261            {
     262                *phVfsObj = RTVfsObjFromDir(hVfsDir);
     263                RTVfsDirRelease(hVfsDir);
     264                if (*phVfsObj != NIL_RTVFSOBJ)
     265                    return VINF_SUCCESS;
     266                rc = VERR_VFS_CHAIN_CAST_FAILED;
     267            }
     268            return rc;
     269        }
     270        return VERR_VFS_CHAIN_IPE;
     271    }
     272
     273    AssertFailed();
     274    return VERR_VFS_CHAIN_CAST_FAILED;
     275}
     276
     277
     278/**
     279 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnCanReuseElement}
     280 */
     281static DECLCALLBACK(bool) rtVfsChainOpen_CanReuseElement(PCRTVFSCHAINELEMENTREG pProviderReg,
     282                                                         PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement,
     283                                                         PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement)
     284{
     285    RT_NOREF(pProviderReg, pSpec, pElement, pReuseSpec, pReuseElement);
     286    return false;
     287}
     288
     289
     290/** VFS chain element 'gunzip'. */
     291static RTVFSCHAINELEMENTREG g_rtVfsChainGunzipReg =
     292{
     293    /* uVersion = */            RTVFSCHAINELEMENTREG_VERSION,
     294    /* fReserved = */           0,
     295    /* pszName = */             "open",
     296    /* ListEntry = */           { NULL, NULL },
     297    /* pszHelp = */             "Generic VFS open, that can open files (or I/O stream) and directories in a VFS, directory or file system stream.\n"
     298                                "If used as the first element in a chain, it will work like 'stdfile' or 'stddir' and work on the real file system.\n"
     299                                "First argument is the filename or directory path.\n"
     300                                "Second argument is access mode, files only, optional: r, w, rw.\n"
     301                                "Third argument is open disposition, files only, optional: create, create-replace, open, open-create, open-append, open-truncate.\n"
     302                                "Forth argument is file sharing, files only, optional: nr, nw, nrw, d.",
     303    /* pfnValidate = */         rtVfsChainOpen_Validate,
     304    /* pfnInstantiate = */      rtVfsChainOpen_Instantiate,
     305    /* pfnCanReuseElement = */  rtVfsChainOpen_CanReuseElement,
     306    /* uEndMarker = */          RTVFSCHAINELEMENTREG_VERSION
     307};
     308
     309RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainGunzipReg, rtVfsChainGunzipReg);
     310
     311
     312
    63313
    64314/**
     
    155405        pSpec->fOpenDir       = 0;
    156406        pSpec->cElements      = 0;
    157         pSpec->uProvider      = 0;
    158407        pSpec->paElements     = NULL;
    159408    }
     
    628877            {
    629878                PRTVFSCHAINELEMSPEC const pElement = &pSpec->paElements[i];
     879                *poffError = pElement->offSpec;
    630880
    631881                /*
     
    8621112}
    8631113
     1114
  • trunk/src/VBox/Runtime/common/vfs/vfsreadahead.cpp

    r66598 r66601  
    826826     * Basics.
    827827     */
    828     if (pElement->enmTypeIn == RTVFSOBJTYPE_INVALID)
    829         return VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT;
    830     if (pElement->cArgs > 2)
    831         return VERR_VFS_CHAIN_AT_MOST_TWO_ARGS;
    832828    if (   pElement->enmType != RTVFSOBJTYPE_FILE
    833829        && pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
    834830        return VERR_VFS_CHAIN_ONLY_FILE_OR_IOS;
     831    if (pElement->enmTypeIn == RTVFSOBJTYPE_INVALID)
     832        return VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT;
     833    if (   pElement->enmTypeIn != RTVFSOBJTYPE_FILE
     834        && pElement->enmTypeIn != RTVFSOBJTYPE_IO_STREAM)
     835        return VERR_VFS_CHAIN_TAKES_FILE_OR_IOS;
    835836    if (pSpec->fOpenFile & RTFILE_O_WRITE)
    836837        return VERR_VFS_CHAIN_READ_ONLY_IOS;
     838    if (pElement->cArgs > 2)
     839        return VERR_VFS_CHAIN_AT_MOST_TWO_ARGS;
    837840
    838841    /*
     
    872875     * Save the parsed arguments in the spec since their both optional.
    873876     */
    874     pSpec->uProvider = RT_MAKE_U64(cBuffers, cbBuffer);
     877    pElement->uProvider = RT_MAKE_U64(cBuffers, cbBuffer);
    875878
    876879    return VINF_SUCCESS;
     
    894897    {
    895898        RTVFSFILE hVfsFile = NIL_RTVFSFILE;
    896         rc = RTVfsCreateReadAheadForFile(hVfsFileIn, 0 /*fFlags*/, RT_LO_U32(pSpec->uProvider),
    897                                          RT_HI_U32(pSpec->uProvider), &hVfsFile);
     899        rc = RTVfsCreateReadAheadForFile(hVfsFileIn, 0 /*fFlags*/, RT_LO_U32(pElement->uProvider),
     900                                         RT_HI_U32(pElement->uProvider), &hVfsFile);
    898901        RTVfsFileRelease(hVfsFileIn);
    899902        if (RT_SUCCESS(rc))
     
    912915        {
    913916            RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM;
    914             rc = RTVfsCreateReadAheadForIoStream(hVfsIosIn, 0 /*fFlags*/, RT_LO_U32(pSpec->uProvider),
    915                                                  RT_HI_U32(pSpec->uProvider), &hVfsIos);
     917            rc = RTVfsCreateReadAheadForIoStream(hVfsIosIn, 0 /*fFlags*/, RT_LO_U32(pElement->uProvider),
     918                                                 RT_HI_U32(pElement->uProvider), &hVfsIos);
    916919            RTVfsIoStrmRelease(hVfsIosIn);
    917920            if (RT_SUCCESS(rc))
  • trunk/src/VBox/Runtime/common/vfs/vfsstdfile.cpp

    r66594 r66601  
    526526    if (pElement->enmTypeIn != RTVFSOBJTYPE_INVALID)
    527527        return VERR_VFS_CHAIN_MUST_BE_FIRST_ELEMENT;
    528     if (pElement->cArgs < 1)
    529         return VERR_VFS_CHAIN_AT_LEAST_ONE_ARG;
    530     if (pElement->cArgs > 4)
    531         return VERR_VFS_CHAIN_AT_MOST_FOUR_ARGS;
    532     if (!*pElement->paArgs[0].psz)
    533         return VERR_VFS_CHAIN_EMPTY_ARG;
    534528    if (   pElement->enmType != RTVFSOBJTYPE_FILE
    535529        && pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
    536530        return VERR_VFS_CHAIN_ONLY_FILE_OR_IOS;
    537531
     532
    538533    /*
    539      * Calculate the flags, storing them in the first argument.
     534     * Join common cause with the 'open' provider.
    540535     */
    541     const char *pszAccess = pElement->cArgs >= 2 ? pElement->paArgs[1].psz : "";
    542     if (!*pszAccess)
    543         pszAccess = (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READWRITE ? "rw"
    544                   : (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ      ? "r"
    545                   : (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_WRITE     ? "w"
    546                   :                                                                   "rw";
    547 
    548     const char *pszDisp = pElement->cArgs >= 3 ? pElement->paArgs[2].psz : "";
    549     if (!*pszDisp)
    550         pszDisp = strchr(pszAccess, 'w') != NULL ? "open-create" : "open";
    551 
    552     const char *pszSharing = pElement->cArgs >= 4 ? pElement->paArgs[3].psz : "";
    553 
    554     int rc = RTFileModeToFlagsEx(pszAccess, pszDisp, pszSharing, &pElement->paArgs[0].uProvider);
    555     if (RT_SUCCESS(rc))
    556         return VINF_SUCCESS;
    557 
    558     /*
    559      * Now try figure out which argument offended us.
    560      */
    561     AssertReturn(pElement->cArgs > 1, VERR_VFS_CHAIN_IPE);
    562     if (   pElement->cArgs == 2
    563         || RT_FAILURE(RTFileModeToFlagsEx(pszAccess, "open-create", "", &pElement->paArgs[0].uProvider)))
    564         *poffError = pElement->paArgs[1].offSpec;
    565     else if (   pElement->cArgs == 3
    566              || RT_FAILURE(RTFileModeToFlagsEx(pszAccess, pszDisp, "", &pElement->paArgs[0].uProvider)))
    567         *poffError = pElement->paArgs[2].offSpec;
    568     else
    569         *poffError = pElement->paArgs[3].offSpec;
    570     return VERR_VFS_CHAIN_INVALID_ARGUMENT;
     536    return RTVfsChainValidateOpenFileOrIoStream(pSpec, pElement, poffError);
    571537}
    572538
     
    583549
    584550    RTVFSFILE hVfsFile;
    585     int rc = RTVfsFileOpenNormal(pElement->paArgs[0].psz, pElement->paArgs[0].uProvider, &hVfsFile);
     551    int rc = RTVfsFileOpenNormal(pElement->paArgs[0].psz, pElement->uProvider, &hVfsFile);
    586552    if (RT_SUCCESS(rc))
    587553    {
  • trunk/src/VBox/Runtime/common/zip/gzipvfs.cpp

    r66596 r66601  
    839839    RT_NOREF(pProviderReg, poffError);
    840840
     841    if (pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
     842        return VERR_VFS_CHAIN_ONLY_IOS;
    841843    if (pElement->enmTypeIn == RTVFSOBJTYPE_INVALID)
    842844        return VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT;
     845    if (   pElement->enmTypeIn != RTVFSOBJTYPE_FILE
     846        && pElement->enmTypeIn != RTVFSOBJTYPE_IO_STREAM)
     847        return VERR_VFS_CHAIN_TAKES_FILE_OR_IOS;
     848    if (pSpec->fOpenFile & RTFILE_O_WRITE)
     849        return VERR_VFS_CHAIN_READ_ONLY_IOS;
    843850    if (pElement->cArgs != 0)
    844851        return VERR_VFS_CHAIN_NO_ARGS;
    845     if (pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
    846         return VERR_VFS_CHAIN_ONLY_IOS;
    847     if (pSpec->fOpenFile & RTFILE_O_WRITE)
    848         return VERR_VFS_CHAIN_READ_ONLY_IOS;
    849852
    850853    return VINF_SUCCESS;
     
    922925     * Basics.
    923926     */
     927    if (pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
     928        return VERR_VFS_CHAIN_ONLY_IOS;
    924929    if (pElement->enmTypeIn == RTVFSOBJTYPE_INVALID)
    925930        return VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT;
     931    if (   pElement->enmTypeIn != RTVFSOBJTYPE_FILE
     932        && pElement->enmTypeIn != RTVFSOBJTYPE_IO_STREAM)
     933        return VERR_VFS_CHAIN_TAKES_FILE_OR_IOS;
     934    if (pSpec->fOpenFile & RTFILE_O_READ)
     935        return VERR_VFS_CHAIN_WRITE_ONLY_IOS;
    926936    if (pElement->cArgs > 1)
    927937        return VERR_VFS_CHAIN_AT_MOST_ONE_ARG;
    928     if (pElement->enmType != RTVFSOBJTYPE_IO_STREAM)
    929         return VERR_VFS_CHAIN_ONLY_IOS;
    930     if (pSpec->fOpenFile & RTFILE_O_READ)
    931         return VERR_VFS_CHAIN_WRITE_ONLY_IOS;
    932938
    933939    /*
     
    939945        const char *psz = pElement->paArgs[0].psz;
    940946        if (!*psz || !strcmp(psz, "default"))
    941             pSpec->uProvider = 6;
     947            pElement->uProvider = 6;
    942948        else if (!strcmp(psz, "fast"))
    943             pSpec->uProvider = 3;
     949            pElement->uProvider = 3;
    944950        else if (   RT_C_IS_DIGIT(*psz)
    945951                 && *psz != '0'
    946952                 && *RTStrStripL(psz + 1) == '\0')
    947             pSpec->uProvider = *psz - '0';
     953            pElement->uProvider = *psz - '0';
    948954        else
    949955        {
     
    953959    }
    954960    else
    955         pSpec->uProvider = 6;
     961        pElement->uProvider = 6;
    956962
    957963    return VINF_SUCCESS;
     
    974980
    975981    RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM;
    976     int rc = RTZipGzipCompressIoStream(hVfsIosOut, 0 /*fFlags*/, pSpec->uProvider, &hVfsIos);
     982    int rc = RTZipGzipCompressIoStream(hVfsIosOut, 0 /*fFlags*/, pElement->uProvider, &hVfsIos);
    977983    RTVfsObjFromIoStream(hVfsIosOut);
    978984    if (RT_SUCCESS(rc))
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