在macOS Catalina,Big Sur和更高版本中确定卷组 [英] Determine Volume Groups in macOS Catalina, Big Sur and later

查看:138
本文介绍了在macOS Catalina,Big Sur和更高版本中确定卷组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从macOS 10.15(Catalina)开始,一个卷(如用户所见)实际上可能由多个卷组成,例如系统"卷和数据"卷.

Since macOS 10.15 (Catalina), a volume, as the user sees it, may actually be comprised of multiple volumes, such as the System and the Data volume.

我正在编写一个需要分别识别这些卷的工具,因为使用诸如 searchfs fts_read 之类的特定文件操作时,它们不会跨越这些卷的边界,我需要了解哪些卷属于同一类,以便在用户想要搜索系统卷时,我知道同时包括系统"卷和系统"卷.及其数据"卷在文件操作中.

I'm writing a tool that needs to identify these volumes separately because when using specific file operations, such as searchfs and fts_read, which do not cross such volume boundaries, I need to understand which volumes belong together, so that, when the user wants to search a system volume, I know to include both the "System" and its "Data" volumes in the file operations.

如何安全地确定哪些卷属于同一卷?

How do I safely determine which volumes belong together?

仅使用 [NSFileManager MountedVolumeURLsIn includedResourceValuesForKeys:options:] 并没有多大帮助,因为它不会在/System/Volumes/Data 中包含根系统的数据卷(但可能包含隐藏的/System/Volumes/Data/home 卷).使用诸如 df 之类的命令行工具也是如此.

Using [NSFileManager mountedVolumeURLsIncludingResourceValuesForKeys:options:] is not much help alone because it won't include the root system's Data volume at /System/Volumes/Data (but may include the hidden /System/Volumes/Data/home volume). Same goes for using command line tools such as df.

我需要考虑当前未引导的其他系统卷.例如,如果我同时拥有BigSur和Catalina系统,并且已经从前者启动,那么我希望能够识别出这四个卷:

I need to consider other system volumes that are not currently booted. E.g, if I have both a BigSur and a Catalina system, and have started up from the former, I want to be able to identify these four volumes:

/                              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"的两个卷中实际属于同一个群体?我不喜欢用部分名称来匹配它们,因为这对我来说似乎是随机的并且不可靠.数据量甚至没有使用数据"这一事实也得到了证实.如果它不是在英语系统上创建的,那么它的名称已经太难了.

How would I tell that the two volumes containing "Catalina" actually belong to the same group? I don't like to match them up by partial names as this seems rather random and unreliable to me. And the fact that the data volume is not even using "Data" in the name if it's not created on an English system makes this already much too difficult to get right.

也许还有其他一些卷属性可以帮助识别这些卷组吗?

Is there perhaps some other volume property that would help identify these volume groups?

推荐答案

Mike Bombich 为我提供了此解决方案:

Mike Bombich provided me with this solution:

您可以从IOKit获取卷UUID和卷组UUID.同一组中的两个卷将具有相同的组UUID.请注意,组UUID始终与数据卷的UUID相同(至少在实践中是这样).

You can get the volume UUID and the volume group UUID from IOKit. Two volumes that are in the same group will have the same group UUID. Note that the group UUID is always the same as the Data volume's UUID (at least in practice).

以下是获取已安装卷列表的代码,包括作为卷组一部分的隐藏卷:

Here's the code for getting the list of mounted volumes, including the hidden ones that are part of a volume group:

- (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及其角色的代码:

And the code for listing the volume group IDs, and their roles:

- (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匹配.

With both this information, the volumes from IOKit can be matched to the NSURLs through their BSD Names.

但是,还有另一种特殊情况:在macOS Big Sur上,根系统的设备不是常规的"diskXsY"设备.而是快照设备,例如"diskXsYsZ".尽管IOKit代码也列出了该条目,但其条目缺少角色信息.

However, there's one more special case: On macOS Big Sur the root system's device is not the regular "diskXsY" but a snapshot device such as "diskXsYsZ". And while that gets listed as well by the IOKit code, its entry is missing the role information.

以下是Mac的示例输出,该Mac同时具有Big Sur和Catalina系统(问题略作编辑,以提高可读性):

Here's an example output from the Mac with both a Big Sur and a Catalina system as shown in the question (slightly edited for readability):

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 文件中替换):

I have published a working code sample that determines all mounted volumes, and their group relationships. The entire compilable code (which you can replace in a new Obj-C App project's AppDelegate.m file can be found here: https://gist.github.com/tempelmann/80efc2eb84f0171a96822290dee7d8d9

这篇关于在macOS Catalina,Big Sur和更高版本中确定卷组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