VirtualBox

Changeset 69716 in vbox for trunk


Ignore:
Timestamp:
Nov 16, 2017 2:31:25 PM (7 years ago)
Author:
vboxsync
Message:

IPRT: More work on directory relative APIs (NT mainly) and VFS; introducing RTMkDir (test) tool.

  • Added RTVfsDirCreateDir
  • Added RTVfsChainOpenParentDir and RTVfsChainSplitOffFinalPath.
  • Added new tool for testing this called RTMkDir.
  • Fixed directory traversal problem with stddir by making it okay to return VERR_FILE_NOT_FOUND as well.
Location:
trunk
Files:
1 added
14 edited

Legend:

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

    r69709 r69716  
    620620 * @param   fMode           The mode of the new directory.
    621621 * @param   fCreate         Create flags, RTDIRCREATE_FLAGS_XXX.
     622 * @param   phSubDir        Where to return the handle of the created directory.
     623 *                          Optional.
    622624 *
    623625 * @sa      RTDirCreate
    624626 */
    625 RTDECL(int) RTDirRelDirCreate(PRTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate);
     627RTDECL(int) RTDirRelDirCreate(PRTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate, PRTDIR *phSubDir);
    626628
    627629/**
  • trunk/include/iprt/err.h

    r69105 r69716  
    20792079/** VFS chain doesn't end with a path only element. */
    20802080#define VERR_VFS_CHAIN_NOT_PATH_ONLY                (-22157)
     2081/** The path only element at the end of the VFS chain is too short to make out
     2082 *  the parent directory. */
     2083#define VERR_VFS_CHAIN_TOO_SHORT_FOR_PARENT         (-22158)
    20812084/** @} */
    20822085
  • trunk/include/iprt/mangling.h

    r69674 r69716  
    24182418# define RTVfsChainMsgErrorExitFailure                  RT_MANGLER(RTVfsChainMsgErrorExitFailure)
    24192419# define RTVfsChainOpenDir                              RT_MANGLER(RTVfsChainOpenDir)
     2420# define RTVfsChainOpenParentDir                        RT_MANGLER(RTVfsChainOpenParentDir)
    24202421# define RTVfsChainOpenFile                             RT_MANGLER(RTVfsChainOpenFile)
    24212422# define RTVfsChainOpenIoStream                         RT_MANGLER(RTVfsChainOpenIoStream)
     
    24252426# define RTVfsChainSpecFree                             RT_MANGLER(RTVfsChainSpecFree)
    24262427# define RTVfsChainSpecParse                            RT_MANGLER(RTVfsChainSpecParse)
     2428# define RTVfsChainSplitOffFinalPath                    RT_MANGLER(RTVfsChainSplitOffFinalPath)
    24272429# define RTVfsChainValidateOpenFileOrIoStream           RT_MANGLER(RTVfsChainValidateOpenFileOrIoStream)
    24282430# define RTVfsDirRelease                                RT_MANGLER(RTVfsDirRelease)
     
    24312433# define RTVfsDirOpen                                   RT_MANGLER(RTVfsDirOpen)
    24322434# define RTVfsDirOpenDir                                RT_MANGLER(RTVfsDirOpenDir)
     2435# define RTVfsDirCreateDir                              RT_MANGLER(RTVfsDirCreateDir)
    24332436# define RTVfsDirOpenFile                               RT_MANGLER(RTVfsDirOpenFile)
    24342437# define RTVfsDirOpenFileAsIoStream                     RT_MANGLER(RTVfsDirOpenFileAsIoStream)
  • trunk/include/iprt/vfs.h

    r69679 r69716  
    478478
    479479/**
     480 * Creates a directory relative to @a hVfsDir.
     481 *
     482 * @returns IPRT status code
     483 * @param   hVfsDir             The directory the path is relative to.
     484 * @param   pszRelPath          The relative path to the new directory.
     485 * @param   fMode               The file mode for the new directory.
     486 * @param   fFlags              Directory creation flags, RTDIRCREATE_FLAGS_XXX.
     487 * @param   phVfsDir            Where to return the handle to the newly created
     488 *                              directory.  Optional.
     489 * @sa      RTDirCreate, RTDirRelDirCreate
     490 */
     491RTDECL(int) RTVfsDirCreateDir(RTVFSDIR hVfsDir, const char *pszRelPath, RTFMODE fMode, uint32_t fFlags, PRTVFSDIR phVfsDir);
     492
     493/**
    480494 * Create a VFS directory handle from a standard IPRT directory handle (PRTDIR).
    481495 *
     
    15351549RTDECL(int) RTVfsChainOpenFsStream(const char *pszSpec, PRTVFSFSSTREAM  phVfsFss, uint32_t *poffError, PRTERRINFO pErrInfo);
    15361550RTDECL(int) RTVfsChainOpenDir(const char *pszSpec, uint32_t fOpen, PRTVFSDIR phVfsDir, uint32_t *poffError, PRTERRINFO pErrInfo);
     1551RTDECL(int) RTVfsChainOpenParentDir(const char *pszSpec, uint32_t fOpen, PRTVFSDIR phVfsDir, const char **ppszChild,
     1552                                    uint32_t *poffError, PRTERRINFO pErrInfo);
    15371553RTDECL(int) RTVfsChainOpenFile(const char *pszSpec, uint64_t fOpen, PRTVFSFILE phVfsFile, uint32_t *poffError, PRTERRINFO pErrInfo);
    15381554RTDECL(int) RTVfsChainOpenIoStream(const char *pszSpec, uint64_t fOpen, PRTVFSIOSTREAM phVfsIos, uint32_t *poffError, PRTERRINFO pErrInfo);
     
    15661582
    15671583/**
     1584 * Splits the given chain spec into a final path and the preceeding spec.
     1585 *
     1586 * This works on plain paths too.
     1587 *
     1588 * @returns IPRT status code.
     1589 * @param   pszSpec         The chain spec to split.  This will be modified!
     1590 * @param   ppszSpec        Where to return the pointer to the chain spec part.
     1591 *                          This is set to NULL if it's a plain path or a chain
     1592 *                          spec with only a final-path element.
     1593 * @param   ppszFinalPath   Where to return the pointer to the final path.  This
     1594 *                          is set to NULL if no final path.
     1595 * @param   poffError       Where to on error return an offset into @a pszSpec
     1596 *                          of what cause the error.  Optional.
     1597 */
     1598RTDECL(int) RTVfsChainSplitOffFinalPath(char *pszSpec, char **ppszSpec, char **ppszFinalPath, uint32_t *poffError);
     1599
     1600/**
    15681601 * Common code for reporting errors of a RTVfsChainOpen* API.
    15691602 *
  • trunk/include/iprt/vfslowlevel.h

    r69705 r69716  
    566566     * @param   fFlags      RTDIR_F_XXX.
    567567     * @param   phVfsDir    Where to return the handle to the opened directory.
     568     *                      Optional.
    568569     * @sa      RTDirOpen.
    569570     */
  • trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp

    r69705 r69716  
    15231523            *pszEntryEnd = '\0';
    15241524            if (   rc == VERR_PATH_NOT_FOUND
     1525                || rc == VERR_FILE_NOT_FOUND
    15251526                || rc == VERR_NOT_A_DIRECTORY
    15261527                || rc == VERR_NOT_SYMLINK)
     
    23502351
    23512352
     2353RTDECL(int) RTVfsDirCreateDir(RTVFSDIR hVfsDir, const char *pszRelPath, RTFMODE fMode, uint32_t fFlags, PRTVFSDIR phVfsDir)
     2354{
     2355    /*
     2356     * Validate input.
     2357     */
     2358    RTVFSDIRINTERNAL *pThis = hVfsDir;
     2359    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     2360    AssertReturn(pThis->uMagic == RTVFSDIR_MAGIC, VERR_INVALID_HANDLE);
     2361    AssertPtrReturn(pszRelPath, VERR_INVALID_POINTER);
     2362    AssertPtrReturn(phVfsDir, VERR_INVALID_POINTER);
     2363    AssertReturn(!(fFlags & ~RTDIRCREATE_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
     2364    fMode = rtFsModeNormalize(fMode, pszRelPath, 0);
     2365    AssertReturn(rtFsModeIsValidPermissions(fMode), VERR_INVALID_FMODE);
     2366    if (!(fFlags & RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_DONT_SET))
     2367        fMode |= RTFS_DOS_NT_NOT_CONTENT_INDEXED;
     2368
     2369    /*
     2370     * Parse the path, it's always relative to the given directory.
     2371     */
     2372    PRTVFSPARSEDPATH pPath;
     2373    int rc = RTVfsParsePathA(pszRelPath, NULL, &pPath);
     2374    if (RT_SUCCESS(rc))
     2375    {
     2376        if (pPath->cComponents > 0)
     2377        {
     2378            /*
     2379             * Tranverse the path, resolving the parent node, not checking for symbolic
     2380             * links in the final element, and ask the directory to create the subdir.
     2381             */
     2382            RTVFSDIRINTERNAL *pVfsParentDir;
     2383            rc = rtVfsDirTraverseToParent(pThis, pPath,
     2384                                            fFlags & RTDIRCREATE_FLAGS_NO_SYMLINKS
     2385                                          ? RTPATH_F_NO_SYMLINKS | RTPATH_F_ON_LINK : RTPATH_F_FOLLOW_LINK,
     2386                                          &pVfsParentDir);
     2387            if (RT_SUCCESS(rc))
     2388            {
     2389                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
     2390
     2391                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
     2392                rc = pVfsParentDir->pOps->pfnCreateDir(pVfsParentDir->Base.pvThis, pszEntryName, fMode, phVfsDir);
     2393                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
     2394
     2395                RTVfsDirRelease(pVfsParentDir);
     2396
     2397                if (RT_SUCCESS(rc) && phVfsDir)
     2398                {
     2399                    AssertPtr(*phVfsDir);
     2400                    Assert((*phVfsDir)->uMagic == RTVFSDIR_MAGIC);
     2401                }
     2402            }
     2403        }
     2404        else
     2405            rc = VERR_PATH_ZERO_LENGTH;
     2406        RTVfsParsePathFree(pPath);
     2407    }
     2408    return rc;
     2409}
     2410
     2411
    23522412RTDECL(int) RTVfsDirOpenFile(RTVFSDIR hVfsDir, const char *pszPath, uint64_t fOpen, PRTVFSFILE phVfsFile)
    23532413{
  • trunk/src/VBox/Runtime/common/vfs/vfschain.cpp

    r69705 r69716  
    3434#include <iprt/asm.h>
    3535#include <iprt/critsect.h>
     36#include <iprt/ctype.h>
    3637#include <iprt/err.h>
    3738#include <iprt/file.h>
     
    11981199
    11991200
     1201RTDECL(int) RTVfsChainOpenParentDir(const char *pszSpec, uint32_t fOpen, PRTVFSDIR phVfsDir, const char **ppszChild,
     1202                                    uint32_t *poffError, PRTERRINFO pErrInfo)
     1203{
     1204    uint32_t offErrorIgn;
     1205    if (!poffError)
     1206        poffError = &offErrorIgn;
     1207    *poffError = 0;
     1208    AssertPtrReturn(pszSpec, VERR_INVALID_POINTER);
     1209    AssertReturn(*pszSpec != '\0', VERR_INVALID_PARAMETER);
     1210    AssertPtrReturn(phVfsDir, VERR_INVALID_POINTER);
     1211    AssertPtrReturn(ppszChild, VERR_INVALID_POINTER);
     1212    *ppszChild = NULL;
     1213    AssertPtrNullReturn(pErrInfo, VERR_INVALID_POINTER);
     1214
     1215    /*
     1216     * Process the spec from the end, trying to find the child part of it.
     1217     * We cannot use RTPathFilename here because we must ignore trailing slashes.
     1218     */
     1219    const char * const pszEnd   = RTStrEnd(pszSpec, RTSTR_MAX);
     1220    const char        *pszChild = pszEnd;
     1221    while (   pszChild != pszSpec
     1222           && RTPATH_IS_SLASH(pszChild[-1]))
     1223        pszChild--;
     1224    while (   pszChild != pszSpec
     1225           && !RTPATH_IS_SLASH(pszChild[-1])
     1226           && !RTPATH_IS_VOLSEP(pszChild[-1]))
     1227        pszChild--;
     1228    size_t const cchChild = pszEnd - pszChild;
     1229    *ppszChild = pszChild;
     1230
     1231    /*
     1232     * Try for a VFS chain first, falling back on regular file system stuff if it's just a path.
     1233     */
     1234    int rc;
     1235    PRTVFSCHAINSPEC pSpec = NULL;
     1236    if (strncmp(pszSpec, RTVFSCHAIN_SPEC_PREFIX, sizeof(RTVFSCHAIN_SPEC_PREFIX) - 1) == 0)
     1237    {
     1238        rc = RTVfsChainSpecParse(pszSpec,  0 /*fFlags*/, RTVFSOBJTYPE_DIR, &pSpec, poffError);
     1239        if (RT_FAILURE(rc))
     1240            return rc;
     1241
     1242        Assert(pSpec->cElements > 0);
     1243        if (   pSpec->cElements > 1
     1244            || pSpec->paElements[0].enmType != RTVFSOBJTYPE_END)
     1245        {
     1246            /*
     1247             * Check that it ends with a path-only element and that this in turn ends with
     1248             * what pszChild points to.  (We cannot easiy figure out the parent part of
     1249             * an element that isn't path-only, so we don't bother trying try.)
     1250             */
     1251            PRTVFSCHAINELEMSPEC pLast = &pSpec->paElements[pSpec->cElements - 1];
     1252            if (pLast->pszProvider == NULL)
     1253            {
     1254                size_t cchFinal = strlen(pLast->paArgs[0].psz);
     1255                if (   cchFinal >= cchChild
     1256                    && memcmp(&pLast->paArgs[0].psz[cchFinal - cchChild], pszChild, cchChild + 1) == 0)
     1257                {
     1258                    /*
     1259                     * Drop the child part so we have a path to the parent, then setup the chain.
     1260                     */
     1261                    if (cchFinal > cchChild)
     1262                        pLast->paArgs[0].psz[cchFinal - cchChild] = '\0';
     1263                    else
     1264                        pSpec->cElements--;
     1265
     1266                    const char *pszFinal = NULL;
     1267                    RTVFSOBJ    hVfsObj  = NIL_RTVFSOBJ;
     1268                    pSpec->fOpenFile = fOpen;
     1269                    rc = RTVfsChainSpecCheckAndSetup(pSpec, NULL /*pReuseSpec*/, &hVfsObj, &pszFinal, poffError, pErrInfo);
     1270                    if (RT_SUCCESS(rc))
     1271                    {
     1272                        if (!pszFinal)
     1273                        {
     1274                            Assert(cchFinal == cchChild);
     1275
     1276                            /* Try convert it to a file object and we're done. */
     1277                            *phVfsDir = RTVfsObjToDir(hVfsObj);
     1278                            if (*phVfsDir)
     1279                                rc = VINF_SUCCESS;
     1280                            else
     1281                                rc = VERR_VFS_CHAIN_CAST_FAILED;
     1282                        }
     1283                        else
     1284                        {
     1285                            /*
     1286                             * Do a file open with the final path on the returned object.
     1287                             */
     1288                            RTVFS           hVfs    = RTVfsObjToVfs(hVfsObj);
     1289                            RTVFSDIR        hVfsDir = RTVfsObjToDir(hVfsObj);
     1290                            RTVFSFSSTREAM   hVfsFss = RTVfsObjToFsStream(hVfsObj);
     1291                            if (hVfs != NIL_RTVFS)
     1292                                rc = RTVfsDirOpen(hVfs, pszFinal, fOpen, phVfsDir);
     1293                            else if (hVfsDir != NIL_RTVFSDIR)
     1294                                rc = RTVfsDirOpenDir(hVfsDir, pszFinal, fOpen, phVfsDir);
     1295                            else if (hVfsFss != NIL_RTVFSFSSTREAM)
     1296                                rc = VERR_NOT_IMPLEMENTED;
     1297                            else
     1298                                rc = VERR_VFS_CHAIN_TYPE_MISMATCH_PATH_ONLY;
     1299                            RTVfsRelease(hVfs);
     1300                            RTVfsDirRelease(hVfsDir);
     1301                            RTVfsFsStrmRelease(hVfsFss);
     1302                        }
     1303                        RTVfsObjRelease(hVfsObj);
     1304                    }
     1305                }
     1306                else
     1307                    rc = VERR_VFS_CHAIN_TOO_SHORT_FOR_PARENT;
     1308            }
     1309            else
     1310                rc = VERR_VFS_CHAIN_NOT_PATH_ONLY;
     1311
     1312            RTVfsChainSpecFree(pSpec);
     1313            return rc;
     1314        }
     1315
     1316        /* Only a path element. */
     1317        pszSpec = pSpec->paElements[0].paArgs[0].psz;
     1318    }
     1319
     1320    /*
     1321     * Path to regular file system.
     1322     */
     1323    if (RTPathHasPath(pszSpec))
     1324    {
     1325        char *pszCopy = RTStrDup(pszSpec);
     1326        if (pszCopy)
     1327        {
     1328            RTPathStripFilename(pszCopy);
     1329            rc = RTVfsDirOpenNormal(pszCopy, fOpen, phVfsDir);
     1330            RTStrFree(pszCopy);
     1331        }
     1332        else
     1333            rc = VERR_NO_STR_MEMORY;
     1334    }
     1335    else
     1336        rc = RTVfsDirOpenNormal(".", fOpen, phVfsDir);
     1337
     1338    RTVfsChainSpecFree(pSpec);
     1339    return rc;
     1340
     1341}
     1342
     1343
    12001344RTDECL(int) RTVfsChainOpenFile(const char *pszSpec, uint64_t fOpen,
    12011345                               PRTVFSFILE phVfsFile, uint32_t *poffError, PRTERRINFO pErrInfo)
     
    12251369            || pSpec->paElements[0].enmType != RTVFSOBJTYPE_END)
    12261370        {
    1227 
    12281371            const char *pszFinal = NULL;
    12291372            RTVFSOBJ    hVfsObj  = NIL_RTVFSOBJ;
     
    13191462            || pSpec->paElements[0].enmType != RTVFSOBJTYPE_END)
    13201463        {
    1321 
    13221464            const char *pszFinal = NULL;
    13231465            RTVFSOBJ    hVfsObj  = NIL_RTVFSOBJ;
     
    14311573            || pSpec->paElements[0].enmType != RTVFSOBJTYPE_END)
    14321574        {
    1433 
    14341575            const char *pszFinal = NULL;
    14351576            RTVFSOBJ    hVfsObj  = NIL_RTVFSOBJ;
     
    15271668}
    15281669
     1670
     1671RTDECL(int) RTVfsChainSplitOffFinalPath(char *pszSpec, char **ppszSpec, char **ppszFinalPath, uint32_t *poffError)
     1672{
     1673    /* Make sure we've got an error info variable. */
     1674    uint32_t offErrorIgn;
     1675    if (!poffError)
     1676        poffError = &offErrorIgn;
     1677    *poffError = 0;
     1678
     1679    /*
     1680     * If not chain specifier, just duplicate the input and return.
     1681     */
     1682    if (strncmp(pszSpec, RTVFSCHAIN_SPEC_PREFIX, sizeof(RTVFSCHAIN_SPEC_PREFIX) - 1) != 0)
     1683    {
     1684        *ppszSpec      = NULL;
     1685        *ppszFinalPath = pszSpec;
     1686        return VINF_SUCCESS;
     1687    }
     1688
     1689    /*
     1690     * Parse it and check out the last element.
     1691     */
     1692    PRTVFSCHAINSPEC pSpec = NULL;
     1693    int rc = RTVfsChainSpecParse(pszSpec,  0 /*fFlags*/, RTVFSOBJTYPE_BASE, &pSpec, poffError);
     1694    if (RT_SUCCESS(rc))
     1695    {
     1696        Assert(pSpec->cElements > 0);
     1697        PCRTVFSCHAINELEMSPEC pLast = &pSpec->paElements[pSpec->cElements - 1];
     1698        if (pLast->pszProvider == NULL)
     1699        {
     1700            char *psz = &pszSpec[pLast->offSpec];
     1701            *ppszFinalPath = psz;
     1702            if (pSpec->cElements > 1)
     1703            {
     1704                *ppszSpec = pszSpec;
     1705
     1706                /* Remove the separator and any whitespace around it. */
     1707                while (   psz != pszSpec
     1708                       && RT_C_IS_SPACE(psz[-1]))
     1709                    psz--;
     1710                if (    psz != pszSpec
     1711                    && (   psz[-1] == ':'
     1712                        || psz[-1] == '|'))
     1713                    psz--;
     1714                while (   psz != pszSpec
     1715                       && RT_C_IS_SPACE(psz[-1]))
     1716                    psz--;
     1717                *psz = '\0';
     1718            }
     1719            else
     1720                *ppszSpec = NULL;
     1721        }
     1722        else
     1723        {
     1724            *ppszFinalPath = NULL;
     1725            *ppszSpec      = pszSpec;
     1726        }
     1727        RTVfsChainSpecFree(pSpec);
     1728    }
     1729    else
     1730    {
     1731        *ppszSpec      = NULL;
     1732        *ppszFinalPath = NULL;
     1733    }
     1734    return rc;
     1735}
     1736
  • trunk/src/VBox/Runtime/common/vfs/vfsstddir.cpp

    r69679 r69716  
    347347{
    348348    PRTVFSSTDDIR pThis = (PRTVFSSTDDIR)pvThis;
    349     int rc = RTDirRelDirCreate(pThis->hDir, pszSubDir, fMode, 0 /* fFlags */);
    350     if (   RT_SUCCESS(rc)
    351         && phVfsDir)
    352     {
    353         /** @todo subdir open flags */
     349    int rc;
     350    if (!phVfsDir)
     351        rc = RTDirRelDirCreate(pThis->hDir, pszSubDir, fMode, 0 /* fFlags */, NULL);
     352    else
     353    {
    354354        PRTDIR hSubDir;
    355         rc = RTDirRelDirOpen(pThis->hDir, pszSubDir, &hSubDir);
     355        rc = RTDirRelDirCreate(pThis->hDir, pszSubDir, fMode, 0 /* fFlags */, &hSubDir);
    356356        if (RT_SUCCESS(rc))
    357357        {
     358            /** @todo subdir open flags...   */
    358359            rc = rtVfsDirFromRTDir(hSubDir, 0, false, phVfsDir);
    359360            if (RT_FAILURE(rc))
     
    361362        }
    362363    }
     364
    363365    return rc;
    364366}
  • trunk/src/VBox/Runtime/include/internal/dir.h

    r69691 r69716  
    166166 * @param   hRelativeDir        The directory @a pvNativeRelative is relative,
    167167 *                              ~(uintptr_t)0 if absolute.
    168  * @param   pvNativeRelative    The native relative path.  NULL if absolute.
     168 * @param   pvNativeRelative    The native relative path.  NULL if absolute or
     169 *                              we're to use (consume) hRelativeDir.
    169170 */
    170171int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf, uintptr_t hRelativeDir, void *pvNativeRelative);
     
    179180
    180181
    181 DECLHIDDEN(int) rtDirOpenRelative(PRTDIR *ppDir, const char *pszRelativeAndFilter, RTDIRFILTER enmFilter, uint32_t fFlags,
    182                                   uintptr_t hRelativeDir, void *pvNativeRelative);
     182DECLHIDDEN(int) rtDirOpenRelativeOrHandle(PRTDIR *ppDir, const char *pszRelativeAndFilter, RTDIRFILTER enmFilter, uint32_t fFlags,
     183                                          uintptr_t hRelativeDir, void *pvNativeRelative);
    183184
    184185#endif
  • trunk/src/VBox/Runtime/r3/dir.cpp

    r69691 r69716  
    512512 * @param   enmFilter           The type of filter to apply.
    513513 * @param   fFlags              RTDIR_F_XXX.
    514  * @param   hRelativeDir        The directory @a pvNativeRelative is relative,
    515  *                              ~(uintptr_t)0 if absolute.
    516  * @param   pvNativeRelative    The native relative path.  NULL if absolute.
     514 * @param   hRelativeDir        The directory @a pvNativeRelative is relative
     515 *                              to, ~(uintptr_t)0 if absolute.
     516 * @param   pvNativeRelative    The native relative path.  NULL if absolute or
     517 *                              we're to use (consume) hRelativeDir.
    517518 */
    518519static int rtDirOpenCommon(PRTDIR *ppDir, const char *pszPath, const char *pszFilter, RTDIRFILTER enmFilter, uint32_t fFlags,
     
    655656
    656657
    657 DECLHIDDEN(int) rtDirOpenRelative(PRTDIR *ppDir, const char *pszPath, RTDIRFILTER enmFilter, uint32_t fFlags,
    658                                   uintptr_t hRelativeDir, void *pvNativeRelative)
     658DECLHIDDEN(int) rtDirOpenRelativeOrHandle(PRTDIR *ppDir, const char *pszPath, RTDIRFILTER enmFilter, uint32_t fFlags,
     659                                          uintptr_t hRelativeDir, void *pvNativeRelative)
    659660{
    660661    /*
     
    704705RTDECL(int) RTDirOpenFiltered(PRTDIR *ppDir, const char *pszPath, RTDIRFILTER enmFilter, uint32_t fFlags)
    705706{
    706     return rtDirOpenRelative(ppDir, pszPath, enmFilter, fFlags, ~(uintptr_t)0, NULL);
     707    return rtDirOpenRelativeOrHandle(ppDir, pszPath, enmFilter, fFlags, ~(uintptr_t)0, NULL);
    707708}
    708709
  • trunk/src/VBox/Runtime/r3/generic/dirrel-r3-generic.cpp

    r69705 r69716  
    211211 * @param   fMode           The mode of the new directory.
    212212 * @param   fCreate         Create flags, RTDIRCREATE_FLAGS_XXX.
     213 * @param   phSubDir        Where to return the handle of the created directory.
     214 *                          Optional.
    213215 *
    214216 * @sa      RTDirCreate
    215217 */
    216 RTDECL(int) RTDirRelDirCreate(PRTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate)
    217 {
    218     PRTDIR pThis = hDir;
    219     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    220     AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
    221 
    222     char szPath[RTPATH_MAX];
    223     int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
    224     if (RT_SUCCESS(rc))
     218RTDECL(int) RTDirRelDirCreate(PRTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate, PRTDIR *phSubDir)
     219{
     220    PRTDIR pThis = hDir;
     221    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     222    AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
     223
     224    char szPath[RTPATH_MAX];
     225    int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
     226    if (RT_SUCCESS(rc))
     227    {
    225228        rc = RTDirCreate(szPath, fMode, fCreate);
     229        if (RT_SUCCESS(rc) && phSubDir)
     230            rc = RTDirOpen(phSubDir, szPath);
     231    }
    226232    return rc;
    227233}
  • trunk/src/VBox/Runtime/r3/nt/direnum-r3-nt.cpp

    r69705 r69716  
    106106    bool fObjDir = false;
    107107#endif
    108     if (pvNativeRelative == NULL)
     108    if (hRelativeDir == ~(uintptr_t)0 && pvNativeRelative == NULL)
    109109        rc = RTNtPathOpenDir(pszPathBuf,
    110110                             FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE,
     
    119119#endif
    120120                             );
    121     else
     121    else if (pvNativeRelative != NULL)
    122122        rc = RTNtPathOpenDirEx((HANDLE)hRelativeDir,
    123123                               (struct _UNICODE_STRING *)pvNativeRelative,
     
    134134
    135135                               );
     136    else
     137    {
     138        pDir->hDir = (HANDLE)hRelativeDir;
     139        rc = VINF_SUCCESS;
     140    }
    136141    if (RT_SUCCESS(rc))
    137142    {
  • trunk/src/VBox/Runtime/r3/nt/dirrel-r3-nt.cpp

    r69705 r69716  
    210210    if (RT_SUCCESS(rc))
    211211    {
    212         rc = rtDirOpenRelative(phDir, pszDirAndFilter, enmFilter, fFlags, (uintptr_t)hRoot, &NtName);
     212        rc = rtDirOpenRelativeOrHandle(phDir, pszDirAndFilter, enmFilter, fFlags, (uintptr_t)hRoot, &NtName);
    213213        RTNtPathFree(&NtName, NULL);
    214214    }
     
    225225 * @param   fMode           The mode of the new directory.
    226226 * @param   fCreate         Create flags, RTDIRCREATE_FLAGS_XXX.
     227 * @param   phSubDir        Where to return the handle of the created directory.
     228 *                          Optional.
    227229 *
    228230 * @sa      RTDirCreate
    229231 */
    230 RTDECL(int) RTDirRelDirCreate(PRTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate)
    231 {
    232     PRTDIR pThis = hDir;
    233     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    234     AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
    235 
    236     char szPath[RTPATH_MAX];
    237     int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
    238     if (RT_SUCCESS(rc))
    239     {
    240 RTAssertMsg2("DBG: RTDirRelDirCreate(%s)...\n", szPath);
    241         rc = RTDirCreate(szPath, fMode, fCreate);
     232RTDECL(int) RTDirRelDirCreate(PRTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate, PRTDIR *phSubDir)
     233{
     234    PRTDIR pThis = hDir;
     235    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     236    AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
     237    AssertReturn(!(fCreate & ~RTDIRCREATE_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
     238    fMode = rtFsModeNormalize(fMode, pszRelPath, 0);
     239    AssertReturn(rtFsModeIsValidPermissions(fMode), VERR_INVALID_FMODE);
     240    AssertPtrNullReturn(phSubDir, VERR_INVALID_POINTER);
     241
     242    /*
     243     * Convert and normalize the path.
     244     */
     245    UNICODE_STRING NtName;
     246    HANDLE hRoot = pThis->hDir;
     247    int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
     248                                      pThis->enmInfoClass == FileMaximumInformation);
     249    if (RT_SUCCESS(rc))
     250    {
     251        HANDLE              hNewDir = RTNT_INVALID_HANDLE_VALUE;
     252        IO_STATUS_BLOCK     Ios     = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     253        OBJECT_ATTRIBUTES   ObjAttr;
     254        InitializeObjectAttributes(&ObjAttr, &NtName, 0 /*fAttrib*/, hRoot, NULL);
     255
     256        ULONG fDirAttribs = (fCreate & RTFS_DOS_MASK_NT) >> RTFS_DOS_SHIFT;
     257        if (!(fCreate & RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_DONT_SET))
     258            fDirAttribs |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
     259        if (!fDirAttribs)
     260            fDirAttribs = RTFS_DOS_NT_NORMAL;
     261
     262        NTSTATUS rcNt = NtCreateFile(&hNewDir,
     263                                     phSubDir
     264                                     ? FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE
     265                                     : SYNCHRONIZE,
     266                                     &ObjAttr,
     267                                     &Ios,
     268                                     NULL /*AllocationSize*/,
     269                                     fDirAttribs,
     270                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
     271                                     FILE_CREATE,
     272                                     FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     273                                     NULL /*EaBuffer*/,
     274                                     0 /*EaLength*/);
     275        if (NT_SUCCESS(rcNt))
     276        {
     277            if (!phSubDir)
     278            {
     279                NtClose(hNewDir);
     280                rc = VINF_SUCCESS;
     281            }
     282            else
     283            {
     284                rc = rtDirOpenRelativeOrHandle(phSubDir, pszRelPath, RTDIRFILTER_NONE, 0 /*fFlags*/,
     285                                               (uintptr_t)hNewDir, NULL /*pvNativeRelative*/);
     286                if (RT_FAILURE(rc))
     287                    NtClose(hNewDir);
     288            }
     289        }
     290        else
     291            rc = RTErrConvertFromNtStatus(rcNt);
     292        RTNtPathFree(&NtName, NULL);
    242293    }
    243294    return rc;
     
    259310    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    260311    AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
     312
    261313
    262314    char szPath[RTPATH_MAX];
  • trunk/src/VBox/Runtime/tools/Makefile.kmk

    r69603 r69716  
    113113 endif
    114114
     115 # RTMkDir - our mkdir clone.
     116 PROGRAMS += RTMkDir
     117 RTMkDir_TEMPLATE = VBoxR3Tool
     118 RTMkDir_SOURCES = RTMkDir.cpp
     119
    115120 # RTShutdown - similar (but not identical) to a typical unix shutdown command.
    116121 PROGRAMS += RTShutdown
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