VirtualBox

Ignore:
Timestamp:
Nov 28, 2017 7:01:35 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119307
Message:

iprt/formats/ntfs: updates

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

Legend:

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

    r69844 r69861  
    30083008    if (RT_SUCCESS(rc))
    30093009    {
    3010         if (pPath->cComponents > 0)
     3010        /*
     3011         * Tranverse the path, resolving the parent node.
     3012         * We'll do the symbolic link checking here with help of pfnOpen.
     3013         */
     3014        RTVFSDIRINTERNAL *pVfsParentDir;
     3015        rc = rtVfsDirTraverseToParent(pThis, pPath, (fFlags & RTPATH_F_NO_SYMLINKS) | RTPATH_F_ON_LINK, &pVfsParentDir);
     3016        if (RT_SUCCESS(rc))
    30113017        {
    3012             RTVFSDIRINTERNAL *pVfsParentDir;
    3013             rc = rtVfsDirTraverseToParent(pThis, pPath, fFlags, &pVfsParentDir);
    3014             if (RT_SUCCESS(rc))
     3018            /*
     3019             * Do the opening.  Loop if we need to follow symbolic links.
     3020             */
     3021            uint32_t fObjFlags = RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING;
     3022            for (uint32_t cLoops = 1;; cLoops++)
    30153023            {
    3016                 /*
    3017                  * Call the query method on the parent directory.
    3018                  */
    3019                 /** @todo symlink race condition here :/ */
     3024                /* If we end with a directory slash, adjust open flags. */
     3025                if (pPath->fDirSlash)
     3026                {
     3027                    fObjFlags &= ~RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_OPEN_DIRECTORY;
     3028                    if ((fObjFlags & RTVFSOBJ_F_CREATE_MASK) != RTVFSOBJ_F_CREATE_DIRECTORY)
     3029                        fObjFlags = (fObjFlags & ~RTVFSOBJ_F_CREATE_MASK) | RTVFSOBJ_F_CREATE_NOTHING;
     3030                }
     3031                if (fObjFlags & RTPATH_F_FOLLOW_LINK)
     3032                    fObjFlags |= RTVFSOBJ_F_OPEN_SYMLINK;
     3033
     3034                /* Do the querying.  If pfnQueryEntryInfo is available, we use it first,
     3035                   falling back on pfnOpen in case of symbolic links that needs following. */
    30203036                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
    3021                 RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
    3022                 rc = pVfsParentDir->pOps->pfnQueryEntryInfo(pVfsParentDir->Base.pvThis, pszEntryName, pObjInfo, enmAddAttr);
    3023                 RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
    3024 
    3025                 RTVfsDirRelease(pVfsParentDir);
     3037                if (pVfsParentDir->pOps->pfnQueryEntryInfo)
     3038                {
     3039                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
     3040                    rc = pVfsParentDir->pOps->pfnQueryEntryInfo(pVfsParentDir->Base.pvThis, pszEntryName, pObjInfo, enmAddAttr);
     3041                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
     3042                    if (RT_FAILURE(rc))
     3043                        break;
     3044                    if (   !RTFS_IS_SYMLINK(pObjInfo->Attr.fMode)
     3045                        || !(fFlags & RTPATH_F_FOLLOW_LINK))
     3046                    {
     3047                        if (   (fObjFlags & RTVFSOBJ_F_OPEN_MASK) != RTVFSOBJ_F_OPEN_ANY
     3048                            && RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode))
     3049                            rc = VERR_NOT_A_DIRECTORY;
     3050                        break;
     3051                    }
     3052                }
     3053
     3054                RTVFSOBJ hVfsObj;
     3055                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
     3056                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName,
     3057                                                  RTFILE_O_ACCESS_ATTR_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
     3058                                                  fObjFlags, &hVfsObj);
     3059                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
     3060                if (RT_FAILURE(rc))
     3061                    break;
     3062
     3063                /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */
     3064                if (   !(fObjFlags & RTPATH_F_FOLLOW_LINK)
     3065                    || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
     3066                {
     3067                    rc = RTVfsObjQueryInfo(hVfsObj, pObjInfo, enmAddAttr);
     3068                    RTVfsObjRelease(hVfsObj);
     3069                    break;
     3070                }
     3071
     3072                /* Follow symbolic link. */
     3073                if (cLoops < RTVFS_MAX_LINKS)
     3074                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fObjFlags & RTPATH_F_MASK);
     3075                else
     3076                    rc = VERR_TOO_MANY_SYMLINKS;
     3077                RTVfsObjRelease(hVfsObj);
     3078                if (RT_FAILURE(rc))
     3079                    break;
    30263080            }
    3027             else
    3028                 rc = VERR_INVALID_PARAMETER;
    3029         }
    3030         /*
    3031          * The path boils down to '.' so just query the directory.
    3032          */
    3033         else
    3034         {
    3035             RTVfsLockAcquireRead(pThis->Base.hLock);
    3036             rc = pThis->Base.pOps->pfnQueryInfo(pThis->Base.pvThis, pObjInfo, enmAddAttr);
    3037             RTVfsLockReleaseRead(pThis->Base.hLock);
     3081
     3082            RTVfsDirRelease(pVfsParentDir);
    30383083        }
    30393084        RTVfsParsePathFree(pPath);
  • trunk/src/VBox/Runtime/common/vfs/vfsmount.cpp

    r69853 r69861  
    3535#include <iprt/assert.h>
    3636#include <iprt/err.h>
     37#include <iprt/file.h>
    3738#include <iprt/fsvfs.h>
    3839#include <iprt/mem.h>
    3940#include <iprt/log.h>
    4041#include <iprt/string.h>
     42#include <iprt/vfslowlevel.h>
    4143
    4244#include <iprt/formats/fat.h>
     
    422424
    423425    if (rtVfsMountIsNtfs(&pBuf->Bootsector))
    424         return RTERRINFO_LOG_SET(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT, "NTFS not yet supported");
     426        return RTFsNtfsVolOpen(hVfsFileIn, fFlags, 0 /*fNtfsFlags*/, phVfs, pErrInfo);
    425427
    426428    if (rtVfsMountIsHpfs(&pBuf->Bootsector, hVfsFileIn, pBuf2))
     
    462464}
    463465
     466
     467/**
     468 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnValidate}
     469 */
     470static DECLCALLBACK(int) rtVfsChainMountVol_Validate(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec,
     471                                                     PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError, PRTERRINFO pErrInfo)
     472{
     473    RT_NOREF(pProviderReg);
     474
     475    /*
     476     * Basic checks.
     477     */
     478    if (pElement->enmTypeIn != RTVFSOBJTYPE_FILE)
     479        return pElement->enmTypeIn == RTVFSOBJTYPE_INVALID ? VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT : VERR_VFS_CHAIN_TAKES_FILE;
     480    if (   pElement->enmType != RTVFSOBJTYPE_VFS
     481        && pElement->enmType != RTVFSOBJTYPE_DIR)
     482        return VERR_VFS_CHAIN_ONLY_DIR_OR_VFS;
     483    if (pElement->cArgs > 1)
     484        return VERR_VFS_CHAIN_AT_MOST_ONE_ARG;
     485
     486    /*
     487     * Parse the flag if present, save in pElement->uProvider.
     488     */
     489    bool fReadOnly = (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ;
     490    if (pElement->cArgs > 0)
     491    {
     492        const char *psz = pElement->paArgs[0].psz;
     493        if (*psz)
     494        {
     495            if (!strcmp(psz, "ro"))
     496                fReadOnly = true;
     497            else if (!strcmp(psz, "rw"))
     498                fReadOnly = false;
     499            else
     500            {
     501                *poffError = pElement->paArgs[0].offSpec;
     502                return RTErrInfoSet(pErrInfo, VERR_VFS_CHAIN_INVALID_ARGUMENT, "Expected 'ro' or 'rw' as argument");
     503            }
     504        }
     505    }
     506
     507    pElement->uProvider = fReadOnly ? RTVFSMNT_F_READ_ONLY : 0;
     508    return VINF_SUCCESS;
     509}
     510
     511
     512/**
     513 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate}
     514 */
     515static DECLCALLBACK(int) rtVfsChainMountVol_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec,
     516                                                        PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj,
     517                                                        PRTVFSOBJ phVfsObj, uint32_t *poffError, PRTERRINFO pErrInfo)
     518{
     519    RT_NOREF(pProviderReg, pSpec, poffError);
     520
     521    int         rc;
     522    RTVFSFILE   hVfsFileIn = RTVfsObjToFile(hPrevVfsObj);
     523    if (hVfsFileIn != NIL_RTVFSFILE)
     524    {
     525        RTVFS hVfs;
     526        rc = RTVfsMountVol(hVfsFileIn, (uint32_t)pElement->uProvider, &hVfs, pErrInfo);
     527        RTVfsFileRelease(hVfsFileIn);
     528        if (RT_SUCCESS(rc))
     529        {
     530            *phVfsObj = RTVfsObjFromVfs(hVfs);
     531            RTVfsRelease(hVfs);
     532            if (*phVfsObj != NIL_RTVFSOBJ)
     533                return VINF_SUCCESS;
     534            rc = VERR_VFS_CHAIN_CAST_FAILED;
     535        }
     536    }
     537    else
     538        rc = VERR_VFS_CHAIN_CAST_FAILED;
     539    return rc;
     540}
     541
     542
     543/**
     544 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnCanReuseElement}
     545 */
     546static DECLCALLBACK(bool) rtVfsChainMountVol_CanReuseElement(PCRTVFSCHAINELEMENTREG pProviderReg,
     547                                                             PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement,
     548                                                             PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement)
     549{
     550    RT_NOREF(pProviderReg, pSpec, pReuseSpec);
     551    if (   pElement->paArgs[0].uProvider == pReuseElement->paArgs[0].uProvider
     552        || !pReuseElement->paArgs[0].uProvider)
     553        return true;
     554    return false;
     555}
     556
     557
     558/** VFS chain element 'file'. */
     559static RTVFSCHAINELEMENTREG g_rtVfsChainMountVolReg =
     560{
     561    /* uVersion = */            RTVFSCHAINELEMENTREG_VERSION,
     562    /* fReserved = */           0,
     563    /* pszName = */             "mount",
     564    /* ListEntry = */           { NULL, NULL },
     565    /* pszHelp = */             "Open a file system, requires a file object on the left side.\n"
     566                                "First argument is an optional 'ro' (read-only) or 'rw' (read-write) flag.\n",
     567    /* pfnValidate = */         rtVfsChainMountVol_Validate,
     568    /* pfnInstantiate = */      rtVfsChainMountVol_Instantiate,
     569    /* pfnCanReuseElement = */  rtVfsChainMountVol_CanReuseElement,
     570    /* uEndMarker = */          RTVFSCHAINELEMENTREG_VERSION
     571};
     572
     573RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainMountVolReg, rtVfsChainMountVolReg);
     574
Note: See TracChangeset for help on using the changeset viewer.

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