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
signaturelock-open 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 {
220220 var put_count: usize = puts_per_thread;
221221 var r = std.rand.DefaultPrng.init(0xdeadbeef);
222222 while (put_count != 0) : (put_count -= 1) {
223 std.os.time.sleep(1); // let the os scheduler be our fuzz
223 std.time.sleep(1); // let the os scheduler be our fuzz
224224 const x = @bitCast(i32, r.random.scalar(u32));
225225 const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;
226226 node.* = Queue(i32).Node{
......@@ -239,7 +239,7 @@ fn startGets(ctx: *Context) u8 {
239239 const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
240240
241241 while (ctx.queue.get()) |node| {
242 std.os.time.sleep(1); // let the os scheduler be our fuzz
242 std.time.sleep(1); // let the os scheduler be our fuzz
243243 _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
244244 _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
245245 }
std/atomic/stack.zig+2-2
......@@ -154,7 +154,7 @@ fn startPuts(ctx: *Context) u8 {
154154 var put_count: usize = puts_per_thread;
155155 var r = std.rand.DefaultPrng.init(0xdeadbeef);
156156 while (put_count != 0) : (put_count -= 1) {
157 std.os.time.sleep(1); // let the os scheduler be our fuzz
157 std.time.sleep(1); // let the os scheduler be our fuzz
158158 const x = @bitCast(i32, r.random.scalar(u32));
159159 const node = ctx.allocator.create(Stack(i32).Node) catch unreachable;
160160 node.* = Stack(i32).Node{
......@@ -172,7 +172,7 @@ fn startGets(ctx: *Context) u8 {
172172 const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
173173
174174 while (ctx.stack.pop()) |node| {
175 std.os.time.sleep(1); // let the os scheduler be our fuzz
175 std.time.sleep(1); // let the os scheduler be our fuzz
176176 _ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
177177 _ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
178178 }
std/build.zig+3-2
......@@ -14,6 +14,7 @@ const Term = os.ChildProcess.Term;
1414const BufSet = std.BufSet;
1515const BufMap = std.BufMap;
1616const fmt_lib = std.fmt;
17const File = std.fs.File;
1718
1819pub const FmtStep = @import("build/fmt.zig").FmtStep;
1920
......@@ -668,10 +669,10 @@ pub const Builder = struct {
668669 }
669670
670671 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);
672673 }
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 {
675676 if (self.verbose) {
676677 warn("cp {} {}\n", source_path, dest_path);
677678 }
std/c.zig+1-1
......@@ -75,7 +75,7 @@ pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usi
7575pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;
7676pub extern "c" fn socket(domain: c_int, sock_type: c_int, protocol: c_int) c_int;
7777pub 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;
7979pub extern "c" fn openat(fd: c_int, path: [*]const u8, flags: c_int) c_int;
8080pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
8181pub extern "c" fn setuid(uid: c_uint) c_int;
std/child_process.zig+28-64
......@@ -3,7 +3,7 @@ const cstr = std.cstr;
33const unicode = std.unicode;
44const io = std.io;
55const os = std.os;
6const posix = os.posix;
6const File = std.fs.File;
77const windows = os.windows;
88const mem = std.mem;
99const debug = std.debug;
......@@ -23,9 +23,9 @@ pub const ChildProcess = struct {
2323
2424 pub allocator: *mem.Allocator,
2525
26 pub stdin: ?os.File,
27 pub stdout: ?os.File,
28 pub stderr: ?os.File,
26 pub stdin: ?File,
27 pub stdout: ?File,
28 pub stderr: ?File,
2929
3030 pub term: ?(SpawnError!Term),
3131
......@@ -148,12 +148,7 @@ pub const ChildProcess = struct {
148148 return term;
149149 }
150150
151 if (!windows.TerminateProcess(self.handle, exit_code)) {
152 const err = windows.GetLastError();
153 return switch (err) {
154 else => os.unexpectedErrorWindows(err),
155 };
156 }
151 try windows.TerminateProcess(self.handle, exit_code);
157152 try self.waitUnwrappedWindows();
158153 return self.term.?;
159154 }
......@@ -163,16 +158,7 @@ pub const ChildProcess = struct {
163158 self.cleanupStreams();
164159 return term;
165160 }
166 const ret = posix.kill(self.pid, posix.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 }
161 try os.kill(self.pid, os.SIGTERM);
176162 self.waitUnwrapped();
177163 return self.term.?;
178164 }
......@@ -267,19 +253,9 @@ pub const ChildProcess = struct {
267253 }
268254
269255 fn waitUnwrapped(self: *ChildProcess) void {
270 var status: i32 = undefined;
271 while (true) {
272 const err = posix.getErrno(posix.waitpid(self.pid, &status, 0));
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 }
256 const status = os.waitpid(self.pid, 0);
257 self.cleanupStreams();
258 self.handleWaitResult(status);
283259 }
284260
285261 fn handleWaitResult(self: *ChildProcess, status: i32) void {
......@@ -324,34 +300,34 @@ pub const ChildProcess = struct {
324300 }
325301
326302 fn statusToTerm(status: i32) Term {
327 return if (posix.WIFEXITED(status))
328 Term{ .Exited = posix.WEXITSTATUS(status) }
329 else if (posix.WIFSIGNALED(status))
330 Term{ .Signal = posix.WTERMSIG(status) }
331 else if (posix.WIFSTOPPED(status))
332 Term{ .Stopped = posix.WSTOPSIG(status) }
303 return if (os.WIFEXITED(status))
304 Term{ .Exited = os.WEXITSTATUS(status) }
305 else if (os.WIFSIGNALED(status))
306 Term{ .Signal = os.WTERMSIG(status) }
307 else if (os.WIFSTOPPED(status))
308 Term{ .Stopped = os.WSTOPSIG(status) }
333309 else
334310 Term{ .Unknown = status };
335311 }
336312
337313 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;
339315 errdefer if (self.stdin_behavior == StdIo.Pipe) {
340316 destroyPipe(stdin_pipe);
341317 };
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;
344320 errdefer if (self.stdout_behavior == StdIo.Pipe) {
345321 destroyPipe(stdout_pipe);
346322 };
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;
349325 errdefer if (self.stderr_behavior == StdIo.Pipe) {
350326 destroyPipe(stderr_pipe);
351327 };
352328
353329 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;
355331 defer {
356332 if (any_ignore) os.close(dev_null_fd);
357333 }
......@@ -372,7 +348,7 @@ pub const ChildProcess = struct {
372348
373349 // This pipe is used to communicate errors between the time of fork
374350 // and execve from the child process to the parent process.
375 const err_pipe = try makePipe();
351 const err_pipe = try os.pipe();
376352 errdefer destroyPipe(err_pipe);
377353
378354 const pid_result = try posix.fork();
......@@ -413,17 +389,17 @@ pub const ChildProcess = struct {
413389 // we are the parent
414390 const pid = @intCast(i32, pid_result);
415391 if (self.stdin_behavior == StdIo.Pipe) {
416 self.stdin = os.File.openHandle(stdin_pipe[1]);
392 self.stdin = File.openHandle(stdin_pipe[1]);
417393 } else {
418394 self.stdin = null;
419395 }
420396 if (self.stdout_behavior == StdIo.Pipe) {
421 self.stdout = os.File.openHandle(stdout_pipe[0]);
397 self.stdout = File.openHandle(stdout_pipe[0]);
422398 } else {
423399 self.stdout = null;
424400 }
425401 if (self.stderr_behavior == StdIo.Pipe) {
426 self.stderr = os.File.openHandle(stderr_pipe[0]);
402 self.stderr = File.openHandle(stderr_pipe[0]);
427403 } else {
428404 self.stderr = null;
429405 }
......@@ -608,17 +584,17 @@ pub const ChildProcess = struct {
608584 };
609585
610586 if (g_hChildStd_IN_Wr) |h| {
611 self.stdin = os.File.openHandle(h);
587 self.stdin = File.openHandle(h);
612588 } else {
613589 self.stdin = null;
614590 }
615591 if (g_hChildStd_OUT_Rd) |h| {
616 self.stdout = os.File.openHandle(h);
592 self.stdout = File.openHandle(h);
617593 } else {
618594 self.stdout = null;
619595 }
620596 if (g_hChildStd_ERR_Rd) |h| {
621 self.stderr = os.File.openHandle(h);
597 self.stderr = File.openHandle(h);
622598 } else {
623599 self.stderr = null;
624600 }
......@@ -751,18 +727,6 @@ fn windowsMakePipeOut(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *const
751727 wr.* = wr_h;
752728}
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
766730fn destroyPipe(pipe: [2]i32) void {
767731 os.close(pipe[0]);
768732 os.close(pipe[1]);
......@@ -778,12 +742,12 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
778742const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
779743
780744fn writeIntFd(fd: i32, value: ErrInt) !void {
781 const stream = &os.File.openHandle(fd).outStream().stream;
745 const stream = &File.openHandle(fd).outStream().stream;
782746 stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
783747}
784748
785749fn readIntFd(fd: i32) !ErrInt {
786 const stream = &os.File.openHandle(fd).inStream().stream;
750 const stream = &File.openHandle(fd).inStream().stream;
787751 return stream.readIntNative(ErrInt) catch return error.SystemResources;
788752}
789753
std/coff.zig+3-2
......@@ -3,6 +3,7 @@ const std = @import("std.zig");
33const io = std.io;
44const mem = std.mem;
55const os = std.os;
6const File = std.fs.File;
67
78const ArrayList = std.ArrayList;
89
......@@ -28,7 +29,7 @@ pub const CoffError = error{
2829};
2930
3031pub const Coff = struct {
31 in_file: os.File,
32 in_file: File,
3233 allocator: *mem.Allocator,
3334
3435 coff_header: CoffHeader,
......@@ -77,7 +78,7 @@ pub const Coff = struct {
7778 try self.loadOptionalHeader(&file_stream);
7879 }
7980
80 fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
81 fn loadOptionalHeader(self: *Coff, file_stream: *File.InStream) !void {
8182 const in = &file_stream.stream;
8283 self.pe_header.magic = try in.readIntLittle(u16);
8384 // For now we're only interested in finding the reference to the .pdb,
std/crypto/throughput_test.zig+1-1
......@@ -1,6 +1,6 @@
11const builtin = @import("builtin");
22const std = @import("std");
3const time = std.os.time;
3const time = std.time;
44const Timer = time.Timer;
55const crypto = @import("../crypto.zig");
66
std/debug.zig+7-6
......@@ -12,6 +12,7 @@ const windows = os.windows;
1212const ArrayList = std.ArrayList;
1313const builtin = @import("builtin");
1414const maxInt = std.math.maxInt;
15const File = std.fs.File;
1516
1617const leb = @import("debug/leb128.zig");
1718
......@@ -36,10 +37,10 @@ const Module = struct {
3637
3738/// Tries to write to stderr, unbuffered, and ignores any error returned.
3839/// Does not append a newline.
39var stderr_file: os.File = undefined;
40var stderr_file_out_stream: os.File.OutStream = undefined;
40var stderr_file: File = 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;
4344var stderr_mutex = std.Mutex.init();
4445pub fn warn(comptime fmt: []const u8, args: ...) void {
4546 const held = stderr_mutex.acquire();
......@@ -48,7 +49,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {
4849 stderr.print(fmt, args) catch return;
4950}
5051
51pub fn getStderrStream() !*io.OutStream(os.File.WriteError) {
52pub fn getStderrStream() !*io.OutStream(File.WriteError) {
5253 if (stderr_stream) |st| {
5354 return st;
5455 } else {
......@@ -1003,7 +1004,7 @@ pub fn openElfDebugInfo(
10031004
10041005fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
10051006 const S = struct {
1006 var self_exe_file: os.File = undefined;
1007 var self_exe_file: File = undefined;
10071008 var self_exe_mmap_seekable: io.SliceSeekableInStream = undefined;
10081009 };
10091010
......@@ -1112,7 +1113,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
11121113}
11131114
11141115fn 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);
11161117 defer f.close();
11171118 // TODO fstat and make sure that the file has the correct size
11181119
std/dynamic_library.zig+13-15
......@@ -1,5 +1,4 @@
11const builtin = @import("builtin");
2const Os = builtin.Os;
32
43const std = @import("std.zig");
54const mem = std.mem;
......@@ -8,14 +7,13 @@ const os = std.os;
87const assert = std.debug.assert;
98const testing = std.testing;
109const elf = std.elf;
11const linux = os.linux;
1210const windows = os.windows;
1311const win_util = @import("os/windows/util.zig");
1412const maxInt = std.math.maxInt;
1513
1614pub const DynLib = switch (builtin.os) {
17 Os.linux => LinuxDynLib,
18 Os.windows => WindowsDynLib,
15 .linux => LinuxDynLib,
16 .windows => WindowsDynLib,
1917 else => void,
2018};
2119
......@@ -110,20 +108,20 @@ pub const LinuxDynLib = struct {
110108
111109 /// Trusts the file
112110 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);
114112 errdefer std.os.close(fd);
115113
116114 const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
117115
118 const addr = linux.mmap(
116 const addr = os.mmap(
119117 null,
120118 size,
121 linux.PROT_READ | linux.PROT_EXEC,
122 linux.MAP_PRIVATE | linux.MAP_LOCKED,
119 os.PROT_READ | os.PROT_EXEC,
120 os.MAP_PRIVATE | os.MAP_LOCKED,
123121 fd,
124122 0,
125123 );
126 errdefer _ = linux.munmap(addr, size);
124 errdefer os.munmap(addr, size);
127125
128126 const bytes = @intToPtr([*]align(mem.page_size) u8, addr)[0..size];
129127
......@@ -136,7 +134,7 @@ pub const LinuxDynLib = struct {
136134 }
137135
138136 pub fn close(self: *DynLib) void {
139 _ = linux.munmap(self.map_addr, self.map_size);
137 os.munmap(self.map_addr, self.map_size);
140138 std.os.close(self.fd);
141139 self.* = undefined;
142140 }
......@@ -149,7 +147,7 @@ pub const LinuxDynLib = struct {
149147pub const ElfLib = struct {
150148 strings: [*]u8,
151149 syms: [*]elf.Sym,
152 hashtab: [*]linux.Elf_Symndx,
150 hashtab: [*]os.Elf_Symndx,
153151 versym: ?[*]u16,
154152 verdef: ?*elf.Verdef,
155153 base: usize,
......@@ -184,7 +182,7 @@ pub const ElfLib = struct {
184182
185183 var maybe_strings: ?[*]u8 = null;
186184 var maybe_syms: ?[*]elf.Sym = null;
187 var maybe_hashtab: ?[*]linux.Elf_Symndx = null;
185 var maybe_hashtab: ?[*]os.Elf_Symndx = null;
188186 var maybe_versym: ?[*]u16 = null;
189187 var maybe_verdef: ?*elf.Verdef = null;
190188
......@@ -195,7 +193,7 @@ pub const ElfLib = struct {
195193 switch (dynv[i]) {
196194 elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
197195 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),
199197 elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
200198 elf.DT_VERDEF => maybe_verdef = @intToPtr(*elf.Verdef, p),
201199 else => {},
......@@ -283,8 +281,8 @@ pub const WindowsDynLib = struct {
283281
284282test "dynamic_library" {
285283 const libname = switch (builtin.os) {
286 Os.linux => "invalid_so.so",
287 Os.windows => "invalid_dll.dll",
284 .linux => "invalid_so.so",
285 .windows => "invalid_dll.dll",
288286 else => return,
289287 };
290288
std/elf.zig+3-2
......@@ -6,6 +6,7 @@ const math = std.math;
66const mem = std.mem;
77const debug = std.debug;
88const InStream = std.stream.InStream;
9const File = std.fs.File;
910
1011pub const AT_NULL = 0;
1112pub const AT_IGNORE = 1;
......@@ -367,7 +368,7 @@ pub const Elf = struct {
367368 string_section: *SectionHeader,
368369 section_headers: []SectionHeader,
369370 allocator: *mem.Allocator,
370 prealloc_file: os.File,
371 prealloc_file: File,
371372
372373 /// Call close when done.
373374 pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {
......@@ -375,7 +376,7 @@ pub const Elf = struct {
375376 }
376377
377378 /// 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 {
379380 @compileError("TODO implement");
380381 }
381382
std/event/fs.zig+22-21
......@@ -9,6 +9,7 @@ const posix = os.posix;
99const windows = os.windows;
1010const Loop = event.Loop;
1111const fd_t = posix.fd_t;
12const File = std.fs.File;
1213
1314pub const RequestNode = std.atomic.Queue(Request).Node;
1415
......@@ -52,20 +53,20 @@ pub const Request = struct {
5253 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
5354 path: []const u8,
5455 flags: u32,
55 mode: os.File.Mode,
56 mode: File.Mode,
5657 result: Error!fd_t,
5758
58 pub const Error = os.File.OpenError;
59 pub const Error = File.OpenError;
5960 };
6061
6162 pub const WriteFile = struct {
6263 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
6364 path: []const u8,
6465 contents: []const u8,
65 mode: os.File.Mode,
66 mode: File.Mode,
6667 result: Error!void,
6768
68 pub const Error = os.File.OpenError || os.File.WriteError;
69 pub const Error = File.OpenError || File.WriteError;
6970 };
7071
7172 pub const Close = struct {
......@@ -74,7 +75,7 @@ pub const Request = struct {
7475 };
7576};
7677
77pub const PWriteVError = error{OutOfMemory} || os.File.WriteError;
78pub const PWriteVError = error{OutOfMemory} || File.WriteError;
7879
7980/// data - just the inner references - must live until pwritev promise completes.
8081pub async fn pwritev(loop: *Loop, fd: fd_t, data: []const []const u8, offset: usize) PWriteVError!void {
......@@ -209,7 +210,7 @@ pub async fn pwritevPosix(
209210 return req_node.data.msg.PWriteV.result;
210211}
211212
212pub const PReadVError = error{OutOfMemory} || os.File.ReadError;
213pub const PReadVError = error{OutOfMemory} || File.ReadError;
213214
214215/// data - just the inner references - must live until preadv promise completes.
215216pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PReadVError!usize {
......@@ -361,8 +362,8 @@ pub async fn openPosix(
361362 loop: *Loop,
362363 path: []const u8,
363364 flags: u32,
364 mode: os.File.Mode,
365) os.File.OpenError!fd_t {
365 mode: File.Mode,
366) File.OpenError!fd_t {
366367 // workaround for https://github.com/ziglang/zig/issues/1194
367368 suspend {
368369 resume @handle();
......@@ -401,11 +402,11 @@ pub async fn openPosix(
401402 return req_node.data.msg.Open.result;
402403}
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 {
405406 switch (builtin.os) {
406407 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
407408 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);
409410 },
410411
411412 builtin.Os.windows => return os.windowsOpen(
......@@ -422,12 +423,12 @@ pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
422423
423424/// Creates if does not exist. Truncates the file if it exists.
424425/// Uses the default mode.
425pub async fn openWrite(loop: *Loop, path: []const u8) os.File.OpenError!fd_t {
426 return await (async openWriteMode(loop, path, os.File.default_mode) catch unreachable);
426pub async fn openWrite(loop: *Loop, path: []const u8) File.OpenError!fd_t {
427 return await (async openWriteMode(loop, path, File.default_mode) catch unreachable);
427428}
428429
429430/// 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 {
431432 switch (builtin.os) {
432433 builtin.Os.macosx,
433434 builtin.Os.linux,
......@@ -435,7 +436,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
435436 builtin.Os.netbsd,
436437 => {
437438 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);
439440 },
440441 builtin.Os.windows => return os.windowsOpen(
441442 path,
......@@ -452,8 +453,8 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
452453pub async fn openReadWrite(
453454 loop: *Loop,
454455 path: []const u8,
455 mode: os.File.Mode,
456) os.File.OpenError!fd_t {
456 mode: File.Mode,
457) File.OpenError!fd_t {
457458 switch (builtin.os) {
458459 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd, builtin.Os.netbsd => {
459460 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
......@@ -605,11 +606,11 @@ pub const CloseOperation = struct {
605606/// contents must remain alive until writeFile completes.
606607/// TODO make this atomic or provide writeFileAtomic and rename this one to writeFileTruncate
607608pub 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);
609610}
610611
611612/// 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 {
613614 switch (builtin.os) {
614615 builtin.Os.linux,
615616 builtin.Os.macosx,
......@@ -634,7 +635,7 @@ async fn writeFileWindows(loop: *Loop, path: []const u8, contents: []const u8) !
634635 try await (async pwriteWindows(loop, handle, contents, 0) catch unreachable);
635636}
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 {
638639 // workaround for https://github.com/ziglang/zig/issues/1194
639640 suspend {
640641 resume @handle();
......@@ -1363,7 +1364,7 @@ async fn testFsWatch(loop: *Loop) !void {
13631364 defer if (!ev_consumed) cancel ev;
13641365
13651366 // 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);
13671368 {
13681369 defer os.close(fd);
13691370
......@@ -1390,7 +1391,7 @@ pub const OutStream = struct {
13901391 loop: *Loop,
13911392 offset: usize,
13921393
1393 pub const Error = os.File.WriteError;
1394 pub const Error = File.WriteError;
13941395 pub const Stream = event.io.OutStream(Error);
13951396
13961397 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 {
155155}
156156
157157async fn sleepALittle(count: *usize) void {
158 std.os.time.sleep(1 * std.os.time.millisecond);
158 std.time.sleep(1 * std.time.millisecond);
159159 _ = @atomicRmw(usize, count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
160160}
161161
std/event/loop.zig+2-2
......@@ -789,13 +789,13 @@ pub const Loop = struct {
789789 msg.result = os.posix_preadv(msg.fd, msg.iov.ptr, msg.iov.len, msg.offset);
790790 },
791791 @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);
793793 },
794794 @TagType(fs.Request.Msg).Close => |*msg| os.close(msg.fd),
795795 @TagType(fs.Request.Msg).WriteFile => |*msg| blk: {
796796 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT |
797797 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| {
799799 msg.result = err;
800800 break :blk;
801801 };
std/event/net.zig+8-7
......@@ -6,11 +6,12 @@ const mem = std.mem;
66const os = std.os;
77const posix = os.posix;
88const Loop = std.event.Loop;
9const File = std.fs.File;
910
1011const fd_t = posix.fd_t;
1112
1213pub 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
1516 loop: *Loop,
1617 sockfd: ?i32,
......@@ -42,7 +43,7 @@ pub const Server = struct {
4243 pub fn listen(
4344 self: *Server,
4445 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,
4647 ) !void {
4748 self.handleRequestFn = handleRequestFn;
4849
......@@ -83,7 +84,7 @@ pub const Server = struct {
8384 suspend; // we will get resumed by epoll_wait in the event loop
8485 continue;
8586 }
86 var socket = os.File.openHandle(accepted_fd);
87 var socket = File.openHandle(accepted_fd);
8788 _ = async<self.loop.allocator> self.handleRequestFn(self, &accepted_addr, socket) catch |err| switch (err) {
8889 error.OutOfMemory => {
8990 socket.close();
......@@ -250,7 +251,7 @@ pub async fn readv(loop: *Loop, fd: fd_t, data: []const []u8) !usize {
250251 return await (async readvPosix(loop, fd, iovecs.ptr, data.len) catch unreachable);
251252}
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 {
254255 var address = _address.*; // TODO https://github.com/ziglang/zig/issues/1592
255256
256257 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 {
260261 try await try async loop.linuxWaitFd(sockfd, posix.EPOLLIN | posix.EPOLLOUT | posix.EPOLLET);
261262 try os.posixGetSockOptConnectError(sockfd);
262263
263 return os.File.openHandle(sockfd);
264 return File.openHandle(sockfd);
264265}
265266
266267test "listen on a port, send bytes, receive bytes" {
......@@ -276,7 +277,7 @@ test "listen on a port, send bytes, receive bytes" {
276277 tcp_server: Server,
277278
278279 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 {
280281 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
281282 var socket = _socket; // TODO https://github.com/ziglang/zig/issues/1592
282283 defer socket.close();
......@@ -289,7 +290,7 @@ test "listen on a port, send bytes, receive bytes" {
289290 cancel @handle();
290291 }
291292 }
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 {
293294 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/1592
294295 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 {
271271
272272 var i: usize = 0;
273273 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);
275275 const lock_promise = async lock.acquireWrite() catch @panic("out of memory");
276276 const handle = await lock_promise;
277277 defer handle.release();
......@@ -286,7 +286,7 @@ async fn writeRunner(lock: *RwLock) void {
286286
287287async fn readRunner(lock: *RwLock) void {
288288 suspend; // resumed by onNextTick
289 std.os.time.sleep(1);
289 std.time.sleep(1);
290290
291291 var i: usize = 0;
292292 while (i < shared_test_data.len) : (i += 1) {
std/fs.zig+175-192
......@@ -11,6 +11,7 @@ pub const deleteFile = os.unlink;
1111pub const deleteFileC = os.unlinkC;
1212pub const rename = os.rename;
1313pub const renameC = os.renameC;
14pub const renameW = os.renameW;
1415pub const changeCurDir = os.chdir;
1516pub const changeCurDirC = os.chdirC;
1617pub const realpath = os.realpath;
......@@ -25,24 +26,24 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE
2526/// fit into a UTF-8 encoded array of this length.
2627/// path being too long if it is this 0long
2728pub 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,
2930 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
3031 // If it would require 4 UTF-8 bytes, then there would be a surrogate
3132 // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
3233 // +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,
3435 else => @compileError("Unsupported OS"),
3536};
3637
3738/// The result is a slice of `out_buffer`, from index `0`.
3839pub fn getCwd(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
39 return posix.getcwd(out_buffer);
40 return os.getcwd(out_buffer);
4041}
4142
4243/// Caller must free the returned memory.
4344pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
4445 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));
4647}
4748
4849test "getCwdAlloc" {
......@@ -90,7 +91,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
9091/// in the same directory as dest_path.
9192/// Destination file will have the same mode as the source file.
9293pub 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);
9495 defer in_file.close();
9596
9697 const mode = try in_file.mode();
......@@ -113,7 +114,7 @@ pub fn copyFile(source_path: []const u8, dest_path: []const u8) !void {
113114/// merged and readily available,
114115/// there is a possibility of power loss or application termination leaving temporary files present
115116pub 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);
117118 defer in_file.close();
118119
119120 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
130131}
131132
132133pub const AtomicFile = struct {
133 file: os.File,
134 file: File,
134135 tmp_path_buf: [MAX_PATH_BYTES]u8,
135136 dest_path: []const u8,
136137 finished: bool,
137138
138 const InitError = os.File.OpenError;
139 const InitError = File.OpenError;
139140
140141 /// dest_path must remain valid for the lifetime of AtomicFile
141142 /// call finish to atomically replace dest_path with contents
......@@ -161,7 +162,7 @@ pub const AtomicFile = struct {
161162 try getRandomBytes(rand_buf[0..]);
162163 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) {
165166 error.PathAlreadyExists => continue,
166167 // TODO zig should figure out that this error set does not include PathAlreadyExists since
167168 // it is handled in the above switch
......@@ -190,16 +191,13 @@ pub const AtomicFile = struct {
190191 assert(!self.finished);
191192 self.file.close();
192193 self.finished = true;
193 if (is_posix) {
194 const dest_path_c = try toPosixPath(self.dest_path);
195 return renameC(&self.tmp_path_buf, &dest_path_c);
196 } else if (is_windows) {
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");
194 if (os.windows.is_the_target) {
195 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
196 const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
197 return os.renameW(&tmp_path_w, &dest_path_w);
202198 }
199 const dest_path_c = try os.toPosixPath(self.dest_path);
200 return os.renameC(&self.tmp_path_buf, &dest_path_c);
203201 }
204202};
205203
......@@ -207,17 +205,17 @@ const default_new_dir_mode = 0o755;
207205
208206/// Create a new directory.
209207pub 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);
211209}
212210
213211/// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.
214212pub 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);
216214}
217215
218216/// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.
219217pub 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);
221219}
222220
223221/// 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 {
260258/// Returns `error.DirNotEmpty` if the directory is not empty.
261259/// To delete a directory recursively, see `deleteTree`.
262260pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
263 return posix.rmdir(dir_path);
261 return os.rmdir(dir_path);
264262}
265263
266264/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.
267265pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
268 return posix.rmdirC(dir_path);
266 return os.rmdirC(dir_path);
269267}
270268
271269/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.
272270pub fn deleteDirW(dir_path: [*]const u16) DeleteDirError!void {
273 return posix.rmdirW(dir_path);
271 return os.rmdirW(dir_path);
274272}
275273
276274/// Whether ::full_path describes a symlink, file, or directory, this function
......@@ -383,22 +381,22 @@ pub const Dir = struct {
383381 allocator: *Allocator,
384382
385383 pub const Handle = switch (builtin.os) {
386 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => struct {
384 .macosx, .ios, .freebsd, .netbsd => struct {
387385 fd: i32,
388386 seek: i64,
389387 buf: []u8,
390388 index: usize,
391389 end_index: usize,
392390 },
393 Os.linux => struct {
391 .linux => struct {
394392 fd: i32,
395393 buf: []u8,
396394 index: usize,
397395 end_index: usize,
398396 },
399 Os.windows => struct {
400 handle: windows.HANDLE,
401 find_file_data: windows.WIN32_FIND_DATAW,
397 .windows => struct {
398 handle: os.windows.HANDLE,
399 find_file_data: os.windows.WIN32_FIND_DATAW,
402400 first: bool,
403401 name_data: [256]u8,
404402 },
......@@ -449,9 +447,9 @@ pub const Dir = struct {
449447 return Dir{
450448 .allocator = allocator,
451449 .handle = switch (builtin.os) {
452 Os.windows => blk: {
453 var find_file_data: windows.WIN32_FIND_DATAW = undefined;
454 const handle = try windows_util.windowsFindFirstFile(dir_path, &find_file_data);
450 .windows => blk: {
451 var find_file_data: os.windows.WIN32_FIND_DATAW = undefined;
452 const handle = try os.windows.FindFirstFile(dir_path, &find_file_data);
455453 break :blk Handle{
456454 .handle = handle,
457455 .find_file_data = find_file_data, // TODO guaranteed copy elision
......@@ -459,23 +457,15 @@ pub const Dir = struct {
459457 .name_data = undefined,
460458 };
461459 },
462 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => Handle{
463 .fd = try posixOpen(
464 dir_path,
465 posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
466 0,
467 ),
460 .macosx, .ios, .freebsd, .netbsd => Handle{
461 .fd = try os.open(dir_path, os.O_RDONLY | os.O_NONBLOCK | os.O_DIRECTORY | os.O_CLOEXEC, 0),
468462 .seek = 0,
469463 .index = 0,
470464 .end_index = 0,
471465 .buf = []u8{},
472466 },
473 Os.linux => Handle{
474 .fd = try posixOpen(
475 dir_path,
476 posix.O_RDONLY | posix.O_DIRECTORY | posix.O_CLOEXEC,
477 0,
478 ),
467 .linux => Handle{
468 .fd = try os.open(dir_path, os.O_RDONLY | os.O_DIRECTORY | os.O_CLOEXEC, 0),
479469 .index = 0,
480470 .end_index = 0,
481471 .buf = []u8{},
......@@ -486,27 +476,22 @@ pub const Dir = struct {
486476 }
487477
488478 pub fn close(self: *Dir) void {
489 switch (builtin.os) {
490 Os.windows => {
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"),
479 if (os.windows.is_the_target) {
480 return os.windows.FindClose(self.handle.handle);
498481 }
482 self.allocator.free(self.handle.buf);
483 os.close(self.handle.fd);
499484 }
500485
501486 /// Memory such as file names referenced in this returned entry becomes invalid
502487 /// with subsequent calls to next, as well as when this `Dir` is deinitialized.
503488 pub fn next(self: *Dir) !?Entry {
504489 switch (builtin.os) {
505 Os.linux => return self.nextLinux(),
506 Os.macosx, Os.ios => return self.nextDarwin(),
507 Os.windows => return self.nextWindows(),
508 Os.freebsd => return self.nextFreebsd(),
509 Os.netbsd => return self.nextFreebsd(),
490 .linux => return self.nextLinux(),
491 .macosx, .ios => return self.nextDarwin(),
492 .windows => return self.nextWindows(),
493 .freebsd => return self.nextBsd(),
494 .netbsd => return self.nextBsd(),
510495 else => @compileError("unimplemented"),
511496 }
512497 }
......@@ -519,18 +504,23 @@ pub const Dir = struct {
519504 }
520505
521506 while (true) {
522 const result = system.__getdirentries64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);
523 if (result == 0) return null;
524 if (result < 0) {
525 switch (system.getErrno(result)) {
526 posix.EBADF => unreachable,
527 posix.EFAULT => unreachable,
528 posix.ENOTDIR => unreachable,
529 posix.EINVAL => {
507 const rc = os.system.__getdirentries64(
508 self.handle.fd,
509 self.handle.buf.ptr,
510 self.handle.buf.len,
511 &self.handle.seek,
512 );
513 if (rc == 0) return null;
514 if (rc < 0) {
515 switch (os.errno(rc)) {
516 os.EBADF => unreachable,
517 os.EFAULT => unreachable,
518 os.ENOTDIR => unreachable,
519 os.EINVAL => {
530520 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
531521 continue;
532522 },
533 else => return unexpectedErrorPosix(err),
523 else => |err| return os.unexpectedErrno(err),
534524 }
535525 }
536526 self.handle.index = 0;
......@@ -538,7 +528,7 @@ pub const Dir = struct {
538528 break;
539529 }
540530 }
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]);
542532 const next_index = self.handle.index + darwin_entry.d_reclen;
543533 self.handle.index = next_index;
544534
......@@ -549,14 +539,14 @@ pub const Dir = struct {
549539 }
550540
551541 const entry_kind = switch (darwin_entry.d_type) {
552 posix.DT_BLK => Entry.Kind.BlockDevice,
553 posix.DT_CHR => Entry.Kind.CharacterDevice,
554 posix.DT_DIR => Entry.Kind.Directory,
555 posix.DT_FIFO => Entry.Kind.NamedPipe,
556 posix.DT_LNK => Entry.Kind.SymLink,
557 posix.DT_REG => Entry.Kind.File,
558 posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
559 posix.DT_WHT => Entry.Kind.Whiteout,
542 os.DT_BLK => Entry.Kind.BlockDevice,
543 os.DT_CHR => Entry.Kind.CharacterDevice,
544 os.DT_DIR => Entry.Kind.Directory,
545 os.DT_FIFO => Entry.Kind.NamedPipe,
546 os.DT_LNK => Entry.Kind.SymLink,
547 os.DT_REG => Entry.Kind.File,
548 os.DT_SOCK => Entry.Kind.UnixDomainSocket,
549 os.DT_WHT => Entry.Kind.Whiteout,
560550 else => Entry.Kind.Unknown,
561551 };
562552 return Entry{
......@@ -571,7 +561,7 @@ pub const Dir = struct {
571561 if (self.handle.first) {
572562 self.handle.first = false;
573563 } 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))
575565 return null;
576566 }
577567 const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);
......@@ -582,9 +572,9 @@ pub const Dir = struct {
582572 const name_utf8 = self.handle.name_data[0..name_utf8_len];
583573 const kind = blk: {
584574 const attrs = self.handle.find_file_data.dwFileAttributes;
585 if (attrs & windows.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;
586 if (attrs & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;
587 if (attrs & windows.FILE_ATTRIBUTE_NORMAL != 0) break :blk Entry.Kind.File;
575 if (attrs & os.windows.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk Entry.Kind.Directory;
576 if (attrs & os.windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk Entry.Kind.SymLink;
577 if (attrs & os.windows.FILE_ATTRIBUTE_NORMAL != 0) break :blk Entry.Kind.File;
588578 break :blk Entry.Kind.Unknown;
589579 };
590580 return Entry{
......@@ -602,25 +592,25 @@ pub const Dir = struct {
602592 }
603593
604594 while (true) {
605 const result = posix.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
606 const err = posix.getErrno(result);
607 if (err > 0) {
608 switch (err) {
609 posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
610 posix.EINVAL => {
611 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
612 continue;
613 },
614 else => return unexpectedErrorPosix(err),
615 }
595 const rc = os.system.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
596 switch (os.errno(rc)) {
597 0 => {},
598 os.EBADF => unreachable,
599 os.EFAULT => unreachable,
600 os.ENOTDIR => unreachable,
601 os.EINVAL => {
602 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
603 continue;
604 },
605 else => |err| return os.unexpectedErrno(err),
616606 }
617 if (result == 0) return null;
607 if (rc == 0) return null;
618608 self.handle.index = 0;
619 self.handle.end_index = result;
609 self.handle.end_index = rc;
620610 break;
621611 }
622612 }
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]);
624614 const next_index = self.handle.index + linux_entry.d_reclen;
625615 self.handle.index = next_index;
626616
......@@ -632,13 +622,13 @@ pub const Dir = struct {
632622 }
633623
634624 const entry_kind = switch (linux_entry.d_type) {
635 posix.DT_BLK => Entry.Kind.BlockDevice,
636 posix.DT_CHR => Entry.Kind.CharacterDevice,
637 posix.DT_DIR => Entry.Kind.Directory,
638 posix.DT_FIFO => Entry.Kind.NamedPipe,
639 posix.DT_LNK => Entry.Kind.SymLink,
640 posix.DT_REG => Entry.Kind.File,
641 posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
625 os.DT_BLK => Entry.Kind.BlockDevice,
626 os.DT_CHR => Entry.Kind.CharacterDevice,
627 os.DT_DIR => Entry.Kind.Directory,
628 os.DT_FIFO => Entry.Kind.NamedPipe,
629 os.DT_LNK => Entry.Kind.SymLink,
630 os.DT_REG => Entry.Kind.File,
631 os.DT_SOCK => Entry.Kind.UnixDomainSocket,
642632 else => Entry.Kind.Unknown,
643633 };
644634 return Entry{
......@@ -648,7 +638,7 @@ pub const Dir = struct {
648638 }
649639 }
650640
651 fn nextFreebsd(self: *Dir) !?Entry {
641 fn nextBsd(self: *Dir) !?Entry {
652642 start_over: while (true) {
653643 if (self.handle.index >= self.handle.end_index) {
654644 if (self.handle.buf.len == 0) {
......@@ -656,25 +646,30 @@ pub const Dir = struct {
656646 }
657647
658648 while (true) {
659 const result = posix.getdirentries(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);
660 const err = posix.getErrno(result);
661 if (err > 0) {
662 switch (err) {
663 posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
664 posix.EINVAL => {
665 self.handle.buf = try self.allocator.realloc(self.handle.buf, self.handle.buf.len * 2);
666 continue;
667 },
668 else => return unexpectedErrorPosix(err),
669 }
649 const rc = os.system.getdirentries(
650 self.handle.fd,
651 self.handle.buf.ptr,
652 self.handle.buf.len,
653 &self.handle.seek,
654 );
655 switch (os.errno(rc)) {
656 0 => {},
657 os.EBADF => unreachable,
658 os.EFAULT => unreachable,
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),
670665 }
671 if (result == 0) return null;
666 if (rc == 0) return null;
672667 self.handle.index = 0;
673 self.handle.end_index = result;
668 self.handle.end_index = @intCast(usize, rc);
674669 break;
675670 }
676671 }
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]);
678673 const next_index = self.handle.index + freebsd_entry.d_reclen;
679674 self.handle.index = next_index;
680675
......@@ -685,14 +680,14 @@ pub const Dir = struct {
685680 }
686681
687682 const entry_kind = switch (freebsd_entry.d_type) {
688 posix.DT_BLK => Entry.Kind.BlockDevice,
689 posix.DT_CHR => Entry.Kind.CharacterDevice,
690 posix.DT_DIR => Entry.Kind.Directory,
691 posix.DT_FIFO => Entry.Kind.NamedPipe,
692 posix.DT_LNK => Entry.Kind.SymLink,
693 posix.DT_REG => Entry.Kind.File,
694 posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
695 posix.DT_WHT => Entry.Kind.Whiteout,
683 os.DT_BLK => Entry.Kind.BlockDevice,
684 os.DT_CHR => Entry.Kind.CharacterDevice,
685 os.DT_DIR => Entry.Kind.Directory,
686 os.DT_FIFO => Entry.Kind.NamedPipe,
687 os.DT_LNK => Entry.Kind.SymLink,
688 os.DT_REG => Entry.Kind.File,
689 os.DT_SOCK => Entry.Kind.UnixDomainSocket,
690 os.DT_WHT => Entry.Kind.Whiteout,
696691 else => Entry.Kind.Unknown,
697692 };
698693 return Entry{
......@@ -705,52 +700,40 @@ pub const Dir = struct {
705700
706701/// Read value of a symbolic link.
707702/// The return value is a slice of buffer, from index `0`.
708pub fn readLink(buffer: *[posix.PATH_MAX]u8, pathname: []const u8) ![]u8 {
709 return posix.readlink(pathname, buffer);
703pub fn readLink(pathname: []const u8, buffer: *[os.PATH_MAX]u8) ![]u8 {
704 return os.readlink(pathname, buffer);
710705}
711706
712707/// Same as `readLink`, except the `pathname` parameter is null-terminated.
713pub fn readLinkC(buffer: *[posix.PATH_MAX]u8, pathname: [*]const u8) ![]u8 {
714 return posix.readlinkC(pathname, buffer);
708pub fn readLinkC(pathname: [*]const u8, buffer: *[os.PATH_MAX]u8) ![]u8 {
709 return os.readlinkC(pathname, buffer);
715710}
716711
717pub fn openSelfExe() !os.File {
718 switch (builtin.os) {
719 Os.linux => return os.File.openReadC(c"/proc/self/exe"),
720 Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
721 var buf: [MAX_PATH_BYTES]u8 = undefined;
722 const self_exe_path = try selfExePath(&buf);
723 buf[self_exe_path.len] = 0;
724 return os.File.openReadC(self_exe_path.ptr);
725 },
726 Os.windows => {
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"),
712pub const OpenSelfExeError = error{};
713
714pub fn openSelfExe() OpenSelfExeError!File {
715 if (os.linux.is_the_target) {
716 return File.openReadC(c"/proc/self/exe");
717 }
718 if (os.windows.is_the_target) {
719 var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
720 const wide_slice = try selfExePathW(&buf);
721 return File.openReadW(wide_slice.ptr);
732722 }
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);
733727}
734728
735729test "openSelfExe" {
736730 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(),
738732 else => return error.SkipZigTest, // Unsupported OS.
739733 }
740734}
741735
742pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {
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}
736pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;
754737
755738/// Get the path to the current executable.
756739/// If you only need the directory, use selfExeDirPath.
......@@ -763,39 +746,44 @@ pub fn selfExePathW(out_buffer: *[posix.PATH_MAX_WIDE]u16) ![]u16 {
763746/// been deleted, the file path looks something like `/a/b/c/exe (deleted)`.
764747/// TODO make the return type of this a null terminated pointer
765748pub 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 }
766755 switch (builtin.os) {
767 Os.linux => return readLink(out_buffer, "/proc/self/exe"),
768 Os.freebsd => {
769 var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC, posix.KERN_PROC_PATHNAME, -1 };
756 .linux => return os.readlinkC(c"/proc/self/exe", out_buffer),
757 .freebsd => {
758 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };
770759 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);
772761 // TODO could this slice from 0 to out_len instead?
773762 return mem.toSlice(u8, out_buffer);
774763 },
775 Os.netbsd => {
776 var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC_ARGS, -1, posix.KERN_PROC_PATHNAME };
764 .netbsd => {
765 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC_ARGS, -1, os.KERN_PROC_PATHNAME };
777766 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);
779768 // TODO could this slice from 0 to out_len instead?
780769 return mem.toSlice(u8, out_buffer);
781770 },
782 Os.windows => {
783 var utf16le_buf: [posix.PATH_MAX_WIDE]u16 = undefined;
771 .windows => {
772 var utf16le_buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
784773 const utf16le_slice = try selfExePathW(&utf16le_buf);
785774 // Trust that Windows gives us valid UTF-16LE.
786775 const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;
787776 return out_buffer[0..end_index];
788777 },
789 Os.macosx, Os.ios => {
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"),
778 else => @compileError("std.fs.selfExePath not supported for this target"),
796779 }
797780}
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
799787/// `selfExeDirPath` except allocates the result on the heap.
800788/// Caller owns returned memory.
801789pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
......@@ -806,31 +794,26 @@ pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
806794/// Get the directory path that contains the current executable.
807795/// Returned value is a slice of out_buffer.
808796pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
809 switch (builtin.os) {
810 Os.linux => {
811 // If the currently executing binary has been deleted,
812 // the file path looks something like `/a/b/c/exe (deleted)`
813 // This path cannot be opened, but it's valid for determining the directory
814 // the executable was in when it was run.
815 const full_exe_path = try readLinkC(out_buffer, c"/proc/self/exe");
816 // Assume that /proc/self/exe has an absolute path, and therefore dirname
817 // will not return null.
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"),
797 if (os.linux.is_the_target) {
798 // If the currently executing binary has been deleted,
799 // 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
801 // the executable was in when it was run.
802 const full_exe_path = try os.readlinkC(c"/proc/self/exe", out_buffer);
803 // Assume that /proc/self/exe has an absolute path, and therefore dirname
804 // will not return null.
805 return path.dirname(full_exe_path).?;
827806 }
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).?;
828811}
829812
830813/// `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 {
832815 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));
834817}
835818
836819test "" {
std/io.zig+6-6
......@@ -12,7 +12,7 @@ const meta = std.meta;
1212const trait = meta.trait;
1313const Buffer = std.Buffer;
1414const fmt = std.fmt;
15const File = std.os.File;
15const File = std.fs.File;
1616const testing = std.testing;
1717
1818const is_posix = builtin.os != builtin.Os.windows;
......@@ -963,8 +963,8 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
963963
964964pub const BufferedAtomicFile = struct {
965965 atomic_file: os.AtomicFile,
966 file_stream: os.File.OutStream,
967 buffered_stream: BufferedOutStream(os.File.WriteError),
966 file_stream: File.OutStream,
967 buffered_stream: BufferedOutStream(File.WriteError),
968968 allocator: *mem.Allocator,
969969
970970 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
......@@ -978,11 +978,11 @@ pub const BufferedAtomicFile = struct {
978978 };
979979 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);
982982 errdefer self.atomic_file.deinit();
983983
984984 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);
986986 return self;
987987 }
988988
......@@ -997,7 +997,7 @@ pub const BufferedAtomicFile = struct {
997997 try self.atomic_file.finish();
998998 }
999999
1000 pub fn stream(self: *BufferedAtomicFile) *OutStream(os.File.WriteError) {
1000 pub fn stream(self: *BufferedAtomicFile) *OutStream(File.WriteError) {
10011001 return &self.buffered_stream.stream;
10021002 }
10031003};
std/io/c_out_stream.zig+17-22
......@@ -1,13 +1,13 @@
11const std = @import("../std.zig");
2const os = std.os;
23const OutStream = std.io.OutStream;
34const builtin = @import("builtin");
4const posix = std.os.posix;
55
6/// TODO make std.os.FILE use *FILE when linking libc and this just becomes
7/// std.io.FileOutStream because std.os.File.write would do this when linking
6/// TODO make a proposal to make `std.fs.File` use *FILE when linking libc and this just becomes
7/// std.io.FileOutStream because std.fs.File.write would do this when linking
88/// libc.
99pub const COutStream = struct {
10 pub const Error = std.os.File.WriteError;
10 pub const Error = std.fs.File.WriteError;
1111 pub const Stream = OutStream(Error);
1212
1313 stream: Stream,
......@@ -24,25 +24,20 @@ pub const COutStream = struct {
2424 const self = @fieldParentPtr(COutStream, "stream", out_stream);
2525 const amt_written = std.c.fwrite(bytes.ptr, 1, bytes.len, self.c_file);
2626 if (amt_written == bytes.len) return;
27 // TODO errno on windows. should we have a posix layer for windows?
28 if (builtin.os == .windows) {
29 return error.InputOutput;
30 }
31 const errno = std.c._errno().*;
32 switch (errno) {
27 switch (std.c._errno().*) {
3328 0 => unreachable,
34 posix.EINVAL => unreachable,
35 posix.EFAULT => unreachable,
36 posix.EAGAIN => unreachable, // this is a blocking API
37 posix.EBADF => unreachable, // always a race condition
38 posix.EDESTADDRREQ => unreachable, // connect was never called
39 posix.EDQUOT => return error.DiskQuota,
40 posix.EFBIG => return error.FileTooBig,
41 posix.EIO => return error.InputOutput,
42 posix.ENOSPC => return error.NoSpaceLeft,
43 posix.EPERM => return error.AccessDenied,
44 posix.EPIPE => return error.BrokenPipe,
45 else => return std.os.unexpectedErrorPosix(@intCast(usize, errno)),
29 os.EINVAL => unreachable,
30 os.EFAULT => unreachable,
31 os.EAGAIN => unreachable, // this is a blocking API
32 os.EBADF => unreachable, // always a race condition
33 os.EDESTADDRREQ => unreachable, // connect was never called
34 os.EDQUOT => return error.DiskQuota,
35 os.EFBIG => return error.FileTooBig,
36 os.EIO => return error.InputOutput,
37 os.ENOSPC => return error.NoSpaceLeft,
38 os.EPERM => return error.AccessDenied,
39 os.EPIPE => return error.BrokenPipe,
40 else => return os.unexpectedErrno(@intCast(usize, errno)),
4641 }
4742 }
4843};
std/io/test.zig+12-11
......@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
12const std = @import("../std.zig");
23const io = std.io;
34const meta = std.meta;
......@@ -7,7 +8,7 @@ const expect = std.testing.expect;
78const expectError = std.testing.expectError;
89const mem = std.mem;
910const os = std.os;
10const builtin = @import("builtin");
11const File = std.fs.File;
1112
1213test "write a file, read it, then delete it" {
1314 var raw_bytes: [200 * 1024]u8 = undefined;
......@@ -18,11 +19,11 @@ test "write a file, read it, then delete it" {
1819 prng.random.bytes(data[0..]);
1920 const tmp_file_name = "temp_test_file.txt";
2021 {
21 var file = try os.File.openWrite(tmp_file_name);
22 var file = try File.openWrite(tmp_file_name);
2223 defer file.close();
2324
2425 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);
2627 const st = &buf_stream.stream;
2728 try st.print("begin");
2829 try st.write(data[0..]);
......@@ -32,15 +33,15 @@ test "write a file, read it, then delete it" {
3233
3334 {
3435 // 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| {
3637 unreachable;
3738 } else |err| {
38 std.debug.assert(err == os.File.OpenError.PathAlreadyExists);
39 std.debug.assert(err == File.OpenError.PathAlreadyExists);
3940 }
4041 }
4142
4243 {
43 var file = try os.File.openRead(tmp_file_name);
44 var file = try File.openRead(tmp_file_name);
4445 defer file.close();
4546
4647 const file_size = try file.getEndPos();
......@@ -48,7 +49,7 @@ test "write a file, read it, then delete it" {
4849 expect(file_size == expected_file_size);
4950
5051 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);
5253 const st = &buf_stream.stream;
5354 const contents = try st.readAllAlloc(allocator, 2 * 1024);
5455 defer allocator.free(contents);
......@@ -273,12 +274,12 @@ test "BitOutStream" {
273274test "BitStreams with File Stream" {
274275 const tmp_file_name = "temp_test_file.txt";
275276 {
276 var file = try os.File.openWrite(tmp_file_name);
277 var file = try File.openWrite(tmp_file_name);
277278 defer file.close();
278279
279280 var file_out = file.outStream();
280281 var file_out_stream = &file_out.stream;
281 const OutError = os.File.WriteError;
282 const OutError = File.WriteError;
282283 var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
283284
284285 try bit_stream.writeBits(u2(1), 1);
......@@ -290,12 +291,12 @@ test "BitStreams with File Stream" {
290291 try bit_stream.flushBits();
291292 }
292293 {
293 var file = try os.File.openRead(tmp_file_name);
294 var file = try File.openRead(tmp_file_name);
294295 defer file.close();
295296
296297 var file_in = file.inStream();
297298 var file_in_stream = &file_in.stream;
298 const InError = os.File.ReadError;
299 const InError = File.ReadError;
299300 var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
300301
301302 var out_bits: usize = undefined;
std/os.zig+97-13
......@@ -16,6 +16,7 @@
1616
1717const std = @import("std.zig");
1818const builtin = @import("builtin");
19const math = std.math;
1920const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
2021
2122comptime {
......@@ -114,7 +115,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
114115 const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
115116 defer close(fd);
116117
117 const stream = &os.File.openHandle(fd).inStream().stream;
118 const stream = &std.fs.File.openHandle(fd).inStream().stream;
118119 stream.readNoEof(buf) catch return error.Unexpected;
119120}
120121
......@@ -177,6 +178,21 @@ pub fn raise(sig: u8) RaiseError!void {
177178 }
178179}
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
180196/// Exits the program cleanly with the specified status code.
181197pub fn exit(status: u8) noreturn {
182198 if (builtin.link_libc) {
......@@ -885,8 +901,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
885901 if (windows.is_the_target and !builtin.link_libc) {
886902 const old_path_w = try windows.sliceToPrefixedFileW(old_path);
887903 const new_path_w = try windows.sliceToPrefixedFileW(new_path);
888 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
889 return windows.MoveFileExW(&old_path_w, &new_path_w, flags);
904 return renameW(&old_path_w, &new_path_w);
890905 } else {
891906 const old_path_c = try toPosixPath(old_path);
892907 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 {
899914 if (windows.is_the_target and !builtin.link_libc) {
900915 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
901916 const new_path_w = try windows.cStrToPrefixedFileW(new_path);
902 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
903 return windows.MoveFileExW(&old_path_w, &new_path_w, flags);
917 return renameW(&old_path_w, &new_path_w);
904918 }
905919 switch (errno(system.rename(old_path, new_path))) {
906920 0 => return,
......@@ -926,6 +940,13 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
926940 }
927941}
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
929950pub const MakeDirError = error{
930951 AccessDenied,
931952 DiskQuota,
......@@ -1684,10 +1705,10 @@ pub fn getsockoptError(sockfd: i32) ConnectError!void {
16841705 }
16851706}
16861707
1687pub fn waitpid(pid: i32) i32 {
1708pub fn waitpid(pid: i32, flags: u32) i32 {
16881709 var status: i32 = undefined;
16891710 while (true) {
1690 switch (errno(system.waitpid(pid, &status, 0))) {
1711 switch (errno(system.waitpid(pid, &status, flags))) {
16911712 0 => return status,
16921713 EINTR => continue,
16931714 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{
19882009};
19892010
19902011/// Creates a unidirectional data channel that can be used for interprocess communication.
1991pub fn pipe(fds: *[2]fd_t) PipeError!void {
1992 switch (errno(system.pipe(fds))) {
1993 0 => return,
2012pub fn pipe() PipeError![2]fd_t {
2013 var fds: [2]i32 = undefined;
2014 switch (errno(system.pipe(&fds))) {
2015 0 => return fds,
19942016 EINVAL => unreachable, // Invalid parameters to pipe()
19952017 EFAULT => unreachable, // Invalid fds pointer
19962018 ENFILE => return error.SystemFdQuotaExceeded,
......@@ -1999,9 +2021,10 @@ pub fn pipe(fds: *[2]fd_t) PipeError!void {
19992021 }
20002022}
20012023
2002pub fn pipe2(fds: *[2]fd_t, flags: u32) PipeError!void {
2003 switch (errno(system.pipe2(fds, flags))) {
2004 0 => return,
2024pub fn pipe2(flags: u32) PipeError![2]fd_t {
2025 var fds: [2]i32 = undefined;
2026 switch (errno(system.pipe2(&fds, flags))) {
2027 0 => return fds,
20052028 EINVAL => unreachable, // Invalid flags
20062029 EFAULT => unreachable, // Invalid fds pointer
20072030 ENFILE => return error.SystemFdQuotaExceeded,
......@@ -2281,6 +2304,67 @@ pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPa
22812304 return out_buffer[0..end_index];
22822305}
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
22842368/// Used to convert a slice to a null terminated slice on the stack.
22852369/// TODO https://github.com/ziglang/zig/issues/287
22862370pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
std/os/bits/linux.zig+1-11
......@@ -1,4 +1,4 @@
1pub use @import("errno.zig");
1pub use @import("linux/errno.zig");
22pub use switch (builtin.arch) {
33 .x86_64 => @import("linux/x86_64.zig"),
44 .aarch64 => @import("linux/arm64.zig"),
......@@ -744,16 +744,6 @@ pub const sockaddr_un = extern struct {
744744 path: [108]u8,
745745};
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
757747pub const mmsghdr = extern struct {
758748 msg_hdr: msghdr,
759749 msg_len: u32,
std/os/test.zig+4-3
......@@ -4,6 +4,7 @@ const testing = std.testing;
44const expect = std.testing.expect;
55const io = std.io;
66const mem = std.mem;
7const File = std.fs.File;
78
89const a = std.debug.global_allocator;
910
......@@ -25,14 +26,14 @@ test "makePath, put some files in it, deleteTree" {
2526
2627test "access file" {
2728 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| {
2930 @panic("expected error");
3031 } else |err| {
3132 expect(err == error.FileNotFound);
3233 }
3334
3435 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");
3637 try os.deleteTree(a, "os_test_tmp");
3738}
3839
......@@ -102,7 +103,7 @@ test "AtomicFile" {
102103 \\ this is a test file
103104 ;
104105 {
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);
106107 defer af.deinit();
107108 try af.file.write(test_content);
108109 try af.finish();
std/os/windows.zig+26
......@@ -753,6 +753,10 @@ pub fn CloseHandle(hObject: HANDLE) void {
753753 assert(kernel32.CloseHandle(hObject) != 0);
754754}
755755
756pub fn FindClose(hFindFile: HANDLE) void {
757 assert(kernel32.FindClose(hFindFile) != 0);
758}
759
756760pub const ReadFileError = error{Unexpected};
757761
758762pub fn ReadFile(in_hFile: HANDLE, buffer: []u8) ReadFileError!usize {
......@@ -1063,6 +1067,28 @@ pub fn GetFileAttributesW(lpFileName: [*]const u16) GetFileAttributesError!DWORD
10631067 return rc;
10641068}
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
10661092pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
10671093 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
10681094}
std/pdb.zig+6-5
......@@ -6,6 +6,7 @@ const mem = std.mem;
66const os = std.os;
77const warn = std.debug.warn;
88const coff = std.coff;
9const File = std.fs.File;
910
1011const ArrayList = std.ArrayList;
1112
......@@ -459,7 +460,7 @@ pub const PDBStringTableHeader = packed struct {
459460};
460461
461462pub const Pdb = struct {
462 in_file: os.File,
463 in_file: File,
463464 allocator: *mem.Allocator,
464465 coff: *coff.Coff,
465466 string_table: *MsfStream,
......@@ -468,7 +469,7 @@ pub const Pdb = struct {
468469 msf: Msf,
469470
470471 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);
472473 self.allocator = coff_ptr.allocator;
473474 self.coff = coff_ptr;
474475
......@@ -492,7 +493,7 @@ const Msf = struct {
492493 directory: MsfStream,
493494 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 {
496497 var file_stream = file.inStream();
497498 const in = &file_stream.stream;
498499
......@@ -587,7 +588,7 @@ const SuperBlock = packed struct {
587588};
588589
589590const MsfStream = struct {
590 in_file: os.File,
591 in_file: File,
591592 pos: u64,
592593 blocks: []u32,
593594 block_size: u32,
......@@ -598,7 +599,7 @@ const MsfStream = struct {
598599 pub const Error = @typeOf(read).ReturnType.ErrorSet;
599600 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 {
602603 var stream = MsfStream{
603604 .in_file = file,
604605 .pos = 0,
std/special/build_runner.zig+3-2
......@@ -8,6 +8,7 @@ const Builder = std.build.Builder;
88const mem = std.mem;
99const ArrayList = std.ArrayList;
1010const warn = std.debug.warn;
11const File = std.fs.File;
1112
1213pub fn main() !void {
1314 var arg_it = os.args();
......@@ -48,14 +49,14 @@ pub fn main() !void {
4849 var prefix: ?[]const u8 = null;
4950
5051 var stderr_file = io.getStdErr();
51 var stderr_file_stream: os.File.OutStream = undefined;
52 var stderr_file_stream: File.OutStream = undefined;
5253 var stderr_stream = if (stderr_file) |f| x: {
5354 stderr_file_stream = f.outStream();
5455 break :x &stderr_file_stream.stream;
5556 } else |err| err;
5657
5758 var stdout_file = io.getStdOut();
58 var stdout_file_stream: os.File.OutStream = undefined;
59 var stdout_file_stream: File.OutStream = undefined;
5960 var stdout_stream = if (stdout_file) |f| x: {
6061 stdout_file_stream = f.outStream();
6162 break :x &stdout_file_stream.stream;
std/time.zig+100-184
......@@ -1,116 +1,61 @@
1const std = @import("../std.zig");
21const builtin = @import("builtin");
3const Os = builtin.Os;
4const debug = std.debug;
2const std = @import("std.zig");
3const assert = std.debug.assert;
54const testing = std.testing;
6const math = std.math;
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;
5const os = std.os;
136
147pub const epoch = @import("epoch.zig");
158
169/// Spurious wakeups are possible and no precision of timing is guaranteed.
1710pub fn sleep(nanoseconds: u64) void {
18 switch (builtin.os) {
19 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
20 const s = nanoseconds / ns_per_s;
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 }
11 const s = nanoseconds / ns_per_s;
12 const ns = nanoseconds % ns_per_s;
13 std.os.nanosleep(s, ns);
5914}
6015
6116/// Get the posix timestamp, UTC, in seconds
17/// TODO audit this function. is it possible to return an error?
6218pub fn timestamp() u64 {
6319 return @divFloor(milliTimestamp(), ms_per_s);
6420}
6521
6622/// Get the posix timestamp, UTC, in milliseconds
67pub const milliTimestamp = switch (builtin.os) {
68 Os.windows => milliTimestampWindows,
69 Os.linux, Os.freebsd, Os.netbsd => milliTimestampPosix,
70 Os.macosx, Os.ios => milliTimestampDarwin,
71 Os.wasi => milliTimestampWasi,
72 else => @compileError("Unsupported OS"),
73};
74
75fn milliTimestampWasi() u64 {
76 var ns: wasi.timestamp_t = undefined;
77
78 // TODO: Verify that precision is ignored
79 const err = wasi.clock_time_get(wasi.CLOCK_REALTIME, 1, &ns);
80 debug.assert(err == wasi.ESUCCESS);
81
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}
23/// TODO audit this function. is it possible to return an error?
24pub fn milliTimestamp() u64 {
25 if (os.windows.is_the_target and !builtin.link_libc) {
26 //FileTime has a granularity of 100 nanoseconds
27 // and uses the NTFS/Windows epoch
28 var ft: os.windows.FILETIME = undefined;
29 os.windows.kernel32.GetSystemTimeAsFileTime(&ft);
30 const hns_per_ms = (ns_per_s / 100) / ms_per_s;
31 const epoch_adj = epoch.windows * ms_per_s;
32
33 const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
34 return @divFloor(ft64, hns_per_ms) - -epoch_adj;
35 }
36 if (os.wasi.is_the_target and !builtin.link_libc) {
37 var ns: os.wasi.timestamp_t = undefined;
9738
98fn milliTimestampDarwin() u64 {
99 var tv: darwin.timeval = undefined;
100 var err = darwin.gettimeofday(&tv, null);
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}
39 // TODO: Verify that precision is ignored
40 const err = os.wasi.clock_time_get(os.wasi.CLOCK_REALTIME, 1, &ns);
41 assert(err == os.wasi.ESUCCESS);
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;
10855 //From what I can tell there's no reason clock_gettime
10956 // should ever fail for us with CLOCK_REALTIME,
11057 // seccomp aside.
111 var ts: posix.timespec = undefined;
112 const err = posix.clock_gettime(posix.CLOCK_REALTIME, &ts);
113 debug.assert(err == 0);
58 os.clock_gettime(os.CLOCK_REALTIME, &ts) catch unreachable;
11459 const sec_ms = @intCast(u64, ts.tv_sec) * ms_per_s;
11560 const nsec_ms = @divFloor(@intCast(u64, ts.tv_nsec), ns_per_s / ms_per_s);
11661 return sec_ms + nsec_ms;
......@@ -145,27 +90,23 @@ pub const s_per_week = s_per_day * 7;
14590/// depends on the OS. On Windows and Darwin it is a hardware counter
14691/// value that requires calculation to convert to a meaninful unit.
14792pub const Timer = struct {
148
149 //if we used resolution's value when performing the
150 // performance counter calc on windows/darwin, it would
151 // be less precise
93 ///if we used resolution's value when performing the
94 /// performance counter calc on windows/darwin, it would
95 /// be less precise
15296 frequency: switch (builtin.os) {
153 Os.windows => u64,
154 Os.macosx, Os.ios => darwin.mach_timebase_info_data,
97 .windows => u64,
98 .macosx, .ios, .tvos, .watchos => darwin.mach_timebase_info_data,
15599 else => void,
156100 },
157101 resolution: u64,
158102 start_time: u64,
159103
160 //At some point we may change our minds on RAW, but for now we're
161 // sticking with posix standard MONOTONIC. For more information, see:
162 // https://github.com/ziglang/zig/pull/933
163 //
164 //const monotonic_clock_id = switch(builtin.os) {
165 // Os.linux => linux.CLOCK_MONOTONIC_RAW,
166 // else => posix.CLOCK_MONOTONIC,
167 //};
168 const monotonic_clock_id = posix.CLOCK_MONOTONIC;
104 const Error = error{TimerUnsupported};
105
106 ///At some point we may change our minds on RAW, but for now we're
107 /// sticking with posix standard MONOTONIC. For more information, see:
108 /// https://github.com/ziglang/zig/pull/933
109 const monotonic_clock_id = os.CLOCK_MONOTONIC;
169110 /// Initialize the timer structure.
170111 //This gives us an opportunity to grab the counter frequency in windows.
171112 //On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.
......@@ -174,66 +115,51 @@ pub const Timer = struct {
174115 // impossible here barring cosmic rays or other such occurrences of
175116 // incredibly bad luck.
176117 //On Darwin: This cannot fail, as far as I am able to tell.
177 const TimerError = error{
178 TimerUnsupported,
179 Unexpected,
180 };
181 pub fn start() TimerError!Timer {
118 pub fn start() Error!Timer {
182119 var self: Timer = undefined;
183120
184 switch (builtin.os) {
185 Os.windows => {
186 var freq: i64 = undefined;
187 var err = windows.QueryPerformanceFrequency(&freq);
188 if (err == windows.FALSE) return error.TimerUnsupported;
189 self.frequency = @intCast(u64, freq);
190 self.resolution = @divFloor(ns_per_s, self.frequency);
191
192 var start_time: i64 = undefined;
193 err = windows.QueryPerformanceCounter(&start_time);
194 debug.assert(err != windows.FALSE);
195 self.start_time = @intCast(u64, start_time);
196 },
197 Os.linux, Os.freebsd, Os.netbsd => {
198 //On Linux, seccomp can do arbitrary things to our ability to call
199 // syscalls, including return any errno value it wants and
200 // inconsistently throwing errors. Since we can't account for
201 // abuses of seccomp in a reasonable way, we'll assume that if
202 // seccomp is going to block us it will at least do so consistently
203 var ts: posix.timespec = undefined;
204 var result = posix.clock_getres(monotonic_clock_id, &ts);
205 var errno = posix.getErrno(result);
206 switch (errno) {
207 0 => {},
208 posix.EINVAL => return error.TimerUnsupported,
209 else => return std.os.unexpectedErrorPosix(errno),
210 }
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"),
121 if (os.windows.is_the_target) {
122 var freq: i64 = undefined;
123 var err = windows.QueryPerformanceFrequency(&freq);
124 if (err == windows.FALSE) return error.TimerUnsupported;
125 self.frequency = @intCast(u64, freq);
126 self.resolution = @divFloor(ns_per_s, self.frequency);
127
128 var start_time: i64 = undefined;
129 err = windows.QueryPerformanceCounter(&start_time);
130 assert(err != windows.FALSE);
131 self.start_time = @intCast(u64, start_time);
132 } else if (os.darwin.is_the_target) {
133 darwin.mach_timebase_info(&self.frequency);
134 self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
135 self.start_time = darwin.mach_absolute_time();
136 } else {
137 //On Linux, seccomp can do arbitrary things to our ability to call
138 // syscalls, including return any errno value it wants and
139 // inconsistently throwing errors. Since we can't account for
140 // abuses of seccomp in a reasonable way, we'll assume that if
141 // seccomp is going to block us it will at least do so consistently
142 var ts: os.timespec = undefined;
143 os.clock_getres(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
144 self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
145
146 os.clock_gettime(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
147 self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
224148 }
149
225150 return self;
226151 }
227152
228153 /// Reads the timer value since start or the last reset in nanoseconds
229154 pub fn read(self: *Timer) u64 {
230155 var clock = clockNative() - self.start_time;
231 return switch (builtin.os) {
232 Os.windows => @divFloor(clock * ns_per_s, self.frequency),
233 Os.linux, Os.freebsd, Os.netbsd => clock,
234 Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
235 else => @compileError("Unsupported OS"),
236 };
156 if (os.windows.is_the_target) {
157 return @divFloor(clock * ns_per_s, self.frequency);
158 }
159 if (os.darwin.is_the_target) {
160 return @divFloor(clock * self.frequency.numer, self.frequency.denom);
161 }
162 return clock;
237163 }
238164
239165 /// Resets the timer value to 0/now.
......@@ -249,37 +175,27 @@ pub const Timer = struct {
249175 return lap_time;
250176 }
251177
252 const clockNative = switch (builtin.os) {
253 Os.windows => clockWindows,
254 Os.linux, Os.freebsd, Os.netbsd => clockLinux,
255 Os.macosx, Os.ios => clockDarwin,
256 else => @compileError("Unsupported OS"),
257 };
258
259 fn clockWindows() u64 {
260 var result: i64 = undefined;
261 var err = windows.QueryPerformanceCounter(&result);
262 debug.assert(err != windows.FALSE);
263 return @intCast(u64, result);
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);
178 fn clockNative() u64 {
179 if (os.windows.is_the_target) {
180 var result: i64 = undefined;
181 var err = windows.QueryPerformanceCounter(&result);
182 assert(err != windows.FALSE);
183 return @intCast(u64, result);
184 }
185 if (os.darwin.is_the_target) {
186 return darwin.mach_absolute_time();
187 }
188 var ts: os.timespec = undefined;
189 os.clock_gettime(monotonic_clock_id, &ts) catch unreachable;
274190 return @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
275191 }
276192};
277193
278test "os.time.sleep" {
194test "sleep" {
279195 sleep(1);
280196}
281197
282test "os.time.timestamp" {
198test "timestamp" {
283199 const ns_per_ms = (ns_per_s / ms_per_s);
284200 const margin = 50;
285201
......@@ -290,7 +206,7 @@ test "os.time.timestamp" {
290206 testing.expect(interval > 0 and interval < margin);
291207}
292208
293test "os.time.Timer" {
209test "Timer" {
294210 const ns_per_ms = (ns_per_s / ms_per_s);
295211 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;
1010
1111pub fn main() !void {
1212 var i: usize = 0;
13 var timer = try std.os.time.Timer.start();
13 var timer = try std.time.Timer.start();
1414 const start = timer.lap();
1515 const iterations = 100;
1616 var memory_used: usize = 0;
......@@ -19,7 +19,7 @@ pub fn main() !void {
1919 }
2020 const end = timer.read();
2121 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;
2323 const bytes_per_sec = @intToFloat(f64, source.len * iterations) / elapsed_s;
2424 const mb_per_sec = bytes_per_sec / (1024 * 1024);
2525