| author | |
| committer | |
| log | 0bdd1b5274ceb6ca4145fc880a3d78276801c3fe |
| tree | 0df4edc19cd18e44d78bbd7c20fe2fdf8031dd78 |
| parent | 328ae41468f3514251ac1b0726c41eca9fbc3fb5 |
| parent | 7bf740ee718f4b6109cd9fe7014d1784d48ada48 |
| signature |
Return WTF-16 from W-suffixed functions instead of converting to WTF-83 files changed, 79 insertions(+), 38 deletions(-)
lib/std/fs.zig+11-2| ... | @@ -31,6 +31,7 @@ pub const wasi = @import("fs/wasi.zig"); | ... | @@ -31,6 +31,7 @@ pub const wasi = @import("fs/wasi.zig"); |
| 31 | pub const realpath = posix.realpath; | 31 | pub const realpath = posix.realpath; |
| 32 | pub const realpathZ = posix.realpathZ; | 32 | pub const realpathZ = posix.realpathZ; |
| 33 | pub const realpathW = posix.realpathW; | 33 | pub const realpathW = posix.realpathW; |
| 34 | pub const realpathW2 = posix.realpathW2; | ||
| 34 | 35 | ||
| 35 | pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir; | 36 | pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir; |
| 36 | pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirError; | 37 | pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirError; |
| ... | @@ -642,11 +643,19 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 { | ... | @@ -642,11 +643,19 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 { |
| 642 | // If ImagePathName is a symlink, then it will contain the path of the | 643 | // If ImagePathName is a symlink, then it will contain the path of the |
| 643 | // symlink, not the path that the symlink points to. We want the path | 644 | // symlink, not the path that the symlink points to. We want the path |
| 644 | // that the symlink points to, though, so we need to get the realpath. | 645 | // that the symlink points to, though, so we need to get the realpath. |
| 645 | const pathname_w = try windows.wToPrefixedFileW(null, image_path_name); | 646 | var pathname_w = try windows.wToPrefixedFileW(null, image_path_name); |
| 646 | return std.fs.cwd().realpathW(pathname_w.span(), out_buffer) catch |err| switch (err) { | 647 | |
| 648 | const wide_slice = std.fs.cwd().realpathW2(pathname_w.span(), &pathname_w.data) catch |err| switch (err) { | ||
| 647 | error.InvalidWtf8 => unreachable, | 649 | error.InvalidWtf8 => unreachable, |
| 648 | else => |e| return e, | 650 | else => |e| return e, |
| 649 | }; | 651 | }; |
| 652 | |||
| 653 | const len = std.unicode.calcWtf8Len(wide_slice); | ||
| 654 | if (len > out_buffer.len) | ||
| 655 | return error.NameTooLong; | ||
| 656 | |||
| 657 | const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); | ||
| 658 | return out_buffer[0..end_index]; | ||
| 650 | }, | 659 | }, |
| 651 | else => @compileError("std.fs.selfExePath not supported for this target"), | 660 | else => @compileError("std.fs.selfExePath not supported for this target"), |
| 652 | } | 661 | } |
lib/std/fs/Dir.zig+45-11| ... | @@ -1369,8 +1369,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError | ... | @@ -1369,8 +1369,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError |
| 1369 | @compileError("realpath is not available on WASI"); | 1369 | @compileError("realpath is not available on WASI"); |
| 1370 | } | 1370 | } |
| 1371 | if (native_os == .windows) { | 1371 | if (native_os == .windows) { |
| 1372 | const pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname); | 1372 | var pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname); |
| 1373 | return self.realpathW(pathname_w.span(), out_buffer); | 1373 | |
| 1374 | const wide_slice = try self.realpathW2(pathname_w.span(), &pathname_w.data); | ||
| 1375 | |||
| 1376 | const len = std.unicode.calcWtf8Len(wide_slice); | ||
| 1377 | if (len > out_buffer.len) | ||
| 1378 | return error.NameTooLong; | ||
| 1379 | |||
| 1380 | const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); | ||
| 1381 | return out_buffer[0..end_index]; | ||
| 1374 | } | 1382 | } |
| 1375 | const pathname_c = try posix.toPosixPath(pathname); | 1383 | const pathname_c = try posix.toPosixPath(pathname); |
| 1376 | return self.realpathZ(&pathname_c, out_buffer); | 1384 | return self.realpathZ(&pathname_c, out_buffer); |
| ... | @@ -1380,8 +1388,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError | ... | @@ -1380,8 +1388,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError |
| 1380 | /// See also `Dir.realpath`, `realpathZ`. | 1388 | /// See also `Dir.realpath`, `realpathZ`. |
| 1381 | pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathError![]u8 { | 1389 | pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathError![]u8 { |
| 1382 | if (native_os == .windows) { | 1390 | if (native_os == .windows) { |
| 1383 | const pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname); | 1391 | var pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname); |
| 1384 | return self.realpathW(pathname_w.span(), out_buffer); | 1392 | |
| 1393 | const wide_slice = try self.realpathW2(pathname_w.span(), &pathname_w.data); | ||
| 1394 | |||
| 1395 | const len = std.unicode.calcWtf8Len(wide_slice); | ||
| 1396 | if (len > out_buffer.len) | ||
| 1397 | return error.NameTooLong; | ||
| 1398 | |||
| 1399 | const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); | ||
| 1400 | return out_buffer[0..end_index]; | ||
| 1385 | } | 1401 | } |
| 1386 | 1402 | ||
| 1387 | var flags: posix.O = .{}; | 1403 | var flags: posix.O = .{}; |
| ... | @@ -1410,10 +1426,34 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathE | ... | @@ -1410,10 +1426,34 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathE |
| 1410 | return result; | 1426 | return result; |
| 1411 | } | 1427 | } |
| 1412 | 1428 | ||
| 1429 | /// Deprecated: use `realpathW2`. | ||
| 1430 | /// | ||
| 1413 | /// Windows-only. Same as `Dir.realpath` except `pathname` is WTF16 LE encoded. | 1431 | /// Windows-only. Same as `Dir.realpath` except `pathname` is WTF16 LE encoded. |
| 1414 | /// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). | 1432 | /// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). |
| 1415 | /// See also `Dir.realpath`, `realpathW`. | 1433 | /// See also `Dir.realpath`, `realpathW`. |
| 1416 | pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathError![]u8 { | 1434 | pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathError![]u8 { |
| 1435 | var wide_buf: [std.os.windows.PATH_MAX_WIDE]u16 = undefined; | ||
| 1436 | |||
| 1437 | const wide_slice = try self.realpathW2(pathname, &wide_buf); | ||
| 1438 | |||
| 1439 | var big_out_buf: [fs.max_path_bytes]u8 = undefined; | ||
| 1440 | const end_index = std.unicode.wtf16LeToWtf8(&big_out_buf, wide_slice); | ||
| 1441 | if (end_index > out_buffer.len) | ||
| 1442 | return error.NameTooLong; | ||
| 1443 | const result = out_buffer[0..end_index]; | ||
| 1444 | @memcpy(result, big_out_buf[0..end_index]); | ||
| 1445 | return result; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | /// Windows-only. Same as `Dir.realpath` except | ||
| 1449 | /// * `pathname` and the result are WTF-16 LE encoded | ||
| 1450 | /// * `pathname` is relative or has the NT namespace prefix. See `windows.wToPrefixedFileW` for details. | ||
| 1451 | /// | ||
| 1452 | /// Additionally, `pathname` will never be accessed after `out_buffer` has been written to, so it | ||
| 1453 | /// is safe to reuse a single buffer for both. | ||
| 1454 | /// | ||
| 1455 | /// See also `Dir.realpath`, `realpathW`. | ||
| 1456 | pub fn realpathW2(self: Dir, pathname: []const u16, out_buffer: []u16) RealPathError![]u16 { | ||
| 1417 | const w = windows; | 1457 | const w = windows; |
| 1418 | 1458 | ||
| 1419 | const access_mask = w.GENERIC_READ | w.SYNCHRONIZE; | 1459 | const access_mask = w.GENERIC_READ | w.SYNCHRONIZE; |
| ... | @@ -1434,13 +1474,7 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathErr | ... | @@ -1434,13 +1474,7 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathErr |
| 1434 | }; | 1474 | }; |
| 1435 | defer w.CloseHandle(h_file); | 1475 | defer w.CloseHandle(h_file); |
| 1436 | 1476 | ||
| 1437 | var wide_buf: [w.PATH_MAX_WIDE]u16 = undefined; | 1477 | return w.GetFinalPathNameByHandle(h_file, .{}, out_buffer); |
| 1438 | const wide_slice = try w.GetFinalPathNameByHandle(h_file, .{}, &wide_buf); | ||
| 1439 | const len = std.unicode.calcWtf8Len(wide_slice); | ||
| 1440 | if (len > out_buffer.len) | ||
| 1441 | return error.NameTooLong; | ||
| 1442 | const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); | ||
| 1443 | return out_buffer[0..end_index]; | ||
| 1444 | } | 1478 | } |
| 1445 | 1479 | ||
| 1446 | pub const RealPathAllocError = RealPathError || Allocator.Error; | 1480 | pub const RealPathAllocError = RealPathError || Allocator.Error; |
lib/std/posix.zig+23-25| ... | @@ -5675,8 +5675,12 @@ pub const RealPathError = error{ | ... | @@ -5675,8 +5675,12 @@ pub const RealPathError = error{ |
| 5675 | /// Calling this function is usually a bug. | 5675 | /// Calling this function is usually a bug. |
| 5676 | pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { | 5676 | pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { |
| 5677 | if (native_os == .windows) { | 5677 | if (native_os == .windows) { |
| 5678 | const pathname_w = try windows.sliceToPrefixedFileW(null, pathname); | 5678 | var pathname_w = try windows.sliceToPrefixedFileW(null, pathname); |
| 5679 | return realpathW(pathname_w.span(), out_buffer); | 5679 | |
| 5680 | const wide_slice = try realpathW2(pathname_w.span(), &pathname_w.data); | ||
| 5681 | |||
| 5682 | const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); | ||
| 5683 | return out_buffer[0..end_index]; | ||
| 5680 | } else if (native_os == .wasi and !builtin.link_libc) { | 5684 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 5681 | @compileError("WASI does not support os.realpath"); | 5685 | @compileError("WASI does not support os.realpath"); |
| 5682 | } | 5686 | } |
| ... | @@ -5689,8 +5693,12 @@ pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathE | ... | @@ -5689,8 +5693,12 @@ pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathE |
| 5689 | /// Calling this function is usually a bug. | 5693 | /// Calling this function is usually a bug. |
| 5690 | pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { | 5694 | pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { |
| 5691 | if (native_os == .windows) { | 5695 | if (native_os == .windows) { |
| 5692 | const pathname_w = try windows.cStrToPrefixedFileW(null, pathname); | 5696 | var pathname_w = try windows.cStrToPrefixedFileW(null, pathname); |
| 5693 | return realpathW(pathname_w.span(), out_buffer); | 5697 | |
| 5698 | const wide_slice = try realpathW2(pathname_w.span(), &pathname_w.data); | ||
| 5699 | |||
| 5700 | const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice); | ||
| 5701 | return out_buffer[0..end_index]; | ||
| 5694 | } else if (native_os == .wasi and !builtin.link_libc) { | 5702 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 5695 | return realpath(mem.sliceTo(pathname, 0), out_buffer); | 5703 | return realpath(mem.sliceTo(pathname, 0), out_buffer); |
| 5696 | } | 5704 | } |
| ... | @@ -5734,34 +5742,24 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealP | ... | @@ -5734,34 +5742,24 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealP |
| 5734 | return mem.sliceTo(result_path, 0); | 5742 | return mem.sliceTo(result_path, 0); |
| 5735 | } | 5743 | } |
| 5736 | 5744 | ||
| 5745 | /// Deprecated: use `realpathW2`. | ||
| 5746 | /// | ||
| 5737 | /// Same as `realpath` except `pathname` is WTF16LE-encoded. | 5747 | /// Same as `realpath` except `pathname` is WTF16LE-encoded. |
| 5738 | /// | 5748 | /// |
| 5739 | /// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). | 5749 | /// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). |
| 5740 | /// | 5750 | /// |
| 5741 | /// Calling this function is usually a bug. | 5751 | /// Calling this function is usually a bug. |
| 5742 | pub fn realpathW(pathname: []const u16, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { | 5752 | pub fn realpathW(pathname: []const u16, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { |
| 5743 | const w = windows; | 5753 | return fs.cwd().realpathW(pathname, out_buffer); |
| 5744 | 5754 | } | |
| 5745 | const dir = fs.cwd().fd; | ||
| 5746 | const access_mask = w.GENERIC_READ | w.SYNCHRONIZE; | ||
| 5747 | const share_access = w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE; | ||
| 5748 | const creation = w.FILE_OPEN; | ||
| 5749 | const h_file = blk: { | ||
| 5750 | const res = w.OpenFile(pathname, .{ | ||
| 5751 | .dir = dir, | ||
| 5752 | .access_mask = access_mask, | ||
| 5753 | .share_access = share_access, | ||
| 5754 | .creation = creation, | ||
| 5755 | .filter = .any, | ||
| 5756 | }) catch |err| switch (err) { | ||
| 5757 | error.WouldBlock => unreachable, | ||
| 5758 | else => |e| return e, | ||
| 5759 | }; | ||
| 5760 | break :blk res; | ||
| 5761 | }; | ||
| 5762 | defer w.CloseHandle(h_file); | ||
| 5763 | 5755 | ||
| 5764 | return std.os.getFdPath(h_file, out_buffer); | 5756 | /// Same as `realpath` except `pathname` is WTF16LE-encoded. |
| 5757 | /// | ||
| 5758 | /// The result is encoded as WTF16LE. | ||
| 5759 | /// | ||
| 5760 | /// Calling this function is usually a bug. | ||
| 5761 | pub fn realpathW2(pathname: []const u16, out_buffer: *[std.os.windows.PATH_MAX_WIDE]u16) RealPathError![]u16 { | ||
| 5762 | return fs.cwd().realpathW2(pathname, out_buffer); | ||
| 5765 | } | 5763 | } |
| 5766 | 5764 | ||
| 5767 | /// Spurious wakeups are possible and no precision of timing is guaranteed. | 5765 | /// Spurious wakeups are possible and no precision of timing is guaranteed. |