diff --git a/lib/std/os.zig b/lib/std/os.zig index f9c50adc06..75254b52c8 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2381,7 +2381,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { @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); - return readlinkW(file_path_w.span(), out_buffer); + return readlinkW(file_path_w.span().ptr, out_buffer); } else { const file_path_c = try toPosixPath(file_path); return readlinkZ(&file_path_c, out_buffer); @@ -2392,26 +2392,28 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); /// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded. /// See also `readlinkZ`. -pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 { - const handle = windows.ReadLink(file_path) catch |err| { +pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { + const w = windows; + const access_mode: w.DWORD = 0; + const sharing = w.FILE_SHARE_DELETE | w.FILE_SHARE_READ | w.FILE_SHARE_WRITE; + const disposition = w.OPEN_EXISTING; + const flags = w.FILE_FLAG_BACKUP_SEMANTICS | w.FILE_FLAG_OPEN_REPARSE_POINT; + const handle = w.CreateFileW(file_path, access_mode, sharing, null, disposition, flags, null) catch |err| { switch (err) { - error.IsDir => unreachable, - error.NoDevice => return error.FileNotFound, error.SharingViolation => return error.AccessDenied, - error.PipeBusy => unreachable, error.PathAlreadyExists => unreachable, - error.WouldBlock => unreachable, + error.PipeBusy => unreachable, else => |e| return e, } }; - var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; - _ = try windows.DeviceIoControl(handle, windows.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); - const reparse_struct = mem.bytesAsValue(windows._REPARSE_DATA_BUFFER, reparse_buf[0..@sizeOf(windows._REPARSE_DATA_BUFFER)]); + var reparse_buf: [w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; + _ = try w.DeviceIoControl(handle, w.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); + const reparse_struct = mem.bytesAsValue(w.REPARSE_DATA_BUFFER, reparse_buf[0..@sizeOf(w.REPARSE_DATA_BUFFER)]); switch (reparse_struct.ReparseTag) { - windows.IO_REPARSE_TAG_SYMLINK => { + w.IO_REPARSE_TAG_SYMLINK => { std.debug.warn("got symlink!", .{}); }, - windows.IO_REPARSE_TAG_MOUNT_POINT => { + w.IO_REPARSE_TAG_MOUNT_POINT => { std.debug.warn("got mount point!", .{}); }, else => |value| { @@ -2426,7 +2428,7 @@ pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 { 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); - return readlinkW(file_path_w.span(), out_buffer); + return readlinkW(file_path_w.span().ptr, out_buffer); } const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len); switch (errno(rc)) { diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 9fc0a123be..0a850a25c4 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1370,54 +1370,4 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError { std.debug.dumpCurrentStackTrace(null); } return error.Unexpected; -} - -pub fn ReadLink(path_w: []const u16) OpenError!HANDLE { - var result: HANDLE = undefined; - - const path_len_bytes = math.cast(u16, path_w.len * 2) catch |err| switch (err) { - error.Overflow => return error.NameTooLong, - }; - var nt_name = UNICODE_STRING{ - .Length = path_len_bytes, - .MaximumLength = path_len_bytes, - .Buffer = @intToPtr([*]u16, @ptrToInt(path_w.ptr)), - }; - var attr = OBJECT_ATTRIBUTES{ - .Length = @sizeOf(OBJECT_ATTRIBUTES), - .RootDirectory = null, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; - var io: IO_STATUS_BLOCK = undefined; - const rc = ntdll.NtCreateFile( - &result, - FILE_LIST_DIRECTORY, - &attr, - &io, - null, - FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ | FILE_SHARE_DELETE, - FILE_OPEN, - FILE_OPEN_REPARSE_POINT, - null, - 0, - ); - switch (rc) { - .SUCCESS => return result, - .OBJECT_NAME_INVALID => unreachable, - .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, - .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, - .NO_MEDIA_IN_DEVICE => return error.NoDevice, - .INVALID_PARAMETER => unreachable, - .SHARING_VIOLATION => return error.WouldBlock, - .ACCESS_DENIED => return error.AccessDenied, - .PIPE_BUSY => return error.PipeBusy, - .OBJECT_PATH_SYNTAX_BAD => unreachable, - .OBJECT_NAME_COLLISION => return error.PathAlreadyExists, - .FILE_IS_A_DIRECTORY => return error.IsDir, - else => return unexpectedStatus(rc), - } } \ No newline at end of file diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index 715a3cce7e..fef9af9bda 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -1543,7 +1543,7 @@ pub const LPOSVERSIONINFOW = *OSVERSIONINFOW; pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW; pub const PRTL_OSVERSIONINFOW = *RTL_OSVERSIONINFOW; -pub const _REPARSE_DATA_BUFFER = extern struct { +pub const REPARSE_DATA_BUFFER = extern struct { ReparseTag: ULONG, ReparseDataLength: USHORT, Reserved: USHORT, u: extern union { SymbolicLinkReparseBuffer: extern struct { SubstituteNameOffset: USHORT, @@ -1572,4 +1572,4 @@ pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003; pub const SYMBOLIC_LINK_FLAG_FILE: DWORD = 0x0; pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; -pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; \ No newline at end of file +pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;