authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-24 22:52:07-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-26 18:32:44-04:00
logca6debcaf4a4f85b7aff94c7b5fe821530b0f195
treea05bdab98809538db5bd3106b42ce60a8e868d6b
parent3d61e4228298dcb973c13d8d6eba0bff36acf1ca
signature Commit is signed but in an unrecognized format.

starting to fix the regressions


27 files changed, 547 insertions(+), 581 deletions(-)

std/atomic/queue.zig+2-2
...@@ -220,7 +220,7 @@ fn startPuts(ctx: *Context) u8 {...@@ -220,7 +220,7 @@ fn startPuts(ctx: *Context) u8 {
220 var put_count: usize = puts_per_thread;220 var put_count: usize = puts_per_thread;
221 var r = std.rand.DefaultPrng.init(0xdeadbeef);221 var r = std.rand.DefaultPrng.init(0xdeadbeef);
222 while (put_count != 0) : (put_count -= 1) {222 while (put_count != 0) : (put_count -= 1) {
223 std.os.time.sleep(1); // let the os scheduler be our fuzz223 std.time.sleep(1); // let the os scheduler be our fuzz
224 const x = @bitCast(i32, r.random.scalar(u32));224 const x = @bitCast(i32, r.random.scalar(u32));
225 const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;225 const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;
226 node.* = Queue(i32).Node{226 node.* = Queue(i32).Node{
...@@ -239,7 +239,7 @@ fn startGets(ctx: *Context) u8 {...@@ -239,7 +239,7 @@ fn startGets(ctx: *Context) u8 {
239 const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;239 const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
240240
241 while (ctx.queue.get()) |node| {241 while (ctx.queue.get()) |node| {
242 std.os.time.sleep(1); // let the os scheduler be our fuzz242 std.time.sleep(1); // let the os scheduler be our fuzz
243 _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);243 _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
244 _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);244 _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
245 }245 }
std/atomic/stack.zig+2-2
...@@ -154,7 +154,7 @@ fn startPuts(ctx: *Context) u8 {...@@ -154,7 +154,7 @@ fn startPuts(ctx: *Context) u8 {
154 var put_count: usize = puts_per_thread;154 var put_count: usize = puts_per_thread;
155 var r = std.rand.DefaultPrng.init(0xdeadbeef);155 var r = std.rand.DefaultPrng.init(0xdeadbeef);
156 while (put_count != 0) : (put_count -= 1) {156 while (put_count != 0) : (put_count -= 1) {
157 std.os.time.sleep(1); // let the os scheduler be our fuzz157 std.time.sleep(1); // let the os scheduler be our fuzz
158 const x = @bitCast(i32, r.random.scalar(u32));158 const x = @bitCast(i32, r.random.scalar(u32));
159 const node = ctx.allocator.create(Stack(i32).Node) catch unreachable;159 const node = ctx.allocator.create(Stack(i32).Node) catch unreachable;
160 node.* = Stack(i32).Node{160 node.* = Stack(i32).Node{
...@@ -172,7 +172,7 @@ fn startGets(ctx: *Context) u8 {...@@ -172,7 +172,7 @@ fn startGets(ctx: *Context) u8 {
172 const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;172 const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
173173
174 while (ctx.stack.pop()) |node| {174 while (ctx.stack.pop()) |node| {
175 std.os.time.sleep(1); // let the os scheduler be our fuzz175 std.time.sleep(1); // let the os scheduler be our fuzz
176 _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);176 _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
177 _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);177 _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
178 }178 }
std/build.zig+3-2
...@@ -14,6 +14,7 @@ const Term = os.ChildProcess.Term;...@@ -14,6 +14,7 @@ const Term = os.ChildProcess.Term;
14const BufSet = std.BufSet;14const BufSet = std.BufSet;
15const BufMap = std.BufMap;15const BufMap = std.BufMap;
16const fmt_lib = std.fmt;16const fmt_lib = std.fmt;
17const File = std.fs.File;
1718
18pub const FmtStep = @import("build/fmt.zig").FmtStep;19pub const FmtStep = @import("build/fmt.zig").FmtStep;
1920
...@@ -668,10 +669,10 @@ pub const Builder = struct {...@@ -668,10 +669,10 @@ pub const Builder = struct {
668 }669 }
669670
670 fn copyFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void {671 fn copyFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void {
671 return self.copyFileMode(source_path, dest_path, os.File.default_mode);672 return self.copyFileMode(source_path, dest_path, File.default_mode);
672 }673 }
673674
674 fn copyFileMode(self: *Builder, source_path: []const u8, dest_path: []const u8, mode: os.File.Mode) !void {675 fn copyFileMode(self: *Builder, source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
675 if (self.verbose) {676 if (self.verbose) {
676 warn("cp {} {}\n", source_path, dest_path);677 warn("cp {} {}\n", source_path, dest_path);
677 }678 }
std/c.zig+1-1
...@@ -75,7 +75,7 @@ pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usi...@@ -75,7 +75,7 @@ pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usi
75pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;75pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;
76pub extern "c" fn socket(domain: c_int, sock_type: c_int, protocol: c_int) c_int;76pub extern "c" fn socket(domain: c_int, sock_type: c_int, protocol: c_int) c_int;
77pub extern "c" fn kill(pid: pid_t, sig: c_int) c_int;77pub extern "c" fn kill(pid: pid_t, sig: c_int) c_int;
78pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) usize;78pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) isize;
79pub extern "c" fn openat(fd: c_int, path: [*]const u8, flags: c_int) c_int;79pub extern "c" fn openat(fd: c_int, path: [*]const u8, flags: c_int) c_int;
80pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;80pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
81pub extern "c" fn setuid(uid: c_uint) c_int;81pub extern "c" fn setuid(uid: c_uint) c_int;
std/child_process.zig+28-64
...@@ -3,7 +3,7 @@ const cstr = std.cstr;...@@ -3,7 +3,7 @@ const cstr = std.cstr;
3const unicode = std.unicode;3const unicode = std.unicode;
4const io = std.io;4const io = std.io;
5const os = std.os;5const os = std.os;
6const posix = os.posix;6const File = std.fs.File;
7const windows = os.windows;7const windows = os.windows;
8const mem = std.mem;8const mem = std.mem;
9const debug = std.debug;9const debug = std.debug;
...@@ -23,9 +23,9 @@ pub const ChildProcess = struct {...@@ -23,9 +23,9 @@ pub const ChildProcess = struct {
2323
24 pub allocator: *mem.Allocator,24 pub allocator: *mem.Allocator,
2525
26 pub stdin: ?os.File,26 pub stdin: ?File,
27 pub stdout: ?os.File,27 pub stdout: ?File,
28 pub stderr: ?os.File,28 pub stderr: ?File,
2929
30 pub term: ?(SpawnError!Term),30 pub term: ?(SpawnError!Term),
3131
...@@ -148,12 +148,7 @@ pub const ChildProcess = struct {...@@ -148,12 +148,7 @@ pub const ChildProcess = struct {
148 return term;148 return term;
149 }149 }
150150
151 if (!windows.TerminateProcess(self.handle, exit_code)) {151 try windows.TerminateProcess(self.handle, exit_code);
152 const err = windows.GetLastError();
153 return switch (err) {
154 else => os.unexpectedErrorWindows(err),
155 };
156 }
157 try self.waitUnwrappedWindows();152 try self.waitUnwrappedWindows();
158 return self.term.?;153 return self.term.?;
159 }154 }
...@@ -163,16 +158,7 @@ pub const ChildProcess = struct {...@@ -163,16 +158,7 @@ pub const ChildProcess = struct {
163 self.cleanupStreams();158 self.cleanupStreams();
164 return term;159 return term;
165 }160 }
166 const ret = posix.kill(self.pid, posix.SIGTERM);161 try os.kill(self.pid, os.SIGTERM);
167 const err = posix.getErrno(ret);
168 if (err > 0) {
169 return switch (err) {
170 posix.EINVAL => unreachable,
171 posix.EPERM => error.PermissionDenied,
172 posix.ESRCH => error.ProcessNotFound,
173 else => os.unexpectedErrorPosix(err),
174 };
175 }
176 self.waitUnwrapped();162 self.waitUnwrapped();
177 return self.term.?;163 return self.term.?;
178 }164 }
...@@ -267,19 +253,9 @@ pub const ChildProcess = struct {...@@ -267,19 +253,9 @@ pub const ChildProcess = struct {
267 }253 }
268254
269 fn waitUnwrapped(self: *ChildProcess) void {255 fn waitUnwrapped(self: *ChildProcess) void {
270 var status: i32 = undefined;256 const status = os.waitpid(self.pid, 0);
271 while (true) {257 self.cleanupStreams();
272 const err = posix.getErrno(posix.waitpid(self.pid, &status, 0));258 self.handleWaitResult(status);
273 if (err > 0) {
274 switch (err) {
275 posix.EINTR => continue,
276 else => unreachable,
277 }
278 }
279 self.cleanupStreams();
280 self.handleWaitResult(status);
281 return;
282 }
283 }259 }
284260
285 fn handleWaitResult(self: *ChildProcess, status: i32) void {261 fn handleWaitResult(self: *ChildProcess, status: i32) void {
...@@ -324,34 +300,34 @@ pub const ChildProcess = struct {...@@ -324,34 +300,34 @@ pub const ChildProcess = struct {
324 }300 }
325301
326 fn statusToTerm(status: i32) Term {302 fn statusToTerm(status: i32) Term {
327 return if (posix.WIFEXITED(status))303 return if (os.WIFEXITED(status))
328 Term{ .Exited = posix.WEXITSTATUS(status) }304 Term{ .Exited = os.WEXITSTATUS(status) }
329 else if (posix.WIFSIGNALED(status))305 else if (os.WIFSIGNALED(status))
330 Term{ .Signal = posix.WTERMSIG(status) }306 Term{ .Signal = os.WTERMSIG(status) }
331 else if (posix.WIFSTOPPED(status))307 else if (os.WIFSTOPPED(status))
332 Term{ .Stopped = posix.WSTOPSIG(status) }308 Term{ .Stopped = os.WSTOPSIG(status) }
333 else309 else
334 Term{ .Unknown = status };310 Term{ .Unknown = status };
335 }311 }
336312
337 fn spawnPosix(self: *ChildProcess) !void {313 fn spawnPosix(self: *ChildProcess) !void {
338 const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined;314 const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try os.pipe() else undefined;
339 errdefer if (self.stdin_behavior == StdIo.Pipe) {315 errdefer if (self.stdin_behavior == StdIo.Pipe) {
340 destroyPipe(stdin_pipe);316 destroyPipe(stdin_pipe);
341 };317 };
342318
343 const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined;319 const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try os.pipe() else undefined;
344 errdefer if (self.stdout_behavior == StdIo.Pipe) {320 errdefer if (self.stdout_behavior == StdIo.Pipe) {
345 destroyPipe(stdout_pipe);321 destroyPipe(stdout_pipe);
346 };322 };
347323
348 const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined;324 const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try os.pipe() else undefined;
349 errdefer if (self.stderr_behavior == StdIo.Pipe) {325 errdefer if (self.stderr_behavior == StdIo.Pipe) {
350 destroyPipe(stderr_pipe);326 destroyPipe(stderr_pipe);
351 };327 };
352328
353 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);329 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
354 const dev_null_fd = if (any_ignore) try os.posixOpenC(c"/dev/null", posix.O_RDWR, 0) else undefined;330 const dev_null_fd = if (any_ignore) try os.openC(c"/dev/null", os.O_RDWR, 0) else undefined;
355 defer {331 defer {
356 if (any_ignore) os.close(dev_null_fd);332 if (any_ignore) os.close(dev_null_fd);
357 }333 }
...@@ -372,7 +348,7 @@ pub const ChildProcess = struct {...@@ -372,7 +348,7 @@ pub const ChildProcess = struct {
372348
373 // This pipe is used to communicate errors between the time of fork349 // This pipe is used to communicate errors between the time of fork
374 // and execve from the child process to the parent process.350 // and execve from the child process to the parent process.
375 const err_pipe = try makePipe();351 const err_pipe = try os.pipe();
376 errdefer destroyPipe(err_pipe);352 errdefer destroyPipe(err_pipe);
377353
378 const pid_result = try posix.fork();354 const pid_result = try posix.fork();
...@@ -413,17 +389,17 @@ pub const ChildProcess = struct {...@@ -413,17 +389,17 @@ pub const ChildProcess = struct {
413 // we are the parent389 // we are the parent
414 const pid = @intCast(i32, pid_result);390 const pid = @intCast(i32, pid_result);
415 if (self.stdin_behavior == StdIo.Pipe) {391 if (self.stdin_behavior == StdIo.Pipe) {
416 self.stdin = os.File.openHandle(stdin_pipe[1]);392 self.stdin = File.openHandle(stdin_pipe[1]);
417 } else {393 } else {
418 self.stdin = null;394 self.stdin = null;
419 }395 }
420 if (self.stdout_behavior == StdIo.Pipe) {396 if (self.stdout_behavior == StdIo.Pipe) {
421 self.stdout = os.File.openHandle(stdout_pipe[0]);397 self.stdout = File.openHandle(stdout_pipe[0]);
422 } else {398 } else {
423 self.stdout = null;399 self.stdout = null;
424 }400 }
425 if (self.stderr_behavior == StdIo.Pipe) {401 if (self.stderr_behavior == StdIo.Pipe) {
426 self.stderr = os.File.openHandle(stderr_pipe[0]);402 self.stderr = File.openHandle(stderr_pipe[0]);
427 } else {403 } else {
428 self.stderr = null;404 self.stderr = null;
429 }405 }
...@@ -608,17 +584,17 @@ pub const ChildProcess = struct {...@@ -608,17 +584,17 @@ pub const ChildProcess = struct {
608 };584 };
609585
610 if (g_hChildStd_IN_Wr) |h| {586 if (g_hChildStd_IN_Wr) |h| {
611 self.stdin = os.File.openHandle(h);587 self.stdin = File.openHandle(h);
612 } else {588 } else {
613 self.stdin = null;589 self.stdin = null;
614 }590 }
615 if (g_hChildStd_OUT_Rd) |h| {591 if (g_hChildStd_OUT_Rd) |h| {
616 self.stdout = os.File.openHandle(h);592 self.stdout = File.openHandle(h);
617 } else {593 } else {
618 self.stdout = null;594 self.stdout = null;
619 }595 }
620 if (g_hChildStd_ERR_Rd) |h| {596 if (g_hChildStd_ERR_Rd) |h| {
621 self.stderr = os.File.openHandle(h);597 self.stderr = File.openHandle(h);
622 } else {598 } else {
623 self.stderr = null;599 self.stderr = null;
624 }600 }
...@@ -751,18 +727,6 @@ fn windowsMakePipeOut(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const...@@ -751,18 +727,6 @@ fn windowsMakePipeOut(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const
751 wr.* = wr_h;727 wr.* = wr_h;
752}728}
753729
754fn makePipe() ![2]i32 {
755 var fds: [2]i32 = undefined;
756 const err = posix.getErrno(posix.pipe(&fds));
757 if (err > 0) {
758 return switch (err) {
759 posix.EMFILE, posix.ENFILE => error.SystemResources,
760 else => os.unexpectedErrorPosix(err),
761 };
762 }
763 return fds;
764}
765
766fn destroyPipe(pipe: [2]i32) void {730fn destroyPipe(pipe: [2]i32) void {
767 os.close(pipe[0]);731 os.close(pipe[0]);
768 os.close(pipe[1]);732 os.close(pipe[1]);
...@@ -778,12 +742,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {...@@ -778,12 +742,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
778const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);742const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
779743
780fn writeIntFd(fd: i32, value: ErrInt) !void {744fn writeIntFd(fd: i32, value: ErrInt) !void {
781 const stream = &os.File.openHandle(fd).outStream().stream;745 const stream = &File.openHandle(fd).outStream().stream;
782 stream.writeIntNative(ErrInt, value) catch return error.SystemResources;746 stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
783}747}
784748
785fn readIntFd(fd: i32) !ErrInt {749fn readIntFd(fd: i32) !ErrInt {
786 const stream = &os.File.openHandle(fd).inStream().stream;750 const stream = &File.openHandle(fd).inStream().stream;
787 return stream.readIntNative(ErrInt) catch return error.SystemResources;751 return stream.readIntNative(ErrInt) catch return error.SystemResources;
788}752}
789753
std/coff.zig+3-2
...@@ -3,6 +3,7 @@ const std = @import("std.zig");...@@ -3,6 +3,7 @@ const std = @import("std.zig");
3const io = std.io;3const io = std.io;
4const mem = std.mem;4const mem = std.mem;
5const os = std.os;5const os = std.os;
6const File = std.fs.File;
67
7const ArrayList = std.ArrayList;8const ArrayList = std.ArrayList;
89
...@@ -28,7 +29,7 @@ pub const CoffError = error{...@@ -28,7 +29,7 @@ pub const CoffError = error{
28};29};
2930
30pub const Coff = struct {31pub const Coff = struct {
31 in_file: os.File,32 in_file: File,
32 allocator: *mem.Allocator,33 allocator: *mem.Allocator,
3334
34 coff_header: CoffHeader,35 coff_header: CoffHeader,
...@@ -77,7 +78,7 @@ pub const Coff = struct {...@@ -77,7 +78,7 @@ pub const Coff = struct {
77 try self.loadOptionalHeader(&file_stream);78 try self.loadOptionalHeader(&file_stream);
78 }79 }
7980
80 fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {81 fn loadOptionalHeader(self: *Coff, file_stream: *File.InStream) !void {
81 const in = &file_stream.stream;82 const in = &file_stream.stream;
82 self.pe_header.magic = try in.readIntLittle(u16);83 self.pe_header.magic = try in.readIntLittle(u16);
83 // For now we're only interested in finding the reference to the .pdb,84 // For now we're only interested in finding the reference to the .pdb,
std/crypto/throughput_test.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
3const time = std.os.time;3const time = std.time;
4const Timer = time.Timer;4const Timer = time.Timer;
5const crypto = @import("../crypto.zig");5const crypto = @import("../crypto.zig");
66
std/debug.zig+7-6
...@@ -12,6 +12,7 @@ const windows = os.windows;...@@ -12,6 +12,7 @@ const windows = os.windows;
12const ArrayList = std.ArrayList;12const ArrayList = std.ArrayList;
13const builtin = @import("builtin");13const builtin = @import("builtin");
14const maxInt = std.math.maxInt;14const maxInt = std.math.maxInt;
15const File = std.fs.File;
1516
16const leb = @import("debug/leb128.zig");17const leb = @import("debug/leb128.zig");
1718
...@@ -36,10 +37,10 @@ const Module = struct {...@@ -36,10 +37,10 @@ const Module = struct {
3637
37/// Tries to write to stderr, unbuffered, and ignores any error returned.38/// Tries to write to stderr, unbuffered, and ignores any error returned.
38/// Does not append a newline.39/// Does not append a newline.
39var stderr_file: os.File = undefined;40var stderr_file: File = undefined;
40var stderr_file_out_stream: os.File.OutStream = undefined;41var stderr_file_out_stream: File.OutStream = undefined;
4142
42var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;43var stderr_stream: ?*io.OutStream(File.WriteError) = null;
43var stderr_mutex = std.Mutex.init();44var stderr_mutex = std.Mutex.init();
44pub fn warn(comptime fmt: []const u8, args: ...) void {45pub fn warn(comptime fmt: []const u8, args: ...) void {
45 const held = stderr_mutex.acquire();46 const held = stderr_mutex.acquire();
...@@ -48,7 +49,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {...@@ -48,7 +49,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {
48 stderr.print(fmt, args) catch return;49 stderr.print(fmt, args) catch return;
49}50}
5051
51pub fn getStderrStream() !*io.OutStream(os.File.WriteError) {52pub fn getStderrStream() !*io.OutStream(File.WriteError) {
52 if (stderr_stream) |st| {53 if (stderr_stream) |st| {
53 return st;54 return st;
54 } else {55 } else {
...@@ -1003,7 +1004,7 @@ pub fn openElfDebugInfo(...@@ -1003,7 +1004,7 @@ pub fn openElfDebugInfo(
10031004
1004fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {1005fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
1005 const S = struct {1006 const S = struct {
1006 var self_exe_file: os.File = undefined;1007 var self_exe_file: File = undefined;
1007 var self_exe_mmap_seekable: io.SliceSeekableInStream = undefined;1008 var self_exe_mmap_seekable: io.SliceSeekableInStream = undefined;
1008 };1009 };
10091010
...@@ -1112,7 +1113,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {...@@ -1112,7 +1113,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
1112}1113}
11131114
1114fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {1115fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
1115 var f = try os.File.openRead(line_info.file_name);1116 var f = try File.openRead(line_info.file_name);
1116 defer f.close();1117 defer f.close();
1117 // TODO fstat and make sure that the file has the correct size1118 // TODO fstat and make sure that the file has the correct size
11181119
std/dynamic_library.zig+13-15
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const Os = builtin.Os;
32
4const std = @import("std.zig");3const std = @import("std.zig");
5const mem = std.mem;4const mem = std.mem;
...@@ -8,14 +7,13 @@ const os = std.os;...@@ -8,14 +7,13 @@ const os = std.os;
8const assert = std.debug.assert;7const assert = std.debug.assert;
9const testing = std.testing;8const testing = std.testing;
10const elf = std.elf;9const elf = std.elf;
11const linux = os.linux;
12const windows = os.windows;10const windows = os.windows;
13const win_util = @import("os/windows/util.zig");11const win_util = @import("os/windows/util.zig");
14const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1513
16pub const DynLib = switch (builtin.os) {14pub const DynLib = switch (builtin.os) {
17 Os.linux => LinuxDynLib,15 .linux => LinuxDynLib,
18 Os.windows => WindowsDynLib,16 .windows => WindowsDynLib,
19 else => void,17 else => void,
20};18};
2119
...@@ -110,20 +108,20 @@ pub const LinuxDynLib = struct {...@@ -110,20 +108,20 @@ pub const LinuxDynLib = struct {
110108
111 /// Trusts the file109 /// Trusts the file
112 pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {110 pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
113 const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);111 const fd = try os.open(path, 0, os.O_RDONLY | os.O_CLOEXEC);
114 errdefer std.os.close(fd);112 errdefer std.os.close(fd);
115113
116 const size = @intCast(usize, (try std.os.posixFStat(fd)).size);114 const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
117115
118 const addr = linux.mmap(116 const addr = os.mmap(
119 null,117 null,
120 size,118 size,
121 linux.PROT_READ | linux.PROT_EXEC,119 os.PROT_READ | os.PROT_EXEC,
122 linux.MAP_PRIVATE | linux.MAP_LOCKED,120 os.MAP_PRIVATE | os.MAP_LOCKED,
123 fd,121 fd,
124 0,122 0,
125 );123 );
126 errdefer _ = linux.munmap(addr, size);124 errdefer os.munmap(addr, size);
127125
128 const bytes = @intToPtr([*]align(mem.page_size) u8, addr)[0..size];126 const bytes = @intToPtr([*]align(mem.page_size) u8, addr)[0..size];
129127
...@@ -136,7 +134,7 @@ pub const LinuxDynLib = struct {...@@ -136,7 +134,7 @@ pub const LinuxDynLib = struct {
136 }134 }
137135
138 pub fn close(self: *DynLib) void {136 pub fn close(self: *DynLib) void {
139 _ = linux.munmap(self.map_addr, self.map_size);137 os.munmap(self.map_addr, self.map_size);
140 std.os.close(self.fd);138 std.os.close(self.fd);
141 self.* = undefined;139 self.* = undefined;
142 }140 }
...@@ -149,7 +147,7 @@ pub const LinuxDynLib = struct {...@@ -149,7 +147,7 @@ pub const LinuxDynLib = struct {
149pub const ElfLib = struct {147pub const ElfLib = struct {
150 strings: [*]u8,148 strings: [*]u8,
151 syms: [*]elf.Sym,149 syms: [*]elf.Sym,
152 hashtab: [*]linux.Elf_Symndx,150 hashtab: [*]os.Elf_Symndx,
153 versym: ?[*]u16,151 versym: ?[*]u16,
154 verdef: ?*elf.Verdef,152 verdef: ?*elf.Verdef,
155 base: usize,153 base: usize,
...@@ -184,7 +182,7 @@ pub const ElfLib = struct {...@@ -184,7 +182,7 @@ pub const ElfLib = struct {
184182
185 var maybe_strings: ?[*]u8 = null;183 var maybe_strings: ?[*]u8 = null;
186 var maybe_syms: ?[*]elf.Sym = null;184 var maybe_syms: ?[*]elf.Sym = null;
187 var maybe_hashtab: ?[*]linux.Elf_Symndx = null;185 var maybe_hashtab: ?[*]os.Elf_Symndx = null;
188 var maybe_versym: ?[*]u16 = null;186 var maybe_versym: ?[*]u16 = null;
189 var maybe_verdef: ?*elf.Verdef = null;187 var maybe_verdef: ?*elf.Verdef = null;
190188
...@@ -195,7 +193,7 @@ pub const ElfLib = struct {...@@ -195,7 +193,7 @@ pub const ElfLib = struct {
195 switch (dynv[i]) {193 switch (dynv[i]) {
196 elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),194 elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
197 elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),195 elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
198 elf.DT_HASH => maybe_hashtab = @intToPtr([*]linux.Elf_Symndx, p),196 elf.DT_HASH => maybe_hashtab = @intToPtr([*]os.Elf_Symndx, p),
199 elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),197 elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
200 elf.DT_VERDEF => maybe_verdef = @intToPtr(*elf.Verdef, p),198 elf.DT_VERDEF => maybe_verdef = @intToPtr(*elf.Verdef, p),
201 else => {},199 else => {},
...@@ -283,8 +281,8 @@ pub const WindowsDynLib = struct {...@@ -283,8 +281,8 @@ pub const WindowsDynLib = struct {
283281
284test "dynamic_library" {282test "dynamic_library" {
285 const libname = switch (builtin.os) {283 const libname = switch (builtin.os) {
286 Os.linux => "invalid_so.so",284 .linux => "invalid_so.so",
287 Os.windows => "invalid_dll.dll",285 .windows => "invalid_dll.dll",
288 else => return,286 else => return,
289 };287 };
290288
std/elf.zig+3-2
...@@ -6,6 +6,7 @@ const math = std.math;...@@ -6,6 +6,7 @@ const math = std.math;
6const mem = std.mem;6const mem = std.mem;
7const debug = std.debug;7const debug = std.debug;
8const InStream = std.stream.InStream;8const InStream = std.stream.InStream;
9const File = std.fs.File;
910
10pub const AT_NULL = 0;11pub const AT_NULL = 0;
11pub const AT_IGNORE = 1;12pub const AT_IGNORE = 1;
...@@ -367,7 +368,7 @@ pub const Elf = struct {...@@ -367,7 +368,7 @@ pub const Elf = struct {
367 string_section: *SectionHeader,368 string_section: *SectionHeader,
368 section_headers: []SectionHeader,369 section_headers: []SectionHeader,
369 allocator: *mem.Allocator,370 allocator: *mem.Allocator,
370 prealloc_file: os.File,371 prealloc_file: File,
371372
372 /// Call close when done.373 /// Call close when done.
373 pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {374 pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {
...@@ -375,7 +376,7 @@ pub const Elf = struct {...@@ -375,7 +376,7 @@ pub const Elf = struct {
375 }376 }
376377
377 /// Call close when done.378 /// Call close when done.
378 pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void {379 pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: File) !void {
379 @compileError("TODO implement");380 @compileError("TODO implement");
380 }381 }
381382
std/event/fs.zig+22-21
...@@ -9,6 +9,7 @@ const posix = os.posix;...@@ -9,6 +9,7 @@ const posix = os.posix;
9const windows = os.windows;9const windows = os.windows;
10const Loop = event.Loop;10const Loop = event.Loop;
11const fd_t = posix.fd_t;11const fd_t = posix.fd_t;
12const File = std.fs.File;
1213
13pub const RequestNode = std.atomic.Queue(Request).Node;14pub const RequestNode = std.atomic.Queue(Request).Node;
1415
...@@ -52,20 +53,20 @@ pub const Request = struct {...@@ -52,20 +53,20 @@ pub const Request = struct {
52 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/26553 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
53 path: []const u8,54 path: []const u8,
54 flags: u32,55 flags: u32,
55 mode: os.File.Mode,56 mode: File.Mode,
56 result: Error!fd_t,57 result: Error!fd_t,
5758
58 pub const Error = os.File.OpenError;59 pub const Error = File.OpenError;
59 };60 };
6061
61 pub const WriteFile = struct {62 pub const WriteFile = struct {
62 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/26563 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
63 path: []const u8,64 path: []const u8,
64 contents: []const u8,65 contents: []const u8,
65 mode: os.File.Mode,66 mode: File.Mode,
66 result: Error!void,67 result: Error!void,
6768
68 pub const Error = os.File.OpenError || os.File.WriteError;69 pub const Error = File.OpenError || File.WriteError;
69 };70 };
7071
71 pub const Close = struct {72 pub const Close = struct {
...@@ -74,7 +75,7 @@ pub const Request = struct {...@@ -74,7 +75,7 @@ pub const Request = struct {
74 };75 };
75};76};
7677
77pub const PWriteVError = error{OutOfMemory} || os.File.WriteError;78pub const PWriteVError = error{OutOfMemory} || File.WriteError;
7879
79/// data - just the inner references - must live until pwritev promise completes.80/// data - just the inner references - must live until pwritev promise completes.
80pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: usize) PWriteVError!void {81pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: usize) PWriteVError!void {
...@@ -209,7 +210,7 @@ pub async fn pwritevPosix(...@@ -209,7 +210,7 @@ pub async fn pwritevPosix(
209 return req_node.data.msg.PWriteV.result;210 return req_node.data.msg.PWriteV.result;
210}211}
211212
212pub const PReadVError = error{OutOfMemory} || os.File.ReadError;213pub const PReadVError = error{OutOfMemory} || File.ReadError;
213214
214/// data - just the inner references - must live until preadv promise completes.215/// data - just the inner references - must live until preadv promise completes.
215pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PReadVError!usize {216pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PReadVError!usize {
...@@ -361,8 +362,8 @@ pub async fn openPosix(...@@ -361,8 +362,8 @@ pub async fn openPosix(
361 loop: *Loop,362 loop: *Loop,
362 path: []const u8,363 path: []const u8,
363 flags: u32,364 flags: u32,
364 mode: os.File.Mode,365 mode: File.Mode,
365) os.File.OpenError!fd_t {366) File.OpenError!fd_t {
366 // workaround for https://github.com/ziglang/zig/issues/1194367 // workaround for https://github.com/ziglang/zig/issues/1194
367 suspend {368 suspend {
368 resume @handle();369 resume @handle();
...@@ -401,11 +402,11 @@ pub async fn openPosix(...@@ -401,11 +402,11 @@ pub async fn openPosix(
401 return req_node.data.msg.Open.result;402 return req_node.data.msg.Open.result;
402}403}
403404
404pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {405pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t {
405 switch (builtin.os) {406 switch (builtin.os) {
406 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {407 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
407 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;408 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
408 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);409 return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
409 },410 },
410411
411 builtin.Os.windows => return os.windowsOpen(412 builtin.Os.windows => return os.windowsOpen(
...@@ -422,12 +423,12 @@ pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {...@@ -422,12 +423,12 @@ pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
422423
423/// Creates if does not exist. Truncates the file if it exists.424/// Creates if does not exist. Truncates the file if it exists.
424/// Uses the default mode.425/// Uses the default mode.
425pub async fn openWrite(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {426pub async fn openWrite(loop: *Loop, path: []const u8) File.OpenError!fd_t {
426 return await (async openWriteMode(loop, path, os.File.default_mode) catch unreachable);427 return await (async openWriteMode(loop, path, File.default_mode) catch unreachable);
427}428}
428429
429/// Creates if does not exist. Truncates the file if it exists.430/// Creates if does not exist. Truncates the file if it exists.
430pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os.File.OpenError!fd_t {431pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File.OpenError!fd_t {
431 switch (builtin.os) {432 switch (builtin.os) {
432 builtin.Os.macosx,433 builtin.Os.macosx,
433 builtin.Os.linux,434 builtin.Os.linux,
...@@ -435,7 +436,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os...@@ -435,7 +436,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
435 builtin.Os.netbsd,436 builtin.Os.netbsd,
436 => {437 => {
437 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;438 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
438 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);439 return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable);
439 },440 },
440 builtin.Os.windows => return os.windowsOpen(441 builtin.Os.windows => return os.windowsOpen(
441 path,442 path,
...@@ -452,8 +453,8 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os...@@ -452,8 +453,8 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
452pub async fn openReadWrite(453pub async fn openReadWrite(
453 loop: *Loop,454 loop: *Loop,
454 path: []const u8,455 path: []const u8,
455 mode: os.File.Mode,456 mode: File.Mode,
456) os.File.OpenError!fd_t {457) File.OpenError!fd_t {
457 switch (builtin.os) {458 switch (builtin.os) {
458 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {459 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
459 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;460 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
...@@ -605,11 +606,11 @@ pub const CloseOperation = struct {...@@ -605,11 +606,11 @@ pub const CloseOperation = struct {
605/// contents must remain alive until writeFile completes.606/// contents must remain alive until writeFile completes.
606/// TODO make this atomic or provide writeFileAtomic and rename this one to writeFileTruncate607/// TODO make this atomic or provide writeFileAtomic and rename this one to writeFileTruncate
607pub async fn writeFile(loop: *Loop, path: []const u8, contents: []const u8) !void {608pub async fn writeFile(loop: *Loop, path: []const u8, contents: []const u8) !void {
608 return await (async writeFileMode(loop, path, contents, os.File.default_mode) catch unreachable);609 return await (async writeFileMode(loop, path, contents, File.default_mode) catch unreachable);
609}610}
610611
611/// contents must remain alive until writeFile completes.612/// contents must remain alive until writeFile completes.
612pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, mode: os.File.Mode) !void {613pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, mode: File.Mode) !void {
613 switch (builtin.os) {614 switch (builtin.os) {
614 builtin.Os.linux,615 builtin.Os.linux,
615 builtin.Os.macosx,616 builtin.Os.macosx,
...@@ -634,7 +635,7 @@ async fn writeFileWindows(loop: *Loop, path: []const u8, contents: []const u8) !...@@ -634,7 +635,7 @@ async fn writeFileWindows(loop: *Loop, path: []const u8, contents: []const u8) !
634 try await (async pwriteWindows(loop, handle, contents, 0) catch unreachable);635 try await (async pwriteWindows(loop, handle, contents, 0) catch unreachable);
635}636}
636637
637async fn writeFileModeThread(loop: *Loop, path: []const u8, contents: []const u8, mode: os.File.Mode) !void {638async fn writeFileModeThread(loop: *Loop, path: []const u8, contents: []const u8, mode: File.Mode) !void {
638 // workaround for https://github.com/ziglang/zig/issues/1194639 // workaround for https://github.com/ziglang/zig/issues/1194
639 suspend {640 suspend {
640 resume @handle();641 resume @handle();
...@@ -1363,7 +1364,7 @@ async fn testFsWatch(loop: *Loop) !void {...@@ -1363,7 +1364,7 @@ async fn testFsWatch(loop: *Loop) !void {
1363 defer if (!ev_consumed) cancel ev;1364 defer if (!ev_consumed) cancel ev;
13641365
1365 // overwrite line 21366 // overwrite line 2
1366 const fd = try await try async openReadWrite(loop, file_path, os.File.default_mode);1367 const fd = try await try async openReadWrite(loop, file_path, File.default_mode);
1367 {1368 {
1368 defer os.close(fd);1369 defer os.close(fd);
13691370
...@@ -1390,7 +1391,7 @@ pub const OutStream = struct {...@@ -1390,7 +1391,7 @@ pub const OutStream = struct {
1390 loop: *Loop,1391 loop: *Loop,
1391 offset: usize,1392 offset: usize,
13921393
1393 pub const Error = os.File.WriteError;1394 pub const Error = File.WriteError;
1394 pub const Stream = event.io.OutStream(Error);1395 pub const Stream = event.io.OutStream(Error);
13951396
1396 pub fn init(loop: *Loop, fd: fd_t, offset: usize) OutStream {1397 pub fn init(loop: *Loop, fd: fd_t, offset: usize) OutStream {
std/event/group.zig+1-1
...@@ -155,7 +155,7 @@ async fn testGroup(loop: *Loop) void {...@@ -155,7 +155,7 @@ async fn testGroup(loop: *Loop) void {
155}155}
156156
157async fn sleepALittle(count: *usize) void {157async fn sleepALittle(count: *usize) void {
158 std.os.time.sleep(1 * std.os.time.millisecond);158 std.time.sleep(1 * std.time.millisecond);
159 _ = @atomicRmw(usize, count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);159 _ = @atomicRmw(usize, count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
160}160}
161161
std/event/loop.zig+2-2
...@@ -789,13 +789,13 @@ pub const Loop = struct {...@@ -789,13 +789,13 @@ pub const Loop = struct {
789 msg.result = os.posix_preadv(msg.fd, msg.iov.ptr, msg.iov.len, msg.offset);789 msg.result = os.posix_preadv(msg.fd, msg.iov.ptr, msg.iov.len, msg.offset);
790 },790 },
791 @TagType(fs.Request.Msg).Open => |*msg| {791 @TagType(fs.Request.Msg).Open => |*msg| {
792 msg.result = os.posixOpenC(msg.path.ptr, msg.flags, msg.mode);792 msg.result = os.openC(msg.path.ptr, msg.flags, msg.mode);
793 },793 },
794 @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd),794 @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd),
795 @TagType(fs.Request.Msg).WriteFile => |*msg| blk: {795 @TagType(fs.Request.Msg).WriteFile => |*msg| blk: {
796 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT |796 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT |
797 posix.O_CLOEXEC | posix.O_TRUNC;797 posix.O_CLOEXEC | posix.O_TRUNC;
798 const fd = os.posixOpenC(msg.path.ptr, flags, msg.mode) catch |err| {798 const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| {
799 msg.result = err;799 msg.result = err;
800 break :blk;800 break :blk;
801 };801 };
std/event/net.zig+8-7
...@@ -6,11 +6,12 @@ const mem = std.mem;...@@ -6,11 +6,12 @@ const mem = std.mem;
6const os = std.os;6const os = std.os;
7const posix = os.posix;7const posix = os.posix;
8const Loop = std.event.Loop;8const Loop = std.event.Loop;
9const File = std.fs.File;
910
10const fd_t = posix.fd_t;11const fd_t = posix.fd_t;
1112
12pub const Server = struct {13pub const Server = struct {
13 handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, os.File) void,14 handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,
1415
15 loop: *Loop,16 loop: *Loop,
16 sockfd: ?i32,17 sockfd: ?i32,
...@@ -42,7 +43,7 @@ pub const Server = struct {...@@ -42,7 +43,7 @@ pub const Server = struct {
42 pub fn listen(43 pub fn listen(
43 self: *Server,44 self: *Server,
44 address: *const std.net.Address,45 address: *const std.net.Address,
45 handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, os.File) void,46 handleRequestFn: async<*mem.Allocator> fn (*Server, *const std.net.Address, File) void,
46 ) !void {47 ) !void {
47 self.handleRequestFn = handleRequestFn;48 self.handleRequestFn = handleRequestFn;
4849
...@@ -83,7 +84,7 @@ pub const Server = struct {...@@ -83,7 +84,7 @@ pub const Server = struct {
83 suspend; // we will get resumed by epoll_wait in the event loop84 suspend; // we will get resumed by epoll_wait in the event loop
84 continue;85 continue;
85 }86 }
86 var socket = os.File.openHandle(accepted_fd);87 var socket = File.openHandle(accepted_fd);
87 _ = async<self.loop.allocator> self.handleRequestFn(self, &accepted_addr, socket) catch |err| switch (err) {88 _ = async<self.loop.allocator> self.handleRequestFn(self, &accepted_addr, socket) catch |err| switch (err) {
88 error.OutOfMemory => {89 error.OutOfMemory => {
89 socket.close();90 socket.close();
...@@ -250,7 +251,7 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {...@@ -250,7 +251,7 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
250 return await (async readvPosix(loop, fd, iovecs.ptr, data.len) catch unreachable);251 return await (async readvPosix(loop, fd, iovecs.ptr, data.len) catch unreachable);
251}252}
252253
253pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {254pub async fn connect(loop: *Loop, _address: *const std.net.Address) !File {
254 var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592255 var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592
255256
256 const sockfd = try os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);257 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 {...@@ -260,7 +261,7 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
260 try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);261 try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
261 try os.posixGetSockOptConnectError(sockfd);262 try os.posixGetSockOptConnectError(sockfd);
262263
263 return os.File.openHandle(sockfd);264 return File.openHandle(sockfd);
264}265}
265266
266test "listen on a port, send bytes, receive bytes" {267test "listen on a port, send bytes, receive bytes" {
...@@ -276,7 +277,7 @@ test "listen on a port, send bytes, receive bytes" {...@@ -276,7 +277,7 @@ test "listen on a port, send bytes, receive bytes" {
276 tcp_server: Server,277 tcp_server: Server,
277278
278 const Self = @This();279 const Self = @This();
279 async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: os.File) void {280 async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: File) void {
280 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);281 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
281 var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592282 var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
282 defer socket.close();283 defer socket.close();
...@@ -289,7 +290,7 @@ test "listen on a port, send bytes, receive bytes" {...@@ -289,7 +290,7 @@ test "listen on a port, send bytes, receive bytes" {
289 cancel @handle();290 cancel @handle();
290 }291 }
291 }292 }
292 async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: os.File) !void {293 async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: File) !void {
293 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/1592294 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/1592
294 var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592295 var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
295296
std/event/rwlock.zig+2-2
...@@ -271,7 +271,7 @@ async fn writeRunner(lock: *RwLock) void {...@@ -271,7 +271,7 @@ async fn writeRunner(lock: *RwLock) void {
271271
272 var i: usize = 0;272 var i: usize = 0;
273 while (i < shared_test_data.len) : (i += 1) {273 while (i < shared_test_data.len) : (i += 1) {
274 std.os.time.sleep(100 * std.os.time.microsecond);274 std.time.sleep(100 * std.time.microsecond);
275 const lock_promise = async lock.acquireWrite() catch @panic("out of memory");275 const lock_promise = async lock.acquireWrite() catch @panic("out of memory");
276 const handle = await lock_promise;276 const handle = await lock_promise;
277 defer handle.release();277 defer handle.release();
...@@ -286,7 +286,7 @@ async fn writeRunner(lock: *RwLock) void {...@@ -286,7 +286,7 @@ async fn writeRunner(lock: *RwLock) void {
286286
287async fn readRunner(lock: *RwLock) void {287async fn readRunner(lock: *RwLock) void {
288 suspend; // resumed by onNextTick288 suspend; // resumed by onNextTick
289 std.os.time.sleep(1);289 std.time.sleep(1);
290290
291 var i: usize = 0;291 var i: usize = 0;
292 while (i < shared_test_data.len) : (i += 1) {292 while (i < shared_test_data.len) : (i += 1) {
std/fs.zig+175-192
...@@ -11,6 +11,7 @@ pub const deleteFile = os.unlink;...@@ -11,6 +11,7 @@ pub const deleteFile = os.unlink;
11pub const deleteFileC = os.unlinkC;11pub const deleteFileC = os.unlinkC;
12pub const rename = os.rename;12pub const rename = os.rename;
13pub const renameC = os.renameC;13pub const renameC = os.renameC;
14pub const renameW = os.renameW;
14pub const changeCurDir = os.chdir;15pub const changeCurDir = os.chdir;
15pub const changeCurDirC = os.chdirC;16pub const changeCurDirC = os.chdirC;
16pub const realpath = os.realpath;17pub const realpath = os.realpath;
...@@ -25,24 +26,24 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE...@@ -25,24 +26,24 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE
25/// fit into a UTF-8 encoded array of this length.26/// fit into a UTF-8 encoded array of this length.
26/// path being too long if it is this 0long27/// path being too long if it is this 0long
27pub const MAX_PATH_BYTES = switch (builtin.os) {28pub const MAX_PATH_BYTES = switch (builtin.os) {
28 .linux, .macosx, .ios, .freebsd, .netbsd => posix.PATH_MAX,29 .linux, .macosx, .ios, .freebsd, .netbsd => os.PATH_MAX,
29 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.30 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
30 // If it would require 4 UTF-8 bytes, then there would be a surrogate31 // If it would require 4 UTF-8 bytes, then there would be a surrogate
31 // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.32 // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
32 // +1 for the null byte at the end, which can be encoded in 1 byte.33 // +1 for the null byte at the end, which can be encoded in 1 byte.
33 .windows => posix.PATH_MAX_WIDE * 3 + 1,34 .windows => os.windows.PATH_MAX_WIDE * 3 + 1,
34 else => @compileError("Unsupported OS"),35 else => @compileError("Unsupported OS"),
35};36};
3637
37/// The result is a slice of `out_buffer`, from index `0`.38/// The result is a slice of `out_buffer`, from index `0`.
38pub fn getCwd(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {39pub fn getCwd(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
39 return posix.getcwd(out_buffer);40 return os.getcwd(out_buffer);
40}41}
4142
42/// Caller must free the returned memory.43/// Caller must free the returned memory.
43pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {44pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
44 var buf: [MAX_PATH_BYTES]u8 = undefined;45 var buf: [MAX_PATH_BYTES]u8 = undefined;
45 return mem.dupe(allocator, u8, try posix.getcwd(&buf));46 return mem.dupe(allocator, u8, try os.getcwd(&buf));
46}47}
4748
48test "getCwdAlloc" {49test "getCwdAlloc" {
...@@ -90,7 +91,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:...@@ -90,7 +91,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
90/// in the same directory as dest_path.91/// in the same directory as dest_path.
91/// Destination file will have the same mode as the source file.92/// Destination file will have the same mode as the source file.
92pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {93pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
93 var in_file = try os.File.openRead(source_path);94 var in_file = try File.openRead(source_path);
94 defer in_file.close();95 defer in_file.close();
9596
96 const mode = try in_file.mode();97 const mode = try in_file.mode();
...@@ -113,7 +114,7 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {...@@ -113,7 +114,7 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
113/// merged and readily available,114/// merged and readily available,
114/// there is a possibility of power loss or application termination leaving temporary files present115/// there is a possibility of power loss or application termination leaving temporary files present
115pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {116pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.Mode) !void {
116 var in_file = try os.File.openRead(source_path);117 var in_file = try File.openRead(source_path);
117 defer in_file.close();118 defer in_file.close();
118119
119 var atomic_file = try AtomicFile.init(dest_path, mode);120 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...@@ -130,12 +131,12 @@ pub fn copyFileMode(source_path: []const u8, dest_path: []const u8, mode: File.M
130}131}
131132
132pub const AtomicFile = struct {133pub const AtomicFile = struct {
133 file: os.File,134 file: File,
134 tmp_path_buf: [MAX_PATH_BYTES]u8,135 tmp_path_buf: [MAX_PATH_BYTES]u8,
135 dest_path: []const u8,136 dest_path: []const u8,
136 finished: bool,137 finished: bool,
137138
138 const InitError = os.File.OpenError;139 const InitError = File.OpenError;
139140
140 /// dest_path must remain valid for the lifetime of AtomicFile141 /// dest_path must remain valid for the lifetime of AtomicFile
141 /// call finish to atomically replace dest_path with contents142 /// call finish to atomically replace dest_path with contents
...@@ -161,7 +162,7 @@ pub const AtomicFile = struct {...@@ -161,7 +162,7 @@ pub const AtomicFile = struct {
161 try getRandomBytes(rand_buf[0..]);162 try getRandomBytes(rand_buf[0..]);
162 b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);163 b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);
163164
164 const file = os.File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {165 const file = File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
165 error.PathAlreadyExists => continue,166 error.PathAlreadyExists => continue,
166 // TODO zig should figure out that this error set does not include PathAlreadyExists since167 // TODO zig should figure out that this error set does not include PathAlreadyExists since
167 // it is handled in the above switch168 // it is handled in the above switch
...@@ -190,16 +191,13 @@ pub const AtomicFile = struct {...@@ -190,16 +191,13 @@ pub const AtomicFile = struct {
190 assert(!self.finished);191 assert(!self.finished);
191 self.file.close();192 self.file.close();
192 self.finished = true;193 self.finished = true;
193 if (is_posix) {194 if (os.windows.is_the_target) {
194 const dest_path_c = try toPosixPath(self.dest_path);195 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
195 return renameC(&self.tmp_path_buf, &dest_path_c);196 const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
196 } else if (is_windows) {197 return os.renameW(&tmp_path_w, &dest_path_w);
197 const dest_path_w = try posix.sliceToPrefixedFileW(self.dest_path);
198 const tmp_path_w = try posix.cStrToPrefixedFileW(&self.tmp_path_buf);
199 return renameW(&tmp_path_w, &dest_path_w);
200 } else {
201 @compileError("Unsupported OS");
202 }198 }
199 const dest_path_c = try os.toPosixPath(self.dest_path);
200 return os.renameC(&self.tmp_path_buf, &dest_path_c);
203 }201 }
204};202};
205203
...@@ -207,17 +205,17 @@ const default_new_dir_mode = 0o755;...@@ -207,17 +205,17 @@ const default_new_dir_mode = 0o755;
207205
208/// Create a new directory.206/// Create a new directory.
209pub fn makeDir(dir_path: []const u8) !void {207pub fn makeDir(dir_path: []const u8) !void {
210 return posix.mkdir(dir_path, default_new_dir_mode);208 return os.mkdir(dir_path, default_new_dir_mode);
211}209}
212210
213/// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.211/// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.
214pub fn makeDirC(dir_path: [*]const u8) !void {212pub fn makeDirC(dir_path: [*]const u8) !void {
215 return posix.mkdirC(dir_path, default_new_dir_mode);213 return os.mkdirC(dir_path, default_new_dir_mode);
216}214}
217215
218/// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.216/// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.
219pub fn makeDirW(dir_path: [*]const u16) !void {217pub fn makeDirW(dir_path: [*]const u16) !void {
220 return posix.mkdirW(dir_path, default_new_dir_mode);218 return os.mkdirW(dir_path, default_new_dir_mode);
221}219}
222220
223/// Calls makeDir recursively to make an entire path. Returns success if the path221/// 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 {...@@ -260,17 +258,17 @@ pub fn makePath(allocator: *Allocator, full_path: []const u8) !void {
260/// Returns `error.DirNotEmpty` if the directory is not empty.258/// Returns `error.DirNotEmpty` if the directory is not empty.
261/// To delete a directory recursively, see `deleteTree`.259/// To delete a directory recursively, see `deleteTree`.
262pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {260pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
263 return posix.rmdir(dir_path);261 return os.rmdir(dir_path);
264}262}
265263
266/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.264/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.
267pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {265pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
268 return posix.rmdirC(dir_path);266 return os.rmdirC(dir_path);
269}267}
270268
271/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.269/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.
272pub fn deleteDirW(dir_path: [*]const u16) DeleteDirError!void {270pub fn deleteDirW(dir_path: [*]const u16) DeleteDirError!void {
273 return posix.rmdirW(dir_path);271 return os.rmdirW(dir_path);
274}272}
275273
276/// Whether ::full_path describes a symlink, file, or directory, this function274/// Whether ::full_path describes a symlink, file, or directory, this function
...@@ -383,22 +381,22 @@ pub const Dir = struct {...@@ -383,22 +381,22 @@ pub const Dir = struct {
383 allocator: *Allocator,381 allocator: *Allocator,
384382
385 pub const Handle = switch (builtin.os) {383 pub const Handle = switch (builtin.os) {
386 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => struct {384 .macosx, .ios, .freebsd, .netbsd => struct {
387 fd: i32,385 fd: i32,
388 seek: i64,386 seek: i64,
389 buf: []u8,387 buf: []u8,
390 index: usize,388 index: usize,
391 end_index: usize,389 end_index: usize,
392 },390 },
393 Os.linux => struct {391 .linux => struct {
394 fd: i32,392 fd: i32,
395 buf: []u8,393 buf: []u8,
396 index: usize,394 index: usize,
397 end_index: usize,395 end_index: usize,
398 },396 },
399 Os.windows => struct {397 .windows => struct {
400 handle: windows.HANDLE,398 handle: os.windows.HANDLE,
401 find_file_data: windows.WIN32_FIND_DATAW,399 find_file_data: os.windows.WIN32_FIND_DATAW,
402 first: bool,400 first: bool,
403 name_data: [256]u8,401 name_data: [256]u8,
404 },402 },
...@@ -449,9 +447,9 @@ pub const Dir = struct {...@@ -449,9 +447,9 @@ pub const Dir = struct {
449 return Dir{447 return Dir{
450 .allocator = allocator,448 .allocator = allocator,
451 .handle = switch (builtin.os) {449 .handle = switch (builtin.os) {
452 Os.windows => blk: {450 .windows => blk: {
453 var find_file_data: windows.WIN32_FIND_DATAW = undefined;451 var find_file_data: os.windows.WIN32_FIND_DATAW = undefined;
454 const handle = try windows_util.windowsFindFirstFile(dir_path, &find_file_data);452 const handle = try os.windows.FindFirstFile(dir_path, &find_file_data);
455 break :blk Handle{453 break :blk Handle{
456 .handle = handle,454 .handle = handle,
457 .find_file_data = find_file_data, // TODO guaranteed copy elision455 .find_file_data = find_file_data, // TODO guaranteed copy elision
...@@ -459,23 +457,15 @@ pub const Dir = struct {...@@ -459,23 +457,15 @@ pub const Dir = struct {
459 .name_data = undefined,457 .name_data = undefined,
460 };458 };
461 },459 },
462 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => Handle{460 .macosx, .ios, .freebsd, .netbsd => Handle{
463 .fd = try posixOpen(461 .fd = try os.open(dir_path, os.O_RDONLY | os.O_NONBLOCK | os.O_DIRECTORY | os.O_CLOEXEC, 0),
464 dir_path,
465 posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
466 0,
467 ),
468 .seek = 0,462 .seek = 0,
469 .index = 0,463 .index = 0,
470 .end_index = 0,464 .end_index = 0,
471 .buf = []u8{},465 .buf = []u8{},
472 },466 },
473 Os.linux => Handle{467 .linux => Handle{
474 .fd = try posixOpen(468 .fd = try os.open(dir_path, os.O_RDONLY | os.O_DIRECTORY | os.O_CLOEXEC, 0),
475 dir_path,
476 posix.O_RDONLY | posix.O_DIRECTORY | posix.O_CLOEXEC,
477 0,
478 ),
479 .index = 0,469 .index = 0,
480 .end_index = 0,470 .end_index = 0,
481 .buf = []u8{},471 .buf = []u8{},
...@@ -486,27 +476,22 @@ pub const Dir = struct {...@@ -486,27 +476,22 @@ pub const Dir = struct {
486 }476 }
487477
488 pub fn close(self: *Dir) void {478 pub fn close(self: *Dir) void {
489 switch (builtin.os) {479 if (os.windows.is_the_target) {
490 Os.windows => {480 return os.windows.FindClose(self.handle.handle);
491 _ = windows.FindClose(self.handle.handle);
492 },
493 Os.macosx, Os.ios, Os.linux, Os.freebsd, Os.netbsd => {
494 self.allocator.free(self.handle.buf);
495 os.close(self.handle.fd);
496 },
497 else => @compileError("unimplemented"),
498 }481 }
482 self.allocator.free(self.handle.buf);
483 os.close(self.handle.fd);
499 }484 }
500485
501 /// Memory such as file names referenced in this returned entry becomes invalid486 /// Memory such as file names referenced in this returned entry becomes invalid
502 /// with subsequent calls to next, as well as when this `Dir` is deinitialized.487 /// with subsequent calls to next, as well as when this `Dir` is deinitialized.
503 pub fn next(self: *Dir) !?Entry {488 pub fn next(self: *Dir) !?Entry {
504 switch (builtin.os) {489 switch (builtin.os) {
505 Os.linux => return self.nextLinux(),490 .linux => return self.nextLinux(),
506 Os.macosx, Os.ios => return self.nextDarwin(),491 .macosx, .ios => return self.nextDarwin(),
507 Os.windows => return self.nextWindows(),492 .windows => return self.nextWindows(),
508 Os.freebsd => return self.nextFreebsd(),493 .freebsd => return self.nextBsd(),
509 Os.netbsd => return self.nextFreebsd(),494 .netbsd => return self.nextBsd(),
510 else => @compileError("unimplemented"),495 else => @compileError("unimplemented"),
511 }496 }
512 }497 }
...@@ -519,18 +504,23 @@ pub const Dir = struct {...@@ -519,18 +504,23 @@ pub const Dir = struct {
519 }504 }
520505
521 while (true) {506 while (true) {
522 const result = system.__getdirentries64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);507 const rc = os.system.__getdirentries64(
523 if (result == 0) return null;508 self.handle.fd,
524 if (result < 0) {509 self.handle.buf.ptr,
525 switch (system.getErrno(result)) {510 self.handle.buf.len,
526 posix.EBADF => unreachable,511 &self.handle.seek,
527 posix.EFAULT => unreachable,512 );
528 posix.ENOTDIR => unreachable,513 if (rc == 0) return null;
529 posix.EINVAL => {514 if (rc < 0) {
515 switch (os.errno(rc)) {
516 os.EBADF => unreachable,
517 os.EFAULT => unreachable,
518 os.ENOTDIR => unreachable,
519 os.EINVAL => {
530 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);520 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
531 continue;521 continue;
532 },522 },
533 else => return unexpectedErrorPosix(err),523 else => |err| return os.unexpectedErrno(err),
534 }524 }
535 }525 }
536 self.handle.index = 0;526 self.handle.index = 0;
...@@ -538,7 +528,7 @@ pub const Dir = struct {...@@ -538,7 +528,7 @@ pub const Dir = struct {
538 break;528 break;
539 }529 }
540 }530 }
541 const darwin_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);531 const darwin_entry = @ptrCast(*align(1) os.dirent, &self.handle.buf[self.handle.index]);
542 const next_index = self.handle.index + darwin_entry.d_reclen;532 const next_index = self.handle.index + darwin_entry.d_reclen;
543 self.handle.index = next_index;533 self.handle.index = next_index;
544534
...@@ -549,14 +539,14 @@ pub const Dir = struct {...@@ -549,14 +539,14 @@ pub const Dir = struct {
549 }539 }
550540
551 const entry_kind = switch (darwin_entry.d_type) {541 const entry_kind = switch (darwin_entry.d_type) {
552 posix.DT_BLK => Entry.Kind.BlockDevice,542 os.DT_BLK => Entry.Kind.BlockDevice,
553 posix.DT_CHR => Entry.Kind.CharacterDevice,543 os.DT_CHR => Entry.Kind.CharacterDevice,
554 posix.DT_DIR => Entry.Kind.Directory,544 os.DT_DIR => Entry.Kind.Directory,
555 posix.DT_FIFO => Entry.Kind.NamedPipe,545 os.DT_FIFO => Entry.Kind.NamedPipe,
556 posix.DT_LNK => Entry.Kind.SymLink,546 os.DT_LNK => Entry.Kind.SymLink,
557 posix.DT_REG => Entry.Kind.File,547 os.DT_REG => Entry.Kind.File,
558 posix.DT_SOCK => Entry.Kind.UnixDomainSocket,548 os.DT_SOCK => Entry.Kind.UnixDomainSocket,
559 posix.DT_WHT => Entry.Kind.Whiteout,549 os.DT_WHT => Entry.Kind.Whiteout,
560 else => Entry.Kind.Unknown,550 else => Entry.Kind.Unknown,
561 };551 };
562 return Entry{552 return Entry{
...@@ -571,7 +561,7 @@ pub const Dir = struct {...@@ -571,7 +561,7 @@ pub const Dir = struct {
571 if (self.handle.first) {561 if (self.handle.first) {
572 self.handle.first = false;562 self.handle.first = false;
573 } else {563 } else {
574 if (!try posix.FindNextFile(self.handle.handle, &self.handle.find_file_data))564 if (!try os.windows.FindNextFile(self.handle.handle, &self.handle.find_file_data))
575 return null;565 return null;
576 }566 }
577 const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);567 const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);
...@@ -582,9 +572,9 @@ pub const Dir = struct {...@@ -582,9 +572,9 @@ pub const Dir = struct {
582 const name_utf8 = self.handle.name_data[0..name_utf8_len];572 const name_utf8 = self.handle.name_data[0..name_utf8_len];
583 const kind = blk: {573 const kind = blk: {
584 const attrs = self.handle.find_file_data.dwFileAttributes;574 const attrs = self.handle.find_file_data.dwFileAttributes;
585 if (attrs & windows.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;575 if (attrs & os.windows.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;
586 if (attrs & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;576 if (attrs & os.windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;
587 if (attrs & windows.FILE_ATTRIBUTE_NORMAL != 0) break :blk Entry.Kind.File;577 if (attrs & os.windows.FILE_ATTRIBUTE_NORMAL != 0) break :blk Entry.Kind.File;
588 break :blk Entry.Kind.Unknown;578 break :blk Entry.Kind.Unknown;
589 };579 };
590 return Entry{580 return Entry{
...@@ -602,25 +592,25 @@ pub const Dir = struct {...@@ -602,25 +592,25 @@ pub const Dir = struct {
602 }592 }
603593
604 while (true) {594 while (true) {
605 const result = posix.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);595 const rc = os.system.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
606 const err = posix.getErrno(result);596 switch (os.errno(rc)) {
607 if (err > 0) {597 0 => {},
608 switch (err) {598 os.EBADF => unreachable,
609 posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,599 os.EFAULT => unreachable,
610 posix.EINVAL => {600 os.ENOTDIR => unreachable,
611 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);601 os.EINVAL => {
612 continue;602 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
613 },603 continue;
614 else => return unexpectedErrorPosix(err),604 },
615 }605 else => |err| return os.unexpectedErrno(err),
616 }606 }
617 if (result == 0) return null;607 if (rc == 0) return null;
618 self.handle.index = 0;608 self.handle.index = 0;
619 self.handle.end_index = result;609 self.handle.end_index = rc;
620 break;610 break;
621 }611 }
622 }612 }
623 const linux_entry = @ptrCast(*align(1) posix.dirent64, &self.handle.buf[self.handle.index]);613 const linux_entry = @ptrCast(*align(1) os.dirent64, &self.handle.buf[self.handle.index]);
624 const next_index = self.handle.index + linux_entry.d_reclen;614 const next_index = self.handle.index + linux_entry.d_reclen;
625 self.handle.index = next_index;615 self.handle.index = next_index;
626616
...@@ -632,13 +622,13 @@ pub const Dir = struct {...@@ -632,13 +622,13 @@ pub const Dir = struct {
632 }622 }
633623
634 const entry_kind = switch (linux_entry.d_type) {624 const entry_kind = switch (linux_entry.d_type) {
635 posix.DT_BLK => Entry.Kind.BlockDevice,625 os.DT_BLK => Entry.Kind.BlockDevice,
636 posix.DT_CHR => Entry.Kind.CharacterDevice,626 os.DT_CHR => Entry.Kind.CharacterDevice,
637 posix.DT_DIR => Entry.Kind.Directory,627 os.DT_DIR => Entry.Kind.Directory,
638 posix.DT_FIFO => Entry.Kind.NamedPipe,628 os.DT_FIFO => Entry.Kind.NamedPipe,
639 posix.DT_LNK => Entry.Kind.SymLink,629 os.DT_LNK => Entry.Kind.SymLink,
640 posix.DT_REG => Entry.Kind.File,630 os.DT_REG => Entry.Kind.File,
641 posix.DT_SOCK => Entry.Kind.UnixDomainSocket,631 os.DT_SOCK => Entry.Kind.UnixDomainSocket,
642 else => Entry.Kind.Unknown,632 else => Entry.Kind.Unknown,
643 };633 };
644 return Entry{634 return Entry{
...@@ -648,7 +638,7 @@ pub const Dir = struct {...@@ -648,7 +638,7 @@ pub const Dir = struct {
648 }638 }
649 }639 }
650640
651 fn nextFreebsd(self: *Dir) !?Entry {641 fn nextBsd(self: *Dir) !?Entry {
652 start_over: while (true) {642 start_over: while (true) {
653 if (self.handle.index >= self.handle.end_index) {643 if (self.handle.index >= self.handle.end_index) {
654 if (self.handle.buf.len == 0) {644 if (self.handle.buf.len == 0) {
...@@ -656,25 +646,30 @@ pub const Dir = struct {...@@ -656,25 +646,30 @@ pub const Dir = struct {
656 }646 }
657647
658 while (true) {648 while (true) {
659 const result = posix.getdirentries(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);649 const rc = os.system.getdirentries(
660 const err = posix.getErrno(result);650 self.handle.fd,
661 if (err > 0) {651 self.handle.buf.ptr,
662 switch (err) {652 self.handle.buf.len,
663 posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,653 &self.handle.seek,
664 posix.EINVAL => {654 );
665 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);655 switch (os.errno(rc)) {
666 continue;656 0 => {},
667 },657 os.EBADF => unreachable,
668 else => return unexpectedErrorPosix(err),658 os.EFAULT => unreachable,
669 }659 os.ENOTDIR => unreachable,
660 os.EINVAL => {
661 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
662 continue;
663 },
664 else => |err| return os.unexpectedErrno(err),
670 }665 }
671 if (result == 0) return null;666 if (rc == 0) return null;
672 self.handle.index = 0;667 self.handle.index = 0;
673 self.handle.end_index = result;668 self.handle.end_index = @intCast(usize, rc);
674 break;669 break;
675 }670 }
676 }671 }
677 const freebsd_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);672 const freebsd_entry = @ptrCast(*align(1) os.dirent, &self.handle.buf[self.handle.index]);
678 const next_index = self.handle.index + freebsd_entry.d_reclen;673 const next_index = self.handle.index + freebsd_entry.d_reclen;
679 self.handle.index = next_index;674 self.handle.index = next_index;
680675
...@@ -685,14 +680,14 @@ pub const Dir = struct {...@@ -685,14 +680,14 @@ pub const Dir = struct {
685 }680 }
686681
687 const entry_kind = switch (freebsd_entry.d_type) {682 const entry_kind = switch (freebsd_entry.d_type) {
688 posix.DT_BLK => Entry.Kind.BlockDevice,683 os.DT_BLK => Entry.Kind.BlockDevice,
689 posix.DT_CHR => Entry.Kind.CharacterDevice,684 os.DT_CHR => Entry.Kind.CharacterDevice,
690 posix.DT_DIR => Entry.Kind.Directory,685 os.DT_DIR => Entry.Kind.Directory,
691 posix.DT_FIFO => Entry.Kind.NamedPipe,686 os.DT_FIFO => Entry.Kind.NamedPipe,
692 posix.DT_LNK => Entry.Kind.SymLink,687 os.DT_LNK => Entry.Kind.SymLink,
693 posix.DT_REG => Entry.Kind.File,688 os.DT_REG => Entry.Kind.File,
694 posix.DT_SOCK => Entry.Kind.UnixDomainSocket,689 os.DT_SOCK => Entry.Kind.UnixDomainSocket,
695 posix.DT_WHT => Entry.Kind.Whiteout,690 os.DT_WHT => Entry.Kind.Whiteout,
696 else => Entry.Kind.Unknown,691 else => Entry.Kind.Unknown,
697 };692 };
698 return Entry{693 return Entry{
...@@ -705,52 +700,40 @@ pub const Dir = struct {...@@ -705,52 +700,40 @@ pub const Dir = struct {
705700
706/// Read value of a symbolic link.701/// Read value of a symbolic link.
707/// The return value is a slice of buffer, from index `0`.702/// The return value is a slice of buffer, from index `0`.
708pub fn readLink(buffer: *[posix.PATH_MAX]u8, pathname: []const u8) ![]u8 {703pub fn readLink(pathname: []const u8, buffer: *[os.PATH_MAX]u8) ![]u8 {
709 return posix.readlink(pathname, buffer);704 return os.readlink(pathname, buffer);
710}705}
711706
712/// Same as `readLink`, except the `pathname` parameter is null-terminated.707/// Same as `readLink`, except the `pathname` parameter is null-terminated.
713pub fn readLinkC(buffer: *[posix.PATH_MAX]u8, pathname: [*]const u8) ![]u8 {708pub fn readLinkC(pathname: [*]const u8, buffer: *[os.PATH_MAX]u8) ![]u8 {
714 return posix.readlinkC(pathname, buffer);709 return os.readlinkC(pathname, buffer);
715}710}
716711
717pub fn openSelfExe() !os.File {712pub const OpenSelfExeError = error{};
718 switch (builtin.os) {713
719 Os.linux => return os.File.openReadC(c"/proc/self/exe"),714pub fn openSelfExe() OpenSelfExeError!File {
720 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {715 if (os.linux.is_the_target) {
721 var buf: [MAX_PATH_BYTES]u8 = undefined;716 return File.openReadC(c"/proc/self/exe");
722 const self_exe_path = try selfExePath(&buf);717 }
723 buf[self_exe_path.len] = 0;718 if (os.windows.is_the_target) {
724 return os.File.openReadC(self_exe_path.ptr);719 var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
725 },720 const wide_slice = try selfExePathW(&buf);
726 Os.windows => {721 return File.openReadW(wide_slice.ptr);
727 var buf: [posix.PATH_MAX_WIDE]u16 = undefined;
728 const wide_slice = try selfExePathW(&buf);
729 return os.File.openReadW(wide_slice.ptr);
730 },
731 else => @compileError("Unsupported OS"),
732 }722 }
723 var buf: [MAX_PATH_BYTES]u8 = undefined;
724 const self_exe_path = try selfExePath(&buf);
725 buf[self_exe_path.len] = 0;
726 return File.openReadC(self_exe_path.ptr);
733}727}
734728
735test "openSelfExe" {729test "openSelfExe" {
736 switch (builtin.os) {730 switch (builtin.os) {
737 Os.linux, Os.macosx, Os.ios, Os.windows, Os.freebsd => (try openSelfExe()).close(),731 .linux, .macosx, .ios, .windows, .freebsd => (try openSelfExe()).close(),
738 else => return error.SkipZigTest, // Unsupported OS.732 else => return error.SkipZigTest, // Unsupported OS.
739 }733 }
740}734}
741735
742pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {736pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;
743 const casted_len = @intCast(windows.DWORD, out_buffer.len); // TODO shouldn't need this cast
744 const rc = windows.GetModuleFileNameW(null, out_buffer, casted_len);
745 assert(rc <= out_buffer.len);
746 if (rc == 0) {
747 const err = windows.GetLastError();
748 switch (err) {
749 else => return windows.unexpectedError(err),
750 }
751 }
752 return out_buffer[0..rc];
753}
754737
755/// Get the path to the current executable.738/// Get the path to the current executable.
756/// If you only need the directory, use selfExeDirPath.739/// If you only need the directory, use selfExeDirPath.
...@@ -763,39 +746,44 @@ pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {...@@ -763,39 +746,44 @@ pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {
763/// been deleted, the file path looks something like `/a/b/c/exe (deleted)`.746/// been deleted, the file path looks something like `/a/b/c/exe (deleted)`.
764/// TODO make the return type of this a null terminated pointer747/// TODO make the return type of this a null terminated pointer
765pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {748pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
749 if (os.darwin.is_the_target) {
750 var u32_len: u32 = out_buffer.len;
751 const rc = c._NSGetExecutablePath(out_buffer, &u32_len);
752 if (rc != 0) return error.NameTooLong;
753 return mem.toSlice(u8, out_buffer);
754 }
766 switch (builtin.os) {755 switch (builtin.os) {
767 Os.linux => return readLink(out_buffer, "/proc/self/exe"),756 .linux => return os.readlinkC(c"/proc/self/exe", out_buffer),
768 Os.freebsd => {757 .freebsd => {
769 var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC, posix.KERN_PROC_PATHNAME, -1 };758 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };
770 var out_len: usize = out_buffer.len;759 var out_len: usize = out_buffer.len;
771 try posix.sysctl(&mib, out_buffer, &out_len, null, 0);760 try os.sysctl(&mib, out_buffer, &out_len, null, 0);
772 // TODO could this slice from 0 to out_len instead?761 // TODO could this slice from 0 to out_len instead?
773 return mem.toSlice(u8, out_buffer);762 return mem.toSlice(u8, out_buffer);
774 },763 },
775 Os.netbsd => {764 .netbsd => {
776 var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC_ARGS, -1, posix.KERN_PROC_PATHNAME };765 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC_ARGS, -1, os.KERN_PROC_PATHNAME };
777 var out_len: usize = out_buffer.len;766 var out_len: usize = out_buffer.len;
778 try posix.sysctl(&mib, out_buffer, &out_len, null, 0);767 try os.sysctl(&mib, out_buffer, &out_len, null, 0);
779 // TODO could this slice from 0 to out_len instead?768 // TODO could this slice from 0 to out_len instead?
780 return mem.toSlice(u8, out_buffer);769 return mem.toSlice(u8, out_buffer);
781 },770 },
782 Os.windows => {771 .windows => {
783 var utf16le_buf: [posix.PATH_MAX_WIDE]u16 = undefined;772 var utf16le_buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
784 const utf16le_slice = try selfExePathW(&utf16le_buf);773 const utf16le_slice = try selfExePathW(&utf16le_buf);
785 // Trust that Windows gives us valid UTF-16LE.774 // Trust that Windows gives us valid UTF-16LE.
786 const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;775 const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;
787 return out_buffer[0..end_index];776 return out_buffer[0..end_index];
788 },777 },
789 Os.macosx, Os.ios => {778 else => @compileError("std.fs.selfExePath not supported for this target"),
790 var u32_len: u32 = @intCast(u32, out_buffer.len); // TODO shouldn't need this cast
791 const rc = c._NSGetExecutablePath(out_buffer, &u32_len);
792 if (rc != 0) return error.NameTooLong;
793 return mem.toSlice(u8, out_buffer);
794 },
795 else => @compileError("Unsupported OS"),
796 }779 }
797}780}
798781
782/// Same as `selfExePath` except the result is UTF16LE-encoded.
783pub fn selfExePathW(out_buffer: *[os.windows.PATH_MAX_WIDE]u16) ![]u16 {
784 return os.windows.GetModuleFileNameW(null, out_buffer, out_buffer.len);
785}
786
799/// `selfExeDirPath` except allocates the result on the heap.787/// `selfExeDirPath` except allocates the result on the heap.
800/// Caller owns returned memory.788/// Caller owns returned memory.
801pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {789pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
...@@ -806,31 +794,26 @@ pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {...@@ -806,31 +794,26 @@ pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
806/// Get the directory path that contains the current executable.794/// Get the directory path that contains the current executable.
807/// Returned value is a slice of out_buffer.795/// Returned value is a slice of out_buffer.
808pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {796pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
809 switch (builtin.os) {797 if (os.linux.is_the_target) {
810 Os.linux => {798 // If the currently executing binary has been deleted,
811 // If the currently executing binary has been deleted,799 // the file path looks something like `/a/b/c/exe (deleted)`
812 // the file path looks something like `/a/b/c/exe (deleted)`800 // This path cannot be opened, but it's valid for determining the directory
813 // This path cannot be opened, but it's valid for determining the directory801 // the executable was in when it was run.
814 // the executable was in when it was run.802 const full_exe_path = try os.readlinkC(c"/proc/self/exe", out_buffer);
815 const full_exe_path = try readLinkC(out_buffer, c"/proc/self/exe");803 // Assume that /proc/self/exe has an absolute path, and therefore dirname
816 // Assume that /proc/self/exe has an absolute path, and therefore dirname804 // will not return null.
817 // will not return null.805 return path.dirname(full_exe_path).?;
818 return path.dirname(full_exe_path).?;
819 },
820 Os.windows, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
821 const self_exe_path = try selfExePath(out_buffer);
822 // Assume that the OS APIs return absolute paths, and therefore dirname
823 // will not return null.
824 return path.dirname(self_exe_path).?;
825 },
826 else => @compileError("Unsupported OS"),
827 }806 }
807 const self_exe_path = try selfExePath(out_buffer);
808 // Assume that the OS APIs return absolute paths, and therefore dirname
809 // will not return null.
810 return path.dirname(self_exe_path).?;
828}811}
829812
830/// `realpath`, except caller must free the returned memory.813/// `realpath`, except caller must free the returned memory.
831pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {814pub fn realpathAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
832 var buf: [MAX_PATH_BYTES]u8 = undefined;815 var buf: [MAX_PATH_BYTES]u8 = undefined;
833 return mem.dupe(allocator, u8, try realpath(pathname, &buf));816 return mem.dupe(allocator, u8, try os.realpath(pathname, &buf));
834}817}
835818
836test "" {819test "" {
std/io.zig+6-6
...@@ -12,7 +12,7 @@ const meta = std.meta;...@@ -12,7 +12,7 @@ const meta = std.meta;
12const trait = meta.trait;12const trait = meta.trait;
13const Buffer = std.Buffer;13const Buffer = std.Buffer;
14const fmt = std.fmt;14const fmt = std.fmt;
15const File = std.os.File;15const File = std.fs.File;
16const testing = std.testing;16const testing = std.testing;
1717
18const is_posix = builtin.os != builtin.Os.windows;18const is_posix = builtin.os != builtin.Os.windows;
...@@ -963,8 +963,8 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {...@@ -963,8 +963,8 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
963963
964pub const BufferedAtomicFile = struct {964pub const BufferedAtomicFile = struct {
965 atomic_file: os.AtomicFile,965 atomic_file: os.AtomicFile,
966 file_stream: os.File.OutStream,966 file_stream: File.OutStream,
967 buffered_stream: BufferedOutStream(os.File.WriteError),967 buffered_stream: BufferedOutStream(File.WriteError),
968 allocator: *mem.Allocator,968 allocator: *mem.Allocator,
969969
970 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {970 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
...@@ -978,11 +978,11 @@ pub const BufferedAtomicFile = struct {...@@ -978,11 +978,11 @@ pub const BufferedAtomicFile = struct {
978 };978 };
979 errdefer allocator.destroy(self);979 errdefer allocator.destroy(self);
980980
981 self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);981 self.atomic_file = try os.AtomicFile.init(dest_path, File.default_mode);
982 errdefer self.atomic_file.deinit();982 errdefer self.atomic_file.deinit();
983983
984 self.file_stream = self.atomic_file.file.outStream();984 self.file_stream = self.atomic_file.file.outStream();
985 self.buffered_stream = BufferedOutStream(os.File.WriteError).init(&self.file_stream.stream);985 self.buffered_stream = BufferedOutStream(File.WriteError).init(&self.file_stream.stream);
986 return self;986 return self;
987 }987 }
988988
...@@ -997,7 +997,7 @@ pub const BufferedAtomicFile = struct {...@@ -997,7 +997,7 @@ pub const BufferedAtomicFile = struct {
997 try self.atomic_file.finish();997 try self.atomic_file.finish();
998 }998 }
999999
1000 pub fn stream(self: *BufferedAtomicFile) *OutStream(os.File.WriteError) {1000 pub fn stream(self: *BufferedAtomicFile) *OutStream(File.WriteError) {
1001 return &self.buffered_stream.stream;1001 return &self.buffered_stream.stream;
1002 }1002 }
1003};1003};
std/io/c_out_stream.zig+17-22
...@@ -1,13 +1,13 @@...@@ -1,13 +1,13 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const os = std.os;
2const OutStream = std.io.OutStream;3const OutStream = std.io.OutStream;
3const builtin = @import("builtin");4const builtin = @import("builtin");
4const posix = std.os.posix;
55
6/// TODO make std.os.FILE use *FILE when linking libc and this just becomes6/// TODO make a proposal to make `std.fs.File` use *FILE when linking libc and this just becomes
7/// std.io.FileOutStream because std.os.File.write would do this when linking7/// std.io.FileOutStream because std.fs.File.write would do this when linking
8/// libc.8/// libc.
9pub const COutStream = struct {9pub const COutStream = struct {
10 pub const Error = std.os.File.WriteError;10 pub const Error = std.fs.File.WriteError;
11 pub const Stream = OutStream(Error);11 pub const Stream = OutStream(Error);
1212
13 stream: Stream,13 stream: Stream,
...@@ -24,25 +24,20 @@ pub const COutStream = struct {...@@ -24,25 +24,20 @@ pub const COutStream = struct {
24 const self = @fieldParentPtr(COutStream, "stream", out_stream);24 const self = @fieldParentPtr(COutStream, "stream", out_stream);
25 const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);25 const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);
26 if (amt_written == bytes.len) return;26 if (amt_written == bytes.len) return;
27 // TODO errno on windows. should we have a posix layer for windows?27 switch (std.c._errno().*) {
28 if (builtin.os == .windows) {
29 return error.InputOutput;
30 }
31 const errno = std.c._errno().*;
32 switch (errno) {
33 0 => unreachable,28 0 => unreachable,
34 posix.EINVAL => unreachable,29 os.EINVAL => unreachable,
35 posix.EFAULT => unreachable,30 os.EFAULT => unreachable,
36 posix.EAGAIN => unreachable, // this is a blocking API31 os.EAGAIN => unreachable, // this is a blocking API
37 posix.EBADF => unreachable, // always a race condition32 os.EBADF => unreachable, // always a race condition
38 posix.EDESTADDRREQ => unreachable, // connect was never called33 os.EDESTADDRREQ => unreachable, // connect was never called
39 posix.EDQUOT => return error.DiskQuota,34 os.EDQUOT => return error.DiskQuota,
40 posix.EFBIG => return error.FileTooBig,35 os.EFBIG => return error.FileTooBig,
41 posix.EIO => return error.InputOutput,36 os.EIO => return error.InputOutput,
42 posix.ENOSPC => return error.NoSpaceLeft,37 os.ENOSPC => return error.NoSpaceLeft,
43 posix.EPERM => return error.AccessDenied,38 os.EPERM => return error.AccessDenied,
44 posix.EPIPE => return error.BrokenPipe,39 os.EPIPE => return error.BrokenPipe,
45 else => return std.os.unexpectedErrorPosix(@intCast(usize, errno)),40 else => return os.unexpectedErrno(@intCast(usize, errno)),
46 }41 }
47 }42 }
48};43};
std/io/test.zig+12-11
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
1const std = @import("../std.zig");2const std = @import("../std.zig");
2const io = std.io;3const io = std.io;
3const meta = std.meta;4const meta = std.meta;
...@@ -7,7 +8,7 @@ const expect = std.testing.expect;...@@ -7,7 +8,7 @@ const expect = std.testing.expect;
7const expectError = std.testing.expectError;8const expectError = std.testing.expectError;
8const mem = std.mem;9const mem = std.mem;
9const os = std.os;10const os = std.os;
10const builtin = @import("builtin");11const File = std.fs.File;
1112
12test "write a file, read it, then delete it" {13test "write a file, read it, then delete it" {
13 var raw_bytes: [200 * 1024]u8 = undefined;14 var raw_bytes: [200 * 1024]u8 = undefined;
...@@ -18,11 +19,11 @@ test "write a file, read it, then delete it" {...@@ -18,11 +19,11 @@ test "write a file, read it, then delete it" {
18 prng.random.bytes(data[0..]);19 prng.random.bytes(data[0..]);
19 const tmp_file_name = "temp_test_file.txt";20 const tmp_file_name = "temp_test_file.txt";
20 {21 {
21 var file = try os.File.openWrite(tmp_file_name);22 var file = try File.openWrite(tmp_file_name);
22 defer file.close();23 defer file.close();
2324
24 var file_out_stream = file.outStream();25 var file_out_stream = file.outStream();
25 var buf_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);26 var buf_stream = io.BufferedOutStream(File.WriteError).init(&file_out_stream.stream);
26 const st = &buf_stream.stream;27 const st = &buf_stream.stream;
27 try st.print("begin");28 try st.print("begin");
28 try st.write(data[0..]);29 try st.write(data[0..]);
...@@ -32,15 +33,15 @@ test "write a file, read it, then delete it" {...@@ -32,15 +33,15 @@ test "write a file, read it, then delete it" {
3233
33 {34 {
34 // make sure openWriteNoClobber doesn't harm the file35 // make sure openWriteNoClobber doesn't harm the file
35 if (os.File.openWriteNoClobber(tmp_file_name, os.File.default_mode)) |file| {36 if (File.openWriteNoClobber(tmp_file_name, File.default_mode)) |file| {
36 unreachable;37 unreachable;
37 } else |err| {38 } else |err| {
38 std.debug.assert(err == os.File.OpenError.PathAlreadyExists);39 std.debug.assert(err == File.OpenError.PathAlreadyExists);
39 }40 }
40 }41 }
4142
42 {43 {
43 var file = try os.File.openRead(tmp_file_name);44 var file = try File.openRead(tmp_file_name);
44 defer file.close();45 defer file.close();
4546
46 const file_size = try file.getEndPos();47 const file_size = try file.getEndPos();
...@@ -48,7 +49,7 @@ test "write a file, read it, then delete it" {...@@ -48,7 +49,7 @@ test "write a file, read it, then delete it" {
48 expect(file_size == expected_file_size);49 expect(file_size == expected_file_size);
4950
50 var file_in_stream = file.inStream();51 var file_in_stream = file.inStream();
51 var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);52 var buf_stream = io.BufferedInStream(File.ReadError).init(&file_in_stream.stream);
52 const st = &buf_stream.stream;53 const st = &buf_stream.stream;
53 const contents = try st.readAllAlloc(allocator, 2 * 1024);54 const contents = try st.readAllAlloc(allocator, 2 * 1024);
54 defer allocator.free(contents);55 defer allocator.free(contents);
...@@ -273,12 +274,12 @@ test "BitOutStream" {...@@ -273,12 +274,12 @@ test "BitOutStream" {
273test "BitStreams with File Stream" {274test "BitStreams with File Stream" {
274 const tmp_file_name = "temp_test_file.txt";275 const tmp_file_name = "temp_test_file.txt";
275 {276 {
276 var file = try os.File.openWrite(tmp_file_name);277 var file = try File.openWrite(tmp_file_name);
277 defer file.close();278 defer file.close();
278279
279 var file_out = file.outStream();280 var file_out = file.outStream();
280 var file_out_stream = &file_out.stream;281 var file_out_stream = &file_out.stream;
281 const OutError = os.File.WriteError;282 const OutError = File.WriteError;
282 var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);283 var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
283284
284 try bit_stream.writeBits(u2(1), 1);285 try bit_stream.writeBits(u2(1), 1);
...@@ -290,12 +291,12 @@ test "BitStreams with File Stream" {...@@ -290,12 +291,12 @@ test "BitStreams with File Stream" {
290 try bit_stream.flushBits();291 try bit_stream.flushBits();
291 }292 }
292 {293 {
293 var file = try os.File.openRead(tmp_file_name);294 var file = try File.openRead(tmp_file_name);
294 defer file.close();295 defer file.close();
295296
296 var file_in = file.inStream();297 var file_in = file.inStream();
297 var file_in_stream = &file_in.stream;298 var file_in_stream = &file_in.stream;
298 const InError = os.File.ReadError;299 const InError = File.ReadError;
299 var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);300 var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
300301
301 var out_bits: usize = undefined;302 var out_bits: usize = undefined;
std/os.zig+97-13
...@@ -16,6 +16,7 @@...@@ -16,6 +16,7 @@
1616
17const std = @import("std.zig");17const std = @import("std.zig");
18const builtin = @import("builtin");18const builtin = @import("builtin");
19const math = std.math;
19const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;20const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
2021
21comptime {22comptime {
...@@ -114,7 +115,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {...@@ -114,7 +115,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
114 const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0);115 const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
115 defer close(fd);116 defer close(fd);
116117
117 const stream = &os.File.openHandle(fd).inStream().stream;118 const stream = &std.fs.File.openHandle(fd).inStream().stream;
118 stream.readNoEof(buf) catch return error.Unexpected;119 stream.readNoEof(buf) catch return error.Unexpected;
119}120}
120121
...@@ -177,6 +178,21 @@ pub fn raise(sig: u8) RaiseError!void {...@@ -177,6 +178,21 @@ pub fn raise(sig: u8) RaiseError!void {
177 }178 }
178}179}
179180
181pub const KillError = error{
182 PermissionDenied,
183 Unexpected,
184};
185
186pub fn kill(pid: pid_t, sig: u8) KillError!void {
187 switch (errno(system.kill(pid, sig))) {
188 0 => return,
189 EINVAL => unreachable, // invalid signal
190 EPERM => return error.PermissionDenied,
191 ESRCH => unreachable, // always a race condition
192 else => |err| return unexpectedErrno(err),
193 }
194}
195
180/// Exits the program cleanly with the specified status code.196/// Exits the program cleanly with the specified status code.
181pub fn exit(status: u8) noreturn {197pub fn exit(status: u8) noreturn {
182 if (builtin.link_libc) {198 if (builtin.link_libc) {
...@@ -885,8 +901,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {...@@ -885,8 +901,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
885 if (windows.is_the_target and !builtin.link_libc) {901 if (windows.is_the_target and !builtin.link_libc) {
886 const old_path_w = try windows.sliceToPrefixedFileW(old_path);902 const old_path_w = try windows.sliceToPrefixedFileW(old_path);
887 const new_path_w = try windows.sliceToPrefixedFileW(new_path);903 const new_path_w = try windows.sliceToPrefixedFileW(new_path);
888 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;904 return renameW(&old_path_w, &new_path_w);
889 return windows.MoveFileExW(&old_path_w, &new_path_w, flags);
890 } else {905 } else {
891 const old_path_c = try toPosixPath(old_path);906 const old_path_c = try toPosixPath(old_path);
892 const new_path_c = try toPosixPath(new_path);907 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 {...@@ -899,8 +914,7 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
899 if (windows.is_the_target and !builtin.link_libc) {914 if (windows.is_the_target and !builtin.link_libc) {
900 const old_path_w = try windows.cStrToPrefixedFileW(old_path);915 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
901 const new_path_w = try windows.cStrToPrefixedFileW(new_path);916 const new_path_w = try windows.cStrToPrefixedFileW(new_path);
902 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;917 return renameW(&old_path_w, &new_path_w);
903 return windows.MoveFileExW(&old_path_w, &new_path_w, flags);
904 }918 }
905 switch (errno(system.rename(old_path, new_path))) {919 switch (errno(system.rename(old_path, new_path))) {
906 0 => return,920 0 => return,
...@@ -926,6 +940,13 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {...@@ -926,6 +940,13 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
926 }940 }
927}941}
928942
943/// Same as `rename` except the parameters are null-terminated UTF16LE encoded byte arrays.
944/// Assumes target is Windows.
945pub fn renameW(old_path: [*]const u16, new_path: [*]const u16) RenameError!void {
946 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
947 return windows.MoveFileExW(old_path_w, new_path_w, flags);
948}
949
929pub const MakeDirError = error{950pub const MakeDirError = error{
930 AccessDenied,951 AccessDenied,
931 DiskQuota,952 DiskQuota,
...@@ -1684,10 +1705,10 @@ pub fn getsockoptError(sockfd: i32) ConnectError!void {...@@ -1684,10 +1705,10 @@ pub fn getsockoptError(sockfd: i32) ConnectError!void {
1684 }1705 }
1685}1706}
16861707
1687pub fn waitpid(pid: i32) i32 {1708pub fn waitpid(pid: i32, flags: u32) i32 {
1688 var status: i32 = undefined;1709 var status: i32 = undefined;
1689 while (true) {1710 while (true) {
1690 switch (errno(system.waitpid(pid, &status, 0))) {1711 switch (errno(system.waitpid(pid, &status, flags))) {
1691 0 => return status,1712 0 => return status,
1692 EINTR => continue,1713 EINTR => continue,
1693 ECHILD => unreachable, // The process specified does not exist. It would be a race condition to handle this error.1714 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{...@@ -1988,9 +2009,10 @@ pub const PipeError = error{
1988};2009};
19892010
1990/// Creates a unidirectional data channel that can be used for interprocess communication.2011/// Creates a unidirectional data channel that can be used for interprocess communication.
1991pub fn pipe(fds: *[2]fd_t) PipeError!void {2012pub fn pipe() PipeError![2]fd_t {
1992 switch (errno(system.pipe(fds))) {2013 var fds: [2]i32 = undefined;
1993 0 => return,2014 switch (errno(system.pipe(&fds))) {
2015 0 => return fds,
1994 EINVAL => unreachable, // Invalid parameters to pipe()2016 EINVAL => unreachable, // Invalid parameters to pipe()
1995 EFAULT => unreachable, // Invalid fds pointer2017 EFAULT => unreachable, // Invalid fds pointer
1996 ENFILE => return error.SystemFdQuotaExceeded,2018 ENFILE => return error.SystemFdQuotaExceeded,
...@@ -1999,9 +2021,10 @@ pub fn pipe(fds: *[2]fd_t) PipeError!void {...@@ -1999,9 +2021,10 @@ pub fn pipe(fds: *[2]fd_t) PipeError!void {
1999 }2021 }
2000}2022}
20012023
2002pub fn pipe2(fds: *[2]fd_t, flags: u32) PipeError!void {2024pub fn pipe2(flags: u32) PipeError![2]fd_t {
2003 switch (errno(system.pipe2(fds, flags))) {2025 var fds: [2]i32 = undefined;
2004 0 => return,2026 switch (errno(system.pipe2(&fds, flags))) {
2027 0 => return fds,
2005 EINVAL => unreachable, // Invalid flags2028 EINVAL => unreachable, // Invalid flags
2006 EFAULT => unreachable, // Invalid fds pointer2029 EFAULT => unreachable, // Invalid fds pointer
2007 ENFILE => return error.SystemFdQuotaExceeded,2030 ENFILE => return error.SystemFdQuotaExceeded,
...@@ -2281,6 +2304,67 @@ pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPa...@@ -2281,6 +2304,67 @@ pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPa
2281 return out_buffer[0..end_index];2304 return out_buffer[0..end_index];
2282}2305}
22832306
2307/// Spurious wakeups are possible and no precision of timing is guaranteed.
2308pub fn nanosleep(seconds: u64, nanoseconds: u64) void {
2309 if (windows.is_the_target and !builtin.link_libc) {
2310 // TODO https://github.com/ziglang/zig/issues/1284
2311 const small_s = math.cast(windows.DWORD, seconds) catch math.maxInt(windows.DWORD);
2312 const ms_from_s = math.mul(small_s, std.time.ms_per_s) catch math.maxInt(windows.DWORD);
2313
2314 const ns_per_ms = std.time.ns_per_s / std.time.ms_per_s;
2315 const big_ms_from_ns = nanoseconds / ns_per_ms;
2316 const ms_from_ns = math.cast(windows.DWORD, big_ms_from_ns) catch math.maxInt(windows.DWORD);
2317
2318 const ms = math.add(ms_from_s, ms_from_ns) catch math.maxInt(windows.DWORD);
2319 windows.kernel32.Sleep(ms);
2320 return;
2321 }
2322 var req = timespec{
2323 .tv_sec = math.cast(isize, seconds) catch math.maxInt(isize),
2324 .tv_nsec = math.cast(isize, nanoseconds) catch math.maxInt(isize),
2325 };
2326 var rem: timespec = undefined;
2327 while (true) {
2328 switch (errno(system.nanosleep(&req, &rem))) {
2329 EFAULT => unreachable,
2330 EINVAL => {
2331 // Sometimes Darwin returns EINVAL for no reason.
2332 // We treat it as a spurious wakeup.
2333 return;
2334 },
2335 EINTR => {
2336 req = rem;
2337 continue;
2338 },
2339 // This prong handles success as well as unexpected errors.
2340 else => return,
2341 }
2342 }
2343}
2344
2345pub const ClockGetTimeError = error{
2346 UnsupportedClock,
2347 Unexpected,
2348};
2349
2350pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
2351 switch (errno(system.clock_gettime(clk_id, tp))) {
2352 0 => return,
2353 EFAULT => unreachable,
2354 EINVAL => return error.UnsupportedClock,
2355 else => |err| return unexpectedErrno(err),
2356 }
2357}
2358
2359pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
2360 switch (errno(system.clock_getres(clk_id, tp))) {
2361 0 => return,
2362 EFAULT => unreachable,
2363 EINVAL => return error.UnsupportedClock,
2364 else => |err| return unexpectedErrno(err),
2365 }
2366}
2367
2284/// Used to convert a slice to a null terminated slice on the stack.2368/// Used to convert a slice to a null terminated slice on the stack.
2285/// TODO https://github.com/ziglang/zig/issues/2872369/// TODO https://github.com/ziglang/zig/issues/287
2286pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {2370pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
std/os/bits/linux.zig+1-11
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1pub use @import("errno.zig");1pub use @import("linux/errno.zig");
2pub use switch (builtin.arch) {2pub use switch (builtin.arch) {
3 .x86_64 => @import("linux/x86_64.zig"),3 .x86_64 => @import("linux/x86_64.zig"),
4 .aarch64 => @import("linux/arm64.zig"),4 .aarch64 => @import("linux/arm64.zig"),
...@@ -744,16 +744,6 @@ pub const sockaddr_un = extern struct {...@@ -744,16 +744,6 @@ pub const sockaddr_un = extern struct {
744 path: [108]u8,744 path: [108]u8,
745};745};
746746
747pub const iovec = extern struct {
748 iov_base: [*]u8,
749 iov_len: usize,
750};
751
752pub const iovec_const = extern struct {
753 iov_base: [*]const u8,
754 iov_len: usize,
755};
756
757pub const mmsghdr = extern struct {747pub const mmsghdr = extern struct {
758 msg_hdr: msghdr,748 msg_hdr: msghdr,
759 msg_len: u32,749 msg_len: u32,
std/os/test.zig+4-3
...@@ -4,6 +4,7 @@ const testing = std.testing;...@@ -4,6 +4,7 @@ const testing = std.testing;
4const expect = std.testing.expect;4const expect = std.testing.expect;
5const io = std.io;5const io = std.io;
6const mem = std.mem;6const mem = std.mem;
7const File = std.fs.File;
78
8const a = std.debug.global_allocator;9const a = std.debug.global_allocator;
910
...@@ -25,14 +26,14 @@ test "makePath, put some files in it, deleteTree" {...@@ -25,14 +26,14 @@ test "makePath, put some files in it, deleteTree" {
2526
26test "access file" {27test "access file" {
27 try os.makePath(a, "os_test_tmp");28 try os.makePath(a, "os_test_tmp");
28 if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {29 if (File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {
29 @panic("expected error");30 @panic("expected error");
30 } else |err| {31 } else |err| {
31 expect(err == error.FileNotFound);32 expect(err == error.FileNotFound);
32 }33 }
3334
34 try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", "");35 try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", "");
35 try os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt");36 try File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt");
36 try os.deleteTree(a, "os_test_tmp");37 try os.deleteTree(a, "os_test_tmp");
37}38}
3839
...@@ -102,7 +103,7 @@ test "AtomicFile" {...@@ -102,7 +103,7 @@ test "AtomicFile" {
102 \\ this is a test file103 \\ this is a test file
103 ;104 ;
104 {105 {
105 var af = try os.AtomicFile.init(test_out_file, os.File.default_mode);106 var af = try os.AtomicFile.init(test_out_file, File.default_mode);
106 defer af.deinit();107 defer af.deinit();
107 try af.file.write(test_content);108 try af.file.write(test_content);
108 try af.finish();109 try af.finish();
std/os/windows.zig+26
...@@ -753,6 +753,10 @@ pub fn CloseHandle(hObject: HANDLE) void {...@@ -753,6 +753,10 @@ pub fn CloseHandle(hObject: HANDLE) void {
753 assert(kernel32.CloseHandle(hObject) != 0);753 assert(kernel32.CloseHandle(hObject) != 0);
754}754}
755755
756pub fn FindClose(hFindFile: HANDLE) void {
757 assert(kernel32.FindClose(hFindFile) != 0);
758}
759
756pub const ReadFileError = error{Unexpected};760pub const ReadFileError = error{Unexpected};
757761
758pub fn ReadFile(in_hFile: HANDLE, buffer: []u8) ReadFileError!usize {762pub fn ReadFile(in_hFile: HANDLE, buffer: []u8) ReadFileError!usize {
...@@ -1063,6 +1067,28 @@ pub fn GetFileAttributesW(lpFileName: [*]const u16) GetFileAttributesError!DWORD...@@ -1063,6 +1067,28 @@ pub fn GetFileAttributesW(lpFileName: [*]const u16) GetFileAttributesError!DWORD
1063 return rc;1067 return rc;
1064}1068}
10651069
1070const GetModuleFileNameError = error{Unexpected};
1071
1072pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) GetModuleFileNameError![]u16 {
1073 const rc = kernel32.GetModuleFileNameW(hModule, buf_ptr, buf_len);
1074 if (rc == 0) {
1075 switch (kernel32.GetLastError()) {
1076 else => |err| return unexpectedError(err),
1077 }
1078 }
1079 return buf_ptr[0..rc];
1080}
1081
1082pub const TerminateProcessError = error{Unexpected};
1083
1084pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void {
1085 if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) {
1086 switch (kernel32.GetLastError()) {
1087 else => |err| return unexpectedError(err),
1088 }
1089 }
1090}
1091
1066pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {1092pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
1067 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));1093 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
1068}1094}
std/pdb.zig+6-5
...@@ -6,6 +6,7 @@ const mem = std.mem;...@@ -6,6 +6,7 @@ const mem = std.mem;
6const os = std.os;6const os = std.os;
7const warn = std.debug.warn;7const warn = std.debug.warn;
8const coff = std.coff;8const coff = std.coff;
9const File = std.fs.File;
910
10const ArrayList = std.ArrayList;11const ArrayList = std.ArrayList;
1112
...@@ -459,7 +460,7 @@ pub const PDBStringTableHeader = packed struct {...@@ -459,7 +460,7 @@ pub const PDBStringTableHeader = packed struct {
459};460};
460461
461pub const Pdb = struct {462pub const Pdb = struct {
462 in_file: os.File,463 in_file: File,
463 allocator: *mem.Allocator,464 allocator: *mem.Allocator,
464 coff: *coff.Coff,465 coff: *coff.Coff,
465 string_table: *MsfStream,466 string_table: *MsfStream,
...@@ -468,7 +469,7 @@ pub const Pdb = struct {...@@ -468,7 +469,7 @@ pub const Pdb = struct {
468 msf: Msf,469 msf: Msf,
469470
470 pub fn openFile(self: *Pdb, coff_ptr: *coff.Coff, file_name: []u8) !void {471 pub fn openFile(self: *Pdb, coff_ptr: *coff.Coff, file_name: []u8) !void {
471 self.in_file = try os.File.openRead(file_name);472 self.in_file = try File.openRead(file_name);
472 self.allocator = coff_ptr.allocator;473 self.allocator = coff_ptr.allocator;
473 self.coff = coff_ptr;474 self.coff = coff_ptr;
474475
...@@ -492,7 +493,7 @@ const Msf = struct {...@@ -492,7 +493,7 @@ const Msf = struct {
492 directory: MsfStream,493 directory: MsfStream,
493 streams: []MsfStream,494 streams: []MsfStream,
494495
495 fn openFile(self: *Msf, allocator: *mem.Allocator, file: os.File) !void {496 fn openFile(self: *Msf, allocator: *mem.Allocator, file: File) !void {
496 var file_stream = file.inStream();497 var file_stream = file.inStream();
497 const in = &file_stream.stream;498 const in = &file_stream.stream;
498499
...@@ -587,7 +588,7 @@ const SuperBlock = packed struct {...@@ -587,7 +588,7 @@ const SuperBlock = packed struct {
587};588};
588589
589const MsfStream = struct {590const MsfStream = struct {
590 in_file: os.File,591 in_file: File,
591 pos: u64,592 pos: u64,
592 blocks: []u32,593 blocks: []u32,
593 block_size: u32,594 block_size: u32,
...@@ -598,7 +599,7 @@ const MsfStream = struct {...@@ -598,7 +599,7 @@ const MsfStream = struct {
598 pub const Error = @typeOf(read).ReturnType.ErrorSet;599 pub const Error = @typeOf(read).ReturnType.ErrorSet;
599 pub const Stream = io.InStream(Error);600 pub const Stream = io.InStream(Error);
600601
601 fn init(block_size: u32, block_count: u32, pos: u64, file: os.File, allocator: *mem.Allocator) !MsfStream {602 fn init(block_size: u32, block_count: u32, pos: u64, file: File, allocator: *mem.Allocator) !MsfStream {
602 var stream = MsfStream{603 var stream = MsfStream{
603 .in_file = file,604 .in_file = file,
604 .pos = 0,605 .pos = 0,
std/special/build_runner.zig+3-2
...@@ -8,6 +8,7 @@ const Builder = std.build.Builder;...@@ -8,6 +8,7 @@ const Builder = std.build.Builder;
8const mem = std.mem;8const mem = std.mem;
9const ArrayList = std.ArrayList;9const ArrayList = std.ArrayList;
10const warn = std.debug.warn;10const warn = std.debug.warn;
11const File = std.fs.File;
1112
12pub fn main() !void {13pub fn main() !void {
13 var arg_it = os.args();14 var arg_it = os.args();
...@@ -48,14 +49,14 @@ pub fn main() !void {...@@ -48,14 +49,14 @@ pub fn main() !void {
48 var prefix: ?[]const u8 = null;49 var prefix: ?[]const u8 = null;
4950
50 var stderr_file = io.getStdErr();51 var stderr_file = io.getStdErr();
51 var stderr_file_stream: os.File.OutStream = undefined;52 var stderr_file_stream: File.OutStream = undefined;
52 var stderr_stream = if (stderr_file) |f| x: {53 var stderr_stream = if (stderr_file) |f| x: {
53 stderr_file_stream = f.outStream();54 stderr_file_stream = f.outStream();
54 break :x &stderr_file_stream.stream;55 break :x &stderr_file_stream.stream;
55 } else |err| err;56 } else |err| err;
5657
57 var stdout_file = io.getStdOut();58 var stdout_file = io.getStdOut();
58 var stdout_file_stream: os.File.OutStream = undefined;59 var stdout_file_stream: File.OutStream = undefined;
59 var stdout_stream = if (stdout_file) |f| x: {60 var stdout_stream = if (stdout_file) |f| x: {
60 stdout_file_stream = f.outStream();61 stdout_file_stream = f.outStream();
61 break :x &stdout_file_stream.stream;62 break :x &stdout_file_stream.stream;
std/time.zig+100-184
...@@ -1,116 +1,61 @@...@@ -1,116 +1,61 @@
1const std = @import("../std.zig");
2const builtin = @import("builtin");1const builtin = @import("builtin");
3const Os = builtin.Os;2const std = @import("std.zig");
4const debug = std.debug;3const assert = std.debug.assert;
5const testing = std.testing;4const testing = std.testing;
6const math = std.math;5const os = std.os;
7
8const windows = std.os.windows;
9const linux = std.os.linux;
10const darwin = std.os.darwin;
11const wasi = std.os.wasi;
12const posix = std.os.posix;
136
14pub const epoch = @import("epoch.zig");7pub const epoch = @import("epoch.zig");
158
16/// Spurious wakeups are possible and no precision of timing is guaranteed.9/// Spurious wakeups are possible and no precision of timing is guaranteed.
17pub fn sleep(nanoseconds: u64) void {10pub fn sleep(nanoseconds: u64) void {
18 switch (builtin.os) {11 const s = nanoseconds / ns_per_s;
19 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {12 const ns = nanoseconds % ns_per_s;
20 const s = nanoseconds / ns_per_s;13 std.os.nanosleep(s, ns);
21 const ns = nanoseconds % ns_per_s;
22 posixSleep(s, ns);
23 },
24 Os.windows => {
25 const ns_per_ms = ns_per_s / ms_per_s;
26 const milliseconds = nanoseconds / ns_per_ms;
27 const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD);
28 windows.Sleep(ms_that_will_fit);
29 },
30 else => @compileError("Unsupported OS"),
31 }
32}
33
34/// Spurious wakeups are possible and no precision of timing is guaranteed.
35pub fn posixSleep(seconds: u64, nanoseconds: u64) void {
36 var req = posix.timespec{
37 .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize),
38 .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize),
39 };
40 var rem: posix.timespec = undefined;
41 while (true) {
42 const ret_val = posix.nanosleep(&req, &rem);
43 const err = posix.getErrno(ret_val);
44 switch (err) {
45 posix.EFAULT => unreachable,
46 posix.EINVAL => {
47 // Sometimes Darwin returns EINVAL for no reason.
48 // We treat it as a spurious wakeup.
49 return;
50 },
51 posix.EINTR => {
52 req = rem;
53 continue;
54 },
55 // This prong handles success as well as unexpected errors.
56 else => return,
57 }
58 }
59}14}
6015
61/// Get the posix timestamp, UTC, in seconds16/// Get the posix timestamp, UTC, in seconds
17/// TODO audit this function. is it possible to return an error?
62pub fn timestamp() u64 {18pub fn timestamp() u64 {
63 return @divFloor(milliTimestamp(), ms_per_s);19 return @divFloor(milliTimestamp(), ms_per_s);
64}20}
6521
66/// Get the posix timestamp, UTC, in milliseconds22/// Get the posix timestamp, UTC, in milliseconds
67pub const milliTimestamp = switch (builtin.os) {23/// TODO audit this function. is it possible to return an error?
68 Os.windows => milliTimestampWindows,24pub fn milliTimestamp() u64 {
69 Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,25 if (os.windows.is_the_target and !builtin.link_libc) {
70 Os.macosx, Os.ios => milliTimestampDarwin,26 //FileTime has a granularity of 100 nanoseconds
71 Os.wasi => milliTimestampWasi,27 // and uses the NTFS/Windows epoch
72 else => @compileError("Unsupported OS"),28 var ft: os.windows.FILETIME = undefined;
73};29 os.windows.kernel32.GetSystemTimeAsFileTime(&ft);
7430 const hns_per_ms = (ns_per_s / 100) / ms_per_s;
75fn milliTimestampWasi() u64 {31 const epoch_adj = epoch.windows * ms_per_s;
76 var ns: wasi.timestamp_t = undefined;32
7733 const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
78 // TODO: Verify that precision is ignored34 return @divFloor(ft64, hns_per_ms) - -epoch_adj;
79 const err = wasi.clock_time_get(wasi.CLOCK_REALTIME, 1, &ns);35 }
80 debug.assert(err == wasi.ESUCCESS);36 if (os.wasi.is_the_target and !builtin.link_libc) {
8137 var ns: os.wasi.timestamp_t = undefined;
82 const ns_per_ms = 1000;
83 return @divFloor(ns, ns_per_ms);
84}
85
86fn milliTimestampWindows() u64 {
87 //FileTime has a granularity of 100 nanoseconds
88 // and uses the NTFS/Windows epoch
89 var ft: windows.FILETIME = undefined;
90 windows.GetSystemTimeAsFileTime(&ft);
91 const hns_per_ms = (ns_per_s / 100) / ms_per_s;
92 const epoch_adj = epoch.windows * ms_per_s;
93
94 const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
95 return @divFloor(ft64, hns_per_ms) - -epoch_adj;
96}
9738
98fn milliTimestampDarwin() u64 {39 // TODO: Verify that precision is ignored
99 var tv: darwin.timeval = undefined;40 const err = os.wasi.clock_time_get(os.wasi.CLOCK_REALTIME, 1, &ns);
100 var err = darwin.gettimeofday(&tv, null);41 assert(err == os.wasi.ESUCCESS);
101 debug.assert(err == 0);
102 const sec_ms = tv.tv_sec * ms_per_s;
103 const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
104 return @intCast(u64, sec_ms + usec_ms);
105}
10642
107fn milliTimestampPosix() u64 {43 const ns_per_ms = 1000;
44 return @divFloor(ns, ns_per_ms);
45 }
46 if (os.darwin.is_the_target) {
47 var tv: os.darwin.timeval = undefined;
48 var err = os.darwin.gettimeofday(&tv, null);
49 assert(err == 0);
50 const sec_ms = tv.tv_sec * ms_per_s;
51 const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
52 return @intCast(u64, sec_ms + usec_ms);
53 }
54 var ts: os.timespec = undefined;
108 //From what I can tell there's no reason clock_gettime55 //From what I can tell there's no reason clock_gettime
109 // should ever fail for us with CLOCK_REALTIME,56 // should ever fail for us with CLOCK_REALTIME,
110 // seccomp aside.57 // seccomp aside.
111 var ts: posix.timespec = undefined;58 os.clock_gettime(os.CLOCK_REALTIME, &ts) catch unreachable;
112 const err = posix.clock_gettime(posix.CLOCK_REALTIME, &ts);
113 debug.assert(err == 0);
114 const sec_ms = @intCast(u64, ts.tv_sec) * ms_per_s;59 const sec_ms = @intCast(u64, ts.tv_sec) * ms_per_s;
115 const nsec_ms = @divFloor(@intCast(u64, ts.tv_nsec), ns_per_s / ms_per_s);60 const nsec_ms = @divFloor(@intCast(u64, ts.tv_nsec), ns_per_s / ms_per_s);
116 return sec_ms + nsec_ms;61 return sec_ms + nsec_ms;
...@@ -145,27 +90,23 @@ pub const s_per_week = s_per_day * 7;...@@ -145,27 +90,23 @@ pub const s_per_week = s_per_day * 7;
145/// depends on the OS. On Windows and Darwin it is a hardware counter90/// depends on the OS. On Windows and Darwin it is a hardware counter
146/// value that requires calculation to convert to a meaninful unit.91/// value that requires calculation to convert to a meaninful unit.
147pub const Timer = struct {92pub const Timer = struct {
14893 ///if we used resolution's value when performing the
149 //if we used resolution's value when performing the94 /// performance counter calc on windows/darwin, it would
150 // performance counter calc on windows/darwin, it would95 /// be less precise
151 // be less precise
152 frequency: switch (builtin.os) {96 frequency: switch (builtin.os) {
153 Os.windows => u64,97 .windows => u64,
154 Os.macosx, Os.ios => darwin.mach_timebase_info_data,98 .macosx, .ios, .tvos, .watchos => darwin.mach_timebase_info_data,
155 else => void,99 else => void,
156 },100 },
157 resolution: u64,101 resolution: u64,
158 start_time: u64,102 start_time: u64,
159103
160 //At some point we may change our minds on RAW, but for now we're104 const Error = error{TimerUnsupported};
161 // sticking with posix standard MONOTONIC. For more information, see:105
162 // https://github.com/ziglang/zig/pull/933106 ///At some point we may change our minds on RAW, but for now we're
163 //107 /// sticking with posix standard MONOTONIC. For more information, see:
164 //const monotonic_clock_id = switch(builtin.os) {108 /// https://github.com/ziglang/zig/pull/933
165 // Os.linux => linux.CLOCK_MONOTONIC_RAW,109 const monotonic_clock_id = os.CLOCK_MONOTONIC;
166 // else => posix.CLOCK_MONOTONIC,
167 //};
168 const monotonic_clock_id = posix.CLOCK_MONOTONIC;
169 /// Initialize the timer structure.110 /// Initialize the timer structure.
170 //This gives us an opportunity to grab the counter frequency in windows.111 //This gives us an opportunity to grab the counter frequency in windows.
171 //On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.112 //On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.
...@@ -174,66 +115,51 @@ pub const Timer = struct {...@@ -174,66 +115,51 @@ pub const Timer = struct {
174 // impossible here barring cosmic rays or other such occurrences of115 // impossible here barring cosmic rays or other such occurrences of
175 // incredibly bad luck.116 // incredibly bad luck.
176 //On Darwin: This cannot fail, as far as I am able to tell.117 //On Darwin: This cannot fail, as far as I am able to tell.
177 const TimerError = error{118 pub fn start() Error!Timer {
178 TimerUnsupported,
179 Unexpected,
180 };
181 pub fn start() TimerError!Timer {
182 var self: Timer = undefined;119 var self: Timer = undefined;
183120
184 switch (builtin.os) {121 if (os.windows.is_the_target) {
185 Os.windows => {122 var freq: i64 = undefined;
186 var freq: i64 = undefined;123 var err = windows.QueryPerformanceFrequency(&freq);
187 var err = windows.QueryPerformanceFrequency(&freq);124 if (err == windows.FALSE) return error.TimerUnsupported;
188 if (err == windows.FALSE) return error.TimerUnsupported;125 self.frequency = @intCast(u64, freq);
189 self.frequency = @intCast(u64, freq);126 self.resolution = @divFloor(ns_per_s, self.frequency);
190 self.resolution = @divFloor(ns_per_s, self.frequency);127
191128 var start_time: i64 = undefined;
192 var start_time: i64 = undefined;129 err = windows.QueryPerformanceCounter(&start_time);
193 err = windows.QueryPerformanceCounter(&start_time);130 assert(err != windows.FALSE);
194 debug.assert(err != windows.FALSE);131 self.start_time = @intCast(u64, start_time);
195 self.start_time = @intCast(u64, start_time);132 } else if (os.darwin.is_the_target) {
196 },133 darwin.mach_timebase_info(&self.frequency);
197 Os.linux, Os.freebsd, Os.netbsd => {134 self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
198 //On Linux, seccomp can do arbitrary things to our ability to call135 self.start_time = darwin.mach_absolute_time();
199 // syscalls, including return any errno value it wants and136 } else {
200 // inconsistently throwing errors. Since we can't account for137 //On Linux, seccomp can do arbitrary things to our ability to call
201 // abuses of seccomp in a reasonable way, we'll assume that if138 // syscalls, including return any errno value it wants and
202 // seccomp is going to block us it will at least do so consistently139 // inconsistently throwing errors. Since we can't account for
203 var ts: posix.timespec = undefined;140 // abuses of seccomp in a reasonable way, we'll assume that if
204 var result = posix.clock_getres(monotonic_clock_id, &ts);141 // seccomp is going to block us it will at least do so consistently
205 var errno = posix.getErrno(result);142 var ts: os.timespec = undefined;
206 switch (errno) {143 os.clock_getres(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
207 0 => {},144 self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
208 posix.EINVAL => return error.TimerUnsupported,145
209 else => return std.os.unexpectedErrorPosix(errno),146 os.clock_gettime(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
210 }147 self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
211 self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
212
213 result = posix.clock_gettime(monotonic_clock_id, &ts);
214 errno = posix.getErrno(result);
215 if (errno != 0) return std.os.unexpectedErrorPosix(errno);
216 self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
217 },
218 Os.macosx, Os.ios => {
219 darwin.mach_timebase_info(&self.frequency);
220 self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
221 self.start_time = darwin.mach_absolute_time();
222 },
223 else => @compileError("Unsupported OS"),
224 }148 }
149
225 return self;150 return self;
226 }151 }
227152
228 /// Reads the timer value since start or the last reset in nanoseconds153 /// Reads the timer value since start or the last reset in nanoseconds
229 pub fn read(self: *Timer) u64 {154 pub fn read(self: *Timer) u64 {
230 var clock = clockNative() - self.start_time;155 var clock = clockNative() - self.start_time;
231 return switch (builtin.os) {156 if (os.windows.is_the_target) {
232 Os.windows => @divFloor(clock * ns_per_s, self.frequency),157 return @divFloor(clock * ns_per_s, self.frequency);
233 Os.linux, Os.freebsd, Os.netbsd => clock,158 }
234 Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),159 if (os.darwin.is_the_target) {
235 else => @compileError("Unsupported OS"),160 return @divFloor(clock * self.frequency.numer, self.frequency.denom);
236 };161 }
162 return clock;
237 }163 }
238164
239 /// Resets the timer value to 0/now.165 /// Resets the timer value to 0/now.
...@@ -249,37 +175,27 @@ pub const Timer = struct {...@@ -249,37 +175,27 @@ pub const Timer = struct {
249 return lap_time;175 return lap_time;
250 }176 }
251177
252 const clockNative = switch (builtin.os) {178 fn clockNative() u64 {
253 Os.windows => clockWindows,179 if (os.windows.is_the_target) {
254 Os.linux, Os.freebsd, Os.netbsd => clockLinux,180 var result: i64 = undefined;
255 Os.macosx, Os.ios => clockDarwin,181 var err = windows.QueryPerformanceCounter(&result);
256 else => @compileError("Unsupported OS"),182 assert(err != windows.FALSE);
257 };183 return @intCast(u64, result);
258184 }
259 fn clockWindows() u64 {185 if (os.darwin.is_the_target) {
260 var result: i64 = undefined;186 return darwin.mach_absolute_time();
261 var err = windows.QueryPerformanceCounter(&result);187 }
262 debug.assert(err != windows.FALSE);188 var ts: os.timespec = undefined;
263 return @intCast(u64, result);189 os.clock_gettime(monotonic_clock_id, &ts) catch unreachable;
264 }
265
266 fn clockDarwin() u64 {
267 return darwin.mach_absolute_time();
268 }
269
270 fn clockLinux() u64 {
271 var ts: posix.timespec = undefined;
272 var result = posix.clock_gettime(monotonic_clock_id, &ts);
273 debug.assert(posix.getErrno(result) == 0);
274 return @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);190 return @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
275 }191 }
276};192};
277193
278test "os.time.sleep" {194test "sleep" {
279 sleep(1);195 sleep(1);
280}196}
281197
282test "os.time.timestamp" {198test "timestamp" {
283 const ns_per_ms = (ns_per_s / ms_per_s);199 const ns_per_ms = (ns_per_s / ms_per_s);
284 const margin = 50;200 const margin = 50;
285201
...@@ -290,7 +206,7 @@ test "os.time.timestamp" {...@@ -290,7 +206,7 @@ test "os.time.timestamp" {
290 testing.expect(interval > 0 and interval < margin);206 testing.expect(interval > 0 and interval < margin);
291}207}
292208
293test "os.time.Timer" {209test "Timer" {
294 const ns_per_ms = (ns_per_s / ms_per_s);210 const ns_per_ms = (ns_per_s / ms_per_s);
295 const margin = ns_per_ms * 150;211 const margin = ns_per_ms * 150;
296212
std/zig/bench.zig+2-2
...@@ -10,7 +10,7 @@ var fixed_buffer_mem: [10 * 1024 * 1024]u8 = undefined;...@@ -10,7 +10,7 @@ var fixed_buffer_mem: [10 * 1024 * 1024]u8 = undefined;
1010
11pub fn main() !void {11pub fn main() !void {
12 var i: usize = 0;12 var i: usize = 0;
13 var timer = try std.os.time.Timer.start();13 var timer = try std.time.Timer.start();
14 const start = timer.lap();14 const start = timer.lap();
15 const iterations = 100;15 const iterations = 100;
16 var memory_used: usize = 0;16 var memory_used: usize = 0;
...@@ -19,7 +19,7 @@ pub fn main() !void {...@@ -19,7 +19,7 @@ pub fn main() !void {
19 }19 }
20 const end = timer.read();20 const end = timer.read();
21 memory_used /= iterations;21 memory_used /= iterations;
22 const elapsed_s = @intToFloat(f64, end - start) / std.os.time.ns_per_s;22 const elapsed_s = @intToFloat(f64, end - start) / std.time.ns_per_s;
23 const bytes_per_sec = @intToFloat(f64, source.len * iterations) / elapsed_s;23 const bytes_per_sec = @intToFloat(f64, source.len * iterations) / elapsed_s;
24 const mb_per_sec = bytes_per_sec / (1024 * 1024);24 const mb_per_sec = bytes_per_sec / (1024 * 1024);
2525