【问题标题】:How to get diskutil info output in a cocoa application如何在可可应用程序中获取 diskutil 信息输出
【发布时间】:2014-01-07 20:20:43
【问题描述】:

有没有办法以编程方式获取diskutil info / | grep "Free Space" 提供给您的相同信息? (出于显而易见的原因,我宁愿有更好的方法来执行此操作,而不仅仅是解析该命令的结果。)

目前我正在使用statfs;然而,我注意到这个报告的空间并不总是准确的,因为 OS X 还会在驱动器上放置临时文件,例如 Time Machine 快照。如果空间用完,这些文件会自动被删除,并且操作系统不会报告这些文件的使用情况。换句话说,statfs 提供的可用空间数量通常少于diskutil info 或在 Finder 中查看磁盘信息。

【问题讨论】:

  • 有趣的是 statfs() 由于 Time Machine 临时文件不准确。我想知道它是怎么做到的?你确定是这样吗?
  • @trojanfoe:我相信statfs 会返回“真实”的可用磁盘空间量。但是,Finder 通过显示更多可用空间来“作弊”,这是因为某些文件会被自动删除。我收到了关于此的错误报告,事实证明这就是问题所在(缩小到df -h 报告的可用空间少于diskutil info / | grep "Free Space"
  • diskutil 显示的可用空间与 df -H 相同。 df -h 使用以 2 为底的尺寸,而 df -H 使用 10。请参阅 man 1 df
  • Wherever a size is supplied as an output, it is always presented as a base-ten approximation with one decimal digit and a base-ten SI multiplier。那是来自man 8 diskutil,这就是你看到不同尺寸的原因。
  • @IvanGenchev:我的测试并非如此。用户报告说:(100.0 * (double)(stats.f_blocks - stats.f_bfree) / (double)stats.f_blocks) 提供的免费百分比与 Finder 不同。

标签: objective-c macos cocoa disk


【解决方案1】:

你可以使用popen(3):

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *f;
    char info[256];

    f = popen("/usr/sbin/diskutil info /", "r");
    if (f == NULL) {
        perror("Failed to run diskutil");
        exit(0);
    }

    while (fgets(info, sizeof(info), f) != NULL) {
        printf("%s", info);
    }

    pclose(f);

    return 0;
}

编辑

抱歉,我没有仔细阅读问题。您也可以使用Disk Arbitration Framework。还有一些示例代码可能会有所帮助 (FSMegaInfo)。

更新

我查看了otool -L $(which diskutil) 的输出,似乎它使用了一个名为DiskManagement.framework 的私有框架。查看class-dump 的输出后,我看到有一个volumeFreeSpaceForDisk:error: 方法。所以我从diskutil -info /FSMegaInfo FSGetVolumeInfo / 和我的工具得到的尺寸是:

  • diskutil:427031642112 Bytes

  • 我的工具:volumeFreeSpaceForDisk: 427031642112

  • FSMegaInfo:freeBytes = 427031642112 (397 GB)

我还观察到,每次运行其中一个工具时,大小都会不同(几 KB),而且 diskutil 除以 1000,FSMegaInfo 除以 1024,因此以 GB 为单位的大小将是总是不同(与 df -hdf -Hdiskutil 的原因相同 - 基数为 10 和基数为 2)。

这是我的示例工具:

#import <Foundation/Foundation.h>
#import "DiskManagement.h"
#import <DiskArbitration/DADisk.h>

int main(int argc, char *argv[])
{
    int                 err;
    const char *        bsdName = "disk0s2";
    DASessionRef        session;
    DADiskRef           disk;
    CFDictionaryRef     descDict;
    session  = NULL;
    disk     = NULL;
    descDict = NULL;
    if (err == 0) {session = DASessionCreate(NULL); if (session == NULL) {err = EINVAL;}}
    if (err == 0) {disk = DADiskCreateFromBSDName(NULL, session, bsdName); if (disk == NULL) {err = EINVAL;}}
    if (err == 0) {descDict = DADiskCopyDescription(disk); if (descDict == NULL) {err = EINVAL;}}

    DMManager *dmMan = [DMManager sharedManager];
    NSLog(@"blockSizeForDisk: %@", [dmMan blockSizeForDisk:disk error:nil]);
    NSLog(@"totalSizeForDisk: %@", [dmMan totalSizeForDisk:disk error:nil]);
    NSLog(@"volumeTotalSizeForDisk: %@", [dmMan volumeTotalSizeForDisk:disk error:nil]);
    NSLog(@"volumeFreeSpaceForDisk: %@", [dmMan volumeFreeSpaceForDisk:disk error:nil]);

    return 0;
}

您可以通过运行class-dump /System/Library/PrivateFrameworks/DiskManagement.framework/Versions/Current/DiskManagement &gt; DiskManagement.h 来获取DiskManagement.h,并且可以通过使用-F/System/Library/PrivateFrameworks/ 包含私有框架路径并添加-framework 来链接到该框架。

编译:

clang -g tool.m -F/System/Library/PrivateFrameworks/ -framework Foundation -framework DiskArbitration -framework DiskManagement -o tool

更新 2: 你也可以看看herehere。如果FSMegaInfo 示例不适合您,那么您可以只使用stat /Volumes/.MobileBackups 并从您从statfs("/", &amp;stats) 获得的大小中减去它的大小。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-21
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
相关资源
最近更新 更多