const std = @import("std"); const builtin = @import("builtin"); const os = std.os; const mem = std.mem; const Stat = std.fs.File.Stat; const Kind = std.fs.File.Kind; const StatError = std.fs.File.StatError; const off_t = std.c.off_t; const errno = os.errno; const zeroes = mem.zeroes; pub extern "c" fn copyfile(from: [*:0]const u8, to: [*:0]const u8, state: ?std.c.copyfile_state_t, flags: u32) c_int; pub const COPYFILE_STATE_SRC_FD = @as(c_int, 1); pub const COPYFILE_STATE_SRC_FILENAME = @as(c_int, 2); pub const COPYFILE_STATE_DST_FD = @as(c_int, 3); pub const COPYFILE_STATE_DST_FILENAME = @as(c_int, 4); pub const COPYFILE_STATE_QUARANTINE = @as(c_int, 5); pub const COPYFILE_STATE_STATUS_CB = @as(c_int, 6); pub const COPYFILE_STATE_STATUS_CTX = @as(c_int, 7); pub const COPYFILE_STATE_COPIED = @as(c_int, 8); pub const COPYFILE_STATE_XATTRNAME = @as(c_int, 9); pub const COPYFILE_STATE_WAS_CLONED = @as(c_int, 10); pub const COPYFILE_DISABLE_VAR = "COPYFILE_DISABLE"; pub const COPYFILE_ACL = @as(c_int, 1) << @as(c_int, 0); pub const COPYFILE_STAT = @as(c_int, 1) << @as(c_int, 1); pub const COPYFILE_XATTR = @as(c_int, 1) << @as(c_int, 2); pub const COPYFILE_DATA = @as(c_int, 1) << @as(c_int, 3); pub const COPYFILE_SECURITY = COPYFILE_STAT | COPYFILE_ACL; pub const COPYFILE_METADATA = COPYFILE_SECURITY | COPYFILE_XATTR; pub const COPYFILE_ALL = COPYFILE_METADATA | COPYFILE_DATA; /// Descend into hierarchies pub const COPYFILE_RECURSIVE = @as(c_int, 1) << @as(c_int, 15); /// return flags for xattr or acls if set pub const COPYFILE_CHECK = @as(c_int, 1) << @as(c_int, 16); /// fail if destination exists pub const COPYFILE_EXCL = @as(c_int, 1) << @as(c_int, 17); /// don't follow if source is a symlink pub const COPYFILE_NOFOLLOW_SRC = @as(c_int, 1) << @as(c_int, 18); /// don't follow if dst is a symlink pub const COPYFILE_NOFOLLOW_DST = @as(c_int, 1) << @as(c_int, 19); /// unlink src after copy pub const COPYFILE_MOVE = @as(c_int, 1) << @as(c_int, 20); /// unlink dst before copy pub const COPYFILE_UNLINK = @as(c_int, 1) << @as(c_int, 21); pub const COPYFILE_NOFOLLOW = COPYFILE_NOFOLLOW_SRC | COPYFILE_NOFOLLOW_DST; pub const COPYFILE_PACK = @as(c_int, 1) << @as(c_int, 22); pub const COPYFILE_UNPACK = @as(c_int, 1) << @as(c_int, 23); pub const COPYFILE_CLONE = @as(c_int, 1) << @as(c_int, 24); pub const COPYFILE_CLONE_FORCE = @as(c_int, 1) << @as(c_int, 25); pub const COPYFILE_RUN_IN_PLACE = @as(c_int, 1) << @as(c_int, 26); pub const COPYFILE_DATA_SPARSE = @as(c_int, 1) << @as(c_int, 27); pub const COPYFILE_PRESERVE_DST_TRACKED = @as(c_int, 1) << @as(c_int, 28); pub const COPYFILE_VERBOSE = @as(c_int, 1) << @as(c_int, 30); pub const COPYFILE_RECURSE_ERROR = @as(c_int, 0); pub const COPYFILE_RECURSE_FILE = @as(c_int, 1); pub const COPYFILE_RECURSE_DIR = @as(c_int, 2); pub const COPYFILE_RECURSE_DIR_CLEANUP = @as(c_int, 3); pub const COPYFILE_COPY_DATA = @as(c_int, 4); pub const COPYFILE_COPY_XATTR = @as(c_int, 5); pub const COPYFILE_START = @as(c_int, 1); pub const COPYFILE_FINISH = @as(c_int, 2); pub const COPYFILE_ERR = @as(c_int, 3); pub const COPYFILE_PROGRESS = @as(c_int, 4); pub const COPYFILE_CONTINUE = @as(c_int, 0); pub const COPYFILE_SKIP = @as(c_int, 1); pub const COPYFILE_QUIT = @as(c_int, 2); // int clonefileat(int src_dirfd, const char * src, int dst_dirfd, const char * dst, int flags); pub extern "c" fn clonefileat(c_int, [*c]const u8, c_int, [*c]const u8, uint32_t: c_int) c_int; // int fclonefileat(int srcfd, int dst_dirfd, const char * dst, int flags); pub extern "c" fn fclonefileat(c_int, c_int, [*c]const u8, uint32_t: c_int) c_int; // int clonefile(const char * src, const char * dst, int flags); pub extern "c" fn clonefile([*c]const u8, [*c]const u8, uint32_t: c_int) c_int; // pub fn stat_absolute(path: [:0]const u8) StatError!Stat { // if (builtin.os.tag == .windows) { // var io_status_block: windows.IO_STATUS_BLOCK = undefined; // var info: windows.FILE_ALL_INFORMATION = undefined; // const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation); // switch (rc) { // .SUCCESS => {}, // .BUFFER_OVERFLOW => {}, // .INVALID_PARAMETER => unreachable, // .ACCESS_DENIED => return error.AccessDenied, // else => return windows.unexpectedStatus(rc), // } // return Stat{ // .inode = info.InternalInformation.IndexNumber, // .size = @bitCast(u64, info.StandardInformation.EndOfFile), // .mode = 0, // .kind = if (info.StandardInformation.Directory == 0) .File else .Directory, // .atime = windows.fromSysTime(info.BasicInformation.LastAccessTime), // .mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime), // .ctime = windows.fromSysTime(info.BasicInformation.CreationTime), // }; // } // var st = zeroes(libc_stat); // switch (errno(stat(path.ptr, &st))) { // 0 => {}, // // .EINVAL => unreachable, // .EBADF => unreachable, // Always a race condition. // .ENOMEM => return error.SystemResources, // .EACCES => return error.AccessDenied, // else => |err| return os.unexpectedErrno(err), // } // const atime = st.atime(); // const mtime = st.mtime(); // const ctime = st.ctime(); // return Stat{ // .inode = st.ino, // .size = @bitCast(u64, st.size), // .mode = st.mode, // .kind = switch (builtin.os.tag) { // .wasi => switch (st.filetype) { // os.FILETYPE_BLOCK_DEVICE => Kind.BlockDevice, // os.FILETYPE_CHARACTER_DEVICE => Kind.CharacterDevice, // os.FILETYPE_DIRECTORY => Kind.Directory, // os.FILETYPE_SYMBOLIC_LINK => Kind.SymLink, // os.FILETYPE_REGULAR_FILE => Kind.File, // os.FILETYPE_SOCKET_STREAM, os.FILETYPE_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, // }, // }, // .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, // }; // } pub const struct_fstore = extern struct { fst_flags: c_uint, fst_posmode: c_int, fst_offset: off_t, fst_length: off_t, fst_bytesalloc: off_t, }; pub const fstore_t = struct_fstore; pub const F_ALLOCATECONTIG = @as(c_int, 0x00000002); pub const F_ALLOCATEALL = @as(c_int, 0x00000004); pub const F_PEOFPOSMODE = @as(c_int, 3); pub const F_VOLPOSMODE = @as(c_int, 4); pub fn preallocate_file(fd: os.fd_t, offset: off_t, len: off_t) !void { var fstore = zeroes(fstore_t); fstore.fst_flags = F_ALLOCATECONTIG; fstore.fst_posmode = F_PEOFPOSMODE; fstore.fst_offset = 0; fstore.fst_length = len + offset; // Based on https://api.kde.org/frameworks/kcoreaddons/html/posix__fallocate__mac_8h_source.html var rc = os.system.fcntl(fd, os.F.PREALLOCATE, &fstore); switch (rc) { 0 => return, else => { fstore.fst_flags = F_ALLOCATEALL; rc = os.system.fcntl(fd, os.F.PREALLOCATE, &fstore); }, } std.mem.doNotOptimizeAway(&fstore); } pub const SystemErrno = enum(u8) { SUCCESS = 0, EPERM = 1, ENOENT = 2, ESRCH = 3, EINTR = 4, EIO = 5, ENXIO = 6, E2BIG = 7, ENOEXEC = 8, EBADF = 9, ECHILD = 10, EDEADLK = 11, ENOMEM = 12, EACCES = 13, EFAULT = 14, ENOTBLK = 15, EBUSY = 16, EEXIST = 17, EXDEV = 18, ENODEV = 19, ENOTDIR = 20, EISDIR = 21, EINVAL = 22, ENFILE = 23, EMFILE = 24, ENOTTY = 25, ETXTBSY = 26, EFBIG = 27, ENOSPC = 28, ESPIPE = 29, EROFS = 30, EMLINK = 31, EPIPE = 32, EDOM = 33, ERANGE = 34, EAGAIN = 35, EINPROGRESS = 36, EALREADY = 37, ENOTSOCK = 38, EDESTADDRREQ = 39, EMSGSIZE = 40, EPROTOTYPE = 41, ENOPROTOOPT = 42, EPROTONOSUPPORT = 43, ESOCKTNOSUPPORT = 44, ENOTSUP = 45, EPFNOSUPPORT = 46, EAFNOSUPPORT = 47, EADDRINUSE = 48, EADDRNOTAVAIL = 49, ENETDOWN = 50, ENETUNREACH = 51, ENETRESET = 52, ECONNABORTED = 53, ECONNRESET = 54, ENOBUFS = 55, EISCONN = 56, ENOTCONN = 57, ESHUTDOWN = 58, ETOOMANYREFS = 59, ETIMEDOUT = 60, ECONNREFUSED = 61, ELOOP = 62, ENAMETOOLONG = 63, EHOSTDOWN = 64, EHOSTUNREACH = 65, ENOTEMPTY = 66, EPROCLIM = 67, EUSERS = 68, EDQUOT = 69, ESTALE = 70, EREMOTE = 71, EBADRPC = 72, ERPCMISMATCH = 73, EPROGUNAVAIL = 74, EPROGMISMATCH = 75, EPROCUNAVAIL = 76, ENOLCK = 77, ENOSYS = 78, EFTYPE = 79, EAUTH = 80, ENEEDAUTH = 81, EPWROFF = 82, EDEVERR = 83, EOVERFLOW = 84, EBADEXEC = 85, EBADARCH = 86, ESHLIBVERS = 87, EBADMACHO = 88, ECANCELED = 89, EIDRM = 90, ENOMSG = 91, EILSEQ = 92, ENOATTR = 93, EBADMSG = 94, EMULTIHOP = 95, ENODATA = 96, ENOLINK = 97, ENOSR = 98, ENOSTR = 99, EPROTO = 100, ETIME = 101, EOPNOTSUPP = 102, ENOPOLICY = 103, ENOTRECOVERABLE = 104, EOWNERDEAD = 105, EQFULL = 106, pub const max = 107; pub fn init(code: anytype) ?SystemErrno { if (comptime std.meta.trait.isSignedInt(@TypeOf(code))) { if (code < 0) return init(-code); } if (code >= max) return null; return @intToEnum(SystemErrno, code); } pub fn label(this: SystemErrno) ?[]const u8 { return labels.get(this) orelse null; } const LabelMap = std.EnumMap(SystemErrno, []const u8); pub const labels: LabelMap = brk: { var map: LabelMap = LabelMap.initFull(""); map.put(.E2BIG, "Argument list too long"); map.put(.EACCES, "Permission denied"); map.put(.EADDRINUSE, "Address already in use"); map.put(.EADDRNOTAVAIL, "Can’t assign requested address"); map.put(.EAFNOSUPPORT, "Address family not supported by protocol family"); map.put(.EAGAIN, "non-blocking and interrupt i/o. Resource temporarily unavailable"); map.put(.EALREADY, "Operation already in progress"); map.put(.EAUTH, "Authentication error"); map.put(.EBADARCH, "Bad CPU type in executable"); map.put(.EBADEXEC, "Program loading errors. Bad executable"); map.put(.EBADF, "Bad file descriptor"); map.put(.EBADMACHO, "Malformed Macho file"); map.put(.EBADMSG, "Bad message"); map.put(.EBADRPC, "RPC struct is bad"); map.put(.EBUSY, "Device / Resource busy"); map.put(.ECANCELED, "Operation canceled"); map.put(.ECHILD, "No child processes"); map.put(.ECONNABORTED, "Software caused connection abort"); map.put(.ECONNREFUSED, "Connection refused"); map.put(.ECONNRESET, "Connection reset by peer"); map.put(.EDEADLK, "Resource deadlock avoided"); map.put(.EDESTADDRREQ, "Destination address required"); map.put(.EDEVERR, "Device error, for example paper out"); map.put(.EDOM, "math software. Numerical argument out of domain"); map.put(.EDQUOT, "Disc quota exceeded"); map.put(.EEXIST, "File or folder exists"); map.put(.EFAULT, "Bad address"); map.put(.EFBIG, "File too large"); map.put(.EFTYPE, "Inappropriate file type or format"); map.put(.EHOSTDOWN, "Host is down"); map.put(.EHOSTUNREACH, "No route to host"); map.put(.EIDRM, "Identifier removed"); map.put(.EILSEQ, "Illegal byte sequence"); map.put(.EINPROGRESS, "Operation now in progress"); map.put(.EINTR, "Interrupted system call"); map.put(.EINVAL, "Invalid argument"); map.put(.EIO, "Input/output error"); map.put(.EISCONN, "Socket is already connected"); map.put(.EISDIR, "Is a directory"); map.put(.ELOOP, "Too many levels of symbolic links"); map.put(.EMFILE, "Too many open files"); map.put(.EMLINK, "Too many links"); map.put(.EMSGSIZE, "Message too long"); map.put(.EMULTIHOP, "Reserved"); map.put(.ENAMETOOLONG, "File name too long"); map.put(.ENEEDAUTH, "Need authenticator"); map.put(.ENETDOWN, "ipc/network software – operational errors Network is down"); map.put(.ENETRESET, "Network dropped connection on reset"); map.put(.ENETUNREACH, "Network is unreachable"); map.put(.ENFILE, "Too many open files in system"); map.put(.ENOATTR, "Attribute not found"); map.put(.ENOBUFS, "No buffer space available"); map.put(.ENODATA, "No message available on STREAM"); map.put(.ENODEV, "Operation not supported by device"); map.put(.ENOENT, "No such file or directory"); map.put(.ENOEXEC, "Exec format error"); map.put(.ENOLCK, "No locks available"); map.put(.ENOLINK, "Reserved"); map.put(.ENOMEM, "Cannot allocate memory"); map.put(.ENOMSG, "No message of desired type"); map.put(.ENOPOLICY, "No such policy registered"); map.put(.ENOPROTOOPT, "Protocol not available"); map.put(.ENOSPC, "No space left on device"); map.put(.ENOSR, "No STREAM resources"); map.put(.ENOSTR, "Not a STREAM"); map.put(.ENOSYS, "Function not implemented"); map.put(.ENOTBLK, "Block device required"); map.put(.ENOTCONN, "Socket is not connected"); map.put(.ENOTDIR, "Not a directory"); map.put(.ENOTEMPTY, "Directory not empty"); map.put(.ENOTRECOVERABLE, "State not recoverable"); map.put(.ENOTSOCK, "ipc/network software – argument errors. Socket operation on non-socket"); map.put(.ENOTSUP, "Operation not supported"); map.put(.ENOTTY, "Inappropriate ioctl for device"); map.put(.ENXIO, "Device not configured"); map.put(.EOVERFLOW, "Value too large to be stored in data type"); map.put(.EOWNERDEAD, "Previous owner died"); map.put(.EPERM, "Operation not permitted"); map.put(.EPFNOSUPPORT, "Protocol family not supported"); map.put(.EPIPE, "Broken pipe"); map.put(.EPROCLIM, "quotas & mush. Too many processes"); map.put(.EPROCUNAVAIL, "Bad procedure for program"); map.put(.EPROGMISMATCH, "Program version wrong"); map.put(.EPROGUNAVAIL, "RPC prog. not avail"); map.put(.EPROTO, "Protocol error"); map.put(.EPROTONOSUPPORT, "Protocol not supported"); map.put(.EPROTOTYPE, "Protocol wrong type for socket"); map.put(.EPWROFF, "Intelligent device errors. Device power is off"); map.put(.EQFULL, "Interface output queue is full"); map.put(.ERANGE, "Result too large"); map.put(.EREMOTE, "Too many levels of remote in path"); map.put(.EROFS, "Read-only file system"); map.put(.ERPCMISMATCH, "RPC version wrong"); map.put(.ESHLIBVERS, "Shared library version mismatch"); map.put(.ESHUTDOWN, "Can’t send after socket shutdown"); map.put(.ESOCKTNOSUPPORT, "Socket type not supported"); map.put(.ESPIPE, "Illegal seek"); map.put(.ESRCH, "No such process"); map.put(.ESTALE, "Network File System. Stale NFS file handle"); map.put(.ETIME, "STREAM ioctl timeout"); map.put(.ETIMEDOUT, "Operation timed out"); map.put(.ETOOMANYREFS, "Too many references: can’t splice"); map.put(.ETXTBSY, "Text file busy"); map.put(.EUSERS, "Too many users"); // map.put(.EWOULDBLOCK, "Operation would block"); map.put(.EXDEV, "Cross-device link"); break :brk map; }; }; // Courtesy of https://github.com/nodejs/node/blob/master/deps/uv/src/unix/darwin-stub.h pub const struct_CFArrayCallBacks = opaque {}; pub const CFIndex = c_long; pub const struct_CFRunLoopSourceContext = extern struct { version: CFIndex, info: ?*anyopaque, pad: [7]?*anyopaque, perform: ?*const fn (?*anyopaque) callconv(.C) void, }; pub const struct_FSEventStreamContext = extern struct { version: CFIndex, info: ?*anyopaque, pad: [3]?*anyopaque, }; pub const struct_CFRange = extern struct { location: CFIndex, length: CFIndex, }; pub const CFAbsoluteTime = f64; pub const CFTimeInterval = f64; pub const FSEventStreamEventFlags = c_int; pub const OSStatus = c_int; pub const CFArrayCallBacks = struct_CFArrayCallBacks; pub const CFRunLoopSourceContext = struct_CFRunLoopSourceContext; pub const FSEventStreamContext = struct_FSEventStreamContext; pub const FSEventStreamCreateFlags = u32; pub const FSEventStreamEventId = u64; pub const CFStringEncoding = c_uint; pub const CFAllocatorRef = ?*anyopaque; pub const CFArrayRef = ?*anyopaque; pub const CFBundleRef = ?*anyopaque; pub const CFDataRef = ?*anyopaque; pub const CFDictionaryRef = ?*anyopaque; pub const CFMutableDictionaryRef = ?*anyopaque; pub const CFRange = struct_CFRange; pub const CFRunLoopRef = ?*anyopaque; pub const CFRunLoopSourceRef = ?*anyopaque; pub const CFStringRef = ?*anyopaque; pub const CFTypeRef = ?*anyopaque; pub const FSEventStreamRef = ?*anyopaque; pub const IOOptionBits = u32; pub const io_iterator_t = c_uint; pub const io_object_t = c_uint; pub const io_service_t = c_uint; pub const io_registry_entry_t = c_uint; pub const FSEventStreamCallback = ?*const fn (FSEventStreamRef, ?*anyopaque, c_int, ?*anyopaque, [*c]const FSEventStreamEventFlags, [*c]const FSEventStreamEventId) callconv(.C) void; pub const kCFStringEncodingUTF8: CFStringEncoding = @bitCast(CFStringEncoding, @as(c_int, 134217984)); pub const noErr: OSStatus = 0; pub const kFSEventStreamEventIdSinceNow: FSEventStreamEventId = @bitCast(FSEventStreamEventId, @as(c_longlong, -@as(c_int, 1))); pub const kFSEventStreamCreateFlagNoDefer: c_int = 2; pub const kFSEventStreamCreateFlagFileEvents: c_int = 16; pub const kFSEventStreamEventFlagEventIdsWrapped: c_int = 8; pub const kFSEventStreamEventFlagHistoryDone: c_int = 16; pub const kFSEventStreamEventFlagItemChangeOwner: c_int = 16384; pub const kFSEventStreamEventFlagItemCreated: c_int = 256; pub const kFSEventStreamEventFlagItemFinderInfoMod: c_int = 8192; pub const kFSEventStreamEventFlagItemInodeMetaMod: c_int = 1024; pub const kFSEventStreamEventFlagItemIsDir: c_int = 131072; pub const kFSEventStreamEventFlagItemModified: c_int = 4096; pub const kFSEventStreamEventFlagItemRemoved: c_int = 512; pub const kFSEventStreamEventFlagItemRenamed: c_int = 2048; pub const kFSEventStreamEventFlagItemXattrMod: c_int = 32768; pub const kFSEventStreamEventFlagKernelDropped: c_int = 4; pub const kFSEventStreamEventFlagMount: c_int = 64; pub const kFSEventStreamEventFlagRootChanged: c_int = 32; pub const kFSEventStreamEventFlagUnmount: c_int = 128; pub const kFSEventStreamEventFlagUserDropped: c_int = 2; pub fn get_free_memory() u64 { // NOT IMPLEMENTED YET return 1024 * 1024; } pub fn get_total_memory() u64 { var memory_: [32]c_ulonglong = undefined; var size: usize = memory_.len; std.os.sysctlbynameZ( "hw.memsize", &memory_, &size, null, 0, ) catch |err| switch (err) { else => return 0, }; return memory_[0]; } pub const struct_BootTime = struct { sec: u32, }; pub fn get_system_uptime() u64 { var uptime_: [16]struct_BootTime = undefined; var size: usize = uptime_.len; std.os.sysctlbynameZ( "kern.boottime", &uptime_, &size, null, 0, ) catch |err| switch (err) { else => return 0, }; return @bitCast(u64, std.time.timestamp() - uptime_[0].sec); } pub const struct_LoadAvg = struct { ldavg: [3]u32, fscale: c_long, }; pub fn get_system_loadavg() [3]f64 { var loadavg_: [24]struct_LoadAvg = undefined; var size: usize = loadavg_.len; std.os.sysctlbynameZ( "vm.loadavg", &loadavg_, &size, null, 0, ) catch |err| switch (err) { else => return [3]f64{ 0, 0, 0 }, }; const loadavg = loadavg_[0]; const scale = @intToFloat(f64, loadavg.fscale); return [3]f64{ @intToFloat(f64, loadavg.ldavg[0]) / scale, @intToFloat(f64, loadavg.ldavg[1]) / scale, @intToFloat(f64, loadavg.ldavg[2]) / scale, }; } pub extern fn getuid(...) std.os.uid_t; pub extern fn getgid(...) std.os.gid_t; pub extern fn get_process_priority(pid: c_uint) i32; pub extern fn set_process_priority(pid: c_uint, priority: c_int) i32; pub fn get_version(buf: []u8) []const u8 { @memset(buf.ptr, 0, buf.len); var size: usize = buf.len; if (std.c.sysctlbyname( "kern.version", buf.ptr, &size, null, 0, ) == -1) return "unknown"; return std.mem.span(std.meta.assumeSentinel(buf.ptr, 0)); } pub fn get_release(buf: []u8) []const u8 { @memset(buf.ptr, 0, buf.len); var size: usize = buf.len; if (std.c.sysctlbyname( "kern.osrelease", buf.ptr, &size, null, 0, ) == -1) return "unknown"; return std.mem.span(std.meta.assumeSentinel(buf.ptr, 0)); } const IO_CTL_RELATED = struct { pub const IOCPARM_MASK = @as(c_int, 0x1fff); pub inline fn IOCPARM_LEN(x: anytype) @TypeOf((x >> @as(c_int, 16)) & IOCPARM_MASK) { return (x >> @as(c_int, 16)) & IOCPARM_MASK; } pub inline fn IOCBASECMD(x: anytype) @TypeOf(x & ~(IOCPARM_MASK << @as(c_int, 16))) { return x & ~(IOCPARM_MASK << @as(c_int, 16)); } pub inline fn IOCGROUP(x: anytype) @TypeOf((x >> @as(c_int, 8)) & @as(c_int, 0xff)) { return (x >> @as(c_int, 8)) & @as(c_int, 0xff); } pub const IOCPARM_MAX = IOCPARM_MASK + @as(c_int, 1); pub const IOC_VOID = @import("std").zig.c_translation.cast(u32, @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x20000000, .hexadecimal)); pub const IOC_OUT = @import("std").zig.c_translation.cast(u32, @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x40000000, .hexadecimal)); pub const IOC_IN = @import("std").zig.c_translation.cast(u32, @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x80000000, .hexadecimal)); pub const IOC_INOUT = IOC_IN | IOC_OUT; pub const IOC_DIRMASK = @import("std").zig.c_translation.cast(u32, @import("std").zig.c_translation.promoteIntLiteral(c_int, 0xe0000000, .hexadecimal)); pub inline fn _IOC(inout: anytype, group: anytype, num: anytype, len: anytype) @TypeOf(((inout | ((len & IOCPARM_MASK) << @as(c_int, 16))) | (group << @as(c_int, 8))) | num) { return ((inout | ((len & IOCPARM_MASK) << @as(c_int, 16))) | (group << @as(c_int, 8))) | num; } pub inline fn _IO(g: anytype, n: anytype) @TypeOf(_IOC(IOC_VOID, g, n, @as(c_int, 0))) { return _IOC(IOC_VOID, g, n, @as(c_int, 0)); } pub inline fn _IOR(g: anytype, n: anytype, t: anytype) @TypeOf(_IOC(IOC_OUT, g, n, @import("std").zig.c_translation.sizeof(t))) { return _IOC(IOC_OUT, g, n, @import("std").zig.c_translation.sizeof(t)); } pub inline fn _IOW(g: anytype, n: anytype, t: anytype) @TypeOf(_IOC(IOC_IN, g, n, @import("std").zig.c_translation.sizeof(t))) { return _IOC(IOC_IN, g, n, @import("std").zig.c_translation.sizeof(t)); } pub inline fn _IOWR(g: anytype, n: anytype, t: anytype) @TypeOf(_IOC(IOC_INOUT, g, n, @import("std").zig.c_translation.sizeof(t))) { return _IOC(IOC_INOUT, g, n, @import("std").zig.c_translation.sizeof(t)); } pub const TIOCMODG = _IOR('t', @as(c_int, 3), c_int); pub const TIOCMODS = _IOW('t', @as(c_int, 4), c_int); pub const TIOCM_LE = @as(c_int, 0o001); pub const TIOCM_DTR = @as(c_int, 0o002); pub const TIOCM_RTS = @as(c_int, 0o004); pub const TIOCM_ST = @as(c_int, 0o010); pub const TIOCM_SR = @as(c_int, 0o020); pub const TIOCM_CTS = @as(c_int, 0o040); pub const TIOCM_CAR = @as(c_int, 0o100); pub const TIOCM_CD = TIOCM_CAR; pub const TIOCM_RNG = @as(c_int, 0o200); pub const TIOCM_RI = TIOCM_RNG; pub const TIOCM_DSR = @as(c_int, 0o400); pub const TIOCEXCL = _IO('t', @as(c_int, 13)); pub const TIOCNXCL = _IO('t', @as(c_int, 14)); pub const TIOCFLUSH = _IOW('t', @as(c_int, 16), c_int); pub const TIOCGETD = _IOR('t', @as(c_int, 26), c_int); pub const TIOCSETD = _IOW('t', @as(c_int, 27), c_int); pub const TIOCIXON = _IO('t', @as(c_int, 129)); pub const TIOCIXOFF = _IO('t', @as(c_int, 128)); pub const TIOCSBRK = _IO('t', @as(c_int, 123)); pub const TIOCCBRK = _IO('t', @as(c_int, 122)); pub const TIOCSDTR = _IO('t', @as(c_int, 121)); pub const TIOCCDTR = _IO('t', @as(c_int, 120)); pub const TIOCGPGRP = _IOR('t', @as(c_int, 119), c_int); pub const TIOCSPGRP = _IOW('t', @as(c_int, 118), c_int); pub const TIOCOUTQ = _IOR('t', @as(c_int, 115), c_int); pub const TIOCSTI = _IOW('t', @as(c_int, 114), u8); pub const TIOCNOTTY = _IO('t', @as(c_int, 113)); pub const TIOCPKT = _IOW('t', @as(c_int, 112), c_int); pub const TIOCPKT_DATA = @as(c_int, 0x00); pub const TIOCPKT_FLUSHREAD = @as(c_int, 0x01); pub const TIOCPKT_FLUSHWRITE = @as(c_int, 0x02); pub const TIOCPKT_STOP = @as(c_int, 0x04); pub const TIOCPKT_START = @as(c_int, 0x08); pub const TIOCPKT_NOSTOP = @as(c_int, 0x10); pub const TIOCPKT_DOSTOP = @as(c_int, 0x20); pub const TIOCPKT_IOCTL = @as(c_int, 0x40); pub const TIOCSTOP = _IO('t', @as(c_int, 111)); pub const TIOCSTART = _IO('t', @as(c_int, 110)); pub const TIOCMSET = _IOW('t', @as(c_int, 109), c_int); pub const TIOCMBIS = _IOW('t', @as(c_int, 108), c_int); pub const TIOCMBIC = _IOW('t', @as(c_int, 107), c_int); pub const TIOCMGET = _IOR('t', @as(c_int, 106), c_int); // pub const TIOCGWINSZ = _IOR('t', @as(c_int, 104), struct_winsize); // pub const TIOCSWINSZ = _IOW('t', @as(c_int, 103), struct_winsize); pub const TIOCUCNTL = _IOW('t', @as(c_int, 102), c_int); pub const TIOCSTAT = _IO('t', @as(c_int, 101)); pub inline fn UIOCCMD(n: anytype) @TypeOf(_IO('u', n)) { return _IO('u', n); } pub const TIOCSCONS = _IO('t', @as(c_int, 99)); pub const TIOCCONS = _IOW('t', @as(c_int, 98), c_int); pub const TIOCSCTTY = _IO('t', @as(c_int, 97)); pub const TIOCEXT = _IOW('t', @as(c_int, 96), c_int); pub const TIOCSIG = _IO('t', @as(c_int, 95)); pub const TIOCDRAIN = _IO('t', @as(c_int, 94)); pub const TIOCMSDTRWAIT = _IOW('t', @as(c_int, 91), c_int); pub const TIOCMGDTRWAIT = _IOR('t', @as(c_int, 90), c_int); pub const TIOCSDRAINWAIT = _IOW('t', @as(c_int, 87), c_int); pub const TIOCGDRAINWAIT = _IOR('t', @as(c_int, 86), c_int); pub const TIOCDSIMICROCODE = _IO('t', @as(c_int, 85)); pub const TIOCPTYGRANT = _IO('t', @as(c_int, 84)); pub const TIOCPTYGNAME = _IOC(IOC_OUT, 't', @as(c_int, 83), @as(c_int, 128)); pub const TIOCPTYUNLK = _IO('t', @as(c_int, 82)); pub const TTYDISC = @as(c_int, 0); pub const TABLDISC = @as(c_int, 3); pub const SLIPDISC = @as(c_int, 4); pub const PPPDISC = @as(c_int, 5); // pub const TIOCGSIZE = TIOCGWINSZ; // pub const TIOCSSIZE = TIOCSWINSZ; pub const FIOCLEX = _IO('f', @as(c_int, 1)); pub const FIONCLEX = _IO('f', @as(c_int, 2)); pub const FIONREAD = _IOR('f', @as(c_int, 127), c_int); pub const FIONBIO = _IOW('f', @as(c_int, 126), c_int); pub const FIOASYNC = _IOW('f', @as(c_int, 125), c_int); pub const FIOSETOWN = _IOW('f', @as(c_int, 124), c_int); pub const FIOGETOWN = _IOR('f', @as(c_int, 123), c_int); pub const FIODTYPE = _IOR('f', @as(c_int, 122), c_int); pub const SIOCSHIWAT = _IOW('s', @as(c_int, 0), c_int); pub const SIOCGHIWAT = _IOR('s', @as(c_int, 1), c_int); pub const SIOCSLOWAT = _IOW('s', @as(c_int, 2), c_int); pub const SIOCGLOWAT = _IOR('s', @as(c_int, 3), c_int); pub const SIOCATMARK = _IOR('s', @as(c_int, 7), c_int); pub const SIOCSPGRP = _IOW('s', @as(c_int, 8), c_int); pub const SIOCGPGRP = _IOR('s', @as(c_int, 9), c_int); // pub const SIOCSETVLAN = SIOCSIFVLAN; // pub const SIOCGETVLAN = SIOCGIFVLAN; }; pub usingnamespace IO_CTL_RELATED; pub const RemoveFileFlags = struct { /// If path is a directory, recurse (depth first traversal) pub const recursive: u32 = (1 << 0); /// Remove contents but not directory itself pub const keep_parent: u32 = (1 << 1); /// 7 pass DoD algorithm pub const secure_7_pass: u32 = (1 << 2); /// 35-pass Gutmann algorithm (overrides REMOVEFILE_SECURE_7_PASS) pub const secure_35_pass: u32 = (1 << 3); /// 1 pass single overwrite), pub const secure_1_pass: u32 = (1 << 4); /// 3 pass overwrite pub const secure_3_pass: u32 = (1 << 5); /// Single-pass overwrite, with 0 instead of random data pub const secure_1_pass_zero: u32 = (1 << 6); /// Cross mountpoints when deleting recursively. << 6), pub const cross_mount: u32 = (1 << 7); /// Paths may be longer than PATH_MAX - requires temporarily changing cwd pub const allow_long_paths: u32 = (1 << 8); }; pub const removefile_state_t = opaque {}; pub extern fn removefileat(fd: c_int, path: [*c]const u8, state: ?*removefile_state_t, flags: u32) c_int;