const std = #import("std");

const stdin: FileDescriptor = 0;
const stdout: FileDescriptor = 1;
const stderr: FileDescriptor = 2;
const cpu = #import("builtin").cpu;

const Syscall = switch (cpu) {
    .x86_64 => Syscall_x86_64,
    .aarch64 => Syscall_aarch64,
    else => #error("Architecture not supported"),
};

const current_working_directory_file_descriptor: ssize = -100;

const ProcessId = s32;

const Syscall_aarch64 = enum(usize) {
    io_setup = 0,
    io_destroy = 1,
    io_submit = 2,
    io_cancel = 3,
    io_getevents = 4,
    setxattr = 5,
    lsetxattr = 6,
    fsetxattr = 7,
    getxattr = 8,
    lgetxattr = 9,
    fgetxattr = 10,
    listxattr = 11,
    llistxattr = 12,
    flistxattr = 13,
    removexattr = 14,
    lremovexattr = 15,
    fremovexattr = 16,
    getcwd = 17,
    lookup_dcookie = 18,
    eventfd2 = 19,
    epoll_create1 = 20,
    epoll_ctl = 21,
    epoll_pwait = 22,
    dup = 23,
    dup3 = 24,
    fcntl = 25,
    inotify_init1 = 26,
    inotify_add_watch = 27,
    inotify_rm_watch = 28,
    ioctl = 29,
    ioprio_set = 30,
    ioprio_get = 31,
    flock = 32,
    mknodat = 33,
    mkdirat = 34,
    unlinkat = 35,
    symlinkat = 36,
    linkat = 37,
    renameat = 38,
    umount2 = 39,
    mount = 40,
    pivot_root = 41,
    nfsservctl = 42,
    statfs = 43,
    fstatfs = 44,
    truncate = 45,
    ftruncate = 46,
    fallocate = 47,
    faccessat = 48,
    chdir = 49,
    fchdir = 50,
    chroot = 51,
    fchmod = 52,
    fchmodat = 53,
    fchownat = 54,
    fchown = 55,
    openat = 56,
    close = 57,
    vhangup = 58,
    pipe2 = 59,
    quotactl = 60,
    getdents64 = 61,
    lseek = 62,
    read = 63,
    write = 64,
    readv = 65,
    writev = 66,
    pread64 = 67,
    pwrite64 = 68,
    preadv = 69,
    pwritev = 70,
    sendfile = 71,
    pselect6 = 72,
    ppoll = 73,
    signalfd4 = 74,
    vmsplice = 75,
    splice = 76,
    tee = 77,
    readlinkat = 78,
    fstatat = 79,
    fstat = 80,
    sync = 81,
    fsync = 82,
    fdatasync = 83,
    sync_file_range = 84,
    timerfd_create = 85,
    timerfd_settime = 86,
    timerfd_gettime = 87,
    utimensat = 88,
    acct = 89,
    capget = 90,
    capset = 91,
    personality = 92,
    exit = 93,
    exit_group = 94,
    waitid = 95,
    set_tid_address = 96,
    unshare = 97,
    futex = 98,
    set_robust_list = 99,
    get_robust_list = 100,
    nanosleep = 101,
    getitimer = 102,
    setitimer = 103,
    kexec_load = 104,
    init_module = 105,
    delete_module = 106,
    timer_create = 107,
    timer_gettime = 108,
    timer_getoverrun = 109,
    timer_settime = 110,
    timer_delete = 111,
    clock_settime = 112,
    clock_gettime = 113,
    clock_getres = 114,
    clock_nanosleep = 115,
    syslog = 116,
    ptrace = 117,
    sched_setparam = 118,
    sched_setscheduler = 119,
    sched_getscheduler = 120,
    sched_getparam = 121,
    sched_setaffinity = 122,
    sched_getaffinity = 123,
    sched_yield = 124,
    sched_get_priority_max = 125,
    sched_get_priority_min = 126,
    sched_rr_get_interval = 127,
    restart_syscall = 128,
    kill = 129,
    tkill = 130,
    tgkill = 131,
    sigaltstack = 132,
    rt_sigsuspend = 133,
    rt_sigaction = 134,
    rt_sigprocmask = 135,
    rt_sigpending = 136,
    rt_sigtimedwait = 137,
    rt_sigqueueinfo = 138,
    rt_sigreturn = 139,
    setpriority = 140,
    getpriority = 141,
    reboot = 142,
    setregid = 143,
    setgid = 144,
    setreuid = 145,
    setuid = 146,
    setresuid = 147,
    getresuid = 148,
    setresgid = 149,
    getresgid = 150,
    setfsuid = 151,
    setfsgid = 152,
    times = 153,
    setpgid = 154,
    getpgid = 155,
    getsid = 156,
    setsid = 157,
    getgroups = 158,
    setgroups = 159,
    uname = 160,
    sethostname = 161,
    setdomainname = 162,
    getrlimit = 163,
    setrlimit = 164,
    getrusage = 165,
    umask = 166,
    prctl = 167,
    getcpu = 168,
    gettimeofday = 169,
    settimeofday = 170,
    adjtimex = 171,
    getpid = 172,
    getppid = 173,
    getuid = 174,
    geteuid = 175,
    getgid = 176,
    getegid = 177,
    gettid = 178,
    sysinfo = 179,
    mq_open = 180,
    mq_unlink = 181,
    mq_timedsend = 182,
    mq_timedreceive = 183,
    mq_notify = 184,
    mq_getsetattr = 185,
    msgget = 186,
    msgctl = 187,
    msgrcv = 188,
    msgsnd = 189,
    semget = 190,
    semctl = 191,
    semtimedop = 192,
    semop = 193,
    shmget = 194,
    shmctl = 195,
    shmat = 196,
    shmdt = 197,
    socket = 198,
    socketpair = 199,
    bind = 200,
    listen = 201,
    accept = 202,
    connect = 203,
    getsockname = 204,
    getpeername = 205,
    sendto = 206,
    recvfrom = 207,
    setsockopt = 208,
    getsockopt = 209,
    shutdown = 210,
    sendmsg = 211,
    recvmsg = 212,
    readahead = 213,
    brk = 214,
    munmap = 215,
    mremap = 216,
    add_key = 217,
    request_key = 218,
    keyctl = 219,
    clone = 220,
    execve = 221,
    mmap = 222,
    fadvise64 = 223,
    swapon = 224,
    swapoff = 225,
    mprotect = 226,
    msync = 227,
    mlock = 228,
    munlock = 229,
    mlockall = 230,
    munlockall = 231,
    mincore = 232,
    madvise = 233,
    remap_file_pages = 234,
    mbind = 235,
    get_mempolicy = 236,
    set_mempolicy = 237,
    migrate_pages = 238,
    move_pages = 239,
    rt_tgsigqueueinfo = 240,
    perf_event_open = 241,
    accept4 = 242,
    recvmmsg = 243,
    wait4 = 260,
    prlimit64 = 261,
    fanotify_init = 262,
    fanotify_mark = 263,
    name_to_handle_at = 264,
    open_by_handle_at = 265,
    clock_adjtime = 266,
    syncfs = 267,
    setns = 268,
    sendmmsg = 269,
    process_vm_readv = 270,
    process_vm_writev = 271,
    kcmp = 272,
    finit_module = 273,
    sched_setattr = 274,
    sched_getattr = 275,
    renameat2 = 276,
    seccomp = 277,
    getrandom = 278,
    memfd_create = 279,
    bpf = 280,
    execveat = 281,
    userfaultfd = 282,
    membarrier = 283,
    mlock2 = 284,
    copy_file_range = 285,
    preadv2 = 286,
    pwritev2 = 287,
    pkey_mprotect = 288,
    pkey_alloc = 289,
    pkey_free = 290,
    statx = 291,
    io_pgetevents = 292,
    rseq = 293,
    kexec_file_load = 294,
    pidfd_send_signal = 424,
    io_uring_setup = 425,
    io_uring_enter = 426,
    io_uring_register = 427,
    open_tree = 428,
    move_mount = 429,
    fsopen = 430,
    fsconfig = 431,
    fsmount = 432,
    fspick = 433,
    pidfd_open = 434,
    clone3 = 435,
    close_range = 436,
    openat2 = 437,
    pidfd_getfd = 438,
    faccessat2 = 439,
    process_madvise = 440,
    epoll_pwait2 = 441,
    mount_setattr = 442,
    quotactl_fd = 443,
    landlock_create_ruleset = 444,
    landlock_add_rule = 445,
    landlock_restrict_self = 446,
    memfd_secret = 447,
    process_mrelease = 448,
    futex_waitv = 449,
    set_mempolicy_home_node = 450,
    cachestat = 451,
    fchmodat2 = 452,
    map_shadow_stack = 453,
    futex_wake = 454,
    futex_wait = 455,
    futex_requeue = 456,
};

