Commit 87fd502fb6

Stephen Gregoratto <dev@sgregoratto.me>
2021-08-31 14:21:23
Initial bringup of the Solaris/Illumos port
1 parent a032fd0
lib/std/c/solaris.zig
@@ -1,15 +1,1913 @@
+const std = @import("../std.zig");
+const builtin = @import("builtin");
+const maxInt = std.math.maxInt;
+const iovec = std.os.iovec;
+const iovec_const = std.os.iovec_const;
+const timezone = std.c.timezone;
+
+extern "c" fn ___errno() *c_int;
+pub const _errno = ___errno;
+
+pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int;
+pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
+
+pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
+pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;
+pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void;
+pub extern "c" fn posix_memalign(memptr: *?*c_void, alignment: usize, size: usize) c_int;
+pub extern "c" fn sysconf(sc: c_int) i64;
+pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) c_int;
+pub extern "c" fn madvise(address: [*]u8, len: usize, advise: u32) c_int;
+
 pub const pthread_mutex_t = extern struct {
-    __pthread_mutex_flag1: u16 = 0,
-    __pthread_mutex_flag2: u8 = 0,
-    __pthread_mutex_ceiling: u8 = 0,
-    __pthread_mutex_type: u16 = 0,
-    __pthread_mutex_magic: u16 = 0x4d58,
-    __pthread_mutex_lock: u64 = 0,
-    __pthread_mutex_data: u64 = 0,
+    flag1: u16 = 0,
+    flag2: u8 = 0,
+    ceiling: u8 = 0,
+    @"type": u16 = 0,
+    magic: u16 = 0x4d58,
+    lock: u64 = 0,
+    data: u64 = 0,
 };
 pub const pthread_cond_t = extern struct {
-    __pthread_cond_flag: u32 = 0,
-    __pthread_cond_type: u16 = 0,
-    __pthread_cond_magic: u16 = 0x4356,
-    __pthread_cond_data: u64 = 0,
+    flag: [4]u8 = [_]u8{0} ** 4,
+    @"type": u16 = 0,
+    magic: u16 = 0x4356,
+    data: u64 = 0,
 };
