Как программно создать разреженный файл в C на Mac OS X?

Я хотел бы создать разреженный файл, чтобы блоки с нулем не занимали фактического дискового пространства, пока я не запишу в них данные. Является ли это возможным?

7 ответов

Решение

Как и в других Unix, это особенность файловой системы. Либо файловая система поддерживает его для ВСЕХ файлов, либо нет. В отличие от Win32, вам не нужно делать ничего особенного, чтобы это произошло. Кроме того, в отличие от Win32, нет никакого снижения производительности за использование разреженного файла.

В MacOS файловой системой по умолчанию является HFS+, которая не поддерживает разреженные файлы.

Обновление: MacOS раньше поддерживал тома UFS с разреженной поддержкой файлов, но это было удалено. Ни одна из поддерживаемых в настоящее время файловых систем не поддерживает разреженные файлы.

Кажется, есть некоторая путаница относительно того, поддерживает ли файловая система 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;
}

Программа создает два файла, каждый длиной 100 000 байт, один из которых имеет отверстие 99 988 байт.

В Mac OS X 10.5 в разделе HFS + оба файла занимают одинаковое количество блоков диска (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

Эта тема становится исчерпывающим источником информации о разреженных файлах. Вот недостающая часть для Win32:

Достойная статья с примерами

Инструмент, который оценивает, имеет ли смысл делать файл разреженным

С уважением

hdiutil может обрабатывать редкие изображения и файлы, но, к сожалению, фреймворк, на который он ссылается, является приватным.

Вы можете попытаться определить внешние символы, как определено в рамках DiskImages ниже, но это, скорее всего, неприемлемо для производственного кода, к тому же, поскольку среда является частной, вам придется перепроектировать ее варианты использования.

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

/ 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 | awk -F '' '{print $ 3}' | с ++ фильт | grep -i разреженный

[..]

CSparseFile:: sector2Band (long long)

CSparseFile:: addIndexNode ()

CSparseFile:: readIndexNode (long long, SparseFileIndexNode *)

CSparseFile:: readHeaderNode (CBackingStore *, SparseFileHeaderNode *, длинный без знака)

[... вырезать для краткости]

Позже Править

Вы можете использовать hdiutil как внешний процесс и создать для него разреженный образ диска. Из процесса C вы затем создадите файл в (смонтированном) разреженном образе диска.

Если вы стремитесь (fseek, ftruncate, ...) к концу, размер файла будет увеличиваться без выделения блоков, пока вы не напишете в дыры. Но нет никакого способа создать волшебный файл, который автоматически преобразует блоки с нулями в дыры. Вы должны сделать это самостоятельно.

Это может быть полезно посмотреть (команда OpenBSD cp вставляет дыры вместо записи нулей). пластырь

Похоже, OS X поддерживает разреженные файлы на томах UDF. Я попробовал тестовую программу Titaniumdecoy на OS X 10.9, и она сгенерировала разреженный файл на образе диска UDF. Кроме того, UFS больше не поддерживается в OS X, поэтому, если вам нужны разреженные файлы, UDF - единственная изначально поддерживаемая файловая система, которая их поддерживает.

Я также попробовал программу на акциях SMB. Когда сервером является Ubuntu (файловая система ext4), программа создает разреженный файл, но 'ls -ls' через SMB этого не показывает. Если вы выполните команду "ls -ls" на самом хосте Ubuntu, это покажет, что файл редкий. Когда на сервере установлена ​​Windows XP (файловая система NTFS), программа не создает разреженный файл.

Если вам нужна мобильность, в крайнем случае вы должны написать свою собственную функцию доступа, чтобы вы могли управлять индексом и набором блоков.

По сути, вы управляете одним файлом, поскольку ОС управляет диском, сохраняя цепочку блоков, которые являются частью файла, растровое изображение выделенных / свободных блоков и т. Д.

Конечно, это приведет к неоптимизированному и более медленному доступу. Я рекомендую этот подход только в том случае, если требование экономии места является абсолютно критическим, и у вас есть достаточно времени для написания надежного набора функций доступа.

И даже в этом случае я бы сначала выяснил, нуждается ли ваша проблема в другом решении. Возможно, вы должны хранить ваши данные по-другому?

Другие вопросы по тегам