====== 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