VirtualBox

Changeset 52944 in vbox for trunk/src/VBox/Runtime/r3/posix


Ignore:
Timestamp:
Oct 5, 2014 4:37:10 AM (10 years ago)
Author:
vboxsync
Message:

IPRT: Separated out RTPathAbs from the posix, fixing it up for windows + OS/2, and made it generic. Also added some NT path routines.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/path-posix.cpp

    r48935 r52944  
    7676    LogFlow(("RTPathReal(%p:{%s}, %p:{%s}, %u): returns %Rrc\n", pszPath, pszPath,
    7777             pszRealPath, RT_SUCCESS(rc) ? pszRealPath : "<failed>",  cchRealPath, rc));
    78     return rc;
    79 }
    80 
    81 
    82 /**
    83  * Cleans up a path specifier a little bit.
    84  * This includes removing duplicate slashes, unnecessary single dots, and
    85  * trailing slashes. Also, replaces all RTPATH_SLASH characters with '/'.
    86  *
    87  * @returns Number of bytes in the clean path.
    88  * @param   pszPath     The path to cleanup.
    89  */
    90 static int fsCleanPath(char *pszPath)
    91 {
    92     /*
    93      * Change to '/' and remove duplicates.
    94      */
    95     char   *pszSrc = pszPath;
    96     char   *pszTrg = pszPath;
    97 #ifdef HAVE_UNC
    98     int     fUnc = 0;
    99     if (    RTPATH_IS_SLASH(pszPath[0])
    100         &&  RTPATH_IS_SLASH(pszPath[1]))
    101     {   /* Skip first slash in a unc path. */
    102         pszSrc++;
    103         *pszTrg++ = '/';
    104         fUnc = 1;
    105     }
    106 #endif
    107 
    108     for (;;)
    109     {
    110         char ch = *pszSrc++;
    111         if (RTPATH_IS_SLASH(ch))
    112         {
    113             *pszTrg++ = '/';
    114             for (;;)
    115             {
    116                 do  ch = *pszSrc++;
    117                 while (RTPATH_IS_SLASH(ch));
    118 
    119                 /* Remove '/./' and '/.'. */
    120                 if (ch != '.' || (*pszSrc && !RTPATH_IS_SLASH(*pszSrc)))
    121                     break;
    122             }
    123         }
    124         *pszTrg = ch;
    125         if (!ch)
    126             break;
    127         pszTrg++;
    128     }
    129 
    130     /*
    131      * Remove trailing slash if the path may be pointing to a directory.
    132      */
    133     int cch = pszTrg - pszPath;
    134     if (    cch > 1
    135         &&  RTPATH_IS_SLASH(pszTrg[-1])
    136 #ifdef HAVE_DRIVE
    137         &&  !RTPATH_IS_VOLSEP(pszTrg[-2])
    138 #endif
    139         &&  !RTPATH_IS_SLASH(pszTrg[-2]))
    140         pszPath[--cch] = '\0';
    141 
    142     return cch;
    143 }
    144 
    145 
    146 RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cchAbsPath)
    147 {
    148     int rc;
    149 
    150     /*
    151      * Validation.
    152      */
    153     AssertPtr(pszAbsPath);
    154     AssertPtr(pszPath);
    155     if (RT_UNLIKELY(!*pszPath))
    156         return VERR_INVALID_PARAMETER;
    157 
    158     /*
    159      * Make a clean working copy of the input.
    160      */
    161     size_t cchPath = strlen(pszPath);
    162     if (cchPath > PATH_MAX)
    163     {
    164         LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cchAbsPath, VERR_FILENAME_TOO_LONG));
    165         return VERR_FILENAME_TOO_LONG;
    166     }
    167 
    168     char szTmpPath[PATH_MAX + 1];
    169     memcpy(szTmpPath, pszPath, cchPath + 1);
    170     size_t cchTmpPath = fsCleanPath(szTmpPath);
    171 
    172     /*
    173      * Handle "." specially (fsCleanPath does).
    174      */
    175     if (szTmpPath[0] == '.' && !szTmpPath[1])
    176         return RTPathGetCurrent(pszAbsPath, cchAbsPath);
    177 
    178     /*
    179      * Do we have a root slash?
    180      */
    181     char *pszCur = szTmpPath;
    182 #ifdef HAVE_DRIVE
    183     if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/')
    184         pszCur += 3;
    185 # ifdef HAVE_UNC
    186     else if (pszCur[0] == '/' && pszCur[1] == '/')
    187         pszCur += 2;
    188 # endif
    189 #else  /* !HAVE_DRIVE */
    190     if (pszCur[0] == '/')
    191         pszCur += 1;
    192 #endif /* !HAVE_DRIVE */
    193     else
    194     {
    195         /*
    196          * No, prepend the current directory to the relative path.
    197          */
    198         char szCurDir[RTPATH_MAX];
    199         rc = RTPathGetCurrent(szCurDir, sizeof(szCurDir));
    200         AssertRCReturn(rc, rc);
    201 
    202         size_t cchCurDir = fsCleanPath(szCurDir); /* paranoia */
    203         if (cchCurDir + cchTmpPath + 1 > PATH_MAX)
    204         {
    205             LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cchAbsPath, VERR_FILENAME_TOO_LONG));
    206             return VERR_FILENAME_TOO_LONG;
    207         }
    208 
    209         memmove(szTmpPath + cchCurDir + 1, szTmpPath, cchTmpPath + 1);
    210         memcpy(szTmpPath, szCurDir, cchCurDir);
    211         szTmpPath[cchCurDir] = '/';
    212 
    213 
    214 #ifdef HAVE_DRIVE
    215         if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/')
    216             pszCur += 3;
    217 # ifdef HAVE_UNC
    218         else if (pszCur[0] == '/' && pszCur[1] == '/')
    219             pszCur += 2;
    220 # endif
    221 #else
    222         if (pszCur[0] == '/')
    223             pszCur += 1;
    224 #endif
    225         else
    226             AssertMsgFailedReturn(("pszCur=%s\n", pszCur), VERR_INTERNAL_ERROR);
    227     }
    228 
    229     char *pszTop = pszCur;
    230 
    231     /*
    232      * Get rid of double dot path components by evaluating them.
    233      */
    234     for (;;)
    235     {
    236         if (   pszCur[0] == '.'
    237             && pszCur[1] == '.'
    238             && (!pszCur[2] || pszCur[2] == '/'))
    239         {
    240             /* rewind to the previous component if any */
    241             char *pszPrev = pszCur - 1;
    242             if (pszPrev > pszTop)
    243                 while (*--pszPrev != '/')
    244                     ;
    245 
    246             AssertMsg(*pszPrev == '/', ("szTmpPath={%s}, pszPrev=+%u\n", szTmpPath, pszPrev - szTmpPath));
    247             memmove(pszPrev, pszCur + 2, strlen(pszCur + 2) + 1);
    248 
    249             pszCur = pszPrev;
    250         }
    251         else
    252         {
    253             /* advance to end of component. */
    254             while (*pszCur && *pszCur != '/')
    255                 pszCur++;
    256         }
    257 
    258         if (!*pszCur)
    259             break;
    260 
    261         /* skip the slash */
    262         ++pszCur;
    263     }
    264 
    265     if (pszCur < pszTop)
    266     {
    267         /*
    268          * We overwrote the root slash with '\0', restore it.
    269          */
    270         *pszCur++ = '/';
    271         *pszCur = '\0';
    272     }
    273     else if (pszCur > pszTop && pszCur[-1] == '/')
    274     {
    275         /*
    276          * Extra trailing slash in a non-root path, remove it.
    277          * (A bit questionable...)
    278          */
    279         *--pszCur = '\0';
    280     }
    281 
    282     /*
    283      * Copy the result to the user buffer.
    284      */
    285     cchTmpPath = pszCur - szTmpPath;
    286     if (cchTmpPath < cchAbsPath)
    287     {
    288         memcpy(pszAbsPath, szTmpPath, cchTmpPath + 1);
    289         rc = VINF_SUCCESS;
    290     }
    291     else
    292         rc = VERR_BUFFER_OVERFLOW;
    293 
    294     LogFlow(("RTPathAbs(%p:{%s}, %p:{%s}, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath,
    295              RT_SUCCESS(rc) ? pszAbsPath : "<failed>", cchAbsPath, rc));
    29678    return rc;
    29779}
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