Skip to content

Commit

Permalink
WASI,libc: enable tests.
Browse files Browse the repository at this point in the history
Signed-off-by: Takeshi Yoneda <[email protected]>
  • Loading branch information
mathetake committed Jul 27, 2021
1 parent fc105f2 commit 1e20a62
Show file tree
Hide file tree
Showing 16 changed files with 221 additions and 86 deletions.
2 changes: 1 addition & 1 deletion lib/std/Thread.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub const Condition = @import("Thread/Condition.zig");

pub const spinLoopHint = @compileError("deprecated: use std.atomic.spinLoopHint");

pub const use_pthreads = target.os.tag != .windows and std.builtin.link_libc;
pub const use_pthreads = target.os.tag != .windows and std.Target.current.os.tag != .wasi and std.builtin.link_libc;

const Thread = @This();
const Impl = if (target.os.tag == .windows)
Expand Down
2 changes: 2 additions & 0 deletions lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub usingnamespace switch (std.Target.current.os.tag) {
.fuchsia => @import("c/fuchsia.zig"),
.minix => @import("c/minix.zig"),
.emscripten => @import("c/emscripten.zig"),
.wasi => @import("c/wasi.zig"),
else => struct {},
};

Expand Down Expand Up @@ -77,6 +78,7 @@ pub extern "c" fn fread(noalias ptr: [*]u8, size_of_type: usize, item_count: usi

pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
pub extern "c" fn abort() noreturn;

pub extern "c" fn exit(code: c_int) noreturn;
pub extern "c" fn _exit(code: c_int) noreturn;
pub extern "c" fn isatty(fd: fd_t) c_int;
Expand Down
60 changes: 60 additions & 0 deletions lib/std/c/wasi.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2015-2021 Zig Contributors
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
usingnamespace @import("../os/bits.zig");

extern threadlocal var errno: c_int;

pub fn _errno() *c_int {
return &errno;
}

pub const pid_t = c_int;
pub const uid_t = u32;
pub const gid_t = u32;
pub const off_t = i64;

pub const libc_stat = extern struct {
dev: i32,
ino: ino_t,
nlink: u64,

mode: mode_t,
uid: uid_t,
gid: gid_t,
__pad0: isize,
rdev: i32,
size: off_t,
blksize: i32,
blocks: i64,

atimesec: time_t,
atimensec: isize,
mtimesec: time_t,
mtimensec: isize,
ctimesec: time_t,
ctimensec: isize,

pub fn atime(self: @This()) timespec {
return timespec{
.tv_sec = self.atimesec,
.tv_nsec = self.atimensec,
};
}

pub fn mtime(self: @This()) timespec {
return timespec{
.tv_sec = self.mtimesec,
.tv_nsec = self.mtimensec,
};
}

pub fn ctime(self: @This()) timespec {
return timespec{
.tv_sec = self.ctimesec,
.tv_nsec = self.ctimensec,
};
}
};
55 changes: 31 additions & 24 deletions lib/std/fs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,9 @@ pub const Dir = struct {
/// Memory such as file names referenced in this returned entry becomes invalid
/// with subsequent calls to `next`, as well as when this `Dir` is deinitialized.
pub fn next(self: *Self) Error!?Entry {
// We intentinally use fd_readdir even when linked with libc,
// since its implementation is exactly the same as below,
// and we avoid the code complexity here.
const w = os.wasi;
start_over: while (true) {
if (self.index >= self.end_index) {
Expand Down Expand Up @@ -770,7 +773,7 @@ pub const Dir = struct {
const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.openFileW(path_w.span(), flags);
}
if (builtin.os.tag == .wasi) {
if (builtin.os.tag == .wasi and !builtin.link_libc) {
return self.openFileWasi(sub_path, flags);
}
const path_c = try os.toPosixPath(sub_path);
Expand Down Expand Up @@ -846,14 +849,16 @@ pub const Dir = struct {
try os.openatZ(self.fd, sub_path, os_flags, 0);
errdefer os.close(fd);

if (!has_flock_open_flags and flags.lock != .None) {
// TODO: integrate async I/O
const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK_NB else @as(i32, 0);
try os.flock(fd, switch (flags.lock) {
.None => unreachable,
.Shared => os.LOCK_SH | lock_nonblocking,
.Exclusive => os.LOCK_EX | lock_nonblocking,
});
if (builtin.target.os.tag != .wasi) {
if (!has_flock_open_flags and flags.lock != .None) {
// TODO: integrate async I/O
const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK_NB else @as(i32, 0);
try os.flock(fd, switch (flags.lock) {
.None => unreachable,
.Shared => os.LOCK_SH | lock_nonblocking,
.Exclusive => os.LOCK_EX | lock_nonblocking,
});
}
}

if (has_flock_open_flags and flags.lock_nonblocking) {
Expand Down Expand Up @@ -926,7 +931,7 @@ pub const Dir = struct {
const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.createFileW(path_w.span(), flags);
}
if (builtin.os.tag == .wasi) {
if (builtin.os.tag == .wasi and !builtin.link_libc) {
return self.createFileWasi(sub_path, flags);
}
const path_c = try os.toPosixPath(sub_path);
Expand Down Expand Up @@ -996,14 +1001,16 @@ pub const Dir = struct {
try os.openatZ(self.fd, sub_path_c, os_flags, flags.mode);
errdefer os.close(fd);

if (!has_flock_open_flags and flags.lock != .None) {
// TODO: integrate async I/O
const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK_NB else @as(i32, 0);
try os.flock(fd, switch (flags.lock) {
.None => unreachable,
.Shared => os.LOCK_SH | lock_nonblocking,
.Exclusive => os.LOCK_EX | lock_nonblocking,
});
if (builtin.target.os.tag != .wasi) {
if (!has_flock_open_flags and flags.lock != .None and builtin.target.os.tag != .wasi) {
// TODO: integrate async I/O
const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK_NB else @as(i32, 0);
try os.flock(fd, switch (flags.lock) {
.None => unreachable,
.Shared => os.LOCK_SH | lock_nonblocking,
.Exclusive => os.LOCK_EX | lock_nonblocking,
});
}
}

if (has_flock_open_flags and flags.lock_nonblocking) {
Expand Down Expand Up @@ -1284,7 +1291,7 @@ pub const Dir = struct {
if (builtin.os.tag == .windows) {
const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.openDirW(sub_path_w.span().ptr, args);
} else if (builtin.os.tag == .wasi) {
} else if (builtin.os.tag == .wasi and !builtin.link_libc) {
return self.openDirWasi(sub_path, args);
} else {
const sub_path_c = try os.toPosixPath(sub_path);
Expand Down Expand Up @@ -1431,7 +1438,7 @@ pub const Dir = struct {
if (builtin.os.tag == .windows) {
const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.deleteFileW(sub_path_w.span());
} else if (builtin.os.tag == .wasi) {
} else if (builtin.os.tag == .wasi and !builtin.link_libc) {
os.unlinkatWasi(self.fd, sub_path, 0) catch |err| switch (err) {
error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
else => |e| return e,
Expand Down Expand Up @@ -1494,7 +1501,7 @@ pub const Dir = struct {
if (builtin.os.tag == .windows) {
const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.deleteDirW(sub_path_w.span());
} else if (builtin.os.tag == .wasi) {
} else if (builtin.os.tag == .wasi and !builtin.link_libc) {
os.unlinkat(self.fd, sub_path, os.AT_REMOVEDIR) catch |err| switch (err) {
error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
else => |e| return e,
Expand Down Expand Up @@ -1553,7 +1560,7 @@ pub const Dir = struct {
sym_link_path: []const u8,
flags: SymLinkFlags,
) !void {
if (builtin.os.tag == .wasi) {
if (builtin.os.tag == .wasi and !builtin.link_libc) {
return self.symLinkWasi(target_path, sym_link_path, flags);
}
if (builtin.os.tag == .windows) {
Expand Down Expand Up @@ -1606,7 +1613,7 @@ pub const Dir = struct {
/// The return value is a slice of `buffer`, from index `0`.
/// Asserts that the path parameter has no null bytes.
pub fn readLink(self: Dir, sub_path: []const u8, buffer: []u8) ![]u8 {
if (builtin.os.tag == .wasi) {
if (builtin.os.tag == .wasi and !builtin.link_libc) {
return self.readLinkWasi(sub_path, buffer);
}
if (builtin.os.tag == .windows) {
Expand Down Expand Up @@ -2025,7 +2032,7 @@ pub const Dir = struct {
pub fn cwd() Dir {
if (builtin.os.tag == .windows) {
return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
} else if (builtin.os.tag == .wasi) {
} else if (builtin.os.tag == .wasi and !builtin.link_libc) {
@compileError("WASI doesn't have a concept of cwd(); use std.fs.wasi.PreopenList to get available Dir handles instead");
} else {
return Dir{ .fd = os.AT_FDCWD };
Expand Down
37 changes: 17 additions & 20 deletions lib/std/fs/file.zig
Original file line number Diff line number Diff line change
Expand Up @@ -326,26 +326,23 @@ pub const File = struct {
.inode = st.ino,
.size = @bitCast(u64, st.size),
.mode = st.mode,
.kind = switch (builtin.os.tag) {
.wasi => switch (st.filetype) {
os.FILETYPE_BLOCK_DEVICE => Kind.BlockDevice,
os.FILETYPE_CHARACTER_DEVICE => Kind.CharacterDevice,
os.FILETYPE_DIRECTORY => Kind.Directory,
os.FILETYPE_SYMBOLIC_LINK => Kind.SymLink,
os.FILETYPE_REGULAR_FILE => Kind.File,
os.FILETYPE_SOCKET_STREAM, os.FILETYPE_SOCKET_DGRAM => Kind.UnixDomainSocket,
else => Kind.Unknown,
},
else => switch (st.mode & os.S_IFMT) {
os.S_IFBLK => Kind.BlockDevice,
os.S_IFCHR => Kind.CharacterDevice,
os.S_IFDIR => Kind.Directory,
os.S_IFIFO => Kind.NamedPipe,
os.S_IFLNK => Kind.SymLink,
os.S_IFREG => Kind.File,
os.S_IFSOCK => Kind.UnixDomainSocket,
else => Kind.Unknown,
},
.kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) {
os.FILETYPE_BLOCK_DEVICE => Kind.BlockDevice,
os.FILETYPE_CHARACTER_DEVICE => Kind.CharacterDevice,
os.FILETYPE_DIRECTORY => Kind.Directory,
os.FILETYPE_SYMBOLIC_LINK => Kind.SymLink,
os.FILETYPE_REGULAR_FILE => Kind.File,
os.FILETYPE_SOCKET_STREAM, os.FILETYPE_SOCKET_DGRAM => Kind.UnixDomainSocket,
else => Kind.Unknown,
} else switch (st.mode & os.S_IFMT) {
os.S_IFBLK => Kind.BlockDevice,
os.S_IFCHR => Kind.CharacterDevice,
os.S_IFDIR => Kind.Directory,
os.S_IFIFO => Kind.NamedPipe,
os.S_IFLNK => Kind.SymLink,
os.S_IFREG => Kind.File,
os.S_IFSOCK => Kind.UnixDomainSocket,
else => Kind.Unknown,
},
.atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
.mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
Expand Down
2 changes: 1 addition & 1 deletion lib/std/fs/wasi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub const PreopenList = struct {
};

test "extracting WASI preopens" {
if (std.builtin.os.tag != .wasi) return error.SkipZigTest;
if (std.builtin.os.tag != .wasi or @import("builtin").link_libc) return error.SkipZigTest;

var preopens = PreopenList.init(std.testing.allocator);
defer preopens.deinit();
Expand Down
2 changes: 1 addition & 1 deletion lib/std/io/c_writer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn cWriterWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!u
}

test {
if (!builtin.link_libc) return error.SkipZigTest;
if (!builtin.link_libc or builtin.os.tag == .wasi) return error.SkipZigTest;

const filename = "tmp_io_test_file.txt";
const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
Expand Down
Loading

0 comments on commit 1e20a62

Please sign in to comment.