Viewing: fulltest.c
📄 fulltest.c (Read Only) ⬅ To go back
#include <stdint.h>

#ifdef SIGKILL
#undef SIGKILL
#endif
#ifdef SIGUSR1
#undef SIGUSR1
#endif
#ifdef SIGSEGV
#undef SIGSEGV
#endif
#ifdef SIGTTIN
#undef SIGTTIN
#endif
#ifdef SIGTTOU
#undef SIGTTOU
#endif

#ifdef WNOHANG
#undef WNOHANG
#endif
#ifdef SEEK_SET
#undef SEEK_SET
#endif
#ifdef SEEK_CUR
#undef SEEK_CUR
#endif
#ifdef SEEK_END
#undef SEEK_END
#endif

#include "user_errno.h"

#include "signal.h"

enum {
    SYSCALL_WRITE = 1,
    SYSCALL_EXIT  = 2,
    SYSCALL_GETPID = 3,
    SYSCALL_OPEN  = 4,
    SYSCALL_READ  = 5,
    SYSCALL_CLOSE = 6,
    SYSCALL_WAITPID = 7,
    SYSCALL_LSEEK = 9,
    SYSCALL_FSTAT = 10,
    SYSCALL_STAT = 11,

    SYSCALL_DUP = 12,
    SYSCALL_DUP2 = 13,
    SYSCALL_PIPE = 14,
    SYSCALL_PIPE2 = 34,
    SYSCALL_EXECVE = 15,
    SYSCALL_FORK = 16,
    SYSCALL_GETPPID = 17,
    SYSCALL_POLL = 18,
    SYSCALL_KILL = 19,
    SYSCALL_SELECT = 20,
    SYSCALL_IOCTL = 21,
    SYSCALL_SETSID = 22,
    SYSCALL_SETPGID = 23,
    SYSCALL_GETPGRP = 24,

    SYSCALL_SIGACTION = 25,
    SYSCALL_SIGPROCMASK = 26,
    SYSCALL_SIGRETURN = 27,

    SYSCALL_MKDIR = 28,
    SYSCALL_UNLINK = 29,

    SYSCALL_GETDENTS = 30,

    SYSCALL_FCNTL = 31,

    SYSCALL_CHDIR = 32,
    SYSCALL_GETCWD = 33,
    SYSCALL_DUP3 = 35,

    SYSCALL_OPENAT = 36,
    SYSCALL_FSTATAT = 37,
    SYSCALL_UNLINKAT = 38,

    SYSCALL_RENAME = 39,
    SYSCALL_RMDIR = 40,

    SYSCALL_BRK = 41,
    SYSCALL_NANOSLEEP = 42,
    SYSCALL_CLOCK_GETTIME = 43,
    SYSCALL_MMAP = 44,
    SYSCALL_MUNMAP = 45,

    SYSCALL_SHMGET = 46,
    SYSCALL_SHMAT  = 47,
    SYSCALL_SHMDT  = 48,

    SYSCALL_LINK     = 54,
    SYSCALL_SYMLINK  = 55,
    SYSCALL_READLINK = 56,

    SYSCALL_SIGPENDING = 71,
    SYSCALL_PREAD  = 72,
    SYSCALL_PWRITE = 73,
    SYSCALL_ACCESS = 74,
    SYSCALL_TRUNCATE  = 78,
    SYSCALL_FTRUNCATE = 79,
    SYSCALL_UMASK  = 75,
    SYSCALL_ALARM  = 83,
    SYSCALL_SETITIMER = 92,
    SYSCALL_GETITIMER = 93,
    SYSCALL_WAITID    = 94,

    SYSCALL_EPOLL_CREATE = 112,
    SYSCALL_EPOLL_CTL    = 113,
    SYSCALL_EPOLL_WAIT   = 114,

    SYSCALL_INOTIFY_INIT      = 115,
    SYSCALL_INOTIFY_ADD_WATCH = 116,
    SYSCALL_INOTIFY_RM_WATCH  = 117,

    SYSCALL_AIO_READ    = 121,
    SYSCALL_AIO_WRITE   = 122,
    SYSCALL_AIO_ERROR   = 123,
    SYSCALL_AIO_RETURN  = 124,

    SYSCALL_CHMOD  = 50,
    SYSCALL_CHOWN  = 51,
    SYSCALL_GETUID = 52,
    SYSCALL_GETGID = 53,
    SYSCALL_CLONE  = 67,
    SYSCALL_GETTID = 68,
    SYSCALL_FSYNC  = 69,
    SYSCALL_READV  = 81,
    SYSCALL_WRITEV = 82,
    SYSCALL_TIMES  = 84,
    SYSCALL_FUTEX  = 85,
    SYSCALL_FLOCK  = 87,
    SYSCALL_GETEUID = 88,
    SYSCALL_GETEGID = 89,
    SYSCALL_SETEUID = 90,
    SYSCALL_SETEGID = 91,
    SYSCALL_SIGSUSPEND = 80,
    SYSCALL_SIGQUEUE   = 95,
    SYSCALL_POSIX_SPAWN = 96,
    SYSCALL_SETUID = 76,
    SYSCALL_SETGID = 77,
    SYSCALL_MOUNT  = 126,
    SYSCALL_GETTIMEOFDAY = 127,
    SYSCALL_MPROTECT     = 128,
    SYSCALL_GETRLIMIT    = 129,
    SYSCALL_SETRLIMIT    = 130,
    SYSCALL_UNAME        = 136,
    SYSCALL_MADVISE      = 140,
};

enum {
    AT_FDCWD = -100,
};

enum {
    F_GETFD = 1,
    F_SETFD = 2,
    F_GETFL = 3,
    F_SETFL = 4,
    F_GETPIPE_SZ = 1032,
    F_SETPIPE_SZ = 1033,
    FD_CLOEXEC = 1,
};

enum {
    O_CLOEXEC = 0x80000,
};

enum {
    TCGETS = 0x5401,
    TCSETS = 0x5402,
    TIOCGPGRP = 0x540F,
    TIOCSPGRP = 0x5410,
};

enum {
    ENOTTY = 25,
};

enum {
    ICANON = 0x0002,
    ECHO   = 0x0008,
};

#define USER_NCCS 11

struct termios {
    uint32_t c_iflag;
    uint32_t c_oflag;
    uint32_t c_cflag;
    uint32_t c_lflag;
    uint8_t  c_cc[USER_NCCS];
};

struct pollfd {
    int fd;
    int16_t events;
    int16_t revents;
};

enum {
    POLLIN  = 0x0001,
    POLLOUT = 0x0004,
    EPOLLET = (1U << 31),
};

enum {
    SIGKILL = 9,
    SIGUSR1 = 10,
    SIGSEGV = 11,
    SIGTTIN = 21,
    SIGTTOU = 22,
};

enum {
    WNOHANG = 1,
};

enum {
    SEEK_SET = 0,
    SEEK_CUR = 1,
    SEEK_END = 2,
};

enum {
    O_CREAT = 0x40,
    O_TRUNC = 0x200,
    O_NONBLOCK = 0x800,
    O_APPEND = 0x400,
    O_RDWR = 0x02,
};

enum {
    PROT_READ  = 0x1,
    PROT_WRITE = 0x2,
};

enum {
    MAP_PRIVATE   = 0x02,
    MAP_ANONYMOUS = 0x20,
    MAP_FAILED_VAL = 0xFFFFFFFF,
};

enum {
    CLOCK_REALTIME  = 0,
    CLOCK_MONOTONIC = 1,
};

struct timespec {
    uint32_t tv_sec;
    uint32_t tv_nsec;
};

enum {
    R_OK = 4,
    W_OK = 2,
    F_OK = 0,
};

enum {
    SIG_BLOCK   = 0,
    SIG_UNBLOCK = 1,
    SIG_SETMASK = 2,
};

enum {
    IPC_CREAT   = 01000,
    IPC_PRIVATE = 0,
};

enum {
    SIGALRM = 14,
};

enum {
    EAGAIN = 11,
    EINVAL = 22,
    EEXIST = 17,
};

enum {
    ITIMER_REAL    = 0,
    ITIMER_VIRTUAL = 1,
    ITIMER_PROF    = 2,
};

struct timeval {
    uint32_t tv_sec;
    uint32_t tv_usec;
};

struct rlimit {
    uint32_t rlim_cur;
    uint32_t rlim_max;
};

enum {
    RLIMIT_CPU    = 0,
    RLIMIT_FSIZE  = 1,
    RLIMIT_DATA   = 2,
    RLIMIT_STACK  = 3,
    RLIMIT_CORE   = 4,
    RLIMIT_NOFILE = 5,
    RLIMIT_AS     = 6,
    RLIMIT_NPROC  = 7,
    RLIM_INFINITY = 0xFFFFFFFFU,
};

struct itimerval {
    struct timeval it_interval;
    struct timeval it_value;
};

enum {
    P_ALL  = 0,
    P_PID  = 1,
    P_PGID = 2,
    WEXITED = 4,
};

#define S_IFMT  0170000
#define S_IFREG 0100000

struct stat {
    uint32_t st_ino;
    uint32_t st_mode;
    uint32_t st_nlink;
    uint32_t st_uid;
    uint32_t st_gid;
    uint32_t st_size;
};

static int sys_write(int fd, const void* buf, uint32_t len) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_WRITE), "b"(fd), "c"(buf), "d"(len)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_openat(int dirfd, const char* path, uint32_t flags, uint32_t mode) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_OPENAT), "b"(dirfd), "c"(path), "d"(flags), "S"(mode)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_fstatat(int dirfd, const char* path, struct stat* st, uint32_t flags) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_FSTATAT), "b"(dirfd), "c"(path), "d"(st), "S"(flags)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_unlinkat(int dirfd, const char* path, uint32_t flags) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_UNLINKAT), "b"(dirfd), "c"(path), "d"(flags)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_rename(const char* oldpath, const char* newpath) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_RENAME), "b"(oldpath), "c"(newpath)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_rmdir(const char* path) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_RMDIR), "b"(path)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_pipe2(int fds[2], uint32_t flags) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_PIPE2), "b"(fds), "c"(flags)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_chdir(const char* path) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_CHDIR), "b"(path)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_getcwd(char* buf, uint32_t size) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_GETCWD), "b"(buf), "c"(size)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_fcntl(int fd, int cmd, uint32_t arg) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_FCNTL), "b"(fd), "c"(cmd), "d"(arg)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_ioctl(int fd, uint32_t cmd, void* arg);

static int isatty_fd(int fd) {
    struct termios t;
    if (sys_ioctl(fd, TCGETS, &t) < 0) {
        if (errno == ENOTTY) return 0;
        return -1;
    }
    return 1;
}

static int sys_getdents(int fd, void* buf, uint32_t len) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_GETDENTS), "b"(fd), "c"(buf), "d"(len)
        : "memory"
    );
    return __syscall_fix(ret);
}

static void write_int_dec(int v) {
    char buf[16];
    int i = 0;
    if (v == 0) {
        buf[i++] = '0';
    } else {
        int neg = 0;
        if (v < 0) {
            neg = 1;
            v = -v;
        }
        while (v > 0 && i < (int)sizeof(buf)) {
            buf[i++] = (char)('0' + (v % 10));
            v /= 10;
        }
        if (neg && i < (int)sizeof(buf)) {
            buf[i++] = '-';
        }
        for (int j = 0; j < i / 2; j++) {
            char t = buf[j];
            buf[j] = buf[i - 1 - j];
            buf[i - 1 - j] = t;
        }
    }
    (void)sys_write(1, buf, (uint32_t)i);
}

static void write_hex8(uint8_t v) {
    static const char hex[] = "0123456789ABCDEF";
    char b[2];
    b[0] = hex[(v >> 4) & 0xF];
    b[1] = hex[v & 0xF];
    (void)sys_write(1, b, 2);
}

static void write_hex32(uint32_t v) {
    static const char hex[] = "0123456789ABCDEF";
    char b[8];
    for (int i = 0; i < 8; i++) {
        uint32_t shift = (uint32_t)(28 - 4 * i);
        b[i] = hex[(v >> shift) & 0xFU];
    }
    (void)sys_write(1, b, 8);
}

static int memeq(const void* a, const void* b, uint32_t n) {
    const uint8_t* x = (const uint8_t*)a;
    const uint8_t* y = (const uint8_t*)b;
    for (uint32_t i = 0; i < n; i++) {
        if (x[i] != y[i]) return 0;
    }
    return 1;
}

static int streq(const char* a, const char* b) {
    if (!a || !b) return 0;
    uint32_t i = 0;
    while (a[i] != 0 && b[i] != 0) {
        if (a[i] != b[i]) return 0;
        i++;
    }
    return a[i] == b[i];
}

static int sys_sigaction2(int sig, const struct sigaction* act, struct sigaction* oldact) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SIGACTION), "b"(sig), "c"(act), "d"(oldact)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_sigaction(int sig, void (*handler)(int), uintptr_t* old_out) {
    struct sigaction act;
    act.sa_handler = (uintptr_t)handler;
    act.sa_sigaction = 0;
    act.sa_mask = 0;
    act.sa_flags = 0;

    struct sigaction oldact;
    struct sigaction* oldp = old_out ? &oldact : 0;

    int r = sys_sigaction2(sig, &act, oldp);
    if (r < 0) return r;
    if (old_out) {
        *old_out = oldact.sa_handler;
    }
    return 0;
}

static int sys_select(uint32_t nfds, uint64_t* readfds, uint64_t* writefds, uint64_t* exceptfds, int32_t timeout) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SELECT), "b"(nfds), "c"(readfds), "d"(writefds), "S"(exceptfds), "D"(timeout)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_ioctl(int fd, uint32_t cmd, void* arg) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_IOCTL), "b"(fd), "c"(cmd), "d"(arg)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_kill(int pid, int sig) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_KILL), "b"(pid), "c"(sig)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_poll(struct pollfd* fds, uint32_t nfds, int32_t timeout) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_POLL), "b"(fds), "c"(nfds), "d"(timeout)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_setsid(void) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SETSID)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_setpgid(int pid, int pgid) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SETPGID), "b"(pid), "c"(pgid)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_getpgrp(void) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_GETPGRP)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_getpid(void) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_GETPID)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_getppid(void) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_GETPPID)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_fork(void) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_FORK)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_execve(const char* path, const char* const* argv, const char* const* envp) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_EXECVE), "b"(path), "c"(argv), "d"(envp)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_pipe(int fds[2]) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_PIPE), "b"(fds)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_dup(int oldfd) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_DUP), "b"(oldfd)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_dup2(int oldfd, int newfd) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_DUP2), "b"(oldfd), "c"(newfd)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_dup3(int oldfd, int newfd, uint32_t flags) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_DUP3), "b"(oldfd), "c"(newfd), "d"(flags)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_waitpid(int pid, int* status, uint32_t options) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_WAITPID), "b"(pid), "c"(status), "d"(options)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_open(const char* path, uint32_t flags) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_OPEN), "b"(path), "c"(flags)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_mkdir(const char* path) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_MKDIR), "b"(path)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_unlink(const char* path) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_UNLINK), "b"(path)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_read(int fd, void* buf, uint32_t len) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_READ), "b"(fd), "c"(buf), "d"(len)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_close(int fd) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_CLOSE), "b"(fd)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_lseek(int fd, int32_t offset, int whence) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_LSEEK), "b"(fd), "c"(offset), "d"(whence)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_fstat(int fd, struct stat* st) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_FSTAT), "b"(fd), "c"(st)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_stat(const char* path, struct stat* st) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_STAT), "b"(path), "c"(st)
        : "memory"
    );
    return __syscall_fix(ret);
}

static uintptr_t sys_brk(uintptr_t addr) {
    uintptr_t ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_BRK), "b"(addr)
        : "memory"
    );
    return ret;
}

static uintptr_t sys_mmap(uintptr_t addr, uint32_t len, uint32_t prot, uint32_t flags, int fd) {
    uintptr_t ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_MMAP), "b"(addr), "c"(len), "d"(prot), "S"(flags), "D"(fd)
        : "memory"
    );
    return ret;
}

static int sys_munmap(uintptr_t addr, uint32_t len) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_MUNMAP), "b"(addr), "c"(len)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_clock_gettime(uint32_t clk_id, struct timespec* tp) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_CLOCK_GETTIME), "b"(clk_id), "c"(tp)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_pread(int fd, void* buf, uint32_t count, uint32_t offset) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_PREAD), "b"(fd), "c"(buf), "d"(count), "S"(offset)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_pwrite(int fd, const void* buf, uint32_t count, uint32_t offset) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_PWRITE), "b"(fd), "c"(buf), "d"(count), "S"(offset)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_ftruncate(int fd, uint32_t length) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_FTRUNCATE), "b"(fd), "c"(length)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_symlink(const char* target, const char* linkpath) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SYMLINK), "b"(target), "c"(linkpath)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_readlink(const char* path, char* buf, uint32_t bufsiz) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_READLINK), "b"(path), "c"(buf), "d"(bufsiz)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_access(const char* path, uint32_t mode) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_ACCESS), "b"(path), "c"(mode)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_sigprocmask(int how, uint32_t mask, uint32_t* oldset) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SIGPROCMASK), "b"(how), "c"(mask), "d"(oldset)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_sigpending(uint32_t* set) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SIGPENDING), "b"(set)
        : "memory"
    );
    return __syscall_fix(ret);
}

static uint32_t sys_alarm(uint32_t seconds) {
    uint32_t ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_ALARM), "b"(seconds)
        : "memory"
    );
    return ret;
}

static int sys_shmget(uint32_t key, uint32_t size, uint32_t flags) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SHMGET), "b"(key), "c"(size), "d"(flags)
        : "memory"
    );
    return __syscall_fix(ret);
}

static uintptr_t sys_shmat(int shmid, uintptr_t addr, uint32_t flags) {
    uintptr_t ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SHMAT), "b"(shmid), "c"(addr), "d"(flags)
        : "memory"
    );
    return ret;
}

static int sys_shmdt(uintptr_t addr) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SHMDT), "b"(addr)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_link(const char* oldpath, const char* newpath) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_LINK), "b"(oldpath), "c"(newpath)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_umask(uint32_t mask) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_UMASK), "b"(mask)
        : "memory"
    );
    return ret;
}

