aboutsummaryrefslogtreecommitdiff
path: root/std/os.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-05-24 22:52:07 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-05-26 18:32:44 -0400
commitca6debcaf4a4f85b7aff94c7b5fe821530b0f195 (patch)
treea05bdab98809538db5bd3106b42ce60a8e868d6b /std/os.zig
parent3d61e4228298dcb973c13d8d6eba0bff36acf1ca (diff)
downloadzig-ca6debcaf4a4f85b7aff94c7b5fe821530b0f195.tar.gz
zig-ca6debcaf4a4f85b7aff94c7b5fe821530b0f195.zip
starting to fix the regressions
Diffstat (limited to 'std/os.zig')
-rw-r--r--std/os.zig110
1 files changed, 97 insertions, 13 deletions
diff --git a/std/os.zig b/std/os.zig
index 5f6716e017..4cd847cf8f 100644
--- a/std/os.zig
+++ b/std/os.zig
@@ -16,6 +16,7 @@
const std = @import("std.zig");
const builtin = @import("builtin");
+const math = std.math;
const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
comptime {
@@ -114,7 +115,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
defer close(fd);
- const stream = &os.File.openHandle(fd).inStream().stream;
+ const stream = &std.fs.File.openHandle(fd).inStream().stream;
stream.readNoEof(buf) catch return error.Unexpected;
}
@@ -177,6 +178,21 @@ pub fn raise(sig: u8) RaiseError!void {
}
}
+pub const KillError = error{
+ PermissionDenied,
+ Unexpected,
+};
+
+pub fn kill(pid: pid_t, sig: u8) KillError!void {
+ switch (errno(system.kill(pid, sig))) {
+ 0 => return,
+ EINVAL => unreachable, // invalid signal
+ EPERM => return error.PermissionDenied,
+ ESRCH => unreachable, // always a race condition
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
/// Exits the program cleanly with the specified status code.
pub fn exit(status: u8) noreturn {
if (builtin.link_libc) {
@@ -885,8 +901,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
if (windows.is_the_target and !builtin.link_libc) {
const old_path_w = try windows.sliceToPrefixedFileW(old_path);
const new_path_w = try windows.sliceToPrefixedFileW(new_path);
- const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
- return windows.MoveFileExW(&old_path_w, &new_path_w, flags);
+ return renameW(&old_path_w, &new_path_w);
} else {
const old_path_c = try toPosixPath(old_path);
const new_path_c = try toPosixPath(new_path);
@@ -899,8 +914,7 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
if (windows.is_the_target and !builtin.link_libc) {
const old_path_w = try windows.cStrToPrefixedFileW(old_path);
const new_path_w = try windows.cStrToPrefixedFileW(new_path);
- const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
- return windows.MoveFileExW(&old_path_w, &new_path_w, flags);
+ return renameW(&old_path_w, &new_path_w);
}
switch (errno(system.rename(old_path, new_path))) {
0 => return,
@@ -926,6 +940,13 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
}
}
+/// Same as `rename` except the parameters are null-terminated UTF16LE encoded byte arrays.
+/// Assumes target is Windows.
+pub fn renameW(old_path: [*]const u16, new_path: [*]const u16) RenameError!void {
+ const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
+ return windows.MoveFileExW(old_path_w, new_path_w, flags);
+}
+
pub const MakeDirError = error{
AccessDenied,
DiskQuota,
@@ -1684,10 +1705,10 @@ pub fn getsockoptError(sockfd: i32) ConnectError!void {
}
}
-pub fn waitpid(pid: i32) i32 {
+pub fn waitpid(pid: i32, flags: u32) i32 {
var status: i32 = undefined;
while (true) {
- switch (errno(system.waitpid(pid, &status, 0))) {
+ switch (errno(system.waitpid(pid, &status, flags))) {
0 => return status,
EINTR => continue,
ECHILD => unreachable, // The process specified does not exist. It would be a race condition to handle this error.
@@ -1988,9 +2009,10 @@ pub const PipeError = error{
};
/// Creates a unidirectional data channel that can be used for interprocess communication.
-pub fn pipe(fds: *[2]fd_t) PipeError!void {
- switch (errno(system.pipe(fds))) {
- 0 => return,
+pub fn pipe() PipeError![2]fd_t {
+ var fds: [2]i32 = undefined;
+ switch (errno(system.pipe(&fds))) {
+ 0 => return fds,
EINVAL => unreachable, // Invalid parameters to pipe()
EFAULT => unreachable, // Invalid fds pointer
ENFILE => return error.SystemFdQuotaExceeded,
@@ -1999,9 +2021,10 @@ pub fn pipe(fds: *[2]fd_t) PipeError!void {
}
}
-pub fn pipe2(fds: *[2]fd_t, flags: u32) PipeError!void {
- switch (errno(system.pipe2(fds, flags))) {
- 0 => return,
+pub fn pipe2(flags: u32) PipeError![2]fd_t {
+ var fds: [2]i32 = undefined;
+ switch (errno(system.pipe2(&fds, flags))) {
+ 0 => return fds,
EINVAL => unreachable, // Invalid flags
EFAULT => unreachable, // Invalid fds pointer
ENFILE => return error.SystemFdQuotaExceeded,
@@ -2281,6 +2304,67 @@ pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPa
return out_buffer[0..end_index];
}
+/// Spurious wakeups are possible and no precision of timing is guaranteed.
+pub fn nanosleep(seconds: u64, nanoseconds: u64) void {
+ if (windows.is_the_target and !builtin.link_libc) {
+ // TODO https://github.com/ziglang/zig/issues/1284
+ const small_s = math.cast(windows.DWORD, seconds) catch math.maxInt(windows.DWORD);
+ const ms_from_s = math.mul(small_s, std.time.ms_per_s) catch math.maxInt(windows.DWORD);
+
+ const ns_per_ms = std.time.ns_per_s / std.time.ms_per_s;
+ const big_ms_from_ns = nanoseconds / ns_per_ms;
+ const ms_from_ns = math.cast(windows.DWORD, big_ms_from_ns) catch math.maxInt(windows.DWORD);
+
+ const ms = math.add(ms_from_s, ms_from_ns) catch math.maxInt(windows.DWORD);
+ windows.kernel32.Sleep(ms);
+ return;
+ }
+ var req = timespec{
+ .tv_sec = math.cast(isize, seconds) catch math.maxInt(isize),
+ .tv_nsec = math.cast(isize, nanoseconds) catch math.maxInt(isize),
+ };
+ var rem: timespec = undefined;
+ while (true) {
+ switch (errno(system.nanosleep(&req, &rem))) {
+ EFAULT => unreachable,
+ EINVAL => {
+ // Sometimes Darwin returns EINVAL for no reason.
+ // We treat it as a spurious wakeup.
+ return;
+ },
+ EINTR => {
+ req = rem;
+ continue;
+ },
+ // This prong handles success as well as unexpected errors.
+ else => return,
+ }
+ }
+}
+
+pub const ClockGetTimeError = error{
+ UnsupportedClock,
+ Unexpected,
+};
+
+pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
+ switch (errno(system.clock_gettime(clk_id, tp))) {
+ 0 => return,
+ EFAULT => unreachable,
+ EINVAL => return error.UnsupportedClock,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
+pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
+ switch (errno(system.clock_getres(clk_id, tp))) {
+ 0 => return,
+ EFAULT => unreachable,
+ EINVAL => return error.UnsupportedClock,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
/// Used to convert a slice to a null terminated slice on the stack.
/// TODO https://github.com/ziglang/zig/issues/287
pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {