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