authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2024-06-15 18:08:09+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2024-06-18 22:35:28+02:00
log5f2bdafa39255234381076d4095140f922d21577
tree75f1b0410af558e1176c3e4bb95715d627a62235
parent7dc52a367ae6bf7d9adbe72f1d3c34103c3c6a4f

std.posix: remove unchecked std.os.linux usage

Using std.os.linux directly in e.g. std.posix.timerfd_create() causes the function to compile but silently fail at runtime when targeting any OS other than Linux. To catch errors like this at compile time, std.os.linux must only be directly accessed within std.posix where there has been a comptime check that the target os is in fact Linux.

2 files changed, 47 insertions(+), 32 deletions(-)

lib/std/c/linux.zig+12
......@@ -51,6 +51,7 @@ pub const Sigaction = linux.Sigaction;
5151pub const T = linux.T;
5252pub const TCP = linux.TCP;
5353pub const TCSA = linux.TCSA;
54pub const TFD = linux.TFD;
5455pub const VDSO = linux.VDSO;
5556pub const W = linux.W;
5657pub const W_OK = linux.W_OK;
......@@ -68,6 +69,7 @@ pub const fd_t = linux.fd_t;
6869pub const gid_t = linux.gid_t;
6970pub const ifreq = linux.ifreq;
7071pub const ino_t = linux.ino_t;
72pub const itimerspec = linux.itimerspec;
7173pub const mcontext_t = linux.mcontext_t;
7274pub const mode_t = linux.mode_t;
7375pub const msghdr = linux.msghdr;
......@@ -75,6 +77,7 @@ pub const msghdr_const = linux.msghdr_const;
7577pub const nfds_t = linux.nfds_t;
7678pub const nlink_t = linux.nlink_t;
7779pub const off_t = linux.off_t;
80pub const perf_event_attr = linux.perf_event_attr;
7881pub const pid_t = linux.pid_t;
7982pub const pollfd = linux.pollfd;
8083pub const rlim_t = linux.rlim_t;
......@@ -344,3 +347,12 @@ pub const dirent64 = extern struct {
344347 type: u8,
345348 name: [256]u8,
346349};
350
351pub extern "c" fn timerfd_create(clockid: c_int, flags: c_int) c_int;
352pub extern "c" fn timerfd_settime(
353 fd: c_int,
354 flags: c_int,
355 new_value: *const itimerspec,
356 old_value: ?*itimerspec,
357) c_int;
358pub extern "c" fn timerfd_gettime(fd: c_int, curr_value: *itimerspec) c_int;
lib/std/posix.zig+35-32
......@@ -3968,7 +3968,7 @@ pub const EpollCtlError = error{
39683968 FileDescriptorIncompatibleWithEpoll,
39693969} || UnexpectedError;
39703970
3971pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: ?*linux.epoll_event) EpollCtlError!void {
3971pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: ?*system.epoll_event) EpollCtlError!void {
39723972 const rc = system.epoll_ctl(epfd, op, fd, event);
39733973 switch (errno(rc)) {
39743974 .SUCCESS => return,
......@@ -3988,7 +3988,7 @@ pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: ?*linux.epoll_event) EpollC
39883988/// Waits for an I/O event on an epoll file descriptor.
39893989/// Returns the number of file descriptors ready for the requested I/O,
39903990/// or zero if no file descriptor became ready during the requested timeout milliseconds.
3991pub fn epoll_wait(epfd: i32, events: []linux.epoll_event, timeout: i32) usize {
3991pub fn epoll_wait(epfd: i32, events: []system.epoll_event, timeout: i32) usize {
39923992 while (true) {
39933993 // TODO get rid of the @intCast
39943994 const rc = system.epoll_wait(epfd, events.ptr, @intCast(events.len), timeout);
......@@ -7142,32 +7142,35 @@ pub const PerfEventOpenError = error{
71427142} || UnexpectedError;
71437143
71447144pub fn perf_event_open(
7145 attr: *linux.perf_event_attr,
7145 attr: *system.perf_event_attr,
71467146 pid: pid_t,
71477147 cpu: i32,
71487148 group_fd: fd_t,
71497149 flags: usize,
71507150) PerfEventOpenError!fd_t {
7151 const rc = linux.perf_event_open(attr, pid, cpu, group_fd, flags);
7152 switch (errno(rc)) {
7153 .SUCCESS => return @intCast(rc),
7154 .@"2BIG" => return error.TooBig,
7155 .ACCES => return error.PermissionDenied,
7156 .BADF => unreachable, // group_fd file descriptor is not valid.
7157 .BUSY => return error.DeviceBusy,
7158 .FAULT => unreachable, // Segmentation fault.
7159 .INVAL => unreachable, // Bad attr settings.
7160 .INTR => unreachable, // Mixed perf and ftrace handling for a uprobe.
7161 .MFILE => return error.ProcessResources,
7162 .NODEV => return error.EventRequiresUnsupportedCpuFeature,
7163 .NOENT => unreachable, // Invalid type setting.
7164 .NOSPC => return error.TooManyBreakpoints,
7165 .NOSYS => return error.SampleStackNotSupported,
7166 .OPNOTSUPP => return error.EventNotSupported,
7167 .OVERFLOW => return error.SampleMaxStackOverflow,
7168 .PERM => return error.PermissionDenied,
7169 .SRCH => return error.ProcessNotFound,
7170 else => |err| return unexpectedErrno(err),
7151 if (native_os == .linux) {
7152 // There is no syscall wrapper for this function exposed by libcs
7153 const rc = linux.perf_event_open(attr, pid, cpu, group_fd, flags);
7154 switch (errno(rc)) {
7155 .SUCCESS => return @intCast(rc),
7156 .@"2BIG" => return error.TooBig,
7157 .ACCES => return error.PermissionDenied,
7158 .BADF => unreachable, // group_fd file descriptor is not valid.
7159 .BUSY => return error.DeviceBusy,
7160 .FAULT => unreachable, // Segmentation fault.
7161 .INVAL => unreachable, // Bad attr settings.
7162 .INTR => unreachable, // Mixed perf and ftrace handling for a uprobe.
7163 .MFILE => return error.ProcessResources,
7164 .NODEV => return error.EventRequiresUnsupportedCpuFeature,
7165 .NOENT => unreachable, // Invalid type setting.
7166 .NOSPC => return error.TooManyBreakpoints,
7167 .NOSYS => return error.SampleStackNotSupported,
7168 .OPNOTSUPP => return error.EventNotSupported,
7169 .OVERFLOW => return error.SampleMaxStackOverflow,
7170 .PERM => return error.PermissionDenied,
7171 .SRCH => return error.ProcessNotFound,
7172 else => |err| return unexpectedErrno(err),
7173 }
71717174 }
71727175}
71737176
......@@ -7182,8 +7185,8 @@ pub const TimerFdCreateError = error{
71827185pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError;
71837186pub const TimerFdSetError = TimerFdGetError || error{Canceled};
71847187
7185pub fn timerfd_create(clokid: i32, flags: linux.TFD) TimerFdCreateError!fd_t {
7186 const rc = linux.timerfd_create(clokid, flags);
7188pub fn timerfd_create(clokid: i32, flags: system.TFD) TimerFdCreateError!fd_t {
7189 const rc = system.timerfd_create(clokid, @bitCast(flags));
71877190 return switch (errno(rc)) {
71887191 .SUCCESS => @intCast(rc),
71897192 .INVAL => unreachable,
......@@ -7198,11 +7201,11 @@ pub fn timerfd_create(clokid: i32, flags: linux.TFD) TimerFdCreateError!fd_t {
71987201
71997202pub fn timerfd_settime(
72007203 fd: i32,
7201 flags: linux.TFD.TIMER,
7202 new_value: *const linux.itimerspec,
7203 old_value: ?*linux.itimerspec,
7204 flags: system.TFD.TIMER,
7205 new_value: *const system.itimerspec,
7206 old_value: ?*system.itimerspec,
72047207) TimerFdSetError!void {
7205 const rc = linux.timerfd_settime(fd, flags, new_value, old_value);
7208 const rc = system.timerfd_settime(fd, @bitCast(flags), new_value, old_value);
72067209 return switch (errno(rc)) {
72077210 .SUCCESS => {},
72087211 .BADF => error.InvalidHandle,
......@@ -7213,9 +7216,9 @@ pub fn timerfd_settime(
72137216 };
72147217}
72157218
7216pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec {
7217 var curr_value: linux.itimerspec = undefined;
7218 const rc = linux.timerfd_gettime(fd, &curr_value);
7219pub fn timerfd_gettime(fd: i32) TimerFdGetError!system.itimerspec {
7220 var curr_value: system.itimerspec = undefined;
7221 const rc = system.timerfd_gettime(fd, &curr_value);
72197222 return switch (errno(rc)) {
72207223 .SUCCESS => return curr_value,
72217224 .BADF => error.InvalidHandle,