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 };