| ... | @@ -2394,11 +2394,10 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); | ... | @@ -2394,11 +2394,10 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); |
| 2394 | /// See also `readlinkZ`. | 2394 | /// See also `readlinkZ`. |
| 2395 | pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { | 2395 | pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { |
| 2396 | const w = windows; | 2396 | const w = windows; |
| 2397 | const access_mode: w.DWORD = 0; | | |
| 2398 | const sharing = w.FILE_SHARE_DELETE | w.FILE_SHARE_READ | w.FILE_SHARE_WRITE; | 2397 | const sharing = w.FILE_SHARE_DELETE | w.FILE_SHARE_READ | w.FILE_SHARE_WRITE; |
| 2399 | const disposition = w.OPEN_EXISTING; | 2398 | const disposition = w.OPEN_EXISTING; |
| 2400 | const flags = w.FILE_FLAG_BACKUP_SEMANTICS | w.FILE_FLAG_OPEN_REPARSE_POINT; | 2399 | const flags = w.FILE_FLAG_BACKUP_SEMANTICS | w.FILE_FLAG_OPEN_REPARSE_POINT; |
| 2401 | const handle = w.CreateFileW(file_path, access_mode, sharing, null, disposition, flags, null) catch |err| { | 2400 | const handle = w.CreateFileW(file_path, 0, sharing, null, disposition, flags, null) catch |err| { |
| 2402 | switch (err) { | 2401 | switch (err) { |
| 2403 | error.SharingViolation => return error.AccessDenied, | 2402 | error.SharingViolation => return error.AccessDenied, |
| 2404 | error.PathAlreadyExists => unreachable, | 2403 | error.PathAlreadyExists => unreachable, |
| ... | @@ -2406,22 +2405,31 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 | ... | @@ -2406,22 +2405,31 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 |
| 2406 | else => |e| return e, | 2405 | else => |e| return e, |
| 2407 | } | 2406 | } |
| 2408 | }; | 2407 | }; |
| 2409 | var reparse_buf: [w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; | 2408 | var reparse_buf align(@alignOf(w.REPARSE_DATA_BUFFER)) = [_]u8{0} ** (w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE); |
| 2410 | _ = try w.DeviceIoControl(handle, w.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); | 2409 | _ = try w.DeviceIoControl(handle, w.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); |
| 2411 | const reparse_struct = mem.bytesAsValue(w.REPARSE_DATA_BUFFER, reparse_buf[0..@sizeOf(w.REPARSE_DATA_BUFFER)]); | 2410 | const reparse_struct = @ptrCast(*const w.REPARSE_DATA_BUFFER, &reparse_buf[0]); |
| 2412 | switch (reparse_struct.ReparseTag) { | 2411 | switch (reparse_struct.ReparseTag) { |
| 2413 | w.IO_REPARSE_TAG_SYMLINK => { | 2412 | w.IO_REPARSE_TAG_SYMLINK => { |
| 2414 | std.debug.warn("got symlink!", .{}); | 2413 | const alignment = @alignOf(w.SymbolicLinkReparseBuffer); |
| | 2414 | const buf = @ptrCast(*const w.SymbolicLinkReparseBuffer, @alignCast(alignment, &reparse_struct.DataBuffer[0])); |
| | 2415 | const offset = buf.SubstituteNameOffset / 2; |
| | 2416 | const len = buf.SubstituteNameLength / 2; |
| | 2417 | const f = buf.Flags; |
| | 2418 | const path_buf = @as([*]const u16, &buf.PathBuffer); |
| | 2419 | std.debug.warn("got symlink => offset={}, len={}, flags = {}, {}\n", .{ offset, len, f, w.SYMLINK_FLAG_RELATIVE }); |
| | 2420 | // TODO handle absolute paths and namespace prefix |
| | 2421 | const out_len = std.unicode.utf16leToUtf8(out_buffer, path_buf[offset .. offset + len]) catch unreachable; |
| | 2422 | std.debug.warn("got symlink => utf8={}\n", .{out_buffer[0..out_len]}); |
| | 2423 | return out_buffer[0..out_len]; |
| 2415 | }, | 2424 | }, |
| 2416 | w.IO_REPARSE_TAG_MOUNT_POINT => { | 2425 | w.IO_REPARSE_TAG_MOUNT_POINT => { |
| 2417 | std.debug.warn("got mount point!", .{}); | 2426 | @panic("TODO parse mount point"); |
| 2418 | }, | 2427 | }, |
| 2419 | else => |value| { | 2428 | else => |value| { |
| 2420 | std.debug.warn("unsupported symlink type: {}", .{value}); | 2429 | std.debug.warn("unsupported symlink type: {}", .{value}); |
| 2421 | return error.UnsupportedSymlinkType; | 2430 | return error.UnsupportedSymlinkType; |
| 2422 | }, | 2431 | }, |
| 2423 | } | 2432 | } |
| 2424 | @panic("Oh no!"); | | |
| 2425 | } | 2433 | } |
| 2426 | | 2434 | |
| 2427 | /// Same as `readlink` except `file_path` is null-terminated. | 2435 | /// Same as `readlink` except `file_path` is null-terminated. |