mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
Merge pull request #23657 from mpfaff/realpathW-no-convert
Return WTF-16 from W-suffixed functions instead of converting to WTF-8
This commit is contained in:
commit
0bdd1b5274
@ -31,6 +31,7 @@ pub const wasi = @import("fs/wasi.zig");
|
||||
pub const realpath = posix.realpath;
|
||||
pub const realpathZ = posix.realpathZ;
|
||||
pub const realpathW = posix.realpathW;
|
||||
pub const realpathW2 = posix.realpathW2;
|
||||
|
||||
pub const getAppDataDir = @import("fs/get_app_data_dir.zig").getAppDataDir;
|
||||
pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirError;
|
||||
@ -642,11 +643,19 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
|
||||
// If ImagePathName is a symlink, then it will contain the path of the
|
||||
// symlink, not the path that the symlink points to. We want the path
|
||||
// that the symlink points to, though, so we need to get the realpath.
|
||||
const pathname_w = try windows.wToPrefixedFileW(null, image_path_name);
|
||||
return std.fs.cwd().realpathW(pathname_w.span(), out_buffer) catch |err| switch (err) {
|
||||
var pathname_w = try windows.wToPrefixedFileW(null, image_path_name);
|
||||
|
||||
const wide_slice = std.fs.cwd().realpathW2(pathname_w.span(), &pathname_w.data) catch |err| switch (err) {
|
||||
error.InvalidWtf8 => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
const len = std.unicode.calcWtf8Len(wide_slice);
|
||||
if (len > out_buffer.len)
|
||||
return error.NameTooLong;
|
||||
|
||||
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
|
||||
return out_buffer[0..end_index];
|
||||
},
|
||||
else => @compileError("std.fs.selfExePath not supported for this target"),
|
||||
}
|
||||
|
||||
@ -1369,8 +1369,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError
|
||||
@compileError("realpath is not available on WASI");
|
||||
}
|
||||
if (native_os == .windows) {
|
||||
const pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname);
|
||||
return self.realpathW(pathname_w.span(), out_buffer);
|
||||
var pathname_w = try windows.sliceToPrefixedFileW(self.fd, pathname);
|
||||
|
||||
const wide_slice = try self.realpathW2(pathname_w.span(), &pathname_w.data);
|
||||
|
||||
const len = std.unicode.calcWtf8Len(wide_slice);
|
||||
if (len > out_buffer.len)
|
||||
return error.NameTooLong;
|
||||
|
||||
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
|
||||
return out_buffer[0..end_index];
|
||||
}
|
||||
const pathname_c = try posix.toPosixPath(pathname);
|
||||
return self.realpathZ(&pathname_c, out_buffer);
|
||||
@ -1380,8 +1388,16 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError
|
||||
/// See also `Dir.realpath`, `realpathZ`.
|
||||
pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathError![]u8 {
|
||||
if (native_os == .windows) {
|
||||
const pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname);
|
||||
return self.realpathW(pathname_w.span(), out_buffer);
|
||||
var pathname_w = try windows.cStrToPrefixedFileW(self.fd, pathname);
|
||||
|
||||
const wide_slice = try self.realpathW2(pathname_w.span(), &pathname_w.data);
|
||||
|
||||
const len = std.unicode.calcWtf8Len(wide_slice);
|
||||
if (len > out_buffer.len)
|
||||
return error.NameTooLong;
|
||||
|
||||
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
|
||||
return out_buffer[0..end_index];
|
||||
}
|
||||
|
||||
var flags: posix.O = .{};
|
||||
@ -1410,10 +1426,34 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathE
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Deprecated: use `realpathW2`.
|
||||
///
|
||||
/// Windows-only. Same as `Dir.realpath` except `pathname` is WTF16 LE encoded.
|
||||
/// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
|
||||
/// See also `Dir.realpath`, `realpathW`.
|
||||
pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathError![]u8 {
|
||||
var wide_buf: [std.os.windows.PATH_MAX_WIDE]u16 = undefined;
|
||||
|
||||
const wide_slice = try self.realpathW2(pathname, &wide_buf);
|
||||
|
||||
var big_out_buf: [fs.max_path_bytes]u8 = undefined;
|
||||
const end_index = std.unicode.wtf16LeToWtf8(&big_out_buf, wide_slice);
|
||||
if (end_index > out_buffer.len)
|
||||
return error.NameTooLong;
|
||||
const result = out_buffer[0..end_index];
|
||||
@memcpy(result, big_out_buf[0..end_index]);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Windows-only. Same as `Dir.realpath` except
|
||||
/// * `pathname` and the result are WTF-16 LE encoded
|
||||
/// * `pathname` is relative or has the NT namespace prefix. See `windows.wToPrefixedFileW` for details.
|
||||
///
|
||||
/// Additionally, `pathname` will never be accessed after `out_buffer` has been written to, so it
|
||||
/// is safe to reuse a single buffer for both.
|
||||
///
|
||||
/// See also `Dir.realpath`, `realpathW`.
|
||||
pub fn realpathW2(self: Dir, pathname: []const u16, out_buffer: []u16) RealPathError![]u16 {
|
||||
const w = windows;
|
||||
|
||||
const access_mask = w.GENERIC_READ | w.SYNCHRONIZE;
|
||||
@ -1434,13 +1474,7 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathErr
|
||||
};
|
||||
defer w.CloseHandle(h_file);
|
||||
|
||||
var wide_buf: [w.PATH_MAX_WIDE]u16 = undefined;
|
||||
const wide_slice = try w.GetFinalPathNameByHandle(h_file, .{}, &wide_buf);
|
||||
const len = std.unicode.calcWtf8Len(wide_slice);
|
||||
if (len > out_buffer.len)
|
||||
return error.NameTooLong;
|
||||
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
|
||||
return out_buffer[0..end_index];
|
||||
return w.GetFinalPathNameByHandle(h_file, .{}, out_buffer);
|
||||
}
|
||||
|
||||
pub const RealPathAllocError = RealPathError || Allocator.Error;
|
||||
|
||||
@ -5675,8 +5675,12 @@ pub const RealPathError = error{
|
||||
/// Calling this function is usually a bug.
|
||||
pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 {
|
||||
if (native_os == .windows) {
|
||||
const pathname_w = try windows.sliceToPrefixedFileW(null, pathname);
|
||||
return realpathW(pathname_w.span(), out_buffer);
|
||||
var pathname_w = try windows.sliceToPrefixedFileW(null, pathname);
|
||||
|
||||
const wide_slice = try realpathW2(pathname_w.span(), &pathname_w.data);
|
||||
|
||||
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
|
||||
return out_buffer[0..end_index];
|
||||
} else if (native_os == .wasi and !builtin.link_libc) {
|
||||
@compileError("WASI does not support os.realpath");
|
||||
}
|
||||
@ -5689,8 +5693,12 @@ pub fn realpath(pathname: []const u8, out_buffer: *[max_path_bytes]u8) RealPathE
|
||||
/// Calling this function is usually a bug.
|
||||
pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 {
|
||||
if (native_os == .windows) {
|
||||
const pathname_w = try windows.cStrToPrefixedFileW(null, pathname);
|
||||
return realpathW(pathname_w.span(), out_buffer);
|
||||
var pathname_w = try windows.cStrToPrefixedFileW(null, pathname);
|
||||
|
||||
const wide_slice = try realpathW2(pathname_w.span(), &pathname_w.data);
|
||||
|
||||
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
|
||||
return out_buffer[0..end_index];
|
||||
} else if (native_os == .wasi and !builtin.link_libc) {
|
||||
return realpath(mem.sliceTo(pathname, 0), out_buffer);
|
||||
}
|
||||
@ -5734,34 +5742,24 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[max_path_bytes]u8) RealP
|
||||
return mem.sliceTo(result_path, 0);
|
||||
}
|
||||
|
||||
/// Deprecated: use `realpathW2`.
|
||||
///
|
||||
/// Same as `realpath` except `pathname` is WTF16LE-encoded.
|
||||
///
|
||||
/// The result is encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
|
||||
///
|
||||
/// Calling this function is usually a bug.
|
||||
pub fn realpathW(pathname: []const u16, out_buffer: *[max_path_bytes]u8) RealPathError![]u8 {
|
||||
const w = windows;
|
||||
return fs.cwd().realpathW(pathname, out_buffer);
|
||||
}
|
||||
|
||||
const dir = fs.cwd().fd;
|
||||
const access_mask = w.GENERIC_READ | w.SYNCHRONIZE;
|
||||
const share_access = w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE;
|
||||
const creation = w.FILE_OPEN;
|
||||
const h_file = blk: {
|
||||
const res = w.OpenFile(pathname, .{
|
||||
.dir = dir,
|
||||
.access_mask = access_mask,
|
||||
.share_access = share_access,
|
||||
.creation = creation,
|
||||
.filter = .any,
|
||||
}) catch |err| switch (err) {
|
||||
error.WouldBlock => unreachable,
|
||||
else => |e| return e,
|
||||
};
|
||||
break :blk res;
|
||||
};
|
||||
defer w.CloseHandle(h_file);
|
||||
|
||||
return std.os.getFdPath(h_file, out_buffer);
|
||||
/// Same as `realpath` except `pathname` is WTF16LE-encoded.
|
||||
///
|
||||
/// The result is encoded as WTF16LE.
|
||||
///
|
||||
/// Calling this function is usually a bug.
|
||||
pub fn realpathW2(pathname: []const u16, out_buffer: *[std.os.windows.PATH_MAX_WIDE]u16) RealPathError![]u16 {
|
||||
return fs.cwd().realpathW2(pathname, out_buffer);
|
||||
}
|
||||
|
||||
/// Spurious wakeups are possible and no precision of timing is guaranteed.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user