import std.xattr;
Drei Themenblöcke:
Syscalls: setxattr(188), getxattr(191), listxattr(194), removexattr(197), fsetxattr(190), fgetxattr(193), flistxattr(196), fremovexattr(199), fallocate(285), statfs(137).
→ std.fs · std.sysadmin
| Konstante | Wert | Bedeutung |
|---|---|---|
XATTR_CREATE | 1 | Fehler wenn Attribut schon existiert |
XATTR_REPLACE | 2 | Fehler wenn Attribut nicht existiert |
Namespace-Konvention für Attributnamen:
| Namespace | Zugriffsrecht | Beispiel |
|---|---|---|
user. | Normale Anwendungen | user.comment |
security. | Kernel-intern (SELinux) | security.selinux |
trusted. | Nur root | trusted.md5sum |
system. | ACLs | system.posix_acl_access |
| Funktion | Signatur | Beschreibung |
|---|---|---|
XattrSet | (path: pchar, name: pchar, val: int64, size: int64, flags: int64): int64 | Setzt Attribut; flags=0 = anlegen oder ersetzen |
XattrGet | (path: pchar, name: pchar, buf: int64, size: int64): int64 | Liest Attribut; buf=0, size=0 liefert benötigte Größe |
XattrList | (path: pchar, buf: int64, size: int64): int64 | Listet alle Attributnamen (null-separiert) |
XattrRemove | (path: pchar, name: pchar): int64 | Löscht Attribut |
| Funktion | Signatur | Beschreibung |
|---|---|---|
FXattrSet | (fd: int64, name: pchar, val: int64, size: int64, flags: int64): int64 | Wie XattrSet, via Dateideskriptor |
FXattrGet | (fd: int64, name: pchar, buf: int64, size: int64): int64 | Wie XattrGet, via Dateideskriptor |
FXattrList | (fd: int64, buf: int64, size: int64): int64 | Wie XattrList, via Dateideskriptor |
FXattrRemove | (fd: int64, name: pchar): int64 | Wie XattrRemove, via Dateideskriptor |
STATFS_SIZE: 120 Bytes (struct statfs auf x86-64).
| Konstante | Offset | Beschreibung |
|---|---|---|
STATFS_BSIZE | 8 | Optimale Blockgröße in Bytes |
STATFS_BLOCKS | 16 | Gesamtanzahl Datenblöcke |
STATFS_BFREE | 24 | Freie Blöcke (nur root sichtbar) |
STATFS_BAVAIL | 32 | Freie Blöcke für nicht-root |
STATFS_FILES | 40 | Gesamtanzahl Inodes |
STATFS_FFREE | 48 | Freie Inodes |
STATFS_NAMELEN | 64 | Maximale Dateinamenslänge |
| Funktion | Signatur | Beschreibung |
|---|---|---|
StatFs | (path: pchar, buf: int64): int64 | Füllt statfs-Puffer (STATFS_SIZE Bytes) |
StatFsBlockSize | (buf: int64): int64 | Blockgröße in Bytes |
StatFsTotalBlocks | (buf: int64): int64 | Gesamtanzahl Datenblöcke |
StatFsFreeBlocks | (buf: int64): int64 | Verfügbare freie Blöcke (für nicht-root) |
StatFsTotalBytes | (buf: int64): int64 | Gesamtkapazität in Bytes |
StatFsFreeBytes | (buf: int64): int64 | Verfügbarer Speicher in Bytes |
| Konstante | Wert | Bedeutung |
|---|---|---|
FALLOC_FL_KEEP_SIZE | 1 | Dateigröße nicht ändern |
FALLOC_FL_PUNCH_HOLE | 2 | Hole stanzen (benötigt KEEP_SIZE) |
FALLOC_FL_COLLAPSE_RANGE | 8 | Bereich entfernen und zusammenführen |
FALLOC_FL_INSERT_RANGE | 32 | Bereich einfügen (Lücke öffnen) |
| Funktion | Signatur | Beschreibung |
|---|---|---|
FileAllocate | (fd: int64, offset: int64, size: int64): int64 | Reserviert Speicherplatz ohne zu schreiben (keine Nullen) |
FileAllocateMode | (fd: int64, mode: int64, offset: int64, size: int64): int64 | Wie FileAllocate mit explizitem Modus-Flag |
import std.xattr;
import std.alloc;
fn main(): int64 {
var val: pchar := "Wichtige Datei";
var r: int64 := XattrSet("/tmp/test.txt", "user.comment",
val as int64, 14, 0);
if (r < 0) { return r; }
// Größe abfragen
var sz: int64 := XattrGet("/tmp/test.txt", "user.comment", 0, 0);
if (sz < 0) { return sz; }
// Wert lesen
var buf: int64 := alloc(sz + 1);
XattrGet("/tmp/test.txt", "user.comment", buf, sz);
poke8(buf + sz, 0); // NUL-terminieren
free(buf, sz + 1);
return 0;
}
import std.xattr;
import std.alloc;
fn ListAttrs(path: pchar): void {
// Benötigte Größe abfragen
var sz: int64 := XattrList(path, 0, 0);
if (sz <= 0) { return; }
var buf: int64 := alloc(sz);
XattrList(path, buf, sz);
// Null-separierte Namen ausgeben
var pos: int64 := 0;
while (pos < sz) {
var name: pchar := (buf + pos) as pchar;
// name ist ein \0-terminierter String
pos := pos + StrLen(name) + 1;
}
free(buf, sz);
}
import std.xattr;
import std.alloc;
fn GetFreeBytes(path: pchar): int64 {
var buf: int64 := alloc(STATFS_SIZE);
var r: int64 := StatFs(path, buf);
if (r < 0) { free(buf, STATFS_SIZE); return r; }
var freeBytes: int64 := StatFsFreeBytes(buf);
free(buf, STATFS_SIZE);
return freeBytes;
}
import std.xattr;
import std.fs;
fn PreallocFile(path: pchar, size: int64): int64 {
var fd: int64 := OpenFile(path, 1); // O_WRONLY
if (fd < 0) { return fd; }
// Speicher reservieren — Kernel muss keine Blöcke on-demand allokieren
var r: int64 := FileAllocate(fd, 0, size);
CloseFile(fd);
return r;
}
import std.xattr;
fn PunchHole(fd: int64, offset: int64, len: int64): int64 {
// Gibt Blöcke im Bereich frei, Dateigröße bleibt gleich
return FileAllocateMode(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
offset, len);
}
user.-Namespace ist für normale Anwendungen auf normalen Dateisystemen (ext4, xfs, btrfs) zugänglich. tmpfs und FAT unterstützen xattr nicht.XattrGet mit buf=0, size=0 gibt die benötigte Puffergröße zurück — immer zuerst aufrufen bevor Speicher alloziert wird.StatFsFreeBytes verwendet BAVAIL (für nicht-root verfügbar), nicht BFREE (root-reservierter Anteil zusätzlich). Das ist der relevante Wert für Anwendungen.FileAllocate reserviert Blöcke, schreibt aber keine Daten — schneller als Nullen zu schreiben. Die reservierten Blöcke enthalten zufällige Daten bis überschrieben.FALLOC_FL_PUNCH_HOLE — ext4/xfs/btrfs ja, FAT/tmpfs nein. Bei Fehler -EOPNOTSUPP.Letzte Aktualisierung: 2026-06-06