The wasm32 (browser) kernel returns ENOSYS for the filesystem-mutation syscalls rename/renameat/renameat2, link/linkat, symlink, and legacy unlink, while unlinkat (and open/write/mkdir/read) work. Net effect: the machine has no atomic rename, no hardlinks, no symlinks, and no fsync.
Reproduction
A standalone C probe (compiled with wasmcc-glibc, dynamic-main) run in the live linux-6.12-glibc-bash-coreutils machine:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
int main(void){
int fd=open("/tmp/a",O_CREAT|O_WRONLY,0644); write(fd,"x",1);
printf("fsync %d\n", fsync(fd)); close(fd);
printf("rename %d\n", rename("/tmp/a","/tmp/b"));
printf("renameat %d\n", renameat(AT_FDCWD,"/tmp/b",AT_FDCWD,"/tmp/c"));
printf("renameat2 %d\n", renameat2(AT_FDCWD,"/tmp/c",AT_FDCWD,"/tmp/d",0));
printf("link %d\n", link("/tmp/d","/tmp/e"));
printf("linkat %d\n", linkat(AT_FDCWD,"/tmp/d",AT_FDCWD,"/tmp/f",0));
printf("symlink %d\n", symlink("/tmp/d","/tmp/sl"));
printf("unlink %d\n", unlink("/tmp/zzz"));
printf("unlinkat %d\n", unlinkat(AT_FDCWD,"/tmp/zzz2",0));
return 0;
}
Observed (errno 38 = ENOSYS "Function not implemented"):
fsync -1 ENOSYS
rename -1 ENOSYS
renameat -1 ENOSYS
renameat2 -1 ENOSYS
link -1 ENOSYS
linkat -1 ENOSYS
symlink -1 ENOSYS
unlink -1 ENOSYS
unlinkat -1 ENOENT <- works (correct: path does not exist)
Impact
Any program using the standard "write to a temp file, then rename() over the target" atomic-update idiom cannot commit. This surfaced porting dpkg: its whole install model is write-.dpkg-new-then-rename() for the status database and for every unpacked file, so rename() ENOSYS aborts dpkg -i/-r at commit. mv appears to work only because gnulib silently falls back to copy-then-delete when rename fails — it is not exercising rename at all. Editors, databases, compilers writing output, and package managers are all affected.
Likely layer
ENOSYS at the syscall boundary points to the wasm32 kernel syscall table (sys_ni_syscall) rather than the virtiofs/FUSE backend (which would more likely return EOPNOTSUPP/EPERM). Worth triaging kernel (arch/wasm syscall wiring) vs the hardwarejs FS backend.
Suggested direction
Wire up (in priority order): renameat2 (load-bearing — unblocks all atomic writers), link/linkat, symlink/symlinkat, and make fsync a success no-op (return 0) on the browser-backed FS rather than ENOSYS. Also worth routing the legacy unlink/rmdir to their *at forms (which work).
Filed while porting dpkg (BRINTOS-31); happy to re-run the probe or test a fix.