Changeset 80517 in vbox for trunk/src/VBox/ImageMounter/vboximg-mount
- Timestamp:
- Aug 30, 2019 5:04:46 PM (5 years ago)
- Location:
- trunk/src/VBox/ImageMounter/vboximg-mount
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ImageMounter/vboximg-mount/vboximg-mount.cpp
r80513 r80517 105 105 /** The VFS file associated with the volume. */ 106 106 RTVFSFILE hVfsFileVol; 107 /** Handle to the VFS root if supported and specified. */ 108 RTVFS hVfsRoot; 109 /** Handle to the root directory. */ 110 RTVFSDIR hVfsDirRoot; 107 111 } VBOXIMGMOUNTVOL; 108 112 /** Pointer to a volume data structure. */ … … 133 137 134 138 static struct fuse_opt vboximgOptDefs[] = { 135 OPTION("--image %s", pszImageUuidOrPath, 0), 136 OPTION("-i %s", pszImageUuidOrPath, 0), 137 OPTION("--rw", fRW, 1), 138 OPTION("--root", fAllowRoot, 0), 139 OPTION("--vm %s", pszVm, 0), 140 OPTION("--partition %d", idxPartition, 1), 141 OPTION("-p %d", idxPartition, 1), 142 OPTION("--offset %d", offset, 1), 143 OPTION("-o %d", offset, 1), 144 OPTION("--size %d", size, 1), 145 OPTION("-s %d", size, 1), 146 OPTION("-l", fList, 1), 147 OPTION("--list", fList, 1), 148 OPTION("--verbose", fVerbose, 1), 149 OPTION("-v", fVerbose, 1), 150 OPTION("--wide", fWide, 1), 151 OPTION("-w", fWide, 1), 152 OPTION("-lv", fVerboseList, 1), 153 OPTION("-vl", fVerboseList, 1), 154 OPTION("-lw", fWideList, 1), 155 OPTION("-wl", fWideList, 1), 156 OPTION("-h", fBriefUsage, 1), 157 FUSE_OPT_KEY("--help", USAGE_FLAG), 158 FUSE_OPT_KEY("-vm", FUSE_OPT_KEY_NONOPT), 139 OPTION("--image %s", pszImageUuidOrPath, 0), 140 OPTION("-i %s", pszImageUuidOrPath, 0), 141 OPTION("--rw", fRW, 1), 142 OPTION("--root", fAllowRoot, 0), 143 OPTION("--vm %s", pszVm, 0), 144 OPTION("-l", fList, 1), 145 OPTION("--list", fList, 1), 146 OPTION("-g", fGstFs, 1), 147 OPTION("--guest-filesystem", fGstFs, 1), 148 OPTION("--verbose", fVerbose, 1), 149 OPTION("-v", fVerbose, 1), 150 OPTION("--wide", fWide, 1), 151 OPTION("-w", fWide, 1), 152 OPTION("-lv", fVerboseList, 1), 153 OPTION("-vl", fVerboseList, 1), 154 OPTION("-lw", fWideList, 1), 155 OPTION("-wl", fWideList, 1), 156 OPTION("-h", fBriefUsage, 1), 157 FUSE_OPT_KEY("--help", USAGE_FLAG), 158 FUSE_OPT_KEY("-vm", FUSE_OPT_KEY_NONOPT), 159 159 FUSE_OPT_END 160 160 }; … … 220 220 " wider than standard 80 column window)\n" 221 221 "\n" 222 " [ { -g | --guest-filesystem } ] Exposes supported guest filesystems directly\n" 223 " in the mounted directory without the need\n" 224 " for a filesystem driver on the host\n" 225 "\n" 222 226 " [ --vm UUID ] Restrict media list to specified vm.\n" 223 "\n"224 " [ { -p | --partition } <part #> ] Expose only specified partition via FUSE.\n"225 "\n"226 " [ { -o | --offset } <byte #> ] Bias disk I/O by offset from disk start.\n"227 " (incompatible with -p, --partition)\n"228 "\n"229 " [ { -s | --size <bytes> } ] Specify size of mounted disk.\n"230 " (incompatible with -p, --partition)\n"231 227 "\n" 232 228 " [ --rw ] Make image writeable (default = readonly)\n" … … 252 248 "The virtual disk is exposed as a device node within a FUSE-based filesystem\n" 253 249 "that overlays the user-provided mount point. The FUSE filesystem consists of a\n" 254 "directory containing two files: A pseudo HDD device node and a symbolic\n" 255 "link. The device node, named 'vhdd', is the access point to the virtual disk\n" 256 "(i.e. the OS-mountable raw binary). The symbolic link has the same basename(1)\n" 250 "directory containing a number of files and possibly other directories:" 251 " * vhdd: Provides access to the raw disk image data as a flat image\n" 252 " * vol<id>: Provides access to individual volumes on the accessed disk image\n" 253 " * fs<id>: Provides access to a supported filesystem without the need for a" 254 " host filesystem driver\n" 255 "\n" 256 "The directory will also contain a symbolic link which has the same basename(1)\n" 257 257 "as the virtual disk base image and points to the location of the\n" 258 "virtual disk base image. If the --partition, --offset, or --size\n" 259 "options are provided, the boundaries of the FUSE-mounted subsection of the\n" 260 "virtual disk will be described as a numeric range in brackets appended to the\n" 261 "symbolic link name.\n" 258 "virtual disk base image.\n" 262 259 "\n" 263 260 ); … … 299 296 { 300 297 if ( RTPATH_PROP_HAS_ROOT_SPEC(pPathSplit->fProps) 301 && pPathSplit->cComps == 2)298 && pPathSplit->cComps >= 2) 302 299 { 303 300 /* Skip the root specifier and start with the component coming afterwards. */ 304 301 if (!RTStrCmp(pPathSplit->apszComps[1], "vhdd")) 305 302 *phVfsObj = RTVfsObjFromFile(g_hVfsFileDisk); 306 else if (!RTStrNCmp( &pszPath[1], "vol", sizeof("vol") - 1))303 else if (!RTStrNCmp(pPathSplit->apszComps[1], "vol", sizeof("vol") - 1)) 307 304 { 308 305 /* Retrieve the accessed volume and return the stat data. */ 309 306 uint32_t idxVol; 310 int rcIprt = RTStrToUInt32Full(&p szPath[4], 10, &idxVol);307 int rcIprt = RTStrToUInt32Full(&pPathSplit->apszComps[1][3], 10, &idxVol); 311 308 if ( rcIprt == VINF_SUCCESS 312 309 && idxVol < g_cVolumes) … … 314 311 else 315 312 rc = VERR_NOT_FOUND; 313 } 314 else if (!RTStrNCmp(pPathSplit->apszComps[1], "fs", sizeof("fs") - 1)) 315 { 316 /* Retrieve the accessed volume and return the stat data. */ 317 uint32_t idxVol; 318 int rcIprt = RTStrToUInt32Full(&pPathSplit->apszComps[1][5], 10, &idxVol); 319 if ( rcIprt == VINF_SUCCESS 320 && idxVol < g_cVolumes 321 && g_paVolumes[idxVol].hVfsDirRoot != NIL_RTVFSDIR) 322 *phVfsObj = RTVfsObjFromDir(g_paVolumes[idxVol].hVfsDirRoot); 323 else 324 rc = VERR_NOT_FOUND; 325 326 /* Is an object inside the guest filesystem requested? */ 327 if (pPathSplit->cComps > 2) 328 { 329 PRTPATHSPLIT pPathSplitVfs = (PRTPATHSPLIT)RTMemTmpAllocZ(RT_UOFFSETOF_DYN(RTPATHSPLIT, apszComps[pPathSplit->cComps - 1])); 330 if (RT_LIKELY(pPathSplitVfs)) 331 { 332 pPathSplitVfs->cComps = pPathSplit->cComps - 1; 333 pPathSplitVfs->fProps = pPathSplit->fProps; 334 pPathSplitVfs->cchPath = pPathSplit->cchPath - strlen(pPathSplit->apszComps[1]) - 1; 335 pPathSplitVfs->cbNeeded = pPathSplit->cbNeeded; 336 pPathSplitVfs->pszSuffix = pPathSplit->pszSuffix; 337 pPathSplitVfs->apszComps[0] = pPathSplit->apszComps[0]; 338 for (uint32_t i = 1; i < pPathSplitVfs->cComps; i++) 339 pPathSplitVfs->apszComps[i] = pPathSplit->apszComps[i + 1]; 340 341 /* Reassemble the path. */ 342 char *pszPathVfs = (char *)RTMemTmpAllocZ(pPathSplitVfs->cbNeeded); 343 if (RT_LIKELY(pszPathVfs)) 344 { 345 rc = RTPathSplitReassemble(pPathSplitVfs, RTPATH_STR_F_STYLE_HOST, pszPathVfs, pPathSplitVfs->cbNeeded); 346 if (RT_SUCCESS(rc)) 347 { 348 rc = RTVfsObjOpen(g_paVolumes[idxVol].hVfsRoot, pszPathVfs, 349 RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, 350 RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING | RTPATH_F_ON_LINK, 351 phVfsObj); 352 } 353 RTMemTmpFree(pszPathVfs); 354 } 355 356 RTMemTmpFree(pPathSplitVfs); 357 } 358 else 359 rc = VERR_NO_MEMORY; 360 } 316 361 } 317 362 else … … 496 541 stbuf->st_mode = S_IFDIR | 0755; 497 542 stbuf->st_nlink = 2; 498 }499 else if (RTStrCmp(pszPath + 1, "vhdd") == 0)500 {501 rc = stat(g_pszImagePath, stbuf);502 if (rc < 0)503 return rc;504 /*505 * st_size represents the size of the FUSE FS-mounted portion of the disk.506 * By default it is the whole disk, but can be a partition or specified507 * (or overridden) directly by the { -s | --size } option on the command line.508 */509 uint64_t cbFile = 0;510 int rcIprt = RTVfsFileGetSize(g_hVfsFileDisk, &cbFile);511 if (RT_SUCCESS(rcIprt))512 stbuf->st_size = cbFile;513 else514 rc = -RTErrConvertToErrno(rcIprt);515 stbuf->st_nlink = 1;516 }517 else if (!RTStrNCmp(&pszPath[1], "vol", sizeof("vol") - 1))518 {519 /* Retrieve the accessed volume and return the stat data. */520 uint32_t idxVol;521 int rcIprt = RTStrToUInt32Full(&pszPath[4], 10, &idxVol);522 if ( rcIprt == VINF_SUCCESS523 && idxVol < g_cVolumes)524 {525 rc = stat(g_pszImagePath, stbuf);526 if (rc < 0)527 return rc;528 /*529 * st_size represents the size of the FUSE FS-mounted portion of the disk.530 * By default it is the whole disk, but can be a partition or specified531 * (or overridden) directly by the { -s | --size } option on the command line.532 */533 stbuf->st_size = RTDvmVolumeGetSize(g_paVolumes[idxVol].hVol);534 stbuf->st_nlink = 1;535 }536 else537 rc = -ENOENT;538 543 } 539 544 else if (RTStrNCmp(pszPath + 1, g_pszImageName, strlen(g_pszImageName)) == 0) … … 555 560 stbuf->st_uid = 0; 556 561 stbuf->st_gid = 0; 557 } else 558 rc = -ENOENT; 562 } 563 else 564 { 565 /* Query the VFS object and fill in the data. */ 566 RTVFSOBJ hVfsObj = NIL_RTVFSOBJ; 567 int rcIprt = vboxImgMntVfsObjQueryFromPath(pszPath, &hVfsObj); 568 if (RT_SUCCESS(rcIprt)) 569 { 570 switch (RTVfsObjGetType(hVfsObj)) 571 { 572 case RTVFSOBJTYPE_FILE: 573 { 574 RTVFSFILE hVfsFile = RTVfsObjToFile(hVfsObj); 575 uint64_t cb; 576 rcIprt = RTVfsFileGetSize(hVfsFile, &cb); AssertRC(rcIprt); 577 RTVfsFileRelease(hVfsFile); 578 579 stbuf->st_mode = S_IFREG | 0644; 580 stbuf->st_size = (off_t)cb; 581 stbuf->st_nlink = 1; 582 break; 583 } 584 case RTVFSOBJTYPE_DIR: 585 { 586 stbuf->st_mode = S_IFDIR | 0755; 587 stbuf->st_nlink = 2; 588 break; 589 } 590 default: 591 rc = -EINVAL; 592 } 593 594 stbuf->st_uid = 0; 595 stbuf->st_gid = 0; 596 RTVfsObjRelease(hVfsObj); 597 } 598 else if (rcIprt == VERR_NOT_FOUND) 599 rc = -ENOENT; 600 else 601 rc = -RTErrConvertToErrno(rcIprt); 602 } 559 603 560 604 return rc; … … 567 611 568 612 { 569 NOREF(offset); 570 NOREF(pInfo); 571 572 if (RTStrCmp(pszPath, "/") != 0) 573 return -ENOENT; 574 575 /* 576 * mandatory '.', '..', ... 577 */ 578 pfnFiller(pvBuf, ".", NULL, 0); 579 pfnFiller(pvBuf, "..", NULL, 0); 580 581 /* 582 * Create FUSE FS dir entry that is depicted here (and exposed via stat()) as 583 * a symbolic link back to the resolved path to the VBox virtual disk image, 584 * whose symlink name is basename that path. This is a convenience so anyone 585 * listing the dir can figure out easily what the vhdd FUSE node entry 586 * represents. 587 */ 588 pfnFiller(pvBuf, g_pszImageName, NULL, 0); 589 590 /* 591 * Create entry named "vhdd" denoting the whole disk, which getattr() will describe as a 592 * regular file, and thus will go through the open/release/read/write vectors 593 * to access the VirtualBox image as processed by the IRPT VD API. 594 */ 595 pfnFiller(pvBuf, "vhdd", NULL, 0); 596 597 /* Create entries for the individual volumes. */ 598 for (uint32_t i = 0; i < g_cVolumes; i++) 599 { 600 char tmp[64]; 601 RTStrPrintf(tmp, sizeof (tmp), "vol%u", i); 602 pfnFiller(pvBuf, tmp, NULL, 0); 603 } 604 return 0; 613 RT_NOREF(offset); 614 RT_NOREF(pInfo); 615 616 int rc = 0; 617 618 /* Special root directory handling?. */ 619 if (!RTStrCmp(pszPath, "/")) 620 { 621 /* 622 * mandatory '.', '..', ... 623 */ 624 pfnFiller(pvBuf, ".", NULL, 0); 625 pfnFiller(pvBuf, "..", NULL, 0); 626 627 /* 628 * Create FUSE FS dir entry that is depicted here (and exposed via stat()) as 629 * a symbolic link back to the resolved path to the VBox virtual disk image, 630 * whose symlink name is basename that path. This is a convenience so anyone 631 * listing the dir can figure out easily what the vhdd FUSE node entry 632 * represents. 633 */ 634 pfnFiller(pvBuf, g_pszImageName, NULL, 0); 635 636 /* 637 * Create entry named "vhdd" denoting the whole disk, which getattr() will describe as a 638 * regular file, and thus will go through the open/release/read/write vectors 639 * to access the VirtualBox image as processed by the IRPT VD API. 640 */ 641 pfnFiller(pvBuf, "vhdd", NULL, 0); 642 643 /* Create entries for the individual volumes. */ 644 for (uint32_t i = 0; i < g_cVolumes; i++) 645 { 646 char tmp[64]; 647 RTStrPrintf(tmp, sizeof (tmp), "vol%u", i); 648 pfnFiller(pvBuf, tmp, NULL, 0); 649 650 if (g_paVolumes[i].hVfsRoot != NIL_RTVFS) 651 { 652 RTStrPrintf(tmp, sizeof (tmp), "fs%u", i); 653 pfnFiller(pvBuf, tmp, NULL, 0); 654 } 655 } 656 } 657 else 658 { 659 /* Query the VFS object and fill in the data. */ 660 RTVFSOBJ hVfsObj = NIL_RTVFSOBJ; 661 int rcIprt = vboxImgMntVfsObjQueryFromPath(pszPath, &hVfsObj); 662 if (RT_SUCCESS(rcIprt)) 663 { 664 switch (RTVfsObjGetType(hVfsObj)) 665 { 666 case RTVFSOBJTYPE_DIR: 667 { 668 RTVFSDIR hVfsDir = RTVfsObjToDir(hVfsObj); 669 RTDIRENTRYEX DirEntry; 670 671 rcIprt = RTVfsDirReadEx(hVfsDir, &DirEntry, NULL, RTFSOBJATTRADD_NOTHING); 672 while (RT_SUCCESS(rcIprt)) 673 { 674 pfnFiller(pvBuf, DirEntry.szName, NULL, 0); 675 rcIprt = RTVfsDirReadEx(hVfsDir, &DirEntry, NULL, RTFSOBJATTRADD_NOTHING); 676 } 677 RTVfsDirRelease(hVfsDir); 678 break; 679 } 680 default: 681 rc = -EINVAL; 682 } 683 684 RTVfsObjRelease(hVfsObj); 685 } 686 else 687 rc = -RTErrConvertToErrno(rcIprt); 688 } 689 690 return rc; 605 691 } 606 692 … … 696 782 if (RT_LIKELY(g_paVolumes)) 697 783 { 784 g_paVolumes[0].hVfsRoot = NIL_RTVFS; 785 698 786 rc = RTDvmMapQueryFirstVolume(g_hDvmMgr, &g_paVolumes[0].hVol); 699 787 if (RT_SUCCESS(rc)) … … 704 792 for (uint32_t i = 1; i < g_cVolumes && RT_SUCCESS(rc); i++) 705 793 { 794 g_paVolumes[i].hVfsRoot = NIL_RTVFS; 706 795 rc = RTDvmMapQueryNextVolume(g_hDvmMgr, g_paVolumes[i-1].hVol, &g_paVolumes[i].hVol); 707 796 if (RT_SUCCESS(rc)) … … 759 848 struct fuse_args args = FUSE_ARGS_INIT(argc, argv); 760 849 memset(&g_vboximgOpts, 0, sizeof(g_vboximgOpts)); 761 762 g_vboximgOpts.idxPartition = -1;763 850 764 851 rc = fuse_opt_parse(&args, &g_vboximgOpts, vboximgOptDefs, vboximgOptHandler); … … 1116 1203 } 1117 1204 1205 /* Try to "mount" supported filesystems inside the disk image if specified. */ 1206 if (g_vboximgOpts.fGstFs) 1207 { 1208 for (uint32_t i = 0; i < g_cVolumes; i++) 1209 { 1210 rc = RTVfsMountVol(g_paVolumes[i].hVfsFileVol, 1211 g_vboximgOpts.fRW ? 0 : RTVFSMNT_F_READ_ONLY, 1212 &g_paVolumes[i].hVfsRoot, 1213 NULL); 1214 if (RT_SUCCESS(rc)) 1215 { 1216 rc = RTVfsOpenRoot(g_paVolumes[i].hVfsRoot, &g_paVolumes[i].hVfsDirRoot); 1217 if (RT_FAILURE(rc)) 1218 { 1219 RTPrintf("\nvboximg-mount: Failed to access filesystem on volume %u, ignoring\n", i); 1220 RTVfsRelease(g_paVolumes[i].hVfsRoot); 1221 g_paVolumes[i].hVfsRoot = NIL_RTVFS; 1222 } 1223 } 1224 else 1225 RTPrintf("\nvboximg-mount: Failed to access filesystem on volume %u, ignoring\n", i); 1226 } 1227 } 1228 1118 1229 /* 1119 1230 * Hand control over to libfuse. -
trunk/src/VBox/ImageMounter/vboximg-mount/vboximgOpts.h
r76585 r80517 28 28 char *pszVm; /** optional VM UUID */ 29 29 char *pszImageUuidOrPath; /** Virtual Disk image UUID or path */ 30 int32_t idxPartition; /** Number of partition to constrain FUSE based FS to (optional) 0 - whole disk*/31 int32_t offset; /** Offset to base virtual disk reads and writes from (altnerative to partition) */32 int32_t size; /** Size of accessible disk region, starting at offset, default = offset 0 */33 30 uint32_t fListMediaLong; /** Flag to list virtual disks of all known VMs */ 34 31 uint32_t fVerboseList; /** FUSE parsing doesn't understand combined flags (-lv, -vl), so we kludge it */ … … 36 33 uint32_t fList; /** Flag to list virtual disks of all known VMs */ 37 34 uint32_t fListParts; /** Flag to summarily list partitions associated with pszImage */ 35 uint32_t fGstFs; /** Flag to try to exposes supported filesystems directly in the mountpoint inside a subdirectory */ 38 36 uint32_t fAllowRoot; /** Flag to allow root to access this FUSE FS */ 39 37 uint32_t fRW; /** Flag to allow changes to FUSE-mounted Virtual Disk image */
Note:
See TracChangeset
for help on using the changeset viewer.