Blog 129: Phase 3 complete — xattr, fdatasync, build tools 19/19 PASS

Date: 2026-03-29 Milestone: M10 Alpine Linux — Phase 3 (Build & Package Ecosystem)

Summary

Phase 3 delivers the build ecosystem needed for Alpine package development:

  1. 12 xattr syscalls — full extended attribute support for fakeroot/abuild
  2. O_TMPFILE + linkat AT_EMPTY_PATH — atomic file creation pattern
  3. setgroups/getgroups — per-process supplementary group storage
  4. fdatasync — missing syscall that broke SQLite entirely
  5. 19/19 integration tests — git, sqlite, perl, gcc/make, xattr all pass

Extended attributes (xattr)

Implemented all 12 xattr syscalls:

  • setxattr / lsetxattr / fsetxattr
  • getxattr / lgetxattr / fgetxattr
  • listxattr / llistxattr / flistxattr
  • removexattr / lremovexattr / fremovexattr

Storage: global in-memory HashMap<(dev_id, inode_no), HashMap<String, Vec<u8>>>. Works across all filesystem types (tmpfs, initramfs, ext4). Supports XATTR_CREATE / XATTR_REPLACE flags, size queries, NUL-separated name lists.

Needed by: fakeroot (capability storage), abuild (Alpine package builder), git (sparse-checkout metadata), rsync (attribute preservation).

O_TMPFILE + linkat AT_EMPTY_PATH

openat(O_TMPFILE) now creates an anonymous temporary file in /tmp (tmpfs) instead of returning ENOSYS. The file isn't linked to any directory entry and is cleaned up when the fd is closed.

linkat(fd, "", ..., AT_EMPTY_PATH) resolves the fd's inode directly and links it to the destination path, enabling the atomic file creation pattern: open(O_TMPFILE) → write → linkat.

setgroups / getgroups

Replaced the Ok(0) stub with real per-process supplementary group storage:

  • groups: SpinLock<Vec<u32>> in the Process struct
  • Inherited on fork/vfork/clone
  • setgroups(size, list) reads GID array from userspace
  • getgroups(size, list) returns stored GIDs (size=0 returns count)

Critical bug: fdatasync missing

The problem

fdatasync(2) (syscall 75 on x86_64, 83 on ARM64) was completely unimplemented — not even a stub. The kernel returned ENOSYS for every call.

The impact

SQLite calls fdatasync() after every write to ensure durability. Without it, every CREATE TABLE, INSERT, and PRAGMA journal_mode=WAL failed with "disk I/O error (10)" — SQLITE_IOERR. This made SQLite completely non-functional.

The fix

Added SYS_FDATASYNC constants for both x86_64 (75) and ARM64 (83), dispatched to the existing sys_fsync() handler. For tmpfs and initramfs, fdatasync and fsync are equivalent (no disk to sync to).

Integration test results: 19/19 PASS

PackageTestsDetails
apk update1/1HTTP package index download
git4/4install, --version, init + commit, log --oneline
sqlite4/4install, --version, CREATE+INSERT+SELECT, WAL journal mode
perl5/5install, -v, print, file I/O (open/close), regex capture
gcc/make4/4install build-base, make build, run compiled binary, shared library link+run
xattr1/1setfattr + getfattr via Alpine's attr package

Test infrastructure

  • testing/test_build_tools.c — C test program following test_alpine_apk pattern
  • make test-build-tools — Makefile target (requires build/alpine.img)
  • 600s timeout (package downloads + compilation take time)

What this validates

  • Dynamic linking: perl, git, sqlite are dynamically linked against musl
  • Shared libraries: gcc builds and links .so files correctly
  • File locking: sqlite WAL mode uses fcntl F_SETLK/F_GETLK
  • Process management: make spawns gcc subprocesses via fork+exec
  • Filesystem: git creates repos, sqlite writes databases, perl does file I/O
  • Networking: apk update downloads over HTTP
  • Extended attributes: setfattr/getfattr roundtrip via kernel xattr table

Phase completion status

All three phases of the Alpine compatibility roadmap are now complete:

PhaseScopeStatusTests
Phase 1Core POSIX gapsComplete + hardened118 contract tests
Phase 2Network servicesCompleteSSH 3/3, nginx 4/4
Phase 3Build ecosystemCompleteBuild tools 19/19

Total test coverage: 300+ tests across 10+ suites, 0 failures.

Files changed

AreaFiles
xattrkernel/syscalls/xattr.rs (new), kernel/syscalls/mod.rs
O_TMPFILEkernel/syscalls/openat.rs, kernel/syscalls/linkat.rs
setgroupskernel/process/process.rs, kernel/syscalls/mod.rs, kernel/syscalls/getgroups.rs
fdatasynckernel/syscalls/mod.rs
ENODATAlibs/kevlar_vfs/src/result.rs
Integration testtesting/test_build_tools.c, Makefile, tools/build-initramfs.py