authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-23 13:58:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:51-07:00
log46f7e3ea9fff4b3f83cab58c20625d3961be6020
treec8cba4670ad23bc0c9a66d31b31ec5e847b0dc39
parent701d4bc80b8cbb649364e8ecf86ed9cea8af739d

std.Io.Threaded: add ioBasic which disables networking


11 files changed, 375 insertions(+), 118 deletions(-)

lib/std/Io/Threaded.zig+333-89
...@@ -168,80 +168,28 @@ pub fn io(t: *Threaded) Io {...@@ -168,80 +168,28 @@ pub fn io(t: *Threaded) Io {
168 .conditionWaitUncancelable = conditionWaitUncancelable,168 .conditionWaitUncancelable = conditionWaitUncancelable,
169 .conditionWake = conditionWake,169 .conditionWake = conditionWake,
170170
171 .dirMake = switch (native_os) {171 .dirMake = dirMake,
172 .windows => dirMakeWindows,172 .dirMakePath = dirMakePath,
173 .wasi => dirMakeWasi,173 .dirMakeOpenPath = dirMakeOpenPath,
174 else => dirMakePosix,
175 },
176 .dirMakePath = switch (native_os) {
177 .windows => dirMakePathWindows,
178 else => dirMakePathPosix,
179 },
180 .dirMakeOpenPath = switch (native_os) {
181 .windows => dirMakeOpenPathWindows,
182 .wasi => dirMakeOpenPathWasi,
183 else => dirMakeOpenPathPosix,
184 },
185 .dirStat = dirStat,174 .dirStat = dirStat,
186 .dirStatPath = switch (native_os) {175 .dirStatPath = dirStatPath,
187 .linux => dirStatPathLinux,176 .fileStat = fileStat,
188 .windows => dirStatPathWindows,177 .dirAccess = dirAccess,
189 .wasi => dirStatPathWasi,178 .dirCreateFile = dirCreateFile,
190 else => dirStatPathPosix,179 .dirOpenFile = dirOpenFile,
191 },180 .dirOpenDir = dirOpenDir,
192 .fileStat = switch (native_os) {
193 .linux => fileStatLinux,
194 .windows => fileStatWindows,
195 .wasi => fileStatWasi,
196 else => fileStatPosix,
197 },
198 .dirAccess = switch (native_os) {
199 .windows => dirAccessWindows,
200 .wasi => dirAccessWasi,
201 else => dirAccessPosix,
202 },
203 .dirCreateFile = switch (native_os) {
204 .windows => dirCreateFileWindows,
205 .wasi => dirCreateFileWasi,
206 else => dirCreateFilePosix,
207 },
208 .dirOpenFile = switch (native_os) {
209 .windows => dirOpenFileWindows,
210 .wasi => dirOpenFileWasi,
211 else => dirOpenFilePosix,
212 },
213 .dirOpenDir = switch (native_os) {
214 .wasi => dirOpenDirWasi,
215 .haiku => dirOpenDirHaiku,
216 else => dirOpenDirPosix,
217 },
218 .dirClose = dirClose,181 .dirClose = dirClose,
219 .fileClose = fileClose,182 .fileClose = fileClose,
220 .fileWriteStreaming = fileWriteStreaming,183 .fileWriteStreaming = fileWriteStreaming,
221 .fileWritePositional = fileWritePositional,184 .fileWritePositional = fileWritePositional,
222 .fileReadStreaming = switch (native_os) {185 .fileReadStreaming = fileReadStreaming,
223 .windows => fileReadStreamingWindows,186 .fileReadPositional = fileReadPositional,
224 else => fileReadStreamingPosix,
225 },
226 .fileReadPositional = switch (native_os) {
227 .windows => fileReadPositionalWindows,
228 else => fileReadPositionalPosix,
229 },
230 .fileSeekBy = fileSeekBy,187 .fileSeekBy = fileSeekBy,
231 .fileSeekTo = fileSeekTo,188 .fileSeekTo = fileSeekTo,
232 .openSelfExe = openSelfExe,189 .openSelfExe = openSelfExe,
233190
234 .now = switch (native_os) {191 .now = now,
235 .windows => nowWindows,192 .sleep = sleep,
236 .wasi => nowWasi,
237 else => nowPosix,
238 },
239 .sleep = switch (native_os) {
240 .windows => sleepWindows,
241 .wasi => sleepWasi,
242 .linux => sleepLinux,
243 else => sleepPosix,
244 },
245193
246 .netListenIp = switch (native_os) {194 .netListenIp = switch (native_os) {
247 .windows => netListenIpWindows,195 .windows => netListenIpWindows,
...@@ -291,6 +239,73 @@ pub fn io(t: *Threaded) Io {...@@ -291,6 +239,73 @@ pub fn io(t: *Threaded) Io {
291 };239 };
292}240}
293241
242/// Same as `io` but disables all networking functionality, which has
243/// an additional dependency on Windows (ws2_32).
244pub fn ioBasic(t: *Threaded) Io {
245 return .{
246 .userdata = t,
247 .vtable = &.{
248 .async = async,
249 .concurrent = concurrent,
250 .await = await,
251 .cancel = cancel,
252 .cancelRequested = cancelRequested,
253 .select = select,
254
255 .groupAsync = groupAsync,
256 .groupWait = groupWait,
257 .groupWaitUncancelable = groupWaitUncancelable,
258 .groupCancel = groupCancel,
259
260 .mutexLock = mutexLock,
261 .mutexLockUncancelable = mutexLockUncancelable,
262 .mutexUnlock = mutexUnlock,
263
264 .conditionWait = conditionWait,
265 .conditionWaitUncancelable = conditionWaitUncancelable,
266 .conditionWake = conditionWake,
267
268 .dirMake = dirMake,
269 .dirMakePath = dirMakePath,
270 .dirMakeOpenPath = dirMakeOpenPath,
271 .dirStat = dirStat,
272 .dirStatPath = dirStatPath,
273 .fileStat = fileStat,
274 .dirAccess = dirAccess,
275 .dirCreateFile = dirCreateFile,
276 .dirOpenFile = dirOpenFile,
277 .dirOpenDir = dirOpenDir,
278 .dirClose = dirClose,
279 .fileClose = fileClose,
280 .fileWriteStreaming = fileWriteStreaming,
281 .fileWritePositional = fileWritePositional,
282 .fileReadStreaming = fileReadStreaming,
283 .fileReadPositional = fileReadPositional,
284 .fileSeekBy = fileSeekBy,
285 .fileSeekTo = fileSeekTo,
286 .openSelfExe = openSelfExe,
287
288 .now = now,
289 .sleep = sleep,
290
291 .netListenIp = netListenIpUnavailable,
292 .netListenUnix = netListenUnixUnavailable,
293 .netAccept = netAcceptUnavailable,
294 .netBindIp = netBindIpUnavailable,
295 .netConnectIp = netConnectIpUnavailable,
296 .netConnectUnix = netConnectUnixUnavailable,
297 .netClose = netCloseUnavailable,
298 .netRead = netReadUnavailable,
299 .netWrite = netWriteUnavailable,
300 .netSend = netSendUnavailable,
301 .netReceive = netReceiveUnavailable,
302 .netInterfaceNameResolve = netInterfaceNameResolveUnavailable,
303 .netInterfaceName = netInterfaceNameUnavailable,
304 .netLookup = netLookupUnavailable,
305 },
306 };
307}
308
294pub const socket_flags_unsupported = native_os.isDarwin() or native_os == .haiku; // 💩💩309pub const socket_flags_unsupported = native_os.isDarwin() or native_os == .haiku; // 💩💩
295const have_accept4 = !socket_flags_unsupported;310const have_accept4 = !socket_flags_unsupported;
296const have_flock_open_flags = @hasField(posix.O, "EXLOCK");311const have_flock_open_flags = @hasField(posix.O, "EXLOCK");
...@@ -804,7 +819,7 @@ fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mut...@@ -804,7 +819,7 @@ fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mut
804fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void {819fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void {
805 if (builtin.single_threaded) unreachable; // Deadlock.820 if (builtin.single_threaded) unreachable; // Deadlock.
806 const t: *Threaded = @ptrCast(@alignCast(userdata));821 const t: *Threaded = @ptrCast(@alignCast(userdata));
807 const t_io = t.io();822 const t_io = ioBasic(t);
808 comptime assert(@TypeOf(cond.state) == u64);823 comptime assert(@TypeOf(cond.state) == u64);
809 const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state);824 const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state);
810 const cond_state = &ints[0];825 const cond_state = &ints[0];
...@@ -835,6 +850,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex:...@@ -835,6 +850,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex:
835fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void {850fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void {
836 if (builtin.single_threaded) unreachable; // Deadlock.851 if (builtin.single_threaded) unreachable; // Deadlock.
837 const t: *Threaded = @ptrCast(@alignCast(userdata));852 const t: *Threaded = @ptrCast(@alignCast(userdata));
853 const t_io = ioBasic(t);
838 comptime assert(@TypeOf(cond.state) == u64);854 comptime assert(@TypeOf(cond.state) == u64);
839 const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state);855 const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state);
840 const cond_state = &ints[0];856 const cond_state = &ints[0];
...@@ -858,8 +874,8 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I...@@ -858,8 +874,8 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I
858 assert(state & waiter_mask != waiter_mask);874 assert(state & waiter_mask != waiter_mask);
859 state += one_waiter;875 state += one_waiter;
860876
861 mutex.unlock(t.io());877 mutex.unlock(t_io);
862 defer mutex.lockUncancelable(t.io());878 defer mutex.lockUncancelable(t_io);
863879
864 while (true) {880 while (true) {
865 try futexWait(t, cond_epoch, epoch);881 try futexWait(t, cond_epoch, epoch);
...@@ -939,6 +955,12 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition....@@ -939,6 +955,12 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.
939 }955 }
940}956}
941957
958const dirMake = switch (native_os) {
959 .windows => dirMakeWindows,
960 .wasi => dirMakeWasi,
961 else => dirMakePosix,
962};
963
942fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {964fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {
943 const t: *Threaded = @ptrCast(@alignCast(userdata));965 const t: *Threaded = @ptrCast(@alignCast(userdata));
944966
...@@ -1027,6 +1049,11 @@ fn dirMakeWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode...@@ -1027,6 +1049,11 @@ fn dirMakeWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode
1027 windows.CloseHandle(sub_dir_handle);1049 windows.CloseHandle(sub_dir_handle);
1028}1050}
10291051
1052const dirMakePath = switch (native_os) {
1053 .windows => dirMakePathWindows,
1054 else => dirMakePathPosix,
1055};
1056
1030fn dirMakePathPosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {1057fn dirMakePathPosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void {
1031 const t: *Threaded = @ptrCast(@alignCast(userdata));1058 const t: *Threaded = @ptrCast(@alignCast(userdata));
1032 _ = t;1059 _ = t;
...@@ -1045,6 +1072,12 @@ fn dirMakePathWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8,...@@ -1045,6 +1072,12 @@ fn dirMakePathWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8,
1045 @panic("TODO implement dirMakePathWindows");1072 @panic("TODO implement dirMakePathWindows");
1046}1073}
10471074
1075const dirMakeOpenPath = switch (native_os) {
1076 .windows => dirMakeOpenPathWindows,
1077 .wasi => dirMakeOpenPathWasi,
1078 else => dirMakeOpenPathPosix,
1079};
1080
1048fn dirMakeOpenPathPosix(1081fn dirMakeOpenPathPosix(
1049 userdata: ?*anyopaque,1082 userdata: ?*anyopaque,
1050 dir: Io.Dir,1083 dir: Io.Dir,
...@@ -1052,11 +1085,11 @@ fn dirMakeOpenPathPosix(...@@ -1052,11 +1085,11 @@ fn dirMakeOpenPathPosix(
1052 options: Io.Dir.OpenOptions,1085 options: Io.Dir.OpenOptions,
1053) Io.Dir.MakeOpenPathError!Io.Dir {1086) Io.Dir.MakeOpenPathError!Io.Dir {
1054 const t: *Threaded = @ptrCast(@alignCast(userdata));1087 const t: *Threaded = @ptrCast(@alignCast(userdata));
1055 const t_io = t.io();1088 const t_io = ioBasic(t);
1056 return dir.openDir(t_io, sub_path, options) catch |err| switch (err) {1089 return dirOpenDirPosix(t, dir, sub_path, options) catch |err| switch (err) {
1057 error.FileNotFound => {1090 error.FileNotFound => {
1058 try dir.makePath(t_io, sub_path);1091 try dir.makePath(t_io, sub_path);
1059 return dir.openDir(t_io, sub_path, options);1092 return dirOpenDirPosix(t, dir, sub_path, options);
1060 },1093 },
1061 else => |e| return e,1094 else => |e| return e,
1062 };1095 };
...@@ -1135,7 +1168,7 @@ fn dirMakeOpenPathWindows(...@@ -1135,7 +1168,7 @@ fn dirMakeOpenPathWindows(
1135 // could cause an infinite loop1168 // could cause an infinite loop
1136 check_dir: {1169 check_dir: {
1137 // workaround for windows, see https://github.com/ziglang/zig/issues/167381170 // workaround for windows, see https://github.com/ziglang/zig/issues/16738
1138 const fstat = dir.statPath(t.io(), component.path, .{1171 const fstat = dirStatPathWindows(t, dir, component.path, .{
1139 .follow_symlinks = options.follow_symlinks,1172 .follow_symlinks = options.follow_symlinks,
1140 }) catch |stat_err| switch (stat_err) {1173 }) catch |stat_err| switch (stat_err) {
1141 error.IsDir => break :check_dir,1174 error.IsDir => break :check_dir,
...@@ -1187,6 +1220,13 @@ fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat {...@@ -1187,6 +1220,13 @@ fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat {
1187 @panic("TODO implement dirStat");1220 @panic("TODO implement dirStat");
1188}1221}
11891222
1223const dirStatPath = switch (native_os) {
1224 .linux => dirStatPathLinux,
1225 .windows => dirStatPathWindows,
1226 .wasi => dirStatPathWasi,
1227 else => dirStatPathPosix,
1228};
1229
1190fn dirStatPathLinux(1230fn dirStatPathLinux(
1191 userdata: ?*anyopaque,1231 userdata: ?*anyopaque,
1192 dir: Io.Dir,1232 dir: Io.Dir,
...@@ -1275,12 +1315,11 @@ fn dirStatPathWindows(...@@ -1275,12 +1315,11 @@ fn dirStatPathWindows(
1275 options: Io.Dir.StatPathOptions,1315 options: Io.Dir.StatPathOptions,
1276) Io.Dir.StatPathError!Io.File.Stat {1316) Io.Dir.StatPathError!Io.File.Stat {
1277 const t: *Threaded = @ptrCast(@alignCast(userdata));1317 const t: *Threaded = @ptrCast(@alignCast(userdata));
1278 const t_io = t.io();1318 const file = try dirOpenFileWindows(t, dir, sub_path, .{
1279 var file = try dir.openFile(t_io, sub_path, .{
1280 .follow_symlinks = options.follow_symlinks,1319 .follow_symlinks = options.follow_symlinks,
1281 });1320 });
1282 defer file.close(t_io);1321 defer windows.CloseHandle(file.handle);
1283 return file.stat(t_io);1322 return fileStatWindows(t, file);
1284}1323}
12851324
1286fn dirStatPathWasi(1325fn dirStatPathWasi(
...@@ -1318,6 +1357,13 @@ fn dirStatPathWasi(...@@ -1318,6 +1357,13 @@ fn dirStatPathWasi(
1318 }1357 }
1319}1358}
13201359
1360const fileStat = switch (native_os) {
1361 .linux => fileStatLinux,
1362 .windows => fileStatWindows,
1363 .wasi => fileStatWasi,
1364 else => fileStatPosix,
1365};
1366
1321fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat {1367fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat {
1322 const t: *Threaded = @ptrCast(@alignCast(userdata));1368 const t: *Threaded = @ptrCast(@alignCast(userdata));
13231369
...@@ -1440,6 +1486,12 @@ fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File....@@ -1440,6 +1486,12 @@ fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.
1440 }1486 }
1441}1487}
14421488
1489const dirAccess = switch (native_os) {
1490 .windows => dirAccessWindows,
1491 .wasi => dirAccessWasi,
1492 else => dirAccessPosix,
1493};
1494
1443fn dirAccessPosix(1495fn dirAccessPosix(
1444 userdata: ?*anyopaque,1496 userdata: ?*anyopaque,
1445 dir: Io.Dir,1497 dir: Io.Dir,
...@@ -1589,6 +1641,12 @@ fn dirAccessWindows(...@@ -1589,6 +1641,12 @@ fn dirAccessWindows(
1589 }1641 }
1590}1642}
15911643
1644const dirCreateFile = switch (native_os) {
1645 .windows => dirCreateFileWindows,
1646 .wasi => dirCreateFileWasi,
1647 else => dirCreateFilePosix,
1648};
1649
1592fn dirCreateFilePosix(1650fn dirCreateFilePosix(
1593 userdata: ?*anyopaque,1651 userdata: ?*anyopaque,
1594 dir: Io.Dir,1652 dir: Io.Dir,
...@@ -1827,6 +1885,12 @@ fn dirCreateFileWasi(...@@ -1827,6 +1885,12 @@ fn dirCreateFileWasi(
1827 }1885 }
1828}1886}
18291887
1888const dirOpenFile = switch (native_os) {
1889 .windows => dirOpenFileWindows,
1890 .wasi => dirOpenFileWasi,
1891 else => dirOpenFilePosix,
1892};
1893
1830fn dirOpenFilePosix(1894fn dirOpenFilePosix(
1831 userdata: ?*anyopaque,1895 userdata: ?*anyopaque,
1832 dir: Io.Dir,1896 dir: Io.Dir,
...@@ -2077,6 +2141,12 @@ fn dirOpenFileWasi(...@@ -2077,6 +2141,12 @@ fn dirOpenFileWasi(
2077 }2141 }
2078}2142}
20792143
2144const dirOpenDir = switch (native_os) {
2145 .wasi => dirOpenDirWasi,
2146 .haiku => dirOpenDirHaiku,
2147 else => dirOpenDirPosix,
2148};
2149
2080fn dirOpenDirPosix(2150fn dirOpenDirPosix(
2081 userdata: ?*anyopaque,2151 userdata: ?*anyopaque,
2082 dir: Io.Dir,2152 dir: Io.Dir,
...@@ -2320,6 +2390,11 @@ fn fileClose(userdata: ?*anyopaque, file: Io.File) void {...@@ -2320,6 +2390,11 @@ fn fileClose(userdata: ?*anyopaque, file: Io.File) void {
2320 posix.close(file.handle);2390 posix.close(file.handle);
2321}2391}
23222392
2393const fileReadStreaming = switch (native_os) {
2394 .windows => fileReadStreamingWindows,
2395 else => fileReadStreamingPosix,
2396};
2397
2323fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize {2398fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize {
2324 const t: *Threaded = @ptrCast(@alignCast(userdata));2399 const t: *Threaded = @ptrCast(@alignCast(userdata));
23252400
...@@ -2482,6 +2557,11 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o...@@ -2482,6 +2557,11 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o
2482 }2557 }
2483}2558}
24842559
2560const fileReadPositional = switch (native_os) {
2561 .windows => fileReadPositionalWindows,
2562 else => fileReadPositionalPosix,
2563};
2564
2485fn fileReadPositionalWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize {2565fn fileReadPositionalWindows(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize {
2486 const t: *Threaded = @ptrCast(@alignCast(userdata));2566 const t: *Threaded = @ptrCast(@alignCast(userdata));
2487 try t.checkCancel();2567 try t.checkCancel();
...@@ -2652,6 +2732,12 @@ fn nowPosix(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp...@@ -2652,6 +2732,12 @@ fn nowPosix(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp
2652 }2732 }
2653}2733}
26542734
2735const now = switch (native_os) {
2736 .windows => nowWindows,
2737 .wasi => nowWasi,
2738 else => nowPosix,
2739};
2740
2655fn nowWindows(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp {2741fn nowWindows(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp {
2656 const t: *Threaded = @ptrCast(@alignCast(userdata));2742 const t: *Threaded = @ptrCast(@alignCast(userdata));
2657 _ = t;2743 _ = t;
...@@ -2680,6 +2766,13 @@ fn nowWasi(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp {...@@ -2680,6 +2766,13 @@ fn nowWasi(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp {
2680 return .fromNanoseconds(ns);2766 return .fromNanoseconds(ns);
2681}2767}
26822768
2769const sleep = switch (native_os) {
2770 .windows => sleepWindows,
2771 .wasi => sleepWasi,
2772 .linux => sleepLinux,
2773 else => sleepPosix,
2774};
2775
2683fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {2776fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
2684 const t: *Threaded = @ptrCast(@alignCast(userdata));2777 const t: *Threaded = @ptrCast(@alignCast(userdata));
2685 const clock_id: posix.clockid_t = clockToPosix(switch (timeout) {2778 const clock_id: posix.clockid_t = clockToPosix(switch (timeout) {
...@@ -2710,9 +2803,10 @@ fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {...@@ -2710,9 +2803,10 @@ fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
27102803
2711fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {2804fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
2712 const t: *Threaded = @ptrCast(@alignCast(userdata));2805 const t: *Threaded = @ptrCast(@alignCast(userdata));
2806 const t_io = ioBasic(t);
2713 try t.checkCancel();2807 try t.checkCancel();
2714 const ms = ms: {2808 const ms = ms: {
2715 const d = (try timeout.toDurationFromNow(t.io())) orelse2809 const d = (try timeout.toDurationFromNow(t_io)) orelse
2716 break :ms std.math.maxInt(windows.DWORD);2810 break :ms std.math.maxInt(windows.DWORD);
2717 break :ms std.math.lossyCast(windows.DWORD, d.raw.toMilliseconds());2811 break :ms std.math.lossyCast(windows.DWORD, d.raw.toMilliseconds());
2718 };2812 };
...@@ -2721,11 +2815,12 @@ fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {...@@ -2721,11 +2815,12 @@ fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
27212815
2722fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {2816fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
2723 const t: *Threaded = @ptrCast(@alignCast(userdata));2817 const t: *Threaded = @ptrCast(@alignCast(userdata));
2818 const t_io = ioBasic(t);
2724 try t.checkCancel();2819 try t.checkCancel();
27252820
2726 const w = std.os.wasi;2821 const w = std.os.wasi;
27272822
2728 const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t.io())) |d| .{2823 const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t_io)) |d| .{
2729 .id = clockToWasi(d.clock),2824 .id = clockToWasi(d.clock),
2730 .timeout = std.math.lossyCast(u64, d.raw.nanoseconds),2825 .timeout = std.math.lossyCast(u64, d.raw.nanoseconds),
2731 .precision = 0,2826 .precision = 0,
...@@ -2750,11 +2845,12 @@ fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {...@@ -2750,11 +2845,12 @@ fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
27502845
2751fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {2846fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
2752 const t: *Threaded = @ptrCast(@alignCast(userdata));2847 const t: *Threaded = @ptrCast(@alignCast(userdata));
2848 const t_io = ioBasic(t);
2753 const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type;2849 const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type;
2754 const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type;2850 const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type;
27552851
2756 var timespec: posix.timespec = t: {2852 var timespec: posix.timespec = t: {
2757 const d = (try timeout.toDurationFromNow(t.io())) orelse break :t .{2853 const d = (try timeout.toDurationFromNow(t_io)) orelse break :t .{
2758 .sec = std.math.maxInt(sec_type),2854 .sec = std.math.maxInt(sec_type),
2759 .nsec = std.math.maxInt(nsec_type),2855 .nsec = std.math.maxInt(nsec_type),
2760 };2856 };
...@@ -2919,6 +3015,17 @@ fn netListenIpWindows(...@@ -2919,6 +3015,17 @@ fn netListenIpWindows(
2919 };3015 };
2920}3016}
29213017
3018fn netListenIpUnavailable(
3019 userdata: ?*anyopaque,
3020 address: IpAddress,
3021 options: IpAddress.ListenOptions,
3022) IpAddress.ListenError!net.Server {
3023 _ = userdata;
3024 _ = address;
3025 _ = options;
3026 return error.NetworkDown;
3027}
3028
2922fn netListenUnixPosix(3029fn netListenUnixPosix(
2923 userdata: ?*anyopaque,3030 userdata: ?*anyopaque,
2924 address: *const net.UnixAddress,3031 address: *const net.UnixAddress,
...@@ -2965,6 +3072,17 @@ fn netListenUnixWindows(...@@ -2965,6 +3072,17 @@ fn netListenUnixWindows(
2965 @panic("TODO implement netListenUnixWindows");3072 @panic("TODO implement netListenUnixWindows");
2966}3073}
29673074
3075fn netListenUnixUnavailable(
3076 userdata: ?*anyopaque,
3077 address: *const net.UnixAddress,
3078 options: net.UnixAddress.ListenOptions,
3079) net.UnixAddress.ListenError!net.Socket.Handle {
3080 _ = userdata;
3081 _ = address;
3082 _ = options;
3083 return error.AddressFamilyUnsupported;
3084}
3085
2968fn posixBindUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void {3086fn posixBindUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void {
2969 while (true) {3087 while (true) {
2970 try t.checkCancel();3088 try t.checkCancel();
...@@ -3235,6 +3353,17 @@ fn netConnectIpWindows(...@@ -3235,6 +3353,17 @@ fn netConnectIpWindows(
3235 } };3353 } };
3236}3354}
32373355
3356fn netConnectIpUnavailable(
3357 userdata: ?*anyopaque,
3358 address: *const IpAddress,
3359 options: IpAddress.ConnectOptions,
3360) IpAddress.ConnectError!net.Stream {
3361 _ = userdata;
3362 _ = address;
3363 _ = options;
3364 return error.NetworkDown;
3365}
3366
3238fn netConnectUnixPosix(3367fn netConnectUnixPosix(
3239 userdata: ?*anyopaque,3368 userdata: ?*anyopaque,
3240 address: *const net.UnixAddress,3369 address: *const net.UnixAddress,
...@@ -3263,6 +3392,15 @@ fn netConnectUnixWindows(...@@ -3263,6 +3392,15 @@ fn netConnectUnixWindows(
3263 @panic("TODO implement netConnectUnixWindows");3392 @panic("TODO implement netConnectUnixWindows");
3264}3393}
32653394
3395fn netConnectUnixUnavailable(
3396 userdata: ?*anyopaque,
3397 address: *const net.UnixAddress,
3398) net.UnixAddress.ConnectError!net.Socket.Handle {
3399 _ = userdata;
3400 _ = address;
3401 return error.AddressFamilyUnsupported;
3402}
3403
3266fn netBindIpPosix(3404fn netBindIpPosix(
3267 userdata: ?*anyopaque,3405 userdata: ?*anyopaque,
3268 address: *const IpAddress,3406 address: *const IpAddress,
...@@ -3330,6 +3468,17 @@ fn netBindIpWindows(...@@ -3330,6 +3468,17 @@ fn netBindIpWindows(
3330 };3468 };
3331}3469}
33323470
3471fn netBindIpUnavailable(
3472 userdata: ?*anyopaque,
3473 address: *const IpAddress,
3474 options: IpAddress.BindOptions,
3475) IpAddress.BindError!net.Socket {
3476 _ = userdata;
3477 _ = address;
3478 _ = options;
3479 return error.NetworkDown;
3480}
3481
3333fn openSocketPosix(3482fn openSocketPosix(
3334 t: *Threaded,3483 t: *Threaded,
3335 family: posix.sa_family_t,3484 family: posix.sa_family_t,
...@@ -3498,7 +3647,14 @@ fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net...@@ -3498,7 +3647,14 @@ fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net
3498 }3647 }
3499}3648}
35003649
3650fn netAcceptUnavailable(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net.Server.AcceptError!net.Stream {
3651 _ = userdata;
3652 _ = listen_handle;
3653 return error.NetworkDown;
3654}
3655
3501fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {3656fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
3657 if (!have_networking) return error.NetworkDown;
3502 const t: *Threaded = @ptrCast(@alignCast(userdata));3658 const t: *Threaded = @ptrCast(@alignCast(userdata));
35033659
3504 var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined;3660 var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined;
...@@ -3560,7 +3716,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net....@@ -3560,7 +3716,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
3560}3716}
35613717
3562fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {3718fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
3563 if (!have_networking) return .{ error.NetworkDown, 0 };3719 if (!have_networking) return error.NetworkDown;
3564 const t: *Threaded = @ptrCast(@alignCast(userdata));3720 const t: *Threaded = @ptrCast(@alignCast(userdata));
3565 _ = t;3721 _ = t;
3566 _ = handle;3722 _ = handle;
...@@ -3568,6 +3724,13 @@ fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8...@@ -3568,6 +3724,13 @@ fn netReadWindows(userdata: ?*anyopaque, handle: net.Socket.Handle, data: [][]u8
3568 @panic("TODO implement netReadWindows");3724 @panic("TODO implement netReadWindows");
3569}3725}
35703726
3727fn netReadUnavailable(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
3728 _ = userdata;
3729 _ = fd;
3730 _ = data;
3731 return error.NetworkDown;
3732}
3733
3571fn netSendPosix(3734fn netSendPosix(
3572 userdata: ?*anyopaque,3735 userdata: ?*anyopaque,
3573 handle: net.Socket.Handle,3736 handle: net.Socket.Handle,
...@@ -3612,6 +3775,19 @@ fn netSendWindows(...@@ -3612,6 +3775,19 @@ fn netSendWindows(
3612 @panic("TODO netSendWindows");3775 @panic("TODO netSendWindows");
3613}3776}
36143777
3778fn netSendUnavailable(
3779 userdata: ?*anyopaque,
3780 handle: net.Socket.Handle,
3781 messages: []net.OutgoingMessage,
3782 flags: net.SendFlags,
3783) struct { ?net.Socket.SendError, usize } {
3784 _ = userdata;
3785 _ = handle;
3786 _ = messages;
3787 _ = flags;
3788 return .{ error.NetworkDown, 0 };
3789}
3790
3615fn netSendOne(3791fn netSendOne(
3616 t: *Threaded,3792 t: *Threaded,
3617 handle: net.Socket.Handle,3793 handle: net.Socket.Handle,
...@@ -3777,6 +3953,7 @@ fn netReceivePosix(...@@ -3777,6 +3953,7 @@ fn netReceivePosix(
3777) struct { ?net.Socket.ReceiveTimeoutError, usize } {3953) struct { ?net.Socket.ReceiveTimeoutError, usize } {
3778 if (!have_networking) return .{ error.NetworkDown, 0 };3954 if (!have_networking) return .{ error.NetworkDown, 0 };
3779 const t: *Threaded = @ptrCast(@alignCast(userdata));3955 const t: *Threaded = @ptrCast(@alignCast(userdata));
3956 const t_io = io(t);
37803957
3781 // recvmmsg is useless, here's why:3958 // recvmmsg is useless, here's why:
3782 // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371)3959 // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371)
...@@ -3803,7 +3980,7 @@ fn netReceivePosix(...@@ -3803,7 +3980,7 @@ fn netReceivePosix(
3803 var message_i: usize = 0;3980 var message_i: usize = 0;
3804 var data_i: usize = 0;3981 var data_i: usize = 0;
38053982
3806 const deadline = timeout.toDeadline(t.io()) catch |err| return .{ err, message_i };3983 const deadline = timeout.toDeadline(t_io) catch |err| return .{ err, message_i };
38073984
3808 recv: while (true) {3985 recv: while (true) {
3809 t.checkCancel() catch |err| return .{ err, message_i };3986 t.checkCancel() catch |err| return .{ err, message_i };
...@@ -3849,7 +4026,7 @@ fn netReceivePosix(...@@ -3849,7 +4026,7 @@ fn netReceivePosix(
38494026
3850 const max_poll_ms = std.math.maxInt(u31);4027 const max_poll_ms = std.math.maxInt(u31);
3851 const timeout_ms: u31 = if (deadline) |d| t: {4028 const timeout_ms: u31 = if (deadline) |d| t: {
3852 const duration = d.durationFromNow(t.io()) catch |err| return .{ err, message_i };4029 const duration = d.durationFromNow(t_io) catch |err| return .{ err, message_i };
3853 if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i };4030 if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i };
3854 break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds()));4031 break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds()));
3855 } else max_poll_ms;4032 } else max_poll_ms;
...@@ -3915,6 +4092,23 @@ fn netReceiveWindows(...@@ -3915,6 +4092,23 @@ fn netReceiveWindows(
3915 @panic("TODO implement netReceiveWindows");4092 @panic("TODO implement netReceiveWindows");
3916}4093}
39174094
4095fn netReceiveUnavailable(
4096 userdata: ?*anyopaque,
4097 handle: net.Socket.Handle,
4098 message_buffer: []net.IncomingMessage,
4099 data_buffer: []u8,
4100 flags: net.ReceiveFlags,
4101 timeout: Io.Timeout,
4102) struct { ?net.Socket.ReceiveTimeoutError, usize } {
4103 _ = userdata;
4104 _ = handle;
4105 _ = message_buffer;
4106 _ = data_buffer;
4107 _ = flags;
4108 _ = timeout;
4109 return .{ error.NetworkDown, 0 };
4110}
4111
3918fn netWritePosix(4112fn netWritePosix(
3919 userdata: ?*anyopaque,4113 userdata: ?*anyopaque,
3920 fd: net.Socket.Handle,4114 fd: net.Socket.Handle,
...@@ -4013,6 +4207,21 @@ fn netWriteWindows(...@@ -4013,6 +4207,21 @@ fn netWriteWindows(
4013 @panic("TODO implement netWriteWindows");4207 @panic("TODO implement netWriteWindows");
4014}4208}
40154209
4210fn netWriteUnavailable(
4211 userdata: ?*anyopaque,
4212 handle: net.Socket.Handle,
4213 header: []const u8,
4214 data: []const []const u8,
4215 splat: usize,
4216) net.Stream.Writer.Error!usize {
4217 _ = userdata;
4218 _ = handle;
4219 _ = header;
4220 _ = data;
4221 _ = splat;
4222 return error.NetworkDown;
4223}
4224
4016fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void {4225fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), bytes: []const u8) void {
4017 // OS checks ptr addr before length so zero length vectors must be omitted.4226 // OS checks ptr addr before length so zero length vectors must be omitted.
4018 if (bytes.len == 0) return;4227 if (bytes.len == 0) return;
...@@ -4030,6 +4239,12 @@ fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void {...@@ -4030,6 +4239,12 @@ fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void {
4030 }4239 }
4031}4240}
40324241
4242fn netCloseUnavailable(userdata: ?*anyopaque, handle: net.Socket.Handle) void {
4243 _ = userdata;
4244 _ = handle;
4245 unreachable; // How you gonna close something that was impossible to open?
4246}
4247
4033fn netInterfaceNameResolve(4248fn netInterfaceNameResolve(
4034 userdata: ?*anyopaque,4249 userdata: ?*anyopaque,
4035 name: *const net.Interface.Name,4250 name: *const net.Interface.Name,
...@@ -4089,6 +4304,15 @@ fn netInterfaceNameResolve(...@@ -4089,6 +4304,15 @@ fn netInterfaceNameResolve(
4089 @panic("unimplemented");4304 @panic("unimplemented");
4090}4305}
40914306
4307fn netInterfaceNameResolveUnavailable(
4308 userdata: ?*anyopaque,
4309 name: *const net.Interface.Name,
4310) net.Interface.Name.ResolveError!net.Interface {
4311 _ = userdata;
4312 _ = name;
4313 return error.InterfaceNotFound;
4314}
4315
4092fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name {4316fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name {
4093 const t: *Threaded = @ptrCast(@alignCast(userdata));4317 const t: *Threaded = @ptrCast(@alignCast(userdata));
4094 try t.checkCancel();4318 try t.checkCancel();
...@@ -4109,6 +4333,12 @@ fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interfa...@@ -4109,6 +4333,12 @@ fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interfa
4109 @panic("unimplemented");4333 @panic("unimplemented");
4110}4334}
41114335
4336fn netInterfaceNameUnavailable(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name {
4337 _ = userdata;
4338 _ = interface;
4339 return error.Unexpected;
4340}
4341
4112fn netLookup(4342fn netLookup(
4113 userdata: ?*anyopaque,4343 userdata: ?*anyopaque,
4114 host_name: HostName,4344 host_name: HostName,
...@@ -4116,17 +4346,31 @@ fn netLookup(...@@ -4116,17 +4346,31 @@ fn netLookup(
4116 options: HostName.LookupOptions,4346 options: HostName.LookupOptions,
4117) void {4347) void {
4118 const t: *Threaded = @ptrCast(@alignCast(userdata));4348 const t: *Threaded = @ptrCast(@alignCast(userdata));
4119 const t_io = t.io();4349 const t_io = io(t);
4120 resolved.putOneUncancelable(t_io, .{ .end = netLookupFallible(t, host_name, resolved, options) });4350 resolved.putOneUncancelable(t_io, .{ .end = netLookupFallible(t, host_name, resolved, options) });
4121}4351}
41224352
4353fn netLookupUnavailable(
4354 userdata: ?*anyopaque,
4355 host_name: HostName,
4356 resolved: *Io.Queue(HostName.LookupResult),
4357 options: HostName.LookupOptions,
4358) void {
4359 _ = host_name;
4360 _ = options;
4361 const t: *Threaded = @ptrCast(@alignCast(userdata));
4362 const t_io = ioBasic(t);
4363 resolved.putOneUncancelable(t_io, .{ .end = error.NetworkDown });
4364}
4365
4123fn netLookupFallible(4366fn netLookupFallible(
4124 t: *Threaded,4367 t: *Threaded,
4125 host_name: HostName,4368 host_name: HostName,
4126 resolved: *Io.Queue(HostName.LookupResult),4369 resolved: *Io.Queue(HostName.LookupResult),
4127 options: HostName.LookupOptions,4370 options: HostName.LookupOptions,
4128) !void {4371) !void {
4129 const t_io = t.io();4372 if (!have_networking) return error.NetworkDown;
4373 const t_io = io(t);
4130 const name = host_name.bytes;4374 const name = host_name.bytes;
4131 assert(name.len <= HostName.max_len);4375 assert(name.len <= HostName.max_len);
41324376
...@@ -4637,7 +4881,7 @@ fn lookupDnsSearch(...@@ -4637,7 +4881,7 @@ fn lookupDnsSearch(
4637 resolved: *Io.Queue(HostName.LookupResult),4881 resolved: *Io.Queue(HostName.LookupResult),
4638 options: HostName.LookupOptions,4882 options: HostName.LookupOptions,
4639) HostName.LookupError!void {4883) HostName.LookupError!void {
4640 const t_io = t.io();4884 const t_io = io(t);
4641 const rc = HostName.ResolvConf.init(t_io) catch return error.ResolvConfParseFailed;4885 const rc = HostName.ResolvConf.init(t_io) catch return error.ResolvConfParseFailed;
46424886
4643 // Count dots, suppress search when >=ndots or name ends in4887 // Count dots, suppress search when >=ndots or name ends in
...@@ -4681,7 +4925,7 @@ fn lookupDns(...@@ -4681,7 +4925,7 @@ fn lookupDns(
4681 resolved: *Io.Queue(HostName.LookupResult),4925 resolved: *Io.Queue(HostName.LookupResult),
4682 options: HostName.LookupOptions,4926 options: HostName.LookupOptions,
4683) HostName.LookupError!void {4927) HostName.LookupError!void {
4684 const t_io = t.io();4928 const t_io = io(t);
4685 const family_records: [2]struct { af: IpAddress.Family, rr: HostName.DnsRecord } = .{4929 const family_records: [2]struct { af: IpAddress.Family, rr: HostName.DnsRecord } = .{
4686 .{ .af = .ip6, .rr = .A },4930 .{ .af = .ip6, .rr = .A },
4687 .{ .af = .ip4, .rr = .AAAA },4931 .{ .af = .ip4, .rr = .AAAA },
...@@ -4868,7 +5112,7 @@ fn lookupHosts(...@@ -4868,7 +5112,7 @@ fn lookupHosts(
4868 resolved: *Io.Queue(HostName.LookupResult),5112 resolved: *Io.Queue(HostName.LookupResult),
4869 options: HostName.LookupOptions,5113 options: HostName.LookupOptions,
4870) !void {5114) !void {
4871 const t_io = t.io();5115 const t_io = io(t);
4872 const file = Io.File.openAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) {5116 const file = Io.File.openAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) {
4873 error.FileNotFound,5117 error.FileNotFound,
4874 error.NotDir,5118 error.NotDir,
...@@ -4906,7 +5150,7 @@ fn lookupHostsReader(...@@ -4906,7 +5150,7 @@ fn lookupHostsReader(
4906 options: HostName.LookupOptions,5150 options: HostName.LookupOptions,
4907 reader: *Io.Reader,5151 reader: *Io.Reader,
4908) error{ ReadFailed, Canceled, UnknownHostName }!void {5152) error{ ReadFailed, Canceled, UnknownHostName }!void {
4909 const t_io = t.io();5153 const t_io = io(t);
4910 var addresses_len: usize = 0;5154 var addresses_len: usize = 0;
4911 var canonical_name: ?HostName = null;5155 var canonical_name: ?HostName = null;
4912 while (true) {5156 while (true) {
...@@ -5374,7 +5618,7 @@ const Wsa = struct {...@@ -5374,7 +5618,7 @@ const Wsa = struct {
5374};5618};
53755619
5376fn initializeWsa(t: *Threaded) error{NetworkDown}!void {5620fn initializeWsa(t: *Threaded) error{NetworkDown}!void {
5377 const t_io = t.io();5621 const t_io = io(t);
5378 const wsa = &t.wsa;5622 const wsa = &t.wsa;
5379 wsa.mutex.lockUncancelable(t_io);5623 wsa.mutex.lockUncancelable(t_io);
5380 defer wsa.mutex.unlock(t_io);5624 defer wsa.mutex.unlock(t_io);
lib/std/Thread.zig+1-1
...@@ -320,7 +320,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co...@@ -320,7 +320,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
320 const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()});320 const path = try std.fmt.bufPrint(&buf, "/proc/self/task/{d}/comm", .{self.getHandle()});
321321
322 var threaded: std.Io.Threaded = .init_single_threaded;322 var threaded: std.Io.Threaded = .init_single_threaded;
323 const io = threaded.io();323 const io = threaded.ioBasic();
324324
325 const file = try std.fs.cwd().openFile(path, .{});325 const file = try std.fs.cwd().openFile(path, .{});
326 defer file.close();326 defer file.close();
lib/std/debug.zig+3-3
...@@ -649,7 +649,7 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf:...@@ -649,7 +649,7 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf:
649/// See `captureCurrentStackTrace` to capture the trace addresses into a buffer instead of printing.649/// See `captureCurrentStackTrace` to capture the trace addresses into a buffer instead of printing.
650pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Writer, tty_config: tty.Config) Writer.Error!void {650pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Writer, tty_config: tty.Config) Writer.Error!void {
651 var threaded: Io.Threaded = .init_single_threaded;651 var threaded: Io.Threaded = .init_single_threaded;
652 const io = threaded.io();652 const io = threaded.ioBasic();
653653
654 if (!std.options.allow_stack_tracing) {654 if (!std.options.allow_stack_tracing) {
655 tty_config.setColor(writer, .dim) catch {};655 tty_config.setColor(writer, .dim) catch {};
...@@ -780,7 +780,7 @@ pub fn writeStackTrace(st: *const StackTrace, writer: *Writer, tty_config: tty.C...@@ -780,7 +780,7 @@ pub fn writeStackTrace(st: *const StackTrace, writer: *Writer, tty_config: tty.C
780 // We use an independent Io implementation here in case there was a problem780 // We use an independent Io implementation here in case there was a problem
781 // with the application's Io implementation itself.781 // with the application's Io implementation itself.
782 var threaded: Io.Threaded = .init_single_threaded;782 var threaded: Io.Threaded = .init_single_threaded;
783 const io = threaded.io();783 const io = threaded.ioBasic();
784784
785 // Fetch `st.index` straight away. Aside from avoiding redundant loads, this prevents issues if785 // Fetch `st.index` straight away. Aside from avoiding redundant loads, this prevents issues if
786 // `st` is `@errorReturnTrace()` and errors are encountered while writing the stack trace.786 // `st` is `@errorReturnTrace()` and errors are encountered while writing the stack trace.
...@@ -1602,7 +1602,7 @@ test "manage resources correctly" {...@@ -1602,7 +1602,7 @@ test "manage resources correctly" {
1602 };1602 };
1603 const gpa = std.testing.allocator;1603 const gpa = std.testing.allocator;
1604 var threaded: Io.Threaded = .init_single_threaded;1604 var threaded: Io.Threaded = .init_single_threaded;
1605 const io = threaded.io();1605 const io = threaded.ioBasic();
1606 var discarding: Io.Writer.Discarding = .init(&.{});1606 var discarding: Io.Writer.Discarding = .init(&.{});
1607 var di: SelfInfo = .init;1607 var di: SelfInfo = .init;
1608 defer di.deinit(gpa);1608 defer di.deinit(gpa);
lib/std/fs.zig+1-1
...@@ -340,7 +340,7 @@ pub const OpenSelfExeError = Io.File.OpenSelfExeError;...@@ -340,7 +340,7 @@ pub const OpenSelfExeError = Io.File.OpenSelfExeError;
340pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {340pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
341 if (native_os == .linux or native_os == .serenity or native_os == .windows) {341 if (native_os == .linux or native_os == .serenity or native_os == .windows) {
342 var threaded: Io.Threaded = .init_single_threaded;342 var threaded: Io.Threaded = .init_single_threaded;
343 const io = threaded.io();343 const io = threaded.ioBasic();
344 return .adaptFromNewApi(try Io.File.openSelfExe(io, flags));344 return .adaptFromNewApi(try Io.File.openSelfExe(io, flags));
345 }345 }
346 // Use of max_path_bytes here is valid as the resulting path is immediately346 // Use of max_path_bytes here is valid as the resulting path is immediately
lib/std/fs/Dir.zig+11-11
...@@ -849,14 +849,14 @@ pub fn close(self: *Dir) void {...@@ -849,14 +849,14 @@ pub fn close(self: *Dir) void {
849/// Deprecated in favor of `Io.Dir.openFile`.849/// Deprecated in favor of `Io.Dir.openFile`.
850pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {850pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
851 var threaded: Io.Threaded = .init_single_threaded;851 var threaded: Io.Threaded = .init_single_threaded;
852 const io = threaded.io();852 const io = threaded.ioBasic();
853 return .adaptFromNewApi(try Io.Dir.openFile(self.adaptToNewApi(), io, sub_path, flags));853 return .adaptFromNewApi(try Io.Dir.openFile(self.adaptToNewApi(), io, sub_path, flags));
854}854}
855855
856/// Deprecated in favor of `Io.Dir.createFile`.856/// Deprecated in favor of `Io.Dir.createFile`.
857pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {857pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
858 var threaded: Io.Threaded = .init_single_threaded;858 var threaded: Io.Threaded = .init_single_threaded;
859 const io = threaded.io();859 const io = threaded.ioBasic();
860 const new_file = try Io.Dir.createFile(self.adaptToNewApi(), io, sub_path, flags);860 const new_file = try Io.Dir.createFile(self.adaptToNewApi(), io, sub_path, flags);
861 return .adaptFromNewApi(new_file);861 return .adaptFromNewApi(new_file);
862}862}
...@@ -867,7 +867,7 @@ pub const MakeError = Io.Dir.MakeError;...@@ -867,7 +867,7 @@ pub const MakeError = Io.Dir.MakeError;
867/// Deprecated in favor of `Io.Dir.makeDir`.867/// Deprecated in favor of `Io.Dir.makeDir`.
868pub fn makeDir(self: Dir, sub_path: []const u8) MakeError!void {868pub fn makeDir(self: Dir, sub_path: []const u8) MakeError!void {
869 var threaded: Io.Threaded = .init_single_threaded;869 var threaded: Io.Threaded = .init_single_threaded;
870 const io = threaded.io();870 const io = threaded.ioBasic();
871 return Io.Dir.makeDir(.{ .handle = self.fd }, io, sub_path);871 return Io.Dir.makeDir(.{ .handle = self.fd }, io, sub_path);
872}872}
873873
...@@ -894,14 +894,14 @@ pub const MakePathError = Io.Dir.MakePathError;...@@ -894,14 +894,14 @@ pub const MakePathError = Io.Dir.MakePathError;
894/// Deprecated in favor of `Io.Dir.makePathStatus`.894/// Deprecated in favor of `Io.Dir.makePathStatus`.
895pub fn makePathStatus(self: Dir, sub_path: []const u8) MakePathError!MakePathStatus {895pub fn makePathStatus(self: Dir, sub_path: []const u8) MakePathError!MakePathStatus {
896 var threaded: Io.Threaded = .init_single_threaded;896 var threaded: Io.Threaded = .init_single_threaded;
897 const io = threaded.io();897 const io = threaded.ioBasic();
898 return Io.Dir.makePathStatus(.{ .handle = self.fd }, io, sub_path);898 return Io.Dir.makePathStatus(.{ .handle = self.fd }, io, sub_path);
899}899}
900900
901/// Deprecated in favor of `Io.Dir.makeOpenPath`.901/// Deprecated in favor of `Io.Dir.makeOpenPath`.
902pub fn makeOpenPath(dir: Dir, sub_path: []const u8, options: OpenOptions) Io.Dir.MakeOpenPathError!Dir {902pub fn makeOpenPath(dir: Dir, sub_path: []const u8, options: OpenOptions) Io.Dir.MakeOpenPathError!Dir {
903 var threaded: Io.Threaded = .init_single_threaded;903 var threaded: Io.Threaded = .init_single_threaded;
904 const io = threaded.io();904 const io = threaded.ioBasic();
905 return .adaptFromNewApi(try Io.Dir.makeOpenPath(dir.adaptToNewApi(), io, sub_path, options));905 return .adaptFromNewApi(try Io.Dir.makeOpenPath(dir.adaptToNewApi(), io, sub_path, options));
906}906}
907907
...@@ -1070,7 +1070,7 @@ pub const OpenOptions = Io.Dir.OpenOptions;...@@ -1070,7 +1070,7 @@ pub const OpenOptions = Io.Dir.OpenOptions;
1070/// Deprecated in favor of `Io.Dir.openDir`.1070/// Deprecated in favor of `Io.Dir.openDir`.
1071pub fn openDir(self: Dir, sub_path: []const u8, args: OpenOptions) OpenError!Dir {1071pub fn openDir(self: Dir, sub_path: []const u8, args: OpenOptions) OpenError!Dir {
1072 var threaded: Io.Threaded = .init_single_threaded;1072 var threaded: Io.Threaded = .init_single_threaded;
1073 const io = threaded.io();1073 const io = threaded.ioBasic();
1074 return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args));1074 return .adaptFromNewApi(try Io.Dir.openDir(.{ .handle = self.fd }, io, sub_path, args));
1075}1075}
10761076
...@@ -1384,7 +1384,7 @@ pub fn readLinkW(self: Dir, sub_path_w: []const u16, buffer: []u8) ![]u8 {...@@ -1384,7 +1384,7 @@ pub fn readLinkW(self: Dir, sub_path_w: []const u16, buffer: []u8) ![]u8 {
1384/// Deprecated in favor of `Io.Dir.readFile`.1384/// Deprecated in favor of `Io.Dir.readFile`.
1385pub fn readFile(self: Dir, file_path: []const u8, buffer: []u8) ![]u8 {1385pub fn readFile(self: Dir, file_path: []const u8, buffer: []u8) ![]u8 {
1386 var threaded: Io.Threaded = .init_single_threaded;1386 var threaded: Io.Threaded = .init_single_threaded;
1387 const io = threaded.io();1387 const io = threaded.ioBasic();
1388 return Io.Dir.readFile(.{ .handle = self.fd }, io, file_path, buffer);1388 return Io.Dir.readFile(.{ .handle = self.fd }, io, file_path, buffer);
1389}1389}
13901390
...@@ -1437,7 +1437,7 @@ pub fn readFileAllocOptions(...@@ -1437,7 +1437,7 @@ pub fn readFileAllocOptions(
1437 comptime sentinel: ?u8,1437 comptime sentinel: ?u8,
1438) ReadFileAllocError!(if (sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) {1438) ReadFileAllocError!(if (sentinel) |s| [:s]align(alignment.toByteUnits()) u8 else []align(alignment.toByteUnits()) u8) {
1439 var threaded: Io.Threaded = .init_single_threaded;1439 var threaded: Io.Threaded = .init_single_threaded;
1440 const io = threaded.io();1440 const io = threaded.ioBasic();
14411441
1442 var file = try dir.openFile(sub_path, .{});1442 var file = try dir.openFile(sub_path, .{});
1443 defer file.close();1443 defer file.close();
...@@ -1892,7 +1892,7 @@ pub const AccessError = Io.Dir.AccessError;...@@ -1892,7 +1892,7 @@ pub const AccessError = Io.Dir.AccessError;
1892/// Deprecated in favor of `Io.Dir.access`.1892/// Deprecated in favor of `Io.Dir.access`.
1893pub fn access(self: Dir, sub_path: []const u8, options: Io.Dir.AccessOptions) AccessError!void {1893pub fn access(self: Dir, sub_path: []const u8, options: Io.Dir.AccessOptions) AccessError!void {
1894 var threaded: Io.Threaded = .init_single_threaded;1894 var threaded: Io.Threaded = .init_single_threaded;
1895 const io = threaded.io();1895 const io = threaded.ioBasic();
1896 return Io.Dir.access(self.adaptToNewApi(), io, sub_path, options);1896 return Io.Dir.access(self.adaptToNewApi(), io, sub_path, options);
1897}1897}
18981898
...@@ -1928,7 +1928,7 @@ pub fn copyFile(...@@ -1928,7 +1928,7 @@ pub fn copyFile(
1928 options: CopyFileOptions,1928 options: CopyFileOptions,
1929) CopyFileError!void {1929) CopyFileError!void {
1930 var threaded: Io.Threaded = .init_single_threaded;1930 var threaded: Io.Threaded = .init_single_threaded;
1931 const io = threaded.io();1931 const io = threaded.ioBasic();
19321932
1933 const file = try source_dir.openFile(source_path, .{});1933 const file = try source_dir.openFile(source_path, .{});
1934 var file_reader: File.Reader = .init(.{ .handle = file.handle }, io, &.{});1934 var file_reader: File.Reader = .init(.{ .handle = file.handle }, io, &.{});
...@@ -1996,7 +1996,7 @@ pub const StatFileError = File.OpenError || File.StatError || posix.FStatAtError...@@ -1996,7 +1996,7 @@ pub const StatFileError = File.OpenError || File.StatError || posix.FStatAtError
1996/// Deprecated in favor of `Io.Dir.statPath`.1996/// Deprecated in favor of `Io.Dir.statPath`.
1997pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {1997pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
1998 var threaded: Io.Threaded = .init_single_threaded;1998 var threaded: Io.Threaded = .init_single_threaded;
1999 const io = threaded.io();1999 const io = threaded.ioBasic();
2000 return Io.Dir.statPath(.{ .handle = self.fd }, io, sub_path, .{});2000 return Io.Dir.statPath(.{ .handle = self.fd }, io, sub_path, .{});
2001}2001}
20022002
lib/std/fs/File.zig+1-1
...@@ -313,7 +313,7 @@ pub const StatError = posix.FStatError;...@@ -313,7 +313,7 @@ pub const StatError = posix.FStatError;
313/// Returns `Stat` containing basic information about the `File`.313/// Returns `Stat` containing basic information about the `File`.
314pub fn stat(self: File) StatError!Stat {314pub fn stat(self: File) StatError!Stat {
315 var threaded: Io.Threaded = .init_single_threaded;315 var threaded: Io.Threaded = .init_single_threaded;
316 const io = threaded.io();316 const io = threaded.ioBasic();
317 return Io.File.stat(.{ .handle = self.handle }, io);317 return Io.File.stat(.{ .handle = self.handle }, io);
318}318}
319319
lib/std/process/Child.zig+1-1
...@@ -1089,7 +1089,7 @@ fn windowsCreateProcessPathExt(...@@ -1089,7 +1089,7 @@ fn windowsCreateProcessPathExt(
1089 // opening function knowing which implementation we are in. Here, we imitate1089 // opening function knowing which implementation we are in. Here, we imitate
1090 // that scenario.1090 // that scenario.
1091 var threaded: std.Io.Threaded = .init_single_threaded;1091 var threaded: std.Io.Threaded = .init_single_threaded;
1092 const io = threaded.io();1092 const io = threaded.ioBasic();
10931093
1094 var dir = dir: {1094 var dir = dir: {
1095 // needs to be null-terminated1095 // needs to be null-terminated
test/standalone/child_process/child.zig+10-3
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const Io = std.Io;
23
3// 42 is expected by parent; other values result in test failure4// 42 is expected by parent; other values result in test failure
4var exit_code: u8 = 42;5var exit_code: u8 = 42;
...@@ -6,12 +7,17 @@ var exit_code: u8 = 42;...@@ -6,12 +7,17 @@ var exit_code: u8 = 42;
6pub fn main() !void {7pub fn main() !void {
7 var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);8 var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
8 const arena = arena_state.allocator();9 const arena = arena_state.allocator();
9 try run(arena);10
11 var threaded: std.Io.Threaded = .init(arena);
12 defer threaded.deinit();
13 const io = threaded.io();
14
15 try run(arena, io);
10 arena_state.deinit();16 arena_state.deinit();
11 std.process.exit(exit_code);17 std.process.exit(exit_code);
12}18}
1319
14fn run(allocator: std.mem.Allocator) !void {20fn run(allocator: std.mem.Allocator, io: Io) !void {
15 var args = try std.process.argsWithAllocator(allocator);21 var args = try std.process.argsWithAllocator(allocator);
16 defer args.deinit();22 defer args.deinit();
17 _ = args.next() orelse unreachable; // skip binary name23 _ = args.next() orelse unreachable; // skip binary name
...@@ -33,7 +39,8 @@ fn run(allocator: std.mem.Allocator) !void {...@@ -33,7 +39,8 @@ fn run(allocator: std.mem.Allocator) !void {
33 const hello_stdin = "hello from stdin";39 const hello_stdin = "hello from stdin";
34 var buf: [hello_stdin.len]u8 = undefined;40 var buf: [hello_stdin.len]u8 = undefined;
35 const stdin: std.fs.File = .stdin();41 const stdin: std.fs.File = .stdin();
36 const n = try stdin.readAll(&buf);42 var reader = stdin.reader(io, &.{});
43 const n = try reader.interface.readSliceShort(&buf);
37 if (!std.mem.eql(u8, buf[0..n], hello_stdin)) {44 if (!std.mem.eql(u8, buf[0..n], hello_stdin)) {
38 testError("stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin });45 testError("stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin });
39 }46 }
test/standalone/simple/cat/main.zig+6-2
...@@ -9,6 +9,10 @@ pub fn main() !void {...@@ -9,6 +9,10 @@ pub fn main() !void {
9 defer arena_instance.deinit();9 defer arena_instance.deinit();
10 const arena = arena_instance.allocator();10 const arena = arena_instance.allocator();
1111
12 var threaded: std.Io.Threaded = .init(arena);
13 defer threaded.deinit();
14 const io = threaded.io();
15
12 const args = try std.process.argsAlloc(arena);16 const args = try std.process.argsAlloc(arena);
1317
14 const exe = args[0];18 const exe = args[0];
...@@ -16,7 +20,7 @@ pub fn main() !void {...@@ -16,7 +20,7 @@ pub fn main() !void {
16 var stdout_buffer: [4096]u8 = undefined;20 var stdout_buffer: [4096]u8 = undefined;
17 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);21 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
18 const stdout = &stdout_writer.interface;22 const stdout = &stdout_writer.interface;
19 var stdin_reader = fs.File.stdin().readerStreaming(&.{});23 var stdin_reader = fs.File.stdin().readerStreaming(io, &.{});
2024
21 const cwd = fs.cwd();25 const cwd = fs.cwd();
2226
...@@ -32,7 +36,7 @@ pub fn main() !void {...@@ -32,7 +36,7 @@ pub fn main() !void {
32 defer file.close();36 defer file.close();
3337
34 catted_anything = true;38 catted_anything = true;
35 var file_reader = file.reader(&.{});39 var file_reader = file.reader(io, &.{});
36 _ = try stdout.sendFileAll(&file_reader, .unlimited);40 _ = try stdout.sendFileAll(&file_reader, .unlimited);
37 try stdout.flush();41 try stdout.flush();
38 }42 }
tools/fetch_them_macos_headers.zig+7-5
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const Io = std.Io;
2const fs = std.fs;3const fs = std.fs;
3const mem = std.mem;4const mem = std.mem;
4const process = std.process;5const process = std.process;
...@@ -85,7 +86,7 @@ pub fn main() anyerror!void {...@@ -85,7 +86,7 @@ pub fn main() anyerror!void {
85 } else try argv.append(arg);86 } else try argv.append(arg);
86 }87 }
8788
88 var threaded: std.Io.Threaded = .init(gpa);89 var threaded: Io.Threaded = .init(gpa);
89 defer threaded.deinit();90 defer threaded.deinit();
90 const io = threaded.io();91 const io = threaded.io();
9192
...@@ -118,12 +119,13 @@ pub fn main() anyerror!void {...@@ -118,12 +119,13 @@ pub fn main() anyerror!void {
118 .arch = arch,119 .arch = arch,
119 .os_ver = os_ver,120 .os_ver = os_ver,
120 };121 };
121 try fetchTarget(allocator, argv.items, sysroot_path, target, version, tmp);122 try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp);
122 }123 }
123}124}
124125
125fn fetchTarget(126fn fetchTarget(
126 arena: Allocator,127 arena: Allocator,
128 io: Io,
127 args: []const []const u8,129 args: []const []const u8,
128 sysroot: []const u8,130 sysroot: []const u8,
129 target: Target,131 target: Target,
...@@ -194,7 +196,7 @@ fn fetchTarget(...@@ -194,7 +196,7 @@ fn fetchTarget(
194 var dirs = std.StringHashMap(fs.Dir).init(arena);196 var dirs = std.StringHashMap(fs.Dir).init(arena);
195 try dirs.putNoClobber(".", dest_dir);197 try dirs.putNoClobber(".", dest_dir);
196198
197 var headers_list_file_reader = headers_list_file.reader(&.{});199 var headers_list_file_reader = headers_list_file.reader(io, &.{});
198 const headers_list_str = try headers_list_file_reader.interface.allocRemaining(arena, .unlimited);200 const headers_list_str = try headers_list_file_reader.interface.allocRemaining(arena, .unlimited);
199 const prefix = "/usr/include";201 const prefix = "/usr/include";
200202
...@@ -267,8 +269,8 @@ const Version = struct {...@@ -267,8 +269,8 @@ const Version = struct {
267269
268 pub fn format(270 pub fn format(
269 v: Version,271 v: Version,
270 writer: *std.Io.Writer,272 writer: *Io.Writer,
271 ) std.Io.Writer.Error!void {273 ) Io.Writer.Error!void {
272 try writer.print("{d}.{d}.{d}", .{ v.major, v.minor, v.patch });274 try writer.print("{d}.{d}.{d}", .{ v.major, v.minor, v.patch });
273 }275 }
274};276};
tools/gen_macos_headers_c.zig+1-1
...@@ -73,7 +73,7 @@ fn findHeaders(...@@ -73,7 +73,7 @@ fn findHeaders(
73 switch (entry.kind) {73 switch (entry.kind) {
74 .directory => {74 .directory => {
75 const path = try std.fs.path.join(arena, &.{ prefix, entry.name });75 const path = try std.fs.path.join(arena, &.{ prefix, entry.name });
76 var subdir = try dir.openDir(entry.name, .{ .no_follow = true });76 var subdir = try dir.openDir(entry.name, .{ .follow_symlinks = false });
77 defer subdir.close();77 defer subdir.close();
78 try findHeaders(arena, subdir, path, paths);78 try findHeaders(arena, subdir, path, paths);
79 },79 },