Changeset 52944 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Oct 5, 2014 4:37:10 AM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 96384
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 2 added
- 7 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile.kmk
r52600 r52944 587 587 generic/RTLogWriteStdOut-generic.cpp \ 588 588 generic/RTLogWriteUser-generic.cpp \ 589 generic/RTPathGetCurrentDrive-generic.cpp \ 589 590 generic/RTPathIsSame-generic.cpp \ 590 591 generic/RTProcessQueryUsernameA-generic.cpp \ … … 702 703 generic/RTMpGetCurFrequency-generic.cpp \ 703 704 generic/RTMpGetMaxFrequency-generic.cpp \ 705 generic/RTPathAbs-generic.cpp \ 704 706 generic/RTRandAdvCreateSystemFaster-generic.cpp \ 705 707 generic/RTRandAdvCreateSystemTruer-generic.cpp \ … … 768 770 generic/RTFileMove-generic.cpp \ 769 771 generic/RTLogWriteDebugger-generic.cpp \ 772 generic/RTPathAbs-generic.cpp \ 773 generic/RTPathGetCurrentOnDrive-generic.cpp \ 770 774 generic/RTProcDaemonize-generic.cpp \ 771 775 generic/RTSemEventMultiWait-2-ex-generic.cpp \ … … 852 856 generic/RTFileMove-generic.cpp \ 853 857 generic/RTLogWriteDebugger-generic.cpp \ 858 generic/RTPathAbs-generic.cpp \ 859 generic/RTPathGetCurrentOnDrive-generic.cpp \ 854 860 generic/RTProcDaemonize-generic.cpp \ 855 861 generic/RTRandAdvCreateSystemFaster-generic.cpp \ … … 924 930 generic/RTFileMove-generic.cpp \ 925 931 generic/RTLogWriteDebugger-generic.cpp \ 932 generic/RTPathAbs-generic.cpp \ 933 generic/RTPathGetCurrentOnDrive-generic.cpp \ 926 934 generic/RTProcDaemonize-generic.cpp \ 927 935 generic/RTThreadGetAffinity-stub-generic.cpp \ … … 991 999 generic/RTFileMove-generic.cpp \ 992 1000 generic/RTLogWriteDebugger-generic.cpp \ 1001 generic/RTPathAbs-generic.cpp \ 1002 generic/RTPathGetCurrentOnDrive-generic.cpp \ 993 1003 generic/RTSemEventMultiWait-2-ex-generic.cpp \ 994 1004 generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp \ … … 1060 1070 generic/RTFileMove-generic.cpp \ 1061 1071 generic/RTLogWriteDebugger-generic.cpp \ 1072 generic/RTPathAbs-generic.cpp \ 1073 generic/RTPathGetCurrentOnDrive-generic.cpp \ 1062 1074 generic/RTProcDaemonize-generic.cpp \ 1063 1075 generic/RTProcIsRunningByName-generic.cpp \ … … 1132 1144 generic/RTFileMove-generic.cpp \ 1133 1145 generic/RTLogWriteDebugger-generic.cpp \ 1146 generic/RTPathAbs-generic.cpp \ 1147 generic/RTPathGetCurrentOnDrive-generic.cpp \ 1134 1148 generic/RTProcDaemonize-generic.cpp \ 1135 1149 generic/RTTimeLocalNow-generic.cpp \ -
trunk/src/VBox/Runtime/common/string/utf-16.cpp
r51770 r52944 100 100 101 101 102 RTDECL(PRTUTF16) RTUtf16AllocTag(size_t cb, const char *pszTag) 103 { 104 if (cb > sizeof(RTUTF16)) 105 cb = RT_ALIGN_Z(cb, sizeof(RTUTF16)); 106 else 107 cb = sizeof(RTUTF16); 108 PRTUTF16 pwsz = (PRTUTF16)RTMemAllocTag(cb, pszTag); 109 if (pwsz) 110 *pwsz = '\0'; 111 return pwsz; 112 } 113 RT_EXPORT_SYMBOL(RTUtf16AllocTag); 114 115 102 116 RTDECL(void) RTUtf16Free(PRTUTF16 pwszString) 103 117 { -
trunk/src/VBox/Runtime/generic/RTPathAbs-generic.cpp
r52854 r52944 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Path Manipulation, POSIX, Part 1.3 * IPRT - RTPathAbs, generic implementation. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-201 2Oracle Corporation7 * Copyright (C) 2006-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 30 30 *******************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_PATH 32 #include <stdlib.h>33 #include <limits.h>34 #include <errno.h>35 #include <unistd.h>36 #include <sys/stat.h>37 #include <sys/time.h>38 #include <stdio.h>39 #include <sys/types.h>40 #include <pwd.h>41 42 32 #include <iprt/path.h> 43 #include <iprt/env.h> 33 44 34 #include <iprt/assert.h> 45 #include <iprt/ string.h>35 #include <iprt/ctype.h> 46 36 #include <iprt/err.h> 47 37 #include <iprt/log.h> 38 #include <iprt/string.h> 48 39 #include "internal/path.h" 49 #include "internal/process.h"50 40 #include "internal/fs.h" 51 41 52 42 53 54 RTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, size_t cchRealPath) 43 static char *rtPathSkipRootSpec(char *pszCur) 55 44 { 56 /* 57 * Convert input. 58 */ 59 char const *pszNativePath; 60 int rc = rtPathToNative(&pszNativePath, pszPath, NULL); 61 if (RT_SUCCESS(rc)) 62 { 63 /* 64 * On POSIX platforms the API doesn't take a length parameter, which makes it 65 * a little bit more work. 66 */ 67 char szTmpPath[PATH_MAX + 1]; 68 const char *psz = realpath(pszNativePath, szTmpPath); 69 if (psz) 70 rc = rtPathFromNativeCopy(pszRealPath, cchRealPath, szTmpPath, NULL); 71 else 72 rc = RTErrConvertFromErrno(errno); 73 rtPathFreeNative(pszNativePath, pszPath); 74 } 75 76 LogFlow(("RTPathReal(%p:{%s}, %p:{%s}, %u): returns %Rrc\n", pszPath, pszPath, 77 pszRealPath, RT_SUCCESS(rc) ? pszRealPath : "<failed>", cchRealPath, rc)); 78 return rc; 45 #ifdef HAVE_DRIVE 46 if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == RTPATH_SLASH) 47 pszCur += 3; 48 # ifdef HAVE_UNC 49 else if (pszCur[0] == RTPATH_SLASH && pszCur[1] == RTPATH_SLASH) 50 { 51 pszCur += 2; 52 while (*pszCur == RTPATH_SLASH) 53 pszCur++; 54 if (*pszCur) 55 { 56 while (*pszCur != RTPATH_SLASH && *pszCur) 57 pszCur++; 58 if (*pszCur == RTPATH_SLASH) 59 { 60 pszCur++; 61 while (*pszCur != RTPATH_SLASH && *pszCur) 62 pszCur++; 63 if (*pszCur == RTPATH_SLASH) 64 pszCur++; 65 } 66 } 67 } 68 # endif 69 #else 70 if (pszCur[0] == RTPATH_SLASH) 71 pszCur += 1; 72 #endif 73 return pszCur; 79 74 } 80 75 … … 82 77 /** 83 78 * Cleans up a path specifier a little bit. 79 * 84 80 * 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.81 * trailing slashes. Also, replaces all slash characters with RTPATH_SLASH. 82 * 83 * @returns Length of the cleaned path (in chars). 88 84 * @param pszPath The path to cleanup. 89 85 */ 90 86 static int fsCleanPath(char *pszPath) 91 87 { 92 /* 93 * Change to '/' and remove duplicates. 94 */ 95 char *pszSrc = pszPath; 96 char *pszTrg = pszPath; 88 char *pszSrc = pszPath; 89 char *pszTrg = pszPath; 90 91 /* 92 * On windows, you either use on or two slashes at the head of a path, 93 * seems like it treats additional slashes as part of the UNC server name. 94 * Just change slashes to RTPATH_SLASH and skip them. 95 */ 96 /** @todo check how OS/2 treats unnecessary leading slashes */ 97 int cchIgnoreLeading = 0; 97 98 #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 99 if ( RTPATH_IS_SLASH(pszSrc[0]) 100 && RTPATH_IS_SLASH(pszSrc[1])) 101 { 102 pszTrg[0] = RTPATH_SLASH; 103 pszTrg[1] = RTPATH_SLASH; 104 pszTrg += 2; 105 pszSrc += 2; 106 cchIgnoreLeading = 1; 107 while (RTPATH_IS_SLASH(*pszSrc)) 108 { 109 cchIgnoreLeading++; 110 pszSrc++; 111 *pszTrg++ = RTPATH_SLASH; 112 } 113 } 114 #endif 115 116 /* 117 * Change slashes to RTPATH_SLASH and remove duplicates. 118 */ 108 119 for (;;) 109 120 { … … 111 122 if (RTPATH_IS_SLASH(ch)) 112 123 { 113 *pszTrg++ = '/';124 *pszTrg++ = RTPATH_SLASH; 114 125 for (;;) 115 126 { 116 do ch = *pszSrc++; 127 do 128 ch = *pszSrc++; 117 129 while (RTPATH_IS_SLASH(ch)); 118 130 119 131 /* Remove '/./' and '/.'. */ 120 if (ch != '.' || (*pszSrc && !RTPATH_IS_SLASH(*pszSrc))) 132 if ( ch != '.' 133 || (*pszSrc && !RTPATH_IS_SLASH(*pszSrc))) 121 134 break; 122 135 } … … 128 141 } 129 142 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 return pszTrg - pszPath; 143 144 } 144 145 … … 154 155 AssertPtr(pszPath); 155 156 if (RT_UNLIKELY(!*pszPath)) 156 return VERR_INVALID_PARAMETER; 157 return VERR_INVALID_PARAMETER; //VERR_INVALID_NAME; 157 158 158 159 /* … … 160 161 */ 161 162 size_t cchPath = strlen(pszPath); 162 if (cchPath > 163 if (cchPath >= RTPATH_MAX) 163 164 { 164 165 LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cchAbsPath, VERR_FILENAME_TOO_LONG)); … … 166 167 } 167 168 168 char szTmpPath[ PATH_MAX + 1];169 char szTmpPath[RTPATH_MAX]; 169 170 memcpy(szTmpPath, pszPath, cchPath + 1); 170 171 size_t cchTmpPath = fsCleanPath(szTmpPath); … … 173 174 * Handle "." specially (fsCleanPath does). 174 175 */ 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; 176 if (szTmpPath[0] == '.') 177 { 178 if ( cchTmpPath == 1 179 || (cchTmpPath == 2 && szTmpPath[1] == RTPATH_SLASH)) 180 { 181 rc = RTPathGetCurrent(pszAbsPath, cchAbsPath); 182 if (RT_SUCCESS(rc)) 183 { 184 size_t cch = fsCleanPath(pszAbsPath); 185 char *pszTop = rtPathSkipRootSpec(pszAbsPath); 186 #if 1 187 if ((uintptr_t)&pszAbsPath[cch] > (uintptr_t)pszTop && pszAbsPath[cch - 1] == RTPATH_SLASH) 188 pszAbsPath[cch - 1] = '\0'; 189 #else 190 if ( cchTmpPath == 2 191 && (uintptr_t)&pszAbsPath[cch - 1] > (uintptr_t)pszTop && pszAbsPath[cch - 1] != RTPATH_SLASH) 192 { 193 if (cch + 1 < cchAbsPath) 194 { 195 pszAbsPath[cch++] = RTPATH_SLASH; 196 pszAbsPath[cch] = '\0'; 197 } 198 else 199 rc = VERR_BUFFER_OVERFLOW; 200 } 201 #endif 202 } 203 return rc; 204 } 205 } 206 207 /* 208 * Do we have an incomplete root spec? Supply the missing bits. 209 */ 182 210 #ifdef HAVE_DRIVE 183 if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/') 184 pszCur += 3; 211 if ( !(szTmpPath[0] && RTPATH_IS_VOLSEP(szTmpPath[1]) && szTmpPath[2] == RTPATH_SLASH) 185 212 # ifdef HAVE_UNC 186 else if (pszCur[0] == '/' && pszCur[1] == '/') 187 pszCur += 2; 213 && !(szTmpPath[0] == RTPATH_SLASH && szTmpPath[1] == RTPATH_SLASH) 188 214 # 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 215 ) 216 #else 217 if (szTmpPath[0] != RTPATH_SLASH) 218 #endif 219 { 220 char szCurDir[RTPATH_MAX]; 221 size_t cchCurDir; 222 int offApplyAt; 223 bool fNeedSlash; 214 224 #ifdef HAVE_DRIVE 215 if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == '/') 216 pszCur += 3; 225 if (szTmpPath[0] && RTPATH_IS_VOLSEP(szTmpPath[1]) && szTmpPath[2] != RTPATH_SLASH) 226 { 227 /* 228 * Relative to drive specific current directory. 229 */ 230 rc = RTPathGetCurrentOnDrive(szTmpPath[0], szCurDir, sizeof(szCurDir)); 231 fNeedSlash = true; 232 offApplyAt = 2; 233 } 217 234 # ifdef HAVE_UNC 218 else if (pszCur[0] == '/' && pszCur[1] == '/') 219 pszCur += 2; 235 else if (szTmpPath[0] == RTPATH_SLASH && szTmpPath[1] != RTPATH_SLASH) 236 # else 237 else if (szTmpPath[0] == RTPATH_SLASH) 220 238 # endif 221 #else 222 if (pszCur[0] == '/') 223 pszCur += 1; 224 #endif 239 { 240 /* 241 * Root of current drive. This may return a UNC root if we're not 242 * standing on a drive but on a UNC share. 243 */ 244 rc = RTPathGetCurrentDrive(szCurDir, sizeof(szCurDir)); 245 fNeedSlash = false; 246 offApplyAt = 0; 247 } 225 248 else 226 AssertMsgFailedReturn(("pszCur=%s\n", pszCur), VERR_INTERNAL_ERROR); 227 } 228 229 char *pszTop = pszCur; 249 #endif 250 { 251 /* 252 * Relative to current directory. 253 */ 254 rc = RTPathGetCurrent(szCurDir, sizeof(szCurDir)); 255 fNeedSlash = true; 256 offApplyAt = 0; 257 } 258 if (RT_SUCCESS(rc)) 259 { 260 cchCurDir = fsCleanPath(szCurDir); 261 if (fNeedSlash && cchCurDir > 0 && szCurDir[cchCurDir - 1] == RTPATH_SLASH) 262 fNeedSlash = false; 263 264 if (cchCurDir + fNeedSlash + cchTmpPath - offApplyAt <= RTPATH_MAX) 265 { 266 memmove(szTmpPath + cchCurDir + fNeedSlash, szTmpPath + offApplyAt, cchTmpPath + 1 - offApplyAt); 267 memcpy(szTmpPath, szCurDir, cchCurDir); 268 if (fNeedSlash) 269 szTmpPath[cchCurDir] = RTPATH_SLASH; 270 } 271 else 272 rc = VERR_FILENAME_TOO_LONG; 273 } 274 if (RT_FAILURE(rc)) 275 { 276 LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cchAbsPath, rc)); 277 return rc; 278 } 279 } 280 281 /* 282 * Skip past the root spec. 283 */ 284 char *pszCur = rtPathSkipRootSpec(szTmpPath); 285 AssertMsgReturn(pszCur != &szTmpPath[0], ("pszCur=%s\n", pszCur), VERR_INTERNAL_ERROR); 286 char * const pszTop = pszCur; 230 287 231 288 /* … … 236 293 if ( pszCur[0] == '.' 237 294 && pszCur[1] == '.' 238 && (!pszCur[2] || pszCur[2] == '/'))295 && (!pszCur[2] || pszCur[2] == RTPATH_SLASH)) 239 296 { 240 297 /* 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; 298 char *pszPrev = pszCur; 299 if ((uintptr_t)pszPrev > (uintptr_t)pszTop) 300 { 301 pszPrev--; 302 while ( (uintptr_t)pszPrev > (uintptr_t)pszTop 303 && pszPrev[-1] != RTPATH_SLASH) 304 pszPrev--; 305 } 306 if (!pszCur[2]) 307 { 308 if (pszPrev != pszTop) 309 pszPrev[-1] = '\0'; 310 else 311 *pszPrev = '\0'; 312 break; 313 } 314 Assert(pszPrev[-1] == RTPATH_SLASH); 315 memmove(pszPrev, pszCur + 3, strlen(pszCur + 3) + 1); 316 pszCur = pszPrev - 1; 250 317 } 251 318 else 252 319 { 253 320 /* advance to end of component. */ 254 while (*pszCur && *pszCur != '/')321 while (*pszCur && *pszCur != RTPATH_SLASH) 255 322 pszCur++; 256 323 } … … 263 330 } 264 331 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 } 332 cchTmpPath = pszCur - szTmpPath; 333 334 #if 1 335 /* 336 * Strip trailing slash if that's what's desired. 337 */ 338 339 if ((uintptr_t)&szTmpPath[cchTmpPath] > (uintptr_t)pszTop && szTmpPath[cchTmpPath - 1] == RTPATH_SLASH) 340 szTmpPath[--cchTmpPath] = '\0'; 341 #endif 281 342 282 343 /* 283 344 * Copy the result to the user buffer. 284 345 */ 285 cchTmpPath = pszCur - szTmpPath;286 346 if (cchTmpPath < cchAbsPath) 287 347 { … … 297 357 } 298 358 299 300 RTR3DECL(int) RTPathSetMode(const char *pszPath, RTFMODE fMode)301 {302 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);303 AssertReturn(*pszPath, VERR_INVALID_PARAMETER);304 305 int rc;306 fMode = rtFsModeNormalize(fMode, pszPath, 0);307 if (rtFsModeIsValidPermissions(fMode))308 {309 char const *pszNativePath;310 rc = rtPathToNative(&pszNativePath, pszPath, NULL);311 if (RT_SUCCESS(rc))312 {313 if (chmod(pszNativePath, fMode & RTFS_UNIX_MASK) != 0)314 rc = RTErrConvertFromErrno(errno);315 rtPathFreeNative(pszNativePath, pszPath);316 }317 }318 else319 {320 AssertMsgFailed(("Invalid file mode! %RTfmode\n", fMode));321 rc = VERR_INVALID_FMODE;322 }323 return rc;324 }325 326 327 /**328 * Checks if two files are the one and same file.329 */330 static bool rtPathSame(const char *pszNativeSrc, const char *pszNativeDst)331 {332 struct stat SrcStat;333 if (lstat(pszNativeSrc, &SrcStat))334 return false;335 struct stat DstStat;336 if (lstat(pszNativeDst, &DstStat))337 return false;338 Assert(SrcStat.st_dev && DstStat.st_dev);339 Assert(SrcStat.st_ino && DstStat.st_ino);340 if ( SrcStat.st_dev == DstStat.st_dev341 && SrcStat.st_ino == DstStat.st_ino342 && (SrcStat.st_mode & S_IFMT) == (DstStat.st_mode & S_IFMT))343 return true;344 return false;345 }346 347 348 /**349 * Worker for RTPathRename, RTDirRename, RTFileRename.350 *351 * @returns IPRT status code.352 * @param pszSrc The source path.353 * @param pszDst The destination path.354 * @param fRename The rename flags.355 * @param fFileType The filetype. We use the RTFMODE filetypes here. If it's 0,356 * anything goes. If it's RTFS_TYPE_DIRECTORY we'll check that the357 * source is a directory. If Its RTFS_TYPE_FILE we'll check that it's358 * not a directory (we are NOT checking whether it's a file).359 */360 DECLHIDDEN(int) rtPathPosixRename(const char *pszSrc, const char *pszDst, unsigned fRename, RTFMODE fFileType)361 {362 /*363 * Convert the paths.364 */365 char const *pszNativeSrc;366 int rc = rtPathToNative(&pszNativeSrc, pszSrc, NULL);367 if (RT_SUCCESS(rc))368 {369 char const *pszNativeDst;370 rc = rtPathToNative(&pszNativeDst, pszDst, NULL);371 if (RT_SUCCESS(rc))372 {373 /*374 * Check that the source exists and that any types that's specified matches.375 * We have to check this first to avoid getting errnous VERR_ALREADY_EXISTS376 * errors from the next step.377 *378 * There are race conditions here (perhaps unlikely ones, but still), but I'm379 * afraid there is little with can do to fix that.380 */381 struct stat SrcStat;382 if (lstat(pszNativeSrc, &SrcStat))383 rc = RTErrConvertFromErrno(errno);384 else if (!fFileType)385 rc = VINF_SUCCESS;386 else if (RTFS_IS_DIRECTORY(fFileType))387 rc = S_ISDIR(SrcStat.st_mode) ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;388 else389 rc = S_ISDIR(SrcStat.st_mode) ? VERR_IS_A_DIRECTORY : VINF_SUCCESS;390 if (RT_SUCCESS(rc))391 {392 bool fSameFile = false;393 394 /*395 * Check if the target exists, rename is rather destructive.396 * We'll have to make sure we don't overwrite the source!397 * Another race condition btw.398 */399 struct stat DstStat;400 if (lstat(pszNativeDst, &DstStat))401 rc = errno == ENOENT ? VINF_SUCCESS : RTErrConvertFromErrno(errno);402 else403 {404 Assert(SrcStat.st_dev && DstStat.st_dev);405 Assert(SrcStat.st_ino && DstStat.st_ino);406 if ( SrcStat.st_dev == DstStat.st_dev407 && SrcStat.st_ino == DstStat.st_ino408 && (SrcStat.st_mode & S_IFMT) == (DstStat.st_mode & S_IFMT))409 {410 /*411 * It's likely that we're talking about the same file here.412 * We should probably check paths or whatever, but for now this'll have to be enough.413 */414 fSameFile = true;415 }416 if (fSameFile)417 rc = VINF_SUCCESS;418 else if (S_ISDIR(DstStat.st_mode) || !(fRename & RTPATHRENAME_FLAGS_REPLACE))419 rc = VERR_ALREADY_EXISTS;420 else421 rc = VINF_SUCCESS;422 423 }424 if (RT_SUCCESS(rc))425 {426 if (!rename(pszNativeSrc, pszNativeDst))427 rc = VINF_SUCCESS;428 else if ( (fRename & RTPATHRENAME_FLAGS_REPLACE)429 && (errno == ENOTDIR || errno == EEXIST))430 {431 /*432 * Check that the destination isn't a directory.433 * Yet another race condition.434 */435 if (rtPathSame(pszNativeSrc, pszNativeDst))436 {437 rc = VINF_SUCCESS;438 Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): appears to be the same file... (errno=%d)\n",439 pszSrc, pszDst, fRename, fFileType, errno));440 }441 else442 {443 if (lstat(pszNativeDst, &DstStat))444 rc = errno != ENOENT ? RTErrConvertFromErrno(errno) : VINF_SUCCESS;445 else if (S_ISDIR(DstStat.st_mode))446 rc = VERR_ALREADY_EXISTS;447 else448 rc = VINF_SUCCESS;449 if (RT_SUCCESS(rc))450 {451 if (!unlink(pszNativeDst))452 {453 if (!rename(pszNativeSrc, pszNativeDst))454 rc = VINF_SUCCESS;455 else456 {457 rc = RTErrConvertFromErrno(errno);458 Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): rename failed rc=%Rrc errno=%d\n",459 pszSrc, pszDst, fRename, fFileType, rc, errno));460 }461 }462 else463 {464 rc = RTErrConvertFromErrno(errno);465 Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): failed to unlink dst rc=%Rrc errno=%d\n",466 pszSrc, pszDst, fRename, fFileType, rc, errno));467 }468 }469 else470 Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): dst !dir check failed rc=%Rrc\n",471 pszSrc, pszDst, fRename, fFileType, rc));472 }473 }474 else475 {476 rc = RTErrConvertFromErrno(errno);477 if (errno == ENOTDIR)478 rc = VERR_ALREADY_EXISTS; /* unless somebody is racing us, this is the right interpretation */479 Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): rename failed rc=%Rrc errno=%d\n",480 pszSrc, pszDst, fRename, fFileType, rc, errno));481 }482 }483 else484 Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): destination check failed rc=%Rrc errno=%d\n",485 pszSrc, pszDst, fRename, fFileType, rc, errno));486 }487 else488 Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): source type check failed rc=%Rrc errno=%d\n",489 pszSrc, pszDst, fRename, fFileType, rc, errno));490 491 rtPathFreeNative(pszNativeDst, pszDst);492 }493 rtPathFreeNative(pszNativeSrc, pszSrc);494 }495 return rc;496 }497 498 499 RTR3DECL(int) RTPathRename(const char *pszSrc, const char *pszDst, unsigned fRename)500 {501 /*502 * Validate input.503 */504 AssertMsgReturn(VALID_PTR(pszSrc), ("%p\n", pszSrc), VERR_INVALID_POINTER);505 AssertMsgReturn(VALID_PTR(pszDst), ("%p\n", pszDst), VERR_INVALID_POINTER);506 AssertMsgReturn(*pszSrc, ("%p\n", pszSrc), VERR_INVALID_PARAMETER);507 AssertMsgReturn(*pszDst, ("%p\n", pszDst), VERR_INVALID_PARAMETER);508 AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);509 510 /*511 * Hand it to the worker.512 */513 int rc = rtPathPosixRename(pszSrc, pszDst, fRename, 0);514 515 Log(("RTPathRename(%p:{%s}, %p:{%s}, %#x): returns %Rrc\n", pszSrc, pszSrc, pszDst, pszDst, fRename, rc));516 return rc;517 }518 519 520 RTR3DECL(int) RTPathUnlink(const char *pszPath, uint32_t fUnlink)521 {522 return VERR_NOT_IMPLEMENTED;523 }524 525 526 RTDECL(bool) RTPathExists(const char *pszPath)527 {528 return RTPathExistsEx(pszPath, RTPATH_F_FOLLOW_LINK);529 }530 531 532 RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags)533 {534 /*535 * Validate input.536 */537 AssertPtrReturn(pszPath, false);538 AssertReturn(*pszPath, false);539 Assert(RTPATH_F_IS_VALID(fFlags, 0));540 541 /*542 * Convert the path and check if it exists using stat().543 */544 char const *pszNativePath;545 int rc = rtPathToNative(&pszNativePath, pszPath, NULL);546 if (RT_SUCCESS(rc))547 {548 struct stat Stat;549 if (fFlags & RTPATH_F_FOLLOW_LINK)550 rc = stat(pszNativePath, &Stat);551 else552 rc = lstat(pszNativePath, &Stat);553 if (!rc)554 rc = VINF_SUCCESS;555 else556 rc = VERR_GENERAL_FAILURE;557 rtPathFreeNative(pszNativePath, pszPath);558 }559 return RT_SUCCESS(rc);560 }561 562 563 RTDECL(int) RTPathGetCurrent(char *pszPath, size_t cchPath)564 {565 int rc;566 char szNativeCurDir[RTPATH_MAX];567 if (getcwd(szNativeCurDir, sizeof(szNativeCurDir)) != NULL)568 rc = rtPathFromNativeCopy(pszPath, cchPath, szNativeCurDir, NULL);569 else570 rc = RTErrConvertFromErrno(errno);571 return rc;572 }573 574 575 RTDECL(int) RTPathSetCurrent(const char *pszPath)576 {577 /*578 * Validate input.579 */580 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);581 AssertReturn(*pszPath, VERR_INVALID_PARAMETER);582 583 /*584 * Change the directory.585 */586 char const *pszNativePath;587 int rc = rtPathToNative(&pszNativePath, pszPath, NULL);588 if (RT_SUCCESS(rc))589 {590 if (chdir(pszNativePath))591 rc = RTErrConvertFromErrno(errno);592 rtPathFreeNative(pszNativePath, pszPath);593 }594 return rc;595 }596 -
trunk/src/VBox/Runtime/r3/nt/internal-r3-nt.h
r49150 r52944 29 29 #define ___internal_r3_nt_h___ 30 30 31 32 #include <iprt/nt/nt.h> 31 #ifdef IN_SUP_HARDENED_R3 32 # include <iprt/nt/nt-and-windows.h> 33 #else 34 # include <iprt/nt/nt.h> 35 #endif 33 36 #include "internal/iprt.h" 34 37 -
trunk/src/VBox/Runtime/r3/nt/pathint-nt.cpp
r49150 r52944 38 38 39 39 40 41 /** 42 * Handles the pass thru case. 40 /******************************************************************************* 41 * Global Variables * 42 *******************************************************************************/ 43 static char const g_szPrefixUnc[] = "\\??\\UNC\\"; 44 static char const g_szPrefix[] = "\\??\\"; 45 46 47 /** 48 * Handles the pass thru case for UTF-8 input. 43 49 * 44 50 * @returns IPRT status code. … … 47 53 * @param pszPath The UTF-8 path. 48 54 */ 49 static int rtNtPath ToNativePassThruWin(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)55 static int rtNtPathFromWinUtf8PassThru(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath) 50 56 { 51 57 PRTUTF16 pwszPath = NULL; … … 61 67 62 68 pNtName->Buffer = pwszPath; 63 pNtName->MaximumLength = pNtName->Length = (uint16_t)(cwcLen * 2); 69 pNtName->Length = (uint16_t)(cwcLen * sizeof(RTUTF16)); 70 pNtName->MaximumLength = pNtName->Length + sizeof(RTUTF16); 64 71 *phRootDir = NULL; 65 72 return VINF_SUCCESS; … … 71 78 return rc; 72 79 } 80 81 82 /** 83 * Handles the pass thru case for UTF-16 input. 84 * 85 * @returns IPRT status code. 86 * @param pNtName Where to return the NT name. 87 * @param phRootDir Stores NULL here, as we don't use it. 88 * @param pwszWinPath The UTF-16 windows-style path. 89 * @param cwcWinPath The length of the windows-style input path. 90 */ 91 static int rtNtPathFromWinUtf16PassThru(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, 92 PCRTUTF16 pwszWinPath, size_t cwcWinPath) 93 { 94 /* Drop a character because: \\?\ -> \.\ */ 95 pwszWinPath++; 96 cwcWinPath--; 97 98 /* Check length and allocate memory for it. */ 99 int rc; 100 if (cwcWinPath < _32K - 1) 101 { 102 PRTUTF16 pwszNtPath = (PRTUTF16)RTUtf16Alloc((cwcWinPath + 1) * sizeof(RTUTF16)); 103 if (pwszNtPath) 104 { 105 /* Intialize the path. */ 106 pwszNtPath[0] = '\\'; 107 pwszNtPath[1] = '.'; 108 pwszNtPath[2] = '\\'; 109 memcpy(pwszNtPath + 3, pwszWinPath + 3, (cwcWinPath - 3) * sizeof(RTUTF16)); 110 pwszNtPath[cwcWinPath] = '\0'; 111 112 /* Initialize the return values. */ 113 pNtName->Buffer = pwszNtPath; 114 pNtName->Length = (uint16_t)(cwcWinPath * sizeof(RTUTF16)); 115 pNtName->MaximumLength = pNtName->Length + sizeof(RTUTF16); 116 *phRootDir = NULL; 117 118 rc = VINF_SUCCESS; 119 } 120 else 121 rc = VERR_NO_UTF16_MEMORY; 122 } 123 else 124 rc = VERR_FILENAME_TOO_LONG; 125 return rc; 126 } 127 128 129 73 130 74 131 … … 81 138 * @param pszPath The UTF-8 path. 82 139 */ 83 static int rtNtPath ToNativeToUtf16(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)140 static int rtNtPathUtf8ToUniStr(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath) 84 141 { 85 142 PRTUTF16 pwszPath = NULL; … … 91 148 { 92 149 pNtName->Buffer = pwszPath; 93 pNtName->MaximumLength = pNtName->Length = (uint16_t)(cwcLen * 2); 150 pNtName->Length = (uint16_t)(cwcLen * sizeof(RTUTF16)); 151 pNtName->MaximumLength = pNtName->Length + sizeof(RTUTF16); 94 152 *phRootDir = NULL; 95 153 return VINF_SUCCESS; … … 113 171 static int rtNtPathToNative(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath) 114 172 { 115 static char const s_szPrefixUnc[] = "\\??\\UNC\\";116 static char const s_szPrefix[] = "\\??\\";117 118 173 /* 119 174 * Very simple conversion of a win32-like path into an NT path. 120 175 */ 121 const char *pszPrefix = s_szPrefix;122 size_t cchPrefix = sizeof( s_szPrefix) - 1;176 const char *pszPrefix = g_szPrefix; 177 size_t cchPrefix = sizeof(g_szPrefix) - 1; 123 178 size_t cchSkip = 0; 124 179 … … 130 185 if ( pszPath[2] == '?' 131 186 && RTPATH_IS_SLASH(pszPath[3])) 132 return rtNtPath ToNativePassThruWin(pNtName, phRootDir, pszPath);187 return rtNtPathFromWinUtf8PassThru(pNtName, phRootDir, pszPath); 133 188 134 189 #ifdef IPRT_WITH_NT_PATH_PASSTHRU … … 136 191 if ( pszPath[2] == '!' 137 192 && RTPATH_IS_SLASH(pszPath[3])) 138 return rtNtPath ToNativeToUtf16(pNtName, phRootDir, pszPath + 3);193 return rtNtPathUtf8ToUniStr(pNtName, phRootDir, pszPath + 3); 139 194 #endif 140 195 … … 151 206 { 152 207 /* UNC */ 153 pszPrefix = s_szPrefixUnc;154 cchPrefix = sizeof( s_szPrefixUnc) - 1;208 pszPrefix = g_szPrefixUnc; 209 cchPrefix = sizeof(g_szPrefixUnc) - 1; 155 210 cchSkip = 2; 156 211 } … … 169 224 */ 170 225 memcpy(szPath, pszPrefix, cchPrefix); 171 return rtNtPathToNativeToUtf16(pNtName, phRootDir, szPath); 226 return rtNtPathUtf8ToUniStr(pNtName, phRootDir, szPath); 227 } 228 229 230 /** 231 * Converts a UTF-16 windows-style path to NT format. 232 * 233 * @returns IPRT status code. 234 * @param pNtName Where to return the NT name. Free using 235 * RTNtPathFree. 236 * @param phRootDir Where to return the root handle, if applicable. 237 * @param pwszWinPath The UTF-16 windows-style path. 238 * @param cwcWinPath The max length of the windows-style path in 239 * RTUTF16 units. Use RTSTR_MAX if unknown and @a 240 * pwszWinPath is correctly terminated. 241 */ 242 RTDECL(int) RTNtPathFromWinUtf16Ex(struct _UNICODE_STRING *pNtName, HANDLE *phRootDir, PCRTUTF16 pwszWinPath, size_t cwcWinPath) 243 { 244 /* 245 * Validate the input, calculating the correct length. 246 */ 247 if (cwcWinPath == 0 || *pwszWinPath == '\0') 248 return VERR_INVALID_NAME; 249 250 int rc = RTUtf16NLenEx(pwszWinPath, cwcWinPath, &cwcWinPath); 251 if (RT_FAILURE(rc)) 252 return rc; 253 254 /* 255 * Very simple conversion of a win32-like path into an NT path. 256 */ 257 const char *pszPrefix = g_szPrefix; 258 size_t cchPrefix = sizeof(g_szPrefix) - 1; 259 size_t cchSkip = 0; 260 261 if ( RTPATH_IS_SLASH(pwszWinPath[0]) 262 && cwcWinPath >= 3 263 && RTPATH_IS_SLASH(pwszWinPath[1]) 264 && !RTPATH_IS_SLASH(pwszWinPath[2]) ) 265 { 266 if ( pwszWinPath[2] == '?' 267 && cwcWinPath >= 4 268 && RTPATH_IS_SLASH(pwszWinPath[3])) 269 return rtNtPathFromWinUtf16PassThru(pNtName, phRootDir, pwszWinPath, cwcWinPath); 270 271 #ifdef IPRT_WITH_NT_PATH_PASSTHRU 272 /* Special hack: The path starts with "\\\\!\\", we will skip past the bang and pass it thru. */ 273 if ( pwszWinPath[2] == '!' 274 && cwcWinPath >= 4 275 && RTPATH_IS_SLASH(pwszWinPath[3])) 276 { 277 pwszWinPath += 3; 278 cwcWinPath -= 3; 279 if (cwcWinPath < _32K - 1) 280 { 281 PRTUTF16 pwszNtPath = RTUtf16Alloc((cwcWinPath + 1) * sizeof(RTUTF16)); 282 if (pwszNtPath) 283 { 284 memcpy(pwszNtPath, pwszWinPath, cwcWinPath * sizeof(RTUTF16)); 285 pwszNtPath[cwcWinPath] = '\0'; 286 pNtName->Buffer = pwszNtPath; 287 pNtName->Length = (uint16_t)(cwcWinPath * sizeof(RTUTF16)); 288 pNtName->MaximumLength = pNtName->Length + sizeof(RTUTF16); 289 *phRootDir = NULL; 290 return VINF_SUCCESS; 291 } 292 rc = VERR_NO_UTF16_MEMORY; 293 } 294 else 295 rc = VERR_FILENAME_TOO_LONG; 296 return rc; 297 } 298 #endif 299 300 if ( pwszWinPath[2] == '.' 301 && cwcWinPath >= 4 302 && RTPATH_IS_SLASH(pwszWinPath[3])) 303 { 304 /* 305 * Device path. 306 * Note! I suspect \\.\stuff\..\otherstuff may be handled differently by windows. 307 */ 308 cchSkip = 4; 309 } 310 else 311 { 312 /* UNC */ 313 pszPrefix = g_szPrefixUnc; 314 cchPrefix = sizeof(g_szPrefixUnc) - 1; 315 cchSkip = 2; 316 } 317 } 318 319 /* 320 * Straighten out all .. and unnecessary . references and convert slashes. 321 */ 322 char szAbsPath[RTPATH_MAX]; 323 char szRelPath[RTPATH_MAX]; 324 char *pszRelPath = szRelPath; 325 size_t cchRelPath; 326 rc = RTUtf16ToUtf8Ex(pwszWinPath, cwcWinPath, &pszRelPath, sizeof(szRelPath), &cchRelPath); 327 if (RT_SUCCESS(rc)) 328 rc = RTPathAbs(szRelPath, &szAbsPath[cchPrefix - cchSkip], sizeof(szAbsPath) - (cchPrefix - cchSkip)); 329 if (RT_SUCCESS(rc)) 330 { 331 /* 332 * Add prefix and convert it to UTF16. 333 */ 334 memcpy(szAbsPath, pszPrefix, cchPrefix); 335 return rtNtPathUtf8ToUniStr(pNtName, phRootDir, szAbsPath); 336 } 337 return rc; 172 338 } 173 339 … … 181 347 * rtNtPathToNative. 182 348 */ 183 void rtNtPathFreeNative(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir)349 static void rtNtPathFreeNative(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir) 184 350 { 185 351 RTUtf16Free(pNtName->Buffer); 186 352 pNtName->Buffer = NULL; 353 } 354 355 356 /** 357 * Frees the native path and root handle. 358 * 359 * @param pNtName The NT path after a successful 360 * RTNtPathFromWinUtf16Ex call. 361 * @param phRootDir The root handle variable after a successfull 362 * RTNtPathFromWinUtf16Ex call. 363 */ 364 RTDECL(void) RTNtPathFree(struct _UNICODE_STRING *pNtName, HANDLE *phRootDir) 365 { 366 rtNtPathFreeNative(pNtName, phRootDir); 187 367 } 188 368 -
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 } -
trunk/src/VBox/Runtime/r3/win/path-win.cpp
r48935 r52944 89 89 } 90 90 91 91 #if 0 92 92 /** 93 93 * Get the absolute path (no symlinks, no . or .. components), doesn't have to exit. … … 125 125 if (RT_SUCCESS(rc)) 126 126 { 127 # if 1 /** @todo This code is completely bonkers. */ 127 128 /* 128 129 * Remove trailing slash if the path may be pointing to a directory. … … 134 135 && !RTPATH_IS_SLASH(pszAbsPath[cch - 2])) 135 136 pszAbsPath[cch - 1] = '\0'; 137 # endif 136 138 } 137 139 } … … 144 146 return rc; 145 147 } 148 #endif 146 149 147 150 … … 684 687 } 685 688 689 690 RTDECL(int) RTPathGetCurrentOnDrive(char chDrive, char *pszPath, size_t cbPath) 691 { 692 WCHAR wszInput[4]; 693 wszInput[0] = chDrive; 694 wszInput[1] = ':'; 695 wszInput[2] = '\0'; 696 697 int rc; 698 RTUTF16 wszFullPath[RTPATH_MAX]; 699 if (GetFullPathNameW(wszInput, RTPATH_MAX, wszFullPath, NULL)) 700 rc = RTUtf16ToUtf8Ex(&wszFullPath[0], RTSTR_MAX, &pszPath, cbPath, NULL); 701 else 702 rc = RTErrConvertFromWin32(GetLastError()); 703 return rc; 704 } 705 -
trunk/src/VBox/Runtime/testcase/tstRTPath.cpp
r49084 r52944 315 315 { "C:\\temp", "D:\\data", VINF_SUCCESS, "D:\\data" }, 316 316 { NULL, "\\\\server\\..\\share", VINF_SUCCESS, "\\\\server\\..\\share" /* kind of strange */ }, 317 { NULL, "\\\\server/", VINF_SUCCESS, "\\\\server " },317 { NULL, "\\\\server/", VINF_SUCCESS, "\\\\server\\" }, 318 318 { NULL, "\\\\", VINF_SUCCESS, "\\\\" }, 319 319 { NULL, "\\\\\\something", VINF_SUCCESS, "\\\\\\something" /* kind of strange */ },
Note:
See TracChangeset
for help on using the changeset viewer.