Changeset 75266 in vbox
- Timestamp:
- Nov 6, 2018 6:15:26 AM (6 years ago)
- Location:
- trunk/src/VBox/ImageMounter/vboxraw
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ImageMounter/vboxraw/vboxraw.cpp
r74444 r75266 20 20 * Header Files * 21 21 *********************************************************************************************************************************/ 22 23 22 #define LOG_GROUP LOG_GROUP_DEFAULT /** @todo log group */ 24 #define VBox_WITH_XPCOM23 #define UNUSED(x) (void)(x) 25 24 26 25 #define FUSE_USE_VERSION 27 27 26 #if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined(RT_OS_FEEBSD) 28 # define UNIX Y27 # define UNIX_DERIVATIVE 29 28 #endif 30 29 #define MAX_READERS (INT32_MAX / 32) 31 30 32 #include <VBox/vd.h>33 #include <VBox/log.h>34 #include <VBox/err.h>35 #include <iprt/critsect.h>36 #include <iprt/assert.h>37 #include <iprt/message.h>38 #include <iprt/asm.h>39 #include <iprt/mem.h>40 #include <iprt/string.h>41 #include <iprt/initterm.h>42 #include <iprt/stream.h>43 #include <iprt/types.h>44 #include <iprt/path.h>45 46 31 #include <fuse.h> 47 #ifdef UNIX Y32 #ifdef UNIX_DERIVATIVE 48 33 #include <errno.h> 49 34 #include <fcntl.h> … … 57 42 # undef PVM /* Blasted old BSD mess still hanging around darwin. */ 58 43 #endif 59 60 /* 61 * Include the XPCOM headers 62 */ 44 #ifdef RT_OS_LINUX 45 # include <linux/fs.h> 46 # include <linux/hdreg.h> 47 #endif 63 48 #include <VirtualBox_XPCOM.h> 64 #include <nsIComponentRegistrar.h> 65 #include <nsIServiceManager.h> 66 #include <nsEventQueueUtils.h> 67 #include <nsIExceptionService.h> 68 #include <nsMemory.h> 69 #include <nsArray.h> 70 #include <nsString.h> 71 #include <nsReadableUtils.h> 49 #include <VBox/com/VirtualBox.h> 50 #include <VBox/vd.h> 51 #include <VBox/log.h> 52 #include <VBox/err.h> 53 #include <VBox/com/ErrorInfo.h> 54 #include <VBox/com/NativeEventQueue.h> 55 #include <VBox/com/com.h> 56 #include <VBox/com/string.h> 57 #include <VBox/com/Guid.h> 58 #include <VBox/com/array.h> 59 #include <VBox/com/errorprint.h> 60 61 #include <iprt/initterm.h> 62 #include <iprt/critsect.h> 63 #include <iprt/assert.h> 64 #include <iprt/message.h> 65 #include <iprt/asm.h> 66 #include <iprt/mem.h> 67 #include <iprt/string.h> 68 #include <iprt/initterm.h> 69 #include <iprt/stream.h> 70 #include <iprt/types.h> 71 #include <iprt/path.h> 72 73 using namespace com; 72 74 73 75 enum { … … 92 94 #define PADMAX 50 93 95 #define MAX_ID_LEN 256 96 #define CSTR(arg) Utf8Str(arg).c_str() 94 97 95 98 static struct fuse_operations g_vboxrawOps; … … 103 106 char *nsIDToString(nsID *guid); 104 107 void printErrorInfo(); 105 106 108 /** XPCOM stuff */ 107 static struct {108 nsCOMPtr<nsIServiceManager> serviceManager;109 nsCOMPtr<nsIEventQueue> eventQ;110 nsCOMPtr<nsIComponentManager> manager;111 nsCOMPtr<IVirtualBox> virtualBox;112 } g_XPCOM;113 109 114 110 static struct vboxrawOpts { … … 118 114 uint32_t cHddImageDiffMax; 119 115 uint32_t fList; 120 uint32_t fWriteable; 116 uint32_t fAllowRoot; 117 uint32_t fRW; 121 118 uint32_t fVerbose; 122 119 } g_vboxrawOpts; … … 126 123 static struct fuse_opt vboxrawOptDefs[] = { 127 124 OPTION("--list", fList, 1), 125 OPTION("--root", fAllowRoot, 1), 128 126 OPTION("--vm=%s", pszVm, 0), 129 127 OPTION("--maxdiff=%d", cHddImageDiffMax, 1), 130 128 OPTION("--diff=%d", cHddImageDiffMax, 1), 131 129 OPTION("--image=%s", pszImage, 0), 132 OPTION("-- writable", fWriteable,1),130 OPTION("--rw", fRW, 1), 133 131 OPTION("--verbose", fVerbose, 1), 134 132 FUSE_OPT_KEY("-h", USAGE_FLAG), … … 149 147 "%s options:\n" 150 148 " [--list] List media\n" 149 " [--root] Same as -o allow_root\n" 150 " [--rw] writeable (default = readonly)\n" 151 151 " [--vm <name | UUID >] vm UUID (limit media list to specific VM)\n\n" 152 152 " [--diff=<diff #> ] Apply diffs to base image up " … … 181 181 int rc = 0; 182 182 183 #ifdef UNIX Y183 #ifdef UNIX_DERIVATIVE 184 184 # ifdef RT_OS_DARWIN 185 185 notsup = O_APPEND | O_NONBLOCK | O_SYMLINK | O_NOCTTY | O_SHLOCK | O_EXLOCK | … … 189 189 /* | O_LARGEFILE | O_SYNC | ? */ 190 190 # elif defined(RT_OS_FREEBSD) 191 notsup = O_APPEND | O_ASYNC | O_DIRECT | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK ';191 notsup = O_APPEND | O_ASYNC | O_DIRECT | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK; 192 192 /* | O_LARGEFILE | O_SYNC | ? */ 193 193 # endif … … 199 199 rc -EINVAL; 200 200 201 #ifdef UNIX Y201 #ifdef UNIX_DERIVATIVE 202 202 if ((pInfo->flags & O_ACCMODE) == O_ACCMODE) 203 203 rc = -EINVAL; … … 258 258 LogFlowFunc(("\"%s\"\n", pszPath)); 259 259 return 0; 260 } 261 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; 260 273 } 261 274 … … 295 308 if ( !(offset & VBoxRAW_MIN_SIZE_MASK_OFF) 296 309 && !(cbBuf & VBoxRAW_MIN_SIZE_MASK_OFF)) 297 rc2 = VDRead(g_pVDisk, offset, pbBuf, cbBuf); 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 } 298 319 else 299 320 { … … 305 326 { 306 327 /* a single partial block. */ 307 rc2 = VDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);328 rc2 = retryableVDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE); 308 329 if (RT_SUCCESS(rc2)) 330 { 309 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 } 310 339 } 311 340 else … … 315 344 if (offset & VBoxRAW_MIN_SIZE_MASK_OFF) 316 345 { 317 rc2 = VDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE);346 rc2 = retryableVDRead(g_pVDisk, offset & VBoxRAW_MIN_SIZE_MASK_BLK, abBlock, VBoxRAW_MIN_SIZE); 318 347 if (RT_SUCCESS(rc2)) 319 348 { … … 324 353 cbBuf -= cbCopy; 325 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 } 326 361 } 327 362 … … 331 366 { 332 367 size_t cbRead = cbBuf & VBoxRAW_MIN_SIZE_MASK_BLK; 333 rc2 = VDRead(g_pVDisk, offset, pbBuf, cbRead);368 rc2 = retryableVDRead(g_pVDisk, offset, pbBuf, cbRead); 334 369 if (RT_SUCCESS(rc2)) 335 370 { … … 337 372 offset += cbRead; 338 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; 339 380 } 340 381 } … … 345 386 if (cbBuf && RT_SUCCESS(rc2)) 346 387 { 347 rc2 = VDRead(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE);348 if (RT_SUCCESS(rc2)) 388 rc2 = retryableVDRead(g_pVDisk, offset, abBlock, VBoxRAW_MIN_SIZE); 389 if (RT_SUCCESS(rc2)) { 349 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 } 350 398 } 351 399 } … … 356 404 rc = cbBuf; 357 405 else 406 { 358 407 rc = -RTErrConvertToErrno(rc2); 408 LogFlowFunc(("Error rc2=%d, rc=%d=%s\n", rc2, rc, strerror(rc))); 409 } 359 410 return rc; 360 411 } … … 369 420 (void) pszPath; 370 421 (void) pInfo; 422 371 423 372 424 AssertReturn((int)cbBuf >= 0, -EINVAL); … … 375 427 AssertReturn((off_t)(offset + cbBuf) >= offset, -EINVAL); 376 428 429 377 430 LogFlowFunc(("offset=%#llx size=%#zx path=\"%s\"\n", (uint64_t)offset, cbBuf, pszPath)); 378 431 379 432 int rc; 380 if ((off_t)(offset + cbBuf) < offset) 433 if (!g_vboxrawOpts.fRW) 434 rc = -EPERM; 435 else if ((off_t)(offset + cbBuf) < offset) 381 436 rc = -EINVAL; 382 437 else if (offset >= g_cbPrimary) … … 396 451 if ( !(offset & VBoxRAW_MIN_SIZE_MASK_OFF) 397 452 && !(cbBuf & VBoxRAW_MIN_SIZE_MASK_OFF)) 398 rc2 = VDWrite(g_pVDisk, offset, pbBuf, cbBuf); 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 } 399 462 else 400 463 { … … 412 475 /* Update the block */ 413 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; 414 489 } 415 490 } … … 429 504 cbBuf -= cbCopy; 430 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; 431 518 } 432 519 } … … 443 530 offset += cbWrite; 444 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; 445 538 } 446 539 } … … 456 549 memcpy(&abBlock[0], pbBuf, cbBuf); 457 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; 458 563 } 459 564 } … … 465 570 rc = cbBuf; 466 571 else 572 { 467 573 rc = -RTErrConvertToErrno(rc2); 574 LogFlowFunc(("Error rc2=%d, rc=%d=%s\n", rc2, rc, strerror(rc))); 468 575 return rc; 576 } 469 577 } 470 578 return rc; … … 472 580 473 581 /** @copydoc fuse_operations::getattr */ 474 static int vboxrawOp_getattr(const char *pszPath,475 582 static int 583 vboxrawOp_getattr(const char *pszPath, struct stat *stbuf) 476 584 { 477 585 int rc = 0; … … 491 599 if (rc < 0) 492 600 return rc; 601 602 stbuf->st_size = VDGetSize(g_pVDisk, 0); 493 603 stbuf->st_nlink = 1; 494 604 } … … 501 611 stbuf->st_mode = S_IFLNK | 0444; 502 612 stbuf->st_nlink = 1; 613 stbuf->st_uid = 0; 614 stbuf->st_gid = 0; 503 615 } else 504 616 rc = -ENOENT; … … 508 620 509 621 /** @copydoc fuse_operations::readdir */ 510 static int vboxrawOp_readdir(const char *pszPath, void *pvBuf, fuse_fill_dir_t pfnFiller, 622 static int 623 vboxrawOp_readdir(const char *pszPath, void *pvBuf, fuse_fill_dir_t pfnFiller, 511 624 off_t offset, struct fuse_file_info *pInfo) 512 625 … … 543 656 544 657 /** @copydoc fuse_operations::readlink */ 545 static int vboxrawOp_readlink(const char *pszPath, char *buf, size_t size) 658 static int 659 vboxrawOp_readlink(const char *pszPath, char *buf, size_t size) 546 660 { 547 661 (void) pszPath; … … 550 664 } 551 665 552 553 static int 666 static void 554 667 listMedia(IMachine *pMachine) 555 668 { 556 IMediumAttachment **pMediumAttachments = NULL; 557 PRUint32 pMediumAttachmentsSize = 0; 558 nsresult rc = pMachine->GetMediumAttachments(&pMediumAttachmentsSize, &pMediumAttachments); 559 if (NS_SUCCEEDED(rc)) 560 { 561 for (PRUint32 i = 0; i < pMediumAttachmentsSize; i++) 562 { 563 IMedium *pMedium; 564 DeviceType_T deviceType; 565 nsXPIDLString pMediumUuid; 566 nsXPIDLString pMediumName; 567 nsXPIDLString pMediumPath; 568 569 pMediumAttachments[i]->GetType(&deviceType); 570 if (deviceType == DeviceType_HardDisk) 571 { 572 rc = pMediumAttachments[i]->GetMedium(&pMedium); 573 if (NS_SUCCEEDED(rc) && pMedium) 574 { 575 IMedium *pParent = pMedium; 576 IMedium *pEarliestAncestor; 577 while (pParent != nsnull) 578 { 579 pEarliestAncestor = pParent; 580 pParent->GetParent(&pParent); 581 } 582 PRUint32 cChildren = 1; 583 IMedium **aMediumChildren = nsnull; 584 IMedium *pChild = pEarliestAncestor; 585 uint32_t ancestorNumber = 0; 586 RTPrintf("\n"); 587 do 588 { 589 rc = pChild->GetName(getter_Copies(pMediumName)); 590 if (NS_FAILED(rc)) 591 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 592 "Couldn't access pMedium name rc=%#x\n", rc); 593 594 rc = pChild->GetId(getter_Copies(pMediumUuid)); 595 if (NS_FAILED(rc)) 596 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 597 "Couldn't access pMedium ID rc=%#x\n", rc); 598 599 rc = pChild->GetLocation(getter_Copies(pMediumPath)); 600 if (NS_FAILED(rc)) 601 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 602 "Couldn't access pMedium location rc=%#x\n", rc); 603 604 const char *pszMediumName = ToNewCString(pMediumName); 605 const char *pszMediumUuid = ToNewCString(pMediumUuid); 606 const char *pszMediumPath = ToNewCString(pMediumPath); 607 608 if (ancestorNumber == 0) 609 { 610 RTPrintf(" -----------------------\n"); 611 RTPrintf(" HDD base: \"%s\"\n", pszMediumName); 612 RTPrintf(" UUID: %s\n", pszMediumUuid); 613 RTPrintf(" Location: %s\n\n", pszMediumPath); 614 } 615 else 616 { 617 RTPrintf(" Diff %d:\n", ancestorNumber); 618 RTPrintf(" UUID: %s\n", pszMediumUuid); 619 RTPrintf(" Location: %s\n\n", pszMediumPath); 620 } 621 622 free((void*)pszMediumName); 623 free((void*)pszMediumUuid); 624 free((void*)pszMediumPath); 625 626 rc = pChild->GetChildren(&cChildren, &aMediumChildren); 627 if (NS_FAILED(rc)) 628 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 629 "could not get children of media! rc=%#x\n", rc); 630 631 pChild = aMediumChildren[0]; 632 ++ancestorNumber; 633 } while(NS_SUCCEEDED(rc) && cChildren); 634 } 635 pMedium->Release(); 636 } 669 int rc = 0; 670 com::SafeIfaceArray<IMediumAttachment> pMediumAttachments; 671 672 CHECK_ERROR(pMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(pMediumAttachments))); 673 for (size_t i = 0; i < pMediumAttachments.size(); i++) 674 { 675 ComPtr<IMedium> pMedium; 676 DeviceType_T deviceType; 677 Bstr pMediumUuid; 678 Bstr pMediumName; 679 Bstr pMediumPath; 680 681 CHECK_ERROR(pMediumAttachments[i], COMGETTER(Type)(&deviceType)); 682 683 if (deviceType == DeviceType_HardDisk) 684 { 685 CHECK_ERROR(pMediumAttachments[i], COMGETTER(Medium)(pMedium.asOutParam())); 686 if (pMedium.isNull()) 687 return; 688 689 MediumState_T state; 690 CHECK_ERROR(pMedium, COMGETTER(State)(&state)); 691 if (FAILED(rc)) 692 return; 693 if (state == MediumState_Inaccessible) 694 { 695 CHECK_ERROR(pMedium, RefreshState(&state)); 696 if (FAILED(rc)) 697 return; 698 } 699 700 ComPtr<IMedium> pEarliestAncestor; 701 CHECK_ERROR(pMedium, COMGETTER(Base)(pEarliestAncestor.asOutParam())); 702 ComPtr<IMedium> pChild = pEarliestAncestor; 703 uint32_t ancestorNumber = 0; 704 if (pEarliestAncestor.isNull()) 705 return; 706 RTPrintf("\n"); 707 do 708 { 709 com::SafeIfaceArray<IMedium> aMediumChildren; 710 CHECK_ERROR(pChild, COMGETTER(Name)(pMediumName.asOutParam())); 711 CHECK_ERROR(pChild, COMGETTER(Id)(pMediumUuid.asOutParam())); 712 CHECK_ERROR(pChild, COMGETTER(Location)(pMediumPath.asOutParam())); 713 714 if (ancestorNumber == 0) 715 { 716 RTPrintf(" -----------------------\n"); 717 RTPrintf(" HDD base: \"%s\"\n", CSTR(pMediumName)); 718 RTPrintf(" UUID: %s\n", CSTR(pMediumUuid)); 719 RTPrintf(" Location: %s\n\n", CSTR(pMediumPath)); 720 } 721 else 722 { 723 RTPrintf(" Diff %d:\n", ancestorNumber); 724 RTPrintf(" UUID: %s\n", CSTR(pMediumUuid)); 725 RTPrintf(" Location: %s\n\n", CSTR(pMediumPath)); 726 } 727 CHECK_ERROR_BREAK(pChild, COMGETTER(Children)(ComSafeArrayAsOutParam(aMediumChildren))); 728 pChild = (aMediumChildren.size()) ? aMediumChildren[0] : NULL; 729 ++ancestorNumber; 730 } while(pChild); 637 731 } 638 732 } 639 return rc;640 641 733 } 642 734 /** … … 645 737 * @param virtualBox VirtualBox instance object. 646 738 */ 647 static int 648 listVMs(IVirtualBox *virtualBox) 649 { 650 IMachine **ppMachines = NULL; 651 PRUint32 cMachines = 0; 652 nsresult rc; 653 654 rc = virtualBox->GetMachines(&cMachines, &ppMachines); 655 if (NS_SUCCEEDED(rc)) 656 { 657 for (PRUint32 i = 0; i < cMachines; ++ i) 658 { 659 IMachine *pMachine = ppMachines[i]; 660 if (pMachine) 661 { 662 PRBool isAccessible = PR_FALSE; 663 pMachine->GetAccessible(&isAccessible); 664 665 if (isAccessible) 666 { 667 nsXPIDLString pMachineUuid; 668 nsXPIDLString pMachineName; 669 nsXPIDLString pMachinePath; 670 671 rc = pMachine->GetName(getter_Copies(pMachineName)); 672 if (NS_FAILED(rc)) 673 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 674 "Couldn't access pMachine name rc=%#x\n", rc); 675 676 rc = pMachine->GetId(getter_Copies(pMachineUuid)); 677 if (NS_FAILED(rc)) 678 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 679 "Couldn't access pMachine Id rc=%#x\n", rc); 680 681 rc = pMachine->GetStateFilePath(getter_Copies(pMachinePath)); 682 if (NS_FAILED(rc)) 683 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 684 "Couldn't access pMachine Location rc=%#x\n", rc); 685 686 const char *pszMachineName = ToNewCString(pMachineName); 687 const char *pszMachineUuid = ToNewCString(pMachineUuid); 688 const char *pszMachinePath = ToNewCString(pMachinePath); 689 690 if ( g_vboxrawOpts.pszVm == NULL 691 || RTStrNCmp(pszMachineUuid, g_vboxrawOpts.pszVm, MAX_ID_LEN) == 0 692 || RTStrNCmp(pszMachineName, g_vboxrawOpts.pszVm, MAX_ID_LEN) == 0) 693 { 694 RTPrintf("------------------------------------------------------\n"); 695 RTPrintf("VM Name: \"%s\"\n", pszMachineName); 696 RTPrintf("UUID: %s\n", pszMachineUuid); 697 RTPrintf("Location: %s\n", pszMachinePath); 698 699 rc = listMedia(pMachine); 700 if (NS_FAILED(rc)) 701 return rc; 702 703 RTPrintf("\n"); 704 } 705 free((void *)pszMachineUuid); 706 free((void *)pszMachineName); 707 free((void *)pszMachinePath); 708 } 709 pMachine->Release(); 739 static void 740 listVMs(IVirtualBox *pVirtualBox) 741 { 742 HRESULT rc = 0; 743 com::SafeIfaceArray<IMachine> pMachines; 744 CHECK_ERROR(pVirtualBox, COMGETTER(Machines)(ComSafeArrayAsOutParam(pMachines))); 745 for (size_t i = 0; i < pMachines.size(); ++i) 746 { 747 ComPtr<IMachine> pMachine = pMachines[i]; 748 if (pMachine) 749 { 750 BOOL fAccessible; 751 CHECK_ERROR(pMachines[i], COMGETTER(Accessible)(&fAccessible)); 752 if (fAccessible) 753 { 754 Bstr pMachineName; 755 Bstr pMachineUuid; 756 Bstr pDescription; 757 Bstr pMachineLocation; 758 759 CHECK_ERROR(pMachine, COMGETTER(Name)(pMachineName.asOutParam())); 760 CHECK_ERROR(pMachine, COMGETTER(Id)(pMachineUuid.asOutParam())); 761 CHECK_ERROR(pMachine, COMGETTER(Description)(pDescription.asOutParam())); 762 CHECK_ERROR(pMachine, COMGETTER(SettingsFilePath)(pMachineLocation.asOutParam())); 763 764 if ( g_vboxrawOpts.pszVm == NULL 765 || RTStrNCmp(CSTR(pMachineUuid), g_vboxrawOpts.pszVm, MAX_ID_LEN) == 0 766 || RTStrNCmp((const char *)pMachineName.raw(), g_vboxrawOpts.pszVm, MAX_ID_LEN) == 0) 767 { 768 RTPrintf("------------------------------------------------------\n"); 769 RTPrintf("VM Name: \"%s\"\n", CSTR(pMachineName)); 770 RTPrintf("UUID: %s\n", CSTR(pMachineUuid)); 771 if (*pDescription.raw() != '\0') 772 RTPrintf("Description: %s\n", CSTR(pDescription)); 773 RTPrintf("Location: %s\n", CSTR(pMachineLocation)); 774 775 listMedia(pMachine); 776 777 RTPrintf("\n"); 778 } 710 779 } 711 780 } 712 781 } 713 return rc; 714 } 715 716 static int 717 searchForBaseImage(IVirtualBox *virtualBox, char *pszImageString, IMedium **baseImage) 718 { 719 PRUint32 cDisks; 720 IMedium **ppDisks; 721 722 nsresult rc = virtualBox->GetHardDisks(&cDisks, &ppDisks); 723 if (NS_SUCCEEDED(rc)) 724 { 725 for (PRUint32 i = 0; i < cDisks && ppDisks[i]; i++) 726 { 727 if (ppDisks[i]) 728 { 729 nsXPIDLString pMediumUuid; 730 nsXPIDLString pMediumName; 731 732 rc = ppDisks[i]->GetName(getter_Copies(pMediumName)); 733 if (NS_FAILED(rc)) 734 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 735 "Couldn't access pMedium name rc=%#x\n", rc); 736 737 rc = ppDisks[i]->GetId(getter_Copies(pMediumUuid)); 738 if (NS_FAILED(rc)) 739 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 740 "Couldn't access pMedium Id rc=%#x\n", rc); 741 742 const char *pszMediumName = ToNewCString(pMediumName); 743 const char *pszMediumUuid = ToNewCString(pMediumUuid); 744 745 if ( RTStrCmp(pszImageString, pszMediumUuid) == 0 746 || RTStrCmp(pszImageString, pszMediumName) == 0) 747 { 748 *baseImage = ppDisks[i]; 749 free((void*)pszMediumUuid); 750 free((void*)pszMediumName); 751 return rc; 752 } 753 ppDisks[i]->Release(); 754 free((void*)pszMediumUuid); 755 free((void*)pszMediumName); 782 } 783 784 static void 785 searchForBaseImage(IVirtualBox *pVirtualBox, char *pszImageString, ComPtr<IMedium> *pBaseImage) 786 { 787 int rc = 0; 788 com::SafeIfaceArray<IMedium> aDisks; 789 790 CHECK_ERROR(pVirtualBox, COMGETTER(HardDisks)(ComSafeArrayAsOutParam(aDisks))); 791 for (size_t i = 0; i < aDisks.size() && aDisks[i]; i++) 792 { 793 if (aDisks[i]) 794 { 795 Bstr pMediumUuid; 796 Bstr pMediumName; 797 798 CHECK_ERROR(aDisks[i], COMGETTER(Name)(pMediumName.asOutParam())); 799 CHECK_ERROR(aDisks[i], COMGETTER(Id)(pMediumUuid.asOutParam())); 800 801 if ( RTStrCmp(pszImageString, CSTR(pMediumUuid)) == 0 802 || RTStrCmp(pszImageString, CSTR(pMediumName)) == 0) 803 { 804 *pBaseImage = aDisks[i]; 805 return; 756 806 } 757 807 } 758 808 } 759 return rc;760 809 } 761 810 … … 780 829 g_vboxrawOps.readdir = vboxrawOp_readdir; 781 830 g_vboxrawOps.readlink = vboxrawOp_readlink; 782 783 831 struct fuse_args args = FUSE_ARGS_INIT(argc, argv); 784 832 … … 786 834 787 835 rc = fuse_opt_parse(&args, &g_vboxrawOpts, vboxrawOptDefs, vboxrawOptHandler); 836 if (g_vboxrawOpts.fAllowRoot) 837 fuse_opt_add_arg(&args, "-oallow_root"); 838 788 839 if (rc == -1) 789 840 return RTMsgErrorExitFailure("vboxraw: ERROR: Couldn't parse fuse options, rc=%Rrc\n", rc); 790 841 791 842 /* 792 * Initialize XPCOM to so we can use the API843 * Initialize COM. 793 844 */ 794 rc = NS_InitXPCOM2(getter_AddRefs(g_XPCOM.serviceManager), nsnull, nsnull); 795 if (NS_FAILED(rc)) 796 return RTMsgErrorExitFailure("vboxraw: ERROR: " 797 "XPCOM could not be initialized! rc=%#x\n", rc); 798 799 rc = NS_GetMainEventQ(getter_AddRefs(g_XPCOM.eventQ)); 800 if (NS_FAILED(rc)) 801 return RTMsgErrorExitFailure("vboxraw: ERROR: " 802 "could not get main event queue! rc=%#x\n", rc); 803 804 rc = NS_GetComponentManager(getter_AddRefs(g_XPCOM.manager)); 805 if (NS_FAILED(rc)) 806 return RTMsgErrorExitFailure("vboxraw: ERROR: " 807 "couldn't get the component manager! rc=%#x\n", rc); 808 809 rc = g_XPCOM.manager->CreateInstanceByContractID(NS_VIRTUALBOX_CONTRACTID, 810 nsnull, 811 NS_GET_IID(IVirtualBox), 812 getter_AddRefs(g_XPCOM.virtualBox)); 813 if (NS_FAILED(rc)) 814 return RTMsgErrorExitFailure("vboxraw: ERROR: " 815 "could not instantiate VirtualBox object! rc=%#x\n", rc); 845 using namespace com; 846 HRESULT hrc = com::Initialize(); 847 if (FAILED(hrc)) 848 { 849 # ifdef VBOX_WITH_XPCOM 850 if (hrc == NS_ERROR_FILE_ACCESS_DENIED) 851 { 852 char szHome[RTPATH_MAX] = ""; 853 com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome)); 854 return RTMsgErrorExit(RTEXITCODE_FAILURE, 855 "Failed to initialize COM because the global settings directory '%s' is not accessible!", szHome); 856 } 857 # endif 858 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize COM! (hrc=%Rhrc)", hrc); 859 } 860 861 /* 862 * Get the remote VirtualBox object and create a local session object. 863 */ 864 ComPtr<IVirtualBoxClient> pVirtualBoxClient; 865 ComPtr<IVirtualBox> pVirtualBox; 866 867 hrc = pVirtualBoxClient.createInprocObject(CLSID_VirtualBoxClient); 868 if (SUCCEEDED(hrc)) 869 hrc = pVirtualBoxClient->COMGETTER(VirtualBox)(pVirtualBox.asOutParam()); 870 if (FAILED(hrc)) 871 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to get IVirtualBox object! (hrc=%Rhrc)", hrc); 816 872 817 873 if (g_vboxrawOpts.fVerbose) … … 819 875 820 876 if (g_vboxrawOpts.fList) 821 return listVMs(g_XPCOM.virtualBox); 877 { 878 listVMs(pVirtualBox); 879 return 0; 880 } 822 881 823 882 if (g_vboxrawOpts.pszImage == NULL) 883 { 824 884 RTMsgErrorExitFailure("vboxraw: ERROR: " 825 885 "Must provide at at least --list or --image option\n"); 826 827 IMedium *pBaseImageMedium = NULL; 886 return 0; 887 } 888 ComPtr<IMedium> pBaseImageMedium = NULL; 828 889 char *pszFormat; 829 890 VDTYPE enmType; 830 891 831 rc = searchForBaseImage(g_XPCOM.virtualBox, g_vboxrawOpts.pszImage, &pBaseImageMedium); 832 if (NS_FAILED(rc)) 833 RTMsgErrorExitFailure("vboxraw: ERROR: " 834 "Couldn't locate base image \"%s\"\n", g_vboxrawOpts.pszImage); 835 892 searchForBaseImage(pVirtualBox, g_vboxrawOpts.pszImage, &pBaseImageMedium); 836 893 if (pBaseImageMedium == NULL) 837 894 { … … 844 901 return cbNameMax; 845 902 846 char *pszBounceA = (char *)RTMemAlloc(cbNameMax + 1); 847 if (!pszBounceA) 848 return VERR_NO_MEMORY; 849 memset(pszBounceA, 0, cbNameMax + 1); 850 851 char *pszBounceB = (char *)RTMemAlloc(cbNameMax + 1); 852 if (!pszBounceB) 853 return VERR_NO_MEMORY; 854 memset(pszBounceB, 0, cbNameMax + 1); 855 856 RTStrCopy(pszBounceA, cbNameMax, g_vboxrawOpts.pszImage); 857 while (readlink(pszBounceA, pszBounceB, cbNameMax) >= 0) 858 RTStrCopy(pszBounceA, cbNameMax, pszBounceB); 859 860 free(g_vboxrawOpts.pszImage); 861 862 g_pszBaseImagePath = RTStrDup(pszBounceA); 903 g_pszBaseImagePath = RTStrDup(g_vboxrawOpts.pszImage); 863 904 if (g_pszBaseImagePath == NULL) 864 905 return RTMsgErrorExitFailure("vboxraw: out of memory\n"); 865 866 RTMemFree(pszBounceA);867 RTMemFree(pszBounceB);868 906 869 907 if (access(g_pszBaseImagePath, F_OK) < 0) … … 875 913 "Virtual disk image not readable: \"%s\"\n", g_pszBaseImagePath); 876 914 877 if ( g_vboxrawOpts.f Writeable&& access(g_vboxrawOpts.pszImage, W_OK) < 0)915 if ( g_vboxrawOpts.fRW && access(g_vboxrawOpts.pszImage, W_OK) < 0) 878 916 return RTMsgErrorExitFailure("vboxraw: ERROR: " 879 917 "Virtual disk image not writeable: \"%s\"\n", g_pszBaseImagePath); … … 889 927 890 928 g_pszBaseImageName = g_u.split.apszComps[g_u.split.cComps - 1]; 891 rc = searchForBaseImage(g_XPCOM.virtualBox, g_pszBaseImageName, &pBaseImageMedium);929 searchForBaseImage(pVirtualBox, g_pszBaseImageName, &pBaseImageMedium); 892 930 893 931 if (pBaseImageMedium == NULL) … … 923 961 if (g_pVDisk == NULL) 924 962 { 925 IMedium **aMediumChildren = nsnull; 926 IMedium *pChild = pBaseImageMedium; 927 PRUint32 cChildren; 963 com::SafeIfaceArray<IMedium> aMediumChildren; 964 ComPtr<IMedium> pChild = pBaseImageMedium; 928 965 uint32_t diffNumber = 0; /* diff # 0 = base image */ 929 930 966 do 931 967 { 932 nsXPIDLString pMediumUuid; 933 nsXPIDLString pMediumName; 934 nsXPIDLString pMediumPath; 935 936 rc = pChild->GetName(getter_Copies(pMediumName)); 937 if (NS_FAILED(rc)) 938 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 939 "Couldn't access pMedium name rc=%#x\n", rc); 940 941 rc = pChild->GetId(getter_Copies(pMediumUuid)); 942 if (NS_FAILED(rc)) 943 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 944 "Couldn't access pMedium ID rc=%#x\n", rc); 945 946 rc = pChild->GetLocation(getter_Copies(pMediumPath)); 947 if (NS_FAILED(rc)) 948 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 949 "Couldn't access pMedium location rc=%#x\n", rc); 950 951 const char *pszMediumName = ToNewCString(pMediumName); 952 const char *pszMediumUuid = ToNewCString(pMediumUuid); 953 const char *pszMediumPath = ToNewCString(pMediumPath); 968 Bstr pMediumName; 969 Bstr pMediumPath; 970 971 CHECK_ERROR(pChild, COMGETTER(Name)(pMediumName.asOutParam())); 972 CHECK_ERROR(pChild, COMGETTER(Location)(pMediumPath.asOutParam())); 954 973 955 974 if (pChild == pBaseImageMedium) 956 975 { 957 976 free((void *)g_pszBaseImageName); 958 g_pszBaseImageName = RTStrDup( pszMediumName);977 g_pszBaseImageName = RTStrDup(CSTR(pMediumName)); 959 978 960 979 free((void *)g_pszBaseImagePath); 961 g_pszBaseImagePath = RTStrDup(pszMediumPath); 962 963 free((void *)pszMediumUuid); 964 free((void *)pszMediumName); 965 980 g_pszBaseImagePath = RTStrDup(CSTR(pMediumPath)); 966 981 if (g_pszBaseImageName == NULL) 967 982 return RTMsgErrorExitFailure("vboxraw: out of memory\n"); … … 977 992 return RTMsgErrorExitFailure("vboxraw: VDGetFormat(,,%s,,) " 978 993 "failed (during HDD container creation), rc=%Rrc\n", g_pszBaseImagePath, rc); 979 980 994 if (g_vboxrawOpts.fVerbose) 981 995 RTPrintf("vboxraw: Creating container for base image of format %s\n", pszFormat); … … 986 1000 return RTMsgErrorExitFailure("vboxraw: ERROR: Couldn't create virtual disk container\n"); 987 1001 } 988 else989 {990 free((void *)pszMediumUuid);991 free((void *)pszMediumName);992 }993 1002 if ( g_vboxrawOpts.cHddImageDiffMax != 0 && diffNumber > g_vboxrawOpts.cHddImageDiffMax) 994 1003 break; … … 998 1007 if (diffNumber == 0) 999 1008 RTPrintf("\nvboxraw: Opening base image into container:\n %s\n", 1000 pszMediumPath);1009 g_pszBaseImagePath); 1001 1010 else 1002 1011 RTPrintf("\nvboxraw: Opening difference image #%d into container:\n %s\n", 1003 diffNumber, pszMediumPath);1004 } 1005 1006 rc = VDOpen(g_pVDisk, pszFormat, pszMediumPath, 0, NULL /* pVDIfsImage */);1012 diffNumber, g_pszBaseImagePath); 1013 } 1014 1015 rc = VDOpen(g_pVDisk, pszFormat, g_pszBaseImagePath, 0, NULL /* pVDIfsImage */); 1007 1016 if (RT_FAILURE(rc)) 1008 1017 { 1009 1018 VDClose(g_pVDisk, false /* fDeletes */); 1010 free((void *)pszMediumPath); 1011 return RTMsgErrorExitFailure("vboxraw: VDOpen(,,%s,,) failed, rc=%Rrc\n", pszMediumPath, rc); 1012 } 1013 1014 rc = pChild->GetChildren(&cChildren, &aMediumChildren); 1015 if (NS_FAILED(rc)) 1016 { 1017 free((void *)pszMediumPath); 1018 return RTMsgErrorExitFailure("vboxraw: VBox API/XPCOM ERROR: " 1019 "Couldn't get children of medium, rc=%Rrc\n", pszMediumPath, rc); 1020 } 1021 1022 pChild = aMediumChildren[0]; 1019 return RTMsgErrorExitFailure("vboxraw: VDOpen(,,%s,,) failed, rc=%Rrc\n", 1020 g_pszBaseImagePath, rc); 1021 } 1022 1023 CHECK_ERROR(pChild, COMGETTER(Children)(ComSafeArrayAsOutParam(aMediumChildren))); 1024 1025 if (aMediumChildren.size() != 0) { 1026 pChild = aMediumChildren[0]; 1027 } 1028 1029 aMediumChildren.setNull(); 1030 1023 1031 ++diffNumber; 1024 free((void *)pszMediumPath); 1025 1026 1027 } while(NS_SUCCEEDED(rc) && cChildren); 1032 1033 1034 } while(NS_SUCCEEDED(rc) && aMediumChildren.size()); 1028 1035 } 1029 1036
Note:
See TracChangeset
for help on using the changeset viewer.