authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-21 00:08:48+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-22 08:51:23+02:00
logc53bcd027f4522753d2f27c80e69c36980f3f754
tree178760b4a25e8d2391ec07548112cbd64f076de0
parent2c9c13f624a48e6a22ae84b236eb131c24ba2eb4

Start drafting CreateSymbolicLink using ntdll syscalls


2 files changed, 47 insertions(+), 0 deletions(-)

lib/std/os/windows.zig+46
...@@ -604,6 +604,52 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 {...@@ -604,6 +604,52 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 {
604604
605pub const CreateSymbolicLinkError = error{ AccessDenied, PathAlreadyExists, FileNotFound, NameTooLong, InvalidUtf8, BadPathName, Unexpected };605pub const CreateSymbolicLinkError = error{ AccessDenied, PathAlreadyExists, FileNotFound, NameTooLong, InvalidUtf8, BadPathName, Unexpected };
606606
607pub fn NtCreateSymbolicLinkW(dir: ?HANDLE, sym_link_path: []const u16, target_path: []const u16) CreateSymbolicLinkError!void {
608 const SYMLINK_DATA = extern struct {
609 ReparseTag: ULONG,
610 ReparseDataLength: USHORT,
611 Reserved: USHORT,
612 SubstituteNameOffset: USHORT,
613 SubstituteNameLength: USHORT,
614 PrintNameOffset: USHORT,
615 PrintNameLength: USHORT,
616 Flags: ULONG,
617 };
618
619 const symlink_handle = OpenFile(sym_link_path, .{
620 .access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
621 .dir = dir,
622 .creation = FILE_CREATE,
623 .io_mode = .blocking,
624 }) catch |err| switch (err) {
625 error.IsDir => unreachable, // TODO
626 else => |e| unreachable,
627 };
628 defer CloseHandle(symlink_handle);
629
630 // prepare reparse data buffer
631 var buffer: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
632 const buf_len = @sizeOf(SYMLINK_DATA) + target_path.len * 4;
633 const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2;
634 const symlink_data = SYMLINK_DATA{
635 .ReparseTag = IO_REPARSE_TAG_SYMLINK,
636 .ReparseDataLength = @intCast(u16, buf_len - header_len),
637 .Reserved = 0,
638 .SubstituteNameOffset = @intCast(u16, target_path.len * 2),
639 .SubstituteNameLength = @intCast(u16, target_path.len * 2),
640 .PrintNameOffset = 0,
641 .PrintNameLength = @intCast(u16, target_path.len * 2),
642 .Flags = if (dir) |_| SYMLINK_FLAG_RELATIVE else 0,
643 };
644
645 std.mem.copy(u8, buffer[0..], std.mem.asBytes(&symlink_data));
646 @memcpy(buffer[@sizeOf(SYMLINK_DATA)..], @ptrCast([*]const u8, target_path), target_path.len * 2);
647 const paths_start = @sizeOf(SYMLINK_DATA) + target_path.len * 2;
648 @memcpy(buffer[paths_start..].ptr, @ptrCast([*]const u8, target_path), target_path.len * 2);
649 // TODO replace with NtDeviceIoControl
650 _ = try DeviceIoControl(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null, null);
651}
652
607pub fn CreateSymbolicLink(653pub fn CreateSymbolicLink(
608 sym_link_path: []const u8,654 sym_link_path: []const u8,
609 target_path: []const u8,655 target_path: []const u8,
lib/std/os/windows/bits.zig+1
...@@ -1565,6 +1565,7 @@ pub const MOUNT_POINT_REPARSE_BUFFER = extern struct {...@@ -1565,6 +1565,7 @@ pub const MOUNT_POINT_REPARSE_BUFFER = extern struct {
1565 PathBuffer: [1]WCHAR,1565 PathBuffer: [1]WCHAR,
1566};1566};
1567pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;1567pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;
1568pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
1568pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;1569pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
1569pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c;1570pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c;
1570pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;1571pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;