mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
Start drafting CreateSymbolicLink using ntdll syscalls
This commit is contained in:
parent
2c9c13f624
commit
c53bcd027f
@ -604,6 +604,52 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 {
|
|||||||
|
|
||||||
pub const CreateSymbolicLinkError = error{ AccessDenied, PathAlreadyExists, FileNotFound, NameTooLong, InvalidUtf8, BadPathName, Unexpected };
|
pub const CreateSymbolicLinkError = error{ AccessDenied, PathAlreadyExists, FileNotFound, NameTooLong, InvalidUtf8, BadPathName, Unexpected };
|
||||||
|
|
||||||
|
pub fn NtCreateSymbolicLinkW(dir: ?HANDLE, sym_link_path: []const u16, target_path: []const u16) CreateSymbolicLinkError!void {
|
||||||
|
const SYMLINK_DATA = extern struct {
|
||||||
|
ReparseTag: ULONG,
|
||||||
|
ReparseDataLength: USHORT,
|
||||||
|
Reserved: USHORT,
|
||||||
|
SubstituteNameOffset: USHORT,
|
||||||
|
SubstituteNameLength: USHORT,
|
||||||
|
PrintNameOffset: USHORT,
|
||||||
|
PrintNameLength: USHORT,
|
||||||
|
Flags: ULONG,
|
||||||
|
};
|
||||||
|
|
||||||
|
const symlink_handle = OpenFile(sym_link_path, .{
|
||||||
|
.access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
|
||||||
|
.dir = dir,
|
||||||
|
.creation = FILE_CREATE,
|
||||||
|
.io_mode = .blocking,
|
||||||
|
}) catch |err| switch (err) {
|
||||||
|
error.IsDir => unreachable, // TODO
|
||||||
|
else => |e| unreachable,
|
||||||
|
};
|
||||||
|
defer CloseHandle(symlink_handle);
|
||||||
|
|
||||||
|
// prepare reparse data buffer
|
||||||
|
var buffer: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
|
||||||
|
const buf_len = @sizeOf(SYMLINK_DATA) + target_path.len * 4;
|
||||||
|
const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2;
|
||||||
|
const symlink_data = SYMLINK_DATA{
|
||||||
|
.ReparseTag = IO_REPARSE_TAG_SYMLINK,
|
||||||
|
.ReparseDataLength = @intCast(u16, buf_len - header_len),
|
||||||
|
.Reserved = 0,
|
||||||
|
.SubstituteNameOffset = @intCast(u16, target_path.len * 2),
|
||||||
|
.SubstituteNameLength = @intCast(u16, target_path.len * 2),
|
||||||
|
.PrintNameOffset = 0,
|
||||||
|
.PrintNameLength = @intCast(u16, target_path.len * 2),
|
||||||
|
.Flags = if (dir) |_| SYMLINK_FLAG_RELATIVE else 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
std.mem.copy(u8, buffer[0..], std.mem.asBytes(&symlink_data));
|
||||||
|
@memcpy(buffer[@sizeOf(SYMLINK_DATA)..], @ptrCast([*]const u8, target_path), target_path.len * 2);
|
||||||
|
const paths_start = @sizeOf(SYMLINK_DATA) + target_path.len * 2;
|
||||||
|
@memcpy(buffer[paths_start..].ptr, @ptrCast([*]const u8, target_path), target_path.len * 2);
|
||||||
|
// TODO replace with NtDeviceIoControl
|
||||||
|
_ = try DeviceIoControl(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null, null);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn CreateSymbolicLink(
|
pub fn CreateSymbolicLink(
|
||||||
sym_link_path: []const u8,
|
sym_link_path: []const u8,
|
||||||
target_path: []const u8,
|
target_path: []const u8,
|
||||||
|
@ -1565,6 +1565,7 @@ pub const MOUNT_POINT_REPARSE_BUFFER = extern struct {
|
|||||||
PathBuffer: [1]WCHAR,
|
PathBuffer: [1]WCHAR,
|
||||||
};
|
};
|
||||||
pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;
|
pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;
|
||||||
|
pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
|
||||||
pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
|
pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
|
||||||
pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c;
|
pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c;
|
||||||
pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;
|
pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;
|
||||||
|
Loading…
Reference in New Issue
Block a user