Czy typowe interfejsy wywołań systemowych pozwalają zmniejszyć rozmiar pliku (bez zastępowania go innym i-węzłem)?

9

Czy istnieje sposób na open()plik i spowodować jego zmniejszenie? Oczywiście można je otwierać w trybie dołączania lub szukać do końca i pisać, aby spowodować ich wzrost. Jednak, o ile mi wiadomo, nie ma metody zmniejszania pliku za pomocą typowych interfejsów wywołań systemowych w stylu uniksowym.

O ile mi wiadomo, jedynym sposobem na zrobienie tego jest sfałszowanie go przez utworzenie nowego krótszego pliku i zastąpienie go rename()starszym.

Chciałem tylko potwierdzenia, ponieważ zobaczyłem odpowiedź, która sugerowała, że ​​można było utworzyć edytory plików, które działały bezpośrednio na pliku, zamiast przechodzić proces tworzenia nowego i zmiany jego nazwy.

Zawsze myślałem, że interfejs plików w interfejsach wywołań systemowych w stylu libc i unix nie pozwala na zmniejszanie plików w celu ułatwienia implementacji systemów plików i może uniknąć wzorców użytkowania, które mogłyby przyczynić się do fragmentacji.

JoL
źródło
2
Samo otwarcie pliku fopenw trybie „w” (lub „w +”) spowoduje automatyczne obcięcie go do zera. A może masz na myśli zmniejszenie się do zera, aby zachować część starej zawartości?
Wyzard
4
Po prostu FYI, open()a openat()już masz flagę do obcinania, O_TRUNCwięc technicznie powoduje to, że plik się zmniejsza - to znaczy całkowicie się zmniejsza - bez zmiany i-węzła. Najbardziej znanym przykładem jest to command > file.txt, że plik zostanie obcięty, jeśli istnieje. Po uruchomieniu stracena bash -c 'true > /dev/null'zobaczysz openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666)na wyjściu. Oczywiście dla zmiennej wielkości obcięcia potrzebujesz truncate()syscall. Daj mi znać, jeśli chcesz to jako rzeczywistą odpowiedź zamiast komentarza.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy Myślałem o zmniejszeniu się do dowolnego rozmiaru. Głosowałem za odpowiedzią Davida Foerstera, ponieważ odpowiada ona na część pytania, ale nie akceptuję jej w świetle odpowiedzi Iwana. Uznałbym to za odpowiedź typu „tak i nie”, podczas gdy odpowiedź Iwana już pokazała, że ​​prawdziwą odpowiedzią jest „tak”.
JoL

Odpowiedzi:

22

man -s 2 ftruncate mówi

DESCRIPTION
   The  truncate()  and  ftruncate()  functions cause the regular file
   named by path or referenced by fd to be truncated to a size of precisely
   length bytes.

...

CONFORMING TO
   POSIX.1-2001, POSIX.1-2008, 4.4BSD, SVr4 (these calls first appeared in 4.2BSD).

mówi dalej, że jeśli używasz ftruncate, musisz otworzyć plik do zapisu, a jeśli używasz skrótu, plik musi być zapisywalny.

Ikar
źródło
Dołączenie do pliku powoduje, że system operacyjny najpierw truncatedostosowuje go do nowego rozmiaru pliku, a następnie write go. Podobnie truncatejest szukane połączenie systemowe.
mgarciaisaia
1
W systemie Linux zobacz takżefallocate(FALLOC_FL_COLLAPSE_RANGE)
Stéphane Chazelas,
2

open(2)Wywołanie systemowe akceptuje O_TRUNCflagi, które mogą zmniejszyć rozmiar pliku:

O_TRUNC- Jeśli plik istnieje i jest zwykłym plikiem, a plik został pomyślnie otwarty O_RDWRlub O_WRONLYjego długość zostanie obcięta do 0, a tryb i właściciel pozostaną niezmienione. Nie ma to wpływu na pliki specjalne FIFO ani pliki urządzeń końcowych. Jego wpływ na inne typy plików jest zdefiniowany w implementacji. Wynik użycia O_TRUNCbez albo O_RDWRczy O_WRONLYjest niezdefiniowane.

Jest często używany, gdy program ma na celu całkowite zastąpienie zawartości pliku. Przykładem jest operator przekierowania plików powłoki jak w command > file.

David Foerster
źródło