syscalls.ha (30436B)
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 clock_settime(clock_id: int, tp: *const timespec) (void | errno) = { 483 wrap_return(syscall2(SYS_clock_settime, 484 clock_id: u64, tp: uintptr: u64))?; 485 }; 486 487 export fn nanosleep(req: *const timespec, rem: *timespec) (void | errno) = { 488 wrap_return(syscall2(SYS_nanosleep, 489 req: uintptr: u64, rem: uintptr: u64))?; 490 }; 491 492 export fn uname(uts: *utsname) (void | errno) = { 493 wrap_return(syscall1(SYS_uname, uts: uintptr: u64))?; 494 }; 495 496 // The return value is statically allocated and must be duplicated before 497 // calling getcwd again. 498 export fn getcwd() (*const u8 | errno) = { 499 static let pathbuf: [PATH_MAX]u8 = [0...]; 500 wrap_return(syscall2(SYS_getcwd, 501 &pathbuf: *[*]u8: uintptr: u64, 502 PATH_MAX))?; 503 return &pathbuf: *const u8; 504 }; 505 506 export fn ppoll( 507 fds: *[*]pollfd, 508 nfds: nfds_t, 509 timeout: const nullable *timespec, 510 sigmask: const nullable *sigset, 511 ) (int | errno) = { 512 return wrap_return(syscall4(SYS_ppoll, fds: uintptr: u64, nfds: u64, 513 timeout: uintptr: u64, sigmask: uintptr: u64))?: int; 514 }; 515 516 export fn poll(fds: *[*]pollfd, nfds: nfds_t, timeout: int) (int | errno) = { 517 const ts = timespec { 518 tv_sec = timeout % 1000, 519 tv_nsec = timeout * 1000000, 520 }; 521 return ppoll(fds, nfds, (if (timeout != -1) &ts else null), null); 522 }; 523 524 export fn epoll_create1(flags: int) (int | errno) = { 525 return wrap_return(syscall1(SYS_epoll_create1, flags: u64))?: int; 526 }; 527 528 export fn epoll_create(size_: int) (int | errno) = { 529 return epoll_create1(0); 530 }; 531 532 export fn epoll_ctl( 533 epfd: int, 534 op: int, 535 fd: int, 536 event: nullable *epoll_event 537 ) (void | errno) = { 538 wrap_return(syscall4(SYS_epoll_ctl, 539 epfd: u64, op: u64, fd: u64, event: uintptr: u64))?; 540 }; 541 542 export fn epoll_pwait( 543 epfd: int, 544 events: *epoll_event, 545 maxevents: int, 546 timeout: int, 547 sigmask: nullable *sigset 548 ) (int | errno) = { 549 return wrap_return(syscall6(SYS_epoll_pwait, 550 epfd: u64, events: uintptr: u64, 551 maxevents: u64, timeout: u64, 552 sigmask: uintptr: u64, size(sigset): u64))?: int; 553 }; 554 555 export fn epoll_wait( 556 epfd: int, 557 events: *epoll_event, 558 maxevents: int, 559 timeout: int, 560 ) (int | errno) = { 561 return epoll_pwait(epfd, events, maxevents, timeout, null); 562 }; 563 564 export fn timerfd_create(clock_id: int, flags: int) (int | errno) = { 565 return wrap_return(syscall2(SYS_timerfd_create, 566 clock_id: u64, flags: u64))?: int; 567 }; 568 569 export fn eventfd(initval: uint, flags: int) (int | errno) = { 570 return wrap_return(syscall2(SYS_eventfd2, 571 initval: u64, flags: u64))?: int; 572 }; 573 574 export fn timerfd_settime( 575 fd: int, 576 flags: int, 577 new_value: *const itimerspec, 578 old_value: nullable *itimerspec 579 ) (int | errno) = { 580 return wrap_return(syscall4(SYS_timerfd_settime, 581 fd: u64, flags: u64, 582 new_value: uintptr: u64, old_value: uintptr: u64))?: int; 583 }; 584 585 export fn timerfd_gettime(fd: int, curr_value: *itimerspec) (int | errno) = { 586 return wrap_return(syscall2(SYS_timerfd_gettime, 587 fd: u64, curr_value: uintptr: u64))?: int; 588 }; 589 590 export fn signalfd(fd: int, mask: *const sigset, flags: int) (int | errno) = { 591 return wrap_return(syscall4(SYS_signalfd4, 592 fd: u64, mask: uintptr: u64, size(sigset): u64, 593 flags: u64))?: int; 594 }; 595 596 export fn sigprocmask( 597 how: int, 598 set: nullable *const sigset, 599 old: nullable *sigset 600 ) (int | errno) = { 601 return wrap_return(syscall4(SYS_rt_sigprocmask, 602 how: u64, set: uintptr: u64, old: uintptr: u64, 603 size(sigset): u64))?: int; 604 }; 605 606 fn restore() void; 607 fn restore_si() void; 608 609 export fn sigaction( 610 signum: int, 611 act: *const sigact, 612 old: nullable *sigact 613 ) (int | errno) = { 614 let real_act = *act; 615 real_act.sa_flags |= SA_RESTORER; 616 let restore_fn = if ((act.sa_flags & SA_SIGINFO) != 0) &restore_si else &restore; 617 real_act.sa_restorer = &restore; 618 return wrap_return(syscall4(SYS_rt_sigaction, 619 signum: u64, &real_act: uintptr: u64, old: uintptr: u64, 620 size(sigset): u64))?: int; 621 }; 622 623 export fn sigaltstack( 624 ss: nullable *stack_t, 625 old_ss: nullable *stack_t, 626 ) (void | errno) = { 627 wrap_return(syscall2(SYS_sigaltstack, 628 ss: uintptr: u64, old_ss: uintptr: u64))?; 629 }; 630 631 export fn socket(domain: int, type_: int, protocol: int) (int | errno) = { 632 return wrap_return(syscall3(SYS_socket, 633 domain: u64, type_: u64, protocol: u64))?: int; 634 }; 635 636 export fn socketpair( 637 domain: int, 638 type_: int, 639 protocol: int, 640 sv: *[2]int 641 ) (int | errno) = { 642 return wrap_return(syscall4(SYS_socketpair, domain: u64, 643 type_: u64, protocol: u64, sv: uintptr : u64))?: int; 644 }; 645 646 export fn connect(sockfd: int, addr: *const sockaddr, addrlen: u32) (int | errno) = { 647 return wrap_return(syscall3(SYS_connect, 648 sockfd: u64, addr: uintptr: u64, addrlen: u64))?: int; 649 }; 650 651 export fn bind(sockfd: int, addr: *const sockaddr, addrlen: u32) (int | errno) = { 652 return wrap_return(syscall3(SYS_bind, 653 sockfd: u64, addr: uintptr: u64, addrlen: u64))?: int; 654 }; 655 656 export fn listen(sockfd: int, backlog: u32) (int | errno) = { 657 return wrap_return(syscall2(SYS_listen, 658 sockfd: u64, backlog: u64))?: int; 659 }; 660 661 export fn accept(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = { 662 return wrap_return(syscall3(SYS_accept, 663 sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int; 664 }; 665 666 export fn accept4(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32, flags: int) (int | errno) = { 667 return wrap_return(syscall4(SYS_accept4, 668 sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64, flags: u64))?: int; 669 }; 670 671 export fn recvfrom(sockfd: int, buf: *opaque, len_: size, flags: int, 672 src_addr: nullable *sockaddr, addrlen: nullable *u32 673 ) (size | errno) = { 674 return wrap_return(syscall6(SYS_recvfrom, 675 sockfd: u64, buf: uintptr: u64, len_: u64, flags: u64, 676 src_addr: uintptr: u64, addrlen: uintptr: u64))?: size; 677 }; 678 679 export fn sendto(sockfd: int, buf: *opaque, len_: size, flags: int, 680 dest_addr: nullable *sockaddr, addrlen: u32 681 ) (size | errno) = { 682 return wrap_return(syscall6(SYS_sendto, 683 sockfd: u64, buf: uintptr: u64, len_: u64, flags: u64, 684 dest_addr: uintptr: u64, addrlen: u64))?: size; 685 }; 686 687 export fn recv(sockfd: int, buf: *opaque, len_: size, flags: int) (size | errno) = { 688 return recvfrom(sockfd, buf, len_, flags, null, null); 689 }; 690 691 export fn send(sockfd: int, buf: *opaque, len_: size, flags: int) (size | errno) = { 692 return sendto(sockfd, buf, len_, flags, null, 0); 693 }; 694 695 export fn getsockopt(sockfd: int, level: int, optname: int, optval: nullable *opaque, optlen: nullable *u32) (int | errno) = { 696 return wrap_return(syscall5(SYS_getsockopt, 697 sockfd: u64, level: u64, optname: u64, 698 optval: uintptr: u64, optlen: uintptr: u64))?: int; 699 }; 700 701 export fn setsockopt(sockfd: int, level: int, optname: int, optval: *opaque, optlen: u32) (int | errno) = { 702 return wrap_return(syscall5(SYS_setsockopt, 703 sockfd: u64, level: u64, optname: u64, 704 optval: uintptr: u64, optlen: u64))?: int; 705 }; 706 707 export type ioctl_arg = (nullable *opaque | u64); 708 709 export fn ioctl(fd: int, req: u64, arg: ioctl_arg) (int | errno) = { 710 let fd = fd: u64, req = req: u64; 711 return wrap_return(match (arg) { 712 case let u: u64 => 713 yield syscall3(SYS_ioctl, fd, req, u); 714 case let v: nullable *opaque => 715 yield syscall3(SYS_ioctl, fd, req, v: uintptr: u64); 716 })?: int; 717 }; 718 719 export fn getsockname(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = { 720 return wrap_return(syscall3(SYS_getsockname, 721 sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int; 722 }; 723 724 export fn getpeername(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = { 725 return wrap_return(syscall3(SYS_getpeername, 726 sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int; 727 }; 728 729 export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = { 730 return wrap_return(syscall3(SYS_readv, 731 fd: u64, iov: uintptr: u64, iovcnt: u64))?: size; 732 }; 733 734 export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = { 735 return wrap_return(syscall3(SYS_writev, 736 fd: u64, iov: uintptr: u64, iovcnt: u64))?: size; 737 }; 738 739 export fn sendmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = { 740 return wrap_return(syscall3(SYS_sendmsg, 741 fd: u64, msg: uintptr: u64, flags: u64))?: int; 742 }; 743 744 export fn recvmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = { 745 return wrap_return(syscall3(SYS_recvmsg, 746 fd: u64, msg: uintptr: u64, flags: u64))?: int; 747 }; 748 749 export fn umask(mode: mode_t) (mode_t | errno) = { 750 return wrap_return(syscall1(SYS_umask, mode: u64))?: mode_t; 751 }; 752 753 export fn setresuid(uid: uid_t, euid: uid_t, suid: uid_t) (void | errno) = { 754 wrap_return(syscall3(SYS_setresuid, uid: u64, euid: u64, suid: u64))?; 755 }; 756 757 export fn setresgid(gid: gid_t, egid: gid_t, sgid: gid_t) (void | errno) = { 758 wrap_return(syscall3(SYS_setresgid, gid: u64, egid: u64, sgid: u64))?; 759 }; 760 761 export fn getresuid(uid: *uid_t, euid: *uid_t, suid: *uid_t) (void | errno) = { 762 wrap_return(syscall3(SYS_getresuid, 763 uid: uintptr: u64, 764 euid: uintptr: u64, 765 suid: uintptr: u64))?; 766 }; 767 768 export fn getresgid(gid: *gid_t, egid: *gid_t, sgid: *gid_t) (void | errno) = { 769 wrap_return(syscall3(SYS_getresgid, 770 gid: uintptr: u64, 771 egid: uintptr: u64, 772 sgid: uintptr: u64))?; 773 }; 774 775 export fn getgroups(gids: []gid_t) (uint | errno) = { 776 return wrap_return(syscall2(SYS_getgroups, 777 len(gids): u64, gids: *[*]gid_t: uintptr: u64))?: uint; 778 }; 779 780 export fn setgroups(gids: []gid_t) (void | errno) = { 781 wrap_return(syscall2(SYS_setgroups, 782 len(gids): u64, gids: *[*]gid_t: uintptr: u64))?; 783 }; 784 785 export fn getpriority(which: int, who: id_t) (int | errno) = { 786 return wrap_return(syscall2(SYS_setpriority, 787 which: u64, who: u64))?: int; 788 }; 789 790 export fn setpriority(which: int, who: id_t, prio: int) (void | errno) = { 791 wrap_return(syscall3(SYS_setpriority, which: u64, who: u64, prio: u64))?; 792 }; 793 794 export fn io_uring_setup(entries: u32, params: *io_uring_params) (int | errno) = { 795 return wrap_return(syscall2(SYS_io_uring_setup, 796 entries: u64, params: uintptr: u64))?: int; 797 }; 798 799 export fn io_uring_register( 800 fd: int, 801 opcode: uint, 802 arg: nullable *opaque, 803 nr_args: uint, 804 ) (int | errno) = wrap_return(syscall4(SYS_io_uring_register, 805 fd: u64, opcode: u64, arg: uintptr: u64, nr_args: u64))?: int; 806 807 export fn io_uring_enter( 808 fd: int, 809 to_submit: uint, 810 min_complete: uint, 811 flags: uint, 812 sig: const nullable *sigset, 813 ) (uint | errno) = { 814 return wrap_return(syscall5(SYS_io_uring_enter, 815 fd: u64, to_submit: u64, min_complete: u64, 816 flags: u64, sig: uintptr: u64))?: uint; 817 }; 818 819 export fn io_uring_enter2( 820 fd: int, 821 to_submit: uint, 822 min_complete: uint, 823 flags: uint, 824 arg: const nullable *opaque, 825 argsz: size, 826 ) (uint | errno) = { 827 return wrap_return(syscall6(SYS_io_uring_enter, 828 fd: u64, to_submit: u64, min_complete: u64, 829 flags: u64, arg: uintptr: u64, argsz: u64))?: uint; 830 }; 831 832 export fn mlock2(addr: *opaque, length: size, flags: uint) (void | errno) = { 833 return wrap_return(syscall3(SYS_mlock2, addr: uintptr: u64, 834 length: u64, flags: u64))?: void; 835 }; 836 837 export fn munlock(addr: *opaque, length: size) (void | errno) = { 838 return wrap_return(syscall2(SYS_munlock, addr: uintptr: u64, 839 length: u64))?: void; 840 }; 841 842 export fn mlockall(flags: uint) (void | errno) = { 843 return wrap_return(syscall1(SYS_mlockall, flags: u64))?: void; 844 }; 845 846 export fn munlockall() (void | errno) = { 847 return wrap_return(syscall0(SYS_munlockall))?: void; 848 }; 849 850 export fn prctl( 851 option: int, 852 arg2: u64, 853 arg3: u64, 854 arg4: u64, 855 arg5: u64, 856 ) (int | errno) = { 857 return wrap_return(syscall5(SYS_prctl, option: u64, arg2, arg3, arg4, 858 arg5))?: int; 859 }; 860 861 export fn add_key( 862 keytype: *const u8, 863 name: *const u8, 864 payload: *opaque, 865 plen: size, 866 keyring: int, 867 ) (int | errno) = { 868 return wrap_return(syscall5(SYS_add_key, 869 keytype: uintptr: u64, name: uintptr: u64, 870 payload: uintptr: u64, plen: u64, 871 keyring: u64))?: int; 872 }; 873 874 export fn keyctl( 875 operation: int, 876 arg2: u64, 877 arg3: u64, 878 arg4: u64, 879 arg5: u64, 880 ) (int | errno) = { 881 return wrap_return(syscall5(SYS_keyctl, operation: u64, 882 arg2, arg3, arg4, arg5))?: int; 883 }; 884 885 export fn getsid(pid: pid_t) (pid_t | errno) = { 886 return wrap_return(syscall1(SYS_getsid, pid: u64))?: pid_t; 887 }; 888 889 export fn setsid() (void | errno) = { 890 return wrap_return(syscall0(SYS_setsid))?: void; 891 }; 892 893 export fn mount( 894 source: path, 895 target: path, 896 filesystemtype: *const u8, 897 mountflags: u64, 898 data: nullable *opaque 899 ) (void | errno) = { 900 let source = kpath(source)?; 901 let target = kpath(target)?; 902 wrap_return(syscall5(SYS_mount, source: uintptr, target: uintptr, 903 filesystemtype: uintptr, mountflags: u64, data: uintptr))?; 904 }; 905 906 export fn umount2(target: path, flags: int) (void | errno) = { 907 let target = kpath(target)?; 908 wrap_return(syscall2(SYS_umount2, target: uintptr, flags: u64))?; 909 }; 910 911 export fn ptrace( 912 request: int, 913 pid: pid_t, 914 addr: uintptr, 915 data: uintptr, 916 ) (u64 | errno) = { 917 // PTRACE_PEEK* requests write into *data instead of just returning 918 // the word that they read 919 let result = 0u64; 920 const wrdata = request >= PTRACE_PEEKTEXT && request <= PTRACE_PEEKUSER; 921 if (wrdata) { 922 data = &result: uintptr; 923 }; 924 const ret = wrap_return(syscall4(SYS_ptrace, request: u64, pid: u64, 925 addr, data))?: u64; 926 if (wrdata) { 927 return result; 928 } else { 929 return ret; 930 }; 931 }; 932 933 934 export fn sync() void = { 935 wrap_return(syscall0(SYS_sync))!; 936 }; 937 938 export fn memfd_create(name: path, flags: uint) (int | errno) = { 939 let path = kpath(name)?; 940 return wrap_return(syscall2(SYS_memfd_create, 941 path: uintptr: u64, flags: u64))?: int; 942 }; 943 944 export fn splice( 945 fd_in: int, 946 off_in: nullable *u64, 947 fd_out: int, 948 off_out: nullable *u64, 949 ln: size, 950 flags: uint, 951 ) (size | errno) = { 952 return wrap_return(syscall6(SYS_splice, 953 fd_in: u64, off_in: uintptr: u64, 954 fd_out: u64, off_out: uintptr: u64, 955 ln: u64, flags: u64))?: size; 956 }; 957 958 export fn tee(fd_in: int, fd_out: int, ln: size, flags: uint) (size | errno) = { 959 return wrap_return(syscall4(SYS_tee, 960 fd_in: u64, fd_out: u64, 961 ln: u64, flags: u64))?: size; 962 }; 963 964 export fn fallocate(fd: int, mode: int, off: i64, ln: i64) (void | errno) = { 965 wrap_return(syscall4(SYS_fallocate, 966 fd: u64, mode: u64, off: u64, ln: u64))?; 967 }; 968 969 export fn posix_fallocate(fd: int, off: i64, ln: i64) (void | errno) = { 970 fallocate(fd, 0, off, ln)?; 971 }; 972 973 export fn flock(fd: int, op: int) (void | errno) = { 974 wrap_return(syscall2(SYS_flock, 975 fd: u64, op: u64))?; 976 }; 977 978 export def NAME_MAX: size = 255z; 979 export def INOTIFY_EVENT_MAX_SIZE: size = size(int) + size(u32)*3 + NAME_MAX + 1z; 980 981 export fn inotify_init() (int | errno) = { 982 return wrap_return(syscall1(SYS_inotify_init1, 0))?: int; 983 }; 984 985 export fn inotify_init1(flags: int) (int | errno) = { 986 return wrap_return(syscall1(SYS_inotify_init1, flags: u64))?: int; 987 }; 988 989 export fn inotify_add_watch(fd: int, path: path, mask: u32) (int | errno) = { 990 let path = kpath(path)?; 991 return wrap_return(syscall3(SYS_inotify_add_watch, 992 fd: u64, path: uintptr: u64, mask))?: int; 993 }; 994 995 export fn inotify_rm_watch(fd: int, wd: int) (int | errno) = { 996 return wrap_return(syscall2(SYS_inotify_rm_watch, 997 fd: u64, wd: u64))?: int; 998 }; 999 1000 export type inotify_event = struct { 1001 wd: int, 1002 mask: u32, 1003 cookie: u32, 1004 length: u32, 1005 name: [*]u8, 1006 }; 1007 1008 export fn shmat(id: int, addr: *const opaque, flag: int) *opaque = { 1009 return syscall3(SYS_shmat, id: u64, addr: uintptr: u64, 1010 flag: u64): uintptr: *opaque; 1011 }; 1012 1013 export fn sched_getaffinity( 1014 pid: pid_t, 1015 cpusetsize: size, 1016 mask: *cpu_set, 1017 ) (void | errno) = { 1018 wrap_return(syscall3(SYS_sched_getaffinity, 1019 pid: u64, cpusetsize: u64, mask: uintptr: u64))?; 1020 }; 1021 1022 export fn sched_setaffinity( 1023 pid: pid_t, 1024 cpusetsize: size, 1025 mask: *const cpu_set, 1026 ) (void | errno) = { 1027 wrap_return(syscall3(SYS_sched_setaffinity, 1028 pid: u64, cpusetsize: u64, mask: uintptr: u64))?; 1029 }; 1030 1031 export fn getrlimit(resource: int, rlim: *rlimit) (void | errno) = { 1032 wrap_return(syscall2(SYS_getrlimit, 1033 resource: u64, rlim: uintptr: u64))?; 1034 }; 1035 1036 export fn setrlimit(resource: int, rlim: *const rlimit) (void | errno) = { 1037 wrap_return(syscall2(SYS_setrlimit, 1038 resource: u64, rlim: uintptr: u64))?; 1039 }; 1040 1041 export fn shutdown(sockfd: int, how: int) (void | errno) = { 1042 wrap_return(syscall2(SYS_shutdown, 1043 sockfd: u64, how: u64))?; 1044 }; 1045 1046 // Sets an extended file attribute. 1047 export fn setxattr( 1048 path: path, 1049 name: str, 1050 value: []u8, 1051 flags: int = 0 1052 ) (void | errno) = { 1053 let path = kpath(path)?; 1054 static let namebuf: [PATH_MAX]u8 = [0...]; 1055 let name = copy_kpath(name, namebuf)?; 1056 1057 wrap_return(syscall5(SYS_setxattr, 1058 path: uintptr: u64, 1059 name: uintptr: u64, 1060 value: *[*]u8: uintptr: u64, 1061 len(value): u64, 1062 flags: u64 1063 ))?; 1064 }; 1065 1066 // Gets an extended file attribute. 1067 export fn getxattr(path: path, name: str, value: []u8) (u64 | errno) = { 1068 let path = kpath(path)?; 1069 static let namebuf: [PATH_MAX]u8 = [0...]; 1070 let name = copy_kpath(name, namebuf)?; 1071 1072 return wrap_return(syscall4(SYS_getxattr, 1073 path: uintptr, 1074 name: uintptr, 1075 value: *[*]u8: uintptr: u64, 1076 len(value): u64, 1077 )); 1078 }; 1079 1080 // Removes an extended file attribute. 1081 export fn removexattr(path: path, name: str) (void | errno) = { 1082 let path = kpath(path)?; 1083 static let namebuf: [PATH_MAX]u8 = [0...]; 1084 let name = copy_kpath(name, namebuf)?; 1085 1086 wrap_return(syscall2(SYS_removexattr, path: uintptr, name: uintptr))?; 1087 }; 1088 1089 export fn fsync(fd: int) (void | errno) = { 1090 wrap_return(syscall1(SYS_fsync, fd: u64))?; 1091 }; 1092 1093 export fn fdatasync(fd: int) (void | errno) = { 1094 wrap_return(syscall1(SYS_fdatasync, fd: u64))?; 1095 }; 1096 1097 export fn sigqueueinfo(tgid: pid_t, sig: int, info: *siginfo) (void | errno) = { 1098 wrap_return(syscall3(SYS_rt_sigqueueinfo, tgid: u64, 1099 sig: u64, info: uintptr: u64))?; 1100 };