Ermöglichen typische Systemaufrufschnittstellen das Reduzieren der Größe einer Datei (ohne sie durch einen anderen Inode zu ersetzen)?

9

Gibt es eine Möglichkeit, open()eine Datei zu verkleinern? Man kann sie natürlich im Append-Modus öffnen oder bis zum Ende suchen und schreiben, damit sie wachsen. Soweit ich weiß, gibt es jedoch keine Methode, um eine Datei über typische Systemaufrufschnittstellen im Unix-Stil zu verkleinern.

Soweit ich weiß, besteht die einzige Möglichkeit darin, sie zu fälschen, indem eine neue kürzere Datei erstellt wird und rename()diese anstelle der älteren.

Ich wollte nur eine Bestätigung, weil ich eine Antwort sah, die implizierte, dass es möglich war, Datei-Editoren zu erstellen, die direkt an einer Datei arbeiteten, anstatt eine neue zu erstellen und sie umzubenennen.

Ich habe immer gedacht, dass die Datei-API in libc- und Unix-ähnlichen Systemaufrufschnittstellen das Verkleinern von Dateien nicht zulässt, um die Implementierung von Dateisystemen zu vereinfachen und möglicherweise Verwendungsmuster zu vermeiden, die zur Fragmentierung beitragen könnten.

JoL
quelle
2
Wenn Sie eine Datei fopenim Modus "w" (oder "w +") öffnen, wird sie automatisch auf die Länge Null gekürzt. Oder wollen Sie auf eine Größe ungleich Null schrumpfen, um einen Teil des alten Inhalts zu erhalten?
Wyzard
4
Nur zu Ihrer Information, open()und Sie haben openat()bereits ein Flag zum Abschneiden. O_TRUNCTechnisch gesehen führt dies dazu, dass die Datei verkleinert wird, dh vollständig verkleinert wird, ohne den Inode zu ändern. Das bekannteste Beispiel dafür ist command > file.txt, dass Dateien abgeschnitten werden, wenn sie vorhanden sind. Wenn Sie laufen straceauf bash -c 'true > /dev/null'Sie werden sehen , openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666)in der Ausgabe. Für eine variable Größe der Kürzung benötigen Sie natürlich truncate()syscall. Lassen Sie mich wissen, ob Sie dies als tatsächliche Antwort anstelle des Kommentars wünschen.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy Ich dachte daran, auf eine beliebige Größe zu schrumpfen. Ich habe die Antwort von David Foerster positiv bewertet, weil sie eine Teilmenge der Frage beantwortet, aber ich akzeptiere sie angesichts der von icarus nicht. Ich hätte es als Ja-Nein-Antwort genommen, während die Antwort von icarus bereits zeigte, dass die eigentliche Antwort ein "Ja" ist.
JoL

Antworten:

22

man -s 2 ftruncate sagt

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).

Wenn Sie ftruncate verwenden, müssen Sie die Datei zum Schreiben geöffnet haben, und wenn Sie truncate verwenden, muss die Datei beschreibbar sein.

icarus
quelle
Das Anhängen an eine Datei bewirkt, dass das Betriebssystem zuerst truncatedie neue Dateigröße berücksichtigt und dann write diese. So truncateist der Systemaufruf, den Sie suchen.
mgarciaisaia
1
Unter Linux siehe auchfallocate(FALLOC_FL_COLLAPSE_RANGE)
Stéphane Chazelas
2

Der open(2)Systemaufruf akzeptiert das O_TRUNCFlag, das die Dateigröße reduzieren kann:

O_TRUNC- Wenn die Datei existiert und eine reguläre Datei ist und die Datei erfolgreich geöffnet wurde O_RDWRoder O_WRONLY, wird ihre Länge auf 0 gekürzt und der Modus und der Eigentümer bleiben unverändert. Es hat keine Auswirkungen auf FIFO-Spezialdateien oder Endgerätedateien. Die Auswirkung auf andere Dateitypen ist implementierungsdefiniert. Das Ergebnis der Verwendung O_TRUNCohne O_RDWRoder O_WRONLYist undefiniert.

Es wird häufig verwendet, wenn das Programm den Inhalt einer Datei vollständig überschreiben soll. Ein Beispiel ist der Dateiumleitungsoperator Ihrer Shell wie in command > file.

David Foerster
quelle