diff --git a/lib/std/os.zig b/lib/std/os.zig index 67b7dfe05b..eb033babfb 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1554,7 +1554,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError! 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); - return symlinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr); + return symlinkW(target_path_w.span().ptr, sym_link_path_w.span().ptr); } const target_path_c = try toPosixPath(target_path); const sym_link_path_c = try toPosixPath(sym_link_path); @@ -1578,7 +1578,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin 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); - return windows.CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, 0); + return symlinkW(target_path_w.span().ptr, sym_link_path_w.span().ptr); } switch (errno(system.symlink(target_path, sym_link_path))) { 0 => return, @@ -2394,8 +2394,9 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); /// See also `readlinkZ`. pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 { const handle = windows.OpenFile(file_path, .{ - .access_mask = 0, - .creation = windows.FILE_OPEN_REPARSE_POINT | windows.FILE_LIST_DIRECTORY, + .access_mask = windows.GENERIC_READ, + .creation = windows.FILE_OPEN, + .options = windows.FILE_OPEN_REPARSE_POINT, .io_mode = std.io.default_mode, }) catch |err| { switch (err) { diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index b3f0136cf6..eb2da384a6 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -45,7 +45,8 @@ test "readlink" { if (builtin.os.tag == .wasi) return error.SkipZigTest; var tmp = tmpDir(.{}); - defer tmp.cleanup(); + //defer tmp.cleanup(); + std.debug.print("tmp = {}\n", .{tmp.sub_path[0..]}); // create file try tmp.dir.writeFile("file.txt", "nonsense"); @@ -59,8 +60,8 @@ test "readlink" { const relative_path = try fs.path.join(&arena.allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..]}); break :blk try fs.realpathAlloc(&arena.allocator, relative_path); }; - const target_path = try fs.path.join(&arena.allocator, &[_][]const u8{"file.txt"}); - const symlink_path = try fs.path.join(&arena.allocator, &[_][]const u8{"symlinked"}); + const target_path = try fs.path.join(&arena.allocator, &[_][]const u8{base_path, "file.txt"}); + const symlink_path = try fs.path.join(&arena.allocator, &[_][]const u8{base_path, "symlinked"}); // create symbolic link by path try os.symlink(target_path, symlink_path); diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 5439bc0df9..049a2a8612 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -110,6 +110,7 @@ pub const OpenFileOptions = struct { share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, share_access_nonblocking: bool = false, creation: ULONG, + options: ?ULONG = null, io_mode: std.io.ModeOverride, }; @@ -145,7 +146,15 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN var delay: usize = 1; while (true) { - const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0; + var flags: ULONG = undefined; + if (options.options) |opt| { + flags = opt; + } else { + const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0; + flags = FILE_NON_DIRECTORY_FILE | blocking_flag; + } + // const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0; + // const flags = if (options.options) |opt| opt else FILE_NON_DIRECTORY_FILE; const rc = ntdll.NtCreateFile( &result, options.access_mask, @@ -155,7 +164,8 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN FILE_ATTRIBUTE_NORMAL, options.share_access, options.creation, - FILE_NON_DIRECTORY_FILE | blocking_flag, + // flags | blocking_flag, + flags, null, 0, ); @@ -601,7 +611,12 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 { return buffer[0..end_index]; } -pub const CreateSymbolicLinkError = error{AccessDenied, FileNotFound, Unexpected}; +pub const CreateSymbolicLinkError = error{ + AccessDenied, + PathAlreadyExists, + FileNotFound, + Unexpected +}; pub const CreateSymbolicLinkFlags = enum(DWORD) { File = SYMBOLIC_LINK_FLAG_FILE, @@ -638,6 +653,7 @@ pub fn CreateSymbolicLinkW( .FILE_NOT_FOUND => return error.FileNotFound, .PATH_NOT_FOUND => return error.FileNotFound, .ACCESS_DENIED => return error.AccessDenied, + .ALREADY_EXISTS => return error.PathAlreadyExists, else => |err| return unexpectedError(err), } } @@ -647,6 +663,7 @@ pub fn CreateSymbolicLinkW( .FILE_NOT_FOUND => return error.FileNotFound, .PATH_NOT_FOUND => return error.FileNotFound, .ACCESS_DENIED => return error.AccessDenied, + .ALREADY_EXISTS => return error.PathAlreadyExists, else => |err| return unexpectedError(err), } }