| author | |
| committer | |
| log | 1373df4c34436b18b570f5b0f1be14da63966557 |
| tree | fb53a6071543007e904ff8a186e0c1bd3a029377 |
| parent | c53423f8aac8de49e700ba6eb89ccac462ed2212 |
| parent | 68617c9fb05ad7e92315edb0dec7c5fad56b6265 |
| signature |
WASI,libc: fix libstd with wasi-libc linkage, and enable tests.16 files changed, 223 insertions(+), 86 deletions(-)
lib/std/Thread.zig+1-1| ... | @@ -24,7 +24,7 @@ pub const Condition = @import("Thread/Condition.zig"); | ... | @@ -24,7 +24,7 @@ pub const Condition = @import("Thread/Condition.zig"); |
| 24 | 24 | ||
| 25 | pub const spinLoopHint = @compileError("deprecated: use std.atomic.spinLoopHint"); | 25 | pub const spinLoopHint = @compileError("deprecated: use std.atomic.spinLoopHint"); |
| 26 | 26 | ||
| 27 | pub const use_pthreads = target.os.tag != .windows and std.builtin.link_libc; | 27 | pub const use_pthreads = target.os.tag != .windows and std.Target.current.os.tag != .wasi and std.builtin.link_libc; |
| 28 | 28 | ||
| 29 | const Thread = @This(); | 29 | const Thread = @This(); |
| 30 | const Impl = if (target.os.tag == .windows) | 30 | const Impl = if (target.os.tag == .windows) |
lib/std/c.zig+1| ... | @@ -31,6 +31,7 @@ pub usingnamespace switch (std.Target.current.os.tag) { | ... | @@ -31,6 +31,7 @@ pub usingnamespace switch (std.Target.current.os.tag) { |
| 31 | .fuchsia => @import("c/fuchsia.zig"), | 31 | .fuchsia => @import("c/fuchsia.zig"), |
| 32 | .minix => @import("c/minix.zig"), | 32 | .minix => @import("c/minix.zig"), |
| 33 | .emscripten => @import("c/emscripten.zig"), | 33 | .emscripten => @import("c/emscripten.zig"), |
| 34 | .wasi => @import("c/wasi.zig"), | ||
| 34 | else => struct {}, | 35 | else => struct {}, |
| 35 | }; | 36 | }; |
| 36 | 37 |
lib/std/c/wasi.zig created+60| ... | @@ -0,0 +1,60 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | usingnamespace @import("../os/bits.zig"); | ||
| 7 | |||
| 8 | extern threadlocal var errno: c_int; | ||
| 9 | |||
| 10 | pub fn _errno() *c_int { | ||
| 11 | return &errno; | ||
| 12 | } | ||
| 13 | |||
| 14 | pub const pid_t = c_int; | ||
| 15 | pub const uid_t = u32; | ||
| 16 | pub const gid_t = u32; | ||
| 17 | pub const off_t = i64; | ||
| 18 | |||
| 19 | pub const libc_stat = extern struct { | ||
| 20 | dev: i32, | ||
| 21 | ino: ino_t, | ||
| 22 | nlink: u64, | ||
| 23 | |||
| 24 | mode: mode_t, | ||
| 25 | uid: uid_t, | ||
| 26 | gid: gid_t, | ||
| 27 | __pad0: isize, | ||
| 28 | rdev: i32, | ||
| 29 | size: off_t, | ||
| 30 | blksize: i32, | ||
| 31 | blocks: i64, | ||
| 32 | |||
| 33 | atimesec: time_t, | ||
| 34 | atimensec: isize, | ||
| 35 | mtimesec: time_t, | ||
| 36 | mtimensec: isize, | ||
| 37 | ctimesec: time_t, | ||
| 38 | ctimensec: isize, | ||
| 39 | |||
| 40 | pub fn atime(self: @This()) timespec { | ||
| 41 | return timespec{ | ||
| 42 | .tv_sec = self.atimesec, | ||
| 43 | .tv_nsec = self.atimensec, | ||
| 44 | }; | ||
| 45 | } | ||
| 46 | |||
| 47 | pub fn mtime(self: @This()) timespec { | ||
| 48 | return timespec{ | ||
| 49 | .tv_sec = self.mtimesec, | ||
| 50 | .tv_nsec = self.mtimensec, | ||
| 51 | }; | ||
| 52 | } | ||
| 53 | |||
| 54 | pub fn ctime(self: @This()) timespec { | ||
| 55 | return timespec{ | ||
| 56 | .tv_sec = self.ctimesec, | ||
| 57 | .tv_nsec = self.ctimensec, | ||
| 58 | }; | ||
| 59 | } | ||
| 60 | }; | ||
lib/std/fs.zig+35-24| ... | @@ -647,6 +647,9 @@ pub const Dir = struct { | ... | @@ -647,6 +647,9 @@ pub const Dir = struct { |
| 647 | /// Memory such as file names referenced in this returned entry becomes invalid | 647 | /// Memory such as file names referenced in this returned entry becomes invalid |
| 648 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. | 648 | /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized. |
| 649 | pub fn next(self: *Self) Error!?Entry { | 649 | pub fn next(self: *Self) Error!?Entry { |
| 650 | // We intentinally use fd_readdir even when linked with libc, | ||
| 651 | // since its implementation is exactly the same as below, | ||
| 652 | // and we avoid the code complexity here. | ||
| 650 | const w = os.wasi; | 653 | const w = os.wasi; |
| 651 | start_over: while (true) { | 654 | start_over: while (true) { |
| 652 | if (self.index >= self.end_index) { | 655 | if (self.index >= self.end_index) { |
| ... | @@ -858,7 +861,7 @@ pub const Dir = struct { | ... | @@ -858,7 +861,7 @@ pub const Dir = struct { |
| 858 | const path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 861 | const path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 859 | return self.openFileW(path_w.span(), flags); | 862 | return self.openFileW(path_w.span(), flags); |
| 860 | } | 863 | } |
| 861 | if (builtin.os.tag == .wasi) { | 864 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 862 | return self.openFileWasi(sub_path, flags); | 865 | return self.openFileWasi(sub_path, flags); |
| 863 | } | 866 | } |
| 864 | const path_c = try os.toPosixPath(sub_path); | 867 | const path_c = try os.toPosixPath(sub_path); |
| ... | @@ -934,14 +937,18 @@ pub const Dir = struct { | ... | @@ -934,14 +937,18 @@ pub const Dir = struct { |
| 934 | try os.openatZ(self.fd, sub_path, os_flags, 0); | 937 | try os.openatZ(self.fd, sub_path, os_flags, 0); |
| 935 | errdefer os.close(fd); | 938 | errdefer os.close(fd); |
| 936 | 939 | ||
| 937 | if (!has_flock_open_flags and flags.lock != .None) { | 940 | // WASI doesn't have os.flock so we intetinally check OS prior to the inner if block |
| 938 | // TODO: integrate async I/O | 941 | // since it is not compiltime-known and we need to avoid undefined symbol in Wasm. |
| 939 | const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK_NB else @as(i32, 0); | 942 | if (builtin.target.os.tag != .wasi) { |
| 940 | try os.flock(fd, switch (flags.lock) { | 943 | if (!has_flock_open_flags and flags.lock != .None) { |
| 941 | .None => unreachable, | 944 | // TODO: integrate async I/O |
| 942 | .Shared => os.LOCK_SH | lock_nonblocking, | 945 | const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK_NB else @as(i32, 0); |
| 943 | .Exclusive => os.LOCK_EX | lock_nonblocking, | 946 | try os.flock(fd, switch (flags.lock) { |
| 944 | }); | 947 | .None => unreachable, |
| 948 | .Shared => os.LOCK_SH | lock_nonblocking, | ||
| 949 | .Exclusive => os.LOCK_EX | lock_nonblocking, | ||
| 950 | }); | ||
| 951 | } | ||
| 945 | } | 952 | } |
| 946 | 953 | ||
| 947 | if (has_flock_open_flags and flags.lock_nonblocking) { | 954 | if (has_flock_open_flags and flags.lock_nonblocking) { |
| ... | @@ -1014,7 +1021,7 @@ pub const Dir = struct { | ... | @@ -1014,7 +1021,7 @@ pub const Dir = struct { |
| 1014 | const path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1021 | const path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 1015 | return self.createFileW(path_w.span(), flags); | 1022 | return self.createFileW(path_w.span(), flags); |
| 1016 | } | 1023 | } |
| 1017 | if (builtin.os.tag == .wasi) { | 1024 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1018 | return self.createFileWasi(sub_path, flags); | 1025 | return self.createFileWasi(sub_path, flags); |
| 1019 | } | 1026 | } |
| 1020 | const path_c = try os.toPosixPath(sub_path); | 1027 | const path_c = try os.toPosixPath(sub_path); |
| ... | @@ -1084,14 +1091,18 @@ pub const Dir = struct { | ... | @@ -1084,14 +1091,18 @@ pub const Dir = struct { |
| 1084 | try os.openatZ(self.fd, sub_path_c, os_flags, flags.mode); | 1091 | try os.openatZ(self.fd, sub_path_c, os_flags, flags.mode); |
| 1085 | errdefer os.close(fd); | 1092 | errdefer os.close(fd); |
| 1086 | 1093 | ||
| 1087 | if (!has_flock_open_flags and flags.lock != .None) { | 1094 | // WASI doesn't have os.flock so we intetinally check OS prior to the inner if block |
| 1088 | // TODO: integrate async I/O | 1095 | // since it is not compiltime-known and we need to avoid undefined symbol in Wasm. |
| 1089 | const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK_NB else @as(i32, 0); | 1096 | if (builtin.target.os.tag != .wasi) { |
| 1090 | try os.flock(fd, switch (flags.lock) { | 1097 | if (!has_flock_open_flags and flags.lock != .None) { |
| 1091 | .None => unreachable, | 1098 | // TODO: integrate async I/O |
| 1092 | .Shared => os.LOCK_SH | lock_nonblocking, | 1099 | const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK_NB else @as(i32, 0); |
| 1093 | .Exclusive => os.LOCK_EX | lock_nonblocking, | 1100 | try os.flock(fd, switch (flags.lock) { |
| 1094 | }); | 1101 | .None => unreachable, |
| 1102 | .Shared => os.LOCK_SH | lock_nonblocking, | ||
| 1103 | .Exclusive => os.LOCK_EX | lock_nonblocking, | ||
| 1104 | }); | ||
| 1105 | } | ||
| 1095 | } | 1106 | } |
| 1096 | 1107 | ||
| 1097 | if (has_flock_open_flags and flags.lock_nonblocking) { | 1108 | if (has_flock_open_flags and flags.lock_nonblocking) { |
| ... | @@ -1372,7 +1383,7 @@ pub const Dir = struct { | ... | @@ -1372,7 +1383,7 @@ pub const Dir = struct { |
| 1372 | if (builtin.os.tag == .windows) { | 1383 | if (builtin.os.tag == .windows) { |
| 1373 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1384 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 1374 | return self.openDirW(sub_path_w.span().ptr, args); | 1385 | return self.openDirW(sub_path_w.span().ptr, args); |
| 1375 | } else if (builtin.os.tag == .wasi) { | 1386 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1376 | return self.openDirWasi(sub_path, args); | 1387 | return self.openDirWasi(sub_path, args); |
| 1377 | } else { | 1388 | } else { |
| 1378 | const sub_path_c = try os.toPosixPath(sub_path); | 1389 | const sub_path_c = try os.toPosixPath(sub_path); |
| ... | @@ -1519,7 +1530,7 @@ pub const Dir = struct { | ... | @@ -1519,7 +1530,7 @@ pub const Dir = struct { |
| 1519 | if (builtin.os.tag == .windows) { | 1530 | if (builtin.os.tag == .windows) { |
| 1520 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1531 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 1521 | return self.deleteFileW(sub_path_w.span()); | 1532 | return self.deleteFileW(sub_path_w.span()); |
| 1522 | } else if (builtin.os.tag == .wasi) { | 1533 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1523 | os.unlinkatWasi(self.fd, sub_path, 0) catch |err| switch (err) { | 1534 | os.unlinkatWasi(self.fd, sub_path, 0) catch |err| switch (err) { |
| 1524 | error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR | 1535 | error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR |
| 1525 | else => |e| return e, | 1536 | else => |e| return e, |
| ... | @@ -1582,7 +1593,7 @@ pub const Dir = struct { | ... | @@ -1582,7 +1593,7 @@ pub const Dir = struct { |
| 1582 | if (builtin.os.tag == .windows) { | 1593 | if (builtin.os.tag == .windows) { |
| 1583 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1594 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); |
| 1584 | return self.deleteDirW(sub_path_w.span()); | 1595 | return self.deleteDirW(sub_path_w.span()); |
| 1585 | } else if (builtin.os.tag == .wasi) { | 1596 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1586 | os.unlinkat(self.fd, sub_path, os.AT_REMOVEDIR) catch |err| switch (err) { | 1597 | os.unlinkat(self.fd, sub_path, os.AT_REMOVEDIR) catch |err| switch (err) { |
| 1587 | error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR | 1598 | error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR |
| 1588 | else => |e| return e, | 1599 | else => |e| return e, |
| ... | @@ -1641,7 +1652,7 @@ pub const Dir = struct { | ... | @@ -1641,7 +1652,7 @@ pub const Dir = struct { |
| 1641 | sym_link_path: []const u8, | 1652 | sym_link_path: []const u8, |
| 1642 | flags: SymLinkFlags, | 1653 | flags: SymLinkFlags, |
| 1643 | ) !void { | 1654 | ) !void { |
| 1644 | if (builtin.os.tag == .wasi) { | 1655 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1645 | return self.symLinkWasi(target_path, sym_link_path, flags); | 1656 | return self.symLinkWasi(target_path, sym_link_path, flags); |
| 1646 | } | 1657 | } |
| 1647 | if (builtin.os.tag == .windows) { | 1658 | if (builtin.os.tag == .windows) { |
| ... | @@ -1694,7 +1705,7 @@ pub const Dir = struct { | ... | @@ -1694,7 +1705,7 @@ pub const Dir = struct { |
| 1694 | /// The return value is a slice of `buffer`, from index `0`. | 1705 | /// The return value is a slice of `buffer`, from index `0`. |
| 1695 | /// Asserts that the path parameter has no null bytes. | 1706 | /// Asserts that the path parameter has no null bytes. |
| 1696 | pub fn readLink(self: Dir, sub_path: []const u8, buffer: []u8) ![]u8 { | 1707 | pub fn readLink(self: Dir, sub_path: []const u8, buffer: []u8) ![]u8 { |
| 1697 | if (builtin.os.tag == .wasi) { | 1708 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1698 | return self.readLinkWasi(sub_path, buffer); | 1709 | return self.readLinkWasi(sub_path, buffer); |
| 1699 | } | 1710 | } |
| 1700 | if (builtin.os.tag == .windows) { | 1711 | if (builtin.os.tag == .windows) { |
| ... | @@ -2113,7 +2124,7 @@ pub const Dir = struct { | ... | @@ -2113,7 +2124,7 @@ pub const Dir = struct { |
| 2113 | pub fn cwd() Dir { | 2124 | pub fn cwd() Dir { |
| 2114 | if (builtin.os.tag == .windows) { | 2125 | if (builtin.os.tag == .windows) { |
| 2115 | return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle }; | 2126 | return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle }; |
| 2116 | } else if (builtin.os.tag == .wasi) { | 2127 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2117 | @compileError("WASI doesn't have a concept of cwd(); use std.fs.wasi.PreopenList to get available Dir handles instead"); | 2128 | @compileError("WASI doesn't have a concept of cwd(); use std.fs.wasi.PreopenList to get available Dir handles instead"); |
| 2118 | } else { | 2129 | } else { |
| 2119 | return Dir{ .fd = os.AT_FDCWD }; | 2130 | return Dir{ .fd = os.AT_FDCWD }; |
lib/std/fs/file.zig+17-20| ... | @@ -326,26 +326,23 @@ pub const File = struct { | ... | @@ -326,26 +326,23 @@ pub const File = struct { |
| 326 | .inode = st.ino, | 326 | .inode = st.ino, |
| 327 | .size = @bitCast(u64, st.size), | 327 | .size = @bitCast(u64, st.size), |
| 328 | .mode = st.mode, | 328 | .mode = st.mode, |
| 329 | .kind = switch (builtin.os.tag) { | 329 | .kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) { |
| 330 | .wasi => switch (st.filetype) { | 330 | os.FILETYPE_BLOCK_DEVICE => Kind.BlockDevice, |
| 331 | os.FILETYPE_BLOCK_DEVICE => Kind.BlockDevice, | 331 | os.FILETYPE_CHARACTER_DEVICE => Kind.CharacterDevice, |
| 332 | os.FILETYPE_CHARACTER_DEVICE => Kind.CharacterDevice, | 332 | os.FILETYPE_DIRECTORY => Kind.Directory, |
| 333 | os.FILETYPE_DIRECTORY => Kind.Directory, | 333 | os.FILETYPE_SYMBOLIC_LINK => Kind.SymLink, |
| 334 | os.FILETYPE_SYMBOLIC_LINK => Kind.SymLink, | 334 | os.FILETYPE_REGULAR_FILE => Kind.File, |
| 335 | os.FILETYPE_REGULAR_FILE => Kind.File, | 335 | os.FILETYPE_SOCKET_STREAM, os.FILETYPE_SOCKET_DGRAM => Kind.UnixDomainSocket, |
| 336 | os.FILETYPE_SOCKET_STREAM, os.FILETYPE_SOCKET_DGRAM => Kind.UnixDomainSocket, | 336 | else => Kind.Unknown, |
| 337 | else => Kind.Unknown, | 337 | } else switch (st.mode & os.S_IFMT) { |
| 338 | }, | 338 | os.S_IFBLK => Kind.BlockDevice, |
| 339 | else => switch (st.mode & os.S_IFMT) { | 339 | os.S_IFCHR => Kind.CharacterDevice, |
| 340 | os.S_IFBLK => Kind.BlockDevice, | 340 | os.S_IFDIR => Kind.Directory, |
| 341 | os.S_IFCHR => Kind.CharacterDevice, | 341 | os.S_IFIFO => Kind.NamedPipe, |
| 342 | os.S_IFDIR => Kind.Directory, | 342 | os.S_IFLNK => Kind.SymLink, |
| 343 | os.S_IFIFO => Kind.NamedPipe, | 343 | os.S_IFREG => Kind.File, |
| 344 | os.S_IFLNK => Kind.SymLink, | 344 | os.S_IFSOCK => Kind.UnixDomainSocket, |
| 345 | os.S_IFREG => Kind.File, | 345 | else => Kind.Unknown, |
| 346 | os.S_IFSOCK => Kind.UnixDomainSocket, | ||
| 347 | else => Kind.Unknown, | ||
| 348 | }, | ||
| 349 | }, | 346 | }, |
| 350 | .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, | 347 | .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, |
| 351 | .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, | 348 | .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, |
lib/std/fs/wasi.zig+1-1| ... | @@ -169,7 +169,7 @@ pub const PreopenList = struct { | ... | @@ -169,7 +169,7 @@ pub const PreopenList = struct { |
| 169 | }; | 169 | }; |
| 170 | 170 | ||
| 171 | test "extracting WASI preopens" { | 171 | test "extracting WASI preopens" { |
| 172 | if (std.builtin.os.tag != .wasi) return error.SkipZigTest; | 172 | if (std.builtin.os.tag != .wasi or std.builtin.link_libc) return error.SkipZigTest; |
| 173 | 173 | ||
| 174 | var preopens = PreopenList.init(std.testing.allocator); | 174 | var preopens = PreopenList.init(std.testing.allocator); |
| 175 | defer preopens.deinit(); | 175 | defer preopens.deinit(); |
lib/std/io/c_writer.zig+1-1| ... | @@ -35,7 +35,7 @@ fn cWriterWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!u | ... | @@ -35,7 +35,7 @@ fn cWriterWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!u |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | test { | 37 | test { |
| 38 | if (!builtin.link_libc) return error.SkipZigTest; | 38 | if (!builtin.link_libc or builtin.os.tag == .wasi) return error.SkipZigTest; |
| 39 | 39 | ||
| 40 | const filename = "tmp_io_test_file.txt"; | 40 | const filename = "tmp_io_test_file.txt"; |
| 41 | const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile; | 41 | const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile; |
lib/std/os.zig+25-22| ... | @@ -404,7 +404,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { | ... | @@ -404,7 +404,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { |
| 404 | const first = iov[0]; | 404 | const first = iov[0]; |
| 405 | return read(fd, first.iov_base[0..first.iov_len]); | 405 | return read(fd, first.iov_base[0..first.iov_len]); |
| 406 | } | 406 | } |
| 407 | if (builtin.os.tag == .wasi) { | 407 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 408 | var nread: usize = undefined; | 408 | var nread: usize = undefined; |
| 409 | switch (wasi.fd_read(fd, iov.ptr, iov.len, &nread)) { | 409 | switch (wasi.fd_read(fd, iov.ptr, iov.len, &nread)) { |
| 410 | wasi.ESUCCESS => return nread, | 410 | wasi.ESUCCESS => return nread, |
| ... | @@ -461,7 +461,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { | ... | @@ -461,7 +461,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { |
| 461 | if (builtin.os.tag == .windows) { | 461 | if (builtin.os.tag == .windows) { |
| 462 | return windows.ReadFile(fd, buf, offset, std.io.default_mode); | 462 | return windows.ReadFile(fd, buf, offset, std.io.default_mode); |
| 463 | } | 463 | } |
| 464 | if (builtin.os.tag == .wasi) { | 464 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 465 | const iovs = [1]iovec{iovec{ | 465 | const iovs = [1]iovec{iovec{ |
| 466 | .iov_base = buf.ptr, | 466 | .iov_base = buf.ptr, |
| 467 | .iov_len = buf.len, | 467 | .iov_len = buf.len, |
| ... | @@ -556,7 +556,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { | ... | @@ -556,7 +556,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { |
| 556 | else => return windows.unexpectedStatus(rc), | 556 | else => return windows.unexpectedStatus(rc), |
| 557 | } | 557 | } |
| 558 | } | 558 | } |
| 559 | if (std.Target.current.os.tag == .wasi) { | 559 | if (std.Target.current.os.tag == .wasi and !builtin.link_libc) { |
| 560 | switch (wasi.fd_filestat_set_size(fd, length)) { | 560 | switch (wasi.fd_filestat_set_size(fd, length)) { |
| 561 | wasi.ESUCCESS => return, | 561 | wasi.ESUCCESS => return, |
| 562 | wasi.EINTR => unreachable, | 562 | wasi.EINTR => unreachable, |
| ... | @@ -617,7 +617,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { | ... | @@ -617,7 +617,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { |
| 617 | const first = iov[0]; | 617 | const first = iov[0]; |
| 618 | return pread(fd, first.iov_base[0..first.iov_len], offset); | 618 | return pread(fd, first.iov_base[0..first.iov_len], offset); |
| 619 | } | 619 | } |
| 620 | if (builtin.os.tag == .wasi) { | 620 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 621 | var nread: usize = undefined; | 621 | var nread: usize = undefined; |
| 622 | switch (wasi.fd_pread(fd, iov.ptr, iov.len, offset, &nread)) { | 622 | switch (wasi.fd_pread(fd, iov.ptr, iov.len, offset, &nread)) { |
| 623 | wasi.ESUCCESS => return nread, | 623 | wasi.ESUCCESS => return nread, |
| ... | @@ -795,7 +795,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { | ... | @@ -795,7 +795,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { |
| 795 | const first = iov[0]; | 795 | const first = iov[0]; |
| 796 | return write(fd, first.iov_base[0..first.iov_len]); | 796 | return write(fd, first.iov_base[0..first.iov_len]); |
| 797 | } | 797 | } |
| 798 | if (builtin.os.tag == .wasi) { | 798 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 799 | var nwritten: usize = undefined; | 799 | var nwritten: usize = undefined; |
| 800 | switch (wasi.fd_write(fd, iov.ptr, iov.len, &nwritten)) { | 800 | switch (wasi.fd_write(fd, iov.ptr, iov.len, &nwritten)) { |
| 801 | wasi.ESUCCESS => return nwritten, | 801 | wasi.ESUCCESS => return nwritten, |
| ... | @@ -867,7 +867,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { | ... | @@ -867,7 +867,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { |
| 867 | if (std.Target.current.os.tag == .windows) { | 867 | if (std.Target.current.os.tag == .windows) { |
| 868 | return windows.WriteFile(fd, bytes, offset, std.io.default_mode); | 868 | return windows.WriteFile(fd, bytes, offset, std.io.default_mode); |
| 869 | } | 869 | } |
| 870 | if (builtin.os.tag == .wasi) { | 870 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 871 | const ciovs = [1]iovec_const{iovec_const{ | 871 | const ciovs = [1]iovec_const{iovec_const{ |
| 872 | .iov_base = bytes.ptr, | 872 | .iov_base = bytes.ptr, |
| 873 | .iov_len = bytes.len, | 873 | .iov_len = bytes.len, |
| ... | @@ -968,7 +968,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz | ... | @@ -968,7 +968,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz |
| 968 | const first = iov[0]; | 968 | const first = iov[0]; |
| 969 | return pwrite(fd, first.iov_base[0..first.iov_len], offset); | 969 | return pwrite(fd, first.iov_base[0..first.iov_len], offset); |
| 970 | } | 970 | } |
| 971 | if (builtin.os.tag == .wasi) { | 971 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 972 | var nwritten: usize = undefined; | 972 | var nwritten: usize = undefined; |
| 973 | switch (wasi.fd_pwrite(fd, iov.ptr, iov.len, offset, &nwritten)) { | 973 | switch (wasi.fd_pwrite(fd, iov.ptr, iov.len, offset, &nwritten)) { |
| 974 | wasi.ESUCCESS => return nwritten, | 974 | wasi.ESUCCESS => return nwritten, |
| ... | @@ -1627,7 +1627,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin | ... | @@ -1627,7 +1627,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin |
| 1627 | /// If `sym_link_path` exists, it will not be overwritten. | 1627 | /// If `sym_link_path` exists, it will not be overwritten. |
| 1628 | /// See also `symlinkatWasi`, `symlinkatZ` and `symlinkatW`. | 1628 | /// See also `symlinkatWasi`, `symlinkatZ` and `symlinkatW`. |
| 1629 | pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void { | 1629 | pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const u8) SymLinkError!void { |
| 1630 | if (builtin.os.tag == .wasi) { | 1630 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1631 | return symlinkatWasi(target_path, newdirfd, sym_link_path); | 1631 | return symlinkatWasi(target_path, newdirfd, sym_link_path); |
| 1632 | } | 1632 | } |
| 1633 | if (builtin.os.tag == .windows) { | 1633 | if (builtin.os.tag == .windows) { |
| ... | @@ -1856,7 +1856,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo | ... | @@ -1856,7 +1856,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo |
| 1856 | if (builtin.os.tag == .windows) { | 1856 | if (builtin.os.tag == .windows) { |
| 1857 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 1857 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); |
| 1858 | return unlinkatW(dirfd, file_path_w.span(), flags); | 1858 | return unlinkatW(dirfd, file_path_w.span(), flags); |
| 1859 | } else if (builtin.os.tag == .wasi) { | 1859 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1860 | return unlinkatWasi(dirfd, file_path, flags); | 1860 | return unlinkatWasi(dirfd, file_path, flags); |
| 1861 | } else { | 1861 | } else { |
| 1862 | const file_path_c = try toPosixPath(file_path); | 1862 | const file_path_c = try toPosixPath(file_path); |
| ... | @@ -2023,7 +2023,7 @@ pub fn renameat( | ... | @@ -2023,7 +2023,7 @@ pub fn renameat( |
| 2023 | const old_path_w = try windows.sliceToPrefixedFileW(old_path); | 2023 | const old_path_w = try windows.sliceToPrefixedFileW(old_path); |
| 2024 | const new_path_w = try windows.sliceToPrefixedFileW(new_path); | 2024 | const new_path_w = try windows.sliceToPrefixedFileW(new_path); |
| 2025 | return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE); | 2025 | return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE); |
| 2026 | } else if (builtin.os.tag == .wasi) { | 2026 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2027 | return renameatWasi(old_dir_fd, old_path, new_dir_fd, new_path); | 2027 | return renameatWasi(old_dir_fd, old_path, new_dir_fd, new_path); |
| 2028 | } else { | 2028 | } else { |
| 2029 | const old_path_c = try toPosixPath(old_path); | 2029 | const old_path_c = try toPosixPath(old_path); |
| ... | @@ -2159,7 +2159,7 @@ pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!v | ... | @@ -2159,7 +2159,7 @@ pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!v |
| 2159 | if (builtin.os.tag == .windows) { | 2159 | if (builtin.os.tag == .windows) { |
| 2160 | const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path); | 2160 | const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path); |
| 2161 | return mkdiratW(dir_fd, sub_dir_path_w.span(), mode); | 2161 | return mkdiratW(dir_fd, sub_dir_path_w.span(), mode); |
| 2162 | } else if (builtin.os.tag == .wasi) { | 2162 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2163 | return mkdiratWasi(dir_fd, sub_dir_path, mode); | 2163 | return mkdiratWasi(dir_fd, sub_dir_path, mode); |
| 2164 | } else { | 2164 | } else { |
| 2165 | const sub_dir_path_c = try toPosixPath(sub_dir_path); | 2165 | const sub_dir_path_c = try toPosixPath(sub_dir_path); |
| ... | @@ -2519,7 +2519,7 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 | ... | @@ -2519,7 +2519,7 @@ pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 |
| 2519 | /// The return value is a slice of `out_buffer` from index 0. | 2519 | /// The return value is a slice of `out_buffer` from index 0. |
| 2520 | /// See also `readlinkatWasi`, `realinkatZ` and `realinkatW`. | 2520 | /// See also `readlinkatWasi`, `realinkatZ` and `realinkatW`. |
| 2521 | pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { | 2521 | pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2522 | if (builtin.os.tag == .wasi) { | 2522 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2523 | return readlinkatWasi(dirfd, file_path, out_buffer); | 2523 | return readlinkatWasi(dirfd, file_path, out_buffer); |
| 2524 | } | 2524 | } |
| 2525 | if (builtin.os.tag == .windows) { | 2525 | if (builtin.os.tag == .windows) { |
| ... | @@ -3481,7 +3481,7 @@ pub const FStatError = error{ | ... | @@ -3481,7 +3481,7 @@ pub const FStatError = error{ |
| 3481 | 3481 | ||
| 3482 | /// Return information about a file descriptor. | 3482 | /// Return information about a file descriptor. |
| 3483 | pub fn fstat(fd: fd_t) FStatError!Stat { | 3483 | pub fn fstat(fd: fd_t) FStatError!Stat { |
| 3484 | if (builtin.os.tag == .wasi) { | 3484 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 3485 | var stat: wasi.filestat_t = undefined; | 3485 | var stat: wasi.filestat_t = undefined; |
| 3486 | switch (wasi.fd_filestat_get(fd, &stat)) { | 3486 | switch (wasi.fd_filestat_get(fd, &stat)) { |
| 3487 | wasi.ESUCCESS => return Stat.fromFilestat(stat), | 3487 | wasi.ESUCCESS => return Stat.fromFilestat(stat), |
| ... | @@ -3519,7 +3519,7 @@ pub const FStatAtError = FStatError || error{ NameTooLong, FileNotFound, SymLink | ... | @@ -3519,7 +3519,7 @@ pub const FStatAtError = FStatError || error{ NameTooLong, FileNotFound, SymLink |
| 3519 | /// which is relative to `dirfd` handle. | 3519 | /// which is relative to `dirfd` handle. |
| 3520 | /// See also `fstatatZ` and `fstatatWasi`. | 3520 | /// See also `fstatatZ` and `fstatatWasi`. |
| 3521 | pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { | 3521 | pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { |
| 3522 | if (builtin.os.tag == .wasi) { | 3522 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 3523 | return fstatatWasi(dirfd, pathname, flags); | 3523 | return fstatatWasi(dirfd, pathname, flags); |
| 3524 | } else if (builtin.os.tag == .windows) { | 3524 | } else if (builtin.os.tag == .windows) { |
| 3525 | @compileError("fstatat is not yet implemented on Windows"); | 3525 | @compileError("fstatat is not yet implemented on Windows"); |
| ... | @@ -4123,7 +4123,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void { | ... | @@ -4123,7 +4123,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void { |
| 4123 | if (builtin.os.tag == .windows) { | 4123 | if (builtin.os.tag == .windows) { |
| 4124 | return windows.SetFilePointerEx_BEGIN(fd, offset); | 4124 | return windows.SetFilePointerEx_BEGIN(fd, offset); |
| 4125 | } | 4125 | } |
| 4126 | if (builtin.os.tag == .wasi) { | 4126 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4127 | var new_offset: wasi.filesize_t = undefined; | 4127 | var new_offset: wasi.filesize_t = undefined; |
| 4128 | switch (wasi.fd_seek(fd, @bitCast(wasi.filedelta_t, offset), wasi.WHENCE_SET, &new_offset)) { | 4128 | switch (wasi.fd_seek(fd, @bitCast(wasi.filedelta_t, offset), wasi.WHENCE_SET, &new_offset)) { |
| 4129 | wasi.ESUCCESS => return, | 4129 | wasi.ESUCCESS => return, |
| ... | @@ -4171,7 +4171,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void { | ... | @@ -4171,7 +4171,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void { |
| 4171 | if (builtin.os.tag == .windows) { | 4171 | if (builtin.os.tag == .windows) { |
| 4172 | return windows.SetFilePointerEx_CURRENT(fd, offset); | 4172 | return windows.SetFilePointerEx_CURRENT(fd, offset); |
| 4173 | } | 4173 | } |
| 4174 | if (builtin.os.tag == .wasi) { | 4174 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4175 | var new_offset: wasi.filesize_t = undefined; | 4175 | var new_offset: wasi.filesize_t = undefined; |
| 4176 | switch (wasi.fd_seek(fd, offset, wasi.WHENCE_CUR, &new_offset)) { | 4176 | switch (wasi.fd_seek(fd, offset, wasi.WHENCE_CUR, &new_offset)) { |
| 4177 | wasi.ESUCCESS => return, | 4177 | wasi.ESUCCESS => return, |
| ... | @@ -4218,7 +4218,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void { | ... | @@ -4218,7 +4218,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void { |
| 4218 | if (builtin.os.tag == .windows) { | 4218 | if (builtin.os.tag == .windows) { |
| 4219 | return windows.SetFilePointerEx_END(fd, offset); | 4219 | return windows.SetFilePointerEx_END(fd, offset); |
| 4220 | } | 4220 | } |
| 4221 | if (builtin.os.tag == .wasi) { | 4221 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4222 | var new_offset: wasi.filesize_t = undefined; | 4222 | var new_offset: wasi.filesize_t = undefined; |
| 4223 | switch (wasi.fd_seek(fd, offset, wasi.WHENCE_END, &new_offset)) { | 4223 | switch (wasi.fd_seek(fd, offset, wasi.WHENCE_END, &new_offset)) { |
| 4224 | wasi.ESUCCESS => return, | 4224 | wasi.ESUCCESS => return, |
| ... | @@ -4265,7 +4265,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 { | ... | @@ -4265,7 +4265,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 { |
| 4265 | if (builtin.os.tag == .windows) { | 4265 | if (builtin.os.tag == .windows) { |
| 4266 | return windows.SetFilePointerEx_CURRENT_get(fd); | 4266 | return windows.SetFilePointerEx_CURRENT_get(fd); |
| 4267 | } | 4267 | } |
| 4268 | if (builtin.os.tag == .wasi) { | 4268 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4269 | var new_offset: wasi.filesize_t = undefined; | 4269 | var new_offset: wasi.filesize_t = undefined; |
| 4270 | switch (wasi.fd_seek(fd, 0, wasi.WHENCE_CUR, &new_offset)) { | 4270 | switch (wasi.fd_seek(fd, 0, wasi.WHENCE_CUR, &new_offset)) { |
| 4271 | wasi.ESUCCESS => return new_offset, | 4271 | wasi.ESUCCESS => return new_offset, |
| ... | @@ -4665,7 +4665,7 @@ pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError; | ... | @@ -4665,7 +4665,7 @@ pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError; |
| 4665 | /// TODO: change this to return the timespec as a return value | 4665 | /// TODO: change this to return the timespec as a return value |
| 4666 | /// TODO: look into making clk_id an enum | 4666 | /// TODO: look into making clk_id an enum |
| 4667 | pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void { | 4667 | pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void { |
| 4668 | if (std.Target.current.os.tag == .wasi) { | 4668 | if (std.Target.current.os.tag == .wasi and !builtin.link_libc) { |
| 4669 | var ts: timestamp_t = undefined; | 4669 | var ts: timestamp_t = undefined; |
| 4670 | switch (system.clock_time_get(@bitCast(u32, clk_id), 1, &ts)) { | 4670 | switch (system.clock_time_get(@bitCast(u32, clk_id), 1, &ts)) { |
| 4671 | 0 => { | 4671 | 0 => { |
| ... | @@ -4706,7 +4706,7 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void { | ... | @@ -4706,7 +4706,7 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void { |
| 4706 | } | 4706 | } |
| 4707 | 4707 | ||
| 4708 | pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void { | 4708 | pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void { |
| 4709 | if (std.Target.current.os.tag == .wasi) { | 4709 | if (std.Target.current.os.tag == .wasi and !builtin.link_libc) { |
| 4710 | var ts: timestamp_t = undefined; | 4710 | var ts: timestamp_t = undefined; |
| 4711 | switch (system.clock_res_get(@bitCast(u32, clk_id), &ts)) { | 4711 | switch (system.clock_res_get(@bitCast(u32, clk_id), &ts)) { |
| 4712 | 0 => res.* = .{ | 4712 | 0 => res.* = .{ |
| ... | @@ -4834,7 +4834,7 @@ pub const FutimensError = error{ | ... | @@ -4834,7 +4834,7 @@ pub const FutimensError = error{ |
| 4834 | } || UnexpectedError; | 4834 | } || UnexpectedError; |
| 4835 | 4835 | ||
| 4836 | pub fn futimens(fd: fd_t, times: *const [2]timespec) FutimensError!void { | 4836 | pub fn futimens(fd: fd_t, times: *const [2]timespec) FutimensError!void { |
| 4837 | if (builtin.os.tag == .wasi) { | 4837 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4838 | // TODO WASI encodes `wasi.fstflags` to signify magic values | 4838 | // TODO WASI encodes `wasi.fstflags` to signify magic values |
| 4839 | // similar to UTIME_NOW and UTIME_OMIT. Currently, we ignore | 4839 | // similar to UTIME_NOW and UTIME_OMIT. Currently, we ignore |
| 4840 | // this here, but we should really handle it somehow. | 4840 | // this here, but we should really handle it somehow. |
| ... | @@ -5581,7 +5581,10 @@ var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true); | ... | @@ -5581,7 +5581,10 @@ var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true); |
| 5581 | /// | 5581 | /// |
| 5582 | /// Maximum offsets on Linux are `math.maxInt(i64)`. | 5582 | /// Maximum offsets on Linux are `math.maxInt(i64)`. |
| 5583 | pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize { | 5583 | pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize { |
| 5584 | const call_cfr = comptime if (builtin.link_libc) | 5584 | const call_cfr = comptime if (std.Target.current.os.tag == .wasi) |
| 5585 | // WASI-libc doesn't have copy_file_range. | ||
| 5586 | false | ||
| 5587 | else if (builtin.link_libc) | ||
| 5585 | std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok | 5588 | std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok |
| 5586 | else | 5589 | else |
| 5587 | std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true; | 5590 | std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true; |
lib/std/os/bits/wasi.zig+55-8| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | // The MIT license requires this copyright notice to be included in all copies | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | // Convenience types and consts used by std.os module | 6 | // Convenience types and consts used by std.os module |
| 7 | const builtin = @import("builtin"); | ||
| 7 | const posix = @import("posix.zig"); | 8 | const posix = @import("posix.zig"); |
| 8 | pub const iovec = posix.iovec; | 9 | pub const iovec = posix.iovec; |
| 9 | pub const iovec_const = posix.iovec_const; | 10 | pub const iovec_const = posix.iovec_const; |
| ... | @@ -12,7 +13,7 @@ pub const STDIN_FILENO = 0; | ... | @@ -12,7 +13,7 @@ pub const STDIN_FILENO = 0; |
| 12 | pub const STDOUT_FILENO = 1; | 13 | pub const STDOUT_FILENO = 1; |
| 13 | pub const STDERR_FILENO = 2; | 14 | pub const STDERR_FILENO = 2; |
| 14 | 15 | ||
| 15 | pub const mode_t = u0; | 16 | pub const mode_t = u32; |
| 16 | 17 | ||
| 17 | pub const time_t = i64; // match https://github.com/CraneStation/wasi-libc | 18 | pub const time_t = i64; // match https://github.com/CraneStation/wasi-libc |
| 18 | 19 | ||
| ... | @@ -75,7 +76,8 @@ pub const kernel_stat = struct { | ... | @@ -75,7 +76,8 @@ pub const kernel_stat = struct { |
| 75 | } | 76 | } |
| 76 | }; | 77 | }; |
| 77 | 78 | ||
| 78 | pub const AT_REMOVEDIR: u32 = 1; // there's no AT_REMOVEDIR in WASI, but we simulate here to match other OSes | 79 | pub const AT_REMOVEDIR: u32 = 0x4; |
| 80 | pub const AT_FDCWD: fd_t = -2; | ||
| 79 | 81 | ||
| 80 | // As defined in the wasi_snapshot_preview1 spec file: | 82 | // As defined in the wasi_snapshot_preview1 spec file: |
| 81 | // https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx | 83 | // https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx |
| ... | @@ -115,6 +117,7 @@ pub const EADDRINUSE: errno_t = 3; | ... | @@ -115,6 +117,7 @@ pub const EADDRINUSE: errno_t = 3; |
| 115 | pub const EADDRNOTAVAIL: errno_t = 4; | 117 | pub const EADDRNOTAVAIL: errno_t = 4; |
| 116 | pub const EAFNOSUPPORT: errno_t = 5; | 118 | pub const EAFNOSUPPORT: errno_t = 5; |
| 117 | pub const EAGAIN: errno_t = 6; | 119 | pub const EAGAIN: errno_t = 6; |
| 120 | pub const EWOULDBLOCK = EAGAIN; | ||
| 118 | pub const EALREADY: errno_t = 7; | 121 | pub const EALREADY: errno_t = 7; |
| 119 | pub const EBADF: errno_t = 8; | 122 | pub const EBADF: errno_t = 8; |
| 120 | pub const EBADMSG: errno_t = 9; | 123 | pub const EBADMSG: errno_t = 9; |
| ... | @@ -167,6 +170,7 @@ pub const ENOTEMPTY: errno_t = 55; | ... | @@ -167,6 +170,7 @@ pub const ENOTEMPTY: errno_t = 55; |
| 167 | pub const ENOTRECOVERABLE: errno_t = 56; | 170 | pub const ENOTRECOVERABLE: errno_t = 56; |
| 168 | pub const ENOTSOCK: errno_t = 57; | 171 | pub const ENOTSOCK: errno_t = 57; |
| 169 | pub const ENOTSUP: errno_t = 58; | 172 | pub const ENOTSUP: errno_t = 58; |
| 173 | pub const EOPNOTSUPP = ENOTSUP; | ||
| 170 | pub const ENOTTY: errno_t = 59; | 174 | pub const ENOTTY: errno_t = 59; |
| 171 | pub const ENXIO: errno_t = 60; | 175 | pub const ENXIO: errno_t = 60; |
| 172 | pub const EOVERFLOW: errno_t = 61; | 176 | pub const EOVERFLOW: errno_t = 61; |
| ... | @@ -208,7 +212,7 @@ pub const EVENTTYPE_FD_WRITE: eventtype_t = 2; | ... | @@ -208,7 +212,7 @@ pub const EVENTTYPE_FD_WRITE: eventtype_t = 2; |
| 208 | 212 | ||
| 209 | pub const exitcode_t = u32; | 213 | pub const exitcode_t = u32; |
| 210 | 214 | ||
| 211 | pub const fd_t = u32; | 215 | pub const fd_t = if (builtin.link_libc) c_int else u32; |
| 212 | 216 | ||
| 213 | pub const fdflags_t = u16; | 217 | pub const fdflags_t = u16; |
| 214 | pub const FDFLAG_APPEND: fdflags_t = 0x0001; | 218 | pub const FDFLAG_APPEND: fdflags_t = 0x0001; |
| ... | @@ -275,11 +279,34 @@ pub const linkcount_t = u64; | ... | @@ -275,11 +279,34 @@ pub const linkcount_t = u64; |
| 275 | pub const lookupflags_t = u32; | 279 | pub const lookupflags_t = u32; |
| 276 | pub const LOOKUP_SYMLINK_FOLLOW: lookupflags_t = 0x00000001; | 280 | pub const LOOKUP_SYMLINK_FOLLOW: lookupflags_t = 0x00000001; |
| 277 | 281 | ||
| 278 | pub const oflags_t = u16; | 282 | pub usingnamespace if (builtin.link_libc) struct { |
| 279 | pub const O_CREAT: oflags_t = 0x0001; | 283 | // Derived from https://github.com/WebAssembly/wasi-libc/blob/main/expected/wasm32-wasi/predefined-macros.txt |
| 280 | pub const O_DIRECTORY: oflags_t = 0x0002; | 284 | pub const O_ACCMODE = (O_EXEC | O_RDWR | O_SEARCH); |
| 281 | pub const O_EXCL: oflags_t = 0x0004; | 285 | pub const O_APPEND = FDFLAG_APPEND; |
| 282 | pub const O_TRUNC: oflags_t = 0x0008; | 286 | pub const O_CLOEXEC = (0); |
| 287 | pub const O_CREAT = ((1 << 0) << 12); // = __WASI_OFLAGS_CREAT << 12 | ||
| 288 | pub const O_DIRECTORY = ((1 << 1) << 12); // = __WASI_OFLAGS_DIRECTORY << 12 | ||
| 289 | pub const O_DSYNC = FDFLAG_DSYNC; | ||
| 290 | pub const O_EXCL = ((1 << 2) << 12); // = __WASI_OFLAGS_EXCL << 12 | ||
| 291 | pub const O_EXEC = (0x02000000); | ||
| 292 | pub const O_NOCTTY = (0); | ||
| 293 | pub const O_NOFOLLOW = (0x01000000); | ||
| 294 | pub const O_NONBLOCK = (1 << FDFLAG_NONBLOCK); | ||
| 295 | pub const O_RDONLY = (0x04000000); | ||
| 296 | pub const O_RDWR = (O_RDONLY | O_WRONLY); | ||
| 297 | pub const O_RSYNC = (1 << FDFLAG_RSYNC); | ||
| 298 | pub const O_SEARCH = (0x08000000); | ||
| 299 | pub const O_SYNC = (1 << FDFLAG_SYNC); | ||
| 300 | pub const O_TRUNC = ((1 << 3) << 12); // = __WASI_OFLAGS_TRUNC << 12 | ||
| 301 | pub const O_TTY_INIT = (0); | ||
| 302 | pub const O_WRONLY = (0x10000000); | ||
| 303 | } else struct { | ||
| 304 | pub const oflags_t = u16; | ||
| 305 | pub const O_CREAT: oflags_t = 0x0001; | ||
| 306 | pub const O_DIRECTORY: oflags_t = 0x0002; | ||
| 307 | pub const O_EXCL: oflags_t = 0x0004; | ||
| 308 | pub const O_TRUNC: oflags_t = 0x0008; | ||
| 309 | }; | ||
| 283 | 310 | ||
| 284 | pub const preopentype_t = u8; | 311 | pub const preopentype_t = u8; |
| 285 | pub const PREOPENTYPE_DIR: preopentype_t = 0; | 312 | pub const PREOPENTYPE_DIR: preopentype_t = 0; |
| ... | @@ -441,3 +468,23 @@ pub const whence_t = u8; | ... | @@ -441,3 +468,23 @@ pub const whence_t = u8; |
| 441 | pub const WHENCE_SET: whence_t = 0; | 468 | pub const WHENCE_SET: whence_t = 0; |
| 442 | pub const WHENCE_CUR: whence_t = 1; | 469 | pub const WHENCE_CUR: whence_t = 1; |
| 443 | pub const WHENCE_END: whence_t = 2; | 470 | pub const WHENCE_END: whence_t = 2; |
| 471 | |||
| 472 | pub const S_IEXEC = S_IXUSR; | ||
| 473 | pub const S_IFBLK = 0x6000; | ||
| 474 | pub const S_IFCHR = 0x2000; | ||
| 475 | pub const S_IFDIR = 0x4000; | ||
| 476 | pub const S_IFIFO = 0xc000; | ||
| 477 | pub const S_IFLNK = 0xa000; | ||
| 478 | pub const S_IFMT = S_IFBLK | S_IFCHR | S_IFDIR | S_IFIFO | S_IFLNK | S_IFREG | S_IFSOCK; | ||
| 479 | pub const S_IFREG = 0x8000; | ||
| 480 | // There's no concept of UNIX domain socket but we define this value here in order to line with other OSes. | ||
| 481 | pub const S_IFSOCK = 0x1; | ||
| 482 | |||
| 483 | pub const SEEK_SET = WHENCE_SET; | ||
| 484 | pub const SEEK_CUR = WHENCE_CUR; | ||
| 485 | pub const SEEK_END = WHENCE_END; | ||
| 486 | |||
| 487 | pub const LOCK_SH = 0x1; | ||
| 488 | pub const LOCK_EX = 0x2; | ||
| 489 | pub const LOCK_NB = 0x4; | ||
| 490 | pub const LOCK_UN = 0x8; |
lib/std/process.zig+4-4| ... | @@ -88,7 +88,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { | ... | @@ -88,7 +88,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap { |
| 88 | try result.putMove(key, value); | 88 | try result.putMove(key, value); |
| 89 | } | 89 | } |
| 90 | return result; | 90 | return result; |
| 91 | } else if (builtin.os.tag == .wasi) { | 91 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 92 | var environ_count: usize = undefined; | 92 | var environ_count: usize = undefined; |
| 93 | var environ_buf_size: usize = undefined; | 93 | var environ_buf_size: usize = undefined; |
| 94 | 94 | ||
| ... | @@ -450,7 +450,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -450,7 +450,7 @@ pub const ArgIteratorWindows = struct { |
| 450 | pub const ArgIterator = struct { | 450 | pub const ArgIterator = struct { |
| 451 | const InnerType = switch (builtin.os.tag) { | 451 | const InnerType = switch (builtin.os.tag) { |
| 452 | .windows => ArgIteratorWindows, | 452 | .windows => ArgIteratorWindows, |
| 453 | .wasi => ArgIteratorWasi, | 453 | .wasi => if (builtin.link_libc) ArgIteratorPosix else ArgIteratorWasi, |
| 454 | else => ArgIteratorPosix, | 454 | else => ArgIteratorPosix, |
| 455 | }; | 455 | }; |
| 456 | 456 | ||
| ... | @@ -469,7 +469,7 @@ pub const ArgIterator = struct { | ... | @@ -469,7 +469,7 @@ pub const ArgIterator = struct { |
| 469 | 469 | ||
| 470 | /// You must deinitialize iterator's internal buffers by calling `deinit` when done. | 470 | /// You must deinitialize iterator's internal buffers by calling `deinit` when done. |
| 471 | pub fn initWithAllocator(allocator: *mem.Allocator) InitError!ArgIterator { | 471 | pub fn initWithAllocator(allocator: *mem.Allocator) InitError!ArgIterator { |
| 472 | if (builtin.os.tag == .wasi) { | 472 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 473 | return ArgIterator{ .inner = try InnerType.init(allocator) }; | 473 | return ArgIterator{ .inner = try InnerType.init(allocator) }; |
| 474 | } | 474 | } |
| 475 | 475 | ||
| ... | @@ -507,7 +507,7 @@ pub const ArgIterator = struct { | ... | @@ -507,7 +507,7 @@ pub const ArgIterator = struct { |
| 507 | /// was created with `initWithAllocator` function. | 507 | /// was created with `initWithAllocator` function. |
| 508 | pub fn deinit(self: *ArgIterator) void { | 508 | pub fn deinit(self: *ArgIterator) void { |
| 509 | // Unless we're targeting WASI, this is a no-op. | 509 | // Unless we're targeting WASI, this is a no-op. |
| 510 | if (builtin.os.tag == .wasi) { | 510 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 511 | self.inner.deinit(); | 511 | self.inner.deinit(); |
| 512 | } | 512 | } |
| 513 | } | 513 | } |
lib/std/start.zig+8-1| ... | @@ -46,7 +46,9 @@ comptime { | ... | @@ -46,7 +46,9 @@ comptime { |
| 46 | } | 46 | } |
| 47 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { | 47 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { |
| 48 | if (builtin.link_libc and @hasDecl(root, "main")) { | 48 | if (builtin.link_libc and @hasDecl(root, "main")) { |
| 49 | if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { | 49 | if (native_arch.isWasm()) { |
| 50 | @export(mainWithoutEnv, .{ .name = "main" }); | ||
| 51 | } else if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { | ||
| 50 | @export(main, .{ .name = "main" }); | 52 | @export(main, .{ .name = "main" }); |
| 51 | } | 53 | } |
| 52 | } else if (native_os == .windows) { | 54 | } else if (native_os == .windows) { |
| ... | @@ -420,6 +422,11 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) | ... | @@ -420,6 +422,11 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) |
| 420 | return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp }); | 422 | return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp }); |
| 421 | } | 423 | } |
| 422 | 424 | ||
| 425 | fn mainWithoutEnv(c_argc: i32, c_argv: [*][*:0]u8) callconv(.C) usize { | ||
| 426 | std.os.argv = c_argv[0..@intCast(usize, c_argc)]; | ||
| 427 | return @call(.{ .modifier = .always_inline }, callMain, .{}); | ||
| 428 | } | ||
| 429 | |||
| 423 | // General error message for a malformed return type | 430 | // General error message for a malformed return type |
| 424 | const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'"; | 431 | const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'"; |
| 425 | 432 |
lib/std/testing.zig+2-1| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | // The MIT license requires this copyright notice to be included in all copies | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 7 | |||
| 7 | const math = std.math; | 8 | const math = std.math; |
| 8 | const print = std.debug.print; | 9 | const print = std.debug.print; |
| 9 | 10 | ||
| ... | @@ -326,7 +327,7 @@ pub const TmpDir = struct { | ... | @@ -326,7 +327,7 @@ pub const TmpDir = struct { |
| 326 | }; | 327 | }; |
| 327 | 328 | ||
| 328 | fn getCwdOrWasiPreopen() std.fs.Dir { | 329 | fn getCwdOrWasiPreopen() std.fs.Dir { |
| 329 | if (std.builtin.os.tag == .wasi) { | 330 | if (std.builtin.os.tag == .wasi and !std.builtin.link_libc) { |
| 330 | var preopens = std.fs.wasi.PreopenList.init(allocator); | 331 | var preopens = std.fs.wasi.PreopenList.init(allocator); |
| 331 | defer preopens.deinit(); | 332 | defer preopens.deinit(); |
| 332 | preopens.populate() catch | 333 | preopens.populate() catch |
src/stage1/codegen.cpp+3-1| ... | @@ -582,7 +582,9 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { | ... | @@ -582,7 +582,9 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 582 | 582 | ||
| 583 | bool want_ssp_attrs = g->build_mode != BuildModeFastRelease && | 583 | bool want_ssp_attrs = g->build_mode != BuildModeFastRelease && |
| 584 | g->build_mode != BuildModeSmallRelease && | 584 | g->build_mode != BuildModeSmallRelease && |
| 585 | g->link_libc; | 585 | g->link_libc && |
| 586 | // WASI-libc does not support stack-protector yet. | ||
| 587 | !target_is_wasm(g->zig_target); | ||
| 586 | if (want_ssp_attrs) { | 588 | if (want_ssp_attrs) { |
| 587 | addLLVMFnAttr(llvm_fn, "sspstrong"); | 589 | addLLVMFnAttr(llvm_fn, "sspstrong"); |
| 588 | addLLVMFnAttrStr(llvm_fn, "stack-protector-buffer-size", "4"); | 590 | addLLVMFnAttrStr(llvm_fn, "stack-protector-buffer-size", "4"); |
test/cases.zig+1-1| ... | @@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 26 | var case = ctx.exe("hello world with updates", linux_x64); | 26 | var case = ctx.exe("hello world with updates", linux_x64); |
| 27 | 27 | ||
| 28 | case.addError("", &[_][]const u8{ | 28 | case.addError("", &[_][]const u8{ |
| 29 | ":93:9: error: struct 'tmp.tmp' has no member named 'main'", | 29 | ":95:9: error: struct 'tmp.tmp' has no member named 'main'", |
| 30 | }); | 30 | }); |
| 31 | 31 | ||
| 32 | // Incorrect return type | 32 | // Incorrect return type |
test/stage2/darwin.zig+1-1| ... | @@ -14,7 +14,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -14,7 +14,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 14 | { | 14 | { |
| 15 | var case = ctx.exe("hello world with updates", target); | 15 | var case = ctx.exe("hello world with updates", target); |
| 16 | case.addError("", &[_][]const u8{ | 16 | case.addError("", &[_][]const u8{ |
| 17 | ":93:9: error: struct 'tmp.tmp' has no member named 'main'", | 17 | ":95:9: error: struct 'tmp.tmp' has no member named 'main'", |
| 18 | }); | 18 | }); |
| 19 | 19 | ||
| 20 | // Incorrect return type | 20 | // Incorrect return type |
test/tests.zig+8| ... | @@ -57,6 +57,14 @@ const test_targets = blk: { | ... | @@ -57,6 +57,14 @@ const test_targets = blk: { |
| 57 | .link_libc = false, | 57 | .link_libc = false, |
| 58 | .single_threaded = true, | 58 | .single_threaded = true, |
| 59 | }, | 59 | }, |
| 60 | TestTarget{ | ||
| 61 | .target = .{ | ||
| 62 | .cpu_arch = .wasm32, | ||
| 63 | .os_tag = .wasi, | ||
| 64 | }, | ||
| 65 | .link_libc = true, | ||
| 66 | .single_threaded = true, | ||
| 67 | }, | ||
| 60 | 68 | ||
| 61 | TestTarget{ | 69 | TestTarget{ |
| 62 | .target = .{ | 70 | .target = .{ |