2015-11-24 13 views
6

Jeśli prowadzisz dd z tym:Jak programowo utworzyć całkowicie pusty plik rzadki na Linuksie?

dd if=/dev/zero of=sparsefile bs=1 count=0 seek=1048576 

pojawiasz się uzyskać całkowicie nieprzydzielone rzadki plik (jest ext4)

[email protected]:/sp$ ls -ls sparsefile 
0 -rw-rw-r-- 1 smark smark 1048576 Nov 24 16:19 sparsefile 

fibmap zgadza:

[email protected]:/sp$ sudo hdparm --fibmap sparsefile 
sparsefile: 
filesystem blocksize 4096, begins at LBA 2048; assuming 512 byte sectors. 
byte_offset begin_LBA end_LBA sectors 

bez konieczności przekopać się przez źródło dd, próbuję dowiedzieć się, jak to zrobić w C.

Próbowałem fseeking i fwriting zero bajtów, ale nic nie zrobił. Nie jestem pewien, co jeszcze spróbować, pomyślałem, że ktoś może wiedzieć, zanim poluję na dd's innards.

EDIT: w tym moim przykładzie ...

FILE *f = fopen("/sp/sparse2", "wb"); 
fseek(f, 1048576, SEEK_CUR); 
fwrite("x", 1, 0, f); 
fclose(f); 
+1

'dd' jest open source. chwyć źródło i przejrzyj je ... –

+0

musisz pominąć część o "bez konieczności przekopywania się przez źródło dd". Pomyślałem, że ktoś może po prostu wiedzieć. – stu

+0

Może nie rozumiem pytania, ale czy szukasz 'touch '? –

Odpowiedz

6

Podczas zapisu do pliku przy użyciu write lub różne procedury biblioteczne, które ostatecznie nazwać write, tam offsetu pliku wskaźnik związane z deskryptora pliku, który określa gdzie w pliku pójdą bajty. Zazwyczaj znajduje się na końcu danych przetworzonych przez ostatnie wywołanie na read lub write. Ale możesz użyć lseek, aby ustawić wskaźnik w dowolnym miejscu w pliku, a nawet poza bieżącym końcem pliku. Podczas zapisywania danych w punkcie poza bieżącym EOF, obszar, który został pominięty, jest koncepcyjnie wypełniony zerami. Wiele systemów zoptymalizuje rzeczy, tak że cały system plików blokowany w tym pomijanym obszarze po prostu nie zostanie przydzielony, co powoduje powstanie rzadkiego pliku . Próby odczytu takich bloków zakończą się powodzeniem, zwracając zera.

Pisanie pełnych zera pełnych wymiarów do pliku nie powoduje generowania pliku rozrzedzonego, chociaż niektóre systemy plików mogą to zrobić.

Innym sposobem utworzenia pliku rzadkiego, używanego przez GNU dd, jest wywołanie ftruncate. Numer documentation mówi:

Funkcja ftruncate() powoduje, że zwykły plik, do którego odwołują się fildes, ma rozmiar długości bajtów.

Jeśli poprzednio plik był większy niż długość, dodatkowe dane są odrzucane. Jeśli był wcześniej krótszy niż długość, nie jest określone, czy plik zostanie zmieniony, czy zwiększy się jego rozmiar. Jeśli plik zostanie przedłużony, rozszerzony obszar pojawi się tak, jakby był wypełniony zerami.

Wsparcie dla plików rzadkich plików jest specyficzne, chociaż praktycznie wszystkie zaprojektowane-for-UNIX lokalnych systemów plików obsługuje ich.

+0

Właśnie pokonałeś mnie to! –

+0

zfs robi to przy okazji, zapisując fragmenty sąsiadujących zera do pliku (jeśli jakiś schemat kompresji jest włączony) w zasadzie dziurkuje ten obszar z powrotem w rzadkość. – stu

+0

@stu Dzięki za to - miałem nadzieję, że ludzie z doświadczeniem w różnych systemach plików będą komentować. Dodam dodatkowe informacje do mojej odpowiedzi po kilku dniach. –

3

ten jest komplementarny do odpowiedzi przez @MarkPlotnick, to próbka prosta implementacja Żądana funkcja użyciu 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; 
} 
+0

Użycie 'fchmod()' nie jest tutaj zalecane, ponieważ pomija 'umask'. Tryb powinien zostać przekazany do 'open()'. –

+0

Naprawiłem to. 'mode' jest trzecim parametrem' open() '. –

+0

Dzięki za przesłanie przykładu - dodaj parsowanie wiersza poleceń dla nazwy pliku i rozmiaru, a byłoby to przydatne narzędzie. – ChuckCottrill