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 {
23812381 @compileError("readlink is not supported in WASI; use readlinkat instead");
23822382 } else if (builtin.os.tag == .windows) {
23832383 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);
23852385 } else {
23862386 const file_path_c = try toPosixPath(file_path);
23872387 return readlinkZ(&file_path_c, out_buffer);
......@@ -2392,26 +2392,28 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ");
23922392
23932393/// Windows-only. Same as `readlink` except `file_path` is null-terminated, WTF16 encoded.
23942394/// See also `readlinkZ`.
2395pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 {
2396 const handle = windows.ReadLink(file_path) catch |err| {
2395pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {
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| {
23972402 switch (err) {
2398 error.IsDir => unreachable,
2399 error.NoDevice => return error.FileNotFound,
24002403 error.SharingViolation => return error.AccessDenied,
2401 error.PipeBusy => unreachable,
24022404 error.PathAlreadyExists => unreachable,
2403 error.WouldBlock => unreachable,
2405 error.PipeBusy => unreachable,
24042406 else => |e| return e,
24052407 }
24062408 };
2407 var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
2408 _ = try windows.DeviceIoControl(handle, windows.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)]);
2409 var reparse_buf: [w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
2410 _ = 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)]);
24102412 switch (reparse_struct.ReparseTag) {
2411 windows.IO_REPARSE_TAG_SYMLINK => {
2413 w.IO_REPARSE_TAG_SYMLINK => {
24122414 std.debug.warn("got symlink!", .{});
24132415 },
2414 windows.IO_REPARSE_TAG_MOUNT_POINT => {
2416 w.IO_REPARSE_TAG_MOUNT_POINT => {
24152417 std.debug.warn("got mount point!", .{});
24162418 },
24172419 else => |value| {
......@@ -2426,7 +2428,7 @@ pub fn readlinkW(file_path: []const u16, out_buffer: []u8) ReadLinkError![]u8 {
24262428pub fn readlinkZ(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
24272429 if (builtin.os.tag == .windows) {
24282430 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);
24302432 }
24312433 const rc = system.readlink(file_path, out_buffer.ptr, out_buffer.len);
24322434 switch (errno(rc)) {
lib/std/os/windows.zig-50
......@@ -1370,54 +1370,4 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
13701370 std.debug.dumpCurrentStackTrace(null);
13711371 }
13721372 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 }
14231373}
\ No newline at end of file
lib/std/os/windows/bits.zig+2-2
......@@ -1543,7 +1543,7 @@ pub const LPOSVERSIONINFOW = *OSVERSIONINFOW;
15431543pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW;
15441544pub const PRTL_OSVERSIONINFOW = *RTL_OSVERSIONINFOW;
15451545
1546pub const _REPARSE_DATA_BUFFER = extern struct {
1546pub const REPARSE_DATA_BUFFER = extern struct {
15471547 ReparseTag: ULONG, ReparseDataLength: USHORT, Reserved: USHORT, u: extern union {
15481548 SymbolicLinkReparseBuffer: extern struct {
15491549 SubstituteNameOffset: USHORT,
......@@ -1572,4 +1572,4 @@ pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;
15721572
15731573pub const SYMBOLIC_LINK_FLAG_FILE: DWORD = 0x0;
15741574pub 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;