Commit 46f7e3ea9f
Changed files (11)
lib
std
lib/std/fs/Dir.zig
@@ -849,14 +849,14 @@ pub fn close(self: *Dir) void {
/// Deprecated in favor of `Io.Dir.openFile`.
pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return .adaptFromNewApi(try Io.Dir.openFile(self.adaptToNewApi(), io, sub_path, flags));
}
/// Deprecated in favor of `Io.Dir.createFile`.
pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
const new_file = try Io.Dir.createFile(self.adaptToNewApi(), io, sub_path, flags);
return .adaptFromNewApi(new_file);
}
@@ -867,7 +867,7 @@ pub const MakeError = Io.Dir.MakeError;
/// Deprecated in favor of `Io.Dir.makeDir`.
pub fn makeDir(self: Dir, sub_path: []const u8) MakeError!void {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return Io.Dir.makeDir(.{ .handle = self.fd }, io, sub_path);
}
@@ -894,14 +894,14 @@ pub const MakePathError = Io.Dir.MakePathError;
/// Deprecated in favor of `Io.Dir.makePathStatus`.
pub fn makePathStatus(self: Dir, sub_path: []const u8) MakePathError!MakePathStatus {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return Io.Dir.makePathStatus(.{ .handle = self.fd }, io, sub_path);
}
/// Deprecated in favor of `Io.Dir.makeOpenPath`.
pub fn makeOpenPath(dir: Dir, sub_path: []const u8, options: OpenOptions) Io.Dir.MakeOpenPathError!Dir {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return .adaptFromNewApi(try Io.Dir.makeOpenPath(dir.adaptToNewApi(), io, sub_path, options));
}
@@ -1070,7 +1070,7 @@ pub const OpenOptions = Io.Dir.OpenOptions;
/// Deprecated in favor of `Io.Dir.openDir`.
pub fn openDir(self: Dir, sub_path: []const u8, args: OpenOptions) OpenError!Dir {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args));
}
@@ -1384,7 +1384,7 @@ pub fn readLinkW(self: Dir, sub_path_w: []const u16, buffer: []u8) ![]u8 {
/// Deprecated in favor of `Io.Dir.readFile`.
pub fn readFile(self: Dir, file_path: []const u8, buffer: []u8) ![]u8 {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return Io.Dir.readFile(.{ .handle = self.fd }, io, file_path, buffer);
}
@@ -1437,7 +1437,7 @@ pub fn readFileAllocOptions(
comptime sentinel: ?u8,
) ReadFileAllocError!(if (sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
var file = try dir.openFile(sub_path, .{});
defer file.close();
@@ -1892,7 +1892,7 @@ pub const AccessError = Io.Dir.AccessError;
/// Deprecated in favor of `Io.Dir.access`.
pub fn access(self: Dir, sub_path: []const u8, options: Io.Dir.AccessOptions) AccessError!void {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return Io.Dir.access(self.adaptToNewApi(), io, sub_path, options);
}
@@ -1928,7 +1928,7 @@ pub fn copyFile(
options: CopyFileOptions,
) CopyFileError!void {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
const file = try source_dir.openFile(source_path, .{});
var file_reader: File.Reader = .init(.{ .handle = file.handle }, io, &.{});
@@ -1996,7 +1996,7 @@ pub const StatFileError = File.OpenError || File.StatError || posix.FStatAtError
/// Deprecated in favor of `Io.Dir.statPath`.
pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return Io.Dir.statPath(.{ .handle = self.fd }, io, sub_path, .{});
}
lib/std/fs/File.zig
@@ -313,7 +313,7 @@ pub const StatError = posix.FStatError;
/// Returns `Stat` containing basic information about the `File`.
pub fn stat(self: File) StatError!Stat {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return Io.File.stat(.{ .handle = self.handle }, io);
}
lib/std/Io/Threaded.zig
@@ -168,80 +168,28 @@ pub fn io(t: *Threaded) Io {
.conditionWaitUncancelable = conditionWaitUncancelable,
.conditionWake = conditionWake,
- .dirMake = switch (native_os) {
- .windows => dirMakeWindows,
- .wasi => dirMakeWasi,
- else => dirMakePosix,
- },
- .dirMakePath = switch (native_os) {
- .windows => dirMakePathWindows,
- else => dirMakePathPosix,
- },
- .dirMakeOpenPath = switch (native_os) {
- .windows => dirMakeOpenPathWindows,
- .wasi => dirMakeOpenPathWasi,
- else => dirMakeOpenPathPosix,
- },
+ .dirMake = dirMake,
+ .dirMakePath = dirMakePath,
+ .dirMakeOpenPath = dirMakeOpenPath,
.dirStat = dirStat,
- .dirStatPath = switch (native_os) {
- .linux => dirStatPathLinux,
- .windows => dirStatPathWindows,
- .wasi => dirStatPathWasi,
- else => dirStatPathPosix,
- },
- .fileStat = switch (native_os) {
- .linux => fileStatLinux,
- .windows => fileStatWindows,
- .wasi => fileStatWasi,
- else => fileStatPosix,
- },
- .dirAccess = switch (native_os) {
- .windows => dirAccessWindows,
- .wasi => dirAccessWasi,
- else => dirAccessPosix,
- },
- .dirCreateFile = switch (native_os) {
- .windows => dirCreateFileWindows,
- .wasi => dirCreateFileWasi,
- else => dirCreateFilePosix,
- },
- .dirOpenFile = switch (native_os) {
- .windows => dirOpenFileWindows,
- .wasi => dirOpenFileWasi,
- else => dirOpenFilePosix,
- },
- .dirOpenDir = switch (native_os) {
- .wasi => dirOpenDirWasi,
- .haiku => dirOpenDirHaiku,
- else => dirOpenDirPosix,
- },
+ .dirStatPath = dirStatPath,
+ .fileStat = fileStat,
+ .dirAccess = dirAccess,
+ .dirCreateFile = dirCreateFile,
+ .dirOpenFile = dirOpenFile,
+ .dirOpenDir = dirOpenDir,
.dirClose = dirClose,
.fileClose = fileClose,
.fileWriteStreaming = fileWriteStreaming,
.fileWritePositional = fileWritePositional,
- .fileReadStreaming = switch (native_os) {
- .windows => fileReadStreamingWindows,
- else => fileReadStreamingPosix,
- },
- .fileReadPositional = switch (native_os) {
- .windows => fileReadPositionalWindows,
- else => fileReadPositionalPosix,
- },
+ .fileReadStreaming = fileReadStreaming,
+ .fileReadPositional = fileReadPositional,
.fileSeekBy = fileSeekBy,
.fileSeekTo = fileSeekTo,
.openSelfExe = openSelfExe,
- .now = switch (native_os) {
- .windows => nowWindows,
- .wasi => nowWasi,
- else => nowPosix,
- },
- .sleep = switch (native_os) {
- .windows => sleepWindows,
- .wasi => sleepWasi,
- .linux => sleepLinux,
- else => sleepPosix,
- },
+ .now = now,
+ .sleep = sleep,
.netListenIp = switch (native_os) {
.windows => netListenIpWindows,
@@ -291,6 +239,73 @@ pub fn io(t: *Threaded) Io {
};
}
+/// Same as `io` but disables all networking functionality, which has
+/// an additional dependency on Windows (ws2_32).
+pub fn ioBasic(t: *Threaded) Io {
+ return .{
+ .userdata = t,
+ .vtable = &.{
+ .async = async,
+ .concurrent = concurrent,
+ .await = await,
+ .cancel = cancel,
+ .cancelRequested = cancelRequested,
+ .select = select,
+
+ .groupAsync = groupAsync,
+ .groupWait = groupWait,
+ .groupWaitUncancelable = groupWaitUncancelable,
+ .groupCancel = groupCancel,
+
+ .mutexLock = mutexLock,
+ .mutexLockUncancelable = mutexLockUncancelable,
+ .mutexUnlock = mutexUnlock,
+
+ .conditionWait = conditionWait,
+ .conditionWaitUncancelable = conditionWaitUncancelable,
+ .conditionWake = conditionWake,
+
+ .dirMake = dirMake,
+ .dirMakePath = dirMakePath,
+ .dirMakeOpenPath = dirMakeOpenPath,
+ .dirStat = dirStat,
+ .dirStatPath = dirStatPath,
+ .fileStat = fileStat,
+ .dirAccess = dirAccess,
+ .dirCreateFile = dirCreateFile,
+ .dirOpenFile = dirOpenFile,
+ .dirOpenDir = dirOpenDir,
+ .dirClose = dirClose,
+ .fileClose = fileClose,
+ .fileWriteStreaming = fileWriteStreaming,
+ .fileWritePositional = fileWritePositional,
+ .fileReadStreaming = fileReadStreaming,
+ .fileReadPositional = fileReadPositional,
+ .fileSeekBy = fileSeekBy,
+ .fileSeekTo = fileSeekTo,
+ .openSelfExe = openSelfExe,
+
+ .now = now,
+ .sleep = sleep,
+
+ .netListenIp = netListenIpUnavailable,
+ .netListenUnix = netListenUnixUnavailable,
+ .netAccept = netAcceptUnavailable,
+ .netBindIp = netBindIpUnavailable,
+ .netConnectIp = netConnectIpUnavailable,
+ .netConnectUnix = netConnectUnixUnavailable,
+ .netClose = netCloseUnavailable,
+ .netRead = netReadUnavailable,
+ .netWrite = netWriteUnavailable,
+ .netSend = netSendUnavailable,
+ .netReceive = netReceiveUnavailable,
+ .netInterfaceNameResolve = netInterfaceNameResolveUnavailable,
+ .netInterfaceName = netInterfaceNameUnavailable,
+ .netLookup = netLookupUnavailable,
+ },
+ };
+}
+
pub const socket_flags_unsupported = native_os.isDarwin() or native_os == .haiku; // 💩💩
const have_accept4 = !socket_flags_unsupported;
const have_flock_open_flags = @hasField(posix.O, "EXLOCK");
@@ -804,7 +819,7 @@ fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mut
fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void {
if (builtin.single_threaded) unreachable; // Deadlock.
const t: *Threaded = @ptrCast(@alignCast(userdata));
- const t_io = t.io();
+ const t_io = ioBasic(t);
comptime assert(@TypeOf(cond.state) == u64);
const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state);
const cond_state = &ints[0];
@@ -835,6 +850,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex:
fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void {
if (builtin.single_threaded) unreachable; // Deadlock.
const t: *Threaded = @ptrCast(@alignCast(userdata));
+ const t_io = ioBasic(t);
comptime assert(@TypeOf(cond.state) == u64);
const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state);
const cond_state = &ints[0];
@@ -858,8 +874,8 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I
assert(state & waiter_mask != waiter_mask);
state += one_waiter;
- mutex.unlock(t.io());
- defer mutex.lockUncancelable(t.io());
+ mutex.unlock(t_io);
+ defer mutex.lockUncancelable(t_io);
while (true) {
try futexWait(t, cond_epoch, epoch);
@@ -939,6 +955,12 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.
}
}
+const dirMake = switch (native_os) {
+ .windows => dirMakeWindows,
+ .wasi => dirMakeWasi,
+ else => dirMakePosix,
+};
+
fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
@@ -1027,6 +1049,11 @@ fn dirMakeWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode
windows.CloseHandle(sub_dir_handle);
}
+const dirMakePath = switch (native_os) {
+ .windows => dirMakePathWindows,
+ else => dirMakePathPosix,
+};
+
fn dirMakePathPosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
@@ -1045,6 +1072,12 @@ fn dirMakePathWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8,
@panic("TODO implement dirMakePathWindows");
}
+const dirMakeOpenPath = switch (native_os) {
+ .windows => dirMakeOpenPathWindows,
+ .wasi => dirMakeOpenPathWasi,
+ else => dirMakeOpenPathPosix,
+};
+
fn dirMakeOpenPathPosix(
userdata: ?*anyopaque,
dir: Io.Dir,
@@ -1052,11 +1085,11 @@ fn dirMakeOpenPathPosix(
options: Io.Dir.OpenOptions,
) Io.Dir.MakeOpenPathError!Io.Dir {
const t: *Threaded = @ptrCast(@alignCast(userdata));
- const t_io = t.io();
- return dir.openDir(t_io, sub_path, options) catch |err| switch (err) {
+ const t_io = ioBasic(t);
+ return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) {
error.FileNotFound => {
try dir.makePath(t_io, sub_path);
- return dir.openDir(t_io, sub_path, options);
+ return dirOpenDirPosix(t, dir, sub_path, options);
},
else => |e| return e,
};
@@ -1135,7 +1168,7 @@ fn dirMakeOpenPathWindows(
// could cause an infinite loop
check_dir: {
// workaround for windows, see https://github.com/ziglang/zig/issues/16738
- const fstat = dir.statPath(t.io(), component.path, .{
+ const fstat = dirStatPathWindows(t, dir, component.path, .{
.follow_symlinks = options.follow_symlinks,
}) catch |stat_err| switch (stat_err) {
error.IsDir => break :check_dir,
@@ -1187,6 +1220,13 @@ fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat {
@panic("TODO implement dirStat");
}
+const dirStatPath = switch (native_os) {
+ .linux => dirStatPathLinux,
+ .windows => dirStatPathWindows,
+ .wasi => dirStatPathWasi,
+ else => dirStatPathPosix,
+};
+
fn dirStatPathLinux(
userdata: ?*anyopaque,
dir: Io.Dir,
@@ -1275,12 +1315,11 @@ fn dirStatPathWindows(
options: Io.Dir.StatPathOptions,
) Io.Dir.StatPathError!Io.File.Stat {
const t: *Threaded = @ptrCast(@alignCast(userdata));
- const t_io = t.io();
- var file = try dir.openFile(t_io, sub_path, .{
+ const file = try dirOpenFileWindows(t, dir, sub_path, .{
.follow_symlinks = options.follow_symlinks,
});
- defer file.close(t_io);
- return file.stat(t_io);
+ defer windows.CloseHandle(file.handle);
+ return fileStatWindows(t, file);
}
fn dirStatPathWasi(
@@ -1318,6 +1357,13 @@ fn dirStatPathWasi(
}
}
+const fileStat = switch (native_os) {
+ .linux => fileStatLinux,
+ .windows => fileStatWindows,
+ .wasi => fileStatWasi,
+ else => fileStatPosix,
+};
+
fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat {
const t: *Threaded = @ptrCast(@alignCast(userdata));
@@ -1440,6 +1486,12 @@ fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.
}
}
+const dirAccess = switch (native_os) {
+ .windows => dirAccessWindows,
+ .wasi => dirAccessWasi,
+ else => dirAccessPosix,
+};
+
fn dirAccessPosix(
userdata: ?*anyopaque,
dir: Io.Dir,
@@ -1589,6 +1641,12 @@ fn dirAccessWindows(
}
}
+const dirCreateFile = switch (native_os) {
+ .windows => dirCreateFileWindows,
+ .wasi => dirCreateFileWasi,
+ else => dirCreateFilePosix,
+};
+
fn dirCreateFilePosix(
userdata: ?*anyopaque,
dir: Io.Dir,
@@ -1827,6 +1885,12 @@ fn dirCreateFileWasi(
}
}
+const dirOpenFile = switch (native_os) {
+ .windows => dirOpenFileWindows,
+ .wasi => dirOpenFileWasi,
+ else => dirOpenFilePosix,
+};
+
fn dirOpenFilePosix(
userdata: ?*anyopaque,
dir: Io.Dir,
@@ -2077,6 +2141,12 @@ fn dirOpenFileWasi(
}
}
+const dirOpenDir = switch (native_os) {
+ .wasi => dirOpenDirWasi,
+ .haiku => dirOpenDirHaiku,
+ else => dirOpenDirPosix,
+};
+
fn dirOpenDirPosix(
userdata: ?*anyopaque,
dir: Io.Dir,
@@ -2320,6 +2390,11 @@ fn fileClose(userdata: ?*anyopaque, file: Io.File) void {
posix.close(file.handle);
}
+const fileReadStreaming = switch (native_os) {
+ .windows => fileReadStreamingWindows,
+ else => fileReadStreamingPosix,
+};
+
fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize {
const t: *Threaded = @ptrCast(@alignCast(userdata));
@@ -2482,6 +2557,11 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o
}
}
+const fileReadPositional = switch (native_os) {
+ .windows => fileReadPositionalWindows,
+ else => fileReadPositionalPosix,
+};
+
fn fileReadPositionalWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize {
const t: *Threaded = @ptrCast(@alignCast(userdata));
try t.checkCancel();
@@ -2652,6 +2732,12 @@ fn nowPosix(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp
}
}
+const now = switch (native_os) {
+ .windows => nowWindows,
+ .wasi => nowWasi,
+ else => nowPosix,
+};
+
fn nowWindows(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp {
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
@@ -2680,6 +2766,13 @@ fn nowWasi(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp {
return .fromNanoseconds(ns);
}
+const sleep = switch (native_os) {
+ .windows => sleepWindows,
+ .wasi => sleepWasi,
+ .linux => sleepLinux,
+ else => sleepPosix,
+};
+
fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
const clock_id: posix.clockid_t = clockToPosix(switch (timeout) {
@@ -2710,9 +2803,10 @@ fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
+ const t_io = ioBasic(t);
try t.checkCancel();
const ms = ms: {
- const d = (try timeout.toDurationFromNow(t.io())) orelse
+ const d = (try timeout.toDurationFromNow(t_io)) orelse
break :ms std.math.maxInt(windows.DWORD);
break :ms std.math.lossyCast(windows.DWORD, d.raw.toMilliseconds());
};
@@ -2721,11 +2815,12 @@ fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
+ const t_io = ioBasic(t);
try t.checkCancel();
const w = std.os.wasi;
- const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t.io())) |d| .{
+ const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t_io)) |d| .{
.id = clockToWasi(d.clock),
.timeout = std.math.lossyCast(u64, d.raw.nanoseconds),
.precision = 0,
@@ -2750,11 +2845,12 @@ fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
+ const t_io = ioBasic(t);
const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type;
const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type;
var timespec: posix.timespec = t: {
- const d = (try timeout.toDurationFromNow(t.io())) orelse break :t .{
+ const d = (try timeout.toDurationFromNow(t_io)) orelse break :t .{
.sec = std.math.maxInt(sec_type),
.nsec = std.math.maxInt(nsec_type),
};
@@ -2919,6 +3015,17 @@ fn netListenIpWindows(
};
}
+fn netListenIpUnavailable(
+ userdata: ?*anyopaque,
+ address: IpAddress,
+ options: IpAddress.ListenOptions,
+) IpAddress.ListenError!net.Server {
+ _ = userdata;
+ _ = address;
+ _ = options;
+ return error.NetworkDown;
+}
+
fn netListenUnixPosix(
userdata: ?*anyopaque,
address: *const net.UnixAddress,
@@ -2965,6 +3072,17 @@ fn netListenUnixWindows(
@panic("TODO implement netListenUnixWindows");
}
+fn netListenUnixUnavailable(
+ userdata: ?*anyopaque,
+ address: *const net.UnixAddress,
+ options: net.UnixAddress.ListenOptions,
+) net.UnixAddress.ListenError!net.Socket.Handle {
+ _ = userdata;
+ _ = address;
+ _ = options;
+ return error.AddressFamilyUnsupported;
+}
+
fn posixBindUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void {
while (true) {
try t.checkCancel();
@@ -3235,6 +3353,17 @@ fn netConnectIpWindows(
} };
}
+fn netConnectIpUnavailable(
+ userdata: ?*anyopaque,
+ address: *const IpAddress,
+ options: IpAddress.ConnectOptions,
+) IpAddress.ConnectError!net.Stream {
+ _ = userdata;
+ _ = address;
+ _ = options;
+ return error.NetworkDown;
+}
+
fn netConnectUnixPosix(
userdata: ?*anyopaque,
address: *const net.UnixAddress,
@@ -3263,6 +3392,15 @@ fn netConnectUnixWindows(
@panic("TODO implement netConnectUnixWindows");
}
+fn netConnectUnixUnavailable(
+ userdata: ?*anyopaque,
+ address: *const net.UnixAddress,
+) net.UnixAddress.ConnectError!net.Socket.Handle {
+ _ = userdata;
+ _ = address;
+ return error.AddressFamilyUnsupported;
+}
+
fn netBindIpPosix(
userdata: ?*anyopaque,
address: *const IpAddress,
@@ -3330,6 +3468,17 @@ fn netBindIpWindows(
};
}
+fn netBindIpUnavailable(
+ userdata: ?*anyopaque,
+ address: *const IpAddress,
+ options: IpAddress.BindOptions,
+) IpAddress.BindError!net.Socket {
+ _ = userdata;
+ _ = address;
+ _ = options;
+ return error.NetworkDown;
+}
+
fn openSocketPosix(
t: *Threaded,
family: posix.sa_family_t,
@@ -3498,7 +3647,14 @@ fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net
}
}
+fn netAcceptUnavailable(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net.Server.AcceptError!net.Stream {
+ _ = userdata;
+ _ = listen_handle;
+ return error.NetworkDown;
+}
+
fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
+ if (!have_networking) return error.NetworkDown;
const t: *Threaded = @ptrCast(@alignCast(userdata));
var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined;
@@ -3560,7 +3716,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
}
fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
- if (!have_networking) return .{ error.NetworkDown, 0 };
+ if (!have_networking) return error.NetworkDown;
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
_ = handle;
@@ -3568,6 +3724,13 @@ fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8
@panic("TODO implement netReadWindows");
}
+fn netReadUnavailable(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
+ _ = userdata;
+ _ = fd;
+ _ = data;
+ return error.NetworkDown;
+}
+
fn netSendPosix(
userdata: ?*anyopaque,
handle: net.Socket.Handle,
@@ -3612,6 +3775,19 @@ fn netSendWindows(
@panic("TODO netSendWindows");
}
+fn netSendUnavailable(
+ userdata: ?*anyopaque,
+ handle: net.Socket.Handle,
+ messages: []net.OutgoingMessage,
+ flags: net.SendFlags,
+) struct { ?net.Socket.SendError, usize } {
+ _ = userdata;
+ _ = handle;
+ _ = messages;
+ _ = flags;
+ return .{ error.NetworkDown, 0 };
+}
+
fn netSendOne(
t: *Threaded,
handle: net.Socket.Handle,
@@ -3777,6 +3953,7 @@ fn netReceivePosix(
) struct { ?net.Socket.ReceiveTimeoutError, usize } {
if (!have_networking) return .{ error.NetworkDown, 0 };
const t: *Threaded = @ptrCast(@alignCast(userdata));
+ const t_io = io(t);
// recvmmsg is useless, here's why:
// * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371)
@@ -3803,7 +3980,7 @@ fn netReceivePosix(
var message_i: usize = 0;
var data_i: usize = 0;
- const deadline = timeout.toDeadline(t.io()) catch |err| return .{ err, message_i };
+ const deadline = timeout.toDeadline(t_io) catch |err| return .{ err, message_i };
recv: while (true) {
t.checkCancel() catch |err| return .{ err, message_i };
@@ -3849,7 +4026,7 @@ fn netReceivePosix(
const max_poll_ms = std.math.maxInt(u31);
const timeout_ms: u31 = if (deadline) |d| t: {
- const duration = d.durationFromNow(t.io()) catch |err| return .{ err, message_i };
+ const duration = d.durationFromNow(t_io) catch |err| return .{ err, message_i };
if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i };
break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds()));
} else max_poll_ms;
@@ -3915,6 +4092,23 @@ fn netReceiveWindows(
@panic("TODO implement netReceiveWindows");
}
+fn netReceiveUnavailable(
+ userdata: ?*anyopaque,
+ handle: net.Socket.Handle,
+ message_buffer: []net.IncomingMessage,
+ data_buffer: []u8,
+ flags: net.ReceiveFlags,
+ timeout: Io.Timeout,
+) struct { ?net.Socket.ReceiveTimeoutError, usize } {
+ _ = userdata;
+ _ = handle;
+ _ = message_buffer;
+ _ = data_buffer;
+ _ = flags;
+ _ = timeout;
+ return .{ error.NetworkDown, 0 };
+}
+
fn netWritePosix(
userdata: ?*anyopaque,
fd: net.Socket.Handle,
@@ -4013,6 +4207,21 @@ fn netWriteWindows(
@panic("TODO implement netWriteWindows");
}
+fn netWriteUnavailable(
+ userdata: ?*anyopaque,
+ handle: net.Socket.Handle,
+ header: []const u8,
+ data: []const []const u8,
+ splat: usize,
+) net.Stream.Writer.Error!usize {
+ _ = userdata;
+ _ = handle;
+ _ = header;
+ _ = data;
+ _ = splat;
+ return error.NetworkDown;
+}
+
fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void {
// OS checks ptr addr before length so zero length vectors must be omitted.
if (bytes.len == 0) return;
@@ -4030,6 +4239,12 @@ fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void {
}
}
+fn netCloseUnavailable(userdata: ?*anyopaque, handle: net.Socket.Handle) void {
+ _ = userdata;
+ _ = handle;
+ unreachable; // How you gonna close something that was impossible to open?
+}
+
fn netInterfaceNameResolve(
userdata: ?*anyopaque,
name: *const net.Interface.Name,
@@ -4089,6 +4304,15 @@ fn netInterfaceNameResolve(
@panic("unimplemented");
}
+fn netInterfaceNameResolveUnavailable(
+ userdata: ?*anyopaque,
+ name: *const net.Interface.Name,
+) net.Interface.Name.ResolveError!net.Interface {
+ _ = userdata;
+ _ = name;
+ return error.InterfaceNotFound;
+}
+
fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name {
const t: *Threaded = @ptrCast(@alignCast(userdata));
try t.checkCancel();
@@ -4109,6 +4333,12 @@ fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interfa
@panic("unimplemented");
}
+fn netInterfaceNameUnavailable(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name {
+ _ = userdata;
+ _ = interface;
+ return error.Unexpected;
+}
+
fn netLookup(
userdata: ?*anyopaque,
host_name: HostName,
@@ -4116,17 +4346,31 @@ fn netLookup(
options: HostName.LookupOptions,
) void {
const t: *Threaded = @ptrCast(@alignCast(userdata));
- const t_io = t.io();
+ const t_io = io(t);
resolved.putOneUncancelable(t_io, .{ .end = netLookupFallible(t, host_name, resolved, options) });
}
+fn netLookupUnavailable(
+ userdata: ?*anyopaque,
+ host_name: HostName,
+ resolved: *Io.Queue(HostName.LookupResult),
+ options: HostName.LookupOptions,
+) void {
+ _ = host_name;
+ _ = options;
+ const t: *Threaded = @ptrCast(@alignCast(userdata));
+ const t_io = ioBasic(t);
+ resolved.putOneUncancelable(t_io, .{ .end = error.NetworkDown });
+}
+
fn netLookupFallible(
t: *Threaded,
host_name: HostName,
resolved: *Io.Queue(HostName.LookupResult),
options: HostName.LookupOptions,
) !void {
- const t_io = t.io();
+ if (!have_networking) return error.NetworkDown;
+ const t_io = io(t);
const name = host_name.bytes;
assert(name.len <= HostName.max_len);
@@ -4637,7 +4881,7 @@ fn lookupDnsSearch(
resolved: *Io.Queue(HostName.LookupResult),
options: HostName.LookupOptions,
) HostName.LookupError!void {
- const t_io = t.io();
+ const t_io = io(t);
const rc = HostName.ResolvConf.init(t_io) catch return error.ResolvConfParseFailed;
// Count dots, suppress search when >=ndots or name ends in
@@ -4681,7 +4925,7 @@ fn lookupDns(
resolved: *Io.Queue(HostName.LookupResult),
options: HostName.LookupOptions,
) HostName.LookupError!void {
- const t_io = t.io();
+ const t_io = io(t);
const family_records: [2]struct { af: IpAddress.Family, rr: HostName.DnsRecord } = .{
.{ .af = .ip6, .rr = .A },
.{ .af = .ip4, .rr = .AAAA },
@@ -4868,7 +5112,7 @@ fn lookupHosts(
resolved: *Io.Queue(HostName.LookupResult),
options: HostName.LookupOptions,
) !void {
- const t_io = t.io();
+ const t_io = io(t);
const file = Io.File.openAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) {
error.FileNotFound,
error.NotDir,
@@ -4906,7 +5150,7 @@ fn lookupHostsReader(
options: HostName.LookupOptions,
reader: *Io.Reader,
) error{ ReadFailed, Canceled, UnknownHostName }!void {
- const t_io = t.io();
+ const t_io = io(t);
var addresses_len: usize = 0;
var canonical_name: ?HostName = null;
while (true) {
@@ -5374,7 +5618,7 @@ const Wsa = struct {
};
fn initializeWsa(t: *Threaded) error{NetworkDown}!void {
- const t_io = t.io();
+ const t_io = io(t);
const wsa = &t.wsa;
wsa.mutex.lockUncancelable(t_io);
defer wsa.mutex.unlock(t_io);
lib/std/process/Child.zig
@@ -1089,7 +1089,7 @@ fn windowsCreateProcessPathExt(
// opening function knowing which implementation we are in. Here, we imitate
// that scenario.
var threaded: std.Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
var dir = dir: {
// needs to be null-terminated
lib/std/debug.zig
@@ -649,7 +649,7 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf:
/// See `captureCurrentStackTrace` to capture the trace addresses into a buffer instead of printing.
pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Writer, tty_config: tty.Config) Writer.Error!void {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
if (!std.options.allow_stack_tracing) {
tty_config.setColor(writer, .dim) catch {};
@@ -780,7 +780,7 @@ pub fn writeStackTrace(st: *const StackTrace, writer: *Writer, tty_config: tty.C
// We use an independent Io implementation here in case there was a problem
// with the application's Io implementation itself.
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
// Fetch `st.index` straight away. Aside from avoiding redundant loads, this prevents issues if
// `st` is `@errorReturnTrace()` and errors are encountered while writing the stack trace.
@@ -1602,7 +1602,7 @@ test "manage resources correctly" {
};
const gpa = std.testing.allocator;
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
var discarding: Io.Writer.Discarding = .init(&.{});
var di: SelfInfo = .init;
defer di.deinit(gpa);
lib/std/fs.zig
@@ -340,7 +340,7 @@ pub const OpenSelfExeError = Io.File.OpenSelfExeError;
pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
if (native_os == .linux or native_os == .serenity or native_os == .windows) {
var threaded: Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
return .adaptFromNewApi(try Io.File.openSelfExe(io, flags));
}
// Use of max_path_bytes here is valid as the resulting path is immediately
lib/std/Thread.zig
@@ -320,7 +320,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()});
var threaded: std.Io.Threaded = .init_single_threaded;
- const io = threaded.io();
+ const io = threaded.ioBasic();
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
test/standalone/child_process/child.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const Io = std.Io;
// 42 is expected by parent; other values result in test failure
var exit_code: u8 = 42;
@@ -6,12 +7,17 @@ var exit_code: u8 = 42;
pub fn main() !void {
var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const arena = arena_state.allocator();
- try run(arena);
+
+ var threaded: std.Io.Threaded = .init(arena);
+ defer threaded.deinit();
+ const io = threaded.io();
+
+ try run(arena, io);
arena_state.deinit();
std.process.exit(exit_code);
}
-fn run(allocator: std.mem.Allocator) !void {
+fn run(allocator: std.mem.Allocator, io: Io) !void {
var args = try std.process.argsWithAllocator(allocator);
defer args.deinit();
_ = args.next() orelse unreachable; // skip binary name
@@ -33,7 +39,8 @@ fn run(allocator: std.mem.Allocator) !void {
const hello_stdin = "hello from stdin";
var buf: [hello_stdin.len]u8 = undefined;
const stdin: std.fs.File = .stdin();
- const n = try stdin.readAll(&buf);
+ var reader = stdin.reader(io, &.{});
+ const n = try reader.interface.readSliceShort(&buf);
if (!std.mem.eql(u8, buf[0..n], hello_stdin)) {
testError("stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin });
}
test/standalone/simple/cat/main.zig
@@ -9,6 +9,10 @@ pub fn main() !void {
defer arena_instance.deinit();
const arena = arena_instance.allocator();
+ var threaded: std.Io.Threaded = .init(arena);
+ defer threaded.deinit();
+ const io = threaded.io();
+
const args = try std.process.argsAlloc(arena);
const exe = args[0];
@@ -16,7 +20,7 @@ pub fn main() !void {
var stdout_buffer: [4096]u8 = undefined;
var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
const stdout = &stdout_writer.interface;
- var stdin_reader = fs.File.stdin().readerStreaming(&.{});
+ var stdin_reader = fs.File.stdin().readerStreaming(io, &.{});
const cwd = fs.cwd();
@@ -32,7 +36,7 @@ pub fn main() !void {
defer file.close();
catted_anything = true;
- var file_reader = file.reader(&.{});
+ var file_reader = file.reader(io, &.{});
_ = try stdout.sendFileAll(&file_reader, .unlimited);
try stdout.flush();
}
tools/fetch_them_macos_headers.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const Io = std.Io;
const fs = std.fs;
const mem = std.mem;
const process = std.process;
@@ -85,7 +86,7 @@ pub fn main() anyerror!void {
} else try argv.append(arg);
}
- var threaded: std.Io.Threaded = .init(gpa);
+ var threaded: Io.Threaded = .init(gpa);
defer threaded.deinit();
const io = threaded.io();
@@ -118,12 +119,13 @@ pub fn main() anyerror!void {
.arch = arch,
.os_ver = os_ver,
};
- try fetchTarget(allocator, argv.items, sysroot_path, target, version, tmp);
+ try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp);
}
}
fn fetchTarget(
arena: Allocator,
+ io: Io,
args: []const []const u8,
sysroot: []const u8,
target: Target,
@@ -194,7 +196,7 @@ fn fetchTarget(
var dirs = std.StringHashMap(fs.Dir).init(arena);
try dirs.putNoClobber(".", dest_dir);
- var headers_list_file_reader = headers_list_file.reader(&.{});
+ var headers_list_file_reader = headers_list_file.reader(io, &.{});
const headers_list_str = try headers_list_file_reader.interface.allocRemaining(arena, .unlimited);
const prefix = "/usr/include";
@@ -267,8 +269,8 @@ const Version = struct {
pub fn format(
v: Version,
- writer: *std.Io.Writer,
- ) std.Io.Writer.Error!void {
+ writer: *Io.Writer,
+ ) Io.Writer.Error!void {
try writer.print("{d}.{d}.{d}", .{ v.major, v.minor, v.patch });
}
};
tools/gen_macos_headers_c.zig
@@ -73,7 +73,7 @@ fn findHeaders(
switch (entry.kind) {
.directory => {
const path = try std.fs.path.join(arena, &.{ prefix, entry.name });
- var subdir = try dir.openDir(entry.name, .{ .no_follow = true });
+ var subdir = try dir.openDir(entry.name, .{ .follow_symlinks = false });
defer subdir.close();
try findHeaders(arena, subdir, path, paths);
},