代码之家  ›  专栏  ›  技术社区  ›  robottobor

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

  •  9
  • robottobor  · 技术社区  · 17 年前

    我想创建一个稀疏文件,这样在我向所有零块写入数据之前,它们都不会占用实际的磁盘空间。有可能吗?

    7 回复  |  直到 17 年前
        1
  •  7
  •   David Kanarek    11 年前

    对于默认的Mac OS X文件系统(HFS+)是否支持文件中的漏洞,似乎存在一些混淆。以下程序证明情况并非如此。

    #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;
    }
    

    该程序创建了两个文件,每个文件的长度为100000字节,其中一个文件有一个99988字节的漏洞。

    在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

    而在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
        2
  •  11
  •   titaniumdecoy Mr. T    17 年前

    与其他Unixes一样,这是文件系统的一个特性。文件系统要么支持所有文件,要么不支持。与Win32不同,你不需要做任何特殊的事情来实现它。与Win32不同的是,使用稀疏文件不会带来性能损失。

    在MacOS上,默认文件系统是HFS+ 不 支持稀疏文件。

    更新: MacOS过去支持具有稀疏文件支持的UFS卷,但已被删除。目前支持的文件系统都不支持稀疏文件。

        3
  •  2
  •   opal    16 年前

    此线程成为有关稀疏文件的综合信息源。以下是Win32缺少的部分:

    Decent article with examples

    Tool that estimates if it makes sense to make file as sparse

    当做

        4
  •  1
  •   diciu    17 年前

    hdiutil可以处理稀疏的图像和文件,但不幸的是,它链接的框架是私有的。

    您可以尝试按照下面的DiskImages框架定义外部符号,但这很可能不适用于生产代码,此外,由于该框架是私有的,您必须对其用例进行逆向工程。

    克里斯蒂:~diciu$otool-L/usr/bin/hdiutil

    /usr/bin/hdiutil: /系统/库/私有框架/DiskImages.framework/Versions/A/DiskImages(兼容版本1.0.8,当前版本194.0.0) [..]

    cristi:~diciu$nm/系统/库/私有框架/DiskImages.framework/Versions/A/DiskImages|awk-F''{print$3}'|c++filt|grep-i稀疏

    [..]

    CS解析器文件::sector2Band(长-长)

    CS解析器文件::addIndexNode()

    CSparseFile::readIndexNode(长-长,SparseFileIndexNode*)

    CSparseFile::readHeaderNode(CBackingStore*,SparseFileHeaderNode*,无符号长节点)

    […为简洁起见,请剪切]

    稍后编辑

    你 可能会 将hdiutil用作外部进程,并让它为您创建稀疏磁盘映像。从C进程中,您将在(挂载的)稀疏磁盘映像中创建一个文件。

        5
  •  0
  •   Remo.D    17 年前

    如果您将(fseek,ftruncate,…)搜索到末尾之后,文件大小将增加,而不会分配块,直到您写入孔为止。但是,没有办法创建一个自动将零块转换为空穴的神奇文件。你必须自己做。

    这可能有助于了解(OpenBSD cp命令插入孔而不是写入零)。 patch

        6
  •  0
  •   user10392    17 年前

    如果你想要可移植性,最后的手段是编写自己的访问函数,以便管理索引和一组块。

    本质上,你管理一个文件,就像操作系统管理磁盘一样,保留文件中块的链、分配/空闲块的位图等。

    当然,这将导致非优化和较慢的访问,我建议只有在节省空间的要求绝对关键并且您有足够的时间编写一组健壮的访问函数时才采用这种方法。

    即使在这种情况下,我也会首先调查你的问题是否需要不同的解决方案。也许你应该用不同的方式存储数据?

        7
  •  0
  •   eladts    12 年前

    看起来OS X支持UDF卷上的稀疏文件。我在OS X 10.9上尝试了titaniumdecoy的测试程序,它确实在UDF磁盘映像上生成了一个稀疏文件。此外,并不是说OS X不再支持UFS,所以如果你需要稀疏文件,UDF是唯一支持它们的原生文件系统。

    我还尝试了SMB共享上的程序。当服务器是Ubuntu(ext4文件系统)时,程序会创建一个稀疏文件,但SMB中的“ls-ls”不会显示出来。如果你在Ubuntu主机上执行'ls-ls',它确实会显示文件稀疏。当服务器是Windows XP(NTFS文件系统)时,程序不会生成稀疏文件。