简体   繁体   English

如何在Mac OS X上以C编程方式创建稀疏文件?

[英]How do I create a sparse file programmatically, in C, on Mac OS X?

I'd like to create a sparse file such that all-zero blocks don't take up actual disk space until I write data to them. 我想创建一个稀疏文件,使得在我向它们写入数据之前,全零块不会占用实际的磁盘空间。 Is it possible? 可能吗?

There seems to be some confusion as to whether the default Mac OS X filesystem (HFS+) supports holes in files. 对于默认的Mac OS X文件系统(HFS +)是否支持文件中的漏洞,似乎存在一些混淆。 The following program demonstrates that this is not the case. 以下程序表明情况并非如此。

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

void create_file_with_hole(void)
{
    int fd = open("file.hole", O_WRONLY|O_TRUNC|O_CREAT, 0600);
    write(fd, "Hello", 5);
    lseek(fd, 99988, SEEK_CUR); // Make a hole
    write(fd, "Goodbye", 7);
    close(fd);
}

void create_file_without_hole(void)
{
    int fd = open("file.nohole", O_WRONLY|O_TRUNC|O_CREAT, 0600);
    write(fd, "Hello", 5);
    char buf[99988];
    memset(buf, 'a', 99988);
    write(fd, buf, 99988); // Write lots of bytes
    write(fd, "Goodbye", 7);
    close(fd);
}

int main()
{
    create_file_with_hole();
    create_file_without_hole();
    return 0;
}

The program creates two files, each 100,000 bytes in length, one of which has a hole of 99,988 bytes. 该程序创建两个文件,每个文件长度为100,000字节,其中一个文件的漏洞为99,988字节。

On Mac OS X 10.5 on an HFS+ partition, both files take up the same number of disk blocks (200): 在HFS +分区上的Mac OS X 10.5上,两个文件占用相同数量的磁盘块(200):

$ ls -ls
total 400
200 -rw-------  1 user  staff  100000 Oct 10 13:48 file.hole
200 -rw-------  1 user  staff  100000 Oct 10 13:48 file.nohole

Whereas on CentOS 5, the file without holes consumes 88 more disk blocks than the other: 而在CentOS 5上,没有空洞的文件比另一个消耗多88个磁盘块:

$ ls -ls
total 136
 24 -rw-------  1 user   nobody 100000 Oct 10 13:46 file.hole
112 -rw-------  1 user   nobody 100000 Oct 10 13:46 file.nohole

As in other Unixes, it's a feature of the filesystem. 和其他Unix一样,它是文件系统的一个特性。 Either the filesystem supports it for ALL files or it doesn't. 文件系统支持所有文件,或者不支持。 Unlike Win32, you don't have to do anything special to make it happen. 与Win32不同,您无需执行任何特殊操作即可实现。 Also unlike Win32, there is no performance penalty for using a sparse file. 与Win32不同,使用稀疏文件没有性能损失。

On MacOS, the default filesystem is HFS+ which does not support sparse files. 在MacOS上,默认文件系统是HFS +,它支持稀疏文件。

Update: MacOS used to support UFS volumes with sparse file support, but that has been removed. 更新: MacOS用于支持具有稀疏文件支持的UFS卷,但已被删除。 None of the currently supported filesystems feature sparse file support. 当前支持的文件系统都不支持稀疏文件。

This thread becomes a comprehensive source of info about the sparse files. 该线程成为有关稀疏文件的综合信息源。 Here is the missing part for Win32: 这是Win32缺少的部分:

Decent article with examples 带有例子的体面文章

Tool that estimates if it makes sense to make file as sparse 估计将文件设置为稀疏是否有意义的工具

Regards 问候

hdiutil can handle sparse images and files but unfortunately the framework it links against is private. hdiutil可以处理稀疏的图像和文件,但不幸的是它链接的框架是私有的。

You could try defining external symbols as defined by the DiskImages framework below but this is most likely not acceptable for production code, plus since the framework is private you'd have to reverse engineer its use cases. 您可以尝试定义下面的DiskImages框架定义的外部符号,但这很可能不适用于生产代码,而且由于框架是私有的,您必须对其用例进行反向工程。

cristi:~ diciu$ otool -L /usr/bin/hdiutil cristi:~diciu $ otool -L / usr / bin / hdiutil

