| 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 | 31 | pub const realpath = posix.realpath; |
| 32 | 32 | pub const realpathZ = posix.realpathZ; |
| 33 | 33 | pub const realpathW = posix.realpathW; |
| 34 | pub const realpathW2 = posix.realpathW2; | |
| 34 | 35 | |
| 35 | 36 | pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir; |
| 36 | 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 | 643 | // If ImagePathName is a symlink, then it will contain the path of the |
| 643 | 644 | // symlink, not the path that the symlink points to. We want the path |
| 644 | 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 | return std.fs.cwd().realpathW(pathname_w.span(), out_buffer) catch |err| switch (err) { | |
| 646 | var pathname_w = try windows.wToPrefixedFileW(null, image_path_name); | |
| 647 | ||
| 648 | const wide_slice = std.fs.cwd().realpathW2(pathname_w.span(), &pathname_w.data) catch |err| switch (err) { | |
| 647 | 649 | error.InvalidWtf8 => unreachable, |
| 648 | 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 | 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 | 1369 | @compileError("realpath is not available on WASI"); |
| 1370 | 1370 | } |
| 1371 | 1371 | if (native_os == .windows) { |
| 1372 | const pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname); | |
| 1373 | return self.realpathW(pathname_w.span(), out_buffer); | |
| 1372 | var pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname); | |
| 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 | 1383 | const pathname_c = try posix.toPosixPath(pathname); |
| 1376 | 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 | 1388 | /// See also `Dir.realpath`, `realpathZ`. |
| 1381 | 1389 | pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathError![]u8 { |
| 1382 | 1390 | if (native_os == .windows) { |
| 1383 | const pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname); | |
| 1384 | return self.realpathW(pathname_w.span(), out_buffer); | |
| 1391 | var pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname); | |
| 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 | 1403 | var flags: posix.O = .{}; |
| ... | ... | @@ -1410,10 +1426,34 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathE |
| 1410 | 1426 | return result; |
| 1411 | 1427 | } |
| 1412 | 1428 | |
| 1429 | /// Deprecated: use `realpathW2`. | |
| 1430 | /// | |
| 1413 | 1431 | /// Windows-only. Same as `Dir.realpath` except `pathname` is WTF16 LE encoded. |
| 1414 | 1432 | /// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). |
| 1415 | 1433 | /// See also `Dir.realpath`, `realpathW`. |
| 1416 | 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 | 1457 | const w = windows; |
| 1418 | 1458 | |
| 1419 | 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 | 1474 | }; |
| 1435 | 1475 | defer w.CloseHandle(h_file); |
| 1436 | 1476 | |
| 1437 | var wide_buf: [w.PATH_MAX_WIDE]u16 = undefined; | |
| 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]; | |
| 1477 | return w.GetFinalPathNameByHandle(h_file, .{}, out_buffer); | |
| 1444 | 1478 | } |
| 1445 | 1479 | |
| 1446 | 1480 | pub const RealPathAllocError = RealPathError || Allocator.Error; |
lib/std/posix.zig+23-25| ... | ... | @@ -5675,8 +5675,12 @@ pub const RealPathError = error{ |
| 5675 | 5675 | /// Calling this function is usually a bug. |
| 5676 | 5676 | pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { |
| 5677 | 5677 | if (native_os == .windows) { |
| 5678 | const pathname_w = try windows.sliceToPrefixedFileW(null, pathname); | |
| 5679 | return realpathW(pathname_w.span(), out_buffer); | |
| 5678 | var pathname_w = try windows.sliceToPrefixedFileW(null, pathname); | |
| 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 | 5684 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 5681 | 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 | 5693 | /// Calling this function is usually a bug. |
| 5690 | 5694 | pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { |
| 5691 | 5695 | if (native_os == .windows) { |
| 5692 | const pathname_w = try windows.cStrToPrefixedFileW(null, pathname); | |
| 5693 | return realpathW(pathname_w.span(), out_buffer); | |
| 5696 | var pathname_w = try windows.cStrToPrefixedFileW(null, pathname); | |
| 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 | 5702 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 5695 | 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 | 5742 | return mem.sliceTo(result_path, 0); |
| 5735 | 5743 | } |
| 5736 | 5744 | |
| 5745 | /// Deprecated: use `realpathW2`. | |
| 5746 | /// | |
| 5737 | 5747 | /// Same as `realpath` except `pathname` is WTF16LE-encoded. |
| 5738 | 5748 | /// |
| 5739 | 5749 | /// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/). |
| 5740 | 5750 | /// |
| 5741 | 5751 | /// Calling this function is usually a bug. |
| 5742 | 5752 | pub fn realpathW(pathname: []const u16, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 { |
| 5743 | const w = windows; | |
| 5744 | ||
| 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); | |
| 5753 | return fs.cwd().realpathW(pathname, out_buffer); | |
| 5754 | } | |
| 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 | 5765 | /// Spurious wakeups are possible and no precision of timing is guaranteed. |