====== std.tar — TAR-Archive lesen und schreiben ======
''std.tar'' liest und schreibt TAR-Archive im POSIX ustar Format (IEEE Std 1003.1-1988). TAR komprimiert nicht — es ist ein reines Archivformat. Für komprimierte Archive (.tar.gz) wird TAR mit ''[[lyx_-_programmiersprache:units:gzip|std.gzip]]'' kombiniert.
→ [[lyx_-_programmiersprache:units:archiv|Archiv-Übersicht]] · [[lyx_-_programmiersprache:units:zip|std.zip]] · [[lyx_-_programmiersprache:units:rar|std.rar]] · [[lyx_-_programmiersprache:units:gzip|std.gzip]] · [[lyx_-_programmiersprache:units|Standard Library]]
Alle Beispiele dieser Seite sind mit ''lyxc 1.0.21A'' übersetzt und ausgeführt; die gezeigten Ausgaben sind echte Programmausgaben.
**Einschränkungen:** Max. 4096 Einträge, Dateinamen max. 100 Bytes (kein GNU LongLink / split-header). Beim Lesen werden nur reguläre Dateien (typeflag ''0'') erfasst — Verzeichnisse werden übersprungen.
----
===== Konstanten =====
^ Konstante ^ Wert ^ Bedeutung ^
| ''TAR_BLOCK_SIZE'' | 512 | Header- und Datei-Blöcke sind je 512 Bytes |
| ''TAR_MAX_ENTRIES'' | 4096 | Maximale Einträge pro Archiv |
| ''TAR_ERR_OK'' | 0 | Kein Fehler |
| ''TAR_ERR_NOTTAR'' | 1 | Keine gültige TAR-Datei |
| ''TAR_ERR_IO'' | 2 | I/O-Fehler beim Lesen oder Schreiben |
| ''TAR_ERR_CORRUPT'' | 3 | Archiv beschädigt |
| ''TAR_ERR_FULL'' | 4 | TAR_MAX_ENTRIES erreicht |
----
===== Lesen (TarReader) =====
^ Funktion ^ Rückgabe ^ Beschreibung ^
| ''TarOpen(path)'' | ''int64'' Handle oder 0 | Öffnet TAR-Archiv aus Datei |
| ''TarClose(handle)'' | ''void'' | Gibt Handle und alle Ressourcen frei |
| ''TarCount(handle)'' | ''int64'' | Anzahl der regulären Datei-Einträge |
| ''TarName(handle, idx)'' | ''int64'' pchar | Name des idx-ten Eintrags (interner Puffer — nicht free'n) |
| ''TarSize(handle, idx)'' | ''int64'' | Größe in Bytes |
| ''TarRead(handle, idx, outBuf, maxLen)'' | ''int64'' Bytes oder -1 | Liest Eintrag in outBuf |
| ''TarFind(handle, name)'' | ''int64'' Index oder -1 | Sucht Eintrag nach exaktem Namen |
import std.tar;
import std.alloc;
import std.string;
fn main(): int64 {
var w: int64 := TarWriterNew();
TarWriterAdd(w, "daten/log.txt"c, "Zeile 1\nZeile 2\n"c as int64, 16);
TarWriterAdd(w, "README"c, "TAR aus Lyx"c as int64, 11);
var rc: int64 := TarWriterSave(w, "/tmp/lyx_test.tar"c);
TarWriterFree(w);
PrintLn(StrConcat("Save rc (0 = ok): ", IntToStr(rc)));
var h: int64 := TarOpen("/tmp/lyx_test.tar"c);
if (h == 0) { PrintLn("TarOpen fehlgeschlagen"); return 1; }
PrintLn(StrConcat("Eintraege: ", IntToStr(TarCount(h))));
var i: int64 := 0;
while (i < TarCount(h)) {
PrintLn(StrConcat(StrConcat(" ", TarName(h, i) as pchar),
StrConcat(" ", IntToStr(TarSize(h, i)))));
i := i + 1;
}
var idx: int64 := TarFind(h, "README"c);
var buf: int64 := alloc(256);
var n: int64 := TarRead(h, idx, buf, 256);
poke8(buf + n, 0);
PrintLn(StrConcat("Inhalt: ", buf as pchar));
TarClose(h);
return 0;
}
Save rc (0 = ok): 0
Eintraege: 2
daten/log.txt 16
README 11
Inhalt: TAR aus Lyx
GNU tar liest das Ergebnis unverändert:
$ tar -tvf /tmp/lyx_test.tar
-rw-r--r-- 0/0 16 1970-01-01 01:00 daten/log.txt
-rw-r--r-- 0/0 11 1970-01-01 01:00 README
----
===== Schreiben (TarWriter) =====
^ Funktion ^ Rückgabe ^ Beschreibung ^
| ''TarWriterNew()'' | ''int64'' Writer-Handle | Erstellt neuen leeren Writer |
| ''TarWriterAdd(writer, name, data, dataLen)'' | ''int64'' Fehlercode | Fügt Eintrag hinzu (kopiert Name + Daten) |
| ''TarWriterSave(writer, path)'' | ''int64'' Fehlercode | Schreibt Archiv in Datei (POSIX ustar) |
| ''TarWriterFree(writer)'' | ''void'' | Gibt Writer und alle Einträge frei |
Geschriebene Archive: mode ''0644'', uid/gid 0, mtime 0. Datenblöcke werden auf 512-Byte-Grenzen aufgerundet. Das Archiv endet mit zwei Null-Blöcken (POSIX-Anforderung).
----
===== TAR + Kompression (.tar.gz) =====
TAR selbst komprimiert nicht. Um ein ''.tar.gz'' zu erzeugen, das Archiv in einen Puffer schreiben und anschließend mit ''[[lyx_-_programmiersprache:units:gzip|std.gzip]]'' komprimieren:
import std.tar;
import std.gzip;
import std.fs;
import std.alloc;
import std.string;
fn main(): int64 {
// 1. TAR schreiben
var w: int64 := TarWriterNew();
TarWriterAdd(w, "datei.txt"c, "Inhalt aus Lyx\n"c as int64, 15);
TarWriterSave(w, "/tmp/demo2.tar"c);
TarWriterFree(w);
// 2. TAR-Datei einlesen
var sz: int64 := FileSize("/tmp/demo2.tar"c);
var buf: int64 := alloc(sz);
ReadFile("/tmp/demo2.tar"c, buf as pchar, sz);
PrintLn(StrConcat("TAR-Groesse: ", IntToStr(sz)));
// 3. Mit gzip komprimieren
var bound: int64 := GzipCompressBound(sz);
var cbuf: int64 := alloc(bound);
var clen: int64 := GzipCompress(buf, sz, cbuf, bound);
PrintLn(StrConcat("gzip-Groesse: ", IntToStr(clen)));
WriteFile("/tmp/demo2.tar.gz"c, cbuf as pchar, clen);
free(buf, sz); free(cbuf, bound);
return 0;
}
TAR-Groesse: 2048
gzip-Groesse: 105
$ tar -tzf /tmp/demo2.tar.gz
datei.txt
Die 2048 Byte sind kein Fehler: TAR rundet jeden Eintrag auf 512-Byte-Blöcke auf und hängt zwei Nullblöcke als Endmarke an. Genau diese Nullen komprimiert gzip auf 105 Byte.
----
===== Fallstricke =====
> **Zu lange Pfade werden stillschweigend gekürzt.** Das ustar-Namensfeld fasst 100 Byte; ''TarWriterAdd'' nimmt auch längere Pfade an und meldet ''0'' (Erfolg), ''TarWriterSave'' schreibt dann den auf 100 Zeichen abgeschnittenen Namen. Nachgemessen mit einem 110 Zeichen langen Pfad — sowohl ''TarName'' als auch GNU tar zeigen anschließend den gekürzten Namen. Die ustar-Erweiterung mit ''prefix''-Feld und GNU LongLink sind nicht umgesetzt; Pfade selbst auf ≤ 100 Byte prüfen.
* **Zeitstempel sind 0** (1. Januar 1970), Eigentümer und Gruppe ebenfalls — ''std.tar'' schreibt keine echten Metadaten.
* **Nur reguläre Dateien.** Beim Lesen werden Verzeichniseinträge (typeflag ''5''), Symlinks und Gerätedateien übersprungen; beim Schreiben entstehen Ordner allein durch Schrägstriche im Namen.
* **''TarWriterSave'' liefert 0 bei Erfolg**, ''TarOpen'' dagegen 0 im Fehlerfall.
* **''TarRead'' terminiert nicht** — Nullbyte selbst setzen, wenn der Puffer als Text ausgegeben wird.
* **Pfade als ''pchar''**: ''TarOpen("/tmp/a.tar"c)'' — ohne ''as int64''. ''std.zip'' macht es umgekehrt.
----
===== Speicherverwaltung =====
^ Handle ^ Freigabe ^
| ''TarOpen'' → Reader-Handle | ''TarClose(handle)'' |
| ''TarWriterNew'' → Writer-Handle | ''TarWriterFree(writer)'' |
| ''TarName'' → interner Puffer | **nicht free'n** — gehört dem Handle |
| ''outBuf'' in ''TarRead'' | Aufrufer allokiert, Aufrufer gibt frei |
Letzte Aktualisierung: 2026-08-13 — Beispiele lauffähig gemacht, ausgeführt und mit GNU tar gegengelesen (lyxc 1.0.17K); belegt und dokumentiert: Pfade über 100 Byte werden stillschweigend gekürzt. ''.tar.gz''-Beispiel neu geschrieben.
Codebeispiele geprüft: gegen **lyxc 1.2.5C** übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die ''pub fn''-Signaturen in ''aurum/std'' gehalten, 0 Abweichungen).