====== std.iso — ISO 9660-Images lesen und schreiben ====== ''std.iso'' liest und schreibt ISO 9660-Images (Level 1) ohne externe Abhängigkeiten. Der Reader traversiert den vollständigen Verzeichnisbaum per BFS und gibt vollständige Pfade zurück (''subdir/DATEI.TXT''). Der Writer erzeugt ein gültiges bootfähiges ISO-Image mit flachem Root-Verzeichnis. → [[lyx_-_programmiersprache:units:archiv|Archiv-Übersicht]] · [[lyx_-_programmiersprache:units:zip|std.zip]] · [[lyx_-_programmiersprache:units:tar|std.tar]] · [[lyx_-_programmiersprache:guides:iso|Guide: ISO-Abbilder]] · [[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. **Image-Layout (festes Schema):** Sektor 0–15 System Area (leer) Sektor 16 PVD — Primary Volume Descriptor (Volume-ID: "LYXISO") Sektor 17 VDST — Volume Descriptor Set Terminator Sektor 18–19 Path Table (L-Type + M-Type) Sektor 20 Root-Verzeichnis Sektor 21+ Dateidaten **Einschränkungen:** * Sektorgröße: 2048 Bytes (ISO 9660 Standard) * Max. 4096 Dateieinträge, max. 256 Verzeichnisse (Lesen) * Writer: nur flaches Root-Verzeichnis — keine Unterverzeichnisse * Dateinamen (Writer): max. 36 Zeichen, nur ''A–Z 0–9 _ .'' — ungültige Zeichen werden zu ''_'', Kleinbuchstaben zu Großbuchstaben * Kein Joliet, kein Rock Ridge, kein El Torito Boot-Record ---- ===== Konstanten ===== ^ Konstante ^ Wert ^ Bedeutung ^ | ''ISO_SECTOR'' | 2048 | Sektorgröße in Bytes | | ''ISO_MAX_ENTRIES'' | 4096 | Maximale Dateieinträge pro Image | | ''ISO_MAX_DIRS'' | 256 | Maximale Verzeichnisse (BFS-Queue beim Lesen) | | ''ISO_MAX_PATH'' | 512 | Maximale Pfadlänge in Bytes | | ''ISO_ERR_OK'' | 0 | Kein Fehler | | ''ISO_ERR_NOTISO'' | 1 | Keine gültige ISO 9660-Datei (PVD-Signatur fehlt) | | ''ISO_ERR_IO'' | 2 | I/O-Fehler beim Lesen oder Schreiben | | ''ISO_ERR_CORRUPT'' | 3 | Image beschädigt | | ''ISO_ERR_FULL'' | 4 | ISO_MAX_ENTRIES erreicht | | ''ISO_ERR_NAMETOOLONG'' | 5 | Dateiname > 36 Zeichen oder leer | ---- ===== Lesen (IsoReader) ===== ^ Funktion ^ Rückgabe ^ Beschreibung ^ | ''IsoOpen(path)'' | ''int64'' Handle oder 0 | Öffnet ISO-Image, traversiert vollständigen Verzeichnisbaum (BFS) | | ''IsoClose(handle)'' | ''void'' | Gibt Handle und alle Ressourcen frei | | ''IsoCount(handle)'' | ''int64'' | Anzahl der Dateieinträge (keine Verzeichnisse) | | ''IsoName(handle, idx)'' | ''int64'' pchar | Vollständiger Pfad des idx-ten Eintrags (interner Puffer — nicht free'n) | | ''IsoSize(handle, idx)'' | ''int64'' | Dateigröße in Bytes | | ''IsoRead(handle, idx, outBuf, maxLen)'' | ''int64'' Bytes oder -1 | Liest Dateiinhalt in outBuf | | ''IsoFind(handle, name)'' | ''int64'' Index oder -1 | Sucht Eintrag nach exaktem Pfad. **Der Index folgt der Reihenfolge im Abbild, nicht der Anlegereihenfolge** — die Verzeichniseinträge stehen nach ISO 9660 sortiert, ''DATEN.BIN'' also vor ''README.TXT'' | Der Reader gibt vollständige Pfade zurück, inklusive Verzeichnisnamen: ''BOOT/GRUB/GRUB.CFG'' oder ''DATA/LOG.TXT''. Verzeichniseinträge selbst erscheinen nicht in der Liste — nur reguläre Dateien. import std.iso; import std.alloc; import std.string; fn main(): int64 { var w: int64 := IsoWriterNew(); IsoWriterAdd(w, "README.TXT"c, "ISO 9660 aus Lyx"c as int64, 16); IsoWriterAdd(w, "DATEN.BIN"c, "0123456789"c as int64, 10); var rc: int64 := IsoWriterSave(w, "/tmp/lyx_test.iso"c); IsoWriterFree(w); PrintLn(StrConcat("Save rc (0 = ok): ", IntToStr(rc))); var h: int64 := IsoOpen("/tmp/lyx_test.iso"c); if (h == 0) { PrintLn("IsoOpen fehlgeschlagen"); return 1; } PrintLn(StrConcat("Eintraege: ", IntToStr(IsoCount(h)))); var i: int64 := 0; while (i < IsoCount(h)) { PrintLn(StrConcat(StrConcat(" ", IsoName(h, i) as pchar), StrConcat(" ", IntToStr(IsoSize(h, i))))); i := i + 1; } var idx: int64 := IsoFind(h, "README.TXT"c); PrintLn(StrConcat("Find(README.TXT): ", IntToStr(idx))); if (idx >= 0) { var buf: int64 := alloc(256); var n: int64 := IsoRead(h, idx, buf, 256); poke8(buf + n, 0); PrintLn(StrConcat("Inhalt: ", buf as pchar)); } IsoClose(h); return 0; } Save rc (0 = ok): 0 Eintraege: 2 DATEN.BIN 10 README.TXT 16 Find(README.TXT): 1 Inhalt: ISO 9660 aus Lyx Das Abbild ist 47 104 Byte groß (23 Sektoren à 2048 Byte) und wird von ''7z'' gelesen: $ 7z l /tmp/lyx_test.iso ..... 16 16 README.TXT ..... 10 10 DATEN.BIN ---- ===== Schreiben (IsoWriter) ===== ^ Funktion ^ Rückgabe ^ Beschreibung ^ | ''IsoWriterNew()'' | ''int64'' Writer-Handle | Erstellt neuen leeren Writer | | ''IsoWriterAdd(w, name, data, dataLen)'' | ''int64'' Fehlercode | Fügt Datei hinzu; Name wird automatisch normalisiert | | ''IsoWriterSave(w, path)'' | ''int64'' Fehlercode | Schreibt vollständiges ISO 9660-Image | | ''IsoWriterFree(w)'' | ''void'' | Gibt Writer frei (nicht die data-Puffer — diese gehören dem Aufrufer) | ''IsoWriterAdd'' normalisiert den Dateinamen automatisch: Kleinbuchstaben → Großbuchstaben, ungültige Zeichen → ''_''. Das Version-Suffix '';1'' wird beim Schreiben angehängt. Beim Lesen entfernt der Reader es automatisch — ''IsoName'' gibt Namen ohne '';1'' zurück. **Hinweis zu data-Puffern:** ''IsoWriterAdd'' kopiert die Daten **nicht** — es speichert nur den Zeiger. Die Puffer müssen bis zum Aufruf von ''IsoWriterSave'' gültig bleiben. ''IsoWriterFree'' gibt nur die Name-Strings frei, nicht die data-Zeiger. ---- ===== Dateinamen-Normalisierung ===== ISO 9660 Level 1 kennt nur einen kleinen Zeichenvorrat: ''A''–''Z'', ''0''–''9'', ''_'' und den Punkt. ''IsoWriterAdd'' nimmt den Namen unverändert entgegen — normalisiert wird erst beim Schreiben: ^ Übergeben ^ Im Abbild ^ | ''README.TXT'' | ''README.TXT'' | | ''readme.txt'' | ''README.TXT'' | | ''boot-config.cfg'' | ''BOOT_CONFIG.CFG'' | | ''mein datei.bin'' | ''MEIN_DATEI.BIN'' | | ''EinLangerName.txt'' | ''EINLANGERNAME.TXT'' | | ''unterordner/a.txt'' | ''UNTERORDNER_A.TXT'' | Nachgemessen mit lyxc 1.0.21A: Kleinbuchstaben werden großgeschrieben, jedes andere unzulässige Zeichen wird zu ''_''. > **Der Schrägstrich ist keine Ausnahme.** ''unterordner/a.txt'' erzeugt **kein** Unterverzeichnis, sondern eine Datei namens ''UNTERORDNER_A.TXT'' im Wurzelverzeichnis. Der Writer legt ausschließlich flache Abbilder an; wer eine Verzeichnisstruktur braucht, kommt mit dieser Unit nicht weiter. Der **Reader** dagegen kennt Unterverzeichnisse und liefert vollständige Pfade. > > Die 8.3-Regel von Level 1 wird beim Schreiben ebenfalls nicht erzwungen: ''EINLANGERNAME.TXT'' (13 Zeichen vor dem Punkt) landet unverändert im Abbild. Lesegeräte, die streng nach Level 1 arbeiten, könnten den Namen abweisen. ---- ===== Speicherverwaltung ===== ^ Handle ^ Freigabe ^ | ''IsoOpen'' → Reader-Handle | ''IsoClose(handle)'' | | ''IsoWriterNew'' → Writer-Handle | ''IsoWriterFree(w)'' | | ''IsoName'' → interner Puffer | **nicht free'n** — gehört dem Handle | | ''outBuf'' in ''IsoRead'' | Aufrufer allokiert, Aufrufer gibt frei | | ''data''-Zeiger in ''IsoWriterAdd'' | Aufrufer verwaltet — bis ''IsoWriterSave'' gültig halten | Letzte Aktualisierung: 2026-08-13 — Beispiele lauffähig gemacht, ausgeführt und mit ''7z'' gegengelesen (lyxc 1.0.21A); Namens-Normalisierung nachgemessen — der Schrägstrich erzeugt kein Unterverzeichnis, die 8.3-Regel wird beim Schreiben nicht erzwungen. 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). Letzte Aktualisierung: 2026-08-30 — Beispielausgabe gegen ''lyxc 1.1.14A'' nachgezogen: die Einträge kommen sortiert zurück (''DATEN.BIN'' vor ''README.TXT''), ''IsoFind(README.TXT)'' liefert deshalb ''1'' statt ''0''.