VirtualBox

Ignore:
Timestamp:
Nov 19, 2010 5:18:15 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
67956
Message:

IPRT: Added RTPathJoinEx and RTPathAppendEx.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/path/RTPathAppend.cpp

    r30320 r34214  
    3232#include <iprt/path.h>
    3333
    34 #include <iprt/assert.h>
    35 #include <iprt/ctype.h>
    36 #include <iprt/err.h>
    3734#include <iprt/string.h>
    38 
    39 
    40 /**
    41  * Figures the length of the root part of the path.
    42  *
    43  * @returns length of the root specifier.
    44  * @retval  0 if none.
    45  *
    46  * @param   pszPath         The path to investigate.
    47  *
    48  * @remarks Unnecessary root slashes will not be counted. The caller will have
    49  *          to deal with it where it matters.  (Unlike rtPathRootSpecLen which
    50  *          counts them.)
    51  */
    52 static size_t rtPathRootSpecLen2(const char *pszPath)
    53 {
    54     /* fend of wildlife. */
    55     if (!pszPath)
    56         return 0;
    57 
    58     /* Root slash? */
    59     if (RTPATH_IS_SLASH(pszPath[0]))
    60     {
    61 #if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
    62         /* UNC? */
    63         if (    RTPATH_IS_SLASH(pszPath[1])
    64             &&  pszPath[2] != '\0'
    65             &&  !RTPATH_IS_SLASH(pszPath[2]))
    66         {
    67             /* Find the end of the server name. */
    68             const char *pszEnd = pszPath + 2;
    69             pszEnd += 2;
    70             while (   *pszEnd != '\0'
    71                    && !RTPATH_IS_SLASH(*pszEnd))
    72                 pszEnd++;
    73             if (RTPATH_IS_SLASH(*pszEnd))
    74             {
    75                 pszEnd++;
    76                 while (RTPATH_IS_SLASH(*pszEnd))
    77                     pszEnd++;
    78 
    79                 /* Find the end of the share name */
    80                 while (   *pszEnd != '\0'
    81                        && !RTPATH_IS_SLASH(*pszEnd))
    82                     pszEnd++;
    83                 if (RTPATH_IS_SLASH(*pszEnd))
    84                     pszEnd++;
    85                 return pszPath - pszEnd;
    86             }
    87         }
    88 #endif
    89         return 1;
    90     }
    91 
    92 #if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
    93     /* Drive specifier? */
    94     if (   pszPath[0] != '\0'
    95         && pszPath[1] == ':'
    96         && RT_C_IS_ALPHA(pszPath[0]))
    97     {
    98         if (RTPATH_IS_SLASH(pszPath[2]))
    99             return 3;
    100         return 2;
    101     }
    102 #endif
    103     return 0;
    104 }
    10535
    10636
    10737RTDECL(int) RTPathAppend(char *pszPath, size_t cbPathDst, const char *pszAppend)
    10838{
    109     char *pszPathEnd = RTStrEnd(pszPath, cbPathDst);
    110     AssertReturn(pszPathEnd, VERR_INVALID_PARAMETER);
    111 
    112     /*
    113      * Special cases.
    114      */
    115     if (!pszAppend)
    116         return VINF_SUCCESS;
    117     size_t cchAppend = strlen(pszAppend);
    118     if (!cchAppend)
    119         return VINF_SUCCESS;
    120     if (pszPathEnd == pszPath)
    121     {
    122         if (cchAppend >= cbPathDst)
    123             return VERR_BUFFER_OVERFLOW;
    124         memcpy(pszPath, pszAppend, cchAppend + 1);
    125         return VINF_SUCCESS;
    126     }
    127 
    128     /*
    129      * Balance slashes and check for buffer overflow.
    130      */
    131     bool fAddSlash = false;
    132     if (!RTPATH_IS_SLASH(pszPathEnd[-1]))
    133     {
    134         if (!RTPATH_IS_SLASH(pszAppend[0]))
    135         {
    136 #if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
    137             if (    (size_t)(pszPathEnd - pszPath) == 2
    138                 &&  pszPath[1] == ':'
    139                 &&  RT_C_IS_ALPHA(pszPath[0]))
    140             {
    141                 if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
    142                     return VERR_BUFFER_OVERFLOW;
    143             }
    144             else
    145 #endif
    146             {
    147                 if ((size_t)(pszPathEnd - pszPath) + 1 + cchAppend >= cbPathDst)
    148                     return VERR_BUFFER_OVERFLOW;
    149                 *pszPathEnd++ = '/';
    150             }
    151         }
    152         else
    153         {
    154             /* One slash is sufficient at this point. */
    155             while (RTPATH_IS_SLASH(pszAppend[1]))
    156                 pszAppend++, cchAppend--;
    157 
    158             if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
    159                 return VERR_BUFFER_OVERFLOW;
    160         }
    161     }
    162     else
    163     {
    164         /* No slashes needed in the appended bit. */
    165         while (RTPATH_IS_SLASH(*pszAppend))
    166             pszAppend++, cchAppend--;
    167 
    168         /* In the leading path we can skip unnecessary trailing slashes, but
    169            be sure to leave one. */
    170         size_t const cchRoot = rtPathRootSpecLen2(pszPath);
    171         while (     (size_t)(pszPathEnd - pszPath) > RT_MAX(1, cchRoot)
    172                &&   RTPATH_IS_SLASH(pszPathEnd[-2]))
    173             pszPathEnd--;
    174 
    175         if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
    176             return VERR_BUFFER_OVERFLOW;
    177     }
    178 
    179     /*
    180      * What remains now is the just the copying.
    181      */
    182     memcpy(pszPathEnd, pszAppend, cchAppend + 1);
    183     return VINF_SUCCESS;
     39    return RTPathAppendEx(pszPath, cbPathDst, pszAppend, RTSTR_MAX);
    18440}
    18541
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