VirtualBox

Changeset 87002 in vbox for trunk/src/VBox/Storage


Ignore:
Timestamp:
Nov 27, 2020 10:06:09 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
141564
Message:

Main: bugref:9224: Added device and partition paths checks for FreeBSD

Location:
trunk/src/VBox/Storage
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/VMDK.cpp

    r86604 r87002  
    5151# include <iprt/symlink.h>
    5252# 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>
    5358#endif
    5459
     
    36233628#endif /* RT_OS_LINUX */
    36243629
     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 */
     3641static 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 */
     3688static 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
    36253755
    36263756/**
     
    38223952        }
    38233953        /* 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);
    38244015    }
    38254016#else
  • trunk/src/VBox/Storage/testcase/Makefile.kmk

    r86430 r87002  
    150150  endif
    151151 else ifeq ($(KBUILD_TARGET),freebsd)
    152   vbox-img_LIBS += iconv
     152  vbox-img_LIBS += iconv geom bsdxml sbuf
    153153  ifdef SDK_VBOX_LIBXML2_LIBS
    154154   vbox-img_LIBS += xml2 lzma
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette