import std.fs.ntfs;
Liest NTFS: Bootsektor auswerten, MFT-Sätze lesen, Attribute finden, Verzeichnisse durchsuchen, Dateien lesen. Nur lesend.
Diese Unit hat den größten Abstand zu ihren Schwestern. FAT, exFAT und ext4 haben alle irgendwo eine Tabelle, die Blöcke aufzählt. NTFS hat stattdessen die Master File Table: jede Datei ist dort ein Satz aus Attributen, und die Daten sind nur eines davon ($DATA).
→ Die Dateisystem-Sammlung · std.fs.part · Guide: Fremde Dateisysteme lesen
Jede von ihnen ist eine eigene Fehlerquelle, und alle drei sind still:
| Konstante | Wert | Bedeutung |
|---|---|---|
NTFS_ERR | −1 | Lesefehler oder ungültige Struktur |
NTFS_MFT_SELF | 0 | die MFT selbst |
NTFS_MFT_VOLUME | 3 | trägt $VOLUME_NAME |
NTFS_MFT_ROOT | 5 | das Wurzelverzeichnis |
NTFS_AT_STANDARD | 0x10 | $STANDARD_INFORMATION |
NTFS_AT_FILE_NAME | 0x30 | $FILE_NAME |
NTFS_AT_VOLUME_NAME | 0x60 | $VOLUME_NAME |
NTFS_AT_DATA | 0x80 | $DATA — der Inhalt |
NTFS_AT_INDEX_ROOT · NTFS_AT_INDEX_ALLOC | 0x90 · 0xA0 | Verzeichnisindex |
NTFS_AT_END | 0xFFFFFFFF | Ende der Attributliste |
NTFS_FLAG_INUSE · NTFS_FLAG_DIR | 1 · 2 | Satz in Gebrauch, Satz ist Verzeichnis |
NTFS_LCN_LOCH | −1 | Loch in einer Lauffolge (spärliche Datei) |
pub type NtfsVolume = struct {
fd: int64;
partOffset: int64;
bytesPerSector: int64;
sectorsPerClus: int64;
clusterBytes: int64;
totalSectors: int64;
mftLcn: int64;
recordSize: int64; // Bytes je MFT-Satz
indexSize: int64; // Bytes je Indexblock
mftRuns: int64; // Laufliste der MFT: je 24 Byte (vcn, lcn, len)
mftRunCount: int64;
gueltig: bool;
}
pub type NtfsAttr = struct {
typ: int64;
nonResident: bool;
wertPtr: int64; // resident: Zeiger auf den Wert IM Satzpuffer
wertLen: int64;
runs: int64; // nicht-resident: Laufliste (je 24 Byte)
runCount: int64;
realSize: int64;
gefunden: bool;
}
pub type NtfsEntry = struct {
mftRef: int64;
size: int64;
isDir: bool;
}
Die Trennung in wertPtr/wertLen gegen runs/runCount bildet genau den residenten und den nicht-residenten Fall ab — nonResident sagt, welche Felder gelten.
| Signatur | Zweck |
|---|---|
NtfsMount(fd: int64, byteOffset: int64): NtfsVolume | Bootsektor lesen, MFT-Laufliste aufbauen |
NtfsUnmount(ref vol: NtfsVolume): void | Laufliste freigeben |
NtfsValid(vol: NtfsVolume): bool | Wurde ein gültiges NTFS gefunden? |
NtfsReadRecord(vol, nr: int64, puffer: int64): int64 | MFT-Satz nr lesen — mit Fixup-Rücktausch |
NtfsRecordInUse(satz: int64): bool | Ist der Satz belegt? |
NtfsRecordIsDir(satz: int64): bool | Ist es ein Verzeichnis? |
NtfsVolumeLabel(vol, buf: int64, max: int64): int64 | Datenträgerkennung aus Satz 3 |
| Signatur | Zweck |
|---|---|
NtfsFindAttr(vol, satz: int64, typ: int64, runPuffer: int64, ref a: NtfsAttr): int64 | Attribut im Satz suchen; Lauflisten landen in runPuffer |
NtfsReadAttr(vol, a: NtfsAttr, buf: int64, max: int64): int64 | Wert des Attributs lesen — resident wie nicht-resident |
| Signatur | Zweck |
|---|---|
NtfsReadFile(vol, mftNr: int64, buf: int64, max: int64): int64 | Datei über ihre MFT-Nummer lesen |
NtfsFileSize(vol: NtfsVolume, mftNr: int64): int64 | Größe der Datei |
NtfsDirCount(vol: NtfsVolume, dirNr: int64): int64 | Zahl der Einträge eines Verzeichnisses |
NtfsFindInDir(vol, dirNr: int64, name: pchar, ref e: NtfsEntry): int64 | Eintrag im Verzeichnis suchen |
NtfsFindPath(vol: NtfsVolume, path: pchar): int64 | Pfad ab der Wurzel auflösen → MFT-Nummer |
Ein Verzeichnis ist in NTFS ein B-Baum aus $INDEX_ROOT und $INDEX_ALLOCATION; die Unit durchläuft beide.
unit main;
import std.fs.ntfs;
import std.alloc;
import std.io;
import std.string;
fn main(): int64 {
var fd: int64 := open("/tmp/ntfs.img"c, 0, 0);
if (fd < 0) { return 1; }
var vol: NtfsVolume := NtfsMount(fd, 0);
if (!NtfsValid(vol)) { PrintLn("kein NTFS"); close(fd); return 1; }
var nr: int64 := NtfsFindPath(vol, "/ordner/datei.txt"c);
if (nr == NTFS_ERR) { PrintLn("nicht gefunden"); }
else {
var groesse: int64 := NtfsFileSize(vol, nr);
var buf: int64 := alloc(groesse + 1);
NtfsReadFile(vol, nr, buf, groesse);
PrintLn(StrConcat("gelesen: ", IntToStr(groesse)));
free(buf, groesse + 1);
}
NtfsUnmount(vol);
close(fd);
return 0;
}
Nicht enthalten — und im Zweifel gemeldet, nicht geraten:
$ATTRIBUTE_LIST — ein Satz, dessen Attribute nicht mehr in einen Satz passen$LogFile-Wiedergabe
Namen werden nach ASCII gelesen; alles darüber wird zu ? — dieselbe Angabe wie in den Schwester-Units.
Nur lesen. Schreiben verlangt zusätzlich die Pflege des $LogFile (NTFS führt ein Journal), der $Bitmap und der Indexbäume.
Prüfstand: tests/ntfs_test.sh — 33 Prüfungen gegen ein erzeugtes Abbild.
Letzte Aktualisierung: 2026-09-05 — Seite neu angelegt; erhoben aus std/fs/ntfs.lyx (#1926).
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.