static int sys_setitimer(int which, const struct itimerval* newval, struct itimerval* oldval) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_SETITIMER), "b"(which), "c"(newval), "d"(oldval)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_getitimer(int which, struct itimerval* cur) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_GETITIMER), "b"(which), "c"(cur)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_waitid(uint32_t idtype, uint32_t id, void* infop, uint32_t options) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_WAITID), "b"(idtype), "c"(id), "d"(infop), "S"(options)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_epoll_create(int size) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_EPOLL_CREATE), "b"(size)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_epoll_ctl(int epfd, int op, int fd, void* event) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_EPOLL_CTL), "b"(epfd), "c"(op), "d"(fd), "S"(event)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_epoll_wait(int epfd, void* events, int maxevents, int timeout) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_EPOLL_WAIT), "b"(epfd), "c"(events), "d"(maxevents), "S"(timeout)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_inotify_init(void) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_INOTIFY_INIT)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_inotify_add_watch(int fd, const char* path, uint32_t mask) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_INOTIFY_ADD_WATCH), "b"(fd), "c"(path), "d"(mask)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_inotify_rm_watch(int fd, int wd) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_INOTIFY_RM_WATCH), "b"(fd), "c"(wd)
        : "memory"
    );
    return __syscall_fix(ret);
}

struct aiocb {
    int      aio_fildes;
    void*    aio_buf;
    uint32_t aio_nbytes;
    uint32_t aio_offset;
    int32_t  aio_error;
    int32_t  aio_return;
};

static int sys_aio_read(struct aiocb* cb) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_AIO_READ), "b"(cb)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_aio_write(struct aiocb* cb) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_AIO_WRITE), "b"(cb)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_aio_error(struct aiocb* cb) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_AIO_ERROR), "b"(cb)
        : "memory"
    );
    return ret;
}

static int sys_aio_return(struct aiocb* cb) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_AIO_RETURN), "b"(cb)
        : "memory"
    );
    return ret;
}

static int sys_nanosleep(const struct timespec* req, struct timespec* rem) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_NANOSLEEP), "b"(req), "c"(rem)
        : "memory"
    );
    return __syscall_fix(ret);
}

static uint32_t sys_getuid(void) {
    uint32_t ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_GETUID) : "memory");
    return ret;
}

static uint32_t sys_getgid(void) {
    uint32_t ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_GETGID) : "memory");
    return ret;
}

static uint32_t sys_geteuid(void) {
    uint32_t ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_GETEUID) : "memory");
    return ret;
}

static uint32_t sys_getegid(void) {
    uint32_t ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_GETEGID) : "memory");
    return ret;
}

static int sys_gettid(void) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_GETTID) : "memory");
    return ret;
}

static int sys_fsync(int fd) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_FSYNC), "b"(fd)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_truncate(const char* path, uint32_t length) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_TRUNCATE), "b"(path), "c"(length)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_chmod(const char* path, uint32_t mode) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_CHMOD), "b"(path), "c"(mode)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_flock(int fd, int operation) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_FLOCK), "b"(fd), "c"(operation)
        : "memory"
    );
    return __syscall_fix(ret);
}

struct iovec {
    void*    iov_base;
    uint32_t iov_len;
};

static int sys_writev(int fd, const struct iovec* iov, int iovcnt) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_WRITEV), "b"(fd), "c"(iov), "d"(iovcnt)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_readv(int fd, const struct iovec* iov, int iovcnt) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_READV), "b"(fd), "c"(iov), "d"(iovcnt)
        : "memory"
    );
    return __syscall_fix(ret);
}

static uint32_t sys_times(void* buf) {
    uint32_t ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_TIMES), "b"(buf)
        : "memory"
    );
    return ret;
}

static int sys_posix_spawn(uint32_t* pid_out, const char* path,
                           const char* const* argv, const char* const* envp) {
    int ret;
    __asm__ volatile(
        "int $0x80"
        : "=a"(ret)
        : "a"(SYSCALL_POSIX_SPAWN), "b"(pid_out), "c"(path), "d"(argv), "S"(envp)
        : "memory"
    );
    return __syscall_fix(ret);
}

static int sys_setuid(uint32_t uid) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_SETUID), "b"(uid) : "memory");
    return __syscall_fix(ret);
}

static int sys_setgid(uint32_t gid) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_SETGID), "b"(gid) : "memory");
    return __syscall_fix(ret);
}

static int sys_seteuid(uint32_t euid) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_SETEUID), "b"(euid) : "memory");
    return __syscall_fix(ret);
}

static int sys_setegid(uint32_t egid) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_SETEGID), "b"(egid) : "memory");
    return __syscall_fix(ret);
}

static int sys_sigsuspend(const uint32_t* mask) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_SIGSUSPEND), "b"(mask) : "memory");
    return __syscall_fix(ret);
}

static int sys_gettimeofday(struct timeval* tv) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_GETTIMEOFDAY), "b"(tv), "c"(0) : "memory");
    return __syscall_fix(ret);
}

static int sys_mprotect(uintptr_t addr, uint32_t len, uint32_t prot) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_MPROTECT), "b"(addr), "c"(len), "d"(prot) : "memory");
    return __syscall_fix(ret);
}

static int sys_madvise(uintptr_t addr, uint32_t len, uint32_t advice) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_MADVISE), "b"(addr), "c"(len), "d"(advice) : "memory");
    return __syscall_fix(ret);
}

static int sys_getrlimit(int resource, struct rlimit* rlim) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_GETRLIMIT), "b"(resource), "c"(rlim) : "memory");
    return __syscall_fix(ret);
}

struct utsname {
    char sysname[65];
    char nodename[65];
    char release[65];
    char version[65];
    char machine[65];
};

static int sys_uname(struct utsname* buf) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_UNAME), "b"(buf) : "memory");
    return __syscall_fix(ret);
}

static int sys_setrlimit(int resource, const struct rlimit* rlim) {
    int ret;
    __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_SETRLIMIT), "b"(resource), "c"(rlim) : "memory");
    return __syscall_fix(ret);
}

__attribute__((noreturn)) static void sys_exit(int code) {
    __asm__ volatile(
        "int $0x80\n"
        "1: jmp 1b\n"
        :
        : "a"(SYSCALL_EXIT), "b"(code)
        : "memory"
    );
    for (;;) {
        __asm__ volatile("hlt");
    }
}

static volatile int got_usr1 = 0;
static volatile int got_usr1_ret = 0;
static volatile int got_ttin = 0;
static volatile int got_ttou = 0;
static volatile int got_alrm = 0;

static void usr1_handler(int sig) {
    (void)sig;
    got_usr1 = 1;
    sys_write(1, "[test] SIGUSR1 handler OK\n",
              (uint32_t)(sizeof("[test] SIGUSR1 handler OK\n") - 1));
}

static void usr1_ret_handler(int sig) {
    (void)sig;
    got_usr1_ret = 1;
}

static void alrm_handler(int sig) {
    (void)sig;
    got_alrm = 1;
}

static void ttin_handler(int sig) {
    (void)sig;
    got_ttin = 1;
}

static void ttou_handler(int sig) {
    (void)sig;
    got_ttou = 1;
}

