Changeset 34214 in vbox for trunk/src/VBox/Runtime/common/path/RTPathAppend.cpp
- Timestamp:
- Nov 19, 2010 5:18:15 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 67956
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/path/RTPathAppend.cpp
r30320 r34214 32 32 #include <iprt/path.h> 33 33 34 #include <iprt/assert.h>35 #include <iprt/ctype.h>36 #include <iprt/err.h>37 34 #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 have49 * to deal with it where it matters. (Unlike rtPathRootSpecLen which50 * 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 #endif89 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 #endif103 return 0;104 }105 35 106 36 107 37 RTDECL(int) RTPathAppend(char *pszPath, size_t cbPathDst, const char *pszAppend) 108 38 { 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); 184 40 } 185 41
Note:
See TracChangeset
for help on using the changeset viewer.