VirtualBox

Changeset 19926 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
May 22, 2009 11:37:39 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
47628
Message:

IPRT: Added RTPathAppend.

File:
1 edited

Legend:

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

    r19924 r19926  
    448448 * such as:
    449449 * <ul>
    450  * <li>On DOS-like platforms, both |\| and |/| separator chars are considered
     450 * <li>On DOS-like platforms, both separator chars (|\| and |/|) are considered
    451451 *     to be equal.
    452452 * <li>On platforms with case-insensitive file systems, mismatching characters
     
    454454 * </ul>
    455455 *
    456  * @remark
    457  *
    458  * File system details are currently ignored. This means that you won't get
    459  * case-insentive compares on unix systems when a path goes into a case-insensitive
    460  * filesystem like FAT, HPFS, HFS, NTFS, JFS, or similar. For NT, OS/2 and similar
    461  * you'll won't get case-sensitve compares on a case-sensitive file system.
    462  *
    463  * @param   pszPath1    Path to compare (must be an absolute path).
    464  * @param   pszPath2    Path to compare (must be an absolute path).
    465  *
    466456 * @returns @< 0 if the first path less than the second path.
    467457 * @returns 0 if the first path identical to the second path.
    468458 * @returns @> 0 if the first path greater than the second path.
     459 *
     460 * @param   pszPath1    Path to compare (must be an absolute path).
     461 * @param   pszPath2    Path to compare (must be an absolute path).
     462 *
     463 * @remarks File system details are currently ignored. This means that you won't
     464 *          get case-insentive compares on unix systems when a path goes into a
     465 *          case-insensitive filesystem like FAT, HPFS, HFS, NTFS, JFS, or
     466 *          similar. For NT, OS/2 and similar you'll won't get case-sensitve
     467 *          compares on a case-sensitive file system.
    469468 */
    470469RTDECL(int) RTPathCompare(const char *pszPath1, const char *pszPath2)
     
    477476 * Checks if a path starts with the given parent path.
    478477 *
    479  * This means that either the path and the parent path matches completely, or that
    480  * the path is to some file or directory residing in the tree given by the parent
    481  * directory.
     478 * This means that either the path and the parent path matches completely, or
     479 * that the path is to some file or directory residing in the tree given by the
     480 * parent directory.
    482481 *
    483482 * The path comparison takes platform-dependent details into account,
    484483 * see RTPathCompare() for details.
     484 *
     485 * @returns |true| when \a pszPath starts with \a pszParentPath (or when they
     486 *          are identical), or |false| otherwise.
    485487 *
    486488 * @param   pszPath         Path to check, must be an absolute path.
     
    488490 *                          No trailing directory slash!
    489491 *
    490  * @returns |true| when \a pszPath starts with \a pszParentPath (or when they
    491  *          are identical), or |false| otherwise.
    492  *
    493  * @remark  This API doesn't currently handle root directory compares in a manner
    494  *          consistant with the other APIs. RTPathStartsWith(pszSomePath, "/") will
    495  *          not work if pszSomePath isn't "/".
     492 * @remarks This API doesn't currently handle root directory compares in a
     493 *          manner consistant with the other APIs. RTPathStartsWith(pszSomePath,
     494 *          "/") will not work if pszSomePath isn't "/".
    496495 */
    497496RTDECL(bool) RTPathStartsWith(const char *pszPath, const char *pszParentPath)
     
    542541        return RTStrDup(szPath);
    543542    return NULL;
     543}
     544
     545
     546/**
     547 * Figures the length of the root part of the path.
     548 *
     549 * @returns length of the root specifier.
     550 * @retval  0 if none.
     551 *
     552 * @param   pszPath         The path to investigate.
     553 *
     554 * @remarks Unnecessary root slashes will not be counted. The caller will have
     555 *          to deal with it where it matters.
     556 */
     557static size_t rtPathRootSpecLen(const char *pszPath)
     558{
     559    /* fend of wildlife. */
     560    if (!pszPath)
     561        return 0;
     562
     563    /* Root slash? */
     564    if (RTPATH_IS_SLASH(pszPath[0]))
     565    {
     566#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
     567        /* UNC? */
     568        if (    RTPATH_IS_SLASH(pszPath[1])
     569            &&  pszPath[2] != '\0'
     570            &&  !RTPATH_IS_SLASH(pszPath[2]))
     571        {
     572            /* Find the end of the server name. */
     573            const char *pszEnd = pszPath + 2;
     574            pszEnd += 2;
     575            while (   *pszEnd != '\0'
     576                   && !RTPATH_IS_SLASH(*pszEnd))
     577                pszEnd++;
     578            if (RTPATH_IS_SLASH(*pszEnd))
     579            {
     580                pszEnd++;
     581                while (RTPATH_IS_SLASH(*pszEnd))
     582                    pszEnd++;
     583
     584                /* Find the end of the share name */
     585                while (   *pszEnd != '\0'
     586                       && !RTPATH_IS_SLASH(*pszEnd))
     587                    pszEnd++;
     588                if (RTPATH_IS_SLASH(*pszEnd))
     589                    pszEnd++;
     590                return pszPath - pszEnd;
     591            }
     592        }
     593#endif
     594        return 1;
     595    }
     596
     597#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
     598    /* Drive specifier? */
     599    if (   pszPath[0] != '\0'
     600        && pszPath[1] == ':'
     601        && RT_C_IS_ALPHA(pszPath[0]))
     602    {
     603        if (RTPATH_IS_SLASH(pszPath[2]))
     604            return 3;
     605        return 2;
     606    }
     607#endif
     608    return 0;
    544609}
    545610
     
    664729
    665730
     731RTDECL(int) RTPathAppend(char *pszPath, size_t cchPath, const char *pszAppend)
     732{
     733    char *pszPathEnd = (char *)memchr(pszPath, '\0', cchPath);
     734    AssertReturn(pszPathEnd, VERR_INVALID_PARAMETER);
     735
     736    /*
     737     * Special cases.
     738     */
     739    if (!pszAppend)
     740        return VINF_SUCCESS;
     741    size_t cchAppend = strlen(pszAppend);
     742    if (!cchAppend)
     743        return VINF_SUCCESS;
     744    if (pszPathEnd == pszPath)
     745    {
     746        if (cchAppend >= cchPath)
     747            return VERR_BUFFER_OVERFLOW;
     748        memcpy(pszPath, pszAppend, cchAppend + 1);
     749        return VINF_SUCCESS;
     750    }
     751
     752    /*
     753     * Balance slashes and check for buffer overflow.
     754     */
     755    bool fAddSlash = false;
     756    if (!RTPATH_IS_SLASH(pszPathEnd[-1]))
     757    {
     758        if (!RTPATH_IS_SLASH(pszAppend[0]))
     759        {
     760#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
     761            if (    pszPath[1] == ':'
     762                &&  RT_C_IS_ALPHA(pszPath[0]))
     763            {
     764                if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cchPath)
     765                    return VERR_BUFFER_OVERFLOW;
     766            }
     767            else
     768#endif
     769            {
     770                if ((size_t)(pszPathEnd - pszPath) + 1 + cchAppend >= cchPath)
     771                    return VERR_BUFFER_OVERFLOW;
     772                *pszPathEnd++ = '/';
     773            }
     774        }
     775        else
     776        {
     777            /* One slash is sufficient at this point. */
     778            while (RTPATH_IS_SLASH(pszAppend[1]))
     779                pszAppend++, cchAppend--;
     780
     781            if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cchPath)
     782                return VERR_BUFFER_OVERFLOW;
     783        }
     784    }
     785    else
     786    {
     787        /* No slashes needed in the appended bit. */
     788        while (RTPATH_IS_SLASH(*pszAppend))
     789            pszAppend++, cchAppend--;
     790
     791        /* In the leading path we can skip unnecessary trailing slashes, but
     792           be sure to leave one. */
     793        size_t const cchRoot = rtPathRootSpecLen(pszPath);
     794        while (     (size_t)(pszPathEnd - pszPath) > RT_MAX(1, cchRoot)
     795               &&   RTPATH_IS_SLASH(pszPathEnd[-2]))
     796            pszPathEnd--;
     797
     798        if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cchPath)
     799            return VERR_BUFFER_OVERFLOW;
     800    }
     801
     802    /*
     803     * What remains now is the just the copying.
     804     */
     805    memcpy(pszPathEnd, pszAppend, cchAppend + 1);
     806    return VINF_SUCCESS;
     807}
     808
     809
    666810#ifndef RT_MINI
    667811
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