syscalls.ha (26791B)
1 // License: MPL-2.0 2 // (c) 2021 Alexey Yerin <yyp@disroot.org> 3 // (c) 2021 Drew DeVault <sir@cmpwn.com> 4 // (c) 2021 Ember Sawady <ecs@d2evs.net> 5 // (c) 2021 Mykyta Holubakha <hilobakho@gmail.com> 6 // (c) 2021 Thomas Bracht Laumann Jespersen <t@laumann.xyz> 7 // (c) 2022 Vincent Dagonneau <v@vda.io> 8 9 fn syscall0(u64) u64; 10 fn syscall1(u64, u64) u64; 11 fn syscall2(u64, u64, u64) u64; 12 fn syscall3(u64, u64, u64, u64) u64; 13 fn syscall4(u64, u64, u64, u64, u64) u64; 14 fn syscall5(u64, u64, u64, u64, u64, u64) u64; 15 fn syscall6(u64, u64, u64, u64, u64, u64, u64) u64; 16 17 export def PATH_MAX: size = 4096z; 18 export type path = (str | []u8 | *const u8); 19 let pathbuf: [PATH_MAX + 1]u8 = [0...]; 20 21 fn copy_kpath(path: path, buf: []u8) (*const u8 | errno) = { 22 let path = match (path) { 23 case let c: *const u8 => 24 return c; 25 case let s: str => 26 let ptr = &s: *struct { 27 buf: *[*]u8, 28 length: size, 29 capacity: size, 30 }; 31 yield ptr.buf[..ptr.length]; 32 case let b: []u8 => 33 yield b; 34 }; 35 if (len(path) + 1 >= len(pathbuf)) { 36 return ENAMETOOLONG; 37 }; 38 memcpy(buf: *[*]u8, path: *[*]u8, len(path)); 39 buf[len(path)] = 0; 40 return buf: *[*]u8: *const u8; 41 }; 42 43 // NUL terminates a string and stores it in a static buffer of PATH_MAX+1 bytes 44 // in length. 45 fn kpath(path: path) (*const u8 | errno) = { 46 return copy_kpath(path, pathbuf); 47 }; 48 49 export fn read(fd: int, buf: *void, count: size) (size | errno) = { 50 return wrap_return(syscall3(SYS_read, 51 fd: u64, buf: uintptr: u64, count: u64))?: size; 52 }; 53 54 export fn write(fd: int, buf: *const void, count: size) (size | errno) = { 55 return wrap_return(syscall3(SYS_write, 56 fd: u64, buf: uintptr: u64, count: u64))?: size; 57 }; 58 59 export fn open(path: path, flags: int, mode: uint) (int | errno) = { 60 let path = kpath(path)?; 61 return wrap_return(syscall4(SYS_openat, AT_FDCWD: u64, 62 path: uintptr: u64, flags: u64, mode: u64))?: int; 63 }; 64 65 fn openat( 66 dirfd: int, 67 path: path, 68 flags: int, 69 mode: uint, 70 ) (int | errno) = { 71 let path = kpath(path)?; 72 return wrap_return(syscall4(SYS_openat, dirfd: u64, 73 path: uintptr: u64, flags: u64, mode: u64))?: int; 74 }; 75 76 export fn openat2( 77 dirfd: int, 78 path: path, 79 how: *open_how, 80 how_sz: size, 81 ) (int | errno) = { 82 let path = kpath(path)?; 83 return openat(dirfd, path, how.flags: int, how.mode: uint); 84 }; 85 86 export fn readlinkat( 87 dirfd: int, 88 path: path, 89 buf: []u8, 90 ) (size | errno) = { 91 let path = kpath(path)?; 92 return wrap_return(syscall4(SYS_readlinkat, 93 dirfd: u64, path: uintptr: u64, 94 buf: *[*]u8: uintptr: u64, 95 len(buf): u64))?: size; 96 }; 97 98 export fn unlink(path: path) (void | errno) = { 99 let path = kpath(path)?; 100 wrap_return(syscall3(SYS_unlinkat, 101 AT_FDCWD: u64, path: uintptr: u64, 0u64))?; 102 }; 103 104 export fn unlinkat(dirfd: int, path: path, flags: int) (void | errno) = { 105 let path = kpath(path)?; 106 wrap_return(syscall3(SYS_unlinkat, 107 dirfd: u64, path: uintptr: u64, flags: u64))?; 108 }; 109 110 export fn linkat( 111 olddirfd: int, 112 oldpath: path, 113 newdirfd: int, 114 newpath: path, 115 flags: int, 116 ) (void | errno) = { 117 let oldpath = kpath(oldpath)?; 118 static let newpathbuf: [PATH_MAX + 1]u8 = [0...]; 119 let newpath = copy_kpath(newpath, newpathbuf)?; 120 wrap_return(syscall5(SYS_linkat, 121 olddirfd: u64, oldpath: uintptr: u64, 122 newdirfd: u64, newpath: uintptr: u64, flags: u64))?; 123 }; 124 125 export fn symlinkat( 126 target: path, 127 newdirfd: int, 128 linkpath: path, 129 ) (void | errno) = { 130 let target = kpath(target)?; 131 static let linkpathbuf: [PATH_MAX + 1]u8 = [0...]; 132 let linkpath = copy_kpath(linkpath, linkpathbuf)?; 133 wrap_return(syscall3(SYS_symlinkat, target: uintptr: u64, 134 newdirfd: u64, linkpath: uintptr: u64))?; 135 }; 136 137 export fn mknodat( 138 dirfd: int, 139 path: path, 140 mode: mode_t, 141 dev: dev_t, 142 ) (void | errno) = { 143 let path = kpath(path)?; 144 wrap_return(syscall4(SYS_mknodat, 145 dirfd: u64, path: uintptr: u64, mode: u64, dev: u64))?; 146 }; 147 148 export fn chmod(path: path, mode: uint) (void | errno) = { 149 let path = kpath(path)?; 150 wrap_return(syscall4(SYS_fchmodat, 151 AT_FDCWD: u64, path: uintptr: u64, mode: u64, 0))?; 152 }; 153 154 export fn fchmodat(dirfd: int, path: path, mode: uint, flags: int) (void | errno) = { 155 let path = kpath(path)?; 156 wrap_return(syscall4(SYS_fchmodat, 157 dirfd: u64, path: uintptr: u64, mode: u64, flags: u64))?; 158 }; 159 160 export fn chown(path: path, uid: uint, gid: uint) (void | errno) = { 161 let path = kpath(path)?; 162 wrap_return(syscall5(SYS_fchownat, 163 AT_FDCWD: u64, path: uintptr: u64, uid: u32, gid: u32, 0))?; 164 }; 165 166 export fn fchownat(dirfd: int, path: path, uid: uint, gid: uint, flags: int) (void | errno) = { 167 let path = kpath(path)?; 168 wrap_return(syscall5(SYS_fchownat, 169 dirfd: u64, path: uintptr: u64, uid: u32, gid: u32, flags: u64))?; 170 }; 171 172 export fn renameat( 173 olddirfd: int, 174 oldpath: path, 175 newdirfd: int, 176 newpath: path, 177 flags: uint, 178 ) (void | errno) = { 179 let oldpath = kpath(oldpath)?; 180 static let newpathbuf: [PATH_MAX + 1]u8 = [0...]; 181 let newpath = copy_kpath(newpath, newpathbuf)?; 182 wrap_return(syscall5(SYS_renameat2, 183 olddirfd: u64, oldpath: uintptr: u64, 184 newdirfd: u64, newpath: uintptr: u64, 185 flags: u64))?; 186 }; 187 188 export fn dup(fd: int) (int | errno) = { 189 return wrap_return(syscall1(SYS_dup, fd: u64))?: int; 190 }; 191 192 export fn dup2(oldfd: int, newfd: int) (int | errno) = { 193 return dup3(oldfd, newfd, 0); 194 }; 195 196 export fn dup3(oldfd: int, newfd: int, flags: int) (int | errno) = { 197 return wrap_return(syscall3(SYS_dup3, 198 oldfd: u64, newfd: u64, flags: u64))?: int; 199 }; 200 201 export fn close(fd: int) (void | errno) = { 202 wrap_return(syscall1(SYS_close, fd: u64))?; 203 }; 204 205 export fn chdir(path: path) (void | errno) = { 206 let path = kpath(path)?; 207 wrap_return(syscall1(SYS_chdir, path: uintptr: u64))?; 208 }; 209 210 export fn fchdir(fd: int) (void | errno) = { 211 wrap_return(syscall1(SYS_fchdir, fd: u64))?; 212 }; 213 214 export fn chroot(path: path) (void | errno) = { 215 let path = kpath(path)?; 216 wrap_return(syscall1(SYS_chroot, path: uintptr: u64))?; 217 }; 218 219 export fn mkdir(path: path, mode: uint) (void | errno) = { 220 let path = kpath(path)?; 221 wrap_return(syscall3(SYS_mkdirat, AT_FDCWD: u64, 222 path: uintptr: u64, mode: u64))?; 223 }; 224 225 export fn mkdirat(dirfd: int, path: path, mode: uint) (void | errno) = { 226 let path = kpath(path)?; 227 wrap_return(syscall3(SYS_mkdirat, 228 dirfd: u64, path: uintptr: u64, mode: u64))?; 229 }; 230 231 export fn execveat(dirfd: int, path: path, argv: *[*]nullable *const u8, 232 envp: *[*]nullable *const u8, flags: int) errno = { 233 let path = kpath(path)?; 234 return match (wrap_return(syscall5(SYS_execveat, dirfd: u64, 235 path: uintptr: u64, argv: uintptr: u64, 236 envp: uintptr: u64, flags: u64))) { 237 case let err: errno => 238 yield err; 239 case u64 => 240 abort("unreachable"); 241 }; 242 }; 243 244 export fn execve(path: path, argv: *[*]nullable *const u8, 245 envp: *[*]nullable *const u8) errno = { 246 let path = kpath(path)?; 247 return match (wrap_return(syscall3(SYS_execve, path: uintptr: u64, 248 argv: uintptr, envp: uintptr))) { 249 case let err: errno => 250 yield err; 251 case u64 => 252 abort("unreachable"); 253 }; 254 }; 255 256 // Returns the new PID to the parent, void to the child, or errno if something 257 // goes wrong. 258 export fn fork() (int | void | errno) = clone(null, SIGCHLD, null, null, 0); 259 260 export fn getpid() int = syscall0(SYS_getpid): int; 261 262 export fn wait4( 263 pid: int, 264 wstatus: nullable *int, 265 options: int, 266 rusage: nullable *rusage, 267 ) (int | errno) = { 268 return wrap_return(syscall4(SYS_wait4, 269 pid: u64, wstatus: uintptr: u64, 270 options: u64, rusage: uintptr: u64))?: int; 271 }; 272 273 export fn sendfile( 274 out: int, 275 in: int, 276 offs: nullable *size, 277 count: size, 278 ) (size | errno) = wrap_return(syscall4(SYS_sendfile, 279 out: u64, in: u64, offs: uintptr: u64, count: u64))?: size; 280 281 export @noreturn fn exit(status: int) void = { 282 syscall1(SYS_exit_group, status: u64); 283 }; 284 285 export fn kill(pid: int, signal: int) (void | errno) = { 286 wrap_return(syscall2(SYS_kill, pid: u64, signal: u64))?; 287 }; 288 289 export fn pipe2(pipefd: *[2]int, flags: int) (void | errno) = { 290 wrap_return(syscall2(SYS_pipe2, pipefd: uintptr: u64, flags: u64))?; 291 }; 292 293 export fn mmap( 294 addr: nullable *void, 295 length: size, 296 prot: uint, 297 flags: uint, 298 fd: int, 299 offs: size 300 ) (*void | errno) = { 301 let r = syscall6(SYS_mmap, addr: uintptr: u64, 302 length: u64, prot: u64, flags: u64, fd: u64, offs: u64); 303 match (wrap_return(r)) { 304 case let err: errno => 305 if (err == -EPERM && addr == null && (flags & MAP_ANON) > 0 306 && (flags & MAP_FIXED) == 0) { 307 // Fix up incorrect EPERM from kernel: 308 return wrap_errno(ENOMEM); 309 }; 310 return err; 311 case let n: u64 => 312 return n: uintptr: *void; 313 }; 314 }; 315 316 export fn mremap( 317 old_addr: *void, 318 old_len: size, 319 new_len: size, 320 flags: uint, 321 new_addr: nullable *void, 322 ) (*void | errno) = { 323 let r = syscall5(SYS_mremap, old_addr: uintptr: u64, old_len: u64, 324 new_len: u64, flags: u64, new_addr: uintptr: u64); 325 return wrap_return(r)?: uintptr: *void; 326 }; 327 328 export fn munmap(addr: *void, length: size) (void | errno) = { 329 wrap_return(syscall2(SYS_munmap, 330 addr: uintptr: u64, length: u64))?; 331 }; 332 333 export fn mprotect(addr: *void, length: size, prot: uint) (void | errno) = { 334 wrap_return(syscall3(SYS_mprotect, 335 addr: uintptr: u64, length: u64, prot: u64))?; 336 }; 337 338 export fn lseek(fd: int, off: i64, whence: int) (i64 | errno) = { 339 return wrap_return(syscall3(SYS_lseek, 340 fd: u64, off: u64, whence: u64))?: i64; 341 }; 342 343 export fn ftruncate(fd: int, ln: off_t) (void | errno) = { 344 wrap_return(syscall2(SYS_ftruncate, fd: u64, ln: u32))?; 345 }; 346 347 fn faccessat1(dirfd: int, path: *const u8, mode: int) (bool | errno) = { 348 return match (wrap_return(syscall3(SYS_faccessat, dirfd: u64, 349 path: uintptr: u64, mode: u64))) { 350 case let err: errno => 351 yield switch (err) { 352 case EACCES => 353 yield false; 354 case => 355 yield err; 356 }; 357 case let n: u64 => 358 assert(n == 0); 359 yield true; 360 }; 361 }; 362 363 // The use of this function is discouraged, as it can create race conditions. 364 // TOCTOU is preferred: attempt to simply use the resource you need and handle 365 // any access errors which occur. 366 export fn faccessat( 367 dirfd: int, 368 path: path, 369 mode: int, 370 flags: int, 371 ) (bool | errno) = { 372 let path = kpath(path)?; 373 match (wrap_return(syscall4(SYS_faccessat2, dirfd: u64, 374 path: uintptr: u64, mode: u64, flags: u64))) { 375 case let err: errno => 376 switch (err) { 377 case EACCES => 378 return false; 379 case ENOSYS => 380 if (flags == 0) { 381 return faccessat1(dirfd, path, mode); 382 } else { 383 return err; 384 }; 385 case => 386 return err; 387 }; 388 case let n: u64 => 389 assert(n == 0); 390 return true; 391 }; 392 }; 393 394 export fn getdents64(dirfd: int, dirp: *void, count: size) (size | errno) = { 395 return wrap_return(syscall3(SYS_getdents64, dirfd: u64, 396 dirp: uintptr: u64, count: u64))?: size; 397 }; 398 399 // The use of this function is discouraged, as it can create race conditions. 400 // TOCTOU is preferred: attempt to simply use the resource you need and handle 401 // any access errors which occur. 402 export fn access(path: path, mode: int) (bool | errno) = 403 faccessat(AT_FDCWD, path, mode, 0); 404 405 export type fcntl_arg = (void | int | *st_flock | *f_owner_ex | *u64); 406 407 export fn fcntl(fd: int, cmd: int, arg: fcntl_arg) (int | errno) = { 408 let _fd = fd: u64, _cmd = cmd: u64; 409 return wrap_return(match (arg) { 410 case void => 411 yield syscall2(SYS_fcntl, _fd, _cmd); 412 case let i: int => 413 yield syscall3(SYS_fcntl, _fd, _cmd, i: u64); 414 case let l: *st_flock => 415 yield syscall3(SYS_fcntl, _fd, _cmd, l: uintptr: u64); 416 case let o: *f_owner_ex => 417 yield syscall3(SYS_fcntl, _fd, _cmd, o: uintptr: u64); 418 case let u: *u64 => 419 yield syscall3(SYS_fcntl, _fd, _cmd, u: uintptr: u64); 420 })?: int; 421 }; 422 423 export fn getrandom(buf: *void, bufln: size, flags: uint) (size | errno) = { 424 return wrap_return(syscall3(SYS_getrandom, 425 buf: uintptr: u64, bufln: u64, flags: u64))?: size; 426 }; 427 428 export fn clock_gettime(clock_id: int, tp: *timespec) (void | errno) = { 429 wrap_return(syscall2(SYS_clock_gettime, 430 clock_id: u64, tp: uintptr: u64))?; 431 }; 432 433 export fn nanosleep(req: *const timespec, rem: *timespec) (void | errno) = { 434 wrap_return(syscall2(SYS_nanosleep, 435 req: uintptr: u64, rem: uintptr: u64))?; 436 }; 437 438 export fn uname(uts: *utsname) (void | errno) = { 439 wrap_return(syscall1(SYS_uname, uts: uintptr: u64))?; 440 }; 441 442 // The return value is statically allocated and must be duplicated before 443 // calling getcwd again. 444 export fn getcwd() (*const u8 | errno) = { 445 static let pathbuf: [PATH_MAX + 1]u8 = [0...]; 446 wrap_return(syscall2(SYS_getcwd, 447 &pathbuf: *[*]u8: uintptr: u64, 448 PATH_MAX + 1))?; 449 return &pathbuf: *const u8; 450 }; 451 452 export fn ppoll( 453 fds: *[*]pollfd, 454 nfds: nfds_t, 455 timeout: const nullable *timespec, 456 sigmask: const nullable *sigset, 457 ) (int | errno) = { 458 return wrap_return(syscall4(SYS_ppoll, fds: uintptr: u64, nfds: u64, 459 timeout: uintptr: u64, sigmask: uintptr: u64))?: int; 460 }; 461 462 export fn poll(fds: *[*]pollfd, nfds: nfds_t, timeout: int) (int | errno) = { 463 const ts = timespec { 464 tv_sec = timeout % 1000, 465 tv_nsec = timeout * 1000000, 466 }; 467 return ppoll(fds, nfds, (if (timeout != -1) &ts else null), null); 468 }; 469 470 export fn epoll_create1(flags: int) (int | errno) = { 471 return wrap_return(syscall1(SYS_epoll_create1, flags: u64))?: int; 472 }; 473 474 export fn epoll_create(size_: int) (int | errno) = { 475 return epoll_create1(0); 476 }; 477 478 export fn epoll_ctl( 479 epfd: int, 480 op: int, 481 fd: int, 482 event: nullable *epoll_event 483 ) (void | errno) = { 484 wrap_return(syscall4(SYS_epoll_ctl, 485 epfd: u64, op: u64, fd: u64, event: uintptr: u64))?; 486 }; 487 488 export fn epoll_pwait( 489 epfd: int, 490 events: *epoll_event, 491 maxevents: int, 492 timeout: int, 493 sigmask: nullable *sigset 494 ) (int | errno) = { 495 return wrap_return(syscall6(SYS_epoll_pwait, 496 epfd: u64, events: uintptr: u64, 497 maxevents: u64, timeout: u64, 498 sigmask: uintptr: u64, size(sigset): u64))?: int; 499 }; 500 501 export fn epoll_wait( 502 epfd: int, 503 events: *epoll_event, 504 maxevents: int, 505 timeout: int, 506 ) (int | errno) = { 507 return epoll_pwait(epfd, events, maxevents, timeout, null); 508 }; 509 510 export fn timerfd_create(clock_id: int, flags: int) (int | errno) = { 511 return wrap_return(syscall2(SYS_timerfd_create, 512 clock_id: u64, flags: u64))?: int; 513 }; 514 515 export fn eventfd(initval: uint, flags: int) (int | errno) = { 516 return wrap_return(syscall2(SYS_eventfd2, 517 initval: u64, flags: u64))?: int; 518 }; 519 520 export fn timerfd_settime( 521 fd: int, 522 flags: int, 523 new_value: *const itimerspec, 524 old_value: nullable *itimerspec 525 ) (int | errno) = { 526 return wrap_return(syscall4(SYS_timerfd_settime, 527 fd: u64, flags: u64, 528 new_value: uintptr: u64, old_value: uintptr: u64))?: int; 529 }; 530 531 export fn timerfd_gettime(fd: int, curr_value: *itimerspec) (int | errno) = { 532 return wrap_return(syscall2(SYS_timerfd_gettime, 533 fd: u64, curr_value: uintptr: u64))?: int; 534 }; 535 536 export fn signalfd(fd: int, mask: *const sigset, flags: int) (int | errno) = { 537 return wrap_return(syscall4(SYS_signalfd4, 538 fd: u64, mask: uintptr: u64, size(sigset): u64, 539 flags: u64))?: int; 540 }; 541 542 export fn sigprocmask( 543 how: int, 544 set: nullable *const sigset, 545 old: nullable *sigset 546 ) (int | errno) = { 547 return wrap_return(syscall4(SYS_rt_sigprocmask, 548 how: u64, set: uintptr: u64, old: uintptr: u64, 549 size(sigset): u64))?: int; 550 }; 551 552 fn restore() void; 553 fn restore_si() void; 554 555 export fn sigaction( 556 signum: int, 557 act: *const sigact, 558 old: nullable *sigact 559 ) (int | errno) = { 560 let real_act = *act; 561 real_act.sa_flags |= SA_RESTORER; 562 let restore_fn = if ((act.sa_flags & SA_SIGINFO) != 0) &restore_si else &restore; 563 real_act.sa_restorer = &restore; 564 return wrap_return(syscall4(SYS_rt_sigaction, 565 signum: u64, &real_act: uintptr: u64, old: uintptr: u64, 566 size(sigset): u64))?: int; 567 }; 568 569 export fn socket(domain: int, type_: int, protocol: int) (int | errno) = { 570 return wrap_return(syscall3(SYS_socket, 571 domain: u64, type_: u64, protocol: u64))?: int; 572 }; 573 574 export fn socketpair( 575 domain: int, 576 type_: int, 577 protocol: int, 578 sv: *[2]int 579 ) (int | errno) = { 580 return wrap_return(syscall4(SYS_socketpair, domain: u64, 581 type_: u64, protocol: u64, sv: uintptr : u64))?: int; 582 }; 583 584 export fn connect(sockfd: int, addr: *const sockaddr, addrlen: u32) (int | errno) = { 585 return wrap_return(syscall3(SYS_connect, 586 sockfd: u64, addr: uintptr: u64, addrlen: u64))?: int; 587 }; 588 589 export fn bind(sockfd: int, addr: *const sockaddr, addrlen: u32) (int | errno) = { 590 return wrap_return(syscall3(SYS_bind, 591 sockfd: u64, addr: uintptr: u64, addrlen: u64))?: int; 592 }; 593 594 export fn listen(sockfd: int, backlog: u32) (int | errno) = { 595 return wrap_return(syscall2(SYS_listen, 596 sockfd: u64, backlog: u64))?: int; 597 }; 598 599 export fn accept(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = { 600 return wrap_return(syscall3(SYS_accept, 601 sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int; 602 }; 603 604 export fn accept4(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32, flags: int) (int | errno) = { 605 return wrap_return(syscall4(SYS_accept4, 606 sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64, flags: u64))?: int; 607 }; 608 609 export fn recvfrom(sockfd: int, buf: *void, len_: size, flags: int, 610 src_addr: nullable *sockaddr, addrlen: nullable *u32 611 ) (size | errno) = { 612 return wrap_return(syscall6(SYS_recvfrom, 613 sockfd: u64, buf: uintptr: u64, len_: u64, flags: u64, 614 src_addr: uintptr: u64, addrlen: uintptr: u64))?: size; 615 }; 616 617 export fn sendto(sockfd: int, buf: *void, len_: size, flags: int, 618 dest_addr: nullable *sockaddr, addrlen: u32 619 ) (size | errno) = { 620 return wrap_return(syscall6(SYS_sendto, 621 sockfd: u64, buf: uintptr: u64, len_: u64, flags: u64, 622 dest_addr: uintptr: u64, addrlen: u64))?: size; 623 }; 624 625 export fn recv(sockfd: int, buf: *void, len_: size, flags: int) (size | errno) = { 626 return recvfrom(sockfd, buf, len_, flags, null, null); 627 }; 628 629 export fn send(sockfd: int, buf: *void, len_: size, flags: int) (size | errno) = { 630 return sendto(sockfd, buf, len_, flags, null, 0); 631 }; 632 633 export fn getsockopt(sockfd: int, level: int, optname: int, optval: nullable *void, optlen: nullable *u32) (int | errno) = { 634 return wrap_return(syscall5(SYS_getsockopt, 635 sockfd: u64, level: u64, optname: u64, 636 optval: uintptr: u64, optlen: uintptr: u64))?: int; 637 }; 638 639 export fn setsockopt(sockfd: int, level: int, optname: int, optval: *void, optlen: u32) (int | errno) = { 640 return wrap_return(syscall5(SYS_setsockopt, 641 sockfd: u64, level: u64, optname: u64, 642 optval: uintptr: u64, optlen: u64))?: int; 643 }; 644 645 export type ioctl_arg = (nullable *void | u64); 646 647 export fn ioctl(fd: int, req: u64, arg: ioctl_arg) (int | errno) = { 648 let fd = fd: u64, req = req: u64; 649 return wrap_return(match (arg) { 650 case let u: u64 => 651 yield syscall3(SYS_ioctl, fd, req, u); 652 case let v: nullable *void => 653 yield syscall3(SYS_ioctl, fd, req, v: uintptr: u64); 654 })?: int; 655 }; 656 657 export fn getsockname(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = { 658 return wrap_return(syscall3(SYS_getsockname, 659 sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int; 660 }; 661 662 export fn getpeername(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = { 663 return wrap_return(syscall3(SYS_getpeername, 664 sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int; 665 }; 666 667 export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = { 668 return wrap_return(syscall3(SYS_readv, 669 fd: u64, iov: uintptr: u64, iovcnt: u64))?: size; 670 }; 671 672 export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = { 673 return wrap_return(syscall3(SYS_writev, 674 fd: u64, iov: uintptr: u64, iovcnt: u64))?: size; 675 }; 676 677 export fn sendmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = { 678 return wrap_return(syscall3(SYS_sendmsg, 679 fd: u64, msg: uintptr: u64, flags: u64))?: int; 680 }; 681 682 export fn recvmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = { 683 return wrap_return(syscall3(SYS_recvmsg, 684 fd: u64, msg: uintptr: u64, flags: u64))?: int; 685 }; 686 687 export fn umask(mode: mode_t) (mode_t | errno) = { 688 return wrap_return(syscall1(SYS_umask, mode: u64))?: mode_t; 689 }; 690 691 export fn setresuid(uid: uid_t, euid: uid_t, suid: uid_t) (void | errno) = { 692 wrap_return(syscall3(SYS_setresuid, uid: u64, euid: u64, suid: u64))?; 693 }; 694 695 export fn setresgid(gid: gid_t, egid: gid_t, sgid: gid_t) (void | errno) = { 696 wrap_return(syscall3(SYS_setresgid, gid: u64, egid: u64, sgid: u64))?; 697 }; 698 699 export fn getresuid(uid: *uid_t, euid: *uid_t, suid: *uid_t) (void | errno) = { 700 wrap_return(syscall3(SYS_getresuid, 701 uid: uintptr: u64, 702 euid: uintptr: u64, 703 suid: uintptr: u64))?; 704 }; 705 706 export fn getresgid(gid: *gid_t, egid: *gid_t, sgid: *gid_t) (void | errno) = { 707 wrap_return(syscall3(SYS_getresgid, 708 gid: uintptr: u64, 709 egid: uintptr: u64, 710 sgid: uintptr: u64))?; 711 }; 712 713 export fn getgroups(gids: []uint) (uint | errno) = { 714 return wrap_return(syscall2(SYS_getgroups, 715 len(gids): u64, gids: *[*]uint: uintptr: u64))?: uint; 716 }; 717 718 export fn setgroups(gids: []uint) (void | errno) = { 719 wrap_return(syscall2(SYS_setgroups, 720 len(gids): u64, gids: *[*]uint: uintptr: u64))?; 721 }; 722 723 export fn getpriority(which: int, who: id_t) (int | errno) = { 724 return wrap_return(syscall2(SYS_setpriority, 725 which: u64, who: u64))?: int; 726 }; 727 728 export fn setpriority(which: int, who: id_t, prio: int) (void | errno) = { 729 wrap_return(syscall3(SYS_setpriority, which: u64, who: u64, prio: u64))?; 730 }; 731 732 export fn io_uring_setup(entries: u32, params: *void) (int | errno) = { 733 return wrap_return(syscall2(SYS_io_uring_setup, 734 entries: u64, params: uintptr: u64))?: int; 735 }; 736 737 export fn io_uring_register( 738 fd: int, 739 opcode: uint, 740 arg: nullable *void, 741 nr_args: uint, 742 ) (int | errno) = wrap_return(syscall4(SYS_io_uring_register, 743 fd: u64, opcode: u64, arg: uintptr: u64, nr_args: u64))?: int; 744 745 export fn io_uring_enter( 746 fd: int, 747 to_submit: uint, 748 min_complete: uint, 749 flags: uint, 750 sig: const nullable *sigset, 751 ) (uint | errno) = { 752 return wrap_return(syscall5(SYS_io_uring_enter, 753 fd: u64, to_submit: u64, min_complete: u64, 754 flags: u64, sig: uintptr: u64))?: uint; 755 }; 756 757 export fn mlock2(addr: *void, length: size, flags: uint) (void | errno) = { 758 return wrap_return(syscall3(SYS_mlock2, addr: uintptr: u64, 759 length: u64, flags: u64))?: void; 760 }; 761 762 export fn munlock(addr: *void, length: size) (void | errno) = { 763 return wrap_return(syscall2(SYS_munlock, addr: uintptr: u64, 764 length: u64))?: void; 765 }; 766 767 export fn mlockall(flags: uint) (void | errno) = { 768 return wrap_return(syscall1(SYS_mlockall, flags: u64))?: void; 769 }; 770 771 export fn munlockall() (void | errno) = { 772 return wrap_return(syscall0(SYS_munlockall))?: void; 773 }; 774 775 export fn prctl( 776 option: int, 777 arg2: u64, 778 arg3: u64, 779 arg4: u64, 780 arg5: u64, 781 ) (int | errno) = { 782 return wrap_return(syscall5(SYS_prctl, option: u64, arg2, arg3, arg4, 783 arg5))?: int; 784 }; 785 786 export fn add_key( 787 keytype: *const u8, 788 name: *const u8, 789 payload: *void, 790 plen: size, 791 keyring: int, 792 ) (int | errno) = { 793 return wrap_return(syscall5(SYS_add_key, 794 keytype: uintptr: u64, name: uintptr: u64, 795 payload: uintptr: u64, plen: u64, 796 keyring: u64))?: int; 797 }; 798 799 export fn keyctl( 800 operation: int, 801 arg2: u64, 802 arg3: u64, 803 arg4: u64, 804 arg5: u64, 805 ) (int | errno) = { 806 return wrap_return(syscall5(SYS_keyctl, operation: u64, 807 arg2, arg3, arg4, arg5))?: int; 808 }; 809 810 export fn getsid(pid: int) (int | errno) = { 811 return wrap_return(syscall1(SYS_getsid, pid: u64))?: int; 812 }; 813 814 export fn setsid() (void | errno) = { 815 return wrap_return(syscall0(SYS_setsid))?: void; 816 }; 817 818 export fn mount( 819 source: path, 820 target: path, 821 filesystemtype: *const u8, 822 mountflags: u64, 823 data: nullable *void 824 ) (void | errno) = { 825 let source = kpath(source)?; 826 let target = kpath(target)?; 827 wrap_return(syscall5(SYS_mount, source: uintptr, target: uintptr, 828 filesystemtype: uintptr, mountflags: u64, data: uintptr))?; 829 }; 830 831 export fn umount2(target: path, flags: int) (void | errno) = { 832 let target = kpath(target)?; 833 wrap_return(syscall2(SYS_umount2, target: uintptr, flags: u64))?; 834 }; 835 836 export fn ptrace( 837 request: int, 838 pid: int, 839 addr: uintptr, 840 data: uintptr, 841 ) (u64 | errno) = { 842 // PTRACE_PEEK* requests write into *data instead of just returning 843 // the word that they read 844 let result = 0u64; 845 const wrdata = request >= PTRACE_PEEKTEXT && request <= PTRACE_PEEKUSER; 846 if (wrdata) { 847 data = &result: uintptr; 848 }; 849 const ret = wrap_return(syscall4(SYS_ptrace, request: u64, pid: u64, 850 addr, data))?: u64; 851 if (wrdata) { 852 return result; 853 } else { 854 return ret; 855 }; 856 }; 857 858 859 export fn sync() void = { 860 wrap_return(syscall0(SYS_sync))!; 861 }; 862 863 export fn memfd_create(name: path, flags: uint) (int | errno) = { 864 let path = kpath(name)?; 865 return wrap_return(syscall2(SYS_memfd_create, 866 path: uintptr: u64, flags: u64))?: int; 867 }; 868 869 export fn splice( 870 fd_in: int, 871 off_in: nullable *u64, 872 fd_out: int, 873 off_out: nullable *u64, 874 ln: size, 875 flags: uint, 876 ) (size | errno) = { 877 return wrap_return(syscall6(SYS_splice, 878 fd_in: u64, off_in: uintptr: u64, 879 fd_out: u64, off_out: uintptr: u64, 880 ln: u64, flags: u64))?: size; 881 }; 882 883 export fn tee(fd_in: int, fd_out: int, ln: size, flags: uint) (size | errno) = { 884 return wrap_return(syscall4(SYS_tee, 885 fd_in: u64, fd_out: u64, 886 ln: u64, flags: u64))?: size; 887 }; 888 889 export fn fallocate(fd: int, mode: int, off: i64, ln: i64) (void | errno) = { 890 wrap_return(syscall4(SYS_fallocate, 891 fd: u64, mode: u64, off: u64, ln: u64))?; 892 }; 893 894 export fn posix_fallocate(fd: int, off: i64, ln: i64) (void | errno) = { 895 fallocate(fd, 0, off, ln)?; 896 }; 897 898 export fn flock(fd: int, op: int) (void | errno) = { 899 wrap_return(syscall2(SYS_flock, 900 fd: u64, op: u64))?; 901 }; 902 903 export fn inotify_init() (int | errno) = { 904 return wrap_return(syscall1(SYS_inotify_init1, 0))?: int; 905 }; 906 907 export fn inotify_init1(flags: int) (int | errno) = { 908 return wrap_return(syscall1(SYS_inotify_init1, flags: u64))?: int; 909 }; 910 911 export fn inotify_add_watch(fd: int, path: path, mask: u32) (int | errno) = { 912 let path = kpath(path)?; 913 return wrap_return(syscall3(SYS_inotify_add_watch, 914 fd: u64, path: uintptr: u64, mask))?: int; 915 }; 916 917 export fn inotify_rm_watch(fd: int, wd: int) (int | errno) = { 918 return wrap_return(syscall2(SYS_inotify_rm_watch, 919 fd: u64, wd: u64))?: int; 920 }; 921 922 export type inotify_event = struct { 923 wd: int, 924 mask: u32, 925 cookie: u32, 926 length: u32, 927 name: *const u8 928 }; 929 930 export fn shmat(id: int, addr: *const void, flag: int) *void = { 931 return syscall3(SYS_shmat, id: u64, addr: uintptr: u64, 932 flag: u64): uintptr: *void; 933 }; 934 935 export fn sched_getaffinity( 936 pid: int, 937 cpusetsize: size, 938 mask: *cpu_set, 939 ) (void | errno) = { 940 wrap_return(syscall3(SYS_sched_getaffinity, 941 pid: u64, cpusetsize: u64, mask: uintptr: u64))?; 942 }; 943 944 export fn sched_setaffinity( 945 pid: int, 946 cpusetsize: size, 947 mask: *const cpu_set, 948 ) (void | errno) = { 949 wrap_return(syscall3(SYS_sched_setaffinity, 950 pid: u64, cpusetsize: u64, mask: uintptr: u64))?; 951 }; 952 953 export fn getrlimit(resource: int, rlim: *rlimit) (void | errno) = { 954 wrap_return(syscall2(SYS_getrlimit, 955 resource: u64, rlim: uintptr: u64))?; 956 }; 957 958 export fn setrlimit(resource: int, rlim: *const rlimit) (void | errno) = { 959 wrap_return(syscall2(SYS_setrlimit, 960 resource: u64, rlim: uintptr: u64))?; 961 }; 962 963 export fn shutdown(sockfd: int, how: int) (void | errno) = { 964 wrap_return(syscall2(SYS_shutdown, 965 sockfd: u64, how: u64))?; 966 };