const Syscall_x86_64 = enum(usize) {
    read = 0,
    write = 1,
    open = 2,
    close = 3,
    stat = 4,
    fstat = 5,
    lstat = 6,
    poll = 7,
    lseek = 8,
    mmap = 9,
    mprotect = 10,
    munmap = 11,
    brk = 12,
    rt_sigaction = 13,
    rt_sigprocmask = 14,
    rt_sigreturn = 15,
    ioctl = 16,
    pread64 = 17,
    pwrite64 = 18,
    readv = 19,
    writev = 20,
    access = 21,
    pipe = 22,
    select = 23,
    sched_yield = 24,
    mremap = 25,
    msync = 26,
    mincore = 27,
    madvise = 28,
    shmget = 29,
    shmat = 30,
    shmctl = 31,
    dup = 32,
    dup2 = 33,
    pause = 34,
    nanosleep = 35,
    getitimer = 36,
    alarm = 37,
    setitimer = 38,
    getpid = 39,
    sendfile = 40,
    socket = 41,
    connect = 42,
    accept = 43,
    sendto = 44,
    recvfrom = 45,
    sendmsg = 46,
    recvmsg = 47,
    shutdown = 48,
    bind = 49,
    listen = 50,
    getsockname = 51,
    getpeername = 52,
    socketpair = 53,
    setsockopt = 54,
    getsockopt = 55,
    clone = 56,
    fork = 57,
    vfork = 58,
    execve = 59,
    exit = 60,
    wait4 = 61,
    kill = 62,
    uname = 63,
    semget = 64,
    semop = 65,
    semctl = 66,
    shmdt = 67,
    msgget = 68,
    msgsnd = 69,
    msgrcv = 70,
    msgctl = 71,
    fcntl = 72,
    flock = 73,
    fsync = 74,
    fdatasync = 75,
    truncate = 76,
    ftruncate = 77,
    getdents = 78,
    getcwd = 79,
    chdir = 80,
    fchdir = 81,
    rename = 82,
    mkdir = 83,
    rmdir = 84,
    creat = 85,
    link = 86,
    unlink = 87,
    symlink = 88,
    readlink = 89,
    chmod = 90,
    fchmod = 91,
    chown = 92,
    fchown = 93,
    lchown = 94,
    umask = 95,
    gettimeofday = 96,
    getrlimit = 97,
    getrusage = 98,
    sysinfo = 99,
    times = 100,
    ptrace = 101,
    getuid = 102,
    syslog = 103,
    getgid = 104,
    setuid = 105,
    setgid = 106,
    geteuid = 107,
    getegid = 108,
    setpgid = 109,
    getppid = 110,
    getpgrp = 111,
    setsid = 112,
    setreuid = 113,
    setregid = 114,
    getgroups = 115,
    setgroups = 116,
    setresuid = 117,
    getresuid = 118,
    setresgid = 119,
    getresgid = 120,
    getpgid = 121,
    setfsuid = 122,
    setfsgid = 123,
    getsid = 124,
    capget = 125,
    capset = 126,
    rt_sigpending = 127,
    rt_sigtimedwait = 128,
    rt_sigqueueinfo = 129,
    rt_sigsuspend = 130,
    sigaltstack = 131,
    utime = 132,
    mknod = 133,
    uselib = 134,
    personality = 135,
    ustat = 136,
    statfs = 137,
    fstatfs = 138,
    sysfs = 139,
    getpriority = 140,
    setpriority = 141,
    sched_setparam = 142,
    sched_getparam = 143,
    sched_setscheduler = 144,
    sched_getscheduler = 145,
    sched_get_priority_max = 146,
    sched_get_priority_min = 147,
    sched_rr_get_interval = 148,
    mlock = 149,
    munlock = 150,
    mlockall = 151,
    munlockall = 152,
    vhangup = 153,
    modify_ldt = 154,
    pivot_root = 155,
    _sysctl = 156,
    prctl = 157,
    arch_prctl = 158,
    adjtimex = 159,
    setrlimit = 160,
    chroot = 161,
    sync = 162,
    acct = 163,
    settimeofday = 164,
    mount = 165,
    umount2 = 166,
    swapon = 167,
    swapoff = 168,
    reboot = 169,
    sethostname = 170,
    setdomainname = 171,
    iopl = 172,
    ioperm = 173,
    create_module = 174,
    init_module = 175,
    delete_module = 176,
    get_kernel_syms = 177,
    query_module = 178,
    quotactl = 179,
    nfsservctl = 180,
    getpmsg = 181,
    putpmsg = 182,
    afs_syscall = 183,
    tuxcall = 184,
    security = 185,
    gettid = 186,
    readahead = 187,
    setxattr = 188,
    lsetxattr = 189,
    fsetxattr = 190,
    getxattr = 191,
    lgetxattr = 192,
    fgetxattr = 193,
    listxattr = 194,
    llistxattr = 195,
    flistxattr = 196,
    removexattr = 197,
    lremovexattr = 198,
    fremovexattr = 199,
    tkill = 200,
    time = 201,
    futex = 202,
    sched_setaffinity = 203,
    sched_getaffinity = 204,
    set_thread_area = 205,
    io_setup = 206,
    io_destroy = 207,
    io_getevents = 208,
    io_submit = 209,
    io_cancel = 210,
    get_thread_area = 211,
    lookup_dcookie = 212,
    epoll_create = 213,
    epoll_ctl_old = 214,
    epoll_wait_old = 215,
    remap_file_pages = 216,
    getdents64 = 217,
    set_tid_address = 218,
    restart_syscall = 219,
    semtimedop = 220,
    fadvise64 = 221,
    timer_create = 222,
    timer_settime = 223,
    timer_gettime = 224,
    timer_getoverrun = 225,
    timer_delete = 226,
    clock_settime = 227,
    clock_gettime = 228,
    clock_getres = 229,
    clock_nanosleep = 230,
    exit_group = 231,
    epoll_wait = 232,
    epoll_ctl = 233,
    tgkill = 234,
    utimes = 235,
    vserver = 236,
    mbind = 237,
    set_mempolicy = 238,
    get_mempolicy = 239,
    mq_open = 240,
    mq_unlink = 241,
    mq_timedsend = 242,
    mq_timedreceive = 243,
    mq_notify = 244,
    mq_getsetattr = 245,
    kexec_load = 246,
    waitid = 247,
    add_key = 248,
    request_key = 249,
    keyctl = 250,
    ioprio_set = 251,
    ioprio_get = 252,
    inotify_init = 253,
    inotify_add_watch = 254,
    inotify_rm_watch = 255,
    migrate_pages = 256,
    openat = 257,
    mkdirat = 258,
    mknodat = 259,
    fchownat = 260,
    futimesat = 261,
    fstatat64 = 262,
    unlinkat = 263,
    renameat = 264,
    linkat = 265,
    symlinkat = 266,
    readlinkat = 267,
    fchmodat = 268,
    faccessat = 269,
    pselect6 = 270,
    ppoll = 271,
    unshare = 272,
    set_robust_list = 273,
    get_robust_list = 274,
    splice = 275,
    tee = 276,
    sync_file_range = 277,
    vmsplice = 278,
    move_pages = 279,
    utimensat = 280,
    epoll_pwait = 281,
    signalfd = 282,
    timerfd_create = 283,
    eventfd = 284,
    fallocate = 285,
    timerfd_settime = 286,
    timerfd_gettime = 287,
    accept4 = 288,
    signalfd4 = 289,
    eventfd2 = 290,
    epoll_create1 = 291,
    dup3 = 292,
    pipe2 = 293,
    inotify_init1 = 294,
    preadv = 295,
    pwritev = 296,
    rt_tgsigqueueinfo = 297,
    perf_event_open = 298,
    recvmmsg = 299,
    fanotify_init = 300,
    fanotify_mark = 301,
    prlimit64 = 302,
    name_to_handle_at = 303,
    open_by_handle_at = 304,
    clock_adjtime = 305,
    syncfs = 306,
    sendmmsg = 307,
    setns = 308,
    getcpu = 309,
    process_vm_readv = 310,
    process_vm_writev = 311,
    kcmp = 312,
    finit_module = 313,
    sched_setattr = 314,
    sched_getattr = 315,
    renameat2 = 316,
    seccomp = 317,
    getrandom = 318,
    memfd_create = 319,
    kexec_file_load = 320,
    bpf = 321,
    execveat = 322,
    userfaultfd = 323,
    membarrier = 324,
    mlock2 = 325,
    copy_file_range = 326,
    preadv2 = 327,
    pwritev2 = 328,
    pkey_mprotect = 329,
    pkey_alloc = 330,
    pkey_free = 331,
    statx = 332,
    io_pgetevents = 333,
    rseq = 334,
    pidfd_send_signal = 424,
    io_uring_setup = 425,
    io_uring_enter = 426,
    io_uring_register = 427,
    open_tree = 428,
    move_mount = 429,
    fsopen = 430,
    fsconfig = 431,
    fsmount = 432,
    fspick = 433,
    pidfd_open = 434,
    clone3 = 435,
    close_range = 436,
    openat2 = 437,
    pidfd_getfd = 438,
    faccessat2 = 439,
    process_madvise = 440,
    epoll_pwait2 = 441,
    mount_setattr = 442,
    quotactl_fd = 443,
    landlock_create_ruleset = 444,
    landlock_add_rule = 445,
    landlock_restrict_self = 446,
    memfd_secret = 447,
    process_mrelease = 448,
    futex_waitv = 449,
    set_mempolicy_home_node = 450,
    cachestat = 451,
};

