我有兴趣在OSX上迭代所有挂载的文件系统(目前运行10.9 Mavericks)。我正在寻找类似于getmntent()或mount shell命令的输出(尽管我想从目标C中执行此操作,因此解析shell命令的输出显然不是最佳的)。
我一直在查看磁盘仲裁框架,看来我可以使用此框架通知mount和unmount事件。我可能在那里遗漏了一些东西,但是我不清楚是否有办法使用磁盘仲裁来迭代现有的已安装文件系统。
我已经探索过使用getfsent(),它似乎会提供一个解决方案,但经过测试后我发现我没有从迭代getfsent()获得多个条目。请参阅以下代码:
struct fstab* fsentry;
setfsent();
fsentry = getfsent();
while(fsentry)
{
//do something with fsentry
fsentry = getfsent();
}
endfsent();
我到这里的唯一条目是/ file系统。第二次调用getfsent()时,它返回NULL,好像没有更多的条目。 mount命令向我展示了其他几个,包括已安装的cifs / smb文件系统:
/dev/disk0s2 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)
//user@<ip address>/public on /Volumes/public (smbfs, nodev, nosuid, mounted by user)
所以似乎getfsent()开始做我期望的事情,但出于某种原因停止?
总结我的问题是:在OSX上迭代文件系统的最佳方法是什么?
如果有人对我为什么只从getfsent()获得一个结果的答案,我也会对此感兴趣。
答案 0 :(得分:7)
有两种不同的方法可以在OS X上枚举已装载的卷,每种方法都使用不同的API集。在最高(也是最简单)级别,您可以使用NSFileManager的mountedVolumeURLsIncludingResourceValuesForKeys:options:
。这是一个简短的例子:
NSArray *urls = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:@[NSURLVolumeNameKey] options:0];
for (NSURL *url in urls) {
NSLog(@"Volume mounted at: %@", [url path]);
}
下一个选项将我们带回C领域 - 你与原来的方法非常接近。在OS X(和BSD)上,没有getmntent()
;相反,有getmntinfo()
,这是非常相似的。要通过getmntinfo()
列出已装入的卷,您可以执行以下操作:
struct statfs* mounts;
int num_mounts = getmntinfo(&mounts, MNT_WAIT);
if (num_mounts < 0) {
// do something with the error
}
for (int i = 0; i < num_mounts; i++) {
NSLog(@"Disk type '%s' mounted at: %s", mounts[i].f_fstypename, mounts[i].f_mntonname);
}
自10.6发布以来,我已经并排使用了这两种API。 getmntinfo()
总是比[NSFileManager mountedVolumeURLsIncludingResourceValuesForKeys:options:]
更完整:后者会过滤您可能想知道或不想知道的/dev
和其他文件系统。但是,对于插入系统的磁盘,它通常是可靠的。
正如您所注意到的,DiskArbitration框架背后的目的是不同的。 DiskArbitration是关于监视和管理磁盘资产的。使用DA,只要安装或卸载新磁盘,就可以调用它。您还可以通过重命名,装载,卸载或弹出这些磁盘来管理这些磁盘,以及将您自己插入到装载/卸载过程中 - 并可能暂停请求以执行相同操作。但是,正如您所指出的,它没有提供列出现有磁盘的接口。一旦你获得了已安装卷的列表,DA是一个很好的下一站(当然,取决于你获得该列表的原因!)。