diff options
| author | Bas <BarabasGitHub@users.noreply.github.com> | 2020-09-08 11:56:59 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-08 11:56:59 +0200 |
| commit | 4a6ca735d9b3d466aba37c4488c1235b06a0bc84 (patch) | |
| tree | 10ef029ccaefe15c5152c1512a952ca6fdb01358 /lib/std/os.zig | |
| parent | 0a40a61548ad9f666ed5300a8910f9040cc1390b (diff) | |
| parent | 389c26025283edef2206d19d9ad1ddc41e98f007 (diff) | |
| download | zig-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.zig | 136 |
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), + } +} |