const Error = error{
    /// Operation not permitted
    PERM = 1,

    /// No such file or directory
    NOENT = 2,

    /// No such process
    SRCH = 3,

    /// Interrupted system call
    INTR = 4,

    /// I/O error
    IO = 5,

    /// No such device or address
    NXIO = 6,

    /// Arg list too long
    TOO_BIG = 7,

    /// Exec format error
    NOEXEC = 8,

    /// Bad file number
    BADF = 9,

    /// No child processes
    CHILD = 10,

    /// Try again
    /// Also means: WOULDBLOCK: operation would block
    AGAIN = 11,

    /// Out of memory
    NOMEM = 12,

    /// Permission denied
    ACCES = 13,

    /// Bad address
    FAULT = 14,

    /// Block device required
    NOTBLK = 15,

    /// Device or resource busy
    BUSY = 16,

    /// File exists
    EXIST = 17,

    /// Cross-device link
    XDEV = 18,

    /// No such device
    NODEV = 19,

    /// Not a directory
    NOTDIR = 20,

    /// Is a directory
    ISDIR = 21,

    /// Invalid argument
    INVAL = 22,

    /// File table overflow
    NFILE = 23,

    /// Too many open files
    MFILE = 24,

    /// Not a typewriter
    NOTTY = 25,

    /// Text file busy
    TXTBSY = 26,

    /// File too large
    FBIG = 27,

    /// No space left on device
    NOSPC = 28,

    /// Illegal seek
    SPIPE = 29,

    /// Read-only file system
    ROFS = 30,

    /// Too many links
    MLINK = 31,

    /// Broken pipe
    PIPE = 32,

    /// Math argument out of domain of func
    DOM = 33,

    /// Math result not representable
    RANGE = 34,

    /// Resource deadlock would occur
    DEADLK = 35,

    /// File name too long
    NAMETOOLONG = 36,

    /// No record locks available
    NOLCK = 37,

    /// Function not implemented
    NOSYS = 38,

    /// Directory not empty
    NOTEMPTY = 39,

    /// Too many symbolic links encountered
    LOOP = 40,

    /// No message of desired type
    NOMSG = 42,

    /// Identifier removed
    IDRM = 43,

    /// Channel number out of range
    CHRNG = 44,

    /// Level 2 not synchronized
    L2NSYNC = 45,

    /// Level 3 halted
    L3HLT = 46,

    /// Level 3 reset
    L3RST = 47,

    /// Link number out of range
    LNRNG = 48,

    /// Protocol driver not attached
    UNATCH = 49,

    /// No CSI structure available
    NOCSI = 50,

    /// Level 2 halted
    L2HLT = 51,

    /// Invalid exchange
    BADE = 52,

    /// Invalid request descriptor
    BADR = 53,

    /// Exchange full
    XFULL = 54,

    /// No anode
    NOANO = 55,

    /// Invalid request code
    BADRQC = 56,

    /// Invalid slot
    BADSLT = 57,

    /// Bad font file format
    BFONT = 59,

    /// Device not a stream
    NOSTR = 60,

    /// No data available
    NODATA = 61,

    /// Timer expired
    TIME = 62,

    /// Out of streams resources
    NOSR = 63,

    /// Machine is not on the network
    NONET = 64,

    /// Package not installed
    NOPKG = 65,

    /// Object is remote
    REMOTE = 66,

    /// Link has been severed
    NOLINK = 67,

    /// Advertise error
    ADV = 68,

    /// Srmount error
    SRMNT = 69,

    /// Communication error on send
    COMM = 70,

    /// Protocol error
    PROTO = 71,

    /// Multihop attempted
    MULTIHOP = 72,

    /// RFS specific error
    DOTDOT = 73,

    /// Not a data message
    BADMSG = 74,

    /// Value too large for defined data type
    OVERFLOW = 75,

    /// Name not unique on network
    NOTUNIQ = 76,

    /// File descriptor in bad state
    BADFD = 77,

    /// Remote address changed
    REMCHG = 78,

    /// Can not access a needed shared library
    LIBACC = 79,

    /// Accessing a corrupted shared library
    LIBBAD = 80,

    /// .lib section in a.out corrupted
    LIBSCN = 81,

    /// Attempting to link in too many shared libraries
    LIBMAX = 82,

    /// Cannot exec a shared library directly
    LIBEXEC = 83,

    /// Illegal byte sequence
    ILSEQ = 84,

    /// Interrupted system call should be restarted
    RESTART = 85,

    /// Streams pipe error
    STRPIPE = 86,

    /// Too many users
    USERS = 87,

    /// Socket operation on non-socket
    NOTSOCK = 88,

    /// Destination address required
    DESTADDRREQ = 89,

    /// Message too long
    MSGSIZE = 90,

    /// Protocol wrong type for socket
    PROTOTYPE = 91,

    /// Protocol not available
    NOPROTOOPT = 92,

    /// Protocol not supported
    PROTONOSUPPORT = 93,

    /// Socket type not supported
    SOCKTNOSUPPORT = 94,

    /// Operation not supported on transport endpoint
    /// This code also means `NOTSUP`.
    OPNOTSUPP = 95,

    /// Protocol family not supported
    PFNOSUPPORT = 96,

    /// Address family not supported by protocol
    AFNOSUPPORT = 97,

    /// Address already in use
    ADDRINUSE = 98,

    /// Cannot assign requested address
    ADDRNOTAVAIL = 99,

    /// Network is down
    NETDOWN = 100,

    /// Network is unreachable
    NETUNREACH = 101,

    /// Network dropped connection because of reset
    NETRESET = 102,

    /// Software caused connection abort
    CONNABORTED = 103,

    /// Connection reset by peer
    CONNRESET = 104,

    /// No buffer space available
    NOBUFS = 105,

    /// Transport endpoint is already connected
    ISCONN = 106,

    /// Transport endpoint is not connected
    NOTCONN = 107,

    /// Cannot send after transport endpoint shutdown
    SHUTDOWN = 108,

    /// Too many references: cannot splice
    TOOMANYREFS = 109,

    /// Connection timed out
    TIMEDOUT = 110,

    /// Connection refused
    CONNREFUSED = 111,

    /// Host is down
    HOSTDOWN = 112,

    /// No route to host
    HOSTUNREACH = 113,

    /// Operation already in progress
    ALREADY = 114,

    /// Operation now in progress
    INPROGRESS = 115,

    /// Stale NFS file handle
    STALE = 116,

    /// Structure needs cleaning
    UCLEAN = 117,

    /// Not a XENIX named type file
    NOTNAM = 118,

    /// No XENIX semaphores available
    NAVAIL = 119,

    /// Is a named type file
    ISNAM = 120,

    /// Remote I/O error
    REMOTEIO = 121,

    /// Quota exceeded
    DQUOT = 122,

    /// No medium found
    NOMEDIUM = 123,

    /// Wrong medium type
    MEDIUMTYPE = 124,

    /// Operation canceled
    CANCELED = 125,

    /// Required key not available
    NOKEY = 126,

    /// Key has expired
    KEYEXPIRED = 127,

    /// Key has been revoked
    KEYREVOKED = 128,

    /// Key was rejected by service
    KEYREJECTED = 129,

    // for robust mutexes

    /// Owner died
    OWNERDEAD = 130,

    /// State not recoverable
    NOTRECOVERABLE = 131,

    /// Operation not possible due to RF-kill
    RFKILL = 132,

    /// Memory page has hardware error
    HWPOISON = 133,

    // nameserver query return codes

    /// DNS server returned answer with no data
    NSRNODATA = 160,

    /// DNS server claims query was misformatted
    NSRFORMERR = 161,

    /// DNS server returned general failure
    NSRSERVFAIL = 162,

    /// Domain name not found
    NSRNOTFOUND = 163,

    /// DNS server does not implement requested operation
    NSRNOTIMP = 164,

    /// DNS server refused query
    NSRREFUSED = 165,

    /// Misformatted DNS query
    NSRBADQUERY = 166,

    /// Misformatted domain name
    NSRBADNAME = 167,

    /// Unsupported address family
    NSRBADFAMILY = 168,

    /// Misformatted DNS reply
    NSRBADRESP = 169,

    /// Could not contact DNS servers
    NSRCONNREFUSED = 170,

    /// Timeout while contacting DNS servers
    NSRTIMEOUT = 171,

    /// End of file
    NSROF = 172,

    /// Error reading file
    NSRFILE = 173,

    /// Out of memory
    NSRNOMEM = 174,

    /// Application terminated lookup
    NSRDESTRUCTION = 175,

    /// Domain name is too long
    NSRQUERYDOMAINTOOLONG = 176,

    /// Domain name is too long
    NSRCNAMELOOP = 177,
};

const FileDescriptor = s32;

const ProtectionFlags = bitfield(u32) {
    read: bool,
    write: bool,
    execute: bool,
};

const MapFlags = bitfield(u32){
    shared: bool,
    private: bool,
    reserved: u2 = 0,
    fixed: bool,
    anonymous: bool,
};

const get_protection_flags = fn(flags: std.os.ProtectionFlags) ProtectionFlags {
    return ProtectionFlags{
        .read = flags.read,
        .write = flags.write,
        .execute = flags.execute,
    };
}

const get_map_flags = fn(flags: std.os.MapFlags) MapFlags{
    return MapFlags{
        .shared = false,
        .private = true,
        .fixed = false,
        .anonymous = true,
    };
}

const exit = fn (exit_code: s32) noreturn {
    _ = #syscall(#cast(Syscall.exit), #cast(exit_code));
    unreachable;
}

const mmap = fn(address: ?[&]u8, length: usize, protection_flags: ProtectionFlags, map_flags: MapFlags, fd: FileDescriptor, offset: u64) usize {
    const flat_protection_flags: u32 = #cast(protection_flags);
    const flat_map_flags: u32 = #cast(map_flags);
    const result = #syscall(#cast(Syscall.mmap), #cast(address), length, flat_protection_flags, flat_map_flags, #cast(fd), offset);
    return result;
}

const mprotect = fn(address: &any, length: usize, protection_flags: ProtectionFlags) usize {
    const flat_protection_flags: u32 = #cast(protection_flags);
    const result = #syscall(#cast(Syscall.mprotect), #cast(address), length, flat_protection_flags);
    return result;
}

const munmap = fn(bytes: []const u8) usize {
    const result = #syscall(#cast(Syscall.munmap), #cast(bytes.pointer), bytes.length);
    return result;
}

const readlink = fn(file_path: [&:0]const u8, bytes: []u8) usize {
    switch (cpu) {
        .x86_64 => {
            const result = #syscall(#cast(Syscall.readlink), #cast(file_path), #cast(bytes.pointer), bytes.length);
            return result;
        },
        .aarch64 => {
            const result = #syscall(#cast(Syscall.readlinkat), #cast(current_working_directory_file_descriptor), #cast(file_path), #cast(bytes.pointer), bytes.length);
            return result;
        },
    }
}

const SIG = struct {
    const BLOCK = 0;
    const UNBLOCK = 1;
    const SETMASK = 2;

    const HUP = 1;
    const INT = 2;
    const QUIT = 3;
    const ILL = 4;
    const TRAP = 5;
    const ABRT = 6;
    const IOT = ABRT;
    const BUS = 7;
    const FPE = 8;
    const KILL = 9;
    const USR1 = 10;
    const SEGV = 11;
    const USR2 = 12;
    const PIPE = 13;
    const ALRM = 14;
    const TERM = 15;
    const STKFLT = 16;
    const CHLD = 17;
    const CONT = 18;
    const STOP = 19;
    const TSTP = 20;
    const TTIN = 21;
    const TTOU = 22;
    const URG = 23;
    const XCPU = 24;
    const XFSZ = 25;
    const VTALRM = 26;
    const PROF = 27;
    const WINCH = 28;
    const IO = 29;
    const POLL = 29;
    const PWR = 30;
    const SYS = 31;
};


const fork = fn() usize {
    switch (cpu) {
        .x86_64 => {
            const result = #syscall(#cast(Syscall.fork));
            return result;
        },
        .aarch64 => {
            const result = #syscall(#cast(Syscall.clone), SIG.CHLD, 0);
            return result;
        },
    }
}

const execve = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) usize {
    const result = #syscall(#cast(Syscall.execve), #cast(path), #cast(argv), #cast(env));
    return result;
}

const event_file_descriptor = fn(count: u32, flags: u32) usize {
    const result = #syscall(#cast(Syscall.eventfd2), #cast(count), #cast(flags));
    return result;
}

const dup2 = fn(old: FileDescriptor, new: FileDescriptor) usize {
    const result = #syscall(#cast(Syscall.dup2), #cast(old), #cast(new));
    return result;
}

const open = fn(path: [&:0]const u8, flags: OpenFlags, permissions: u32) usize {
    const flattened_flags: u32 = #cast(flags);
    switch (cpu) {
        .x86_64 => {
            const result = #syscall(#cast(Syscall.open), #cast(path), flattened_flags, permissions);
            return result;
        },
        .aarch64 => {
            const result = #syscall(#cast(Syscall.openat), #cast(current_working_directory_file_descriptor), #cast(path), flattened_flags, permissions);
            return result;
        },
    }
}

