aboutsummaryrefslogtreecommitdiff
path: root/lib/std/os.zig
diff options
context:
space:
mode:
authorBas <BarabasGitHub@users.noreply.github.com>2020-09-08 11:56:59 +0200
committerGitHub <noreply@github.com>2020-09-08 11:56:59 +0200
commit4a6ca735d9b3d466aba37c4488c1235b06a0bc84 (patch)
tree10ef029ccaefe15c5152c1512a952ca6fdb01358 /lib/std/os.zig
parent0a40a61548ad9f666ed5300a8910f9040cc1390b (diff)
parent389c26025283edef2206d19d9ad1ddc41e98f007 (diff)
downloadzig-4a6ca735d9b3d466aba37c4488c1235b06a0bc84.tar.gz
zig-4a6ca735d9b3d466aba37c4488c1235b06a0bc84.zip
Merge branch 'master' into improve-windows-networking
Diffstat (limited to 'lib/std/os.zig')
-rw-r--r--lib/std/os.zig136
1 files changed, 113 insertions, 23 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig
index abf72529ad..08021cdefe 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -2512,13 +2512,14 @@ pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) Read
}
}
-pub const SetIdError = error{
- ResourceLimitReached,
+pub const SetEidError = error{
InvalidUserId,
PermissionDenied,
-} || UnexpectedError;
+};
+
+pub const SetIdError = error{ResourceLimitReached} || SetEidError || UnexpectedError;
-pub fn setuid(uid: u32) SetIdError!void {
+pub fn setuid(uid: uid_t) SetIdError!void {
switch (errno(system.setuid(uid))) {
0 => return,
EAGAIN => return error.ResourceLimitReached,
@@ -2528,7 +2529,16 @@ pub fn setuid(uid: u32) SetIdError!void {
}
}
-pub fn setreuid(ruid: u32, euid: u32) SetIdError!void {
+pub fn seteuid(uid: uid_t) SetEidError!void {
+ switch (errno(system.seteuid(uid))) {
+ 0 => return,
+ EINVAL => return error.InvalidUserId,
+ EPERM => return error.PermissionDenied,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
+pub fn setreuid(ruid: uid_t, euid: uid_t) SetIdError!void {
switch (errno(system.setreuid(ruid, euid))) {
0 => return,
EAGAIN => return error.ResourceLimitReached,
@@ -2538,7 +2548,7 @@ pub fn setreuid(ruid: u32, euid: u32) SetIdError!void {
}
}
-pub fn setgid(gid: u32) SetIdError!void {
+pub fn setgid(gid: gid_t) SetIdError!void {
switch (errno(system.setgid(gid))) {
0 => return,
EAGAIN => return error.ResourceLimitReached,
@@ -2548,7 +2558,16 @@ pub fn setgid(gid: u32) SetIdError!void {
}
}
-pub fn setregid(rgid: u32, egid: u32) SetIdError!void {
+pub fn setegid(uid: uid_t) SetEidError!void {
+ switch (errno(system.setegid(uid))) {
+ 0 => return,
+ EINVAL => return error.InvalidUserId,
+ EPERM => return error.PermissionDenied,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
+pub fn setregid(rgid: gid_t, egid: gid_t) SetIdError!void {
switch (errno(system.setregid(rgid, egid))) {
0 => return,
EAGAIN => return error.ResourceLimitReached,
@@ -2815,6 +2834,9 @@ pub const AcceptError = error{
/// by the socket buffer limits, not by the system memory.
SystemResources,
+ /// Socket is not listening for new connections.
+ SocketNotListening,
+
ProtocolFailure,
/// Firewall rules forbid connection.
@@ -2884,21 +2906,21 @@ pub fn accept(
loop.waitUntilFdReadable(sock);
continue;
} else {
- return error.WouldBlock;
- },
- EBADF => unreachable, // always a race condition
- ECONNABORTED => return error.ConnectionAborted,
- EFAULT => unreachable,
- EINVAL => unreachable,
- ENOTSOCK => unreachable,
- EMFILE => return error.ProcessFdQuotaExceeded,
- ENFILE => return error.SystemFdQuotaExceeded,
- ENOBUFS => return error.SystemResources,
- ENOMEM => return error.SystemResources,
- EOPNOTSUPP => unreachable,
- EPROTO => return error.ProtocolFailure,
- EPERM => return error.BlockedByFirewall,
- else => |err| return unexpectedErrno(err),
+ return error.WouldBlock;
+ },
+ EBADF => unreachable, // always a race condition
+ ECONNABORTED => return error.ConnectionAborted,
+ EFAULT => unreachable,
+ EINVAL => return error.SocketNotListening,
+ ENOTSOCK => unreachable,
+ EMFILE => return error.ProcessFdQuotaExceeded,
+ ENFILE => return error.SystemFdQuotaExceeded,
+ ENOBUFS => return error.SystemResources,
+ ENOMEM => return error.SystemResources,
+ EOPNOTSUPP => unreachable,
+ EPROTO => return error.ProtocolFailure,
+ EPERM => return error.BlockedByFirewall,
+ else => |err| return unexpectedErrno(err),
}
}
} else unreachable;
@@ -4554,7 +4576,7 @@ pub fn res_mkquery(
// Make a reasonably unpredictable id
var ts: timespec = undefined;
clock_gettime(CLOCK_REALTIME, &ts) catch {};
- const UInt = std.meta.Int(false, @TypeOf(ts.tv_nsec).bit_count);
+ const UInt = std.meta.Int(false, std.meta.bitCount(@TypeOf(ts.tv_nsec)));
const unsec = @bitCast(UInt, ts.tv_nsec);
const id = @truncate(u32, unsec + unsec / 65536);
q[0] = @truncate(u8, id / 256);
@@ -5404,3 +5426,71 @@ pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t {
else => |err| return std.os.unexpectedErrno(err),
}
}
+
+pub const SyncError = error{
+ InputOutput,
+ NoSpaceLeft,
+ DiskQuota,
+ AccessDenied,
+} || UnexpectedError;
+
+/// Write all pending file contents and metadata modifications to all filesystems.
+pub fn sync() void {
+ system.sync();
+}
+
+/// Write all pending file contents and metadata modifications to the filesystem which contains the specified file.
+pub fn syncfs(fd: fd_t) SyncError!void {
+ const rc = system.syncfs(fd);
+ switch (errno(rc)) {
+ 0 => return,
+ EBADF, EINVAL, EROFS => unreachable,
+ EIO => return error.InputOutput,
+ ENOSPC => return error.NoSpaceLeft,
+ EDQUOT => return error.DiskQuota,
+ else => |err| return std.os.unexpectedErrno(err),
+ }
+}
+
+/// Write all pending file contents and metadata modifications for the specified file descriptor to the underlying filesystem.
+pub fn fsync(fd: fd_t) SyncError!void {
+ if (std.Target.current.os.tag == .windows) {
+ if (windows.kernel32.FlushFileBuffers(fd) != 0)
+ return;
+ switch (windows.kernel32.GetLastError()) {
+ .SUCCESS => return,
+ .INVALID_HANDLE => unreachable,
+ .ACCESS_DENIED => return error.AccessDenied, // a sync was performed but the system couldn't update the access time
+ .UNEXP_NET_ERR => return error.InputOutput,
+ else => return error.InputOutput,
+ }
+ }
+ const rc = system.fsync(fd);
+ switch (errno(rc)) {
+ 0 => return,
+ EBADF, EINVAL, EROFS => unreachable,
+ EIO => return error.InputOutput,
+ ENOSPC => return error.NoSpaceLeft,
+ EDQUOT => return error.DiskQuota,
+ else => |err| return std.os.unexpectedErrno(err),
+ }
+}
+
+/// Write all pending file contents for the specified file descriptor to the underlying filesystem, but not necessarily the metadata.
+pub fn fdatasync(fd: fd_t) SyncError!void {
+ if (std.Target.current.os.tag == .windows) {
+ return fsync(fd) catch |err| switch (err) {
+ SyncError.AccessDenied => return, // fdatasync doesn't promise that the access time was synced
+ else => return err,
+ };
+ }
+ const rc = system.fdatasync(fd);
+ switch (errno(rc)) {
+ 0 => return,
+ EBADF, EINVAL, EROFS => unreachable,
+ EIO => return error.InputOutput,
+ ENOSPC => return error.NoSpaceLeft,
+ EDQUOT => return error.DiskQuota,
+ else => |err| return std.os.unexpectedErrno(err),
+ }
+}