1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 11:27:35 +00:00
serenity/Ports/zig/patches/0012-Implement-SerenityOS-support-in-std.patch
sin-ack cda5a530e6 Ports: Add zig port :^)
:yakkie:

The build process for the Zig compiler is more involved than most of
the other ports, because the Zig compiler is mostly self-hosting. In
order to build it, the zig-bootstrap build system is used, which does
the following:

1) Build LLVM for the host OS;
2) Build Zig for the host OS with the SerenityOS target enabled;
3) Build zlib, zstd and LLVM for SerenityOS using `zig cc` as the C/C++
   compiler;
4) Build Zig for SerenityOS using the host Zig.

A few hacks are required in order to tell `zig cc` and zig about what
Serenity's libc looks like in the build process, but other than that
it's fairly straightforward. All of the patches that are included with
this commit are Zig-upstream ready once the LLVM patches are upstreamed.
2022-12-11 19:55:37 -07:00

616 lines
23 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: sin-ack <sin-ack@users.noreply.github.com>
Date: Sun, 30 Oct 2022 19:30:50 +0000
Subject: [PATCH] Implement SerenityOS support in std
---
zig/lib/std/Thread.zig | 2 +-
zig/lib/std/c.zig | 1 +
zig/lib/std/c/serenity.zig | 396 +++++++++++++++++++++++++++
zig/lib/std/c/serenity/constants.zig | 6 +
zig/lib/std/debug.zig | 3 +-
zig/lib/std/fs.zig | 72 ++++-
zig/lib/std/fs/get_app_data_dir.zig | 2 +-
zig/lib/std/os.zig | 3 +-
8 files changed, 479 insertions(+), 6 deletions(-)
create mode 100644 zig/lib/std/c/serenity.zig
create mode 100644 zig/lib/std/c/serenity/constants.zig
diff --git a/zig/lib/std/Thread.zig b/zig/lib/std/Thread.zig
index e2e17a29259e1e2cf323ad90451f6fe7906e12a9..125e63bfd138a5a08653f4c815846c42e8eca3c5 100644
--- a/zig/lib/std/Thread.zig
+++ b/zig/lib/std/Thread.zig
@@ -617,7 +617,7 @@ const PosixThreadImpl = struct {
};
return @intCast(usize, count);
},
- .solaris => {
+ .solaris, .serenity => {
// The "proper" way to get the cpu count would be to query
// /dev/kstat via ioctls, and traverse a linked list for each
// cpu.
diff --git a/zig/lib/std/c.zig b/zig/lib/std/c.zig
index 5f03f1c61902a191de87b49f0dcbdfec4a872d34..92c4bfcccb6bf45fcd8df748d346c8ec0dc84208 100644
--- a/zig/lib/std/c.zig
+++ b/zig/lib/std/c.zig
@@ -54,6 +54,7 @@ pub usingnamespace switch (builtin.os.tag) {
.minix => @import("c/minix.zig"),
.emscripten => @import("c/emscripten.zig"),
.wasi => @import("c/wasi.zig"),
+ .serenity => @import("c/serenity.zig"),
else => struct {},
};
diff --git a/zig/lib/std/c/serenity.zig b/zig/lib/std/c/serenity.zig
new file mode 100644
index 0000000000000000000000000000000000000000..057813c1b13fcedc87271003220c42da7ef36e0e
--- /dev/null
+++ b/zig/lib/std/c/serenity.zig
@@ -0,0 +1,396 @@
+pub const std = @import("std");
+pub const SerenityConstants = @import("serenity/constants.zig");
+
+pub const fd_t = c_int;
+pub const dev_t = u32;
+pub const ino_t = u64;
+pub const off_t = i64;
+pub const nlink_t = u32;
+
+pub const E = enum(i32) {
+ SUCCESS = SerenityConstants.ESUCCESS,
+ PERM = SerenityConstants.EPERM,
+ NOENT = SerenityConstants.ENOENT,
+ SRCH = SerenityConstants.ESRCH,
+ INTR = SerenityConstants.EINTR,
+ IO = SerenityConstants.EIO,
+ NXIO = SerenityConstants.ENXIO,
+ @"2BIG" = SerenityConstants.E2BIG,
+ NOEXEC = SerenityConstants.ENOEXEC,
+ BADF = SerenityConstants.EBADF,
+ CHILD = SerenityConstants.ECHILD,
+ AGAIN = SerenityConstants.EAGAIN,
+ NOMEM = SerenityConstants.ENOMEM,
+ ACCES = SerenityConstants.EACCES,
+ FAULT = SerenityConstants.EFAULT,
+ NOTBLK = SerenityConstants.ENOTBLK,
+ BUSY = SerenityConstants.EBUSY,
+ EXIST = SerenityConstants.EEXIST,
+ XDEV = SerenityConstants.EXDEV,
+ NODEV = SerenityConstants.ENODEV,
+ NOTDIR = SerenityConstants.ENOTDIR,
+ ISDIR = SerenityConstants.EISDIR,
+ INVAL = SerenityConstants.EINVAL,
+ NFILE = SerenityConstants.ENFILE,
+ MFILE = SerenityConstants.EMFILE,
+ NOTTY = SerenityConstants.ENOTTY,
+ TXTBSY = SerenityConstants.ETXTBSY,
+ FBIG = SerenityConstants.EFBIG,
+ NOSPC = SerenityConstants.ENOSPC,
+ SPIPE = SerenityConstants.ESPIPE,
+ ROFS = SerenityConstants.EROFS,
+ MLINK = SerenityConstants.EMLINK,
+ PIPE = SerenityConstants.EPIPE,
+ RANGE = SerenityConstants.ERANGE,
+ NAMETOOLONG = SerenityConstants.ENAMETOOLONG,
+ LOOP = SerenityConstants.ELOOP,
+ OVERFLOW = SerenityConstants.EOVERFLOW,
+ OPNOTSUPP = SerenityConstants.EOPNOTSUPP,
+ NOSYS = SerenityConstants.ENOSYS,
+ NOTIMPL = SerenityConstants.ENOTIMPL,
+ AFNOSUPPORT = SerenityConstants.EAFNOSUPPORT,
+ NOTSOCK = SerenityConstants.ENOTSOCK,
+ ADDRINUSE = SerenityConstants.EADDRINUSE,
+ NOTEMPTY = SerenityConstants.ENOTEMPTY,
+ DOM = SerenityConstants.EDOM,
+ CONNREFUSED = SerenityConstants.ECONNREFUSED,
+ HOSTDOWN = SerenityConstants.EHOSTDOWN,
+ ADDRNOTAVAIL = SerenityConstants.EADDRNOTAVAIL,
+ ISCONN = SerenityConstants.EISCONN,
+ CONNABORTED = SerenityConstants.ECONNABORTED,
+ ALREADY = SerenityConstants.EALREADY,
+ CONNRESET = SerenityConstants.ECONNRESET,
+ DESTADDRREQ = SerenityConstants.EDESTADDRREQ,
+ HOSTUNREACH = SerenityConstants.EHOSTUNREACH,
+ ILSEQ = SerenityConstants.EILSEQ,
+ MSGSIZE = SerenityConstants.EMSGSIZE,
+ NETDOWN = SerenityConstants.ENETDOWN,
+ NETUNREACH = SerenityConstants.ENETUNREACH,
+ NETRESET = SerenityConstants.ENETRESET,
+ NOBUFS = SerenityConstants.ENOBUFS,
+ NOLCK = SerenityConstants.ENOLCK,
+ NOMSG = SerenityConstants.ENOMSG,
+ NOPROTOOPT = SerenityConstants.ENOPROTOOPT,
+ NOTCONN = SerenityConstants.ENOTCONN,
+ SHUTDOWN = SerenityConstants.ESHUTDOWN,
+ TOOMANYREFS = SerenityConstants.ETOOMANYREFS,
+ SOCKTNOSUPPORT = SerenityConstants.ESOCKTNOSUPPORT,
+ PROTONOSUPPORT = SerenityConstants.EPROTONOSUPPORT,
+ DEADLK = SerenityConstants.EDEADLK,
+ TIMEDOUT = SerenityConstants.ETIMEDOUT,
+ PROTOTYPE = SerenityConstants.EPROTOTYPE,
+ INPROGRESS = SerenityConstants.EINPROGRESS,
+ NOTHREAD = SerenityConstants.ENOTHREAD,
+ PROTO = SerenityConstants.EPROTO,
+ NOTSUP = SerenityConstants.ENOTSUP,
+ PFNOSUPPORT = SerenityConstants.EPFNOSUPPORT,
+ DIRINTOSELF = SerenityConstants.EDIRINTOSELF,
+ DQUOT = SerenityConstants.EDQUOT,
+ NOTRECOVERABLE = SerenityConstants.ENOTRECOVERABLE,
+ CANCELED = SerenityConstants.ECANCELED,
+ PROMISEVIOLATION = SerenityConstants.EPROMISEVIOLATION,
+ STALE = SerenityConstants.ESTALE,
+};
+
+pub const PATH_MAX = SerenityConstants.PATH_MAX;
+
+pub const time_t = i64;
+pub const timespec = struct {
+ tv_sec: time_t,
+ tv_nsec: c_long,
+};
+
+pub const mode_t = u16;
+
+pub const AT = struct {
+ pub const FDCWD = SerenityConstants.AT_FDCWD;
+ pub const SYMLINK_NOFOLLOW = SerenityConstants.AT_SYMLINK_NOFOLLOW;
+ pub const REMOVEDIR = SerenityConstants.AT_REMOVEDIR;
+};
+
+pub const _errno = struct {
+ extern "c" fn __errno_location() *c_int;
+}.__errno_location;
+
+pub const pthread_attr_t = *anyopaque;
+
+pub const LOCK = struct {
+ pub const SH = SerenityConstants.LOCK_SH;
+ pub const EX = SerenityConstants.LOCK_EX;
+ pub const UN = SerenityConstants.LOCK_UN;
+ pub const NB = SerenityConstants.LOCK_NB;
+};
+
+pub const STDIN_FILENO = SerenityConstants.STDIN_FILENO;
+pub const STDOUT_FILENO = SerenityConstants.STDOUT_FILENO;
+pub const STDERR_FILENO = SerenityConstants.STDERR_FILENO;
+
+pub const F = struct {
+ pub const DUPFD = SerenityConstants.F_DUPFD;
+ pub const GETFD = SerenityConstants.F_GETFD;
+ pub const SETFD = SerenityConstants.F_SETFD;
+ pub const GETFL = SerenityConstants.F_GETFL;
+ pub const SETFL = SerenityConstants.F_SETFL;
+ pub const ISTTY = SerenityConstants.F_ISTTY;
+ pub const GETLK = SerenityConstants.F_GETLK;
+ pub const SETLK = SerenityConstants.F_SETLK;
+ pub const SETLKW = SerenityConstants.F_SETLKW;
+};
+
+pub const FD_CLOEXEC = SerenityConstants.FD_CLOEXEC;
+
+pub const O = struct {
+ pub const RDONLY = SerenityConstants.O_RDONLY;
+ pub const WRONLY = SerenityConstants.O_WRONLY;
+ pub const RDWR = SerenityConstants.O_RDWR;
+ pub const ACCMODE = SerenityConstants.O_ACCMODE;
+ pub const EXEC = SerenityConstants.O_EXEC;
+ pub const CREAT = SerenityConstants.O_CREAT;
+ pub const EXCL = SerenityConstants.O_EXCL;
+ pub const NOCTTY = SerenityConstants.O_NOCTTY;
+ pub const TRUNC = SerenityConstants.O_TRUNC;
+ pub const APPEND = SerenityConstants.O_APPEND;
+ pub const NONBLOCK = SerenityConstants.O_NONBLOCK;
+ pub const DIRECTORY = SerenityConstants.O_DIRECTORY;
+ pub const NOFOLLOW = SerenityConstants.O_NOFOLLOW;
+ pub const CLOEXEC = SerenityConstants.O_CLOEXEC;
+ pub const DIRECT = SerenityConstants.O_DIRECT;
+ pub const SYNC = SerenityConstants.O_SYNC;
+};
+
+pub const R_OK = SerenityConstants.R_OK;
+pub const W_OK = SerenityConstants.W_OK;
+pub const X_OK = SerenityConstants.X_OK;
+pub const F_OK = SerenityConstants.F_OK;
+
+pub const CLOCK = struct {
+ pub const REALTIME = SerenityConstants.CLOCK_REALTIME;
+ pub const MONOTONIC = SerenityConstants.CLOCK_MONOTONIC;
+ pub const MONOTONIC_RAW = SerenityConstants.CLOCK_MONOTONIC_RAW;
+ pub const REALTIME_COARSE = SerenityConstants.CLOCK_REALTIME_COARSE;
+ pub const MONOTONIC_COARSE = SerenityConstants.CLOCK_MONOTONIC_COARSE;
+};
+
+pub const IOV_MAX = SerenityConstants.IOV_MAX;
+
+pub const pthread_mutex_t = struct {
+ lock: u32 = 0,
+ owner: ?std.c.pthread_t = null,
+ level: c_int = 0,
+ type: c_int = 0, // __PTHREAD_MUTEX_NORMAL
+};
+
+pub const pthread_cond_t = struct {
+ mutex: ?*pthread_mutex_t = null,
+ value: u32 = 0,
+ clockid: c_int = CLOCK.MONOTONIC_COARSE, // clockid_t
+};
+
+pub const uid_t = u32;
+pub const gid_t = u32;
+
+pub const blksize_t = u32;
+pub const blkcnt_t = u32;
+
+pub const Stat = 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,
+ blksize: blksize_t,
+ blocks: blkcnt_t,
+ atim: timespec,
+ mtim: timespec,
+ ctim: timespec,
+
+ 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 pid_t = c_int;
+
+pub const S = struct {
+ pub const IFMT = SerenityConstants.S_IFMT;
+ pub const IFDIR = SerenityConstants.S_IFDIR;
+ pub const IFCHR = SerenityConstants.S_IFCHR;
+ pub const IFBLK = SerenityConstants.S_IFBLK;
+ pub const IFREG = SerenityConstants.S_IFREG;
+ pub const IFIFO = SerenityConstants.S_IFIFO;
+ pub const IFLNK = SerenityConstants.S_IFLNK;
+ pub const IFSOCK = SerenityConstants.S_IFSOCK;
+
+ pub const ISUID = SerenityConstants.S_ISUID;
+ pub const ISGID = SerenityConstants.S_ISGID;
+ pub const ISVTX = SerenityConstants.S_ISVTX;
+ pub const IRUSR = SerenityConstants.S_IRUSR;
+ pub const IWUSR = SerenityConstants.S_IWUSR;
+ pub const IXUSR = SerenityConstants.S_IXUSR;
+ pub const IREAD = SerenityConstants.S_IREAD;
+ pub const IWRITE = SerenityConstants.S_IWRITE;
+ pub const IEXEC = SerenityConstants.S_IEXEC;
+ pub const IRGRP = SerenityConstants.S_IRGRP;
+ pub const IWGRP = SerenityConstants.S_IWGRP;
+ pub const IXGRP = SerenityConstants.S_IXGRP;
+ pub const IROTH = SerenityConstants.S_IROTH;
+ pub const IWOTH = SerenityConstants.S_IWOTH;
+ pub const IXOTH = SerenityConstants.S_IXOTH;
+
+ pub const IRWXU = SerenityConstants.S_IRWXU;
+
+ pub const IRWXG = SerenityConstants.S_IRWXG;
+ pub const IRWXO = SerenityConstants.S_IRWXO;
+
+ pub fn ISREG(m: u32) bool {
+ return m & IFMT == IFREG;
+ }
+
+ pub fn ISLNK(m: u32) bool {
+ return m & IFMT == IFLNK;
+ }
+
+ pub fn ISBLK(m: u32) bool {
+ return m & IFMT == IFBLK;
+ }
+
+ pub fn ISDIR(m: u32) bool {
+ return m & IFMT == IFDIR;
+ }
+
+ pub fn ISCHR(m: u32) bool {
+ return m & IFMT == IFCHR;
+ }
+
+ pub fn ISFIFO(m: u32) bool {
+ return m & IFMT == IFIFO;
+ }
+
+ pub fn ISSOCK(m: u32) bool {
+ return m & IFMT == IFSOCK;
+ }
+};
+
+pub const SEEK = struct {
+ pub const SET = SerenityConstants.SEEK_SET;
+ pub const CUR = SerenityConstants.SEEK_CUR;
+ pub const END = SerenityConstants.SEEK_END;
+};
+
+pub const POLL = struct {
+ pub const IN = SerenityConstants.POLLIN;
+ pub const RDNORM = SerenityConstants.POLLRDNORM;
+ pub const PRI = SerenityConstants.POLLPRI;
+ pub const OUT = SerenityConstants.POLLOUT;
+ pub const WRNORM = SerenityConstants.POLLWRNORM;
+ pub const ERR = SerenityConstants.POLLERR;
+ pub const HUP = SerenityConstants.POLLHUP;
+ pub const NVAL = SerenityConstants.POLLNVAL;
+ pub const WRBAND = SerenityConstants.POLLWRBAND;
+ pub const RDHUP = SerenityConstants.POLLRDHUP;
+};
+
+pub const pollfd = struct {
+ fd: c_int,
+ events: c_short,
+ revents: c_short,
+};
+
+pub const nfds_t = c_uint;
+
+pub const W = struct {
+ pub const NOHANG = SerenityConstants.WNOHANG;
+ pub const UNTRACED = SerenityConstants.WUNTRACED;
+ pub const STOPPED = SerenityConstants.WSTOPPED;
+ pub const EXITED = SerenityConstants.WEXITED;
+ pub const CONTINUED = SerenityConstants.WCONTINUED;
+ pub const NOWAIT = SerenityConstants.WNOWAIT;
+
+ pub fn EXITSTATUS(s: u32) u8 {
+ return @intCast(u8, (s & 0xff00) >> 8);
+ }
+
+ pub fn STOPSIG(s: u32) u32 {
+ return EXITSTATUS(s);
+ }
+
+ pub fn TERMSIG(s: u32) u32 {
+ return s & 0x7f;
+ }
+
+ pub fn IFEXITED(s: u32) bool {
+ return TERMSIG(s) == 0;
+ }
+
+ pub fn IFSTOPPED(s: u32) bool {
+ return (s & 0xff) == 0x7f;
+ }
+
+ pub fn IFSIGNALED(s: u32) bool {
+ return (@intCast(u8, (s & 0x7f) + 1) >> 1) > 0;
+ }
+
+ pub fn IFCONTINUED(s: u32) bool {
+ return s == 0xffff;
+ }
+};
+
+pub const dirent = extern struct {
+ d_ino: ino_t,
+ d_off: off_t,
+ d_reclen: c_ushort,
+ d_type: u8,
+ d_name: [256]u8,
+};
+pub extern "c" fn readdir_r(dir: *std.c.DIR, entry: *dirent, result: *?*dirent) i32;
+
+pub const PROT = struct {
+ pub const READ = SerenityConstants.PROT_READ;
+ pub const WRITE = SerenityConstants.PROT_WRITE;
+ pub const EXEC = SerenityConstants.PROT_EXEC;
+ pub const NONE = SerenityConstants.PROT_NONE;
+};
+
+pub const MAP = struct {
+ pub const FILE = SerenityConstants.MAP_FILE;
+ pub const SHARED = SerenityConstants.MAP_SHARED;
+ pub const PRIVATE = SerenityConstants.MAP_PRIVATE;
+ pub const FIXED = SerenityConstants.MAP_FIXED;
+ pub const ANONYMOUS = SerenityConstants.MAP_ANONYMOUS;
+ pub const ANON = SerenityConstants.MAP_ANON;
+ pub const STACK = SerenityConstants.MAP_STACK;
+ pub const NORESERVE = SerenityConstants.MAP_NORESERVE;
+ pub const RANDOMIZED = SerenityConstants.MAP_RANDOMIZED;
+ pub const PURGEABLE = SerenityConstants.MAP_PURGEABLE;
+ pub const FIXED_NOREPLACE = SerenityConstants.MAP_FIXED_NOREPLACE;
+ pub const FAILED = @intToPtr(*anyopaque, @bitCast(usize, @as(isize, -1)));
+};
+
+pub const MSF = struct {
+ pub const SYNC = SerenityConstants.MS_SYNC;
+ pub const ASYNC = SerenityConstants.MS_ASYNC;
+ pub const INVALIDATE = SerenityConstants.MS_INVALIDATE;
+};
+
+pub extern "c" fn sysconf(sc: c_int) c_long;
+pub const _SC = struct {
+ pub const NPROCESSORS_ONLN = SerenityConstants._SC_NPROCESSORS_ONLN;
+};
+
+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,
+};
+pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.C) c_int;
+pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int;
diff --git a/zig/lib/std/c/serenity/constants.zig b/zig/lib/std/c/serenity/constants.zig
new file mode 100644
index 0000000000000000000000000000000000000000..94d7b1c091f7affb5c968738a8719cbbe526650b
--- /dev/null
+++ b/zig/lib/std/c/serenity/constants.zig
@@ -0,0 +1,6 @@
+comptime {
+ @compileError(
+ "A Zig compilation targeting SerenityOS can only be done by installing the SerenityOS Zig port. " ++
+ "This file is replaced by the actual POSIX constants during the port build process.",
+ );
+}
diff --git a/zig/lib/std/debug.zig b/zig/lib/std/debug.zig
index 90ceff3df157f3d94feddceae12de59fc2e3581d..5c25a8c9cebcb0cce01b229808ea67c57c968d5e 100644
--- a/zig/lib/std/debug.zig
+++ b/zig/lib/std/debug.zig
@@ -812,6 +812,7 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo {
.macos,
.windows,
.solaris,
+ .serenity,
=> return DebugInfo.init(allocator),
else => return error.UnsupportedDebugInfo,
}
@@ -1761,7 +1762,7 @@ pub const ModuleDebugInfo = switch (native_os) {
};
}
},
- .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris => struct {
+ .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku, .solaris, .serenity => struct {
base_address: usize,
dwarf: DW.DwarfInfo,
mapped_memory: []align(mem.page_size) const u8,
diff --git a/zig/lib/std/fs.zig b/zig/lib/std/fs.zig
index e253aaff9e9505182db90c8fa08aa931dca8a0ba..cebf86fc05164ff311731deb4c75730d4dc84d27 100644
--- a/zig/lib/std/fs.zig
+++ b/zig/lib/std/fs.zig
@@ -34,7 +34,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, .solaris => os.PATH_MAX,
+ .linux, .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .haiku, .solaris, .serenity => 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.
@@ -521,6 +521,69 @@ pub const IterableDir = struct {
self.first_iter = true;
}
},
+ .serenity => struct {
+ dir: Dir,
+ dir_ptr: *os.system.DIR,
+
+ const Self = @This();
+
+ pub const Error = IteratorError;
+
+ pub fn next(self: *Self) Error!?Entry {
+ const errno_location = os.system._errno();
+ start_over: while (true) {
+ // HACK: readdir_r currently doesn't work properly on
+ // SerenityOS. Until it does, we need to rely on
+ // readdir which has legacy errno behavior.
+ const saved_errno = errno_location.*;
+ errno_location.* = 0;
+ const entry = os.system.readdir(self.dir_ptr);
+ if (entry == null) {
+ if (errno_location.* != 0) {
+ switch (os.errno(-1)) {
+ .OVERFLOW => unreachable,
+ .BADF => unreachable,
+ .NOENT => unreachable,
+ else => |err| return os.unexpectedErrno(err),
+ }
+ }
+
+ // No error, just end of directory.
+ errno_location.* = saved_errno;
+ return null;
+ }
+
+ const name = mem.sliceTo(@ptrCast([*:0]u8, &entry.?.d_name), 0);
+ if (mem.eql(u8, name, ".") or mem.eql(u8, name, ".."))
+ continue :start_over;
+
+ 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,
+ else => Entry.Kind.Unknown,
+ };
+ return Entry{
+ .name = name,
+ .kind = entry_kind,
+ };
+ }
+ }
+ },
.haiku => struct {
dir: Dir,
buf: [1024]u8, // TODO align(@alignOf(os.dirent64)),
@@ -906,6 +969,11 @@ pub const IterableDir = struct {
.buf = undefined,
.first_iter = first_iter_start_value,
},
+ .serenity => return Iterator{
+ .dir = self.dir,
+ // FIXME: Very small chance this may fail.
+ .dir_ptr = os.system.fdopendir(self.dir.fd).?,
+ },
.windows => return Iterator{
.dir = self.dir,
.index = 0,
@@ -2941,7 +3009,7 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
return out_buffer[0..real_path.len];
}
switch (builtin.os.tag) {
- .linux => return os.readlinkZ("/proc/self/exe", out_buffer),
+ .linux, .serenity => 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 };
diff --git a/zig/lib/std/fs/get_app_data_dir.zig b/zig/lib/std/fs/get_app_data_dir.zig
index 4f7ba9af623841cc8be7b6c48d55037f689fec8d..5a5b4de8aefe6962979a9a65f937cc35c78d7631 100644
--- a/zig/lib/std/fs/get_app_data_dir.zig
+++ b/zig/lib/std/fs/get_app_data_dir.zig
@@ -44,7 +44,7 @@ pub fn getAppDataDir(allocator: mem.Allocator, appname: []const u8) GetAppDataDi
};
return fs.path.join(allocator, &[_][]const u8{ home_dir, "Library", "Application Support", appname });
},
- .linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris => {
+ .linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris, .serenity => {
if (os.getenv("XDG_DATA_HOME")) |xdg| {
return fs.path.join(allocator, &[_][]const u8{ xdg, appname });
}
diff --git a/zig/lib/std/os.zig b/zig/lib/std/os.zig
index f13ee03a967df2899aed1b935dd12975f5d07332..b1c174b774b40553c455d768c11ec6c752796a06 100644
--- a/zig/lib/std/os.zig
+++ b/zig/lib/std/os.zig
@@ -36,6 +36,7 @@ pub const haiku = std.c;
pub const netbsd = std.c;
pub const openbsd = std.c;
pub const solaris = std.c;
+pub const serenity = std.c;
pub const linux = @import("os/linux.zig");
pub const plan9 = @import("os/plan9.zig");
pub const uefi = @import("os/uefi.zig");
@@ -5112,7 +5113,7 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
const len = mem.indexOfScalar(u8, out_buffer[0..], @as(u8, 0)) orelse MAX_PATH_BYTES;
return out_buffer[0..len];
},
- .linux => {
+ .linux, .serenity => {
var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined;
const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{d}\x00", .{fd}) catch unreachable;