Commit 143127529b
Changed files (5)
lib
std
lib/std/Io/Threaded.zig
@@ -167,7 +167,7 @@ pub fn io(t: *Threaded) Io {
.dirMake = switch (builtin.os.tag) {
.windows => @panic("TODO"),
- .wasi => @panic("TODO"),
+ .wasi => dirMakeWasi,
else => dirMakePosix,
},
.dirStat = dirStat,
@@ -906,6 +906,37 @@ fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode:
}
}
+fn dirMakeWasi(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {
+ if (builtin.link_libc) return dirMakePosix(userdata, dir, sub_path, mode);
+ const t: *Threaded = @ptrCast(@alignCast(userdata));
+ while (true) {
+ try t.checkCancel();
+ switch (std.os.wasi.path_create_directory(dir.handle, sub_path.ptr, sub_path.len)) {
+ .SUCCESS => return,
+ .INTR => continue,
+ .CANCELED => return error.Canceled,
+
+ .ACCES => return error.AccessDenied,
+ .BADF => |err| return errnoBug(err),
+ .PERM => return error.PermissionDenied,
+ .DQUOT => return error.DiskQuota,
+ .EXIST => return error.PathAlreadyExists,
+ .FAULT => |err| return errnoBug(err),
+ .LOOP => return error.SymLinkLoop,
+ .MLINK => return error.LinkQuotaExceeded,
+ .NAMETOOLONG => return error.NameTooLong,
+ .NOENT => return error.FileNotFound,
+ .NOMEM => return error.SystemResources,
+ .NOSPC => return error.NoSpaceLeft,
+ .NOTDIR => return error.NotDir,
+ .ROFS => return error.ReadOnlyFileSystem,
+ .NOTCAPABLE => return error.AccessDenied,
+ .ILSEQ => return error.BadPathName,
+ else => |err| return posix.unexpectedErrno(err),
+ }
+ }
+}
+
fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat {
const t: *Threaded = @ptrCast(@alignCast(userdata));
try t.checkCancel();
@@ -1005,13 +1036,13 @@ fn dirStatPathWasi(
const t: *Threaded = @ptrCast(@alignCast(userdata));
const wasi = std.os.wasi;
const flags: wasi.lookupflags_t = .{
- .SYMLINK_FOLLOW = @intFromBool(options.follow_symlinks),
+ .SYMLINK_FOLLOW = options.follow_symlinks,
};
var stat: wasi.filestat_t = undefined;
while (true) {
try t.checkCancel();
switch (wasi.path_filestat_get(dir.handle, flags, sub_path.ptr, sub_path.len, &stat)) {
- .SUCCESS => return statFromWasi(stat),
+ .SUCCESS => return statFromWasi(&stat),
.INTR => continue,
.CANCELED => return error.Canceled,
@@ -1166,19 +1197,19 @@ fn dirAccessWasi(
userdata: ?*anyopaque,
dir: Io.Dir,
sub_path: []const u8,
- options: Io.File.OpenFlags,
-) Io.File.AccessError!void {
+ options: Io.Dir.AccessOptions,
+) Io.Dir.AccessError!void {
if (builtin.link_libc) return dirAccessPosix(userdata, dir, sub_path, options);
const t: *Threaded = @ptrCast(@alignCast(userdata));
const wasi = std.os.wasi;
const flags: wasi.lookupflags_t = .{
- .SYMLINK_FOLLOW = @intFromBool(options.follow_symlinks),
+ .SYMLINK_FOLLOW = options.follow_symlinks,
};
- const stat = while (true) {
- var stat: wasi.filestat_t = undefined;
+ var stat: wasi.filestat_t = undefined;
+ while (true) {
try t.checkCancel();
switch (wasi.path_filestat_get(dir.handle, flags, sub_path.ptr, sub_path.len, &stat)) {
- .SUCCESS => break statFromWasi(stat),
+ .SUCCESS => break,
.INTR => continue,
.CANCELED => return error.Canceled,
@@ -1194,9 +1225,9 @@ fn dirAccessWasi(
.ILSEQ => return error.BadPathName,
else => |err| return posix.unexpectedErrno(err),
}
- };
+ }
- if (!options.mode.read and !options.mode.write and !options.mode.execute)
+ if (!options.read and !options.write and !options.execute)
return;
var directory: wasi.fdstat_t = undefined;
@@ -1204,14 +1235,14 @@ fn dirAccessWasi(
return error.AccessDenied;
var rights: wasi.rights_t = .{};
- if (options.mode.read) {
+ if (options.read) {
if (stat.filetype == .DIRECTORY) {
rights.FD_READDIR = true;
} else {
rights.FD_READ = true;
}
}
- if (options.mode.write)
+ if (options.write)
rights.FD_WRITE = true;
// No validation for execution.
@@ -3262,9 +3293,9 @@ fn statFromWasi(st: *const std.os.wasi.filestat_t) Io.File.Stat {
.SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket,
else => .unknown,
},
- .atime = st.atim,
- .mtime = st.mtim,
- .ctime = st.ctim,
+ .atime = .fromNanoseconds(st.atim),
+ .mtime = .fromNanoseconds(st.mtim),
+ .ctime = .fromNanoseconds(st.ctim),
};
}
lib/std/posix/test.zig
@@ -109,64 +109,6 @@ test "open smoke test" {
}
}
-test "openat smoke test" {
- if (native_os == .windows) return error.SkipZigTest;
-
- // TODO verify file attributes using `fstatat`
-
- var tmp = tmpDir(.{});
- defer tmp.cleanup();
-
- var fd: posix.fd_t = undefined;
- const mode: posix.mode_t = if (native_os == .windows) 0 else 0o666;
-
- // Create some file using `openat`.
- fd = try posix.openat(tmp.dir.fd, "some_file", CommonOpenFlags.lower(.{
- .ACCMODE = .RDWR,
- .CREAT = true,
- .EXCL = true,
- }), mode);
- posix.close(fd);
-
- // Try this again with the same flags. This op should fail with error.PathAlreadyExists.
- try expectError(error.PathAlreadyExists, posix.openat(tmp.dir.fd, "some_file", CommonOpenFlags.lower(.{
- .ACCMODE = .RDWR,
- .CREAT = true,
- .EXCL = true,
- }), mode));
-
- // Try opening without `EXCL` flag.
- fd = try posix.openat(tmp.dir.fd, "some_file", CommonOpenFlags.lower(.{
- .ACCMODE = .RDWR,
- .CREAT = true,
- }), mode);
- posix.close(fd);
-
- // Try opening as a directory which should fail.
- try expectError(error.NotDir, posix.openat(tmp.dir.fd, "some_file", CommonOpenFlags.lower(.{
- .ACCMODE = .RDWR,
- .DIRECTORY = true,
- }), mode));
-
- // Create some directory
- try posix.mkdirat(tmp.dir.fd, "some_dir", mode);
-
- // Open dir using `open`
- fd = try posix.openat(tmp.dir.fd, "some_dir", CommonOpenFlags.lower(.{
- .ACCMODE = .RDONLY,
- .DIRECTORY = true,
- }), mode);
- posix.close(fd);
-
- // Try opening as file which should fail (skip on wasi+libc due to
- // https://github.com/bytecodealliance/wasmtime/issues/9054)
- if (native_os != .wasi or !builtin.link_libc) {
- try expectError(error.IsDir, posix.openat(tmp.dir.fd, "some_dir", CommonOpenFlags.lower(.{
- .ACCMODE = .RDWR,
- }), mode));
- }
-}
-
test "readlink on Windows" {
if (native_os != .windows) return error.SkipZigTest;
lib/std/Io.zig
@@ -883,6 +883,10 @@ pub const Timestamp = struct {
return .{ .nanoseconds = t.nanoseconds, .clock = clock };
}
+ pub fn fromNanoseconds(x: i96) Timestamp {
+ return .{ .nanoseconds = x };
+ }
+
pub fn toSeconds(t: Timestamp) i64 {
return @intCast(@divTrunc(t.nanoseconds, std.time.ns_per_s));
}
lib/std/os.zig
@@ -201,7 +201,13 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
}
}
-pub fn fstat_wasi(fd: posix.fd_t) posix.FStatError!wasi.filestat_t {
+pub const FstatError = error{
+ SystemResources,
+ AccessDenied,
+ Unexpected,
+};
+
+pub fn fstat_wasi(fd: posix.fd_t) FstatError!wasi.filestat_t {
var stat: wasi.filestat_t = undefined;
switch (wasi.fd_filestat_get(fd, &stat)) {
.SUCCESS => return stat,
lib/std/posix.zig
@@ -2809,37 +2809,13 @@ pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: mode_t) MakeDirErro
const sub_dir_path_w = try windows.sliceToPrefixedFileW(dir_fd, sub_dir_path);
return mkdiratW(dir_fd, sub_dir_path_w.span(), mode);
} else if (native_os == .wasi and !builtin.link_libc) {
- return mkdiratWasi(dir_fd, sub_dir_path, mode);
+ @compileError("use std.Io instead");
} else {
const sub_dir_path_c = try toPosixPath(sub_dir_path);
return mkdiratZ(dir_fd, &sub_dir_path_c, mode);
}
}
-pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: mode_t) MakeDirError!void {
- _ = mode;
- switch (wasi.path_create_directory(dir_fd, sub_dir_path.ptr, sub_dir_path.len)) {
- .SUCCESS => return,
- .ACCES => return error.AccessDenied,
- .BADF => unreachable,
- .PERM => return error.PermissionDenied,
- .DQUOT => return error.DiskQuota,
- .EXIST => return error.PathAlreadyExists,
- .FAULT => unreachable,
- .LOOP => return error.SymLinkLoop,
- .MLINK => return error.LinkQuotaExceeded,
- .NAMETOOLONG => return error.NameTooLong,
- .NOENT => return error.FileNotFound,
- .NOMEM => return error.SystemResources,
- .NOSPC => return error.NoSpaceLeft,
- .NOTDIR => return error.NotDir,
- .ROFS => return error.ReadOnlyFileSystem,
- .NOTCAPABLE => return error.AccessDenied,
- .ILSEQ => return error.BadPathName,
- else => |err| return unexpectedErrno(err),
- }
-}
-
/// Same as `mkdirat` except the parameters are null-terminated.
pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: mode_t) MakeDirError!void {
if (native_os == .windows) {