+pub const pthread_rwlock_t = extern struct {
+    readers: i32 = 0,
+    @"type": u16 = 0,
+    magic: u16 = 0x5257,
+    mutex: pthread_mutex_t = .{},
+    readercv: pthread_cond_t = .{},
+    writercv: pthread_cond_t = .{},
+};
+pub const pthread_attr_t = extern struct {
+    mutexattr: ?*c_void = null,
+};
+pub const pthread_key_t = c_int;
+
+pub const sem_t = extern struct {
+    count: u32 = 0,
+    @"type": u16 = 0,
+    magic: u16 = 0x534d,
+    __pad1: [3]u64 = [_]u64{0} ** 3,
+    __pad2: [2]u64 = [_]u64{0} ** 2,
+};
+
+pub extern "c" fn pthread_setname_np(thread: std.c.pthread_t, name: [*:0]const u8, arg: ?*c_void) E;
+pub extern "c" fn pthread_getname_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) E;
+
+pub const blkcnt_t = i64;
+pub const blksize_t = i32;
+pub const clock_t = i64;
+pub const dev_t = i32;
+pub const fd_t = c_int;
+pub const gid_t = u32;
+pub const ino_t = u64;
+pub const mode_t = u32;
+pub const nlink_t = u32;
+pub const off_t = i64;
+pub const pid_t = i32;
+pub const socklen_t = u32;
+pub const time_t = i64;
+pub const suseconds_t = i64;
+pub const uid_t = u32;
+pub const major_t = u32;
+pub const minor_t = u32;
+pub const port_t = c_int;
+pub const nfds_t = usize;
+pub const id_t = i32;
+pub const taskid_t = id_t;
+pub const projid_t = id_t;
+pub const poolid_t = id_t;
+pub const zoneid_t = id_t;
+pub const ctid_t = id_t;
+
+pub const dl_phdr_info = extern struct {
+    dlpi_addr: std.elf.Addr,
+    dlpi_name: ?[*:0]const u8,
+    dlpi_phdr: [*]std.elf.Phdr,
+    dlpi_phnum: std.elf.Half,
+    /// Incremented when a new object is mapped into the process.
+    dlpi_adds: u64,
+    /// Incremented when an object is unmapped from the process.
+    dlpi_subs: u64,
+};
+
+pub const RTLD = struct {
+    pub const LAZY = 0x00001;
+    pub const NOW = 0x00002;
+    pub const NOLOAD = 0x00004;
+    pub const GLOBAL = 0x00100;
+    pub const LOCAL = 0x00000;
+    pub const PARENT = 0x00200;
+    pub const GROUP = 0x00400;
+    pub const WORLD = 0x00800;
+    pub const NODELETE = 0x01000;
+    pub const FIRST = 0x02000;
+    pub const CONFGEN = 0x10000;
+
+    pub const NEXT = @intToPtr(*c_void, @bitCast(usize, @as(isize, -1)));
+    pub const DEFAULT = @intToPtr(*c_void, @bitCast(usize, @as(isize, -2)));
+    pub const SELF = @intToPtr(*c_void, @bitCast(usize, @as(isize, -3)));
+    pub const PROBE = @intToPtr(*c_void, @bitCast(usize, @as(isize, -4)));
+};
+
+pub const Flock = extern struct {
+    l_type: c_short,
+    l_whence: c_short,
+    l_start: off_t,
+    // len == 0 means until end of file.
+    l_len: off_t,
+    l_sysid: c_int,
+    l_pid: pid_t,
+    __pad: [4]c_long,
+};
+
+pub const utsname = extern struct {
+    sysname: [256:0]u8,
+    nodename: [256:0]u8,
+    release: [256:0]u8,
+    version: [256:0]u8,
+    machine: [256:0]u8,
+    domainname: [256:0]u8,
+};
+
+pub const addrinfo = extern struct {
+    flags: i32,
+    family: i32,
+    socktype: i32,
+    protocol: i32,
+    addrlen: socklen_t,
+    canonname: ?[*:0]u8,
+    addr: ?*sockaddr,
+    next: ?*addrinfo,
+};
+
+pub const EAI = enum(c_int) {
+    /// address family for hostname not supported
+    ADDRFAMILY = 1,
+    /// name could not be resolved at this time
+    AGAIN = 2,
+    /// flags parameter had an invalid value
+    BADFLAGS = 3,
+    /// non-recoverable failure in name resolution
+    FAIL = 4,
+    /// address family not recognized
+    FAMILY = 5,
+    /// memory allocation failure
+    MEMORY = 6,
+    /// no address associated with hostname
+    NODATA = 7,
+    /// name does not resolve
+    NONAME = 8,
+    /// service not recognized for socket type
+    SERVICE = 9,
+    /// intended socket type was not recognized
+    SOCKTYPE = 10,
+    /// system error returned in errno
+    SYSTEM = 11,
+    /// argument buffer overflow
+    OVERFLOW = 12,
+    /// resolved protocol is unknown
+    PROTOCOL = 13,
+
+    _,
+};
+
+pub const EAI_MAX = 14;
+
+pub const msghdr = extern struct {
+    /// optional address
+    msg_name: ?*sockaddr,
+    /// size of address
+    msg_namelen: socklen_t,
+    /// scatter/gather array
+    msg_iov: [*]iovec,
+    /// # elements in msg_iov
+    msg_iovlen: i32,
+    /// ancillary data
+    msg_control: ?*c_void,
+    /// ancillary data buffer len
+    msg_controllen: socklen_t,
+    /// flags on received message
+    msg_flags: i32,
+};
+
+pub const msghdr_const = extern struct {
+    /// optional address
+    msg_name: ?*const sockaddr,
+    /// size of address
+    msg_namelen: socklen_t,
+    /// scatter/gather array
+    msg_iov: [*]iovec_const,
+    /// # elements in msg_iov
+    msg_iovlen: i32,
+    /// ancillary data
+    msg_control: ?*c_void,
+    /// ancillary data buffer len
+    msg_controllen: socklen_t,
+    /// flags on received message
+    msg_flags: i32,
+};
+
+pub const cmsghdr = extern struct {
+    cmsg_len: socklen_t,
+    cmsg_level: i32,
+    cmsg_type: i32,
+};
+
+/// The stat structure used by libc.
+pub const Stat = extern struct {
+    dev: dev_t,
+    ino: ino_t,
+    mode: mode_t,
+    nlink: nlink_t,
+    uid: uid_t,
+    gid: gid_t,
+    rdev: dev_t,
+    size: off_t,
+    atim: timespec,
+    mtim: timespec,
+    ctim: timespec,
+    blksize: blksize_t,
+    blocks: blkcnt_t,
+    fstype: [16]u8,
+
+    pub fn atime(self: @This()) timespec {
+        return self.atim;
+    }
+
+    pub fn mtime(self: @This()) timespec {
+        return self.mtim;
+    }
+
+    pub fn ctime(self: @This()) timespec {
+        return self.ctim;
+    }
+};
+
+pub const timespec = extern struct {
+    tv_sec: i64,
+    tv_nsec: isize,
+};
+
+pub const timeval = extern struct {
+    /// seconds
+    tv_sec: time_t,
+    /// microseconds
+    tv_usec: suseconds_t,
+};
+
+pub const MAXNAMLEN = 511;
+
+pub const dirent = extern struct {
+    /// Inode number of entry.
+    d_ino: ino_t,
+    /// Offset of this entry on disk.
+    d_off: off_t,
+    /// Length of this record.
+    d_reclen: u16,
+    /// File name.
+    d_name: [MAXNAMLEN:0]u8,
+
+    pub fn reclen(self: dirent) u16 {
+        return self.d_reclen;
+    }
+};
+
+pub const SOCK = struct {
+    /// Datagram.
+    pub const DGRAM = 1;
+    /// STREAM.
+    pub const STREAM = 2;
+    /// Raw-protocol interface.
+    pub const RAW = 4;
+    /// Reliably-delivered message.
+    pub const RDM = 5;
+    /// Sequenced packed stream.
+    pub const SEQPACKET = 6;
+
+    pub const NONBLOCK = 0x100000;
+    pub const NDELAY = 0x200000;
+    pub const CLOEXEC = 0x080000;
+};
+
+pub const SO = struct {
+    pub const DEBUG = 0x0001;
+    pub const ACCEPTCONN = 0x0002;
+    pub const REUSEADDR = 0x0004;
+    pub const KEEPALIVE = 0x0008;
+    pub const DONTROUTE = 0x0010;
+    pub const BROADCAST = 0x0020;
+    pub const USELOOPBACK = 0x0040;
+    pub const LINGER = 0x0080;
+    pub const OOBINLINE = 0x0100;
+    pub const DGRAM_ERRIND = 0x0200;
+    pub const RECVUCRED = 0x0400;
+
+    pub const SNDBUF = 0x1001;
+    pub const RCVBUF = 0x1002;
+    pub const SNDLOWAT = 0x1003;
+    pub const RCVLOWAT = 0x1004;
+    pub const SNDTIMEO = 0x1005;
+    pub const RCVTIMEO = 0x1006;
+    pub const ERROR = 0x1007;
+    pub const TYPE = 0x1008;
+    pub const PROTOTYPE = 0x1009;
+    pub const ANON_MLP = 0x100a;
+    pub const MAC_EXEMPT = 0x100b;
+    pub const DOMAIN = 0x100c;
+    pub const RCVPSH = 0x100d;
+
+    pub const SECATTR = 0x1011;
+    pub const TIMESTAMP = 0x1013;
+    pub const ALLZONES = 0x1014;
+    pub const EXCLBIND = 0x1015;
+    pub const MAC_IMPLICIT = 0x1016;
+    pub const VRRP = 0x1017;
+};
+
+pub const SOMAXCONN = 128;
+
+pub const SCM = struct {
+    pub const UCRED = 0x1012;
+    pub const RIGHTS = 0x1010;
+    pub const TIMESTAMP = SO.TIMESTAMP;
+};
+
+pub const AF = struct {
+    pub const UNSPEC = 0;
+    pub const UNIX = 1;
+    pub const LOCAL = UNIX;
+    pub const FILE = UNIX;
+    pub const INET = 2;
+    pub const IMPLINK = 3;
+    pub const PUP = 4;
+    pub const CHAOS = 5;
+    pub const NS = 6;
+    pub const NBS = 7;
+    pub const ECMA = 8;
+    pub const DATAKIT = 9;
+    pub const CCITT = 10;
+    pub const SNA = 11;
+    pub const DECnet = 12;
+    pub const DLI = 13;
+    pub const LAT = 14;
+    pub const HYLINK = 15;
+    pub const APPLETALK = 16;
+    pub const NIT = 17;
+    pub const @"802" = 18;
+    pub const OSI = 19;
+    pub const X25 = 20;
+    pub const OSINET = 21;
+    pub const GOSIP = 22;
+    pub const IPX = 23;
+    pub const ROUTE = 24;
+    pub const LINK = 25;
+    pub const INET6 = 26;
+    pub const KEY = 27;
+    pub const NCA = 28;
+    pub const POLICY = 29;
+    pub const INET_OFFLOAD = 30;
+    pub const TRILL = 31;
+    pub const PACKET = 32;
+    pub const LX_NETLINK = 33;
+    pub const MAX = 33;
+};
+
+pub const SOL = struct {
+    pub const SOCKET = 0xffff;
+    pub const ROUTE = 0xfffe;
+    pub const PACKET = 0xfffd;
+    pub const FILTER = 0xfffc;
+};
+
+pub const PF = struct {
+    pub const UNSPEC = AF.UNSPEC;
+    pub const UNIX = AF.UNIX;
+    pub const LOCAL = UNIX;
+    pub const FILE = UNIX;
+    pub const INET = AF.INET;
+    pub const IMPLINK = AF.IMPLINK;
+    pub const PUP = AF.PUP;
+    pub const CHAOS = AF.CHAOS;
+    pub const NS = AF.NS;
+    pub const NBS = AF.NBS;
+    pub const ECMA = AF.ECMA;
+    pub const DATAKIT = AF.DATAKIT;
+    pub const CCITT = AF.CCITT;
+    pub const SNA = AF.SNA;
+    pub const DECnet = AF.DECnet;
+    pub const DLI = AF.DLI;
+    pub const LAT = AF.LAT;
+    pub const HYLINK = AF.HYLINK;
+    pub const APPLETALK = AF.APPLETALK;
+    pub const NIT = AF.NIT;
+    pub const @"802" = AF.@"802";
+    pub const OSI = AF.OSI;
+    pub const X25 = AF.X25;
+    pub const OSINET = AF.OSINET;
+    pub const GOSIP = AF.GOSIP;
+    pub const IPX = AF.IPX;
+    pub const ROUTE = AF.ROUTE;
+    pub const LINK = AF.LINK;
+    pub const INET6 = AF.INET6;
+    pub const KEY = AF.KEY;
+    pub const NCA = AF.NCA;
+    pub const POLICY = AF.POLICY;
+    pub const TRILL = AF.TRILL;
+    pub const PACKET = AF.PACKET;
+    pub const LX_NETLINK = AF.LX_NETLINK;
+    pub const MAX = AF.MAX;
+};
+
+pub const in_port_t = u16;
+pub const sa_family_t = u16;
+
+pub const sockaddr = extern struct {
+    /// address family
+    family: sa_family_t,
+
+    /// actually longer; address value
+    data: [14]u8,
+
+    pub const SS_MAXSIZE = 256;
+    pub const storage = std.x.os.Socket.Address.Native.Storage;
+
+    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 },
+    };
+
+    pub const in6 = extern struct {
+        family: sa_family_t = AF.INET6,
+        port: in_port_t,
+        flowinfo: u32,
+        addr: [16]u8,
+        scope_id: u32,
+        __src_id: u32 = 0,
+    };
+
+    /// Definitions for UNIX IPC domain.
+    pub const un = extern struct {
+        family: sa_family_t = AF.UNIX,
+        path: [108]u8,
+    };
+};
+
+pub const AI = struct {
+    /// IPv4-mapped IPv6 address
+    pub const V4MAPPED = 0x0001;
+    pub const ALL = 0x0002;
+    /// only if any address is assigned
+    pub const ADDRCONFIG = 0x0004;
+    /// get address to use bind()
+    pub const PASSIVE = 0x0008;
+    /// fill ai_canonname
+    pub const CANONNAME = 0x0010;
+    /// prevent host name resolution
+    pub const NUMERICHOST = 0x0020;
+    /// prevent service name resolution
+    pub const NUMERICSERV = 0x0040;
+};
+
+pub const NI = struct {
+    pub const NOFQDN = 0x0001;
+    pub const NUMERICHOST = 0x0002;
+    pub const NAMEREQD = 0x0004;
+    pub const NUMERICSERV = 0x0008;
+    pub const DGRAM = 0x0010;
+    pub const WITHSCOPEID = 0x0020;
+    pub const NUMERICSCOPE = 0x0040;
+
+    pub const MAXHOST = 1025;
+    pub const MAXSERV = 32;
+};
+
+pub const PATH_MAX = 1024;
+pub const IOV_MAX = 1024;
+
+pub const STDIN_FILENO = 0;
+pub const STDOUT_FILENO = 1;
+pub const STDERR_FILENO = 2;
+
+pub const PROT = struct {
+    pub const NONE = 0;
+    pub const READ = 1;
+    pub const WRITE = 2;
+    pub const EXEC = 4;
+};
+
+pub const CLOCK = struct {
+    pub const VIRTUAL = 1;
+    pub const THREAD_CPUTIME_ID = 2;
+    pub const REALTIME = 3;
+    pub const MONOTONIC = 4;
+    pub const PROCESS_CPUTIME_ID = 5;
+    pub const HIGHRES = MONOTONIC;
+    pub const PROF = THREAD_CPUTIME_ID;
+};
+
+pub const MAP = struct {
+    pub const FAILED = @intToPtr(*c_void, maxInt(usize));
+    pub const SHARED = 0x0001;
+    pub const PRIVATE = 0x0002;
+    pub const TYPE = 0x000f;
+
+    pub const FILE = 0x0000;
+    pub const FIXED = 0x0010;
+    // Unimplemented
+    pub const RENAME = 0x0020;
+    pub const NORESERVE = 0x0040;
+    /// Force mapping in lower 4G address space
+    pub const @"32BIT" = 0x0080;
+
+    pub const ANON = 0x0100;
+    pub const ANONYMOUS = ANON;
+    pub const ALIGN = 0x0200;
+    pub const TEXT = 0x0400;
+    pub const INITDATA = 0x0800;
+};
+
+pub const MADV = struct {
+    /// no further special treatment
+    pub const NORMAL = 0;
+    /// expect random page references
+    pub const RANDOM = 1;
+    /// expect sequential page references
+    pub const SEQUENTIAL = 2;
+    /// will need these pages
+    pub const WILLNEED = 3;
+    /// don't need these pages
+    pub const DONTNEED = 4;
+    /// contents can be freed
+    pub const FREE = 5;
+    /// default access
+    pub const ACCESS_DEFAULT = 6;
+    /// next LWP to access heavily
+    pub const ACCESS_LWP = 7;
+    /// many processes to access heavily
+    pub const ACCESS_MANY = 8;
+    /// contents will be purged
+    pub const PURGE = 9;
+};
+
+pub const W = struct {
+    pub const EXITED = 0o001;
+    pub const TRAPPED = 0o002;
+    pub const UNTRACED = 0o004;
+    pub const STOPPED = UNTRACED;
+    pub const CONTINUED = 0o010;
+    pub const NOHANG = 0o100;
+    pub const NOWAIT = 0o200;
+
+    pub fn EXITSTATUS(s: u32) u8 {
+        return @intCast(u8, (s >> 8) & 0xff);
+    }
+    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 IFCONTINUED(s: u32) bool {
+        return ((s & 0o177777) == 0o177777);
+    }
+
+    pub fn IFSTOPPED(s: u32) bool {
+        return (s & 0x00ff != 0o177) and !(s & 0xff00 != 0);
+    }
+
+    pub fn IFSIGNALED(s: u32) bool {
+        return s & 0x00ff > 0 and s & 0xff00 == 0;
+    }
+};
+
+pub const SA = struct {
+    pub const ONSTACK = 0x00000001;
+    pub const RESETHAND = 0x00000002;
+    pub const RESTART = 0x00000004;
+    pub const SIGINFO = 0x00000008;
+    pub const NODEFER = 0x00000010;
+    pub const NOCLDWAIT = 0x00010000;
+};
+
+// access function
+pub const F_OK = 0; // test for existence of file
+pub const X_OK = 1; // test for execute or search permission
+pub const W_OK = 2; // test for write permission
+pub const R_OK = 4; // test for read permission
+
+pub const F = struct {
+    /// Unlock a previously locked region
+    pub const ULOCK = 0;
+    /// Lock a region for exclusive use
+    pub const LOCK = 1;
+    /// Test and lock a region for exclusive use
+    pub const TLOCK = 2;
+    /// Test a region for other processes locks
+    pub const TEST = 3;
+
+    /// Duplicate fildes
+    pub const DUPFD = 0;
+    /// Get fildes flags
+    pub const GETFD = 1;
+    /// Set fildes flags
+    pub const SETFD = 2;
+    /// Get file flags
+    pub const GETFL = 3;
+    /// Get file flags including open-only flags
+    pub const GETXFL = 45;
+    /// Set file flags
+    pub const SETFL = 4;
+
+    /// Unused
+    pub const CHKFL = 8;
+    /// Duplicate fildes at third arg
+    pub const DUP2FD = 9;
+    /// Like DUP2FD with O_CLOEXEC set EINVAL is fildes matches arg1
+    pub const DUP2FD_CLOEXEC = 36;
+    /// Like DUPFD with O_CLOEXEC set
+    pub const DUPFD_CLOEXEC = 37;
+
+    /// Is the file desc. a stream ?
+    pub const ISSTREAM = 13;
+    /// Turn on private access to file
+    pub const PRIV = 15;
+    /// Turn off private access to file
+    pub const NPRIV = 16;
+    /// UFS quota call
+    pub const QUOTACTL = 17;
+    /// Get number of BLKSIZE blocks allocated
+    pub const BLOCKS = 18;
+    /// Get optimal I/O block size
+    pub const BLKSIZE = 19;
+    /// Get owner (socket emulation)
+    pub const GETOWN = 23;
+    /// Set owner (socket emulation)
+    pub const SETOWN = 24;
+    /// Object reuse revoke access to file desc.
+    pub const REVOKE = 25;
+    /// Does vp have NFS locks private to lock manager
+    pub const HASREMOTELOCKS = 26;
+
+    /// Set file lock
+    pub const SETLK = 6;
+    /// Set file lock and wait
+    pub const SETLKW = 7;
+    /// Allocate file space
+    pub const ALLOCSP = 10;
+    /// Free file space
+    pub const FREESP = 11;
+    /// Get file lock
+    pub const GETLK = 14;
+    /// Get file lock owned by file
+    pub const OFD_GETLK = 47;
+    /// Set file lock owned by file
+    pub const OFD_SETLK = 48;
+    /// Set file lock owned by file and wait
+    pub const OFD_SETLKW = 49;
+    /// Set a file share reservation
+    pub const SHARE = 40;
+    /// Remove a file share reservation
+    pub const UNSHARE = 41;
+    /// Create Poison FD
+    pub const BADFD = 46;
+
+    /// Read lock
+    pub const RDLCK = 1;
+    /// Write lock
+    pub const WRLCK = 2;
+    /// Remove lock(s)
+    pub const UNLCK = 3;
+    /// remove remote locks for a given system
+    pub const UNLKSYS = 4;
+
+    // f_access values
+    /// Read-only share access
+    pub const RDACC = 0x1;
+    /// Write-only share access
+    pub const WRACC = 0x2;
+    /// Read-Write share access
+    pub const RWACC = 0x3;
+
+    // f_deny values
+    /// Don't deny others access
+    pub const NODNY = 0x0;
+    /// Deny others read share access
+    pub const RDDNY = 0x1;
+    /// Deny others write share access
+    pub const WRDNY = 0x2;
+    /// Deny others read or write share access
+    pub const RWDNY = 0x3;
+    /// private flag: Deny delete share access
+    pub const RMDNY = 0x4;
+};
+
+pub const O = struct {
+    pub const RDONLY = 0;
+    pub const WRONLY = 1;
+    pub const RDWR = 2;
+    pub const SEARCH = 0x200000;
+    pub const EXEC = 0x400000;
+    pub const NDELAY = 0x04;
+    pub const APPEND = 0x08;
+    pub const SYNC = 0x10;
+    pub const DSYNC = 0x40;
+    pub const RSYNC = 0x8000;
+    pub const NONBLOCK = 0x80;
+    pub const LARGEFILE = 0x2000;
+
+    pub const CREAT = 0x100;
+    pub const TRUNC = 0x200;
+    pub const EXCL = 0x400;
+    pub const NOCTTY = 0x800;
+    pub const XATTR = 0x4000;
+    pub const NOFOLLOW = 0x20000;
+    pub const NOLINKS = 0x40000;
+    pub const CLOEXEC = 0x800000;
+    pub const DIRECTORY = 0x1000000;
+    pub const DIRECT = 0x2000000;
+};
+
+pub const LOCK = struct {
+    pub const SH = 1;
+    pub const EX = 2;
+    pub const NB = 4;
+    pub const UN = 8;
+};
+
+pub const FD_CLOEXEC = 1;
+
+pub const SEEK = struct {
+    pub const SET = 0;
+    pub const CUR = 1;
+    pub const END = 2;
+    pub const DATA = 3;
+    pub const HOLE = 4;
+};
+
+pub const tcflag_t = c_uint;
+pub const cc_t = u8;
+pub const speed_t = c_uint;
+
+pub const NCCS = 19;
+
+pub const termios = extern struct {
+    c_iflag: tcflag_t,
+    c_oflag: tcflag_t,
+    c_cflag: tcflag_t,
+    c_lflag: tcflag_t,
+    c_cc: [NCCS]cc_t,
+};
+
+fn tioc(t: u16, num: u8) u16 {
+    return (t << 8) | num;
+}
+
+pub const T = struct {
+    pub const CGETA = tioc('T', 1);
+    pub const CSETA = tioc('T', 2);
+    pub const CSETAW = tioc('T', 3);
+    pub const CSETAF = tioc('T', 4);
+    pub const CSBRK = tioc('T', 5);
+    pub const CXONC = tioc('T', 6);
+    pub const CFLSH = tioc('T', 7);
+    pub const IOCGWINSZ = tioc('T', 104);
+    pub const IOCSWINSZ = tioc('T', 103);
+    // Softcarrier ioctls
+    pub const IOCGSOFTCAR = tioc('T', 105);
+    pub const IOCSSOFTCAR = tioc('T', 106);
+    // termios ioctls
+    pub const CGETS = tioc('T', 13);
+    pub const CSETS = tioc('T', 14);
+    pub const CSANOW = tioc('T', 14);
+    pub const CSETSW = tioc('T', 15);
+    pub const CSADRAIN = tioc('T', 15);
+    pub const CSETSF = tioc('T', 16);
+    pub const IOCSETLD = tioc('T', 123);
+    pub const IOCGETLD = tioc('T', 124);
+    // NTP PPS ioctls
+    pub const IOCGPPS = tioc('T', 125);
+    pub const IOCSPPS = tioc('T', 126);
+    pub const IOCGPPSEV = tioc('T', 127);
+
+    pub const IOCGETD = tioc('t', 0);
+    pub const IOCSETD = tioc('t', 1);
+    pub const IOCHPCL = tioc('t', 2);
+    pub const IOCGETP = tioc('t', 8);
+    pub const IOCSETP = tioc('t', 9);
+    pub const IOCSETN = tioc('t', 10);
+    pub const IOCEXCL = tioc('t', 13);
+    pub const IOCNXCL = tioc('t', 14);
+    pub const IOCFLUSH = tioc('t', 16);
+    pub const IOCSETC = tioc('t', 17);
+    pub const IOCGETC = tioc('t', 18);
+    /// bis local mode bits
+    pub const IOCLBIS = tioc('t', 127);
+    /// bic local mode bits
+    pub const IOCLBIC = tioc('t', 126);
+    /// set entire local mode word
+    pub const IOCLSET = tioc('t', 125);
+    /// get local modes
+    pub const IOCLGET = tioc('t', 124);
+    /// set break bit
+    pub const IOCSBRK = tioc('t', 123);
+    /// clear break bit
+    pub const IOCCBRK = tioc('t', 122);
+    /// set data terminal ready
+    pub const IOCSDTR = tioc('t', 121);
+    /// clear data terminal ready
+    pub const IOCCDTR = tioc('t', 120);
+    /// set local special chars
+    pub const IOCSLTC = tioc('t', 117);
+    /// get local special chars
+    pub const IOCGLTC = tioc('t', 116);
+    /// driver output queue size
+    pub const IOCOUTQ = tioc('t', 115);
+    /// void tty association
+    pub const IOCNOTTY = tioc('t', 113);
+    /// get a ctty
+    pub const IOCSCTTY = tioc('t', 132);
+    /// stop output, like ^S
+    pub const IOCSTOP = tioc('t', 111);
+    /// start output, like ^Q
+    pub const IOCSTART = tioc('t', 110);
+    /// get pgrp of tty
+    pub const IOCGPGRP = tioc('t', 20);
+    /// set pgrp of tty
+    pub const IOCSPGRP = tioc('t', 21);
+    /// get session id on ctty
+    pub const IOCGSID = tioc('t', 22);
+    /// simulate terminal input
+    pub const IOCSTI = tioc('t', 23);
+    /// set all modem bits
+    pub const IOCMSET = tioc('t', 26);
+    /// bis modem bits
+    pub const IOCMBIS = tioc('t', 27);
+    /// bic modem bits
+    pub const IOCMBIC = tioc('t', 28);
+    /// get all modem bits
+    pub const IOCMGET = tioc('t', 29);
+};
+
+pub const winsize = extern struct {
+    ws_row: u16,
+    ws_col: u16,
+    ws_xpixel: u16,
+    ws_ypixel: u16,
+};
+
+const NSIG = 75;
+
+pub const SIG = struct {
+    pub const DFL = @intToPtr(?Sigaction.sigaction_fn, 0);
+    pub const ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize));
+    pub const IGN = @intToPtr(?Sigaction.sigaction_fn, 1);
+    pub const HOLD = @intToPtr(?Sigaction.sigaction_fn, 2);
+
+    pub const WORDS = 4;
+    pub const MAXSIG = 75;
+
+    pub const SIG_BLOCK = 1;
+    pub const SIG_UNBLOCK = 2;
+    pub const SIG_SETMASK = 3;
+
+    pub const HUP = 1;
+    pub const INT = 2;
+    pub const QUIT = 3;
+    pub const ILL = 4;
+    pub const TRAP = 5;
+    pub const IOT = 6;
+    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 USR1 = 16;
+    pub const USR2 = 17;
+    pub const CLD = 18;
+    pub const CHLD = 18;
+    pub const PWR = 19;
+    pub const WINCH = 20;
+    pub const URG = 21;
+    pub const POLL = 22;
+    pub const IO = .POLL;
+    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 XFSZ = 31;
+    pub const WAITING = 32;
+    pub const LWP = 33;
+    pub const FREEZE = 34;
+    pub const THAW = 35;
+    pub const CANCEL = 36;
+    pub const LOST = 37;
+    pub const XRES = 38;
+    pub const JVM1 = 39;
+    pub const JVM2 = 40;
+    pub const INFO = 41;
+
+    pub const RTMIN = 42;
+    pub const RTMAX = 74;
+
+    pub inline fn IDX(sig: usize) usize {
+        return sig - 1;
+    }
+    pub inline fn WORD(sig: usize) usize {
+        return IDX(sig) >> 5;
+    }
+    pub inline fn BIT(sig: usize) usize {
+        return 1 << (IDX(sig) & 31);
+    }
+    pub inline fn VALID(sig: usize) usize {
+        return sig <= MAXSIG and sig > 0;
+    }
+};
+
+/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
+pub const Sigaction = extern struct {
+    pub const handler_fn = fn (c_int) callconv(.C) void;
+    pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const c_void) callconv(.C) void;
+
+    /// signal options
+    flags: c_uint,
+    /// signal handler
+    handler: extern union {
+        handler: ?handler_fn,
+        sigaction: ?sigaction_fn,
+    },
+    /// signal mask to apply
+    mask: sigset_t,
+};
+
+pub const sigval_t = extern union {
+    int: c_int,
+    ptr: ?*c_void,
+};
+
+pub const siginfo_t = extern struct {
+    signo: c_int,
+    code: c_int,
+    errno: c_int,
+    // 64bit architectures insert 4bytes of padding here, this is done by
+    // correctly aligning the reason field
+    reason: extern union {
+        proc: extern struct {
+            pid: pid_t,
+            pdata: extern union {
+                kill: extern struct {
+                    uid: uid_t,
+                    value: sigval_t,
+                },
+                cld: extern struct {
+                    utime: clock_t,
+                    status: c_int,
+                    stime: clock_t,
+                },
+            },
+            contract: ctid_t,
+            zone: zoneid_t,
+        },
+        fault: extern struct {
+            addr: ?*c_void,
+            trapno: c_int,
+            pc: ?*c_void,
+        },
+        file: extern struct {
+            // fd not currently available for SIGPOLL.
+            fd: c_int,
+            band: c_long,
+        },
+        prof: extern struct {
+            addr: ?*c_void,
+            timestamp: timespec,
+            syscall: c_short,
+            sysarg: u8,
+            fault: u8,
+            args: [8]c_long,
+            state: [10]c_int,
+        },
+        rctl: extern struct {
+            entity: i32,
+        },
+        __pad: [256 - 4 * @sizeOf(c_int)]u8,
+    } align(@sizeOf(usize)),
+};
+
+comptime {
+    std.debug.assert(@sizeOf(siginfo_t) == 256);
+    std.debug.assert(@alignOf(siginfo_t) == @sizeOf(usize));
+}
+
+pub const sigset_t = extern struct {
+    __bits: [SIG.WORDS]u32,
+};
+
+pub const empty_sigset = sigset_t{ .__bits = [_]u32{0} ** SIG.WORDS };
+
+pub const fpregset_t = extern union {
+    regs: [130]u32,
+    chip_state: extern struct {
+        cw: u16,
+        sw: u16,
+        fctw: u8,
+        __fx_rsvd: u8,
+        fop: u16,
+        rip: u64,
+        rdp: u64,
+        mxcsr: u32,
+        mxcsr_mask: u32,
+        st: [8]extern union {
+            fpr_16: [5]u16,
+            __fpr_pad: u128,
+        },
+        xmm: [16]u128,
+        __fx_ign2: [6]u128,
+        status: u32,
+        xstatus: u32,
+    },
+};
+
+pub const mcontext_t = extern struct {
+    gregs: [28]u64,
+    fpregs: fpregset_t,
+};
+
+pub const REG = struct {
+    pub const RBP = 10;
+    pub const RIP = 17;
+    pub const RSP = 20;
+};
+
+pub const ucontext_t = extern struct {
+    flags: u64,
+    link: ?*ucontext_t,
+    sigmask: sigset_t,
+    stack: stack_t,
+    mcontext: mcontext_t,
+    brand_data: [3]?*c_void,
+    filler: [2]i64,
+};
+
+pub const GETCONTEXT = 0;
+pub const SETCONTEXT = 1;
+pub const GETUSTACK = 2;
+pub const SETUSTACK = 3;
+
+pub const E = enum(u16) {
+    /// No error occurred.
+    SUCCESS = 0,
+    /// Not super-user
+    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 children
+    CHILD = 10,
+    /// Resource temporarily unavailable.
+    /// also: WOULDBLOCK: Operation would block.
+    AGAIN = 11,
+    /// Not enough core
+    NOMEM = 12,
+    /// Permission denied
+    ACCES = 13,
+    /// Bad address
+    FAULT = 14,
+    /// Block device required
+    NOTBLK = 15,
+    /// Mount device 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,
+    /// Inappropriate ioctl for device
+    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 arg out of domain of func
+    DOM = 33,
+    /// Math result not representable
+    RANGE = 34,
+    /// No message of desired type
+    NOMSG = 35,
+    /// Identifier removed
+    IDRM = 36,
+    /// Channel number out of range
+    CHRNG = 37,
+    /// Level 2 not synchronized
+    L2NSYNC = 38,
+    /// Level 3 halted
+    L3HLT = 39,
+    /// Level 3 reset
+    L3RST = 40,
+    /// Link number out of range
+    LNRNG = 41,
+    /// Protocol driver not attached
+    UNATCH = 42,
+    /// No CSI structure available
+    NOCSI = 43,
+    /// Level 2 halted
+    L2HLT = 44,
+    /// Deadlock condition.
+    DEADLK = 45,
+    /// No record locks available.
+    NOLCK = 46,
+    /// Operation canceled
+    CANCELED = 47,
+    /// Operation not supported
+    NOTSUP = 48,
+
+    // Filesystem Quotas
+    /// Disc quota exceeded
+    DQUOT = 49,
+
+    // Convergent Error Returns
+    /// invalid exchange
+    BADE = 50,
+    /// invalid request descriptor
+    BADR = 51,
+    /// exchange full
+    XFULL = 52,
+    /// no anode
+    NOANO = 53,
+    /// invalid request code
+    BADRQC = 54,
+    /// invalid slot
+    BADSLT = 55,
+    /// file locking deadlock error
+    DEADLOCK = 56,
+    /// bad font file fmt
+    BFONT = 57,
+
+    // Interprocess Robust Locks
+    /// process died with the lock
+    OWNERDEAD = 58,
+    /// lock is not recoverable
+    NOTRECOVERABLE = 59,
+    /// locked lock was unmapped
+    LOCKUNMAPPED = 72,
+    /// Facility is not active
+    NOTACTIVE = 73,
+    /// multihop attempted
+    MULTIHOP = 74,
+    /// trying to read unreadable message
+    BADMSG = 77,
+    /// path name is too long
+    NAMETOOLONG = 78,
+    /// value too large to be stored in data type
+    OVERFLOW = 79,
+    /// given log. name not unique
+    NOTUNIQ = 80,
+    /// f.d. invalid for this operation
+    BADFD = 81,
+    /// Remote address changed
+    REMCHG = 82,
+
+    // Stream Problems
+    /// Device not a stream
+    NOSTR = 60,
+    /// no data (for no delay io)
+    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,
+    /// The object is remote
+    REMOTE = 66,
+    /// the link has been severed
+    NOLINK = 67,
+    /// advertise error
+    ADV = 68,
+    /// srmount error
+    SRMNT = 69,
+    /// Communication error on send
+    COMM = 70,
+    /// Protocol error
+    PROTO = 71,
+
+    // Shared Library Problems
+    /// Can't access a needed shared lib.
+    LIBACC = 83,
+    /// Accessing a corrupted shared lib.
+    LIBBAD = 84,
+    /// .lib section in a.out corrupted.
+    LIBSCN = 85,
+    /// Attempting to link in too many libs.
+    LIBMAX = 86,
+    /// Attempting to exec a shared library.
+    LIBEXEC = 87,
+    /// Illegal byte sequence.
+    ILSEQ = 88,
+    /// Unsupported file system operation
+    NOSYS = 89,
+    /// Symbolic link loop
+    LOOP = 90,
+    /// Restartable system call
+    RESTART = 91,
+    /// if pipe/FIFO, don't sleep in stream head
+    STRPIPE = 92,
+    /// directory not empty
+    NOTEMPTY = 93,
+    /// Too many users (for UFS)
+    USERS = 94,
+
+    // BSD Networking Software
+    // Argument Errors
+    /// Socket operation on non-socket
+    NOTSOCK = 95,
+    /// Destination address required
+    DESTADDRREQ = 96,
+    /// Message too long
+    MSGSIZE = 97,
+    /// Protocol wrong type for socket
+    PROTOTYPE = 98,
+    /// Protocol not available
+    NOPROTOOPT = 99,
+    /// Protocol not supported
+    PROTONOSUPPORT = 120,
+    /// Socket type not supported
+    SOCKTNOSUPPORT = 121,
+    /// Operation not supported on socket
+    OPNOTSUPP = 122,
+    /// Protocol family not supported
+    PFNOSUPPORT = 123,
+    /// Address family not supported by
+    AFNOSUPPORT = 124,
+    /// Address already in use
+    ADDRINUSE = 125,
+    /// Can't assign requested address
+    ADDRNOTAVAIL = 126,
+
+    // Operational Errors
+    /// Network is down
+    NETDOWN = 127,
+    /// Network is unreachable
+    NETUNREACH = 128,
+    /// Network dropped connection because
+    NETRESET = 129,
+    /// Software caused connection abort
+    CONNABORTED = 130,
+    /// Connection reset by peer
+    CONNRESET = 131,
+    /// No buffer space available
+    NOBUFS = 132,
+    /// Socket is already connected
+    ISCONN = 133,
+    /// Socket is not connected
+    NOTCONN = 134,
+    /// Can't send after socket shutdown
+    SHUTDOWN = 143,
+    /// Too many references: can't splice
+    TOOMANYREFS = 144,
+    /// Connection timed out
+    TIMEDOUT = 145,
+    /// Connection refused
+    CONNREFUSED = 146,
+    /// Host is down
+    HOSTDOWN = 147,
+    /// No route to host
+    HOSTUNREACH = 148,
+    /// operation already in progress
+    ALREADY = 149,
+    /// operation now in progress
+    INPROGRESS = 150,
+
+    // SUN Network File System
+    /// Stale NFS file handle
+    STALE = 151,
+
+    _,
+};
+
+pub const MINSIGSTKSZ = 2048;
+pub const SIGSTKSZ = 8192;
+
+pub const SS_ONSTACK = 0x1;
+pub const SS_DISABLE = 0x2;
+
+pub const stack_t = extern struct {
+    sp: [*]u8,
+    size: isize,
+    flags: i32,
+};
+
+pub const S = struct {
+    pub const IFMT = 0o170000;
+
+    pub const IFIFO = 0o010000;
+    pub const IFCHR = 0o020000;
+    pub const IFDIR = 0o040000;
+    pub const IFBLK = 0o060000;
+    pub const IFREG = 0o100000;
+    pub const IFLNK = 0o120000;
+    pub const IFSOCK = 0o140000;
+    /// SunOS 2.6 Door
+    pub const IFDOOR = 0o150000;
+    /// Solaris 10 Event Port
+    pub const IFPORT = 0o160000;
+
+    pub const ISUID = 0o4000;
+    pub const ISGID = 0o2000;
+    pub const ISVTX = 0o1000;
+    pub const IRWXU = 0o700;
+    pub const IRUSR = 0o400;
+    pub const IWUSR = 0o200;
+    pub const IXUSR = 0o100;
+    pub const IRWXG = 0o070;
+    pub const IRGRP = 0o040;
+    pub const IWGRP = 0o020;
+    pub const IXGRP = 0o010;
+    pub const IRWXO = 0o007;
+    pub const IROTH = 0o004;
+    pub const IWOTH = 0o002;
+    pub const IXOTH = 0o001;
+
+    pub fn ISFIFO(m: u32) bool {
+        return m & IFMT == IFIFO;
+    }
+
+    pub fn ISCHR(m: u32) bool {
+        return m & IFMT == IFCHR;
+    }
+
+    pub fn ISDIR(m: u32) bool {
+        return m & IFMT == IFDIR;
+    }
+
+    pub fn ISBLK(m: u32) bool {
+        return m & IFMT == IFBLK;
+    }
+
+    pub fn ISREG(m: u32) bool {
+        return m & IFMT == IFREG;
+    }
+
+    pub fn ISLNK(m: u32) bool {
+        return m & IFMT == IFLNK;
+    }
+
+    pub fn ISSOCK(m: u32) bool {
+        return m & IFMT == IFSOCK;
+    }
+
+    pub fn ISDOOR(m: u32) bool {
+        return m & IFMT == IFDOOR;
+    }
+
+    pub fn ISPORT(m: u32) bool {
+        return m & IFMT == IFPORT;
+    }
+};
+
+pub const AT = struct {
+    /// Magic value that specify the use of the current working directory
+    /// to determine the target of relative file paths in the openat() and
+    /// similar syscalls.
+    pub const FDCWD = @bitCast(fd_t, @as(u32, 0xffd19553));
+
+    /// Do not follow symbolic links
+    pub const SYMLINK_NOFOLLOW = 0x1000;
+    /// Follow symbolic link
+    pub const SYMLINK_FOLLOW = 0x2000;
+    /// Remove directory instead of file
+    pub const REMOVEDIR = 0x1;
+    pub const TRIGGER = 0x2;
+    /// Check access using effective user and group ID
+    pub const EACCESS = 0x4;
+};
+
+pub const POSIX_FADV = 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 HOST_NAME_MAX = 255;
+
+pub const IPPROTO = struct {
+    /// dummy for IP
+    pub const IP = 0;
+    /// Hop by hop header for IPv6
+    pub const HOPOPTS = 0;
+    /// control message protocol
+    pub const ICMP = 1;
+    /// group control protocol
+    pub const IGMP = 2;
+    /// gateway^2 (deprecated)
+    pub const GGP = 3;
+    /// IP in IP encapsulation
+    pub const ENCAP = 4;
+    /// tcp
+    pub const TCP = 6;
+    /// exterior gateway protocol
+    pub const EGP = 8;
+    /// pup
+    pub const PUP = 12;
+    /// user datagram protocol
+    pub const UDP = 17;
+    /// xns idp
+    pub const IDP = 22;
+    /// IPv6 encapsulated in IP
+    pub const IPV6 = 41;
+    /// Routing header for IPv6
+    pub const ROUTING = 43;
+    /// Fragment header for IPv6
+    pub const FRAGMENT = 44;
+    /// rsvp
+    pub const RSVP = 46;
+    /// IPsec Encap. Sec. Payload
+    pub const ESP = 50;
+    /// IPsec Authentication Hdr.
+    pub const AH = 51;
+    /// ICMP for IPv6
+    pub const ICMPV6 = 58;
+    /// No next header for IPv6
+    pub const NONE = 59;
+    /// Destination options
+    pub const DSTOPTS = 60;
+    /// "hello" routing protocol
+    pub const HELLO = 63;
+    /// UNOFFICIAL net disk proto
+    pub const ND = 77;
+    /// ISO clnp
+    pub const EON = 80;
+    /// OSPF
+    pub const OSPF = 89;
+    /// PIM routing protocol
+    pub const PIM = 103;
+    /// Stream Control
+    pub const SCTP = 132;
+    /// raw IP packet
+    pub const RAW = 255;
+    /// Sockets Direct Protocol
+    pub const PROTO_SDP = 257;
+};
+
+pub const priority = enum(c_int) {
+    PROCESS = 0,
+    PGRP = 1,
+    USER = 2,
+    GROUP = 3,
+    SESSION = 4,
+    LWP = 5,
+    TASK = 6,
+    PROJECT = 7,
+    ZONE = 8,
+    CONTRACT = 9,
+};
+
+pub const rlimit_resource = enum(c_int) {
+    CPU = 0,
+    FSIZE = 1,
+    DATA = 2,
+    STACK = 3,
+    CORE = 4,
+    NOFILE = 5,
+    VMEM = 6,
+    _,
+
+    pub const AS: rlimit_resource = .VMEM;
+};
+
+pub const rlim_t = u64;
+
+pub const RLIM = struct {
+    /// No limit
+    pub const INFINITY: rlim_t = (1 << 63) - 3;
+    pub const SAVED_MAX: rlim_t = (1 << 63) - 2;
+    pub const SAVED_CUR: rlim_t = (1 << 63) - 1;
+};
+
+pub const rlimit = extern struct {
+    /// Soft limit
+    cur: rlim_t,
+    /// Hard limit
+    max: rlim_t,
+};
+
+pub const RUSAGE_SELF = 0;
+pub const RUSAGE_CHILDREN = -1;
+pub const RUSAGE_THREAD = 1;
+
+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,
+};
+
+pub const SHUT = struct {
+    pub const RD = 0;
+    pub const WR = 1;
+    pub const RDWR = 2;
+};
+
+pub const pollfd = extern struct {
+    fd: fd_t,
+    events: i16,
+    revents: i16,
+};
+
+/// Testable events (may be specified in ::pollfd::events).
+pub const POLL = struct {
+    pub const IN = 0x0001;
+    pub const PRI = 0x0002;
+    pub const OUT = 0x0004;
+    pub const RDNORM = 0x0040;
+    pub const WRNORM = .OUT;
+    pub const RDBAND = 0x0080;
+    pub const WRBAND = 0x0100;
+    /// Read-side hangup.
+    pub const RDHUP = 0x4000;
+
+    /// Non-testable events (may not be specified in events).
+    pub const ERR = 0x0008;
+    pub const HUP = 0x0010;
+    pub const NVAL = 0x0020;
+
+    /// Events to control `/dev/poll` (not specified in revents)
+    pub const REMOVE = 0x0800;
+    pub const ONESHOT = 0x1000;
+    pub const ET = 0x2000;
+};
+
+/// Extensions to the ELF auxiliary vector.
+pub const AT_SUN = struct {
+    /// effective user id
+    pub const UID = 2000;
+    /// real user id
+    pub const RUID = 2001;
+    /// effective group id
+    pub const GID = 2002;
+    /// real group id
+    pub const RGID = 2003;
+    /// dynamic linker's ELF header
+    pub const LDELF = 2004;
+    /// dynamic linker's section headers
+    pub const LDSHDR = 2005;
+    /// name of dynamic linker
+    pub const LDNAME = 2006;
+    /// large pagesize
+    pub const LPAGESZ = 2007;
+    /// platform name
+    pub const PLATFORM = 2008;
+    /// hints about hardware capabilities.
+    pub const HWCAP = 2009;
+    pub const HWCAP2 = 2023;
+    /// flush icache?
+    pub const IFLUSH = 2010;
+    /// cpu name
+    pub const CPU = 2011;
+    /// exec() path name in the auxv, null terminated.
+    pub const EXECNAME = 2014;
+    /// mmu module name
+    pub const MMU = 2015;
+    /// dynamic linkers data segment
+    pub const LDDATA = 2016;
+    /// AF_SUN_ flags passed from the kernel
+    pub const AUXFLAGS = 2017;
+    /// name of the emulation binary for the linker
+    pub const EMULATOR = 2018;
+    /// name of the brand library for the linker
+    pub const BRANDNAME = 2019;
+    /// vectors for brand modules.
+    pub const BRAND_AUX1 = 2020;
+    pub const BRAND_AUX2 = 2021;
+    pub const BRAND_AUX3 = 2022;
+    pub const BRAND_AUX4 = 2025;
+    pub const BRAND_NROOT = 2024;
+    /// vector for comm page.
+    pub const COMMPAGE = 2026;
+    /// information about the x86 FPU.
+    pub const FPTYPE = 2027;
+    pub const FPSIZE = 2028;
+};
+
+/// ELF auxiliary vector flags.
+pub const AF_SUN = struct {
+    /// tell ld.so.1 to run "secure" and ignore the environment.
+    pub const SETUGID = 0x00000001;
+    /// hardware capabilities can be verified against AT_SUN_HWCAP
+    pub const HWCAPVERIFY = 0x00000002;
+    pub const NOPLM = 0x00000004;
+};
+
+// TODO: Add sysconf numbers when the other OSs do.
+pub const _SC = struct {
+    pub const NPROCESSORS_ONLN = 15;
+};
+
+pub const procfs = struct {
+    pub const misc_header = extern struct {
+        size: u32,
+        @"type": enum(u32) {
+            Pathname,
+            Socketname,
+            Peersockname,
+            SockoptsBoolOpts,
+            SockoptLinger,
+            SockoptSndbuf,
+            SockoptRcvbuf,
+            SockoptIpNexthop,
+            SockoptIpv6Nexthop,
+            SockoptType,
+            SockoptTcpCongestion,
+            SockfiltersPriv = 14,
+        },
+    };
+
+    pub const fdinfo = extern struct {
+        fd: fd_t,
+        mode: mode_t,
+        ino: ino_t,
+        size: off_t,
+        offset: off_t,
+        uid: uid_t,
+        gid: gid_t,
+        dev_major: major_t,
+        dev_minor: minor_t,
+        special_major: major_t,
+        special_minor: minor_t,
+        fileflags: i32,
+        fdflags: i32,
+        locktype: i16,
+        lockpid: pid_t,
+        locksysid: i32,
+        peerpid: pid_t,
+        __filler: [25]c_int,
+        peername: [15:0]u8,
+        misc: [1]u8,
+    };
+};
+
+pub const SFD = struct {
+    pub const CLOEXEC = 0o2000000;
+    pub const NONBLOCK = 0o4000;
+};
+
+pub const signalfd_siginfo = extern struct {
+    signo: u32,
+    errno: i32,
+    code: i32,
+    pid: u32,
+    uid: uid_t,
+    fd: i32,
+    tid: u32, // unused
+    band: u32,
+    overrun: u32, // unused
+    trapno: u32,
+    status: i32,
+    int: i32, // unused
+    ptr: u64, // unused
+    utime: u64,
+    stime: u64,
+    addr: u64,
+    __pad: [48]u8,
+};
+
+pub const PORT_SOURCE = struct {
+    pub const AIO = 1;
+    pub const TIMER = 2;
+    pub const USER = 3;
+    pub const FD = 4;
+    pub const ALERT = 5;
+    pub const MQ = 6;
+    pub const FILE = 7;
+};
+
+pub const PORT_ALERT = struct {
+    pub const SET = 0x01;
+    pub const UPDATE = 0x02;
+};
+
+/// User watchable file events.
+pub const FILE_EVENT = struct {
+    pub const ACCESS = 0x00000001;
+    pub const MODIFIED = 0x00000002;
+    pub const ATTRIB = 0x00000004;
+    pub const DELETE = 0x00000010;
+    pub const RENAME_TO = 0x00000020;
+    pub const RENAME_FROM = 0x00000040;
+    pub const TRUNC = 0x00100000;
+    pub const NOFOLLOW = 0x10000000;
+    /// The filesystem holding the watched file was unmounted.
+    pub const UNMOUNTED = 0x20000000;
+    /// Some other file/filesystem got mounted over the watched file/directory.
+    pub const MOUNTEDOVER = 0x40000000;
+
+    pub fn isException(event: u32) bool {
+        return event & (UNMOUNTED | DELETE | RENAME_TO | RENAME_FROM | MOUNTEDOVER) > 0;
+    }
+};
+
+pub const port_event = extern struct {
+    events: u32,
+    /// Event source.
+    source: u16,
+    __pad: u16,
+    /// Source-specific object.
+    object: ?*c_void,
+    /// User cookie.
+    cookie: ?*c_void,
+};
+
+pub const port_notify = extern struct {
+    /// Bind request(s) to port.
+    port: u32,
+    /// User defined variable.
+    user: ?*void,
+};
+
+pub const file_obj = extern struct {
+    /// Access time.
+    atim: timespec,
+    /// Modification time
+    mtim: timespec,
+    /// Change time
+    ctim: timespec,
+    __pad: [3]usize,
+    name: [*:0]u8,
+};
+
+// struct ifreq is marked obsolete, with struct lifreq prefered for interface requests.
+// Here we alias lifreq to ifreq to avoid chainging existing code in os and x.os.IPv6.
+pub const SIOCGLIFINDEX = IOWR('i', 133, lifreq);
+pub const SIOCGIFINDEX = SIOCGLIFINDEX;
+pub const MAX_HDW_LEN = 64;
+pub const IFNAMESIZE = 32;
+
+pub const lif_nd_req = extern struct {
+    addr: sockaddr.storage,
+    state_create: u8,
+    state_same_lla: u8,
+    state_diff_lla: u8,
+    hdw_len: i32,
+    flags: i32,
+    __pad: i32,
+    hdw_addr: [MAX_HDW_LEN]u8,
+};
+
+pub const lif_ifinfo_req = extern struct {
+    maxhops: u8,
+    reachtime: u32,
+    reachretrans: u32,
+    maxmtu: u32,
+};
+
+/// IP interface request. See if_tcp(7p) for more info.
+pub const lifreq = extern struct {
+    // Not actually in a union, but the stdlib expects one for ifreq
+    ifrn: extern union {
+        /// Interface name, e.g. "lo0", "en0".
+        name: [IFNAMESIZE]u8,
+    },
+    ru1: extern union {
+        /// For subnet/token etc.
+        addrlen: i32,
+        /// Driver's PPA (physical point of attachment).
+        ppa: u32,
+    },
+    /// One of the IFT types, e.g. IFT_ETHER.
+    @"type": u32,
+    ifru: extern union {
+        /// Address.
+        addr: sockaddr.storage,
+        /// Other end of a peer-to-peer link.
+        dstaddr: sockaddr.storage,
+        /// Broadcast address.
+        broadaddr: sockaddr.storage,
+        /// Address token.
+        token: sockaddr.storage,
+        /// Subnet prefix.
+        subnet: sockaddr.storage,
+        /// Interface index.
+        ivalue: i32,
+        /// Flags for SIOC?LIFFLAGS.
+        flags: u64,
+        /// Hop count metric
+        metric: i32,
+        /// Maximum transmission unit
+        mtu: u32,
+        // Technically [2]i32
+        muxid: packed struct { ip: i32, arp: i32 },
+        /// Neighbor reachability determination entries
+        nd_req: lif_nd_req,
+        /// Link info
+        ifinfo_req: lif_ifinfo_req,
+        /// Name of the multipath interface group
+        groupname: [IFNAMESIZE]u8,
+        binding: [IFNAMESIZE]u8,
+        /// Zone id associated with this interface.
+        zoneid: zoneid_t,
+        /// Duplicate address detection state. Either in progress or completed.
+        dadstate: u32,
+    },
+};
+
+pub const ifreq = lifreq;
+
+const IoCtlCommand = enum(u32) {
+    none = 0x20000000, // no parameters
+    write = 0x40000000, // copy out parameters
+    read = 0x80000000, // copy in parameters
+    read_write = 0xc0000000,
+};
+
+fn ioImpl(cmd: IoCtlCommand, io_type: u8, nr: u8, comptime IOT: type) i32 {
+    const size = @intCast(u32, @truncate(u8, @sizeOf(IOT))) << 16;
+    const t = @intCast(u32, io_type) << 8;
+    return @bitCast(i32, @enumToInt(cmd) | size | t | nr);
+}
+
+pub fn IO(io_type: u8, nr: u8) i32 {
+    return ioImpl(.none, io_type, nr, void);
+}
+
+pub fn IOR(io_type: u8, nr: u8, comptime IOT: type) i32 {
+    return ioImpl(.write, io_type, nr, IOT);
+}
+
+pub fn IOW(io_type: u8, nr: u8, comptime IOT: type) i32 {
+    return ioImpl(.read, io_type, nr, IOT);
+}
+
+pub fn IOWR(io_type: u8, nr: u8, comptime IOT: type) i32 {
+    return ioImpl(.read_write, io_type, nr, IOT);
+}
lib/std/fs/file.zig
@@ -41,6 +41,8 @@ pub const File = struct {
         File,
         UnixDomainSocket,
         Whiteout,
+        Door,
+        EventPort,
         Unknown,
     };
 
