Changeset 85384 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jul 18, 2020 9:17:43 PM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 139398
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/path/RTPathFindCommon.cpp
r85382 r85384 30 30 *********************************************************************************************************************************/ 31 31 #include "internal/iprt.h" 32 #include <iprt/path.h> 33 34 #include <iprt/alloca.h> 32 35 #include <iprt/assert.h> 33 36 #include <iprt/errcore.h> 34 #include <iprt/path.h> 37 #include <iprt/mem.h> 38 #include <iprt/string.h> 39 #include <iprt/uni.h> 40 41 42 #define RTPATH_TEMPLATE_CPP_H "RTPathFindCommon.cpp.h" 43 #include "rtpath-expand-template.cpp.h" 35 44 36 45 37 46 RTDECL(size_t) RTPathFindCommonEx(size_t cPaths, const char * const *papszPaths, uint32_t fFlags) 38 47 { 48 /* 49 * Validate input. 50 */ 51 AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, RTPATHFINDCOMMON_F_IGNORE_DOTDOT), 0); 39 52 AssertReturn(cPaths > 0, 0); 40 53 AssertPtrReturn(papszPaths, 0); 41 AssertReturn(RTPATH_STR_F_IS_VALID(fFlags, 0), 0); 54 size_t i = cPaths; 55 while (i-- > 0) 56 AssertPtrReturn(papszPaths[i], 0); 42 57 43 /** @todo r=bird: Extremely naive code. 44 * - The original idea of taking either '/' or '\\' as separators is very out of 45 * touch with the rest of path.h. On DOS based systems we need to handle both 46 * of those as well as ':'. 47 * - Why compare pszRef with itself? 48 * - Why derefernece pszRef[cch] for each other path. 49 * - Why perform NULL checks for each outer iteration. 50 * - Why perform '\0' check before comparing with pszRef[cch]? 51 * It's sufficient to check if pszRef[cch] is '\0'. 52 * - Why backtrack to the last path separator? It won't return the expected 53 * result for cPaths=1, unless the path ends with a separator. 54 * - Multiple consequtive path separators must be treated as a single one (most 55 * of the time anyways - UNC crap). 58 /* 59 * Duplicate papszPaths so we can have individual positions in each path. 60 * Use the stack if we haven't got too many paths. 56 61 */ 57 const char *pszRef = papszPaths[0]; /* The reference we're comparing with. */ 58 const char chNaiveSep = (fFlags & RTPATH_STR_F_STYLE_MASK) == RTPATH_STR_F_STYLE_HOST 59 ? RTPATH_SLASH 60 : (fFlags & RTPATH_STR_F_STYLE_MASK) == RTPATH_STR_F_STYLE_DOS ? '\\' : '/'; 62 void *pvFree; 63 const char **papszCopy; 64 size_t cbNeeded = cPaths * sizeof(papszCopy[0]); 65 if (cbNeeded <= _2K) 66 { 67 pvFree = NULL; 68 papszCopy = (const char **)alloca(cbNeeded); 69 } 70 else 71 { 72 pvFree = RTMemTmpAlloc(cbNeeded); 73 papszCopy = (const char **)pvFree; 74 } 75 AssertReturn(papszCopy, 0); 76 memcpy(papszCopy, papszPaths, cbNeeded); 61 77 62 size_t cch = 0; 63 do 78 /* 79 * Invoke the worker for the selected path style. 80 */ 81 size_t cchRet; 82 switch (fFlags & RTPATH_STR_F_STYLE_MASK) 64 83 { 65 for (size_t i = 0; i < cPaths; ++i) 66 { 67 const char *pcszPath = papszPaths[i]; 68 if ( pcszPath 69 && pcszPath[cch] 70 && pcszPath[cch] == pszRef[cch]) 71 continue; 84 #if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS 85 case RTPATH_STR_F_STYLE_HOST: 86 #endif 87 case RTPATH_STR_F_STYLE_DOS: 88 cchRet= rtPathFindCommonStyleDos(cPaths, papszCopy, fFlags); 89 break; 72 90 73 while ( cch 74 && pszRef[--cch] != chNaiveSep) { } 91 #if RTPATH_STYLE != RTPATH_STR_F_STYLE_DOS 92 case RTPATH_STR_F_STYLE_HOST: 93 #endif 94 case RTPATH_STR_F_STYLE_UNIX: 95 cchRet = rtPathFindCommonStyleUnix(cPaths, papszCopy, fFlags); 96 break; 75 97 76 return cch ? cch + 1 : 0;77 }78 } while (++cch);98 default: 99 AssertFailedStmt(cchRet = 0); /* impossible */ 100 } 79 101 80 return 0; 102 /* 103 * Clean up and return. 104 */ 105 if (pvFree) 106 RTMemTmpFree(pvFree); 107 return cchRet; 81 108 } 82 109 RT_EXPORT_SYMBOL(RTPathFindCommonEx); -
trunk/src/VBox/Runtime/testcase/tstRTPath.cpp
r85383 r85384 371 371 { { "", "", "", NULL, }, RTPATH_STR_F_STYLE_UNIX, 372 372 "" }, 373 { { "", "", "", NULL, }, RTPATH_STR_F_STYLE_DOS, 374 "" }, 373 375 { { "none", "none", "", NULL, }, RTPATH_STR_F_STYLE_UNIX, 374 376 "" }, 375 /* Missing start slash. */ 377 { { "none", "none", "", NULL, }, RTPATH_STR_F_STYLE_DOS, 378 "" }, 379 { { "same", "same", "same", "same", }, RTPATH_STR_F_STYLE_UNIX, 380 "same" }, 381 { { "same", "same", "same", "same", }, RTPATH_STR_F_STYLE_DOS, 382 "same" }, 383 /* More complicated. */ 376 384 { { "/path/to/stuff1", "path/to/stuff2", NULL, NULL, }, RTPATH_STR_F_STYLE_UNIX, 377 385 "" }, 378 /* Working stuff. */379 386 { { "/path/to/stuff1", "/path/to/stuff2", "/path/to/stuff3", NULL, }, RTPATH_STR_F_STYLE_UNIX, 380 387 "/path/to/" }, … … 382 389 "/path/" }, 383 390 { { "/path/to/stuff1", "/", "/path/", NULL, }, RTPATH_STR_F_STYLE_UNIX, 384 " " },391 "/" }, 385 392 { { "/path/to/../stuff1", "./../", "/path/to/stuff2/..", NULL, }, RTPATH_STR_F_STYLE_UNIX, 386 393 "" }, 387 388 #if 0 /** @todo */389 /* Things that should be working that aren't: */390 394 { { "a/single/path", NULL, NULL, NULL, }, RTPATH_STR_F_STYLE_UNIX, 391 395 "a/single/path" }, … … 396 400 { { "c:/windows", "c:\\program files", "C:\\AppData", NULL, }, RTPATH_STR_F_STYLE_DOS, 397 401 "c:/" }, 402 { { "c:/windows", "c:windows", "C:system32", NULL, }, RTPATH_STR_F_STYLE_DOS, 403 "c:" }, 404 { { "c:/windows", "d:windows", "e:windows", NULL, }, RTPATH_STR_F_STYLE_DOS, 405 "" }, 398 406 { { "//usr/bin/env", "/usr//bin/env", "/usr/bin///env", "/usr/bin/env", }, RTPATH_STR_F_STYLE_UNIX, 399 407 "//usr/bin/env" }, … … 404 412 { { "//./unc/is/weird", "///./unc/is/weird", NULL, NULL, }, RTPATH_STR_F_STYLE_DOS, 405 413 "" }, 414 { { "//system360/share", "//system370/share", "//system390/share", NULL, }, RTPATH_STR_F_STYLE_DOS, 415 "" }, 416 { { "//system370/share1", "//sysTEM370/share2", "//SYsTeM370/share3", NULL, }, RTPATH_STR_F_STYLE_DOS, 417 "//system370/" }, 418 { { "//system370/share1", "Z:/", NULL, NULL, }, RTPATH_STR_F_STYLE_DOS, 419 "" }, 420 { { "//system370/share1", "/", NULL, NULL, }, RTPATH_STR_F_STYLE_DOS, 421 "" }, 422 { { "//system370/share1", "somedir", NULL, NULL, }, RTPATH_STR_F_STYLE_DOS, 423 "" }, 406 424 { { "/path/to/stuff1", "path/to/stuff2", NULL, NULL, }, RTPATH_STR_F_STYLE_UNIX | RTPATH_STR_F_NO_START, 407 425 "/path/to/" }, 408 426 { { "path/to/stuff1", "//path\\/to\\stuff2", NULL, NULL, }, RTPATH_STR_F_STYLE_DOS | RTPATH_STR_F_NO_START, 409 427 "path/to/" }, 410 411 /* '..' elements are not supported for now and leads to zero return. */ 428 /* '..' elements are not supported for now and leads to zero return, unless RTPATHFINDCOMMON_F_IGNORE_DOTDOT is given. */ 412 429 { { "/usr/bin/env", "/usr/../usr/bin/env", "/usr/bin/../bin/env", NULL, }, RTPATH_STR_F_STYLE_UNIX, 413 430 "" }, 414 431 { { "/lib/", "/lib/amd64/../lib.so", "/lib/i386/../libdl.so", NULL, }, RTPATH_STR_F_STYLE_UNIX, 415 432 "" }, 416 #endif 433 { { "/lib/", "/lib/amd64/../lib.so", "/lib/i386/../libdl.so", NULL, }, RTPATH_STR_F_STYLE_UNIX | RTPATHFINDCOMMON_F_IGNORE_DOTDOT, 434 "/lib/" }, 417 435 }; 418 436
Note:
See TracChangeset
for help on using the changeset viewer.