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