@@ -320,28 +322,40 @@ pub const File = struct {
         const atime = st.atime();
         const mtime = st.mtime();
         const ctime = st.ctime();
+        const kind: Kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) {
+            .BLOCK_DEVICE => Kind.BlockDevice,
+            .CHARACTER_DEVICE => Kind.CharacterDevice,
+            .DIRECTORY => Kind.Directory,
+            .SYMBOLIC_LINK => Kind.SymLink,
+            .REGULAR_FILE => Kind.File,
+            .SOCKET_STREAM, .SOCKET_DGRAM => Kind.UnixDomainSocket,
+            else => Kind.Unknown,
+        } else blk: {
+            const m = st.mode & os.S.IFMT;
+            switch (m) {
+                os.S.IFBLK => break :blk Kind.BlockDevice,
+                os.S.IFCHR => break :blk Kind.CharacterDevice,
+                os.S.IFDIR => break :blk Kind.Directory,
+                os.S.IFIFO => break :blk Kind.NamedPipe,
+                os.S.IFLNK => break :blk Kind.SymLink,
+                os.S.IFREG => break :blk Kind.File,
+                os.S.IFSOCK => break :blk Kind.UnixDomainSocket,
+                else => {},
+            }
+            if (builtin.os.tag == .solaris) switch (m) {
+                os.S.IFDOOR => break :blk Kind.Door,
+                os.S.IFPORT => break :blk Kind.EventPort,
+                else => {},
+            };
+
+            break :blk .Unknown;
+        };
+
         return Stat{
             .inode = st.ino,
             .size = @bitCast(u64, st.size),
             .mode = st.mode,
-            .kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) {
-                .BLOCK_DEVICE => Kind.BlockDevice,
-                .CHARACTER_DEVICE => Kind.CharacterDevice,
-                .DIRECTORY => Kind.Directory,
-                .SYMBOLIC_LINK => Kind.SymLink,
-                .REGULAR_FILE => Kind.File,
-                .SOCKET_STREAM, .SOCKET_DGRAM => Kind.UnixDomainSocket,
-                else => Kind.Unknown,
-            } else switch (st.mode & os.S.IFMT) {
-                os.S.IFBLK => Kind.BlockDevice,
-                os.S.IFCHR => Kind.CharacterDevice,
-                os.S.IFDIR => Kind.Directory,
-                os.S.IFIFO => Kind.NamedPipe,
-                os.S.IFLNK => Kind.SymLink,
-                os.S.IFREG => Kind.File,
-                os.S.IFSOCK => Kind.UnixDomainSocket,
-                else => Kind.Unknown,
-            },
+            .kind = kind,
             .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
             .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
             .ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
