Changeset 87002 in vbox for trunk/src/VBox/Storage
- Timestamp:
- Nov 27, 2020 10:06:09 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 141564
- Location:
- trunk/src/VBox/Storage
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VMDK.cpp
r86604 r87002 51 51 # include <iprt/symlink.h> 52 52 # include <iprt/linux/sysfs.h> 53 #endif 54 #ifdef RT_OS_FREEBSD 55 #include <libgeom.h> 56 #include <sys/stat.h> 57 #include <stdlib.h> 53 58 #endif 54 59 … … 3623 3628 #endif /* RT_OS_LINUX */ 3624 3629 3630 #ifdef RT_OS_FREEBSD 3631 3632 3633 /** 3634 * Reads the config data from the provider and returns offset and size 3635 * 3636 * @return IPRT status code 3637 * @param pProvider GEOM provider representing partition 3638 * @param pcbOffset Placeholder for the offset of the partition 3639 * @param pcbSize Placeholder for the size of the partition 3640 */ 3641 static int vmdkReadPartitionsParamsFromProvider(gprovider *pProvider, uint64_t *pcbOffset, uint64_t *pcbSize) 3642 { 3643 gconfig *pConfEntry; 3644 int rc = VERR_NOT_FOUND; 3645 3646 /* 3647 * Required parameters are located in the list containing key/value pairs. 3648 * Both key and value are in text form. Manuals tells nothing about the fact 3649 * that the both parameters should be present in the list. Thus, there are 3650 * cases when only one parameter is presented. To handle such cases we treat 3651 * absent params as zero allowing the caller decide the case is either correct 3652 * or an error. 3653 */ 3654 uint64_t cbOffset = 0; 3655 uint64_t cbSize = 0; 3656 LIST_FOREACH(pConfEntry, &pProvider->lg_config, lg_config) 3657 { 3658 if (RTStrCmp(pConfEntry->lg_name, "offset") == 0) 3659 { 3660 cbOffset = RTStrToUInt64(pConfEntry->lg_val); 3661 rc = VINF_SUCCESS; 3662 } 3663 else if (RTStrCmp(pConfEntry->lg_name, "length") == 0) 3664 { 3665 cbSize = RTStrToUInt64(pConfEntry->lg_val); 3666 rc = VINF_SUCCESS; 3667 } 3668 } 3669 if (RT_SUCCESS(rc)) 3670 { 3671 *pcbOffset = cbOffset; 3672 *pcbSize = cbSize; 3673 } 3674 return rc; 3675 } 3676 3677 3678 /** 3679 * Searches the partition specified by name and calculates its size and absolute offset. 3680 * 3681 * @return IPRT status code. 3682 * @param pParentClass Class containing pParentGeom 3683 * @param pszParentGeomName Name of the parent geom where we are looking for provider 3684 * @param pszProviderName Name of the provider we are looking for 3685 * @param pcbAbsoluteOffset Placeholder for the absolute offset of the partition, i.e. offset from the beginning of the disk 3686 * @param psbSize Placeholder for the size of the partition. 3687 */ 3688 static int vmdkFindPartitionParamsByName(gclass *pParentClass, const char *pszParentGeomName, const char *pszProviderName, 3689 uint64_t *pcbAbsoluteOffset, uint64_t *pcbSize) 3690 { 3691 AssertReturn(pParentClass, VERR_INVALID_PARAMETER); 3692 AssertReturn(pszParentGeomName, VERR_INVALID_PARAMETER); 3693 AssertReturn(pszProviderName, VERR_INVALID_PARAMETER); 3694 AssertReturn(pcbAbsoluteOffset, VERR_INVALID_PARAMETER); 3695 AssertReturn(pcbSize, VERR_INVALID_PARAMETER); 3696 3697 ggeom *pParentGeom; 3698 int rc = VERR_NOT_FOUND; 3699 LIST_FOREACH(pParentGeom, &pParentClass->lg_geom, lg_geom) 3700 { 3701 if (RTStrCmp(pParentGeom->lg_name, pszParentGeomName) == 0) 3702 { 3703 rc = VINF_SUCCESS; 3704 break; 3705 } 3706 } 3707 if (RT_FAILURE(rc)) 3708 return rc; 3709 3710 gprovider *pProvider; 3711 /* 3712 * First, go over providers without handling EBR or BSDLabel 3713 * partitions for case when looking provider is child 3714 * of the givng geom, to reduce searching time 3715 */ 3716 LIST_FOREACH(pProvider, &pParentGeom->lg_provider, lg_provider) 3717 { 3718 if (RTStrCmp(pProvider->lg_name, pszProviderName) == 0) 3719 return vmdkReadPartitionsParamsFromProvider(pProvider, pcbAbsoluteOffset, pcbSize); 3720 } 3721 3722 /* 3723 * No provider found. Go over the parent geom again 3724 * and make recursions if geom represents EBR or BSDLabel. 3725 * In this case given parent geom contains only EBR or BSDLabel 3726 * partition itself and their own partitions are in the separate 3727 * geoms. Also, partition offsets are relative to geom, so 3728 * we have to add offset from child provider with parent geoms 3729 * provider 3730 */ 3731 3732 LIST_FOREACH(pProvider, &pParentGeom->lg_provider, lg_provider) 3733 { 3734 uint64_t cbOffset = 0; 3735 uint64_t cbSize = 0; 3736 rc = vmdkReadPartitionsParamsFromProvider(pProvider, &cbOffset, &cbSize); 3737 if (RT_FAILURE(rc)) 3738 return rc; 3739 3740 uint64_t cbProviderOffset = 0; 3741 uint64_t cbProviderSize = 0; 3742 rc = vmdkFindPartitionParamsByName(pParentClass, pProvider->lg_name, pszProviderName, &cbProviderOffset, &cbProviderSize); 3743 if (RT_SUCCESS(rc)) 3744 { 3745 *pcbAbsoluteOffset = cbOffset + cbProviderOffset; 3746 *pcbSize = cbProviderSize; 3747 return rc; 3748 } 3749 } 3750 3751 return VERR_NOT_FOUND; 3752 } 3753 #endif 3754 3625 3755 3626 3756 /** … … 3822 3952 } 3823 3953 /* else: We've got nothing to work on, so only do content comparison. */ 3954 } 3955 #elif defined(RT_OS_FREEBSD) 3956 char szDriveDevName[256]; 3957 char* pszDevName = fdevname_r(RTFileToNative(hRawDrive), szDriveDevName, 256); 3958 if (pszDevName == NULL) 3959 rc = vdIfError(pImage->pIfError, VERR_INVALID_PARAMETER, RT_SRC_POS, 3960 N_("VMDK: Image path: '%s'. '%s' is not a drive path"), pImage->pszFilename, pszRawDrive); 3961 char szPartDevName[256]; 3962 if (RT_SUCCESS(rc)) 3963 { 3964 pszDevName = fdevname_r(RTFileToNative(hRawPart), szPartDevName, 256); 3965 if (pszDevName == NULL) 3966 rc = vdIfError(pImage->pIfError, VERR_INVALID_PARAMETER, RT_SRC_POS, 3967 N_("VMDK: Image path: '%s'. '%s' is not a partition path"), pImage->pszFilename, pPartDesc->pszRawDevice); 3968 } 3969 if (RT_SUCCESS(rc)) 3970 { 3971 gmesh geomMesh; 3972 int err = geom_gettree(&geomMesh); 3973 if (err == 0) 3974 { 3975 /* Find root class containg partitions info */ 3976 gclass* pPartClass; 3977 LIST_FOREACH(pPartClass, &geomMesh.lg_class, lg_class) 3978 { 3979 if (RTStrCmp(pPartClass->lg_name, "PART") == 0) 3980 break; 3981 } 3982 if (pPartClass == NULL || RTStrCmp(pPartClass->lg_name, "PART") != 0) 3983 rc = vdIfError(pImage->pIfError, VERR_GENERAL_FAILURE, RT_SRC_POS, 3984 N_("VMDK: Image path: '%s'. 'PART' class not found in the GEOM tree"), pImage->pszFilename); 3985 3986 3987 if (RT_SUCCESS(rc)) 3988 { 3989 /* Find provider representing partition device */ 3990 uint64_t cbOffset; 3991 uint64_t cbSize; 3992 rc = vmdkFindPartitionParamsByName(pPartClass, szDriveDevName, szPartDevName, &cbOffset, &cbSize); 3993 if (RT_SUCCESS(rc)) 3994 { 3995 if (cbOffset != pPartDesc->offStartInVDisk) 3996 rc = vdIfError(pImage->pIfError, VERR_MISMATCH, RT_SRC_POS, 3997 N_("VMDK: Image path: '%s'. Partition #%u path ('%s') verification failed on '%s': Start offset %RU64, expected %RU64"), 3998 pImage->pszFilename, idxPartition, pPartDesc->pszRawDevice, pszRawDrive, cbOffset, pPartDesc->offStartInVDisk); 3999 if (cbSize != pPartDesc->cbData) 4000 rc = vdIfError(pImage->pIfError, VERR_MISMATCH, RT_SRC_POS, 4001 N_("VMDK: Image path: '%s'. Partition #%u path ('%s') verification failed on '%s': Size %RU64, expected %RU64"), 4002 pImage->pszFilename, idxPartition, pPartDesc->pszRawDevice, pszRawDrive, cbSize, pPartDesc->cbData); 4003 } 4004 else 4005 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 4006 N_("VMDK: Image path: '%s'. Error getting geom provider for the partition '%s' of the drive '%s' in the GEOM tree: %Rrc"), 4007 pImage->pszFilename, pPartDesc->pszRawDevice, pszRawDrive, rc); 4008 } 4009 4010 geom_deletetree(&geomMesh); 4011 } 4012 else 4013 rc = vdIfError(pImage->pIfError, RTErrConvertFromErrno(err), RT_SRC_POS, 4014 N_("VMDK: Image path: '%s'. geom_gettree failed: %d"), pImage->pszFilename, err); 3824 4015 } 3825 4016 #else -
trunk/src/VBox/Storage/testcase/Makefile.kmk
r86430 r87002 150 150 endif 151 151 else ifeq ($(KBUILD_TARGET),freebsd) 152 vbox-img_LIBS += iconv 152 vbox-img_LIBS += iconv geom bsdxml sbuf 153 153 ifdef SDK_VBOX_LIBXML2_LIBS 154 154 vbox-img_LIBS += xml2 lzma
Note:
See TracChangeset
for help on using the changeset viewer.