1const std = @import("std");
2const builtin = @import("builtin");
3
4comptime {
5 std.debug.assert(builtin.target.os.tag == .macos);
6 std.debug.assert(@bitSizeOf(usize) == 64);
7}
8
9pub const errno = struct {
10 pub const Error = error{
11 Unexpected,
12 EPERM,
13 ENOENT,
14 ESRCH,
15 EINTR,
16 EIO,
17 ENXIO,
18 E2BIG,
19 ENOEXEC,
20 EBADF,
21 ECHILD,
22 EDEADLK,
23 ENOMEM,
24 EACCES,
25 EFAULT,
26 ENOTBLK,
27 EBUSY,
28 EEXIST,
29 EXDEV,
30 ENODEV,
31 ENOTDIR,
32 EISDIR,
33 EINVAL,
34 ENFILE,
35 EMFILE,
36 ENOTTY,
37 ETXTBSY,
38 EFBIG,
39 ENOSPC,
40 ESPIPE,
41 EROFS,
42 EMLINK,
43 EPIPE,
44 EDOM,
45 ERANGE,
46 EAGAIN,
47 EINPROGRESS,
48 EALREADY,
49 ENOTSOCK,
50 EDESTADDRREQ,
51 EMSGSIZE,
52 EPROTOTYPE,
53 ENOPROTOOPT,
54 EPROTONOSUPPORT,
55 ESOCKTNOSUPPORT,
56 ENOTSUP,
57 EPFNOSUPPORT,
58 EAFNOSUPPORT,
59 EADDRINUSE,
60 EADDRNOTAVAIL,
61 ENETDOWN,
62 ENETUNREACH,
63 ENETRESET,
64 ECONNABORTED,
65 ECONNRESET,
66 ENOBUFS,
67 EISCONN,
68 ENOTCONN,
69 ESHUTDOWN,
70 ETOOMANYREFS,
71 ETIMEDOUT,
72 ECONNREFUSED,
73 ELOOP,
74 ENAMETOOLONG,
75 EHOSTDOWN,
76 EHOSTUNREACH,
77 ENOTEMPTY,
78 EPROCLIM,
79 EUSERS,
80 EDQUOT,
81 ESTALE,
82 EREMOTE,
83 EBADRPC,
84 ERPCMISMATCH,
85 EPROGUNAVAIL,
86 EPROGMISMATCH,
87 EPROCUNAVAIL,
88 ENOLCK,
89 ENOSYS,
90 EFTYPE,
91 EAUTH,
92 ENEEDAUTH,
93 EPWROFF,
94 EDEVERR,
95 EOVERFLOW,
96 EBADEXEC,
97 EBADARCH,
98 ESHLIBVERS,
99 EBADMACHO,
100 ECANCELED,
101 EIDRM,
102 ENOMSG,
103 EILSEQ,
104 ENOATTR,
105 EBADMSG,
106 EMULTIHOP,
107 ENODATA,
108 ENOLINK,
109 ENOSR,
110 ENOSTR,
111 EPROTO,
112 ETIME,
113 EOPNOTSUPP,
114 ENOPOLICY,
115 ENOTRECOVERABLE,
116 EOWNERDEAD,
117 EQFULL,
118 ENOTCAPABLE,
119 };
120
121 pub const Enum = enum(c_ushort) {
122 EPERM = 1,
123 ENOENT = 2,
124 ESRCH = 3,
125 EINTR = 4,
126 EIO = 5,
127 ENXIO = 6,
128 E2BIG = 7,
129 ENOEXEC = 8,
130 EBADF = 9,
131 ECHILD = 10,
132 EDEADLK = 11,
133 ENOMEM = 12,
134 EACCES = 13,
135 EFAULT = 14,
136 ENOTBLK = 15,
137 EBUSY = 16,
138 EEXIST = 17,
139 EXDEV = 18,
140 ENODEV = 19,
141 ENOTDIR = 20,
142 EISDIR = 21,
143 EINVAL = 22,
144 ENFILE = 23,
145 EMFILE = 24,
146 ENOTTY = 25,
147 ETXTBSY = 26,
148 EFBIG = 27,
149 ENOSPC = 28,
150 ESPIPE = 29,
151 EROFS = 30,
152 EMLINK = 31,
153 EPIPE = 32,
154 EDOM = 33,
155 ERANGE = 34,
156 EAGAIN = 35,
157 EINPROGRESS = 36,
158 EALREADY = 37,
159 ENOTSOCK = 38,
160 EDESTADDRREQ = 39,
161 EMSGSIZE = 40,
162 EPROTOTYPE = 41,
163 ENOPROTOOPT = 42,
164 EPROTONOSUPPORT = 43,
165 ESOCKTNOSUPPORT = 44,
166 ENOTSUP = 45,
167 EPFNOSUPPORT = 46,
168 EAFNOSUPPORT = 47,
169 EADDRINUSE = 48,
170 EADDRNOTAVAIL = 49,
171 ENETDOWN = 50,
172 ENETUNREACH = 51,
173 ENETRESET = 52,
174 ECONNABORTED = 53,
175 ECONNRESET = 54,
176 ENOBUFS = 55,
177 EISCONN = 56,
178 ENOTCONN = 57,
179 ESHUTDOWN = 58,
180 ETOOMANYREFS = 59,
181 ETIMEDOUT = 60,
182 ECONNREFUSED = 61,
183 ELOOP = 62,
184 ENAMETOOLONG = 63,
185 EHOSTDOWN = 64,
186 EHOSTUNREACH = 65,
187 ENOTEMPTY = 66,
188 EPROCLIM = 67,
189 EUSERS = 68,
190 EDQUOT = 69,
191 ESTALE = 70,
192 EREMOTE = 71,
193 EBADRPC = 72,
194 ERPCMISMATCH = 73,
195 EPROGUNAVAIL = 74,
196 EPROGMISMATCH = 75,
197 EPROCUNAVAIL = 76,
198 ENOLCK = 77,
199 ENOSYS = 78,
200 EFTYPE = 79,
201 EAUTH = 80,
202 ENEEDAUTH = 81,
203 EPWROFF = 82,
204 EDEVERR = 83,
205 EOVERFLOW = 84,
206 EBADEXEC = 85,
207 EBADARCH = 86,
208 ESHLIBVERS = 87,
209 EBADMACHO = 88,
210 ECANCELED = 89,
211 EIDRM = 90,
212 ENOMSG = 91,
213 EILSEQ = 92,
214 ENOATTR = 93,
215 EBADMSG = 94,
216 EMULTIHOP = 95,
217 ENODATA = 96,
218 ENOLINK = 97,
219 ENOSR = 98,
220 ENOSTR = 99,
221 EPROTO = 100,
222 ETIME = 101,
223 // 102 is only defined in the kernel
224 ENOPOLICY = 103,
225 ENOTRECOVERABLE = 104,
226 EOWNERDEAD = 105,
227 EQFULL = 106,
228 ENOTCAPABLE = 107,
229
230 pub const EWOULDBLOCK: Enum = .EAGAIN;
231 pub const EOPNOTSUPP: Enum = .ENOTSUP;
232 };
233
234 comptime {
235 // assert Enum is sequential
236 var value: c_ushort = 0; // SUCCESS
237 for (std.enums.values(Enum)) |val| {
238 std.debug.assert(@intFromEnum(val) > value);
239 value = @intFromEnum(val);
240 }
241 }
242 comptime {
243 // sanity test
244 std.debug.assert(@intFromEnum(Enum.EPERM) == 1);
245 }
246 const list = blk: {
247 const values = std.enums.values(Enum);
248 const len = @intFromEnum(values[values.len - 1]) + 1;
249 var errors: [len]Error = @splat(error.Unexpected);
250 for (values) |f| errors[@intFromEnum(f)] = @field(Error, @tagName(f));
251 const final = errors;
252 break :blk final;
253 };
254 pub fn fromInt(code: c_int) Error {
255 @setRuntimeSafety(false);
256 if (code >= list.len) return error.Unexpected;
257 if (code <= 0) return error.Unexpected;
258 return list[@intCast(code)];
259 }
260 pub fn fromLibC() c_int {
261 return libc.__error().*;
262 }
263};
264
265pub const libc = struct {
266 pub extern fn __error() *c_int;
267 pub extern fn openat(fd: c_int, file: [*:0]const u8, oflag: c_int, ...) c_int;
268 pub extern fn fstat(fd: c_int, buf: *struct_stat) c_int;
269 pub extern fn close(fildes: c_int) c_int;
270 pub extern fn read(fd: c_int, buf: [*]u8, count: usize) isize;
271 pub extern fn clock_gettime(clock_id: clockid_t, tp: *struct_timespec) c_int;
272 pub extern fn fcntl(fd: c_int, cmd: c_int, ...) c_int;
273 pub extern fn mkdirat(fd: c_int, path: [*:0]const u8, mode: mode_t) c_int;
274 pub extern fn fstatat(fd: c_int, noalias path: [*:0]const u8, noalias buf: *struct_stat, flag: c_int) c_int;
275 pub extern fn getdirentries(fd: c_int, buf: [*]u8, nbytes: c_int, basep: *c_long) c_int;
276 pub extern fn unlinkat(fd: c_int, name: [*:0]const u8, flag: c_int) c_int;
277 pub extern fn write(fd: c_int, buf: *const anyopaque, n: usize) isize;
278 pub extern fn writev(fd: c_int, iovec: [*]const struct_iovec, count: c_int) isize;
279 pub extern fn isatty(fd: c_int) c_int;
280 pub extern fn lseek(fd: c_int, offset: off_t, whence: c_int) off_t;
281 pub extern fn getcwd(buf: [*]u8, size: usize) ?[*:0]u8;
282 pub extern fn fchmod(fildes: c_int, mode: mode_t) c_int;
283 pub extern fn faccessat(fd: c_int, path: [*:0]const u8, amode: c_int, flag: c_int) c_int;
284 pub extern fn readlinkat(fd: c_int, noalias path: [*:0]const u8, noalias buf: [*]u8, len: usize) isize;
285};
286
287pub const natural_t = c_uint;
288pub const blkcnt_t = i64;
289pub const blksize_t = i32;
290pub const dev_t = i32;
291pub const fsblkcnt_t = c_uint;
292pub const fsfilcnt_t = c_uint;
293pub const gid_t = u32;
294pub const id_t = u32;
295pub const ino_t = u64;
296pub const mach_port_name_t = natural_t;
297pub const mach_port_t = mach_port_name_t;
298pub const mode_t = u16;
299pub const off_t = i64;
300pub const pid_t = i32;
301pub const sigset_t = u32;
302pub const suseconds_t = i32;
303pub const uid_t = u32;
304pub const useconds_t = u32;
305pub const nlink_t = u16;
306pub const clockid_t = c_int;
307
308pub const time_t = c_ulong;
309
310pub const struct_timespec = extern struct { sec: time_t, nsec: c_long };
311pub const struct_stat = extern struct { dev: dev_t, mode: mode_t, nlink: nlink_t, ino: ino_t, uid: uid_t, gid: gid_t, rdev: dev_t, atimespec: struct_timespec, mtimespec: struct_timespec, ctimespec: struct_timespec, birthtimespec: struct_timespec, size: off_t, blocks: blkcnt_t, blksize: blksize_t, flags: u32, gen: u32, lspare: i32, qspare: [2]i64 };
312pub const struct_iovec = extern struct { base: [*]u8, len: usize };
313pub const struct_dirent = extern struct { ino: u64, seekoff: u64, reclen: u16, namlen: u16, type: DT, name: [PATH_MAX]u8 };
314
315pub const PATH_MAX = 1024;
316pub const NAME_MAX = 255;
317
318pub const O = struct {
319 pub const RDONLY = 0x0000;
320 pub const WRONLY = 0x0001;
321 pub const RDWR = 0x0002;
322 pub const ACCMODE = 0x0003;
323 pub const NONBLOCK = 0x00000004;
324 pub const APPEND = 0x00000008;
325 pub const SYNC = 0x0080;
326 pub const SHLOCK = 0x00000010;
327 pub const EXLOCK = 0x00000020;
328 pub const ASYNC = 0x00000040;
329 pub const FSYNC = SYNC;
330 pub const NOFOLLOW = 0x00000100;
331 pub const CREAT = 0x00000200;
332 pub const TRUNC = 0x00000400;
333 pub const EXCL = 0x00000800;
334 pub const RESOLVE_BENEATH = 0x00001000;
335 pub const UNIQUE = 0x00002000;
336 pub const EVTONLY = 0x00008000;
337 pub const NOCTTY = 0x00020000;
338 pub const DIRECTORY = 0x00100000;
339 pub const SYMLINK = 0x00200000;
340 pub const DSYNC = 0x00400000;
341 pub const CLOEXEC = 0x01000000;
342 pub const NOFOLLOW_ANY = 0x20000000;
343 pub const EXEC = 0x40000000;
344 pub const SEARCH = (EXEC | DIRECTORY);
345};
346
347pub const CLOCK = struct {
348 pub const REALTIME = 0;
349 pub const MONOTONIC = 6;
350 pub const MONOTONIC_RAW = 4;
351 pub const MONOTONIC_RAW_APPROX = 5;
352 pub const UPTIME_RAW = 8;
353 pub const UPTIME_RAW_APPROX = 9;
354 pub const PROCESS_CPUTIME_ID = 12;
355 pub const THREAD_CPUTIME_ID = 16;
356};
357
358pub const AT = struct {
359 pub const FDCWD = -2;
360 pub const EACCESS = 0x0010;
361 pub const SYMLINK_NOFOLLOW = 0x0020;
362 pub const SYMLINK_FOLLOW = 0x0040;
363 pub const REMOVEDIR = 0x0080;
364 pub const REALDEV = 0x0200;
365 pub const FDONLY = 0x0400;
366 pub const SYMLINK_NOFOLLOW_ANY = 0x0800;
367 pub const RESOLVE_BENEATH = 0x2000;
368 pub const NODELETEBUSY = 0x4000;
369 pub const UNIQUE = 0x8000;
370};
371
372pub const F = struct {
373 pub const DUPFD = 0;
374 pub const GETFD = 1;
375 pub const SETFD = 2;
376 pub const GETFL = 3;
377 pub const SETFL = 4;
378 pub const GETOWN = 5;
379 pub const SETOWN = 6;
380 pub const GETLK = 7;
381 pub const SETLK = 8;
382 pub const SETLKW = 9;
383 pub const SETLKWTIMEOUT = 10;
384 pub const FLUSH_DATA = 40;
385 pub const CHKCLEAN = 41;
386 pub const PREALLOCATE = 42;
387 pub const SETSIZE = 43;
388 pub const RDADVISE = 44;
389 pub const RDAHEAD = 45;
390 pub const NOCACHE = 48;
391 pub const LOG2PHYS = 49;
392 pub const GETPATH = 50;
393 pub const FULLFSYNC = 51;
394 pub const PATHPKG_CHECK = 52;
395 pub const FREEZE_FS = 53;
396 pub const THAW_FS = 54;
397 pub const GLOBAL_NOCACHE = 55;
398 pub const ADDSIGS = 59;
399 pub const ADDFILESIGS = 61;
400 pub const NODIRECT = 62;
401 pub const GETPROTECTIONCLASS = 63;
402 pub const SETPROTECTIONCLASS = 64;
403 pub const LOG2PHYS_EXT = 65;
404 pub const GETLKPID = 66;
405 pub const SETBACKINGSTORE = 70;
406 pub const GETPATH_MTMINFO = 71;
407 pub const GETCODEDIR = 72;
408 pub const SETNOSIGPIPE = 73;
409 pub const GETNOSIGPIPE = 74;
410 pub const TRANSCODEKEY = 75;
411 pub const SINGLE_WRITER = 76;
412 pub const GETPROTECTIONLEVEL = 77;
413 pub const FINDSIGS = 78;
414 pub const ADDFILESIGS_FOR_DYLD_SIM = 83;
415 pub const BARRIERFSYNC = 85;
416 pub const OFD_SETLK = 90;
417 pub const OFD_SETLKW = 91;
418 pub const OFD_GETLK = 92;
419 pub const OFD_SETLKWTIMEOUT = 93;
420 pub const ADDFILESIGS_RETURN = 97;
421 pub const CHECK_LV = 98;
422 pub const PUNCHHOLE = 99;
423 pub const TRIM_ACTIVE_FILE = 100;
424 pub const SPECULATIVE_READ = 101;
425 pub const GETPATH_NOFIRMLINK = 102;
426 pub const ADDFILESIGS_INFO = 103;
427 pub const ADDFILESUPPL = 104;
428 pub const GETSIGSINFO = 105;
429 pub const SETLEASE = 106;
430 pub const GETLEASE = 107;
431 pub const TRANSFEREXTENTS = 110;
432 pub const ATTRIBUTION_TAG = 111;
433 pub const NOCACHE_EXT = 112;
434 pub const ADDSIGS_MAIN_BINARY = 113;
435};
436
437pub const DT = enum(u8) {
438 UNKNOWN = 0,
439 FIFO = 1,
440 CHR = 2,
441 DIR = 4,
442 BLK = 6,
443 REG = 8,
444 LNK = 10,
445 SOCK = 12,
446 WHT = 14,
447};
448
449pub const S = struct {
450 pub const IFMT = 0o170000;
451 pub const IFIFO = 0o010000;
452 pub const IFCHR = 0o020000;
453 pub const IFDIR = 0o040000;
454 pub const IFBLK = 0o060000;
455 pub const IFREG = 0o100000;
456 pub const IFLNK = 0o120000;
457 pub const IFSOCK = 0o140000;
458 pub const IFWHT = 0o160000;
459 pub const IRWXU = 0o000700;
460 pub const IRUSR = 0o000400;
461 pub const IWUSR = 0o000200;
462 pub const IXUSR = 0o000100;
463 pub const IRWXG = 0o000070;
464 pub const IRGRP = 0o000040;
465 pub const IWGRP = 0o000020;
466 pub const IXGRP = 0o000010;
467 pub const IRWXO = 0o000007;
468 pub const IROTH = 0o000004;
469 pub const IWOTH = 0o000002;
470 pub const IXOTH = 0o000001;
471 pub const ISUID = 0o004000;
472 pub const ISGID = 0o002000;
473 pub const ISVTX = 0o001000;
474 pub const ISTXT = ISVTX;
475 pub const IREAD = IRUSR;
476 pub const IWRITE = IWUSR;
477 pub const IEXEC = IXUSR;
478};
479
480pub const SEEK = struct {
481 pub const SET = 0;
482 pub const CUR = 1;
483 pub const END = 2;
484 pub const HOLE = 3;
485 pub const DATA = 4;
486};
487
488pub fn openat(fd: c_int, file: [*:0]const u8, oflag: c_int) errno.Error!c_int {
489 const rc = libc.openat(fd, file, oflag);
490 if (rc == -1) return errno.fromInt(errno.fromLibC());
491 std.debug.assert(rc >= 0);
492 return rc;
493}
494pub fn openat4(fd: c_int, file: [*:0]const u8, oflag: c_int, mode: mode_t) errno.Error!c_int {
495 const rc = libc.openat(fd, file, oflag, mode);
496 if (rc == -1) return errno.fromInt(errno.fromLibC());
497 return rc;
498}
499pub fn fstat(fd: c_int) errno.Error!struct_stat {
500 var buf: struct_stat = undefined;
501 const rc = libc.fstat(fd, &buf);
502 if (rc == -1) return errno.fromInt(errno.fromLibC());
503 std.debug.assert(rc == 0);
504 return buf;
505}
506pub fn close(fd: c_int) errno.Error!void {
507 const rc = libc.close(fd);
508 if (rc == -1) return errno.fromInt(errno.fromLibC());
509 std.debug.assert(rc == 0);
510}
511pub fn read(fd: c_int, buf: []u8) errno.Error!usize {
512 const rc = libc.read(fd, buf.ptr, buf.len);
513 if (rc == -1) return errno.fromInt(errno.fromLibC());
514 std.debug.assert(rc >= 0);
515 return @intCast(rc);
516}
517pub fn clock_gettime(clock_id: clockid_t) !struct_timespec {
518 var tp: struct_timespec = undefined;
519 const rc = libc.clock_gettime(clock_id, &tp);
520 if (rc == -1) return errno.fromInt(errno.fromLibC());
521 std.debug.assert(rc == 0);
522 return tp;
523}
524pub fn mkdirat(fd: c_int, path: [*:0]const u8, mode: mode_t) errno.Error!void {
525 const rc = libc.mkdirat(fd, path, mode);
526 if (rc == -1) return errno.fromInt(errno.fromLibC());
527 std.debug.assert(rc == 0);
528}
529pub fn fstatat(fd: c_int, path: [*:0]const u8, flag: c_int) errno.Error!struct_stat {
530 var buf: struct_stat = undefined;
531 const rc = libc.fstatat(fd, path, &buf, flag);
532 if (rc == -1) return errno.fromInt(errno.fromLibC());
533 std.debug.assert(rc == 0);
534 return buf;
535}
536pub fn getdirentries(fd: c_int, buf: []u8, basep: *c_long) errno.Error!c_uint {
537 const rc = libc.getdirentries(fd, buf.ptr, @intCast(buf.len), basep);
538 if (rc == -1) return errno.fromInt(errno.fromLibC());
539 std.debug.assert(rc >= 0);
540 return @intCast(rc);
541}
542pub fn unlinkat(fd: c_int, name: [*:0]const u8, flag: c_int) !void {
543 const rc = libc.unlinkat(fd, name, flag);
544 if (rc == -1) return errno.fromInt(errno.fromLibC());
545 std.debug.assert(rc == 0);
546}
547pub fn write(fd: c_int, buf: []const u8) !usize {
548 const rc = libc.write(fd, buf.ptr, buf.len);
549 if (rc == -1) return errno.fromInt(errno.fromLibC());
550 std.debug.assert(rc >= 0);
551 return @intCast(rc);
552}
553pub fn writev(fd: c_int, iovec: []const struct_iovec) !usize {
554 const rc = libc.writev(fd, iovec.ptr, @intCast(iovec.len));
555 if (rc == -1) return errno.fromInt(errno.fromLibC());
556 std.debug.assert(rc >= 0);
557 return @intCast(rc);
558}
559pub fn lseek(fd: c_int, offset: off_t, whence: c_int) !void {
560 const rc = libc.lseek(fd, offset, whence);
561 if (rc == -1) return errno.fromInt(errno.fromLibC());
562 std.debug.assert(rc >= 0);
563}
564pub fn getcwd(buf: []u8) ![*:0]u8 {
565 const rc = libc.getcwd(buf.ptr, buf.len);
566 if (rc == null) return errno.fromInt(errno.fromLibC());
567 return rc.?;
568}
569pub fn fchmod(fd: c_int, mode: mode_t) !void {
570 const rc = libc.fchmod(fd, mode);
571 if (rc == -1) return errno.fromInt(errno.fromLibC());
572 std.debug.assert(rc == 0);
573}
574pub fn faccessat(fd: c_int, path: [*:0]const u8, amode: c_int, flag: c_int) !void {
575 const rc = libc.faccessat(fd, path, amode, flag);
576 if (rc == -1) return errno.fromInt(errno.fromLibC());
577 std.debug.assert(rc == 0);
578}
579pub fn readlinkat(dirfd: c_int, noalias path: [*:0]const u8, noalias buf: []u8) ![:0]u8 {
580 const rc = libc.readlinkat(dirfd, path, buf.ptr, buf.len);
581 if (rc == -1) return errno.fromInt(errno.fromLibC());
582 std.debug.assert(rc >= 0);
583 buf[@intCast(rc)] = 0;
584 return buf[0..@intCast(rc) :0];
585}