/usr/bin/hdiutil: /System/Library/PrivateFrameworks/DiskImages.framework/Versions/A/DiskImages (compatibility version 1.0.8, current version 194.0.0) [..] / usr / bin / hdiutil:/System/Library/PrivateFrameworks/DiskImages.framework/Versions/A/DiskImages(兼容版本1.0.8,当前版本194.0.0)[..]

cristi:~ diciu$ nm /System/Library/PrivateFrameworks/DiskImages.framework/Versions/A/DiskImages | cristi:~diciu $ nm /System/Library/PrivateFrameworks/DiskImages.framework/Versions/A/DiskImages | awk -F' ' '{print $3}' | awk -F'''{print $ 3}'| c++filt | c ++ filt | grep -i sparse grep -i稀疏

[..] [..]

CSparseFile::sector2Band(long long) CSparseFile :: sector2Band(long long)

CSparseFile::addIndexNode() CSparseFile :: addIndexNode()

CSparseFile::readIndexNode(long long, SparseFileIndexNode*) CSparseFile :: readIndexNode(long long,SparseFileIndexNode *)

CSparseFile::readHeaderNode(CBackingStore*, SparseFileHeaderNode*, unsigned long) CSparseFile :: readHeaderNode(CBackingStore *,SparseFileHeaderNode *,unsigned long)

[... cut for brevity] [...为简洁起见]

Later Edit 稍后编辑

You could use hdiutil as an external process and have it create an sparse disk image for you. 可以将hdiutil用作外部进程,并让它为您创建稀疏磁盘映像。 From the C process you would then create a file in the (mounted) sparse disk image. 然后,在C进程中,您将在(已安装的)稀疏磁盘映像中创建一个文件。

If you want portability, the last resort is to write your own access function so that you manage an index and a set of blocks. 如果您想要可移植性,最后的方法是编写自己的访问函数,以便管理索引和一组块。

In essence you manage a single file as the OS manages the disk keeping the chain of the blocks that are part of the file, the bitmap of allocated/free blocks etc. 本质上,您管理单个文件,因为操作系统管理磁盘,保留作为文件一部分的块链,分配/空闲块的位图等。

Of course this will lead to a non optimized and slower access, I would reccomend this apprach only if the requirement to save space is absolutely critical and you have enough time to write a robust set of access functions. 当然这会导致非优化和较慢的访问,只有节省空间的要求绝对关键并且你有足够的时间来编写一组强大的访问函数时,我才会推荐这个apprach。

And even in that case, I would first investigate if your problem is in need of a different solution. 即使在这种情况下,我也会首先调查您的问题是否需要不同的解决方案。 Probably you should store your data differently? 您可能应该以不同方式存储数据吗?

If you seek (fseek, ftruncate, ...) to past the end, the file size will be increased without allocating blocks until you write to the holes. 如果你寻找(fseek,ftruncate,...)到最后,文件大小将增加而不分配块,直到你写入孔。 But there's no way to create a magic file that automatically converts blocks of zeroes to holes. 但是没有办法创建一个自动将零块转换为空洞的魔术文件。 You have to do it yourself. 你必须自己做。

This may be helpful to look at (the OpenBSD cp command inserts holes instead of writing zeroes). 这可能有助于查看(OpenBSD cp命令插入孔而不是写入零)。 patch 补丁

It looks like OS X supports sparse files on UDF volumes. 看起来OS X支持UDF卷上的稀疏文件。 I tried titaniumdecoy's test program on OS X 10.9 and it did generate a sparse file on a UDF disk image. 我在OS X 10.9上尝试了titaniumdecoy的测试程序,它确实在UDF磁盘映像上生成了一个稀疏文件。 Also, not that UFS is no longer supported in OS X, so if you need sparse files, UDF is the only natively supported file system that supports them. 此外,OS X不再支持UFS,因此如果您需要稀疏文件,UDF是唯一支持它们的本机支持的文件系统。

I also tried the program on SMB shares. 我也尝试过关于SMB股票的计划。 When the server is Ubuntu (ext4 filesystem) the program creates a sparse file, but 'ls -ls' through SMB doesn't show that. 当服务器是Ubuntu(ext4文件系统)时,程序会创建一个稀疏文件,但是通过SMB的'ls -ls'不会显示该文件。 If you do 'ls -ls' on the Ubuntu host itself it does show the file is sparse. 如果你在Ubuntu主机上做'ls -ls',它确实显示文件是稀疏的。 When the server is Windows XP (NTFS filesystem) the program does not generate a sparse file. 当服务器是Windows XP(NTFS文件系统)时,程序不会生成稀疏文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM