nativity/lib/std/os/linux.nat
2024-04-20 08:25:31 -06:00

1053 lines
22 KiB
Plaintext

const std = #import("std");
const stdin: FileDescriptor = 0;
const stdout: FileDescriptor = 1;
const stderr: FileDescriptor = 2;
const Syscall = switch (#import("builtin").cpu) {
.x86_64 => Syscall_x86_64,
else => #error("Architecture not supported"),
};
const ProcessId = s32;
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 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 {
const result = #syscall(#cast(Syscall.readlink), #cast(file_path), #cast(bytes.pointer), bytes.length);
return result;
}
const fork = fn() usize {
const result = #syscall(#cast(Syscall.fork));
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);
const result = #syscall(#cast(Syscall.open), #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,
};