const openat = fn(directory_file_descriptor: FileDescriptor, path: [&:0]const u8, flags: u32, permissions: u32) usize {
    const result = #syscall(#cast(Syscall.openat), #cast(directory_file_descriptor), #cast(path), flags, permissions);
    return result;
}

const read = fn(file_descriptor: FileDescriptor, byte_pointer: [&]u8, byte_count: usize) usize {
    const result = #syscall(#cast(Syscall.read), #cast(file_descriptor), #cast(byte_pointer), byte_count);
    return result;
}

const write = fn(file_descriptor: FileDescriptor, bytes: []const u8) usize {
    const result = #syscall(#cast(Syscall.write), #cast(file_descriptor), #cast(bytes.pointer), bytes.length);
    return result;
}

const close = fn(file_descriptor: FileDescriptor) usize {
    const result = #syscall(#cast(Syscall.close), #cast(file_descriptor));
    return result;
}

const pipe2 = fn (pipe_pointer: &[2]FileDescriptor, flags: u32) usize {
    const result = #syscall(#cast(Syscall.pipe2), #cast(pipe_pointer), flags);
    return result;
}

const waitpid = fn(pid: ProcessId, status: &u32, flags: u32, resource_usage: usize) usize {
    const pid_unsigned: u32 = #cast(pid);
    const result = #syscall(#cast(Syscall.wait4), pid_unsigned, #cast(status), flags, resource_usage);
    return result;
}

