Changeset 52944 in vbox for trunk/src/VBox/Runtime/r3/posix
- Timestamp:
- Oct 5, 2014 4:37:10 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/path-posix.cpp
r48935 r52944 76 76 LogFlow(("RTPathReal(%p:{%s}, %p:{%s}, %u): returns %Rrc\n", pszPath, pszPath, 77 77 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, and85 * 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_UNC98 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 #endif107 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 > 1135 && RTPATH_IS_SLASH(pszTrg[-1])136 #ifdef HAVE_DRIVE137 && !RTPATH_IS_VOLSEP(pszTrg[-2])138 #endif139 && !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_DRIVE183 if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/')184 pszCur += 3;185 # ifdef HAVE_UNC186 else if (pszCur[0] == '/' && pszCur[1] == '/')187 pszCur += 2;188 # endif189 #else /* !HAVE_DRIVE */190 if (pszCur[0] == '/')191 pszCur += 1;192 #endif /* !HAVE_DRIVE */193 else194 {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_DRIVE215 if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/')216 pszCur += 3;217 # ifdef HAVE_UNC218 else if (pszCur[0] == '/' && pszCur[1] == '/')219 pszCur += 2;220 # endif221 #else222 if (pszCur[0] == '/')223 pszCur += 1;224 #endif225 else226 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 else252 {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 else292 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));296 78 return rc; 297 79 }
Note:
See TracChangeset
for help on using the changeset viewer.