authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-18 02:30:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:50-07:00
log2d7d98da0cd54e9dc12c5d4f97cdf2e7dac36446
tree3574da909b04785c6ac47592dde4402f178f4cce
parent97b9cc0adfee5b21079fccfde535b43391ac6233

std.fs: use BadPathName rather than InvalidWtf8 on Windows


12 files changed, 64 insertions(+), 105 deletions(-)

lib/compiler/translate-c/main.zig+5-1
...@@ -18,6 +18,10 @@ pub fn main() u8 {...@@ -18,6 +18,10 @@ pub fn main() u8 {
18 defer arena_instance.deinit();18 defer arena_instance.deinit();
19 const arena = arena_instance.allocator();19 const arena = arena_instance.allocator();
2020
21 var threaded: std.Io.Threaded = .init(gpa);
22 defer threaded.deinit();
23 const io = threaded.io();
24
21 var args = process.argsAlloc(arena) catch {25 var args = process.argsAlloc(arena) catch {
22 std.debug.print("ran out of memory allocating arguments\n", .{});26 std.debug.print("ran out of memory allocating arguments\n", .{});
23 if (fast_exit) process.exit(1);27 if (fast_exit) process.exit(1);
...@@ -42,7 +46,7 @@ pub fn main() u8 {...@@ -42,7 +46,7 @@ pub fn main() u8 {
42 };46 };
43 defer diagnostics.deinit();47 defer diagnostics.deinit();
4448
45 var comp = aro.Compilation.initDefault(gpa, arena, &diagnostics, std.fs.cwd()) catch |err| switch (err) {49 var comp = aro.Compilation.initDefault(gpa, arena, io, &diagnostics, std.fs.cwd()) catch |err| switch (err) {
46 error.OutOfMemory => {50 error.OutOfMemory => {
47 std.debug.print("ran out of memory initializing C compilation\n", .{});51 std.debug.print("ran out of memory initializing C compilation\n", .{});
48 if (fast_exit) process.exit(1);52 if (fast_exit) process.exit(1);
lib/std/Build/Cache/Path.zig+6-4
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1const Path = @This();1const Path = @This();
2
2const std = @import("../../std.zig");3const std = @import("../../std.zig");
4const Io = std.Io;
3const assert = std.debug.assert;5const assert = std.debug.assert;
4const fs = std.fs;6const fs = std.fs;
5const Allocator = std.mem.Allocator;7const Allocator = std.mem.Allocator;
...@@ -119,7 +121,7 @@ pub fn atomicFile(...@@ -119,7 +121,7 @@ pub fn atomicFile(
119 return p.root_dir.handle.atomicFile(joined_path, options);121 return p.root_dir.handle.atomicFile(joined_path, options);
120}122}
121123
122pub fn access(p: Path, sub_path: []const u8, flags: fs.File.OpenFlags) !void {124pub fn access(p: Path, sub_path: []const u8, flags: Io.Dir.AccessOptions) !void {
123 var buf: [fs.max_path_bytes]u8 = undefined;125 var buf: [fs.max_path_bytes]u8 = undefined;
124 const joined_path = if (p.sub_path.len == 0) sub_path else p: {126 const joined_path = if (p.sub_path.len == 0) sub_path else p: {
125 break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{127 break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{
...@@ -151,7 +153,7 @@ pub fn fmtEscapeString(path: Path) std.fmt.Alt(Path, formatEscapeString) {...@@ -151,7 +153,7 @@ pub fn fmtEscapeString(path: Path) std.fmt.Alt(Path, formatEscapeString) {
151 return .{ .data = path };153 return .{ .data = path };
152}154}
153155
154pub fn formatEscapeString(path: Path, writer: *std.Io.Writer) std.Io.Writer.Error!void {156pub fn formatEscapeString(path: Path, writer: *Io.Writer) Io.Writer.Error!void {
155 if (path.root_dir.path) |p| {157 if (path.root_dir.path) |p| {
156 try std.zig.stringEscape(p, writer);158 try std.zig.stringEscape(p, writer);
157 if (path.sub_path.len > 0) try std.zig.stringEscape(fs.path.sep_str, writer);159 if (path.sub_path.len > 0) try std.zig.stringEscape(fs.path.sep_str, writer);
...@@ -167,7 +169,7 @@ pub fn fmtEscapeChar(path: Path) std.fmt.Alt(Path, formatEscapeChar) {...@@ -167,7 +169,7 @@ pub fn fmtEscapeChar(path: Path) std.fmt.Alt(Path, formatEscapeChar) {
167}169}
168170
169/// Deprecated, use double quoted escape to print paths.171/// Deprecated, use double quoted escape to print paths.
170pub fn formatEscapeChar(path: Path, writer: *std.Io.Writer) std.Io.Writer.Error!void {172pub fn formatEscapeChar(path: Path, writer: *Io.Writer) Io.Writer.Error!void {
171 if (path.root_dir.path) |p| {173 if (path.root_dir.path) |p| {
172 for (p) |byte| try std.zig.charEscape(byte, writer);174 for (p) |byte| try std.zig.charEscape(byte, writer);
173 if (path.sub_path.len > 0) try writer.writeByte(fs.path.sep);175 if (path.sub_path.len > 0) try writer.writeByte(fs.path.sep);
...@@ -177,7 +179,7 @@ pub fn formatEscapeChar(path: Path, writer: *std.Io.Writer) std.Io.Writer.Error!...@@ -177,7 +179,7 @@ pub fn formatEscapeChar(path: Path, writer: *std.Io.Writer) std.Io.Writer.Error!
177 }179 }
178}180}
179181
180pub fn format(self: Path, writer: *std.Io.Writer) std.Io.Writer.Error!void {182pub fn format(self: Path, writer: *Io.Writer) Io.Writer.Error!void {
181 if (std.fs.path.isAbsolute(self.sub_path)) {183 if (std.fs.path.isAbsolute(self.sub_path)) {
182 try writer.writeAll(self.sub_path);184 try writer.writeAll(self.sub_path);
183 return;185 return;
lib/std/Thread.zig+1
...@@ -171,6 +171,7 @@ pub const SetNameError = error{...@@ -171,6 +171,7 @@ pub const SetNameError = error{
171 NameTooLong,171 NameTooLong,
172 Unsupported,172 Unsupported,
173 Unexpected,173 Unexpected,
174 InvalidWtf8,
174} || posix.PrctlError || posix.WriteError || std.fs.File.OpenError || std.fmt.BufPrintError;175} || posix.PrctlError || posix.WriteError || std.fs.File.OpenError || std.fmt.BufPrintError;
175176
176pub fn setName(self: Thread, name: []const u8) SetNameError!void {177pub fn setName(self: Thread, name: []const u8) SetNameError!void {
lib/std/debug/SelfInfo/Windows.zig+10-9
...@@ -20,11 +20,11 @@ pub fn deinit(si: *SelfInfo, gpa: Allocator) void {...@@ -20,11 +20,11 @@ pub fn deinit(si: *SelfInfo, gpa: Allocator) void {
20 module_name_arena.deinit();20 module_name_arena.deinit();
21}21}
2222
23pub fn getSymbol(si: *SelfInfo, gpa: Allocator, address: usize) Error!std.debug.Symbol {23pub fn getSymbol(si: *SelfInfo, gpa: Allocator, io: Io, address: usize) Error!std.debug.Symbol {
24 si.mutex.lock();24 si.mutex.lock();
25 defer si.mutex.unlock();25 defer si.mutex.unlock();
26 const module = try si.findModule(gpa, address);26 const module = try si.findModule(gpa, address);
27 const di = try module.getDebugInfo(gpa);27 const di = try module.getDebugInfo(gpa, io);
28 return di.getSymbol(gpa, address - module.base_address);28 return di.getSymbol(gpa, address - module.base_address);
29}29}
30pub fn getModuleName(si: *SelfInfo, gpa: Allocator, address: usize) Error![]const u8 {30pub fn getModuleName(si: *SelfInfo, gpa: Allocator, address: usize) Error![]const u8 {
...@@ -190,6 +190,7 @@ const Module = struct {...@@ -190,6 +190,7 @@ const Module = struct {
190190
191 const DebugInfo = struct {191 const DebugInfo = struct {
192 arena: std.heap.ArenaAllocator.State,192 arena: std.heap.ArenaAllocator.State,
193 io: Io,
193 coff_image_base: u64,194 coff_image_base: u64,
194 mapped_file: ?MappedFile,195 mapped_file: ?MappedFile,
195 dwarf: ?Dwarf,196 dwarf: ?Dwarf,
...@@ -209,9 +210,10 @@ const Module = struct {...@@ -209,9 +210,10 @@ const Module = struct {
209 };210 };
210211
211 fn deinit(di: *DebugInfo, gpa: Allocator) void {212 fn deinit(di: *DebugInfo, gpa: Allocator) void {
213 const io = di.io;
212 if (di.dwarf) |*dwarf| dwarf.deinit(gpa);214 if (di.dwarf) |*dwarf| dwarf.deinit(gpa);
213 if (di.pdb) |*pdb| {215 if (di.pdb) |*pdb| {
214 pdb.file_reader.file.close();216 pdb.file_reader.file.close(io);
215 pdb.deinit();217 pdb.deinit();
216 }218 }
217 if (di.mapped_file) |*mf| mf.deinit();219 if (di.mapped_file) |*mf| mf.deinit();
...@@ -277,11 +279,11 @@ const Module = struct {...@@ -277,11 +279,11 @@ const Module = struct {
277 }279 }
278 };280 };
279281
280 fn getDebugInfo(module: *Module, gpa: Allocator) Error!*DebugInfo {282 fn getDebugInfo(module: *Module, gpa: Allocator, io: Io) Error!*DebugInfo {
281 if (module.di == null) module.di = loadDebugInfo(module, gpa);283 if (module.di == null) module.di = loadDebugInfo(module, gpa, io);
282 return if (module.di.?) |*di| di else |err| err;284 return if (module.di.?) |*di| di else |err| err;
283 }285 }
284 fn loadDebugInfo(module: *const Module, gpa: Allocator) Error!DebugInfo {286 fn loadDebugInfo(module: *const Module, gpa: Allocator, io: Io) Error!DebugInfo {
285 const mapped_ptr: [*]const u8 = @ptrFromInt(module.base_address);287 const mapped_ptr: [*]const u8 = @ptrFromInt(module.base_address);
286 const mapped = mapped_ptr[0..module.size];288 const mapped = mapped_ptr[0..module.size];
287 var coff_obj = coff.Coff.init(mapped, true) catch return error.InvalidDebugInfo;289 var coff_obj = coff.Coff.init(mapped, true) catch return error.InvalidDebugInfo;
...@@ -306,6 +308,7 @@ const Module = struct {...@@ -306,6 +308,7 @@ const Module = struct {
306 );308 );
307 if (len == 0) return error.MissingDebugInfo;309 if (len == 0) return error.MissingDebugInfo;
308 const coff_file = fs.openFileAbsoluteW(name_buffer[0 .. len + 4 :0], .{}) catch |err| switch (err) {310 const coff_file = fs.openFileAbsoluteW(name_buffer[0 .. len + 4 :0], .{}) catch |err| switch (err) {
311 error.Canceled => |e| return e,
309 error.Unexpected => |e| return e,312 error.Unexpected => |e| return e,
310 error.FileNotFound => return error.MissingDebugInfo,313 error.FileNotFound => return error.MissingDebugInfo,
311314
...@@ -314,8 +317,6 @@ const Module = struct {...@@ -314,8 +317,6 @@ const Module = struct {
314 error.NotDir,317 error.NotDir,
315 error.SymLinkLoop,318 error.SymLinkLoop,
316 error.NameTooLong,319 error.NameTooLong,
317 error.InvalidUtf8,
318 error.InvalidWtf8,
319 error.BadPathName,320 error.BadPathName,
320 => return error.InvalidDebugInfo,321 => return error.InvalidDebugInfo,
321322
...@@ -435,7 +436,7 @@ const Module = struct {...@@ -435,7 +436,7 @@ const Module = struct {
435 errdefer pdb_file.close();436 errdefer pdb_file.close();
436437
437 const pdb_reader = try arena.create(Io.File.Reader);438 const pdb_reader = try arena.create(Io.File.Reader);
438 pdb_reader.* = pdb_file.reader(try arena.alloc(u8, 4096));439 pdb_reader.* = pdb_file.reader(io, try arena.alloc(u8, 4096));
439440
440 var pdb = Pdb.init(gpa, pdb_reader) catch |err| switch (err) {441 var pdb = Pdb.init(gpa, pdb_reader) catch |err| switch (err) {
441 error.OutOfMemory, error.ReadFailed, error.Unexpected => |e| return e,442 error.OutOfMemory, error.ReadFailed, error.Unexpected => |e| return e,
lib/std/fs.zig+1-10
...@@ -500,7 +500,6 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {...@@ -500,7 +500,6 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
500500
501 var real_path_buf: [max_path_bytes]u8 = undefined;501 var real_path_buf: [max_path_bytes]u8 = undefined;
502 const real_path = std.posix.realpathZ(&symlink_path_buf, &real_path_buf) catch |err| switch (err) {502 const real_path = std.posix.realpathZ(&symlink_path_buf, &real_path_buf) catch |err| switch (err) {
503 error.InvalidWtf8 => unreachable, // Windows-only
504 error.NetworkNotFound => unreachable, // Windows-only503 error.NetworkNotFound => unreachable, // Windows-only
505 else => |e| return e,504 else => |e| return e,
506 };505 };
...@@ -511,15 +510,11 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {...@@ -511,15 +510,11 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
511 }510 }
512 switch (native_os) {511 switch (native_os) {
513 .linux, .serenity => return posix.readlinkZ("/proc/self/exe", out_buffer) catch |err| switch (err) {512 .linux, .serenity => return posix.readlinkZ("/proc/self/exe", out_buffer) catch |err| switch (err) {
514 error.InvalidUtf8 => unreachable, // WASI-only
515 error.InvalidWtf8 => unreachable, // Windows-only
516 error.UnsupportedReparsePointType => unreachable, // Windows-only513 error.UnsupportedReparsePointType => unreachable, // Windows-only
517 error.NetworkNotFound => unreachable, // Windows-only514 error.NetworkNotFound => unreachable, // Windows-only
518 else => |e| return e,515 else => |e| return e,
519 },516 },
520 .illumos => return posix.readlinkZ("/proc/self/path/a.out", out_buffer) catch |err| switch (err) {517 .illumos => return posix.readlinkZ("/proc/self/path/a.out", out_buffer) catch |err| switch (err) {
521 error.InvalidUtf8 => unreachable, // WASI-only
522 error.InvalidWtf8 => unreachable, // Windows-only
523 error.UnsupportedReparsePointType => unreachable, // Windows-only518 error.UnsupportedReparsePointType => unreachable, // Windows-only
524 error.NetworkNotFound => unreachable, // Windows-only519 error.NetworkNotFound => unreachable, // Windows-only
525 else => |e| return e,520 else => |e| return e,
...@@ -548,7 +543,6 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {...@@ -548,7 +543,6 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
548 // argv[0] is a path (relative or absolute): use realpath(3) directly543 // argv[0] is a path (relative or absolute): use realpath(3) directly
549 var real_path_buf: [max_path_bytes]u8 = undefined;544 var real_path_buf: [max_path_bytes]u8 = undefined;
550 const real_path = posix.realpathZ(std.os.argv[0], &real_path_buf) catch |err| switch (err) {545 const real_path = posix.realpathZ(std.os.argv[0], &real_path_buf) catch |err| switch (err) {
551 error.InvalidWtf8 => unreachable, // Windows-only
552 error.NetworkNotFound => unreachable, // Windows-only546 error.NetworkNotFound => unreachable, // Windows-only
553 else => |e| return e,547 else => |e| return e,
554 };548 };
...@@ -591,10 +585,7 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {...@@ -591,10 +585,7 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
591 // that the symlink points to, though, so we need to get the realpath.585 // that the symlink points to, though, so we need to get the realpath.
592 var pathname_w = try windows.wToPrefixedFileW(null, image_path_name);586 var pathname_w = try windows.wToPrefixedFileW(null, image_path_name);
593587
594 const wide_slice = std.fs.cwd().realpathW2(pathname_w.span(), &pathname_w.data) catch |err| switch (err) {588 const wide_slice = try std.fs.cwd().realpathW2(pathname_w.span(), &pathname_w.data);
595 error.InvalidWtf8 => unreachable,
596 else => |e| return e,
597 };
598589
599 const len = std.unicode.calcWtf8Len(wide_slice);590 const len = std.unicode.calcWtf8Len(wide_slice);
600 if (len > out_buffer.len)591 if (len > out_buffer.len)
lib/std/fs/Dir.zig+5-19
...@@ -1472,11 +1472,9 @@ pub const DeleteDirError = error{...@@ -1472,11 +1472,9 @@ pub const DeleteDirError = error{
1472 NotDir,1472 NotDir,
1473 SystemResources,1473 SystemResources,
1474 ReadOnlyFileSystem,1474 ReadOnlyFileSystem,
1475 /// WASI-only; file paths must be valid UTF-8.1475 /// WASI: file paths must be valid UTF-8.
1476 InvalidUtf8,1476 /// Windows: file paths provided by the user must be valid WTF-8.
1477 /// Windows-only; file paths provided by the user must be valid WTF-8.
1478 /// https://wtf-8.codeberg.page/1477 /// https://wtf-8.codeberg.page/
1479 InvalidWtf8,
1480 BadPathName,1478 BadPathName,
1481 /// On Windows, `\\server` or `\\server\share` was not found.1479 /// On Windows, `\\server` or `\\server\share` was not found.
1482 NetworkNotFound,1480 NetworkNotFound,
...@@ -1577,9 +1575,7 @@ pub fn symLink(...@@ -1577,9 +1575,7 @@ pub fn symLink(
1577 // when converting to an NT namespaced path. CreateSymbolicLink in1575 // when converting to an NT namespaced path. CreateSymbolicLink in
1578 // symLinkW will handle the necessary conversion.1576 // symLinkW will handle the necessary conversion.
1579 var target_path_w: windows.PathSpace = undefined;1577 var target_path_w: windows.PathSpace = undefined;
1580 if (try std.unicode.checkWtf8ToWtf16LeOverflow(target_path, &target_path_w.data)) {1578 try std.unicode.checkWtf8ToWtf16LeOverflow(target_path, &target_path_w.data);
1581 return error.NameTooLong;
1582 }
1583 target_path_w.len = try std.unicode.wtf8ToWtf16Le(&target_path_w.data, target_path);1579 target_path_w.len = try std.unicode.wtf8ToWtf16Le(&target_path_w.data, target_path);
1584 target_path_w.data[target_path_w.len] = 0;1580 target_path_w.data[target_path_w.len] = 0;
1585 // However, we need to canonicalize any path separators to `\`, since if1581 // However, we need to canonicalize any path separators to `\`, since if
...@@ -1808,11 +1804,9 @@ pub const DeleteTreeError = error{...@@ -1808,11 +1804,9 @@ pub const DeleteTreeError = error{
1808 /// One of the path components was not a directory.1804 /// One of the path components was not a directory.
1809 /// This error is unreachable if `sub_path` does not contain a path separator.1805 /// This error is unreachable if `sub_path` does not contain a path separator.
1810 NotDir,1806 NotDir,
1811 /// WASI-only; file paths must be valid UTF-8.1807 /// WASI: file paths must be valid UTF-8.
1812 InvalidUtf8,1808 /// Windows: file paths provided by the user must be valid WTF-8.
1813 /// Windows-only; file paths provided by the user must be valid WTF-8.
1814 /// https://wtf-8.codeberg.page/1809 /// https://wtf-8.codeberg.page/
1815 InvalidWtf8,
1816 /// On Windows, file paths cannot contain these characters:1810 /// On Windows, file paths cannot contain these characters:
1817 /// '/', '*', '?', '"', '<', '>', '|'1811 /// '/', '*', '?', '"', '<', '>', '|'
1818 BadPathName,1812 BadPathName,
...@@ -1913,8 +1907,6 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {...@@ -1913,8 +1907,6 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {
19131907
1914 error.AccessDenied,1908 error.AccessDenied,
1915 error.PermissionDenied,1909 error.PermissionDenied,
1916 error.InvalidUtf8,
1917 error.InvalidWtf8,
1918 error.SymLinkLoop,1910 error.SymLinkLoop,
1919 error.NameTooLong,1911 error.NameTooLong,
1920 error.SystemResources,1912 error.SystemResources,
...@@ -1999,8 +1991,6 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {...@@ -1999,8 +1991,6 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {
19991991
2000 error.AccessDenied,1992 error.AccessDenied,
2001 error.PermissionDenied,1993 error.PermissionDenied,
2002 error.InvalidUtf8,
2003 error.InvalidWtf8,
2004 error.SymLinkLoop,1994 error.SymLinkLoop,
2005 error.NameTooLong,1995 error.NameTooLong,
2006 error.SystemResources,1996 error.SystemResources,
...@@ -2112,8 +2102,6 @@ fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint...@@ -2112,8 +2102,6 @@ fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint
21122102
2113 error.AccessDenied,2103 error.AccessDenied,
2114 error.PermissionDenied,2104 error.PermissionDenied,
2115 error.InvalidUtf8,
2116 error.InvalidWtf8,
2117 error.SymLinkLoop,2105 error.SymLinkLoop,
2118 error.NameTooLong,2106 error.NameTooLong,
2119 error.SystemResources,2107 error.SystemResources,
...@@ -2201,8 +2189,6 @@ fn deleteTreeOpenInitialSubpath(self: Dir, sub_path: []const u8, kind_hint: File...@@ -2201,8 +2189,6 @@ fn deleteTreeOpenInitialSubpath(self: Dir, sub_path: []const u8, kind_hint: File
22012189
2202 error.AccessDenied,2190 error.AccessDenied,
2203 error.PermissionDenied,2191 error.PermissionDenied,
2204 error.InvalidUtf8,
2205 error.InvalidWtf8,
2206 error.SymLinkLoop,2192 error.SymLinkLoop,
2207 error.NameTooLong,2193 error.NameTooLong,
2208 error.SystemResources,2194 error.SystemResources,
lib/std/fs/test.zig+2-2
...@@ -2019,8 +2019,8 @@ test "delete a setAsCwd directory on Windows" {...@@ -2019,8 +2019,8 @@ test "delete a setAsCwd directory on Windows" {
20192019
2020test "invalid UTF-8/WTF-8 paths" {2020test "invalid UTF-8/WTF-8 paths" {
2021 const expected_err = switch (native_os) {2021 const expected_err = switch (native_os) {
2022 .wasi => error.InvalidUtf8,2022 .wasi => error.BadPathName,
2023 .windows => error.InvalidWtf8,2023 .windows => error.BadPathName,
2024 else => return error.SkipZigTest,2024 else => return error.SkipZigTest,
2025 };2025 };
20262026
lib/std/os.zig-3
...@@ -137,8 +137,6 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix....@@ -137,8 +137,6 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
137 switch (err) {137 switch (err) {
138 error.NotLink => unreachable,138 error.NotLink => unreachable,
139 error.BadPathName => unreachable,139 error.BadPathName => unreachable,
140 error.InvalidUtf8 => unreachable, // WASI-only
141 error.InvalidWtf8 => unreachable, // Windows-only
142 error.UnsupportedReparsePointType => unreachable, // Windows-only140 error.UnsupportedReparsePointType => unreachable, // Windows-only
143 error.NetworkNotFound => unreachable, // Windows-only141 error.NetworkNotFound => unreachable, // Windows-only
144 else => |e| return e,142 else => |e| return e,
...@@ -153,7 +151,6 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix....@@ -153,7 +151,6 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
153 const target = posix.readlinkZ(proc_path, out_buffer) catch |err| switch (err) {151 const target = posix.readlinkZ(proc_path, out_buffer) catch |err| switch (err) {
154 error.UnsupportedReparsePointType => unreachable,152 error.UnsupportedReparsePointType => unreachable,
155 error.NotLink => unreachable,153 error.NotLink => unreachable,
156 error.InvalidUtf8 => unreachable, // WASI-only
157 else => |e| return e,154 else => |e| return e,
158 };155 };
159 return target;156 return target;
lib/std/os/windows.zig+4-2
...@@ -2425,7 +2425,7 @@ pub fn normalizePath(comptime T: type, path: []T) RemoveDotDirsError!usize {...@@ -2425,7 +2425,7 @@ pub fn normalizePath(comptime T: type, path: []T) RemoveDotDirsError!usize {
2425 return prefix_len + try removeDotDirsSanitized(T, path[prefix_len..new_len]);2425 return prefix_len + try removeDotDirsSanitized(T, path[prefix_len..new_len]);
2426}2426}
24272427
2428pub const Wtf8ToPrefixedFileWError = error{InvalidWtf8} || Wtf16ToPrefixedFileWError;2428pub const Wtf8ToPrefixedFileWError = Wtf16ToPrefixedFileWError;
24292429
2430/// Same as `sliceToPrefixedFileW` but accepts a pointer2430/// Same as `sliceToPrefixedFileW` but accepts a pointer
2431/// to a null-terminated WTF-8 encoded path.2431/// to a null-terminated WTF-8 encoded path.
...@@ -2438,7 +2438,9 @@ pub fn cStrToPrefixedFileW(dir: ?HANDLE, s: [*:0]const u8) Wtf8ToPrefixedFileWEr...@@ -2438,7 +2438,9 @@ pub fn cStrToPrefixedFileW(dir: ?HANDLE, s: [*:0]const u8) Wtf8ToPrefixedFileWEr
2438/// https://wtf-8.codeberg.page/2438/// https://wtf-8.codeberg.page/
2439pub fn sliceToPrefixedFileW(dir: ?HANDLE, path: []const u8) Wtf8ToPrefixedFileWError!PathSpace {2439pub fn sliceToPrefixedFileW(dir: ?HANDLE, path: []const u8) Wtf8ToPrefixedFileWError!PathSpace {
2440 var temp_path: PathSpace = undefined;2440 var temp_path: PathSpace = undefined;
2441 temp_path.len = try std.unicode.wtf8ToWtf16Le(&temp_path.data, path);2441 temp_path.len = std.unicode.wtf8ToWtf16Le(&temp_path.data, path) catch |err| switch (err) {
2442 error.InvalidWtf8 => return error.BadPathName,
2443 };
2442 temp_path.data[temp_path.len] = 0;2444 temp_path.data[temp_path.len] = 0;
2443 return wToPrefixedFileW(dir, temp_path.span());2445 return wToPrefixedFileW(dir, temp_path.span());
2444}2446}
lib/std/posix.zig+23-47
...@@ -486,8 +486,8 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr...@@ -486,8 +486,8 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr
486 const stat = fstatatZ(pathfd, "", AT.EMPTY_PATH) catch |err| switch (err) {486 const stat = fstatatZ(pathfd, "", AT.EMPTY_PATH) catch |err| switch (err) {
487 error.NameTooLong => unreachable,487 error.NameTooLong => unreachable,
488 error.FileNotFound => unreachable,488 error.FileNotFound => unreachable,
489 error.InvalidUtf8 => unreachable,
490 error.Streaming => unreachable,489 error.Streaming => unreachable,
490 error.BadPathName => return error.Unexpected,
491 error.Canceled => return error.Canceled,491 error.Canceled => return error.Canceled,
492 else => |e| return e,492 else => |e| return e,
493 };493 };
...@@ -1914,14 +1914,9 @@ pub const SymLinkError = error{...@@ -1914,14 +1914,9 @@ pub const SymLinkError = error{
1914 ReadOnlyFileSystem,1914 ReadOnlyFileSystem,
1915 NotDir,1915 NotDir,
1916 NameTooLong,1916 NameTooLong,
19171917 /// WASI: file paths must be valid UTF-8.
1918 /// WASI-only; file paths must be valid UTF-8.1918 /// Windows: file paths provided by the user must be valid WTF-8.
1919 InvalidUtf8,
1920
1921 /// Windows-only; file paths provided by the user must be valid WTF-8.
1922 /// https://wtf-8.codeberg.page/1919 /// https://wtf-8.codeberg.page/
1923 InvalidWtf8,
1924
1925 BadPathName,1920 BadPathName,
1926} || UnexpectedError;1921} || UnexpectedError;
19271922
...@@ -2210,14 +2205,10 @@ pub const UnlinkError = error{...@@ -2210,14 +2205,10 @@ pub const UnlinkError = error{
2210 SystemResources,2205 SystemResources,
2211 ReadOnlyFileSystem,2206 ReadOnlyFileSystem,
22122207
2213 /// WASI-only; file paths must be valid UTF-8.2208 /// WASI: file paths must be valid UTF-8.
2214 InvalidUtf8,2209 /// Windows: file paths provided by the user must be valid WTF-8.
2215
2216 /// Windows-only; file paths provided by the user must be valid WTF-8.
2217 /// https://wtf-8.codeberg.page/2210 /// https://wtf-8.codeberg.page/
2218 InvalidWtf8,2211 /// Windows: file paths cannot contain these characters:
2219
2220 /// On Windows, file paths cannot contain these characters:
2221 /// '/', '*', '?', '"', '<', '>', '|'2212 /// '/', '*', '?', '"', '<', '>', '|'
2222 BadPathName,2213 BadPathName,
22232214
...@@ -2396,11 +2387,9 @@ pub const RenameError = error{...@@ -2396,11 +2387,9 @@ pub const RenameError = error{
2396 PathAlreadyExists,2387 PathAlreadyExists,
2397 ReadOnlyFileSystem,2388 ReadOnlyFileSystem,
2398 RenameAcrossMountPoints,2389 RenameAcrossMountPoints,
2399 /// WASI-only; file paths must be valid UTF-8.2390 /// WASI: file paths must be valid UTF-8.
2400 InvalidUtf8,2391 /// Windows: file paths provided by the user must be valid WTF-8.
2401 /// Windows-only; file paths provided by the user must be valid WTF-8.
2402 /// https://wtf-8.codeberg.page/2392 /// https://wtf-8.codeberg.page/
2403 InvalidWtf8,
2404 BadPathName,2393 BadPathName,
2405 NoDevice,2394 NoDevice,
2406 SharingViolation,2395 SharingViolation,
...@@ -2839,11 +2828,9 @@ pub const DeleteDirError = error{...@@ -2839,11 +2828,9 @@ pub const DeleteDirError = error{
2839 NotDir,2828 NotDir,
2840 DirNotEmpty,2829 DirNotEmpty,
2841 ReadOnlyFileSystem,2830 ReadOnlyFileSystem,
2842 /// WASI-only; file paths must be valid UTF-8.2831 /// WASI: file paths must be valid UTF-8.
2843 InvalidUtf8,2832 /// Windows: file paths provided by the user must be valid WTF-8.
2844 /// Windows-only; file paths provided by the user must be valid WTF-8.
2845 /// https://wtf-8.codeberg.page/2833 /// https://wtf-8.codeberg.page/
2846 InvalidWtf8,
2847 BadPathName,2834 BadPathName,
2848 /// On Windows, `\\server` or `\\server\share` was not found.2835 /// On Windows, `\\server` or `\\server\share` was not found.
2849 NetworkNotFound,2836 NetworkNotFound,
...@@ -2916,12 +2903,10 @@ pub const ChangeCurDirError = error{...@@ -2916,12 +2903,10 @@ pub const ChangeCurDirError = error{
2916 FileNotFound,2903 FileNotFound,
2917 SystemResources,2904 SystemResources,
2918 NotDir,2905 NotDir,
2919 BadPathName,2906 /// WASI: file paths must be valid UTF-8.
2920 /// WASI-only; file paths must be valid UTF-8.2907 /// Windows: file paths provided by the user must be valid WTF-8.
2921 InvalidUtf8,
2922 /// Windows-only; file paths provided by the user must be valid WTF-8.
2923 /// https://wtf-8.codeberg.page/2908 /// https://wtf-8.codeberg.page/
2924 InvalidWtf8,2909 BadPathName,
2925} || UnexpectedError;2910} || UnexpectedError;
29262911
2927/// Changes the current working directory of the calling process.2912/// Changes the current working directory of the calling process.
...@@ -2933,9 +2918,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {...@@ -2933,9 +2918,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
2933 @compileError("WASI does not support os.chdir");2918 @compileError("WASI does not support os.chdir");
2934 } else if (native_os == .windows) {2919 } else if (native_os == .windows) {
2935 var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;2920 var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;
2936 if (try std.unicode.checkWtf8ToWtf16LeOverflow(dir_path, &wtf16_dir_path)) {2921 try std.unicode.checkWtf8ToWtf16LeOverflow(dir_path, &wtf16_dir_path);
2937 return error.NameTooLong;
2938 }
2939 const len = try std.unicode.wtf8ToWtf16Le(&wtf16_dir_path, dir_path);2922 const len = try std.unicode.wtf8ToWtf16Le(&wtf16_dir_path, dir_path);
2940 return chdirW(wtf16_dir_path[0..len]);2923 return chdirW(wtf16_dir_path[0..len]);
2941 } else {2924 } else {
...@@ -2952,9 +2935,7 @@ pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {...@@ -2952,9 +2935,7 @@ pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
2952 if (native_os == .windows) {2935 if (native_os == .windows) {
2953 const dir_path_span = mem.span(dir_path);2936 const dir_path_span = mem.span(dir_path);
2954 var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;2937 var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;
2955 if (try std.unicode.checkWtf8ToWtf16LeOverflow(dir_path_span, &wtf16_dir_path)) {2938 try std.unicode.checkWtf8ToWtf16LeOverflow(dir_path_span, &wtf16_dir_path);
2956 return error.NameTooLong;
2957 }
2958 const len = try std.unicode.wtf8ToWtf16Le(&wtf16_dir_path, dir_path_span);2939 const len = try std.unicode.wtf8ToWtf16Le(&wtf16_dir_path, dir_path_span);
2959 return chdirW(wtf16_dir_path[0..len]);2940 return chdirW(wtf16_dir_path[0..len]);
2960 } else if (native_os == .wasi and !builtin.link_libc) {2941 } else if (native_os == .wasi and !builtin.link_libc) {
...@@ -3016,11 +2997,9 @@ pub const ReadLinkError = error{...@@ -3016,11 +2997,9 @@ pub const ReadLinkError = error{
3016 SystemResources,2997 SystemResources,
3017 NotLink,2998 NotLink,
3018 NotDir,2999 NotDir,
3019 /// WASI-only; file paths must be valid UTF-8.3000 /// WASI: file paths must be valid UTF-8.
3020 InvalidUtf8,3001 /// Windows: file paths provided by the user must be valid WTF-8.
3021 /// Windows-only; file paths provided by the user must be valid WTF-8.
3022 /// https://wtf-8.codeberg.page/3002 /// https://wtf-8.codeberg.page/
3023 InvalidWtf8,
3024 BadPathName,3003 BadPathName,
3025 /// Windows-only. This error may occur if the opened reparse point is3004 /// Windows-only. This error may occur if the opened reparse point is
3026 /// of unsupported type.3005 /// of unsupported type.
...@@ -4705,22 +4684,20 @@ pub const AccessError = error{...@@ -4705,22 +4684,20 @@ pub const AccessError = error{
4705 NameTooLong,4684 NameTooLong,
4706 InputOutput,4685 InputOutput,
4707 SystemResources,4686 SystemResources,
4708 BadPathName,
4709 FileBusy,4687 FileBusy,
4710 SymLinkLoop,4688 SymLinkLoop,
4711 ReadOnlyFileSystem,4689 ReadOnlyFileSystem,
4712 /// WASI-only; file paths must be valid UTF-8.4690 /// WASI: file paths must be valid UTF-8.
4713 InvalidUtf8,4691 /// Windows: file paths provided by the user must be valid WTF-8.
4714 /// Windows-only; file paths provided by the user must be valid WTF-8.
4715 /// https://wtf-8.codeberg.page/4692 /// https://wtf-8.codeberg.page/
4716 InvalidWtf8,4693 BadPathName,
4717 Canceled,4694 Canceled,
4718} || UnexpectedError;4695} || UnexpectedError;
47194696
4720/// check user's permissions for a file4697/// check user's permissions for a file
4721///4698///
4722/// * On Windows, asserts `path` is valid [WTF-8](https://wtf-8.codeberg.page/).4699/// * On Windows, asserts `path` is valid [WTF-8](https://wtf-8.codeberg.page/).
4723/// * On WASI, invalid UTF-8 passed to `path` causes `error.InvalidUtf8`.4700/// * On WASI, invalid UTF-8 passed to `path` causes `error.BadPathName`.
4724/// * On other platforms, `path` is an opaque sequence of bytes with no particular encoding.4701/// * On other platforms, `path` is an opaque sequence of bytes with no particular encoding.
4725///4702///
4726/// On Windows, `mode` is ignored. This is a POSIX API that is only partially supported by4703/// On Windows, `mode` is ignored. This is a POSIX API that is only partially supported by
...@@ -5154,16 +5131,15 @@ pub const RealPathError = error{...@@ -5154,16 +5131,15 @@ pub const RealPathError = error{
5154 SystemResources,5131 SystemResources,
5155 NoSpaceLeft,5132 NoSpaceLeft,
5156 FileSystem,5133 FileSystem,
5157 BadPathName,
5158 DeviceBusy,5134 DeviceBusy,
5159 ProcessNotFound,5135 ProcessNotFound,
51605136
5161 SharingViolation,5137 SharingViolation,
5162 PipeBusy,5138 PipeBusy,
51635139
5164 /// Windows-only; file paths provided by the user must be valid WTF-8.5140 /// Windows: file paths provided by the user must be valid WTF-8.
5165 /// https://wtf-8.codeberg.page/5141 /// https://wtf-8.codeberg.page/
5166 InvalidWtf8,5142 BadPathName,
51675143
5168 /// On Windows, `\\server` or `\\server\share` was not found.5144 /// On Windows, `\\server` or `\\server\share` was not found.
5169 NetworkNotFound,5145 NetworkNotFound,
lib/std/unicode.zig+7-6
...@@ -1809,27 +1809,28 @@ pub fn wtf8ToWtf16Le(wtf16le: []u16, wtf8: []const u8) error{InvalidWtf8}!usize...@@ -1809,27 +1809,28 @@ pub fn wtf8ToWtf16Le(wtf16le: []u16, wtf8: []const u8) error{InvalidWtf8}!usize
1809 return utf8ToUtf16LeImpl(wtf16le, wtf8, .can_encode_surrogate_half);1809 return utf8ToUtf16LeImpl(wtf16le, wtf8, .can_encode_surrogate_half);
1810}1810}
18111811
1812fn checkUtf8ToUtf16LeOverflowImpl(utf8: []const u8, utf16le: []const u16, comptime surrogates: Surrogates) !bool {1812fn checkUtf8ToUtf16LeOverflowImpl(utf8: []const u8, utf16le: []const u16, comptime surrogates: Surrogates) !void {
1813 // Each u8 in UTF-8/WTF-8 correlates to at most one u16 in UTF-16LE/WTF-16LE.1813 // Each u8 in UTF-8/WTF-8 correlates to at most one u16 in UTF-16LE/WTF-16LE.
1814 if (utf16le.len >= utf8.len) return false;1814 if (utf16le.len >= utf8.len) return;
1815 const utf16_len = calcUtf16LeLenImpl(utf8, surrogates) catch {1815 const utf16_len = calcUtf16LeLenImpl(utf8, surrogates) catch {
1816 return switch (surrogates) {1816 return switch (surrogates) {
1817 .cannot_encode_surrogate_half => error.InvalidUtf8,1817 .cannot_encode_surrogate_half => error.InvalidUtf8,
1818 .can_encode_surrogate_half => error.InvalidWtf8,1818 .can_encode_surrogate_half => error.InvalidWtf8,
1819 };1819 };
1820 };1820 };
1821 return utf16_len > utf16le.len;1821 if (utf16_len > utf16le.len)
1822 return error.NameTooLong;
1822}1823}
18231824
1824/// Checks if calling `utf8ToUtf16Le` would overflow. Might fail if utf8 is not1825/// Checks if calling `utf8ToUtf16Le` would overflow. Might fail if utf8 is not
1825/// valid UTF-8.1826/// valid UTF-8.
1826pub fn checkUtf8ToUtf16LeOverflow(utf8: []const u8, utf16le: []const u16) error{InvalidUtf8}!bool {1827pub fn checkUtf8ToUtf16LeOverflow(utf8: []const u8, utf16le: []const u16) error{ InvalidUtf8, NameTooLong }!void {
1827 return checkUtf8ToUtf16LeOverflowImpl(utf8, utf16le, .cannot_encode_surrogate_half);1828 return checkUtf8ToUtf16LeOverflowImpl(utf8, utf16le, .cannot_encode_surrogate_half);
1828}1829}
18291830
1830/// Checks if calling `utf8ToUtf16Le` would overflow. Might fail if wtf8 is not1831/// Checks if calling `utf8ToUtf16Le` would overflow. Might fail if wtf8 is not
1831/// valid WTF-8.1832/// valid WTF-8.
1832pub fn checkWtf8ToWtf16LeOverflow(wtf8: []const u8, wtf16le: []const u16) error{InvalidWtf8}!bool {1833pub fn checkWtf8ToWtf16LeOverflow(wtf8: []const u8, wtf16le: []const u16) error{ InvalidWtf8, NameTooLong }!void {
1833 return checkUtf8ToUtf16LeOverflowImpl(wtf8, wtf16le, .can_encode_surrogate_half);1834 return checkUtf8ToUtf16LeOverflowImpl(wtf8, wtf16le, .can_encode_surrogate_half);
1834}1835}
18351836
...@@ -2039,7 +2040,7 @@ fn testRoundtripWtf8(wtf8: []const u8) !void {...@@ -2039,7 +2040,7 @@ fn testRoundtripWtf8(wtf8: []const u8) !void {
2039 var wtf16_buf: [32]u16 = undefined;2040 var wtf16_buf: [32]u16 = undefined;
2040 const wtf16_len = try wtf8ToWtf16Le(&wtf16_buf, wtf8);2041 const wtf16_len = try wtf8ToWtf16Le(&wtf16_buf, wtf8);
2041 try testing.expectEqual(wtf16_len, calcWtf16LeLen(wtf8));2042 try testing.expectEqual(wtf16_len, calcWtf16LeLen(wtf8));
2042 try testing.expectEqual(false, checkWtf8ToWtf16LeOverflow(wtf8, &wtf16_buf));2043 try checkWtf8ToWtf16LeOverflow(wtf8, &wtf16_buf);
2043 const wtf16 = wtf16_buf[0..wtf16_len];2044 const wtf16 = wtf16_buf[0..wtf16_len];
20442045
2045 var roundtripped_buf: [32]u8 = undefined;2046 var roundtripped_buf: [32]u8 = undefined;
lib/std/zig/system.zig-2
...@@ -674,8 +674,6 @@ fn abiAndDynamicLinkerFromFile(...@@ -674,8 +674,6 @@ fn abiAndDynamicLinkerFromFile(
674 var link_buf: [posix.PATH_MAX]u8 = undefined;674 var link_buf: [posix.PATH_MAX]u8 = undefined;
675 const link_name = posix.readlink(dl_path, &link_buf) catch |err| switch (err) {675 const link_name = posix.readlink(dl_path, &link_buf) catch |err| switch (err) {
676 error.NameTooLong => unreachable,676 error.NameTooLong => unreachable,
677 error.InvalidUtf8 => unreachable, // WASI only
678 error.InvalidWtf8 => unreachable, // Windows only
679 error.BadPathName => unreachable, // Windows only677 error.BadPathName => unreachable, // Windows only
680 error.UnsupportedReparsePointType => unreachable, // Windows only678 error.UnsupportedReparsePointType => unreachable, // Windows only
681 error.NetworkNotFound => unreachable, // Windows only679 error.NetworkNotFound => unreachable, // Windows only