Skip to content

Commit f2227ae

Browse files
mpfaffsqueek502
authored andcommitted
Return WTF16LE encoded path from realpathW
1 parent 328ae41 commit f2227ae

File tree

3 files changed

+48
-38
lines changed

3 files changed

+48
-38
lines changed

lib/std/fs.zig

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,10 +643,19 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
643643
// symlink, not the path that the symlink points to. We want the path
644644
// that the symlink points to, though, so we need to get the realpath.
645645
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+
647+
var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;
648+
const wide_slice = std.fs.cwd().realpathW(pathname_w.span(), &wide_buf) catch |err| switch (err) {
647649
error.InvalidWtf8 => unreachable,
648650
else => |e| return e,
649651
};
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];
650659
},
651660
else => @compileError("std.fs.selfExePath not supported for this target"),
652661
}

lib/std/fs/Dir.zig

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError
13701370
}
13711371
if (native_os == .windows) {
13721372
const pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname);
1373-
return self.realpathW(pathname_w.span(), out_buffer);
1373+
1374+
var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;
1375+
const wide_slice = try self.realpathW(pathname_w.span(), &wide_buf);
1376+
1377+
const len = std.unicode.calcWtf8Len(wide_slice);
1378+
if (len > out_buffer.len)
1379+
return error.NameTooLong;
1380+
1381+
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
1382+
return out_buffer[0..end_index];
13741383
}
13751384
const pathname_c = try posix.toPosixPath(pathname);
13761385
return self.realpathZ(&pathname_c, out_buffer);
@@ -1381,7 +1390,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError
13811390
pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathError![]u8 {
13821391
if (native_os == .windows) {
13831392
const pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname);
1384-
return self.realpathW(pathname_w.span(), out_buffer);
1393+
1394+
var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;
1395+
const wide_slice = try self.realpathW(pathname_w.span(), &wide_buf);
1396+
1397+
const len = std.unicode.calcWtf8Len(wide_slice);
1398+
if (len > out_buffer.len)
1399+
return error.NameTooLong;
1400+
1401+
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
1402+
return out_buffer[0..end_index];
13851403
}
13861404

13871405
var flags: posix.O = .{};
@@ -1411,9 +1429,9 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathE
14111429
}
14121430

14131431
/// 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 WTF16 LE.
14151433
/// 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: []u16) RealPathError![]u16 {
14171435
const w = windows;
14181436

14191437
const access_mask = w.GENERIC_READ | w.SYNCHRONIZE;
@@ -1434,13 +1452,7 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathErr
14341452
};
14351453
defer w.CloseHandle(h_file);
14361454

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];
1455+
return w.GetFinalPathNameByHandle(h_file, .{}, out_buffer);
14441456
}
14451457

14461458
pub const RealPathAllocError = RealPathError || Allocator.Error;

lib/std/posix.zig

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5676,7 +5676,12 @@ pub const RealPathError = error{
56765676
pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 {
56775677
if (native_os == .windows) {
56785678
const pathname_w = try windows.sliceToPrefixedFileW(null, pathname);
5679-
return realpathW(pathname_w.span(), out_buffer);
5679+
5680+
var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;
5681+
const wide_slice = try realpathW(pathname_w.span(), &wide_buf);
5682+
5683+
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
5684+
return out_buffer[0..end_index];
56805685
} else if (native_os == .wasi and !builtin.link_libc) {
56815686
@compileError("WASI does not support os.realpath");
56825687
}
@@ -5690,7 +5695,12 @@ pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathE
56905695
pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 {
56915696
if (native_os == .windows) {
56925697
const pathname_w = try windows.cStrToPrefixedFileW(null, pathname);
5693-
return realpathW(pathname_w.span(), out_buffer);
5698+
5699+
var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;
5700+
const wide_slice = try realpathW(pathname_w.span(), &wide_buf);
5701+
5702+
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
5703+
return out_buffer[0..end_index];
56945704
} else if (native_os == .wasi and !builtin.link_libc) {
56955705
return realpath(mem.sliceTo(pathname, 0), out_buffer);
56965706
}
@@ -5736,32 +5746,11 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealP
57365746

57375747
/// Same as `realpath` except `pathname` is WTF16LE-encoded.
57385748
///
5739-
/// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
5749+
/// The result is encoded as WTF16LE.
57405750
///
57415751
/// Calling this function is usually a bug.
5742-
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);
5763-
5764-
return std.os.getFdPath(h_file, out_buffer);
5752+
pub fn realpathW(pathname: []const u16, out_buffer: *[max_path_bytes]u16) RealPathError![]u16 {
5753+
return fs.cwd().realpathW(pathname, out_buffer);
57655754
}
57665755

57675756
/// Spurious wakeups are possible and no precision of timing is guaranteed.

0 commit comments

Comments
 (0)