//! This file provides the system interface functions for Linux matching those //! that are provided by libc, whether or not libc is linked. The following //! abstractions are made: //! * Implement all the syscalls in the same way that libc functions will //! provide `rename` when only the `renameat` syscall exists. const std = @import("../std.zig"); const builtin = @import("builtin"); const assert = std.debug.assert; const maxInt = std.math.maxInt; const elf = std.elf; const vdso = @import("linux/vdso.zig"); const dl = @import("../dynamic_library.zig"); const native_arch = builtin.cpu.arch; const native_abi = builtin.abi; const native_endian = native_arch.endian(); const is_loongarch = native_arch.isLoongArch(); const is_mips = native_arch.isMIPS(); const is_ppc = native_arch.isPowerPC(); const is_riscv = native_arch.isRISCV(); const is_sparc = native_arch.isSPARC(); const iovec = std.posix.iovec; const iovec_const = std.posix.iovec_const; const winsize = std.posix.winsize; const ACCMODE = std.posix.ACCMODE; test { if (builtin.os.tag == .linux) { _ = @import("linux/test.zig"); } } const arch_bits = switch (native_arch) { .aarch64, .aarch64_be => @import("linux/aarch64.zig"), .arm, .armeb, .thumb, .thumbeb => @import("linux/arm.zig"), .hexagon => @import("linux/hexagon.zig"), .loongarch64 => @import("linux/loongarch64.zig"), .m68k => @import("linux/m68k.zig"), .mips, .mipsel => @import("linux/mips.zig"), .mips64, .mips64el => switch (builtin.abi) { .gnuabin32, .muslabin32 => @import("linux/mipsn32.zig"), else => @import("linux/mips64.zig"), }, .or1k => @import("linux/or1k.zig"), .powerpc, .powerpcle => @import("linux/powerpc.zig"), .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), .riscv32 => @import("linux/riscv32.zig"), .riscv64 => @import("linux/riscv64.zig"), .s390x => @import("linux/s390x.zig"), .sparc64 => @import("linux/sparc64.zig"), .x86 => @import("linux/x86.zig"), .x86_64 => switch (builtin.abi) { .gnux32, .muslx32 => @import("linux/x32.zig"), else => @import("linux/x86_64.zig"), }, else => struct {}, }; const syscall_bits = if (native_arch.isThumb()) @import("linux/thumb.zig") else arch_bits; pub const syscall0 = syscall_bits.syscall0; pub const syscall1 = syscall_bits.syscall1; pub const syscall2 = syscall_bits.syscall2; pub const syscall3 = syscall_bits.syscall3; pub const syscall4 = syscall_bits.syscall4; pub const syscall5 = syscall_bits.syscall5; pub const syscall6 = syscall_bits.syscall6; pub const syscall7 = syscall_bits.syscall7; pub const restore = syscall_bits.restore; pub const restore_rt = syscall_bits.restore_rt; pub const socketcall = syscall_bits.socketcall; pub const syscall_pipe = syscall_bits.syscall_pipe; pub const syscall_fork = syscall_bits.syscall_fork; pub fn clone( func: *const fn (arg: usize) callconv(.c) u8, stack: usize, flags: u32, arg: usize, ptid: ?*i32, tp: usize, // aka tls ctid: ?*i32, ) usize { // Can't directly call a naked function; cast to C calling convention first. return @as(*const fn ( *const fn (arg: usize) callconv(.c) u8, usize, u32, usize, ?*i32, usize, ?*i32, ) callconv(.c) usize, @ptrCast(&syscall_bits.clone))(func, stack, flags, arg, ptid, tp, ctid); } pub const ARCH = arch_bits.ARCH; pub const HWCAP = arch_bits.HWCAP; pub const SC = arch_bits.SC; pub const Stat = arch_bits.Stat; pub const VDSO = arch_bits.VDSO; pub const blkcnt_t = arch_bits.blkcnt_t; pub const blksize_t = arch_bits.blksize_t; pub const dev_t = arch_bits.dev_t; pub const ino_t = arch_bits.ino_t; pub const mode_t = arch_bits.mode_t; pub const nlink_t = arch_bits.nlink_t; pub const off_t = arch_bits.off_t; pub const time_t = arch_bits.time_t; pub const user_desc = arch_bits.user_desc; pub const tls = @import("linux/tls.zig"); pub const BPF = @import("linux/bpf.zig"); pub const IOCTL = @import("linux/ioctl.zig"); pub const SECCOMP = @import("linux/seccomp.zig"); pub const syscalls = @import("linux/syscalls.zig"); pub const SYS = switch (native_arch) { .arc, .arceb => syscalls.Arc, .aarch64, .aarch64_be => syscalls.Arm64, .arm, .armeb, .thumb, .thumbeb => syscalls.Arm, .csky => syscalls.CSky, .hexagon => syscalls.Hexagon, .loongarch64 => syscalls.LoongArch64, .m68k => syscalls.M68k, .mips, .mipsel => syscalls.MipsO32, .mips64, .mips64el => switch (builtin.abi) { .gnuabin32, .muslabin32 => syscalls.MipsN32, else => syscalls.MipsN64, }, .or1k => syscalls.OpenRisc, .powerpc, .powerpcle => syscalls.PowerPC, .powerpc64, .powerpc64le => syscalls.PowerPC64, .riscv32 => syscalls.RiscV32, .riscv64 => syscalls.RiscV64, .s390x => syscalls.S390x, .sparc => syscalls.Sparc, .sparc64 => syscalls.Sparc64, .x86 => syscalls.X86, .x86_64 => switch (builtin.abi) { .gnux32, .muslx32 => syscalls.X32, else => syscalls.X64, }, .xtensa, .xtensaeb => syscalls.Xtensa, else => @compileError("The Zig Standard Library is missing syscall definitions for the target CPU architecture"), }; pub const MAP_TYPE = enum(u4) { SHARED = 0x01, PRIVATE = 0x02, SHARED_VALIDATE = 0x03, }; pub const MAP = switch (native_arch) { .x86_64, .x86 => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, ANONYMOUS: bool = false, @"32BIT": bool = false, _7: u1 = 0, GROWSDOWN: bool = false, _9: u2 = 0, DENYWRITE: bool = false, EXECUTABLE: bool = false, LOCKED: bool = false, NORESERVE: bool = false, POPULATE: bool = false, NONBLOCK: bool = false, STACK: bool = false, HUGETLB: bool = false, SYNC: bool = false, FIXED_NOREPLACE: bool = false, _21: u5 = 0, UNINITIALIZED: bool = false, _: u5 = 0, }, .aarch64, .aarch64_be, .arm, .armeb, .thumb, .thumbeb => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, ANONYMOUS: bool = false, _6: u2 = 0, GROWSDOWN: bool = false, _9: u2 = 0, DENYWRITE: bool = false, EXECUTABLE: bool = false, LOCKED: bool = false, NORESERVE: bool = false, POPULATE: bool = false, NONBLOCK: bool = false, STACK: bool = false, HUGETLB: bool = false, SYNC: bool = false, FIXED_NOREPLACE: bool = false, _21: u5 = 0, UNINITIALIZED: bool = false, _: u5 = 0, }, .riscv32, .riscv64, .loongarch64 => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, ANONYMOUS: bool = false, _6: u9 = 0, POPULATE: bool = false, NONBLOCK: bool = false, STACK: bool = false, HUGETLB: bool = false, SYNC: bool = false, FIXED_NOREPLACE: bool = false, _21: u5 = 0, UNINITIALIZED: bool = false, _: u5 = 0, }, .sparc64 => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, ANONYMOUS: bool = false, NORESERVE: bool = false, _7: u1 = 0, LOCKED: bool = false, GROWSDOWN: bool = false, _10: u1 = 0, DENYWRITE: bool = false, EXECUTABLE: bool = false, _13: u2 = 0, POPULATE: bool = false, NONBLOCK: bool = false, STACK: bool = false, HUGETLB: bool = false, SYNC: bool = false, FIXED_NOREPLACE: bool = false, _21: u5 = 0, UNINITIALIZED: bool = false, _: u5 = 0, }, .mips, .mipsel, .mips64, .mips64el => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, _5: u1 = 0, @"32BIT": bool = false, _7: u3 = 0, NORESERVE: bool = false, ANONYMOUS: bool = false, GROWSDOWN: bool = false, DENYWRITE: bool = false, EXECUTABLE: bool = false, LOCKED: bool = false, POPULATE: bool = false, NONBLOCK: bool = false, STACK: bool = false, HUGETLB: bool = false, FIXED_NOREPLACE: bool = false, _21: u5 = 0, UNINITIALIZED: bool = false, _: u5 = 0, }, .powerpc, .powerpcle, .powerpc64, .powerpc64le => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, ANONYMOUS: bool = false, NORESERVE: bool = false, LOCKED: bool = false, GROWSDOWN: bool = false, _9: u2 = 0, DENYWRITE: bool = false, EXECUTABLE: bool = false, _13: u2 = 0, POPULATE: bool = false, NONBLOCK: bool = false, STACK: bool = false, HUGETLB: bool = false, SYNC: bool = false, FIXED_NOREPLACE: bool = false, _21: u5 = 0, UNINITIALIZED: bool = false, _: u5 = 0, }, .hexagon, .m68k, .or1k, .s390x => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, ANONYMOUS: bool = false, _4: u1 = 0, _5: u1 = 0, GROWSDOWN: bool = false, _7: u1 = 0, _8: u1 = 0, DENYWRITE: bool = false, EXECUTABLE: bool = false, LOCKED: bool = false, NORESERVE: bool = false, POPULATE: bool = false, NONBLOCK: bool = false, STACK: bool = false, HUGETLB: bool = false, SYNC: bool = false, FIXED_NOREPLACE: bool = false, _19: u5 = 0, UNINITIALIZED: bool = false, _: u5 = 0, }, else => @compileError("missing std.os.linux.MAP constants for this architecture"), }; pub const MREMAP = packed struct(u32) { MAYMOVE: bool = false, FIXED: bool = false, DONTUNMAP: bool = false, _: u29 = 0, }; pub const O = switch (native_arch) { .x86_64 => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u4 = 0, CREAT: bool = false, EXCL: bool = false, NOCTTY: bool = false, TRUNC: bool = false, APPEND: bool = false, NONBLOCK: bool = false, DSYNC: bool = false, ASYNC: bool = false, DIRECT: bool = false, _15: u1 = 0, DIRECTORY: bool = false, NOFOLLOW: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, TMPFILE: bool = false, _23: u9 = 0, }, .x86, .riscv32, .riscv64, .loongarch64 => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u4 = 0, CREAT: bool = false, EXCL: bool = false, NOCTTY: bool = false, TRUNC: bool = false, APPEND: bool = false, NONBLOCK: bool = false, DSYNC: bool = false, ASYNC: bool = false, DIRECT: bool = false, LARGEFILE: bool = false, DIRECTORY: bool = false, NOFOLLOW: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, TMPFILE: bool = false, _23: u9 = 0, }, .aarch64, .aarch64_be, .arm, .armeb, .thumb, .thumbeb => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u4 = 0, CREAT: bool = false, EXCL: bool = false, NOCTTY: bool = false, TRUNC: bool = false, APPEND: bool = false, NONBLOCK: bool = false, DSYNC: bool = false, ASYNC: bool = false, DIRECTORY: bool = false, NOFOLLOW: bool = false, DIRECT: bool = false, LARGEFILE: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, TMPFILE: bool = false, _23: u9 = 0, }, .sparc64 => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u1 = 0, APPEND: bool = false, _4: u2 = 0, ASYNC: bool = false, _7: u2 = 0, CREAT: bool = false, TRUNC: bool = false, EXCL: bool = false, _12: u1 = 0, DSYNC: bool = false, NONBLOCK: bool = false, NOCTTY: bool = false, DIRECTORY: bool = false, NOFOLLOW: bool = false, _18: u2 = 0, DIRECT: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, TMPFILE: bool = false, _27: u6 = 0, }, .mips, .mipsel, .mips64, .mips64el => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u1 = 0, APPEND: bool = false, DSYNC: bool = false, _5: u2 = 0, NONBLOCK: bool = false, CREAT: bool = false, TRUNC: bool = false, EXCL: bool = false, NOCTTY: bool = false, ASYNC: bool = false, LARGEFILE: bool = false, SYNC: bool = false, DIRECT: bool = false, DIRECTORY: bool = false, NOFOLLOW: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, _20: u1 = 0, PATH: bool = false, TMPFILE: bool = false, _23: u9 = 0, }, .powerpc, .powerpcle, .powerpc64, .powerpc64le => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u4 = 0, CREAT: bool = false, EXCL: bool = false, NOCTTY: bool = false, TRUNC: bool = false, APPEND: bool = false, NONBLOCK: bool = false, DSYNC: bool = false, ASYNC: bool = false, DIRECTORY: bool = false, NOFOLLOW: bool = false, LARGEFILE: bool = false, DIRECT: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, SYNC: bool = false, PATH: bool = false, TMPFILE: bool = false, _23: u9 = 0, }, .hexagon, .or1k, .s390x => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u4 = 0, CREAT: bool = false, EXCL: bool = false, NOCTTY: bool = false, TRUNC: bool = false, APPEND: bool = false, NONBLOCK: bool = false, DSYNC: bool = false, ASYNC: bool = false, DIRECT: bool = false, LARGEFILE: bool = false, DIRECTORY: bool = false, NOFOLLOW: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, _20: u1 = 0, PATH: bool = false, _22: u10 = 0, // #define O_RSYNC 04010000 // #define O_SYNC 04010000 // #define O_TMPFILE 020200000 // #define O_NDELAY O_NONBLOCK }, .m68k => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u4 = 0, CREAT: bool = false, EXCL: bool = false, NOCTTY: bool = false, TRUNC: bool = false, APPEND: bool = false, NONBLOCK: bool = false, DSYNC: bool = false, ASYNC: bool = false, DIRECTORY: bool = false, NOFOLLOW: bool = false, DIRECT: bool = false, LARGEFILE: bool = false, NOATIME: bool = false, CLOEXEC: bool = false, _20: u1 = 0, PATH: bool = false, _22: u10 = 0, }, else => @compileError("missing std.os.linux.O constants for this architecture"), }; /// Set by startup code, used by `getauxval`. pub var elf_aux_maybe: ?[*]std.elf.Auxv = null; /// Whether an external or internal getauxval implementation is used. const extern_getauxval = switch (builtin.zig_backend) { // Calling extern functions is not yet supported with these backends .stage2_arm, .stage2_powerpc, .stage2_riscv64, .stage2_sparc64, => false, else => !builtin.link_libc, }; pub const getauxval = if (extern_getauxval) struct { comptime { const root = @import("root"); // Export this only when building an executable, otherwise it is overriding // the libc implementation if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { @export(&getauxvalImpl, .{ .name = "getauxval", .linkage = .weak }); } } extern fn getauxval(index: usize) usize; }.getauxval else getauxvalImpl; fn getauxvalImpl(index: usize) callconv(.c) usize { @disableInstrumentation(); const auxv = elf_aux_maybe orelse return 0; var i: usize = 0; while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) { if (auxv[i].a_type == index) return auxv[i].a_un.a_val; } return 0; } // Some architectures (and some syscalls) require 64bit parameters to be passed // in a even-aligned register pair. const require_aligned_register_pair = builtin.cpu.arch.isArm() or builtin.cpu.arch == .hexagon or builtin.cpu.arch.isMIPS32() or builtin.cpu.arch.isPowerPC32(); // Split a 64bit value into a {LSB,MSB} pair. // The LE/BE variants specify the endianness to assume. fn splitValueLE64(val: i64) [2]u32 { const u: u64 = @bitCast(val); return [2]u32{ @as(u32, @truncate(u)), @as(u32, @truncate(u >> 32)), }; } fn splitValueBE64(val: i64) [2]u32 { const u: u64 = @bitCast(val); return [2]u32{ @as(u32, @truncate(u >> 32)), @as(u32, @truncate(u)), }; } fn splitValue64(val: i64) [2]u32 { const u: u64 = @bitCast(val); switch (native_endian) { .little => return [2]u32{ @as(u32, @truncate(u)), @as(u32, @truncate(u >> 32)), }, .big => return [2]u32{ @as(u32, @truncate(u >> 32)), @as(u32, @truncate(u)), }, } } /// Get the errno from a syscall return value, or 0 for no error. /// The public API is exposed via the `E` namespace. fn errnoFromSyscall(r: usize) E { const signed_r: isize = @bitCast(r); const int = if (signed_r > -4096 and signed_r < 0) -signed_r else 0; return @enumFromInt(int); } pub fn dup(old: i32) usize { return syscall1(.dup, @as(usize, @bitCast(@as(isize, old)))); } pub fn dup2(old: i32, new: i32) usize { if (@hasField(SYS, "dup2")) { return syscall2(.dup2, @as(usize, @bitCast(@as(isize, old))), @as(usize, @bitCast(@as(isize, new)))); } else { if (old == new) { if (std.debug.runtime_safety) { const rc = fcntl(F.GETFD, @as(fd_t, old), 0); if (@as(isize, @bitCast(rc)) < 0) return rc; } return @as(usize, @intCast(old)); } else { return syscall3(.dup3, @as(usize, @bitCast(@as(isize, old))), @as(usize, @bitCast(@as(isize, new))), 0); } } } pub fn dup3(old: i32, new: i32, flags: u32) usize { return syscall3(.dup3, @as(usize, @bitCast(@as(isize, old))), @as(usize, @bitCast(@as(isize, new))), flags); } pub fn chdir(path: [*:0]const u8) usize { return syscall1(.chdir, @intFromPtr(path)); } pub fn fchdir(fd: fd_t) usize { return syscall1(.fchdir, @as(usize, @bitCast(@as(isize, fd)))); } pub fn chroot(path: [*:0]const u8) usize { return syscall1(.chroot, @intFromPtr(path)); } pub fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) usize { return syscall3(.execve, @intFromPtr(path), @intFromPtr(argv), @intFromPtr(envp)); } pub fn fork() usize { if (comptime native_arch.isSPARC()) { return syscall_fork(); } else if (@hasField(SYS, "fork")) { return syscall0(.fork); } else { return syscall2(.clone, SIG.CHLD, 0); } } /// This must be inline, and inline call the syscall function, because if the /// child does a return it will clobber the parent's stack. /// It is advised to avoid this function and use clone instead, because /// the compiler is not aware of how vfork affects control flow and you may /// see different results in optimized builds. pub inline fn vfork() usize { return @call(.always_inline, syscall0, .{.vfork}); } pub fn futimens(fd: i32, times: ?*const [2]timespec) usize { return utimensat(fd, null, times, 0); } pub fn utimensat(dirfd: i32, path: ?[*:0]const u8, times: ?*const [2]timespec, flags: u32) usize { return syscall4( if (@hasField(SYS, "utimensat") and native_arch != .hexagon) .utimensat else .utimensat_time64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(times), flags, ); } pub fn fallocate(fd: i32, mode: i32, offset: i64, length: i64) usize { if (usize_bits < 64) { const offset_halves = splitValue64(offset); const length_halves = splitValue64(length); return syscall6( .fallocate, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, mode))), offset_halves[0], offset_halves[1], length_halves[0], length_halves[1], ); } else { return syscall4( .fallocate, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, mode))), @as(u64, @bitCast(offset)), @as(u64, @bitCast(length)), ); } } // The 4th parameter to the v1 futex syscall can either be an optional // pointer to a timespec, or a uint32, depending on which "op" is being // performed. pub const futex_param4 = extern union { timeout: ?*const timespec, /// On all platforms only the bottom 32-bits of `val2` are relevant. /// This is 64-bit to match the pointer in the union. val2: usize, }; /// The futex v1 syscall, see also the newer the futex2_{wait,wakeup,requeue,waitv} syscalls. /// /// The futex_op parameter is a sub-command and flags. The sub-command /// defines which of the subsequent paramters are relevant. pub fn futex(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32, val2timeout: futex_param4, uaddr2: ?*const anyopaque, val3: u32) usize { return syscall6( if (@hasField(SYS, "futex") and native_arch != .hexagon) .futex else .futex_time64, @intFromPtr(uaddr), @as(u32, @bitCast(futex_op)), val, @intFromPtr(val2timeout.timeout), @intFromPtr(uaddr2), val3, ); } /// Three-argument variation of the v1 futex call. Only suitable for a /// futex_op that ignores the remaining arguments (e.g., FUTUX_OP.WAKE). pub fn futex_3arg(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32) usize { return syscall3( if (@hasField(SYS, "futex") and native_arch != .hexagon) .futex else .futex_time64, @intFromPtr(uaddr), @as(u32, @bitCast(futex_op)), val, ); } /// Four-argument variation on the v1 futex call. Only suitable for /// futex_op that ignores the remaining arguments (e.g., FUTEX_OP.WAIT). pub fn futex_4arg(uaddr: *const anyopaque, futex_op: FUTEX_OP, val: u32, timeout: ?*const timespec) usize { return syscall4( if (@hasField(SYS, "futex") and native_arch != .hexagon) .futex else .futex_time64, @intFromPtr(uaddr), @as(u32, @bitCast(futex_op)), val, @intFromPtr(timeout), ); } /// Given an array of `futex2_waitone`, wait on each uaddr. /// The thread wakes if a futex_wake() is performed at any uaddr. /// The syscall returns immediately if any futex has *uaddr != val. /// timeout is an optional, absolute timeout value for the operation. /// The `flags` argument is for future use and currently should be `.{}`. /// Flags for private futexes, sizes, etc. should be set on the /// individual flags of each `futex2_waitone`. /// /// Returns the array index of one of the woken futexes. /// No further information is provided: any number of other futexes may also /// have been woken by the same event, and if more than one futex was woken, /// the returned index may refer to any one of them. /// (It is not necessaryily the futex with the smallest index, nor the one /// most recently woken, nor...) /// /// Requires at least kernel v5.16. pub fn futex2_waitv( futexes: [*]const futex2_waitone, /// Length of `futexes`. Max of FUTEX2_WAITONE_MAX. nr_futexes: u32, flags: FUTEX2_FLAGS_WAITV, /// Optional absolute timeout. Always 64-bit, even on 32-bit platforms. timeout: ?*const kernel_timespec, /// Clock to be used for the timeout, realtime or monotonic. clockid: clockid_t, ) usize { return syscall5( .futex_waitv, @intFromPtr(futexes), nr_futexes, @as(u32, @bitCast(flags)), @intFromPtr(timeout), @intFromEnum(clockid), ); } /// Wait on a single futex. /// Identical to the futex v1 `FUTEX.FUTEX_WAIT_BITSET` op, except it is part of the /// futex2 family of calls. /// /// Requires at least kernel v6.7. pub fn futex2_wait( /// Address of the futex to wait on. uaddr: *const anyopaque, /// Value of `uaddr`. val: usize, /// Bitmask to match against incoming wakeup masks. Must not be zero. mask: usize, flags: FUTEX2_FLAGS, /// Optional absolute timeout. Always 64-bit, even on 32-bit platforms. timeout: ?*const kernel_timespec, /// Clock to be used for the timeout, realtime or monotonic. clockid: clockid_t, ) usize { return syscall6( .futex_wait, @intFromPtr(uaddr), val, mask, @as(u32, @bitCast(flags)), @intFromPtr(timeout), @intFromEnum(clockid), ); } /// Wake (subset of) waiters on given futex. /// Identical to the traditional `FUTEX.FUTEX_WAKE_BITSET` op, except it is part of the /// futex2 family of calls. /// /// Requires at least kernel v6.7. pub fn futex2_wake( /// Futex to wake uaddr: *const anyopaque, /// Bitmask to match against waiters. mask: usize, /// Maximum number of waiters on the futex to wake. nr_wake: i32, flags: FUTEX2_FLAGS, ) usize { return syscall4( .futex_wake, @intFromPtr(uaddr), mask, @as(u32, @bitCast(nr_wake)), @as(u32, @bitCast(flags)), ); } /// Wake and/or requeue waiter(s) from one futex to another. /// Identical to `FUTEX.CMP_REQUEUE`, except it is part of the futex2 family of calls. /// /// Requires at least kernel v6.7. pub fn futex2_requeue( /// The source and destination futexes. Must be a 2-element array. waiters: [*]const futex2_waitone, /// Currently unused. flags: FUTEX2_FLAGS_REQUEUE, /// Maximum number of waiters to wake on the source futex. nr_wake: i32, /// Maximum number of waiters to transfer to the destination futex. nr_requeue: i32, ) usize { return syscall4( .futex_requeue, @intFromPtr(waiters), @as(u32, @bitCast(flags)), @as(u32, @bitCast(nr_wake)), @as(u32, @bitCast(nr_requeue)), ); } pub fn getcwd(buf: [*]u8, size: usize) usize { return syscall2(.getcwd, @intFromPtr(buf), size); } pub fn getdents(fd: i32, dirp: [*]u8, len: usize) usize { return syscall3( .getdents, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(dirp), @min(len, maxInt(c_int)), ); } pub fn getdents64(fd: i32, dirp: [*]u8, len: usize) usize { return syscall3( .getdents64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(dirp), @min(len, maxInt(c_int)), ); } pub fn inotify_init1(flags: u32) usize { return syscall1(.inotify_init1, flags); } pub fn inotify_add_watch(fd: i32, pathname: [*:0]const u8, mask: u32) usize { return syscall3(.inotify_add_watch, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(pathname), mask); } pub fn inotify_rm_watch(fd: i32, wd: i32) usize { return syscall2(.inotify_rm_watch, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, wd)))); } pub fn fanotify_init(flags: fanotify.InitFlags, event_f_flags: u32) usize { return syscall2(.fanotify_init, @as(u32, @bitCast(flags)), event_f_flags); } pub fn fanotify_mark( fd: fd_t, flags: fanotify.MarkFlags, mask: fanotify.MarkMask, dirfd: fd_t, pathname: ?[*:0]const u8, ) usize { if (usize_bits < 64) { const mask_halves = splitValue64(@bitCast(mask)); return syscall6( .fanotify_mark, @bitCast(@as(isize, fd)), @as(u32, @bitCast(flags)), mask_halves[0], mask_halves[1], @bitCast(@as(isize, dirfd)), @intFromPtr(pathname), ); } else { return syscall5( .fanotify_mark, @bitCast(@as(isize, fd)), @as(u32, @bitCast(flags)), @bitCast(mask), @bitCast(@as(isize, dirfd)), @intFromPtr(pathname), ); } } pub fn name_to_handle_at( dirfd: fd_t, pathname: [*:0]const u8, handle: *std.os.linux.file_handle, mount_id: *i32, flags: u32, ) usize { return syscall5( .name_to_handle_at, @as(u32, @bitCast(dirfd)), @intFromPtr(pathname), @intFromPtr(handle), @intFromPtr(mount_id), flags, ); } pub fn readlink(noalias path: [*:0]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { if (@hasField(SYS, "readlink")) { return syscall3(.readlink, @intFromPtr(path), @intFromPtr(buf_ptr), buf_len); } else { return syscall4(.readlinkat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(path), @intFromPtr(buf_ptr), buf_len); } } pub fn readlinkat(dirfd: i32, noalias path: [*:0]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { return syscall4(.readlinkat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(buf_ptr), buf_len); } pub fn mkdir(path: [*:0]const u8, mode: mode_t) usize { if (@hasField(SYS, "mkdir")) { return syscall2(.mkdir, @intFromPtr(path), mode); } else { return syscall3(.mkdirat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(path), mode); } } pub fn mkdirat(dirfd: i32, path: [*:0]const u8, mode: mode_t) usize { return syscall3(.mkdirat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode); } pub fn mknod(path: [*:0]const u8, mode: u32, dev: u32) usize { if (@hasField(SYS, "mknod")) { return syscall3(.mknod, @intFromPtr(path), mode, dev); } else { return mknodat(AT.FDCWD, path, mode, dev); } } pub fn mknodat(dirfd: i32, path: [*:0]const u8, mode: u32, dev: u32) usize { return syscall4(.mknodat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode, dev); } pub fn mount(special: ?[*:0]const u8, dir: [*:0]const u8, fstype: ?[*:0]const u8, flags: u32, data: usize) usize { return syscall5(.mount, @intFromPtr(special), @intFromPtr(dir), @intFromPtr(fstype), flags, data); } pub fn umount(special: [*:0]const u8) usize { return syscall2(.umount2, @intFromPtr(special), 0); } pub fn umount2(special: [*:0]const u8, flags: u32) usize { return syscall2(.umount2, @intFromPtr(special), flags); } pub fn pivot_root(new_root: [*:0]const u8, put_old: [*:0]const u8) usize { return syscall2(.pivot_root, @intFromPtr(new_root), @intFromPtr(put_old)); } pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: MAP, fd: i32, offset: i64) usize { if (@hasField(SYS, "mmap2")) { return syscall6( .mmap2, @intFromPtr(address), length, prot, @as(u32, @bitCast(flags)), @bitCast(@as(isize, fd)), @truncate(@as(u64, @bitCast(offset)) / std.heap.pageSize()), ); } else { // The s390x mmap() syscall existed before Linux supported syscalls with 5+ parameters, so // it takes a single pointer to an array of arguments instead. return if (native_arch == .s390x) syscall1( .mmap, @intFromPtr(&[_]usize{ @intFromPtr(address), length, prot, @as(u32, @bitCast(flags)), @bitCast(@as(isize, fd)), @as(u64, @bitCast(offset)), }), ) else syscall6( .mmap, @intFromPtr(address), length, prot, @as(u32, @bitCast(flags)), @bitCast(@as(isize, fd)), @as(u64, @bitCast(offset)), ); } } pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { return syscall3(.mprotect, @intFromPtr(address), length, protection); } pub fn mremap(old_addr: ?[*]const u8, old_len: usize, new_len: usize, flags: MREMAP, new_addr: ?[*]const u8) usize { return syscall5( .mremap, @intFromPtr(old_addr), old_len, new_len, @as(u32, @bitCast(flags)), @intFromPtr(new_addr), ); } pub const MSF = struct { pub const ASYNC = 1; pub const INVALIDATE = 2; pub const SYNC = 4; }; /// Can only be called on 64 bit systems. pub fn mseal(address: [*]const u8, length: usize, flags: usize) usize { return syscall3(.mseal, @intFromPtr(address), length, flags); } pub fn msync(address: [*]const u8, length: usize, flags: i32) usize { return syscall3(.msync, @intFromPtr(address), length, @as(u32, @bitCast(flags))); } pub fn munmap(address: [*]const u8, length: usize) usize { return syscall2(.munmap, @intFromPtr(address), length); } pub fn mlock(address: [*]const u8, length: usize) usize { return syscall2(.mlock, @intFromPtr(address), length); } pub fn munlock(address: [*]const u8, length: usize) usize { return syscall2(.munlock, @intFromPtr(address), length); } pub const MLOCK = packed struct(u32) { ONFAULT: bool = false, _1: u31 = 0, }; pub fn mlock2(address: [*]const u8, length: usize, flags: MLOCK) usize { return syscall3(.mlock2, @intFromPtr(address), length, @as(u32, @bitCast(flags))); } pub const MCL = if (native_arch.isSPARC() or native_arch.isPowerPC()) packed struct(u32) { _0: u13 = 0, CURRENT: bool = false, FUTURE: bool = false, ONFAULT: bool = false, _4: u16 = 0, } else packed struct(u32) { CURRENT: bool = false, FUTURE: bool = false, ONFAULT: bool = false, _3: u29 = 0, }; pub fn mlockall(flags: MCL) usize { return syscall1(.mlockall, @as(u32, @bitCast(flags))); } pub fn munlockall() usize { return syscall0(.munlockall); } pub fn poll(fds: [*]pollfd, n: nfds_t, timeout: i32) usize { return if (@hasField(SYS, "poll")) return syscall3(.poll, @intFromPtr(fds), n, @as(u32, @bitCast(timeout))) else ppoll( fds, n, if (timeout >= 0) @constCast(×pec{ .sec = @divTrunc(timeout, 1000), .nsec = @rem(timeout, 1000) * 1000000, }) else null, null, ); } pub fn ppoll(fds: [*]pollfd, n: nfds_t, timeout: ?*timespec, sigmask: ?*const sigset_t) usize { return syscall5( if (@hasField(SYS, "ppoll") and native_arch != .hexagon) .ppoll else .ppoll_time64, @intFromPtr(fds), n, @intFromPtr(timeout), @intFromPtr(sigmask), NSIG / 8, ); } pub fn read(fd: i32, buf: [*]u8, count: usize) usize { return syscall3(.read, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), count); } pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: i64) usize { const offset_u: u64 = @bitCast(offset); return syscall5( .preadv, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(iov), count, // Kernel expects the offset is split into largest natural word-size. // See following link for detail: // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=601cc11d054ae4b5e9b5babec3d8e4667a2cb9b5 @as(usize, @truncate(offset_u)), if (usize_bits < 64) @as(usize, @truncate(offset_u >> 32)) else 0, ); } pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: i64, flags: kernel_rwf) usize { const offset_u: u64 = @bitCast(offset); return syscall6( .preadv2, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(iov), count, // See comments in preadv @as(usize, @truncate(offset_u)), if (usize_bits < 64) @as(usize, @truncate(offset_u >> 32)) else 0, flags, ); } pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { return syscall3(.readv, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(iov), count); } pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { return syscall3(.writev, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(iov), count); } pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: i64) usize { const offset_u: u64 = @bitCast(offset); return syscall5( .pwritev, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(iov), count, // See comments in preadv @as(usize, @truncate(offset_u)), if (usize_bits < 64) @as(usize, @truncate(offset_u >> 32)) else 0, ); } pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: i64, flags: kernel_rwf) usize { const offset_u: u64 = @bitCast(offset); return syscall6( .pwritev2, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(iov), count, // See comments in preadv @as(usize, @truncate(offset_u)), if (usize_bits < 64) @as(usize, @truncate(offset_u >> 32)) else 0, flags, ); } pub fn rmdir(path: [*:0]const u8) usize { if (@hasField(SYS, "rmdir")) { return syscall1(.rmdir, @intFromPtr(path)); } else { return syscall3(.unlinkat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(path), AT.REMOVEDIR); } } pub fn symlink(existing: [*:0]const u8, new: [*:0]const u8) usize { if (@hasField(SYS, "symlink")) { return syscall2(.symlink, @intFromPtr(existing), @intFromPtr(new)); } else { return syscall3(.symlinkat, @intFromPtr(existing), @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(new)); } } pub fn symlinkat(existing: [*:0]const u8, newfd: i32, newpath: [*:0]const u8) usize { return syscall3(.symlinkat, @intFromPtr(existing), @as(usize, @bitCast(@as(isize, newfd))), @intFromPtr(newpath)); } pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: i64) usize { if (@hasField(SYS, "pread64") and usize_bits < 64) { const offset_halves = splitValue64(offset); if (require_aligned_register_pair) { return syscall6( .pread64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), count, 0, offset_halves[0], offset_halves[1], ); } else { return syscall5( .pread64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), count, offset_halves[0], offset_halves[1], ); } } else { // Some architectures (eg. 64bit SPARC) pread is called pread64. const syscall_number = if (!@hasField(SYS, "pread") and @hasField(SYS, "pread64")) .pread64 else .pread; return syscall4( syscall_number, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), count, @as(u64, @bitCast(offset)), ); } } pub fn access(path: [*:0]const u8, mode: u32) usize { if (@hasField(SYS, "access")) { return syscall2(.access, @intFromPtr(path), mode); } else { return faccessat(AT.FDCWD, path, mode, 0); } } pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize { if (flags == 0) { return syscall3(.faccessat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode); } return syscall4(.faccessat2, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode, flags); } pub fn pipe(fd: *[2]i32) usize { if (comptime (native_arch.isMIPS() or native_arch.isSPARC())) { return syscall_pipe(fd); } else if (@hasField(SYS, "pipe")) { return syscall1(.pipe, @intFromPtr(fd)); } else { return syscall2(.pipe2, @intFromPtr(fd), 0); } } pub fn pipe2(fd: *[2]i32, flags: O) usize { return syscall2(.pipe2, @intFromPtr(fd), @as(u32, @bitCast(flags))); } pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { return syscall3(.write, @bitCast(@as(isize, fd)), @intFromPtr(buf), count); } pub fn ftruncate(fd: i32, length: i64) usize { if (@hasField(SYS, "ftruncate64") and usize_bits < 64) { const length_halves = splitValue64(length); if (require_aligned_register_pair) { return syscall4( .ftruncate64, @as(usize, @bitCast(@as(isize, fd))), 0, length_halves[0], length_halves[1], ); } else { return syscall3( .ftruncate64, @as(usize, @bitCast(@as(isize, fd))), length_halves[0], length_halves[1], ); } } else { return syscall2( .ftruncate, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(length)), ); } } pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: i64) usize { if (@hasField(SYS, "pwrite64") and usize_bits < 64) { const offset_halves = splitValue64(offset); if (require_aligned_register_pair) { return syscall6( .pwrite64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), count, 0, offset_halves[0], offset_halves[1], ); } else { return syscall5( .pwrite64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), count, offset_halves[0], offset_halves[1], ); } } else { // Some architectures (eg. 64bit SPARC) pwrite is called pwrite64. const syscall_number = if (!@hasField(SYS, "pwrite") and @hasField(SYS, "pwrite64")) .pwrite64 else .pwrite; return syscall4( syscall_number, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), count, @as(u64, @bitCast(offset)), ); } } pub fn rename(old: [*:0]const u8, new: [*:0]const u8) usize { if (@hasField(SYS, "rename")) { return syscall2(.rename, @intFromPtr(old), @intFromPtr(new)); } else if (@hasField(SYS, "renameat")) { return syscall4(.renameat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(old), @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(new)); } else { return syscall5(.renameat2, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(old), @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(new), 0); } } pub fn renameat(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]const u8) usize { if (@hasField(SYS, "renameat")) { return syscall4( .renameat, @as(usize, @bitCast(@as(isize, oldfd))), @intFromPtr(oldpath), @as(usize, @bitCast(@as(isize, newfd))), @intFromPtr(newpath), ); } else { return syscall5( .renameat2, @as(usize, @bitCast(@as(isize, oldfd))), @intFromPtr(oldpath), @as(usize, @bitCast(@as(isize, newfd))), @intFromPtr(newpath), 0, ); } } pub fn renameat2(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]const u8, flags: u32) usize { return syscall5( .renameat2, @as(usize, @bitCast(@as(isize, oldfd))), @intFromPtr(oldpath), @as(usize, @bitCast(@as(isize, newfd))), @intFromPtr(newpath), flags, ); } pub fn open(path: [*:0]const u8, flags: O, perm: mode_t) usize { if (@hasField(SYS, "open")) { return syscall3(.open, @intFromPtr(path), @as(u32, @bitCast(flags)), perm); } else { return syscall4( .openat, @bitCast(@as(isize, AT.FDCWD)), @intFromPtr(path), @as(u32, @bitCast(flags)), perm, ); } } pub fn create(path: [*:0]const u8, perm: mode_t) usize { return syscall2(.creat, @intFromPtr(path), perm); } pub fn openat(dirfd: i32, path: [*:0]const u8, flags: O, mode: mode_t) usize { // dirfd could be negative, for example AT.FDCWD is -100 return syscall4(.openat, @bitCast(@as(isize, dirfd)), @intFromPtr(path), @as(u32, @bitCast(flags)), mode); } /// See also `clone` (from the arch-specific include) pub fn clone5(flags: usize, child_stack_ptr: usize, parent_tid: *i32, child_tid: *i32, newtls: usize) usize { return syscall5(.clone, flags, child_stack_ptr, @intFromPtr(parent_tid), @intFromPtr(child_tid), newtls); } /// See also `clone` (from the arch-specific include) pub fn clone2(flags: u32, child_stack_ptr: usize) usize { return syscall2(.clone, flags, child_stack_ptr); } pub fn close(fd: i32) usize { return syscall1(.close, @as(usize, @bitCast(@as(isize, fd)))); } pub fn fchmod(fd: i32, mode: mode_t) usize { return syscall2(.fchmod, @as(usize, @bitCast(@as(isize, fd))), mode); } pub fn chmod(path: [*:0]const u8, mode: mode_t) usize { if (@hasField(SYS, "chmod")) { return syscall2(.chmod, @intFromPtr(path), mode); } else { return fchmodat(AT.FDCWD, path, mode, 0); } } pub fn fchown(fd: i32, owner: uid_t, group: gid_t) usize { if (@hasField(SYS, "fchown32")) { return syscall3(.fchown32, @as(usize, @bitCast(@as(isize, fd))), owner, group); } else { return syscall3(.fchown, @as(usize, @bitCast(@as(isize, fd))), owner, group); } } pub fn fchmodat(fd: i32, path: [*:0]const u8, mode: mode_t, _: u32) usize { return syscall3(.fchmodat, @bitCast(@as(isize, fd)), @intFromPtr(path), mode); } pub fn fchmodat2(fd: i32, path: [*:0]const u8, mode: mode_t, flags: u32) usize { return syscall4(.fchmodat2, @bitCast(@as(isize, fd)), @intFromPtr(path), mode, flags); } /// Can only be called on 32 bit systems. For 64 bit see `lseek`. pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { // NOTE: The offset parameter splitting is independent from the target // endianness. return syscall5( .llseek, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @truncate(offset >> 32)), @as(usize, @truncate(offset)), @intFromPtr(result), whence, ); } /// Can only be called on 64 bit systems. For 32 bit see `llseek`. pub fn lseek(fd: i32, offset: i64, whence: usize) usize { return syscall3(.lseek, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(offset)), whence); } pub fn exit(status: i32) noreturn { _ = syscall1(.exit, @as(usize, @bitCast(@as(isize, status)))); unreachable; } pub fn exit_group(status: i32) noreturn { _ = syscall1(.exit_group, @as(usize, @bitCast(@as(isize, status)))); unreachable; } /// flags for the `reboot' system call. pub const LINUX_REBOOT = struct { /// First magic value required to use _reboot() system call. pub const MAGIC1 = enum(u32) { MAGIC1 = 0xfee1dead, _, }; /// Second magic value required to use _reboot() system call. pub const MAGIC2 = enum(u32) { MAGIC2 = 672274793, MAGIC2A = 85072278, MAGIC2B = 369367448, MAGIC2C = 537993216, _, }; /// Commands accepted by the _reboot() system call. pub const CMD = enum(u32) { /// Restart system using default command and mode. RESTART = 0x01234567, /// Stop OS and give system control to ROM monitor, if any. HALT = 0xCDEF0123, /// Ctrl-Alt-Del sequence causes RESTART command. CAD_ON = 0x89ABCDEF, /// Ctrl-Alt-Del sequence sends SIGINT to init task. CAD_OFF = 0x00000000, /// Stop OS and remove all power from system, if possible. POWER_OFF = 0x4321FEDC, /// Restart system using given command string. RESTART2 = 0xA1B2C3D4, /// Suspend system using software suspend if compiled in. SW_SUSPEND = 0xD000FCE2, /// Restart system using a previously loaded Linux kernel KEXEC = 0x45584543, _, }; }; pub fn reboot(magic: LINUX_REBOOT.MAGIC1, magic2: LINUX_REBOOT.MAGIC2, cmd: LINUX_REBOOT.CMD, arg: ?*const anyopaque) usize { return std.os.linux.syscall4( .reboot, @intFromEnum(magic), @intFromEnum(magic2), @intFromEnum(cmd), @intFromPtr(arg), ); } pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { return syscall3(.getrandom, @intFromPtr(buf), count, flags); } pub fn kill(pid: pid_t, sig: i32) usize { return syscall2(.kill, @as(usize, @bitCast(@as(isize, pid))), @as(usize, @bitCast(@as(isize, sig)))); } pub fn tkill(tid: pid_t, sig: i32) usize { return syscall2(.tkill, @as(usize, @bitCast(@as(isize, tid))), @as(usize, @bitCast(@as(isize, sig)))); } pub fn tgkill(tgid: pid_t, tid: pid_t, sig: i32) usize { return syscall3(.tgkill, @as(usize, @bitCast(@as(isize, tgid))), @as(usize, @bitCast(@as(isize, tid))), @as(usize, @bitCast(@as(isize, sig)))); } pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) usize { if (@hasField(SYS, "link")) { return syscall2( .link, @intFromPtr(oldpath), @intFromPtr(newpath), ); } else { return syscall5( .linkat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(oldpath), @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(newpath), 0, ); } } pub fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: i32) usize { return syscall5( .linkat, @as(usize, @bitCast(@as(isize, oldfd))), @intFromPtr(oldpath), @as(usize, @bitCast(@as(isize, newfd))), @intFromPtr(newpath), @as(usize, @bitCast(@as(isize, flags))), ); } pub fn unlink(path: [*:0]const u8) usize { if (@hasField(SYS, "unlink")) { return syscall1(.unlink, @intFromPtr(path)); } else { return syscall3(.unlinkat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(path), 0); } } pub fn unlinkat(dirfd: i32, path: [*:0]const u8, flags: u32) usize { return syscall3(.unlinkat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), flags); } pub fn waitpid(pid: pid_t, status: *u32, flags: u32) usize { return syscall4(.wait4, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(status), flags, 0); } pub fn wait4(pid: pid_t, status: *u32, flags: u32, usage: ?*rusage) usize { return syscall4( .wait4, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(status), flags, @intFromPtr(usage), ); } pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize { return syscall5(.waitid, @intFromEnum(id_type), @as(usize, @bitCast(@as(isize, id))), @intFromPtr(infop), flags, 0); } pub const F = struct { pub const DUPFD = 0; pub const GETFD = 1; pub const SETFD = 2; pub const GETFL = 3; pub const SETFL = 4; pub const GETLK = GET_SET_LK.GETLK; pub const SETLK = GET_SET_LK.SETLK; pub const SETLKW = GET_SET_LK.SETLKW; const GET_SET_LK = if (@sizeOf(usize) == 64) extern struct { pub const GETLK = if (is_mips) 14 else if (is_sparc) 7 else 5; pub const SETLK = if (is_mips) 6 else if (is_sparc) 8 else 6; pub const SETLKW = if (is_mips) 7 else if (is_sparc) 9 else 7; } else extern struct { // Ensure that 32-bit code uses the large-file variants (GETLK64, etc). pub const GETLK = if (is_mips) 33 else 12; pub const SETLK = if (is_mips) 34 else 13; pub const SETLKW = if (is_mips) 35 else 14; }; pub const SETOWN = if (is_mips) 24 else if (is_sparc) 6 else 8; pub const GETOWN = if (is_mips) 23 else if (is_sparc) 5 else 9; pub const SETSIG = 10; pub const GETSIG = 11; pub const SETOWN_EX = 15; pub const GETOWN_EX = 16; pub const GETOWNER_UIDS = 17; pub const OFD_GETLK = 36; pub const OFD_SETLK = 37; pub const OFD_SETLKW = 38; pub const RDLCK = if (is_sparc) 1 else 0; pub const WRLCK = if (is_sparc) 2 else 1; pub const UNLCK = if (is_sparc) 3 else 2; }; pub const F_OWNER = enum(i32) { TID = 0, PID = 1, PGRP = 2, _, }; pub const f_owner_ex = extern struct { type: F_OWNER, pid: pid_t, }; pub const Flock = extern struct { type: i16, whence: i16, start: off_t, len: off_t, pid: pid_t, _unused: if (is_sparc) i16 else void, }; pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize { if (@hasField(SYS, "fcntl64")) { return syscall3(.fcntl64, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg); } else { return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg); } } pub fn flock(fd: fd_t, operation: i32) usize { return syscall2(.flock, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, operation)))); } pub const Elf_Symndx = if (native_arch == .s390x) u64 else u32; // We must follow the C calling convention when we call into the VDSO const VdsoClockGettime = *align(1) const fn (clockid_t, *timespec) callconv(.c) usize; var vdso_clock_gettime: ?VdsoClockGettime = &init_vdso_clock_gettime; pub fn clock_gettime(clk_id: clockid_t, tp: *timespec) usize { if (VDSO != void) { const ptr = @atomicLoad(?VdsoClockGettime, &vdso_clock_gettime, .unordered); if (ptr) |f| { const rc = f(clk_id, tp); switch (rc) { 0, @as(usize, @bitCast(-@as(isize, @intFromEnum(E.INVAL)))) => return rc, else => {}, } } } return syscall2( if (@hasField(SYS, "clock_gettime") and native_arch != .hexagon) .clock_gettime else .clock_gettime64, @intFromEnum(clk_id), @intFromPtr(tp), ); } fn init_vdso_clock_gettime(clk: clockid_t, ts: *timespec) callconv(.c) usize { const ptr: ?VdsoClockGettime = @ptrFromInt(vdso.lookup(VDSO.CGT_VER, VDSO.CGT_SYM)); // Note that we may not have a VDSO at all, update the stub address anyway // so that clock_gettime will fall back on the good old (and slow) syscall @atomicStore(?VdsoClockGettime, &vdso_clock_gettime, ptr, .monotonic); // Call into the VDSO if available if (ptr) |f| return f(clk, ts); return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS)))); } pub fn clock_getres(clk_id: i32, tp: *timespec) usize { return syscall2( if (@hasField(SYS, "clock_getres") and native_arch != .hexagon) .clock_getres else .clock_getres_time64, @as(usize, @bitCast(@as(isize, clk_id))), @intFromPtr(tp), ); } pub fn clock_settime(clk_id: i32, tp: *const timespec) usize { return syscall2( if (@hasField(SYS, "clock_settime") and native_arch != .hexagon) .clock_settime else .clock_settime64, @as(usize, @bitCast(@as(isize, clk_id))), @intFromPtr(tp), ); } pub fn clock_nanosleep(clockid: clockid_t, flags: TIMER, request: *const timespec, remain: ?*timespec) usize { return syscall4( if (@hasField(SYS, "clock_nanosleep") and native_arch != .hexagon) .clock_nanosleep else .clock_nanosleep_time64, @intFromEnum(clockid), @as(u32, @bitCast(flags)), @intFromPtr(request), @intFromPtr(remain), ); } pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) usize { return syscall2(.gettimeofday, @intFromPtr(tv), @intFromPtr(tz)); } pub fn settimeofday(tv: *const timeval, tz: *const timezone) usize { return syscall2(.settimeofday, @intFromPtr(tv), @intFromPtr(tz)); } pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize { if (native_arch == .riscv32) { @compileError("No nanosleep syscall on this architecture."); } else return syscall2(.nanosleep, @intFromPtr(req), @intFromPtr(rem)); } pub fn pause() usize { if (@hasField(SYS, "pause")) { return syscall0(.pause); } else { return syscall4(.ppoll, 0, 0, 0, 0); } } pub fn setuid(uid: uid_t) usize { if (@hasField(SYS, "setuid32")) { return syscall1(.setuid32, uid); } else { return syscall1(.setuid, uid); } } pub fn setgid(gid: gid_t) usize { if (@hasField(SYS, "setgid32")) { return syscall1(.setgid32, gid); } else { return syscall1(.setgid, gid); } } pub fn setreuid(ruid: uid_t, euid: uid_t) usize { if (@hasField(SYS, "setreuid32")) { return syscall2(.setreuid32, ruid, euid); } else { return syscall2(.setreuid, ruid, euid); } } pub fn setregid(rgid: gid_t, egid: gid_t) usize { if (@hasField(SYS, "setregid32")) { return syscall2(.setregid32, rgid, egid); } else { return syscall2(.setregid, rgid, egid); } } pub fn getuid() uid_t { if (@hasField(SYS, "getuid32")) { return @as(uid_t, @intCast(syscall0(.getuid32))); } else { return @as(uid_t, @intCast(syscall0(.getuid))); } } pub fn getgid() gid_t { if (@hasField(SYS, "getgid32")) { return @as(gid_t, @intCast(syscall0(.getgid32))); } else { return @as(gid_t, @intCast(syscall0(.getgid))); } } pub fn geteuid() uid_t { if (@hasField(SYS, "geteuid32")) { return @as(uid_t, @intCast(syscall0(.geteuid32))); } else { return @as(uid_t, @intCast(syscall0(.geteuid))); } } pub fn getegid() gid_t { if (@hasField(SYS, "getegid32")) { return @as(gid_t, @intCast(syscall0(.getegid32))); } else { return @as(gid_t, @intCast(syscall0(.getegid))); } } pub fn seteuid(euid: uid_t) usize { // We use setresuid here instead of setreuid to ensure that the saved uid // is not changed. This is what musl and recent glibc versions do as well. // // The setresuid(2) man page says that if -1 is passed the corresponding // id will not be changed. Since uid_t is unsigned, this wraps around to the // max value in C. comptime assert(@typeInfo(uid_t) == .int and @typeInfo(uid_t).int.signedness == .unsigned); return setresuid(maxInt(uid_t), euid, maxInt(uid_t)); } pub fn setegid(egid: gid_t) usize { // We use setresgid here instead of setregid to ensure that the saved uid // is not changed. This is what musl and recent glibc versions do as well. // // The setresgid(2) man page says that if -1 is passed the corresponding // id will not be changed. Since gid_t is unsigned, this wraps around to the // max value in C. comptime assert(@typeInfo(uid_t) == .int and @typeInfo(uid_t).int.signedness == .unsigned); return setresgid(maxInt(gid_t), egid, maxInt(gid_t)); } pub fn getresuid(ruid: *uid_t, euid: *uid_t, suid: *uid_t) usize { if (@hasField(SYS, "getresuid32")) { return syscall3(.getresuid32, @intFromPtr(ruid), @intFromPtr(euid), @intFromPtr(suid)); } else { return syscall3(.getresuid, @intFromPtr(ruid), @intFromPtr(euid), @intFromPtr(suid)); } } pub fn getresgid(rgid: *gid_t, egid: *gid_t, sgid: *gid_t) usize { if (@hasField(SYS, "getresgid32")) { return syscall3(.getresgid32, @intFromPtr(rgid), @intFromPtr(egid), @intFromPtr(sgid)); } else { return syscall3(.getresgid, @intFromPtr(rgid), @intFromPtr(egid), @intFromPtr(sgid)); } } pub fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) usize { if (@hasField(SYS, "setresuid32")) { return syscall3(.setresuid32, ruid, euid, suid); } else { return syscall3(.setresuid, ruid, euid, suid); } } pub fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) usize { if (@hasField(SYS, "setresgid32")) { return syscall3(.setresgid32, rgid, egid, sgid); } else { return syscall3(.setresgid, rgid, egid, sgid); } } pub fn setpgid(pid: pid_t, pgid: pid_t) usize { return syscall2(.setpgid, @intCast(pid), @intCast(pgid)); } pub fn getgroups(size: usize, list: ?*gid_t) usize { if (@hasField(SYS, "getgroups32")) { return syscall2(.getgroups32, size, @intFromPtr(list)); } else { return syscall2(.getgroups, size, @intFromPtr(list)); } } pub fn setgroups(size: usize, list: [*]const gid_t) usize { if (@hasField(SYS, "setgroups32")) { return syscall2(.setgroups32, size, @intFromPtr(list)); } else { return syscall2(.setgroups, size, @intFromPtr(list)); } } pub fn setsid() usize { return syscall0(.setsid); } pub fn getpid() pid_t { // Casts result to a pid_t, safety-checking >= 0, because getpid() cannot fail return @intCast(@as(u32, @truncate(syscall0(.getpid)))); } pub fn getppid() pid_t { // Casts result to a pid_t, safety-checking >= 0, because getppid() cannot fail return @intCast(@as(u32, @truncate(syscall0(.getppid)))); } pub fn gettid() pid_t { // Casts result to a pid_t, safety-checking >= 0, because gettid() cannot fail return @intCast(@as(u32, @truncate(syscall0(.gettid)))); } pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?*sigset_t) usize { return syscall4(.rt_sigprocmask, flags, @intFromPtr(set), @intFromPtr(oldset), NSIG / 8); } pub fn sigaction(sig: u8, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { assert(sig > 0); assert(sig < NSIG); assert(sig != SIG.KILL); assert(sig != SIG.STOP); var ksa: k_sigaction = undefined; var oldksa: k_sigaction = undefined; const mask_size = @sizeOf(@TypeOf(ksa.mask)); if (act) |new| { if (native_arch == .hexagon or is_loongarch or is_mips or native_arch == .or1k or is_riscv) { ksa = .{ .handler = new.handler.handler, .flags = new.flags, .mask = new.mask, }; } else { // Zig needs to install our arch restorer function with any signal handler, so // must copy the Sigaction struct const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore; ksa = .{ .handler = new.handler.handler, .flags = new.flags | SA.RESTORER, .mask = new.mask, .restorer = @ptrCast(restorer_fn), }; } } const ksa_arg = if (act != null) @intFromPtr(&ksa) else 0; const oldksa_arg = if (oact != null) @intFromPtr(&oldksa) else 0; const result = switch (native_arch) { // The sparc version of rt_sigaction needs the restorer function to be passed as an argument too. .sparc, .sparc64 => syscall5(.rt_sigaction, sig, ksa_arg, oldksa_arg, @intFromPtr(ksa.restorer), mask_size), else => syscall4(.rt_sigaction, sig, ksa_arg, oldksa_arg, mask_size), }; if (E.init(result) != .SUCCESS) return result; if (oact) |old| { old.handler.handler = oldksa.handler; old.flags = oldksa.flags; old.mask = oldksa.mask; } return 0; } const usize_bits = @typeInfo(usize).int.bits; /// Defined as one greater than the largest defined signal number. pub const NSIG = if (is_mips) 128 else 65; /// Linux kernel's sigset_t. This is logically 64-bit on most /// architectures, but 128-bit on MIPS. Contrast with the 1024-bit /// sigset_t exported by the glibc and musl library ABIs. pub const sigset_t = [(NSIG - 1 + 7) / @bitSizeOf(SigsetElement)]SigsetElement; const SigsetElement = c_ulong; const sigset_len = @typeInfo(sigset_t).array.len; /// Zig's SIGRTMIN, but is a function for compatibility with glibc pub fn sigrtmin() u8 { // Default is 32 in the kernel UAPI: https://github.com/torvalds/linux/blob/78109c591b806e41987e0b83390e61d675d1f724/include/uapi/asm-generic/signal.h#L50 // AFAICT, all architectures that override this also set it to 32: // https://github.com/search?q=repo%3Atorvalds%2Flinux+sigrtmin+path%3Auapi&type=code return 32; } /// Zig's SIGRTMAX, but is a function for compatibility with glibc pub fn sigrtmax() u8 { return NSIG - 1; } /// Zig's version of sigemptyset. Returns initialized sigset_t. pub fn sigemptyset() sigset_t { return [_]SigsetElement{0} ** sigset_len; } /// Zig's version of sigfillset. Returns initalized sigset_t. pub fn sigfillset() sigset_t { return [_]SigsetElement{~@as(SigsetElement, 0)} ** sigset_len; } fn sigset_bit_index(sig: usize) struct { word: usize, mask: SigsetElement } { assert(sig > 0); assert(sig < NSIG); const bit = sig - 1; return .{ .word = bit / @bitSizeOf(SigsetElement), .mask = @as(SigsetElement, 1) << @truncate(bit % @bitSizeOf(SigsetElement)), }; } pub fn sigaddset(set: *sigset_t, sig: usize) void { const index = sigset_bit_index(sig); (set.*)[index.word] |= index.mask; } pub fn sigdelset(set: *sigset_t, sig: usize) void { const index = sigset_bit_index(sig); (set.*)[index.word] ^= index.mask; } pub fn sigismember(set: *const sigset_t, sig: usize) bool { const index = sigset_bit_index(sig); return ((set.*)[index.word] & index.mask) != 0; } pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { if (native_arch == .x86) { return socketcall(SC.getsockname, &[3]usize{ @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len) }); } return syscall3(.getsockname, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len)); } pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { if (native_arch == .x86) { return socketcall(SC.getpeername, &[3]usize{ @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len) }); } return syscall3(.getpeername, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len)); } pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { if (native_arch == .x86) { return socketcall(SC.socket, &[3]usize{ domain, socket_type, protocol }); } return syscall3(.socket, domain, socket_type, protocol); } pub fn setsockopt(fd: i32, level: i32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize { if (native_arch == .x86) { return socketcall(SC.setsockopt, &[5]usize{ @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, level))), optname, @intFromPtr(optval), @as(usize, @intCast(optlen)) }); } return syscall5(.setsockopt, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, level))), optname, @intFromPtr(optval), @as(usize, @intCast(optlen))); } pub fn getsockopt(fd: i32, level: i32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize { if (native_arch == .x86) { return socketcall(SC.getsockopt, &[5]usize{ @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, level))), optname, @intFromPtr(optval), @intFromPtr(optlen) }); } return syscall5(.getsockopt, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, level))), optname, @intFromPtr(optval), @intFromPtr(optlen)); } pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize { const fd_usize = @as(usize, @bitCast(@as(isize, fd))); const msg_usize = @intFromPtr(msg); if (native_arch == .x86) { return socketcall(SC.sendmsg, &[3]usize{ fd_usize, msg_usize, flags }); } else { return syscall3(.sendmsg, fd_usize, msg_usize, flags); } } pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr, vlen: u32, flags: u32) usize { return syscall4(.sendmmsg, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(msgvec), vlen, flags); } pub fn connect(fd: i32, addr: *const anyopaque, len: socklen_t) usize { const fd_usize = @as(usize, @bitCast(@as(isize, fd))); const addr_usize = @intFromPtr(addr); if (native_arch == .x86) { return socketcall(SC.connect, &[3]usize{ fd_usize, addr_usize, len }); } else { return syscall3(.connect, fd_usize, addr_usize, len); } } pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { const fd_usize = @as(usize, @bitCast(@as(isize, fd))); const msg_usize = @intFromPtr(msg); if (native_arch == .x86) { return socketcall(SC.recvmsg, &[3]usize{ fd_usize, msg_usize, flags }); } else { return syscall3(.recvmsg, fd_usize, msg_usize, flags); } } pub fn recvmmsg(fd: i32, msgvec: ?[*]mmsghdr, vlen: u32, flags: u32, timeout: ?*timespec) usize { return syscall5( if (@hasField(SYS, "recvmmsg") and native_arch != .hexagon) .recvmmsg else .recvmmsg_time64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(msgvec), vlen, flags, @intFromPtr(timeout), ); } pub fn recvfrom( fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t, ) usize { const fd_usize = @as(usize, @bitCast(@as(isize, fd))); const buf_usize = @intFromPtr(buf); const addr_usize = @intFromPtr(addr); const alen_usize = @intFromPtr(alen); if (native_arch == .x86) { return socketcall(SC.recvfrom, &[6]usize{ fd_usize, buf_usize, len, flags, addr_usize, alen_usize }); } else { return syscall6(.recvfrom, fd_usize, buf_usize, len, flags, addr_usize, alen_usize); } } pub fn shutdown(fd: i32, how: i32) usize { if (native_arch == .x86) { return socketcall(SC.shutdown, &[2]usize{ @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, how))) }); } return syscall2(.shutdown, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, how)))); } pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize { if (native_arch == .x86) { return socketcall(SC.bind, &[3]usize{ @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @as(usize, @intCast(len)) }); } return syscall3(.bind, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @as(usize, @intCast(len))); } pub fn listen(fd: i32, backlog: u32) usize { if (native_arch == .x86) { return socketcall(SC.listen, &[2]usize{ @as(usize, @bitCast(@as(isize, fd))), backlog }); } return syscall2(.listen, @as(usize, @bitCast(@as(isize, fd))), backlog); } pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize { if (native_arch == .x86) { return socketcall(SC.sendto, &[6]usize{ @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), len, flags, @intFromPtr(addr), @as(usize, @intCast(alen)) }); } return syscall6(.sendto, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), len, flags, @intFromPtr(addr), @as(usize, @intCast(alen))); } pub fn sendfile(outfd: i32, infd: i32, offset: ?*i64, count: usize) usize { if (@hasField(SYS, "sendfile64")) { return syscall4( .sendfile64, @as(usize, @bitCast(@as(isize, outfd))), @as(usize, @bitCast(@as(isize, infd))), @intFromPtr(offset), count, ); } else { return syscall4( .sendfile, @as(usize, @bitCast(@as(isize, outfd))), @as(usize, @bitCast(@as(isize, infd))), @intFromPtr(offset), count, ); } } pub fn socketpair(domain: u32, socket_type: u32, protocol: u32, fd: *[2]i32) usize { if (native_arch == .x86) { return socketcall(SC.socketpair, &[4]usize{ domain, socket_type, protocol, @intFromPtr(fd) }); } return syscall4(.socketpair, domain, socket_type, protocol, @intFromPtr(fd)); } pub fn accept(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t) usize { if (native_arch == .x86) { return socketcall(SC.accept, &[4]usize{ @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len), 0 }); } return accept4(fd, addr, len, 0); } pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flags: u32) usize { if (native_arch == .x86) { return socketcall(SC.accept4, &[4]usize{ @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len), flags }); } return syscall4(.accept4, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len), flags); } pub fn fstat(fd: i32, stat_buf: *Stat) usize { if (native_arch == .riscv32 or native_arch.isLoongArch()) { // riscv32 and loongarch have made the interesting decision to not implement some of // the older stat syscalls, including this one. @compileError("No fstat syscall on this architecture."); } else if (@hasField(SYS, "fstat64")) { return syscall2(.fstat64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf)); } else { return syscall2(.fstat, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf)); } } pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize { if (native_arch == .riscv32 or native_arch.isLoongArch()) { // riscv32 and loongarch have made the interesting decision to not implement some of // the older stat syscalls, including this one. @compileError("No stat syscall on this architecture."); } else if (@hasField(SYS, "stat64")) { return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf)); } else { return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf)); } } pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize { if (native_arch == .riscv32 or native_arch.isLoongArch()) { // riscv32 and loongarch have made the interesting decision to not implement some of // the older stat syscalls, including this one. @compileError("No lstat syscall on this architecture."); } else if (@hasField(SYS, "lstat64")) { return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf)); } else { return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf)); } } pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usize { if (native_arch == .riscv32 or native_arch.isLoongArch()) { // riscv32 and loongarch have made the interesting decision to not implement some of // the older stat syscalls, including this one. @compileError("No fstatat syscall on this architecture."); } else if (@hasField(SYS, "fstatat64")) { return syscall4(.fstatat64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags); } else { return syscall4(.fstatat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags); } } pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize { return syscall5( .statx, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), flags, mask, @intFromPtr(statx_buf), ); } pub fn listxattr(path: [*:0]const u8, list: [*]u8, size: usize) usize { return syscall3(.listxattr, @intFromPtr(path), @intFromPtr(list), size); } pub fn llistxattr(path: [*:0]const u8, list: [*]u8, size: usize) usize { return syscall3(.llistxattr, @intFromPtr(path), @intFromPtr(list), size); } pub fn flistxattr(fd: fd_t, list: [*]u8, size: usize) usize { return syscall3(.flistxattr, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(list), size); } pub fn getxattr(path: [*:0]const u8, name: [*:0]const u8, value: [*]u8, size: usize) usize { return syscall4(.getxattr, @intFromPtr(path), @intFromPtr(name), @intFromPtr(value), size); } pub fn lgetxattr(path: [*:0]const u8, name: [*:0]const u8, value: [*]u8, size: usize) usize { return syscall4(.lgetxattr, @intFromPtr(path), @intFromPtr(name), @intFromPtr(value), size); } pub fn fgetxattr(fd: fd_t, name: [*:0]const u8, value: [*]u8, size: usize) usize { return syscall4(.fgetxattr, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(name), @intFromPtr(value), size); } pub fn setxattr(path: [*:0]const u8, name: [*:0]const u8, value: [*]const u8, size: usize, flags: usize) usize { return syscall5(.setxattr, @intFromPtr(path), @intFromPtr(name), @intFromPtr(value), size, flags); } pub fn lsetxattr(path: [*:0]const u8, name: [*:0]const u8, value: [*]const u8, size: usize, flags: usize) usize { return syscall5(.lsetxattr, @intFromPtr(path), @intFromPtr(name), @intFromPtr(value), size, flags); } pub fn fsetxattr(fd: fd_t, name: [*:0]const u8, value: [*]const u8, size: usize, flags: usize) usize { return syscall5(.fsetxattr, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(name), @intFromPtr(value), size, flags); } pub fn removexattr(path: [*:0]const u8, name: [*:0]const u8) usize { return syscall2(.removexattr, @intFromPtr(path), @intFromPtr(name)); } pub fn lremovexattr(path: [*:0]const u8, name: [*:0]const u8) usize { return syscall2(.lremovexattr, @intFromPtr(path), @intFromPtr(name)); } pub fn fremovexattr(fd: usize, name: [*:0]const u8) usize { return syscall2(.fremovexattr, fd, @intFromPtr(name)); } pub const sched_param = extern struct { priority: i32, }; pub const SCHED = packed struct(i32) { pub const Mode = enum(u3) { /// normal multi-user scheduling NORMAL = 0, /// FIFO realtime scheduling FIFO = 1, /// Round-robin realtime scheduling RR = 2, /// For "batch" style execution of processes BATCH = 3, /// Low latency scheduling IDLE = 5, /// Sporadic task model deadline scheduling DEADLINE = 6, }; mode: Mode, //bits [0, 2] _3: u27 = 0, //bits [3, 29] /// set to true to stop children from inheriting policies RESET_ON_FORK: bool = false, //bit 30 _31: u1 = 0, //bit 31 }; pub fn sched_setparam(pid: pid_t, param: *const sched_param) usize { return syscall2(.sched_setparam, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(param)); } pub fn sched_getparam(pid: pid_t, param: *sched_param) usize { return syscall2(.sched_getparam, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(param)); } pub fn sched_setscheduler(pid: pid_t, policy: SCHED, param: *const sched_param) usize { return syscall3(.sched_setscheduler, @as(usize, @bitCast(@as(isize, pid))), @intCast(@as(u32, @bitCast(policy))), @intFromPtr(param)); } pub fn sched_getscheduler(pid: pid_t) usize { return syscall1(.sched_getscheduler, @as(usize, @bitCast(@as(isize, pid)))); } pub fn sched_get_priority_max(policy: SCHED) usize { return syscall1(.sched_get_priority_max, @intCast(@as(u32, @bitCast(policy)))); } pub fn sched_get_priority_min(policy: SCHED) usize { return syscall1(.sched_get_priority_min, @intCast(@as(u32, @bitCast(policy)))); } pub fn getcpu(cpu: ?*usize, node: ?*usize) usize { return syscall2(.getcpu, @intFromPtr(cpu), @intFromPtr(node)); } pub const sched_attr = extern struct { size: u32 = 48, // Size of this structure policy: u32 = 0, // Policy (SCHED_*) flags: u64 = 0, // Flags nice: u32 = 0, // Nice value (SCHED_OTHER, SCHED_BATCH) priority: u32 = 0, // Static priority (SCHED_FIFO, SCHED_RR) // Remaining fields are for SCHED_DEADLINE runtime: u64 = 0, deadline: u64 = 0, period: u64 = 0, }; pub fn sched_setattr(pid: pid_t, attr: *const sched_attr, flags: usize) usize { return syscall3(.sched_setattr, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(attr), flags); } pub fn sched_getattr(pid: pid_t, attr: *sched_attr, size: usize, flags: usize) usize { return syscall4(.sched_getattr, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(attr), size, flags); } pub fn sched_rr_get_interval(pid: pid_t, tp: *timespec) usize { return syscall2(.sched_rr_get_interval, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(tp)); } pub fn sched_yield() usize { return syscall0(.sched_yield); } pub fn sched_getaffinity(pid: pid_t, size: usize, set: *cpu_set_t) usize { const rc = syscall3(.sched_getaffinity, @as(usize, @bitCast(@as(isize, pid))), size, @intFromPtr(set)); if (@as(isize, @bitCast(rc)) < 0) return rc; if (rc < size) @memset(@as([*]u8, @ptrCast(set))[rc..size], 0); return 0; } pub fn sched_setaffinity(pid: pid_t, set: *const cpu_set_t) !void { const size = @sizeOf(cpu_set_t); const rc = syscall3(.sched_setaffinity, @as(usize, @bitCast(@as(isize, pid))), size, @intFromPtr(set)); switch (E.init(rc)) { .SUCCESS => return, else => |err| return std.posix.unexpectedErrno(err), } } pub fn epoll_create() usize { return epoll_create1(0); } pub fn epoll_create1(flags: usize) usize { return syscall1(.epoll_create1, flags); } pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: ?*epoll_event) usize { return syscall4(.epoll_ctl, @as(usize, @bitCast(@as(isize, epoll_fd))), @as(usize, @intCast(op)), @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(ev)); } pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize { return epoll_pwait(epoll_fd, events, maxevents, timeout, null); } pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*const sigset_t) usize { return syscall6( .epoll_pwait, @as(usize, @bitCast(@as(isize, epoll_fd))), @intFromPtr(events), @as(usize, @intCast(maxevents)), @as(usize, @bitCast(@as(isize, timeout))), @intFromPtr(sigmask), NSIG / 8, ); } pub fn eventfd(count: u32, flags: u32) usize { return syscall2(.eventfd2, count, flags); } pub fn timerfd_create(clockid: timerfd_clockid_t, flags: TFD) usize { return syscall2( .timerfd_create, @intFromEnum(clockid), @as(u32, @bitCast(flags)), ); } pub const itimerspec = extern struct { it_interval: timespec, it_value: timespec, }; pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { return syscall2( if (@hasField(SYS, "timerfd_gettime") and native_arch != .hexagon) .timerfd_gettime else .timerfd_gettime64, @bitCast(@as(isize, fd)), @intFromPtr(curr_value), ); } pub fn timerfd_settime(fd: i32, flags: TFD.TIMER, new_value: *const itimerspec, old_value: ?*itimerspec) usize { return syscall4( if (@hasField(SYS, "timerfd_settime") and native_arch != .hexagon) .timerfd_settime else .timerfd_settime64, @bitCast(@as(isize, fd)), @as(u32, @bitCast(flags)), @intFromPtr(new_value), @intFromPtr(old_value), ); } // Flags for the 'setitimer' system call pub const ITIMER = enum(i32) { REAL = 0, VIRTUAL = 1, PROF = 2, }; pub fn getitimer(which: i32, curr_value: *itimerspec) usize { return syscall2(.getitimer, @as(usize, @bitCast(@as(isize, which))), @intFromPtr(curr_value)); } pub fn setitimer(which: i32, new_value: *const itimerspec, old_value: ?*itimerspec) usize { return syscall3(.setitimer, @as(usize, @bitCast(@as(isize, which))), @intFromPtr(new_value), @intFromPtr(old_value)); } pub fn unshare(flags: usize) usize { return syscall1(.unshare, flags); } pub fn setns(fd: fd_t, flags: u32) usize { return syscall2(.setns, fd, flags); } pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize { return syscall2(.capget, @intFromPtr(hdrp), @intFromPtr(datap)); } pub fn capset(hdrp: *cap_user_header_t, datap: *const cap_user_data_t) usize { return syscall2(.capset, @intFromPtr(hdrp), @intFromPtr(datap)); } pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) usize { return syscall2(.sigaltstack, @intFromPtr(ss), @intFromPtr(old_ss)); } pub fn uname(uts: *utsname) usize { return syscall1(.uname, @intFromPtr(uts)); } pub fn io_uring_setup(entries: u32, p: *io_uring_params) usize { return syscall2(.io_uring_setup, entries, @intFromPtr(p)); } pub fn io_uring_enter(fd: i32, to_submit: u32, min_complete: u32, flags: u32, sig: ?*sigset_t) usize { return syscall6(.io_uring_enter, @as(usize, @bitCast(@as(isize, fd))), to_submit, min_complete, flags, @intFromPtr(sig), NSIG / 8); } pub fn io_uring_register(fd: i32, opcode: IORING_REGISTER, arg: ?*const anyopaque, nr_args: u32) usize { return syscall4(.io_uring_register, @as(usize, @bitCast(@as(isize, fd))), @intFromEnum(opcode), @intFromPtr(arg), nr_args); } pub fn memfd_create(name: [*:0]const u8, flags: u32) usize { return syscall2(.memfd_create, @intFromPtr(name), flags); } pub fn getrusage(who: i32, usage: *rusage) usize { return syscall2(.getrusage, @as(usize, @bitCast(@as(isize, who))), @intFromPtr(usage)); } pub fn tcgetattr(fd: fd_t, termios_p: *termios) usize { return syscall3(.ioctl, @as(usize, @bitCast(@as(isize, fd))), T.CGETS, @intFromPtr(termios_p)); } pub fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) usize { return syscall3(.ioctl, @as(usize, @bitCast(@as(isize, fd))), T.CSETS + @intFromEnum(optional_action), @intFromPtr(termios_p)); } pub fn tcgetpgrp(fd: fd_t, pgrp: *pid_t) usize { return syscall3(.ioctl, @as(usize, @bitCast(@as(isize, fd))), T.IOCGPGRP, @intFromPtr(pgrp)); } pub fn tcsetpgrp(fd: fd_t, pgrp: *const pid_t) usize { return syscall3(.ioctl, @as(usize, @bitCast(@as(isize, fd))), T.IOCSPGRP, @intFromPtr(pgrp)); } pub fn tcdrain(fd: fd_t) usize { return syscall3(.ioctl, @as(usize, @bitCast(@as(isize, fd))), T.CSBRK, 1); } pub fn ioctl(fd: fd_t, request: u32, arg: usize) usize { return syscall3(.ioctl, @as(usize, @bitCast(@as(isize, fd))), request, arg); } pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) usize { return syscall4(.signalfd4, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(mask), NSIG / 8, flags); } pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) usize { return syscall6( .copy_file_range, @as(usize, @bitCast(@as(isize, fd_in))), @intFromPtr(off_in), @as(usize, @bitCast(@as(isize, fd_out))), @intFromPtr(off_out), len, flags, ); } pub fn bpf(cmd: BPF.Cmd, attr: *BPF.Attr, size: u32) usize { return syscall3(.bpf, @intFromEnum(cmd), @intFromPtr(attr), size); } pub fn sync() void { _ = syscall0(.sync); } pub fn syncfs(fd: fd_t) usize { return syscall1(.syncfs, @as(usize, @bitCast(@as(isize, fd)))); } pub fn fsync(fd: fd_t) usize { return syscall1(.fsync, @as(usize, @bitCast(@as(isize, fd)))); } pub fn fdatasync(fd: fd_t) usize { return syscall1(.fdatasync, @as(usize, @bitCast(@as(isize, fd)))); } pub fn prctl(option: i32, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { return syscall5(.prctl, @as(usize, @bitCast(@as(isize, option))), arg2, arg3, arg4, arg5); } pub fn getrlimit(resource: rlimit_resource, rlim: *rlimit) usize { // use prlimit64 to have 64 bit limits on 32 bit platforms return prlimit(0, resource, null, rlim); } pub fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) usize { // use prlimit64 to have 64 bit limits on 32 bit platforms return prlimit(0, resource, rlim, null); } pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit, old_limit: ?*rlimit) usize { return syscall4( .prlimit64, @as(usize, @bitCast(@as(isize, pid))), @as(usize, @bitCast(@as(isize, @intFromEnum(resource)))), @intFromPtr(new_limit), @intFromPtr(old_limit), ); } pub fn mincore(address: [*]u8, len: usize, vec: [*]u8) usize { return syscall3(.mincore, @intFromPtr(address), len, @intFromPtr(vec)); } pub fn madvise(address: [*]u8, len: usize, advice: u32) usize { return syscall3(.madvise, @intFromPtr(address), len, advice); } pub fn pidfd_open(pid: pid_t, flags: u32) usize { return syscall2(.pidfd_open, @as(usize, @bitCast(@as(isize, pid))), flags); } pub fn pidfd_getfd(pidfd: fd_t, targetfd: fd_t, flags: u32) usize { return syscall3( .pidfd_getfd, @as(usize, @bitCast(@as(isize, pidfd))), @as(usize, @bitCast(@as(isize, targetfd))), flags, ); } pub fn pidfd_send_signal(pidfd: fd_t, sig: i32, info: ?*siginfo_t, flags: u32) usize { return syscall4( .pidfd_send_signal, @as(usize, @bitCast(@as(isize, pidfd))), @as(usize, @bitCast(@as(isize, sig))), @intFromPtr(info), flags, ); } pub fn process_vm_readv(pid: pid_t, local: []const iovec, remote: []const iovec_const, flags: usize) usize { return syscall6( .process_vm_readv, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(local.ptr), local.len, @intFromPtr(remote.ptr), remote.len, flags, ); } pub fn process_vm_writev(pid: pid_t, local: []const iovec_const, remote: []const iovec_const, flags: usize) usize { return syscall6( .process_vm_writev, @as(usize, @bitCast(@as(isize, pid))), @intFromPtr(local.ptr), local.len, @intFromPtr(remote.ptr), remote.len, flags, ); } pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize { if (comptime native_arch.isArm() or native_arch == .hexagon or native_arch.isPowerPC32()) { // These architectures reorder the arguments so that a register is not skipped to align the // register number that `offset` is passed in. const offset_halves = splitValue64(offset); const length_halves = splitValue64(len); return syscall6( .fadvise64_64, @as(usize, @bitCast(@as(isize, fd))), advice, offset_halves[0], offset_halves[1], length_halves[0], length_halves[1], ); } else if (native_arch.isMIPS32()) { // MIPS O32 does not deal with the register alignment issue, so pass a dummy value. const offset_halves = splitValue64(offset); const length_halves = splitValue64(len); return syscall7( .fadvise64, @as(usize, @bitCast(@as(isize, fd))), 0, offset_halves[0], offset_halves[1], length_halves[0], length_halves[1], advice, ); } else if (comptime usize_bits < 64) { // Other 32-bit architectures do not require register alignment. const offset_halves = splitValue64(offset); const length_halves = splitValue64(len); return syscall6( switch (builtin.abi) { .gnuabin32, .gnux32, .muslabin32, .muslx32 => .fadvise64, else => .fadvise64_64, }, @as(usize, @bitCast(@as(isize, fd))), offset_halves[0], offset_halves[1], length_halves[0], length_halves[1], advice, ); } else { // On 64-bit architectures, fadvise64_64 and fadvise64 are the same. Generally, older ports // call it fadvise64 (x86, PowerPC, etc), while newer ports call it fadvise64_64 (RISC-V, // LoongArch, etc). SPARC is the odd one out because it has both. return syscall4( if (@hasField(SYS, "fadvise64_64")) .fadvise64_64 else .fadvise64, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(offset)), @as(usize, @bitCast(len)), advice, ); } } pub fn perf_event_open( attr: *perf_event_attr, pid: pid_t, cpu: i32, group_fd: fd_t, flags: usize, ) usize { return syscall5( .perf_event_open, @intFromPtr(attr), @as(usize, @bitCast(@as(isize, pid))), @as(usize, @bitCast(@as(isize, cpu))), @as(usize, @bitCast(@as(isize, group_fd))), flags, ); } pub fn seccomp(operation: u32, flags: u32, args: ?*const anyopaque) usize { return syscall3(.seccomp, operation, flags, @intFromPtr(args)); } pub fn ptrace( req: u32, pid: pid_t, addr: usize, data: usize, addr2: usize, ) usize { return syscall5( .ptrace, req, @as(usize, @bitCast(@as(isize, pid))), addr, data, addr2, ); } /// Query the page cache statistics of a file. pub fn cachestat( /// The open file descriptor to retrieve statistics from. fd: fd_t, /// The byte range in `fd` to query. /// When `len > 0`, the range is `[off..off + len]`. /// When `len` == 0, the range is from `off` to the end of `fd`. cstat_range: *const cache_stat_range, /// The structure where page cache statistics are stored. cstat: *cache_stat, /// Currently unused, and must be set to `0`. flags: u32, ) usize { return syscall4( .cachestat, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(cstat_range), @intFromPtr(cstat), flags, ); } pub fn map_shadow_stack(addr: u64, size: u64, flags: u32) usize { return syscall3(.map_shadow_stack, addr, size, flags); } pub const Sysinfo = switch (native_abi) { .gnux32, .muslx32 => extern struct { /// Seconds since boot uptime: i64, /// 1, 5, and 15 minute load averages loads: [3]u64, /// Total usable main memory size totalram: u64, /// Available memory size freeram: u64, /// Amount of shared memory sharedram: u64, /// Memory used by buffers bufferram: u64, /// Total swap space size totalswap: u64, /// swap space still available freeswap: u64, /// Number of current processes procs: u16, /// Explicit padding for m68k pad: u16, /// Total high memory size totalhigh: u64, /// Available high memory size freehigh: u64, /// Memory unit size in bytes mem_unit: u32, }, else => extern struct { /// Seconds since boot uptime: isize, /// 1, 5, and 15 minute load averages loads: [3]usize, /// Total usable main memory size totalram: usize, /// Available memory size freeram: usize, /// Amount of shared memory sharedram: usize, /// Memory used by buffers bufferram: usize, /// Total swap space size totalswap: usize, /// swap space still available freeswap: usize, /// Number of current processes procs: u16, /// Explicit padding for m68k pad: u16, /// Total high memory size totalhigh: usize, /// Available high memory size freehigh: usize, /// Memory unit size in bytes mem_unit: u32, /// Pad _f: [20 - 2 * @sizeOf(usize) - @sizeOf(u32)]u8, }, }; pub fn sysinfo(info: *Sysinfo) usize { return syscall1(.sysinfo, @intFromPtr(info)); } pub const E = switch (native_arch) { .mips, .mipsel, .mips64, .mips64el => enum(u16) { /// No error occurred. SUCCESS = 0, PERM = 1, NOENT = 2, SRCH = 3, INTR = 4, IO = 5, NXIO = 6, @"2BIG" = 7, NOEXEC = 8, BADF = 9, CHILD = 10, /// Also used for WOULDBLOCK. AGAIN = 11, NOMEM = 12, ACCES = 13, FAULT = 14, NOTBLK = 15, BUSY = 16, EXIST = 17, XDEV = 18, NODEV = 19, NOTDIR = 20, ISDIR = 21, INVAL = 22, NFILE = 23, MFILE = 24, NOTTY = 25, TXTBSY = 26, FBIG = 27, NOSPC = 28, SPIPE = 29, ROFS = 30, MLINK = 31, PIPE = 32, DOM = 33, RANGE = 34, NOMSG = 35, IDRM = 36, CHRNG = 37, L2NSYNC = 38, L3HLT = 39, L3RST = 40, LNRNG = 41, UNATCH = 42, NOCSI = 43, L2HLT = 44, DEADLK = 45, NOLCK = 46, BADE = 50, BADR = 51, XFULL = 52, NOANO = 53, BADRQC = 54, BADSLT = 55, DEADLOCK = 56, BFONT = 59, NOSTR = 60, NODATA = 61, TIME = 62, NOSR = 63, NONET = 64, NOPKG = 65, REMOTE = 66, NOLINK = 67, ADV = 68, SRMNT = 69, COMM = 70, PROTO = 71, DOTDOT = 73, MULTIHOP = 74, BADMSG = 77, NAMETOOLONG = 78, OVERFLOW = 79, NOTUNIQ = 80, BADFD = 81, REMCHG = 82, LIBACC = 83, LIBBAD = 84, LIBSCN = 85, LIBMAX = 86, LIBEXEC = 87, ILSEQ = 88, NOSYS = 89, LOOP = 90, RESTART = 91, STRPIPE = 92, NOTEMPTY = 93, USERS = 94, NOTSOCK = 95, DESTADDRREQ = 96, MSGSIZE = 97, PROTOTYPE = 98, NOPROTOOPT = 99, PROTONOSUPPORT = 120, SOCKTNOSUPPORT = 121, OPNOTSUPP = 122, PFNOSUPPORT = 123, AFNOSUPPORT = 124, ADDRINUSE = 125, ADDRNOTAVAIL = 126, NETDOWN = 127, NETUNREACH = 128, NETRESET = 129, CONNABORTED = 130, CONNRESET = 131, NOBUFS = 132, ISCONN = 133, NOTCONN = 134, UCLEAN = 135, NOTNAM = 137, NAVAIL = 138, ISNAM = 139, REMOTEIO = 140, SHUTDOWN = 143, TOOMANYREFS = 144, TIMEDOUT = 145, CONNREFUSED = 146, HOSTDOWN = 147, HOSTUNREACH = 148, ALREADY = 149, INPROGRESS = 150, STALE = 151, CANCELED = 158, NOMEDIUM = 159, MEDIUMTYPE = 160, NOKEY = 161, KEYEXPIRED = 162, KEYREVOKED = 163, KEYREJECTED = 164, OWNERDEAD = 165, NOTRECOVERABLE = 166, RFKILL = 167, HWPOISON = 168, DQUOT = 1133, _, pub const init = errnoFromSyscall; }, .sparc, .sparc64 => enum(u16) { /// No error occurred. SUCCESS = 0, PERM = 1, NOENT = 2, SRCH = 3, INTR = 4, IO = 5, NXIO = 6, @"2BIG" = 7, NOEXEC = 8, BADF = 9, CHILD = 10, /// Also used for WOULDBLOCK AGAIN = 11, NOMEM = 12, ACCES = 13, FAULT = 14, NOTBLK = 15, BUSY = 16, EXIST = 17, XDEV = 18, NODEV = 19, NOTDIR = 20, ISDIR = 21, INVAL = 22, NFILE = 23, MFILE = 24, NOTTY = 25, TXTBSY = 26, FBIG = 27, NOSPC = 28, SPIPE = 29, ROFS = 30, MLINK = 31, PIPE = 32, DOM = 33, RANGE = 34, INPROGRESS = 36, ALREADY = 37, NOTSOCK = 38, DESTADDRREQ = 39, MSGSIZE = 40, PROTOTYPE = 41, NOPROTOOPT = 42, PROTONOSUPPORT = 43, SOCKTNOSUPPORT = 44, /// Also used for NOTSUP OPNOTSUPP = 45, PFNOSUPPORT = 46, AFNOSUPPORT = 47, ADDRINUSE = 48, ADDRNOTAVAIL = 49, NETDOWN = 50, NETUNREACH = 51, NETRESET = 52, CONNABORTED = 53, CONNRESET = 54, NOBUFS = 55, ISCONN = 56, NOTCONN = 57, SHUTDOWN = 58, TOOMANYREFS = 59, TIMEDOUT = 60, CONNREFUSED = 61, LOOP = 62, NAMETOOLONG = 63, HOSTDOWN = 64, HOSTUNREACH = 65, NOTEMPTY = 66, PROCLIM = 67, USERS = 68, DQUOT = 69, STALE = 70, REMOTE = 71, NOSTR = 72, TIME = 73, NOSR = 74, NOMSG = 75, BADMSG = 76, IDRM = 77, DEADLK = 78, NOLCK = 79, NONET = 80, RREMOTE = 81, NOLINK = 82, ADV = 83, SRMNT = 84, COMM = 85, PROTO = 86, MULTIHOP = 87, DOTDOT = 88, REMCHG = 89, NOSYS = 90, STRPIPE = 91, OVERFLOW = 92, BADFD = 93, CHRNG = 94, L2NSYNC = 95, L3HLT = 96, L3RST = 97, LNRNG = 98, UNATCH = 99, NOCSI = 100, L2HLT = 101, BADE = 102, BADR = 103, XFULL = 104, NOANO = 105, BADRQC = 106, BADSLT = 107, DEADLOCK = 108, BFONT = 109, LIBEXEC = 110, NODATA = 111, LIBBAD = 112, NOPKG = 113, LIBACC = 114, NOTUNIQ = 115, RESTART = 116, UCLEAN = 117, NOTNAM = 118, NAVAIL = 119, ISNAM = 120, REMOTEIO = 121, ILSEQ = 122, LIBMAX = 123, LIBSCN = 124, NOMEDIUM = 125, MEDIUMTYPE = 126, CANCELED = 127, NOKEY = 128, KEYEXPIRED = 129, KEYREVOKED = 130, KEYREJECTED = 131, OWNERDEAD = 132, NOTRECOVERABLE = 133, RFKILL = 134, HWPOISON = 135, _, pub const init = errnoFromSyscall; }, else => enum(u16) { /// No error occurred. /// Same code used for `NSROK`. SUCCESS = 0, /// Operation not permitted PERM = 1, /// No such file or directory NOENT = 2, /// No such process SRCH = 3, /// Interrupted system call INTR = 4, /// I/O error IO = 5, /// No such device or address NXIO = 6, /// Arg list too long @"2BIG" = 7, /// Exec format error NOEXEC = 8, /// Bad file number BADF = 9, /// No child processes CHILD = 10, /// Try again /// Also means: WOULDBLOCK: operation would block AGAIN = 11, /// Out of memory NOMEM = 12, /// Permission denied ACCES = 13, /// Bad address FAULT = 14, /// Block device required NOTBLK = 15, /// Device or resource busy BUSY = 16, /// File exists EXIST = 17, /// Cross-device link XDEV = 18, /// No such device NODEV = 19, /// Not a directory NOTDIR = 20, /// Is a directory ISDIR = 21, /// Invalid argument INVAL = 22, /// File table overflow NFILE = 23, /// Too many open files MFILE = 24, /// Not a typewriter NOTTY = 25, /// Text file busy TXTBSY = 26, /// File too large FBIG = 27, /// No space left on device NOSPC = 28, /// Illegal seek SPIPE = 29, /// Read-only file system ROFS = 30, /// Too many links MLINK = 31, /// Broken pipe PIPE = 32, /// Math argument out of domain of func DOM = 33, /// Math result not representable RANGE = 34, /// Resource deadlock would occur DEADLK = 35, /// File name too long NAMETOOLONG = 36, /// No record locks available NOLCK = 37, /// Function not implemented NOSYS = 38, /// Directory not empty NOTEMPTY = 39, /// Too many symbolic links encountered LOOP = 40, /// No message of desired type NOMSG = 42, /// Identifier removed IDRM = 43, /// Channel number out of range CHRNG = 44, /// Level 2 not synchronized L2NSYNC = 45, /// Level 3 halted L3HLT = 46, /// Level 3 reset L3RST = 47, /// Link number out of range LNRNG = 48, /// Protocol driver not attached UNATCH = 49, /// No CSI structure available NOCSI = 50, /// Level 2 halted L2HLT = 51, /// Invalid exchange BADE = 52, /// Invalid request descriptor BADR = 53, /// Exchange full XFULL = 54, /// No anode NOANO = 55, /// Invalid request code BADRQC = 56, /// Invalid slot BADSLT = 57, /// Bad font file format BFONT = 59, /// Device not a stream NOSTR = 60, /// No data available NODATA = 61, /// Timer expired TIME = 62, /// Out of streams resources NOSR = 63, /// Machine is not on the network NONET = 64, /// Package not installed NOPKG = 65, /// Object is remote REMOTE = 66, /// Link has been severed NOLINK = 67, /// Advertise error ADV = 68, /// Srmount error SRMNT = 69, /// Communication error on send COMM = 70, /// Protocol error PROTO = 71, /// Multihop attempted MULTIHOP = 72, /// RFS specific error DOTDOT = 73, /// Not a data message BADMSG = 74, /// Value too large for defined data type OVERFLOW = 75, /// Name not unique on network NOTUNIQ = 76, /// File descriptor in bad state BADFD = 77, /// Remote address changed REMCHG = 78, /// Can not access a needed shared library LIBACC = 79, /// Accessing a corrupted shared library LIBBAD = 80, /// .lib section in a.out corrupted LIBSCN = 81, /// Attempting to link in too many shared libraries LIBMAX = 82, /// Cannot exec a shared library directly LIBEXEC = 83, /// Illegal byte sequence ILSEQ = 84, /// Interrupted system call should be restarted RESTART = 85, /// Streams pipe error STRPIPE = 86, /// Too many users USERS = 87, /// Socket operation on non-socket NOTSOCK = 88, /// Destination address required DESTADDRREQ = 89, /// Message too long MSGSIZE = 90, /// Protocol wrong type for socket PROTOTYPE = 91, /// Protocol not available NOPROTOOPT = 92, /// Protocol not supported PROTONOSUPPORT = 93, /// Socket type not supported SOCKTNOSUPPORT = 94, /// Operation not supported on transport endpoint /// This code also means `NOTSUP`. OPNOTSUPP = 95, /// Protocol family not supported PFNOSUPPORT = 96, /// Address family not supported by protocol AFNOSUPPORT = 97, /// Address already in use ADDRINUSE = 98, /// Cannot assign requested address ADDRNOTAVAIL = 99, /// Network is down NETDOWN = 100, /// Network is unreachable NETUNREACH = 101, /// Network dropped connection because of reset NETRESET = 102, /// Software caused connection abort CONNABORTED = 103, /// Connection reset by peer CONNRESET = 104, /// No buffer space available NOBUFS = 105, /// Transport endpoint is already connected ISCONN = 106, /// Transport endpoint is not connected NOTCONN = 107, /// Cannot send after transport endpoint shutdown SHUTDOWN = 108, /// Too many references: cannot splice TOOMANYREFS = 109, /// Connection timed out TIMEDOUT = 110, /// Connection refused CONNREFUSED = 111, /// Host is down HOSTDOWN = 112, /// No route to host HOSTUNREACH = 113, /// Operation already in progress ALREADY = 114, /// Operation now in progress INPROGRESS = 115, /// Stale NFS file handle STALE = 116, /// Structure needs cleaning UCLEAN = 117, /// Not a XENIX named type file NOTNAM = 118, /// No XENIX semaphores available NAVAIL = 119, /// Is a named type file ISNAM = 120, /// Remote I/O error REMOTEIO = 121, /// Quota exceeded DQUOT = 122, /// No medium found NOMEDIUM = 123, /// Wrong medium type MEDIUMTYPE = 124, /// Operation canceled CANCELED = 125, /// Required key not available NOKEY = 126, /// Key has expired KEYEXPIRED = 127, /// Key has been revoked KEYREVOKED = 128, /// Key was rejected by service KEYREJECTED = 129, // for robust mutexes /// Owner died OWNERDEAD = 130, /// State not recoverable NOTRECOVERABLE = 131, /// Operation not possible due to RF-kill RFKILL = 132, /// Memory page has hardware error HWPOISON = 133, // nameserver query return codes /// DNS server returned answer with no data NSRNODATA = 160, /// DNS server claims query was misformatted NSRFORMERR = 161, /// DNS server returned general failure NSRSERVFAIL = 162, /// Domain name not found NSRNOTFOUND = 163, /// DNS server does not implement requested operation NSRNOTIMP = 164, /// DNS server refused query NSRREFUSED = 165, /// Misformatted DNS query NSRBADQUERY = 166, /// Misformatted domain name NSRBADNAME = 167, /// Unsupported address family NSRBADFAMILY = 168, /// Misformatted DNS reply NSRBADRESP = 169, /// Could not contact DNS servers NSRCONNREFUSED = 170, /// Timeout while contacting DNS servers NSRTIMEOUT = 171, /// End of file NSROF = 172, /// Error reading file NSRFILE = 173, /// Out of memory NSRNOMEM = 174, /// Application terminated lookup NSRDESTRUCTION = 175, /// Domain name is too long NSRQUERYDOMAINTOOLONG = 176, /// Domain name is too long NSRCNAMELOOP = 177, _, pub const init = errnoFromSyscall; }, }; pub const pid_t = i32; pub const fd_t = i32; pub const socket_t = i32; pub const uid_t = u32; pub const gid_t = u32; pub const clock_t = isize; pub const NAME_MAX = 255; pub const PATH_MAX = 4096; pub const IOV_MAX = 1024; /// Largest hardware address length /// e.g. a mac address is a type of hardware address pub const MAX_ADDR_LEN = 32; pub const STDIN_FILENO = 0; pub const STDOUT_FILENO = 1; pub const STDERR_FILENO = 2; pub const AT = struct { /// Special value used to indicate openat should use the current working directory pub const FDCWD = -100; /// Do not follow symbolic links pub const SYMLINK_NOFOLLOW = 0x100; /// Remove directory instead of unlinking file pub const REMOVEDIR = 0x200; /// Follow symbolic links. pub const SYMLINK_FOLLOW = 0x400; /// Suppress terminal automount traversal pub const NO_AUTOMOUNT = 0x800; /// Allow empty relative pathname pub const EMPTY_PATH = 0x1000; /// Type of synchronisation required from statx() pub const STATX_SYNC_TYPE = 0x6000; /// - Do whatever stat() does pub const STATX_SYNC_AS_STAT = 0x0000; /// - Force the attributes to be sync'd with the server pub const STATX_FORCE_SYNC = 0x2000; /// - Don't sync attributes with the server pub const STATX_DONT_SYNC = 0x4000; /// Apply to the entire subtree pub const RECURSIVE = 0x8000; pub const HANDLE_FID = REMOVEDIR; }; pub const FALLOC = struct { /// Default is extend size pub const FL_KEEP_SIZE = 0x01; /// De-allocates range pub const FL_PUNCH_HOLE = 0x02; /// Reserved codepoint pub const FL_NO_HIDE_STALE = 0x04; /// Removes a range of a file without leaving a hole in the file pub const FL_COLLAPSE_RANGE = 0x08; /// Converts a range of file to zeros preferably without issuing data IO pub const FL_ZERO_RANGE = 0x10; /// Inserts space within the file size without overwriting any existing data pub const FL_INSERT_RANGE = 0x20; /// Unshares shared blocks within the file size without overwriting any existing data pub const FL_UNSHARE_RANGE = 0x40; }; // Futex v1 API commands. See futex man page for each command's // interpretation of the futex arguments. pub const FUTEX_COMMAND = enum(u7) { WAIT = 0, WAKE = 1, FD = 2, REQUEUE = 3, CMP_REQUEUE = 4, WAKE_OP = 5, LOCK_PI = 6, UNLOCK_PI = 7, TRYLOCK_PI = 8, WAIT_BITSET = 9, WAKE_BITSET = 10, WAIT_REQUEUE_PI = 11, CMP_REQUEUE_PI = 12, }; /// Futex v1 API command and flags for the `futex_op` parameter pub const FUTEX_OP = packed struct(u32) { cmd: FUTEX_COMMAND, private: bool, realtime: bool = false, // realtime clock vs. monotonic clock _reserved: u23 = 0, }; /// Futex v1 FUTEX_WAKE_OP `val3` operation: pub const FUTEX_WAKE_OP = packed struct(u32) { cmd: FUTEX_WAKE_OP_CMD, /// From C API `FUTEX_OP_ARG_SHIFT`: Use (1 << oparg) as operand arg_shift: bool = false, cmp: FUTEX_WAKE_OP_CMP, oparg: u12, cmdarg: u12, }; /// Futex v1 cmd for FUTEX_WAKE_OP `val3` command. pub const FUTEX_WAKE_OP_CMD = enum(u3) { /// uaddr2 = oparg SET = 0, /// uaddr2 += oparg ADD = 1, /// uaddr2 |= oparg OR = 2, /// uaddr2 &= ~oparg ANDN = 3, /// uaddr2 ^= oparg XOR = 4, }; /// Futex v1 comparison op for FUTEX_WAKE_OP `val3` cmp pub const FUTEX_WAKE_OP_CMP = enum(u4) { EQ = 0, NE = 1, LT = 2, LE = 3, GT = 4, GE = 5, }; /// Max numbers of elements in a `futex2_waitone` array. pub const FUTEX2_WAITONE_MAX = 128; /// For futex v2 API, the size of the futex at the uaddr. v1 futex are /// always implicitly U32. As of kernel v6.14, only U32 is implemented /// for v2 futexes. pub const FUTEX2_SIZE = enum(u2) { U8 = 0, U16 = 1, U32 = 2, U64 = 3, }; /// As of kernel 6.14 there are no defined flags to futex2_waitv. pub const FUTEX2_FLAGS_WAITV = packed struct(u32) { _reserved: u32 = 0, }; /// As of kernel 6.14 there are no defined flags to futex2_requeue. pub const FUTEX2_FLAGS_REQUEUE = packed struct(u32) { _reserved: u32 = 0, }; /// Flags for futex v2 APIs (futex2_wait, futex2_wake, futex2_requeue, but /// not the futex2_waitv syscall, but also used in the futex2_waitone struct). pub const FUTEX2_FLAGS = packed struct(u32) { size: FUTEX2_SIZE, numa: bool = false, _reserved: u4 = 0, private: bool, _undefined: u24 = 0, }; pub const PROT = struct { /// page can not be accessed pub const NONE = 0x0; /// page can be read pub const READ = 0x1; /// page can be written pub const WRITE = 0x2; /// page can be executed pub const EXEC = 0x4; /// page may be used for atomic ops pub const SEM = switch (native_arch) { .mips, .mipsel, .mips64, .mips64el, .xtensa, .xtensaeb => 0x10, else => 0x8, }; /// mprotect flag: extend change to start of growsdown vma pub const GROWSDOWN = 0x01000000; /// mprotect flag: extend change to end of growsup vma pub const GROWSUP = 0x02000000; }; pub const FD_CLOEXEC = 1; pub const F_OK = 0; pub const X_OK = 1; pub const W_OK = 2; pub const R_OK = 4; pub const W = struct { pub const NOHANG = 1; pub const UNTRACED = 2; pub const STOPPED = 2; pub const EXITED = 4; pub const CONTINUED = 8; pub const NOWAIT = 0x1000000; pub fn EXITSTATUS(s: u32) u8 { return @as(u8, @intCast((s & 0xff00) >> 8)); } pub fn TERMSIG(s: u32) u32 { return s & 0x7f; } pub fn STOPSIG(s: u32) u32 { return EXITSTATUS(s); } pub fn IFEXITED(s: u32) bool { return TERMSIG(s) == 0; } pub fn IFSTOPPED(s: u32) bool { return @as(u16, @truncate(((s & 0xffff) *% 0x10001) >> 8)) > 0x7f00; } pub fn IFSIGNALED(s: u32) bool { return (s & 0xffff) -% 1 < 0xff; } }; // waitid id types pub const P = enum(c_uint) { ALL = 0, PID = 1, PGID = 2, PIDFD = 3, _, }; pub const SA = if (is_mips) struct { pub const NOCLDSTOP = 1; pub const NOCLDWAIT = 0x10000; pub const SIGINFO = 8; pub const RESTART = 0x10000000; pub const RESETHAND = 0x80000000; pub const ONSTACK = 0x08000000; pub const NODEFER = 0x40000000; } else if (is_sparc) struct { pub const NOCLDSTOP = 0x8; pub const NOCLDWAIT = 0x100; pub const SIGINFO = 0x200; pub const RESTART = 0x2; pub const RESETHAND = 0x4; pub const ONSTACK = 0x1; pub const NODEFER = 0x20; pub const RESTORER = 0x04000000; } else if (native_arch == .hexagon or is_loongarch or native_arch == .or1k or is_riscv) struct { pub const NOCLDSTOP = 1; pub const NOCLDWAIT = 2; pub const SIGINFO = 4; pub const RESTART = 0x10000000; pub const RESETHAND = 0x80000000; pub const ONSTACK = 0x08000000; pub const NODEFER = 0x40000000; } else struct { pub const NOCLDSTOP = 1; pub const NOCLDWAIT = 2; pub const SIGINFO = 4; pub const RESTART = 0x10000000; pub const RESETHAND = 0x80000000; pub const ONSTACK = 0x08000000; pub const NODEFER = 0x40000000; pub const RESTORER = 0x04000000; }; pub const SIG = if (is_mips) struct { pub const BLOCK = 1; pub const UNBLOCK = 2; pub const SETMASK = 3; // https://github.com/torvalds/linux/blob/ca91b9500108d4cf083a635c2e11c884d5dd20ea/arch/mips/include/uapi/asm/signal.h#L25 pub const HUP = 1; pub const INT = 2; pub const QUIT = 3; pub const ILL = 4; pub const TRAP = 5; pub const ABRT = 6; pub const IOT = ABRT; pub const EMT = 7; pub const FPE = 8; pub const KILL = 9; pub const BUS = 10; pub const SEGV = 11; pub const SYS = 12; pub const PIPE = 13; pub const ALRM = 14; pub const TERM = 15; pub const USR1 = 16; pub const USR2 = 17; pub const CHLD = 18; pub const PWR = 19; pub const WINCH = 20; pub const URG = 21; pub const IO = 22; pub const POLL = IO; pub const STOP = 23; pub const TSTP = 24; pub const CONT = 25; pub const TTIN = 26; pub const TTOU = 27; pub const VTALRM = 28; pub const PROF = 29; pub const XCPU = 30; pub const XFZ = 31; pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); } else if (is_sparc) struct { pub const BLOCK = 1; pub const UNBLOCK = 2; pub const SETMASK = 4; pub const HUP = 1; pub const INT = 2; pub const QUIT = 3; pub const ILL = 4; pub const TRAP = 5; pub const ABRT = 6; pub const EMT = 7; pub const FPE = 8; pub const KILL = 9; pub const BUS = 10; pub const SEGV = 11; pub const SYS = 12; pub const PIPE = 13; pub const ALRM = 14; pub const TERM = 15; pub const URG = 16; pub const STOP = 17; pub const TSTP = 18; pub const CONT = 19; pub const CHLD = 20; pub const TTIN = 21; pub const TTOU = 22; pub const POLL = 23; pub const XCPU = 24; pub const XFSZ = 25; pub const VTALRM = 26; pub const PROF = 27; pub const WINCH = 28; pub const LOST = 29; pub const USR1 = 30; pub const USR2 = 31; pub const IOT = ABRT; pub const CLD = CHLD; pub const PWR = LOST; pub const IO = SIG.POLL; pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); } else struct { pub const BLOCK = 0; pub const UNBLOCK = 1; pub const SETMASK = 2; pub const HUP = 1; pub const INT = 2; pub const QUIT = 3; pub const ILL = 4; pub const TRAP = 5; pub const ABRT = 6; pub const IOT = ABRT; pub const BUS = 7; pub const FPE = 8; pub const KILL = 9; pub const USR1 = 10; pub const SEGV = 11; pub const USR2 = 12; pub const PIPE = 13; pub const ALRM = 14; pub const TERM = 15; pub const STKFLT = 16; pub const CHLD = 17; pub const CONT = 18; pub const STOP = 19; pub const TSTP = 20; pub const TTIN = 21; pub const TTOU = 22; pub const URG = 23; pub const XCPU = 24; pub const XFSZ = 25; pub const VTALRM = 26; pub const PROF = 27; pub const WINCH = 28; pub const IO = 29; pub const POLL = 29; pub const PWR = 30; pub const SYS = 31; pub const UNUSED = SIG.SYS; pub const ERR: ?Sigaction.handler_fn = @ptrFromInt(maxInt(usize)); pub const DFL: ?Sigaction.handler_fn = @ptrFromInt(0); pub const IGN: ?Sigaction.handler_fn = @ptrFromInt(1); }; pub const kernel_rwf = u32; pub const RWF = struct { pub const HIPRI: kernel_rwf = 0x00000001; pub const DSYNC: kernel_rwf = 0x00000002; pub const SYNC: kernel_rwf = 0x00000004; pub const NOWAIT: kernel_rwf = 0x00000008; pub const APPEND: kernel_rwf = 0x00000010; }; pub const SEEK = struct { pub const SET = 0; pub const CUR = 1; pub const END = 2; }; pub const SHUT = struct { pub const RD = 0; pub const WR = 1; pub const RDWR = 2; }; pub const SOCK = struct { pub const STREAM = if (is_mips) 2 else 1; pub const DGRAM = if (is_mips) 1 else 2; pub const RAW = 3; pub const RDM = 4; pub const SEQPACKET = 5; pub const DCCP = 6; pub const PACKET = 10; pub const CLOEXEC = if (is_sparc) 0o20000000 else 0o2000000; pub const NONBLOCK = if (is_mips) 0o200 else if (is_sparc) 0o40000 else 0o4000; }; pub const TCP = struct { /// Turn off Nagle's algorithm pub const NODELAY = 1; /// Limit MSS pub const MAXSEG = 2; /// Never send partially complete segments. pub const CORK = 3; /// Start keeplives after this period, in seconds pub const KEEPIDLE = 4; /// Interval between keepalives pub const KEEPINTVL = 5; /// Number of keepalives before death pub const KEEPCNT = 6; /// Number of SYN retransmits pub const SYNCNT = 7; /// Life time of orphaned FIN-WAIT-2 state pub const LINGER2 = 8; /// Wake up listener only when data arrive pub const DEFER_ACCEPT = 9; /// Bound advertised window pub const WINDOW_CLAMP = 10; /// Information about this connection. pub const INFO = 11; /// Block/reenable quick acks pub const QUICKACK = 12; /// Congestion control algorithm pub const CONGESTION = 13; /// TCP MD5 Signature (RFC2385) pub const MD5SIG = 14; /// Use linear timeouts for thin streams pub const THIN_LINEAR_TIMEOUTS = 16; /// Fast retrans. after 1 dupack pub const THIN_DUPACK = 17; /// How long for loss retry before timeout pub const USER_TIMEOUT = 18; /// TCP sock is under repair right now pub const REPAIR = 19; pub const REPAIR_QUEUE = 20; pub const QUEUE_SEQ = 21; pub const REPAIR_OPTIONS = 22; /// Enable FastOpen on listeners pub const FASTOPEN = 23; pub const TIMESTAMP = 24; /// limit number of unsent bytes in write queue pub const NOTSENT_LOWAT = 25; /// Get Congestion Control (optional) info pub const CC_INFO = 26; /// Record SYN headers for new connections pub const SAVE_SYN = 27; /// Get SYN headers recorded for connection pub const SAVED_SYN = 28; /// Get/set window parameters pub const REPAIR_WINDOW = 29; /// Attempt FastOpen with connect pub const FASTOPEN_CONNECT = 30; /// Attach a ULP to a TCP connection pub const ULP = 31; /// TCP MD5 Signature with extensions pub const MD5SIG_EXT = 32; /// Set the key for Fast Open (cookie) pub const FASTOPEN_KEY = 33; /// Enable TFO without a TFO cookie pub const FASTOPEN_NO_COOKIE = 34; pub const ZEROCOPY_RECEIVE = 35; /// Notify bytes available to read as a cmsg on read pub const INQ = 36; pub const CM_INQ = INQ; /// delay outgoing packets by XX usec pub const TX_DELAY = 37; pub const REPAIR_ON = 1; pub const REPAIR_OFF = 0; /// Turn off without window probes pub const REPAIR_OFF_NO_WP = -1; }; pub const UDP = struct { /// Never send partially complete segments pub const CORK = 1; /// Set the socket to accept encapsulated packets pub const ENCAP = 100; /// Disable sending checksum for UDP6X pub const NO_CHECK6_TX = 101; /// Disable accepting checksum for UDP6 pub const NO_CHECK6_RX = 102; /// Set GSO segmentation size pub const SEGMENT = 103; /// This socket can receive UDP GRO packets pub const GRO = 104; }; pub const UDP_ENCAP = struct { pub const ESPINUDP_NON_IKE = 1; pub const ESPINUDP = 2; pub const L2TPINUDP = 3; pub const GTP0 = 4; pub const GTP1U = 5; pub const RXRPC = 6; }; pub const PF = struct { pub const UNSPEC = 0; pub const LOCAL = 1; pub const UNIX = LOCAL; pub const FILE = LOCAL; pub const INET = 2; pub const AX25 = 3; pub const IPX = 4; pub const APPLETALK = 5; pub const NETROM = 6; pub const BRIDGE = 7; pub const ATMPVC = 8; pub const X25 = 9; pub const INET6 = 10; pub const ROSE = 11; pub const DECnet = 12; pub const NETBEUI = 13; pub const SECURITY = 14; pub const KEY = 15; pub const NETLINK = 16; pub const ROUTE = PF.NETLINK; pub const PACKET = 17; pub const ASH = 18; pub const ECONET = 19; pub const ATMSVC = 20; pub const RDS = 21; pub const SNA = 22; pub const IRDA = 23; pub const PPPOX = 24; pub const WANPIPE = 25; pub const LLC = 26; pub const IB = 27; pub const MPLS = 28; pub const CAN = 29; pub const TIPC = 30; pub const BLUETOOTH = 31; pub const IUCV = 32; pub const RXRPC = 33; pub const ISDN = 34; pub const PHONET = 35; pub const IEEE802154 = 36; pub const CAIF = 37; pub const ALG = 38; pub const NFC = 39; pub const VSOCK = 40; pub const KCM = 41; pub const QIPCRTR = 42; pub const SMC = 43; pub const XDP = 44; pub const MAX = 45; }; pub const AF = struct { pub const UNSPEC = PF.UNSPEC; pub const LOCAL = PF.LOCAL; pub const UNIX = AF.LOCAL; pub const FILE = AF.LOCAL; pub const INET = PF.INET; pub const AX25 = PF.AX25; pub const IPX = PF.IPX; pub const APPLETALK = PF.APPLETALK; pub const NETROM = PF.NETROM; pub const BRIDGE = PF.BRIDGE; pub const ATMPVC = PF.ATMPVC; pub const X25 = PF.X25; pub const INET6 = PF.INET6; pub const ROSE = PF.ROSE; pub const DECnet = PF.DECnet; pub const NETBEUI = PF.NETBEUI; pub const SECURITY = PF.SECURITY; pub const KEY = PF.KEY; pub const NETLINK = PF.NETLINK; pub const ROUTE = PF.ROUTE; pub const PACKET = PF.PACKET; pub const ASH = PF.ASH; pub const ECONET = PF.ECONET; pub const ATMSVC = PF.ATMSVC; pub const RDS = PF.RDS; pub const SNA = PF.SNA; pub const IRDA = PF.IRDA; pub const PPPOX = PF.PPPOX; pub const WANPIPE = PF.WANPIPE; pub const LLC = PF.LLC; pub const IB = PF.IB; pub const MPLS = PF.MPLS; pub const CAN = PF.CAN; pub const TIPC = PF.TIPC; pub const BLUETOOTH = PF.BLUETOOTH; pub const IUCV = PF.IUCV; pub const RXRPC = PF.RXRPC; pub const ISDN = PF.ISDN; pub const PHONET = PF.PHONET; pub const IEEE802154 = PF.IEEE802154; pub const CAIF = PF.CAIF; pub const ALG = PF.ALG; pub const NFC = PF.NFC; pub const VSOCK = PF.VSOCK; pub const KCM = PF.KCM; pub const QIPCRTR = PF.QIPCRTR; pub const SMC = PF.SMC; pub const XDP = PF.XDP; pub const MAX = PF.MAX; }; pub const SO = if (is_mips) struct { pub const DEBUG = 1; pub const REUSEADDR = 0x0004; pub const KEEPALIVE = 0x0008; pub const DONTROUTE = 0x0010; pub const BROADCAST = 0x0020; pub const LINGER = 0x0080; pub const OOBINLINE = 0x0100; pub const REUSEPORT = 0x0200; pub const SNDBUF = 0x1001; pub const RCVBUF = 0x1002; pub const SNDLOWAT = 0x1003; pub const RCVLOWAT = 0x1004; pub const RCVTIMEO = 0x1006; pub const SNDTIMEO = 0x1005; pub const ERROR = 0x1007; pub const TYPE = 0x1008; pub const ACCEPTCONN = 0x1009; pub const PROTOCOL = 0x1028; pub const DOMAIN = 0x1029; pub const NO_CHECK = 11; pub const PRIORITY = 12; pub const BSDCOMPAT = 14; pub const PASSCRED = 17; pub const PEERCRED = 18; pub const PEERSEC = 30; pub const SNDBUFFORCE = 31; pub const RCVBUFFORCE = 33; pub const SECURITY_AUTHENTICATION = 22; pub const SECURITY_ENCRYPTION_TRANSPORT = 23; pub const SECURITY_ENCRYPTION_NETWORK = 24; pub const BINDTODEVICE = 25; pub const ATTACH_FILTER = 26; pub const DETACH_FILTER = 27; pub const GET_FILTER = ATTACH_FILTER; pub const PEERNAME = 28; pub const TIMESTAMP_OLD = 29; pub const PASSSEC = 34; pub const TIMESTAMPNS_OLD = 35; pub const MARK = 36; pub const TIMESTAMPING_OLD = 37; pub const RXQ_OVFL = 40; pub const WIFI_STATUS = 41; pub const PEEK_OFF = 42; pub const NOFCS = 43; pub const LOCK_FILTER = 44; pub const SELECT_ERR_QUEUE = 45; pub const BUSY_POLL = 46; pub const MAX_PACING_RATE = 47; pub const BPF_EXTENSIONS = 48; pub const INCOMING_CPU = 49; pub const ATTACH_BPF = 50; pub const DETACH_BPF = DETACH_FILTER; pub const ATTACH_REUSEPORT_CBPF = 51; pub const ATTACH_REUSEPORT_EBPF = 52; pub const CNX_ADVICE = 53; pub const MEMINFO = 55; pub const INCOMING_NAPI_ID = 56; pub const COOKIE = 57; pub const PEERGROUPS = 59; pub const ZEROCOPY = 60; pub const TXTIME = 61; pub const BINDTOIFINDEX = 62; pub const TIMESTAMP_NEW = 63; pub const TIMESTAMPNS_NEW = 64; pub const TIMESTAMPING_NEW = 65; pub const RCVTIMEO_NEW = 66; pub const SNDTIMEO_NEW = 67; pub const DETACH_REUSEPORT_BPF = 68; } else if (is_ppc) struct { pub const DEBUG = 1; pub const REUSEADDR = 2; pub const TYPE = 3; pub const ERROR = 4; pub const DONTROUTE = 5; pub const BROADCAST = 6; pub const SNDBUF = 7; pub const RCVBUF = 8; pub const KEEPALIVE = 9; pub const OOBINLINE = 10; pub const NO_CHECK = 11; pub const PRIORITY = 12; pub const LINGER = 13; pub const BSDCOMPAT = 14; pub const REUSEPORT = 15; pub const RCVLOWAT = 16; pub const SNDLOWAT = 17; pub const RCVTIMEO = 18; pub const SNDTIMEO = 19; pub const PASSCRED = 20; pub const PEERCRED = 21; pub const ACCEPTCONN = 30; pub const PEERSEC = 31; pub const SNDBUFFORCE = 32; pub const RCVBUFFORCE = 33; pub const PROTOCOL = 38; pub const DOMAIN = 39; pub const SECURITY_AUTHENTICATION = 22; pub const SECURITY_ENCRYPTION_TRANSPORT = 23; pub const SECURITY_ENCRYPTION_NETWORK = 24; pub const BINDTODEVICE = 25; pub const ATTACH_FILTER = 26; pub const DETACH_FILTER = 27; pub const GET_FILTER = ATTACH_FILTER; pub const PEERNAME = 28; pub const TIMESTAMP_OLD = 29; pub const PASSSEC = 34; pub const TIMESTAMPNS_OLD = 35; pub const MARK = 36; pub const TIMESTAMPING_OLD = 37; pub const RXQ_OVFL = 40; pub const WIFI_STATUS = 41; pub const PEEK_OFF = 42; pub const NOFCS = 43; pub const LOCK_FILTER = 44; pub const SELECT_ERR_QUEUE = 45; pub const BUSY_POLL = 46; pub const MAX_PACING_RATE = 47; pub const BPF_EXTENSIONS = 48; pub const INCOMING_CPU = 49; pub const ATTACH_BPF = 50; pub const DETACH_BPF = DETACH_FILTER; pub const ATTACH_REUSEPORT_CBPF = 51; pub const ATTACH_REUSEPORT_EBPF = 52; pub const CNX_ADVICE = 53; pub const MEMINFO = 55; pub const INCOMING_NAPI_ID = 56; pub const COOKIE = 57; pub const PEERGROUPS = 59; pub const ZEROCOPY = 60; pub const TXTIME = 61; pub const BINDTOIFINDEX = 62; pub const TIMESTAMP_NEW = 63; pub const TIMESTAMPNS_NEW = 64; pub const TIMESTAMPING_NEW = 65; pub const RCVTIMEO_NEW = 66; pub const SNDTIMEO_NEW = 67; pub const DETACH_REUSEPORT_BPF = 68; } else if (is_sparc) struct { pub const DEBUG = 1; pub const REUSEADDR = 4; pub const TYPE = 4104; pub const ERROR = 4103; pub const DONTROUTE = 16; pub const BROADCAST = 32; pub const SNDBUF = 4097; pub const RCVBUF = 4098; pub const KEEPALIVE = 8; pub const OOBINLINE = 256; pub const NO_CHECK = 11; pub const PRIORITY = 12; pub const LINGER = 128; pub const BSDCOMPAT = 1024; pub const REUSEPORT = 512; pub const PASSCRED = 2; pub const PEERCRED = 64; pub const RCVLOWAT = 2048; pub const SNDLOWAT = 4096; pub const RCVTIMEO = 8192; pub const SNDTIMEO = 16384; pub const ACCEPTCONN = 32768; pub const PEERSEC = 30; pub const SNDBUFFORCE = 4106; pub const RCVBUFFORCE = 4107; pub const PROTOCOL = 4136; pub const DOMAIN = 4137; pub const SECURITY_AUTHENTICATION = 20481; pub const SECURITY_ENCRYPTION_TRANSPORT = 20482; pub const SECURITY_ENCRYPTION_NETWORK = 20484; pub const BINDTODEVICE = 13; pub const ATTACH_FILTER = 26; pub const DETACH_FILTER = 27; pub const GET_FILTER = 26; pub const PEERNAME = 28; pub const TIMESTAMP_OLD = 29; pub const PASSSEC = 31; pub const TIMESTAMPNS_OLD = 33; pub const MARK = 34; pub const TIMESTAMPING_OLD = 35; pub const RXQ_OVFL = 36; pub const WIFI_STATUS = 37; pub const PEEK_OFF = 38; pub const NOFCS = 39; pub const LOCK_FILTER = 40; pub const SELECT_ERR_QUEUE = 41; pub const BUSY_POLL = 48; pub const MAX_PACING_RATE = 49; pub const BPF_EXTENSIONS = 50; pub const INCOMING_CPU = 51; pub const ATTACH_BPF = 52; pub const DETACH_BPF = 27; pub const ATTACH_REUSEPORT_CBPF = 53; pub const ATTACH_REUSEPORT_EBPF = 54; pub const CNX_ADVICE = 55; pub const MEMINFO = 57; pub const INCOMING_NAPI_ID = 58; pub const COOKIE = 59; pub const PEERGROUPS = 61; pub const ZEROCOPY = 62; pub const TXTIME = 63; pub const BINDTOIFINDEX = 65; pub const TIMESTAMP_NEW = 70; pub const TIMESTAMPNS_NEW = 66; pub const TIMESTAMPING_NEW = 67; pub const RCVTIMEO_NEW = 68; pub const SNDTIMEO_NEW = 69; pub const DETACH_REUSEPORT_BPF = 71; } else struct { pub const DEBUG = 1; pub const REUSEADDR = 2; pub const TYPE = 3; pub const ERROR = 4; pub const DONTROUTE = 5; pub const BROADCAST = 6; pub const SNDBUF = 7; pub const RCVBUF = 8; pub const KEEPALIVE = 9; pub const OOBINLINE = 10; pub const NO_CHECK = 11; pub const PRIORITY = 12; pub const LINGER = 13; pub const BSDCOMPAT = 14; pub const REUSEPORT = 15; pub const PASSCRED = 16; pub const PEERCRED = 17; pub const RCVLOWAT = 18; pub const SNDLOWAT = 19; pub const RCVTIMEO = 20; pub const SNDTIMEO = 21; pub const ACCEPTCONN = 30; pub const PEERSEC = 31; pub const SNDBUFFORCE = 32; pub const RCVBUFFORCE = 33; pub const PROTOCOL = 38; pub const DOMAIN = 39; pub const SECURITY_AUTHENTICATION = 22; pub const SECURITY_ENCRYPTION_TRANSPORT = 23; pub const SECURITY_ENCRYPTION_NETWORK = 24; pub const BINDTODEVICE = 25; pub const ATTACH_FILTER = 26; pub const DETACH_FILTER = 27; pub const GET_FILTER = ATTACH_FILTER; pub const PEERNAME = 28; pub const TIMESTAMP_OLD = 29; pub const PASSSEC = 34; pub const TIMESTAMPNS_OLD = 35; pub const MARK = 36; pub const TIMESTAMPING_OLD = 37; pub const RXQ_OVFL = 40; pub const WIFI_STATUS = 41; pub const PEEK_OFF = 42; pub const NOFCS = 43; pub const LOCK_FILTER = 44; pub const SELECT_ERR_QUEUE = 45; pub const BUSY_POLL = 46; pub const MAX_PACING_RATE = 47; pub const BPF_EXTENSIONS = 48; pub const INCOMING_CPU = 49; pub const ATTACH_BPF = 50; pub const DETACH_BPF = DETACH_FILTER; pub const ATTACH_REUSEPORT_CBPF = 51; pub const ATTACH_REUSEPORT_EBPF = 52; pub const CNX_ADVICE = 53; pub const MEMINFO = 55; pub const INCOMING_NAPI_ID = 56; pub const COOKIE = 57; pub const PEERGROUPS = 59; pub const ZEROCOPY = 60; pub const TXTIME = 61; pub const BINDTOIFINDEX = 62; pub const TIMESTAMP_NEW = 63; pub const TIMESTAMPNS_NEW = 64; pub const TIMESTAMPING_NEW = 65; pub const RCVTIMEO_NEW = 66; pub const SNDTIMEO_NEW = 67; pub const DETACH_REUSEPORT_BPF = 68; }; pub const SCM = struct { // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/socket.h?id=f777d1112ee597d7f7dd3ca232220873a34ad0c8#n178 pub const RIGHTS = 1; pub const CREDENTIALS = 2; pub const SECURITY = 3; pub const PIDFD = 4; pub const WIFI_STATUS = SO.WIFI_STATUS; pub const TIMESTAMPING_OPT_STATS = 54; pub const TIMESTAMPING_PKTINFO = 58; pub const TXTIME = SO.TXTIME; }; pub const SOL = struct { pub const SOCKET = if (is_mips or is_sparc) 65535 else 1; pub const IP = 0; pub const IPV6 = 41; pub const ICMPV6 = 58; pub const RAW = 255; pub const DECNET = 261; pub const X25 = 262; pub const PACKET = 263; pub const ATM = 264; pub const AAL = 265; pub const IRDA = 266; pub const NETBEUI = 267; pub const LLC = 268; pub const DCCP = 269; pub const NETLINK = 270; pub const TIPC = 271; pub const RXRPC = 272; pub const PPPOL2TP = 273; pub const BLUETOOTH = 274; pub const PNPIPE = 275; pub const RDS = 276; pub const IUCV = 277; pub const CAIF = 278; pub const ALG = 279; pub const NFC = 280; pub const KCM = 281; pub const TLS = 282; pub const XDP = 283; }; pub const SOMAXCONN = 128; pub const IP = struct { pub const TOS = 1; pub const TTL = 2; pub const HDRINCL = 3; pub const OPTIONS = 4; pub const ROUTER_ALERT = 5; pub const RECVOPTS = 6; pub const RETOPTS = 7; pub const PKTINFO = 8; pub const PKTOPTIONS = 9; pub const PMTUDISC = 10; pub const MTU_DISCOVER = 10; pub const RECVERR = 11; pub const RECVTTL = 12; pub const RECVTOS = 13; pub const MTU = 14; pub const FREEBIND = 15; pub const IPSEC_POLICY = 16; pub const XFRM_POLICY = 17; pub const PASSSEC = 18; pub const TRANSPARENT = 19; pub const ORIGDSTADDR = 20; pub const RECVORIGDSTADDR = IP.ORIGDSTADDR; pub const MINTTL = 21; pub const NODEFRAG = 22; pub const CHECKSUM = 23; pub const BIND_ADDRESS_NO_PORT = 24; pub const RECVFRAGSIZE = 25; pub const MULTICAST_IF = 32; pub const MULTICAST_TTL = 33; pub const MULTICAST_LOOP = 34; pub const ADD_MEMBERSHIP = 35; pub const DROP_MEMBERSHIP = 36; pub const UNBLOCK_SOURCE = 37; pub const BLOCK_SOURCE = 38; pub const ADD_SOURCE_MEMBERSHIP = 39; pub const DROP_SOURCE_MEMBERSHIP = 40; pub const MSFILTER = 41; pub const MULTICAST_ALL = 49; pub const UNICAST_IF = 50; pub const RECVRETOPTS = IP.RETOPTS; pub const PMTUDISC_DONT = 0; pub const PMTUDISC_WANT = 1; pub const PMTUDISC_DO = 2; pub const PMTUDISC_PROBE = 3; pub const PMTUDISC_INTERFACE = 4; pub const PMTUDISC_OMIT = 5; pub const DEFAULT_MULTICAST_TTL = 1; pub const DEFAULT_MULTICAST_LOOP = 1; pub const MAX_MEMBERSHIPS = 20; }; /// IPv6 socket options pub const IPV6 = struct { pub const ADDRFORM = 1; pub const @"2292PKTINFO" = 2; pub const @"2292HOPOPTS" = 3; pub const @"2292DSTOPTS" = 4; pub const @"2292RTHDR" = 5; pub const @"2292PKTOPTIONS" = 6; pub const CHECKSUM = 7; pub const @"2292HOPLIMIT" = 8; pub const NEXTHOP = 9; pub const AUTHHDR = 10; pub const FLOWINFO = 11; pub const UNICAST_HOPS = 16; pub const MULTICAST_IF = 17; pub const MULTICAST_HOPS = 18; pub const MULTICAST_LOOP = 19; pub const ADD_MEMBERSHIP = 20; pub const DROP_MEMBERSHIP = 21; pub const ROUTER_ALERT = 22; pub const MTU_DISCOVER = 23; pub const MTU = 24; pub const RECVERR = 25; pub const V6ONLY = 26; pub const JOIN_ANYCAST = 27; pub const LEAVE_ANYCAST = 28; // IPV6.MTU_DISCOVER values pub const PMTUDISC_DONT = 0; pub const PMTUDISC_WANT = 1; pub const PMTUDISC_DO = 2; pub const PMTUDISC_PROBE = 3; pub const PMTUDISC_INTERFACE = 4; pub const PMTUDISC_OMIT = 5; // Flowlabel pub const FLOWLABEL_MGR = 32; pub const FLOWINFO_SEND = 33; pub const IPSEC_POLICY = 34; pub const XFRM_POLICY = 35; pub const HDRINCL = 36; // Advanced API (RFC3542) (1) pub const RECVPKTINFO = 49; pub const PKTINFO = 50; pub const RECVHOPLIMIT = 51; pub const HOPLIMIT = 52; pub const RECVHOPOPTS = 53; pub const HOPOPTS = 54; pub const RTHDRDSTOPTS = 55; pub const RECVRTHDR = 56; pub const RTHDR = 57; pub const RECVDSTOPTS = 58; pub const DSTOPTS = 59; pub const RECVPATHMTU = 60; pub const PATHMTU = 61; pub const DONTFRAG = 62; // Advanced API (RFC3542) (2) pub const RECVTCLASS = 66; pub const TCLASS = 67; pub const AUTOFLOWLABEL = 70; // RFC5014: Source address selection pub const ADDR_PREFERENCES = 72; pub const PREFER_SRC_TMP = 0x0001; pub const PREFER_SRC_PUBLIC = 0x0002; pub const PREFER_SRC_PUBTMP_DEFAULT = 0x0100; pub const PREFER_SRC_COA = 0x0004; pub const PREFER_SRC_HOME = 0x0400; pub const PREFER_SRC_CGA = 0x0008; pub const PREFER_SRC_NONCGA = 0x0800; // RFC5082: Generalized Ttl Security Mechanism pub const MINHOPCOUNT = 73; pub const ORIGDSTADDR = 74; pub const RECVORIGDSTADDR = IPV6.ORIGDSTADDR; pub const TRANSPARENT = 75; pub const UNICAST_IF = 76; pub const RECVFRAGSIZE = 77; pub const FREEBIND = 78; }; // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/ip.h?id=64e844505bc08cde3f346f193cbbbab0096fef54#n24 pub const IPTOS = struct { pub const TOS_MASK = 0x1e; pub fn TOS(t: anytype) @TypeOf(t) { return t & TOS_MASK; } pub const MINCOST = 0x02; pub const RELIABILITY = 0x04; pub const THROUGHPUT = 0x08; pub const LOWDELAY = 0x10; pub const PREC_MASK = 0xe0; pub fn PREC(t: anytype) @TypeOf(t) { return t & PREC_MASK; } pub const PREC_ROUTINE = 0x00; pub const PREC_PRIORITY = 0x20; pub const PREC_IMMEDIATE = 0x40; pub const PREC_FLASH = 0x60; pub const PREC_FLASHOVERRIDE = 0x80; pub const PREC_CRITIC_ECP = 0xa0; pub const PREC_INTERNETCONTROL = 0xc0; pub const PREC_NETCONTROL = 0xe0; }; // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/socket.h?id=b1e904999542ad6764eafa54545f1c55776006d1#n43 pub const linger = extern struct { onoff: i32, // non-zero to linger on close linger: i32, // time to linger in seconds }; // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/in.h?id=64e844505bc08cde3f346f193cbbbab0096fef54#n250 pub const in_pktinfo = extern struct { ifindex: i32, spec_dst: u32, addr: u32, }; // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/ipv6.h?id=f24987ef6959a7efaf79bffd265522c3df18d431#n22 pub const in6_pktinfo = extern struct { addr: [16]u8, ifindex: i32, }; /// IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble /// and FCS/CRC (frame check sequence). pub const ETH = struct { /// Octets in one ethernet addr pub const ALEN = 6; /// Octets in ethernet type field pub const TLEN = 2; /// Total octets in header pub const HLEN = 14; /// Min. octets in frame sans FC pub const ZLEN = 60; /// Max. octets in payload pub const DATA_LEN = 1500; /// Max. octets in frame sans FCS pub const FRAME_LEN = 1514; /// Octets in the FCS pub const FCS_LEN = 4; /// Min IPv4 MTU per RFC791 pub const MIN_MTU = 68; /// 65535, same as IP_MAX_MTU pub const MAX_MTU = 0xFFFF; /// These are the defined Ethernet Protocol ID's. pub const P = struct { /// Ethernet Loopback packet pub const LOOP = 0x0060; /// Xerox PUP packet pub const PUP = 0x0200; /// Xerox PUP Addr Trans packet pub const PUPAT = 0x0201; /// TSN (IEEE 1722) packet pub const TSN = 0x22F0; /// ERSPAN version 2 (type III) pub const ERSPAN2 = 0x22EB; /// Internet Protocol packet pub const IP = 0x0800; /// CCITT X.25 pub const X25 = 0x0805; /// Address Resolution packet pub const ARP = 0x0806; /// G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] pub const BPQ = 0x08FF; /// Xerox IEEE802.3 PUP packet pub const IEEEPUP = 0x0a00; /// Xerox IEEE802.3 PUP Addr Trans packet pub const IEEEPUPAT = 0x0a01; /// B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] pub const BATMAN = 0x4305; /// DEC Assigned proto pub const DEC = 0x6000; /// DEC DNA Dump/Load pub const DNA_DL = 0x6001; /// DEC DNA Remote Console pub const DNA_RC = 0x6002; /// DEC DNA Routing pub const DNA_RT = 0x6003; /// DEC LAT pub const LAT = 0x6004; /// DEC Diagnostics pub const DIAG = 0x6005; /// DEC Customer use pub const CUST = 0x6006; /// DEC Systems Comms Arch pub const SCA = 0x6007; /// Trans Ether Bridging pub const TEB = 0x6558; /// Reverse Addr Res packet pub const RARP = 0x8035; /// Appletalk DDP pub const ATALK = 0x809B; /// Appletalk AARP pub const AARP = 0x80F3; /// 802.1Q VLAN Extended Header pub const P_8021Q = 0x8100; /// ERSPAN type II pub const ERSPAN = 0x88BE; /// IPX over DIX pub const IPX = 0x8137; /// IPv6 over bluebook pub const IPV6 = 0x86DD; /// IEEE Pause frames. See 802.3 31B pub const PAUSE = 0x8808; /// Slow Protocol. See 802.3ad 43B pub const SLOW = 0x8809; /// Web-cache coordination protocol defined in draft-wilson-wrec-wccp-v2-00.txt pub const WCCP = 0x883E; /// MPLS Unicast traffic pub const MPLS_UC = 0x8847; /// MPLS Multicast traffic pub const MPLS_MC = 0x8848; /// MultiProtocol Over ATM pub const ATMMPOA = 0x884c; /// PPPoE discovery messages pub const PPP_DISC = 0x8863; /// PPPoE session messages pub const PPP_SES = 0x8864; /// HPNA, wlan link local tunnel pub const LINK_CTL = 0x886c; /// Frame-based ATM Transport over Ethernet pub const ATMFATE = 0x8884; /// Port Access Entity (IEEE 802.1X) pub const PAE = 0x888E; /// PROFINET pub const PROFINET = 0x8892; /// Multiple proprietary protocols pub const REALTEK = 0x8899; /// ATA over Ethernet pub const AOE = 0x88A2; /// EtherCAT pub const ETHERCAT = 0x88A4; /// 802.1ad Service VLAN pub const @"8021AD" = 0x88A8; /// 802.1 Local Experimental 1. pub const @"802_EX1" = 0x88B5; /// 802.11 Preauthentication pub const PREAUTH = 0x88C7; /// TIPC pub const TIPC = 0x88CA; /// Link Layer Discovery Protocol pub const LLDP = 0x88CC; /// Media Redundancy Protocol pub const MRP = 0x88E3; /// 802.1ae MACsec pub const MACSEC = 0x88E5; /// 802.1ah Backbone Service Tag pub const @"8021AH" = 0x88E7; /// 802.1Q MVRP pub const MVRP = 0x88F5; /// IEEE 1588 Timesync pub const @"1588" = 0x88F7; /// NCSI protocol pub const NCSI = 0x88F8; /// IEC 62439-3 PRP/HSRv0 pub const PRP = 0x88FB; /// Connectivity Fault Management pub const CFM = 0x8902; /// Fibre Channel over Ethernet pub const FCOE = 0x8906; /// Infiniband over Ethernet pub const IBOE = 0x8915; /// TDLS pub const TDLS = 0x890D; /// FCoE Initialization Protocol pub const FIP = 0x8914; /// IEEE 802.21 Media Independent Handover Protocol pub const @"80221" = 0x8917; /// IEC 62439-3 HSRv1 pub const HSR = 0x892F; /// Network Service Header pub const NSH = 0x894F; /// Ethernet loopback packet, per IEEE 802.3 pub const LOOPBACK = 0x9000; /// deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] pub const QINQ1 = 0x9100; /// deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] pub const QINQ2 = 0x9200; /// deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] pub const QINQ3 = 0x9300; /// Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] pub const EDSA = 0xDADA; /// Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] pub const DSA_8021Q = 0xDADB; /// A5PSW Tag Value [ NOT AN OFFICIALLY REGISTERED ID ] pub const DSA_A5PSW = 0xE001; /// ForCES inter-FE LFB type pub const IFE = 0xED3E; /// IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] pub const AF_IUCV = 0xFBFB; /// If the value in the ethernet type is more than this value then the frame is Ethernet II. Else it is 802.3 pub const @"802_3_MIN" = 0x0600; // Non DIX types. Won't clash for 1500 types. /// Dummy type for 802.3 frames pub const @"802_3" = 0x0001; /// Dummy protocol id for AX.25 pub const AX25 = 0x0002; /// Every packet (be careful!!!) pub const ALL = 0x0003; /// 802.2 frames pub const @"802_2" = 0x0004; /// Internal only pub const SNAP = 0x0005; /// DEC DDCMP: Internal only pub const DDCMP = 0x0006; /// Dummy type for WAN PPP frames pub const WAN_PPP = 0x0007; /// Dummy type for PPP MP frames pub const PPP_MP = 0x0008; /// Localtalk pseudo type pub const LOCALTALK = 0x0009; /// CAN: Controller Area Network pub const CAN = 0x000C; /// CANFD: CAN flexible data rate pub const CANFD = 0x000D; /// CANXL: eXtended frame Length pub const CANXL = 0x000E; /// Dummy type for Atalk over PPP pub const PPPTALK = 0x0010; /// 802.2 frames pub const TR_802_2 = 0x0011; /// Mobitex (kaz@cafe.net) pub const MOBITEX = 0x0015; /// Card specific control frames pub const CONTROL = 0x0016; /// Linux-IrDA pub const IRDA = 0x0017; /// Acorn Econet pub const ECONET = 0x0018; /// HDLC frames pub const HDLC = 0x0019; /// 1A for ArcNet :-) pub const ARCNET = 0x001A; /// Distributed Switch Arch. pub const DSA = 0x001B; /// Trailer switch tagging pub const TRAILER = 0x001C; /// Nokia Phonet frames pub const PHONET = 0x00F5; /// IEEE802.15.4 frame pub const IEEE802154 = 0x00F6; /// ST-Ericsson CAIF protocol pub const CAIF = 0x00F7; /// Multiplexed DSA protocol pub const XDSA = 0x00F8; /// Qualcomm multiplexing and aggregation protocol pub const MAP = 0x00F9; /// Management component transport protocol packets pub const MCTP = 0x00FA; }; }; pub const MSG = struct { pub const OOB = 0x0001; pub const PEEK = 0x0002; pub const DONTROUTE = 0x0004; pub const CTRUNC = 0x0008; pub const PROXY = 0x0010; pub const TRUNC = 0x0020; pub const DONTWAIT = 0x0040; pub const EOR = 0x0080; pub const WAITALL = 0x0100; pub const FIN = 0x0200; pub const SYN = 0x0400; pub const CONFIRM = 0x0800; pub const RST = 0x1000; pub const ERRQUEUE = 0x2000; pub const NOSIGNAL = 0x4000; pub const MORE = 0x8000; pub const WAITFORONE = 0x10000; pub const BATCH = 0x40000; pub const ZEROCOPY = 0x4000000; pub const FASTOPEN = 0x20000000; pub const CMSG_CLOEXEC = 0x40000000; }; pub const DT = struct { pub const UNKNOWN = 0; pub const FIFO = 1; pub const CHR = 2; pub const DIR = 4; pub const BLK = 6; pub const REG = 8; pub const LNK = 10; pub const SOCK = 12; pub const WHT = 14; }; pub const T = if (is_mips) struct { pub const CGETA = 0x5401; pub const CSETA = 0x5402; pub const CSETAW = 0x5403; pub const CSETAF = 0x5404; pub const CSBRK = 0x5405; pub const CXONC = 0x5406; pub const CFLSH = 0x5407; pub const CGETS = 0x540d; pub const CSETS = 0x540e; pub const CSETSW = 0x540f; pub const CSETSF = 0x5410; pub const IOCEXCL = 0x740d; pub const IOCNXCL = 0x740e; pub const IOCOUTQ = 0x7472; pub const IOCSTI = 0x5472; pub const IOCMGET = 0x741d; pub const IOCMBIS = 0x741b; pub const IOCMBIC = 0x741c; pub const IOCMSET = 0x741a; pub const IOCPKT = 0x5470; pub const IOCPKT_DATA = 0x00; pub const IOCPKT_FLUSHREAD = 0x01; pub const IOCPKT_FLUSHWRITE = 0x02; pub const IOCPKT_STOP = 0x04; pub const IOCPKT_START = 0x08; pub const IOCPKT_NOSTOP = 0x10; pub const IOCPKT_DOSTOP = 0x20; pub const IOCPKT_IOCTL = 0x40; pub const IOCSWINSZ = IOCTL.IOW('t', 103, winsize); pub const IOCGWINSZ = IOCTL.IOR('t', 104, winsize); pub const IOCNOTTY = 0x5471; pub const IOCSETD = 0x7401; pub const IOCGETD = 0x7400; pub const FIOCLEX = 0x6601; pub const FIONCLEX = 0x6602; pub const FIOASYNC = 0x667d; pub const FIONBIO = 0x667e; pub const FIOQSIZE = 0x667f; pub const IOCGLTC = 0x7474; pub const IOCSLTC = 0x7475; pub const IOCSPGRP = IOCTL.IOW('t', 118, c_int); pub const IOCGPGRP = IOCTL.IOR('t', 119, c_int); pub const IOCCONS = IOCTL.IOW('t', 120, c_int); pub const FIONREAD = 0x467f; pub const IOCINQ = FIONREAD; pub const IOCGETP = 0x7408; pub const IOCSETP = 0x7409; pub const IOCSETN = 0x740a; pub const IOCSBRK = 0x5427; pub const IOCCBRK = 0x5428; pub const IOCGSID = 0x7416; pub const CGETS2 = IOCTL.IOR('T', 0x2a, termios2); pub const CSETS2 = IOCTL.IOW('T', 0x2b, termios2); pub const CSETSW2 = IOCTL.IOW('T', 0x2c, termios2); pub const CSETSF2 = IOCTL.IOW('T', 0x2d, termios2); pub const IOCGRS485 = IOCTL.IOR('T', 0x2e, serial_rs485); pub const IOCSRS485 = IOCTL.IOWR('T', 0x2f, serial_rs485); pub const IOCGPTN = IOCTL.IOR('T', 0x30, c_uint); pub const IOCSPTLCK = IOCTL.IOW('T', 0x31, c_int); pub const IOCGDEV = IOCTL.IOR('T', 0x32, c_uint); pub const IOCSIG = IOCTL.IOW('T', 0x36, c_int); pub const IOCVHANGUP = 0x5437; pub const IOCGPKT = IOCTL.IOR('T', 0x38, c_int); pub const IOCGPTLCK = IOCTL.IOR('T', 0x39, c_int); pub const IOCGEXCL = IOCTL.IOR('T', 0x40, c_int); pub const IOCGPTPEER = IOCTL.IO('T', 0x41); pub const IOCGISO7816 = IOCTL.IOR('T', 0x42, serial_iso7816); pub const IOCSISO7816 = IOCTL.IOWR('T', 0x43, serial_iso7816); pub const IOCSCTTY = 0x5480; pub const IOCGSOFTCAR = 0x5481; pub const IOCSSOFTCAR = 0x5482; pub const IOCLINUX = 0x5483; pub const IOCGSERIAL = 0x5484; pub const IOCSSERIAL = 0x5485; pub const CSBRKP = 0x5486; pub const IOCSERCONFIG = 0x5488; pub const IOCSERGWILD = 0x5489; pub const IOCSERSWILD = 0x548a; pub const IOCGLCKTRMIOS = 0x548b; pub const IOCSLCKTRMIOS = 0x548c; pub const IOCSERGSTRUCT = 0x548d; pub const IOCSERGETLSR = 0x548e; pub const IOCSERGETMULTI = 0x548f; pub const IOCSERSETMULTI = 0x5490; pub const IOCMIWAIT = 0x5491; pub const IOCGICOUNT = 0x5492; } else if (is_ppc) struct { pub const FIOCLEX = IOCTL.IO('f', 1); pub const FIONCLEX = IOCTL.IO('f', 2); pub const FIOASYNC = IOCTL.IOW('f', 125, c_int); pub const FIONBIO = IOCTL.IOW('f', 126, c_int); pub const FIONREAD = IOCTL.IOR('f', 127, c_int); pub const IOCINQ = FIONREAD; pub const FIOQSIZE = IOCTL.IOR('f', 128, c_longlong); // loff_t -> __kernel_loff_t -> long long pub const IOCGETP = IOCTL.IOR('t', 8, sgttyb); pub const IOCSETP = IOCTL.IOW('t', 9, sgttyb); pub const IOCSETN = IOCTL.IOW('t', 10, sgttyb); pub const IOCSETC = IOCTL.IOW('t', 17, tchars); pub const IOCGETC = IOCTL.IOR('t', 18, tchars); pub const CGETS = IOCTL.IOR('t', 19, termios); pub const CSETS = IOCTL.IOW('t', 20, termios); pub const CSETSW = IOCTL.IOW('t', 21, termios); pub const CSETSF = IOCTL.IOW('t', 22, termios); pub const CGETA = IOCTL.IOR('t', 23, termio); pub const CSETA = IOCTL.IOW('t', 24, termio); pub const CSETAW = IOCTL.IOW('t', 25, termio); pub const CSETAF = IOCTL.IOW('t', 28, termio); pub const CSBRK = IOCTL.IO('t', 29); pub const CXONC = IOCTL.IO('t', 30); pub const CFLSH = IOCTL.IO('t', 31); pub const IOCSWINSZ = IOCTL.IOW('t', 103, winsize); pub const IOCGWINSZ = IOCTL.IOR('t', 104, winsize); pub const IOCSTART = IOCTL.IO('t', 110); pub const IOCSTOP = IOCTL.IO('t', 111); pub const IOCOUTQ = IOCTL.IOR('t', 115, c_int); pub const IOCGLTC = IOCTL.IOR('t', 116, ltchars); pub const IOCSLTC = IOCTL.IOW('t', 117, ltchars); pub const IOCSPGRP = IOCTL.IOW('t', 118, c_int); pub const IOCGPGRP = IOCTL.IOR('t', 119, c_int); pub const IOCEXCL = 0x540c; pub const IOCNXCL = 0x540d; pub const IOCSCTTY = 0x540e; pub const IOCSTI = 0x5412; pub const IOCMGET = 0x5415; pub const IOCMBIS = 0x5416; pub const IOCMBIC = 0x5417; pub const IOCMSET = 0x5418; pub const IOCM_LE = 0x001; pub const IOCM_DTR = 0x002; pub const IOCM_RTS = 0x004; pub const IOCM_ST = 0x008; pub const IOCM_SR = 0x010; pub const IOCM_CTS = 0x020; pub const IOCM_CAR = 0x040; pub const IOCM_RNG = 0x080; pub const IOCM_DSR = 0x100; pub const IOCM_CD = IOCM_CAR; pub const IOCM_RI = IOCM_RNG; pub const IOCM_OUT1 = 0x2000; pub const IOCM_OUT2 = 0x4000; pub const IOCM_LOOP = 0x8000; pub const IOCGSOFTCAR = 0x5419; pub const IOCSSOFTCAR = 0x541a; pub const IOCLINUX = 0x541c; pub const IOCCONS = 0x541d; pub const IOCGSERIAL = 0x541e; pub const IOCSSERIAL = 0x541f; pub const IOCPKT = 0x5420; pub const IOCPKT_DATA = 0; pub const IOCPKT_FLUSHREAD = 1; pub const IOCPKT_FLUSHWRITE = 2; pub const IOCPKT_STOP = 4; pub const IOCPKT_START = 8; pub const IOCPKT_NOSTOP = 16; pub const IOCPKT_DOSTOP = 32; pub const IOCPKT_IOCTL = 64; pub const IOCNOTTY = 0x5422; pub const IOCSETD = 0x5423; pub const IOCGETD = 0x5424; pub const CSBRKP = 0x5425; pub const IOCSBRK = 0x5427; pub const IOCCBRK = 0x5428; pub const IOCGSID = 0x5429; pub const IOCGRS485 = 0x542e; pub const IOCSRS485 = 0x542f; pub const IOCGPTN = IOCTL.IOR('T', 0x30, c_uint); pub const IOCSPTLCK = IOCTL.IOW('T', 0x31, c_int); pub const IOCGDEV = IOCTL.IOR('T', 0x32, c_uint); pub const IOCSIG = IOCTL.IOW('T', 0x36, c_int); pub const IOCVHANGUP = 0x5437; pub const IOCGPKT = IOCTL.IOR('T', 0x38, c_int); pub const IOCGPTLCK = IOCTL.IOR('T', 0x39, c_int); pub const IOCGEXCL = IOCTL.IOR('T', 0x40, c_int); pub const IOCGPTPEER = IOCTL.IO('T', 0x41); pub const IOCGISO7816 = IOCTL.IOR('T', 0x42, serial_iso7816); pub const IOCSISO7816 = IOCTL.IOWR('T', 0x43, serial_iso7816); pub const IOCSERCONFIG = 0x5453; pub const IOCSERGWILD = 0x5454; pub const IOCSERSWILD = 0x5455; pub const IOCGLCKTRMIOS = 0x5456; pub const IOCSLCKTRMIOS = 0x5457; pub const IOCSERGSTRUCT = 0x5458; pub const IOCSERGETLSR = 0x5459; pub const IOCSER_TEMT = 0x01; pub const IOCSERGETMULTI = 0x545a; pub const IOCSERSETMULTI = 0x545b; pub const IOCMIWAIT = 0x545c; pub const IOCGICOUNT = 0x545d; } else if (is_sparc) struct { // Entries with double-underscore prefix have not been translated as they are unsupported. pub const CGETA = IOCTL.IOR('T', 1, termio); pub const CSETA = IOCTL.IOW('T', 2, termio); pub const CSETAW = IOCTL.IOW('T', 3, termio); pub const CSETAF = IOCTL.IOW('T', 4, termio); pub const CSBRK = IOCTL.IO('T', 5); pub const CXONC = IOCTL.IO('T', 6); pub const CFLSH = IOCTL.IO('T', 7); pub const CGETS = IOCTL.IOR('T', 8, termios); pub const CSETS = IOCTL.IOW('T', 9, termios); pub const CSETSW = IOCTL.IOW('T', 10, termios); pub const CSETSF = IOCTL.IOW('T', 11, termios); pub const CGETS2 = IOCTL.IOR('T', 12, termios2); pub const CSETS2 = IOCTL.IOW('T', 13, termios2); pub const CSETSW2 = IOCTL.IOW('T', 14, termios2); pub const CSETSF2 = IOCTL.IOW('T', 15, termios2); pub const IOCGDEV = IOCTL.IOR('T', 0x32, c_uint); pub const IOCVHANGUP = IOCTL.IO('T', 0x37); pub const IOCGPKT = IOCTL.IOR('T', 0x38, c_int); pub const IOCGPTLCK = IOCTL.IOR('T', 0x39, c_int); pub const IOCGEXCL = IOCTL.IOR('T', 0x40, c_int); pub const IOCGRS485 = IOCTL.IOR('T', 0x41, serial_rs485); pub const IOCSRS485 = IOCTL.IOWR('T', 0x42, serial_rs485); pub const IOCGISO7816 = IOCTL.IOR('T', 0x43, serial_iso7816); pub const IOCSISO7816 = IOCTL.IOWR('T', 0x44, serial_iso7816); pub const IOCGETD = IOCTL.IOR('t', 0, c_int); pub const IOCSETD = IOCTL.IOW('t', 1, c_int); pub const IOCEXCL = IOCTL.IO('t', 13); pub const IOCNXCL = IOCTL.IO('t', 14); pub const IOCCONS = IOCTL.IO('t', 36); pub const IOCGSOFTCAR = IOCTL.IOR('t', 100, c_int); pub const IOCSSOFTCAR = IOCTL.IOW('t', 101, c_int); pub const IOCSWINSZ = IOCTL.IOW('t', 103, winsize); pub const IOCGWINSZ = IOCTL.IOR('t', 104, winsize); pub const IOCMGET = IOCTL.IOR('t', 106, c_int); pub const IOCMBIC = IOCTL.IOW('t', 107, c_int); pub const IOCMBIS = IOCTL.IOW('t', 108, c_int); pub const IOCMSET = IOCTL.IOW('t', 109, c_int); pub const IOCSTART = IOCTL.IO('t', 110); pub const IOCSTOP = IOCTL.IO('t', 111); pub const IOCPKT = IOCTL.IOW('t', 112, c_int); pub const IOCNOTTY = IOCTL.IO('t', 113); pub const IOCSTI = IOCTL.IOW('t', 114, c_char); pub const IOCOUTQ = IOCTL.IOR('t', 115, c_int); pub const IOCCBRK = IOCTL.IO('t', 122); pub const IOCSBRK = IOCTL.IO('t', 123); pub const IOCSPGRP = IOCTL.IOW('t', 130, c_int); pub const IOCGPGRP = IOCTL.IOR('t', 131, c_int); pub const IOCSCTTY = IOCTL.IO('t', 132); pub const IOCGSID = IOCTL.IOR('t', 133, c_int); pub const IOCGPTN = IOCTL.IOR('t', 134, c_uint); pub const IOCSPTLCK = IOCTL.IOW('t', 135, c_int); pub const IOCSIG = IOCTL.IOW('t', 136, c_int); pub const IOCGPTPEER = IOCTL.IO('t', 137); pub const FIOCLEX = IOCTL.IO('f', 1); pub const FIONCLEX = IOCTL.IO('f', 2); pub const FIOASYNC = IOCTL.IOW('f', 125, c_int); pub const FIONBIO = IOCTL.IOW('f', 126, c_int); pub const FIONREAD = IOCTL.IOR('f', 127, c_int); pub const IOCINQ = FIONREAD; pub const FIOQSIZE = IOCTL.IOR('f', 128, c_longlong); // loff_t -> __kernel_loff_t -> long long pub const IOCLINUX = 0x541c; pub const IOCGSERIAL = 0x541e; pub const IOCSSERIAL = 0x541f; pub const CSBRKP = 0x5425; pub const IOCSERCONFIG = 0x5453; pub const IOCSERGWILD = 0x5454; pub const IOCSERSWILD = 0x5455; pub const IOCGLCKTRMIOS = 0x5456; pub const IOCSLCKTRMIOS = 0x5457; pub const IOCSERGSTRUCT = 0x5458; pub const IOCSERGETLSR = 0x5459; pub const IOCSERGETMULTI = 0x545a; pub const IOCSERSETMULTI = 0x545b; pub const IOCMIWAIT = 0x545c; pub const IOCGICOUNT = 0x545d; pub const IOCPKT_DATA = 0; pub const IOCPKT_FLUSHREAD = 1; pub const IOCPKT_FLUSHWRITE = 2; pub const IOCPKT_STOP = 4; pub const IOCPKT_START = 8; pub const IOCPKT_NOSTOP = 16; pub const IOCPKT_DOSTOP = 32; pub const IOCPKT_IOCTL = 64; } else struct { pub const CGETS = 0x5401; pub const CSETS = 0x5402; pub const CSETSW = 0x5403; pub const CSETSF = 0x5404; pub const CGETA = 0x5405; pub const CSETA = 0x5406; pub const CSETAW = 0x5407; pub const CSETAF = 0x5408; pub const CSBRK = 0x5409; pub const CXONC = 0x540a; pub const CFLSH = 0x540b; pub const IOCEXCL = 0x540c; pub const IOCNXCL = 0x540d; pub const IOCSCTTY = 0x540e; pub const IOCGPGRP = 0x540f; pub const IOCSPGRP = 0x5410; pub const IOCOUTQ = 0x5411; pub const IOCSTI = 0x5412; pub const IOCGWINSZ = 0x5413; pub const IOCSWINSZ = 0x5414; pub const IOCMGET = 0x5415; pub const IOCMBIS = 0x5416; pub const IOCMBIC = 0x5417; pub const IOCMSET = 0x5418; pub const IOCGSOFTCAR = 0x5419; pub const IOCSSOFTCAR = 0x541a; pub const FIONREAD = 0x541b; pub const IOCINQ = FIONREAD; pub const IOCLINUX = 0x541c; pub const IOCCONS = 0x541d; pub const IOCGSERIAL = 0x541e; pub const IOCSSERIAL = 0x541f; pub const IOCPKT = 0x5420; pub const FIONBIO = 0x5421; pub const IOCNOTTY = 0x5422; pub const IOCSETD = 0x5423; pub const IOCGETD = 0x5424; pub const CSBRKP = 0x5425; pub const IOCSBRK = 0x5427; pub const IOCCBRK = 0x5428; pub const IOCGSID = 0x5429; pub const CGETS2 = IOCTL.IOR('T', 0x2a, termios2); pub const CSETS2 = IOCTL.IOW('T', 0x2b, termios2); pub const CSETSW2 = IOCTL.IOW('T', 0x2c, termios2); pub const CSETSF2 = IOCTL.IOW('T', 0x2d, termios2); pub const IOCGRS485 = 0x542e; pub const IOCSRS485 = 0x542f; pub const IOCGPTN = IOCTL.IOR('T', 0x30, c_uint); pub const IOCSPTLCK = IOCTL.IOW('T', 0x31, c_int); pub const IOCGDEV = IOCTL.IOR('T', 0x32, c_uint); pub const CGETX = 0x5432; pub const CSETX = 0x5433; pub const CSETXF = 0x5434; pub const CSETXW = 0x5435; pub const IOCSIG = IOCTL.IOW('T', 0x36, c_int); pub const IOCVHANGUP = 0x5437; pub const IOCGPKT = IOCTL.IOR('T', 0x38, c_int); pub const IOCGPTLCK = IOCTL.IOR('T', 0x39, c_int); pub const IOCGEXCL = IOCTL.IOR('T', 0x40, c_int); pub const IOCGPTPEER = IOCTL.IO('T', 0x41); pub const IOCGISO7816 = IOCTL.IOR('T', 0x42, serial_iso7816); pub const IOCSISO7816 = IOCTL.IOWR('T', 0x43, serial_iso7816); pub const FIONCLEX = 0x5450; pub const FIOCLEX = 0x5451; pub const FIOASYNC = 0x5452; pub const IOCSERCONFIG = 0x5453; pub const IOCSERGWILD = 0x5454; pub const IOCSERSWILD = 0x5455; pub const IOCGLCKTRMIOS = 0x5456; pub const IOCSLCKTRMIOS = 0x5457; pub const IOCSERGSTRUCT = 0x5458; pub const IOCSERGETLSR = 0x5459; pub const IOCSERGETMULTI = 0x545a; pub const IOCSERSETMULTI = 0x545b; pub const IOCMIWAIT = 0x545c; pub const IOCGICOUNT = 0x545d; pub const FIOQSIZE = switch (native_arch) { .arm, .armeb, .thumb, .thumbeb, .m68k, .s390x, => 0x545e, else => 0x5460, }; pub const IOCPKT_DATA = 0; pub const IOCPKT_FLUSHREAD = 1; pub const IOCPKT_FLUSHWRITE = 2; pub const IOCPKT_STOP = 4; pub const IOCPKT_START = 8; pub const IOCPKT_NOSTOP = 16; pub const IOCPKT_DOSTOP = 32; pub const IOCPKT_IOCTL = 64; pub const IOCSER_TEMT = 0x01; }; pub const serial_rs485 = extern struct { flags: u32, delay_rts_before_send: u32, delay_rts_after_send: u32, extra: extern union { _pad1: [5]u32, s: extern struct { addr_recv: u8, addr_dest: u8, _pad2: [2]u8, _pad3: [4]u32, }, }, }; pub const serial_iso7816 = extern struct { flags: u32, tg: u32, sc_fi: u32, sc_di: u32, clk: u32, _reserved: [5]u32, }; pub const SER = struct { pub const RS485 = struct { pub const ENABLED = 1 << 0; pub const RTS_ON_SEND = 1 << 1; pub const RTS_AFTER_SEND = 1 << 2; pub const RX_DURING_TX = 1 << 4; pub const TERMINATE_BUS = 1 << 5; pub const ADDRB = 1 << 6; pub const ADDR_RECV = 1 << 7; pub const ADDR_DEST = 1 << 8; }; pub const ISO7816 = struct { pub const ENABLED = 1 << 0; pub const T_PARAM = 0x0f << 4; pub fn T(t: anytype) @TypeOf(t) { return (t & 0x0f) << 4; } }; }; pub const EPOLL = struct { pub const CLOEXEC = 1 << @bitOffsetOf(O, "CLOEXEC"); pub const CTL_ADD = 1; pub const CTL_DEL = 2; pub const CTL_MOD = 3; pub const IN = 0x001; pub const PRI = 0x002; pub const OUT = 0x004; pub const RDNORM = 0x040; pub const RDBAND = 0x080; pub const WRNORM = if (is_mips) 0x004 else 0x100; pub const WRBAND = if (is_mips) 0x100 else 0x200; pub const MSG = 0x400; pub const ERR = 0x008; pub const HUP = 0x010; pub const RDHUP = 0x2000; pub const EXCLUSIVE = (@as(u32, 1) << 28); pub const WAKEUP = (@as(u32, 1) << 29); pub const ONESHOT = (@as(u32, 1) << 30); pub const ET = (@as(u32, 1) << 31); }; pub const CLOCK = clockid_t; pub const clockid_t = enum(u32) { REALTIME = 0, MONOTONIC = 1, PROCESS_CPUTIME_ID = 2, THREAD_CPUTIME_ID = 3, MONOTONIC_RAW = 4, REALTIME_COARSE = 5, MONOTONIC_COARSE = 6, BOOTTIME = 7, REALTIME_ALARM = 8, BOOTTIME_ALARM = 9, // In the linux kernel header file (time.h) is the following note: // * The driver implementing this got removed. The clock ID is kept as a // * place holder. Do not reuse! // Therefore, calling clock_gettime() with these IDs will result in an error. // // Some backgrond: // - SGI_CYCLE was for Silicon Graphics (SGI) workstations, // which are probably no longer in use, so it makes sense to disable // - TAI_CLOCK was designed as CLOCK_REALTIME(UTC) + tai_offset, // but tai_offset was always 0 in the kernel. // So there is no point in using this clock. // SGI_CYCLE = 10, // TAI = 11, _, }; // For use with posix.timerfd_create() // Actually, the parameter for the timerfd_create() function is in integer, // which means that the developer has to figure out which value is appropriate. // To make this easier and, above all, safer, because an incorrect value leads // to a panic, an enum is introduced which only allows the values // that actually work. pub const TIMERFD_CLOCK = timerfd_clockid_t; pub const timerfd_clockid_t = enum(u32) { REALTIME = 0, MONOTONIC = 1, BOOTTIME = 7, REALTIME_ALARM = 8, BOOTTIME_ALARM = 9, _, }; pub const TIMER = packed struct(u32) { ABSTIME: bool, _: u31 = 0, }; pub const CSIGNAL = 0x000000ff; pub const CLONE = struct { pub const VM = 0x00000100; pub const FS = 0x00000200; pub const FILES = 0x00000400; pub const SIGHAND = 0x00000800; pub const PIDFD = 0x00001000; pub const PTRACE = 0x00002000; pub const VFORK = 0x00004000; pub const PARENT = 0x00008000; pub const THREAD = 0x00010000; pub const NEWNS = 0x00020000; pub const SYSVSEM = 0x00040000; pub const SETTLS = 0x00080000; pub const PARENT_SETTID = 0x00100000; pub const CHILD_CLEARTID = 0x00200000; pub const DETACHED = 0x00400000; pub const UNTRACED = 0x00800000; pub const CHILD_SETTID = 0x01000000; pub const NEWCGROUP = 0x02000000; pub const NEWUTS = 0x04000000; pub const NEWIPC = 0x08000000; pub const NEWUSER = 0x10000000; pub const NEWPID = 0x20000000; pub const NEWNET = 0x40000000; pub const IO = 0x80000000; // Flags for the clone3() syscall. /// Clear any signal handler and reset to SIG_DFL. pub const CLEAR_SIGHAND = 0x100000000; /// Clone into a specific cgroup given the right permissions. pub const INTO_CGROUP = 0x200000000; // cloning flags intersect with CSIGNAL so can be used with unshare and clone3 syscalls only. /// New time namespace pub const NEWTIME = 0x00000080; }; pub const EFD = struct { pub const SEMAPHORE = 1; pub const CLOEXEC = 1 << @bitOffsetOf(O, "CLOEXEC"); pub const NONBLOCK = 1 << @bitOffsetOf(O, "NONBLOCK"); }; pub const MS = struct { pub const RDONLY = 1; pub const NOSUID = 2; pub const NODEV = 4; pub const NOEXEC = 8; pub const SYNCHRONOUS = 16; pub const REMOUNT = 32; pub const MANDLOCK = 64; pub const DIRSYNC = 128; pub const NOATIME = 1024; pub const NODIRATIME = 2048; pub const BIND = 4096; pub const MOVE = 8192; pub const REC = 16384; pub const SILENT = 32768; pub const POSIXACL = (1 << 16); pub const UNBINDABLE = (1 << 17); pub const PRIVATE = (1 << 18); pub const SLAVE = (1 << 19); pub const SHARED = (1 << 20); pub const RELATIME = (1 << 21); pub const KERNMOUNT = (1 << 22); pub const I_VERSION = (1 << 23); pub const STRICTATIME = (1 << 24); pub const LAZYTIME = (1 << 25); pub const NOREMOTELOCK = (1 << 27); pub const NOSEC = (1 << 28); pub const BORN = (1 << 29); pub const ACTIVE = (1 << 30); pub const NOUSER = (1 << 31); pub const RMT_MASK = (RDONLY | SYNCHRONOUS | MANDLOCK | I_VERSION | LAZYTIME); pub const MGC_VAL = 0xc0ed0000; pub const MGC_MSK = 0xffff0000; }; pub const MNT = struct { pub const FORCE = 1; pub const DETACH = 2; pub const EXPIRE = 4; }; pub const UMOUNT_NOFOLLOW = 8; pub const IN = struct { pub const CLOEXEC = 1 << @bitOffsetOf(O, "CLOEXEC"); pub const NONBLOCK = 1 << @bitOffsetOf(O, "NONBLOCK"); pub const ACCESS = 0x00000001; pub const MODIFY = 0x00000002; pub const ATTRIB = 0x00000004; pub const CLOSE_WRITE = 0x00000008; pub const CLOSE_NOWRITE = 0x00000010; pub const CLOSE = CLOSE_WRITE | CLOSE_NOWRITE; pub const OPEN = 0x00000020; pub const MOVED_FROM = 0x00000040; pub const MOVED_TO = 0x00000080; pub const MOVE = MOVED_FROM | MOVED_TO; pub const CREATE = 0x00000100; pub const DELETE = 0x00000200; pub const DELETE_SELF = 0x00000400; pub const MOVE_SELF = 0x00000800; pub const ALL_EVENTS = 0x00000fff; pub const UNMOUNT = 0x00002000; pub const Q_OVERFLOW = 0x00004000; pub const IGNORED = 0x00008000; pub const ONLYDIR = 0x01000000; pub const DONT_FOLLOW = 0x02000000; pub const EXCL_UNLINK = 0x04000000; pub const MASK_CREATE = 0x10000000; pub const MASK_ADD = 0x20000000; pub const ISDIR = 0x40000000; pub const ONESHOT = 0x80000000; }; pub const fanotify = struct { pub const InitFlags = packed struct(u32) { CLOEXEC: bool = false, NONBLOCK: bool = false, CLASS: enum(u2) { NOTIF = 0, CONTENT = 1, PRE_CONTENT = 2, } = .NOTIF, UNLIMITED_QUEUE: bool = false, UNLIMITED_MARKS: bool = false, ENABLE_AUDIT: bool = false, REPORT_PIDFD: bool = false, REPORT_TID: bool = false, REPORT_FID: bool = false, REPORT_DIR_FID: bool = false, REPORT_NAME: bool = false, REPORT_TARGET_FID: bool = false, _: u19 = 0, }; pub const MarkFlags = packed struct(u32) { ADD: bool = false, REMOVE: bool = false, DONT_FOLLOW: bool = false, ONLYDIR: bool = false, MOUNT: bool = false, /// Mutually exclusive with `IGNORE` IGNORED_MASK: bool = false, IGNORED_SURV_MODIFY: bool = false, FLUSH: bool = false, FILESYSTEM: bool = false, EVICTABLE: bool = false, /// Mutually exclusive with `IGNORED_MASK` IGNORE: bool = false, _: u21 = 0, }; pub const MarkMask = packed struct(u64) { /// File was accessed ACCESS: bool = false, /// File was modified MODIFY: bool = false, /// Metadata changed ATTRIB: bool = false, /// Writtable file closed CLOSE_WRITE: bool = false, /// Unwrittable file closed CLOSE_NOWRITE: bool = false, /// File was opened OPEN: bool = false, /// File was moved from X MOVED_FROM: bool = false, /// File was moved to Y MOVED_TO: bool = false, /// Subfile was created CREATE: bool = false, /// Subfile was deleted DELETE: bool = false, /// Self was deleted DELETE_SELF: bool = false, /// Self was moved MOVE_SELF: bool = false, /// File was opened for exec OPEN_EXEC: bool = false, reserved13: u1 = 0, /// Event queued overflowed Q_OVERFLOW: bool = false, /// Filesystem error FS_ERROR: bool = false, /// File open in perm check OPEN_PERM: bool = false, /// File accessed in perm check ACCESS_PERM: bool = false, /// File open/exec in perm check OPEN_EXEC_PERM: bool = false, reserved19: u8 = 0, /// Interested in child events EVENT_ON_CHILD: bool = false, /// File was renamed RENAME: bool = false, reserved30: u1 = 0, /// Event occurred against dir ONDIR: bool = false, reserved31: u33 = 0, }; pub const event_metadata = extern struct { event_len: u32, vers: u8, reserved: u8, metadata_len: u16, mask: MarkMask align(8), fd: i32, pid: i32, pub const VERSION = 3; }; pub const response = extern struct { fd: i32, response: u32, }; /// Unique file identifier info record. /// /// This structure is used for records of types `EVENT_INFO_TYPE.FID`. /// `EVENT_INFO_TYPE.DFID` and `EVENT_INFO_TYPE.DFID_NAME`. /// /// For `EVENT_INFO_TYPE.DFID_NAME` there is additionally a null terminated /// name immediately after the file handle. pub const event_info_fid = extern struct { hdr: event_info_header, fsid: kernel_fsid_t, /// Following is an opaque struct file_handle that can be passed as /// an argument to open_by_handle_at(2). handle: [0]u8, }; /// Variable length info record following event metadata. pub const event_info_header = extern struct { info_type: EVENT_INFO_TYPE, pad: u8, len: u16, }; pub const EVENT_INFO_TYPE = enum(u8) { FID = 1, DFID_NAME = 2, DFID = 3, PIDFD = 4, ERROR = 5, OLD_DFID_NAME = 10, OLD_DFID = 11, NEW_DFID_NAME = 12, NEW_DFID = 13, }; }; pub const file_handle = extern struct { handle_bytes: u32, handle_type: i32, f_handle: [0]u8, }; pub const kernel_fsid_t = fsid_t; pub const fsid_t = [2]i32; pub const S = struct { pub const IFMT = 0o170000; pub const IFDIR = 0o040000; pub const IFCHR = 0o020000; pub const IFBLK = 0o060000; pub const IFREG = 0o100000; pub const IFIFO = 0o010000; pub const IFLNK = 0o120000; pub const IFSOCK = 0o140000; pub const ISUID = 0o4000; pub const ISGID = 0o2000; pub const ISVTX = 0o1000; pub const IRUSR = 0o400; pub const IWUSR = 0o200; pub const IXUSR = 0o100; pub const IRWXU = 0o700; pub const IRGRP = 0o040; pub const IWGRP = 0o020; pub const IXGRP = 0o010; pub const IRWXG = 0o070; pub const IROTH = 0o004; pub const IWOTH = 0o002; pub const IXOTH = 0o001; pub const IRWXO = 0o007; pub fn ISREG(m: mode_t) bool { return m & IFMT == IFREG; } pub fn ISDIR(m: mode_t) bool { return m & IFMT == IFDIR; } pub fn ISCHR(m: mode_t) bool { return m & IFMT == IFCHR; } pub fn ISBLK(m: mode_t) bool { return m & IFMT == IFBLK; } pub fn ISFIFO(m: mode_t) bool { return m & IFMT == IFIFO; } pub fn ISLNK(m: mode_t) bool { return m & IFMT == IFLNK; } pub fn ISSOCK(m: mode_t) bool { return m & IFMT == IFSOCK; } }; pub const UTIME = struct { pub const NOW = 0x3fffffff; pub const OMIT = 0x3ffffffe; }; const TFD_TIMER = packed struct(u32) { ABSTIME: bool = false, CANCEL_ON_SET: bool = false, _: u30 = 0, }; pub const TFD = switch (native_arch) { .sparc64 => packed struct(u32) { _0: u14 = 0, NONBLOCK: bool = false, _15: u7 = 0, CLOEXEC: bool = false, _: u9 = 0, pub const TIMER = TFD_TIMER; }, .mips, .mipsel, .mips64, .mips64el => packed struct(u32) { _0: u7 = 0, NONBLOCK: bool = false, _8: u11 = 0, CLOEXEC: bool = false, _: u12 = 0, pub const TIMER = TFD_TIMER; }, else => packed struct(u32) { _0: u11 = 0, NONBLOCK: bool = false, _12: u7 = 0, CLOEXEC: bool = false, _: u12 = 0, pub const TIMER = TFD_TIMER; }, }; const k_sigaction_funcs = struct { const handler = ?*align(1) const fn (i32) callconv(.c) void; const restorer = *const fn () callconv(.c) void; }; /// Kernel sigaction struct, as expected by the `rt_sigaction` syscall. Includes `restorer` on /// targets where userspace is responsible for hooking up `rt_sigreturn`. pub const k_sigaction = switch (native_arch) { .mips, .mipsel, .mips64, .mips64el => extern struct { flags: c_uint, handler: k_sigaction_funcs.handler, mask: sigset_t, }, .hexagon, .loongarch32, .loongarch64, .or1k, .riscv32, .riscv64 => extern struct { handler: k_sigaction_funcs.handler, flags: c_ulong, mask: sigset_t, }, else => extern struct { handler: k_sigaction_funcs.handler, flags: c_ulong, restorer: k_sigaction_funcs.restorer, mask: sigset_t, }, }; /// Kernel Sigaction wrapper for the actual ABI `k_sigaction`. The Zig /// linux.zig wrapper library still does some pre-processing on /// sigaction() calls (to add the `restorer` field). /// /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = struct { pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.c) void; handler: extern union { handler: ?handler_fn, sigaction: ?sigaction_fn, }, mask: sigset_t, flags: switch (native_arch) { .mips, .mipsel, .mips64, .mips64el => c_uint, else => c_ulong, }, }; pub const SFD = struct { pub const CLOEXEC = 1 << @bitOffsetOf(O, "CLOEXEC"); pub const NONBLOCK = 1 << @bitOffsetOf(O, "NONBLOCK"); }; pub const signalfd_siginfo = extern struct { signo: u32, errno: i32, code: i32, pid: u32, uid: uid_t, fd: i32, tid: u32, band: u32, overrun: u32, trapno: u32, status: i32, int: i32, ptr: u64, utime: u64, stime: u64, addr: u64, addr_lsb: u16, __pad2: u16, syscall: i32, call_addr: u64, native_arch: u32, __pad: [28]u8, }; pub const in_port_t = u16; pub const sa_family_t = u16; pub const socklen_t = u32; pub const sockaddr = extern struct { family: sa_family_t, data: [14]u8, pub const SS_MAXSIZE = 128; pub const storage = extern struct { family: sa_family_t align(8), padding: [SS_MAXSIZE - @sizeOf(sa_family_t)]u8 = undefined, comptime { assert(@sizeOf(storage) == SS_MAXSIZE); assert(@alignOf(storage) == 8); } }; /// IPv4 socket address pub const in = extern struct { family: sa_family_t = AF.INET, port: in_port_t, addr: u32, zero: [8]u8 = [8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }, }; /// IPv6 socket address pub const in6 = extern struct { family: sa_family_t = AF.INET6, port: in_port_t, flowinfo: u32, addr: [16]u8, scope_id: u32, }; /// UNIX domain socket address pub const un = extern struct { family: sa_family_t = AF.UNIX, path: [108]u8, }; /// Packet socket address pub const ll = extern struct { family: sa_family_t = AF.PACKET, protocol: u16, ifindex: i32, hatype: u16, pkttype: u8, halen: u8, addr: [8]u8, }; /// Netlink socket address pub const nl = extern struct { family: sa_family_t = AF.NETLINK, __pad1: c_ushort = 0, /// port ID pid: u32, /// multicast groups mask groups: u32, }; pub const xdp = extern struct { family: u16 = AF.XDP, flags: u16, ifindex: u32, queue_id: u32, shared_umem_fd: u32, }; /// Address structure for vSockets pub const vm = extern struct { family: sa_family_t = AF.VSOCK, reserved1: u16 = 0, port: u32, cid: u32, flags: u8, /// The total size of this structure should be exactly the same as that of struct sockaddr. zero: [3]u8 = [_]u8{0} ** 3, comptime { std.debug.assert(@sizeOf(vm) == @sizeOf(sockaddr)); } }; }; pub const mmsghdr = extern struct { hdr: msghdr, len: u32, }; pub const epoll_data = extern union { ptr: usize, fd: i32, u32: u32, u64: u64, }; pub const epoll_event = extern struct { events: u32, data: epoll_data align(switch (native_arch) { .x86_64 => 4, else => @alignOf(epoll_data), }), }; pub const VFS_CAP_REVISION_MASK = 0xFF000000; pub const VFS_CAP_REVISION_SHIFT = 24; pub const VFS_CAP_FLAGS_MASK = ~@as(u32, VFS_CAP_REVISION_MASK); pub const VFS_CAP_FLAGS_EFFECTIVE = 0x000001; pub const VFS_CAP_REVISION_1 = 0x01000000; pub const VFS_CAP_U32_1 = 1; pub const XATTR_CAPS_SZ_1 = @sizeOf(u32) * (1 + 2 * VFS_CAP_U32_1); pub const VFS_CAP_REVISION_2 = 0x02000000; pub const VFS_CAP_U32_2 = 2; pub const XATTR_CAPS_SZ_2 = @sizeOf(u32) * (1 + 2 * VFS_CAP_U32_2); pub const XATTR_CAPS_SZ = XATTR_CAPS_SZ_2; pub const VFS_CAP_U32 = VFS_CAP_U32_2; pub const VFS_CAP_REVISION = VFS_CAP_REVISION_2; pub const vfs_cap_data = extern struct { //all of these are mandated as little endian //when on disk. const Data = extern struct { permitted: u32, inheritable: u32, }; magic_etc: u32, data: [VFS_CAP_U32]Data, }; pub const CAP = struct { pub const CHOWN = 0; pub const DAC_OVERRIDE = 1; pub const DAC_READ_SEARCH = 2; pub const FOWNER = 3; pub const FSETID = 4; pub const KILL = 5; pub const SETGID = 6; pub const SETUID = 7; pub const SETPCAP = 8; pub const LINUX_IMMUTABLE = 9; pub const NET_BIND_SERVICE = 10; pub const NET_BROADCAST = 11; pub const NET_ADMIN = 12; pub const NET_RAW = 13; pub const IPC_LOCK = 14; pub const IPC_OWNER = 15; pub const SYS_MODULE = 16; pub const SYS_RAWIO = 17; pub const SYS_CHROOT = 18; pub const SYS_PTRACE = 19; pub const SYS_PACCT = 20; pub const SYS_ADMIN = 21; pub const SYS_BOOT = 22; pub const SYS_NICE = 23; pub const SYS_RESOURCE = 24; pub const SYS_TIME = 25; pub const SYS_TTY_CONFIG = 26; pub const MKNOD = 27; pub const LEASE = 28; pub const AUDIT_WRITE = 29; pub const AUDIT_CONTROL = 30; pub const SETFCAP = 31; pub const MAC_OVERRIDE = 32; pub const MAC_ADMIN = 33; pub const SYSLOG = 34; pub const WAKE_ALARM = 35; pub const BLOCK_SUSPEND = 36; pub const AUDIT_READ = 37; pub const PERFMON = 38; pub const BPF = 39; pub const CHECKPOINT_RESTORE = 40; pub const LAST_CAP = CHECKPOINT_RESTORE; pub fn valid(x: u8) bool { return x >= 0 and x <= LAST_CAP; } pub fn TO_MASK(cap: u8) u32 { return @as(u32, 1) << @as(u5, @intCast(cap & 31)); } pub fn TO_INDEX(cap: u8) u8 { return cap >> 5; } }; pub const cap_t = extern struct { hdrp: *cap_user_header_t, datap: *cap_user_data_t, }; pub const cap_user_header_t = extern struct { version: u32, pid: usize, }; pub const cap_user_data_t = extern struct { effective: u32, permitted: u32, inheritable: u32, }; pub const inotify_event = extern struct { wd: i32, mask: u32, cookie: u32, len: u32, //name: [?]u8, // if an event is returned for a directory or file inside the directory being watched // returns the name of said directory/file // returns `null` if the directory/file is the one being watched pub fn getName(self: *const inotify_event) ?[:0]const u8 { if (self.len == 0) return null; return std.mem.span(@as([*:0]const u8, @ptrCast(self)) + @sizeOf(inotify_event)); } }; pub const dirent64 = extern struct { ino: u64, off: u64, reclen: u16, type: u8, name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173 }; pub const dl_phdr_info = extern struct { addr: usize, name: ?[*:0]const u8, phdr: [*]std.elf.Phdr, phnum: u16, }; pub const CPU_SETSIZE = 128; pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize; pub const cpu_count_t = std.meta.Int(.unsigned, std.math.log2(CPU_SETSIZE * 8)); pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t { var sum: cpu_count_t = 0; for (set) |x| { sum += @popCount(x); } return sum; } pub const MINSIGSTKSZ = switch (native_arch) { .arc, .arceb, .arm, .armeb, .csky, .hexagon, .m68k, .mips, .mipsel, .mips64, .mips64el, .or1k, .powerpc, .powerpcle, .riscv32, .riscv64, .s390x, .thumb, .thumbeb, .x86, .x86_64, .xtensa, .xtensaeb, => 2048, .loongarch64, .sparc, .sparc64, => 4096, .aarch64, .aarch64_be, => 5120, .powerpc64, .powerpc64le, => 8192, else => @compileError("MINSIGSTKSZ not defined for this architecture"), }; pub const SIGSTKSZ = switch (native_arch) { .arc, .arceb, .arm, .armeb, .csky, .hexagon, .m68k, .mips, .mipsel, .mips64, .mips64el, .or1k, .powerpc, .powerpcle, .riscv32, .riscv64, .s390x, .thumb, .thumbeb, .x86, .x86_64, .xtensa, .xtensaeb, => 8192, .aarch64, .aarch64_be, .loongarch64, .sparc, .sparc64, => 16384, .powerpc64, .powerpc64le, => 32768, else => @compileError("SIGSTKSZ not defined for this architecture"), }; pub const SS = struct { pub const ONSTACK = 1; pub const DISABLE = 2; pub const AUTODISARM = 1 << 31; }; pub const stack_t = if (is_mips) // IRIX compatible stack_t extern struct { sp: [*]u8, size: usize, flags: i32, } else extern struct { sp: [*]u8, flags: i32, size: usize, }; pub const sigval = extern union { int: i32, ptr: *anyopaque, }; const siginfo_fields_union = extern union { pad: [128 - 2 * @sizeOf(c_int) - @sizeOf(c_long)]u8, common: extern struct { first: extern union { piduid: extern struct { pid: pid_t, uid: uid_t, }, timer: extern struct { timerid: i32, overrun: i32, }, }, second: extern union { value: sigval, sigchld: extern struct { status: i32, utime: clock_t, stime: clock_t, }, }, }, sigfault: extern struct { addr: *allowzero anyopaque, addr_lsb: i16, first: extern union { addr_bnd: extern struct { lower: *anyopaque, upper: *anyopaque, }, pkey: u32, }, }, sigpoll: extern struct { band: isize, fd: i32, }, sigsys: extern struct { call_addr: *anyopaque, syscall: i32, native_arch: u32, }, }; pub const siginfo_t = if (is_mips) extern struct { signo: i32, code: i32, errno: i32, fields: siginfo_fields_union, } else extern struct { signo: i32, errno: i32, code: i32, fields: siginfo_fields_union, }; // io_uring_params.flags /// io_context is polled pub const IORING_SETUP_IOPOLL = 1 << 0; /// SQ poll thread pub const IORING_SETUP_SQPOLL = 1 << 1; /// sq_thread_cpu is valid pub const IORING_SETUP_SQ_AFF = 1 << 2; /// app defines CQ size pub const IORING_SETUP_CQSIZE = 1 << 3; /// clamp SQ/CQ ring sizes pub const IORING_SETUP_CLAMP = 1 << 4; /// attach to existing wq pub const IORING_SETUP_ATTACH_WQ = 1 << 5; /// start with ring disabled pub const IORING_SETUP_R_DISABLED = 1 << 6; /// continue submit on error pub const IORING_SETUP_SUBMIT_ALL = 1 << 7; /// Cooperative task running. When requests complete, they often require /// forcing the submitter to transition to the kernel to complete. If this /// flag is set, work will be done when the task transitions anyway, rather /// than force an inter-processor interrupt reschedule. This avoids interrupting /// a task running in userspace, and saves an IPI. pub const IORING_SETUP_COOP_TASKRUN = 1 << 8; /// If COOP_TASKRUN is set, get notified if task work is available for /// running and a kernel transition would be needed to run it. This sets /// IORING_SQ_TASKRUN in the sq ring flags. Not valid with COOP_TASKRUN. pub const IORING_SETUP_TASKRUN_FLAG = 1 << 9; /// SQEs are 128 byte pub const IORING_SETUP_SQE128 = 1 << 10; /// CQEs are 32 byte pub const IORING_SETUP_CQE32 = 1 << 11; /// Only one task is allowed to submit requests pub const IORING_SETUP_SINGLE_ISSUER = 1 << 12; /// Defer running task work to get events. /// Rather than running bits of task work whenever the task transitions /// try to do it just before it is needed. pub const IORING_SETUP_DEFER_TASKRUN = 1 << 13; /// Application provides ring memory pub const IORING_SETUP_NO_MMAP = 1 << 14; /// Register the ring fd in itself for use with /// IORING_REGISTER_USE_REGISTERED_RING; return a registered fd index rather /// than an fd. pub const IORING_SETUP_REGISTERED_FD_ONLY = 1 << 15; /// Removes indirection through the SQ index array. pub const IORING_SETUP_NO_SQARRAY = 1 << 16; /// IO submission data structure (Submission Queue Entry) pub const io_uring_sqe = @import("linux/io_uring_sqe.zig").io_uring_sqe; pub const IoUring = @import("linux/IoUring.zig"); /// If sqe->file_index is set to this for opcodes that instantiate a new /// direct descriptor (like openat/openat2/accept), then io_uring will allocate /// an available direct descriptor instead of having the application pass one /// in. The picked direct descriptor will be returned in cqe->res, or -ENFILE /// if the space is full. /// Available since Linux 5.19 pub const IORING_FILE_INDEX_ALLOC = maxInt(u32); pub const IOSQE_BIT = enum(u8) { FIXED_FILE, IO_DRAIN, IO_LINK, IO_HARDLINK, ASYNC, BUFFER_SELECT, CQE_SKIP_SUCCESS, _, }; // io_uring_sqe.flags /// use fixed fileset pub const IOSQE_FIXED_FILE = 1 << @intFromEnum(IOSQE_BIT.FIXED_FILE); /// issue after inflight IO pub const IOSQE_IO_DRAIN = 1 << @intFromEnum(IOSQE_BIT.IO_DRAIN); /// links next sqe pub const IOSQE_IO_LINK = 1 << @intFromEnum(IOSQE_BIT.IO_LINK); /// like LINK, but stronger pub const IOSQE_IO_HARDLINK = 1 << @intFromEnum(IOSQE_BIT.IO_HARDLINK); /// always go async pub const IOSQE_ASYNC = 1 << @intFromEnum(IOSQE_BIT.ASYNC); /// select buffer from buf_group pub const IOSQE_BUFFER_SELECT = 1 << @intFromEnum(IOSQE_BIT.BUFFER_SELECT); /// don't post CQE if request succeeded /// Available since Linux 5.17 pub const IOSQE_CQE_SKIP_SUCCESS = 1 << @intFromEnum(IOSQE_BIT.CQE_SKIP_SUCCESS); pub const IORING_OP = enum(u8) { NOP, READV, WRITEV, FSYNC, READ_FIXED, WRITE_FIXED, POLL_ADD, POLL_REMOVE, SYNC_FILE_RANGE, SENDMSG, RECVMSG, TIMEOUT, TIMEOUT_REMOVE, ACCEPT, ASYNC_CANCEL, LINK_TIMEOUT, CONNECT, FALLOCATE, OPENAT, CLOSE, FILES_UPDATE, STATX, READ, WRITE, FADVISE, MADVISE, SEND, RECV, OPENAT2, EPOLL_CTL, SPLICE, PROVIDE_BUFFERS, REMOVE_BUFFERS, TEE, SHUTDOWN, RENAMEAT, UNLINKAT, MKDIRAT, SYMLINKAT, LINKAT, MSG_RING, FSETXATTR, SETXATTR, FGETXATTR, GETXATTR, SOCKET, URING_CMD, SEND_ZC, SENDMSG_ZC, READ_MULTISHOT, WAITID, FUTEX_WAIT, FUTEX_WAKE, FUTEX_WAITV, FIXED_FD_INSTALL, FTRUNCATE, BIND, LISTEN, RECV_ZC, _, }; // io_uring_sqe.uring_cmd_flags (rw_flags in the Zig struct) /// use registered buffer; pass thig flag along with setting sqe->buf_index. pub const IORING_URING_CMD_FIXED = 1 << 0; // io_uring_sqe.fsync_flags (rw_flags in the Zig struct) pub const IORING_FSYNC_DATASYNC = 1 << 0; // io_uring_sqe.timeout_flags (rw_flags in the Zig struct) pub const IORING_TIMEOUT_ABS = 1 << 0; pub const IORING_TIMEOUT_UPDATE = 1 << 1; // Available since Linux 5.11 pub const IORING_TIMEOUT_BOOTTIME = 1 << 2; // Available since Linux 5.15 pub const IORING_TIMEOUT_REALTIME = 1 << 3; // Available since Linux 5.15 pub const IORING_LINK_TIMEOUT_UPDATE = 1 << 4; // Available since Linux 5.15 pub const IORING_TIMEOUT_ETIME_SUCCESS = 1 << 5; // Available since Linux 5.16 pub const IORING_TIMEOUT_CLOCK_MASK = IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME; pub const IORING_TIMEOUT_UPDATE_MASK = IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE; // io_uring_sqe.splice_flags (rw_flags in the Zig struct) // extends splice(2) flags pub const IORING_SPLICE_F_FD_IN_FIXED = 1 << 31; // POLL_ADD flags. // Note that since sqe->poll_events (rw_flags in the Zig struct) is the flag space, the command flags for POLL_ADD are stored in sqe->len. /// Multishot poll. Sets IORING_CQE_F_MORE if the poll handler will continue to report CQEs on behalf of the same SQE. pub const IORING_POLL_ADD_MULTI = 1 << 0; /// Update existing poll request, matching sqe->addr as the old user_data field. pub const IORING_POLL_UPDATE_EVENTS = 1 << 1; pub const IORING_POLL_UPDATE_USER_DATA = 1 << 2; pub const IORING_POLL_ADD_LEVEL = 1 << 3; // ASYNC_CANCEL flags. /// Cancel all requests that match the given key pub const IORING_ASYNC_CANCEL_ALL = 1 << 0; /// Key off 'fd' for cancelation rather than the request 'user_data'. pub const IORING_ASYNC_CANCEL_FD = 1 << 1; /// Match any request pub const IORING_ASYNC_CANCEL_ANY = 1 << 2; /// 'fd' passed in is a fixed descriptor. Available since Linux 6.0 pub const IORING_ASYNC_CANCEL_FD_FIXED = 1 << 3; // send/sendmsg and recv/recvmsg flags (sqe->ioprio) /// If set, instead of first attempting to send or receive and arm poll if that yields an -EAGAIN result, /// arm poll upfront and skip the initial transfer attempt. pub const IORING_RECVSEND_POLL_FIRST = 1 << 0; /// Multishot recv. Sets IORING_CQE_F_MORE if the handler will continue to report CQEs on behalf of the same SQE. pub const IORING_RECV_MULTISHOT = 1 << 1; /// Use registered buffers, the index is stored in the buf_index field. pub const IORING_RECVSEND_FIXED_BUF = 1 << 2; /// If set, SEND[MSG]_ZC should report the zerocopy usage in cqe.res for the IORING_CQE_F_NOTIF cqe. pub const IORING_SEND_ZC_REPORT_USAGE = 1 << 3; /// If set, send or recv will grab as many buffers from the buffer group ID given and send them all. /// The completion result will be the number of buffers send, with the starting buffer ID in cqe as per usual. /// The buffers be contigious from the starting buffer ID. /// Used with IOSQE_BUFFER_SELECT. pub const IORING_RECVSEND_BUNDLE = 1 << 4; /// CQE.RES FOR IORING_CQE_F_NOTIF if IORING_SEND_ZC_REPORT_USAGE was requested pub const IORING_NOTIF_USAGE_ZC_COPIED = 1 << 31; /// accept flags stored in sqe->iopri pub const IORING_ACCEPT_MULTISHOT = 1 << 0; /// IORING_OP_MSG_RING command types, stored in sqe->addr pub const IORING_MSG_RING_COMMAND = enum(u8) { /// pass sqe->len as 'res' and off as user_data DATA, /// send a registered fd to another ring SEND_FD, }; // io_uring_sqe.msg_ring_flags (rw_flags in the Zig struct) /// Don't post a CQE to the target ring. Not applicable for IORING_MSG_DATA, obviously. pub const IORING_MSG_RING_CQE_SKIP = 1 << 0; /// Pass through the flags from sqe->file_index (splice_fd_in in the zig struct) to cqe->flags */ pub const IORING_MSG_RING_FLAGS_PASS = 1 << 1; // IO completion data structure (Completion Queue Entry) pub const io_uring_cqe = extern struct { /// io_uring_sqe.data submission passed back user_data: u64, /// result code for this event res: i32, flags: u32, // Followed by 16 bytes of padding if initialized with IORING_SETUP_CQE32, doubling cqe size pub fn err(self: io_uring_cqe) E { if (self.res > -4096 and self.res < 0) { return @as(E, @enumFromInt(-self.res)); } return .SUCCESS; } // On successful completion of the provided buffers IO request, the CQE flags field // will have IORING_CQE_F_BUFFER set and the selected buffer ID will be indicated by // the upper 16-bits of the flags field. pub fn buffer_id(self: io_uring_cqe) !u16 { if (self.flags & IORING_CQE_F_BUFFER != IORING_CQE_F_BUFFER) { return error.NoBufferSelected; } return @as(u16, @intCast(self.flags >> IORING_CQE_BUFFER_SHIFT)); } }; // io_uring_cqe.flags /// If set, the upper 16 bits are the buffer ID pub const IORING_CQE_F_BUFFER = 1 << 0; /// If set, parent SQE will generate more CQE entries. /// Available since Linux 5.13. pub const IORING_CQE_F_MORE = 1 << 1; /// If set, more data to read after socket recv pub const IORING_CQE_F_SOCK_NONEMPTY = 1 << 2; /// Set for notification CQEs. Can be used to distinct them from sends. pub const IORING_CQE_F_NOTIF = 1 << 3; /// If set, the buffer ID set in the completion will get more completions. pub const IORING_CQE_F_BUF_MORE = 1 << 4; pub const IORING_CQE_BUFFER_SHIFT = 16; /// Magic offsets for the application to mmap the data it needs pub const IORING_OFF_SQ_RING = 0; pub const IORING_OFF_CQ_RING = 0x8000000; pub const IORING_OFF_SQES = 0x10000000; /// Filled with the offset for mmap(2) pub const io_sqring_offsets = extern struct { /// offset of ring head head: u32, /// offset of ring tail tail: u32, /// ring mask value ring_mask: u32, /// entries in ring ring_entries: u32, /// ring flags flags: u32, /// number of sqes not submitted dropped: u32, /// sqe index array array: u32, resv1: u32, user_addr: u64, }; // io_sqring_offsets.flags /// needs io_uring_enter wakeup pub const IORING_SQ_NEED_WAKEUP = 1 << 0; /// kernel has cqes waiting beyond the cq ring pub const IORING_SQ_CQ_OVERFLOW = 1 << 1; /// task should enter the kernel pub const IORING_SQ_TASKRUN = 1 << 2; pub const io_cqring_offsets = extern struct { head: u32, tail: u32, ring_mask: u32, ring_entries: u32, overflow: u32, cqes: u32, flags: u32, resv: u32, user_addr: u64, }; // io_cqring_offsets.flags /// disable eventfd notifications pub const IORING_CQ_EVENTFD_DISABLED = 1 << 0; // io_uring_enter flags pub const IORING_ENTER_GETEVENTS = 1 << 0; pub const IORING_ENTER_SQ_WAKEUP = 1 << 1; pub const IORING_ENTER_SQ_WAIT = 1 << 2; pub const IORING_ENTER_EXT_ARG = 1 << 3; pub const IORING_ENTER_REGISTERED_RING = 1 << 4; pub const io_uring_params = extern struct { sq_entries: u32, cq_entries: u32, flags: u32, sq_thread_cpu: u32, sq_thread_idle: u32, features: u32, wq_fd: u32, resv: [3]u32, sq_off: io_sqring_offsets, cq_off: io_cqring_offsets, }; // io_uring_params.features flags pub const IORING_FEAT_SINGLE_MMAP = 1 << 0; pub const IORING_FEAT_NODROP = 1 << 1; pub const IORING_FEAT_SUBMIT_STABLE = 1 << 2; pub const IORING_FEAT_RW_CUR_POS = 1 << 3; pub const IORING_FEAT_CUR_PERSONALITY = 1 << 4; pub const IORING_FEAT_FAST_POLL = 1 << 5; pub const IORING_FEAT_POLL_32BITS = 1 << 6; pub const IORING_FEAT_SQPOLL_NONFIXED = 1 << 7; pub const IORING_FEAT_EXT_ARG = 1 << 8; pub const IORING_FEAT_NATIVE_WORKERS = 1 << 9; pub const IORING_FEAT_RSRC_TAGS = 1 << 10; pub const IORING_FEAT_CQE_SKIP = 1 << 11; pub const IORING_FEAT_LINKED_FILE = 1 << 12; // io_uring_register opcodes and arguments pub const IORING_REGISTER = enum(u32) { REGISTER_BUFFERS, UNREGISTER_BUFFERS, REGISTER_FILES, UNREGISTER_FILES, REGISTER_EVENTFD, UNREGISTER_EVENTFD, REGISTER_FILES_UPDATE, REGISTER_EVENTFD_ASYNC, REGISTER_PROBE, REGISTER_PERSONALITY, UNREGISTER_PERSONALITY, REGISTER_RESTRICTIONS, REGISTER_ENABLE_RINGS, // extended with tagging REGISTER_FILES2, REGISTER_FILES_UPDATE2, REGISTER_BUFFERS2, REGISTER_BUFFERS_UPDATE, // set/clear io-wq thread affinities REGISTER_IOWQ_AFF, UNREGISTER_IOWQ_AFF, // set/get max number of io-wq workers REGISTER_IOWQ_MAX_WORKERS, // register/unregister io_uring fd with the ring REGISTER_RING_FDS, UNREGISTER_RING_FDS, // register ring based provide buffer group REGISTER_PBUF_RING, UNREGISTER_PBUF_RING, // sync cancelation API REGISTER_SYNC_CANCEL, // register a range of fixed file slots for automatic slot allocation REGISTER_FILE_ALLOC_RANGE, // return status information for a buffer group REGISTER_PBUF_STATUS, // set/clear busy poll settings REGISTER_NAPI, UNREGISTER_NAPI, REGISTER_CLOCK, // clone registered buffers from source ring to current ring REGISTER_CLONE_BUFFERS, // send MSG_RING without having a ring REGISTER_SEND_MSG_RING, // register a netdev hw rx queue for zerocopy REGISTER_ZCRX_IFQ, // resize CQ ring REGISTER_RESIZE_RINGS, REGISTER_MEM_REGION, // flag added to the opcode to use a registered ring fd REGISTER_USE_REGISTERED_RING = 1 << 31, _, }; /// io_uring_restriction->opcode values pub const IOWQ_CATEGORIES = enum(u8) { BOUND, UNBOUND, }; /// deprecated, see struct io_uring_rsrc_update pub const io_uring_files_update = extern struct { offset: u32, resv: u32, fds: u64, }; /// Register a fully sparse file space, rather than pass in an array of all -1 file descriptors. pub const IORING_RSRC_REGISTER_SPARSE = 1 << 0; pub const io_uring_rsrc_register = extern struct { nr: u32, flags: u32, resv2: u64, data: u64, tags: u64, }; pub const io_uring_rsrc_update = extern struct { offset: u32, resv: u32, data: u64, }; pub const io_uring_rsrc_update2 = extern struct { offset: u32, resv: u32, data: u64, tags: u64, nr: u32, resv2: u32, }; pub const io_uring_notification_slot = extern struct { tag: u64, resv: [3]u64, }; pub const io_uring_notification_register = extern struct { nr_slots: u32, resv: u32, resv2: u64, data: u64, resv3: u64, }; pub const io_uring_napi = extern struct { busy_poll_to: u32, prefer_busy_poll: u8, _pad: [3]u8, resv: u64, }; /// Skip updating fd indexes set to this value in the fd table */ pub const IORING_REGISTER_FILES_SKIP = -2; pub const IO_URING_OP_SUPPORTED = 1 << 0; pub const io_uring_probe_op = extern struct { op: IORING_OP, resv: u8, /// IO_URING_OP_* flags flags: u16, resv2: u32, pub fn is_supported(self: @This()) bool { return self.flags & IO_URING_OP_SUPPORTED != 0; } }; pub const io_uring_probe = extern struct { /// Last opcode supported last_op: IORING_OP, /// Length of ops[] array below ops_len: u8, resv: u16, resv2: [3]u32, ops: [256]io_uring_probe_op, /// Is the operation supported on the running kernel. pub fn is_supported(self: @This(), op: IORING_OP) bool { const i = @intFromEnum(op); if (i > @intFromEnum(self.last_op) or i >= self.ops_len) return false; return self.ops[i].is_supported(); } }; pub const io_uring_restriction = extern struct { opcode: IORING_RESTRICTION, arg: extern union { /// IORING_RESTRICTION_REGISTER_OP register_op: IORING_REGISTER, /// IORING_RESTRICTION_SQE_OP sqe_op: IORING_OP, /// IORING_RESTRICTION_SQE_FLAGS_* sqe_flags: u8, }, resv: u8, resv2: [3]u32, }; /// io_uring_restriction->opcode values pub const IORING_RESTRICTION = enum(u16) { /// Allow an io_uring_register(2) opcode REGISTER_OP = 0, /// Allow an sqe opcode SQE_OP = 1, /// Allow sqe flags SQE_FLAGS_ALLOWED = 2, /// Require sqe flags (these flags must be set on each submission) SQE_FLAGS_REQUIRED = 3, _, }; pub const IO_URING_SOCKET_OP = enum(u16) { SIOCIN = 0, SIOCOUTQ = 1, GETSOCKOPT = 2, SETSOCKOPT = 3, }; pub const io_uring_buf = extern struct { addr: u64, len: u32, bid: u16, resv: u16, }; pub const io_uring_buf_ring = extern struct { resv1: u64, resv2: u32, resv3: u16, tail: u16, }; /// argument for IORING_(UN)REGISTER_PBUF_RING pub const io_uring_buf_reg = extern struct { ring_addr: u64, ring_entries: u32, bgid: u16, flags: Flags, resv: [3]u64, pub const Flags = packed struct { _0: u1 = 0, /// Incremental buffer consumption. inc: bool, _: u14 = 0, }; }; pub const io_uring_getevents_arg = extern struct { sigmask: u64, sigmask_sz: u32, pad: u32, ts: u64, }; /// Argument for IORING_REGISTER_SYNC_CANCEL pub const io_uring_sync_cancel_reg = extern struct { addr: u64, fd: i32, flags: u32, timeout: kernel_timespec, pad: [4]u64, }; /// Argument for IORING_REGISTER_FILE_ALLOC_RANGE /// The range is specified as [off, off + len) pub const io_uring_file_index_range = extern struct { off: u32, len: u32, resv: u64, }; pub const io_uring_recvmsg_out = extern struct { namelen: u32, controllen: u32, payloadlen: u32, flags: u32, }; pub const utsname = extern struct { sysname: [64:0]u8, nodename: [64:0]u8, release: [64:0]u8, version: [64:0]u8, machine: [64:0]u8, domainname: [64:0]u8, }; pub const HOST_NAME_MAX = 64; pub const STATX_TYPE = 0x0001; pub const STATX_MODE = 0x0002; pub const STATX_NLINK = 0x0004; pub const STATX_UID = 0x0008; pub const STATX_GID = 0x0010; pub const STATX_ATIME = 0x0020; pub const STATX_MTIME = 0x0040; pub const STATX_CTIME = 0x0080; pub const STATX_INO = 0x0100; pub const STATX_SIZE = 0x0200; pub const STATX_BLOCKS = 0x0400; pub const STATX_BASIC_STATS = 0x07ff; pub const STATX_BTIME = 0x0800; pub const STATX_ATTR_COMPRESSED = 0x0004; pub const STATX_ATTR_IMMUTABLE = 0x0010; pub const STATX_ATTR_APPEND = 0x0020; pub const STATX_ATTR_NODUMP = 0x0040; pub const STATX_ATTR_ENCRYPTED = 0x0800; pub const STATX_ATTR_AUTOMOUNT = 0x1000; pub const statx_timestamp = extern struct { sec: i64, nsec: u32, __pad1: u32, }; /// Renamed to `Statx` to not conflict with the `statx` function. pub const Statx = extern struct { /// Mask of bits indicating filled fields mask: u32, /// Block size for filesystem I/O blksize: u32, /// Extra file attribute indicators attributes: u64, /// Number of hard links nlink: u32, /// User ID of owner uid: uid_t, /// Group ID of owner gid: gid_t, /// File type and mode mode: u16, __pad1: u16, /// Inode number ino: u64, /// Total size in bytes size: u64, /// Number of 512B blocks allocated blocks: u64, /// Mask to show what's supported in `attributes`. attributes_mask: u64, /// Last access file timestamp atime: statx_timestamp, /// Creation file timestamp btime: statx_timestamp, /// Last status change file timestamp ctime: statx_timestamp, /// Last modification file timestamp mtime: statx_timestamp, /// Major ID, if this file represents a device. rdev_major: u32, /// Minor ID, if this file represents a device. rdev_minor: u32, /// Major ID of the device containing the filesystem where this file resides. dev_major: u32, /// Minor ID of the device containing the filesystem where this file resides. dev_minor: u32, __pad2: [14]u64, }; pub const addrinfo = extern struct { flags: AI, family: i32, socktype: i32, protocol: i32, addrlen: socklen_t, addr: ?*sockaddr, canonname: ?[*:0]u8, next: ?*addrinfo, }; pub const AI = packed struct(u32) { PASSIVE: bool = false, CANONNAME: bool = false, NUMERICHOST: bool = false, V4MAPPED: bool = false, ALL: bool = false, ADDRCONFIG: bool = false, _6: u4 = 0, NUMERICSERV: bool = false, _: u21 = 0, }; pub const IPPORT_RESERVED = 1024; pub const IPPROTO = struct { pub const IP = 0; pub const HOPOPTS = 0; pub const ICMP = 1; pub const IGMP = 2; pub const IPIP = 4; pub const TCP = 6; pub const EGP = 8; pub const PUP = 12; pub const UDP = 17; pub const IDP = 22; pub const TP = 29; pub const DCCP = 33; pub const IPV6 = 41; pub const ROUTING = 43; pub const FRAGMENT = 44; pub const RSVP = 46; pub const GRE = 47; pub const ESP = 50; pub const AH = 51; pub const ICMPV6 = 58; pub const NONE = 59; pub const DSTOPTS = 60; pub const MTP = 92; pub const BEETPH = 94; pub const ENCAP = 98; pub const PIM = 103; pub const COMP = 108; pub const SCTP = 132; pub const MH = 135; pub const UDPLITE = 136; pub const MPLS = 137; pub const RAW = 255; pub const MAX = 256; }; pub const RR = struct { pub const A = 1; pub const CNAME = 5; pub const AAAA = 28; }; pub const tcp_repair_opt = extern struct { opt_code: u32, opt_val: u32, }; pub const tcp_repair_window = extern struct { snd_wl1: u32, snd_wnd: u32, max_window: u32, rcv_wnd: u32, rcv_wup: u32, }; pub const TcpRepairOption = enum { TCP_NO_QUEUE, TCP_RECV_QUEUE, TCP_SEND_QUEUE, TCP_QUEUES_NR, }; /// why fastopen failed from client perspective pub const tcp_fastopen_client_fail = enum { /// catch-all TFO_STATUS_UNSPEC, /// if not in TFO_CLIENT_NO_COOKIE mode TFO_COOKIE_UNAVAILABLE, /// SYN-ACK did not ack SYN data TFO_DATA_NOT_ACKED, /// SYN-ACK did not ack SYN data after timeout TFO_SYN_RETRANSMITTED, }; /// for TCP_INFO socket option pub const TCPI_OPT_TIMESTAMPS = 1; pub const TCPI_OPT_SACK = 2; pub const TCPI_OPT_WSCALE = 4; /// ECN was negotiated at TCP session init pub const TCPI_OPT_ECN = 8; /// we received at least one packet with ECT pub const TCPI_OPT_ECN_SEEN = 16; /// SYN-ACK acked data in SYN sent or rcvd pub const TCPI_OPT_SYN_DATA = 32; pub const nfds_t = usize; pub const pollfd = extern struct { fd: fd_t, events: i16, revents: i16, }; pub const POLL = struct { pub const IN = 0x001; pub const PRI = 0x002; pub const OUT = 0x004; pub const ERR = 0x008; pub const HUP = 0x010; pub const NVAL = 0x020; pub const RDNORM = 0x040; pub const RDBAND = 0x080; }; pub const HUGETLB_FLAG_ENCODE_SHIFT = 26; pub const HUGETLB_FLAG_ENCODE_MASK = 0x3f; pub const HUGETLB_FLAG_ENCODE_64KB = 16 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_512KB = 19 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_1MB = 20 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_2MB = 21 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_8MB = 23 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_16MB = 24 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_32MB = 25 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_256MB = 28 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_512MB = 29 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_1GB = 30 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_2GB = 31 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_16GB = 34 << HUGETLB_FLAG_ENCODE_SHIFT; pub const MFD = struct { pub const CLOEXEC = 0x0001; pub const ALLOW_SEALING = 0x0002; pub const HUGETLB = 0x0004; pub const ALL_FLAGS = CLOEXEC | ALLOW_SEALING | HUGETLB; pub const HUGE_SHIFT = HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGE_MASK = HUGETLB_FLAG_ENCODE_MASK; pub const HUGE_64KB = HUGETLB_FLAG_ENCODE_64KB; pub const HUGE_512KB = HUGETLB_FLAG_ENCODE_512KB; pub const HUGE_1MB = HUGETLB_FLAG_ENCODE_1MB; pub const HUGE_2MB = HUGETLB_FLAG_ENCODE_2MB; pub const HUGE_8MB = HUGETLB_FLAG_ENCODE_8MB; pub const HUGE_16MB = HUGETLB_FLAG_ENCODE_16MB; pub const HUGE_32MB = HUGETLB_FLAG_ENCODE_32MB; pub const HUGE_256MB = HUGETLB_FLAG_ENCODE_256MB; pub const HUGE_512MB = HUGETLB_FLAG_ENCODE_512MB; pub const HUGE_1GB = HUGETLB_FLAG_ENCODE_1GB; pub const HUGE_2GB = HUGETLB_FLAG_ENCODE_2GB; pub const HUGE_16GB = HUGETLB_FLAG_ENCODE_16GB; }; pub const rusage = extern struct { utime: timeval, stime: timeval, maxrss: isize, ixrss: isize, idrss: isize, isrss: isize, minflt: isize, majflt: isize, nswap: isize, inblock: isize, oublock: isize, msgsnd: isize, msgrcv: isize, nsignals: isize, nvcsw: isize, nivcsw: isize, __reserved: [16]isize = [1]isize{0} ** 16, pub const SELF = 0; pub const CHILDREN = -1; pub const THREAD = 1; }; pub const NCC = if (is_ppc) 10 else 8; pub const NCCS = if (is_mips) 32 else if (is_ppc) 19 else if (is_sparc) 17 else 32; pub const speed_t = if (is_ppc) enum(c_uint) { B0 = 0x0000000, B50 = 0x0000001, B75 = 0x0000002, B110 = 0x0000003, B134 = 0x0000004, B150 = 0x0000005, B200 = 0x0000006, B300 = 0x0000007, B600 = 0x0000008, B1200 = 0x0000009, B1800 = 0x000000a, B2400 = 0x000000b, B4800 = 0x000000c, B9600 = 0x000000d, B19200 = 0x000000e, B38400 = 0x000000f, B57600 = 0x00000010, B115200 = 0x00000011, B230400 = 0x00000012, B460800 = 0x00000013, B500000 = 0x00000014, B576000 = 0x00000015, B921600 = 0x00000016, B1000000 = 0x00000017, B1152000 = 0x00000018, B1500000 = 0x00000019, B2000000 = 0x0000001a, B2500000 = 0x0000001b, B3000000 = 0x0000001c, B3500000 = 0x0000001d, B4000000 = 0x0000001e, pub const EXTA = speed_t.B19200; pub const EXTB = speed_t.B38400; } else if (is_sparc) enum(c_uint) { B0 = 0x0000000, B50 = 0x0000001, B75 = 0x0000002, B110 = 0x0000003, B134 = 0x0000004, B150 = 0x0000005, B200 = 0x0000006, B300 = 0x0000007, B600 = 0x0000008, B1200 = 0x0000009, B1800 = 0x000000a, B2400 = 0x000000b, B4800 = 0x000000c, B9600 = 0x000000d, B19200 = 0x000000e, B38400 = 0x000000f, B57600 = 0x00001001, B115200 = 0x00001002, B230400 = 0x00001003, B460800 = 0x00001004, B76800 = 0x00001005, B153600 = 0x00001006, B307200 = 0x00001007, B614400 = 0x00001008, B921600 = 0x00001009, B500000 = 0x0000100a, B576000 = 0x0000100b, B1000000 = 0x0000100c, B1152000 = 0x0000100d, B1500000 = 0x0000100e, B2000000 = 0x0000100f, pub const EXTA = speed_t.B19200; pub const EXTB = speed_t.B38400; } else enum(c_uint) { B0 = 0x0000000, B50 = 0x0000001, B75 = 0x0000002, B110 = 0x0000003, B134 = 0x0000004, B150 = 0x0000005, B200 = 0x0000006, B300 = 0x0000007, B600 = 0x0000008, B1200 = 0x0000009, B1800 = 0x000000a, B2400 = 0x000000b, B4800 = 0x000000c, B9600 = 0x000000d, B19200 = 0x000000e, B38400 = 0x000000f, B57600 = 0x00001001, B115200 = 0x00001002, B230400 = 0x00001003, B460800 = 0x00001004, B500000 = 0x00001005, B576000 = 0x00001006, B921600 = 0x00001007, B1000000 = 0x00001008, B1152000 = 0x00001009, B1500000 = 0x0000100a, B2000000 = 0x0000100b, B2500000 = 0x0000100c, B3000000 = 0x0000100d, B3500000 = 0x0000100e, B4000000 = 0x0000100f, pub const EXTA = speed_t.B19200; pub const EXTB = speed_t.B38400; }; pub const tcflag_t = if (native_arch == .sparc) c_ulong else c_uint; pub const tc_iflag_t = if (is_ppc) packed struct(tcflag_t) { IGNBRK: bool = false, BRKINT: bool = false, IGNPAR: bool = false, PARMRK: bool = false, INPCK: bool = false, ISTRIP: bool = false, INLCR: bool = false, IGNCR: bool = false, ICRNL: bool = false, IXON: bool = false, IXOFF: bool = false, IXANY: bool = false, IUCLC: bool = false, IMAXBEL: bool = false, IUTF8: bool = false, _15: u17 = 0, } else packed struct(tcflag_t) { IGNBRK: bool = false, BRKINT: bool = false, IGNPAR: bool = false, PARMRK: bool = false, INPCK: bool = false, ISTRIP: bool = false, INLCR: bool = false, IGNCR: bool = false, ICRNL: bool = false, IUCLC: bool = false, IXON: bool = false, IXANY: bool = false, IXOFF: bool = false, IMAXBEL: bool = false, IUTF8: bool = false, _15: u17 = 0, }; pub const NLDLY = if (is_ppc) enum(u2) { NL0 = 0, NL1 = 1, NL2 = 2, NL3 = 3, } else enum(u1) { NL0 = 0, NL1 = 1, }; pub const CRDLY = enum(u2) { CR0 = 0, CR1 = 1, CR2 = 2, CR3 = 3, }; pub const TABDLY = enum(u2) { TAB0 = 0, TAB1 = 1, TAB2 = 2, TAB3 = 3, pub const XTABS = TABDLY.TAB3; }; pub const BSDLY = enum(u1) { BS0 = 0, BS1 = 1, }; pub const VTDLY = enum(u1) { VT0 = 0, VT1 = 1, }; pub const FFDLY = enum(u1) { FF0 = 0, FF1 = 1, }; pub const tc_oflag_t = if (is_ppc) packed struct(tcflag_t) { OPOST: bool = false, ONLCR: bool = false, OLCUC: bool = false, OCRNL: bool = false, ONOCR: bool = false, ONLRET: bool = false, OFILL: bool = false, OFDEL: bool = false, NLDLY: NLDLY = .NL0, TABDLY: TABDLY = .TAB0, CRDLY: CRDLY = .CR0, FFDLY: FFDLY = .FF0, BSDLY: BSDLY = .BS0, VTDLY: VTDLY = .VT0, _17: u15 = 0, } else if (is_sparc) packed struct(tcflag_t) { OPOST: bool = false, OLCUC: bool = false, ONLCR: bool = false, OCRNL: bool = false, ONOCR: bool = false, ONLRET: bool = false, OFILL: bool = false, OFDEL: bool = false, NLDLY: NLDLY = .NL0, CRDLY: CRDLY = .CR0, TABDLY: TABDLY = .TAB0, BSDLY: BSDLY = .BS0, VTDLY: VTDLY = .VT0, FFDLY: FFDLY = .FF0, PAGEOUT: bool = false, WRAP: bool = false, _18: u14 = 0, } else packed struct(tcflag_t) { OPOST: bool = false, OLCUC: bool = false, ONLCR: bool = false, OCRNL: bool = false, ONOCR: bool = false, ONLRET: bool = false, OFILL: bool = false, OFDEL: bool = false, NLDLY: NLDLY = .NL0, CRDLY: CRDLY = .CR0, TABDLY: TABDLY = .TAB0, BSDLY: BSDLY = .BS0, VTDLY: VTDLY = .VT0, FFDLY: FFDLY = .FF0, _16: u16 = 0, }; pub const CSIZE = enum(u2) { CS5 = 0, CS6 = 1, CS7 = 2, CS8 = 3, }; pub const tc_cflag_t = if (is_ppc) packed struct(tcflag_t) { _0: u8 = 0, CSIZE: CSIZE = .CS5, CSTOPB: bool = false, CREAD: bool = false, PARENB: bool = false, PARODD: bool = false, HUPCL: bool = false, CLOCAL: bool = false, _16: u13 = 0, ADDRB: bool = false, CMSPAR: bool = false, CRTSCTS: bool = false, } else packed struct(tcflag_t) { _0: u4 = 0, CSIZE: CSIZE = .CS5, CSTOPB: bool = false, CREAD: bool = false, PARENB: bool = false, PARODD: bool = false, HUPCL: bool = false, CLOCAL: bool = false, _12: u17 = 0, ADDRB: bool = false, CMSPAR: bool = false, CRTSCTS: bool = false, }; pub const tc_lflag_t = if (is_mips) packed struct(tcflag_t) { ISIG: bool = false, ICANON: bool = false, XCASE: bool = false, ECHO: bool = false, ECHOE: bool = false, ECHOK: bool = false, ECHONL: bool = false, NOFLSH: bool = false, IEXTEN: bool = false, ECHOCTL: bool = false, ECHOPRT: bool = false, ECHOKE: bool = false, _12: u1 = 0, FLUSHO: bool = false, PENDIN: bool = false, TOSTOP: bool = false, EXTPROC: bool = false, _17: u15 = 0, } else if (is_ppc) packed struct(tcflag_t) { ECHOKE: bool = false, ECHOE: bool = false, ECHOK: bool = false, ECHO: bool = false, ECHONL: bool = false, ECHOPRT: bool = false, ECHOCTL: bool = false, ISIG: bool = false, ICANON: bool = false, _9: u1 = 0, IEXTEN: bool = false, _11: u3 = 0, XCASE: bool = false, _15: u7 = 0, TOSTOP: bool = false, FLUSHO: bool = false, _24: u4 = 0, EXTPROC: bool = false, PENDIN: bool = false, _30: u1 = 0, NOFLSH: bool = false, } else if (is_sparc) packed struct(tcflag_t) { ISIG: bool = false, ICANON: bool = false, XCASE: bool = false, ECHO: bool = false, ECHOE: bool = false, ECHOK: bool = false, ECHONL: bool = false, NOFLSH: bool = false, TOSTOP: bool = false, ECHOCTL: bool = false, ECHOPRT: bool = false, ECHOKE: bool = false, DEFECHO: bool = false, FLUSHO: bool = false, PENDIN: bool = false, IEXTEN: bool = false, EXTPROC: bool = false, _17: u15 = 0, } else packed struct(tcflag_t) { ISIG: bool = false, ICANON: bool = false, XCASE: bool = false, ECHO: bool = false, ECHOE: bool = false, ECHOK: bool = false, ECHONL: bool = false, NOFLSH: bool = false, TOSTOP: bool = false, ECHOCTL: bool = false, ECHOPRT: bool = false, ECHOKE: bool = false, FLUSHO: bool = false, _13: u1 = 0, PENDIN: bool = false, IEXTEN: bool = false, EXTPROC: bool = false, _17: u15 = 0, }; pub const cc_t = u8; /// Indices into the `cc` array in the `termios` struct. pub const V = if (is_mips) enum(u32) { INTR = 0, QUIT = 1, ERASE = 2, KILL = 3, MIN = 4, TIME = 5, EOL2 = 6, SWTC = 7, START = 8, STOP = 9, SUSP = 10, REPRINT = 12, DISCARD = 13, WERASE = 14, LNEXT = 15, EOF = 16, EOL = 17, } else if (is_ppc) enum(u32) { INTR = 0, QUIT = 1, ERASE = 2, KILL = 3, EOF = 4, MIN = 5, EOL = 6, TIME = 7, EOL2 = 8, SWTC = 9, WERASE = 10, REPRINT = 11, SUSP = 12, START = 13, STOP = 14, LNEXT = 15, DISCARD = 16, } else enum(u32) { INTR = 0, QUIT = 1, ERASE = 2, KILL = 3, EOF = 4, TIME = 5, MIN = 6, SWTC = 7, START = 8, STOP = 9, SUSP = 10, EOL = 11, REPRINT = 12, DISCARD = 13, WERASE = 14, LNEXT = 15, EOL2 = 16, }; pub const TCSA = std.posix.TCSA; pub const sgttyb = if (is_mips or is_ppc or is_sparc) extern struct { ispeed: c_char, ospeed: c_char, erase: c_char, kill: c_char, flags: if (is_mips) c_int else c_short, } else void; pub const tchars = if (is_mips or is_ppc or is_sparc) extern struct { intrc: c_char, quitc: c_char, startc: c_char, stopc: c_char, eofc: c_char, brkc: c_char, } else void; pub const ltchars = if (is_mips or is_ppc or is_sparc) extern struct { suspc: c_char, dsuspc: c_char, rprntc: c_char, flushc: c_char, werasc: c_char, lnextc: c_char, } else void; pub const termio = extern struct { iflag: c_ushort, oflag: c_ushort, cflag: c_ushort, lflag: c_ushort, line: if (is_mips) c_char else u8, cc: [if (is_mips) NCCS else NCC]u8, }; pub const termios = if (is_mips or is_sparc) extern struct { iflag: tc_iflag_t, oflag: tc_oflag_t, cflag: tc_cflag_t, lflag: tc_lflag_t, line: cc_t, cc: [NCCS]cc_t, } else if (is_ppc) extern struct { iflag: tc_iflag_t, oflag: tc_oflag_t, cflag: tc_cflag_t, lflag: tc_lflag_t, cc: [NCCS]cc_t, line: cc_t, ispeed: speed_t, ospeed: speed_t, } else extern struct { iflag: tc_iflag_t, oflag: tc_oflag_t, cflag: tc_cflag_t, lflag: tc_lflag_t, line: cc_t, cc: [NCCS]cc_t, ispeed: speed_t, ospeed: speed_t, }; pub const termios2 = if (is_mips) extern struct { iflag: tc_iflag_t, oflag: tc_oflag_t, cflag: tc_cflag_t, lflag: tc_lflag_t, cc: [NCCS]cc_t, line: cc_t, ispeed: speed_t, ospeed: speed_t, } else extern struct { iflag: tc_iflag_t, oflag: tc_oflag_t, cflag: tc_cflag_t, lflag: tc_lflag_t, line: cc_t, cc: [NCCS + if (is_sparc) 2 else 0]cc_t, ispeed: speed_t, ospeed: speed_t, }; /// Linux-specific socket ioctls pub const SIOCINQ = T.FIONREAD; /// Linux-specific socket ioctls /// output queue size (not sent + not acked) pub const SIOCOUTQ = T.IOCOUTQ; pub const SOCK_IOC_TYPE = 0x89; pub const SIOCGSTAMP_NEW = IOCTL.IOR(SOCK_IOC_TYPE, 0x06, i64[2]); pub const SIOCGSTAMP_OLD = IOCTL.IOR('s', 100, timeval); /// Get stamp (timeval) pub const SIOCGSTAMP = if (native_arch == .x86_64 or @sizeOf(timeval) == 8) SIOCGSTAMP_OLD else SIOCGSTAMP_NEW; pub const SIOCGSTAMPNS_NEW = IOCTL.IOR(SOCK_IOC_TYPE, 0x07, i64[2]); pub const SIOCGSTAMPNS_OLD = IOCTL.IOR('s', 101, kernel_timespec); /// Get stamp (timespec) pub const SIOCGSTAMPNS = if (native_arch == .x86_64 or @sizeOf(timespec) == 8) SIOCGSTAMPNS_OLD else SIOCGSTAMPNS_NEW; // Routing table calls. /// Add routing table entry pub const SIOCADDRT = 0x890B; /// Delete routing table entry pub const SIOCDELRT = 0x890C; /// Unused pub const SIOCRTMSG = 0x890D; // Socket configuration controls. /// Get iface name pub const SIOCGIFNAME = 0x8910; /// Set iface channel pub const SIOCSIFLINK = 0x8911; /// Get iface list pub const SIOCGIFCONF = 0x8912; /// Get flags pub const SIOCGIFFLAGS = 0x8913; /// Set flags pub const SIOCSIFFLAGS = 0x8914; /// Get PA address pub const SIOCGIFADDR = 0x8915; /// Set PA address pub const SIOCSIFADDR = 0x8916; /// Get remote PA address pub const SIOCGIFDSTADDR = 0x8917; /// Set remote PA address pub const SIOCSIFDSTADDR = 0x8918; /// Get broadcast PA address pub const SIOCGIFBRDADDR = 0x8919; /// Set broadcast PA address pub const SIOCSIFBRDADDR = 0x891a; /// Get network PA mask pub const SIOCGIFNETMASK = 0x891b; /// Set network PA mask pub const SIOCSIFNETMASK = 0x891c; /// Get metric pub const SIOCGIFMETRIC = 0x891d; /// Set metric pub const SIOCSIFMETRIC = 0x891e; /// Get memory address (BSD) pub const SIOCGIFMEM = 0x891f; /// Set memory address (BSD) pub const SIOCSIFMEM = 0x8920; /// Get MTU size pub const SIOCGIFMTU = 0x8921; /// Set MTU size pub const SIOCSIFMTU = 0x8922; /// Set interface name pub const SIOCSIFNAME = 0x8923; /// Set hardware address pub const SIOCSIFHWADDR = 0x8924; /// Get encapsulations pub const SIOCGIFENCAP = 0x8925; /// Set encapsulations pub const SIOCSIFENCAP = 0x8926; /// Get hardware address pub const SIOCGIFHWADDR = 0x8927; /// Driver slaving support pub const SIOCGIFSLAVE = 0x8929; /// Driver slaving support pub const SIOCSIFSLAVE = 0x8930; /// Add to Multicast address lists pub const SIOCADDMULTI = 0x8931; /// Delete from Multicast address lists pub const SIOCDELMULTI = 0x8932; /// name -> if_index mapping pub const SIOCGIFINDEX = 0x8933; /// Set extended flags set pub const SIOCSIFPFLAGS = 0x8934; /// Get extended flags set pub const SIOCGIFPFLAGS = 0x8935; /// Delete PA address pub const SIOCDIFADDR = 0x8936; /// Set hardware broadcast addr pub const SIOCSIFHWBROADCAST = 0x8937; /// Get number of devices pub const SIOCGIFCOUNT = 0x8938; /// Bridging support pub const SIOCGIFBR = 0x8940; /// Set bridging options pub const SIOCSIFBR = 0x8941; /// Get the tx queue length pub const SIOCGIFTXQLEN = 0x8942; /// Set the tx queue length pub const SIOCSIFTXQLEN = 0x8943; /// Ethtool interface pub const SIOCETHTOOL = 0x8946; /// Get address of MII PHY in use. pub const SIOCGMIIPHY = 0x8947; /// Read MII PHY register. pub const SIOCGMIIREG = 0x8948; /// Write MII PHY register. pub const SIOCSMIIREG = 0x8949; /// Get / Set netdev parameters pub const SIOCWANDEV = 0x894A; /// Output queue size (not sent only) pub const SIOCOUTQNSD = 0x894B; /// Get socket network namespace pub const SIOCGSKNS = 0x894C; // ARP cache control calls. // 0x8950 - 0x8952 obsolete calls. /// Delete ARP table entry pub const SIOCDARP = 0x8953; /// Get ARP table entry pub const SIOCGARP = 0x8954; /// Set ARP table entry pub const SIOCSARP = 0x8955; // RARP cache control calls. /// Delete RARP table entry pub const SIOCDRARP = 0x8960; /// Get RARP table entry pub const SIOCGRARP = 0x8961; /// Set RARP table entry pub const SIOCSRARP = 0x8962; // Driver configuration calls /// Get device parameters pub const SIOCGIFMAP = 0x8970; /// Set device parameters pub const SIOCSIFMAP = 0x8971; // DLCI configuration calls /// Create new DLCI device pub const SIOCADDDLCI = 0x8980; /// Delete DLCI device pub const SIOCDELDLCI = 0x8981; /// 802.1Q VLAN support pub const SIOCGIFVLAN = 0x8982; /// Set 802.1Q VLAN options pub const SIOCSIFVLAN = 0x8983; // bonding calls /// Enslave a device to the bond pub const SIOCBONDENSLAVE = 0x8990; /// Release a slave from the bond pub const SIOCBONDRELEASE = 0x8991; /// Set the hw addr of the bond pub const SIOCBONDSETHWADDR = 0x8992; /// rtn info about slave state pub const SIOCBONDSLAVEINFOQUERY = 0x8993; /// rtn info about bond state pub const SIOCBONDINFOQUERY = 0x8994; /// Update to a new active slave pub const SIOCBONDCHANGEACTIVE = 0x8995; // Bridge calls /// Create new bridge device pub const SIOCBRADDBR = 0x89a0; /// Remove bridge device pub const SIOCBRDELBR = 0x89a1; /// Add interface to bridge pub const SIOCBRADDIF = 0x89a2; /// Remove interface from bridge pub const SIOCBRDELIF = 0x89a3; /// Get hardware time stamp config pub const SIOCSHWTSTAMP = 0x89b0; /// Set hardware time stamp config pub const SIOCGHWTSTAMP = 0x89b1; /// Device private ioctl calls pub const SIOCDEVPRIVATE = 0x89F0; /// These 16 ioctl calls are protocol private pub const SIOCPROTOPRIVATE = 0x89E0; pub const IFNAMESIZE = 16; pub const IFF = packed struct(u16) { UP: bool = false, BROADCAST: bool = false, DEBUG: bool = false, LOOPBACK: bool = false, POINTOPOINT: bool = false, NOTRAILERS: bool = false, RUNNING: bool = false, NOARP: bool = false, PROMISC: bool = false, _9: u7 = 0, }; pub const ifmap = extern struct { mem_start: usize, mem_end: usize, base_addr: u16, irq: u8, dma: u8, port: u8, }; pub const ifreq = extern struct { ifrn: extern union { name: [IFNAMESIZE]u8, }, ifru: extern union { addr: sockaddr, dstaddr: sockaddr, broadaddr: sockaddr, netmask: sockaddr, hwaddr: sockaddr, flags: IFF, ivalue: i32, mtu: i32, map: ifmap, slave: [IFNAMESIZE - 1:0]u8, newname: [IFNAMESIZE - 1:0]u8, data: ?[*]u8, }, }; pub const PACKET = struct { pub const HOST = 0; pub const BROADCAST = 1; pub const MULTICAST = 2; pub const OTHERHOST = 3; pub const OUTGOING = 4; pub const LOOPBACK = 5; pub const USER = 6; pub const KERNEL = 7; pub const ADD_MEMBERSHIP = 1; pub const DROP_MEMBERSHIP = 2; pub const RECV_OUTPUT = 3; pub const RX_RING = 5; pub const STATISTICS = 6; pub const COPY_THRESH = 7; pub const AUXDATA = 8; pub const ORIGDEV = 9; pub const VERSION = 10; pub const HDRLEN = 11; pub const RESERVE = 12; pub const TX_RING = 13; pub const LOSS = 14; pub const VNET_HDR = 15; pub const TX_TIMESTAMP = 16; pub const TIMESTAMP = 17; pub const FANOUT = 18; pub const TX_HAS_OFF = 19; pub const QDISC_BYPASS = 20; pub const ROLLOVER_STATS = 21; pub const FANOUT_DATA = 22; pub const IGNORE_OUTGOING = 23; pub const VNET_HDR_SZ = 24; pub const FANOUT_HASH = 0; pub const FANOUT_LB = 1; pub const FANOUT_CPU = 2; pub const FANOUT_ROLLOVER = 3; pub const FANOUT_RND = 4; pub const FANOUT_QM = 5; pub const FANOUT_CBPF = 6; pub const FANOUT_EBPF = 7; pub const FANOUT_FLAG_ROLLOVER = 0x1000; pub const FANOUT_FLAG_UNIQUEID = 0x2000; pub const FANOUT_FLAG_IGNORE_OUTGOING = 0x4000; pub const FANOUT_FLAG_DEFRAG = 0x8000; }; pub const tpacket_versions = enum(u32) { V1 = 0, V2 = 1, V3 = 2, }; pub const tpacket_req3 = extern struct { block_size: c_uint, // Minimal size of contiguous block block_nr: c_uint, // Number of blocks frame_size: c_uint, // Size of frame frame_nr: c_uint, // Total number of frames retire_blk_tov: c_uint, // Timeout in msecs sizeof_priv: c_uint, // Offset to private data area feature_req_word: c_uint, }; pub const tpacket_bd_ts = extern struct { sec: c_uint, frac: extern union { usec: c_uint, nsec: c_uint, }, }; pub const TP_STATUS = extern union { rx: packed struct(u32) { USER: bool, COPY: bool, LOSING: bool, CSUMNOTREADY: bool, VLAN_VALID: bool, BLK_TMO: bool, VLAN_TPID_VALID: bool, CSUM_VALID: bool, GSO_TCP: bool, _: u20, TS_SOFTWARE: bool, TS_SYS_HARDWARE: bool, TS_RAW_HARDWARE: bool, }, tx: packed struct(u32) { SEND_REQUEST: bool, SENDING: bool, WRONG_FORMAT: bool, _: u26, TS_SOFTWARE: bool, TS_SYS_HARDWARE: bool, TS_RAW_HARDWARE: bool, }, }; pub const tpacket_hdr_v1 = extern struct { block_status: TP_STATUS, num_pkts: u32, offset_to_first_pkt: u32, blk_len: u32, seq_num: u64 align(8), ts_first_pkt: tpacket_bd_ts, ts_last_pkt: tpacket_bd_ts, }; pub const tpacket_bd_header_u = extern union { bh1: tpacket_hdr_v1, }; pub const tpacket_block_desc = extern struct { version: u32, offset_to_priv: u32, hdr: tpacket_bd_header_u, }; pub const tpacket_hdr_variant1 = extern struct { rxhash: u32, vlan_tci: u32, vlan_tpid: u16, padding: u16, }; pub const tpacket3_hdr = extern struct { next_offset: u32, sec: u32, nsec: u32, snaplen: u32, len: u32, status: u32, mac: u16, net: u16, variant: extern union { hv1: tpacket_hdr_variant1, }, padding: [8]u8, }; pub const tpacket_stats_v3 = extern struct { packets: c_uint, drops: c_uint, freeze_q_cnt: c_uint, }; // doc comments copied from musl pub const rlimit_resource = if (native_arch.isMIPS()) enum(c_int) { /// Per-process CPU limit, in seconds. CPU = 0, /// Largest file that can be created, in bytes. FSIZE = 1, /// Maximum size of data segment, in bytes. DATA = 2, /// Maximum size of stack segment, in bytes. STACK = 3, /// Largest core file that can be created, in bytes. CORE = 4, /// Number of open files. NOFILE = 5, /// Address space limit. AS = 6, /// Largest resident set size, in bytes. /// This affects swapping; processes that are exceeding their /// resident set size will be more likely to have physical memory /// taken from them. RSS = 7, /// Number of processes. NPROC = 8, /// Locked-in-memory address space. MEMLOCK = 9, /// Maximum number of file locks. LOCKS = 10, /// Maximum number of pending signals. SIGPENDING = 11, /// Maximum bytes in POSIX message queues. MSGQUEUE = 12, /// Maximum nice priority allowed to raise to. /// Nice levels 19 .. -20 correspond to 0 .. 39 /// values of this resource limit. NICE = 13, /// Maximum realtime priority allowed for non-privileged /// processes. RTPRIO = 14, /// Maximum CPU time in µs that a process scheduled under a real-time /// scheduling policy may consume without making a blocking system /// call before being forcibly descheduled. RTTIME = 15, _, } else if (native_arch.isSPARC()) enum(c_int) { /// Per-process CPU limit, in seconds. CPU = 0, /// Largest file that can be created, in bytes. FSIZE = 1, /// Maximum size of data segment, in bytes. DATA = 2, /// Maximum size of stack segment, in bytes. STACK = 3, /// Largest core file that can be created, in bytes. CORE = 4, /// Largest resident set size, in bytes. /// This affects swapping; processes that are exceeding their /// resident set size will be more likely to have physical memory /// taken from them. RSS = 5, /// Number of open files. NOFILE = 6, /// Number of processes. NPROC = 7, /// Locked-in-memory address space. MEMLOCK = 8, /// Address space limit. AS = 9, /// Maximum number of file locks. LOCKS = 10, /// Maximum number of pending signals. SIGPENDING = 11, /// Maximum bytes in POSIX message queues. MSGQUEUE = 12, /// Maximum nice priority allowed to raise to. /// Nice levels 19 .. -20 correspond to 0 .. 39 /// values of this resource limit. NICE = 13, /// Maximum realtime priority allowed for non-privileged /// processes. RTPRIO = 14, /// Maximum CPU time in µs that a process scheduled under a real-time /// scheduling policy may consume without making a blocking system /// call before being forcibly descheduled. RTTIME = 15, _, } else enum(c_int) { /// Per-process CPU limit, in seconds. CPU = 0, /// Largest file that can be created, in bytes. FSIZE = 1, /// Maximum size of data segment, in bytes. DATA = 2, /// Maximum size of stack segment, in bytes. STACK = 3, /// Largest core file that can be created, in bytes. CORE = 4, /// Largest resident set size, in bytes. /// This affects swapping; processes that are exceeding their /// resident set size will be more likely to have physical memory /// taken from them. RSS = 5, /// Number of processes. NPROC = 6, /// Number of open files. NOFILE = 7, /// Locked-in-memory address space. MEMLOCK = 8, /// Address space limit. AS = 9, /// Maximum number of file locks. LOCKS = 10, /// Maximum number of pending signals. SIGPENDING = 11, /// Maximum bytes in POSIX message queues. MSGQUEUE = 12, /// Maximum nice priority allowed to raise to. /// Nice levels 19 .. -20 correspond to 0 .. 39 /// values of this resource limit. NICE = 13, /// Maximum realtime priority allowed for non-privileged /// processes. RTPRIO = 14, /// Maximum CPU time in µs that a process scheduled under a real-time /// scheduling policy may consume without making a blocking system /// call before being forcibly descheduled. RTTIME = 15, _, }; pub const rlim_t = u64; pub const RLIM = struct { /// No limit pub const INFINITY = ~@as(rlim_t, 0); pub const SAVED_MAX = INFINITY; pub const SAVED_CUR = INFINITY; }; pub const rlimit = extern struct { /// Soft limit cur: rlim_t, /// Hard limit max: rlim_t, }; pub const MADV = struct { pub const NORMAL = 0; pub const RANDOM = 1; pub const SEQUENTIAL = 2; pub const WILLNEED = 3; pub const DONTNEED = 4; pub const FREE = 8; pub const REMOVE = 9; pub const DONTFORK = 10; pub const DOFORK = 11; pub const MERGEABLE = 12; pub const UNMERGEABLE = 13; pub const HUGEPAGE = 14; pub const NOHUGEPAGE = 15; pub const DONTDUMP = 16; pub const DODUMP = 17; pub const WIPEONFORK = 18; pub const KEEPONFORK = 19; pub const COLD = 20; pub const PAGEOUT = 21; pub const HWPOISON = 100; pub const SOFT_OFFLINE = 101; }; pub const POSIX_FADV = switch (native_arch) { .s390x => if (@typeInfo(usize).int.bits == 64) struct { pub const NORMAL = 0; pub const RANDOM = 1; pub const SEQUENTIAL = 2; pub const WILLNEED = 3; pub const DONTNEED = 6; pub const NOREUSE = 7; } else struct { pub const NORMAL = 0; pub const RANDOM = 1; pub const SEQUENTIAL = 2; pub const WILLNEED = 3; pub const DONTNEED = 4; pub const NOREUSE = 5; }, else => struct { pub const NORMAL = 0; pub const RANDOM = 1; pub const SEQUENTIAL = 2; pub const WILLNEED = 3; pub const DONTNEED = 4; pub const NOREUSE = 5; }, }; pub const timeval = extern struct { sec: isize, usec: i64, }; pub const timezone = extern struct { minuteswest: i32, dsttime: i32, }; /// The timespec struct used by the kernel. pub const kernel_timespec = extern struct { sec: i64, nsec: i64, }; // https://github.com/ziglang/zig/issues/4726#issuecomment-2190337877 pub const timespec = if (native_arch == .hexagon or native_arch == .riscv32) kernel_timespec else extern struct { sec: isize, nsec: isize, }; pub const XDP = struct { pub const SHARED_UMEM = (1 << 0); pub const COPY = (1 << 1); pub const ZEROCOPY = (1 << 2); pub const UMEM_UNALIGNED_CHUNK_FLAG = (1 << 0); pub const USE_NEED_WAKEUP = (1 << 3); pub const MMAP_OFFSETS = 1; pub const RX_RING = 2; pub const TX_RING = 3; pub const UMEM_REG = 4; pub const UMEM_FILL_RING = 5; pub const UMEM_COMPLETION_RING = 6; pub const STATISTICS = 7; pub const OPTIONS = 8; pub const OPTIONS_ZEROCOPY = (1 << 0); pub const PGOFF_RX_RING = 0; pub const PGOFF_TX_RING = 0x80000000; pub const UMEM_PGOFF_FILL_RING = 0x100000000; pub const UMEM_PGOFF_COMPLETION_RING = 0x180000000; }; pub const xdp_ring_offset = extern struct { producer: u64, consumer: u64, desc: u64, flags: u64, }; pub const xdp_mmap_offsets = extern struct { rx: xdp_ring_offset, tx: xdp_ring_offset, fr: xdp_ring_offset, cr: xdp_ring_offset, }; pub const xdp_umem_reg = extern struct { addr: u64, len: u64, chunk_size: u32, headroom: u32, flags: u32, }; pub const xdp_statistics = extern struct { rx_dropped: u64, rx_invalid_descs: u64, tx_invalid_descs: u64, rx_ring_full: u64, rx_fill_ring_empty_descs: u64, tx_ring_empty_descs: u64, }; pub const xdp_options = extern struct { flags: u32, }; pub const XSK_UNALIGNED_BUF_OFFSET_SHIFT = 48; pub const XSK_UNALIGNED_BUF_ADDR_MASK = (1 << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1; pub const xdp_desc = extern struct { addr: u64, len: u32, options: u32, }; fn issecure_mask(comptime x: comptime_int) comptime_int { return 1 << x; } pub const SECUREBITS_DEFAULT = 0x00000000; pub const SECURE_NOROOT = 0; pub const SECURE_NOROOT_LOCKED = 1; pub const SECBIT_NOROOT = issecure_mask(SECURE_NOROOT); pub const SECBIT_NOROOT_LOCKED = issecure_mask(SECURE_NOROOT_LOCKED); pub const SECURE_NO_SETUID_FIXUP = 2; pub const SECURE_NO_SETUID_FIXUP_LOCKED = 3; pub const SECBIT_NO_SETUID_FIXUP = issecure_mask(SECURE_NO_SETUID_FIXUP); pub const SECBIT_NO_SETUID_FIXUP_LOCKED = issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED); pub const SECURE_KEEP_CAPS = 4; pub const SECURE_KEEP_CAPS_LOCKED = 5; pub const SECBIT_KEEP_CAPS = issecure_mask(SECURE_KEEP_CAPS); pub const SECBIT_KEEP_CAPS_LOCKED = issecure_mask(SECURE_KEEP_CAPS_LOCKED); pub const SECURE_NO_CAP_AMBIENT_RAISE = 6; pub const SECURE_NO_CAP_AMBIENT_RAISE_LOCKED = 7; pub const SECBIT_NO_CAP_AMBIENT_RAISE = issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE); pub const SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED = issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE_LOCKED); pub const SECURE_ALL_BITS = issecure_mask(SECURE_NOROOT) | issecure_mask(SECURE_NO_SETUID_FIXUP) | issecure_mask(SECURE_KEEP_CAPS) | issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE); pub const SECURE_ALL_LOCKS = SECURE_ALL_BITS << 1; pub const PR = enum(i32) { SET_PDEATHSIG = 1, GET_PDEATHSIG = 2, GET_DUMPABLE = 3, SET_DUMPABLE = 4, GET_UNALIGN = 5, SET_UNALIGN = 6, GET_KEEPCAPS = 7, SET_KEEPCAPS = 8, GET_FPEMU = 9, SET_FPEMU = 10, GET_FPEXC = 11, SET_FPEXC = 12, GET_TIMING = 13, SET_TIMING = 14, SET_NAME = 15, GET_NAME = 16, GET_ENDIAN = 19, SET_ENDIAN = 20, GET_SECCOMP = 21, SET_SECCOMP = 22, CAPBSET_READ = 23, CAPBSET_DROP = 24, GET_TSC = 25, SET_TSC = 26, GET_SECUREBITS = 27, SET_SECUREBITS = 28, SET_TIMERSLACK = 29, GET_TIMERSLACK = 30, TASK_PERF_EVENTS_DISABLE = 31, TASK_PERF_EVENTS_ENABLE = 32, MCE_KILL = 33, MCE_KILL_GET = 34, SET_MM = 35, SET_PTRACER = 0x59616d61, SET_CHILD_SUBREAPER = 36, GET_CHILD_SUBREAPER = 37, SET_NO_NEW_PRIVS = 38, GET_NO_NEW_PRIVS = 39, GET_TID_ADDRESS = 40, SET_THP_DISABLE = 41, GET_THP_DISABLE = 42, MPX_ENABLE_MANAGEMENT = 43, MPX_DISABLE_MANAGEMENT = 44, SET_FP_MODE = 45, GET_FP_MODE = 46, CAP_AMBIENT = 47, SVE_SET_VL = 50, SVE_GET_VL = 51, GET_SPECULATION_CTRL = 52, SET_SPECULATION_CTRL = 53, _, pub const UNALIGN_NOPRINT = 1; pub const UNALIGN_SIGBUS = 2; pub const FPEMU_NOPRINT = 1; pub const FPEMU_SIGFPE = 2; pub const FP_EXC_SW_ENABLE = 0x80; pub const FP_EXC_DIV = 0x010000; pub const FP_EXC_OVF = 0x020000; pub const FP_EXC_UND = 0x040000; pub const FP_EXC_RES = 0x080000; pub const FP_EXC_INV = 0x100000; pub const FP_EXC_DISABLED = 0; pub const FP_EXC_NONRECOV = 1; pub const FP_EXC_ASYNC = 2; pub const FP_EXC_PRECISE = 3; pub const TIMING_STATISTICAL = 0; pub const TIMING_TIMESTAMP = 1; pub const ENDIAN_BIG = 0; pub const ENDIAN_LITTLE = 1; pub const ENDIAN_PPC_LITTLE = 2; pub const TSC_ENABLE = 1; pub const TSC_SIGSEGV = 2; pub const MCE_KILL_CLEAR = 0; pub const MCE_KILL_SET = 1; pub const MCE_KILL_LATE = 0; pub const MCE_KILL_EARLY = 1; pub const MCE_KILL_DEFAULT = 2; pub const SET_MM_START_CODE = 1; pub const SET_MM_END_CODE = 2; pub const SET_MM_START_DATA = 3; pub const SET_MM_END_DATA = 4; pub const SET_MM_START_STACK = 5; pub const SET_MM_START_BRK = 6; pub const SET_MM_BRK = 7; pub const SET_MM_ARG_START = 8; pub const SET_MM_ARG_END = 9; pub const SET_MM_ENV_START = 10; pub const SET_MM_ENV_END = 11; pub const SET_MM_AUXV = 12; pub const SET_MM_EXE_FILE = 13; pub const SET_MM_MAP = 14; pub const SET_MM_MAP_SIZE = 15; pub const SET_PTRACER_ANY = maxInt(c_ulong); pub const FP_MODE_FR = 1 << 0; pub const FP_MODE_FRE = 1 << 1; pub const CAP_AMBIENT_IS_SET = 1; pub const CAP_AMBIENT_RAISE = 2; pub const CAP_AMBIENT_LOWER = 3; pub const CAP_AMBIENT_CLEAR_ALL = 4; pub const SVE_SET_VL_ONEXEC = 1 << 18; pub const SVE_VL_LEN_MASK = 0xffff; pub const SVE_VL_INHERIT = 1 << 17; pub const SPEC_STORE_BYPASS = 0; pub const SPEC_NOT_AFFECTED = 0; pub const SPEC_PRCTL = 1 << 0; pub const SPEC_ENABLE = 1 << 1; pub const SPEC_DISABLE = 1 << 2; pub const SPEC_FORCE_DISABLE = 1 << 3; }; pub const prctl_mm_map = extern struct { start_code: u64, end_code: u64, start_data: u64, end_data: u64, start_brk: u64, brk: u64, start_stack: u64, arg_start: u64, arg_end: u64, env_start: u64, env_end: u64, auxv: *u64, auxv_size: u32, exe_fd: u32, }; pub const NETLINK = struct { /// Routing/device hook pub const ROUTE = 0; /// Unused number pub const UNUSED = 1; /// Reserved for user mode socket protocols pub const USERSOCK = 2; /// Unused number, formerly ip_queue pub const FIREWALL = 3; /// socket monitoring pub const SOCK_DIAG = 4; /// netfilter/iptables ULOG pub const NFLOG = 5; /// ipsec pub const XFRM = 6; /// SELinux event notifications pub const SELINUX = 7; /// Open-iSCSI pub const ISCSI = 8; /// auditing pub const AUDIT = 9; pub const FIB_LOOKUP = 10; pub const CONNECTOR = 11; /// netfilter subsystem pub const NETFILTER = 12; pub const IP6_FW = 13; /// DECnet routing messages pub const DNRTMSG = 14; /// Kernel messages to userspace pub const KOBJECT_UEVENT = 15; pub const GENERIC = 16; // leave room for NETLINK_DM (DM Events) /// SCSI Transports pub const SCSITRANSPORT = 18; pub const ECRYPTFS = 19; pub const RDMA = 20; /// Crypto layer pub const CRYPTO = 21; /// SMC monitoring pub const SMC = 22; }; // Flags values /// It is request message. pub const NLM_F_REQUEST = 0x01; /// Multipart message, terminated by NLMSG_DONE pub const NLM_F_MULTI = 0x02; /// Reply with ack, with zero or error code pub const NLM_F_ACK = 0x04; /// Echo this request pub const NLM_F_ECHO = 0x08; /// Dump was inconsistent due to sequence change pub const NLM_F_DUMP_INTR = 0x10; /// Dump was filtered as requested pub const NLM_F_DUMP_FILTERED = 0x20; // Modifiers to GET request /// specify tree root pub const NLM_F_ROOT = 0x100; /// return all matching pub const NLM_F_MATCH = 0x200; /// atomic GET pub const NLM_F_ATOMIC = 0x400; pub const NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH; // Modifiers to NEW request /// Override existing pub const NLM_F_REPLACE = 0x100; /// Do not touch, if it exists pub const NLM_F_EXCL = 0x200; /// Create, if it does not exist pub const NLM_F_CREATE = 0x400; /// Add to end of list pub const NLM_F_APPEND = 0x800; // Modifiers to DELETE request /// Do not delete recursively pub const NLM_F_NONREC = 0x100; // Flags for ACK message /// request was capped pub const NLM_F_CAPPED = 0x100; /// extended ACK TVLs were included pub const NLM_F_ACK_TLVS = 0x200; pub const NetlinkMessageType = enum(u16) { /// < 0x10: reserved control messages pub const MIN_TYPE = 0x10; /// Nothing. NOOP = 0x1, /// Error ERROR = 0x2, /// End of a dump DONE = 0x3, /// Data lost OVERRUN = 0x4, // rtlink types RTM_NEWLINK = 16, RTM_DELLINK, RTM_GETLINK, RTM_SETLINK, RTM_NEWADDR = 20, RTM_DELADDR, RTM_GETADDR, RTM_NEWROUTE = 24, RTM_DELROUTE, RTM_GETROUTE, RTM_NEWNEIGH = 28, RTM_DELNEIGH, RTM_GETNEIGH, RTM_NEWRULE = 32, RTM_DELRULE, RTM_GETRULE, RTM_NEWQDISC = 36, RTM_DELQDISC, RTM_GETQDISC, RTM_NEWTCLASS = 40, RTM_DELTCLASS, RTM_GETTCLASS, RTM_NEWTFILTER = 44, RTM_DELTFILTER, RTM_GETTFILTER, RTM_NEWACTION = 48, RTM_DELACTION, RTM_GETACTION, RTM_NEWPREFIX = 52, RTM_GETMULTICAST = 58, RTM_GETANYCAST = 62, RTM_NEWNEIGHTBL = 64, RTM_GETNEIGHTBL = 66, RTM_SETNEIGHTBL, RTM_NEWNDUSEROPT = 68, RTM_NEWADDRLABEL = 72, RTM_DELADDRLABEL, RTM_GETADDRLABEL, RTM_GETDCB = 78, RTM_SETDCB, RTM_NEWNETCONF = 80, RTM_DELNETCONF, RTM_GETNETCONF = 82, RTM_NEWMDB = 84, RTM_DELMDB = 85, RTM_GETMDB = 86, RTM_NEWNSID = 88, RTM_DELNSID = 89, RTM_GETNSID = 90, RTM_NEWSTATS = 92, RTM_GETSTATS = 94, RTM_NEWCACHEREPORT = 96, RTM_NEWCHAIN = 100, RTM_DELCHAIN, RTM_GETCHAIN, RTM_NEWNEXTHOP = 104, RTM_DELNEXTHOP, RTM_GETNEXTHOP, _, }; /// Netlink message header /// Specified in RFC 3549 Section 2.3.2 pub const nlmsghdr = extern struct { /// Length of message including header len: u32, /// Message content type: NetlinkMessageType, /// Additional flags flags: u16, /// Sequence number seq: u32, /// Sending process port ID pid: u32, }; pub const ifinfomsg = extern struct { family: u8, __pad1: u8 = 0, /// ARPHRD_* type: c_ushort, /// Link index index: c_int, /// IFF_* flags flags: c_uint, /// IFF_* change mask change: c_uint, }; pub const rtattr = extern struct { /// Length of option len: c_ushort, /// Type of option type: extern union { /// IFLA_* from linux/if_link.h link: IFLA, /// IFA_* from linux/if_addr.h addr: IFA, }, pub const ALIGNTO = 4; }; pub const IFA = enum(c_ushort) { UNSPEC, ADDRESS, LOCAL, LABEL, BROADCAST, ANYCAST, CACHEINFO, MULTICAST, FLAGS, RT_PRIORITY, TARGET_NETNSID, PROTO, _, }; pub const IFLA = enum(c_ushort) { UNSPEC, ADDRESS, BROADCAST, IFNAME, MTU, LINK, QDISC, STATS, COST, PRIORITY, MASTER, /// Wireless Extension event WIRELESS, /// Protocol specific information for a link PROTINFO, TXQLEN, MAP, WEIGHT, OPERSTATE, LINKMODE, LINKINFO, NET_NS_PID, IFALIAS, /// Number of VFs if device is SR-IOV PF NUM_VF, VFINFO_LIST, STATS64, VF_PORTS, PORT_SELF, AF_SPEC, /// Group the device belongs to GROUP, NET_NS_FD, /// Extended info mask, VFs, etc EXT_MASK, /// Promiscuity count: > 0 means acts PROMISC PROMISCUITY, NUM_TX_QUEUES, NUM_RX_QUEUES, CARRIER, PHYS_PORT_ID, CARRIER_CHANGES, PHYS_SWITCH_ID, LINK_NETNSID, PHYS_PORT_NAME, PROTO_DOWN, GSO_MAX_SEGS, GSO_MAX_SIZE, PAD, XDP, EVENT, NEW_NETNSID, IF_NETNSID, CARRIER_UP_COUNT, CARRIER_DOWN_COUNT, NEW_IFINDEX, MIN_MTU, MAX_MTU, _, pub const TARGET_NETNSID: IFLA = .IF_NETNSID; }; pub const rtnl_link_ifmap = extern struct { mem_start: u64, mem_end: u64, base_addr: u64, irq: u16, dma: u8, port: u8, }; pub const rtnl_link_stats = extern struct { /// total packets received rx_packets: u32, /// total packets transmitted tx_packets: u32, /// total bytes received rx_bytes: u32, /// total bytes transmitted tx_bytes: u32, /// bad packets received rx_errors: u32, /// packet transmit problems tx_errors: u32, /// no space in linux buffers rx_dropped: u32, /// no space available in linux tx_dropped: u32, /// multicast packets received multicast: u32, collisions: u32, // detailed rx_errors rx_length_errors: u32, /// receiver ring buff overflow rx_over_errors: u32, /// recved pkt with crc error rx_crc_errors: u32, /// recv'd frame alignment error rx_frame_errors: u32, /// recv'r fifo overrun rx_fifo_errors: u32, /// receiver missed packet rx_missed_errors: u32, // detailed tx_errors tx_aborted_errors: u32, tx_carrier_errors: u32, tx_fifo_errors: u32, tx_heartbeat_errors: u32, tx_window_errors: u32, // for cslip etc rx_compressed: u32, tx_compressed: u32, /// dropped, no handler found rx_nohandler: u32, }; pub const rtnl_link_stats64 = extern struct { /// total packets received rx_packets: u64, /// total packets transmitted tx_packets: u64, /// total bytes received rx_bytes: u64, /// total bytes transmitted tx_bytes: u64, /// bad packets received rx_errors: u64, /// packet transmit problems tx_errors: u64, /// no space in linux buffers rx_dropped: u64, /// no space available in linux tx_dropped: u64, /// multicast packets received multicast: u64, collisions: u64, // detailed rx_errors rx_length_errors: u64, /// receiver ring buff overflow rx_over_errors: u64, /// recved pkt with crc error rx_crc_errors: u64, /// recv'd frame alignment error rx_frame_errors: u64, /// recv'r fifo overrun rx_fifo_errors: u64, /// receiver missed packet rx_missed_errors: u64, // detailed tx_errors tx_aborted_errors: u64, tx_carrier_errors: u64, tx_fifo_errors: u64, tx_heartbeat_errors: u64, tx_window_errors: u64, // for cslip etc rx_compressed: u64, tx_compressed: u64, /// dropped, no handler found rx_nohandler: u64, }; pub const perf_event_attr = extern struct { /// Major type: hardware/software/tracepoint/etc. type: PERF.TYPE = undefined, /// Size of the attr structure, for fwd/bwd compat. size: u32 = @sizeOf(perf_event_attr), /// Type specific configuration information. config: u64 = 0, sample_period_or_freq: u64 = 0, sample_type: u64 = 0, read_format: u64 = 0, flags: packed struct { /// off by default disabled: bool = false, /// children inherit it inherit: bool = false, /// must always be on PMU pinned: bool = false, /// only group on PMU exclusive: bool = false, /// don't count user exclude_user: bool = false, /// ditto kernel exclude_kernel: bool = false, /// ditto hypervisor exclude_hv: bool = false, /// don't count when idle exclude_idle: bool = false, /// include mmap data mmap: bool = false, /// include comm data comm: bool = false, /// use freq, not period freq: bool = false, /// per task counts inherit_stat: bool = false, /// next exec enables enable_on_exec: bool = false, /// trace fork/exit task: bool = false, /// wakeup_watermark watermark: bool = false, /// precise_ip: /// /// 0 - SAMPLE_IP can have arbitrary skid /// 1 - SAMPLE_IP must have constant skid /// 2 - SAMPLE_IP requested to have 0 skid /// 3 - SAMPLE_IP must have 0 skid /// /// See also PERF_RECORD_MISC_EXACT_IP /// skid constraint precise_ip: u2 = 0, /// non-exec mmap data mmap_data: bool = false, /// sample_type all events sample_id_all: bool = false, /// don't count in host exclude_host: bool = false, /// don't count in guest exclude_guest: bool = false, /// exclude kernel callchains exclude_callchain_kernel: bool = false, /// exclude user callchains exclude_callchain_user: bool = false, /// include mmap with inode data mmap2: bool = false, /// flag comm events that are due to an exec comm_exec: bool = false, /// use @clockid for time fields use_clockid: bool = false, /// context switch data context_switch: bool = false, /// Write ring buffer from end to beginning write_backward: bool = false, /// include namespaces data namespaces: bool = false, /// include ksymbol events ksymbol: bool = false, /// include BPF events bpf_event: bool = false, /// generate AUX records instead of events aux_output: bool = false, /// include cgroup events cgroup: bool = false, /// include text poke events text_poke: bool = false, /// use build ID in mmap2 events build_id: bool = false, /// children only inherit if cloned with CLONE_THREAD inherit_thread: bool = false, /// event is removed from task on exec remove_on_exec: bool = false, /// send synchronous SIGTRAP on event sigtrap: bool = false, __reserved_1: u26 = 0, } = .{}, /// wakeup every n events, or /// bytes before wakeup wakeup_events_or_watermark: u32 = 0, bp_type: u32 = 0, /// This field is also used for: /// bp_addr /// kprobe_func for perf_kprobe /// uprobe_path for perf_uprobe config1: u64 = 0, /// This field is also used for: /// bp_len /// kprobe_addr when kprobe_func == null /// probe_offset for perf_[k,u]probe config2: u64 = 0, /// enum perf_branch_sample_type branch_sample_type: u64 = 0, /// Defines set of user regs to dump on samples. /// See asm/perf_regs.h for details. sample_regs_user: u64 = 0, /// Defines size of the user stack to dump on samples. sample_stack_user: u32 = 0, clockid: clockid_t = .REALTIME, /// Defines set of regs to dump for each sample /// state captured on: /// - precise = 0: PMU interrupt /// - precise > 0: sampled instruction /// /// See asm/perf_regs.h for details. sample_regs_intr: u64 = 0, /// Wakeup watermark for AUX area aux_watermark: u32 = 0, sample_max_stack: u16 = 0, /// Align to u64 __reserved_2: u16 = 0, aux_sample_size: u32 = 0, aux_action: packed struct(u32) { /// start AUX area tracing paused start_paused: bool = false, /// on overflow, pause AUX area tracing pause: bool = false, /// on overflow, resume AUX area tracing @"resume": bool = false, __reserved_3: u29 = 0, } = .{}, /// User provided data if sigtrap == true sig_data: u64 = 0, /// Extension of config2 config3: u64 = 0, }; pub const perf_event_header = extern struct { /// Event type: sample/mmap/fork/etc. type: PERF.RECORD, /// Additional informations on the event: kernel/user/hypervisor/etc. misc: packed struct(u16) { cpu_mode: PERF.RECORD.MISC.CPU_MODE, _: u9, PROC_MAP_PARSE_TIMEOUT: bool, bit13: packed union { MMAP_DATA: bool, COMM_EXEC: bool, FORK_EXEC: bool, SWITCH_OUT: bool, }, bit14: packed union { EXACT_IP: bool, SWITCH_OUT_PREEMPT: bool, MMAP_BUILD_ID: bool, }, EXT_RESERVED: bool, }, /// Size of the following record size: u16, }; pub const perf_event_mmap_page = extern struct { /// Version number of this struct version: u32, /// Lowest version this is compatible with compt_version: u32, /// Seqlock for synchronization lock: u32, /// Hardware counter identifier index: u32, /// Add to hardware counter value offset: i64, /// Time the event was active time_enabled: u64, /// Time the event was running time_running: u64, capabilities: packed struct(u64) { /// If kernel version < 3.12 /// this rapresents both user_rdpmc and user_time (user_rdpmc | user_time) /// otherwise deprecated. bit0: bool, /// Set if bit0 is deprecated bit0_is_deprecated: bool, /// Hardware support for userspace read of performance counters user_rdpmc: bool, /// Hardware support for a constant non stop timestamp counter (Eg. TSC on x86) user_time: bool, /// The time_zero field is used user_time_zero: bool, /// The time_{cycle,mask} fields are used user_time_short: bool, ____res: u58, }, /// If capabilities.user_rdpmc /// this field reports the bit-width of the value read with rdpmc() or equivalent pcm_width: u16, /// If capabilities.user_time the following fields can be used to compute the time /// delta since time_enabled (in ns) using RDTSC or similar time_shift: u16, time_mult: u32, time_offset: u64, /// If capabilities.user_time_zero the hardware clock can be calculated from /// sample timestamps time_zero: u64, /// Header size size: u32, __reserved_1: u32, /// The following fields are used to compute the timestamp when the hardware clock /// is less than 64bit wide time_cycles: u64, time_mask: u64, __reserved: [116 * 8]u8, /// Head in the data section data_head: u64, /// Userspace written tail data_tail: u64, /// Where the buffer starts data_offset: u64, /// Data buffer size data_size: u64, // if aux is used, head in the data section aux_head: u64, // if aux is used, userspace written tail aux_tail: u64, // if aux is used, where the buffer starts aux_offset: u64, // if aux is used, data buffer size aux_size: u64, }; pub const PERF = struct { pub const TYPE = enum(u32) { HARDWARE, SOFTWARE, TRACEPOINT, HW_CACHE, RAW, BREAKPOINT, MAX, _, }; pub const COUNT = struct { pub const HW = enum(u32) { CPU_CYCLES, INSTRUCTIONS, CACHE_REFERENCES, CACHE_MISSES, BRANCH_INSTRUCTIONS, BRANCH_MISSES, BUS_CYCLES, STALLED_CYCLES_FRONTEND, STALLED_CYCLES_BACKEND, REF_CPU_CYCLES, MAX, pub const CACHE = enum(u32) { L1D, L1I, LL, DTLB, ITLB, BPU, NODE, MAX, pub const OP = enum(u32) { READ, WRITE, PREFETCH, MAX, }; pub const RESULT = enum(u32) { ACCESS, MISS, MAX, }; }; }; pub const SW = enum(u32) { CPU_CLOCK, TASK_CLOCK, PAGE_FAULTS, CONTEXT_SWITCHES, CPU_MIGRATIONS, PAGE_FAULTS_MIN, PAGE_FAULTS_MAJ, ALIGNMENT_FAULTS, EMULATION_FAULTS, DUMMY, BPF_OUTPUT, MAX, }; }; pub const SAMPLE = struct { pub const IP = 1; pub const TID = 2; pub const TIME = 4; pub const ADDR = 8; pub const READ = 16; pub const CALLCHAIN = 32; pub const ID = 64; pub const CPU = 128; pub const PERIOD = 256; pub const STREAM_ID = 512; pub const RAW = 1024; pub const BRANCH_STACK = 2048; pub const REGS_USER = 4096; pub const STACK_USER = 8192; pub const WEIGHT = 16384; pub const DATA_SRC = 32768; pub const IDENTIFIER = 65536; pub const TRANSACTION = 131072; pub const REGS_INTR = 262144; pub const PHYS_ADDR = 524288; pub const MAX = 1048576; pub const BRANCH = struct { pub const USER = 1 << 0; pub const KERNEL = 1 << 1; pub const HV = 1 << 2; pub const ANY = 1 << 3; pub const ANY_CALL = 1 << 4; pub const ANY_RETURN = 1 << 5; pub const IND_CALL = 1 << 6; pub const ABORT_TX = 1 << 7; pub const IN_TX = 1 << 8; pub const NO_TX = 1 << 9; pub const COND = 1 << 10; pub const CALL_STACK = 1 << 11; pub const IND_JUMP = 1 << 12; pub const CALL = 1 << 13; pub const NO_FLAGS = 1 << 14; pub const NO_CYCLES = 1 << 15; pub const TYPE_SAVE = 1 << 16; pub const MAX = 1 << 17; }; }; pub const RECORD = enum(u32) { MMAP = 1, LOST = 2, COMM = 3, EXIT = 4, THROTTLE = 5, UNTHROTTLE = 6, FORK = 7, READ = 8, SAMPLE = 9, MMAP2 = 10, AUX = 11, ITRACE_START = 12, LOST_SAMPLES = 13, SWITCH = 14, SWITCH_CPU_WIDE = 15, NAMESPACES = 16, KSYMBOL = 17, BPF_EVENT = 18, CGROUP = 19, TEXT_POKE = 20, AUX_OUTPUT_HW_ID = 21, const MISC = struct { pub const CPU_MODE = enum(u3) { UNKNOWN = 0, KERNEL = 1, USER = 2, HYPERVISOR = 3, GUEST_KERNEL = 4, GUEST_USER = 5, }; }; }; pub const FLAG = struct { pub const FD_NO_GROUP = 1 << 0; pub const FD_OUTPUT = 1 << 1; pub const PID_CGROUP = 1 << 2; pub const FD_CLOEXEC = 1 << 3; }; pub const EVENT_IOC = struct { pub const ENABLE = 9216; pub const DISABLE = 9217; pub const REFRESH = 9218; pub const RESET = 9219; pub const PERIOD = 1074275332; pub const SET_OUTPUT = 9221; pub const SET_FILTER = 1074275334; pub const SET_BPF = 1074013192; pub const PAUSE_OUTPUT = 1074013193; pub const QUERY_BPF = 3221758986; pub const MODIFY_ATTRIBUTES = 1074275339; }; pub const IOC_FLAG_GROUP = 1; }; // TODO: Add the rest of the AUDIT defines? pub const AUDIT = struct { pub const ARCH = enum(u32) { const CONVENTION_MIPS64_N32 = 0x20000000; const @"64BIT" = 0x80000000; const LE = 0x40000000; AARCH64 = toAudit(.AARCH64, @"64BIT" | LE), ALPHA = toAudit(.ALPHA, @"64BIT" | LE), ARCOMPACT = toAudit(.ARC_COMPACT, LE), ARCOMPACTBE = toAudit(.ARC_COMPACT, 0), ARCV2 = toAudit(.ARC_COMPACT2, LE), ARCV2BE = toAudit(.ARC_COMPACT2, 0), ARM = toAudit(.ARM, LE), ARMEB = toAudit(.ARM, 0), C6X = toAudit(.TI_C6000, LE), C6XBE = toAudit(.TI_C6000, 0), CRIS = toAudit(.CRIS, LE), CSKY = toAudit(.CSKY, LE), FRV = toAudit(.FRV, 0), H8300 = toAudit(.H8_300, 0), HEXAGON = toAudit(.HEXAGON, 0), I386 = toAudit(.@"386", LE), IA64 = toAudit(.IA_64, @"64BIT" | LE), M32R = toAudit(.M32R, 0), M68K = toAudit(.@"68K", 0), MICROBLAZE = toAudit(.MICROBLAZE, 0), MIPS = toAudit(.MIPS, 0), MIPSEL = toAudit(.MIPS, LE), MIPS64 = toAudit(.MIPS, @"64BIT"), MIPS64N32 = toAudit(.MIPS, @"64BIT" | CONVENTION_MIPS64_N32), MIPSEL64 = toAudit(.MIPS, @"64BIT" | LE), MIPSEL64N32 = toAudit(.MIPS, @"64BIT" | LE | CONVENTION_MIPS64_N32), NDS32 = toAudit(.NDS32, LE), NDS32BE = toAudit(.NDS32, 0), NIOS2 = toAudit(.ALTERA_NIOS2, LE), OPENRISC = toAudit(.OPENRISC, 0), PARISC = toAudit(.PARISC, 0), PARISC64 = toAudit(.PARISC, @"64BIT"), PPC = toAudit(.PPC, 0), PPC64 = toAudit(.PPC64, @"64BIT"), PPC64LE = toAudit(.PPC64, @"64BIT" | LE), RISCV32 = toAudit(.RISCV, LE), RISCV64 = toAudit(.RISCV, @"64BIT" | LE), S390 = toAudit(.S390, 0), S390X = toAudit(.S390, @"64BIT"), SH = toAudit(.SH, 0), SHEL = toAudit(.SH, LE), SH64 = toAudit(.SH, @"64BIT"), SHEL64 = toAudit(.SH, @"64BIT" | LE), SPARC = toAudit(.SPARC, 0), SPARC64 = toAudit(.SPARCV9, @"64BIT"), TILEGX = toAudit(.TILEGX, @"64BIT" | LE), TILEGX32 = toAudit(.TILEGX, LE), TILEPRO = toAudit(.TILEPRO, LE), UNICORE = toAudit(.UNICORE, LE), X86_64 = toAudit(.X86_64, @"64BIT" | LE), XTENSA = toAudit(.XTENSA, 0), LOONGARCH32 = toAudit(.LOONGARCH, LE), LOONGARCH64 = toAudit(.LOONGARCH, @"64BIT" | LE), fn toAudit(em: elf.EM, flags: u32) u32 { return @intFromEnum(em) | flags; } pub const current: AUDIT.ARCH = switch (native_arch) { .arm, .thumb => .ARM, .armeb, .thumbeb => .ARMEB, .aarch64 => .AARCH64, .arc => .ARCV2, .arceb => .ARCV2BE, .csky => .CSKY, .hexagon => .HEXAGON, .loongarch32 => .LOONGARCH32, .loongarch64 => .LOONGARCH64, .m68k => .M68K, .mips => .MIPS, .mipsel => .MIPSEL, .mips64 => switch (native_abi) { .gnuabin32, .muslabin32 => .MIPS64N32, else => .MIPS64, }, .mips64el => switch (native_abi) { .gnuabin32, .muslabin32 => .MIPSEL64N32, else => .MIPSEL64, }, .or1k => .OPENRISC, .powerpc => .PPC, .powerpc64 => .PPC64, .powerpc64le => .PPC64LE, .riscv32 => .RISCV32, .riscv64 => .RISCV64, .sparc => .SPARC, .sparc64 => .SPARC64, .s390x => .S390X, .x86 => .I386, .x86_64 => .X86_64, .xtensa => .XTENSA, else => @compileError("unsupported architecture"), }; }; }; pub const PTRACE = struct { pub const TRACEME = 0; pub const PEEKTEXT = 1; pub const PEEKDATA = 2; pub const PEEKUSER = 3; pub const POKETEXT = 4; pub const POKEDATA = 5; pub const POKEUSER = 6; pub const CONT = 7; pub const KILL = 8; pub const SINGLESTEP = 9; pub const GETREGS = 12; pub const SETREGS = 13; pub const GETFPREGS = 14; pub const SETFPREGS = 15; pub const ATTACH = 16; pub const DETACH = 17; pub const GETFPXREGS = 18; pub const SETFPXREGS = 19; pub const SYSCALL = 24; pub const SETOPTIONS = 0x4200; pub const GETEVENTMSG = 0x4201; pub const GETSIGINFO = 0x4202; pub const SETSIGINFO = 0x4203; pub const GETREGSET = 0x4204; pub const SETREGSET = 0x4205; pub const SEIZE = 0x4206; pub const INTERRUPT = 0x4207; pub const LISTEN = 0x4208; pub const PEEKSIGINFO = 0x4209; pub const GETSIGMASK = 0x420a; pub const SETSIGMASK = 0x420b; pub const SECCOMP_GET_FILTER = 0x420c; pub const SECCOMP_GET_METADATA = 0x420d; pub const GET_SYSCALL_INFO = 0x420e; pub const EVENT = struct { pub const FORK = 1; pub const VFORK = 2; pub const CLONE = 3; pub const EXEC = 4; pub const VFORK_DONE = 5; pub const EXIT = 6; pub const SECCOMP = 7; pub const STOP = 128; }; pub const O = struct { pub const TRACESYSGOOD = 1; pub const TRACEFORK = 1 << PTRACE.EVENT.FORK; pub const TRACEVFORK = 1 << PTRACE.EVENT.VFORK; pub const TRACECLONE = 1 << PTRACE.EVENT.CLONE; pub const TRACEEXEC = 1 << PTRACE.EVENT.EXEC; pub const TRACEVFORKDONE = 1 << PTRACE.EVENT.VFORK_DONE; pub const TRACEEXIT = 1 << PTRACE.EVENT.EXIT; pub const TRACESECCOMP = 1 << PTRACE.EVENT.SECCOMP; pub const EXITKILL = 1 << 20; pub const SUSPEND_SECCOMP = 1 << 21; pub const MASK = 0x000000ff | PTRACE.O.EXITKILL | PTRACE.O.SUSPEND_SECCOMP; }; }; /// For futex2_waitv and futex2_requeue. Arrays of `futex2_waitone` allow /// waiting on multiple futexes in one call. pub const futex2_waitone = extern struct { /// Expected value at uaddr, should match size of futex. val: u64, /// User address to wait on. Top-bits must be 0 on 32-bit. uaddr: u64, /// Flags for this waiter. flags: FUTEX2_FLAGS, /// Reserved member to preserve alignment. __reserved: u32 = 0, }; pub const cache_stat_range = extern struct { off: u64, len: u64, }; pub const cache_stat = extern struct { /// Number of cached pages. cache: u64, /// Number of dirty pages. dirty: u64, /// Number of pages marked for writeback. writeback: u64, /// Number of pages evicted from the cache. evicted: u64, /// Number of recently evicted pages. /// A page is recently evicted if its last eviction was recent enough that its /// reentry to the cache would indicate that it is actively being used by the /// system, and that there is memory pressure on the system. recently_evicted: u64, }; pub const SHADOW_STACK = struct { /// Set up a restore token in the shadow stack. pub const SET_TOKEN: u64 = 1 << 0; }; pub const msghdr = extern struct { name: ?*sockaddr, namelen: socklen_t, iov: [*]iovec, iovlen: usize, control: ?*anyopaque, controllen: usize, flags: u32, }; pub const msghdr_const = extern struct { name: ?*const sockaddr, namelen: socklen_t, iov: [*]const iovec_const, iovlen: usize, control: ?*const anyopaque, controllen: usize, flags: u32, }; // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/socket.h?id=b320789d6883cc00ac78ce83bccbfe7ed58afcf0#n105 pub const cmsghdr = extern struct { len: usize, level: i32, type: i32, }; /// The syscalls, but with Zig error sets, going through libc if linking libc, /// and with some footguns eliminated. pub const wrapped = struct { pub const lfs64_abi = builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid()); const system = if (builtin.link_libc) std.c else std.os.linux; pub const SendfileError = std.posix.UnexpectedError || error{ /// `out_fd` is an unconnected socket, or out_fd closed its read end. BrokenPipe, /// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd. UnsupportedOperation, /// Nonblocking I/O has been selected but the write would block. WouldBlock, /// Unspecified error while reading from in_fd. InputOutput, /// Insufficient kernel memory to read from in_fd. SystemResources, /// `offset` is not `null` but the input file is not seekable. Unseekable, }; pub fn sendfile( out_fd: fd_t, in_fd: fd_t, in_offset: ?*off_t, in_len: usize, ) SendfileError!usize { const adjusted_len = @min(in_len, 0x7ffff000); // Prevents EOVERFLOW. const sendfileSymbol = if (lfs64_abi) system.sendfile64 else system.sendfile; const rc = sendfileSymbol(out_fd, in_fd, in_offset, adjusted_len); switch (errno(rc)) { .SUCCESS => return @intCast(rc), .BADF => return invalidApiUsage(), // Always a race condition. .FAULT => return invalidApiUsage(), // Segmentation fault. .OVERFLOW => return unexpectedErrno(.OVERFLOW), // We avoid passing too large of a `count`. .NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket .INVAL => return error.UnsupportedOperation, .AGAIN => return error.WouldBlock, .IO => return error.InputOutput, .PIPE => return error.BrokenPipe, .NOMEM => return error.SystemResources, .NXIO => return error.Unseekable, .SPIPE => return error.Unseekable, else => |err| return unexpectedErrno(err), } } pub const CopyFileRangeError = std.posix.UnexpectedError || error{ /// One of: /// * One or more file descriptors are not valid. /// * fd_in is not open for reading; or fd_out is not open for writing. /// * The O_APPEND flag is set for the open file description referred /// to by the file descriptor fd_out. BadFileFlags, /// One of: /// * An attempt was made to write at a position past the maximum file /// offset the kernel supports. /// * An attempt was made to write a range that exceeds the allowed /// maximum file size. The maximum file size differs between /// filesystem implementations and can be different from the maximum /// allowed file offset. /// * An attempt was made to write beyond the process's file size /// resource limit. This may also result in the process receiving a /// SIGXFSZ signal. FileTooBig, /// One of: /// * either fd_in or fd_out is not a regular file /// * flags argument is not zero /// * fd_in and fd_out refer to the same file and the source and target ranges overlap. InvalidArguments, /// A low-level I/O error occurred while copying. InputOutput, /// Either fd_in or fd_out refers to a directory. IsDir, OutOfMemory, /// There is not enough space on the target filesystem to complete the copy. NoSpaceLeft, /// (since Linux 5.19) the filesystem does not support this operation. OperationNotSupported, /// The requested source or destination range is too large to represent /// in the specified data types. Overflow, /// fd_out refers to an immutable file. PermissionDenied, /// Either fd_in or fd_out refers to an active swap file. SwapFile, /// The files referred to by fd_in and fd_out are not on the same /// filesystem, and the source and target filesystems are not of the /// same type, or do not support cross-filesystem copy. NotSameFileSystem, }; pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize { const use_c = std.c.versionCheck(if (builtin.abi.isAndroid()) .{ .major = 34, .minor = 0, .patch = 0 } else .{ .major = 2, .minor = 27, .patch = 0 }); const sys = if (use_c) std.c else std.os.linux; const rc = sys.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags); switch (errno(rc)) { .SUCCESS => return @intCast(rc), .BADF => return error.BadFileFlags, .FBIG => return error.FileTooBig, .INVAL => return error.InvalidArguments, .IO => return error.InputOutput, .ISDIR => return error.IsDir, .NOMEM => return error.OutOfMemory, .NOSPC => return error.NoSpaceLeft, .OPNOTSUPP => return error.OperationNotSupported, .OVERFLOW => return error.Overflow, .PERM => return error.PermissionDenied, .TXTBSY => return error.SwapFile, .XDEV => return error.NotSameFileSystem, else => |err| return unexpectedErrno(err), } } const unexpectedErrno = std.posix.unexpectedErrno; fn invalidApiUsage() error{Unexpected} { if (builtin.mode == .Debug) @panic("invalid API usage"); return error.Unexpected; } fn errno(rc: anytype) E { if (builtin.link_libc) { return if (rc == -1) @enumFromInt(std.c._errno().*) else .SUCCESS; } else { return errnoFromSyscall(rc); } } };