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