import std.fs.ext4;
Liest die ext-Familie: Superblock und Gruppendeskriptoren auswerten, Inodes lesen, Verzeichnisse durchlaufen, Dateien und symbolische Verweise lesen. Nur lesend.
Anders als FAT und exFAT hat diese Familie eine Inode-Tabelle: der Verzeichniseintrag trägt nur einen Namen und eine Nummer, alles Weitere — Größe, Rechte, Zeiten und der Weg zu den Blöcken — steht im Inode.
→ Die Dateisystem-Sammlung · std.fs.part · Guide: Fremde Dateisysteme lesen
| Konstante | Wert | Bedeutung |
|---|---|---|
EXT4_ERR | −1 | Lesefehler oder ungültige Struktur |
EXT4_ROOT_INO | 2 | Inode-Nummer des Wurzelverzeichnisses |
EXT4_S_IFMT | 0xF000 | Maske für die Art im mode-Feld |
EXT4_S_IFREG · EXT4_S_IFDIR · EXT4_S_IFLNK | 0x8000 · 0x4000 · 0xA000 | Datei, Verzeichnis, Verweis |
EXT4_FL_EXTENTS | 0x80000 | Inode benutzt Extent-Baum statt Blockliste |
EXT4_FL_INLINE_DATA | 0x10000000 | Daten stehen im Inode selbst |
EXT4_FL_ENCRYPT | 0x800 | verschlüsselt |
EXT4_FT_REG · EXT4_FT_DIR · EXT4_FT_LNK | 1 · 2 · 7 | Art im Verzeichniseintrag |
Die Art steht an zwei Stellen: im Verzeichniseintrag (EXT4_FT_*, schnell) und im Inode (EXT4_S_IF*, verbindlich). Bei alten Dateisystemen ohne das Merkmal filetype ist das Feld im Verzeichnis 0 — dann entscheidet der Inode.
pub type Ext4Volume = struct {
fd: int64;
partOffset: int64;
blockSize: int64;
inodeSize: int64;
descSize: int64; // 32 oder 64 (Eigenschaft 64bit)
blocksPerGroup: int64;
inodesPerGroup: int64;
firstDataBlock: int64;
inodeCount: int64;
blockCount: int64;
featIncompat: int64;
gdtBlock: int64; // erster Block der Gruppendeskriptoren
gueltig: bool;
}
pub type Ext4Inode = struct {
ino: int64;
mode: int64;
size: int64;
flags: int64;
links: int64;
isDir: bool;
isFile: bool;
isLink: bool;
iblock: int64; // Kopie der 60 Byte aus i_block — vom Aufrufer freizugeben
}
Ext4Dir enthält den Inode als Kopie — sein iblock-Zeiger aber nicht, den teilen beide. Wer den ursprünglichen Inode freigibt, während das Verzeichnis offen ist, zieht dem Durchlauf den Boden weg. Also immer erst Ext4DirClose, dann Ext4InodeFree.
| Signatur | Zweck |
|---|---|
Ext4Mount(fd: int64, byteOffset: int64): Ext4Volume | Superblock lesen, Volume aufbauen |
Ext4Valid(vol: Ext4Volume): bool | Wurde ein gültiges ext-Dateisystem gefunden? |
Ext4ReadInode(vol: Ext4Volume, nr: int64, ref out: Ext4Inode): int64 | Inode nr lesen (Wurzel: EXT4_ROOT_INO) |
Ext4InodeFree(ino: Ext4Inode): void | Gibt die iblock-Kopie frei |
Ext4BlockOf(vol, ino: Ext4Inode, logisch: int64): int64 | Logischen Block → physischen Block |
Ext4VolumeLabel(vol, buf: int64, max: int64): int64 | Datenträgerkennung |
Ext4BlockOf geht beide Wege: Extent-Baum (ext4, Merkmal EXT4_FL_EXTENTS) und die klassische Blockliste mit einfacher Indirektion (ext2/ext3).
| Signatur | Zweck |
|---|---|
Ext4DirOpen(vol: Ext4Volume, ino: Ext4Inode): Ext4Dir | Verzeichnis öffnen |
Ext4DirNext(vol, ref d: Ext4Dir, ref e: Ext4Entry, nameBuf: int64, nameMax: int64): int64 | Nächster Eintrag; Name nach nameBuf |
Ext4DirClose(vol: Ext4Volume, ref d: Ext4Dir): void | Puffer freigeben |
Ext4FindInDir(vol, dir: Ext4Inode, name: pchar): int64 | Inode-Nummer eines Namens, oder EXT4_ERR |
Ext4FindPath(vol: Ext4Volume, path: pchar): int64 | Pfad ab der Wurzel auflösen → Inode-Nummer |
| Signatur | Zweck |
|---|---|
Ext4ReadFile(vol, ino: Ext4Inode, buf: int64, max: int64): int64 | Datei in den Puffer lesen |
Ext4ReadLink(vol, ino: Ext4Inode, buf: int64, max: int64): int64 | Ziel eines symbolischen Verweises |
Kurze Verweisziele stehen im Inode selbst (in den 60 Byte von i_block), längere in einem Datenblock — Ext4ReadLink behandelt beide Fälle.
unit main;
import std.fs.ext4;
import std.alloc;
import std.io;
import std.string;
fn main(): int64 {
var fd: int64 := open("/tmp/ext4.img"c, 0, 0);
if (fd < 0) { return 1; }
var vol: Ext4Volume := Ext4Mount(fd, 0);
if (!Ext4Valid(vol)) { PrintLn("kein ext-Dateisystem"); close(fd); return 1; }
var wurzel: Ext4Inode;
Ext4ReadInode(vol, EXT4_ROOT_INO, wurzel);
var name: int64 := alloc(300);
var d: Ext4Dir := Ext4DirOpen(vol, wurzel);
var e: Ext4Entry;
while (Ext4DirNext(vol, d, e, name, 300) > 0) {
PrintLn(StrConcat(name as pchar, StrConcat(" Inode ", IntToStr(e.ino))));
}
Ext4DirClose(vol, d); // erst das Verzeichnis …
Ext4InodeFree(wurzel); // … dann der Inode
free(name, 300);
close(fd);
return 0;
}
EXT4_FL_ENCRYPT) werden erkannt, aber nicht entschlüsselt.
Prüfstand: tests/ext4_test.sh — 53 Prüfungen gegen ein erzeugtes Abbild.
Letzte Aktualisierung: 2026-09-05 — Seite neu angelegt; erhoben aus std/fs/ext4.lyx (#1924).
Prüflauf 2026-09-05 mit doku-pruefer.py (Repo-Compiler lyxc 1.2.2A): 7 Vollprogramme der Sammlung, 7 übersetzen, 0 echte Fehler; 53 Aufrufe gegen die pub fn-Signaturen gehalten, 0 Abweichungen.