mirror of
https://github.com/ziglang/zig.git
synced 2025-02-09 06:00:40 +00:00
Ensure we use Win32 prefix in Win32 calls
This commit is contained in:
parent
cc9c5c5b0e
commit
3ab5e6b1a9
@ -1556,8 +1556,8 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8, flags: Symlin
|
||||
@compileError("symlink is not supported in WASI; use symlinkat instead");
|
||||
}
|
||||
if (builtin.os.tag == .windows) {
|
||||
const target_path_w = try windows.sliceToPrefixedFileW(target_path);
|
||||
const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);
|
||||
const target_path_w = try windows.sliceToWin32PrefixedFileW(target_path);
|
||||
const sym_link_path_w = try windows.sliceToWin32PrefixedFileW(sym_link_path);
|
||||
return symlinkW(target_path_w.span().ptr, sym_link_path_w.span().ptr, flags);
|
||||
}
|
||||
const target_path_c = try toPosixPath(target_path);
|
||||
@ -1578,8 +1578,8 @@ pub fn symlinkW(target_path: [*:0]const u16, sym_link_path: [*:0]const u16, flag
|
||||
/// See also `symlink`.
|
||||
pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8, flags: SymlinkFlags) SymLinkError!void {
|
||||
if (builtin.os.tag == .windows) {
|
||||
const target_path_w = try windows.cStrToPrefixedFileW(target_path);
|
||||
const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
|
||||
const target_path_w = try windows.cStrToWin32PrefixedFileW(target_path);
|
||||
const sym_link_path_w = try windows.cStrToWin32PrefixedFileW(sym_link_path);
|
||||
return symlinkW(target_path_w.span().ptr, sym_link_path_w.span().ptr);
|
||||
}
|
||||
switch (errno(system.symlink(target_path, sym_link_path))) {
|
||||
@ -2382,7 +2382,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
|
||||
if (builtin.os.tag == .wasi) {
|
||||
@compileError("readlink is not supported in WASI; use readlinkat instead");
|
||||
} else if (builtin.os.tag == .windows) {
|
||||
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
|
||||
const file_path_w = try windows.sliceToWin32PrefixedFileW(file_path);
|
||||
return readlinkW(file_path_w.span().ptr, out_buffer);
|
||||
} else {
|
||||
const file_path_c = try toPosixPath(file_path);
|
||||
@ -2448,7 +2448,7 @@ fn parseReadlinkPath(path: []const u16, is_relative: bool, out_buffer: []u8) []u
|
||||
/// Same as `readlink` except `file_path` is null-terminated.
|
||||
pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
|
||||
if (builtin.os.tag == .windows) {
|
||||
const file_path_w = try windows.cStrToPrefixedFileW(file_path);
|
||||
const file_path_w = try windows.cStrToWin32PrefixedFileW(file_path);
|
||||
return readlinkW(file_path_w.span().ptr, out_buffer);
|
||||
}
|
||||
const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len);
|
||||
|
@ -80,8 +80,6 @@ test "readlink" {
|
||||
{
|
||||
const target_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "file.txt" });
|
||||
const symlink_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "symlink1" });
|
||||
std.debug.warn("\ntarget_path={}\n", .{target_path});
|
||||
std.debug.warn("symlink_path={}\n", .{symlink_path});
|
||||
|
||||
// Create symbolic link by path
|
||||
try os.symlink(target_path, symlink_path, .{ .is_directory = false });
|
||||
@ -90,8 +88,6 @@ test "readlink" {
|
||||
{
|
||||
const target_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "subdir" });
|
||||
const symlink_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "symlink2" });
|
||||
std.debug.warn("\ntarget_path={}\n", .{target_path});
|
||||
std.debug.warn("symlink_path={}\n", .{symlink_path});
|
||||
|
||||
// Create symbolic link by path
|
||||
try os.symlink(target_path, symlink_path, .{ .is_directory = true });
|
||||
@ -108,7 +104,6 @@ test "readlink" {
|
||||
fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void {
|
||||
var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
|
||||
const given = try os.readlink(symlink_path, buffer[0..]);
|
||||
std.debug.warn("given={}\n", .{given});
|
||||
expect(mem.eql(u8, target_path, given));
|
||||
}
|
||||
|
||||
|
@ -1263,40 +1263,80 @@ pub const PathSpace = struct {
|
||||
pub fn span(self: PathSpace) [:0]const u16 {
|
||||
return self.data[0..self.len :0];
|
||||
}
|
||||
|
||||
fn ensureNtStyle(self: *PathSpace) void {
|
||||
// > File I/O functions in the Windows API convert "/" to "\" as part of
|
||||
// > converting the name to an NT-style name, except when using the "\\?\"
|
||||
// > prefix as detailed in the following sections.
|
||||
// from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
|
||||
// Because we want the larger maximum path length for absolute paths, we
|
||||
// convert forward slashes to backward slashes here.
|
||||
for (self.data[0..self.len]) |*elem| {
|
||||
if (elem.* == '/') {
|
||||
elem.* = '\\';
|
||||
}
|
||||
}
|
||||
self.data[self.len] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// Same as `sliceToPrefixedFileW` but accepts a pointer
|
||||
/// to a null-terminated path.
|
||||
pub fn cStrToPrefixedFileW(s: [*:0]const u8) !PathSpace {
|
||||
return sliceToPrefixedFileW(mem.spanZ(s));
|
||||
}
|
||||
|
||||
/// Same as `sliceToWin32PrefixedFileW` but accepts a pointer
|
||||
/// to a null-terminated path.
|
||||
pub fn cStrToWin32PrefixedFileW(s: [*:0]const u8) !PathSpace {
|
||||
return sliceToWin32PrefixedFileW(mem.spanZ(s));
|
||||
}
|
||||
|
||||
/// Converts the path `s` to WTF16, null-terminated. If the path is absolute,
|
||||
/// it will get NT-style prefix `\??\` prepended automatically. For prepending
|
||||
/// Win32-style prefix, see `sliceToWin32PrefixedFileW` instead.
|
||||
pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace {
|
||||
// TODO https://github.com/ziglang/zig/issues/2765
|
||||
var path_space: PathSpace = undefined;
|
||||
for (s) |byte| {
|
||||
const prefix_index: usize = if (mem.startsWith(u8, s, "\\??\\")) 4 else 0;
|
||||
for (s[prefix_index..]) |byte| {
|
||||
switch (byte) {
|
||||
'*', '?', '"', '<', '>', '|' => return error.BadPathName,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
const start_index = if (mem.startsWith(u8, s, "\\?") or !std.fs.path.isAbsolute(s)) 0 else blk: {
|
||||
const start_index = if (prefix_index > 0 or !std.fs.path.isAbsolute(s)) 0 else blk: {
|
||||
const prefix = [_]u16{ '\\', '?', '?', '\\' };
|
||||
mem.copy(u16, path_space.data[0..], &prefix);
|
||||
break :blk prefix.len;
|
||||
};
|
||||
path_space.len = start_index + try std.unicode.utf8ToUtf16Le(path_space.data[start_index..], s);
|
||||
if (path_space.len > path_space.data.len) return error.NameTooLong;
|
||||
// > File I/O functions in the Windows API convert "/" to "\" as part of
|
||||
// > converting the name to an NT-style name, except when using the "\\?\"
|
||||
// > prefix as detailed in the following sections.
|
||||
// from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
|
||||
// Because we want the larger maximum path length for absolute paths, we
|
||||
// convert forward slashes to backward slashes here.
|
||||
for (path_space.data[0..path_space.len]) |*elem| {
|
||||
if (elem.* == '/') {
|
||||
elem.* = '\\';
|
||||
path_space.ensureNtStyle();
|
||||
return path_space;
|
||||
}
|
||||
|
||||
/// Converts the path `s` to WTF16, null-terminated. If the path is absolute,
|
||||
/// it will get Win32-style extended prefix `\\?\` prepended automatically. For prepending
|
||||
/// NT-style prefix, see `sliceToPrefixedFileW` instead.
|
||||
pub fn sliceToWin32PrefixedFileW(s: []const u8) !PathSpace {
|
||||
// TODO https://github.com/ziglang/zig/issues/2765
|
||||
var path_space: PathSpace = undefined;
|
||||
const prefix_index: usize = if (mem.startsWith(u8, s, "\\\\?\\")) 4 else 0;
|
||||
for (s[prefix_index..]) |byte| {
|
||||
switch (byte) {
|
||||
'*', '?', '"', '<', '>', '|' => return error.BadPathName,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
path_space.data[path_space.len] = 0;
|
||||
const start_index = if (prefix_index > 0 or !std.fs.path.isAbsolute(s)) 0 else blk: {
|
||||
const prefix = [_]u16{ '\\', '\\', '?', '\\' };
|
||||
mem.copy(u16, path_space.data[0..], &prefix);
|
||||
break :blk prefix.len;
|
||||
};
|
||||
path_space.len = start_index + try std.unicode.utf8ToUtf16Le(path_space.data[start_index..], s);
|
||||
if (path_space.len > path_space.data.len) return error.NameTooLong;
|
||||
path_space.ensureNtStyle();
|
||||
return path_space;
|
||||
}
|
||||
|
||||
@ -1313,12 +1353,7 @@ pub fn wToPrefixedFileW(s: []const u16) !PathSpace {
|
||||
path_space.len = start_index + s.len;
|
||||
if (path_space.len > path_space.data.len) return error.NameTooLong;
|
||||
mem.copy(u16, path_space.data[start_index..], s);
|
||||
for (path_space.data[0..path_space.len]) |*elem| {
|
||||
if (elem.* == '/') {
|
||||
elem.* = '\\';
|
||||
}
|
||||
}
|
||||
path_space.data[path_space.len] = 0;
|
||||
path_space.ensureNtStyle();
|
||||
return path_space;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user