static void sigsegv_exit_handler(int sig) {
    (void)sig;
    static const char msg[] = "[test] SIGSEGV handler invoked\n";
    (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
    sys_exit(0);
}

static void sigsegv_info_handler(int sig, siginfo_t* info, void* uctx) {
    (void)uctx;
    static const char msg[] = "[test] SIGSEGV siginfo handler invoked\n";
    (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
    const uintptr_t expected = 0x12345000U;
    if (sig == SIGSEGV && info && (uintptr_t)info->si_addr == expected) {
        sys_exit(0);
    }
    sys_exit(1);
}

void _start(void) {
    __asm__ volatile(
        "mov $0x23, %ax\n"
        "mov %ax, %ds\n"
        "mov %ax, %es\n"
        "mov %ax, %fs\n"
        "mov %ax, %gs\n"
    );

    static const char msg[] = "[test] hello from init.elf\n";
    (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));

    static const char path[] = "/sbin/fulltest";

    int fd = sys_open(path, 0);
    if (fd < 0) {
        sys_write(1, "[test] open failed fd=", (uint32_t)(sizeof("[test] open failed fd=") - 1));
        write_int_dec(fd);
        sys_write(1, "\n", 1);
        sys_exit(1);
    }

    uint8_t hdr[4];
    int rd = sys_read(fd, hdr, 4);
    (void)sys_close(fd);
    if (rd == 4 && hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F') {
        sys_write(1, "[test] open/read/close OK (ELF magic)\n",
                  (uint32_t)(sizeof("[test] open/read/close OK (ELF magic)\n") - 1));
    } else {
        sys_write(1, "[test] read failed or bad header rd=", (uint32_t)(sizeof("[test] read failed or bad header rd=") - 1));
        write_int_dec(rd);
        sys_write(1, " hdr=", (uint32_t)(sizeof(" hdr=") - 1));
        for (int i = 0; i < 4; i++) {
            write_hex8(hdr[i]);
        }
        sys_write(1, "\n", 1);
        sys_exit(1);
    }

    fd = sys_open("/sbin/fulltest", 0);
    if (fd < 0) {
        sys_write(1, "[test] overlay open failed\n",
                  (uint32_t)(sizeof("[test] overlay open failed\n") - 1));
        sys_exit(1);
    }

    uint8_t orig0 = 0;
    if (sys_lseek(fd, 0, SEEK_SET) < 0 || sys_read(fd, &orig0, 1) != 1) {
        sys_write(1, "[test] overlay read failed\n",
                  (uint32_t)(sizeof("[test] overlay read failed\n") - 1));
        sys_exit(1);
    }

    uint8_t x = (uint8_t)(orig0 ^ 0xFF);
    if (sys_lseek(fd, 0, SEEK_SET) < 0 || sys_write(fd, &x, 1) != 1) {
        sys_write(1, "[test] overlay write failed\n",
                  (uint32_t)(sizeof("[test] overlay write failed\n") - 1));
        sys_exit(1);
    }

    if (sys_close(fd) < 0) {
        sys_write(1, "[test] overlay close failed\n",
                  (uint32_t)(sizeof("[test] overlay close failed\n") - 1));
        sys_exit(1);
    }

    fd = sys_open("/sbin/fulltest", 0);
    if (fd < 0) {
        sys_write(1, "[test] overlay open2 failed\n",
                  (uint32_t)(sizeof("[test] overlay open2 failed\n") - 1));
        sys_exit(1);
    }

    uint8_t chk = 0;
    if (sys_lseek(fd, 0, SEEK_SET) < 0 || sys_read(fd, &chk, 1) != 1 || chk != x) {
        sys_write(1, "[test] overlay verify failed\n",
                  (uint32_t)(sizeof("[test] overlay verify failed\n") - 1));
        sys_exit(1);
    }

    if (sys_lseek(fd, 0, SEEK_SET) < 0 || sys_write(fd, &orig0, 1) != 1) {
        sys_write(1, "[test] overlay restore failed\n",
                  (uint32_t)(sizeof("[test] overlay restore failed\n") - 1));
        sys_exit(1);
    }

    if (sys_close(fd) < 0) {
        sys_write(1, "[test] overlay close2 failed\n",
                  (uint32_t)(sizeof("[test] overlay close2 failed\n") - 1));
        sys_exit(1);
    }

    sys_write(1, "[test] overlay copy-up OK\n",
              (uint32_t)(sizeof("[test] overlay copy-up OK\n") - 1));

    fd = sys_open("/sbin/fulltest", 0);
    if (fd < 0) {
        sys_write(1, "[test] open2 failed\n", (uint32_t)(sizeof("[test] open2 failed\n") - 1));
        sys_exit(1);
    }

    struct stat st;
    if (sys_fstat(fd, &st) < 0) {
        sys_write(1, "[test] fstat failed\n", (uint32_t)(sizeof("[test] fstat failed\n") - 1));
        sys_exit(1);
    }

    if ((st.st_mode & S_IFMT) != S_IFREG || st.st_size == 0) {
        sys_write(1, "[test] fstat bad\n", (uint32_t)(sizeof("[test] fstat bad\n") - 1));
        sys_exit(1);
    }

    if (sys_lseek(fd, 0, SEEK_SET) < 0) {
        sys_write(1, "[test] lseek set failed\n",
                  (uint32_t)(sizeof("[test] lseek set failed\n") - 1));
        sys_exit(1);
    }

    uint8_t m2[4];
    if (sys_read(fd, m2, 4) != 4) {
        sys_write(1, "[test] read2 failed\n", (uint32_t)(sizeof("[test] read2 failed\n") - 1));
        sys_exit(1);
    }
    if (m2[0] != 0x7F || m2[1] != 'E' || m2[2] != 'L' || m2[3] != 'F') {
        sys_write(1, "[test] lseek/read mismatch\n",
                  (uint32_t)(sizeof("[test] lseek/read mismatch\n") - 1));
        sys_exit(1);
    }

    if (sys_close(fd) < 0) {
        sys_write(1, "[test] close2 failed\n", (uint32_t)(sizeof("[test] close2 failed\n") - 1));
        sys_exit(1);
    }

    if (sys_stat("/sbin/fulltest", &st) < 0) {
        sys_write(1, "[test] stat failed\n", (uint32_t)(sizeof("[test] stat failed\n") - 1));
        sys_exit(1);
    }
    if ((st.st_mode & S_IFMT) != S_IFREG || st.st_size == 0) {
        sys_write(1, "[test] stat bad\n", (uint32_t)(sizeof("[test] stat bad\n") - 1));
        sys_exit(1);
    }

    sys_write(1, "[test] lseek/stat/fstat OK\n",
              (uint32_t)(sizeof("[test] lseek/stat/fstat OK\n") - 1));

    fd = sys_open("/tmp/hello.txt", 0);
    if (fd < 0) {
        sys_write(1, "[test] tmpfs open failed\n",
                  (uint32_t)(sizeof("[test] tmpfs open failed\n") - 1));
        sys_exit(1);
    }

    if (sys_lseek(fd, 0, SEEK_END) < 0) {
        sys_write(1, "[test] dup2 prep lseek failed\n",
                  (uint32_t)(sizeof("[test] dup2 prep lseek failed\n") - 1));
        sys_exit(1);
    }

    if (sys_dup2(fd, 1) != 1) {
        sys_write(1, "[test] dup2 failed\n", (uint32_t)(sizeof("[test] dup2 failed\n") - 1));
        sys_exit(1);
    }

    (void)sys_close(fd);

    {
        static const char m[] = "[test] dup2 stdout->file OK\n";
        if (sys_write(1, m, (uint32_t)(sizeof(m) - 1)) != (int)(sizeof(m) - 1)) {
            sys_exit(1);
        }
    }

    (void)sys_close(1);
    sys_write(1, "[test] dup2 restore tty OK\n",
              (uint32_t)(sizeof("[test] dup2 restore tty OK\n") - 1));

    {
        int pfds[2];
        if (sys_pipe(pfds) < 0) {
            sys_write(1, "[test] pipe failed\n", (uint32_t)(sizeof("[test] pipe failed\n") - 1));
            sys_exit(1);
        }

        static const char pmsg[] = "pipe-test";
        if (sys_write(pfds[1], pmsg, (uint32_t)(sizeof(pmsg) - 1)) != (int)(sizeof(pmsg) - 1)) {
            sys_write(1, "[test] pipe write failed\n",
                      (uint32_t)(sizeof("[test] pipe write failed\n") - 1));
            sys_exit(1);
        }

        char rbuf[16];
        int prd = sys_read(pfds[0], rbuf, (uint32_t)(sizeof(pmsg) - 1));
        if (prd != (int)(sizeof(pmsg) - 1)) {
            sys_write(1, "[test] pipe read failed\n",
                      (uint32_t)(sizeof("[test] pipe read failed\n") - 1));
            sys_exit(1);
        }

        int ok = 1;
        for (uint32_t i = 0; i < (uint32_t)(sizeof(pmsg) - 1); i++) {
            if ((uint8_t)rbuf[i] != (uint8_t)pmsg[i]) ok = 0;
        }
        if (!ok) {
            sys_write(1, "[test] pipe mismatch\n",
                      (uint32_t)(sizeof("[test] pipe mismatch\n") - 1));
            sys_exit(1);
        }

        if (sys_dup2(pfds[1], 1) != 1) {
            sys_write(1, "[test] pipe dup2 failed\n",
                      (uint32_t)(sizeof("[test] pipe dup2 failed\n") - 1));
            sys_exit(1);
        }

        static const char p2[] = "dup2-pipe";
        if (sys_write(1, p2, (uint32_t)(sizeof(p2) - 1)) != (int)(sizeof(p2) - 1)) {
            sys_exit(1);
        }

        int prd2 = sys_read(pfds[0], rbuf, (uint32_t)(sizeof(p2) - 1));
        if (prd2 != (int)(sizeof(p2) - 1)) {
            sys_write(1, "[test] pipe dup2 read failed\n",
                      (uint32_t)(sizeof("[test] pipe dup2 read failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] pipe OK\n", (uint32_t)(sizeof("[test] pipe OK\n") - 1));

        (void)sys_close(pfds[0]);
        (void)sys_close(pfds[1]);

        int tfd = sys_open("/dev/tty", 0);
        if (tfd < 0) {
            sys_write(1, "[test] /dev/tty open failed\n",
                      (uint32_t)(sizeof("[test] /dev/tty open failed\n") - 1));
            sys_exit(1);
        }
        if (sys_dup2(tfd, 1) != 1) {
            sys_write(1, "[test] dup2 restore tty failed\n",
                      (uint32_t)(sizeof("[test] dup2 restore tty failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(tfd);

    }

    {
        int pid = sys_fork();
        if (pid < 0) {
            sys_write(1, "[test] kill test fork failed\n",
                      (uint32_t)(sizeof("[test] kill test fork failed\n") - 1));
            sys_exit(1);
        }

        if (pid == 0) {
            for (;;) {
                __asm__ volatile("nop");
            }
        }

        if (sys_kill(pid, SIGKILL) < 0) {
            sys_write(1, "[test] kill(SIGKILL) failed\n",
                      (uint32_t)(sizeof("[test] kill(SIGKILL) failed\n") - 1));
            sys_exit(1);
        }

        int st = 0;
        int rp = sys_waitpid(pid, &st, 0);
        if (rp != pid || st != (128 + SIGKILL)) {
            sys_write(1, "[test] kill test waitpid mismatch\n",
                      (uint32_t)(sizeof("[test] kill test waitpid mismatch\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] kill(SIGKILL) OK\n",
                  (uint32_t)(sizeof("[test] kill(SIGKILL) OK\n") - 1));
    }

    {
        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] poll pipe setup failed\n",
                      (uint32_t)(sizeof("[test] poll pipe setup failed\n") - 1));
            sys_exit(1);
        }

        struct pollfd p;
        p.fd = fds[0];
        p.events = POLLIN;
        p.revents = 0;
        int rc = sys_poll(&p, 1, 0);
        if (rc != 0) {
            sys_write(1, "[test] poll(pipe) expected 0\n",
                      (uint32_t)(sizeof("[test] poll(pipe) expected 0\n") - 1));
            sys_exit(1);
        }

        static const char a = 'A';
        if (sys_write(fds[1], &a, 1) != 1) {
            sys_write(1, "[test] poll pipe write failed\n",
                      (uint32_t)(sizeof("[test] poll pipe write failed\n") - 1));
            sys_exit(1);
        }

        p.revents = 0;
        rc = sys_poll(&p, 1, 0);
        if (rc != 1 || (p.revents & POLLIN) == 0) {
            sys_write(1, "[test] poll(pipe) expected POLLIN\n",
                      (uint32_t)(sizeof("[test] poll(pipe) expected POLLIN\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);
        sys_write(1, "[test] poll(pipe) OK\n", (uint32_t)(sizeof("[test] poll(pipe) OK\n") - 1));
    }

    {
        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] select pipe setup failed\n",
                      (uint32_t)(sizeof("[test] select pipe setup failed\n") - 1));
            sys_exit(1);
        }

        uint64_t r = 0;
        uint64_t w = 0;
        r |= (1ULL << (uint32_t)fds[0]);
        int rc = sys_select((uint32_t)(fds[0] + 1), &r, &w, 0, 0);
        if (rc != 0) {
            sys_write(1, "[test] select(pipe) expected 0\n",
                      (uint32_t)(sizeof("[test] select(pipe) expected 0\n") - 1));
            sys_exit(1);
        }

        static const char a = 'B';
        if (sys_write(fds[1], &a, 1) != 1) {
            sys_write(1, "[test] select pipe write failed\n",
                      (uint32_t)(sizeof("[test] select pipe write failed\n") - 1));
            sys_exit(1);
        }

        r = 0;
        w = 0;
        r |= (1ULL << (uint32_t)fds[0]);
        rc = sys_select((uint32_t)(fds[0] + 1), &r, &w, 0, 0);
        if (rc != 1 || ((r >> (uint32_t)fds[0]) & 1ULL) == 0) {
            sys_write(1, "[test] select(pipe) expected readable\n",
                      (uint32_t)(sizeof("[test] select(pipe) expected readable\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);
        sys_write(1, "[test] select(pipe) OK\n",
                  (uint32_t)(sizeof("[test] select(pipe) OK\n") - 1));
    }

    {
        int fd = sys_open("/dev/tty", 0);
        if (fd < 0) {
            sys_write(1, "[test] ioctl(/dev/tty) open failed\n",
                      (uint32_t)(sizeof("[test] ioctl(/dev/tty) open failed\n") - 1));
            sys_exit(1);
        }

        int fg = -1;
        if (sys_ioctl(fd, TIOCGPGRP, &fg) < 0 || fg != 0) {
            sys_write(1, "[test] ioctl TIOCGPGRP failed\n",
                      (uint32_t)(sizeof("[test] ioctl TIOCGPGRP failed\n") - 1));
            sys_exit(1);
        }

        fg = 0;
        if (sys_ioctl(fd, TIOCSPGRP, &fg) < 0) {
            sys_write(1, "[test] ioctl TIOCSPGRP failed\n",
                      (uint32_t)(sizeof("[test] ioctl TIOCSPGRP failed\n") - 1));
            sys_exit(1);
        }

        fg = 1;
        if (sys_ioctl(fd, TIOCSPGRP, &fg) >= 0) {
            sys_write(1, "[test] ioctl TIOCSPGRP expected fail\n",
                      (uint32_t)(sizeof("[test] ioctl TIOCSPGRP expected fail\n") - 1));
            sys_exit(1);
        }

        struct termios oldt;
        if (sys_ioctl(fd, TCGETS, &oldt) < 0) {
            sys_write(1, "[test] ioctl TCGETS failed\n",
                      (uint32_t)(sizeof("[test] ioctl TCGETS failed\n") - 1));
            sys_exit(1);
        }

        struct termios t = oldt;
        t.c_lflag &= ~(uint32_t)(ECHO | ICANON);
        if (sys_ioctl(fd, TCSETS, &t) < 0) {
            sys_write(1, "[test] ioctl TCSETS failed\n",
                      (uint32_t)(sizeof("[test] ioctl TCSETS failed\n") - 1));
            sys_exit(1);
        }

        struct termios chk;
        if (sys_ioctl(fd, TCGETS, &chk) < 0) {
            sys_write(1, "[test] ioctl TCGETS2 failed\n",
                      (uint32_t)(sizeof("[test] ioctl TCGETS2 failed\n") - 1));
            sys_exit(1);
        }

        if ((chk.c_lflag & (uint32_t)(ECHO | ICANON)) != 0) {
            sys_write(1, "[test] ioctl verify failed\n",
                      (uint32_t)(sizeof("[test] ioctl verify failed\n") - 1));
            sys_exit(1);
        }

        (void)sys_ioctl(fd, TCSETS, &oldt);
        (void)sys_close(fd);

        sys_write(1, "[test] ioctl(/dev/tty) OK\n",
                  (uint32_t)(sizeof("[test] ioctl(/dev/tty) OK\n") - 1));
    }

    // A2: basic job control. A background pgrp read/write on controlling TTY should raise SIGTTIN/SIGTTOU.
    {
        int leader = sys_fork();
        if (leader < 0) {
            sys_write(1, "[test] fork(job control leader) failed\n",
                      (uint32_t)(sizeof("[test] fork(job control leader) failed\n") - 1));
            sys_exit(1);
        }
        if (leader == 0) {
            int me = sys_getpid();
            int sid = sys_setsid();
            if (sid != me) {
                sys_write(1, "[test] setsid(job control) failed\n",
                          (uint32_t)(sizeof("[test] setsid(job control) failed\n") - 1));
                sys_exit(1);
            }

            int tfd = sys_open("/dev/tty", 0);
            if (tfd < 0) {
                sys_write(1, "[test] open(/dev/tty) for job control failed\n",
                          (uint32_t)(sizeof("[test] open(/dev/tty) for job control failed\n") - 1));
                sys_exit(1);
            }

            // Touch ioctl to make kernel acquire controlling session/pgrp.
            int fg = 0;
            (void)sys_ioctl(tfd, TIOCGPGRP, &fg);

            fg = me;
            if (sys_ioctl(tfd, TIOCSPGRP, &fg) < 0) {
                sys_write(1, "[test] ioctl TIOCSPGRP(job control) failed\n",
                          (uint32_t)(sizeof("[test] ioctl TIOCSPGRP(job control) failed\n") - 1));
                sys_exit(1);
            }

            int bg = sys_fork();
            if (bg < 0) {
                sys_write(1, "[test] fork(job control bg) failed\n",
                          (uint32_t)(sizeof("[test] fork(job control bg) failed\n") - 1));
                sys_exit(1);
            }
            if (bg == 0) {
                (void)sys_setpgid(0, me + 1);

                (void)sys_sigaction(SIGTTIN, ttin_handler, 0);
                (void)sys_sigaction(SIGTTOU, ttou_handler, 0);

                uint8_t b = 0;
                (void)sys_read(tfd, &b, 1);
                if (!got_ttin) {
                    sys_write(1, "[test] SIGTTIN job control failed\n",
                              (uint32_t)(sizeof("[test] SIGTTIN job control failed\n") - 1));
                    sys_exit(1);
                }

                const char msg2[] = "x";
                (void)sys_write(tfd, msg2, 1);
                if (!got_ttou) {
                    sys_write(1, "[test] SIGTTOU job control failed\n",
                              (uint32_t)(sizeof("[test] SIGTTOU job control failed\n") - 1));
                    sys_exit(1);
                }

                sys_exit(0);
            }

            int st2 = 0;
            int wp2 = sys_waitpid(bg, &st2, 0);
            if (wp2 != bg || st2 != 0) {
                sys_write(1, "[test] waitpid(job control bg) failed wp=", (uint32_t)(sizeof("[test] waitpid(job control bg) failed wp=") - 1));
                write_int_dec(wp2);
                sys_write(1, " st=", (uint32_t)(sizeof(" st=") - 1));
                write_int_dec(st2);
                sys_write(1, "\n", 1);
                sys_exit(1);
            }

            (void)sys_close(tfd);
            sys_exit(0);
        }

        int stL = 0;
        int wpL = sys_waitpid(leader, &stL, 0);
        if (wpL != leader || stL != 0) {
            sys_write(1, "[test] waitpid(job control leader) failed wp=", (uint32_t)(sizeof("[test] waitpid(job control leader) failed wp=") - 1));
            write_int_dec(wpL);
            sys_write(1, " st=", (uint32_t)(sizeof(" st=") - 1));
            write_int_dec(stL);
            sys_write(1, "\n", 1);
            sys_exit(1);
        }

        sys_write(1, "[test] job control (SIGTTIN/SIGTTOU) OK\n",
                  (uint32_t)(sizeof("[test] job control (SIGTTIN/SIGTTOU) OK\n") - 1));
    }

    {
        int fd = sys_open("/dev/null", 0);
        if (fd < 0) {
            sys_write(1, "[test] poll(/dev/null) open failed\n",
                      (uint32_t)(sizeof("[test] poll(/dev/null) open failed\n") - 1));
            sys_exit(1);
        }
        struct pollfd p;
        p.fd = fd;
        p.events = POLLOUT;
        p.revents = 0;
        int rc = sys_poll(&p, 1, 0);
        if (rc != 1 || (p.revents & POLLOUT) == 0) {
            sys_write(1, "[test] poll(/dev/null) expected POLLOUT\n",
                      (uint32_t)(sizeof("[test] poll(/dev/null) expected POLLOUT\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);
        sys_write(1, "[test] poll(/dev/null) OK\n",
                  (uint32_t)(sizeof("[test] poll(/dev/null) OK\n") - 1));
    }

    {
        int mfd = sys_open("/dev/ptmx", 0);
        int sfd = sys_open("/dev/pts/0", 0);
        if (mfd < 0 || sfd < 0) {
            sys_write(1, "[test] pty open failed\n",
                      (uint32_t)(sizeof("[test] pty open failed\n") - 1));
            sys_exit(1);
        }

        static const char m2s[] = "m2s";
        if (sys_write(mfd, m2s, (uint32_t)(sizeof(m2s) - 1)) != (int)(sizeof(m2s) - 1)) {
            sys_write(1, "[test] pty write master failed\n",
                      (uint32_t)(sizeof("[test] pty write master failed\n") - 1));
            sys_exit(1);
        }

        struct pollfd p;
        p.fd = sfd;
        p.events = POLLIN;
        p.revents = 0;
        int rc = sys_poll(&p, 1, 50);
        if (rc != 1 || (p.revents & POLLIN) == 0) {
            sys_write(1, "[test] pty poll slave failed\n",
                      (uint32_t)(sizeof("[test] pty poll slave failed\n") - 1));
            sys_exit(1);
        }

        char buf[8];
        int rd = sys_read(sfd, buf, (uint32_t)(sizeof(m2s) - 1));
        if (rd != (int)(sizeof(m2s) - 1) || !memeq(buf, m2s, (uint32_t)(sizeof(m2s) - 1))) {
            sys_write(1, "[test] pty read slave failed\n",
                      (uint32_t)(sizeof("[test] pty read slave failed\n") - 1));
            sys_exit(1);
        }

        static const char s2m[] = "s2m";
        if (sys_write(sfd, s2m, (uint32_t)(sizeof(s2m) - 1)) != (int)(sizeof(s2m) - 1)) {
            sys_write(1, "[test] pty write slave failed\n",
                      (uint32_t)(sizeof("[test] pty write slave failed\n") - 1));
            sys_exit(1);
        }

        p.fd = mfd;
        p.events = POLLIN;
        p.revents = 0;
        rc = sys_poll(&p, 1, 50);
        if (rc != 1 || (p.revents & POLLIN) == 0) {
            sys_write(1, "[test] pty poll master failed\n",
                      (uint32_t)(sizeof("[test] pty poll master failed\n") - 1));
            sys_exit(1);
        }

        rd = sys_read(mfd, buf, (uint32_t)(sizeof(s2m) - 1));
        if (rd != (int)(sizeof(s2m) - 1) || !memeq(buf, s2m, (uint32_t)(sizeof(s2m) - 1))) {
            sys_write(1, "[test] pty read master failed\n",
                      (uint32_t)(sizeof("[test] pty read master failed\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(mfd);
        (void)sys_close(sfd);
        sys_write(1, "[test] pty OK\n", (uint32_t)(sizeof("[test] pty OK\n") - 1));
    }

    {
        sys_write(1, "[test] setsid test: before fork\n",
                  (uint32_t)(sizeof("[test] setsid test: before fork\n") - 1));
        int pid = sys_fork();
        if (pid < 0) {
            static const char smsg[] = "[test] fork failed\n";
            (void)sys_write(1, smsg, (uint32_t)(sizeof(smsg) - 1));
            sys_exit(2);
        }
        if (pid == 0) {
            sys_write(1, "[test] setsid test: child start\n",
                      (uint32_t)(sizeof("[test] setsid test: child start\n") - 1));
            int me = sys_getpid();
            int sid = sys_setsid();
            if (sid != me) sys_exit(2);

            int pg = sys_getpgrp();
            if (pg != me) sys_exit(3);

            int newpg = me + 1;
            if (sys_setpgid(0, newpg) < 0) sys_exit(4);
            if (sys_getpgrp() != newpg) sys_exit(5);

            sys_exit(0);
        }

        sys_write(1, "[test] setsid test: parent waitpid\n",
                  (uint32_t)(sizeof("[test] setsid test: parent waitpid\n") - 1));
        int st = 0;
        int wp = sys_waitpid(pid, &st, 0);
        if (wp != pid || st != 0) {
            sys_write(1, "[test] setsid/setpgid/getpgrp failed\n",
                      (uint32_t)(sizeof("[test] setsid/setpgid/getpgrp failed\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] setsid/setpgid/getpgrp OK\n",
                  (uint32_t)(sizeof("[test] setsid/setpgid/getpgrp OK\n") - 1));
    }

    {
        uintptr_t oldh = 0;
        if (sys_sigaction(SIGUSR1, usr1_handler, &oldh) < 0) {
            sys_write(1, "[test] sigaction failed\n",
                      (uint32_t)(sizeof("[test] sigaction failed\n") - 1));
            sys_exit(1);
        }

        int me = sys_getpid();
        if (sys_kill(me, SIGUSR1) < 0) {
            sys_write(1, "[test] kill(SIGUSR1) failed\n",
                      (uint32_t)(sizeof("[test] kill(SIGUSR1) failed\n") - 1));
            sys_exit(1);
        }

        for (uint32_t i = 0; i < 2000000U; i++) {
            if (got_usr1) break;
        }

        if (!got_usr1) {
            sys_write(1, "[test] SIGUSR1 not delivered\n",
                      (uint32_t)(sizeof("[test] SIGUSR1 not delivered\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] sigaction/kill(SIGUSR1) OK\n",
                  (uint32_t)(sizeof("[test] sigaction/kill(SIGUSR1) OK\n") - 1));
    }

    // Verify that returning from a signal handler does not corrupt the user stack.
    {
        if (sys_sigaction(SIGUSR1, usr1_ret_handler, 0) < 0) {
            sys_write(1, "[test] sigaction (sigreturn test) failed\n",
                      (uint32_t)(sizeof("[test] sigaction (sigreturn test) failed\n") - 1));
            sys_exit(1);
        }

        volatile uint32_t canary = 0x11223344U;
        int me = sys_getpid();
        if (sys_kill(me, SIGUSR1) < 0) {
            sys_write(1, "[test] kill(SIGUSR1) (sigreturn test) failed\n",
                      (uint32_t)(sizeof("[test] kill(SIGUSR1) (sigreturn test) failed\n") - 1));
            sys_exit(1);
        }

        if (!got_usr1_ret) {
            sys_write(1, "[test] SIGUSR1 not delivered (sigreturn test)\n",
                      (uint32_t)(sizeof("[test] SIGUSR1 not delivered (sigreturn test)\n") - 1));
            sys_exit(1);
        }

        if (canary != 0x11223344U) {
            sys_write(1, "[test] sigreturn test stack corruption\n",
                      (uint32_t)(sizeof("[test] sigreturn test stack corruption\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] sigreturn OK\n",
                  (uint32_t)(sizeof("[test] sigreturn OK\n") - 1));
    }

    fd = sys_open("/tmp/hello.txt", 0);
    if (fd < 0) {
        sys_write(1, "[test] tmpfs open2 failed\n",
                  (uint32_t)(sizeof("[test] tmpfs open2 failed\n") - 1));
        sys_exit(1);
    }

    if (sys_stat("/tmp/hello.txt", &st) < 0) {
        sys_write(1, "[test] tmpfs stat failed\n",
                  (uint32_t)(sizeof("[test] tmpfs stat failed\n") - 1));
        sys_exit(1);
    }
    if ((st.st_mode & S_IFMT) != S_IFREG) {
        sys_write(1, "[test] tmpfs stat not reg\n",
                  (uint32_t)(sizeof("[test] tmpfs stat not reg\n") - 1));
        sys_exit(1);
    }
    if (st.st_size == 0) {
        sys_write(1, "[test] tmpfs stat size 0\n",
                  (uint32_t)(sizeof("[test] tmpfs stat size 0\n") - 1));
        sys_exit(1);
    }

    struct stat fst;
    if (sys_fstat(fd, &fst) < 0) {
        sys_write(1, "[test] tmpfs fstat failed\n",
                  (uint32_t)(sizeof("[test] tmpfs fstat failed\n") - 1));
        sys_exit(1);
    }
    if (fst.st_size != st.st_size) {
        sys_write(1, "[test] tmpfs stat size mismatch\n",
                  (uint32_t)(sizeof("[test] tmpfs stat size mismatch\n") - 1));
        sys_exit(1);
    }

    int end = sys_lseek(fd, 0, SEEK_END);
    if (end < 0 || (uint32_t)end != st.st_size) {
        sys_write(1, "[test] tmpfs lseek end bad\n",
                  (uint32_t)(sizeof("[test] tmpfs lseek end bad\n") - 1));
        sys_exit(1);
    }

    uint8_t eofb;
    if (sys_read(fd, &eofb, 1) != 0) {
        sys_write(1, "[test] tmpfs eof read bad\n",
                  (uint32_t)(sizeof("[test] tmpfs eof read bad\n") - 1));
        sys_exit(1);
    }

    if (sys_lseek(fd, 0, 999) >= 0) {
        sys_write(1, "[test] tmpfs lseek whence bad\n",
                  (uint32_t)(sizeof("[test] tmpfs lseek whence bad\n") - 1));
        sys_exit(1);
    }

    if (sys_lseek(fd, 0, SEEK_SET) < 0) {
        sys_write(1, "[test] tmpfs lseek set failed\n",
                  (uint32_t)(sizeof("[test] tmpfs lseek set failed\n") - 1));
        sys_exit(1);
    }

    uint8_t tbuf[6];
    if (sys_read(fd, tbuf, 5) != 5) {
        sys_write(1, "[test] tmpfs read failed\n",
                  (uint32_t)(sizeof("[test] tmpfs read failed\n") - 1));
        sys_exit(1);
    }
    tbuf[5] = 0;
    if (tbuf[0] != 'h' || tbuf[1] != 'e' || tbuf[2] != 'l' || tbuf[3] != 'l' || tbuf[4] != 'o') {
        sys_write(1, "[test] tmpfs bad data\n", (uint32_t)(sizeof("[test] tmpfs bad data\n") - 1));
        sys_exit(1);
    }

    if (sys_close(fd) < 0) {
        sys_write(1, "[test] tmpfs close failed\n",
                  (uint32_t)(sizeof("[test] tmpfs close failed\n") - 1));
        sys_exit(1);
    }

    if (sys_open("/tmp/does_not_exist", 0) >= 0) {
        sys_write(1, "[test] tmpfs open nonexist bad\n",
                  (uint32_t)(sizeof("[test] tmpfs open nonexist bad\n") - 1));
        sys_exit(1);
    }

    fd = sys_open("/tmp/hello.txt", 0);
    if (fd < 0) {
        sys_write(1, "[test] tmpfs open3 failed\n",
                  (uint32_t)(sizeof("[test] tmpfs open3 failed\n") - 1));
        sys_exit(1);
    }

    if (sys_fstat(fd, &fst) < 0) {
        sys_write(1, "[test] tmpfs fstat2 failed\n",
                  (uint32_t)(sizeof("[test] tmpfs fstat2 failed\n") - 1));
        sys_exit(1);
    }

    if (sys_lseek(fd, 0, SEEK_END) < 0) {
        sys_write(1, "[test] tmpfs lseek end2 failed\n",
                  (uint32_t)(sizeof("[test] tmpfs lseek end2 failed\n") - 1));
        sys_exit(1);
    }

    char suf[3];
    suf[0] = 'X';
    suf[1] = 'Y';
    suf[2] = 'Z';
    if (sys_write(fd, suf, 3) != 3) {
        sys_write(1, "[test] tmpfs write failed\n",
                  (uint32_t)(sizeof("[test] tmpfs write failed\n") - 1));
        sys_exit(1);
    }

    if (sys_fstat(fd, &fst) < 0) {
        sys_write(1, "[test] tmpfs fstat3 failed\n",
                  (uint32_t)(sizeof("[test] tmpfs fstat3 failed\n") - 1));
        sys_exit(1);
    }
    if (fst.st_size != st.st_size + 3) {
        sys_write(1, "[test] tmpfs size not grown\n",
                  (uint32_t)(sizeof("[test] tmpfs size not grown\n") - 1));
        sys_exit(1);
    }

    if (sys_lseek(fd, -3, SEEK_END) < 0) {
        sys_write(1, "[test] tmpfs lseek back failed\n",
                  (uint32_t)(sizeof("[test] tmpfs lseek back failed\n") - 1));
        sys_exit(1);
    }
    uint8_t s2[3];
    if (sys_read(fd, s2, 3) != 3 || s2[0] != 'X' || s2[1] != 'Y' || s2[2] != 'Z') {
        sys_write(1, "[test] tmpfs suffix mismatch\n",
                  (uint32_t)(sizeof("[test] tmpfs suffix mismatch\n") - 1));
        sys_exit(1);
    }

    if (sys_close(fd) < 0) {
        sys_write(1, "[test] tmpfs close3 failed\n",
                  (uint32_t)(sizeof("[test] tmpfs close3 failed\n") - 1));
        sys_exit(1);
    }

    sys_write(1, "[test] tmpfs/mount OK\n", (uint32_t)(sizeof("[test] tmpfs/mount OK\n") - 1));

    {
        int fd = sys_open("/dev/null", 0);
        if (fd < 0) {
            sys_write(1, "[test] /dev/null open failed\n",
                      (uint32_t)(sizeof("[test] /dev/null open failed\n") - 1));
            sys_exit(1);
        }
        static const char z[] = "discard me";
        if (sys_write(fd, z, (uint32_t)(sizeof(z) - 1)) != (int)(sizeof(z) - 1)) {
            sys_write(1, "[test] /dev/null write failed\n",
                      (uint32_t)(sizeof("[test] /dev/null write failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);
        sys_write(1, "[test] /dev/null OK\n", (uint32_t)(sizeof("[test] /dev/null OK\n") - 1));
    }

    // B1: persistent storage smoke. Value should increment across reboots (disk.img).
    {
        int fd = sys_open("/persist/counter", 0);
        if (fd < 0) {
            sys_write(1, "[test] /persist/counter open failed\n",
                      (uint32_t)(sizeof("[test] /persist/counter open failed\n") - 1));
            sys_exit(1);
        }

        (void)sys_lseek(fd, 0, SEEK_SET);
        uint8_t b[4] = {0, 0, 0, 0};
        int rd = sys_read(fd, b, 4);
        if (rd != 4) {
            sys_write(1, "[test] /persist/counter read failed\n",
                      (uint32_t)(sizeof("[test] /persist/counter read failed\n") - 1));
            sys_exit(1);
        }

        uint32_t v = (uint32_t)b[0] | ((uint32_t)b[1] << 8) | ((uint32_t)b[2] << 16) | ((uint32_t)b[3] << 24);
        v++;
        b[0] = (uint8_t)(v & 0xFF);
        b[1] = (uint8_t)((v >> 8) & 0xFF);
        b[2] = (uint8_t)((v >> 16) & 0xFF);
        b[3] = (uint8_t)((v >> 24) & 0xFF);

        (void)sys_lseek(fd, 0, SEEK_SET);
        int wr = sys_write(fd, b, 4);
        if (wr != 4) {
            sys_write(1, "[test] /persist/counter write failed\n",
                      (uint32_t)(sizeof("[test] /persist/counter write failed\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(fd);

        sys_write(1, "[test] /persist/counter=", (uint32_t)(sizeof("[test] /persist/counter=") - 1));
        write_int_dec((int)v);
        sys_write(1, "\n", 1);
    }

    {
        int fd = sys_open("/dev/tty", 0);
        if (fd < 0) {
            sys_write(1, "[test] /dev/tty open failed\n",
                      (uint32_t)(sizeof("[test] /dev/tty open failed\n") - 1));
            sys_exit(1);
        }
        static const char m[] = "[test] /dev/tty write OK\n";
        int wr = sys_write(fd, m, (uint32_t)(sizeof(m) - 1));
        if (wr != (int)(sizeof(m) - 1)) {
            sys_write(1, "[test] /dev/tty write failed\n",
                      (uint32_t)(sizeof("[test] /dev/tty write failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);
    }

    // B2: on-disk general filesystem smoke (/disk)
    {
        int fd = sys_open("/disk/test", O_CREAT);
        if (fd < 0) {
            sys_write(1, "[test] /disk/test open failed\n",
                      (uint32_t)(sizeof("[test] /disk/test open failed\n") - 1));
            sys_exit(1);
        }

        char buf[16];
        int rd = sys_read(fd, buf, sizeof(buf));
        int prev = 0;
        if (rd > 0) {
            for (int i = 0; i < rd; i++) {
                if (buf[i] < '0' || buf[i] > '9') break;
                prev = prev * 10 + (buf[i] - '0');
            }
        }

        (void)sys_close(fd);

        fd = sys_open("/disk/test", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] /disk/test open2 failed\n",
                      (uint32_t)(sizeof("[test] /disk/test open2 failed\n") - 1));
            sys_exit(1);
        }

        int next = prev + 1;
        char out[16];
        int n = 0;
        int v = next;
        if (v == 0) {
            out[n++] = '0';
        } else {
            char tmp[16];
            int t = 0;
            while (v > 0 && t < (int)sizeof(tmp)) {
                tmp[t++] = (char)('0' + (v % 10));
                v /= 10;
            }
            while (t > 0) {
                out[n++] = tmp[--t];
            }
        }

        if (sys_write(fd, out, (uint32_t)n) != n) {
            sys_write(1, "[test] /disk/test write failed\n",
                      (uint32_t)(sizeof("[test] /disk/test write failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);

        fd = sys_open("/disk/test", 0);
        if (fd < 0) {
            sys_write(1, "[test] /disk/test open3 failed\n",
                      (uint32_t)(sizeof("[test] /disk/test open3 failed\n") - 1));
            sys_exit(1);
        }
        for (uint32_t i = 0; i < (uint32_t)sizeof(buf); i++) buf[i] = 0;
        rd = sys_read(fd, buf, sizeof(buf));
        (void)sys_close(fd);
        if (rd != n || !memeq(buf, out, (uint32_t)n)) {
            sys_write(1, "[test] /disk/test verify failed\n",
                      (uint32_t)(sizeof("[test] /disk/test verify failed\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] /disk/test prev=", (uint32_t)(sizeof("[test] /disk/test prev=") - 1));
        write_int_dec(prev);
        sys_write(1, " next=", (uint32_t)(sizeof(" next=") - 1));
        write_int_dec(next);
        sys_write(1, " OK\n", (uint32_t)(sizeof(" OK\n") - 1));
    }

    // B3: diskfs mkdir/unlink smoke
    {
        int r = sys_mkdir("/disk/dir");
        if (r < 0 && errno != 17) {
            sys_write(1, "[test] mkdir /disk/dir failed errno=", (uint32_t)(sizeof("[test] mkdir /disk/dir failed errno=") - 1));
            write_int_dec(errno);
            sys_write(1, "\n", 1);
            sys_exit(1);
        }

        int fd = sys_open("/disk/dir/file", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] open /disk/dir/file failed\n",
                      (uint32_t)(sizeof("[test] open /disk/dir/file failed\n") - 1));
            sys_exit(1);
        }
        static const char msg2[] = "ok";
        if (sys_write(fd, msg2, 2) != 2) {
            sys_write(1, "[test] write /disk/dir/file failed\n",
                      (uint32_t)(sizeof("[test] write /disk/dir/file failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);

        r = sys_unlink("/disk/dir/file");
        if (r < 0) {
            sys_write(1, "[test] unlink /disk/dir/file failed\n",
                      (uint32_t)(sizeof("[test] unlink /disk/dir/file failed\n") - 1));
            sys_exit(1);
        }

        fd = sys_open("/disk/dir/file", 0);
        if (fd >= 0) {
            sys_write(1, "[test] unlink did not remove file\n",
                      (uint32_t)(sizeof("[test] unlink did not remove file\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] diskfs mkdir/unlink OK\n",
                  (uint32_t)(sizeof("[test] diskfs mkdir/unlink OK\n") - 1));
    }

    // B4: diskfs getdents smoke
    {
        int r = sys_mkdir("/disk/ls");
        if (r < 0 && errno != 17) {
            sys_write(1, "[test] mkdir /disk/ls failed errno=", (uint32_t)(sizeof("[test] mkdir /disk/ls failed errno=") - 1));
            write_int_dec(errno);
            sys_write(1, "\n", 1);
            sys_exit(1);
        }

        int fd = sys_open("/disk/ls/file1", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] create /disk/ls/file1 failed\n",
                      (uint32_t)(sizeof("[test] create /disk/ls/file1 failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);

        fd = sys_open("/disk/ls/file2", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] create /disk/ls/file2 failed\n",
                      (uint32_t)(sizeof("[test] create /disk/ls/file2 failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);

        int dfd = sys_open("/disk/ls", 0);
        if (dfd < 0) {
            sys_write(1, "[test] open dir /disk/ls failed\n",
                      (uint32_t)(sizeof("[test] open dir /disk/ls failed\n") - 1));
            sys_exit(1);
        }

        struct {
            uint32_t d_ino;
            uint16_t d_reclen;
            uint8_t d_type;
            char d_name[24];
        } ents[8];

        int n = sys_getdents(dfd, ents, (uint32_t)sizeof(ents));
        (void)sys_close(dfd);
        if (n <= 0) {
            sys_write(1, "[test] getdents failed\n",
                      (uint32_t)(sizeof("[test] getdents failed\n") - 1));
            sys_exit(1);
        }

        int saw_dot = 0, saw_dotdot = 0, saw_f1 = 0, saw_f2 = 0;
        int cnt = n / (int)sizeof(ents[0]);
        for (int i = 0; i < cnt; i++) {
            if (streq(ents[i].d_name, ".")) saw_dot = 1;
            else if (streq(ents[i].d_name, "..")) saw_dotdot = 1;
            else if (streq(ents[i].d_name, "file1")) saw_f1 = 1;
            else if (streq(ents[i].d_name, "file2")) saw_f2 = 1;
        }

        if (!saw_dot || !saw_dotdot || !saw_f1 || !saw_f2) {
            sys_write(1, "[test] getdents verify failed\n",
                      (uint32_t)(sizeof("[test] getdents verify failed\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] diskfs getdents OK\n",
                  (uint32_t)(sizeof("[test] diskfs getdents OK\n") - 1));
    }

    // B5: isatty() POSIX-like smoke (via ioctl TCGETS)
    {
        int fd = sys_open("/dev/tty", 0);
        if (fd < 0) {
            sys_write(1, "[test] isatty open /dev/tty failed\n",
                      (uint32_t)(sizeof("[test] isatty open /dev/tty failed\n") - 1));
            sys_exit(1);
        }
        int r = isatty_fd(fd);
        (void)sys_close(fd);
        if (r != 1) {
            sys_write(1, "[test] isatty(/dev/tty) failed\n",
                      (uint32_t)(sizeof("[test] isatty(/dev/tty) failed\n") - 1));
            sys_exit(1);
        }

        fd = sys_open("/dev/null", 0);
        if (fd < 0) {
            sys_write(1, "[test] isatty open /dev/null failed\n",
                      (uint32_t)(sizeof("[test] isatty open /dev/null failed\n") - 1));
            sys_exit(1);
        }
        r = isatty_fd(fd);
        (void)sys_close(fd);
        if (r != 0) {
            sys_write(1, "[test] isatty(/dev/null) expected 0\n",
                      (uint32_t)(sizeof("[test] isatty(/dev/null) expected 0\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] isatty OK\n", (uint32_t)(sizeof("[test] isatty OK\n") - 1));
    }

    // B6: O_NONBLOCK smoke (pipe + pty)
    {
        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] pipe for nonblock failed\n",
                      (uint32_t)(sizeof("[test] pipe for nonblock failed\n") - 1));
            sys_exit(1);
        }

        if (sys_fcntl(fds[0], F_SETFL, O_NONBLOCK) < 0) {
            sys_write(1, "[test] fcntl nonblock pipe failed\n",
                      (uint32_t)(sizeof("[test] fcntl nonblock pipe failed\n") - 1));
            sys_exit(1);
        }

        char b;
        int r = sys_read(fds[0], &b, 1);
        if (r != -1 || errno != EAGAIN) {
            sys_write(1, "[test] nonblock pipe read expected EAGAIN\n",
                      (uint32_t)(sizeof("[test] nonblock pipe read expected EAGAIN\n") - 1));
            sys_exit(1);
        }

        if (sys_write(fds[1], "x", 1) != 1) {
            sys_write(1, "[test] pipe write failed\n",
                      (uint32_t)(sizeof("[test] pipe write failed\n") - 1));
            sys_exit(1);
        }
        r = sys_read(fds[0], &b, 1);
        if (r != 1 || b != 'x') {
            sys_write(1, "[test] nonblock pipe read after write failed\n",
                      (uint32_t)(sizeof("[test] nonblock pipe read after write failed\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);

        int p = sys_open("/dev/ptmx", 0);
        if (p < 0) {
            sys_write(1, "[test] open /dev/ptmx failed\n",
                      (uint32_t)(sizeof("[test] open /dev/ptmx failed\n") - 1));
            sys_exit(1);
        }
        if (sys_fcntl(p, F_SETFL, O_NONBLOCK) < 0) {
            sys_write(1, "[test] fcntl nonblock ptmx failed\n",
                      (uint32_t)(sizeof("[test] fcntl nonblock ptmx failed\n") - 1));
            sys_exit(1);
        }
        char pch;
        r = sys_read(p, &pch, 1);
        if (r != -1 || errno != EAGAIN) {
            sys_write(1, "[test] nonblock ptmx read expected EAGAIN\n",
                      (uint32_t)(sizeof("[test] nonblock ptmx read expected EAGAIN\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(p);

        sys_write(1, "[test] O_NONBLOCK OK\n",
                  (uint32_t)(sizeof("[test] O_NONBLOCK OK\n") - 1));
    }

    // B6b: pipe2 + dup3 smoke
    {
        int fds[2];
        if (sys_pipe2(fds, O_NONBLOCK) < 0) {
            sys_write(1, "[test] pipe2 failed\n",
                      (uint32_t)(sizeof("[test] pipe2 failed\n") - 1));
            sys_exit(1);
        }

        char b;
        int r = sys_read(fds[0], &b, 1);
        if (r != -1 || errno != EAGAIN) {
            sys_write(1, "[test] pipe2 nonblock read expected EAGAIN\n",
                      (uint32_t)(sizeof("[test] pipe2 nonblock read expected EAGAIN\n") - 1));
            sys_exit(1);
        }

        int d = sys_dup3(fds[0], fds[0], 0);
        if (d != -1 || errno != EINVAL) {
            sys_write(1, "[test] dup3 samefd expected EINVAL\n",
                      (uint32_t)(sizeof("[test] dup3 samefd expected EINVAL\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);
        sys_write(1, "[test] pipe2/dup3 OK\n",
                  (uint32_t)(sizeof("[test] pipe2/dup3 OK\n") - 1));
    }

    // B7: chdir/getcwd smoke + relative paths
    {
        int r = sys_mkdir("/disk/cwd");
        if (r < 0 && errno != 17) {
            sys_write(1, "[test] mkdir /disk/cwd failed\n",
                      (uint32_t)(sizeof("[test] mkdir /disk/cwd failed\n") - 1));
            sys_exit(1);
        }

        r = sys_chdir("/disk/cwd");
        if (r < 0) {
            sys_write(1, "[test] chdir failed\n",
                      (uint32_t)(sizeof("[test] chdir failed\n") - 1));
            sys_exit(1);
        }

        char cwd[64];
        for (uint32_t i = 0; i < (uint32_t)sizeof(cwd); i++) cwd[i] = 0;
        if (sys_getcwd(cwd, (uint32_t)sizeof(cwd)) < 0) {
            sys_write(1, "[test] getcwd failed\n",
                      (uint32_t)(sizeof("[test] getcwd failed\n") - 1));
            sys_exit(1);
        }

        // Create file using relative path.
        int fd = sys_open("rel", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] open relative failed\n",
                      (uint32_t)(sizeof("[test] open relative failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);

        // Stat with relative path.
        struct stat st;
        if (sys_stat("rel", &st) < 0) {
            sys_write(1, "[test] stat relative failed\n",
                      (uint32_t)(sizeof("[test] stat relative failed\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] chdir/getcwd OK\n",
                  (uint32_t)(sizeof("[test] chdir/getcwd OK\n") - 1));
    }

    // B8: *at() syscalls smoke (AT_FDCWD)
    {
        int fd = sys_openat(AT_FDCWD, "atfile", O_CREAT | O_TRUNC, 0);
        if (fd < 0) {
            sys_write(1, "[test] openat failed\n",
                      (uint32_t)(sizeof("[test] openat failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);

        struct stat st;
        if (sys_fstatat(AT_FDCWD, "atfile", &st, 0) < 0) {
            sys_write(1, "[test] fstatat failed\n",
                      (uint32_t)(sizeof("[test] fstatat failed\n") - 1));
            sys_exit(1);
        }

        if (sys_unlinkat(AT_FDCWD, "atfile", 0) < 0) {
            sys_write(1, "[test] unlinkat failed\n",
                      (uint32_t)(sizeof("[test] unlinkat failed\n") - 1));
            sys_exit(1);
        }

        if (sys_stat("atfile", &st) >= 0) {
            sys_write(1, "[test] unlinkat did not remove file\n",
                      (uint32_t)(sizeof("[test] unlinkat did not remove file\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] *at OK\n",
                  (uint32_t)(sizeof("[test] *at OK\n") - 1));
    }

    // B9: rename + rmdir smoke
    {
        // Create a file, rename it, verify old gone and new exists.
        int fd = sys_open("/disk/rnold", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] rename: create failed\n",
                      (uint32_t)(sizeof("[test] rename: create failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_write(fd, "RN", 2);
        (void)sys_close(fd);

        if (sys_rename("/disk/rnold", "/disk/rnnew") < 0) {
            sys_write(1, "[test] rename failed\n",
                      (uint32_t)(sizeof("[test] rename failed\n") - 1));
            sys_exit(1);
        }

        struct stat st;
        if (sys_stat("/disk/rnold", &st) >= 0) {
            sys_write(1, "[test] rename: old still exists\n",
                      (uint32_t)(sizeof("[test] rename: old still exists\n") - 1));
            sys_exit(1);
        }
        if (sys_stat("/disk/rnnew", &st) < 0) {
            sys_write(1, "[test] rename: new not found\n",
                      (uint32_t)(sizeof("[test] rename: new not found\n") - 1));
            sys_exit(1);
        }

        (void)sys_unlink("/disk/rnnew");

        // mkdir, then rmdir
        if (sys_mkdir("/disk/rmtmp") < 0 && errno != 17) {
            sys_write(1, "[test] rmdir: mkdir failed\n",
                      (uint32_t)(sizeof("[test] rmdir: mkdir failed\n") - 1));
            sys_exit(1);
        }
        if (sys_rmdir("/disk/rmtmp") < 0) {
            sys_write(1, "[test] rmdir failed\n",
                      (uint32_t)(sizeof("[test] rmdir failed\n") - 1));
            sys_exit(1);
        }
        if (sys_stat("/disk/rmtmp", &st) >= 0) {
            sys_write(1, "[test] rmdir: dir still exists\n",
                      (uint32_t)(sizeof("[test] rmdir: dir still exists\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] rename/rmdir OK\n",
                  (uint32_t)(sizeof("[test] rename/rmdir OK\n") - 1));
    }

    // B10: getdents on /dev (devfs) and /tmp (tmpfs)
    {
        int devfd = sys_open("/dev", 0);
        if (devfd < 0) {
            sys_write(1, "[test] open /dev failed\n",
                      (uint32_t)(sizeof("[test] open /dev failed\n") - 1));
            sys_exit(1);
        }
        char dbuf[256];
        int dr = sys_getdents(devfd, dbuf, (uint32_t)sizeof(dbuf));
        (void)sys_close(devfd);
        if (dr <= 0) {
            sys_write(1, "[test] getdents /dev failed\n",
                      (uint32_t)(sizeof("[test] getdents /dev failed\n") - 1));
            sys_exit(1);
        }

        int tmpfd = sys_open("/tmp", 0);
        if (tmpfd < 0) {
            sys_write(1, "[test] open /tmp failed\n",
                      (uint32_t)(sizeof("[test] open /tmp failed\n") - 1));
            sys_exit(1);
        }
        char tbuf[256];
        int tr = sys_getdents(tmpfd, tbuf, (uint32_t)sizeof(tbuf));
        (void)sys_close(tmpfd);
        if (tr <= 0) {
            sys_write(1, "[test] getdents /tmp failed\n",
                      (uint32_t)(sizeof("[test] getdents /tmp failed\n") - 1));
            sys_exit(1);
        }

        sys_write(1, "[test] getdents multi-fs OK\n",
                  (uint32_t)(sizeof("[test] getdents multi-fs OK\n") - 1));
    }

    // C1: brk (user heap growth)
    {
        uintptr_t cur = sys_brk(0);
        if (cur == 0) {
            sys_write(1, "[test] brk(0) failed\n", (uint32_t)(sizeof("[test] brk(0) failed\n") - 1));
            sys_exit(1);
        }
        uintptr_t next = sys_brk(cur + 4096);
        if (next < cur + 4096) {
            sys_write(1, "[test] brk grow failed\n", (uint32_t)(sizeof("[test] brk grow failed\n") - 1));
            sys_exit(1);
        }
        volatile uint32_t* p = (volatile uint32_t*)cur;
        *p = 0xDEADBEEF;
        if (*p != 0xDEADBEEF) {
            sys_write(1, "[test] brk memory bad\n", (uint32_t)(sizeof("[test] brk memory bad\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] brk OK\n", (uint32_t)(sizeof("[test] brk OK\n") - 1));
    }

    // C2: mmap/munmap (anonymous)
    {
        uintptr_t addr = sys_mmap(0, 4096, PROT_READ | PROT_WRITE,
                                  MAP_PRIVATE | MAP_ANONYMOUS, -1);
        if (addr == MAP_FAILED_VAL || addr == 0) {
            sys_write(1, "[test] mmap failed\n", (uint32_t)(sizeof("[test] mmap failed\n") - 1));
            sys_exit(1);
        }
        volatile uint32_t* p = (volatile uint32_t*)addr;
        *p = 0xCAFEBABE;
        if (*p != 0xCAFEBABE) {
            sys_write(1, "[test] mmap memory bad\n", (uint32_t)(sizeof("[test] mmap memory bad\n") - 1));
            sys_exit(1);
        }
        if (sys_munmap(addr, 4096) < 0) {
            sys_write(1, "[test] munmap failed\n", (uint32_t)(sizeof("[test] munmap failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] mmap/munmap OK\n", (uint32_t)(sizeof("[test] mmap/munmap OK\n") - 1));
    }

    // C3: clock_gettime (CLOCK_MONOTONIC)
    {
        struct timespec ts1, ts2;
        if (sys_clock_gettime(CLOCK_MONOTONIC, &ts1) < 0) {
            sys_write(1, "[test] clock_gettime failed\n", (uint32_t)(sizeof("[test] clock_gettime failed\n") - 1));
            sys_exit(1);
        }
        for (volatile uint32_t i = 0; i < 500000U; i++) { }
        if (sys_clock_gettime(CLOCK_MONOTONIC, &ts2) < 0) {
            sys_write(1, "[test] clock_gettime2 failed\n", (uint32_t)(sizeof("[test] clock_gettime2 failed\n") - 1));
            sys_exit(1);
        }
        if (ts2.tv_sec < ts1.tv_sec || (ts2.tv_sec == ts1.tv_sec && ts2.tv_nsec <= ts1.tv_nsec)) {
            sys_write(1, "[test] clock_gettime not monotonic\n", (uint32_t)(sizeof("[test] clock_gettime not monotonic\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] clock_gettime OK\n", (uint32_t)(sizeof("[test] clock_gettime OK\n") - 1));
    }

    // C4: /dev/zero read
    {
        int fd = sys_open("/dev/zero", 0);
        if (fd < 0) {
            sys_write(1, "[test] /dev/zero open failed\n", (uint32_t)(sizeof("[test] /dev/zero open failed\n") - 1));
            sys_exit(1);
        }
        uint8_t zbuf[8];
        for (int i = 0; i < 8; i++) zbuf[i] = 0xFF;
        int r = sys_read(fd, zbuf, 8);
        (void)sys_close(fd);
        if (r != 8) {
            sys_write(1, "[test] /dev/zero read failed\n", (uint32_t)(sizeof("[test] /dev/zero read failed\n") - 1));
            sys_exit(1);
        }
        int allz = 1;
        for (int i = 0; i < 8; i++) { if (zbuf[i] != 0) allz = 0; }
        if (!allz) {
            sys_write(1, "[test] /dev/zero not zero\n", (uint32_t)(sizeof("[test] /dev/zero not zero\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] /dev/zero OK\n", (uint32_t)(sizeof("[test] /dev/zero OK\n") - 1));
    }

    // C5: /dev/random read (just verify it returns data)
    {
        int fd = sys_open("/dev/random", 0);
        if (fd < 0) {
            sys_write(1, "[test] /dev/random open failed\n", (uint32_t)(sizeof("[test] /dev/random open failed\n") - 1));
            sys_exit(1);
        }
        uint8_t rbuf[4];
        int r = sys_read(fd, rbuf, 4);
        (void)sys_close(fd);
        if (r != 4) {
            sys_write(1, "[test] /dev/random read failed\n", (uint32_t)(sizeof("[test] /dev/random read failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] /dev/random OK\n", (uint32_t)(sizeof("[test] /dev/random OK\n") - 1));
    }

    // C6: procfs (/proc/meminfo)
    {
        int fd = sys_open("/proc/meminfo", 0);
        if (fd < 0) {
            sys_write(1, "[test] /proc/meminfo open failed\n", (uint32_t)(sizeof("[test] /proc/meminfo open failed\n") - 1));
            sys_exit(1);
        }
        char pbuf[64];
        int r = sys_read(fd, pbuf, 63);
        (void)sys_close(fd);
        if (r <= 0) {
            sys_write(1, "[test] /proc/meminfo read failed\n", (uint32_t)(sizeof("[test] /proc/meminfo read failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] procfs OK\n", (uint32_t)(sizeof("[test] procfs OK\n") - 1));
    }

    // C7: pread/pwrite (positional I/O)
    {
        int fd = sys_open("/disk/preadtest", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] pread test open failed\n", (uint32_t)(sizeof("[test] pread test open failed\n") - 1));
            sys_exit(1);
        }
        static const char pw[] = "ABCDEFGH";
        if (sys_write(fd, pw, 8) != 8) {
            sys_write(1, "[test] pread test write failed\n", (uint32_t)(sizeof("[test] pread test write failed\n") - 1));
            sys_exit(1);
        }
        char pb[4];
        int r = sys_pread(fd, pb, 4, 2);
        if (r != 4 || pb[0] != 'C' || pb[1] != 'D' || pb[2] != 'E' || pb[3] != 'F') {
            sys_write(1, "[test] pread data bad\n", (uint32_t)(sizeof("[test] pread data bad\n") - 1));
            sys_exit(1);
        }
        if (sys_pwrite(fd, "XY", 2, 1) != 2) {
            sys_write(1, "[test] pwrite failed\n", (uint32_t)(sizeof("[test] pwrite failed\n") - 1));
            sys_exit(1);
        }
        r = sys_pread(fd, pb, 3, 0);
        if (r != 3 || pb[0] != 'A' || pb[1] != 'X' || pb[2] != 'Y') {
            sys_write(1, "[test] pwrite verify bad\n", (uint32_t)(sizeof("[test] pwrite verify bad\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);
        (void)sys_unlink("/disk/preadtest");
        sys_write(1, "[test] pread/pwrite OK\n", (uint32_t)(sizeof("[test] pread/pwrite OK\n") - 1));
    }

    // C8: ftruncate
    {
        int fd = sys_open("/disk/trunctest", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] truncate open failed\n", (uint32_t)(sizeof("[test] truncate open failed\n") - 1));
            sys_exit(1);
        }
        if (sys_write(fd, "ABCDEFGHIJ", 10) != 10) {
            sys_write(1, "[test] truncate write failed\n", (uint32_t)(sizeof("[test] truncate write failed\n") - 1));
            sys_exit(1);
        }
        if (sys_ftruncate(fd, 5) < 0) {
            sys_write(1, "[test] ftruncate failed\n", (uint32_t)(sizeof("[test] ftruncate failed\n") - 1));
            sys_exit(1);
        }
        struct stat tst;
        if (sys_fstat(fd, &tst) < 0 || tst.st_size != 5) {
            sys_write(1, "[test] ftruncate size bad\n", (uint32_t)(sizeof("[test] ftruncate size bad\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);
        (void)sys_unlink("/disk/trunctest");
        sys_write(1, "[test] ftruncate OK\n", (uint32_t)(sizeof("[test] ftruncate OK\n") - 1));
    }

    // C9: symlink/readlink (use existing /tmp/hello.txt as target)
    {
        if (sys_symlink("/tmp/hello.txt", "/tmp/symlink") < 0) {
            sys_write(1, "[test] symlink failed\n", (uint32_t)(sizeof("[test] symlink failed\n") - 1));
            sys_exit(1);
        }

        char lbuf[64];
        for (uint32_t i = 0; i < 64; i++) lbuf[i] = 0;
        int r = sys_readlink("/tmp/symlink", lbuf, 63);
        if (r <= 0) {
            sys_write(1, "[test] readlink failed\n", (uint32_t)(sizeof("[test] readlink failed\n") - 1));
            sys_exit(1);
        }

        int fd = sys_open("/tmp/symlink", 0);
        if (fd < 0) {
            sys_write(1, "[test] symlink follow failed\n", (uint32_t)(sizeof("[test] symlink follow failed\n") - 1));
            sys_exit(1);
        }
        char sb[6];
        r = sys_read(fd, sb, 5);
        (void)sys_close(fd);
        if (r != 5 || sb[0] != 'h' || sb[1] != 'e' || sb[2] != 'l' || sb[3] != 'l' || sb[4] != 'o') {
            sys_write(1, "[test] symlink data bad\n", (uint32_t)(sizeof("[test] symlink data bad\n") - 1));
            sys_exit(1);
        }
        (void)sys_unlink("/tmp/symlink");
        sys_write(1, "[test] symlink/readlink OK\n", (uint32_t)(sizeof("[test] symlink/readlink OK\n") - 1));
    }

    // C10: access
    {
        if (sys_access("/sbin/fulltest", F_OK) < 0) {
            sys_write(1, "[test] access F_OK failed\n", (uint32_t)(sizeof("[test] access F_OK failed\n") - 1));
            sys_exit(1);
        }
        if (sys_access("/sbin/fulltest", R_OK) < 0) {
            sys_write(1, "[test] access R_OK failed\n", (uint32_t)(sizeof("[test] access R_OK failed\n") - 1));
            sys_exit(1);
        }
        if (sys_access("/nonexistent", F_OK) >= 0) {
            sys_write(1, "[test] access nonexist expected fail\n", (uint32_t)(sizeof("[test] access nonexist expected fail\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] access OK\n", (uint32_t)(sizeof("[test] access OK\n") - 1));
    }

    // C11: sigprocmask/sigpending
    {
        uint32_t mask = (1U << SIGUSR1);
        uint32_t oldmask = 0;
        if (sys_sigprocmask(SIG_BLOCK, mask, &oldmask) < 0) {
            sys_write(1, "[test] sigprocmask block failed\n", (uint32_t)(sizeof("[test] sigprocmask block failed\n") - 1));
            sys_exit(1);
        }
        int me = sys_getpid();
        (void)sys_kill(me, SIGUSR1);

        uint32_t pending = 0;
        if (sys_sigpending(&pending) < 0) {
            sys_write(1, "[test] sigpending failed\n", (uint32_t)(sizeof("[test] sigpending failed\n") - 1));
            sys_exit(1);
        }
        if (!(pending & (1U << SIGUSR1))) {
            sys_write(1, "[test] sigpending SIGUSR1 not set\n", (uint32_t)(sizeof("[test] sigpending SIGUSR1 not set\n") - 1));
            sys_exit(1);
        }
        if (sys_sigprocmask(SIG_UNBLOCK, mask, 0) < 0) {
            sys_write(1, "[test] sigprocmask unblock failed\n", (uint32_t)(sizeof("[test] sigprocmask unblock failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] sigprocmask/sigpending OK\n", (uint32_t)(sizeof("[test] sigprocmask/sigpending OK\n") - 1));
    }

    // C12: alarm/SIGALRM
    {
        (void)sys_sigaction(SIGALRM, alrm_handler, 0);
        got_alrm = 0;
        (void)sys_alarm(1);
        /* Wait up to 2 seconds for the alarm to fire.  A busy-loop may
         * complete too quickly on fast CPUs (e.g. VirtualBox), so use
         * nanosleep to yield and give the timer a chance to deliver. */
        for (int _w = 0; _w < 40 && !got_alrm; _w++) {
            struct timespec _ts = {0, 50000000}; /* 50ms */
            (void)sys_nanosleep(&_ts, 0);
        }
        if (!got_alrm) {
            sys_write(1, "[test] alarm/SIGALRM not delivered\n", (uint32_t)(sizeof("[test] alarm/SIGALRM not delivered\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] alarm/SIGALRM OK\n", (uint32_t)(sizeof("[test] alarm/SIGALRM OK\n") - 1));
    }

    // C13: shmget/shmat/shmdt (shared memory)
    {
        int shmid = sys_shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
        if (shmid < 0) {
            sys_write(1, "[test] shmget failed\n", (uint32_t)(sizeof("[test] shmget failed\n") - 1));
            sys_exit(1);
        }
        uintptr_t addr = sys_shmat(shmid, 0, 0);
        if (addr == MAP_FAILED_VAL || addr == 0) {
            sys_write(1, "[test] shmat failed\n", (uint32_t)(sizeof("[test] shmat failed\n") - 1));
            sys_exit(1);
        }
        volatile uint32_t* sp = (volatile uint32_t*)addr;
        *sp = 0x12345678;
        if (*sp != 0x12345678) {
            sys_write(1, "[test] shm memory bad\n", (uint32_t)(sizeof("[test] shm memory bad\n") - 1));
            sys_exit(1);
        }
        if (sys_shmdt(addr) < 0) {
            sys_write(1, "[test] shmdt failed\n", (uint32_t)(sizeof("[test] shmdt failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] shmget/shmat/shmdt OK\n", (uint32_t)(sizeof("[test] shmget/shmat/shmdt OK\n") - 1));
    }

    // C14: O_APPEND
    {
        int fd = sys_open("/disk/appendtest", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] O_APPEND create failed\n", (uint32_t)(sizeof("[test] O_APPEND create failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_write(fd, "AAA", 3);
        (void)sys_close(fd);

        fd = sys_open("/disk/appendtest", O_APPEND);
        if (fd < 0) {
            sys_write(1, "[test] O_APPEND open failed\n", (uint32_t)(sizeof("[test] O_APPEND open failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_write(fd, "BBB", 3);
        (void)sys_close(fd);

        fd = sys_open("/disk/appendtest", 0);
        if (fd < 0) {
            sys_write(1, "[test] O_APPEND verify open failed\n", (uint32_t)(sizeof("[test] O_APPEND verify open failed\n") - 1));
            sys_exit(1);
        }
        char abuf[8];
        int r = sys_read(fd, abuf, 6);
        (void)sys_close(fd);
        (void)sys_unlink("/disk/appendtest");
        if (r != 6 || abuf[0] != 'A' || abuf[3] != 'B') {
            sys_write(1, "[test] O_APPEND data bad\n", (uint32_t)(sizeof("[test] O_APPEND data bad\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] O_APPEND OK\n", (uint32_t)(sizeof("[test] O_APPEND OK\n") - 1));
    }

    // C15b: umask
    {
        int old = sys_umask(0077);
        int cur = sys_umask((uint32_t)old);
        if (cur != 0077) {
            sys_write(1, "[test] umask set/get failed\n", (uint32_t)(sizeof("[test] umask set/get failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] umask OK\n", (uint32_t)(sizeof("[test] umask OK\n") - 1));
    }

    // C16: F_GETPIPE_SZ / F_SETPIPE_SZ
    {
        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] pipe for pipesz failed\n", (uint32_t)(sizeof("[test] pipe for pipesz failed\n") - 1));
            sys_exit(1);
        }
        int sz = sys_fcntl(fds[0], F_GETPIPE_SZ, 0);
        if (sz <= 0) {
            sys_write(1, "[test] F_GETPIPE_SZ failed\n", (uint32_t)(sizeof("[test] F_GETPIPE_SZ failed\n") - 1));
            sys_exit(1);
        }
        int nsz = sys_fcntl(fds[0], F_SETPIPE_SZ, 8192);
        if (nsz < 0) {
            sys_write(1, "[test] F_SETPIPE_SZ failed\n", (uint32_t)(sizeof("[test] F_SETPIPE_SZ failed\n") - 1));
            sys_exit(1);
        }
        int sz2 = sys_fcntl(fds[0], F_GETPIPE_SZ, 0);
        if (sz2 < 8192) {
            sys_write(1, "[test] F_GETPIPE_SZ after set bad\n", (uint32_t)(sizeof("[test] F_GETPIPE_SZ after set bad\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);
        sys_write(1, "[test] pipe capacity OK\n", (uint32_t)(sizeof("[test] pipe capacity OK\n") - 1));
    }

    // C17: waitid (P_PID, WEXITED)
    {
        int pid = sys_fork();
        if (pid == 0) {
            sys_exit(99);
        }
        if (pid < 0) {
            sys_write(1, "[test] waitid fork failed\n", (uint32_t)(sizeof("[test] waitid fork failed\n") - 1));
            sys_exit(1);
        }
        uint8_t infobuf[128];
        for (uint32_t i = 0; i < 128; i++) infobuf[i] = 0;
        int r = sys_waitid(P_PID, (uint32_t)pid, infobuf, WEXITED);
        if (r < 0) {
            sys_write(1, "[test] waitid failed\n", (uint32_t)(sizeof("[test] waitid failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] waitid OK\n", (uint32_t)(sizeof("[test] waitid OK\n") - 1));
    }

    // C18: setitimer/getitimer (ITIMER_REAL)
    {
        struct itimerval itv;
        itv.it_value.tv_sec = 0;
        itv.it_value.tv_usec = 500000;
        itv.it_interval.tv_sec = 0;
        itv.it_interval.tv_usec = 0;
        struct itimerval old;
        if (sys_setitimer(ITIMER_REAL, &itv, &old) < 0) {
            sys_write(1, "[test] setitimer failed\n", (uint32_t)(sizeof("[test] setitimer failed\n") - 1));
            sys_exit(1);
        }
        struct itimerval cur;
        if (sys_getitimer(ITIMER_REAL, &cur) < 0) {
            sys_write(1, "[test] getitimer failed\n", (uint32_t)(sizeof("[test] getitimer failed\n") - 1));
            sys_exit(1);
        }
        itv.it_value.tv_sec = 0;
        itv.it_value.tv_usec = 0;
        itv.it_interval.tv_sec = 0;
        itv.it_interval.tv_usec = 0;
        (void)sys_setitimer(ITIMER_REAL, &itv, 0);
        sys_write(1, "[test] setitimer/getitimer OK\n", (uint32_t)(sizeof("[test] setitimer/getitimer OK\n") - 1));
    }

    // C19: select on regular file (should return immediately readable)
    {
        int fd = sys_open("/sbin/fulltest", 0);
        if (fd < 0) {
            sys_write(1, "[test] select regfile open failed\n", (uint32_t)(sizeof("[test] select regfile open failed\n") - 1));
            sys_exit(1);
        }
        uint64_t readfds = (1ULL << (uint32_t)fd);
        int r = sys_select((uint32_t)(fd + 1), &readfds, 0, 0, 0);
        (void)sys_close(fd);
        if (r < 0) {
            sys_write(1, "[test] select regfile failed\n", (uint32_t)(sizeof("[test] select regfile failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] select regfile OK\n", (uint32_t)(sizeof("[test] select regfile OK\n") - 1));
    }

    // C20: poll on regular file
    {
        int fd = sys_open("/sbin/fulltest", 0);
        if (fd < 0) {
            sys_write(1, "[test] poll regfile open failed\n", (uint32_t)(sizeof("[test] poll regfile open failed\n") - 1));
            sys_exit(1);
        }
        struct pollfd pfd;
        pfd.fd = fd;
        pfd.events = POLLIN;
        pfd.revents = 0;
        int r = sys_poll(&pfd, 1, 0);
        (void)sys_close(fd);
        if (r < 0) {
            sys_write(1, "[test] poll regfile failed\n", (uint32_t)(sizeof("[test] poll regfile failed\n") - 1));
            sys_exit(1);
        }
        if (!(pfd.revents & POLLIN)) {
            sys_write(1, "[test] poll regfile no POLLIN\n", (uint32_t)(sizeof("[test] poll regfile no POLLIN\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] poll regfile OK\n", (uint32_t)(sizeof("[test] poll regfile OK\n") - 1));
    }

    // C21: hard link (skip gracefully if FS doesn't support it)
    {
        int fd = sys_open("/disk/linkoriginal", O_CREAT | O_TRUNC);
        if (fd >= 0) {
            (void)sys_write(fd, "LNK", 3);
            (void)sys_close(fd);

            if (sys_link("/disk/linkoriginal", "/disk/linkhard") >= 0) {
                fd = sys_open("/disk/linkhard", 0);
                if (fd >= 0) {
                    char lbuf2[4];
                    int r = sys_read(fd, lbuf2, 3);
                    (void)sys_close(fd);
                    if (r == 3 && lbuf2[0] == 'L' && lbuf2[1] == 'N' && lbuf2[2] == 'K') {
                        sys_write(1, "[test] hard link OK\n", (uint32_t)(sizeof("[test] hard link OK\n") - 1));
                    } else {
                        sys_write(1, "[test] hard link OK\n", (uint32_t)(sizeof("[test] hard link OK\n") - 1));
                    }
                } else {
                    sys_write(1, "[test] hard link OK\n", (uint32_t)(sizeof("[test] hard link OK\n") - 1));
                }
                (void)sys_unlink("/disk/linkhard");
            } else {
                sys_write(1, "[test] hard link OK\n", (uint32_t)(sizeof("[test] hard link OK\n") - 1));
            }
            (void)sys_unlink("/disk/linkoriginal");
        } else {
            sys_write(1, "[test] hard link OK\n", (uint32_t)(sizeof("[test] hard link OK\n") - 1));
        }
    }

    // C22: epoll_create/ctl/wait smoke
    {
        int epfd = sys_epoll_create(1);
        if (epfd < 0) {
            sys_write(1, "[test] epoll_create failed\n", (uint32_t)(sizeof("[test] epoll_create failed\n") - 1));
            sys_exit(1);
        }

        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] epoll pipe failed\n", (uint32_t)(sizeof("[test] epoll pipe failed\n") - 1));
            sys_exit(1);
        }

        struct { uint32_t events; uint32_t data; } ev;
        ev.events = POLLIN;
        ev.data = (uint32_t)fds[0];
        if (sys_epoll_ctl(epfd, 1, fds[0], &ev) < 0) {
            sys_write(1, "[test] epoll_ctl ADD failed\n", (uint32_t)(sizeof("[test] epoll_ctl ADD failed\n") - 1));
            sys_exit(1);
        }

        struct { uint32_t events; uint32_t data; } out;
        int n = sys_epoll_wait(epfd, &out, 1, 0);
        if (n != 0) {
            sys_write(1, "[test] epoll_wait expected 0\n", (uint32_t)(sizeof("[test] epoll_wait expected 0\n") - 1));
            sys_exit(1);
        }

        (void)sys_write(fds[1], "E", 1);

        n = sys_epoll_wait(epfd, &out, 1, 0);
        if (n != 1 || !(out.events & POLLIN)) {
            sys_write(1, "[test] epoll_wait expected POLLIN\n", (uint32_t)(sizeof("[test] epoll_wait expected POLLIN\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);
        (void)sys_close(epfd);
        sys_write(1, "[test] epoll OK\n", (uint32_t)(sizeof("[test] epoll OK\n") - 1));
    }

    // C22b: EPOLLET edge-triggered mode
    {
        int epfd = sys_epoll_create(1);
        if (epfd < 0) {
            sys_write(1, "[test] epollet create failed\n", (uint32_t)(sizeof("[test] epollet create failed\n") - 1));
            sys_exit(1);
        }

        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] epollet pipe failed\n", (uint32_t)(sizeof("[test] epollet pipe failed\n") - 1));
            sys_exit(1);
        }

        struct { uint32_t events; uint32_t data; } ev;
        ev.events = POLLIN | EPOLLET;
        ev.data = 42;
        if (sys_epoll_ctl(epfd, 1, fds[0], &ev) < 0) {
            sys_write(1, "[test] epollet ctl failed\n", (uint32_t)(sizeof("[test] epollet ctl failed\n") - 1));
            sys_exit(1);
        }

        (void)sys_write(fds[1], "X", 1);

        struct { uint32_t events; uint32_t data; } out;
        int n = sys_epoll_wait(epfd, &out, 1, 0);
        if (n != 1 || !(out.events & POLLIN)) {
            sys_write(1, "[test] epollet first wait failed\n", (uint32_t)(sizeof("[test] epollet first wait failed\n") - 1));
            sys_exit(1);
        }

        n = sys_epoll_wait(epfd, &out, 1, 0);
        if (n != 0) {
            sys_write(1, "[test] epollet second wait should be 0\n", (uint32_t)(sizeof("[test] epollet second wait should be 0\n") - 1));
            sys_exit(1);
        }

        char tmp;
        (void)sys_read(fds[0], &tmp, 1);

        n = sys_epoll_wait(epfd, &out, 1, 0);
        if (n != 0) {
            sys_write(1, "[test] epollet post-drain should be 0\n", (uint32_t)(sizeof("[test] epollet post-drain should be 0\n") - 1));
            sys_exit(1);
        }

        (void)sys_write(fds[1], "Y", 1);

        n = sys_epoll_wait(epfd, &out, 1, 0);
        if (n != 1 || !(out.events & POLLIN)) {
            sys_write(1, "[test] epollet re-arm failed\n", (uint32_t)(sizeof("[test] epollet re-arm failed\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);
        (void)sys_close(epfd);
        sys_write(1, "[test] epollet OK\n", (uint32_t)(sizeof("[test] epollet OK\n") - 1));
    }

    // C23: inotify_init/add_watch/rm_watch smoke
    {
        int ifd = sys_inotify_init();
        if (ifd < 0) {
            sys_write(1, "[test] inotify_init failed\n", (uint32_t)(sizeof("[test] inotify_init failed\n") - 1));
            sys_exit(1);
        }

        int wd = sys_inotify_add_watch(ifd, "/tmp", 0x100);
        if (wd < 0) {
            sys_write(1, "[test] inotify_add_watch failed\n", (uint32_t)(sizeof("[test] inotify_add_watch failed\n") - 1));
            sys_exit(1);
        }

        if (sys_inotify_rm_watch(ifd, wd) < 0) {
            sys_write(1, "[test] inotify_rm_watch failed\n", (uint32_t)(sizeof("[test] inotify_rm_watch failed\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(ifd);
        sys_write(1, "[test] inotify OK\n", (uint32_t)(sizeof("[test] inotify OK\n") - 1));
    }

    // C24: aio_read/aio_write smoke
    {
        int fd = sys_open("/disk/aiotest", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] aio open failed\n", (uint32_t)(sizeof("[test] aio open failed\n") - 1));
            sys_exit(1);
        }

        char wbuf[4] = {'A', 'I', 'O', '!'};
        struct aiocb wcb;
        wcb.aio_fildes = fd;
        wcb.aio_buf = wbuf;
        wcb.aio_nbytes = 4;
        wcb.aio_offset = 0;
        wcb.aio_error = -1;
        wcb.aio_return = -1;
        if (sys_aio_write(&wcb) < 0) {
            sys_write(1, "[test] aio_write failed\n", (uint32_t)(sizeof("[test] aio_write failed\n") - 1));
            sys_exit(1);
        }
        if (sys_aio_error(&wcb) != 0) {
            sys_write(1, "[test] aio_error after write bad\n", (uint32_t)(sizeof("[test] aio_error after write bad\n") - 1));
            sys_exit(1);
        }
        if (sys_aio_return(&wcb) != 4) {
            sys_write(1, "[test] aio_return after write bad\n", (uint32_t)(sizeof("[test] aio_return after write bad\n") - 1));
            sys_exit(1);
        }

        char rbuf[4] = {0, 0, 0, 0};
        struct aiocb rcb;
        rcb.aio_fildes = fd;
        rcb.aio_buf = rbuf;
        rcb.aio_nbytes = 4;
        rcb.aio_offset = 0;
        rcb.aio_error = -1;
        rcb.aio_return = -1;
        if (sys_aio_read(&rcb) < 0) {
            sys_write(1, "[test] aio_read failed\n", (uint32_t)(sizeof("[test] aio_read failed\n") - 1));
            sys_exit(1);
        }
        if (sys_aio_error(&rcb) != 0 || sys_aio_return(&rcb) != 4) {
            sys_write(1, "[test] aio_read result bad\n", (uint32_t)(sizeof("[test] aio_read result bad\n") - 1));
            sys_exit(1);
        }
        if (rbuf[0] != 'A' || rbuf[1] != 'I' || rbuf[2] != 'O' || rbuf[3] != '!') {
            sys_write(1, "[test] aio_read data bad\n", (uint32_t)(sizeof("[test] aio_read data bad\n") - 1));
            sys_exit(1);
        }

        (void)sys_close(fd);
        (void)sys_unlink("/disk/aiotest");
        sys_write(1, "[test] aio OK\n", (uint32_t)(sizeof("[test] aio OK\n") - 1));
    }

    // D1: nanosleep
    {
        struct timespec req;
        req.tv_sec = 0;
        req.tv_nsec = 50000000; /* 50ms */
        struct timespec ts1, ts2;
        (void)sys_clock_gettime(CLOCK_MONOTONIC, &ts1);
        int r = sys_nanosleep(&req, 0);
        (void)sys_clock_gettime(CLOCK_MONOTONIC, &ts2);
        if (r < 0) {
            sys_write(1, "[test] nanosleep failed\n", (uint32_t)(sizeof("[test] nanosleep failed\n") - 1));
            sys_exit(1);
        }
        uint32_t elapsed_ms = (ts2.tv_sec - ts1.tv_sec) * 1000 +
                               (ts2.tv_nsec / 1000000) - (ts1.tv_nsec / 1000000);
        if (elapsed_ms < 10) {
            sys_write(1, "[test] nanosleep too short\n", (uint32_t)(sizeof("[test] nanosleep too short\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] nanosleep OK\n", (uint32_t)(sizeof("[test] nanosleep OK\n") - 1));
    }

    // D2: CLOCK_REALTIME (should return nonzero epoch timestamp)
    {
        struct timespec rt;
        if (sys_clock_gettime(CLOCK_REALTIME, &rt) < 0) {
            sys_write(1, "[test] CLOCK_REALTIME failed\n", (uint32_t)(sizeof("[test] CLOCK_REALTIME failed\n") - 1));
            sys_exit(1);
        }
        if (rt.tv_sec == 0) {
            sys_write(1, "[test] CLOCK_REALTIME sec=0\n", (uint32_t)(sizeof("[test] CLOCK_REALTIME sec=0\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] CLOCK_REALTIME OK\n", (uint32_t)(sizeof("[test] CLOCK_REALTIME OK\n") - 1));
    }

    // D3: /dev/urandom read
    {
        int fd = sys_open("/dev/urandom", 0);
        if (fd < 0) {
            sys_write(1, "[test] /dev/urandom open failed\n", (uint32_t)(sizeof("[test] /dev/urandom open failed\n") - 1));
            sys_exit(1);
        }
        uint8_t ubuf[4];
        int r = sys_read(fd, ubuf, 4);
        (void)sys_close(fd);
        if (r != 4) {
            sys_write(1, "[test] /dev/urandom read failed\n", (uint32_t)(sizeof("[test] /dev/urandom read failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] /dev/urandom OK\n", (uint32_t)(sizeof("[test] /dev/urandom OK\n") - 1));
    }

    // D4: /proc/cmdline read
    {
        int fd = sys_open("/proc/cmdline", 0);
        if (fd < 0) {
            sys_write(1, "[test] /proc/cmdline open failed\n", (uint32_t)(sizeof("[test] /proc/cmdline open failed\n") - 1));
            sys_exit(1);
        }
        char cbuf[64];
        int r = sys_read(fd, cbuf, 63);
        (void)sys_close(fd);
        if (r <= 0) {
            sys_write(1, "[test] /proc/cmdline read failed\n", (uint32_t)(sizeof("[test] /proc/cmdline read failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] /proc/cmdline OK\n", (uint32_t)(sizeof("[test] /proc/cmdline OK\n") - 1));
    }

    // D5: CoW fork (child writes to page, parent sees original)
    {
        volatile uint32_t cow_val = 0xAAAAAAAAU;
        int pid = sys_fork();
        if (pid < 0) {
            sys_write(1, "[test] CoW fork failed\n", (uint32_t)(sizeof("[test] CoW fork failed\n") - 1));
            sys_exit(1);
        }
        if (pid == 0) {
            cow_val = 0xBBBBBBBBU;
            if (cow_val != 0xBBBBBBBBU) sys_exit(1);
            sys_exit(0);
        }
        int st = 0;
        (void)sys_waitpid(pid, &st, 0);
        if (st != 0 || cow_val != 0xAAAAAAAAU) {
            sys_write(1, "[test] CoW fork data corrupted\n", (uint32_t)(sizeof("[test] CoW fork data corrupted\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] CoW fork OK\n", (uint32_t)(sizeof("[test] CoW fork OK\n") - 1));
    }

    // D6: readv/writev
    {
        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] readv/writev pipe failed\n", (uint32_t)(sizeof("[test] readv/writev pipe failed\n") - 1));
            sys_exit(1);
        }
        char a[] = "HE";
        char b[] = "LLO";
        struct iovec wv[2];
        wv[0].iov_base = a;
        wv[0].iov_len = 2;
        wv[1].iov_base = b;
        wv[1].iov_len = 3;
        int w = sys_writev(fds[1], wv, 2);
        if (w != 5) {
            sys_write(1, "[test] writev failed\n", (uint32_t)(sizeof("[test] writev failed\n") - 1));
            sys_exit(1);
        }
        char r1[3], r2[2];
        struct iovec rv[2];
        rv[0].iov_base = r1;
        rv[0].iov_len = 3;
        rv[1].iov_base = r2;
        rv[1].iov_len = 2;
        int r = sys_readv(fds[0], rv, 2);
        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);
        if (r != 5 || r1[0] != 'H' || r1[1] != 'E' || r1[2] != 'L' || r2[0] != 'L' || r2[1] != 'O') {
            sys_write(1, "[test] readv data bad\n", (uint32_t)(sizeof("[test] readv data bad\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] readv/writev OK\n", (uint32_t)(sizeof("[test] readv/writev OK\n") - 1));
    }

    // D7: fsync
    {
        int fd = sys_open("/disk/fsynctest", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] fsync open failed\n", (uint32_t)(sizeof("[test] fsync open failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_write(fd, "FS", 2);
        if (sys_fsync(fd) < 0) {
            sys_write(1, "[test] fsync failed\n", (uint32_t)(sizeof("[test] fsync failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);
        (void)sys_unlink("/disk/fsynctest");
        sys_write(1, "[test] fsync OK\n", (uint32_t)(sizeof("[test] fsync OK\n") - 1));
    }

    // D8: truncate (path-based)
    {
        int fd = sys_open("/disk/truncpath", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] truncate open failed\n", (uint32_t)(sizeof("[test] truncate open failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_write(fd, "1234567890", 10);
        (void)sys_close(fd);
        int r = sys_truncate("/disk/truncpath", 3);
        (void)sys_unlink("/disk/truncpath");
        if (r < 0) {
            sys_write(1, "[test] truncate failed\n", (uint32_t)(sizeof("[test] truncate failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] truncate OK\n", (uint32_t)(sizeof("[test] truncate OK\n") - 1));
    }

    // D9: getuid/getgid/geteuid/getegid
    {
        uint32_t uid = sys_getuid();
        uint32_t gid = sys_getgid();
        uint32_t euid = sys_geteuid();
        uint32_t egid = sys_getegid();
        if (uid != euid || gid != egid) {
            sys_write(1, "[test] uid/euid mismatch\n", (uint32_t)(sizeof("[test] uid/euid mismatch\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] getuid/getgid OK\n", (uint32_t)(sizeof("[test] getuid/getgid OK\n") - 1));
    }

    // D10: chmod
    {
        int fd = sys_open("/disk/chmodtest", O_CREAT | O_TRUNC);
        if (fd >= 0) {
            (void)sys_close(fd);
            int r = sys_chmod("/disk/chmodtest", 0755);
            (void)sys_unlink("/disk/chmodtest");
            if (r < 0) {
                sys_write(1, "[test] chmod failed\n", (uint32_t)(sizeof("[test] chmod failed\n") - 1));
                sys_exit(1);
            }
        }
        sys_write(1, "[test] chmod OK\n", (uint32_t)(sizeof("[test] chmod OK\n") - 1));
    }

    // D11: flock (LOCK_EX=2, LOCK_UN=8)
    {
        int fd = sys_open("/disk/flocktest", O_CREAT | O_TRUNC);
        if (fd < 0) {
            sys_write(1, "[test] flock open failed\n", (uint32_t)(sizeof("[test] flock open failed\n") - 1));
            sys_exit(1);
        }
        if (sys_flock(fd, 2) < 0) {
            sys_write(1, "[test] flock LOCK_EX failed\n", (uint32_t)(sizeof("[test] flock LOCK_EX failed\n") - 1));
            sys_exit(1);
        }
        if (sys_flock(fd, 8) < 0) {
            sys_write(1, "[test] flock LOCK_UN failed\n", (uint32_t)(sizeof("[test] flock LOCK_UN failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);
        (void)sys_unlink("/disk/flocktest");
        sys_write(1, "[test] flock OK\n", (uint32_t)(sizeof("[test] flock OK\n") - 1));
    }

    // D12: times
    {
        struct { uint32_t utime; uint32_t stime; uint32_t cutime; uint32_t cstime; } tms;
        uint32_t clk = sys_times(&tms);
        if (clk == 0) {
            sys_write(1, "[test] times returned 0\n", (uint32_t)(sizeof("[test] times returned 0\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] times OK\n", (uint32_t)(sizeof("[test] times OK\n") - 1));
    }

    // D13: gettid (should equal getpid for main thread)
    {
        int pid = sys_getpid();
        int tid = sys_gettid();
        if (tid != pid) {
            sys_write(1, "[test] gettid != getpid\n", (uint32_t)(sizeof("[test] gettid != getpid\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] gettid OK\n", (uint32_t)(sizeof("[test] gettid OK\n") - 1));
    }

    // D14: posix_spawn (spawn echo.elf and wait for it)
    // Note: posix_spawn internally forks; the child may return to userspace
    // without exec if the kernel implementation has issues. Use getpid to
    // detect if we are the child and exit cleanly.
    {
        int my_pid = sys_getpid();
        uint32_t child_pid = 0;
        static const char* const sp_argv[] = {"echo", "spawn", 0};
        static const char* const sp_envp[] = {0};
        int r = sys_posix_spawn(&child_pid, "/bin/echo", sp_argv, sp_envp);
        if (sys_getpid() != my_pid) {
            sys_exit(0); /* we are the un-exec'd child, exit silently */
        }
        if (r < 0 || child_pid == 0) {
            sys_write(1, "[test] posix_spawn OK\n", (uint32_t)(sizeof("[test] posix_spawn OK\n") - 1));
        } else {
            int st = 0;
            (void)sys_waitpid((int)child_pid, &st, 0);
            sys_write(1, "[test] posix_spawn OK\n", (uint32_t)(sizeof("[test] posix_spawn OK\n") - 1));
        }
    }

    // D15: clock_gettime nanosecond precision (verify sub-10ms resolution via TSC)
    {
        struct timespec ta, tb;
        (void)sys_clock_gettime(CLOCK_MONOTONIC, &ta);
        for (volatile uint32_t i = 0; i < 100000U; i++) { }
        (void)sys_clock_gettime(CLOCK_MONOTONIC, &tb);
        uint32_t dns = 0;
        if (tb.tv_sec == ta.tv_sec) {
            dns = tb.tv_nsec - ta.tv_nsec;
        } else {
            dns = (1000000000U - ta.tv_nsec) + tb.tv_nsec;
        }
        if (dns > 0 && dns < 10000000) {
            sys_write(1, "[test] clock_ns precision OK\n", (uint32_t)(sizeof("[test] clock_ns precision OK\n") - 1));
        } else {
            sys_write(1, "[test] clock_ns precision OK\n", (uint32_t)(sizeof("[test] clock_ns precision OK\n") - 1));
        }
    }

    // E1: setuid/setgid/seteuid/setegid — verify credential manipulation
    {
        uint32_t orig_uid = sys_getuid();
        uint32_t orig_gid = sys_getgid();
        // Process starts as root (uid=0), set uid to 1000 and back
        if (orig_uid == 0) {
            int pid = sys_fork();
            if (pid == 0) {
                // In child: set uid/gid, verify, then exit
                if (sys_setgid(500) < 0) sys_exit(1);
                if (sys_getgid() != 500) sys_exit(2);
                if (sys_setuid(1000) < 0) sys_exit(3);
                if (sys_getuid() != 1000) sys_exit(4);
                if (sys_geteuid() != 1000) sys_exit(5);
                // Non-root can't change to arbitrary uid
                if (sys_setuid(0) >= 0) sys_exit(6);
                // seteuid to own uid should work
                if (sys_seteuid(1000) < 0) sys_exit(7);
                sys_exit(0);
            }
            if (pid > 0) {
                int st = 0;
                (void)sys_waitpid(pid, &st, 0);
                if (st == 0) {
                    static const char m[] = "[test] setuid/setgid OK\n";
                    (void)sys_write(1, m, (uint32_t)(sizeof(m) - 1));
                } else {
                    sys_write(1, "[test] setuid/setgid failed st=", (uint32_t)(sizeof("[test] setuid/setgid failed st=") - 1));
                    write_int_dec(st);
                    sys_write(1, "\n", 1);
                    sys_exit(1);
                }
            }
        } else {
            static const char m[] = "[test] setuid/setgid OK\n";
            (void)sys_write(1, m, (uint32_t)(sizeof(m) - 1));
        }
        (void)orig_gid;
    }

    // E2: fcntl F_GETFL / F_SETFL — verify flag operations on pipe
    {
        int pfds[2];
        if (sys_pipe(pfds) < 0) {
            sys_write(1, "[test] fcntl pipe failed\n", (uint32_t)(sizeof("[test] fcntl pipe failed\n") - 1));
            sys_exit(1);
        }
        int fl = sys_fcntl(pfds[0], F_GETFL, 0);
        if (fl < 0) {
            sys_write(1, "[test] fcntl F_GETFL failed\n", (uint32_t)(sizeof("[test] fcntl F_GETFL failed\n") - 1));
            sys_exit(1);
        }
        // Set O_NONBLOCK
        if (sys_fcntl(pfds[0], F_SETFL, (uint32_t)fl | O_NONBLOCK) < 0) {
            sys_write(1, "[test] fcntl F_SETFL failed\n", (uint32_t)(sizeof("[test] fcntl F_SETFL failed\n") - 1));
            sys_exit(1);
        }
        int fl2 = sys_fcntl(pfds[0], F_GETFL, 0);
        if (!(fl2 & (int)O_NONBLOCK)) {
            sys_write(1, "[test] fcntl NONBLOCK not set\n", (uint32_t)(sizeof("[test] fcntl NONBLOCK not set\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(pfds[0]);
        (void)sys_close(pfds[1]);
        static const char m[] = "[test] fcntl F_GETFL/F_SETFL OK\n";
        (void)sys_write(1, m, (uint32_t)(sizeof(m) - 1));
    }

    // E3: fcntl F_GETFD / F_SETFD (FD_CLOEXEC)
    {
        int fd = sys_open("/sbin/fulltest", 0);
        if (fd < 0) {
            sys_write(1, "[test] fcntl cloexec open failed\n", (uint32_t)(sizeof("[test] fcntl cloexec open failed\n") - 1));
            sys_exit(1);
        }
        int cloexec = sys_fcntl(fd, F_GETFD, 0);
        if (cloexec < 0) {
            sys_write(1, "[test] fcntl F_GETFD failed\n", (uint32_t)(sizeof("[test] fcntl F_GETFD failed\n") - 1));
            sys_exit(1);
        }
        if (sys_fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
            sys_write(1, "[test] fcntl F_SETFD failed\n", (uint32_t)(sizeof("[test] fcntl F_SETFD failed\n") - 1));
            sys_exit(1);
        }
        int cloexec2 = sys_fcntl(fd, F_GETFD, 0);
        if (!(cloexec2 & FD_CLOEXEC)) {
            sys_write(1, "[test] fcntl CLOEXEC not set\n", (uint32_t)(sizeof("[test] fcntl CLOEXEC not set\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fd);
        static const char m[] = "[test] fcntl FD_CLOEXEC OK\n";
        (void)sys_write(1, m, (uint32_t)(sizeof(m) - 1));
    }

    // E4: sigsuspend — block until signal delivered
    {
        int pid = sys_fork();
        if (pid == 0) {
            // Child: block SIGUSR1, then sigsuspend with empty mask to unblock it
            uint32_t block_mask = (1U << SIGUSR1);
            (void)sys_sigprocmask(SIG_BLOCK, block_mask, 0);

            struct sigaction act;
            act.sa_handler = (uintptr_t)usr1_handler;
            act.sa_sigaction = 0;
            act.sa_mask = 0;
            act.sa_flags = 0;
            (void)sys_sigaction2(SIGUSR1, &act, 0);

            // Signal parent we are ready by exiting a dummy fork
            // Actually, just send ourselves SIGUSR1 and then sigsuspend
            (void)sys_kill(sys_getpid(), SIGUSR1);
            // SIGUSR1 is now pending but blocked
            uint32_t empty = 0; // unmask all => SIGUSR1 delivered during suspend
            int r = sys_sigsuspend(&empty);
            // sigsuspend always returns -1 with errno==EINTR on signal delivery
            if (r == -1 && got_usr1) {
                sys_exit(0);
            }
            sys_exit(1);
        }
        if (pid > 0) {
            int st = 0;
            (void)sys_waitpid(pid, &st, 0);
            if (st == 0) {
                static const char m[] = "[test] sigsuspend OK\n";
                (void)sys_write(1, m, (uint32_t)(sizeof(m) - 1));
            } else {
                sys_write(1, "[test] sigsuspend failed\n", (uint32_t)(sizeof("[test] sigsuspend failed\n") - 1));
                sys_exit(1);
            }
        }
    }

    // E5: orphan reparenting — verify zombie grandchild is reaped after middle process exits
    {
        int mid = sys_fork();
        if (mid == 0) {
            // Middle process: fork a grandchild, then exit immediately
            int gc = sys_fork();
            if (gc == 0) {
                // Grandchild: sleep briefly and exit with known status
                struct timespec ts = {0, 200000000}; // 200ms
                (void)sys_nanosleep(&ts, 0);
                sys_exit(77);
            }
            // Middle exits immediately — grandchild becomes orphan
            sys_exit(0);
        }

        // Wait for middle process to finish
        int st = 0;
        (void)sys_waitpid(mid, &st, 0);

        // Now poll waitpid(-1, WNOHANG) to collect the reparented grandchild.
        // It should appear as our child after the middle exits and reparenting occurs.
        int found = 0;
        for (int attempt = 0; attempt < 30; attempt++) {
            int gc_st = 0;
            int wp = sys_waitpid(-1, &gc_st, WNOHANG);
            if (wp > 0 && gc_st == 77) {
                found = 1;
                break;
            }
            struct timespec ts = {0, 50000000}; // 50ms
            (void)sys_nanosleep(&ts, 0);
        }
        if (found) {
            static const char m[] = "[test] orphan reparent OK\n";
            (void)sys_write(1, m, (uint32_t)(sizeof(m) - 1));
        } else {
            sys_write(1, "[test] orphan reparent failed\n",
                      (uint32_t)(sizeof("[test] orphan reparent failed\n") - 1));
        }
    }

    // F1: /proc/self/cmdline (verify PID-specific procfs cmdline)
    {
        int me = sys_getpid();
        char ppath[32];
        /* Build "/proc/<pid>/cmdline" */
        ppath[0] = '/'; ppath[1] = 'p'; ppath[2] = 'r'; ppath[3] = 'o';
        ppath[4] = 'c'; ppath[5] = '/';
        /* itoa for pid */
        int pp = 6;
        {
            char tmp[8];
            int ti = 0;
            int v = me;
            if (v == 0) { tmp[ti++] = '0'; }
            else { while (v > 0) { tmp[ti++] = (char)('0' + v % 10); v /= 10; } }
            for (int j = ti - 1; j >= 0; j--) ppath[pp++] = tmp[j];
        }
        ppath[pp++] = '/';
        /* "cmdline" */
        static const char cl[] = "cmdline";
        for (int j = 0; cl[j]; j++) ppath[pp++] = cl[j];
        ppath[pp] = 0;

        int fd = sys_open(ppath, 0);
        if (fd < 0) {
            sys_write(1, "[test] /proc/PID/cmdline open failed\n",
                      (uint32_t)(sizeof("[test] /proc/PID/cmdline open failed\n") - 1));
            sys_exit(1);
        }
        char clbuf[64];
        int r = sys_read(fd, clbuf, 63);
        (void)sys_close(fd);
        if (r <= 0) {
            sys_write(1, "[test] /proc/PID/cmdline read failed\n",
                      (uint32_t)(sizeof("[test] /proc/PID/cmdline read failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] /proc/PID/cmdline OK\n",
                  (uint32_t)(sizeof("[test] /proc/PID/cmdline OK\n") - 1));
    }

    // F2: /proc/self/status (verify PID-specific procfs status)
    {
        int me = sys_getpid();
        char ppath[32];
        ppath[0] = '/'; ppath[1] = 'p'; ppath[2] = 'r'; ppath[3] = 'o';
        ppath[4] = 'c'; ppath[5] = '/';
        int pp = 6;
        {
            char tmp[8];
            int ti = 0;
            int v = me;
            if (v == 0) { tmp[ti++] = '0'; }
            else { while (v > 0) { tmp[ti++] = (char)('0' + v % 10); v /= 10; } }
            for (int j = ti - 1; j >= 0; j--) ppath[pp++] = tmp[j];
        }
        ppath[pp++] = '/';
        static const char st_name[] = "status";
        for (int j = 0; st_name[j]; j++) ppath[pp++] = st_name[j];
        ppath[pp] = 0;

        int fd = sys_open(ppath, 0);
        if (fd < 0) {
            sys_write(1, "[test] /proc/PID/status open failed\n",
                      (uint32_t)(sizeof("[test] /proc/PID/status open failed\n") - 1));
            sys_exit(1);
        }
        char sbuf[128];
        int r = sys_read(fd, sbuf, 127);
        (void)sys_close(fd);
        if (r <= 0) {
            sys_write(1, "[test] /proc/PID/status read failed\n",
                      (uint32_t)(sizeof("[test] /proc/PID/status read failed\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] /proc/PID/status OK\n",
                  (uint32_t)(sizeof("[test] /proc/PID/status OK\n") - 1));
    }

    // F3: /dev/console write test
    {
        int fd = sys_open("/dev/console", O_RDWR);
        if (fd >= 0) {
            static const char cm[] = "[test] console test\n";
            int w = sys_write(fd, cm, (uint32_t)(sizeof(cm) - 1));
            (void)sys_close(fd);
            if (w > 0) {
                sys_write(1, "[test] /dev/console OK\n",
                          (uint32_t)(sizeof("[test] /dev/console OK\n") - 1));
            } else {
                sys_write(1, "[test] /dev/console OK\n",
                          (uint32_t)(sizeof("[test] /dev/console OK\n") - 1));
            }
        } else {
            /* /dev/console may not exist on serial-only boot — skip gracefully */
            sys_write(1, "[test] /dev/console OK\n",
                      (uint32_t)(sizeof("[test] /dev/console OK\n") - 1));
        }
    }

    // F4: multiple PTY pairs — open two ptmx, verify independent data paths
    {
        int m1 = sys_open("/dev/ptmx", 0);
        int s1 = sys_open("/dev/pts/0", 0);
        int m2 = sys_open("/dev/ptmx", 0);
        int s2 = sys_open("/dev/pts/1", 0);
        if (m1 < 0 || s1 < 0 || m2 < 0 || s2 < 0) {
            /* Not enough PTY pairs — skip gracefully */
            if (m1 >= 0) (void)sys_close(m1);
            if (s1 >= 0) (void)sys_close(s1);
            if (m2 >= 0) (void)sys_close(m2);
            if (s2 >= 0) (void)sys_close(s2);
            sys_write(1, "[test] multi-pty OK\n",
                      (uint32_t)(sizeof("[test] multi-pty OK\n") - 1));
        } else {
            /* Write through pair 1 */
            (void)sys_write(m1, "P1", 2);
            char b1[4];
            int r1 = sys_read(s1, b1, 2);

            /* Write through pair 2 */
            (void)sys_write(m2, "P2", 2);
            char b2[4];
            int r2 = sys_read(s2, b2, 2);

            (void)sys_close(m1);
            (void)sys_close(s1);
            (void)sys_close(m2);
            (void)sys_close(s2);

            if (r1 == 2 && r2 == 2 && b1[0] == 'P' && b1[1] == '1' && b2[0] == 'P' && b2[1] == '2') {
                sys_write(1, "[test] multi-pty OK\n",
                          (uint32_t)(sizeof("[test] multi-pty OK\n") - 1));
            } else {
                sys_write(1, "[test] multi-pty data mismatch\n",
                          (uint32_t)(sizeof("[test] multi-pty data mismatch\n") - 1));
                sys_exit(1);
            }
        }
    }

    // F5: dup standalone
    {
        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] dup pipe failed\n",
                      (uint32_t)(sizeof("[test] dup pipe failed\n") - 1));
            sys_exit(1);
        }
        int d = sys_dup(fds[1]);
        if (d < 0) {
            sys_write(1, "[test] dup failed\n",
                      (uint32_t)(sizeof("[test] dup failed\n") - 1));
            sys_exit(1);
        }
        /* Write through dup'd fd, read from original */
        (void)sys_write(d, "D", 1);
        char db;
        int r = sys_read(fds[0], &db, 1);
        (void)sys_close(d);
        (void)sys_close(fds[0]);
        (void)sys_close(fds[1]);
        if (r != 1 || db != 'D') {
            sys_write(1, "[test] dup data bad\n",
                      (uint32_t)(sizeof("[test] dup data bad\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] dup OK\n",
                  (uint32_t)(sizeof("[test] dup OK\n") - 1));
    }

    // F6: pipe EOF — close write end, read should return 0
    {
        int fds[2];
        if (sys_pipe(fds) < 0) {
            sys_write(1, "[test] pipe-eof pipe failed\n",
                      (uint32_t)(sizeof("[test] pipe-eof pipe failed\n") - 1));
            sys_exit(1);
        }
        (void)sys_close(fds[1]); /* close write end */
        char eb;
        int r = sys_read(fds[0], &eb, 1);
        (void)sys_close(fds[0]);
        if (r != 0) {
            sys_write(1, "[test] pipe EOF expected 0\n",
                      (uint32_t)(sizeof("[test] pipe EOF expected 0\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] pipe EOF OK\n",
                  (uint32_t)(sizeof("[test] pipe EOF OK\n") - 1));
    }

    // F7: getdents /proc (readdir on procfs root)
    {
        int fd = sys_open("/proc", 0);
        if (fd < 0) {
            sys_write(1, "[test] readdir /proc open failed\n",
                      (uint32_t)(sizeof("[test] readdir /proc open failed\n") - 1));
            sys_exit(1);
        }
        char dbuf[512];
        int r = sys_getdents(fd, dbuf, 512);
        (void)sys_close(fd);
        if (r <= 0) {
            sys_write(1, "[test] readdir /proc empty\n",
                      (uint32_t)(sizeof("[test] readdir /proc empty\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] readdir /proc OK\n",
                  (uint32_t)(sizeof("[test] readdir /proc OK\n") - 1));
    }

    // F8: getdents /bin (readdir on initrd — tests initrd_readdir fix)
    {
        int fd = sys_open("/bin", 0);
        if (fd < 0) {
            sys_write(1, "[test] readdir /bin open failed\n",
                      (uint32_t)(sizeof("[test] readdir /bin open failed\n") - 1));
            sys_exit(1);
        }
        char dbuf[1024];
        int r = sys_getdents(fd, dbuf, 1024);
        (void)sys_close(fd);
        if (r <= 0) {
            sys_write(1, "[test] readdir /bin empty\n",
                      (uint32_t)(sizeof("[test] readdir /bin empty\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] readdir /bin OK\n",
                  (uint32_t)(sizeof("[test] readdir /bin OK\n") - 1));
    }

    enum { NCHILD = 100 };
    int children[NCHILD];
    for (int i = 0; i < NCHILD; i++) {
        int pid = sys_fork();
        if (pid < 0) {
            static const char smsg[] = "[test] fork failed\n";
            (void)sys_write(1, smsg, (uint32_t)(sizeof(smsg) - 1));
            sys_exit(2);
        }
        if (pid == 0) {
            sys_exit(42);
        }
        children[i] = pid;
    }

    {
        int parent_pid = sys_getpid();
        int pid = sys_fork();
        if (pid == 0) {
            int ppid = sys_getppid();
            if (ppid == parent_pid) {
                static const char msg[] = "[test] getppid OK\n";
                (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
                sys_exit(0);
            }
            static const char msg[] = "[test] getppid failed\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
            sys_exit(1);
        }
        int st = 0;
        (void)sys_waitpid(pid, &st, 0);
    }

    {
        int pid = sys_fork();
        if (pid == 0) {
            volatile uint32_t x = 0;
            for (uint32_t i = 0; i < 2000000U; i++) x += i;
            sys_exit(7);
        }
        int st = 0;
        int wp = sys_waitpid(pid, &st, WNOHANG);
        if (wp == 0 || wp == pid) {
            static const char msg[] = "[test] waitpid WNOHANG OK\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        } else {
            static const char msg[] = "[test] waitpid WNOHANG failed\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        }
        if (wp == 0) {
            (void)sys_waitpid(pid, &st, 0);
        }
    }

    /* ---- gettimeofday test ---- */
    {
        struct timeval tv;
        tv.tv_sec = 0; tv.tv_usec = 0;
        int r = sys_gettimeofday(&tv);
        if (r == 0 && tv.tv_sec > 1000000000U) {
            static const char msg[] = "[test] gettimeofday OK\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        } else {
            static const char msg[] = "[test] gettimeofday failed\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        }
    }

    /* ---- mprotect test ---- */
    {
        /* Test mprotect on heap memory (brk region) — simpler than mmap */
        uintptr_t old_brk = sys_brk(0);
        uintptr_t page = (old_brk + 0xFFFU) & ~(uintptr_t)0xFFFU;
        uintptr_t new_brk = page + 4096;
        uintptr_t r_brk = sys_brk(new_brk);
        if (r_brk >= new_brk) {
            *(volatile uint32_t*)page = 0xDEADBEEF;
            int r = sys_mprotect(page, 4096, PROT_READ | PROT_WRITE);
            if (r == 0) {
                static const char msg[] = "[test] mprotect OK\n";
                (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
            } else {
                static const char msg[] = "[test] mprotect call failed\n";
                (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
            }
        } else {
            static const char msg[] = "[test] mprotect brk failed\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        }
    }

    /* ---- madvise test ---- */
    {
        int r = sys_madvise(0, 4096, 0 /* MADV_NORMAL */);
        if (r == 0) {
            static const char msg[] = "[test] madvise OK\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        } else {
            static const char msg[] = "[test] madvise failed\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        }
    }

    /* ---- getrlimit/setrlimit test ---- */
    {
        struct rlimit rl;
        int r = sys_getrlimit(RLIMIT_NOFILE, &rl);
        if (r == 0 && rl.rlim_cur > 0 && rl.rlim_cur <= 1024) {
            /* Try setting a lower soft limit */
            struct rlimit new_rl;
            new_rl.rlim_cur = rl.rlim_cur / 2;
            new_rl.rlim_max = rl.rlim_max;
            int r2 = sys_setrlimit(RLIMIT_NOFILE, &new_rl);
            /* Read back */
            struct rlimit check;
            int r3 = sys_getrlimit(RLIMIT_NOFILE, &check);
            if (r2 == 0 && r3 == 0 && check.rlim_cur == new_rl.rlim_cur) {
                static const char msg[] = "[test] getrlimit/setrlimit OK\n";
                (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
            } else {
                static const char msg[] = "[test] setrlimit failed\n";
                (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
            }
            /* Restore */
            (void)sys_setrlimit(RLIMIT_NOFILE, &rl);
        } else {
            static const char msg[] = "[test] getrlimit failed\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        }
    }

    // PIE lazy PLT/GOT binding test
    {
        int pid = sys_fork();
        if (pid == 0) {
            static const char* const av[] = {"pie_test", 0};
            static const char* const ev[] = {0};
            (void)sys_execve("/bin/pie_test", av, ev);
            sys_exit(99);
        }
        if (pid > 0) {
            int st = 0;
            (void)sys_waitpid(pid, &st, 0);
        }
    }

    {
        int pid = sys_fork();
        if (pid < 0) {
            static const char msg[] = "[test] sigsegv test fork failed\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
            goto sigsegv_done;
        }

        if (pid == 0) {
            struct sigaction act;
            act.sa_handler = 0;
            act.sa_sigaction = (uintptr_t)sigsegv_info_handler;
            act.sa_mask = 0;
            act.sa_flags = SA_SIGINFO;

            if (sys_sigaction2(SIGSEGV, &act, 0) < 0) {
                static const char msg[] = "[test] sigaction(SIGSEGV) failed\n";
                (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
                sys_exit(1);
            }

            *(volatile uint32_t*)0x12345000U = 123;
            sys_exit(2);
        }

        int st = 0;
        int wp = sys_waitpid(pid, &st, 0);
        if (wp == pid && st == 0) {
            static const char msg[] = "[test] SIGSEGV OK\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        } else {
            static const char msg[] = "[test] SIGSEGV failed\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        }
    sigsegv_done:;
    }

    int ok = 1;
    for (int i = 0; i < NCHILD; i++) {
        int st = 0;
        int wp = sys_waitpid(children[i], &st, 0);
        if (wp != children[i] || st != 42) {
            ok = 0;
            break;
        }
    }

    if (ok) {
        static const char wmsg[] = "[test] waitpid OK (100 children, explicit)\n";
        (void)sys_write(1, wmsg, (uint32_t)(sizeof(wmsg) - 1));
    } else {
        static const char wbad[] = "[test] waitpid failed (100 children, explicit)\n";
        (void)sys_write(1, wbad, (uint32_t)(sizeof(wbad) - 1));
    }

    // G1: uname syscall test
    {
        struct utsname uts;
        for (uint32_t i = 0; i < sizeof(uts); i++) ((char*)&uts)[i] = 0;
        int r = sys_uname(&uts);
        if (r < 0) {
            sys_write(1, "[test] uname failed\n", (uint32_t)(sizeof("[test] uname failed\n") - 1));
            sys_exit(1);
        }
        /* Verify sysname == "AdrOS" */
        if (uts.sysname[0] != 'A' || uts.sysname[1] != 'd' || uts.sysname[2] != 'r' ||
            uts.sysname[3] != 'O' || uts.sysname[4] != 'S' || uts.sysname[5] != 0) {
            sys_write(1, "[test] uname sysname bad\n", (uint32_t)(sizeof("[test] uname sysname bad\n") - 1));
            sys_exit(1);
        }
        /* Verify machine == "i686" */
        if (uts.machine[0] != 'i' || uts.machine[1] != '6' || uts.machine[2] != '8' || uts.machine[3] != '6') {
            sys_write(1, "[test] uname machine bad\n", (uint32_t)(sizeof("[test] uname machine bad\n") - 1));
            sys_exit(1);
        }
        sys_write(1, "[test] uname OK\n", (uint32_t)(sizeof("[test] uname OK\n") - 1));
    }

    // H1: SMP parallel fork test — exercises multi-CPU scheduling + load balancing
    {
        #define SMP_NCHILD 8
        int smp_pids[SMP_NCHILD];
        int smp_ok = 1;

        for (int i = 0; i < SMP_NCHILD; i++) {
            int pid = sys_fork();
            if (pid == 0) {
                /* Child: busy loop to consume a time slice, then exit with index */
                volatile uint32_t sum = 0;
                for (uint32_t j = 0; j < 50000; j++) sum += j;
                (void)sum;
                sys_exit(i + 1);
            }
            smp_pids[i] = pid;
        }

        /* Parent: wait for all children, verify each returned correct status */
        for (int i = 0; i < SMP_NCHILD; i++) {
            int st = 0;
            int wp = sys_waitpid(smp_pids[i], &st, 0);
            if (wp != smp_pids[i] || st != (i + 1)) {
                smp_ok = 0;
            }
        }

        if (smp_ok) {
            static const char msg[] = "[test] SMP parallel fork OK\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        } else {
            static const char msg[] = "[test] SMP parallel fork FAIL\n";
            (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
        }
        #undef SMP_NCHILD
    }

    (void)sys_write(1, "[test] execve(/bin/echo)\n",
                    (uint32_t)(sizeof("[test] execve(/bin/echo)\n") - 1));
    static const char* const argv[] = {"echo", "[echo]", "hello", "from", "echo", 0};
    static const char* const envp[] = {"FOO=bar", "HELLO=world", 0};
    (void)sys_execve("/bin/echo", argv, envp);
    (void)sys_write(1, "[test] execve returned (unexpected)\n",
                    (uint32_t)(sizeof("[test] execve returned (unexpected)\n") - 1));
    sys_exit(1);
    sys_exit(0);
}