====== std.fs_ext ======
Erweitertes Datei-I/O (WP-1): Ergänzt ''std.fs'' um positioniertes Lesen/Schreiben (''PRead''/''PWrite''), Scatter-Gather-I/O (''ReadV''/''WriteV''), Datei-Metadaten (''Fstat''), Zugriffsprüfung (''FileExists''), Synchronisierung (''Fsync''), Größenänderung (''Truncate''), Verzeichniswechsel und kernelseitigen Dateitransfer (''Sendfile'').
→ [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:fs|std.fs]] · [[lyx_-_programmiersprache:units:inotify|std.inotify]]
----
===== Konstanten =====
==== stat-Puffer ====
^ Konstante ^ Wert ^ Typ ^ Beschreibung ^
| ''STAT_SIZE'' | 144 | — | Puffergröße für ''Fstat'' (''alloc(STAT_SIZE)'') |
| ''STAT_DEV'' | 0 | dev_t (8 B) | Geräte-ID |
| ''STAT_INO'' | 8 | ino_t (8 B) | Inode-Nummer |
| ''STAT_NLINK'' | 16 | nlink_t (8 B) | Anzahl Hard-Links |
| ''STAT_MODE'' | 24 | mode_t (4 B) | Zugriffsrechte + Dateityp |
| ''STAT_UID'' | 28 | uid_t (4 B) | Eigentümer-UID |
| ''STAT_GID'' | 32 | gid_t (4 B) | Gruppen-GID |
| ''STAT_SIZE_F'' | 48 | off_t (8 B) | Dateigröße in Bytes |
| ''STAT_BLKSIZE'' | 56 | blksize_t (8 B) | Bevorzugte I/O-Blockgröße |
| ''STAT_BLOCKS'' | 64 | blkcnt_t (8 B) | Belegte 512-Byte-Blöcke |
| ''STAT_ATIME'' | 72 | timespec (16 B) | Letzter Zugriff |
| ''STAT_MTIME'' | 88 | timespec (16 B) | Letzte Änderung |
| ''STAT_CTIME'' | 104 | timespec (16 B) | Letzte Metadatenänderung |
==== Zugriffsmodus-Flags ====
^ Konstante ^ Wert ^ Beschreibung ^
| ''F_OK'' | 0 | Datei existiert |
| ''R_OK'' | 4 | Lesbar |
| ''W_OK'' | 2 | Schreibbar |
| ''X_OK'' | 1 | Ausführbar |
==== iovec / Pfad ====
^ Konstante ^ Wert ^ Beschreibung ^
| ''IOVEC_SIZE'' | 16 | Größe eines ''iovec''-Eintrags ({base: int64, len: int64}) |
| ''PATH_MAX'' | 4096 | Maximale Pfadlänge in Bytes (für ''GetCwd'') |
----
===== Funktionen =====
==== Datei-Metadaten ====
^ Signatur ^ Beschreibung ^
| ''Fstat(fd: int64, statBuf: int64): int64'' | Füllt ''statBuf'' (''alloc(STAT_SIZE)'') mit den Metadaten des geöffneten ''fd''. Gibt 0 bei Erfolg zurück |
| ''StatFileSize(statBuf: int64): int64'' | Dateigröße in Bytes (Offset ''STAT_SIZE_F'') |
| ''StatMtime(statBuf: int64): int64'' | Zeitstempel der letzten Änderung in Nanosekunden |
| ''StatMode(statBuf: int64): int64'' | Zugriffsrechte (12 Bits, z. B. 0644 = 420) |
| ''StatIsDir(statBuf: int64): bool'' | Gibt ''true'' zurück wenn der fd ein Verzeichnis ist |
| ''StatIsFile(statBuf: int64): bool'' | Gibt ''true'' zurück wenn der fd eine reguläre Datei ist |
| ''FileSize(path: pchar): int64'' | Öffnet ''path'', liest die Dateigröße via ''Fstat'' und schließt sofort wieder. Gibt -1 bei Fehler zurück |
==== Positioniertes Lesen / Schreiben ====
^ Signatur ^ Beschreibung ^
| ''PRead(fd: int64, buf: int64, n: int64, off: int64): int64'' | Liest ''n'' Bytes aus ''fd'' ab Position ''off'' — ändert den fd-Offset nicht |
| ''PWrite(fd: int64, buf: int64, n: int64, off: int64): int64'' | Schreibt ''n'' Bytes in ''fd'' an Position ''off'' — ändert den fd-Offset nicht |
==== Scatter-Gather-I/O (iovec) ====
^ Signatur ^ Beschreibung ^
| ''IovecSet(buf: int64, idx: int64, base: int64, len: int64)'' | Setzt ''buf[idx]'' = ''{ base, len }'' (alloc(IOVEC_SIZE * count)) |
| ''IovecBase(buf: int64, idx: int64): int64'' | Liest den ''base''-Zeiger von ''buf[idx]'' |
| ''IovecLen(buf: int64, idx: int64): int64'' | Liest die Länge von ''buf[idx]'' |
| ''ReadV(fd: int64, iov: int64, iovcnt: int64): int64'' | Liest von ''fd'' in mehrere Puffer auf einmal (scatter) |
| ''WriteV(fd: int64, iov: int64, iovcnt: int64): int64'' | Schreibt mehrere Puffer in einem Syscall in ''fd'' (gather) |
==== Zugriffsprüfung ====
^ Signatur ^ Beschreibung ^
| ''FileAccess(path: pchar, mode: int64): bool'' | Gibt ''true'' zurück wenn ''path'' den angegebenen Modus (F_OK / R_OK / W_OK / X_OK) hat |
| ''FileExists(path: pchar): bool'' | Gibt ''true'' zurück wenn ''path'' existiert |
| ''FileReadable(path: pchar): bool'' | Gibt ''true'' zurück wenn ''path'' lesbar ist |
| ''FileWritable(path: pchar): bool'' | Gibt ''true'' zurück wenn ''path'' schreibbar ist |
==== Synchronisierung ====
^ Signatur ^ Beschreibung ^
| ''Fsync(fd: int64): int64'' | Schreibt Daten und Metadaten des fd vollständig auf das Speichermedium |
| ''Fdatasync(fd: int64): int64'' | Wie ''Fsync'', aber ohne Metadaten-Update (schneller) |
==== Dateigröße ändern ====
^ Signatur ^ Beschreibung ^
| ''Truncate(path: pchar, length: int64): int64'' | Setzt die Größe von ''path'' auf ''length'' Bytes (kein offener fd nötig) |
| ''Ftruncate(fd: int64, length: int64): int64'' | Wie ''Truncate'', aber über offenen fd |
==== Arbeitsverzeichnis ====
^ Signatur ^ Beschreibung ^
| ''GetCwd(buf: int64, size: int64): int64'' | Schreibt das aktuelle Verzeichnis in ''buf'' (''alloc(PATH_MAX)''). Gibt Länge zurück oder < 0 |
| ''Chdir(path: pchar): int64'' | Wechselt das Arbeitsverzeichnis des Prozesses |
==== Kernelseitiger Dateitransfer ====
^ Signatur ^ Beschreibung ^
| ''Sendfile(outFd: int64, inFd: int64, offsetPtr: int64, count: int64): int64'' | Überträgt ''count'' Bytes von ''inFd'' nach ''outFd'' ohne Userspace-Kopie. ''offsetPtr'': Zeiger auf int64 (Leseposition) oder 0 für aktuellen fd-Offset. Gibt übertragene Bytes zurück |
----
===== Verwendung =====
==== Datei-Metadaten lesen ====
import std.fs_ext;
import std.fs;
import std.alloc;
import std.io;
fn PrintFileMeta(path: pchar): void {
var fd := open(path, 0, 0); // O_RDONLY
if (fd < 0) { return; }
var stat: int64 := alloc(STAT_SIZE);
Fstat(fd, stat);
PrintLn("Größe: " + IntToStr(StatFileSize(stat)) + " Bytes");
Print("Ist Verzeichnis: ");
if (StatIsDir(stat)) { Print("ja\n"); } else { Print("nein\n"); }
free(stat, STAT_SIZE);
close(fd);
}
==== Positioniertes Lesen (parallele Threads) ====
import std.fs_ext;
import std.alloc;
// Verschiedene Threads können denselben fd lesen ohne lseek-Konflikte.
fn ReadChunk(fd: int64, offset: int64, size: int64): int64 {
var buf: int64 := alloc(size);
var n := PRead(fd, buf, size, offset);
// Puffer verarbeiten...
free(buf, size);
return n;
}
==== Scatter-Gather: Header + Body in einem Syscall ====
import std.fs_ext;
import std.alloc;
fn SendHeaderAndBody(fd: int64, header: int64, hLen: int64,
body: int64, bLen: int64): void {
var iov: int64 := alloc(IOVEC_SIZE * 2);
IovecSet(iov, 0, header, hLen);
IovecSet(iov, 1, body, bLen);
WriteV(fd, iov, 2);
free(iov, IOVEC_SIZE * 2);
}
==== Sendfile: statische Datei ausliefern ====
import std.fs_ext;
import std.fs;
import std.alloc;
fn ServeFile(socketFd: int64, path: pchar): void {
var fd := open(path, 0, 0);
if (fd < 0) { return; }
var stat: int64 := alloc(STAT_SIZE);
Fstat(fd, stat);
var size := StatFileSize(stat);
free(stat, STAT_SIZE);
// Kernel überträgt direkt ohne Userspace-Kopie
Sendfile(socketFd, fd, 0, size);
close(fd);
}
----
===== Hinweise =====
* ''PRead''/''PWrite'' sind thread-sicher: Mehrere Threads können denselben fd mit unterschiedlichen Offsets benutzen.
* ''Sendfile'' funktioniert nur wenn ''outFd'' ein Socket oder regulärer fd ist — nicht für Pipes.
* ''Truncate'' kann eine Datei auch vergrößern; der neue Bereich wird mit Null-Bytes gefüllt.
* ''StatMtime'' liefert einen timespec-Wert in Nanosekunden — für Sekunden durch 1000000000 teilen.
* ''FileAccess'' prüft den effektiven Benutzer (EUID), nicht den realen (UID).
----
===== Verwandte Units =====
* ''[[lyx_-_programmiersprache:units:fs|std.fs]]'' — Basis-Datei-I/O (open, read, write, close, mkdir …)
* ''[[lyx_-_programmiersprache:units:inotify|std.inotify]]'' — Dateisystemereignisse überwachen
* ''[[lyx_-_programmiersprache:units:net:epoll|std.net.epoll]]'' — I/O-Multiplexing
* ''[[lyx_-_programmiersprache:units:mmap_ext|std.mmap_ext]]'' — Memory-Mapped Files
Letzte Aktualisierung: 2026-06-05