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;...@@ -51,6 +51,7 @@ pub const Sigaction = linux.Sigaction;
51pub const T = linux.T;51pub const T = linux.T;
52pub const TCP = linux.TCP;52pub const TCP = linux.TCP;
53pub const TCSA = linux.TCSA;53pub const TCSA = linux.TCSA;
54pub const TFD = linux.TFD;
54pub const VDSO = linux.VDSO;55pub const VDSO = linux.VDSO;
55pub const W = linux.W;56pub const W = linux.W;
56pub const W_OK = linux.W_OK;57pub const W_OK = linux.W_OK;
...@@ -68,6 +69,7 @@ pub const fd_t = linux.fd_t;...@@ -68,6 +69,7 @@ pub const fd_t = linux.fd_t;
68pub const gid_t = linux.gid_t;69pub const gid_t = linux.gid_t;
69pub const ifreq = linux.ifreq;70pub const ifreq = linux.ifreq;
70pub const ino_t = linux.ino_t;71pub const ino_t = linux.ino_t;
72pub const itimerspec = linux.itimerspec;
71pub const mcontext_t = linux.mcontext_t;73pub const mcontext_t = linux.mcontext_t;
72pub const mode_t = linux.mode_t;74pub const mode_t = linux.mode_t;
73pub const msghdr = linux.msghdr;75pub const msghdr = linux.msghdr;
...@@ -75,6 +77,7 @@ pub const msghdr_const = linux.msghdr_const;...@@ -75,6 +77,7 @@ pub const msghdr_const = linux.msghdr_const;
75pub const nfds_t = linux.nfds_t;77pub const nfds_t = linux.nfds_t;
76pub const nlink_t = linux.nlink_t;78pub const nlink_t = linux.nlink_t;
77pub const off_t = linux.off_t;79pub const off_t = linux.off_t;
80pub const perf_event_attr = linux.perf_event_attr;
78pub const pid_t = linux.pid_t;81pub const pid_t = linux.pid_t;
79pub const pollfd = linux.pollfd;82pub const pollfd = linux.pollfd;
80pub const rlim_t = linux.rlim_t;83pub const rlim_t = linux.rlim_t;
...@@ -344,3 +347,12 @@ pub const dirent64 = extern struct {...@@ -344,3 +347,12 @@ pub const dirent64 = extern struct {
344 type: u8,347 type: u8,
345 name: [256]u8,348 name: [256]u8,
346};349};
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{...@@ -3968,7 +3968,7 @@ pub const EpollCtlError = error{
3968 FileDescriptorIncompatibleWithEpoll,3968 FileDescriptorIncompatibleWithEpoll,
3969} || UnexpectedError;3969} || 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 {
3972 const rc = system.epoll_ctl(epfd, op, fd, event);3972 const rc = system.epoll_ctl(epfd, op, fd, event);
3973 switch (errno(rc)) {3973 switch (errno(rc)) {
3974 .SUCCESS => return,3974 .SUCCESS => return,
...@@ -3988,7 +3988,7 @@ pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: ?*linux.epoll_event) EpollC...@@ -3988,7 +3988,7 @@ pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: ?*linux.epoll_event) EpollC
3988/// Waits for an I/O event on an epoll file descriptor.3988/// Waits for an I/O event on an epoll file descriptor.
3989/// Returns the number of file descriptors ready for the requested I/O,3989/// Returns the number of file descriptors ready for the requested I/O,
3990/// or zero if no file descriptor became ready during the requested timeout milliseconds.3990/// 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 {
3992 while (true) {3992 while (true) {
3993 // TODO get rid of the @intCast3993 // TODO get rid of the @intCast
3994 const rc = system.epoll_wait(epfd, events.ptr, @intCast(events.len), timeout);3994 const rc = system.epoll_wait(epfd, events.ptr, @intCast(events.len), timeout);
...@@ -7142,32 +7142,35 @@ pub const PerfEventOpenError = error{...@@ -7142,32 +7142,35 @@ pub const PerfEventOpenError = error{
7142} || UnexpectedError;7142} || UnexpectedError;
71437143
7144pub fn perf_event_open(7144pub fn perf_event_open(
7145 attr: *linux.perf_event_attr,7145 attr: *system.perf_event_attr,
7146 pid: pid_t,7146 pid: pid_t,
7147 cpu: i32,7147 cpu: i32,
7148 group_fd: fd_t,7148 group_fd: fd_t,
7149 flags: usize,7149 flags: usize,
7150) PerfEventOpenError!fd_t {7150) PerfEventOpenError!fd_t {
7151 const rc = linux.perf_event_open(attr, pid, cpu, group_fd, flags);7151 if (native_os == .linux) {
7152 switch (errno(rc)) {7152 // There is no syscall wrapper for this function exposed by libcs
7153 .SUCCESS => return @intCast(rc),7153 const rc = linux.perf_event_open(attr, pid, cpu, group_fd, flags);
7154 .@"2BIG" => return error.TooBig,7154 switch (errno(rc)) {
7155 .ACCES => return error.PermissionDenied,7155 .SUCCESS => return @intCast(rc),
7156 .BADF => unreachable, // group_fd file descriptor is not valid.7156 .@"2BIG" => return error.TooBig,
7157 .BUSY => return error.DeviceBusy,7157 .ACCES => return error.PermissionDenied,
7158 .FAULT => unreachable, // Segmentation fault.7158 .BADF => unreachable, // group_fd file descriptor is not valid.
7159 .INVAL => unreachable, // Bad attr settings.7159 .BUSY => return error.DeviceBusy,
7160 .INTR => unreachable, // Mixed perf and ftrace handling for a uprobe.7160 .FAULT => unreachable, // Segmentation fault.
7161 .MFILE => return error.ProcessResources,7161 .INVAL => unreachable, // Bad attr settings.
7162 .NODEV => return error.EventRequiresUnsupportedCpuFeature,7162 .INTR => unreachable, // Mixed perf and ftrace handling for a uprobe.
7163 .NOENT => unreachable, // Invalid type setting.7163 .MFILE => return error.ProcessResources,
7164 .NOSPC => return error.TooManyBreakpoints,7164 .NODEV => return error.EventRequiresUnsupportedCpuFeature,
7165 .NOSYS => return error.SampleStackNotSupported,7165 .NOENT => unreachable, // Invalid type setting.
7166 .OPNOTSUPP => return error.EventNotSupported,7166 .NOSPC => return error.TooManyBreakpoints,
7167 .OVERFLOW => return error.SampleMaxStackOverflow,7167 .NOSYS => return error.SampleStackNotSupported,
7168 .PERM => return error.PermissionDenied,7168 .OPNOTSUPP => return error.EventNotSupported,
7169 .SRCH => return error.ProcessNotFound,7169 .OVERFLOW => return error.SampleMaxStackOverflow,
7170 else => |err| return unexpectedErrno(err),7170 .PERM => return error.PermissionDenied,
7171 .SRCH => return error.ProcessNotFound,
7172 else => |err| return unexpectedErrno(err),
7173 }
7171 }7174 }
7172}7175}
71737176
...@@ -7182,8 +7185,8 @@ pub const TimerFdCreateError = error{...@@ -7182,8 +7185,8 @@ pub const TimerFdCreateError = error{
7182pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError;7185pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError;
7183pub const TimerFdSetError = TimerFdGetError || error{Canceled};7186pub const TimerFdSetError = TimerFdGetError || error{Canceled};
71847187
7185pub fn timerfd_create(clokid: i32, flags: linux.TFD) TimerFdCreateError!fd_t {7188pub fn timerfd_create(clokid: i32, flags: system.TFD) TimerFdCreateError!fd_t {
7186 const rc = linux.timerfd_create(clokid, flags);7189 const rc = system.timerfd_create(clokid, @bitCast(flags));
7187 return switch (errno(rc)) {7190 return switch (errno(rc)) {
7188 .SUCCESS => @intCast(rc),7191 .SUCCESS => @intCast(rc),
7189 .INVAL => unreachable,7192 .INVAL => unreachable,
...@@ -7198,11 +7201,11 @@ pub fn timerfd_create(clokid: i32, flags: linux.TFD) TimerFdCreateError!fd_t {...@@ -7198,11 +7201,11 @@ pub fn timerfd_create(clokid: i32, flags: linux.TFD) TimerFdCreateError!fd_t {
71987201
7199pub fn timerfd_settime(7202pub fn timerfd_settime(
7200 fd: i32,7203 fd: i32,
7201 flags: linux.TFD.TIMER,7204 flags: system.TFD.TIMER,
7202 new_value: *const linux.itimerspec,7205 new_value: *const system.itimerspec,
7203 old_value: ?*linux.itimerspec,7206 old_value: ?*system.itimerspec,
7204) TimerFdSetError!void {7207) 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);
7206 return switch (errno(rc)) {7209 return switch (errno(rc)) {
7207 .SUCCESS => {},7210 .SUCCESS => {},
7208 .BADF => error.InvalidHandle,7211 .BADF => error.InvalidHandle,
...@@ -7213,9 +7216,9 @@ pub fn timerfd_settime(...@@ -7213,9 +7216,9 @@ pub fn timerfd_settime(
7213 };7216 };
7214}7217}
72157218
7216pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec {7219pub fn timerfd_gettime(fd: i32) TimerFdGetError!system.itimerspec {
7217 var curr_value: linux.itimerspec = undefined;7220 var curr_value: system.itimerspec = undefined;
7218 const rc = linux.timerfd_gettime(fd, &curr_value);7221 const rc = system.timerfd_gettime(fd, &curr_value);
7219 return switch (errno(rc)) {7222 return switch (errno(rc)) {
7220 .SUCCESS => return curr_value,7223 .SUCCESS => return curr_value,
7221 .BADF => error.InvalidHandle,7224 .BADF => error.InvalidHandle,