Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/platform.zig
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ fn linuxResultAsIsize(rc: usize) isize {
return @bitCast(rc);
}

fn linuxResultAsI32(rc: usize) i32 {
const e = std.os.linux.errno(rc);
if (e != .SUCCESS) {
std.c._errno().* = @intFromEnum(e);
return -1;
}
return 0;
}

fn linuxResultAsI64(rc: usize) i64 {
const e = std.os.linux.errno(rc);
if (e != .SUCCESS) {
Expand Down Expand Up @@ -241,6 +250,63 @@ pub fn pfdClose(handle: std.posix.fd_t) void {
}
}

// Path-based helpers. All POSIX-only (callers of these helpers already
// branch to a `std.Io.Dir` path on Windows before reaching here). The
// `.windows` arms return -1 so compilation succeeds on Windows builds;
// the helpers themselves are never reached at runtime on Windows.
pub fn pfdMkdirAt(dirfd: std.posix.fd_t, path: [*:0]const u8, mode: u32) i32 {
switch (comptime builtin.os.tag) {
.windows => return -1,
.linux => return linuxResultAsI32(std.os.linux.mkdirat(dirfd, path, mode)),
else => return @intCast(std.c.mkdirat(dirfd, path, @intCast(mode))),
}
}

pub fn pfdUnlinkAt(dirfd: std.posix.fd_t, path: [*:0]const u8, flags: u32) i32 {
switch (comptime builtin.os.tag) {
.windows => return -1,
.linux => return linuxResultAsI32(std.os.linux.unlinkat(dirfd, path, flags)),
else => return @intCast(std.c.unlinkat(dirfd, path, @intCast(flags))),
}
}

pub fn pfdRenameAt(
old_dirfd: std.posix.fd_t,
old_path: [*:0]const u8,
new_dirfd: std.posix.fd_t,
new_path: [*:0]const u8,
) i32 {
switch (comptime builtin.os.tag) {
.windows => return -1,
.linux => return linuxResultAsI32(std.os.linux.renameat(old_dirfd, old_path, new_dirfd, new_path)),
else => return @intCast(std.c.renameat(old_dirfd, old_path, new_dirfd, new_path)),
}
}

pub fn pfdReadlinkAt(dirfd: std.posix.fd_t, path: [*:0]const u8, buf: []u8) isize {
switch (comptime builtin.os.tag) {
.windows => return -1,
.linux => return linuxResultAsIsize(std.os.linux.readlinkat(dirfd, path, buf.ptr, buf.len)),
else => return std.c.readlinkat(dirfd, path, buf.ptr, buf.len),
}
}

pub fn pfdDup(fd: std.posix.fd_t) i32 {
switch (comptime builtin.os.tag) {
.windows => return -1,
.linux => {
const rc = std.os.linux.dup(fd);
const e = std.os.linux.errno(rc);
if (e != .SUCCESS) {
std.c._errno().* = @intFromEnum(e);
return -1;
}
return @intCast(rc);
},
else => return @intCast(std.c.dup(fd)),
}
}

pub fn pfdFsync(handle: std.posix.fd_t) i32 {
switch (comptime builtin.os.tag) {
.windows => return if (FlushFileBuffers(handle) == windows.BOOL.FALSE) -1 else 0,
Expand Down
24 changes: 17 additions & 7 deletions src/wasi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1652,7 +1652,7 @@ pub fn path_create_directory(ctx: *anyopaque, _: usize) anyerror!void {
try pushErrno(vm, .NAMETOOLONG);
return;
};
if (std.c.mkdirat(host_fd, path_z.ptr, 0o777) != 0) {
if (platform.pfdMkdirAt(host_fd, path_z.ptr, 0o777) != 0) {
try pushErrno(vm, cErrnoToWasi());
return;
}
Expand Down Expand Up @@ -1697,7 +1697,7 @@ pub fn path_remove_directory(ctx: *anyopaque, _: usize) anyerror!void {
try pushErrno(vm, .NAMETOOLONG);
return;
};
if (std.c.unlinkat(host_fd, path_z.ptr, @intCast(posix.AT.REMOVEDIR)) != 0) {
if (platform.pfdUnlinkAt(host_fd, path_z.ptr, @intCast(posix.AT.REMOVEDIR)) != 0) {
try pushErrno(vm, cErrnoToWasi());
return;
}
Expand Down Expand Up @@ -1742,7 +1742,7 @@ pub fn path_unlink_file(ctx: *anyopaque, _: usize) anyerror!void {
try pushErrno(vm, .NAMETOOLONG);
return;
};
if (std.c.unlinkat(host_fd, path_z.ptr, 0) != 0) {
if (platform.pfdUnlinkAt(host_fd, path_z.ptr, 0) != 0) {
try pushErrno(vm, cErrnoToWasi());
return;
}
Expand Down Expand Up @@ -1802,7 +1802,7 @@ pub fn path_rename(ctx: *anyopaque, _: usize) anyerror!void {
try pushErrno(vm, .NAMETOOLONG);
return;
};
if (std.c.renameat(old_host_fd, old_z.ptr, new_host_fd, new_z.ptr) != 0) {
if (platform.pfdRenameAt(old_host_fd, old_z.ptr, new_host_fd, new_z.ptr) != 0) {
try pushErrno(vm, cErrnoToWasi());
return;
}
Expand Down Expand Up @@ -2053,7 +2053,17 @@ pub fn fd_filestat_set_times(ctx: *anyopaque, _: usize) anyerror!void {
};

const times = wasiTimesToTimespec(fst_flags, atim_ns, mtim_ns);
if (std.c.futimens(host_fd, &times) != 0) {
const failed = switch (comptime builtin.os.tag) {
.linux => blk: {
// utimensat(fd, NULL, times, 0) == futimens(fd, times)
const rc = std.os.linux.utimensat(host_fd, null, &times, 0);
const e = std.os.linux.errno(rc);
if (e != .SUCCESS) std.c._errno().* = @intFromEnum(e);
break :blk e != .SUCCESS;
},
else => std.c.futimens(host_fd, &times) != 0,
};
if (failed) {
try pushErrno(vm, cErrnoToWasi());
return;
}
Expand Down Expand Up @@ -2301,7 +2311,7 @@ pub fn fd_renumber(ctx: *anyopaque, _: usize) anyerror!void {
// Dup host fd and assign to fd_to slot
const new_host = blk: {
if (builtin.os.tag == .windows) unreachable;
const rc = std.c.dup(from_host);
const rc = platform.pfdDup(from_host);
if (rc < 0) {
try pushErrno(vm, cErrnoToWasi());
return;
Expand Down Expand Up @@ -2486,7 +2496,7 @@ pub fn path_readlink(ctx: *anyopaque, _: usize) anyerror!void {
try pushErrno(vm, .NAMETOOLONG);
return;
};
const rc = std.c.readlinkat(host_fd, path_z.ptr, buf.ptr, buf.len);
const rc = platform.pfdReadlinkAt(host_fd, path_z.ptr, buf);
if (rc < 0) {
try pushErrno(vm, cErrnoToWasi());
return;
Expand Down
Loading