Changeset 75475 in vbox for trunk/src/VBox/ImageMounter/vboxraw/vboxraw.cpp
- Timestamp:
- Nov 15, 2018 5:24:47 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ImageMounter/vboxraw/vboxraw.cpp
r75266 r75475 21 21 *********************************************************************************************************************************/ 22 22 #define LOG_GROUP LOG_GROUP_DEFAULT /** @todo log group */ 23 #define UNUSED(x) (void)(x)24 23 25 24 #define FUSE_USE_VERSION 27 … … 49 48 #include <VBox/com/VirtualBox.h> 50 49 #include <VBox/vd.h> 50 #include <VBox/vd-ifs.h> 51 51 #include <VBox/log.h> 52 52 #include <VBox/err.h> … … 60 60 61 61 #include <iprt/initterm.h> 62 #include <iprt/critsect.h>63 62 #include <iprt/assert.h> 64 63 #include <iprt/message.h> 64 #include <iprt/critsect.h> 65 65 #include <iprt/asm.h> 66 66 #include <iprt/mem.h> … … 71 71 #include <iprt/path.h> 72 72 73 #pragma GCC diagnostic ignored "-Wunused-variable" 74 #pragma GCC diagnostic ignored "-Wunused-parameter" 75 #pragma GCC diagnostic ignored "-Wunused-function" 76 73 77 using namespace com; 74 78 … … 85 89 86 90 87 /** The VDRead/VDWrite block granularity. */ 88 #define VBoxRAW_MIN_SIZE 512 89 /** Offset mask corresponding to VBoxRAW_MIN_SIZE. */ 90 #define VBoxRAW_MIN_SIZE_MASK_OFF (0x1ff) 91 /** Block mask corresponding to VBoxRAW_MIN_SIZE. */ 92 #define VBoxRAW_MIN_SIZE_MASK_BLK (~UINT64_C(0x1ff)) 93 94 #define PADMAX 50 95 #define MAX_ID_LEN 256 96 #define CSTR(arg) Utf8Str(arg).c_str() 91 #define VD_SECTOR_SIZE 0x200 /* 0t512 */ 92 #define VD_SECTOR_MASK (VD_SECTOR_SIZE - 1) 93 #define VD_SECTOR_OUT_OF_BOUNDS_MASK (~UINT64_C(VD_SECTOR_MASK)) 94 95 #define PADMAX 50 96 #define MAX_ID_LEN 256 97 #define CSTR(arg) Utf8Str(arg).c_str() 97 98 98 99 static struct fuse_operations g_vboxrawOps; 99 PVDISK g_pVDisk; 100 int32_t g_cReaders; 101 int32_t g_cWriters; 102 RTFOFF g_cbPrimary; 103 char *g_pszBaseImageName; 104 char *g_pszBaseImagePath; 100 PVDISK g_pVDisk; 101 int32_t g_cReaders; 102 int32_t g_cWriters; 103 RTFOFF g_cbPrimary; 104 char *g_pszBaseImageName; 105 char *g_pszBaseImagePath; 106 PVDINTERFACE g_pVdIfs; /** @todo Remove when VD I/O becomes threadsafe */ 107 VDINTERFACETHREADSYNC g_VDIfThreadSync; /** @todo Remove when VD I/O becomes threadsafe */ 108 RTCRITSECT g_vdioLock; /** @todo Remove when VD I/O becomes threadsafe */ 105 109 106 110 char *nsIDToString(nsID *guid); … … 109 113 110 114 static struct vboxrawOpts { 111 char *pszVm;112 char *pszImage;113 char *pszImageUuid;115 char *pszVm; 116 char *pszImage; 117 char *pszImageUuid; 114 118 uint32_t cHddImageDiffMax; 115 119 uint32_t fList; … … 235 239 } 236 240 241 /** @todo Remove when VD I/O becomes threadsafe */ 242 static DECLCALLBACK(int) vboxrawThreadStartRead(void *pvUser) 243 { 244 PRTCRITSECT vdioLock = (PRTCRITSECT)pvUser; 245 return RTCritSectEnter(vdioLock); 246 } 247 248 static DECLCALLBACK(int) vboxrawThreadFinishRead(void *pvUser) 249 { 250 PRTCRITSECT vdioLock = (PRTCRITSECT)pvUser; 251 return RTCritSectLeave(vdioLock); 252 } 253 254 static DECLCALLBACK(int) vboxrawThreadStartWrite(void *pvUser) 255 { 256 PRTCRITSECT vdioLock = (PRTCRITSECT)pvUser; 257 return RTCritSectEnter(vdioLock); 258 } 259 260 static DECLCALLBACK(int) vboxrawThreadFinishWrite(void *pvUser) 261 { 262 PRTCRITSECT vdioLock = (PRTCRITSECT)pvUser; 263 return RTCritSectLeave(vdioLock); 264 } 265 266 /** @todo (end of to do section) */ 267 237 268 /** @copydoc fuse_operations::release */ 238 269 static int vboxrawOp_release(const char *pszPath, struct fuse_file_info *pInfo) … … 260 291 } 261 292 262 static int retryableVDRead(PVDISK pvDisk, uint64_t offset, void *pvBuf, size_t cbRead) 263 { 264 int rc = -1; 265 int cRetry = 5; 266 do 267 { 268 if (cRetry < 5) 269 Log(("(rc=%d retrying read)\n", rc)); 270 rc = VDRead(pvDisk, offset, pvBuf, cbRead); 271 } while (RT_FAILURE(rc) && --cRetry); 272 return rc; 273 } 293 294 /** 295 * VD read Sanitizer taking care of unaligned accesses. 296 * 297 * @return VBox status code. 298 * @param pDisk VD disk container. 299 * @param off Offset to start reading from. 300 * @param pvBuf Pointer to the buffer to read into. 301 * @param cbRead Amount of bytes to read. 302 */ 303 static int vdReadSanitizer(PVDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead) 304 { 305 int rc; 306 307 uint64_t const cbMisalignHead = off & VD_SECTOR_MASK; 308 uint64_t const cbcbMisalignTail = (off + cbRead) & VD_SECTOR_MASK; 309 310 if (cbMisalignHead + cbcbMisalignTail == 0) /* perfectly aligned request; just read it and done */ 311 rc = VDRead(pDisk, off, pvBuf, cbRead); 312 else 313 { 314 uint8_t *pbBuf = (uint8_t *)pvBuf; 315 uint8_t abBuf[VD_SECTOR_SIZE]; 316 317 /* If offset not @ sector boundary, read whole sector, then copy unaligned 318 * bytes (requested by user), only up to sector boundary, into user's buffer 319 */ 320 if (cbMisalignHead) 321 { 322 rc = VDRead(pDisk, off - cbMisalignHead, abBuf, VD_SECTOR_SIZE); 323 if (RT_SUCCESS(rc)) 324 { 325 size_t const cbPart = RT_MIN(VD_SECTOR_SIZE - cbMisalignHead, cbRead); 326 memcpy(pbBuf, &abBuf[cbMisalignHead], cbPart); 327 pbBuf += cbPart; 328 off += cbPart; /* Beginning of next sector or EOD */ 329 cbRead -= cbPart; /* # left to read */ 330 } 331 } 332 else /* user's offset already aligned, did nothing */ 333 rc = VINF_SUCCESS; 334 335 /* Read remaining aligned sectors, deferring any tail-skewed bytes */ 336 if (RT_SUCCESS(rc) && cbRead >= VD_SECTOR_SIZE) 337 { 338 Assert(!(off % VD_SECTOR_SIZE)); 339 340 size_t cbPart = cbRead - cbcbMisalignTail; 341 Assert(!(cbPart % VD_SECTOR_SIZE)); 342 rc = VDRead(pDisk, off, pbBuf, cbPart); 343 if (RT_SUCCESS(rc)) 344 { 345 pbBuf += cbPart; 346 off += cbPart; 347 cbRead -= cbPart; 348 } 349 } 350 351 /* Unaligned buffered read of tail. */ 352 if (RT_SUCCESS(rc) && cbRead) 353 { 354 Assert(cbRead == cbcbMisalignTail); 355 Assert(cbRead < VD_SECTOR_SIZE); 356 Assert(!(off % VD_SECTOR_SIZE)); 357 358 rc = VDRead(pDisk, off, abBuf, VD_SECTOR_SIZE); 359 if (RT_SUCCESS(rc)) 360 memcpy(pbBuf, abBuf, cbRead); 361 } 362 } 363 364 if (RT_FAILURE(rc)) 365 { 366 int sysrc = -RTErrConvertToErrno(rc); 367 LogFlowFunc(("error: %s (vbox err: %d)\n", strerror(sysrc), rc)); 368 rc = sysrc; 369 } 370 return cbRead; 371 } 372 373 /** 374 * VD write Sanitizer taking care of unaligned accesses. 375 * 376 * @return VBox status code. 377 * @param pDisk VD disk container. 378 * @param off Offset to start writing to. 379 * @param pvSrc Pointer to the buffer to read from. 380 * @param cbWrite Amount of bytes to write. 381 */ 382 static int vdWriteSanitizer(PVDISK pDisk, uint64_t off, const void *pvSrc, size_t cbWrite) 383 { 384 uint8_t const *pbSrc = (uint8_t const *)pvSrc; 385 uint8_t abBuf[4096]; 386 int rc; 387 int cbRemaining = cbWrite; 388 /* 389 * Take direct route if the request is sector aligned. 390 */ 391 uint64_t const cbMisalignHead = off & 511; 392 size_t const cbcbMisalignTail = (off + cbWrite) & 511; 393 if (!cbMisalignHead && !cbcbMisalignTail) 394 { 395 rc = VDWrite(pDisk, off, pbSrc, cbWrite); 396 do 397 { 398 size_t cbThisWrite = RT_MIN(cbWrite, sizeof(abBuf)); 399 rc = VDWrite(pDisk, off, memcpy(abBuf, pbSrc, cbThisWrite), cbThisWrite); 400 if (RT_SUCCESS(rc)) 401 { 402 pbSrc += cbThisWrite; 403 off += cbThisWrite; 404 cbRemaining -= cbThisWrite; 405 } 406 else 407 break; 408 } while (cbRemaining > 0); 409 } 410 else 411 { 412 /* 413 * Unaligned buffered read+write of head. Aligns the offset. 414 */ 415 if (cbMisalignHead) 416 { 417 rc = VDRead(pDisk, off - cbMisalignHead, abBuf, VD_SECTOR_SIZE); 418 if (RT_SUCCESS(rc)) 419 { 420 size_t const cbPart = RT_MIN(VD_SECTOR_SIZE - cbMisalignHead, cbWrite); 421 memcpy(&abBuf[cbMisalignHead], pbSrc, cbPart); 422 rc = VDWrite(pDisk, off - cbMisalignHead, abBuf, VD_SECTOR_SIZE); 423 if (RT_SUCCESS(rc)) 424 { 425 pbSrc += cbPart; 426 off += cbPart; 427 cbRemaining -= cbPart; 428 } 429 } 430 } 431 else 432 rc = VINF_SUCCESS; 433 434 /* 435 * Aligned direct write. 436 */ 437 if (RT_SUCCESS(rc) && cbWrite >= VD_SECTOR_SIZE) 438 { 439 Assert(!(off % VD_SECTOR_SIZE)); 440 size_t cbPart = cbWrite - cbcbMisalignTail; 441 Assert(!(cbPart % VD_SECTOR_SIZE)); 442 rc = VDWrite(pDisk, off, pbSrc, cbPart); 443 if (RT_SUCCESS(rc)) 444 { 445 pbSrc += cbPart; 446 off += cbPart; 447 cbRemaining -= cbPart; 448 } 449 } 450 451 /* 452 * Unaligned buffered read + write of tail. 453 */ 454 if ( RT_SUCCESS(rc) && cbWrite > 0) 455 { 456 Assert(cbWrite == cbcbMisalignTail); 457 Assert(cbWrite < VD_SECTOR_SIZE); 458 Assert(!(off % VD_SECTOR_SIZE)); 459 rc = VDRead(pDisk, off, abBuf, VD_SECTOR_SIZE); 460 if (RT_SUCCESS(rc)) 461 { 462 memcpy(abBuf, pbSrc, cbWrite); 463 rc = VDWrite(pDisk, off, abBuf, VD_SECTOR_SIZE); 464 } 465 } 466 } 467 if (RT_FAILURE(rc)) 468 { 469 int sysrc = -RTErrConvertToErrno(rc); 470 LogFlowFunc(("error: %s (vbox err: %d)\n", strerror(sysrc), rc)); 471 return sysrc; 472 } 473 return cbWrite - cbRemaining; 474 } 475 274 476 275 477 /** @copydoc fuse_operations::read */ … … 277 479 off_t offset, struct fuse_file_info *pInfo) 278 480 { 279 280 481 (void) pszPath; 281 482 (void) pInfo; … … 283 484 LogFlowFunc(("my offset=%#llx size=%#zx path=\"%s\"\n", (uint64_t)offset, cbBuf, pszPath)); 284 485 285 /* paranoia */486 AssertReturn(offset >= 0, -EINVAL); 286 487 AssertReturn((int)cbBuf >= 0, -EINVAL); 287 488 AssertReturn((unsigned)cbBuf == cbBuf, -EINVAL); 288 AssertReturn(offset >= 0, -EINVAL); 289 AssertReturn((off_t)(offset + cbBuf) >= offset, -EINVAL); 290 291 int rc; 489 490 int rc = 0; 292 491 if ((off_t)(offset + cbBuf) < offset) 293 492 rc = -EINVAL; 294 493 else if (offset >= g_cbPrimary) 295 r c =0;494 return 0; 296 495 else if (!cbBuf) 297 rc = 0; 298 else 299 { 300 /* Adjust for EOF. */ 301 if ((off_t)(offset + cbBuf) >= g_cbPrimary) 302 cbBuf = g_cbPrimary - offset; 303 304 /* 305 * Aligned read? 306 */ 307 int rc2; 308 if ( !(offset & VBoxRAW_MIN_SIZE_MASK_OFF) 309 && !(cbBuf & VBoxRAW_MIN_SIZE_MASK_OFF)) 310 { 311 rc2 = retryableVDRead(g_pVDisk, offset, pbBuf, cbBuf); 312 if (RT_FAILURE(rc2)) 313 { 314 rc = -RTErrConvertToErrno(rc2); 315 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 316 return rc; 317 } 318 } 319 else 320 { 321 /* 322 * Unaligned read - lots of extra work. 323 */ 324 uint8_t abBlock[VBoxRAW_MIN_SIZE]; 325 if (((offset + cbBuf) & VBoxRAW_MIN_SIZE_MASK_BLK) == (offset & VBoxRAW_MIN_SIZE_MASK_BLK)) 326 { 327 /* a single partial block. */ 328 rc2 = retryableVDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE); 329 if (RT_SUCCESS(rc2)) 330 { 331 memcpy(pbBuf, &abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], cbBuf); 332 } 333 else 334 { 335 rc = -RTErrConvertToErrno(rc2); 336 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 337 return rc; 338 } 339 } 340 else 341 { 342 /* read unaligned head. */ 343 rc2 = VINF_SUCCESS; 344 if (offset & VBoxRAW_MIN_SIZE_MASK_OFF) 345 { 346 rc2 = retryableVDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE); 347 if (RT_SUCCESS(rc2)) 348 { 349 size_t cbCopy = VBoxRAW_MIN_SIZE - (offset & VBoxRAW_MIN_SIZE_MASK_OFF); 350 memcpy(pbBuf, &abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], cbCopy); 351 pbBuf += cbCopy; 352 offset += cbCopy; 353 cbBuf -= cbCopy; 354 } 355 else 356 { 357 rc = -RTErrConvertToErrno(rc2); 358 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 359 return rc; 360 } 361 } 362 363 /* read the middle. */ 364 Assert(!(offset & VBoxRAW_MIN_SIZE_MASK_OFF)); 365 if (cbBuf >= VBoxRAW_MIN_SIZE && RT_SUCCESS(rc2)) 366 { 367 size_t cbRead = cbBuf & VBoxRAW_MIN_SIZE_MASK_BLK; 368 rc2 = retryableVDRead(g_pVDisk, offset, pbBuf, cbRead); 369 if (RT_SUCCESS(rc2)) 370 { 371 pbBuf += cbRead; 372 offset += cbRead; 373 cbBuf -= cbRead; 374 } 375 else 376 { 377 rc = -RTErrConvertToErrno(rc2); 378 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 379 return rc; 380 } 381 } 382 383 /* unaligned tail read. */ 384 Assert(cbBuf < VBoxRAW_MIN_SIZE); 385 Assert(!(offset & VBoxRAW_MIN_SIZE_MASK_OFF)); 386 if (cbBuf && RT_SUCCESS(rc2)) 387 { 388 rc2 = retryableVDRead(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE); 389 if (RT_SUCCESS(rc2)) { 390 memcpy(pbBuf, &abBlock[0], cbBuf); 391 } 392 else 393 { 394 rc = -RTErrConvertToErrno(rc2); 395 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 396 return rc; 397 } 398 } 399 } 400 } 401 402 /* convert the return code */ 403 if (RT_SUCCESS(rc2)) 404 rc = cbBuf; 405 else 406 { 407 rc = -RTErrConvertToErrno(rc2); 408 LogFlowFunc(("Error rc2=%d, rc=%d=%s\n", rc2, rc, strerror(rc))); 409 } 410 return rc; 411 } 496 return 0; 497 498 if (rc >= 0) 499 rc = vdReadSanitizer(g_pVDisk, offset, pbBuf, cbBuf); 500 if (rc < 0) 501 LogFlowFunc(("%s\n", strerror(rc))); 412 502 return rc; 413 503 } 414 504 415 /** @ copydocfuse_operations::write */505 /** @… fuse_operations::write */ 416 506 static int vboxrawOp_write(const char *pszPath, const char *pbBuf, size_t cbBuf, 417 507 off_t offset, struct fuse_file_info *pInfo) 418 508 { 419 420 509 (void) pszPath; 421 510 (void) pInfo; 422 511 423 512 LogFlowFunc(("offset=%#llx size=%#zx path=\"%s\"\n", (uint64_t)offset, cbBuf, pszPath)); 513 514 AssertReturn(offset >= 0, -EINVAL); 424 515 AssertReturn((int)cbBuf >= 0, -EINVAL); 425 516 AssertReturn((unsigned)cbBuf == cbBuf, -EINVAL); 426 AssertReturn(offset >= 0, -EINVAL); 427 AssertReturn((off_t)(offset + cbBuf) >= offset, -EINVAL); 428 429 430 LogFlowFunc(("offset=%#llx size=%#zx path=\"%s\"\n", (uint64_t)offset, cbBuf, pszPath)); 431 432 int rc; 433 if (!g_vboxrawOpts.fRW) 434 rc = -EPERM; 435 else if ((off_t)(offset + cbBuf) < offset) 517 518 int rc = 0; 519 if (!g_vboxrawOpts.fRW) { 520 LogFlowFunc(("WARNING: vboxraw (FUSE FS) --rw option not specified\n" 521 " (write operation ignored w/o error!)\n")); 522 return cbBuf; 523 } else if ((off_t)(offset + cbBuf) < offset) 436 524 rc = -EINVAL; 437 525 else if (offset >= g_cbPrimary) 438 r c =0;526 return 0; 439 527 else if (!cbBuf) 440 rc = 0; 441 else 442 { 443 /* Adjust for EOF. */ 444 if ((off_t)(offset + cbBuf) >= g_cbPrimary) 445 cbBuf = g_cbPrimary - offset; 446 447 /* 448 * Aligned write? 449 */ 450 int rc2; 451 if ( !(offset & VBoxRAW_MIN_SIZE_MASK_OFF) 452 && !(cbBuf & VBoxRAW_MIN_SIZE_MASK_OFF)) 453 { 454 rc2 = VDWrite(g_pVDisk, offset, pbBuf, cbBuf); 455 if (RT_FAILURE(rc2)) 456 { 457 rc = -RTErrConvertToErrno(rc2); 458 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 459 return rc; 460 } 461 } 462 else 463 { 464 /* 465 * Unaligned write - lots of extra work. 466 */ 467 uint8_t abBlock[VBoxRAW_MIN_SIZE]; 468 if (((offset + cbBuf) & VBoxRAW_MIN_SIZE_MASK_BLK) == (offset & VBoxRAW_MIN_SIZE_MASK_BLK)) 469 { 470 /* a single partial block. */ 471 rc2 = VDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE); 472 if (RT_SUCCESS(rc2)) 473 { 474 memcpy(&abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], pbBuf, cbBuf); 475 /* Update the block */ 476 rc2 = VDWrite(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE); 477 if (RT_FAILURE(rc2)) 478 { 479 rc = -RTErrConvertToErrno(rc2); 480 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 481 return rc; 482 } 483 } 484 else 485 { 486 rc = -RTErrConvertToErrno(rc2); 487 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 488 return rc; 489 } 490 } 491 else 492 { 493 /* read unaligned head. */ 494 rc2 = VINF_SUCCESS; 495 if (offset & VBoxRAW_MIN_SIZE_MASK_OFF) 496 { 497 rc2 = VDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE); 498 if (RT_SUCCESS(rc2)) 499 { 500 size_t cbCopy = VBoxRAW_MIN_SIZE - (offset & VBoxRAW_MIN_SIZE_MASK_OFF); 501 memcpy(&abBlock[offset & VBoxRAW_MIN_SIZE_MASK_OFF], pbBuf, cbCopy); 502 pbBuf += cbCopy; 503 offset += cbCopy; 504 cbBuf -= cbCopy; 505 rc2 = VDWrite(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE); 506 if (RT_FAILURE(rc2)) 507 { 508 rc = -RTErrConvertToErrno(rc2); 509 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 510 return rc; 511 } 512 } 513 else 514 { 515 rc = -RTErrConvertToErrno(rc2); 516 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 517 return rc; 518 } 519 } 520 521 /* write the middle. */ 522 Assert(!(offset & VBoxRAW_MIN_SIZE_MASK_OFF)); 523 if (cbBuf >= VBoxRAW_MIN_SIZE && RT_SUCCESS(rc2)) 524 { 525 size_t cbWrite = cbBuf & VBoxRAW_MIN_SIZE_MASK_BLK; 526 rc2 = VDWrite(g_pVDisk, offset, pbBuf, cbWrite); 527 if (RT_SUCCESS(rc2)) 528 { 529 pbBuf += cbWrite; 530 offset += cbWrite; 531 cbBuf -= cbWrite; 532 } 533 if (RT_FAILURE(rc2)) 534 { 535 rc = -RTErrConvertToErrno(rc2); 536 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 537 return rc; 538 } 539 } 540 541 /* unaligned tail write. */ 542 Assert(cbBuf < VBoxRAW_MIN_SIZE); 543 Assert(!(offset & VBoxRAW_MIN_SIZE_MASK_OFF)); 544 if (cbBuf && RT_SUCCESS(rc2)) 545 { 546 rc2 = VDRead(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE); 547 if (RT_SUCCESS(rc2)) 548 { 549 memcpy(&abBlock[0], pbBuf, cbBuf); 550 rc2 = VDWrite(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE); 551 if (RT_FAILURE(rc2)) 552 { 553 rc = -RTErrConvertToErrno(rc2); 554 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 555 return rc; 556 } 557 } 558 else 559 { 560 rc = -RTErrConvertToErrno(rc2); 561 LogFlowFunc(("error: rc2=%d, rc=%d, %s\n", rc2, rc, strerror(rc))); 562 return rc; 563 } 564 } 565 } 566 } 567 568 /* convert the return code */ 569 if (RT_SUCCESS(rc2)) 570 rc = cbBuf; 571 else 572 { 573 rc = -RTErrConvertToErrno(rc2); 574 LogFlowFunc(("Error rc2=%d, rc=%d=%s\n", rc2, rc, strerror(rc))); 575 return rc; 576 } 577 } 528 return 0; 529 530 if (rc >= 0) 531 rc = vdWriteSanitizer(g_pVDisk, offset, pbBuf, cbBuf); 532 if (rc < 0) 533 LogFlowFunc(("%s\n", strerror(rc))); 534 578 535 return rc; 579 536 } … … 994 951 if (g_vboxrawOpts.fVerbose) 995 952 RTPrintf("vboxraw: Creating container for base image of format %s\n", pszFormat); 953 /** @todo Remove I/O CB's and crit sect. when VDRead()/VDWrite() are made threadsafe */ 954 rc = RTCritSectInit(&g_vdioLock); 955 if (RT_SUCCESS(rc)) 956 { 957 g_VDIfThreadSync.pfnStartRead = vboxrawThreadStartRead; 958 g_VDIfThreadSync.pfnFinishRead = vboxrawThreadFinishRead; 959 g_VDIfThreadSync.pfnStartWrite = vboxrawThreadStartWrite; 960 g_VDIfThreadSync.pfnFinishWrite = vboxrawThreadFinishWrite; 961 rc = VDInterfaceAdd(&g_VDIfThreadSync.Core, "vboxraw_ThreadSync", VDINTERFACETYPE_THREADSYNC, 962 &g_vdioLock, sizeof(VDINTERFACETHREADSYNC), &g_pVdIfs); 963 } 964 else 965 return RTMsgErrorExitFailure("vboxraw: ERROR: Failed to create critsects " 966 "for virtual disk I/O, rc=%Rrc\n", rc); 996 967 997 968 g_pVDisk = NULL; 998 rc = VDCreate( NULL /* pVDIIfsDisk */, enmType, &g_pVDisk);969 rc = VDCreate(g_pVdIfs, enmType, &g_pVDisk); 999 970 if (NS_FAILED(rc)) 1000 971 return RTMsgErrorExitFailure("vboxraw: ERROR: Couldn't create virtual disk container\n"); 1001 972 } 973 /** @todo (end of to do section) */ 974 1002 975 if ( g_vboxrawOpts.cHddImageDiffMax != 0 && diffNumber > g_vboxrawOpts.cHddImageDiffMax) 1003 976 break;
Note:
See TracChangeset
for help on using the changeset viewer.