lib/std/fs/get_app_data_dir.zig
@@ -44,7 +44,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
             };
             return fs.path.join(allocator, &[_][]const u8{ home_dir, "Library", "Application Support", appname });
         },
-        .linux, .freebsd, .netbsd, .dragonfly, .openbsd => {
+        .linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris => {
             const home_dir = os.getenv("HOME") orelse {
                 // TODO look in /etc/passwd
                 return error.AppDataDirUnavailable;
lib/std/fs/test.zig
@@ -188,7 +188,7 @@ fn contains(entries: *const std.ArrayList(Dir.Entry), el: Dir.Entry) bool {
 
 test "Dir.realpath smoke test" {
     switch (builtin.os.tag) {
-        .linux, .windows, .macos, .ios, .watchos, .tvos => {},
+        .linux, .windows, .macos, .ios, .watchos, .tvos, .solaris => {},
         else => return error.SkipZigTest,
     }
 
lib/std/os/test.zig
@@ -188,7 +188,10 @@ fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {
 }
 
 test "link with relative paths" {
-    if (native_os != .linux) return error.SkipZigTest;
+    switch (native_os) {
+        .linux, .solaris => {},
+        else => return error.SkipZigTest,
+    }
     var cwd = fs.cwd();
 
     cwd.deleteFile("example.txt") catch {};
@@ -222,7 +225,10 @@ test "link with relative paths" {
 }
 
 test "linkat with different directories" {
-    if (native_os != .linux) return error.SkipZigTest;
+    switch (native_os) {
+        .linux, .solaris => {},
+        else => return error.SkipZigTest,
+    }
     var cwd = fs.cwd();
     var tmp = tmpDir(.{});
 
@@ -634,8 +640,10 @@ test "fcntl" {
 }
 
 test "signalfd" {
-    if (native_os != .linux)
-        return error.SkipZigTest;
+    switch (native_os) {
+        .linux, .solaris => {},
+        else => return error.SkipZigTest,
+    }
     _ = std.os.signalfd;
 }
 
@@ -658,8 +666,10 @@ test "sync" {
 }
 
 test "fsync" {
-    if (native_os != .linux and native_os != .windows)
-        return error.SkipZigTest;
+    switch (native_os) {
+        .linux, .windows, .solaris => {},
+        else => return error.SkipZigTest,
+    }
 
     var tmp = tmpDir(.{});
     defer tmp.cleanup();
@@ -754,7 +764,10 @@ test "sigaction" {
 }
 
 test "dup & dup2" {
-    if (native_os != .linux) return error.SkipZigTest;
+    switch (native_os) {
+        .linux, .solaris => {},
+        else => return error.SkipZigTest,
+    }
 
     var tmp = tmpDir(.{});
     defer tmp.cleanup();
lib/std/zig/system.zig
@@ -101,6 +101,17 @@ pub const NativePaths = struct {
             return self;
         }
 
+        if (comptime native_target.os.tag == .solaris) {
+            try self.addLibDir("/usr/lib/64");
+            try self.addLibDir("/usr/local/lib/64");
+            try self.addLibDir("/lib/64");
+
+            try self.addIncludeDir("/usr/include");
+            try self.addIncludeDir("/usr/local/include");
+
+            return self;
+        }
+
         if (native_target.os.tag != .windows) {
             const triple = try native_target.linuxTriple(allocator);
             const qual = native_target.cpu.arch.ptrBitWidth();
@@ -243,6 +254,18 @@ pub const NativeTargetInfo = struct {
                         error.InvalidVersion => {},
                     }
                 },
+                .solaris => {
+                    const uts = std.os.uname();
+                    const release = mem.spanZ(&uts.release);
+                    if (std.builtin.Version.parse(release)) |ver| {
+                        os.version_range.semver.min = ver;
+                        os.version_range.semver.max = ver;
+                    } else |err| switch (err) {
+                        error.Overflow => {},
+                        error.InvalidCharacter => {},
+                        error.InvalidVersion => {},
+                    }
+                },
                 .windows => {
                     const detected_version = windows.detectRuntimeVersion();
                     os.version_range.windows.min = detected_version;
lib/std/c.zig
@@ -252,6 +252,33 @@ pub extern "c" fn kevent(
     timeout: ?*const c.timespec,
 ) c_int;
 
+pub extern "c" fn port_create() c.port_t;
+pub extern "c" fn port_associate(
+    port: c.port_t,
+    source: u32,
+    object: usize,
+    events: u32,
+    user_var: ?*c_void,
+) c_int;
+pub extern "c" fn port_dissociate(port: c.port_t, source: u32, object: usize) c_int;
+pub extern "c" fn port_send(port: c.port_t, events: u32, user_var: ?*c_void) c_int;
+pub extern "c" fn port_sendn(
+    ports: [*]c.port_t,
+    errors: []u32,
+    num_ports: u32,
+    events: u32,
+    user_var: ?*c_void,
+) c_int;
+pub extern "c" fn port_get(port: c.port_t, event: *c.port_event, timeout: ?*c.timespec) c_int;
+pub extern "c" fn port_getn(
+    port: c.port_t,
+    event_list: []c.port_event,
+    max_events: u32,
+    events_retrieved: *u32,
+    timeout: ?*c.timespec,
+) c_int;
+pub extern "c" fn port_alert(port: c.port_t, flags: u32, events: u32, user_var: ?*c_void) c_int;
+
 pub extern "c" fn getaddrinfo(
     noalias node: ?[*:0]const u8,
     noalias service: ?[*:0]const u8,
lib/std/debug.zig
@@ -654,6 +654,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
             .openbsd,
             .macos,
             .windows,
+            .solaris,
             => return DebugInfo.init(allocator),
             else => return error.UnsupportedDebugInfo,
         }
@@ -1420,7 +1421,7 @@ pub const ModuleDebugInfo = switch (native_os) {
             };
         }
     },
-    .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku => struct {
+    .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct {
         base_address: usize,
         dwarf: DW.DwarfInfo,
         mapped_memory: []const u8,
@@ -1468,7 +1469,7 @@ fn getDebugInfoAllocator() *mem.Allocator {
 
 /// Whether or not the current target can print useful debug information when a segfault occurs.
 pub const have_segfault_handling_support = switch (native_os) {
-    .linux, .netbsd => true,
+    .linux, .netbsd, .solaris => true,
     .windows => true,
     .freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"),
     else => false,
@@ -1535,6 +1536,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v
         .freebsd => @ptrToInt(info.addr),
         .netbsd => @ptrToInt(info.info.reason.fault.addr),
         .openbsd => @ptrToInt(info.data.fault.addr),
+        .solaris => @ptrToInt(info.reason.fault.addr),
         else => unreachable,
     };
 
@@ -1559,13 +1561,13 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const c_v
         .x86_64 => {
             const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
             const ip = switch (native_os) {
-                .linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]),
+                .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]),
                 .freebsd => @intCast(usize, ctx.mcontext.rip),
                 .openbsd => @intCast(usize, ctx.sc_rip),
                 else => unreachable,
             };
             const bp = switch (native_os) {
-                .linux, .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]),
+                .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]),
                 .openbsd => @intCast(usize, ctx.sc_rbp),
                 .freebsd => @intCast(usize, ctx.mcontext.rbp),
                 else => unreachable,
lib/std/dynamic_library.zig
@@ -14,7 +14,7 @@ const max = std.math.max;
 pub const DynLib = switch (builtin.os.tag) {
     .linux => if (builtin.link_libc) DlDynlib else ElfDynLib,
     .windows => WindowsDynLib,
-    .macos, .tvos, .watchos, .ios, .freebsd, .netbsd, .openbsd, .dragonfly => DlDynlib,
+    .macos, .tvos, .watchos, .ios, .freebsd, .netbsd, .openbsd, .dragonfly, .solaris => DlDynlib,
     else => void,
 };
 
lib/std/fs.zig
@@ -35,7 +35,7 @@ pub const Watch = @import("fs/watch.zig").Watch;
 /// fit into a UTF-8 encoded array of this length.
 /// The byte count includes room for a null sentinel byte.
 pub const MAX_PATH_BYTES = switch (builtin.os.tag) {
-    .linux, .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .haiku => os.PATH_MAX,
+    .linux, .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .haiku, .solaris => os.PATH_MAX,
     // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
     // If it would require 4 UTF-8 bytes, then there would be a surrogate
     // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
@@ -298,10 +298,10 @@ pub const Dir = struct {
         pub const Kind = File.Kind;
     };
 
-    const IteratorError = error{AccessDenied} || os.UnexpectedError;
+    const IteratorError = error{ AccessDenied, SystemResources } || os.UnexpectedError;
 
     pub const Iterator = switch (builtin.os.tag) {
-        .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd => struct {
+        .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris => struct {
             dir: Dir,
             seek: i64,
             buf: [8192]u8, // TODO align(@alignOf(os.system.dirent)),
@@ -318,6 +318,7 @@ pub const Dir = struct {
                 switch (builtin.os.tag) {
                     .macos, .ios => return self.nextDarwin(),
                     .freebsd, .netbsd, .dragonfly, .openbsd => return self.nextBsd(),
+                    .solaris => return self.nextSolaris(),
                     else => @compileError("unimplemented"),
                 }
             }
@@ -372,6 +373,60 @@ pub const Dir = struct {
                 }
             }
 
+            fn nextSolaris(self: *Self) !?Entry {
+                start_over: while (true) {
+                    if (self.index >= self.end_index) {
+                        const rc = os.system.getdents(self.dir.fd, &self.buf, self.buf.len);
+                        switch (os.errno(rc)) {
+                            .SUCCESS => {},
+                            .BADF => unreachable, // Dir is invalid or was opened without iteration ability
+                            .FAULT => unreachable,
+                            .NOTDIR => unreachable,
+                            .INVAL => unreachable,
+                            else => |err| return os.unexpectedErrno(err),
+                        }
+                        if (rc == 0) return null;
+                        self.index = 0;
+                        self.end_index = @intCast(usize, rc);
+                    }
+                    const entry = @ptrCast(*align(1) os.system.dirent, &self.buf[self.index]);
+                    const next_index = self.index + entry.reclen();
+                    self.index = next_index;
+
+                    const name = mem.spanZ(@ptrCast([*:0]u8, &entry.d_name));
+                    if (mem.eql(u8, name, ".") or mem.eql(u8, name, ".."))
+                        continue :start_over;
+
+                    // Solaris dirent doesn't expose d_type, so we have to call stat to get it.
+                    const stat_info = os.fstatat(
+                        self.dir.fd,
+                        name,
+                        os.AT.SYMLINK_NOFOLLOW,
+                    ) catch |err| switch (err) {
+                        error.NameTooLong => unreachable,
+                        error.SymLinkLoop => unreachable,
+                        error.FileNotFound => unreachable, // lost the race
+                        else => |e| return e,
+                    };
+                    const entry_kind = switch (stat_info.mode & os.S.IFMT) {
+                        os.S.IFIFO => Entry.Kind.NamedPipe,
+                        os.S.IFCHR => Entry.Kind.CharacterDevice,
+                        os.S.IFDIR => Entry.Kind.Directory,
+                        os.S.IFBLK => Entry.Kind.BlockDevice,
+                        os.S.IFREG => Entry.Kind.File,
+                        os.S.IFLNK => Entry.Kind.SymLink,
+                        os.S.IFSOCK => Entry.Kind.UnixDomainSocket,
+                        os.S.IFDOOR => Entry.Kind.Door,
+                        os.S.IFPORT => Entry.Kind.EventPort,
+                        else => Entry.Kind.Unknown,
+                    };
+                    return Entry{
+                        .name = name,
+                        .kind = entry_kind,
+                    };
+                }
+            }
+
             fn nextBsd(self: *Self) !?Entry {
                 start_over: while (true) {
                     if (self.index >= self.end_index) {
@@ -704,6 +759,7 @@ pub const Dir = struct {
             .netbsd,
             .dragonfly,
             .openbsd,
+            .solaris,
             => return Iterator{
                 .dir = self,
                 .seek = 0,
@@ -1556,7 +1612,7 @@ pub const Dir = struct {
             error.AccessDenied => |e| switch (builtin.os.tag) {
                 // non-Linux POSIX systems return EPERM when trying to delete a directory, so
                 // we need to handle that case specifically and translate the error
-                .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd => {
+                .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris => {
                     // Don't follow symlinks to match unlinkat (which acts on symlinks rather than follows them)
                     const fstat = os.fstatatZ(self.fd, sub_path_c, os.AT.SYMLINK_NOFOLLOW) catch return e;
                     const is_dir = fstat.mode & os.S.IFMT == os.S.IFDIR;
@@ -2441,6 +2497,7 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
     }
     switch (builtin.os.tag) {
         .linux => return os.readlinkZ("/proc/self/exe", out_buffer),
+        .solaris => return os.readlinkZ("/proc/self/path/a.out", out_buffer),
         .freebsd, .dragonfly => {
             var mib = [4]c_int{ os.CTL.KERN, os.KERN.PROC, os.KERN.PROC_PATHNAME, -1 };
             var out_len: usize = out_buffer.len;
lib/std/os.zig
@@ -31,6 +31,7 @@ pub const freebsd = std.c;
 pub const haiku = std.c;
 pub const netbsd = std.c;
 pub const openbsd = std.c;
+pub const solaris = std.c;
 pub const linux = @import("os/linux.zig");
 pub const uefi = @import("os/uefi.zig");
 pub const wasi = @import("os/wasi.zig");
@@ -64,8 +65,10 @@ else switch (builtin.os.tag) {
 };
 
 pub const AF = system.AF;
+pub const AF_SUN = system.AF_SUN;
 pub const ARCH = system.ARCH;
 pub const AT = system.AT;
+pub const AT_SUN = system.AT_SUN;
 pub const CLOCK = system.CLOCK;
 pub const CPU_COUNT = system.CPU_COUNT;
 pub const CTL = system.CTL;
@@ -101,6 +104,7 @@ pub const RR = system.RR;
 pub const S = system.S;
 pub const SA = system.SA;
 pub const SC = system.SC;
+pub const _SC = system._SC;
 pub const SEEK = system.SEEK;
 pub const SHUT = system.SHUT;
 pub const SIG = system.SIG;
@@ -143,6 +147,10 @@ pub const off_t = system.off_t;
 pub const oflags_t = system.oflags_t;
 pub const pid_t = system.pid_t;
 pub const pollfd = system.pollfd;
+pub const port_t = system.port_t;
+pub const port_event = system.port_event;
+pub const port_notify = system.port_notify;
+pub const file_obj = system.file_obj;
 pub const rights_t = system.rights_t;
 pub const rlim_t = system.rlim_t;
 pub const rlimit = system.rlimit;
@@ -2038,6 +2046,7 @@ pub fn unlinkatZ(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatEr
         .NOTDIR => return error.NotDir,
         .NOMEM => return error.SystemResources,
         .ROFS => return error.ReadOnlyFileSystem,
+        .EXIST => return error.DirNotEmpty,
         .NOTEMPTY => return error.DirNotEmpty,
 
         .INVAL => unreachable, // invalid flags, or pathname has . as last component
@@ -4667,6 +4676,16 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
             };
             return target;
         },
+        .solaris => {
+            var procfs_buf: ["/proc/self/path/-2147483648".len:0]u8 = undefined;
+            const proc_path = std.fmt.bufPrintZ(procfs_buf[0..], "/proc/self/path/{d}", .{fd}) catch unreachable;
+
+            const target = readlinkZ(proc_path, out_buffer) catch |err| switch (err) {
+                error.UnsupportedReparsePointType => unreachable,
+                else => |e| return e,
+            };
+            return target;
+        },
         else => @compileError("querying for canonical path of a handle is unsupported on this host"),
     }
 }
lib/std/process.zig
@@ -625,7 +625,7 @@ pub const UserInfo = struct {
 /// POSIX function which gets a uid from username.
 pub fn getUserInfo(name: []const u8) !UserInfo {
     return switch (builtin.os.tag) {
-        .linux, .macos, .watchos, .tvos, .ios, .freebsd, .netbsd, .openbsd, .haiku => posixGetUserInfo(name),
+        .linux, .macos, .watchos, .tvos, .ios, .freebsd, .netbsd, .openbsd, .haiku, .solaris => posixGetUserInfo(name),
         else => @compileError("Unsupported OS"),
     };
 }
@@ -753,6 +753,7 @@ pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]
         .netbsd,
         .dragonfly,
         .openbsd,
+        .solaris,
         => {
             var paths = List.init(allocator);
             errdefer {
lib/std/target.zig
@@ -235,7 +235,6 @@ pub const Target = struct {
                     .fuchsia,
                     .kfreebsd,
                     .lv2,
-                    .solaris,
                     .zos,
                     .haiku,
                     .minix,
@@ -310,6 +309,12 @@ pub const Target = struct {
                             .max = .{ .major = 6, .minor = 0 },
                         },
                     },
+                    .solaris => return .{
+                        .semver = .{
+                            .min = .{ .major = 5, .minor = 11 },
+                            .max = .{ .major = 5, .minor = 11 },
+                        },
+                    },
 
                     .linux => return .{
                         .linux = .{
@@ -353,6 +358,7 @@ pub const Target = struct {
                 .netbsd,
                 .openbsd,
                 .dragonfly,
+                .solaris,
                 => return TaggedVersionRange{ .semver = self.version_range.semver },
 
                 else => return .none,
@@ -385,6 +391,7 @@ pub const Target = struct {
                 .dragonfly,
                 .openbsd,
                 .haiku,
+                .solaris,
                 => true,
 
                 .linux,
@@ -395,7 +402,6 @@ pub const Target = struct {
                 .fuchsia,
                 .kfreebsd,
                 .lv2,
-                .solaris,
                 .zos,
                 .minix,
                 .rtems,
@@ -1516,6 +1522,7 @@ pub const Target = struct {
             .netbsd => return copy(&result, "/libexec/ld.elf_so"),
             .openbsd => return copy(&result, "/usr/libexec/ld.so"),
             .dragonfly => return copy(&result, "/libexec/ld-elf.so.2"),
+            .solaris => return copy(&result, "/lib/64/ld.so.1"),
             .linux => switch (self.cpu.arch) {
                 .i386,
                 .sparc,
@@ -1634,7 +1641,6 @@ pub const Target = struct {
             .fuchsia,
             .kfreebsd,
             .lv2,
-            .solaris,
             .zos,
             .minix,
             .rtems,
lib/std/Thread.zig
@@ -41,6 +41,7 @@ pub const max_name_len = switch (target.os.tag) {
     .netbsd => 31,
     .freebsd => 15,
     .openbsd => 31,
+    .solaris => 31,
     else => 0,
 };
 
@@ -112,7 +113,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
                 else => |e| return os.unexpectedErrno(e),
             }
         },
-        .netbsd => if (use_pthreads) {
+        .netbsd, .solaris => if (use_pthreads) {
             const err = std.c.pthread_setname_np(self.getHandle(), name_with_terminator.ptr, null);
             switch (err) {
                 .SUCCESS => return,
@@ -202,7 +203,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
                 else => |e| return os.unexpectedErrno(e),
             }
         },
-        .netbsd => if (use_pthreads) {
+        .netbsd, .solaris => if (use_pthreads) {
             const err = std.c.pthread_getname_np(self.getHandle(), buffer.ptr, max_name_len + 1);
             switch (err) {
                 .SUCCESS => return std.mem.sliceTo(buffer, 0),
@@ -565,6 +566,16 @@ const PosixThreadImpl = struct {
                 };
                 return @intCast(usize, count);
             },
+            .solaris => {
+                // The "proper" way to get the cpu count would be to query
+                // /dev/kstat via ioctls, and traverse a linked list for each
+                // cpu.
+                const rc = c.sysconf(os._SC.NPROCESSORS_ONLN);
+                return switch (os.errno(rc)) {
+                    .SUCCESS => @intCast(usize, rc),
+                    else => |err| os.unexpectedErrno(err),
+                };
+            },
             .haiku => {
                 var count: u32 = undefined;
                 var system_info: os.system_info = undefined;
src/link/Elf.zig
@@ -3446,6 +3446,15 @@ const CsuObjects = struct {
                     .static_pie  => result.set( "start_dyn.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
                     // zig fmt: on
                 },
+                .solaris => switch (mode) {
+                    // zig fmt: off
+                    .dynamic_lib => result.set( null,     "crti.o", null, null, "crtn.o" ),
+                    .dynamic_exe,
+                    .dynamic_pie => result.set( "crt1.o", "crti.o", null, null, "crtn.o" ),
+                    .static_exe,
+                    .static_pie  => result.set( null,     null,     null, null, null     ),
+                    // zig fmt: on
+                },
                 else => {},
             }
         }
src/stage1/os.hpp
@@ -33,6 +33,8 @@
 #define ZIG_OS_OPENBSD
 #elif defined(__HAIKU__)
 #define ZIG_OS_HAIKU
+#elif defined(__sun)
+#define ZIG_OS_SOLARIS
 #else
 #define ZIG_OS_UNKNOWN
 #endif
src/stage1/target.cpp
@@ -399,6 +399,9 @@ Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) {
 #elif defined(ZIG_OS_HAIKU)
         *out_os = OsHaiku;
         return ErrorNone;
+#elif defined(ZIG_OS_SOLARIS)
+        *out_os = OsSolaris;
+        return ErrorNone;
 #else
         zig_panic("stage1 is unable to detect native target for this OS");
 #endif
@@ -670,6 +673,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
         case OsOpenBSD:
         case OsWASI:
         case OsHaiku:
+        case OsSolaris:
         case OsEmscripten:
         case OsPlan9:
             switch (id) {
@@ -728,7 +732,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
         case OsCloudABI:
         case OsKFreeBSD:
         case OsLv2:
-        case OsSolaris:
         case OsZOS:
         case OsMinix:
         case OsRTEMS:
src/libc_installation.zig
@@ -221,6 +221,7 @@ pub const LibCInstallation = struct {
                 batch.add(&async self.findNativeIncludeDirPosix(args));
                 switch (Target.current.os.tag) {
                     .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"),
+                    .solaris => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib/64"),
                     .linux => batch.add(&async self.findNativeCrtDirPosix(args)),
                     else => {},
                 }
src/target.zig
@@ -433,6 +433,13 @@ pub fn libcFullLinkFlags(target: std.Target) []const []const u8 {
             "-lc",
             "-lutil",
         },
+        .solaris => &[_][]const u8{
+            "-lm",
+            "-lsocket",
+            "-lnsl",
+            // Solaris releases after 10 merged the threading libraries into libc.
+            "-lc",
+        },
         .haiku => &[_][]const u8{
             "-lm",
             "-lroot",
src/type.zig
@@ -3800,6 +3800,7 @@ pub const CType = enum {
             .wasi,
             .emscripten,
             .plan9,
+            .solaris,
             => switch (self) {
                 .short,
                 .ushort,
@@ -3851,7 +3852,6 @@ pub const CType = enum {
             .fuchsia,
             .kfreebsd,
             .lv2,
-            .solaris,
             .zos,
             .haiku,
             .minix,