Как программно создать абсолютно пустой разреженный файл в linux?
Если вы запускаете dd с этим:
dd if=/dev/zero of=sparsefile bs=1 count=0 seek=1048576
Вы, кажется, получаете полностью нераспределенный разреженный файл (это ext4)
smark@we:/sp$ ls -ls sparsefile
0 -rw-rw-r-- 1 smark smark 1048576 Nov 24 16:19 sparsefile
Fibmap соглашается:
smark@we:/sp$ sudo hdparm --fibmap sparsefile
sparsefile:
filesystem blocksize 4096, begins at LBA 2048; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
Без необходимости копаться в источнике dd, я пытаюсь выяснить, как это сделать в C.
Я попробовал fseeking и fwriting нулевые байты, но это ничего не дало. Не зная, что еще можно попробовать, я решил, что кто-то может знать, прежде чем я выслежу внутренности ДД.
Правка: включая мой пример...
FILE *f = fopen("/sp/sparse2", "wb");
fseek(f, 1048576, SEEK_CUR);
fwrite("x", 1, 0, f);
fclose(f);
2 ответа:
При записи в файл с помощью
Запись в файл областей размером с блок, полных нулей, как правило, не приводит к созданию разреженного файла, хотя это возможно для некоторых файловых систем.write
или различных библиотечных подпрограмм, которые в конечном счете вызываютwrite
, существует указатель смещения файла, связанный с дескриптором файла, который определяет, куда в файле будут идти байты. Обычно он располагается в конце данных, которые были обработаны последним вызовомread
илиwrite
. Но вы можете использоватьlseek
для размещения указателя в любом месте файла и даже за пределами текущего конца файла. Когда вы записываете данные в точку за пределами текущего EOF область, которая была пропущена, концептуально заполнена нулями. Многие системы оптимизируют вещи так, что любые целые блоки файловой системы в этой пропущенной области просто не выделяются, производя разреженный файл. Попытки считывания таких блоков увенчаются успехом, возвращая нули.Еще один способ получения разреженный файл, используемый GNU dd, должен вызывать
ftruncate
. В документации говорится следующее:Поддержка разреженных файлов зависит от файловой системы, хотя практически все локальные файловые системы, предназначенные для UNIX, поддерживают их.Функция ftruncate () приводит к тому, что обычный файл, на который ссылается fildes, имеет размер в байтах длины.
Если файл ранее был больше длины, то лишние данные отбрасываются. Если ранее он был короче длины, то не указано, изменяется ли файл или увеличивается его размер. Если файл расширен, расширенная область выглядит так, как если бы она была расширена. заполнены нулями.
Это дополнение к ответу @MarkPlotnick, это пример простой реализации функции, которую вы запросили с помощью
ftruncate()
:#include <unistd.h> #include <fcntl.h> #include <sys/stat.h> int main(void) { int file; int mode; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; file = open("sparsefile", O_WRONLY | O_CREAT, mode); if (file == -1) return -1; ftruncate(file, 0x100000); close(file); return 0; }