Commit ca6debcaf4
Changed files (27)
std
crypto
os
special
zig
std/atomic/queue.zig
@@ -220,7 +220,7 @@ fn startPuts(ctx: *Context) u8 {
var put_count: usize = puts_per_thread;
var r = std.rand.DefaultPrng.init(0xdeadbeef);
while (put_count != 0) : (put_count -= 1) {
- std.os.time.sleep(1); // let the os scheduler be our fuzz
+ std.time.sleep(1); // let the os scheduler be our fuzz
const x = @bitCast(i32, r.random.scalar(u32));
const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;
node.* = Queue(i32).Node{
@@ -239,7 +239,7 @@ fn startGets(ctx: *Context) u8 {
const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
while (ctx.queue.get()) |node| {
- std.os.time.sleep(1); // let the os scheduler be our fuzz
+ std.time.sleep(1); // let the os scheduler be our fuzz
_ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
_ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
}
std/atomic/stack.zig
@@ -154,7 +154,7 @@ fn startPuts(ctx: *Context) u8 {
var put_count: usize = puts_per_thread;
var r = std.rand.DefaultPrng.init(0xdeadbeef);
while (put_count != 0) : (put_count -= 1) {
- std.os.time.sleep(1); // let the os scheduler be our fuzz
+ std.time.sleep(1); // let the os scheduler be our fuzz
const x = @bitCast(i32, r.random.scalar(u32));
const node = ctx.allocator.create(Stack(i32).Node) catch unreachable;
node.* = Stack(i32).Node{
@@ -172,7 +172,7 @@ fn startGets(ctx: *Context) u8 {
const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
while (ctx.stack.pop()) |node| {
- std.os.time.sleep(1); // let the os scheduler be our fuzz
+ std.time.sleep(1); // let the os scheduler be our fuzz
_ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
_ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
}
std/crypto/throughput_test.zig
@@ -1,6 +1,6 @@
const builtin = @import("builtin");
const std = @import("std");
-const time = std.os.time;
+const time = std.time;
const Timer = time.Timer;
const crypto = @import("../crypto.zig");
std/event/fs.zig
@@ -9,6 +9,7 @@ const posix = os.posix;
const windows = os.windows;
const Loop = event.Loop;
const fd_t = posix.fd_t;
+const File = std.fs.File;
pub const RequestNode = std.atomic.Queue(Request).Node;
@@ -52,20 +53,20 @@ pub const Request = struct {
/// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
path: []const u8,
flags: u32,
- mode: os.File.Mode,
+ mode: File.Mode,
result: Error!fd_t,
- pub const Error = os.File.OpenError;
+ pub const Error = File.OpenError;
};
pub const WriteFile = struct {
/// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
path: []const u8,
contents: []const u8,
- mode: os.File.Mode,
+ mode: File.Mode,
result: Error!void,
- pub const Error = os.File.OpenError || os.File.WriteError;
+ pub const Error = File.OpenError || File.WriteError;
};
pub const Close = struct {
@@ -74,7 +75,7 @@ pub const Request = struct {
};
};
-pub const PWriteVError = error{OutOfMemory} || os.File.WriteError;
+pub const PWriteVError = error{OutOfMemory} || File.WriteError;
/// data - just the inner references - must live until pwritev promise completes.
pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: usize) PWriteVError!void {
@@ -209,7 +210,7 @@ pub async fn pwritevPosix(
return req_node.data.msg.PWriteV.result;
}
-pub const PReadVError = error{OutOfMemory} || os.File.ReadError;
+pub const PReadVError = error{OutOfMemory} || File.ReadError;
/// data - just the inner references - must live until preadv promise completes.
pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PReadVError!usize {
@@ -361,8 +362,8 @@ pub async fn openPosix(
loop: *Loop,
path: []const u8,
flags: u32,
- mode: os.File.Mode,
-) os.File.OpenError!fd_t {
+ mode: File.Mode,
+) File.OpenError!fd_t {
// workaround for https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
@@ -401,11 +402,11 @@ pub async fn openPosix(
return req_node.data.msg.Open.result;
}
-pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
+pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t {
switch (builtin.os) {
builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
- return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
+ return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
},
builtin.Os.windows => return os.windowsOpen(
@@ -422,12 +423,12 @@ pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
/// Creates if does not exist. Truncates the file if it exists.
/// Uses the default mode.
-pub async fn openWrite(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
- return await (async openWriteMode(loop, path, os.File.default_mode) catch unreachable);
+pub async fn openWrite(loop: *Loop, path: []const u8) File.OpenError!fd_t {
+ return await (async openWriteMode(loop, path, File.default_mode) catch unreachable);
}
/// Creates if does not exist. Truncates the file if it exists.
-pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os.File.OpenError!fd_t {
+pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File.OpenError!fd_t {
switch (builtin.os) {
builtin.Os.macosx,
builtin.Os.linux,
@@ -435,7 +436,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
builtin.Os.netbsd,
=> {
const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
- return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
+ return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
},
builtin.Os.windows => return os.windowsOpen(
path,
@@ -452,8 +453,8 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
pub async fn openReadWrite(
loop: *Loop,
path: []const u8,
- mode: os.File.Mode,
-) os.File.OpenError!fd_t {
+ mode: File.Mode,
+) File.OpenError!fd_t {
switch (builtin.os) {
builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
@@ -605,11 +606,11 @@ pub const CloseOperation = struct {
/// contents must remain alive until writeFile completes.
/// TODO make this atomic or provide writeFileAtomic and rename this one to writeFileTruncate
pub async fn writeFile(loop: *Loop, path: []const u8, contents: []const u8) !void {
- return await (async writeFileMode(loop, path, contents, os.File.default_mode) catch unreachable);
+ return await (async writeFileMode(loop, path, contents, File.default_mode) catch unreachable);
}
/// contents must remain alive until writeFile completes.
-pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, mode: os.File.Mode) !void {
+pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, mode: File.Mode) !void {
switch (builtin.os) {
builtin.Os.linux,
builtin.Os.macosx,
@@ -634,7 +635,7 @@ async fn writeFileWindows(loop: *Loop, path: []const u8, contents: []const u8) !
try await (async pwriteWindows(loop, handle, contents, 0) catch unreachable);
}
-async fn writeFileModeThread(loop: *Loop, path: []const u8, contents: []const u8, mode: os.File.Mode) !void {
+async fn writeFileModeThread(loop: *Loop, path: []const u8, contents: []const u8, mode: File.Mode) !void {
// workaround for https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
@@ -1363,7 +1364,7 @@ async fn testFsWatch(loop: *Loop) !void {
defer if (!ev_consumed) cancel ev;
// overwrite line 2
- const fd = try await try async openReadWrite(loop, file_path, os.File.default_mode);
+ const fd = try await try async openReadWrite(loop, file_path, File.default_mode);
{
defer os.close(fd);
@@ -1390,7 +1391,7 @@ pub const OutStream = struct {
loop: *Loop,
offset: usize,
- pub const Error = os.File.WriteError;
+ pub const Error = File.WriteError;
pub const Stream = event.io.OutStream(Error);
pub fn init(loop: *Loop, fd: fd_t, offset: usize) OutStream {
std/event/group.zig
@@ -155,7 +155,7 @@ async fn testGroup(loop: *Loop) void {
}
async fn sleepALittle(count: *usize) void {
- std.os.time.sleep(1 * std.os.time.millisecond);
+ std.time.sleep(1 * std.time.millisecond);
_ = @atomicRmw(usize, count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
}
std/event/loop.zig
@@ -789,13 +789,13 @@ pub const Loop = struct {
msg.result = os.posix_preadv(msg.fd, msg.iov.ptr, msg.iov.len, msg.offset);
},
@TagType(fs.Request.Msg).Open => |*msg| {
- msg.result = os.posixOpenC(msg.path.ptr, msg.flags, msg.mode);
+ msg.result = os.openC(msg.path.ptr, msg.flags, msg.mode);
},
@TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd),
@TagType(fs.Request.Msg).WriteFile => |*msg| blk: {
const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT |
posix.O_CLOEXEC | posix.O_TRUNC;
- const fd = os.posixOpenC(msg.path.ptr, flags, msg.mode) catch |err| {
+ const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| {
msg.result = err;
break :blk;
};
std/event/net.zig
@@ -6,11 +6,12 @@ const mem = std.mem;
const os = std.os;
const posix = os.posix;
const Loop = std.event.Loop;
+const File = std.fs.File;
const fd_t = posix.fd_t;
pub const Server = struct {
- handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, os.File) void,
+ handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,
loop: *Loop,
sockfd: ?i32,
@@ -42,7 +43,7 @@ pub const Server = struct {
pub fn listen(
self: *Server,
address: *const std.net.Address,
- handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, os.File) void,
+ handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,
) !void {
self.handleRequestFn = handleRequestFn;
@@ -83,7 +84,7 @@ pub const Server = struct {
suspend; // we will get resumed by epoll_wait in the event loop
continue;
}
- var socket = os.File.openHandle(accepted_fd);
+ var socket = File.openHandle(accepted_fd);
_ = async<self.loop.allocator> self.handleRequestFn(self, &accepted_addr, socket) catch |err| switch (err) {
error.OutOfMemory => {
socket.close();
@@ -250,7 +251,7 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
return await (async readvPosix(loop, fd, iovecs.ptr, data.len) catch unreachable);
}
-pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
+pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {
var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592
const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
@@ -260,7 +261,7 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
try os.posixGetSockOptConnectError(sockfd);
- return os.File.openHandle(sockfd);
+ return File.openHandle(sockfd);
}
test "listen on a port, send bytes, receive bytes" {
@@ -276,7 +277,7 @@ test "listen on a port, send bytes, receive bytes" {
tcp_server: Server,
const Self = @This();
- async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: os.File) void {
+ async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: File) void {
const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
defer socket.close();
@@ -289,7 +290,7 @@ test "listen on a port, send bytes, receive bytes" {
cancel @handle();
}
}
- async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: os.File) !void {
+ async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: File) !void {
const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/1592
var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
std/event/rwlock.zig
@@ -271,7 +271,7 @@ async fn writeRunner(lock: *RwLock) void {
var i: usize = 0;
while (i < shared_test_data.len) : (i += 1) {
- std.os.time.sleep(100 * std.os.time.microsecond);
+ std.time.sleep(100 * std.time.microsecond);
const lock_promise = async lock.acquireWrite() catch @panic("out of memory");
const handle = await lock_promise;
defer handle.release();
@@ -286,7 +286,7 @@ async fn writeRunner(lock: *RwLock) void {
async fn readRunner(lock: *RwLock) void {
suspend; // resumed by onNextTick
- std.os.time.sleep(1);
+ std.time.sleep(1);
var i: usize = 0;
while (i < shared_test_data.len) : (i += 1) {
std/io/c_out_stream.zig
@@ -1,13 +1,13 @@
const std = @import("../std.zig");
+const os = std.os;
const OutStream = std.io.OutStream;
const builtin = @import("builtin");
-const posix = std.os.posix;
-/// TODO make std.os.FILE use *FILE when linking libc and this just becomes
-/// std.io.FileOutStream because std.os.File.write would do this when linking
+/// TODO make a proposal to make `std.fs.File` use *FILE when linking libc and this just becomes
+/// std.io.FileOutStream because std.fs.File.write would do this when linking
/// libc.
pub const COutStream = struct {
- pub const Error = std.os.File.WriteError;
+ pub const Error = std.fs.File.WriteError;
pub const Stream = OutStream(Error);
stream: Stream,
@@ -24,25 +24,20 @@ pub const COutStream = struct {
const self = @fieldParentPtr(COutStream, "stream", out_stream);
const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);
if (amt_written == bytes.len) return;
- // TODO errno on windows. should we have a posix layer for windows?
- if (builtin.os == .windows) {
- return error.InputOutput;
- }
- const errno = std.c._errno().*;
- switch (errno) {
+ switch (std.c._errno().*) {
0 => unreachable,
- posix.EINVAL => unreachable,
- posix.EFAULT => unreachable,
- posix.EAGAIN => unreachable, // this is a blocking API
- posix.EBADF => unreachable, // always a race condition
- posix.EDESTADDRREQ => unreachable, // connect was never called
- posix.EDQUOT => return error.DiskQuota,
- posix.EFBIG => return error.FileTooBig,
- posix.EIO => return error.InputOutput,
- posix.ENOSPC => return error.NoSpaceLeft,
- posix.EPERM => return error.AccessDenied,
- posix.EPIPE => return error.BrokenPipe,
- else => return std.os.unexpectedErrorPosix(@intCast(usize, errno)),
+ os.EINVAL => unreachable,
+ os.EFAULT => unreachable,
+ os.EAGAIN => unreachable, // this is a blocking API
+ os.EBADF => unreachable, // always a race condition
+ os.EDESTADDRREQ => unreachable, // connect was never called
+ os.EDQUOT => return error.DiskQuota,
+ os.EFBIG => return error.FileTooBig,
+ os.EIO => return error.InputOutput,
+ os.ENOSPC => return error.NoSpaceLeft,
+ os.EPERM => return error.AccessDenied,
+ os.EPIPE => return error.BrokenPipe,
+ else => return os.unexpectedErrno(@intCast(usize, errno)),
}
}
};
std/io/test.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
const std = @import("../std.zig");
const io = std.io;
const meta = std.meta;
@@ -7,7 +8,7 @@ const expect = std.testing.expect;
const expectError = std.testing.expectError;
const mem = std.mem;
const os = std.os;
-const builtin = @import("builtin");
+const File = std.fs.File;
test "write a file, read it, then delete it" {
var raw_bytes: [200 * 1024]u8 = undefined;
@@ -18,11 +19,11 @@ test "write a file, read it, then delete it" {
prng.random.bytes(data[0..]);
const tmp_file_name = "temp_test_file.txt";
{
- var file = try os.File.openWrite(tmp_file_name);
+ var file = try File.openWrite(tmp_file_name);
defer file.close();
var file_out_stream = file.outStream();
- var buf_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
+ var buf_stream = io.BufferedOutStream(File.WriteError).init(&file_out_stream.stream);
const st = &buf_stream.stream;
try st.print("begin");
try st.write(data[0..]);
@@ -32,15 +33,15 @@ test "write a file, read it, then delete it" {
{
// make sure openWriteNoClobber doesn't harm the file
- if (os.File.openWriteNoClobber(tmp_file_name, os.File.default_mode)) |file| {
+ if (File.openWriteNoClobber(tmp_file_name, File.default_mode)) |file| {
unreachable;
} else |err| {
- std.debug.assert(err == os.File.OpenError.PathAlreadyExists);
+ std.debug.assert(err == File.OpenError.PathAlreadyExists);
}
}
{
- var file = try os.File.openRead(tmp_file_name);
+ var file = try File.openRead(tmp_file_name);
defer file.close();
const file_size = try file.getEndPos();
@@ -48,7 +49,7 @@ test "write a file, read it, then delete it" {
expect(file_size == expected_file_size);
var file_in_stream = file.inStream();
- var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
+ var buf_stream = io.BufferedInStream(File.ReadError).init(&file_in_stream.stream);
const st = &buf_stream.stream;
const contents = try st.readAllAlloc(allocator, 2 * 1024);
defer allocator.free(contents);
@@ -273,12 +274,12 @@ test "BitOutStream" {
test "BitStreams with File Stream" {
const tmp_file_name = "temp_test_file.txt";
{
- var file = try os.File.openWrite(tmp_file_name);
+ var file = try File.openWrite(tmp_file_name);
defer file.close();
var file_out = file.outStream();
var file_out_stream = &file_out.stream;
- const OutError = os.File.WriteError;
+ const OutError = File.WriteError;
var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
try bit_stream.writeBits(u2(1), 1);
@@ -290,12 +291,12 @@ test "BitStreams with File Stream" {
try bit_stream.flushBits();
}
{
- var file = try os.File.openRead(tmp_file_name);
+ var file = try File.openRead(tmp_file_name);
defer file.close();
var file_in = file.inStream();
var file_in_stream = &file_in.stream;
- const InError = os.File.ReadError;
+ const InError = File.ReadError;
var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
var out_bits: usize = undefined;
std/os/bits/linux.zig
@@ -1,4 +1,4 @@
-pub use @import("errno.zig");
+pub use @import("linux/errno.zig");
pub use switch (builtin.arch) {
.x86_64 => @import("linux/x86_64.zig"),
.aarch64 => @import("linux/arm64.zig"),
@@ -744,16 +744,6 @@ pub const sockaddr_un = extern struct {
path: [108]u8,
};
-pub const iovec = extern struct {
- iov_base: [*]u8,
- iov_len: usize,
-};
-
-pub const iovec_const = extern struct {
- iov_base: [*]const u8,
- iov_len: usize,
-};
-
pub const mmsghdr = extern struct {
msg_hdr: msghdr,
msg_len: u32,
std/os/test.zig
@@ -4,6 +4,7 @@ const testing = std.testing;
const expect = std.testing.expect;
const io = std.io;
const mem = std.mem;
+const File = std.fs.File;
const a = std.debug.global_allocator;
@@ -25,14 +26,14 @@ test "makePath, put some files in it, deleteTree" {
test "access file" {
try os.makePath(a, "os_test_tmp");
- if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {
+ if (File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {
@panic("expected error");
} else |err| {
expect(err == error.FileNotFound);
}
try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", "");
- try os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt");
+ try File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt");
try os.deleteTree(a, "os_test_tmp");
}
@@ -102,7 +103,7 @@ test "AtomicFile" {
\\ this is a test file
;
{
- var af = try os.AtomicFile.init(test_out_file, os.File.default_mode);
+ var af = try os.AtomicFile.init(test_out_file, File.default_mode);
defer af.deinit();
try af.file.write(test_content);
try af.finish();
std/os/windows.zig
@@ -753,6 +753,10 @@ pub fn CloseHandle(hObject: HANDLE) void {
assert(kernel32.CloseHandle(hObject) != 0);
}
+pub fn FindClose(hFindFile: HANDLE) void {
+ assert(kernel32.FindClose(hFindFile) != 0);
+}
+
pub const ReadFileError = error{Unexpected};
pub fn ReadFile(in_hFile: HANDLE, buffer: []u8) ReadFileError!usize {
@@ -1063,6 +1067,28 @@ pub fn GetFileAttributesW(lpFileName: [*]const u16) GetFileAttributesError!DWORD
return rc;
}
+const GetModuleFileNameError = error{Unexpected};
+
+pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) GetModuleFileNameError![]u16 {
+ const rc = kernel32.GetModuleFileNameW(hModule, buf_ptr, buf_len);
+ if (rc == 0) {
+ switch (kernel32.GetLastError()) {
+ else => |err| return unexpectedError(err),
+ }
+ }
+ return buf_ptr[0..rc];
+}
+
+pub const TerminateProcessError = error{Unexpected};
+
+pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void {
+ if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) {
+ switch (kernel32.GetLastError()) {
+ else => |err| return unexpectedError(err),
+ }
+ }
+}
+
pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
}
std/special/build_runner.zig
@@ -8,6 +8,7 @@ const Builder = std.build.Builder;
const mem = std.mem;
const ArrayList = std.ArrayList;
const warn = std.debug.warn;
+const File = std.fs.File;
pub fn main() !void {
var arg_it = os.args();
@@ -48,14 +49,14 @@ pub fn main() !void {
var prefix: ?[]const u8 = null;
var stderr_file = io.getStdErr();
- var stderr_file_stream: os.File.OutStream = undefined;
+ var stderr_file_stream: File.OutStream = undefined;
var stderr_stream = if (stderr_file) |f| x: {
stderr_file_stream = f.outStream();
break :x &stderr_file_stream.stream;
} else |err| err;
var stdout_file = io.getStdOut();
- var stdout_file_stream: os.File.OutStream = undefined;
+ var stdout_file_stream: File.OutStream = undefined;
var stdout_stream = if (stdout_file) |f| x: {
stdout_file_stream = f.outStream();
break :x &stdout_file_stream.stream;
std/zig/bench.zig
@@ -10,7 +10,7 @@ var fixed_buffer_mem: [10 * 1024 * 1024]u8 = undefined;
pub fn main() !void {
var i: usize = 0;
- var timer = try std.os.time.Timer.start();
+ var timer = try std.time.Timer.start();
const start = timer.lap();
const iterations = 100;
var memory_used: usize = 0;
@@ -19,7 +19,7 @@ pub fn main() !void {
}
const end = timer.read();
memory_used /= iterations;
- const elapsed_s = @intToFloat(f64, end - start) / std.os.time.ns_per_s;
+ const elapsed_s = @intToFloat(f64, end - start) / std.time.ns_per_s;
const bytes_per_sec = @intToFloat(f64, source.len * iterations) / elapsed_s;
const mb_per_sec = bytes_per_sec / (1024 * 1024);
std/build.zig
@@ -14,6 +14,7 @@ const Term = os.ChildProcess.Term;
const BufSet = std.BufSet;
const BufMap = std.BufMap;
const fmt_lib = std.fmt;
+const File = std.fs.File;
pub const FmtStep = @import("build/fmt.zig").FmtStep;
@@ -668,10 +669,10 @@ pub const Builder = struct {
}
fn copyFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void {
- return self.copyFileMode(source_path, dest_path, os.File.default_mode);
+ return self.copyFileMode(source_path, dest_path, File.default_mode);
}
- fn copyFileMode(self: *Builder, source_path: []const u8, dest_path: []const u8, mode: os.File.Mode) !void {
+ fn copyFileMode(self: *Builder, source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
if (self.verbose) {
warn("cp {} {}\n", source_path, dest_path);
}
std/c.zig
@@ -75,7 +75,7 @@ pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usi
pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;
pub extern "c" fn socket(domain: c_int, sock_type: c_int, protocol: c_int) c_int;
pub extern "c" fn kill(pid: pid_t, sig: c_int) c_int;
-pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) usize;
+pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) isize;
pub extern "c" fn openat(fd: c_int, path: [*]const u8, flags: c_int) c_int;
pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
pub extern "c" fn setuid(uid: c_uint) c_int;
std/child_process.zig
@@ -3,7 +3,7 @@ const cstr = std.cstr;
const unicode = std.unicode;
const io = std.io;
const os = std.os;
-const posix = os.posix;
+const File = std.fs.File;
const windows = os.windows;
const mem = std.mem;
const debug = std.debug;
@@ -23,9 +23,9 @@ pub const ChildProcess = struct {
pub allocator: *mem.Allocator,
- pub stdin: ?os.File,
- pub stdout: ?os.File,
- pub stderr: ?os.File,
+ pub stdin: ?File,
+ pub stdout: ?File,
+ pub stderr: ?File,
pub term: ?(SpawnError!Term),
@@ -148,12 +148,7 @@ pub const ChildProcess = struct {
return term;
}
- if (!windows.TerminateProcess(self.handle, exit_code)) {
- const err = windows.GetLastError();
- return switch (err) {
- else => os.unexpectedErrorWindows(err),
- };
- }
+ try windows.TerminateProcess(self.handle, exit_code);
try self.waitUnwrappedWindows();
return self.term.?;
}
@@ -163,16 +158,7 @@ pub const ChildProcess = struct {
self.cleanupStreams();
return term;
}
- const ret = posix.kill(self.pid, posix.SIGTERM);
- const err = posix.getErrno(ret);
- if (err > 0) {
- return switch (err) {
- posix.EINVAL => unreachable,
- posix.EPERM => error.PermissionDenied,
- posix.ESRCH => error.ProcessNotFound,
- else => os.unexpectedErrorPosix(err),
- };
- }
+ try os.kill(self.pid, os.SIGTERM);
self.waitUnwrapped();
return self.term.?;
}
@@ -267,19 +253,9 @@ pub const ChildProcess = struct {
}
fn waitUnwrapped(self: *ChildProcess) void {
- var status: i32 = undefined;
- while (true) {
- const err = posix.getErrno(posix.waitpid(self.pid, &status, 0));
- if (err > 0) {
- switch (err) {
- posix.EINTR => continue,
- else => unreachable,
- }
- }
- self.cleanupStreams();
- self.handleWaitResult(status);
- return;
- }
+ const status = os.waitpid(self.pid, 0);
+ self.cleanupStreams();
+ self.handleWaitResult(status);
}
fn handleWaitResult(self: *ChildProcess, status: i32) void {
@@ -324,34 +300,34 @@ pub const ChildProcess = struct {
}
fn statusToTerm(status: i32) Term {
- return if (posix.WIFEXITED(status))
- Term{ .Exited = posix.WEXITSTATUS(status) }
- else if (posix.WIFSIGNALED(status))
- Term{ .Signal = posix.WTERMSIG(status) }
- else if (posix.WIFSTOPPED(status))
- Term{ .Stopped = posix.WSTOPSIG(status) }
+ return if (os.WIFEXITED(status))
+ Term{ .Exited = os.WEXITSTATUS(status) }
+ else if (os.WIFSIGNALED(status))
+ Term{ .Signal = os.WTERMSIG(status) }
+ else if (os.WIFSTOPPED(status))
+ Term{ .Stopped = os.WSTOPSIG(status) }
else
Term{ .Unknown = status };
}
fn spawnPosix(self: *ChildProcess) !void {
- const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined;
+ const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try os.pipe() else undefined;
errdefer if (self.stdin_behavior == StdIo.Pipe) {
destroyPipe(stdin_pipe);
};
- const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined;
+ const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try os.pipe() else undefined;
errdefer if (self.stdout_behavior == StdIo.Pipe) {
destroyPipe(stdout_pipe);
};
- const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined;
+ const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try os.pipe() else undefined;
errdefer if (self.stderr_behavior == StdIo.Pipe) {
destroyPipe(stderr_pipe);
};
const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
- const dev_null_fd = if (any_ignore) try os.posixOpenC(c"/dev/null", posix.O_RDWR, 0) else undefined;
+ const dev_null_fd = if (any_ignore) try os.openC(c"/dev/null", os.O_RDWR, 0) else undefined;
defer {
if (any_ignore) os.close(dev_null_fd);
}
@@ -372,7 +348,7 @@ pub const ChildProcess = struct {
// This pipe is used to communicate errors between the time of fork
// and execve from the child process to the parent process.
- const err_pipe = try makePipe();
+ const err_pipe = try os.pipe();
errdefer destroyPipe(err_pipe);
const pid_result = try posix.fork();
@@ -413,17 +389,17 @@ pub const ChildProcess = struct {
// we are the parent
const pid = @intCast(i32, pid_result);
if (self.stdin_behavior == StdIo.Pipe) {
- self.stdin = os.File.openHandle(stdin_pipe[1]);
+ self.stdin = File.openHandle(stdin_pipe[1]);
} else {
self.stdin = null;
}
if (self.stdout_behavior == StdIo.Pipe) {
- self.stdout = os.File.openHandle(stdout_pipe[0]);
+ self.stdout = File.openHandle(stdout_pipe[0]);
} else {
self.stdout = null;
}
if (self.stderr_behavior == StdIo.Pipe) {
- self.stderr = os.File.openHandle(stderr_pipe[0]);
+ self.stderr = File.openHandle(stderr_pipe[0]);
} else {
self.stderr = null;
}
@@ -608,17 +584,17 @@ pub const ChildProcess = struct {
};
if (g_hChildStd_IN_Wr) |h| {
- self.stdin = os.File.openHandle(h);
+ self.stdin = File.openHandle(h);
} else {
self.stdin = null;
}
if (g_hChildStd_OUT_Rd) |h| {
- self.stdout = os.File.openHandle(h);
+ self.stdout = File.openHandle(h);
} else {
self.stdout = null;
}
if (g_hChildStd_ERR_Rd) |h| {
- self.stderr = os.File.openHandle(h);
+ self.stderr = File.openHandle(h);
} else {
self.stderr = null;
}
@@ -751,18 +727,6 @@ fn windowsMakePipeOut(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const
wr.* = wr_h;
}
-fn makePipe() ![2]i32 {
- var fds: [2]i32 = undefined;
- const err = posix.getErrno(posix.pipe(&fds));
- if (err > 0) {
- return switch (err) {
- posix.EMFILE, posix.ENFILE => error.SystemResources,
- else => os.unexpectedErrorPosix(err),
- };
- }
- return fds;
-}
-
fn destroyPipe(pipe: [2]i32) void {
os.close(pipe[0]);
os.close(pipe[1]);
@@ -778,12 +742,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
fn writeIntFd(fd: i32, value: ErrInt) !void {
- const stream = &os.File.openHandle(fd).outStream().stream;
+ const stream = &File.openHandle(fd).outStream().stream;
stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
}
fn readIntFd(fd: i32) !ErrInt {
- const stream = &os.File.openHandle(fd).inStream().stream;
+ const stream = &File.openHandle(fd).inStream().stream;
return stream.readIntNative(ErrInt) catch return error.SystemResources;
}
std/coff.zig
@@ -3,6 +3,7 @@ const std = @import("std.zig");
const io = std.io;
const mem = std.mem;
const os = std.os;
+const File = std.fs.File;
const ArrayList = std.ArrayList;
@@ -28,7 +29,7 @@ pub const CoffError = error{
};
pub const Coff = struct {
- in_file: os.File,
+ in_file: File,
allocator: *mem.Allocator,
coff_header: CoffHeader,
@@ -77,7 +78,7 @@ pub const Coff = struct {
try self.loadOptionalHeader(&file_stream);
}
- fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
+ fn loadOptionalHeader(self: *Coff, file_stream: *File.InStream) !void {
const in = &file_stream.stream;
self.pe_header.magic = try in.readIntLittle(u16);
// For now we're only interested in finding the reference to the .pdb,
std/debug.zig
@@ -12,6 +12,7 @@ const windows = os.windows;
const ArrayList = std.ArrayList;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
+const File = std.fs.File;
const leb = @import("debug/leb128.zig");
@@ -36,10 +37,10 @@ const Module = struct {
/// Tries to write to stderr, unbuffered, and ignores any error returned.
/// Does not append a newline.
-var stderr_file: os.File = undefined;
-var stderr_file_out_stream: os.File.OutStream = undefined;
+var stderr_file: File = undefined;
+var stderr_file_out_stream: File.OutStream = undefined;
-var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;
+var stderr_stream: ?*io.OutStream(File.WriteError) = null;
var stderr_mutex = std.Mutex.init();
pub fn warn(comptime fmt: []const u8, args: ...) void {
const held = stderr_mutex.acquire();
@@ -48,7 +49,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {
stderr.print(fmt, args) catch return;
}
-pub fn getStderrStream() !*io.OutStream(os.File.WriteError) {
+pub fn getStderrStream() !*io.OutStream(File.WriteError) {
if (stderr_stream) |st| {
return st;
} else {
@@ -1003,7 +1004,7 @@ pub fn openElfDebugInfo(
fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
const S = struct {
- var self_exe_file: os.File = undefined;
+ var self_exe_file: File = undefined;
var self_exe_mmap_seekable: io.SliceSeekableInStream = undefined;
};
@@ -1112,7 +1113,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
}
fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
- var f = try os.File.openRead(line_info.file_name);
+ var f = try File.openRead(line_info.file_name);
defer f.close();
// TODO fstat and make sure that the file has the correct size
std/dynamic_library.zig
@@ -1,5 +1,4 @@
const builtin = @import("builtin");
-const Os = builtin.Os;
const std = @import("std.zig");
const mem = std.mem;
@@ -8,14 +7,13 @@ const os = std.os;
const assert = std.debug.assert;
const testing = std.testing;
const elf = std.elf;
-const linux = os.linux;
const windows = os.windows;
const win_util = @import("os/windows/util.zig");
const maxInt = std.math.maxInt;
pub const DynLib = switch (builtin.os) {
- Os.linux => LinuxDynLib,
- Os.windows => WindowsDynLib,
+ .linux => LinuxDynLib,
+ .windows => WindowsDynLib,
else => void,
};
@@ -110,20 +108,20 @@ pub const LinuxDynLib = struct {
/// Trusts the file
pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
- const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
+ const fd = try os.open(path, 0, os.O_RDONLY | os.O_CLOEXEC);
errdefer std.os.close(fd);
const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
- const addr = linux.mmap(
+ const addr = os.mmap(
null,
size,
- linux.PROT_READ | linux.PROT_EXEC,
- linux.MAP_PRIVATE | linux.MAP_LOCKED,
+ os.PROT_READ | os.PROT_EXEC,
+ os.MAP_PRIVATE | os.MAP_LOCKED,
fd,
0,
);
- errdefer _ = linux.munmap(addr, size);
+ errdefer os.munmap(addr, size);
const bytes = @intToPtr([*]align(mem.page_size) u8, addr)[0..size];
@@ -136,7 +134,7 @@ pub const LinuxDynLib = struct {
}
pub fn close(self: *DynLib) void {
- _ = linux.munmap(self.map_addr, self.map_size);
+ os.munmap(self.map_addr, self.map_size);
std.os.close(self.fd);
self.* = undefined;
}
@@ -149,7 +147,7 @@ pub const LinuxDynLib = struct {
pub const ElfLib = struct {
strings: [*]u8,
syms: [*]elf.Sym,
- hashtab: [*]linux.Elf_Symndx,
+ hashtab: [*]os.Elf_Symndx,
versym: ?[*]u16,
verdef: ?*elf.Verdef,
base: usize,
@@ -184,7 +182,7 @@ pub const ElfLib = struct {
var maybe_strings: ?[*]u8 = null;
var maybe_syms: ?[*]elf.Sym = null;
- var maybe_hashtab: ?[*]linux.Elf_Symndx = null;
+ var maybe_hashtab: ?[*]os.Elf_Symndx = null;
var maybe_versym: ?[*]u16 = null;
var maybe_verdef: ?*elf.Verdef = null;
@@ -195,7 +193,7 @@ pub const ElfLib = struct {
switch (dynv[i]) {
elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
- elf.DT_HASH => maybe_hashtab = @intToPtr([*]linux.Elf_Symndx, p),
+ elf.DT_HASH => maybe_hashtab = @intToPtr([*]os.Elf_Symndx, p),
elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
elf.DT_VERDEF => maybe_verdef = @intToPtr(*elf.Verdef, p),
else => {},
@@ -283,8 +281,8 @@ pub const WindowsDynLib = struct {
test "dynamic_library" {
const libname = switch (builtin.os) {
- Os.linux => "invalid_so.so",
- Os.windows => "invalid_dll.dll",
+ .linux => "invalid_so.so",
+ .windows => "invalid_dll.dll",
else => return,
};
std/elf.zig
@@ -6,6 +6,7 @@ const math = std.math;
const mem = std.mem;
const debug = std.debug;
const InStream = std.stream.InStream;
+const File = std.fs.File;
pub const AT_NULL = 0;
pub const AT_IGNORE = 1;
@@ -367,7 +368,7 @@ pub const Elf = struct {
string_section: *SectionHeader,
section_headers: []SectionHeader,
allocator: *mem.Allocator,
- prealloc_file: os.File,
+ prealloc_file: File,
/// Call close when done.
pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {
@@ -375,7 +376,7 @@ pub const Elf = struct {
}
/// Call close when done.
- pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void {
+ pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: File) !void {
@compileError("TODO implement");
}
std/fs.zig
@@ -11,6 +11,7 @@ pub const deleteFile = os.unlink;
pub const deleteFileC = os.unlinkC;
pub const rename = os.rename;
pub const renameC = os.renameC;
+pub const renameW = os.renameW;
pub const changeCurDir = os.chdir;
pub const changeCurDirC = os.chdirC;
pub const realpath = os.realpath;
@@ -25,24 +26,24 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE
/// fit into a UTF-8 encoded array of this length.
/// path being too long if it is this 0long
pub const MAX_PATH_BYTES = switch (builtin.os) {
- .linux, .macosx, .ios, .freebsd, .netbsd => posix.PATH_MAX,
+ .linux, .macosx, .ios, .freebsd, .netbsd => os.PATH_MAX,
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
// If it would require 4 UTF-8 bytes, then there would be a surrogate
// pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
// +1 for the null byte at the end, which can be encoded in 1 byte.
- .windows => posix.PATH_MAX_WIDE * 3 + 1,
+ .windows => os.windows.PATH_MAX_WIDE * 3 + 1,
else => @compileError("Unsupported OS"),
};
/// The result is a slice of `out_buffer`, from index `0`.
pub fn getCwd(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
- return posix.getcwd(out_buffer);
+ return os.getcwd(out_buffer);
}
/// Caller must free the returned memory.
pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
var buf: [MAX_PATH_BYTES]u8 = undefined;
- return mem.dupe(allocator, u8, try posix.getcwd(&buf));
+ return mem.dupe(allocator, u8, try os.getcwd(&buf));
}
test "getCwdAlloc" {
@@ -90,7 +91,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
/// in the same directory as dest_path.
/// Destination file will have the same mode as the source file.
pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
- var in_file = try os.File.openRead(source_path);
+ var in_file = try File.openRead(source_path);
defer in_file.close();
const mode = try in_file.mode();
@@ -113,7 +114,7 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
/// merged and readily available,
/// there is a possibility of power loss or application termination leaving temporary files present
pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
- var in_file = try os.File.openRead(source_path);
+ var in_file = try File.openRead(source_path);
defer in_file.close();
var atomic_file = try AtomicFile.init(dest_path, mode);
@@ -130,12 +131,12 @@ pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.M
}
pub const AtomicFile = struct {
- file: os.File,
+ file: File,
tmp_path_buf: [MAX_PATH_BYTES]u8,
dest_path: []const u8,
finished: bool,
- const InitError = os.File.OpenError;
+ const InitError = File.OpenError;
/// dest_path must remain valid for the lifetime of AtomicFile
/// call finish to atomically replace dest_path with contents
@@ -161,7 +162,7 @@ pub const AtomicFile = struct {
try getRandomBytes(rand_buf[0..]);
b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);
- const file = os.File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
+ const file = File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
error.PathAlreadyExists => continue,
// TODO zig should figure out that this error set does not include PathAlreadyExists since
// it is handled in the above switch
@@ -190,16 +191,13 @@ pub const AtomicFile = struct {
assert(!self.finished);
self.file.close();
self.finished = true;
- if (is_posix) {
- const dest_path_c = try toPosixPath(self.dest_path);
- return renameC(&self.tmp_path_buf, &dest_path_c);
- } else if (is_windows) {
- const dest_path_w = try posix.sliceToPrefixedFileW(self.dest_path);
- const tmp_path_w = try posix.cStrToPrefixedFileW(&self.tmp_path_buf);
- return renameW(&tmp_path_w, &dest_path_w);
- } else {
- @compileError("Unsupported OS");
+ if (os.windows.is_the_target) {
+ const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
+ const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
+ return os.renameW(&tmp_path_w, &dest_path_w);
}
+ const dest_path_c = try os.toPosixPath(self.dest_path);
+ return os.renameC(&self.tmp_path_buf, &dest_path_c);
}
};
@@ -207,17 +205,17 @@ const default_new_dir_mode = 0o755;
/// Create a new directory.
pub fn makeDir(dir_path: []const u8) !void {
- return posix.mkdir(dir_path, default_new_dir_mode);
+ return os.mkdir(dir_path, default_new_dir_mode);
}
/// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.
pub fn makeDirC(dir_path: [*]const u8) !void {
- return posix.mkdirC(dir_path, default_new_dir_mode);
+ return os.mkdirC(dir_path, default_new_dir_mode);
}
/// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.
pub fn makeDirW(dir_path: [*]const u16) !void {
- return posix.mkdirW(dir_path, default_new_dir_mode);
+ return os.mkdirW(dir_path, default_new_dir_mode);
}
/// Calls makeDir recursively to make an entire path. Returns success if the path
@@ -260,17 +258,17 @@ pub fn makePath(allocator: *Allocator, full_path: []const u8) !void {
/// Returns `error.DirNotEmpty` if the directory is not empty.
/// To delete a directory recursively, see `deleteTree`.
pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
- return posix.rmdir(dir_path);
+ return os.rmdir(dir_path);
}
/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.
pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
- return posix.rmdirC(dir_path);
+ return os.rmdirC(dir_path);
}
/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.
pub fn deleteDirW(dir_path: [*]const u16) DeleteDirError!void {
- return posix.rmdirW(dir_path);
+ return os.rmdirW(dir_path);
}
/// Whether ::full_path describes a symlink, file, or directory, this function
@@ -383,22 +381,22 @@ pub const Dir = struct {
allocator: *Allocator,
pub const Handle = switch (builtin.os) {
- Os.macosx, Os.ios, Os.freebsd, Os.netbsd => struct {
+ .macosx, .ios, .freebsd, .netbsd => struct {
fd: i32,
seek: i64,
buf: []u8,
index: usize,
end_index: usize,
},
- Os.linux => struct {
+ .linux => struct {
fd: i32,
buf: []u8,
index: usize,
end_index: usize,
},
- Os.windows => struct {
- handle: windows.HANDLE,
- find_file_data: windows.WIN32_FIND_DATAW,
+ .windows => struct {
+ handle: os.windows.HANDLE,
+ find_file_data: os.windows.WIN32_FIND_DATAW,
first: bool,
name_data: [256]u8,
},
@@ -449,9 +447,9 @@ pub const Dir = struct {
return Dir{
.allocator = allocator,
.handle = switch (builtin.os) {
- Os.windows => blk: {
- var find_file_data: windows.WIN32_FIND_DATAW = undefined;
- const handle = try windows_util.windowsFindFirstFile(dir_path, &find_file_data);
+ .windows => blk: {
+ var find_file_data: os.windows.WIN32_FIND_DATAW = undefined;
+ const handle = try os.windows.FindFirstFile(dir_path, &find_file_data);
break :blk Handle{
.handle = handle,
.find_file_data = find_file_data, // TODO guaranteed copy elision
@@ -459,23 +457,15 @@ pub const Dir = struct {
.name_data = undefined,
};
},
- Os.macosx, Os.ios, Os.freebsd, Os.netbsd => Handle{
- .fd = try posixOpen(
- dir_path,
- posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
- 0,
- ),
+ .macosx, .ios, .freebsd, .netbsd => Handle{
+ .fd = try os.open(dir_path, os.O_RDONLY | os.O_NONBLOCK | os.O_DIRECTORY | os.O_CLOEXEC, 0),
.seek = 0,
.index = 0,
.end_index = 0,
.buf = []u8{},
},
- Os.linux => Handle{
- .fd = try posixOpen(
- dir_path,
- posix.O_RDONLY | posix.O_DIRECTORY | posix.O_CLOEXEC,
- 0,
- ),
+ .linux => Handle{
+ .fd = try os.open(dir_path, os.O_RDONLY | os.O_DIRECTORY | os.O_CLOEXEC, 0),
.index = 0,
.end_index = 0,
.buf = []u8{},
@@ -486,27 +476,22 @@ pub const Dir = struct {
}
pub fn close(self: *Dir) void {
- switch (builtin.os) {
- Os.windows => {
- _ = windows.FindClose(self.handle.handle);
- },
- Os.macosx, Os.ios, Os.linux, Os.freebsd, Os.netbsd => {
- self.allocator.free(self.handle.buf);
- os.close(self.handle.fd);
- },
- else => @compileError("unimplemented"),
+ if (os.windows.is_the_target) {
+ return os.windows.FindClose(self.handle.handle);
}
+ self.allocator.free(self.handle.buf);
+ os.close(self.handle.fd);
}
/// Memory such as file names referenced in this returned entry becomes invalid
/// with subsequent calls to next, as well as when this `Dir` is deinitialized.
pub fn next(self: *Dir) !?Entry {
switch (builtin.os) {
- Os.linux => return self.nextLinux(),
- Os.macosx, Os.ios => return self.nextDarwin(),
- Os.windows => return self.nextWindows(),
- Os.freebsd => return self.nextFreebsd(),
- Os.netbsd => return self.nextFreebsd(),
+ .linux => return self.nextLinux(),
+ .macosx, .ios => return self.nextDarwin(),
+ .windows => return self.nextWindows(),
+ .freebsd => return self.nextBsd(),
+ .netbsd => return self.nextBsd(),
else => @compileError("unimplemented"),
}
}
@@ -519,18 +504,23 @@ pub const Dir = struct {
}
while (true) {
- const result = system.__getdirentries64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);
- if (result == 0) return null;
- if (result < 0) {
- switch (system.getErrno(result)) {
- posix.EBADF => unreachable,
- posix.EFAULT => unreachable,
- posix.ENOTDIR => unreachable,
- posix.EINVAL => {
+ const rc = os.system.__getdirentries64(
+ self.handle.fd,
+ self.handle.buf.ptr,
+ self.handle.buf.len,
+ &self.handle.seek,
+ );
+ if (rc == 0) return null;
+ if (rc < 0) {
+ switch (os.errno(rc)) {
+ os.EBADF => unreachable,
+ os.EFAULT => unreachable,
+ os.ENOTDIR => unreachable,
+ os.EINVAL => {
self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
continue;
},
- else => return unexpectedErrorPosix(err),
+ else => |err| return os.unexpectedErrno(err),
}
}
self.handle.index = 0;
@@ -538,7 +528,7 @@ pub const Dir = struct {
break;
}
}
- const darwin_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);
+ const darwin_entry = @ptrCast(*align(1) os.dirent, &self.handle.buf[self.handle.index]);
const next_index = self.handle.index + darwin_entry.d_reclen;
self.handle.index = next_index;
@@ -549,14 +539,14 @@ pub const Dir = struct {
}
const entry_kind = switch (darwin_entry.d_type) {
- posix.DT_BLK => Entry.Kind.BlockDevice,
- posix.DT_CHR => Entry.Kind.CharacterDevice,
- posix.DT_DIR => Entry.Kind.Directory,
- posix.DT_FIFO => Entry.Kind.NamedPipe,
- posix.DT_LNK => Entry.Kind.SymLink,
- posix.DT_REG => Entry.Kind.File,
- posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
- posix.DT_WHT => Entry.Kind.Whiteout,
+ os.DT_BLK => Entry.Kind.BlockDevice,
+ os.DT_CHR => Entry.Kind.CharacterDevice,
+ os.DT_DIR => Entry.Kind.Directory,
+ os.DT_FIFO => Entry.Kind.NamedPipe,
+ os.DT_LNK => Entry.Kind.SymLink,
+ os.DT_REG => Entry.Kind.File,
+ os.DT_SOCK => Entry.Kind.UnixDomainSocket,
+ os.DT_WHT => Entry.Kind.Whiteout,
else => Entry.Kind.Unknown,
};
return Entry{
@@ -571,7 +561,7 @@ pub const Dir = struct {
if (self.handle.first) {
self.handle.first = false;
} else {
- if (!try posix.FindNextFile(self.handle.handle, &self.handle.find_file_data))
+ if (!try os.windows.FindNextFile(self.handle.handle, &self.handle.find_file_data))
return null;
}
const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);
@@ -582,9 +572,9 @@ pub const Dir = struct {
const name_utf8 = self.handle.name_data[0..name_utf8_len];
const kind = blk: {
const attrs = self.handle.find_file_data.dwFileAttributes;
- if (attrs & windows.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;
- if (attrs & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;
- if (attrs & windows.FILE_ATTRIBUTE_NORMAL != 0) break :blk Entry.Kind.File;
+ if (attrs & os.windows.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;
+ if (attrs & os.windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;
+ if (attrs & os.windows.FILE_ATTRIBUTE_NORMAL != 0) break :blk Entry.Kind.File;
break :blk Entry.Kind.Unknown;
};
return Entry{
@@ -602,25 +592,25 @@ pub const Dir = struct {
}
while (true) {
- const result = posix.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
- const err = posix.getErrno(result);
- if (err > 0) {
- switch (err) {
- posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
- posix.EINVAL => {
- self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
- continue;
- },
- else => return unexpectedErrorPosix(err),
- }
+ const rc = os.system.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
+ switch (os.errno(rc)) {
+ 0 => {},
+ os.EBADF => unreachable,
+ os.EFAULT => unreachable,
+ os.ENOTDIR => unreachable,
+ os.EINVAL => {
+ self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
+ continue;
+ },
+ else => |err| return os.unexpectedErrno(err),
}
- if (result == 0) return null;
+ if (rc == 0) return null;
self.handle.index = 0;
- self.handle.end_index = result;
+ self.handle.end_index = rc;
break;
}
}
- const linux_entry = @ptrCast(*align(1) posix.dirent64, &self.handle.buf[self.handle.index]);
+ const linux_entry = @ptrCast(*align(1) os.dirent64, &self.handle.buf[self.handle.index]);
const next_index = self.handle.index + linux_entry.d_reclen;
self.handle.index = next_index;
@@ -632,13 +622,13 @@ pub const Dir = struct {
}
const entry_kind = switch (linux_entry.d_type) {
- posix.DT_BLK => Entry.Kind.BlockDevice,
- posix.DT_CHR => Entry.Kind.CharacterDevice,
- posix.DT_DIR => Entry.Kind.Directory,
- posix.DT_FIFO => Entry.Kind.NamedPipe,
- posix.DT_LNK => Entry.Kind.SymLink,
- posix.DT_REG => Entry.Kind.File,
- posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
+ os.DT_BLK => Entry.Kind.BlockDevice,
+ os.DT_CHR => Entry.Kind.CharacterDevice,
+ os.DT_DIR => Entry.Kind.Directory,
+ os.DT_FIFO => Entry.Kind.NamedPipe,
+ os.DT_LNK => Entry.Kind.SymLink,
+ os.DT_REG => Entry.Kind.File,
+ os.DT_SOCK => Entry.Kind.UnixDomainSocket,
else => Entry.Kind.Unknown,
};
return Entry{
@@ -648,7 +638,7 @@ pub const Dir = struct {
}
}
- fn nextFreebsd(self: *Dir) !?Entry {
+ fn nextBsd(self: *Dir) !?Entry {
start_over: while (true) {
if (self.handle.index >= self.handle.end_index) {
if (self.handle.buf.len == 0) {
@@ -656,25 +646,30 @@ pub const Dir = struct {
}
while (true) {
- const result = posix.getdirentries(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);
- const err = posix.getErrno(result);
- if (err > 0) {
- switch (err) {
- posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
- posix.EINVAL => {
- self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
- continue;
- },
- else => return unexpectedErrorPosix(err),
- }
+ const rc = os.system.getdirentries(
+ self.handle.fd,
+ self.handle.buf.ptr,
+ self.handle.buf.len,
+ &self.handle.seek,
+ );
+ switch (os.errno(rc)) {
+ 0 => {},
+ os.EBADF => unreachable,
+ os.EFAULT => unreachable,
+ os.ENOTDIR => unreachable,
+ os.EINVAL => {
+ self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
+ continue;
+ },
+ else => |err| return os.unexpectedErrno(err),
}
- if (result == 0) return null;
+ if (rc == 0) return null;
self.handle.index = 0;
- self.handle.end_index = result;
+ self.handle.end_index = @intCast(usize, rc);
break;
}
}
- const freebsd_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);
+ const freebsd_entry = @ptrCast(*align(1) os.dirent, &self.handle.buf[self.handle.index]);
const next_index = self.handle.index + freebsd_entry.d_reclen;
self.handle.index = next_index;
@@ -685,14 +680,14 @@ pub const Dir = struct {
}
const entry_kind = switch (freebsd_entry.d_type) {
- posix.DT_BLK => Entry.Kind.BlockDevice,
- posix.DT_CHR => Entry.Kind.CharacterDevice,
- posix.DT_DIR => Entry.Kind.Directory,
- posix.DT_FIFO => Entry.Kind.NamedPipe,
- posix.DT_LNK => Entry.Kind.SymLink,
- posix.DT_REG => Entry.Kind.File,
- posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
- posix.DT_WHT => Entry.Kind.Whiteout,
+ os.DT_BLK => Entry.Kind.BlockDevice,
+ os.DT_CHR => Entry.Kind.CharacterDevice,
+ os.DT_DIR => Entry.Kind.Directory,
+ os.DT_FIFO => Entry.Kind.NamedPipe,
+ os.DT_LNK => Entry.Kind.SymLink,
+ os.DT_REG => Entry.Kind.File,
+ os.DT_SOCK => Entry.Kind.UnixDomainSocket,
+ os.DT_WHT => Entry.Kind.Whiteout,
else => Entry.Kind.Unknown,
};
return Entry{
@@ -705,52 +700,40 @@ pub const Dir = struct {
/// Read value of a symbolic link.
/// The return value is a slice of buffer, from index `0`.
-pub fn readLink(buffer: *[posix.PATH_MAX]u8, pathname: []const u8) ![]u8 {
- return posix.readlink(pathname, buffer);
+pub fn readLink(pathname: []const u8, buffer: *[os.PATH_MAX]u8) ![]u8 {
+ return os.readlink(pathname, buffer);
}
/// Same as `readLink`, except the `pathname` parameter is null-terminated.
-pub fn readLinkC(buffer: *[posix.PATH_MAX]u8, pathname: [*]const u8) ![]u8 {
- return posix.readlinkC(pathname, buffer);
+pub fn readLinkC(pathname: [*]const u8, buffer: *[os.PATH_MAX]u8) ![]u8 {
+ return os.readlinkC(pathname, buffer);
}
-pub fn openSelfExe() !os.File {
- switch (builtin.os) {
- Os.linux => return os.File.openReadC(c"/proc/self/exe"),
- Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
- var buf: [MAX_PATH_BYTES]u8 = undefined;
- const self_exe_path = try selfExePath(&buf);
- buf[self_exe_path.len] = 0;
- return os.File.openReadC(self_exe_path.ptr);
- },
- Os.windows => {
- var buf: [posix.PATH_MAX_WIDE]u16 = undefined;
- const wide_slice = try selfExePathW(&buf);
- return os.File.openReadW(wide_slice.ptr);
- },
- else => @compileError("Unsupported OS"),
+pub const OpenSelfExeError = error{};
+
+pub fn openSelfExe() OpenSelfExeError!File {
+ if (os.linux.is_the_target) {
+ return File.openReadC(c"/proc/self/exe");
+ }
+ if (os.windows.is_the_target) {
+ var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
+ const wide_slice = try selfExePathW(&buf);
+ return File.openReadW(wide_slice.ptr);
}
+ var buf: [MAX_PATH_BYTES]u8 = undefined;
+ const self_exe_path = try selfExePath(&buf);
+ buf[self_exe_path.len] = 0;
+ return File.openReadC(self_exe_path.ptr);
}
test "openSelfExe" {
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios, Os.windows, Os.freebsd => (try openSelfExe()).close(),
+ .linux, .macosx, .ios, .windows, .freebsd => (try openSelfExe()).close(),
else => return error.SkipZigTest, // Unsupported OS.
}
}
-pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {
- const casted_len = @intCast(windows.DWORD, out_buffer.len); // TODO shouldn't need this cast
- const rc = windows.GetModuleFileNameW(null, out_buffer, casted_len);
- assert(rc <= out_buffer.len);
- if (rc == 0) {
- const err = windows.GetLastError();
- switch (err) {
- else => return windows.unexpectedError(err),
- }
- }
- return out_buffer[0..rc];
-}
+pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;
/// Get the path to the current executable.
/// If you only need the directory, use selfExeDirPath.
@@ -763,39 +746,44 @@ pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {
/// been deleted, the file path looks something like `/a/b/c/exe (deleted)`.
/// TODO make the return type of this a null terminated pointer
pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
+ if (os.darwin.is_the_target) {
+ var u32_len: u32 = out_buffer.len;
+ const rc = c._NSGetExecutablePath(out_buffer, &u32_len);
+ if (rc != 0) return error.NameTooLong;
+ return mem.toSlice(u8, out_buffer);
+ }
switch (builtin.os) {
- Os.linux => return readLink(out_buffer, "/proc/self/exe"),
- Os.freebsd => {
- var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC, posix.KERN_PROC_PATHNAME, -1 };
+ .linux => return os.readlinkC(c"/proc/self/exe", out_buffer),
+ .freebsd => {
+ var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };
var out_len: usize = out_buffer.len;
- try posix.sysctl(&mib, out_buffer, &out_len, null, 0);
+ try os.sysctl(&mib, out_buffer, &out_len, null, 0);
// TODO could this slice from 0 to out_len instead?
return mem.toSlice(u8, out_buffer);
},
- Os.netbsd => {
- var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC_ARGS, -1, posix.KERN_PROC_PATHNAME };
+ .netbsd => {
+ var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC_ARGS, -1, os.KERN_PROC_PATHNAME };
var out_len: usize = out_buffer.len;
- try posix.sysctl(&mib, out_buffer, &out_len, null, 0);
+ try os.sysctl(&mib, out_buffer, &out_len, null, 0);
// TODO could this slice from 0 to out_len instead?
return mem.toSlice(u8, out_buffer);
},
- Os.windows => {
- var utf16le_buf: [posix.PATH_MAX_WIDE]u16 = undefined;
+ .windows => {
+ var utf16le_buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
const utf16le_slice = try selfExePathW(&utf16le_buf);
// Trust that Windows gives us valid UTF-16LE.
const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;
return out_buffer[0..end_index];
},
- Os.macosx, Os.ios => {
- var u32_len: u32 = @intCast(u32, out_buffer.len); // TODO shouldn't need this cast
- const rc = c._NSGetExecutablePath(out_buffer, &u32_len);
- if (rc != 0) return error.NameTooLong;
- return mem.toSlice(u8, out_buffer);
- },
- else => @compileError("Unsupported OS"),
+ else => @compileError("std.fs.selfExePath not supported for this target"),
}
}
+/// Same as `selfExePath` except the result is UTF16LE-encoded.
+pub fn selfExePathW(out_buffer: *[os.windows.PATH_MAX_WIDE]u16) ![]u16 {
+ return os.windows.GetModuleFileNameW(null, out_buffer, out_buffer.len);
+}
+
/// `selfExeDirPath` except allocates the result on the heap.
/// Caller owns returned memory.
pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
@@ -806,31 +794,26 @@ pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
/// Get the directory path that contains the current executable.
/// Returned value is a slice of out_buffer.
pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
- switch (builtin.os) {
- Os.linux => {
- // If the currently executing binary has been deleted,
- // the file path looks something like `/a/b/c/exe (deleted)`
- // This path cannot be opened, but it's valid for determining the directory
- // the executable was in when it was run.
- const full_exe_path = try readLinkC(out_buffer, c"/proc/self/exe");
- // Assume that /proc/self/exe has an absolute path, and therefore dirname
- // will not return null.
- return path.dirname(full_exe_path).?;
- },
- Os.windows, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
- const self_exe_path = try selfExePath(out_buffer);
- // Assume that the OS APIs return absolute paths, and therefore dirname
- // will not return null.
- return path.dirname(self_exe_path).?;
- },
- else => @compileError("Unsupported OS"),
+ if (os.linux.is_the_target) {
+ // If the currently executing binary has been deleted,
+ // the file path looks something like `/a/b/c/exe (deleted)`
+ // This path cannot be opened, but it's valid for determining the directory
+ // the executable was in when it was run.
+ const full_exe_path = try os.readlinkC(c"/proc/self/exe", out_buffer);
+ // Assume that /proc/self/exe has an absolute path, and therefore dirname
+ // will not return null.
+ return path.dirname(full_exe_path).?;
}
+ const self_exe_path = try selfExePath(out_buffer);
+ // Assume that the OS APIs return absolute paths, and therefore dirname
+ // will not return null.
+ return path.dirname(self_exe_path).?;
}
/// `realpath`, except caller must free the returned memory.
-pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
+pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
var buf: [MAX_PATH_BYTES]u8 = undefined;
- return mem.dupe(allocator, u8, try realpath(pathname, &buf));
+ return mem.dupe(allocator, u8, try os.realpath(pathname, &buf));
}
test "" {
std/io.zig
@@ -12,7 +12,7 @@ const meta = std.meta;
const trait = meta.trait;
const Buffer = std.Buffer;
const fmt = std.fmt;
-const File = std.os.File;
+const File = std.fs.File;
const testing = std.testing;
const is_posix = builtin.os != builtin.Os.windows;
@@ -963,8 +963,8 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
pub const BufferedAtomicFile = struct {
atomic_file: os.AtomicFile,
- file_stream: os.File.OutStream,
- buffered_stream: BufferedOutStream(os.File.WriteError),
+ file_stream: File.OutStream,
+ buffered_stream: BufferedOutStream(File.WriteError),
allocator: *mem.Allocator,
pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
@@ -978,11 +978,11 @@ pub const BufferedAtomicFile = struct {
};
errdefer allocator.destroy(self);
- self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);
+ self.atomic_file = try os.AtomicFile.init(dest_path, File.default_mode);
errdefer self.atomic_file.deinit();
self.file_stream = self.atomic_file.file.outStream();
- self.buffered_stream = BufferedOutStream(os.File.WriteError).init(&self.file_stream.stream);
+ self.buffered_stream = BufferedOutStream(File.WriteError).init(&self.file_stream.stream);
return self;
}
@@ -997,7 +997,7 @@ pub const BufferedAtomicFile = struct {
try self.atomic_file.finish();
}
- pub fn stream(self: *BufferedAtomicFile) *OutStream(os.File.WriteError) {
+ pub fn stream(self: *BufferedAtomicFile) *OutStream(File.WriteError) {
return &self.buffered_stream.stream;
}
};
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 {
std/pdb.zig
@@ -6,6 +6,7 @@ const mem = std.mem;
const os = std.os;
const warn = std.debug.warn;
const coff = std.coff;
+const File = std.fs.File;
const ArrayList = std.ArrayList;
@@ -459,7 +460,7 @@ pub const PDBStringTableHeader = packed struct {
};
pub const Pdb = struct {
- in_file: os.File,
+ in_file: File,
allocator: *mem.Allocator,
coff: *coff.Coff,
string_table: *MsfStream,
@@ -468,7 +469,7 @@ pub const Pdb = struct {
msf: Msf,
pub fn openFile(self: *Pdb, coff_ptr: *coff.Coff, file_name: []u8) !void {
- self.in_file = try os.File.openRead(file_name);
+ self.in_file = try File.openRead(file_name);
self.allocator = coff_ptr.allocator;
self.coff = coff_ptr;
@@ -492,7 +493,7 @@ const Msf = struct {
directory: MsfStream,
streams: []MsfStream,
- fn openFile(self: *Msf, allocator: *mem.Allocator, file: os.File) !void {
+ fn openFile(self: *Msf, allocator: *mem.Allocator, file: File) !void {
var file_stream = file.inStream();
const in = &file_stream.stream;
@@ -587,7 +588,7 @@ const SuperBlock = packed struct {
};
const MsfStream = struct {
- in_file: os.File,
+ in_file: File,
pos: u64,
blocks: []u32,
block_size: u32,
@@ -598,7 +599,7 @@ const MsfStream = struct {
pub const Error = @typeOf(read).ReturnType.ErrorSet;
pub const Stream = io.InStream(Error);
- fn init(block_size: u32, block_count: u32, pos: u64, file: os.File, allocator: *mem.Allocator) !MsfStream {
+ fn init(block_size: u32, block_count: u32, pos: u64, file: File, allocator: *mem.Allocator) !MsfStream {
var stream = MsfStream{
.in_file = file,
.pos = 0,
std/time.zig
@@ -1,116 +1,61 @@
-const std = @import("../std.zig");
const builtin = @import("builtin");
-const Os = builtin.Os;
-const debug = std.debug;
+const std = @import("std.zig");
+const assert = std.debug.assert;
const testing = std.testing;
-const math = std.math;
-
-const windows = std.os.windows;
-const linux = std.os.linux;
-const darwin = std.os.darwin;
-const wasi = std.os.wasi;
-const posix = std.os.posix;
+const os = std.os;
pub const epoch = @import("epoch.zig");
/// Spurious wakeups are possible and no precision of timing is guaranteed.
pub fn sleep(nanoseconds: u64) void {
- switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
- const s = nanoseconds / ns_per_s;
- const ns = nanoseconds % ns_per_s;
- posixSleep(s, ns);
- },
- Os.windows => {
- const ns_per_ms = ns_per_s / ms_per_s;
- const milliseconds = nanoseconds / ns_per_ms;
- const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD);
- windows.Sleep(ms_that_will_fit);
- },
- else => @compileError("Unsupported OS"),
- }
-}
-
-/// Spurious wakeups are possible and no precision of timing is guaranteed.
-pub fn posixSleep(seconds: u64, nanoseconds: u64) void {
- var req = posix.timespec{
- .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize),
- .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize),
- };
- var rem: posix.timespec = undefined;
- while (true) {
- const ret_val = posix.nanosleep(&req, &rem);
- const err = posix.getErrno(ret_val);
- switch (err) {
- posix.EFAULT => unreachable,
- posix.EINVAL => {
- // Sometimes Darwin returns EINVAL for no reason.
- // We treat it as a spurious wakeup.
- return;
- },
- posix.EINTR => {
- req = rem;
- continue;
- },
- // This prong handles success as well as unexpected errors.
- else => return,
- }
- }
+ const s = nanoseconds / ns_per_s;
+ const ns = nanoseconds % ns_per_s;
+ std.os.nanosleep(s, ns);
}
/// Get the posix timestamp, UTC, in seconds
+/// TODO audit this function. is it possible to return an error?
pub fn timestamp() u64 {
return @divFloor(milliTimestamp(), ms_per_s);
}
/// Get the posix timestamp, UTC, in milliseconds
-pub const milliTimestamp = switch (builtin.os) {
- Os.windows => milliTimestampWindows,
- Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,
- Os.macosx, Os.ios => milliTimestampDarwin,
- Os.wasi => milliTimestampWasi,
- else => @compileError("Unsupported OS"),
-};
-
-fn milliTimestampWasi() u64 {
- var ns: wasi.timestamp_t = undefined;
-
- // TODO: Verify that precision is ignored
- const err = wasi.clock_time_get(wasi.CLOCK_REALTIME, 1, &ns);
- debug.assert(err == wasi.ESUCCESS);
-
- const ns_per_ms = 1000;
- return @divFloor(ns, ns_per_ms);
-}
-
-fn milliTimestampWindows() u64 {
- //FileTime has a granularity of 100 nanoseconds
- // and uses the NTFS/Windows epoch
- var ft: windows.FILETIME = undefined;
- windows.GetSystemTimeAsFileTime(&ft);
- const hns_per_ms = (ns_per_s / 100) / ms_per_s;
- const epoch_adj = epoch.windows * ms_per_s;
-
- const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
- return @divFloor(ft64, hns_per_ms) - -epoch_adj;
-}
+/// TODO audit this function. is it possible to return an error?
+pub fn milliTimestamp() u64 {
+ if (os.windows.is_the_target and !builtin.link_libc) {
+ //FileTime has a granularity of 100 nanoseconds
+ // and uses the NTFS/Windows epoch
+ var ft: os.windows.FILETIME = undefined;
+ os.windows.kernel32.GetSystemTimeAsFileTime(&ft);
+ const hns_per_ms = (ns_per_s / 100) / ms_per_s;
+ const epoch_adj = epoch.windows * ms_per_s;
+
+ const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+ return @divFloor(ft64, hns_per_ms) - -epoch_adj;
+ }
+ if (os.wasi.is_the_target and !builtin.link_libc) {
+ var ns: os.wasi.timestamp_t = undefined;
-fn milliTimestampDarwin() u64 {
- var tv: darwin.timeval = undefined;
- var err = darwin.gettimeofday(&tv, null);
- debug.assert(err == 0);
- const sec_ms = tv.tv_sec * ms_per_s;
- const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
- return @intCast(u64, sec_ms + usec_ms);
-}
+ // TODO: Verify that precision is ignored
+ const err = os.wasi.clock_time_get(os.wasi.CLOCK_REALTIME, 1, &ns);
+ assert(err == os.wasi.ESUCCESS);
-fn milliTimestampPosix() u64 {
+ const ns_per_ms = 1000;
+ return @divFloor(ns, ns_per_ms);
+ }
+ if (os.darwin.is_the_target) {
+ var tv: os.darwin.timeval = undefined;
+ var err = os.darwin.gettimeofday(&tv, null);
+ assert(err == 0);
+ const sec_ms = tv.tv_sec * ms_per_s;
+ const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
+ return @intCast(u64, sec_ms + usec_ms);
+ }
+ var ts: os.timespec = undefined;
//From what I can tell there's no reason clock_gettime
// should ever fail for us with CLOCK_REALTIME,
// seccomp aside.
- var ts: posix.timespec = undefined;
- const err = posix.clock_gettime(posix.CLOCK_REALTIME, &ts);
- debug.assert(err == 0);
+ os.clock_gettime(os.CLOCK_REALTIME, &ts) catch unreachable;
const sec_ms = @intCast(u64, ts.tv_sec) * ms_per_s;
const nsec_ms = @divFloor(@intCast(u64, ts.tv_nsec), ns_per_s / ms_per_s);
return sec_ms + nsec_ms;
@@ -145,27 +90,23 @@ pub const s_per_week = s_per_day * 7;
/// depends on the OS. On Windows and Darwin it is a hardware counter
/// value that requires calculation to convert to a meaninful unit.
pub const Timer = struct {
-
- //if we used resolution's value when performing the
- // performance counter calc on windows/darwin, it would
- // be less precise
+ ///if we used resolution's value when performing the
+ /// performance counter calc on windows/darwin, it would
+ /// be less precise
frequency: switch (builtin.os) {
- Os.windows => u64,
- Os.macosx, Os.ios => darwin.mach_timebase_info_data,
+ .windows => u64,
+ .macosx, .ios, .tvos, .watchos => darwin.mach_timebase_info_data,
else => void,
},
resolution: u64,
start_time: u64,
- //At some point we may change our minds on RAW, but for now we're
- // sticking with posix standard MONOTONIC. For more information, see:
- // https://github.com/ziglang/zig/pull/933
- //
- //const monotonic_clock_id = switch(builtin.os) {
- // Os.linux => linux.CLOCK_MONOTONIC_RAW,
- // else => posix.CLOCK_MONOTONIC,
- //};
- const monotonic_clock_id = posix.CLOCK_MONOTONIC;
+ const Error = error{TimerUnsupported};
+
+ ///At some point we may change our minds on RAW, but for now we're
+ /// sticking with posix standard MONOTONIC. For more information, see:
+ /// https://github.com/ziglang/zig/pull/933
+ const monotonic_clock_id = os.CLOCK_MONOTONIC;
/// Initialize the timer structure.
//This gives us an opportunity to grab the counter frequency in windows.
//On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.
@@ -174,66 +115,51 @@ pub const Timer = struct {
// impossible here barring cosmic rays or other such occurrences of
// incredibly bad luck.
//On Darwin: This cannot fail, as far as I am able to tell.
- const TimerError = error{
- TimerUnsupported,
- Unexpected,
- };
- pub fn start() TimerError!Timer {
+ pub fn start() Error!Timer {
var self: Timer = undefined;
- switch (builtin.os) {
- Os.windows => {
- var freq: i64 = undefined;
- var err = windows.QueryPerformanceFrequency(&freq);
- if (err == windows.FALSE) return error.TimerUnsupported;
- self.frequency = @intCast(u64, freq);
- self.resolution = @divFloor(ns_per_s, self.frequency);
-
- var start_time: i64 = undefined;
- err = windows.QueryPerformanceCounter(&start_time);
- debug.assert(err != windows.FALSE);
- self.start_time = @intCast(u64, start_time);
- },
- Os.linux, Os.freebsd, Os.netbsd => {
- //On Linux, seccomp can do arbitrary things to our ability to call
- // syscalls, including return any errno value it wants and
- // inconsistently throwing errors. Since we can't account for
- // abuses of seccomp in a reasonable way, we'll assume that if
- // seccomp is going to block us it will at least do so consistently
- var ts: posix.timespec = undefined;
- var result = posix.clock_getres(monotonic_clock_id, &ts);
- var errno = posix.getErrno(result);
- switch (errno) {
- 0 => {},
- posix.EINVAL => return error.TimerUnsupported,
- else => return std.os.unexpectedErrorPosix(errno),
- }
- self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
-
- result = posix.clock_gettime(monotonic_clock_id, &ts);
- errno = posix.getErrno(result);
- if (errno != 0) return std.os.unexpectedErrorPosix(errno);
- self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
- },
- Os.macosx, Os.ios => {
- darwin.mach_timebase_info(&self.frequency);
- self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
- self.start_time = darwin.mach_absolute_time();
- },
- else => @compileError("Unsupported OS"),
+ if (os.windows.is_the_target) {
+ var freq: i64 = undefined;
+ var err = windows.QueryPerformanceFrequency(&freq);
+ if (err == windows.FALSE) return error.TimerUnsupported;
+ self.frequency = @intCast(u64, freq);
+ self.resolution = @divFloor(ns_per_s, self.frequency);
+
+ var start_time: i64 = undefined;
+ err = windows.QueryPerformanceCounter(&start_time);
+ assert(err != windows.FALSE);
+ self.start_time = @intCast(u64, start_time);
+ } else if (os.darwin.is_the_target) {
+ darwin.mach_timebase_info(&self.frequency);
+ self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
+ self.start_time = darwin.mach_absolute_time();
+ } else {
+ //On Linux, seccomp can do arbitrary things to our ability to call
+ // syscalls, including return any errno value it wants and
+ // inconsistently throwing errors. Since we can't account for
+ // abuses of seccomp in a reasonable way, we'll assume that if
+ // seccomp is going to block us it will at least do so consistently
+ var ts: os.timespec = undefined;
+ os.clock_getres(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
+ self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
+
+ os.clock_gettime(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
+ self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
}
+
return self;
}
/// Reads the timer value since start or the last reset in nanoseconds
pub fn read(self: *Timer) u64 {
var clock = clockNative() - self.start_time;
- return switch (builtin.os) {
- Os.windows => @divFloor(clock * ns_per_s, self.frequency),
- Os.linux, Os.freebsd, Os.netbsd => clock,
- Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
- else => @compileError("Unsupported OS"),
- };
+ if (os.windows.is_the_target) {
+ return @divFloor(clock * ns_per_s, self.frequency);
+ }
+ if (os.darwin.is_the_target) {
+ return @divFloor(clock * self.frequency.numer, self.frequency.denom);
+ }
+ return clock;
}
/// Resets the timer value to 0/now.
@@ -249,37 +175,27 @@ pub const Timer = struct {
return lap_time;
}
- const clockNative = switch (builtin.os) {
- Os.windows => clockWindows,
- Os.linux, Os.freebsd, Os.netbsd => clockLinux,
- Os.macosx, Os.ios => clockDarwin,
- else => @compileError("Unsupported OS"),
- };
-
- fn clockWindows() u64 {
- var result: i64 = undefined;
- var err = windows.QueryPerformanceCounter(&result);
- debug.assert(err != windows.FALSE);
- return @intCast(u64, result);
- }
-
- fn clockDarwin() u64 {
- return darwin.mach_absolute_time();
- }
-
- fn clockLinux() u64 {
- var ts: posix.timespec = undefined;
- var result = posix.clock_gettime(monotonic_clock_id, &ts);
- debug.assert(posix.getErrno(result) == 0);
+ fn clockNative() u64 {
+ if (os.windows.is_the_target) {
+ var result: i64 = undefined;
+ var err = windows.QueryPerformanceCounter(&result);
+ assert(err != windows.FALSE);
+ return @intCast(u64, result);
+ }
+ if (os.darwin.is_the_target) {
+ return darwin.mach_absolute_time();
+ }
+ var ts: os.timespec = undefined;
+ os.clock_gettime(monotonic_clock_id, &ts) catch unreachable;
return @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
}
};
-test "os.time.sleep" {
+test "sleep" {
sleep(1);
}
-test "os.time.timestamp" {
+test "timestamp" {
const ns_per_ms = (ns_per_s / ms_per_s);
const margin = 50;
@@ -290,7 +206,7 @@ test "os.time.timestamp" {
testing.expect(interval > 0 and interval < margin);
}
-test "os.time.Timer" {
+test "Timer" {
const ns_per_ms = (ns_per_s / ms_per_s);
const margin = ns_per_ms * 150;