From 57742480414b2060411b0b07f258e9187b4e8ca0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 28 Jan 2026 15:32:40 -0800 Subject: [PATCH] std.os.windows: delete unused CreateSymbolicLink --- lib/std/Io/Threaded.zig | 3 +- lib/std/os/windows.zig | 117 ---------------------------------------- 2 files changed, 1 insertion(+), 119 deletions(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 38f6199f464933112ae6987e13852585805e0428..16608c50a9bdbca1a73817642705f9420b162cfa 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -6353,8 +6353,7 @@ fn dirSymLinkWindows( // Target path does not use sliceToPrefixedFileW because certain paths // are handled differently when creating a symlink than they would be - // when converting to an NT namespaced path. CreateSymbolicLink in - // symLinkW will handle the necessary conversion. + // when converting to an NT namespaced path. var target_path_w: w.PathSpace = undefined; target_path_w.len = try w.wtf8ToWtf16Le(&target_path_w.data, target_path); target_path_w.data[target_path_w.len] = 0; diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 262eaef049a0a6cb198b70195ad85f8356916346..7414ec060876b4b837d05dbc15fba9345b66a9fa 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -2908,123 +2908,6 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 { return buffer[0..end_index]; } -pub const CreateSymbolicLinkError = error{ - AccessDenied, - PathAlreadyExists, - FileNotFound, - NameTooLong, - NoDevice, - NetworkNotFound, - BadPathName, - Unexpected, -}; - -/// Needs either: -/// - `SeCreateSymbolicLinkPrivilege` privilege -/// or -/// - Developer mode on Windows 10 -/// otherwise fails with `error.AccessDenied`. In which case `sym_link_path` may still -/// be created on the file system but will lack reparse processing data applied to it. -pub fn CreateSymbolicLink( - dir: ?HANDLE, - sym_link_path: []const u16, - target_path: [:0]const u16, - is_directory: bool, -) CreateSymbolicLinkError!void { - const SYMLINK_DATA = extern struct { - ReparseTag: IO_REPARSE_TAG, - ReparseDataLength: USHORT, - Reserved: USHORT, - SubstituteNameOffset: USHORT, - SubstituteNameLength: USHORT, - PrintNameOffset: USHORT, - PrintNameLength: USHORT, - Flags: ULONG, - }; - - const symlink_handle = OpenFile(sym_link_path, .{ - .access_mask = .{ - .STANDARD = .{ .SYNCHRONIZE = true }, - .GENERIC = .{ .WRITE = true, .READ = true }, - }, - .dir = dir, - .creation = .CREATE, - .filter = if (is_directory) .dir_only else .non_directory_only, - }) catch |err| switch (err) { - error.IsDir => return error.PathAlreadyExists, - error.NotDir => return error.Unexpected, - error.WouldBlock => return error.Unexpected, - error.PipeBusy => return error.Unexpected, - error.NoDevice => return error.Unexpected, - error.AntivirusInterference => return error.Unexpected, - else => |e| return e, - }; - defer CloseHandle(symlink_handle); - - // Relevant portions of the documentation: - // > Relative links are specified using the following conventions: - // > - Root relative—for example, "\Windows\System32" resolves to "current drive:\Windows\System32". - // > - Current working directory–relative—for example, if the current working directory is - // > C:\Windows\System32, "C:File.txt" resolves to "C:\Windows\System32\File.txt". - // > Note: If you specify a current working directory–relative link, it is created as an absolute - // > link, due to the way the current working directory is processed based on the user and the thread. - // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw - var is_target_absolute = false; - const final_target_path = target_path: { - if (hasCommonNtPrefix(u16, target_path)) { - // Already an NT path, no need to do anything to it - break :target_path target_path; - } else { - switch (std.fs.path.getWin32PathType(u16, target_path)) { - // Rooted paths need to avoid getting put through wToPrefixedFileW - // (and they are treated as relative in this context) - // Note: It seems that rooted paths in symbolic links are relative to - // the drive that the symbolic exists on, not to the CWD's drive. - // So, if the symlink is on C:\ and the CWD is on D:\, - // it will still resolve the path relative to the root of - // the C:\ drive. - .rooted => break :target_path target_path, - // Keep relative paths relative, but anything else needs to get NT-prefixed. - else => if (!std.fs.path.isAbsoluteWindowsWtf16(target_path)) - break :target_path target_path, - } - } - var prefixed_target_path = try wToPrefixedFileW(dir, target_path); - // We do this after prefixing to ensure that drive-relative paths are treated as absolute - is_target_absolute = std.fs.path.isAbsoluteWindowsWtf16(prefixed_target_path.span()); - break :target_path prefixed_target_path.span(); - }; - - // prepare reparse data buffer - var buffer: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; - const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4; - const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2; - const target_is_absolute = std.fs.path.isAbsoluteWindowsWtf16(final_target_path); - const symlink_data: SYMLINK_DATA = .{ - .ReparseTag = .SYMLINK, - .ReparseDataLength = @intCast(buf_len - header_len), - .Reserved = 0, - .SubstituteNameOffset = @intCast(final_target_path.len * 2), - .SubstituteNameLength = @intCast(final_target_path.len * 2), - .PrintNameOffset = 0, - .PrintNameLength = @intCast(final_target_path.len * 2), - .Flags = if (!target_is_absolute) SYMLINK_FLAG_RELATIVE else 0, - }; - - @memcpy(buffer[0..@sizeOf(SYMLINK_DATA)], std.mem.asBytes(&symlink_data)); - @memcpy(buffer[@sizeOf(SYMLINK_DATA)..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); - const paths_start = @sizeOf(SYMLINK_DATA) + final_target_path.len * 2; - @memcpy(buffer[paths_start..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); - const rc = DeviceIoControl(symlink_handle, FSCTL.SET_REPARSE_POINT, .{ .in = buffer[0..buf_len] }); - switch (rc) { - .SUCCESS => {}, - .PRIVILEGE_NOT_HELD => return error.AccessDenied, - .ACCESS_DENIED => return error.AccessDenied, - .INVALID_DEVICE_REQUEST => return error.AccessDenied, // Not supported by the underlying filesystem - else => return unexpectedStatus(rc), - } -} - pub const ReadLinkError = error{ FileNotFound, NetworkNotFound, -- 2.54.0