- Timestamp:
- Jan 1, 2019 8:56:07 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/path.h
r76585 r76589 1086 1086 * terminator included. 1087 1087 * @param pszPathFrom The path to start from creating the relative path. 1088 * @param fFromFile Whether @a pszPathFrom is a file and we should work 1089 * relative to it's parent directory (@c true), or if 1090 * we should assume @a pszPathFrom is a directory and 1091 * work relative to it. 1088 1092 * @param pszPathTo The path to reach with the created relative path. 1089 1093 */ 1090 RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst, 1091 const char *pszPathFrom, 1092 const char *pszPathTo); 1094 RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst, const char *pszPathFrom, bool fFromFile, const char *pszPathTo); 1093 1095 1094 1096 #ifdef IN_RING3 -
trunk/src/VBox/Runtime/common/path/RTPathCalcRelative.cpp
r76553 r76589 31 31 #include "internal/iprt.h" 32 32 #include <iprt/path.h> 33 33 34 #include <iprt/assert.h> 35 #if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS 36 # include <iprt/ctype.h> 37 #endif 34 38 #include <iprt/err.h> 35 39 #include <iprt/string.h> … … 39 43 40 44 RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst, 41 const char *pszPathFrom, 45 const char *pszPathFrom, bool fFromFile, 42 46 const char *pszPathTo) 43 47 { 44 int rc = VINF_SUCCESS;45 46 48 AssertPtrReturn(pszPathDst, VERR_INVALID_POINTER); 47 49 AssertReturn(cbPathDst, VERR_INVALID_PARAMETER); 48 50 AssertPtrReturn(pszPathFrom, VERR_INVALID_POINTER); 49 51 AssertPtrReturn(pszPathTo, VERR_INVALID_POINTER); 50 AssertReturn(RTPathStartsWithRoot(pszPathFrom), VERR_INVALID_PARAMETER);51 AssertReturn(RTPathStartsWithRoot(pszPathTo), VERR_INVALID_PARAMETER);52 AssertReturn(RTStrCmp(pszPathFrom, pszPathTo), VERR_INVALID_PARAMETER);53 52 54 53 /* 55 54 * Check for different root specifiers (drive letters), creating a relative path doesn't work here. 56 * @todo: How to handle case insensitive root specifiers correctly?57 55 */ 58 56 size_t offRootFrom = rtPathRootSpecLen(pszPathFrom); 57 AssertReturn(offRootFrom > 0, VERR_INVALID_PARAMETER); 58 59 59 size_t offRootTo = rtPathRootSpecLen(pszPathTo); 60 61 if ( offRootFrom != offRootTo 62 || RTStrNCmp(pszPathFrom, pszPathTo, offRootFrom)) 60 AssertReturn(offRootTo > 0, VERR_INVALID_PARAMETER); 61 62 63 /** @todo correctly deal with extra root slashes! */ 64 if (offRootFrom != offRootTo) 63 65 return VERR_NOT_SUPPORTED; 64 66 65 /* Filter out the parent path which is equal to both paths. */ 66 while ( *pszPathFrom == *pszPathTo 67 && *pszPathFrom != '\0' 68 && *pszPathTo != '\0') 69 { 70 pszPathFrom++; 71 pszPathTo++; 72 } 67 #if RTPATH_STYLE != RTPATH_STR_F_STYLE_DOS 68 if (RTStrNCmp(pszPathFrom, pszPathTo, offRootFrom)) 69 return VERR_NOT_SUPPORTED; 70 #else 71 if (RTStrNICmp(pszPathFrom, pszPathTo, offRootFrom)) 72 for (size_t off = 0; off < offRootFrom; off++) 73 { 74 char const chFrom = pszPathFrom[off]; 75 char const chTo = pszPathTo[off]; 76 if ( chFrom != chTo 77 && RT_C_TO_LOWER(chFrom) != RT_C_TO_LOWER(chTo) /** @todo proper case insensitivity! */ 78 && (!RTPATH_IS_SLASH(chFrom) || !RTPATH_IS_SLASH(chTo)) ) 79 return VERR_NOT_SUPPORTED; 80 } 81 #endif 82 83 pszPathFrom += offRootFrom; 84 pszPathTo += offRootTo; 73 85 74 86 /* 75 * Because path components can start with an equal string but differ afterwards we 76 * need to go back to the beginning of the current component. 87 * Skip out the part of the path which is equal to both. 77 88 */ 78 while (!RTPATH_IS_SEP(*pszPathFrom)) 79 pszPathFrom--; 80 81 pszPathFrom++; /* Skip path separator. */ 82 83 while (!RTPATH_IS_SEP(*pszPathTo)) 84 pszPathTo--; 85 86 pszPathTo++; /* Skip path separator. */ 89 const char *pszStartOfFromComp = pszPathFrom; 90 for (;;) 91 { 92 char const chFrom = *pszPathFrom; 93 char const chTo = *pszPathTo; 94 if (!RTPATH_IS_SLASH(chFrom)) 95 { 96 if (chFrom == chTo) 97 { 98 if (chFrom) 99 { /* likely */ } 100 else 101 { 102 /* Special case: The two paths are equal. */ 103 if (fFromFile) 104 { 105 size_t cchComp = pszPathFrom - pszStartOfFromComp; 106 if (cchComp < cbPathDst) 107 { 108 memcpy(pszPathDst, pszStartOfFromComp, cchComp); 109 pszPathDst[cchComp] = '\0'; 110 return VINF_SUCCESS; 111 } 112 } 113 else if (sizeof(".") <= cbPathDst) 114 { 115 memcpy(pszPathDst, ".", sizeof(".")); 116 return VINF_SUCCESS; 117 } 118 return VERR_BUFFER_OVERFLOW; 119 } 120 } 121 #if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS 122 else if (RT_C_TO_LOWER(chFrom) == RT_C_TO_LOWER(chTo)) 123 { /* if not likely, then simpler code structure wise. */ } 124 #endif 125 else if (chFrom != '\0' || !RTPATH_IS_SLASH(chTo) || fFromFile) 126 break; 127 else 128 { 129 pszStartOfFromComp = pszPathFrom; 130 do 131 pszPathTo++; 132 while (RTPATH_IS_SLASH(*pszPathTo)); 133 break; 134 } 135 pszPathFrom++; 136 pszPathTo++; 137 } 138 else if (RTPATH_IS_SLASH(chTo)) 139 { 140 /* Both have slashes. Skip any additional ones before taking down 141 the start of the component for rewinding purposes. */ 142 do 143 pszPathTo++; 144 while (RTPATH_IS_SLASH(*pszPathTo)); 145 do 146 pszPathFrom++; 147 while (RTPATH_IS_SLASH(*pszPathFrom)); 148 pszStartOfFromComp = pszPathFrom; 149 } 150 else 151 break; 152 } 153 154 /* Rewind to the start of the current component. */ 155 pszPathTo -= pszPathFrom - pszStartOfFromComp; 156 pszPathFrom = pszStartOfFromComp; 87 157 88 158 /* Paths point to the first non equal component now. */ 89 char aszPathTmp[RTPATH_MAX + 1]; 90 unsigned offPathTmp = 0; 159 160 /* 161 * Constructure the relative path. 162 */ 91 163 92 164 /* Create the part to go up from pszPathFrom. */ 165 unsigned offDst = 0; 166 167 if (!fFromFile && *pszPathFrom != '\0') 168 { 169 if (offDst + 3 < cbPathDst) 170 { 171 pszPathDst[offDst++] = '.'; 172 pszPathDst[offDst++] = '.'; 173 pszPathDst[offDst++] = RTPATH_SLASH; 174 } 175 else 176 return VERR_BUFFER_OVERFLOW; 177 } 178 93 179 while (*pszPathFrom != '\0') 94 180 { 95 while ( !RTPATH_IS_SEP(*pszPathFrom) 96 && *pszPathFrom != '\0') 181 char ch; 182 while ( (ch = *pszPathFrom) != '\0' 183 && !RTPATH_IS_SLASH(*pszPathFrom)) 97 184 pszPathFrom++; 98 99 if (RTPATH_IS_SEP(*pszPathFrom)) 100 { 101 if (offPathTmp + 3 >= sizeof(aszPathTmp) - 1) 102 return VERR_FILENAME_TOO_LONG; 103 aszPathTmp[offPathTmp++] = '.'; 104 aszPathTmp[offPathTmp++] = '.'; 105 aszPathTmp[offPathTmp++] = RTPATH_SLASH; 185 while ( (ch = *pszPathFrom) != '\0' 186 && RTPATH_IS_SLASH(ch)) 106 187 pszPathFrom++; 107 } 108 } 109 110 aszPathTmp[offPathTmp] = '\0'; 188 if (!ch) 189 break; 190 191 if (offDst + 3 < cbPathDst) 192 { 193 pszPathDst[offDst++] = '.'; 194 pszPathDst[offDst++] = '.'; 195 pszPathDst[offDst++] = RTPATH_SLASH; 196 } 197 else 198 return VERR_BUFFER_OVERFLOW; 199 } 111 200 112 201 /* Now append the rest of pszPathTo to the final path. */ 113 char *pszPathTmp = &aszPathTmp[offPathTmp]; 114 size_t cbPathTmp = sizeof(aszPathTmp) - offPathTmp - 1; 115 rc = RTStrCatP(&pszPathTmp, &cbPathTmp, pszPathTo); 116 if (RT_SUCCESS(rc)) 117 { 118 *pszPathTmp = '\0'; 119 120 size_t cchPathTmp = strlen(aszPathTmp); 121 if (cchPathTmp >= cbPathDst) 122 return VERR_BUFFER_OVERFLOW; 123 memcpy(pszPathDst, aszPathTmp, cchPathTmp + 1); 124 } 125 else 126 rc = VERR_FILENAME_TOO_LONG; 127 128 return rc; 202 size_t cchTo = strlen(pszPathTo); 203 if (offDst + cchTo <= cbPathDst) 204 { 205 memcpy(&pszPathDst[offDst], pszPathTo, cchTo); 206 pszPathDst[offDst + cchTo] = '\0'; 207 return VINF_SUCCESS; 208 } 209 return VERR_BUFFER_OVERFLOW; 129 210 } 130 211 -
trunk/src/VBox/Runtime/testcase/tstRTPath.cpp
r76553 r76589 742 742 { 743 743 const char *pszFrom; 744 bool fFromFile; 744 745 const char *pszTo; 745 746 int rc; … … 747 748 } s_aRelPath[] = 748 749 { 749 { "/home/test.ext", "/home/test2.ext", VINF_SUCCESS, "test2.ext"}, 750 { "/dir/test.ext", "/dir/dir2/test2.ext", VINF_SUCCESS, "dir2/test2.ext"}, 751 { "/dir/dir2/test.ext", "/dir/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "test2.ext"}, 752 { "/dir/dir2/test.ext", "/dir/dir3/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext"}, 750 { "/home/test.ext", true, "/home/test2.ext", VINF_SUCCESS, "test2.ext" }, 751 { "/dir/test.ext", true, "/dir/dir2/test2.ext", VINF_SUCCESS, "dir2/test2.ext" }, 752 { "/dir/dir2/test.ext", true, "/dir/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "test2.ext" }, 753 { "/dir/dir2/test.ext", true, "/dir/dir3/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext" }, 754 { "/dir/dir2", false, "/dir/dir3/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext" }, 755 { "/dir/dir2", false, "/dir/dir3//test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3//test2.ext" }, 756 { "/dir/dir2/", false, "/dir/dir3/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext" }, 757 { "/dir/dir2////", false, "/dir//dir3/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext" }, 758 { "/include/iprt", false, "/include/iprt/cdefs.h", VINF_SUCCESS, "cdefs.h" }, 759 { "/include/iprt/", false, "/include/iprt/cdefs.h", VINF_SUCCESS, "cdefs.h" }, 760 { "/include/iprt/tt.h", true, "/include/iprt/cdefs.h", VINF_SUCCESS, "cdefs.h" }, 753 761 #if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS) 754 { "\\\\server\\share\\test.ext", "\\\\server\\share2\\test2.ext", VERR_NOT_SUPPORTED, ""}, 755 { "c:\\dir\\test.ext", "f:\\dir\\test.ext", VERR_NOT_SUPPORTED, ""} 762 { "\\\\server\\share\\test.ext", true, "\\\\server\\share2\\test2.ext", VERR_NOT_SUPPORTED, "" }, 763 { "c:\\dir\\test.ext", true, "f:\\dir\\test.ext", VERR_NOT_SUPPORTED, "" }, 764 { "F:\\dir\\test.ext", false, "f:/dir//test.ext", VINF_SUCCESS, "." } , 765 { "F:\\dir\\test.ext", true, "f:/dir//test.ext", VINF_SUCCESS, "test.ext" } , 756 766 #endif 757 767 }; 758 768 for (unsigned i = 0; i < RT_ELEMENTS(s_aRelPath); i++) 759 769 { 760 const char *pszFrom = s_aRelPath[i].pszFrom; 761 const char *pszTo = s_aRelPath[i].pszTo; 762 763 rc = RTPathCalcRelative(szPath, sizeof(szPath), pszFrom, pszTo); 770 const char *pszFrom = s_aRelPath[i].pszFrom; 771 bool fFromFile = s_aRelPath[i].fFromFile; 772 const char *pszTo = s_aRelPath[i].pszTo; 773 774 rc = RTPathCalcRelative(szPath, sizeof(szPath), pszFrom, fFromFile, pszTo); 764 775 if (rc != s_aRelPath[i].rc) 765 RTTestIFailed("Unexpected return code \n"776 RTTestIFailed("Unexpected return code for %s .. %s\n" 766 777 " got: %Rrc\n" 767 778 "expected: %Rrc", 768 rc, s_aRelPath[i].rc);779 pszFrom, pszTo, rc, s_aRelPath[i].rc); 769 780 else if ( RT_SUCCESS(rc) 770 781 && strcmp(szPath, s_aRelPath[i].pszExpected)) 771 782 RTTestIFailed("Unexpected result\n" 772 " from: '%s' \n"783 " from: '%s' (%s)\n" 773 784 " to: '%s'\n" 774 785 " output: '%s'\n" 775 786 "expected: '%s'", 776 pszFrom, pszTo, szPath, s_aRelPath[i].pszExpected);787 pszFrom, fFromFile ? "file" : "dir", pszTo, szPath, s_aRelPath[i].pszExpected); 777 788 } 778 789 -
trunk/src/VBox/Runtime/tools/RTDbgSymCache.cpp
r76553 r76589 240 240 char szLinkTarget[RTPATH_MAX]; 241 241 //szMapPath[cch] = '\0'; 242 rc = RTPathCalcRelative(szLinkTarget, sizeof(szLinkTarget), szMapPath, pszCacheFile);242 rc = RTPathCalcRelative(szLinkTarget, sizeof(szLinkTarget), szMapPath, false /*fFromFile*/, pszCacheFile); 243 243 //szMapPath[cch] = RTPATH_SLASH; 244 244 if (RT_FAILURE(rc)) -
trunk/src/VBox/Storage/VHD.cpp
r76553 r76589 331 331 /* Convert to relative path. */ 332 332 char szPath[RTPATH_MAX]; 333 rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename, 334 pszFilename); 333 rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename, true /*fFromFile*/, pszFilename); 335 334 if (RT_SUCCESS(rc)) 336 335 { … … 374 373 /* Convert to relative path. */ 375 374 char szPath[RTPATH_MAX]; 376 rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename, 377 pszFilename); 375 rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename, true /*fFromFile*/, pszFilename); 378 376 if (RT_SUCCESS(rc)) 379 377 rc = vhdFilenameToUtf16(szPath, (uint16_t *)pvBuf, cbMaxLen, &cb, false); -
trunk/src/bldprogs/scmrw.cpp
r76572 r76589 2896 2896 else 2897 2897 rc = RTPathCalcRelative(&szNormalized[cchNormalized], sizeof(szNormalized) - cchNormalized, 2898 pSettings->pszGuardRelativeToDir, pState->pszFilename);2898 pSettings->pszGuardRelativeToDir, false /*fFromFile*/, pState->pszFilename); 2899 2899 if (RT_FAILURE(rc)) 2900 2900 return ScmError(pState, rc, "Error calculating guard prefix (RTPathCalcRelative): %Rrc\n", rc);
Note:
See TracChangeset
for help on using the changeset viewer.