Changeset 86604 in vbox for trunk/src/VBox/Storage
- Timestamp:
- Oct 16, 2020 12:00:49 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 140977
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VMDK.cpp
r86298 r86604 44 44 # include <iprt/nt/nt-and-windows.h> 45 45 # include <winioctl.h> 46 #endif 47 #ifdef RT_OS_LINUX 48 # include <errno.h> 49 # include <sys/stat.h> 50 # include <iprt/dir.h> 51 # include <iprt/symlink.h> 52 # include <iprt/linux/sysfs.h> 46 53 #endif 47 54 … … 3544 3551 } 3545 3552 3553 3554 #ifdef RT_OS_LINUX 3555 /** 3556 * Searches the dir specified in @a pszBlockDevDir for subdirectories with a 3557 * 'dev' file matching @a uDevToLocate. 3558 * 3559 * This is used both 3560 * 3561 * @returns IPRT status code, errors have been reported properly. 3562 * @param pImage For error reporting. 3563 * @param pszBlockDevDir Input: Path to the directory search under. 3564 * Output: Path to the directory containing information 3565 * for @a uDevToLocate. 3566 * @param cbBlockDevDir The size of the buffer @a pszBlockDevDir points to. 3567 * @param uDevToLocate The device number of the block device info dir to 3568 * locate. 3569 * @param pszDevToLocate For error reporting. 3570 */ 3571 static int vmdkFindSysBlockDevPath(PVMDKIMAGE pImage, char *pszBlockDevDir, size_t cbBlockDevDir, 3572 dev_t uDevToLocate, const char *pszDevToLocate) 3573 { 3574 size_t const cchDir = RTPathEnsureTrailingSeparator(pszBlockDevDir, cbBlockDevDir); 3575 AssertReturn(cchDir > 0, VERR_BUFFER_OVERFLOW); 3576 3577 RTDIR hDir = NIL_RTDIR; 3578 int rc = RTDirOpen(&hDir, pszBlockDevDir); 3579 if (RT_SUCCESS(rc)) 3580 { 3581 for (;;) 3582 { 3583 RTDIRENTRY Entry; 3584 rc = RTDirRead(hDir, &Entry, NULL); 3585 if (RT_SUCCESS(rc)) 3586 { 3587 /* We're interested in directories and symlinks. */ 3588 if ( Entry.enmType == RTDIRENTRYTYPE_DIRECTORY 3589 || Entry.enmType == RTDIRENTRYTYPE_SYMLINK 3590 || Entry.enmType == RTDIRENTRYTYPE_UNKNOWN) 3591 { 3592 rc = RTStrCopy(&pszBlockDevDir[cchDir], cbBlockDevDir - cchDir, Entry.szName); 3593 AssertContinue(RT_SUCCESS(rc)); /* should not happen! */ 3594 3595 dev_t uThisDevNo = ~uDevToLocate; 3596 rc = RTLinuxSysFsReadDevNumFile(&uThisDevNo, "%s/dev", pszBlockDevDir); 3597 if (RT_SUCCESS(rc) && uThisDevNo == uDevToLocate) 3598 break; 3599 } 3600 } 3601 else 3602 { 3603 pszBlockDevDir[cchDir] = '\0'; 3604 if (rc == VERR_NO_MORE_FILES) 3605 rc = vdIfError(pImage->pIfError, VERR_NOT_FOUND, RT_SRC_POS, 3606 N_("VMDK: Image path: '%s'. Failed to locate device corresponding to '%s' under '%s'"), 3607 pImage->pszFilename, pszDevToLocate, pszBlockDevDir); 3608 else 3609 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 3610 N_("VMDK: Image path: '%s'. RTDirRead failed enumerating '%s': %Rrc"), 3611 pImage->pszFilename, pszBlockDevDir, rc); 3612 break; 3613 } 3614 } 3615 RTDirClose(hDir); 3616 } 3617 else 3618 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 3619 N_("VMDK: Image path: '%s'. Failed to open dir '%s' for listing: %Rrc"), 3620 pImage->pszFilename, pszBlockDevDir, rc); 3621 return rc; 3622 } 3623 #endif /* RT_OS_LINUX */ 3624 3625 3546 3626 /** 3547 3627 * Attempts to verify the raw partition path. … … 3669 3749 else 3670 3750 rc = VERR_NO_TMP_MEMORY; 3751 } 3752 3753 #elif defined(RT_OS_LINUX) 3754 RT_NOREF(hVol); 3755 3756 /* Stat the two devices first to get their device numbers. (We probably 3757 could make some assumptions here about the major & minor number assignments 3758 for legacy nodes, but it doesn't hold up for nvme, so we'll skip that.) */ 3759 struct stat StDrive, StPart; 3760 if (fstat((int)RTFileToNative(hRawDrive), &StDrive) != 0) 3761 rc = vdIfError(pImage->pIfError, RTErrConvertFromErrno(errno), RT_SRC_POS, 3762 N_("VMDK: Image path: '%s'. fstat failed on '%s': %d"), pImage->pszFilename, pszRawDrive, errno); 3763 else if (fstat((int)RTFileToNative(hRawPart), &StPart) != 0) 3764 rc = vdIfError(pImage->pIfError, RTErrConvertFromErrno(errno), RT_SRC_POS, 3765 N_("VMDK: Image path: '%s'. fstat failed on '%s': %d"), pImage->pszFilename, pPartDesc->pszRawDevice, errno); 3766 else 3767 { 3768 /* Scan the directories immediately under /sys/block/ for one with a 3769 'dev' file matching the drive's device number: */ 3770 char szSysPath[RTPATH_MAX]; 3771 rc = RTLinuxConstructPath(szSysPath, sizeof(szSysPath), "block/"); 3772 AssertRCReturn(rc, rc); /* this shall not fail */ 3773 if (RTDirExists(szSysPath)) 3774 { 3775 rc = vmdkFindSysBlockDevPath(pImage, szSysPath, sizeof(szSysPath), StDrive.st_rdev, pszRawDrive); 3776 3777 /* Now, scan the directories under that again for a partition device 3778 matching the hRawPart device's number: */ 3779 if (RT_SUCCESS(rc)) 3780 rc = vmdkFindSysBlockDevPath(pImage, szSysPath, sizeof(szSysPath), StPart.st_rdev, pPartDesc->pszRawDevice); 3781 3782 /* Having found the /sys/block/device/partition/ path, we can finally 3783 read the partition attributes and compare with hVol. */ 3784 if (RT_SUCCESS(rc)) 3785 { 3786 /* partition number: */ 3787 int64_t iLnxPartition = 0; 3788 rc = RTLinuxSysFsReadIntFile(10, &iLnxPartition, "%s/partition", szSysPath); 3789 if (RT_SUCCESS(rc) && iLnxPartition != idxPartition) 3790 rc = vdIfError(pImage->pIfError, VERR_MISMATCH, RT_SRC_POS, 3791 N_("VMDK: Image path: '%s'. Partition #%u path ('%s') verification failed on '%s': Partition number %RI64, expected %RU32"), 3792 pImage->pszFilename, idxPartition, pPartDesc->pszRawDevice, pszRawDrive, iLnxPartition, idxPartition); 3793 /* else: ignore failure? */ 3794 3795 /* start offset: */ 3796 uint32_t const cbLnxSector = 512; /* It's hardcoded in the Linux kernel */ 3797 if (RT_SUCCESS(rc)) 3798 { 3799 int64_t offLnxStart = -1; 3800 rc = RTLinuxSysFsReadIntFile(10, &offLnxStart, "%s/start", szSysPath); 3801 offLnxStart *= cbLnxSector; 3802 if (RT_SUCCESS(rc) && offLnxStart != (int64_t)pPartDesc->offStartInVDisk) 3803 rc = vdIfError(pImage->pIfError, VERR_MISMATCH, RT_SRC_POS, 3804 N_("VMDK: Image path: '%s'. Partition #%u path ('%s') verification failed on '%s': Start offset %RI64, expected %RU64"), 3805 pImage->pszFilename, idxPartition, pPartDesc->pszRawDevice, pszRawDrive, offLnxStart, pPartDesc->offStartInVDisk); 3806 /* else: ignore failure? */ 3807 } 3808 3809 /* the size: */ 3810 if (RT_SUCCESS(rc)) 3811 { 3812 int64_t cbLnxData = -1; 3813 rc = RTLinuxSysFsReadIntFile(10, &cbLnxData, "%s/size", szSysPath); 3814 cbLnxData *= cbLnxSector; 3815 if (RT_SUCCESS(rc) && cbLnxData != (int64_t)pPartDesc->cbData) 3816 rc = vdIfError(pImage->pIfError, VERR_MISMATCH, RT_SRC_POS, 3817 N_("VMDK: Image path: '%s'. Partition #%u path ('%s') verification failed on '%s': Size %RI64, expected %RU64"), 3818 pImage->pszFilename, idxPartition, pPartDesc->pszRawDevice, pszRawDrive, cbLnxData, pPartDesc->cbData); 3819 /* else: ignore failure? */ 3820 } 3821 } 3822 } 3823 /* else: We've got nothing to work on, so only do content comparison. */ 3671 3824 } 3672 3825 #else
Note:
See TracChangeset
for help on using the changeset viewer.