authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-14 08:01:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-22 08:51:22+02:00
log9b00dc941bf641f171443d18466b5fc9cbcc882b
treed657f98a15696c1294f629fb7b22ac4fff167757
parent49b58153642bbff19ab976b70e329c5592fa1684

Use windows.CreateFileW to open the reparse point


3 files changed, 17 insertions(+), 65 deletions(-)

lib/std/os.zig+15-13
...@@ -2381,7 +2381,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {...@@ -2381,7 +2381,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
2381 @compileError("readlink is not supported in WASI; use readlinkat instead");2381 @compileError("readlink is not supported in WASI; use readlinkat instead");
2382 } else if (builtin.os.tag == .windows) {2382 } else if (builtin.os.tag == .windows) {
2383 const file_path_w = try windows.sliceToPrefixedFileW(file_path);2383 const file_path_w = try windows.sliceToPrefixedFileW(file_path);
2384 return readlinkW(file_path_w.span(), out_buffer);2384 return readlinkW(file_path_w.span().ptr, out_buffer);
2385 } else {2385 } else {
2386 const file_path_c = try toPosixPath(file_path);2386 const file_path_c = try toPosixPath(file_path);
2387 return readlinkZ(&file_path_c, out_buffer);2387 return readlinkZ(&file_path_c, out_buffer);
...@@ -2392,26 +2392,28 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ");...@@ -2392,26 +2392,28 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ");
23922392
2393/// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded.2393/// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded.
2394/// See also `readlinkZ`.2394/// See also `readlinkZ`.
2395pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 {2395pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {
2396 const handle = windows.ReadLink(file_path) catch |err| {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;
2399 const disposition = w.OPEN_EXISTING;
2400 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| {
2397 switch (err) {2402 switch (err) {
2398 error.IsDir => unreachable,
2399 error.NoDevice => return error.FileNotFound,
2400 error.SharingViolation => return error.AccessDenied,2403 error.SharingViolation => return error.AccessDenied,
2401 error.PipeBusy => unreachable,
2402 error.PathAlreadyExists => unreachable,2404 error.PathAlreadyExists => unreachable,
2403 error.WouldBlock => unreachable,2405 error.PipeBusy => unreachable,
2404 else => |e| return e,2406 else => |e| return e,
2405 }2407 }
2406 };2408 };
2407 var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;2409 var reparse_buf: [w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
2408 _ = try windows.DeviceIoControl(handle, windows.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null);2410 _ = try w.DeviceIoControl(handle, w.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null);
2409 const reparse_struct = mem.bytesAsValue(windows._REPARSE_DATA_BUFFER, reparse_buf[0..@sizeOf(windows._REPARSE_DATA_BUFFER)]);2411 const reparse_struct = mem.bytesAsValue(w.REPARSE_DATA_BUFFER, reparse_buf[0..@sizeOf(w.REPARSE_DATA_BUFFER)]);
2410 switch (reparse_struct.ReparseTag) {2412 switch (reparse_struct.ReparseTag) {
2411 windows.IO_REPARSE_TAG_SYMLINK => {2413 w.IO_REPARSE_TAG_SYMLINK => {
2412 std.debug.warn("got symlink!", .{});2414 std.debug.warn("got symlink!", .{});
2413 },2415 },
2414 windows.IO_REPARSE_TAG_MOUNT_POINT => {2416 w.IO_REPARSE_TAG_MOUNT_POINT => {
2415 std.debug.warn("got mount point!", .{});2417 std.debug.warn("got mount point!", .{});
2416 },2418 },
2417 else => |value| {2419 else => |value| {
...@@ -2426,7 +2428,7 @@ pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 {...@@ -2426,7 +2428,7 @@ pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 {
2426pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {2428pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
2427 if (builtin.os.tag == .windows) {2429 if (builtin.os.tag == .windows) {
2428 const file_path_w = try windows.cStrToPrefixedFileW(file_path);2430 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
2429 return readlinkW(file_path_w.span(), out_buffer);2431 return readlinkW(file_path_w.span().ptr, out_buffer);
2430 }2432 }
2431 const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len);2433 const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len);
2432 switch (errno(rc)) {2434 switch (errno(rc)) {
lib/std/os/windows.zig-50
...@@ -1370,54 +1370,4 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {...@@ -1370,54 +1370,4 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
1370 std.debug.dumpCurrentStackTrace(null);1370 std.debug.dumpCurrentStackTrace(null);
1371 }1371 }
1372 return error.Unexpected;1372 return error.Unexpected;
1373}
1374
1375pub fn ReadLink(path_w: []const u16) OpenError!HANDLE {
1376 var result: HANDLE = undefined;
1377
1378 const path_len_bytes = math.cast(u16, path_w.len * 2) catch |err| switch (err) {
1379 error.Overflow => return error.NameTooLong,
1380 };
1381 var nt_name = UNICODE_STRING{
1382 .Length = path_len_bytes,
1383 .MaximumLength = path_len_bytes,
1384 .Buffer = @intToPtr([*]u16, @ptrToInt(path_w.ptr)),
1385 };
1386 var attr = OBJECT_ATTRIBUTES{
1387 .Length = @sizeOf(OBJECT_ATTRIBUTES),
1388 .RootDirectory = null,
1389 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
1390 .ObjectName = &nt_name,
1391 .SecurityDescriptor = null,
1392 .SecurityQualityOfService = null,
1393 };
1394 var io: IO_STATUS_BLOCK = undefined;
1395 const rc = ntdll.NtCreateFile(
1396 &result,
1397 FILE_LIST_DIRECTORY,
1398 &attr,
1399 &io,
1400 null,
1401 FILE_ATTRIBUTE_NORMAL,
1402 FILE_SHARE_READ | FILE_SHARE_DELETE,
1403 FILE_OPEN,
1404 FILE_OPEN_REPARSE_POINT,
1405 null,
1406 0,
1407 );
1408 switch (rc) {
1409 .SUCCESS => return result,
1410 .OBJECT_NAME_INVALID => unreachable,
1411 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
1412 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
1413 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
1414 .INVALID_PARAMETER => unreachable,
1415 .SHARING_VIOLATION => return error.WouldBlock,
1416 .ACCESS_DENIED => return error.AccessDenied,
1417 .PIPE_BUSY => return error.PipeBusy,
1418 .OBJECT_PATH_SYNTAX_BAD => unreachable,
1419 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
1420 .FILE_IS_A_DIRECTORY => return error.IsDir,
1421 else => return unexpectedStatus(rc),
1422 }
1423}1373}
\ No newline at end of file
lib/std/os/windows/bits.zig+2-2
...@@ -1543,7 +1543,7 @@ pub const LPOSVERSIONINFOW = *OSVERSIONINFOW;...@@ -1543,7 +1543,7 @@ pub const LPOSVERSIONINFOW = *OSVERSIONINFOW;
1543pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW;1543pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW;
1544pub const PRTL_OSVERSIONINFOW = *RTL_OSVERSIONINFOW;1544pub const PRTL_OSVERSIONINFOW = *RTL_OSVERSIONINFOW;
15451545
1546pub const _REPARSE_DATA_BUFFER = extern struct {1546pub const REPARSE_DATA_BUFFER = extern struct {
1547 ReparseTag: ULONG, ReparseDataLength: USHORT, Reserved: USHORT, u: extern union {1547 ReparseTag: ULONG, ReparseDataLength: USHORT, Reserved: USHORT, u: extern union {
1548 SymbolicLinkReparseBuffer: extern struct {1548 SymbolicLinkReparseBuffer: extern struct {
1549 SubstituteNameOffset: USHORT,1549 SubstituteNameOffset: USHORT,
...@@ -1572,4 +1572,4 @@ pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;...@@ -1572,4 +1572,4 @@ pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;
15721572
1573pub const SYMBOLIC_LINK_FLAG_FILE: DWORD = 0x0;1573pub const SYMBOLIC_LINK_FLAG_FILE: DWORD = 0x0;
1574pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;1574pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
1575pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;
\ No newline at end of file
1575pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;