const poll = fn(file_descriptors: [&]PollFileDescriptor, file_descriptor_count: usize, timeout: s32) usize {
    const result = #syscall(#cast(Syscall.poll), #cast(file_descriptors), file_descriptor_count, #cast(timeout));
    return result;
}

const memfd_create = fn(name: [&:0]const u8, flags: u32) usize {
    const result = #syscall(#cast(Syscall.memfd_create), flags);
    return result;
}

const TimeSpec = struct{
    seconds: s64,
    nanoseconds: s64,
};

const Stat = struct{
    dev: u64,
    inode: u64,
    nlink: u64,

    mode: u32,
    uid: u32,
    gid: u32,
    _: u32,
    rdev: u64,
    size: s64,
    block_size: s64,
    blocks: s64,

    atime: TimeSpec,
    mtime: TimeSpec,
    ctime: TimeSpec,
    _: [3]u64,
};

const fstat = fn(file_descriptor: FileDescriptor, stat_buffer: &Stat) usize {
    const file_descriptor_u: u32 = #cast(file_descriptor);
    const result = #syscall(#cast(Syscall.fstat), file_descriptor_u, #cast(stat_buffer));
    return result;
}

const unwrap_syscall = fn(syscall_result: usize) Error!usize {
    const signed_syscall_result: ssize = #cast(syscall_result);

    if (signed_syscall_result > -4096 and signed_syscall_result < 0) {
        const absolute_error: u64 = #cast(-signed_syscall_result);
        const error_int: u32 = #cast(absolute_error);
        const err: Error = #cast(error_int);
        return err;
    } else {
        return syscall_result;
    }
}

const EventFileDescriptorFlags = enum(u32) {
    semaphore = 1,
    cloexec = 0o2000000,
    nonblock = 0o4000,
};

const PollFileDescriptor = struct{
    file_descriptor: FileDescriptor,
    events: Poll,
    revents: Poll,

    const Poll = bitfield(u16) {
        in: bool = false,
        pri: bool = false,
        out: bool = false,
        err: bool = false,
        hup: bool = false,
        nval: bool = false,
        rdnorm: bool = false,
        rdband: bool = false,
    };
};

const AccessMode = enum(u2) {
    read_only = 0,
    write_only = 1,
    read_write = 2,
};

const OpenFlags = bitfield(u32) {
    access_mode: AccessMode,
    _: u4 = 0,
    creat: bool = false,
    excl: bool = false,
    noctty: bool = false,
    truncate: bool = false,
    append: bool = false,
    non_block: bool = false,
    dsync: bool = false,
    async: bool = false,
    direct: bool = false,
    _: u1 = 0,
    directory: bool = false,
    no_follow: bool = false,
    noatime: bool = false,
    cloexec: bool = false,
    sync: bool = false,
    path: bool = false,
    tmpfile: bool = false,
    _: u9 = 0,
};
