| ... | @@ -2355,6 +2355,8 @@ pub const ReadLinkError = error{ | ... | @@ -2355,6 +2355,8 @@ pub const ReadLinkError = error{ |
| 2355 | FileNotFound, | 2355 | FileNotFound, |
| 2356 | SystemResources, | 2356 | SystemResources, |
| 2357 | NotDir, | 2357 | NotDir, |
| | 2358 | InvalidUtf8, |
| | 2359 | BadPathName, |
| 2358 | /// Windows-only. | 2360 | /// Windows-only. |
| 2359 | UnsupportedSymlinkType, | 2361 | UnsupportedSymlinkType, |
| 2360 | } || UnexpectedError; | 2362 | } || UnexpectedError; |
| ... | @@ -2366,7 +2368,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { | ... | @@ -2366,7 +2368,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2366 | @compileError("readlink is not supported in WASI; use readlinkat instead"); | 2368 | @compileError("readlink is not supported in WASI; use readlinkat instead"); |
| 2367 | } else if (builtin.os.tag == .windows) { | 2369 | } else if (builtin.os.tag == .windows) { |
| 2368 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 2370 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); |
| 2369 | return readlinkW(file_path_w.span().ptr, out_buffer); | 2371 | return readlinkW(file_path_w.span(), out_buffer); |
| 2370 | } else { | 2372 | } else { |
| 2371 | const file_path_c = try toPosixPath(file_path); | 2373 | const file_path_c = try toPosixPath(file_path); |
| 2372 | return readlinkZ(&file_path_c, out_buffer); | 2374 | return readlinkZ(&file_path_c, out_buffer); |
| ... | @@ -2377,11 +2379,11 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); | ... | @@ -2377,11 +2379,11 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ"); |
| 2377 | | 2379 | |
| 2378 | /// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded. | 2380 | /// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded. |
| 2379 | /// See also `readlinkZ`. | 2381 | /// See also `readlinkZ`. |
| 2380 | pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 { | 2382 | pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 { |
| 2381 | const handle = windows.OpenFile(file_path, .{ | 2383 | const handle = windows.OpenFile(file_path, .{ |
| 2382 | .access_mask = 0, | 2384 | .access_mask = 0, |
| 2383 | .creation = c.FILE_OPEN_REPARSE_POINT | c.FILE_LIST_DIRECTORY, | 2385 | .creation = windows.FILE_OPEN_REPARSE_POINT | windows.FILE_LIST_DIRECTORY, |
| 2384 | .io_mode = 0, | 2386 | .io_mode = std.io.default_mode, |
| 2385 | }) catch |err| { | 2387 | }) catch |err| { |
| 2386 | switch (err) { | 2388 | switch (err) { |
| 2387 | error.IsDir => unreachable, | 2389 | error.IsDir => unreachable, |
| ... | @@ -2390,28 +2392,32 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 | ... | @@ -2390,28 +2392,32 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 |
| 2390 | error.PipeBusy => unreachable, | 2392 | error.PipeBusy => unreachable, |
| 2391 | error.PathAlreadyExists => unreachable, | 2393 | error.PathAlreadyExists => unreachable, |
| 2392 | error.WouldBlock => unreachable, | 2394 | error.WouldBlock => unreachable, |
| 2393 | else => return err, | 2395 | else => |e| return e, |
| 2394 | } | 2396 | } |
| 2395 | }; | 2397 | }; |
| 2396 | var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; | 2398 | var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; |
| 2397 | _ = try windows.DeviceIoControl(handle, windows.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); | 2399 | _ = try windows.DeviceIoControl(handle, windows.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null); |
| 2398 | const reparse_struct = @bitCast(windows._REPARSE_DATA_BUFFER, reparse_buf[0..@sizeOf(windows._REPARSE_DATA_BUFFER)]); | 2400 | const reparse_struct = mem.bytesAsValue(windows._REPARSE_DATA_BUFFER, reparse_buf[0..@sizeOf(windows._REPARSE_DATA_BUFFER)]); |
| 2399 | switch (reparse_struct.ReparseTag) { | 2401 | switch (reparse_struct.ReparseTag) { |
| 2400 | windows.IO_REPARSE_TAG_SYMLINK => {}, | 2402 | windows.IO_REPARSE_TAG_SYMLINK => { |
| 2401 | windows.IO_REPARSE_TAG_MOUNT_POINT => {}, | 2403 | std.debug.warn("got symlink!", .{}); |
| | 2404 | }, |
| | 2405 | windows.IO_REPARSE_TAG_MOUNT_POINT => { |
| | 2406 | std.debug.warn("got mount point!", .{}); |
| | 2407 | }, |
| 2402 | else => |value| { | 2408 | else => |value| { |
| 2403 | std.debug.print("unsupported symlink type: {}", value); | 2409 | std.debug.warn("unsupported symlink type: {}", .{value}); |
| 2404 | return error.UnsupportedSymlinkType; | 2410 | return error.UnsupportedSymlinkType; |
| 2405 | }, | 2411 | }, |
| 2406 | } | 2412 | } |
| 2407 | @compileError("TODO implement readlink for Windows"); | 2413 | @panic("Oh no!"); |
| 2408 | } | 2414 | } |
| 2409 | | 2415 | |
| 2410 | /// Same as `readlink` except `file_path` is null-terminated. | 2416 | /// Same as `readlink` except `file_path` is null-terminated. |
| 2411 | pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { | 2417 | pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 2412 | if (builtin.os.tag == .windows) { | 2418 | if (builtin.os.tag == .windows) { |
| 2413 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 2419 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); |
| 2414 | return readlinkW(file_path_w.span().ptr, out_buffer); | 2420 | return readlinkW(file_path_w.span(), out_buffer); |
| 2415 | } | 2421 | } |
| 2416 | const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len); | 2422 | const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len); |
| 2417 | switch (errno(rc)) { | 2423 | switch (errno(rc)) { |