diff options
Diffstat (limited to 'src/VBox/Runtime/testcase/tstRTDvm.cpp')
-rw-r--r-- | src/VBox/Runtime/testcase/tstRTDvm.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/VBox/Runtime/testcase/tstRTDvm.cpp b/src/VBox/Runtime/testcase/tstRTDvm.cpp new file mode 100644 index 00000000..74e0a4d9 --- /dev/null +++ b/src/VBox/Runtime/testcase/tstRTDvm.cpp @@ -0,0 +1,221 @@ +/* $Id: tstRTDvm.cpp $ */ +/** @file + * IPRT Testcase - IPRT Disk Volume Management (DVM) + */ + +/* + * Copyright (C) 2009-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/dvm.h> + +#include <iprt/err.h> +#include <iprt/test.h> +#include <iprt/file.h> +#include <iprt/string.h> +#include <iprt/vfs.h> + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ + + +static int tstRTDvmVolume(RTTEST hTest, RTVFSFILE hVfsDisk, unsigned cNesting) +{ + char szPrefix[100]; + int rc = VINF_SUCCESS; + + RT_ZERO(szPrefix); + + if (cNesting < sizeof(szPrefix) - 1) + { + for (unsigned i = 0; i < cNesting; i++) + szPrefix[i] = '\t'; + } + + RTTestSubF(hTest, "Create DVM"); + RTDVM hVolMgr; + rc = RTDvmCreate(&hVolMgr, hVfsDisk, 512, 0 /*fFlags*/); + if (RT_FAILURE(rc)) + { + RTTestIFailed("RTDvmCreate -> %Rrc", rc); + return RTTestSummaryAndDestroy(hTest); + } + + RTTestSubF(hTest, "Open volume map"); + rc = RTDvmMapOpen(hVolMgr); + if ( RT_FAILURE(rc) + && rc != VERR_NOT_SUPPORTED) + { + RTTestIFailed("RTDvmOpen -> %Rrc", rc); + RTDvmRelease(hVolMgr); + return RTTestSummaryAndDestroy(hTest); + } + if (rc == VERR_NOT_SUPPORTED) + { + RTDvmRelease(hVolMgr); + return VINF_SUCCESS; + } + + RTTestIPrintf(RTTESTLVL_ALWAYS, "%s Successfully opened map with format: %s.\n", szPrefix, RTDvmMapGetFormatName(hVolMgr)); + + /* Dump all volumes. */ + RTTestSubF(hTest, "Dump volumes"); + uint32_t cVolume = 0; + RTDVMVOLUME hVol; + + rc = RTDvmMapQueryFirstVolume(hVolMgr, &hVol); + + while (RT_SUCCESS(rc)) + { + char *pszVolName = NULL; + RTDVMVOLTYPE enmVolType = RTDvmVolumeGetType(hVol); + uint64_t fVolFlags = RTDvmVolumeGetFlags(hVol); + + RTTestIPrintf(RTTESTLVL_ALWAYS, "%s Volume %u:\n", szPrefix, cVolume); + RTTestIPrintf(RTTESTLVL_ALWAYS, "%s Volume type %s\n", szPrefix, RTDvmVolumeTypeGetDescr(enmVolType)); + RTTestIPrintf(RTTESTLVL_ALWAYS, "%s Volume size %llu\n", szPrefix, RTDvmVolumeGetSize(hVol)); + RTTestIPrintf(RTTESTLVL_ALWAYS, "%s Volume flags %s %s %s\n", szPrefix, + fVolFlags & DVMVOLUME_FLAGS_BOOTABLE ? "Bootable" : "", + fVolFlags & DVMVOLUME_FLAGS_ACTIVE ? "Active" : "", + fVolFlags & DVMVOLUME_F_CONTIGUOUS ? "Contiguous" : ""); + + rc = RTDvmVolumeQueryName(hVol, &pszVolName); + if (RT_SUCCESS(rc)) + { + RTTestIPrintf(RTTESTLVL_ALWAYS, "%s Volume name %s.\n", szPrefix, pszVolName); + RTStrFree(pszVolName); + } + else if (rc != VERR_NOT_SUPPORTED) + RTTestIFailed("RTDvmVolumeQueryName -> %Rrc", rc); + else + rc = VINF_SUCCESS; + + if (fVolFlags & DVMVOLUME_F_CONTIGUOUS) + { + uint64_t offStart, offEnd; + rc = RTDvmVolumeQueryRange(hVol, &offStart, &offEnd); + if (RT_SUCCESS(rc)) + RTTestIPrintf(RTTESTLVL_ALWAYS, "%s Volume range %llu:%llu\n", szPrefix, offStart, offEnd); + else + RTTestIFailed("RTDvmVolumeQueryRange -> %Rrc", rc); + } + + RTTestIPrintf(RTTESTLVL_ALWAYS, "\n"); + + /* + * Query all volumes which might be inside this. + * (think of MBR partitions with a bsdlabel inside) + */ + RTVFSFILE hVfsVol; + rc = RTDvmVolumeCreateVfsFile(hVol, RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE, &hVfsVol); + if (RT_SUCCESS(rc)) + { + rc = tstRTDvmVolume(hTest, hVfsVol, cNesting + 1); + RTVfsFileRelease(hVfsVol); + } + else + RTTestIFailed("RTDvmVolumeCreateVfsFile -> %Rrc", rc); + + RTDVMVOLUME hVolNext; + rc = RTDvmMapQueryNextVolume(hVolMgr, hVol, &hVolNext); + RTDvmVolumeRelease(hVol); + hVol = hVolNext; + cVolume++; + } + + RTTestIPrintf(RTTESTLVL_ALWAYS, "%s Dumped %u volumes\n", szPrefix, cVolume); + + if ( rc == VERR_DVM_MAP_EMPTY + || rc == VERR_DVM_MAP_NO_VOLUME) + rc = VINF_SUCCESS; + + RTTESTI_CHECK(rc == VINF_SUCCESS); + + RTDvmRelease(hVolMgr); + + return rc; +} + + +int main(int argc, char **argv) +{ + /* + * Initialize IPRT and create the test. + */ + RTTEST hTest; + int rc = RTTestInitAndCreate("tstRTDvm", &hTest); + if (rc) + return rc; + RTTestBanner(hTest); + + /* + * If no args, display usage. + */ + if (argc < 2) + { + RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Syntax: %s <image>\n", argv[0]); + return RTTestSkipAndDestroy(hTest, "Missing required arguments\n"); + } + + RTVFSFILE hVfsDisk; + rc = RTVfsFileOpenNormal(argv[1], RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE, &hVfsDisk); + if (RT_FAILURE(rc)) + { + RTTestIFailed("RTVfsFileOpenNormal -> %Rrc", rc); + return RTTestSummaryAndDestroy(hTest); + } + + uint64_t cb = 0; + rc = RTVfsFileQuerySize(hVfsDisk, &cb); + if ( RT_FAILURE(rc) + || cb % 512 != 0) /* Assume 512 byte sector size. */ + { + RTTestIFailed("RTVfsFileQuerySize -> %Rrc", rc); + return RTTestSummaryAndDestroy(hTest); + } + + rc = tstRTDvmVolume(hTest, hVfsDisk, 0); + + RTTESTI_CHECK(rc == VINF_SUCCESS); + + RTVfsFileRelease(hVfsDisk); + + /* + * Summary + */ + return RTTestSummaryAndDestroy(hTest); +} + |