Inhaltsverzeichnis

std.fs.exfat — exFAT lesen

import std.fs.exfat;

Liest exFAT-Dateisysteme: Bootsektor auswerten, Clusterketten verfolgen, Verzeichnisse durchlaufen, Dateien lesen. Nur lesend.

exFAT teilt mit FAT32 den Namen und die Grundidee — Cluster, eine Zuordnungstabelle —, aber kaum ein Strukturfeld. Deshalb eine eigene Unit und kein Zweig in std.fs.fat.

Die Dateisystem-Sammlung · std.fs.fat · Guide: Fremde Dateisysteme lesen


1. Was anders ist als bei FAT32


2. Konstanten

Konstante Wert Bedeutung
EXFAT_ERR −1 Lesefehler oder ungültige Struktur
EXFAT_EOC −2 Kettenende
EXFAT_FREI 0 freier Cluster
EXFAT_ET_BITMAP · EXFAT_ET_UPCASE · EXFAT_ET_LABEL 0x81 · 0x82 · 0x83 Systemeinträge
EXFAT_ET_FILE · EXFAT_ET_STREAM · EXFAT_ET_NAME 0x85 · 0xC0 · 0xC1 die drei Teile eines Dateisatzes
EXFAT_ATTR_READ_ONLYEXFAT_ATTR_ARCHIVE 1, 2, 4, 16, 32 schreibgeschützt, versteckt, System, Verzeichnis, Archiv
 
Das oberste Bit der Eintragsart sagt „in Gebrauch„. Ein gelöschter Eintrag trägt dieselbe Art mit gelöschtem Bit 7 — 0x05 statt 0x85. Wer nur auf Gleichheit prüft, übersieht gelöschte Einträge nicht, sondern liest sie mit.

3. Typen

pub type ExfatVolume = struct {
  fd:             int64;
  partOffset:     int64;   // Byte-Versatz des Volumes im Deskriptor
  bytesPerSector: int64;   // schon aus dem Exponenten gerechnet
  sectorsPerClus: int64;
  fatOffset:      int64;   // Sektoren
  fatLength:      int64;   // Sektoren
  heapOffset:     int64;   // Sektoren
  clusterCount:   int64;
  rootCluster:    int64;
  numFats:        int64;
  gueltig:        bool;
}

pub type ExfatEntry = struct {
  attr:       int64;
  cluster:    int64;
  size:       int64;
  isDir:      bool;
  noFatChain: bool;   // Strom liegt zusammenhängend, die FAT ist unbeteiligt
}

pub type ExfatDir = struct {
  cluster:    int64;
  sectorInCl: int64;
  entryInSec: int64;
  fertig:     bool;
  sekPuffer:  int64;
}


4. Volume

Signatur Zweck
ExfatMount(fd: int64, byteOffset: int64): ExfatVolume Bootsektor auswerten und Volume aufbauen
ExfatValid(vol: ExfatVolume): bool Wurde ein gültiges exFAT gefunden?
ExfatBytesPerCluster(vol: ExfatVolume): int64 Clustergröße in Byte
ExfatClusterSector(vol: ExfatVolume, cluster: int64): int64 Erster Sektor eines Clusters
ExfatVolumeLabel(vol: ExfatVolume, buf: int64, max: int64): int64 Datenträgerkennung; Rückgabe: Zeichenzahl, 0 = keine

byteOffset kommt üblicherweise aus ''PartByteOffset''.


5. Clusterkette

Signatur Zweck
ExfatNextCluster(vol: ExfatVolume, cluster: int64): int64 Nächster Cluster, EXFAT_EOC am Ende

Bei Dateien mit noFatChain wird die Kette nicht gebraucht: die Cluster folgen aufeinander. ExfatReadFile berücksichtigt beide Fälle.


6. Verzeichnisse

Signatur Zweck
ExfatDirOpen(vol: ExfatVolume, cluster: int64): ExfatDir Verzeichnis ab diesem Cluster öffnen
ExfatDirNext(vol, ref d: ExfatDir, ref e: ExfatEntry, nameBuf: int64, nameMax: int64): int64 Nächster Eintrag; Name nach nameBuf
ExfatDirClose(vol: ExfatVolume, ref d: ExfatDir): void Puffer freigeben
ExfatFindInDir(vol, dirCluster: int64, name: pchar, ref e: ExfatEntry): int64 Eintrag im Verzeichnis suchen
ExfatFindPath(vol: ExfatVolume, path: pchar, ref e: ExfatEntry): int64 Pfad ab der Wurzel auflösen

Bitmap, Upcase-Tabelle und Datenträgerkennung werden übergangen — sie sind keine Dateien. Wer sie mitliefert, hat in jedem Verzeichnislisting drei Geistereinträge.


7. Dateien und Prüfsummen

Signatur Zweck
ExfatReadFile(vol, e: ExfatEntry, buf: int64, max: int64): int64 Datei in den Puffer lesen
ExfatSystemStream(vol, art: int64, ref e: ExfatEntry): int64 Ersten Cluster und Länge eines Systemstroms (EXFAT_ET_BITMAP oder EXFAT_ET_UPCASE)
ExfatUpcaseStoredChecksum(vol: ExfatVolume): int64 Die im Verzeichnis abgelegte Prüfsumme der Upcase-Tabelle
ExfatChecksum32(daten: int64, len: int64): int64 Prüfsumme nach exFAT-Vorschrift: Rechtsrotation um ein Bit, dann das Byte addieren

8. Beispiel

unit main;
import std.fs.part;
import std.fs.exfat;
import std.alloc;
import std.io;
import std.string;

fn main(): int64 {
    var fd: int64 := open("/tmp/exfat.img"c, 0, 0);
    if (fd < 0) { return 1; }

    var vol: ExfatVolume := ExfatMount(fd, 0);
    if (!ExfatValid(vol)) { PrintLn("kein exFAT"); close(fd); return 1; }

    var name: int64 := alloc(300);
    var d: ExfatDir := ExfatDirOpen(vol, vol.rootCluster);
    var e: ExfatEntry;

    while (ExfatDirNext(vol, d, e, name, 300) > 0) {
        PrintLn(StrConcat(name as pchar, StrConcat("  ", IntToStr(e.size))));
    }

    ExfatDirClose(vol, d);
    free(name, 300);
    close(fd);
    return 0;
}


9. Grenzen

Nur lesen — aus denselben Gründen wie bei FAT, und hier noch etwas mehr: exFAT verlangt beim Schreiben zusätzlich die Pflege der Belegungsbitmap und Prüfsummen über jeden Eintragssatz.

Prüfstand: tests/exfat_test.sh42 Prüfungen gegen ein erzeugtes Abbild.

Letzte Aktualisierung: 2026-09-05 — Seite neu angelegt; erhoben aus std/fs/exfat.lyx (#1922).