Changeset 78399 in vbox for trunk/src/VBox
- Timestamp:
- May 6, 2019 6:09:47 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VMDK.cpp
r77773 r78399 5168 5168 * @param pszWhat UTF-8 string to search for. 5169 5169 * @param pszByWhat UTF-8 string to replace the found string with. 5170 * 5171 * @note r=bird: This is only used by vmdkRenameWorker(). The first use is 5172 * for updating the base name in the descriptor, the second is for 5173 * generating new filenames for extents. This code borked when 5174 * RTPathAbs started correcting the driver letter case on windows, 5175 * when strstr failed because the pExtent->pszFullname was not 5176 * subjected to RTPathAbs but while pExtent->pszFullname was. I fixed 5177 * this by apply RTPathAbs to the places it wasn't applied. 5178 * 5179 * However, this highlights some undocumented ASSUMPTIONS as well as 5180 * terrible short commings of the approach. 5181 * 5182 * Given the right filename, it may also screw up the descriptor. Take 5183 * the descriptor text 'RW 2048 SPARSE "Test0.vmdk"' for instance, 5184 * we'll be asked to replace "Test0" with something, no problem. No, 5185 * imagine 'RW 2048 SPARSE "SPARSE.vmdk"', 'RW 2048 SPARSE "RW.vmdk"' 5186 * or 'RW 2048 SPARSE "2048.vmdk"', and the strstr approach falls on 5187 * its bum. The descriptor string must be parsed and reconstructed, 5188 * the lazy strstr approach doesn't cut it. 5189 * 5190 * I'm also curious as to what would be the correct escaping of '"' in 5191 * the file name and how that is supposed to be handled, because it 5192 * needs to be or such names must be rejected in several places (maybe 5193 * they are, I didn't check). 5194 * 5195 * When this function is used to replace the start of a path, I think 5196 * the assumption from the prep/setup code is that we kind of knows 5197 * what we're working on (I could be wrong). However, using strstr 5198 * instead of strncmp/RTStrNICmp makes no sense and isn't future proof. 5199 * Especially on unix systems, weird stuff could happen if someone 5200 * unwittingly tinkers with the prep/setup code. What should really be 5201 * done here is using a new RTPathStartEx function that (via flags) 5202 * allows matching partial final component and returns the length of 5203 * what it matched up (in case it skipped slashes and '.' components). 5204 * 5170 5205 */ 5171 5206 static char *vmdkStrReplace(const char *pszWhere, const char *pszWhat, … … 5177 5212 const char *pszFoundStr = strstr(pszWhere, pszWhat); 5178 5213 if (!pszFoundStr) 5214 { 5215 LogFlowFunc(("Failed to find '%s' in '%s'!\n", pszWhat, pszWhere)); 5179 5216 return NULL; 5180 size_t cFinal = strlen(pszWhere) + 1 + strlen(pszByWhat) - strlen(pszWhat); 5181 char *pszNewStr = (char *)RTMemAlloc(cFinal); 5217 } 5218 size_t cbFinal = strlen(pszWhere) + 1 + strlen(pszByWhat) - strlen(pszWhat); 5219 char *pszNewStr = (char *)RTMemAlloc(cbFinal); 5182 5220 if (pszNewStr) 5183 5221 { … … 5376 5414 static int vmdkRenameStatePrepare(PVMDKIMAGE pImage, PVMDKRENAMESTATE pRenameState, const char *pszFilename) 5377 5415 { 5416 AssertReturn(RTPathFilename(pszFilename) != NULL, VERR_INVALID_PARAMETER); 5417 5378 5418 int rc = VINF_SUCCESS; 5379 5419 … … 5386 5426 */ 5387 5427 pRenameState->cExtents = pImage->cExtents; 5388 pRenameState->apszOldName = (char **)RTMemTmpAllocZ((pRenameState->cExtents + 1) * sizeof(char *));5389 pRenameState->apszNewName = (char **)RTMemTmpAllocZ((pRenameState->cExtents + 1) * sizeof(char *));5390 pRenameState->apszNewLines = (char **)RTMemTmpAllocZ(pRenameState->cExtents * sizeof(char *));5428 pRenameState->apszOldName = (char **)RTMemTmpAllocZ((pRenameState->cExtents + 1) * sizeof(char *)); 5429 pRenameState->apszNewName = (char **)RTMemTmpAllocZ((pRenameState->cExtents + 1) * sizeof(char *)); 5430 pRenameState->apszNewLines = (char **)RTMemTmpAllocZ(pRenameState->cExtents * sizeof(char *)); 5391 5431 if ( pRenameState->apszOldName 5392 5432 && pRenameState->apszNewName … … 5422 5462 /* Prepare both old and new base names used for string replacement. */ 5423 5463 pRenameState->pszNewBaseName = RTStrDup(RTPathFilename(pszFilename)); 5464 AssertReturn(pRenameState->pszNewBaseName, VERR_NO_STR_MEMORY); 5424 5465 RTPathStripSuffix(pRenameState->pszNewBaseName); 5466 5425 5467 pRenameState->pszOldBaseName = RTStrDup(RTPathFilename(pImage->pszFilename)); 5468 AssertReturn(pRenameState->pszOldBaseName, VERR_NO_STR_MEMORY); 5426 5469 RTPathStripSuffix(pRenameState->pszOldBaseName); 5427 /* Prepare both old and new full names used for string replacement. */ 5428 pRenameState->pszNewFullName = RTStrDup(pszFilename); 5470 5471 /* Prepare both old and new full names used for string replacement. 5472 Note! Must abspath the stuff here, so the strstr weirdness later in 5473 the renaming process get a match against abspath'ed extent paths. 5474 See RTPathAbsDup call in vmdkDescriptorReadSparse(). */ 5475 pRenameState->pszNewFullName = RTPathAbsDup(pszFilename); 5476 AssertReturn(pRenameState->pszNewFullName, VERR_NO_STR_MEMORY); 5429 5477 RTPathStripSuffix(pRenameState->pszNewFullName); 5430 pRenameState->pszOldFullName = RTStrDup(pImage->pszFilename); 5478 5479 pRenameState->pszOldFullName = RTPathAbsDup(pImage->pszFilename); 5480 AssertReturn(pRenameState->pszOldFullName, VERR_NO_STR_MEMORY); 5431 5481 RTPathStripSuffix(pRenameState->pszOldFullName); 5432 5482 5433 5483 /* Save the old name for easy access to the old descriptor file. */ 5434 5484 pRenameState->pszOldDescName = RTStrDup(pImage->pszFilename); 5485 AssertReturn(pRenameState->pszOldDescName, VERR_NO_STR_MEMORY); 5486 5435 5487 /* Save old image name. */ 5436 5488 pRenameState->pszOldImageName = pImage->pszFilename; … … 5438 5490 } 5439 5491 else 5440 rc = VERR_NO_ MEMORY;5492 rc = VERR_NO_TMP_MEMORY; 5441 5493 5442 5494 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.