From e0860839f664c6269261563d11be0495e756ff06 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 3 Feb 2024 21:11:46 +0100 Subject: [PATCH] Use a simpler way to decide what devices we could write to on macOS. This basically involves the kDADiskDescriptionDeviceInternalKey, kDADiskDescriptionMediaRemovableKey and kDADiskDescriptionMediaWritableKey keys revealed by looking in https://github.com/balena-io-modules/drivelist.git --- src/lib/cross.h | 16 ++---- src/lib/cross_common.cc | 97 ----------------------------------- src/lib/cross_osx.cc | 107 +++++++++++---------------------------- test/disk_writer_test.cc | 107 --------------------------------------- 4 files changed, 33 insertions(+), 294 deletions(-) diff --git a/src/lib/cross.h b/src/lib/cross.h index 6904811b7..150199561 100644 --- a/src/lib/cross.h +++ b/src/lib/cross.h @@ -138,29 +138,19 @@ private: void disk_write_finished (); -struct OSXMediaPath -{ - bool real; ///< true for a "real" disk, false for a synthesized APFS one - std::vector parts; ///< parts of the media path after the : -}; - - struct OSXDisk { std::string device; boost::optional vendor; boost::optional model; - OSXMediaPath media_path; - bool whole; std::vector mount_points; unsigned long size; + bool system; + bool writeable; + bool partition; }; -boost::optional analyse_osx_media_path (std::string path); -std::vector osx_disks_to_drives (std::vector disks); - - class ArgFixer { public: diff --git a/src/lib/cross_common.cc b/src/lib/cross_common.cc index b4d322096..b8f1d48f1 100644 --- a/src/lib/cross_common.cc +++ b/src/lib/cross_common.cc @@ -40,9 +40,6 @@ using std::vector; using boost::optional; -auto constexpr MEDIA_PATH_REQUIRED_MATCHES = 3; - - Drive::Drive (string xml) { cxml::Document doc; @@ -122,97 +119,3 @@ Drive::log_summary () const ); } - - -/* This is in _common so we can use it in unit tests */ -optional -analyse_osx_media_path (string path) -{ - if (path.find("/IOHDIXController") != string::npos) { - /* This is a disk image, so we completely ignore it */ - LOG_DISK_NC("Ignoring this as it seems to be a disk image"); - return {}; - } - - OSXMediaPath mp; - vector parts; - split(parts, path, boost::is_any_of("/")); - std::copy(parts.begin() + 1, parts.end(), back_inserter(mp.parts)); - - if (!parts.empty() && parts[0] == "IODeviceTree:") { - mp.real = true; - if (mp.parts.size() < MEDIA_PATH_REQUIRED_MATCHES) { - /* Later we expect at least MEDIA_PATH_REQUIRED_MATCHES parts in a IODeviceTree */ - LOG_DISK_NC("Ignoring this as it has a strange media path"); - return {}; - } - } else if (!parts.empty() && parts[0] == "IOService:") { - mp.real = false; - } else { - return {}; - } - - return mp; -} - - -/* Take some OSXDisk objects, representing disks that `DARegisterDiskAppearedCallback` told us about, - * and find those drives that we could write a DCP to. The drives returned are "real" (not synthesized) - * and are whole disks (not partitions). They may be mounted, or contain mounted partitions, in which - * their mounted() method will return true. - */ -vector -osx_disks_to_drives (vector disks) -{ - using namespace boost::algorithm; - - /* Mark disks containing mounted partitions as themselves mounted */ - for (auto& i: disks) { - if (!i.whole) { - continue; - } - for (auto& j: disks) { - if (&i != &j && !j.mount_points.empty() && starts_with(j.device, i.device)) { - LOG_DISK("Marking %1 as mounted because %2 is", i.device, j.device); - std::copy(j.mount_points.begin(), j.mount_points.end(), back_inserter(i.mount_points)); - } - } - } - - /* Mark containers of mounted synths as themselves mounted */ - for (auto& i: disks) { - if (i.media_path.real) { - for (auto& j: disks) { - if (!j.media_path.real && !j.mount_points.empty()) { - /* i is real, j is a mounted synth; if we see the first MEDIA_PATH_REQUIRED_MATCHES parts - * of i anywhere in j we assume they are related and so i shares j's mount points. - */ - bool one_missing = false; - string all_parts; - DCPOMATIC_ASSERT (i.media_path.parts.size() >= MEDIA_PATH_REQUIRED_MATCHES); - for (auto k = 0; k < MEDIA_PATH_REQUIRED_MATCHES; ++k) { - if (find(j.media_path.parts.begin(), j.media_path.parts.end(), i.media_path.parts[k]) == j.media_path.parts.end()) { - one_missing = true; - } - all_parts += i.media_path.parts[k] + " "; - } - - if (!one_missing) { - LOG_DISK("Marking %1 as mounted because %2 is (found %3)", i.device, j.device, all_parts); - std::copy(j.mount_points.begin(), j.mount_points.end(), back_inserter(i.mount_points)); - } - } - } - } - } - - vector drives; - for (auto const& i: disks) { - if (i.whole && i.media_path.real) { - drives.push_back(Drive(i.device, i.mount_points, i.size, i.vendor, i.model)); - LOG_DISK_NC(drives.back().log_summary()); - } - } - - return drives; -} diff --git a/src/lib/cross_osx.cc b/src/lib/cross_osx.cc index 913b19103..20fe9bce8 100644 --- a/src/lib/cross_osx.cc +++ b/src/lib/cross_osx.cc @@ -240,44 +240,6 @@ get_model (CFDictionaryRef& description) } -static optional -analyse_media_path (CFDictionaryRef& description) -{ - using namespace boost::algorithm; - - void const* str = CFDictionaryGetValue (description, kDADiskDescriptionMediaPathKey); - if (!str) { - LOG_DISK_NC("There is no MediaPathKey (no dictionary value)"); - return {}; - } - - auto path_key_cstr = CFStringGetCStringPtr((CFStringRef) str, kCFStringEncodingUTF8); - if (!path_key_cstr) { - LOG_DISK_NC("There is no MediaPathKey (no cstring)"); - return {}; - } - - string path(path_key_cstr); - LOG_DISK("MediaPathKey is %1", path); - return analyse_osx_media_path (path); -} - - -static bool -is_whole_drive (DADiskRef& disk) -{ - io_service_t service = DADiskCopyIOMedia (disk); - CFTypeRef whole_media_ref = IORegistryEntryCreateCFProperty (service, CFSTR(kIOMediaWholeKey), kCFAllocatorDefault, 0); - bool whole_media = false; - if (whole_media_ref) { - whole_media = CFBooleanGetValue((CFBooleanRef) whole_media_ref); - CFRelease (whole_media_ref); - } - IOObjectRelease (service); - return whole_media; -} - - static optional mount_point (CFDictionaryRef& description) { @@ -294,29 +256,17 @@ mount_point (CFDictionaryRef& description) } -/* Here follows some rather intricate and (probably) fragile code to find the list of available - * "real" drives on macOS that we might want to write a DCP to. - * - * We use the Disk Arbitration framework to give us a series of mount_points (/dev/disk0, /dev/disk1, - * /dev/disk1s1 and so on) and we use the API to gather useful information about these mount_points into - * a vector of Disk structs. - * - * Then we read the Disks that we found and try to derive a list of drives that we should offer to the - * user, with details of whether those drives are currently mounted or not. - * - * At the basic level we find the "disk"-level mount_points, looking at whether any of their partitions are mounted. - * - * This is complicated enormously by recent-ish macOS versions' habit of making `synthesized' volumes which - * reflect data in `real' partitions. So, for example, we might have a real (physical) drive /dev/disk2 with - * a partition /dev/disk2s2 whose content is made into a synthesized /dev/disk3, itself containing some partitions - * which are mounted. /dev/disk2s2 is not considered to be mounted, in this case. So we need to know that - * disk2s2 is related to disk3 so we can consider disk2s2 as mounted if any parts of disk3 are. In order to do - * this I am taking the first two parts of the IODeviceTree and seeing if they exist anywhere in a - * IOService identifier. If they do, I am assuming the IOService device is on the matching IODeviceTree device. - * - * Lots of this is guesswork and may be broken. In my defence the documentation that I have been able to - * unearth is, to put it impolitely, crap. - */ +static bool +get_bool(CFDictionaryRef& description, void const* key) +{ + auto value = CFDictionaryGetValue(description, key); + if (!value) { + return false; + } + + return CFBooleanGetValue(reinterpret_cast(value)); +} + static void disk_appeared (DADiskRef disk, void* context) @@ -339,32 +289,30 @@ disk_appeared (DADiskRef disk, void* context) this_disk.model = get_model (description); LOG_DISK("Vendor/model: %1 %2", this_disk.vendor.get_value_or("[none]"), this_disk.model.get_value_or("[none]")); - auto media_path = analyse_media_path (description); - if (!media_path) { - LOG_DISK("Finding media path for %1 failed", bsd_name); - return; - } - - this_disk.media_path = *media_path; - this_disk.whole = is_whole_drive (disk); auto mp = mount_point (description); if (mp) { this_disk.mount_points.push_back (*mp); } - LOG_DISK( - "%1 %2 mounted at %3", - this_disk.media_path.real ? "Real" : "Synth", - this_disk.whole ? "whole" : "part", - mp ? mp->string() : "[nowhere]" - ); - auto media_size_cstr = CFDictionaryGetValue (description, kDADiskDescriptionMediaSizeKey); if (!media_size_cstr) { LOG_DISK_NC("Could not read media size"); return; } + this_disk.system = get_bool(description, kDADiskDescriptionDeviceInternalKey) && !get_bool(description, kDADiskDescriptionMediaRemovableKey); + this_disk.writeable = get_bool(description, kDADiskDescriptionMediaWritableKey); + this_disk.partition = string(bsd_name).find("s", 5) != std::string::npos; + + LOG_DISK( + "%1 %2 %3 %4 mounted at %5", + bsd_name, + this_disk.system ? "system" : "non-system", + this_disk.writeable ? "writeable" : "read-only", + this_disk.partition ? "partition" : "drive", + mp ? mp->string() : "[nowhere]" + ); + CFNumberGetValue ((CFNumberRef) media_size_cstr, kCFNumberLongType, &this_disk.size); CFRelease (description); @@ -395,7 +343,12 @@ Drive::get () DAUnregisterCallback(session, (void *) disk_appeared, &disks); CFRelease(session); - auto drives = osx_disks_to_drives(disks); + vector drives; + for (auto const& disk: disks) { + if (!disk.system && !disk.partition && disk.writeable) { + drives.push_back({disk.device, disk.mount_points, disk.size, disk.vendor, disk.model}); + } + } LOG_DISK("Drive::get() found %1 drives:", drives.size()); for (auto const& drive: drives) { diff --git a/test/disk_writer_test.cc b/test/disk_writer_test.cc index 553adcae7..ff39eaaea 100644 --- a/test/disk_writer_test.cc +++ b/test/disk_writer_test.cc @@ -228,110 +228,3 @@ BOOST_AUTO_TEST_CASE (disk_writer_test3) cl.run(); } - - -BOOST_AUTO_TEST_CASE (osx_drive_identification_test) -{ - vector disks; - - auto disk = [&disks](string mount_point, string media_path, bool whole, std::vector mount_points) - { - auto mp = analyse_osx_media_path (media_path); - if (mp) { - disks.push_back({mount_point, {}, {}, *mp, whole, mount_points, 0}); - } - }; - - auto find_unmounted = [](vector disks) { - auto drives = osx_disks_to_drives (disks); - vector unmounted; - std::copy_if (drives.begin(), drives.end(), std::back_inserter(unmounted), [](Drive const& drive) { return !drive.mounted(); }); - return unmounted; - }; - - disk("/dev/disk4s1", "IODeviceTree:/arm-io@10F00000/apcie@90000000/pci-bridge1@1/pcie-xhci@0/@7:1", false, {}); - disk("/dev/disk4", "IODeviceTree:/arm-io@10F00000/apcie@90000000/pci-bridge1@1/pcie-xhci@0/@7:0", true, {}); - disk("/dev/disk0", "IODeviceTree:/arm-io@10F00000/ans@77400000/iop-ans-nub/AppleANS3NVMeController/@1:0", true, {}); - disk("/dev/disk0s1", "IODeviceTree:/arm-io@10F00000/ans@77400000/iop-ans-nub/AppleANS3NVMeController/@1:1", false, {}); - disk("/dev/disk0s2", "IODeviceTree:/arm-io@10F00000/ans@77400000/iop-ans-nub/AppleANS3NVMeController/@1:2", false, {}); - disk("/dev/disk0s3", "IODeviceTree:/arm-io@10F00000/ans@77400000/iop-ans-nub/AppleANS3NVMeController/@1:3", false, {}); - disk("/dev/disk1", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/iBootSystemContainer@1/AppleAPFSContainerScheme/AppleAPFSMedia", true, {}); - disk("/dev/disk2", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/RecoveryOSContainer@3/AppleAPFSContainerScheme/AppleAPFSMedia", true, {}); - disk("/dev/disk3", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/Container@2/AppleAPFSContainerScheme/AppleAPFSMedia", false, {}); - disk("/dev/disk1s1", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/iBootSystemContainer@1/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/iSCPreboot@1", false, {}); - disk("/dev/disk1s2", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/iBootSystemContainer@1/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/xART@2", false, {}); - disk("/dev/disk1s3", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/iBootSystemContainer@1/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Hardware@3", false, {}); - disk("/dev/disk1s4", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/iBootSystemContainer@1/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Recovery@4", false, {}); - disk("/dev/disk2s1", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/RecoveryOSContainer@3/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Recovery@1", false, {}); - disk("/dev/disk2s2", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/RecoveryOSContainer@3/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Update@2", false, {}); - disk("/dev/disk3s1", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/Container@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Macintosh HD@1", false, {}); - disk("/dev/disk3s4", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/Container@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Update@4", false, {"/System/Volumes/Update"}); - disk("/dev/disk3s5", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/Container@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Data@5", false, {"/System/Volumes/Data"}); - disk("/dev/disk3s2", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/Container@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Preboot@2", false, {"/System/Volumes/Preboot"}); - disk("/dev/disk3s3", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/Container@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Recovery@3", false, {}); - disk("/dev/disk3s6", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/Container@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/VM@6", false, {"/System/Volumes/VM"}); - disk("/dev/disk3s1s1", "IOService:/AppleARMPE/arm-io@10F00000/AppleT810xIO/ans@77400000/AppleASCWrapV4/iop-ans-nub/RTBuddyV2/RTBuddyService/AppleANS3NVMeController/NS_01@1/IOBlockStorageDriver/APPLE SSD AP0512Q Media/IOGUIDPartitionScheme/Container@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Macintosh HD@1/com.apple.os.update-EA882DCA7A28EBA0A6E94689836BB10D77D84D1AEE2468E17775A447AA815278@1", false, {"/"}); - - vector writeable = find_unmounted (disks); - BOOST_REQUIRE_EQUAL (writeable.size(), 1U); - BOOST_CHECK_EQUAL (writeable[0].device(), "/dev/disk4"); - - disks.clear (); - disk("/dev/disk4s1", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@0/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media/IOGUIDPartitionScheme/disk image@1", false, {}); - disk("/dev/disk4", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@0/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media", true, {}); - disk("/dev/disk3s1", "IODeviceTree:/PCI0@0/XHC1@14/@2:1", false, {}); - disk("/dev/disk3", "IODeviceTree:/PCI0@0/XHC1@14/@2:0", true, {}); - disk("/dev/disk0", "IODeviceTree:/PCI0@0/SATA@1F,2/PRT1@1/PMP@0/@0:0", true, {}); - disk("/dev/disk0s1", "IODeviceTree:/PCI0@0/SATA@1F,2/PRT1@1/PMP@0/@0:1", false, {}); - disk("/dev/disk0s2", "IODeviceTree:/PCI0@0/SATA@1F,2/PRT1@1/PMP@0/@0:2", false, {"/Volumes/Macintosh HD"}); - disk("/dev/disk0s3", "IODeviceTree:/PCI0@0/SATA@1F,2/PRT1@1/PMP@0/@0:3", false, {}); - disk("/dev/disk0s4", "IODeviceTree:/PCI0@0/SATA@1F,2/PRT1@1/PMP@0/@0:4", false, {}); - disk("/dev/disk0s5", "IODeviceTree:/PCI0@0/SATA@1F,2/PRT1@1/PMP@0/@0:5", false, {"/Volumes/High Sierra"}); - disk("/dev/disk0s6", "IODeviceTree:/PCI0@0/SATA@1F,2/PRT1@1/PMP@0/@0:6", false, {}); - disk("/dev/disk0s7", "IODeviceTree:/PCI0@0/SATA@1F,2/PRT1@1/PMP@0/@0:7", false, {"/Volumes/Recovery HD"}); - disk("/dev/disk1", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 3@3/AppleAPFSContainerScheme/AppleAPFSMedia", true, {}); - disk("/dev/disk", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 4@4/AppleAPFSContainerScheme/AppleAPFSMedia", true, {}); - disk("/dev/disk1s1", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 3@3/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Untitled - Data@1", false, {"/Volumes/Untitled - Data"}); - disk("/dev/disk1s2", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 3@3/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Preboot@2", false, {}); - disk("/dev/disk1s3", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 3@3/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Recovery@3", false, {}); - disk("/dev/disk1s4", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 3@3/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/VM@4", false, {}); - disk("/dev/disk1s5", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 3@3/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Untitled@5", false, {"/Volumes/Untitled"}); - disk("/dev/disk2s1", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 4@4/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Catalina - Data@1", false, {}); - disk("/dev/disk2s2", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 4@4/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Preboot@2", false, {}); - disk("/dev/disk2s3", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 4@4/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Recovery@3", false, {}); - disk("/dev/disk2s4", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 4@4/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/VM@4", false, {"/private/var/vm"}); - disk("/dev/disk2s5", "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleIntelPchSeriesAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/APPLE HDD ST500LM012 Media/IOGUIDPartitionScheme/Untitled 4@4/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Catalina@5", false, {"/"}); - - writeable = find_unmounted (disks); - BOOST_REQUIRE_EQUAL (writeable.size(), 1U); - BOOST_CHECK_EQUAL (writeable[0].device(), "/dev/disk3"); - - disks.clear (); - disk("/dev/disk7", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@3/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media", true, {}); - disk("/dev/disk7s1", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@3/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media/IOGUIDPartitionScheme/disk image@1", false, {}); - disk("/dev/disk6s1", "MediaPathKey is IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@2/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media/IOGUIDPartitionScheme/disk image@1", false, {}); - disk("/dev/disk6", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@2/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media", true, {}); - disk("/dev/disk5s1", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@1/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media/IOGUIDPartitionScheme/disk image@1", false, {}); - disk("/dev/disk5", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@1/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media", true, {}); - disk("/dev/disk4s1", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@0/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media/IOGUIDPartitionScheme/disk image@1", false, {}); - disk("/dev/disk4", "IOService:/IOResources/IOHDIXController/IOHDIXHDDriveOutKernel@0/IODiskImageBlockStorageDeviceOutKernel/IOBlockStorageDriver/Apple UDIF read-only compressed (zlib) Media", true, {}); - disk("/dev/disk0", "IODeviceTree:/PCI0@1e0000/pci8086,2829@1F,2/PRT3@3/PMP@0/@0:0", true, {}); - disk("/dev/disk2", "IODeviceTree:/PCI0@1e0000/pci8086,2829@1F,2/PRT1@1/PMP@0/@0:0", true, {}); - disk("/dev/disk1", "IODeviceTree:/PCI0@1e0000/pci8086,2829@1F,2/PRT0@0/PMP@0/@0:0", true, {}); - disk("/dev/disk1s1", "IODeviceTree:/PCI0@1e0000/pci8086,2829@1F,2/PRT0@0/PMP@0/@0:1", false, {"/Volumes/EFI"}); - disk("/dev/disk2s1", "IODeviceTree:/PCI0@1e0000/pci8086,2829@1F,2/PRT1@1/PMP@0/@0:1", false, {}); - disk("/dev/disk2s2", "IODeviceTree:/PCI0@1e0000/pci8086,2829@1F,2/PRT1@1/PMP@0/@0:2", false, {}); - disk("/dev/disk3", "IOService:/AppleACPIPlatformExpert/PCI0@1e0000/AppleACPIPCI/pci8086,2829@1F,2/AppleAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/VBOX HARDDISK Media/IOGUIDPartitionScheme/disk image@2/AppleAPFSContainerScheme/AppleAPFSMedia", false, {}); - disk("/dev/disk3s1", "IOService:/AppleACPIPlatformExpert/PCI0@1e0000/AppleACPIPCI/pci8086,2829@1F,2/AppleAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/VBOX HARDDISK Media/IOGUIDPartitionScheme/disk image@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/macOS - Data@1", false, {"/System/Volumes/Data"}); - disk("/dev/disk3s2", "IOService:/AppleACPIPlatformExpert/PCI0@1e0000/AppleACPIPCI/pci8086,2829@1F,2/AppleAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/VBOX HARDDISK Media/IOGUIDPartitionScheme/disk image@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Preboot@2", false, {"/System/Volumes/Preboot"}); - disk("/dev/disk3s3", "IOService:/AppleACPIPlatformExpert/PCI0@1e0000/AppleACPIPCI/pci8086,2829@1F,2/AppleAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/VBOX HARDDISK Media/IOGUIDPartitionScheme/disk image@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Recovery@3", false, {}); - disk("/dev/disk3s4", "IOService:/AppleACPIPlatformExpert/PCI0@1e0000/AppleACPIPCI/pci8086,2829@1F,2/AppleAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/VBOX HARDDISK Media/IOGUIDPartitionScheme/disk image@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/VM@4", false, {"/System/Volumes/VM"}); - disk("/dev/disk3s5", "IOService:/AppleACPIPlatformExpert/PCI0@1e0000/AppleACPIPCI/pci8086,2829@1F,2/AppleAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/VBOX HARDDISK Media/IOGUIDPartitionScheme/disk image@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/macOS@5", false, {}); - disk("/dev/disk3s6", "IOService:/AppleACPIPlatformExpert/PCI0@1e0000/AppleACPIPCI/pci8086,2829@1F,2/AppleAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/VBOX HARDDISK Media/IOGUIDPartitionScheme/disk image@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/Update@6", false, {"/System/Volumes/Update"}); - disk("/dev/disk3s5s1", "IOService:/AppleACPIPlatformExpert/PCI0@1e0000/AppleACPIPCI/pci8086,2829@1F,2/AppleAHCI/PRT1@1/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/VBOX HARDDISK Media/IOGUIDPartitionScheme/disk image@2/AppleAPFSContainerScheme/AppleAPFSMedia/AppleAPFSContainer/macOS@5/com.apple.os.update-5523D8E63431315F9F949CCDD0274BF797F5CEE4EAF616D4C66A01B8D6A83C7B@1", false, {"/"}); - - writeable = find_unmounted (disks); - BOOST_REQUIRE_EQUAL (writeable.size(), 1U); - BOOST_CHECK_EQUAL (writeable[0].device(), "/dev/disk0"); -} - -- 2.30.2