hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

syscalls.ha (18615B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 fn syscall0(u64) u64;
      5 fn syscall1(u64, u64) u64;
      6 fn syscall2(u64, u64, u64) u64;
      7 fn syscall3(u64, u64, u64, u64) u64;
      8 fn syscall4(u64, u64, u64, u64, u64) u64;
      9 fn syscall5(u64, u64, u64, u64, u64, u64) u64;
     10 fn syscall6(u64, u64, u64, u64, u64, u64, u64) u64;
     11 fn __sigtramp_siginfo_2(u64) u64;
     12 
     13 let pathbuf: [PATH_MAX]u8 = [0...];
     14 
     15 // The use of this function is discouraged, as it can create race conditions.
     16 // TOCTOU is preferred: attempt to simply use the resource you need and handle
     17 // any access errors which occur.
     18 export fn access(path: path, mode: int) (bool | errno) =
     19 	faccessat(AT_FDCWD, path, mode, 0);
     20 
     21 export fn fchdir(fd: int) (void | errno) = {
     22 	wrap_return(syscall1(SYS_fchdir, fd: u64))?;
     23 };
     24 
     25 export fn chdir(path: path) (void | errno) = {
     26 	let path = kpath(path)?;
     27 	wrap_return(syscall1(SYS_chdir, path: uintptr: u64))?;
     28 };
     29 
     30 export fn chroot(path: path) (void | errno) = {
     31 	let path = kpath(path)?;
     32 	wrap_return(syscall1(SYS_chroot, path: uintptr: u64))?;
     33 };
     34 
     35 export fn fchmod(fd: int, mode: uint) (void | errno) = {
     36 	wrap_return(syscall2(SYS_fchmod,
     37 		fd: u64, mode: u64))?;
     38 };
     39 
     40 export fn fchmodat(dirfd: int, path: path, mode: uint, flags: int) (void | errno) = {
     41 	let path = kpath(path)?;
     42 	wrap_return(syscall4(SYS_fchmodat,
     43 		dirfd: u64, path: uintptr: u64, mode: u64, flags: u64))?;
     44 };
     45 
     46 export fn fchown(fd: int, uid: uint, gid: uint) (void | errno) = {
     47 	wrap_return(syscall3(SYS_fchown,
     48 		fd: u64, uid: u32, gid: u32))?;
     49 };
     50 
     51 export fn fchownat(dirfd: int, path: path, uid: uint, gid: uint, flags: int) (void | errno) = {
     52 	let path = kpath(path)?;
     53 	wrap_return(syscall5(SYS_fchownat,
     54 		dirfd: u64, path: uintptr: u64, uid: u32, gid: u32, flags: u64))?;
     55 };
     56 
     57 export fn fstatat(fd: int, path: path, _stat: *st, flag: int) (void | errno) = {
     58 	let path = kpath(path)?;
     59 	let sb = stat { ... };
     60 	wrap_return(syscall4(SYS_fstatat, fd: u64,
     61 		path: uintptr: u64, &sb: uintptr: u64, flag: u64))?;
     62 	_stat.dev = sb.st_dev;
     63 	_stat.ino = sb.st_ino;
     64 	_stat.mode = sb.st_mode;
     65 	_stat.nlink = sb.st_nlink;
     66 	_stat.uid = sb.st_uid;
     67 	_stat.gid = sb.st_gid;
     68 	_stat.rdev = sb.st_rdev;
     69 	_stat.atime.tv_sec = sb.st_atim.tv_sec;
     70 	_stat.atime.tv_nsec = sb.st_atim.tv_nsec: i64;
     71 	_stat.mtime.tv_sec = sb.st_mtim.tv_sec;
     72 	_stat.mtime.tv_nsec = sb.st_mtim.tv_nsec: i64;
     73 	_stat.ctime.tv_sec = sb.st_ctim.tv_sec;
     74 	_stat.ctime.tv_nsec = sb.st_ctim.tv_nsec: i64;
     75 	_stat.btime.tv_sec = sb.st_birthtim.tv_sec;
     76 	_stat.btime.tv_nsec = sb.st_birthtim.tv_nsec: i64;
     77 	_stat.sz = sb.st_size;
     78 	_stat.blocks = sb.st_blocks;
     79 	_stat.blksz = sb.st_blksize;
     80 	_stat.flags = sb.st_flags;
     81 };
     82 
     83 export fn fstatvfs1(fd: int, _statvfs: *statvfs, flag: int) (void | errno) = {
     84 	wrap_return(syscall3(SYS___fstatvfs190, fd: u64,
     85 		_statvfs: uintptr: u64, flag: u64))?;
     86 };
     87 
     88 export fn futimens(fd: int, ts: *[2]timespec) (void | errno) = {
     89 	wrap_return(syscall2(SYS_futimens,
     90 		fd: u64, ts: uintptr: u64))?;
     91 };
     92 
     93 export fn getdents(dirfd: int, buf: *opaque, nbytes: size) (size | errno) = {
     94 	return wrap_return(syscall3(SYS___getdents30, dirfd: u64,
     95 		buf: uintptr: u64, nbytes: u64))?: size;
     96 };
     97 
     98 // The return value is statically allocated and must be duplicated before
     99 // calling getcwd again.
    100 export fn getcwd() (*const u8 | errno) = {
    101 	static let pathbuf: [PATH_MAX]u8 = [0...];
    102 	wrap_return(syscall2(SYS___getcwd,
    103 		&pathbuf: *[*]u8: uintptr: u64,
    104 		PATH_MAX))?;
    105 	return &pathbuf: *const u8;
    106 };
    107 
    108 export fn mkdirat(dirfd: int, path: path, mode: uint) (void | errno) = {
    109 	let path = kpath(path)?;
    110 	wrap_return(syscall3(SYS_mkdirat,
    111 		dirfd: u64, path: uintptr: u64, mode: u64))?;
    112 };
    113 
    114 export fn openat(
    115 	dirfd: int,
    116 	path: path,
    117 	flags: int,
    118 	mode: uint,
    119 ) (int | errno) = {
    120 	let path = kpath(path)?;
    121 	return wrap_return(syscall4(SYS_openat, dirfd: u64,
    122 		path: uintptr: u64, flags: u64, mode: u64))?: int;
    123 };
    124 
    125 export fn readlinkat(
    126 	dirfd: int,
    127 	path: path,
    128 	buf: []u8,
    129 ) (size | errno) = {
    130 	let path = kpath(path)?;
    131 	return wrap_return(syscall4(SYS_readlinkat,
    132 		dirfd: u64, path: uintptr: u64,
    133 		buf: *[*]u8: uintptr: u64,
    134 		len(buf): u64))?: size;
    135 };
    136 
    137 export fn renameat(
    138 	olddirfd: int,
    139 	oldpath: str,
    140 	newdirfd: int,
    141 	newpath: str,
    142 ) (void | errno) = {
    143 	let oldpath = kpath(oldpath)?;
    144 	static let newpathbuf: [PATH_MAX]u8 = [0...];
    145 	let newpath = copy_kpath(newpath, newpathbuf)?;
    146 	wrap_return(syscall4(SYS_renameat,
    147 		olddirfd: u64, oldpath: uintptr: u64,
    148 		newdirfd: u64, newpath: uintptr: u64))?;
    149 };
    150 
    151 export fn sysctl(name: []const u32, oldp: nullable *opaque, oldlenp: nullable *size,
    152 		newp: nullable *const opaque, newlen: size) (void | errno) = {
    153 	wrap_return(syscall6(SYS___sysctl,
    154 		&name[0]: uintptr: u64, len(name): u64,
    155 		oldp: uintptr: u64, oldlenp: uintptr: u64,
    156 		newp: uintptr: u64, newlen: u64))?;
    157 };
    158 
    159 export fn unlink(path: path) (void | errno) = {
    160 	let path = kpath(path)?;
    161 	wrap_return(syscall1(SYS_unlink, path: uintptr: u64))?;
    162 };
    163 
    164 export fn unlinkat(dirfd: int, path: path, flags: int) (void | errno) = {
    165 	let path = kpath(path)?;
    166 	wrap_return(syscall3(SYS_unlinkat,
    167 		dirfd: u64, path: uintptr: u64, flags: u64))?;
    168 };
    169 
    170 export fn utimensat(dirfd: int, path: str, ts: *[2]timespec, flags: int) (void | errno) = {
    171 	let path = kpath(path)?;
    172 	wrap_return(syscall4(SYS_utimensat,
    173 		dirfd: u64, path: uintptr: u64, ts: uintptr: u64, flags: u64))?;
    174 };
    175 
    176 export fn close(fd: int) (void | errno) = {
    177 	wrap_return(syscall1(SYS_close, fd: u64))?;
    178 };
    179 
    180 export fn lseek(fd: int, off: i64, whence: int) (i64 | errno) = {
    181 	return wrap_return(syscall3(SYS_lseek,
    182 		fd: u64, off: u64, whence: u64))?: i64;
    183 };
    184 
    185 export fn dup2(old: int, new: int) (int | errno) =
    186 	wrap_return(syscall2(SYS_dup2, old: u64, new: u64))?: int;
    187 
    188 export fn getpid() pid_t = syscall0(SYS_getpid): pid_t;
    189 
    190 export def EXIT_SUCCESS: int = 0;
    191 
    192 export fn exit(status: int) never = {
    193 	syscall1(SYS_exit, status: u64);
    194 	abort();
    195 };
    196 
    197 export fn fork() (pid_t | void | errno) = {
    198 	let n = wrap_return(syscall0(SYS_fork))?: pid_t;
    199 	switch (n) {
    200 	case 0 =>
    201 		return;
    202 	case =>
    203 		return n;
    204 	};
    205 };
    206 
    207 export fn execve(
    208 	path: *const u8,
    209 	argv: *[*]nullable *const u8,
    210 	envp: *[*]nullable *const u8,
    211 ) int = syscall3(SYS_execve,
    212 	path: uintptr: u64,
    213 	argv: uintptr: u64,
    214 	envp: uintptr: u64): int;
    215 
    216 export fn wait4(
    217 	pid: pid_t,
    218 	wstatus: nullable *int,
    219 	options: int,
    220 	rusage: nullable *rusage,
    221 ) (int | errno) = {
    222 	return wrap_return(syscall4(SYS___wait450,
    223 		pid: u64, wstatus: uintptr: u64,
    224 		options: u64, rusage: uintptr: u64))?: int;
    225 };
    226 
    227 export fn wifexited(status: int) bool = wtermsig(status) == 0;
    228 export fn wexitstatus(status: int) int = (status & 0xff00) >> 8;
    229 
    230 export fn wtermsig(status: int) int = status & 0x7f;
    231 export fn wifsignaled(status: int) bool =
    232 	wtermsig(status) != 0o177 && wtermsig(status) != 0 && status != 0x13;
    233 
    234 export fn kill(pid: pid_t, signal: int) (void | errno) = {
    235 	wrap_return(syscall2(SYS_kill, pid: u64, signal: u64))?;
    236 };
    237 
    238 export fn pipe2(pipefd: *[2]int, flags: int) (void | errno) = {
    239 	wrap_return(syscall2(SYS_pipe2, pipefd: uintptr: u64, flags: u64))?;
    240 };
    241 
    242 export fn mmap(
    243 	addr: nullable *opaque,
    244 	length: size,
    245 	prot: uint,
    246 	flags: uint,
    247 	fd: int,
    248 	offs: size
    249 ) (errno | *opaque) = {
    250 	return wrap_return(syscall6(SYS_mmap, addr: uintptr: u64, length: u64,
    251 		prot: u64, flags: u64, fd: u64, offs: u64)): uintptr: *opaque;
    252 };
    253 
    254 export fn munmap(addr: *opaque, length: size) (void | errno) = {
    255 	wrap_return(syscall2(SYS_munmap, addr: uintptr: u64, length: u64))?;
    256 };
    257 
    258 export type fcntl_arg = (void | int | *st_flock | *u64);
    259 
    260 export fn fcntl(fd: int, cmd: int, arg: fcntl_arg) (int | errno) = {
    261 	let _fd = fd: u64, _cmd = cmd: u64;
    262 	return wrap_return(match (arg) {
    263 	case void =>
    264 		yield syscall2(SYS_fcntl, _fd, _cmd);
    265 	case let i: int =>
    266 		yield syscall3(SYS_fcntl, _fd, _cmd, i: u64);
    267 	case let l: *st_flock =>
    268 		yield syscall3(SYS_fcntl, _fd, _cmd, l: uintptr: u64);
    269 	case let u: *u64 =>
    270 		yield syscall3(SYS_fcntl, _fd, _cmd, u: uintptr: u64);
    271 	})?: int;
    272 };
    273 
    274 export fn read(fd: int, buf: *opaque, count: size) (size | errno) = {
    275 	return wrap_return(syscall3(SYS_read,
    276 		fd: u64, buf: uintptr: u64, count: u64))?: size;
    277 };
    278 
    279 export fn write(fd: int, buf: *const opaque, count: size) (size | errno) = {
    280 	return wrap_return(syscall3(SYS_write,
    281 		fd: u64, buf: uintptr: u64, count: u64))?: size;
    282 };
    283 
    284 export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
    285 	return wrap_return(syscall3(SYS_readv,
    286 		fd: u64, iov: uintptr: u64, iovcnt: u64))?: size;
    287 };
    288 
    289 export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
    290 	return wrap_return(syscall3(SYS_writev,
    291 		fd: u64, iov: uintptr: u64, iovcnt: u64))?: size;
    292 };
    293 
    294 export fn flock(fd: int, op: int) (void | errno) = {
    295 	wrap_return(syscall2(SYS_flock,
    296 		fd: u64, op: u64))?;
    297 };
    298 
    299 export fn ftruncate(fd: int, ln: off_t) (void | errno) = {
    300 	wrap_return(syscall2(SYS_ftruncate, fd: u64, ln: u32))?;
    301 };
    302 
    303 export fn nanosleep(req: *const timespec, rem: *timespec) (void | errno) = {
    304 	wrap_return(syscall2(SYS___nanosleep50,
    305 		req: uintptr: u64, rem: uintptr: u64))?;
    306 };
    307 
    308 export fn clock_gettime(clock_id: int, tp: *timespec) (void | errno) = {
    309 	wrap_return(syscall2(SYS___clock_gettime50,
    310 		clock_id: u64, tp: uintptr: u64))?;
    311 };
    312 
    313 export fn clock_settime(clock_id: int, tp: *const timespec) (void | errno) = {
    314 	wrap_return(syscall2(SYS___clock_settime50,
    315 		clock_id: u64, tp: uintptr: u64))?;
    316 };
    317 
    318 export fn faccessat(
    319 	dirfd: int,
    320 	path: path,
    321 	mode: int,
    322 	flags: int,
    323 ) (bool | errno) = {
    324 	let path = kpath(path)?;
    325 	match (wrap_return(syscall4(SYS_faccessat, dirfd: u64,
    326 		path: uintptr: u64, mode: u64, flags: u64))) {
    327 	case let err: errno =>
    328 		switch (err) {
    329 		case EACCES =>
    330 			return false;
    331 		case =>
    332 			return err;
    333 		};
    334 	case let n: u64 =>
    335 		assert(n == 0);
    336 		return true;
    337 	};
    338 };
    339 
    340 // NUL terminates a string and stores it in a static buffer of PATH_MAX bytes in
    341 // length.
    342 fn kpath(path: path) (*const u8 | errno) = {
    343 	return copy_kpath(path, pathbuf);
    344 };
    345 
    346 fn copy_kpath(path: path, buf: []u8) (*const u8 | errno) = {
    347 	let path = match (path) {
    348 	case let c: *const u8 =>
    349 		return c;
    350 	case let s: str =>
    351 		let ptr = &s: *struct {
    352 			buf: *[*]u8,
    353 			length: size,
    354 			capacity: size,
    355 		};
    356 		yield ptr.buf[..ptr.length];
    357 	case let b: []u8 =>
    358 		yield b;
    359 	};
    360 	if (len(path) + 1 >= len(pathbuf)) {
    361 		return ENAMETOOLONG;
    362 	};
    363 	memcpy(buf: *[*]u8, path: *[*]u8, len(path));
    364 	buf[len(path)] = 0;
    365 	return buf: *[*]u8: *const u8;
    366 };
    367 
    368 export fn getgroups(gids: []gid_t) (uint | errno) = {
    369 	return wrap_return(syscall2(SYS_getgroups,
    370 		len(gids): u64, gids: *[*]gid_t: uintptr: u64))?: uint;
    371 };
    372 
    373 export fn setgroups(gids: []gid_t) (void | errno) = {
    374 	wrap_return(syscall2(SYS_setgroups,
    375 		len(gids): u64, gids: *[*]gid_t: uintptr: u64))?;
    376 };
    377 
    378 export fn getppid() pid_t = syscall0(SYS_getppid): pid_t;
    379 
    380 export fn getpgrp() pid_t = syscall0(SYS_getpgrp): pid_t;
    381 
    382 export fn getsid(pid: pid_t) (pid_t | errno) = {
    383 	return wrap_return(syscall1(SYS_getsid, pid))?: pid_t;
    384 };
    385 
    386 export fn getpriority(which: int, who: id_t) (int | errno) = {
    387 	return wrap_return(syscall2(SYS_getpriority,
    388 		which: u64, who: u64))?: int;
    389 };
    390 
    391 export fn setpriority(which: int, who: id_t, prio: int) (void | errno) = {
    392 	wrap_return(syscall3(SYS_setpriority, which: u64, who: u64, prio: u64))?;
    393 };
    394 
    395 export fn umask(mode: mode_t) (mode_t | errno) = {
    396 	return wrap_return(syscall1(SYS_umask, mode: u64))?: mode_t;
    397 };
    398 
    399 export fn getuid() (uid_t | errno) = {
    400 	return wrap_return(syscall0(SYS_getuid))?: uid_t;
    401 };
    402 
    403 export fn geteuid() (uid_t | errno) = {
    404 	return wrap_return(syscall0(SYS_geteuid))?: uid_t;
    405 };
    406 
    407 export fn getgid() (gid_t | errno) = {
    408 	return wrap_return(syscall0(SYS_getgid))?: gid_t;
    409 };
    410 
    411 export fn getegid() (gid_t | errno) = {
    412 	return wrap_return(syscall0(SYS_getegid))?: gid_t;
    413 };
    414 
    415 export fn setuid(uid: *uid_t) (void | errno) = {
    416 	wrap_return(syscall1(SYS_setuid,
    417 		uid: uintptr: u64))?;
    418 };
    419 
    420 export fn seteuid(euid: *uid_t) (void | errno) = {
    421 	wrap_return(syscall1(SYS_seteuid,
    422 		euid: uintptr: u64))?;
    423 };
    424 
    425 export fn setgid(gid: *gid_t) (void | errno) = {
    426 	wrap_return(syscall1(SYS_setgid,
    427 		gid: uintptr: u64))?;
    428 };
    429 
    430 export fn setegid(egid: *gid_t) (void | errno) = {
    431 	wrap_return(syscall1(SYS_setegid,
    432 		egid: uintptr: u64))?;
    433 };
    434 
    435 export fn sigaction(
    436 	signum: int,
    437 	act: *const sigact,
    438 	old: nullable *sigact,
    439 ) (int | errno) = {
    440 	return wrap_return(syscall5(SYS___sigaction_sigtramp,
    441 		signum: u64, act: uintptr: u64, old: uintptr: u64,
    442 		&__sigtramp_siginfo_2: uintptr: u64,
    443 		__SIGTRAMP_SIGINFO_VERSION: u64))?: int;
    444 };
    445 
    446 export fn sigprocmask(
    447 	how: int,
    448 	set: nullable *const sigset,
    449 	old: nullable *sigset,
    450 ) (int | errno) = {
    451 	return wrap_return(syscall3(SYS___sigprocmask14,
    452 		how: u64, set: uintptr: u64, old: uintptr: u64))?: int;
    453 };
    454 
    455 export fn open(
    456 	path: path,
    457 	flags: int,
    458 	mode: uint,
    459 ) (int | errno) = {
    460 	let path = kpath(path)?;
    461 	return wrap_return(syscall3(SYS_open,
    462 		path: uintptr: u64, flags: u64, mode: u64))?: int;
    463 };
    464 
    465 export fn fstat(fd: int, _stat: *st) (void | errno) = {
    466 	let sb = stat { ... };
    467 	wrap_return(syscall2(SYS___fstat50, fd: u64,
    468 		&sb: uintptr: u64))?;
    469 	_stat.dev = sb.st_dev;
    470 	_stat.ino = sb.st_ino;
    471 	_stat.mode = sb.st_mode;
    472 	_stat.nlink = sb.st_nlink;
    473 	_stat.uid = sb.st_uid;
    474 	_stat.gid = sb.st_gid;
    475 	_stat.rdev = sb.st_rdev;
    476 	_stat.atime.tv_sec = sb.st_atim.tv_sec;
    477 	_stat.atime.tv_nsec = sb.st_atim.tv_nsec: i64;
    478 	_stat.mtime.tv_sec = sb.st_mtim.tv_sec;
    479 	_stat.mtime.tv_nsec = sb.st_mtim.tv_nsec: i64;
    480 	_stat.ctime.tv_sec = sb.st_ctim.tv_sec;
    481 	_stat.ctime.tv_nsec = sb.st_ctim.tv_nsec: i64;
    482 	_stat.btime.tv_sec = sb.st_birthtim.tv_sec;
    483 	_stat.btime.tv_nsec = sb.st_birthtim.tv_nsec: i64;
    484 	_stat.sz = sb.st_size;
    485 	_stat.blocks = sb.st_blocks;
    486 	_stat.blksz = sb.st_blksize;
    487 	_stat.flags = sb.st_flags;
    488 };
    489 
    490 export fn fexecve(fd: int, argv: *[*]nullable *const u8,
    491 		envp: *[*]nullable *const u8) errno = {
    492 	return match (wrap_return(syscall3(SYS_fexecve, fd: u64,
    493 		argv: uintptr: u64, envp: uintptr: u64))) {
    494 	case let err: errno =>
    495 		yield err;
    496 	case u64 =>
    497 		abort("unreachable");
    498 	};
    499 };
    500 
    501 export type ioctl_arg = (nullable *opaque | u64);
    502 
    503 export fn ioctl(fd: int, req: u64, arg: ioctl_arg) (int | errno) = {
    504 	let fd = fd: u64, req = req: u64;
    505 	return wrap_return(match (arg) {
    506 	case let u: u64 =>
    507 		yield syscall3(SYS_ioctl, fd, req, u);
    508 	case let v: nullable *opaque =>
    509 		yield syscall3(SYS_ioctl, fd, req, v: uintptr: u64);
    510 	})?: int;
    511 };
    512 
    513 export fn posix_openpt(flags: int) (int | errno) = {
    514 	return open("/dev/ptmx", flags, 0);
    515 };
    516 
    517 export fn sigaltstack(
    518 	ss: nullable *stack_t,
    519 	old_ss: nullable *stack_t,
    520 ) (void | errno) = {
    521 	wrap_return(syscall2(SYS___sigaltstack14,
    522 		ss: uintptr: u64, old_ss: uintptr: u64))?;
    523 };
    524 
    525 export fn ppoll(
    526 	fds: *[*]pollfd,
    527 	nfds: nfds_t,
    528 	timeout: const nullable *timespec,
    529 	sigmask: const nullable *sigset,
    530 ) (int | errno) = {
    531 	return wrap_return(syscall4(SYS___pollts50, fds: uintptr: u64,
    532 		nfds: u64, timeout: uintptr: u64,
    533 		sigmask: uintptr: u64))?: int;
    534 };
    535 
    536 export fn getrandom(buf: *opaque, bufln: size, flags: uint) (size | errno) = {
    537 	return wrap_return(syscall3(SYS_getrandom,
    538 		buf: uintptr: u64, bufln: u64, flags: u64))?: size;
    539 };
    540 
    541 export fn paccept(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32, mask: nullable *int, flags: int) (int | errno) = {
    542 	return wrap_return(syscall5(SYS_paccept, sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64, mask: uintptr: u64, flags: u64))?: int;
    543 };
    544 
    545 export fn accept4(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32, flags: int) (int | errno) = {
    546 	return paccept(sockfd, addr, addrlen, null, flags);
    547 };
    548 
    549 export fn sendmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = {
    550 	return wrap_return(syscall3(SYS_sendmsg,
    551 		fd: u64, msg: uintptr: u64, flags: u64))?: int;
    552 };
    553 
    554 export fn recvmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = {
    555 	return wrap_return(syscall3(SYS_recvmsg,
    556 		fd: u64, msg: uintptr: u64, flags: u64))?: int;
    557 };
    558 
    559 export fn shutdown(sockfd: int, how: int) (void | errno) = {
    560 	wrap_return(syscall2(SYS_shutdown,
    561 		sockfd: u64, how: u64))?;
    562 };
    563 
    564 export fn socket(domain: int, type_: int, protocol: int) (int | errno) = {
    565 	return wrap_return(syscall3(SYS___socket30,
    566 		domain: u64, type_: u64, protocol: u64))?: int;
    567 };
    568 
    569 export fn connect(sockfd: int, addr: *const sockaddr, addrlen: u32) (int | errno) = {
    570 	return wrap_return(syscall3(SYS_connect,
    571 		sockfd: u64, addr: uintptr: u64, addrlen: u64))?: int;
    572 };
    573 
    574 export fn bind(sockfd: int, addr: *const sockaddr, addrlen: u32) (int | errno) = {
    575 	return wrap_return(syscall3(SYS_bind,
    576 		sockfd: u64, addr: uintptr: u64, addrlen: u64))?: int;
    577 };
    578 
    579 export fn getsockname(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = {
    580 	return wrap_return(syscall3(SYS_getsockname,
    581 		sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int;
    582 };
    583 
    584 export fn send(sockfd: int, buf: *opaque, len_: size, flags: int) (size | errno) = {
    585 	return sendto(sockfd, buf, len_, flags, null, 0);
    586 };
    587 
    588 export fn sendto(sockfd: int, buf: *opaque, len_: size, flags: int,
    589 	dest_addr: nullable *sockaddr, addrlen: u32
    590 ) (size | errno) = {
    591 	return wrap_return(syscall6(SYS_sendto,
    592 		sockfd: u64, buf: uintptr: u64, len_: u64, flags: u64,
    593 		dest_addr: uintptr: u64, addrlen: u64))?: size;
    594 };
    595 
    596 export fn recv(sockfd: int, buf: *opaque, len_: size, flags: int) (size | errno) = {
    597 	return recvfrom(sockfd, buf, len_, flags, null, null);
    598 };
    599 
    600 export fn setsockopt(sockfd: int, level: int, optname: int, optval: *opaque, optlen: u32) (int | errno) = {
    601 	return wrap_return(syscall5(SYS_setsockopt,
    602 		sockfd: u64, level: u64, optname: u64,
    603 		optval: uintptr: u64, optlen: u64))?: int;
    604 };
    605 
    606 export fn recvfrom(sockfd: int, buf: *opaque, len_: size, flags: int,
    607 	src_addr: nullable *sockaddr, addrlen: nullable *u32
    608 ) (size | errno) = {
    609 	return wrap_return(syscall6(SYS_recvfrom,
    610 		sockfd: u64, buf: uintptr: u64, len_: u64, flags: u64,
    611 		src_addr: uintptr: u64, addrlen: uintptr: u64))?: size;
    612 };
    613 
    614 export fn listen(sockfd: int, backlog: u32) (int | errno) = {
    615 	return wrap_return(syscall2(SYS_listen,
    616 		sockfd: u64, backlog: u64))?: int;
    617 };
    618 
    619 export fn getpeername(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = {
    620 	return wrap_return(syscall3(SYS_getpeername,
    621 		sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int;
    622 };
    623 
    624 export fn socketpair(
    625 	domain: int,
    626 	type_: int,
    627 	protocol: int,
    628 	sv: *[*]int,
    629 ) (int | errno) = {
    630 	return wrap_return(syscall4(SYS_socketpair, domain: u64,
    631 		type_: u64, protocol: u64, sv: uintptr : u64))?: int;
    632 };
    633 
    634 export fn fsync(fd: int) (void | errno) = {
    635 	wrap_return(syscall1(SYS_fsync, fd: u64))?;
    636 };
    637 
    638 export fn fdatasync(fd: int) (void | errno) = {
    639 	wrap_return(syscall1(SYS_fdatasync, fd: u64))?;
    640 };