VirtualBox

Changeset 76589 in vbox for trunk


Ignore:
Timestamp:
Jan 1, 2019 8:56:07 AM (6 years ago)
Author:
vboxsync
Message:

IPRT: Attempted to address some the more obvious shortcomings of RTPathCalcRelative. Had to add a parameter that clearifies whether the from path is a file (VHD usage) or directory (rest).

Location:
trunk
Files:
6 edited

Legend:

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

    r76585 r76589  
    10861086 *                          terminator included.
    10871087 * @param   pszPathFrom     The path to start from creating the relative path.
     1088 * @param   fFromFile       Whether @a pszPathFrom is a file and we should work
     1089 *                          relative to it's parent directory (@c true), or if
     1090 *                          we should assume @a pszPathFrom is a directory and
     1091 *                          work relative to it.
    10881092 * @param   pszPathTo       The path to reach with the created relative path.
    10891093 */
    1090 RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst,
    1091                                const char *pszPathFrom,
    1092                                const char *pszPathTo);
     1094RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst, const char *pszPathFrom, bool fFromFile, const char *pszPathTo);
    10931095
    10941096#ifdef IN_RING3
  • trunk/src/VBox/Runtime/common/path/RTPathCalcRelative.cpp

    r76553 r76589  
    3131#include "internal/iprt.h"
    3232#include <iprt/path.h>
     33
    3334#include <iprt/assert.h>
     35#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
     36# include <iprt/ctype.h>
     37#endif
    3438#include <iprt/err.h>
    3539#include <iprt/string.h>
     
    3943
    4044RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst,
    41                                const char *pszPathFrom,
     45                               const char *pszPathFrom, bool fFromFile,
    4246                               const char *pszPathTo)
    4347{
    44     int rc = VINF_SUCCESS;
    45 
    4648    AssertPtrReturn(pszPathDst, VERR_INVALID_POINTER);
    4749    AssertReturn(cbPathDst, VERR_INVALID_PARAMETER);
    4850    AssertPtrReturn(pszPathFrom, VERR_INVALID_POINTER);
    4951    AssertPtrReturn(pszPathTo, VERR_INVALID_POINTER);
    50     AssertReturn(RTPathStartsWithRoot(pszPathFrom), VERR_INVALID_PARAMETER);
    51     AssertReturn(RTPathStartsWithRoot(pszPathTo), VERR_INVALID_PARAMETER);
    52     AssertReturn(RTStrCmp(pszPathFrom, pszPathTo), VERR_INVALID_PARAMETER);
    5352
    5453    /*
    5554     * Check for different root specifiers (drive letters), creating a relative path doesn't work here.
    56      * @todo: How to handle case insensitive root specifiers correctly?
    5755     */
    5856    size_t offRootFrom = rtPathRootSpecLen(pszPathFrom);
     57    AssertReturn(offRootFrom > 0, VERR_INVALID_PARAMETER);
     58
    5959    size_t offRootTo   = rtPathRootSpecLen(pszPathTo);
    60 
    61     if (   offRootFrom != offRootTo
    62         || RTStrNCmp(pszPathFrom, pszPathTo, offRootFrom))
     60    AssertReturn(offRootTo > 0, VERR_INVALID_PARAMETER);
     61
     62
     63    /** @todo correctly deal with extra root slashes! */
     64    if (offRootFrom != offRootTo)
    6365        return VERR_NOT_SUPPORTED;
    6466
    65     /* Filter out the parent path which is equal to both paths. */
    66     while (   *pszPathFrom == *pszPathTo
    67            && *pszPathFrom != '\0'
    68            && *pszPathTo != '\0')
    69     {
    70         pszPathFrom++;
    71         pszPathTo++;
    72     }
     67#if RTPATH_STYLE != RTPATH_STR_F_STYLE_DOS
     68    if (RTStrNCmp(pszPathFrom, pszPathTo, offRootFrom))
     69        return VERR_NOT_SUPPORTED;
     70#else
     71    if (RTStrNICmp(pszPathFrom, pszPathTo, offRootFrom))
     72        for (size_t off = 0; off < offRootFrom; off++)
     73        {
     74            char const chFrom = pszPathFrom[off];
     75            char const chTo   = pszPathTo[off];
     76            if (   chFrom != chTo
     77                && RT_C_TO_LOWER(chFrom) != RT_C_TO_LOWER(chTo) /** @todo proper case insensitivity! */
     78                && (!RTPATH_IS_SLASH(chFrom) || !RTPATH_IS_SLASH(chTo)) )
     79                return VERR_NOT_SUPPORTED;
     80        }
     81#endif
     82
     83    pszPathFrom += offRootFrom;
     84    pszPathTo   += offRootTo;
    7385
    7486    /*
    75      * Because path components can start with an equal string but differ afterwards we
    76      * need to go back to the beginning of the current component.
     87     * Skip out the part of the path which is equal to both.
    7788     */
    78     while (!RTPATH_IS_SEP(*pszPathFrom))
    79         pszPathFrom--;
    80 
    81     pszPathFrom++; /* Skip path separator. */
    82 
    83     while (!RTPATH_IS_SEP(*pszPathTo))
    84         pszPathTo--;
    85 
    86     pszPathTo++; /* Skip path separator. */
     89    const char *pszStartOfFromComp = pszPathFrom;
     90    for (;;)
     91    {
     92        char const chFrom = *pszPathFrom;
     93        char const chTo   = *pszPathTo;
     94        if (!RTPATH_IS_SLASH(chFrom))
     95        {
     96            if (chFrom == chTo)
     97            {
     98                if (chFrom)
     99                { /* likely */ }
     100                else
     101                {
     102                    /* Special case: The two paths are equal. */
     103                    if (fFromFile)
     104                    {
     105                        size_t cchComp = pszPathFrom - pszStartOfFromComp;
     106                        if (cchComp < cbPathDst)
     107                        {
     108                            memcpy(pszPathDst, pszStartOfFromComp, cchComp);
     109                            pszPathDst[cchComp] = '\0';
     110                            return VINF_SUCCESS;
     111                        }
     112                    }
     113                    else if (sizeof(".") <= cbPathDst)
     114                    {
     115                        memcpy(pszPathDst, ".", sizeof("."));
     116                        return VINF_SUCCESS;
     117                    }
     118                    return VERR_BUFFER_OVERFLOW;
     119                }
     120            }
     121#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
     122            else if (RT_C_TO_LOWER(chFrom) == RT_C_TO_LOWER(chTo))
     123            { /* if not likely, then simpler code structure wise. */ }
     124#endif
     125            else if (chFrom != '\0' || !RTPATH_IS_SLASH(chTo) || fFromFile)
     126                break;
     127            else
     128            {
     129                pszStartOfFromComp = pszPathFrom;
     130                do
     131                    pszPathTo++;
     132                while (RTPATH_IS_SLASH(*pszPathTo));
     133                break;
     134            }
     135            pszPathFrom++;
     136            pszPathTo++;
     137        }
     138        else if (RTPATH_IS_SLASH(chTo))
     139        {
     140            /* Both have slashes.  Skip any additional ones before taking down
     141               the start of the component for rewinding purposes. */
     142            do
     143                pszPathTo++;
     144            while (RTPATH_IS_SLASH(*pszPathTo));
     145            do
     146                pszPathFrom++;
     147            while (RTPATH_IS_SLASH(*pszPathFrom));
     148            pszStartOfFromComp = pszPathFrom;
     149        }
     150        else
     151            break;
     152    }
     153
     154    /* Rewind to the start of the current component. */
     155    pszPathTo  -= pszPathFrom - pszStartOfFromComp;
     156    pszPathFrom = pszStartOfFromComp;
    87157
    88158    /* Paths point to the first non equal component now. */
    89     char aszPathTmp[RTPATH_MAX + 1];
    90     unsigned offPathTmp = 0;
     159
     160    /*
     161     * Constructure the relative path.
     162     */
    91163
    92164    /* Create the part to go up from pszPathFrom. */
     165    unsigned offDst = 0;
     166
     167    if (!fFromFile && *pszPathFrom != '\0')
     168    {
     169        if (offDst + 3 < cbPathDst)
     170        {
     171            pszPathDst[offDst++] = '.';
     172            pszPathDst[offDst++] = '.';
     173            pszPathDst[offDst++] = RTPATH_SLASH;
     174        }
     175        else
     176            return VERR_BUFFER_OVERFLOW;
     177    }
     178
    93179    while (*pszPathFrom != '\0')
    94180    {
    95         while (   !RTPATH_IS_SEP(*pszPathFrom)
    96                && *pszPathFrom != '\0')
     181        char ch;
     182        while (   (ch = *pszPathFrom) != '\0'
     183               && !RTPATH_IS_SLASH(*pszPathFrom))
    97184            pszPathFrom++;
    98 
    99         if (RTPATH_IS_SEP(*pszPathFrom))
    100         {
    101             if (offPathTmp + 3 >= sizeof(aszPathTmp) - 1)
    102                 return VERR_FILENAME_TOO_LONG;
    103             aszPathTmp[offPathTmp++] = '.';
    104             aszPathTmp[offPathTmp++] = '.';
    105             aszPathTmp[offPathTmp++] = RTPATH_SLASH;
     185        while (   (ch = *pszPathFrom) != '\0'
     186               && RTPATH_IS_SLASH(ch))
    106187            pszPathFrom++;
    107         }
    108     }
    109 
    110     aszPathTmp[offPathTmp] = '\0';
     188        if (!ch)
     189            break;
     190
     191        if (offDst + 3 < cbPathDst)
     192        {
     193            pszPathDst[offDst++] = '.';
     194            pszPathDst[offDst++] = '.';
     195            pszPathDst[offDst++] = RTPATH_SLASH;
     196        }
     197        else
     198            return VERR_BUFFER_OVERFLOW;
     199    }
    111200
    112201    /* Now append the rest of pszPathTo to the final path. */
    113     char *pszPathTmp = &aszPathTmp[offPathTmp];
    114     size_t cbPathTmp = sizeof(aszPathTmp) - offPathTmp - 1;
    115     rc = RTStrCatP(&pszPathTmp, &cbPathTmp, pszPathTo);
    116     if (RT_SUCCESS(rc))
    117     {
    118         *pszPathTmp = '\0';
    119 
    120         size_t cchPathTmp = strlen(aszPathTmp);
    121         if (cchPathTmp >= cbPathDst)
    122            return VERR_BUFFER_OVERFLOW;
    123         memcpy(pszPathDst, aszPathTmp, cchPathTmp + 1);
    124     }
    125     else
    126         rc = VERR_FILENAME_TOO_LONG;
    127 
    128     return rc;
     202    size_t cchTo = strlen(pszPathTo);
     203    if (offDst + cchTo <= cbPathDst)
     204    {
     205        memcpy(&pszPathDst[offDst], pszPathTo, cchTo);
     206        pszPathDst[offDst + cchTo] = '\0';
     207        return VINF_SUCCESS;
     208    }
     209    return VERR_BUFFER_OVERFLOW;
    129210}
    130211
  • trunk/src/VBox/Runtime/testcase/tstRTPath.cpp

    r76553 r76589  
    742742    {
    743743        const char *pszFrom;
     744        bool fFromFile;
    744745        const char *pszTo;
    745746        int rc;
     
    747748    } s_aRelPath[] =
    748749    {
    749         { "/home/test.ext", "/home/test2.ext", VINF_SUCCESS, "test2.ext"},
    750         { "/dir/test.ext", "/dir/dir2/test2.ext", VINF_SUCCESS, "dir2/test2.ext"},
    751         { "/dir/dir2/test.ext", "/dir/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "test2.ext"},
    752         { "/dir/dir2/test.ext", "/dir/dir3/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext"},
     750        { "/home/test.ext",     true,           "/home/test2.ext",        VINF_SUCCESS, "test2.ext" },
     751        { "/dir/test.ext",      true,           "/dir/dir2/test2.ext",    VINF_SUCCESS, "dir2/test2.ext" },
     752        { "/dir/dir2/test.ext", true,           "/dir/test2.ext",         VINF_SUCCESS, ".." RTPATH_SLASH_STR "test2.ext" },
     753        { "/dir/dir2/test.ext", true,           "/dir/dir3/test2.ext",    VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext" },
     754        { "/dir/dir2",          false,          "/dir/dir3/test2.ext",    VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext" },
     755        { "/dir/dir2",          false,          "/dir/dir3//test2.ext",   VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3//test2.ext" },
     756        { "/dir/dir2/",         false,          "/dir/dir3/test2.ext",    VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext" },
     757        { "/dir/dir2////",      false,          "/dir//dir3/test2.ext",   VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext" },
     758        { "/include/iprt",      false,          "/include/iprt/cdefs.h",  VINF_SUCCESS, "cdefs.h" },
     759        { "/include/iprt/",     false,          "/include/iprt/cdefs.h",  VINF_SUCCESS, "cdefs.h" },
     760        { "/include/iprt/tt.h", true,           "/include/iprt/cdefs.h",  VINF_SUCCESS, "cdefs.h" },
    753761#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
    754         { "\\\\server\\share\\test.ext", "\\\\server\\share2\\test2.ext", VERR_NOT_SUPPORTED, ""},
    755         { "c:\\dir\\test.ext", "f:\\dir\\test.ext", VERR_NOT_SUPPORTED, ""}
     762        { "\\\\server\\share\\test.ext", true,  "\\\\server\\share2\\test2.ext", VERR_NOT_SUPPORTED, "" },
     763        { "c:\\dir\\test.ext",  true,           "f:\\dir\\test.ext",      VERR_NOT_SUPPORTED, "" },
     764        { "F:\\dir\\test.ext",  false,          "f:/dir//test.ext",      VINF_SUCCESS, "." } ,
     765        { "F:\\dir\\test.ext",  true,           "f:/dir//test.ext",      VINF_SUCCESS, "test.ext" } ,
    756766#endif
    757767    };
    758768    for (unsigned i = 0; i < RT_ELEMENTS(s_aRelPath); i++)
    759769    {
    760         const char *pszFrom = s_aRelPath[i].pszFrom;
    761         const char *pszTo   = s_aRelPath[i].pszTo;
    762 
    763         rc = RTPathCalcRelative(szPath, sizeof(szPath), pszFrom, pszTo);
     770        const char *pszFrom   = s_aRelPath[i].pszFrom;
     771        bool        fFromFile = s_aRelPath[i].fFromFile;
     772        const char *pszTo     = s_aRelPath[i].pszTo;
     773
     774        rc = RTPathCalcRelative(szPath, sizeof(szPath), pszFrom, fFromFile, pszTo);
    764775        if (rc != s_aRelPath[i].rc)
    765             RTTestIFailed("Unexpected return code\n"
     776            RTTestIFailed("Unexpected return code for %s .. %s\n"
    766777                          "     got: %Rrc\n"
    767778                          "expected: %Rrc",
    768                           rc, s_aRelPath[i].rc);
     779                          pszFrom, pszTo, rc, s_aRelPath[i].rc);
    769780        else if (   RT_SUCCESS(rc)
    770781                 && strcmp(szPath, s_aRelPath[i].pszExpected))
    771782            RTTestIFailed("Unexpected result\n"
    772                           "    from: '%s'\n"
     783                          "    from: '%s' (%s)\n"
    773784                          "      to: '%s'\n"
    774785                          "  output: '%s'\n"
    775786                          "expected: '%s'",
    776                           pszFrom, pszTo, szPath, s_aRelPath[i].pszExpected);
     787                          pszFrom, fFromFile ? "file" : "dir", pszTo, szPath, s_aRelPath[i].pszExpected);
    777788    }
    778789
  • trunk/src/VBox/Runtime/tools/RTDbgSymCache.cpp

    r76553 r76589  
    240240    char szLinkTarget[RTPATH_MAX];
    241241    //szMapPath[cch] = '\0';
    242     rc = RTPathCalcRelative(szLinkTarget, sizeof(szLinkTarget), szMapPath, pszCacheFile);
     242    rc = RTPathCalcRelative(szLinkTarget, sizeof(szLinkTarget), szMapPath, false /*fFromFile*/, pszCacheFile);
    243243    //szMapPath[cch] = RTPATH_SLASH;
    244244    if (RT_FAILURE(rc))
  • trunk/src/VBox/Storage/VHD.cpp

    r76553 r76589  
    331331                /* Convert to relative path. */
    332332                char szPath[RTPATH_MAX];
    333                 rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename,
    334                                         pszFilename);
     333                rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename, true /*fFromFile*/, pszFilename);
    335334                if (RT_SUCCESS(rc))
    336335                {
     
    374373                /* Convert to relative path. */
    375374                char szPath[RTPATH_MAX];
    376                 rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename,
    377                                         pszFilename);
     375                rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename, true /*fFromFile*/, pszFilename);
    378376                if (RT_SUCCESS(rc))
    379377                    rc = vhdFilenameToUtf16(szPath, (uint16_t *)pvBuf, cbMaxLen, &cb, false);
  • trunk/src/bldprogs/scmrw.cpp

    r76572 r76589  
    28962896        else
    28972897            rc = RTPathCalcRelative(&szNormalized[cchNormalized], sizeof(szNormalized) - cchNormalized,
    2898                                     pSettings->pszGuardRelativeToDir, pState->pszFilename);
     2898                                    pSettings->pszGuardRelativeToDir, false /*fFromFile*/, pState->pszFilename);
    28992899        if (RT_FAILURE(rc))
    29002900            return ScmError(pState, rc, "Error calculating guard prefix (RTPathCalcRelative): %Rrc\n", 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