aboutsummaryrefslogtreecommitdiff
path: root/lib/std/os.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-09-22 11:41:21 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-09-22 11:41:21 -0700
commite2d1f9874df2a9221aaa9ec55bd2974b70601f64 (patch)
treeeff7919b0717e193aa53b70fcee862d6f33deddb /lib/std/os.zig
parent52b8239a22aa37fe3914427cd4e2905231769e59 (diff)
parent58ee5f4e61cd9b7a9ba65798e2214efa3753a733 (diff)
downloadzig-e2d1f9874df2a9221aaa9ec55bd2974b70601f64.tar.gz
zig-e2d1f9874df2a9221aaa9ec55bd2974b70601f64.zip
Merge remote-tracking branch 'origin/master' into llvm11
Diffstat (limited to 'lib/std/os.zig')
-rw-r--r--lib/std/os.zig56
1 files changed, 52 insertions, 4 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 181bf4930d..0b09b1f82a 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -320,6 +320,7 @@ pub const ReadError = error{
/// Linux has a limit on how many bytes may be transferred in one `read` call, which is `0x7ffff000`
/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
/// well as stuffing the errno codes into the last `4096` values. This is noted on the `read` man page.
+/// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL.
/// For POSIX the limit is `math.maxInt(isize)`.
pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
if (builtin.os.tag == .windows) {
@@ -353,6 +354,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
// Prevents EINVAL.
const max_count = switch (std.Target.current.os.tag) {
.linux => 0x7ffff000,
+ .macosx, .ios, .watchos, .tvos => math.maxInt(i32),
else => math.maxInt(isize),
};
const adjusted_len = math.min(max_count, buf.len);
@@ -693,6 +695,7 @@ pub const WriteError = error{
/// Linux has a limit on how many bytes may be transferred in one `write` call, which is `0x7ffff000`
/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page.
+/// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL.
/// The corresponding POSIX limit is `math.maxInt(isize)`.
pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
if (builtin.os.tag == .windows) {
@@ -726,6 +729,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
const max_count = switch (std.Target.current.os.tag) {
.linux => 0x7ffff000,
+ .macosx, .ios, .watchos, .tvos => math.maxInt(i32),
else => math.maxInt(isize),
};
const adjusted_len = math.min(max_count, bytes.len);
@@ -851,6 +855,7 @@ pub const PWriteError = WriteError || error{Unseekable};
/// Linux has a limit on how many bytes may be transferred in one `pwrite` call, which is `0x7ffff000`
/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page.
+/// The limit on Darwin is `0x7fffffff`, trying to write more than that returns EINVAL.
/// The corresponding POSIX limit is `math.maxInt(isize)`.
pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
if (std.Target.current.os.tag == .windows) {
@@ -888,6 +893,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
// Prevent EINVAL.
const max_count = switch (std.Target.current.os.tag) {
.linux => 0x7ffff000,
+ .macosx, .ios, .watchos, .tvos => math.maxInt(i32),
else => math.maxInt(isize),
};
const adjusted_len = math.min(max_count, bytes.len);
@@ -1884,7 +1890,7 @@ pub fn unlinkatW(dirfd: fd_t, sub_path_w: []const u16, flags: u32) UnlinkatError
return windows.DeleteFile(sub_path_w, .{ .dir = dirfd, .remove_dir = remove_dir });
}
-const RenameError = error{
+pub const RenameError = error{
/// In WASI, this error may occur when the file descriptor does
/// not hold the required rights to rename a resource by path relative to it.
AccessDenied,
@@ -2101,6 +2107,7 @@ pub fn renameatW(
.ACCESS_DENIED => return error.AccessDenied,
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
+ .NOT_SAME_DEVICE => return error.RenameAcrossMountPoints,
else => return windows.unexpectedStatus(rc),
}
}
@@ -2515,9 +2522,9 @@ pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) Read
pub const SetEidError = error{
InvalidUserId,
PermissionDenied,
-};
+} || UnexpectedError;
-pub const SetIdError = error{ResourceLimitReached} || SetEidError || UnexpectedError;
+pub const SetIdError = error{ResourceLimitReached} || SetEidError;
pub fn setuid(uid: uid_t) SetIdError!void {
switch (errno(system.setuid(uid))) {
@@ -3084,7 +3091,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con
.WSAECONNREFUSED => return error.ConnectionRefused,
.WSAETIMEDOUT => return error.ConnectionTimedOut,
.WSAEHOSTUNREACH // TODO: should we return NetworkUnreachable in this case as well?
- , .WSAENETUNREACH => return error.NetworkUnreachable,
+ , .WSAENETUNREACH => return error.NetworkUnreachable,
.WSAEFAULT => unreachable,
.WSAEINVAL => unreachable,
.WSAEISCONN => unreachable,
@@ -4711,6 +4718,7 @@ fn count_iovec_bytes(iovs: []const iovec_const) usize {
/// Linux has a limit on how many bytes may be transferred in one `sendfile` call, which is `0x7ffff000`
/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as
/// well as stuffing the errno codes into the last `4096` values. This is cited on the `sendfile` man page.
+/// The limit on Darwin is `0x7fffffff`, trying to write more than that returns EINVAL.
/// The corresponding POSIX limit on this is `math.maxInt(isize)`.
pub fn sendfile(
out_fd: fd_t,
@@ -4733,6 +4741,7 @@ pub fn sendfile(
});
const max_count = switch (std.Target.current.os.tag) {
.linux => 0x7ffff000,
+ .macosx, .ios, .watchos, .tvos => math.maxInt(i32),
else => math.maxInt(size_t),
};
@@ -5418,3 +5427,42 @@ pub fn fdatasync(fd: fd_t) SyncError!void {
else => |err| return std.os.unexpectedErrno(err),
}
}
+
+pub const PrctlError = error{
+ /// Can only occur with PR_SET_SECCOMP/SECCOMP_MODE_FILTER or
+ /// PR_SET_MM/PR_SET_MM_EXE_FILE
+ AccessDenied,
+ /// Can only occur with PR_SET_MM/PR_SET_MM_EXE_FILE
+ InvalidFileDescriptor,
+ InvalidAddress,
+ /// Can only occur with PR_SET_SPECULATION_CTRL, PR_MPX_ENABLE_MANAGEMENT,
+ /// or PR_MPX_DISABLE_MANAGEMENT
+ UnsupportedFeature,
+ /// Can only occur wih PR_SET_FP_MODE
+ OperationNotSupported,
+ PermissionDenied,
+} || UnexpectedError;
+
+pub fn prctl(option: i32, args: anytype) PrctlError!u31 {
+ if (@typeInfo(@TypeOf(args)) != .Struct)
+ @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
+ if (args.len > 4)
+ @compileError("prctl takes a maximum of 4 optional arguments");
+
+ var buf: [4]usize = undefined;
+ inline for (args) |arg, i| buf[i] = arg;
+
+ const rc = system.prctl(option, buf[0], buf[1], buf[2], buf[3]);
+ switch (errno(rc)) {
+ 0 => return @intCast(u31, rc),
+ EACCES => return error.AccessDenied,
+ EBADF => return error.InvalidFileDescriptor,
+ EFAULT => return error.InvalidAddress,
+ EINVAL => unreachable,
+ ENODEV, ENXIO => return error.UnsupportedFeature,
+ EOPNOTSUPP => return error.OperationNotSupported,
+ EPERM, EBUSY => return error.PermissionDenied,
+ ERANGE => unreachable,
+ else => |err| return std.os.unexpectedErrno(err),
+ }
+}