VirtualBox

Ignore:
Timestamp:
Nov 24, 2017 8:00:38 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119261
Message:

IPRT/VFS: Reimplemented RTVfsDirCreate, RTVfsDirOpenFile and RTVfsFileOpen to use pfnOpen, making pfnCreateDir and pfnOpenFile optional. Could of fixes for previous changes.

File:
1 edited

Legend:

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

    r69828 r69830  
    25682568                   back on pfnOpen in case of symbolic links that needs following. */
    25692569                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
    2570                 if (pVfsParentDir->pOps->pfnQueryEntryInfo)
     2570                if (pVfsParentDir->pOps->pfnOpenDir)
    25712571                {
    25722572                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
    25732573                    rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
    25742574                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
    2575                     if (RT_SUCCESS(rc)
     2575                    if (   RT_SUCCESS(rc)
    25762576                        || (   rc != VERR_NOT_A_DIRECTORY
    25772577                            && rc != VERR_IS_A_SYMLINK))
     
    26372637         */
    26382638        RTVFSDIRINTERNAL *pVfsParentDir;
    2639         rc = rtVfsDirTraverseToParent(pThis, pPath, (fFlags & RTPATH_F_NO_SYMLINKS) | RTPATH_F_ON_LINK, &pVfsParentDir);
     2639        uint32_t const    fTraverse = (fFlags & RTPATH_F_NO_SYMLINKS) | RTPATH_F_ON_LINK;
     2640        rc = rtVfsDirTraverseToParent(pThis, pPath, fTraverse, &pVfsParentDir);
    26402641        if (RT_SUCCESS(rc))
    26412642        {
     
    26442645             */
    26452646            uint64_t fOpenFlags = RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN;
    2646             uint32_t fObjFlags  = RTVFSOBJ_F_OPEN_DIRECTORY | RTVFSOBJ_F_OPEN_SYMLINK | RTVFSOBJ_F_CREATE_NOTHING;
     2647            uint32_t fObjFlags  = RTVFSOBJ_F_OPEN_DIRECTORY | RTVFSOBJ_F_OPEN_SYMLINK | RTVFSOBJ_F_CREATE_NOTHING | fTraverse;
    26472648            for (uint32_t cLoops = 1; ; cLoops++)
    26482649            {
     
    26502651                   back on pfnOpen in case of symbolic links that needs following. */
    26512652                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
    2652                 if (pVfsParentDir->pOps->pfnQueryEntryInfo)
     2653                if (pVfsParentDir->pOps->pfnOpenDir)
    26532654                {
    26542655                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
    26552656                    rc = pVfsParentDir->pOps->pfnOpenDir(pVfsParentDir->Base.pvThis, pszEntryName, fFlags, phVfsDir);
    26562657                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
    2657                     if (RT_SUCCESS(rc)
     2658                    if (   RT_SUCCESS(rc)
    26582659                        || (   rc != VERR_NOT_A_DIRECTORY
    26592660                            && rc != VERR_IS_A_SYMLINK))
     
    26802681                /* Follow symbolic link. */
    26812682                if (cLoops < RTVFS_MAX_LINKS)
    2682                     rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fObjFlags & RTPATH_F_MASK);
     2683                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fTraverse);
    26832684                else
    26842685                    rc = VERR_TOO_MANY_SYMLINKS;
     
    27182719    if (RT_SUCCESS(rc))
    27192720    {
    2720         if (pPath->cComponents > 0)
     2721        /*
     2722         * Tranverse the path, resolving the parent node.
     2723         * We'll do the symbolic link checking here with help of pfnOpen/pfnOpenDir.
     2724         */
     2725        RTVFSDIRINTERNAL *pVfsParentDir;
     2726        uint32_t          fTraverse = (fFlags & RTDIRCREATE_FLAGS_NO_SYMLINKS ? RTPATH_F_NO_SYMLINKS : 0) | RTPATH_F_ON_LINK;
     2727        rc = rtVfsDirTraverseToParent(pThis, pPath, fTraverse, &pVfsParentDir);
     2728        if (RT_SUCCESS(rc))
    27212729        {
    27222730            /*
    2723              * Tranverse the path, resolving the parent node, not checking for symbolic
    2724              * links in the final element, and ask the directory to create the subdir.
     2731             * Do the opening.  Loop if we need to follow symbolic links.
    27252732             */
    2726             RTVFSDIRINTERNAL *pVfsParentDir;
    2727             rc = rtVfsDirTraverseToParent(pThis, pPath,
    2728                                             fFlags & RTDIRCREATE_FLAGS_NO_SYMLINKS
    2729                                           ? RTPATH_F_NO_SYMLINKS | RTPATH_F_ON_LINK : RTPATH_F_FOLLOW_LINK,
    2730                                           &pVfsParentDir);
    2731             if (RT_SUCCESS(rc))
     2733            uint64_t fOpenFlags = RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_CREATE
     2734                                | ((fMode << RTFILE_O_CREATE_MODE_SHIFT) & RTFILE_O_CREATE_MODE_MASK);
     2735            uint32_t fObjFlags  = RTVFSOBJ_F_OPEN_SYMLINK | RTVFSOBJ_F_CREATE_DIRECTORY | fTraverse;
     2736            for (uint32_t cLoops = 1; ; cLoops++)
    27322737            {
     2738                /* Do the querying.  If pfnOpenDir is available, we use it first, falling
     2739                   back on pfnOpen in case of symbolic links that needs following. */
    27332740                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
    2734 
     2741                if (pVfsParentDir->pOps->pfnCreateDir)
     2742                {
     2743                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
     2744                    rc = pVfsParentDir->pOps->pfnCreateDir(pVfsParentDir->Base.pvThis, pszEntryName, fMode, phVfsDir);
     2745                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
     2746                    if (   RT_SUCCESS(rc)
     2747                        || (   rc != VERR_NOT_A_DIRECTORY
     2748                            && rc != VERR_IS_A_SYMLINK))
     2749                        break;
     2750                }
     2751
     2752                RTVFSOBJ hVfsObj;
    27352753                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
    2736                 rc = pVfsParentDir->pOps->pfnCreateDir(pVfsParentDir->Base.pvThis, pszEntryName, fMode, phVfsDir);
     2754                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, fOpenFlags, fObjFlags, &hVfsObj);
    27372755                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
    2738 
    2739                 RTVfsDirRelease(pVfsParentDir);
    2740 
    2741                 if (RT_SUCCESS(rc) && phVfsDir)
     2756                if (RT_FAILURE(rc))
     2757                    break;
     2758
     2759                /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */
     2760                if (   !(fObjFlags & RTPATH_F_FOLLOW_LINK)
     2761                    || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
    27422762                {
    2743                     AssertPtr(*phVfsDir);
    2744                     Assert((*phVfsDir)->uMagic == RTVFSDIR_MAGIC);
     2763                    if (phVfsDir)
     2764                    {
     2765                        *phVfsDir = RTVfsObjToDir(hVfsObj);
     2766                        AssertStmt(*phVfsDir != NIL_RTVFSDIR, rc = VERR_INTERNAL_ERROR_3);
     2767                    }
     2768                    RTVfsObjRelease(hVfsObj);
     2769                    break;
    27452770                }
     2771
     2772                /* Follow symbolic link. */
     2773                if (cLoops < RTVFS_MAX_LINKS)
     2774                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fTraverse);
     2775                else
     2776                    rc = VERR_TOO_MANY_SYMLINKS;
     2777                RTVfsObjRelease(hVfsObj);
     2778                if (RT_FAILURE(rc))
     2779                    break;
    27462780            }
     2781            RTVfsDirRelease(pVfsParentDir);
    27472782        }
    2748         else
    2749             rc = VERR_PATH_ZERO_LENGTH;
    27502783        RTVfsParsePathFree(pPath);
    27512784    }
     
    27702803
    27712804    /*
    2772      * Parse the relative path.
     2805     * Parse the path, it's always relative to the given directory.
    27732806     */
    27742807    PRTVFSPARSEDPATH pPath;
     
    27762809    if (RT_SUCCESS(rc))
    27772810    {
    2778         if (pPath->cComponents > 0)
     2811        /*
     2812         * Tranverse the path, resolving the parent node.
     2813         * We'll do the symbolic link checking here with help of pfnOpen/pfnOpenFile.
     2814         */
     2815        RTVFSDIRINTERNAL *pVfsParentDir;
     2816        uint32_t const    fTraverse = (fOpen & RTFILE_O_NO_SYMLINKS ? RTPATH_F_NO_SYMLINKS : 0) | RTPATH_F_ON_LINK;
     2817        rc = rtVfsDirTraverseToParent(pThis, pPath, fTraverse, &pVfsParentDir);
     2818        if (RT_SUCCESS(rc))
    27792819        {
     2820            /** @todo join path with RTVfsFileOpen.   */
     2821
    27802822            /*
    2781              * Tranverse the path, resolving the parent node and any symlinks
    2782              * in the final element, and ask the directory to open the file.
     2823             * Do the opening.  Loop if we need to follow symbolic links.
    27832824             */
    2784             RTVFSDIRINTERNAL *pVfsParentDir;
    2785             rc = rtVfsDirTraverseToParent(pThis, pPath,
    2786                                           (fOpen & RTFILE_O_NO_SYMLINKS ? RTPATH_F_NO_SYMLINKS : 0) | RTPATH_F_FOLLOW_LINK,
    2787                                           &pVfsParentDir);
    2788             if (RT_SUCCESS(rc))
     2825            bool     fDirSlash = pPath->fDirSlash;
     2826
     2827            uint32_t fObjFlags = RTVFSOBJ_F_OPEN_ANY_FILE | RTVFSOBJ_F_OPEN_SYMLINK;
     2828            if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE
     2829                || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
     2830                fObjFlags |= RTVFSOBJ_F_CREATE_FILE;
     2831            else
     2832                fObjFlags |= RTVFSOBJ_F_CREATE_NOTHING;
     2833            fObjFlags  |= fTraverse & RTPATH_F_MASK;
     2834
     2835            for (uint32_t cLoops = 1;; cLoops++)
    27892836            {
     2837                /* Do the querying.  If pfnOpenFile is available, we use it first, falling
     2838                   back on pfnOpen in case of symbolic links that needs following or we got
     2839                   a trailing directory slash (to get file-not-found error). */
    27902840                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
    2791 
    2792                 if (   pVfsParentDir->pOps->pfnOpenFile == NULL
    2793                     || pPath->fDirSlash)
     2841                if (   pVfsParentDir->pOps->pfnOpenFile
     2842                    && !fDirSlash)
    27942843                {
    2795                     RTVFSOBJ hVfsObj;
    2796                     RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
    2797                     rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, fOpen,
    2798                                                       RTVFSOBJ_F_OPEN_ANY_FILE | RTVFSOBJ_F_CREATE_FILE
    2799                                                       | RTPATH_F_FOLLOW_LINK, &hVfsObj);
    2800                     RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
    2801                     if (RT_SUCCESS(rc))
    2802                     {
    2803                         if (RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
    2804                             *phVfsFile = RTVfsObjToFile(hVfsObj);
    2805                         else
    2806                         {
    2807                             /** @todo parse symbolic links. */
    2808                             AssertFailed();
    2809                             rc = VERR_NOT_IMPLEMENTED;
    2810                         }
    2811                         RTVfsObjRelease(hVfsObj);
    2812                     }
     2844                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
     2845                    rc = pVfsParentDir->pOps->pfnOpenFile(pVfsParentDir->Base.pvThis, pszEntryName, fOpen, phVfsFile);
     2846                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
     2847                    if (   RT_SUCCESS(rc)
     2848                        || (   rc != VERR_NOT_A_FILE
     2849                            && rc != VERR_IS_A_SYMLINK))
     2850                        break;
    28132851                }
     2852
     2853                RTVFSOBJ hVfsObj;
     2854                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
     2855                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, fOpen, fObjFlags, &hVfsObj);
     2856                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
     2857                if (RT_FAILURE(rc))
     2858                    break;
     2859
     2860                /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */
     2861                if (   !(fObjFlags & RTPATH_F_FOLLOW_LINK)
     2862                    || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
     2863                {
     2864                    *phVfsFile = RTVfsObjToFile(hVfsObj);
     2865                    AssertStmt(*phVfsFile != NIL_RTVFSFILE, rc = VERR_INTERNAL_ERROR_3);
     2866                    RTVfsObjRelease(hVfsObj);
     2867                    break;
     2868                }
     2869
     2870                /* Follow symbolic link. */
     2871                if (cLoops < RTVFS_MAX_LINKS)
     2872                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fTraverse);
    28142873                else
    2815                 {
    2816                     /** @todo there is a symlink creation race here. */
    2817                     RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
    2818                     rc = pVfsParentDir->pOps->pfnOpenFile(pVfsParentDir->Base.pvThis, pszEntryName, fOpen, phVfsFile);
    2819                     RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
    2820                 }
    2821 
    2822                 if (RT_SUCCESS(rc))
    2823                 {
    2824                     AssertPtr(*phVfsFile);
    2825                     Assert((*phVfsFile)->uMagic == RTVFSFILE_MAGIC);
    2826                 }
    2827 
    2828                 RTVfsDirRelease(pVfsParentDir);
     2874                    rc = VERR_TOO_MANY_SYMLINKS;
     2875                RTVfsObjRelease(hVfsObj);
     2876                if (RT_FAILURE(rc))
     2877                    break;
     2878                fDirSlash |= pPath->fDirSlash;
    28292879            }
     2880            RTVfsDirRelease(pVfsParentDir);
    28302881        }
    2831         else
    2832             rc = VERR_NOT_A_FILE;
    28332882        RTVfsParsePathFree(pPath);
    28342883    }
     
    37573806    if (RT_SUCCESS(rc))
    37583807    {
    3759         if (   !pPath->fDirSlash
    3760             && pPath->cComponents > 0)
     3808        /*
     3809         * Tranverse the path, resolving the parent node.
     3810         * We'll do the symbolic link checking here with help of pfnOpen/pfnOpenFile.
     3811         */
     3812        RTVFSDIRINTERNAL *pVfsParentDir;
     3813        uint32_t const    fTraverse = (fOpen & RTFILE_O_NO_SYMLINKS ? RTPATH_F_NO_SYMLINKS : 0) | RTPATH_F_ON_LINK;
     3814        rc = rtVfsTraverseToParent(pThis, pPath, fTraverse, &pVfsParentDir);
     3815        if (RT_SUCCESS(rc))
    37613816        {
     3817            /** @todo join path with RTVfsDirOpenFile.   */
    37623818            /*
    3763              * Tranverse the path, resolving the parent node and any symlinks
    3764              * in the final element, and ask the directory to open the file.
     3819             * Do the opening.  Loop if we need to follow symbolic links.
    37653820             */
    3766             RTVFSDIRINTERNAL *pVfsParentDir;
    3767             rc = rtVfsTraverseToParent(pThis, pPath, RTPATH_F_FOLLOW_LINK, &pVfsParentDir);
    3768             if (RT_SUCCESS(rc))
     3821            bool     fDirSlash = pPath->fDirSlash;
     3822
     3823            uint32_t fObjFlags = RTVFSOBJ_F_OPEN_ANY_FILE | RTVFSOBJ_F_OPEN_SYMLINK;
     3824            if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE
     3825                || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
     3826                fObjFlags |= RTVFSOBJ_F_CREATE_FILE;
     3827            else
     3828                fObjFlags |= RTVFSOBJ_F_CREATE_NOTHING;
     3829            fObjFlags  |= fTraverse & RTPATH_F_MASK;
     3830
     3831            for (uint32_t cLoops = 1;; cLoops++)
    37693832            {
     3833                /* Do the querying.  If pfnOpenFile is available, we use it first, falling
     3834                   back on pfnOpen in case of symbolic links that needs following or we got
     3835                   a trailing directory slash (to get file-not-found error). */
    37703836                const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]];
    3771 
    3772                 /** @todo there is a symlink creation race here. */
     3837                if (   pVfsParentDir->pOps->pfnOpenFile
     3838                    && !fDirSlash)
     3839                {
     3840                    RTVfsLockAcquireRead(pVfsParentDir->Base.hLock);
     3841                    rc = pVfsParentDir->pOps->pfnOpenFile(pVfsParentDir->Base.pvThis, pszEntryName, fOpen, phVfsFile);
     3842                    RTVfsLockReleaseRead(pVfsParentDir->Base.hLock);
     3843                    if (   RT_SUCCESS(rc)
     3844                        || (   rc != VERR_NOT_A_FILE
     3845                            && rc != VERR_IS_A_SYMLINK))
     3846                        break;
     3847                }
     3848
     3849                RTVFSOBJ hVfsObj;
    37733850                RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock);
    3774                 rc = pVfsParentDir->pOps->pfnOpenFile(pVfsParentDir->Base.pvThis, pszEntryName, fOpen, phVfsFile);
     3851                rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, fOpen, fObjFlags, &hVfsObj);
    37753852                RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock);
    3776 
    3777                 RTVfsDirRelease(pVfsParentDir);
    3778 
    3779                 if (RT_SUCCESS(rc))
     3853                if (RT_FAILURE(rc))
     3854                    break;
     3855
     3856                /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */
     3857                if (   !(fObjFlags & RTPATH_F_FOLLOW_LINK)
     3858                    || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK)
    37803859                {
    3781                     AssertPtr(*phVfsFile);
    3782                     Assert((*phVfsFile)->uMagic == RTVFSFILE_MAGIC);
     3860                    *phVfsFile = RTVfsObjToFile(hVfsObj);
     3861                    AssertStmt(*phVfsFile != NIL_RTVFSFILE, rc = VERR_INTERNAL_ERROR_3);
     3862                    RTVfsObjRelease(hVfsObj);
     3863                    break;
    37833864                }
     3865
     3866                /* Follow symbolic link. */
     3867                if (cLoops < RTVFS_MAX_LINKS)
     3868                    rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fTraverse);
     3869                else
     3870                    rc = VERR_TOO_MANY_SYMLINKS;
     3871                RTVfsObjRelease(hVfsObj);
     3872                if (RT_FAILURE(rc))
     3873                    break;
     3874                fDirSlash |= pPath->fDirSlash;
    37843875            }
     3876            RTVfsDirRelease(pVfsParentDir);
    37853877        }
    3786         else
    3787             rc = VERR_NOT_A_FILE;
    37883878        RTVfsParsePathFree(pPath);
    37893879    }
    37903880    return rc;
     3881
    37913882}
    37923883
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