VirtualBox

Changeset 29649 in vbox


Ignore:
Timestamp:
May 18, 2010 4:29:31 PM (14 years ago)
Author:
vboxsync
Message:

Frontends/VBoxManage: make partition table processing much more generic, solves the long-standing bugs with rejecting many partition tables (e.g. #688).

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxHDD.h

    r28800 r29649  
    103103
    104104/**
    105  * Auxiliary type for describing partitions on raw disks.
    106  */
    107 typedef struct VBOXHDDRAWPART
    108 {
    109     /** Device to use for this partition. Can be the disk device if the offset
    110      * field is set appropriately. If this is NULL, then this partition will
    111      * not be accessible to the guest. The size of the partition must still
    112      * be set correctly. */
     105 * Auxiliary type for describing partitions on raw disks. The entries must be
     106 * in ascending order (as far as uStart is concerned), and must not overlap.
     107 * Note that this does not correspond 1:1 to partitions, it is describing the
     108 * general meaning of contiguous areas on the disk.
     109 */
     110typedef struct VBOXHDDRAWPARTDESC
     111{
     112    /** Device to use for this partition/data area. Can be the disk device if
     113     * the offset field is set appropriately. If this is NULL, then this
     114     * partition will not be accessible to the guest. The size of the data area
     115     * must still be set correctly. */
    113116    const char      *pszRawDevice;
    114     /** Offset where the partition data starts in this device. */
    115     uint64_t        uPartitionStartOffset;
    116     /** Offset where the partition data starts in the disk. */
    117     uint64_t        uPartitionStart;
    118     /** Size of the partition. */
    119     uint64_t        cbPartition;
    120     /** Size of the partitioning info to prepend. */
    121     uint64_t        cbPartitionData;
    122     /** Offset where the partitioning info starts in the disk. */
    123     uint64_t        uPartitionDataStart;
    124     /** Pointer to the partitioning info to prepend. */
     117    /** Pointer to the partitioning info. NULL means this is a regular data
     118     * area on disk, non-NULL denotes data which should be copied to the
     119     * partition data overlay. */
    125120    const void      *pvPartitionData;
    126 } VBOXHDDRAWPART, *PVBOXHDDRAWPART;
     121    /** Offset where the data starts in this device. */
     122    uint64_t        uStartOffset;
     123    /** Offset where the data starts in the disk. */
     124    uint64_t        uStart;
     125    /** Size of the data area. */
     126    uint64_t        cbData;
     127} VBOXHDDRAWPARTDESC, *PVBOXHDDRAWPARTDESC;
    127128
    128129/**
     
    140141     * For Linux e.g. /dev/sda, and for Windows e.g. \\\\.\\PhysicalDisk0. */
    141142    const char      *pszRawDisk;
    142     /** Number of entries in the partitions array. */
    143     unsigned        cPartitions;
    144     /** Pointer to the partitions array. */
    145     PVBOXHDDRAWPART pPartitions;
     143    /** Number of entries in the partition descriptor array. */
     144    unsigned        cPartDescs;
     145    /** Pointer to the partition descriptor array. */
     146    PVBOXHDDRAWPARTDESC pPartDescs;
    146147} VBOXHDDRAW, *PVBOXHDDRAW;
    147148
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r29035 r29649  
    34813481         * open all the (flat) raw disk partitions. */
    34823482
    3483         /* First pass over the partitions to determine how many
    3484          * extents we need. One partition can require up to 4 extents.
    3485          * One to skip over unpartitioned space, one for the
    3486          * partitioning data, one to skip over unpartitioned space
    3487          * and one for the partition data. */
     3483        /* First pass over the partition data areas to determine how many
     3484         * extents we need. One data area can require up to 2 extents, as
     3485         * it might be necessary to skip over unpartitioned space. */
    34883486        unsigned cExtents = 0;
    34893487        uint64_t uStart = 0;
    3490         for (unsigned i = 0; i < pRaw->cPartitions; i++)
    3491         {
    3492             PVBOXHDDRAWPART pPart = &pRaw->pPartitions[i];
    3493             if (pPart->cbPartitionData)
    3494             {
    3495                 if (uStart > pPart->uPartitionDataStart)
    3496                     return vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: cannot go backwards for partitioning information in '%s'"), pImage->pszFilename);
    3497                 else if (uStart != pPart->uPartitionDataStart)
    3498                     cExtents++;
    3499                 uStart = pPart->uPartitionDataStart + pPart->cbPartitionData;
     3488        for (unsigned i = 0; i < pRaw->cPartDescs; i++)
     3489        {
     3490            PVBOXHDDRAWPARTDESC pPart = &pRaw->pPartDescs[i];
     3491            if (uStart > pPart->uStart)
     3492                return vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: incorrect partition data area ordering set up by the caller in '%s'"), pImage->pszFilename);
     3493
     3494            if (uStart < pPart->uStart)
    35003495                cExtents++;
    3501             }
    3502             if (pPart->cbPartition)
    3503             {
    3504                 if (uStart > pPart->uPartitionStart)
    3505                     return vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: cannot go backwards for partition data in '%s'"), pImage->pszFilename);
    3506                 else if (uStart != pPart->uPartitionStart)
    3507                     cExtents++;
    3508                 uStart = pPart->uPartitionStart + pPart->cbPartition;
    3509                 cExtents++;
    3510             }
     3496            uStart = pPart->uStart + pPart->cbData;
     3497            cExtents++;
    35113498        }
    35123499        /* Another extent for filling up the rest of the image. */
     
    35443531        cExtents = 0;
    35453532        uStart = 0;
    3546         for (unsigned i = 0; i < pRaw->cPartitions; i++)
    3547         {
    3548             PVBOXHDDRAWPART pPart = &pRaw->pPartitions[i];
    3549             if (pPart->cbPartitionData)
     3533        for (unsigned i = 0; i < pRaw->cPartDescs; i++)
     3534        {
     3535            PVBOXHDDRAWPARTDESC pPart = &pRaw->pPartDescs[i];
     3536            pExtent = &pImage->pExtents[cExtents++];
     3537
     3538            if (uStart < pPart->uStart)
    35503539            {
    3551                 if (uStart != pPart->uPartitionDataStart)
    3552                 {
    3553                     pExtent = &pImage->pExtents[cExtents++];
    3554                     pExtent->pszBasename = NULL;
    3555                     pExtent->pszFullname = NULL;
    3556                     pExtent->enmType = VMDKETYPE_ZERO;
    3557                     pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uPartitionDataStart - uStart);
    3558                     pExtent->uSectorOffset = 0;
    3559                     pExtent->enmAccess = VMDKACCESS_READWRITE;
    3560                     pExtent->fMetaDirty = false;
    3561                 }
    3562                 uStart = pPart->uPartitionDataStart + pPart->cbPartitionData;
     3540                pExtent->pszBasename = NULL;
     3541                pExtent->pszFullname = NULL;
     3542                pExtent->enmType = VMDKETYPE_ZERO;
     3543                pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uStart - uStart);
     3544                pExtent->uSectorOffset = 0;
     3545                pExtent->enmAccess = VMDKACCESS_READWRITE;
     3546                pExtent->fMetaDirty = false;
     3547                /* go to next extent */
    35633548                pExtent = &pImage->pExtents[cExtents++];
     3549            }
     3550            uStart = pPart->uStart + pPart->cbData;
     3551
     3552            if (pPart->pvPartitionData)
     3553            {
    35643554                /* Set up basename for extent description. Can't use StrDup. */
    35653555                size_t cbBasename = strlen(pszPartition) + 1;
     
    35853575                pExtent->pszFullname = pszFullname;
    35863576                pExtent->enmType = VMDKETYPE_FLAT;
    3587                 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartitionData);
     3577                pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbData);
    35883578                pExtent->uSectorOffset = uPartOffset;
    35893579                pExtent->enmAccess = VMDKACCESS_READWRITE;
     
    35993589                                     VMDK_SECTOR2BYTE(uPartOffset),
    36003590                                     pPart->pvPartitionData,
    3601                                      pPart->cbPartitionData, NULL);
     3591                                     pPart->cbData, NULL);
    36023592                if (RT_FAILURE(rc))
    36033593                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname);
    3604                 uPartOffset += VMDK_BYTE2SECTOR(pPart->cbPartitionData);
     3594                uPartOffset += VMDK_BYTE2SECTOR(pPart->cbData);
    36053595            }
    3606             if (pPart->cbPartition)
     3596            else
    36073597            {
    3608                 if (uStart != pPart->uPartitionStart)
    3609                 {
    3610                     pExtent = &pImage->pExtents[cExtents++];
    3611                     pExtent->pszBasename = NULL;
    3612                     pExtent->pszFullname = NULL;
    3613                     pExtent->enmType = VMDKETYPE_ZERO;
    3614                     pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uPartitionStart - uStart);
    3615                     pExtent->uSectorOffset = 0;
    3616                     pExtent->enmAccess = VMDKACCESS_READWRITE;
    3617                     pExtent->fMetaDirty = false;
    3618                 }
    3619                 uStart = pPart->uPartitionStart + pPart->cbPartition;
    3620                 pExtent = &pImage->pExtents[cExtents++];
    36213598                if (pPart->pszRawDevice)
    36223599                {
     
    36333610                        return VERR_NO_MEMORY;
    36343611                    pExtent->enmType = VMDKETYPE_FLAT;
    3635                     pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartition);
    3636                     pExtent->uSectorOffset = VMDK_BYTE2SECTOR(pPart->uPartitionStartOffset);
     3612                    pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbData);
     3613                    pExtent->uSectorOffset = VMDK_BYTE2SECTOR(pPart->uStartOffset);
    36373614                    pExtent->enmAccess = VMDKACCESS_READWRITE;
    36383615                    pExtent->fMetaDirty = false;
     
    36503627                    pExtent->pszFullname = NULL;
    36513628                    pExtent->enmType = VMDKETYPE_ZERO;
    3652                     pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartition);
     3629                    pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbData);
    36533630                    pExtent->uSectorOffset = 0;
    36543631                    pExtent->enmAccess = VMDKACCESS_READWRITE;
  • trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp

    r28800 r29649  
    496496}
    497497
     498static int handleVDMessage(void *pvUser, const char *pszFormat, ...)
     499{
     500    NOREF(pvUser);
     501    va_list args;
     502    va_start(args, pszFormat);
     503    int rc = RTPrintfV(pszFormat, args);
     504    va_end(args);
     505    return rc;
     506}
     507
    498508static int CmdSetHDUUID(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
    499509{
     
    525535    vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
    526536    vdInterfaceErrorCallbacks.pfnError     = handleVDError;
    527     vdInterfaceErrorCallbacks.pfnMessage   = NULL;
     537    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
    528538
    529539    rc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
     
    557567}
    558568
    559 
    560 static int handleVDMessage(void *pvUser, const char *pszFormat, ...)
    561 {
    562     NOREF(pvUser);
    563     va_list args;
    564     va_start(args, pszFormat);
    565     int rc = RTPrintfV(pszFormat, args);
    566     va_end(args);
    567     return rc;
    568 }
    569569
    570570static int CmdDumpHDInfo(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
     
    769769    }
    770770
    771     /* Now do a lot of consistency checking. */
    772     uint64_t uPrevEnd = 0;
    773     for (unsigned i = 0; i < pPart->cPartitions-1; i++)
    774     {
    775         if (pPart->aPartitions[i].cPartDataSectors)
    776         {
    777             if (pPart->aPartitions[i].uPartDataStart < uPrevEnd)
    778             {
    779                 RTPrintf("Overlapping partition description areas. Aborting\n");
    780                 return VERR_INVALID_PARAMETER;
    781             }
    782             uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors;
    783         }
    784         if (pPart->aPartitions[i].uStart < uPrevEnd)
    785         {
    786             RTPrintf("Overlapping partitions. Aborting\n");
    787             return VERR_INVALID_PARAMETER;
    788         }
    789         if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType))
    790             uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize;
    791     }
    792 
    793771    /* Fill out partitioning location info for MBR. */
    794772    pPart->aPartitions[0].uPartDataStart = 0;
    795773    pPart->aPartitions[0].cPartDataSectors = pPart->aPartitions[0].uStart;
    796774
     775    /* Now do a some partition table consistency checking, to reject the most
     776     * obvious garbage which can lead to trouble later. */
     777    uint64_t uPrevEnd = 0;
     778    for (unsigned i = 0; i < pPart->cPartitions-1; i++)
     779    {
     780        if (pPart->aPartitions[i].cPartDataSectors)
     781            uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors;
     782        if (pPart->aPartitions[i].uStart < uPrevEnd)
     783        {
     784            RTPrintf("Overlapping partitions. Aborting\n");
     785            return VERR_INVALID_PARAMETER;
     786        }
     787        if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType))
     788            uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize;
     789    }
     790
    797791    return VINF_SUCCESS;
    798792}
     
    833827    HOSTPARTITIONS partitions;
    834828    vrc = partRead(RawFile, &partitions);
    835     if (RT_FAILURE(vrc))
    836         return vrc;
     829    /* Don't bail out on errors, print the table and return the result code. */
    837830
    838831    RTPrintf("Number  Type   StartCHS       EndCHS      Size (MiB)  Start (Sect)\n");
    839832    for (unsigned i = 0; i < partitions.cPartitions; i++)
    840833    {
    841         /* Suppress printing the extended partition. Otherwise people
    842          * might add it to the list of partitions for raw partition
    843          * access (which is not good). */
     834        /* Don't show the extended partition, otherwise users might think they
     835         * can add it to the list of partitions for raw partition access. */
    844836        if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType))
    845837            continue;
     
    858850    }
    859851
    860     return 0;
     852    return vrc;
     853}
     854
     855static PVBOXHDDRAWPARTDESC appendPartDesc(uint32_t *pcPartDescs, PVBOXHDDRAWPARTDESC *ppPartDescs)
     856{
     857    (*pcPartDescs)++;
     858    PVBOXHDDRAWPARTDESC p;
     859    p = (PVBOXHDDRAWPARTDESC)RTMemRealloc(*ppPartDescs,
     860                                          *pcPartDescs * sizeof(VBOXHDDRAWPARTDESC));
     861    *ppPartDescs = p;
     862    if (p)
     863    {
     864        p = p + *pcPartDescs - 1;
     865        memset(p, '\0', sizeof(VBOXHDDRAWPARTDESC));
     866    }
     867
     868    return p;
    861869}
    862870
     
    874882    PVBOXHDD pDisk = NULL;
    875883    VBOXHDDRAW RawDescriptor;
    876     HOSTPARTITIONS partitions;
    877     uint32_t uPartitions = 0;
    878884    PVDINTERFACE pVDIfs = NULL;
    879885
     
    11381144        RawDescriptor.fRawDisk = false;
    11391145        RawDescriptor.pszRawDisk = NULL;
    1140         RawDescriptor.cPartitions = 0;
     1146        RawDescriptor.cPartDescs = 0;
     1147        RawDescriptor.pPartDescs = NULL;
     1148
     1149        uint32_t uPartitions = 0;
    11411150
    11421151        const char *p = pszPartitions;
     
    11631172        }
    11641173
     1174        HOSTPARTITIONS partitions;
    11651175        vrc = partRead(RawFile, &partitions);
    11661176        if (RT_FAILURE(vrc))
     
    11861196        }
    11871197
    1188         RawDescriptor.cPartitions = partitions.cPartitions;
    1189         RawDescriptor.pPartitions = (PVBOXHDDRAWPART)RTMemAllocZ(partitions.cPartitions * sizeof(VBOXHDDRAWPART));
    1190         if (!RawDescriptor.pPartitions)
    1191         {
    1192             RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw());
    1193             vrc = VERR_NO_MEMORY;
    1194             goto out;
    1195         }
    11961198        for (unsigned i = 0; i < partitions.cPartitions; i++)
    11971199        {
    1198             if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex))
    1199             {
    1200                 if (fRelative)
     1200            PVBOXHDDRAWPARTDESC pPartDesc = NULL;
     1201
     1202            /* first dump the MBR/EPT data area */
     1203            if (partitions.aPartitions[i].cPartDataSectors)
     1204            {
     1205                pPartDesc = appendPartDesc(&RawDescriptor.cPartDescs,
     1206                                           &RawDescriptor.pPartDescs);
     1207                if (!pPartDesc)
    12011208                {
    1202 #ifdef RT_OS_LINUX
    1203                     /* Refer to the correct partition and use offset 0. */
    1204                     char *pszRawName;
    1205                     vrc = RTStrAPrintf(&pszRawName, "%s%u", rawdisk.raw(),
    1206                                        partitions.aPartitions[i].uIndex);
    1207                     if (RT_FAILURE(vrc))
    1208                     {
    1209                         RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n",
    1210                                  partitions.aPartitions[i].uIndex, vrc);
    1211                         goto out;
    1212                     }
    1213                     RawDescriptor.pPartitions[i].pszRawDevice = pszRawName;
    1214                     RawDescriptor.pPartitions[i].uPartitionStartOffset = 0;
    1215                     RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
    1216 #elif defined(RT_OS_DARWIN)
    1217                     /* Refer to the correct partition and use offset 0. */
    1218                     char *pszRawName;
    1219                     vrc = RTStrAPrintf(&pszRawName, "%ss%u", rawdisk.raw(),
    1220                                        partitions.aPartitions[i].uIndex);
    1221                     if (RT_FAILURE(vrc))
    1222                     {
    1223                         RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n",
    1224                                  partitions.aPartitions[i].uIndex, vrc);
    1225                         goto out;
    1226                     }
    1227                     RawDescriptor.pPartitions[i].pszRawDevice = pszRawName;
    1228                     RawDescriptor.pPartitions[i].uPartitionStartOffset = 0;
    1229                     RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
    1230 #else
    1231                     /** @todo not implemented yet for Windows host. Treat just
    1232                      * like not specified (this code is actually never reached). */
    1233                     RawDescriptor.pPartitions[i].pszRawDevice = rawdisk.raw();
    1234                     RawDescriptor.pPartitions[i].uPartitionStartOffset = partitions.aPartitions[i].uStart * 512;
    1235                     RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
    1236 #endif
     1209                    RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw());
     1210                    vrc = VERR_NO_MEMORY;
     1211                    goto out;
    12371212                }
    1238                 else
    1239                 {
    1240                     /* This is the "everything refers to the base raw device"
    1241                      * variant. This requires opening the base device in RW
    1242                      * mode even for creation. */
    1243                     RawDescriptor.pPartitions[i].pszRawDevice = rawdisk.raw();
    1244                     RawDescriptor.pPartitions[i].uPartitionStartOffset = partitions.aPartitions[i].uStart * 512;
    1245                     RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
    1246                 }
    1247             }
    1248             else
    1249             {
    1250                 /* Suppress access to this partition. */
    1251                 RawDescriptor.pPartitions[i].pszRawDevice = NULL;
    1252                 RawDescriptor.pPartitions[i].uPartitionStartOffset = 0;
    1253                 /* This is used in the plausibility check in the creation
    1254                  * code. In theory it's a dummy, but I don't want to make
    1255                  * the VMDK creatiion any more complicated than what it needs
    1256                  * to be. */
    1257                 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
    1258             }
    1259             if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType))
    1260             {
    1261                 /* Suppress exporting the actual extended partition. Only
    1262                  * logical partitions should be processed. However completely
    1263                  * ignoring it leads to leaving out the MBR data. */
    1264                 RawDescriptor.pPartitions[i].cbPartition = 0;
    1265             }
    1266             else
    1267                 RawDescriptor.pPartitions[i].cbPartition =  partitions.aPartitions[i].uSize * 512;
    1268             RawDescriptor.pPartitions[i].uPartitionDataStart = partitions.aPartitions[i].uPartDataStart * 512;
    1269             /** @todo the clipping below isn't 100% accurate, as it should
    1270              * actually clip to the track size. However that's easier said
    1271              * than done as figuring out the track size is heuristics. */
    1272             RawDescriptor.pPartitions[i].cbPartitionData = RT_MIN(partitions.aPartitions[i].cPartDataSectors, 63) * 512;
    1273             if (RawDescriptor.pPartitions[i].cbPartitionData)
    1274             {
    1275                 Assert (RawDescriptor.pPartitions[i].cbPartitionData -
    1276                         (size_t)RawDescriptor.pPartitions[i].cbPartitionData == 0);
    1277                 void *pPartData = RTMemAlloc((size_t)RawDescriptor.pPartitions[i].cbPartitionData);
     1213
     1214                /** @todo the clipping below isn't 100% accurate, as it should
     1215                 * actually clip to the track size. However that's easier said
     1216                 * than done as figuring out the track size is heuristics. In
     1217                 * any case the clipping is adjusted later after sorting, to
     1218                 * prevent overlapping data areas on the resulting image. */
     1219                pPartDesc->cbData = RT_MIN(partitions.aPartitions[i].cPartDataSectors, 63) * 512;
     1220                pPartDesc->uStart = partitions.aPartitions[i].uPartDataStart * 512;
     1221                Assert(pPartDesc->cbData - (size_t)pPartDesc->cbData == 0);
     1222                void *pPartData = RTMemAlloc((size_t)pPartDesc->cbData);
    12781223                if (!pPartData)
    12791224                {
     
    12821227                    goto out;
    12831228                }
    1284                 vrc = RTFileReadAt(RawFile, partitions.aPartitions[i].uPartDataStart * 512, pPartData, (size_t)RawDescriptor.pPartitions[i].cbPartitionData, NULL);
     1229                vrc = RTFileReadAt(RawFile, partitions.aPartitions[i].uPartDataStart * 512,
     1230                                   pPartData, (size_t)pPartDesc->cbData, NULL);
    12851231                if (RT_FAILURE(vrc))
    12861232                {
     
    13071253                    }
    13081254                }
    1309                 RawDescriptor.pPartitions[i].pvPartitionData = pPartData;
     1255                pPartDesc->pvPartitionData = pPartData;
     1256            }
     1257
     1258            if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType))
     1259            {
     1260                /* Suppress exporting the actual extended partition. Only
     1261                 * logical partitions should be processed. However completely
     1262                 * ignoring it leads to leaving out the EBR data. */
     1263                continue;
     1264            }
     1265
     1266            /* set up values for non-relative device names */
     1267            const char *pszRawName = rawdisk.raw();
     1268            uint64_t uStartOffset = partitions.aPartitions[i].uStart * 512;
     1269
     1270            pPartDesc = appendPartDesc(&RawDescriptor.cPartDescs,
     1271                                       &RawDescriptor.pPartDescs);
     1272            if (!pPartDesc)
     1273            {
     1274                RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw());
     1275                vrc = VERR_NO_MEMORY;
     1276                goto out;
     1277            }
     1278
     1279            if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex))
     1280            {
     1281                if (fRelative)
     1282                {
     1283#ifdef RT_OS_LINUX
     1284                    /* Refer to the correct partition and use offset 0. */
     1285                    char *psz;
     1286                    vrc = RTStrAPrintf(&psz, "%s%u", rawdisk.raw(),
     1287                                       partitions.aPartitions[i].uIndex);
     1288                    if (RT_FAILURE(vrc))
     1289                    {
     1290                        RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n",
     1291                                 partitions.aPartitions[i].uIndex, vrc);
     1292                        goto out;
     1293                    }
     1294                    pszRawName = psz;
     1295                    uStartOffset = 0;
     1296#elif defined(RT_OS_DARWIN)
     1297                    /* Refer to the correct partition and use offset 0. */
     1298                    char *psz;
     1299                    vrc = RTStrAPrintf(&psz, "%ss%u", rawdisk.raw(),
     1300                                       partitions.aPartitions[i].uIndex);
     1301                    if (RT_FAILURE(vrc))
     1302                    {
     1303                        RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n",
     1304                                 partitions.aPartitions[i].uIndex, vrc);
     1305                        goto out;
     1306                    }
     1307                    pszRawName = psz;
     1308                    uStartOffset = 0;
     1309#else
     1310                    /** @todo not implemented for other hosts. Treat just like
     1311                     * not specified (this code is actually never reached). */
     1312#endif
     1313                }
     1314
     1315                pPartDesc->pszRawDevice = pszRawName;
     1316                pPartDesc->uStartOffset = uStartOffset;
     1317            }
     1318            else
     1319            {
     1320                pPartDesc->pszRawDevice = NULL;
     1321                pPartDesc->uStartOffset = 0;
     1322            }
     1323
     1324            pPartDesc->uStart = partitions.aPartitions[i].uStart * 512;
     1325            pPartDesc->cbData = partitions.aPartitions[i].uSize * 512;
     1326        }
     1327
     1328        /* Sort data areas in ascending order of start. */
     1329        for (unsigned i = 0; i < RawDescriptor.cPartDescs-1; i++)
     1330        {
     1331            unsigned uMinIdx = i;
     1332            uint64_t uMinVal = RawDescriptor.pPartDescs[i].uStart;
     1333            for (unsigned j = i + 1; j < RawDescriptor.cPartDescs; j++)
     1334            {
     1335                if (RawDescriptor.pPartDescs[j].uStart < uMinVal)
     1336                {
     1337                    uMinIdx = j;
     1338                    uMinVal = RawDescriptor.pPartDescs[j].uStart;
     1339                }
     1340            }
     1341            if (uMinIdx != i)
     1342            {
     1343                /* Swap entries at index i and uMinIdx. */
     1344                VBOXHDDRAWPARTDESC tmp;
     1345                memcpy(&tmp, &RawDescriptor.pPartDescs[i], sizeof(tmp));
     1346                memcpy(&RawDescriptor.pPartDescs[i], &RawDescriptor.pPartDescs[uMinIdx], sizeof(tmp));
     1347                memcpy(&RawDescriptor.pPartDescs[uMinIdx], &tmp, sizeof(tmp));
     1348            }
     1349        }
     1350
     1351        /* Have a second go at MBR/EPT area clipping. Now that the data areas
     1352         * are sorted this is much easier to get 100% right. */
     1353        for (unsigned i = 0; i < RawDescriptor.cPartDescs-1; i++)
     1354        {
     1355            if (RawDescriptor.pPartDescs[i].pvPartitionData)
     1356            {
     1357                RawDescriptor.pPartDescs[i].cbData = RT_MIN(RawDescriptor.pPartDescs[i+1].uStart - RawDescriptor.pPartDescs[i].uStart, RawDescriptor.pPartDescs[i].cbData);
     1358                if (!RawDescriptor.pPartDescs[i].cbData)
     1359                {
     1360                    RTPrintf("MBR/EPT overlaps with data area\n");
     1361                    vrc = VERR_INVALID_PARAMETER;
     1362                    goto out;
     1363                }
    13101364            }
    13111365        }
     
    13131367
    13141368    RTFileClose(RawFile);
     1369
     1370#ifdef DEBUG_klaus
     1371    RTPrintf("#            start         length    startoffset  partdataptr  device\n");
     1372    for (unsigned i = 0; i < RawDescriptor.cPartDescs; i++)
     1373    {
     1374        RTPrintf("%2u  %14RU64 %14RU64 %14RU64 %#18p %s\n", i,
     1375                 RawDescriptor.pPartDescs[i].uStart,
     1376                 RawDescriptor.pPartDescs[i].cbData,
     1377                 RawDescriptor.pPartDescs[i].uStartOffset,
     1378                 RawDescriptor.pPartDescs[i].pvPartitionData,
     1379                 RawDescriptor.pPartDescs[i].pszRawDevice);
     1380    }
     1381#endif
    13151382
    13161383    VDINTERFACE      vdInterfaceError;
     
    13191386    vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
    13201387    vdInterfaceErrorCallbacks.pfnError     = handleVDError;
    1321     vdInterfaceErrorCallbacks.pfnMessage   = NULL;
     1388    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
    13221389
    13231390    vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
     
    13571424    if (pszPartitions)
    13581425    {
    1359         for (unsigned i = 0; i < partitions.cPartitions; i++)
    1360         {
    1361             if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex))
    1362             {
    1363                 if (fRelative)
    1364                 {
    1365 #ifdef RT_OS_LINUX
    1366                     /* Free memory allocated above. */
    1367                     RTStrFree((char *)(void *)RawDescriptor.pPartitions[i].pszRawDevice);
    1368 #endif /* RT_OS_LINUX */
    1369                 }
    1370             }
    1371         }
     1426        for (unsigned i = 0; i < RawDescriptor.cPartDescs; i++)
     1427        {
     1428            /* Free memory allocated for relative device name. */
     1429            if (RawDescriptor.pPartDescs[i].pszRawDevice)
     1430                RTStrFree((char *)(void *)RawDescriptor.pPartDescs[i].pszRawDevice);
     1431            if (RawDescriptor.pPartDescs[i].pvPartitionData)
     1432                RTMemFree(RawDescriptor.pPartDescs[i].pvPartitionData);
     1433        }
     1434        if (RawDescriptor.pPartDescs)
     1435            RTMemFree(RawDescriptor.pPartDescs);
    13721436    }
    13731437
     
    14291493    vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
    14301494    vdInterfaceErrorCallbacks.pfnError     = handleVDError;
    1431     vdInterfaceErrorCallbacks.pfnMessage   = NULL;
     1495    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
    14321496
    14331497    int vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
     
    15111575    vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
    15121576    vdInterfaceErrorCallbacks.pfnError     = handleVDError;
    1513     vdInterfaceErrorCallbacks.pfnMessage   = NULL;
     1577    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
    15141578
    15151579    int vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
     
    16761740    vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
    16771741    vdInterfaceErrorCallbacks.pfnError     = handleVDError;
    1678     vdInterfaceErrorCallbacks.pfnMessage   = NULL;
     1742    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
    16791743
    16801744    vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
Note: See TracChangeset for help on using the changeset viewer.

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