簡體   English   中英

在 macOS Catalina、Big Sur 及更高版本中確定卷組

[英]Determine Volume Groups in macOS Catalina, Big Sur and later

從 macOS 10.15 (Catalina) 開始,一個卷,如用戶所見,實際上可能由多個卷組成,例如 System 和 Data 卷。

我正在編寫一個需要分別識別這些卷的工具,因為當使用特定的文件操作時,例如searchfsfts_read ,它們不會跨越這些卷邊界,我需要了解哪些卷屬於一起,以便在用戶需要時要搜索系統卷,我知道在文件操作中包括“系統”和它的“數據”卷。

如何安全地確定哪些卷屬於一起?

[NSFileManager mountedVolumeURLsIncludingResourceValuesForKeys:options:]使用[NSFileManager mountedVolumeURLsIncludingResourceValuesForKeys:options:]並沒有多大幫助,因為它不會在/System/Volumes/Data包含根系統的數據卷(但可能包括隱藏的/System/Volumes/Data/home卷)。 使用命令行工具(例如df

我需要考慮當前未啟動的其他系統卷。 例如,如果我同時擁有 BigSur 和 Catalina 系統,並且從前者開始,我希望能夠識別這四個卷:

/                              BigSur System volume
/System/Volumes/Data           BigSur Data volume
/Volumes/Catalina              Catalina System volume
/Volumes/Catalina - Daten      Catalina Data volume (created on a German system)

我如何判斷包含“Catalina”的兩卷實際上屬於同一組? 我不喜歡用部分名稱來匹配它們,因為這對我來說似乎相當隨機且不可靠。 如果數據量不是在英文系統上創建的,那么它的名稱中甚至不使用“Data”這一事實使得這已經太難以正確處理了。

是否有其他一些卷屬性可以幫助識別這些卷組?

Mike Bombich為我提供了以下解決方案:

您可以從 IOKit 獲取卷 UUID 和卷組 UUID。 同一組中的兩個卷將具有相同的組 UUID。 請注意,組 UUID 始終與數據卷的 UUID 相同(至少在實踐中是這樣)。

這是獲取已安裝卷列表的代碼,包括屬於卷組的隱藏卷:

- (void)listVolumes
{
    NSArray<NSURL*> *vols = [NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys:nil options: 0 ];
    vols = [vols arrayByAddingObject:[NSURL fileURLWithPath:@"/System/Volumes/Data"]]; // the root's Data vol isn't added by default
    NSMutableArray<NSString*> *lines = [NSMutableArray new];
    for (NSURL *vol in vols) {
        NSDictionary *d = [vol resourceValuesForKeys:@[
            NSURLVolumeIsBrowsableKey,
            NSURLVolumeIsRootFileSystemKey,
            NSURLVolumeIdentifierKey,
            NSURLVolumeNameKey
        ] error:nil];

        struct statfs fsinfo;
        statfs(vol.path.UTF8String, &fsinfo);
        NSString *bsdName = [NSString stringWithUTF8String:fsinfo.f_mntfromname];
        bsdName = [bsdName lastPathComponent];

        [lines addObject:[NSString stringWithFormat:@"%@, %@, %@, %@", bsdName, vol.path, d[NSURLVolumeIsBrowsableKey], d[NSURLVolumeNameKey]]];
    }
    NSLog(@"\n%@", [lines componentsJoinedByString:@"\n"]);
}

以及用於列出卷組 ID 及其角色的代碼:

- (void)listGroupIDs
{
    io_iterator_t iterator; io_object_t obj;
    IOServiceGetMatchingServices (kIOMasterPortDefault, IOServiceMatching("IOMediaBSDClient"), &iterator);
    while ((obj = IOIteratorNext (iterator)) != 0) {
        io_object_t obj2;
        IORegistryEntryGetParentEntry (obj, kIOServicePlane, &obj2);
        NSString *bsdName = CFBridgingRelease(IORegistryEntryCreateCFProperty(obj2, CFSTR("BSD Name"), kCFAllocatorDefault, 0));
        //NSString *volID = CFBridgingRelease(IORegistryEntryCreateCFProperty(obj2, CFSTR("UUID"), kCFAllocatorDefault, 0));
        NSString *groupID = CFBridgingRelease(IORegistryEntryCreateCFProperty(obj2, CFSTR("VolGroupUUID"), kCFAllocatorDefault, 0));
        NSArray *roles = CFBridgingRelease(IORegistryEntryCreateCFProperty(obj2, CFSTR("Role"), kCFAllocatorDefault, 0));
        if (groupID != nil && ![groupID isEqualToString:@"00000000-0000-0000-0000-000000000000"]) {
            NSLog(@"%@: %@, %@", bsdName, groupID, roles);
        }
    }
}

有了這些信息,來自 IOKit 的卷就可以通過它們的 BSD 名稱與 NSURL 匹配。

但是,還有一種特殊情況:在 macOS Big Sur 上,根系統的設備不是常規的“diskXsY”而是快照設備,例如“diskXsYsZ”。 雖然 IOKit 代碼也列出了這一點,但它的條目缺少角色信息。

這是來自 Mac 的示例輸出,帶有 Big Sur 和 Catalina 系統,如問題所示(為​​了可讀性稍作編輯):

disk3s1s1, /, 1, BigSur
disk3s5,   /System/Volumes/VM, 0, VM
disk3s3,   /System/Volumes/Preboot, 0, Preboot
disk3s6,   /System/Volumes/Update, 0, Update
disk4s1,   /Volumes/Catalina - Daten, 0, Catalina - Daten
disk4s2,   /Volumes/Catalina, 1, Catalina
disk3s2,   /System/Volumes/Data, 1, BigSur

disk4s1:   18464FE4-8321-4D36-B87A-53AC38EF6AEF, 18464FE4-8321-4D36-B87A-53AC38EF6AEF, ("Data")
disk3s1:   86812DBD-9252-4A2E-8887-752418DECE13, 058517A6-48DD-46AB-8A78-C1F115AE6E13, ("System")
disk4s2:   51DEC6AC-2D68-4B60-AE23-74BCA2C3A484, 18464FE4-8321-4D36-B87A-53AC38EF6AEF, ("System")
disk3s2:   058517A6-48DD-46AB-8A78-C1F115AE6E13, 058517A6-48DD-46AB-8A78-C1F115AE6E13, ("Data")
disk3s1s1: C26440B0-0207-4227-A4B1-EBDD62C90D24, 058517A6-48DD-46AB-8A78-C1F115AE6E13, (null)

我發布了一個工作代碼示例,用於確定所有已安裝的卷及其組關系。 完整的可編譯代碼(您可以在新的 Obj-C App 項目的AppDelegate.m文件中替換它,可以在這里找到: https : //gist.github.com/tempelmann/80efc2eb84f0171a96822290dee7d8d9

以下 shell 命令列出卷組:

diskutil apfs listVolumeGroups

對於通過代碼進行解析,可以附加選項作為 plist 輸出,然后可以使用CFPropertyListCreateWithDataformat:kCFPropertyListXMLFormat_v1_0

diskutil apfs listVolumeGroups -plist

(答案在Howard Oakley推文中提供)

使用diskutil list檢查卷及其名稱。 system_profiler顯示很多信息,但您必須解析 Volume 信息的輸出,使用system_profiler -xml > output.xml將創建一個文件以了解特定查詢的可用值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM