VirtualBox

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


Ignore:
Timestamp:
Oct 16, 2020 12:00:49 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
140977
Message:

Main: bugref:9224: Added the drive path and partition checking for linux

File:
1 edited

Legend:

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

    r86298 r86604  
    4444# include <iprt/nt/nt-and-windows.h>
    4545# 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>
    4653#endif
    4754
     
    35443551}
    35453552
     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 */
     3571static 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
    35463626/**
    35473627 * Attempts to verify the raw partition path.
     
    36693749        else
    36703750            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. */
    36713824    }
    36723825#else
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