Refactor
This commit is contained in:
@@ -1568,8 +1568,7 @@ pub const symlinkC = @compileError("deprecated: renamed to symlinkZ");
|
||||
/// like to create a symbolic link to a directory, use `std.os.windows.CreateSymbolicLinkW` directly
|
||||
/// specifying as flags `std.os.windows.CreateSymbolicLinkFlags.Directory`.
|
||||
pub fn symlinkW(target_path: [*:0]const u16, sym_link_path: [*:0]const u16) SymLinkError!void {
|
||||
const flags = windows.CreateSymbolicLinkFlags.File;
|
||||
return windows.CreateSymbolicLinkW(sym_link_path, target_path, flags);
|
||||
return windows.CreateSymbolicLinkW(sym_link_path, target_path, false);
|
||||
}
|
||||
|
||||
/// This is the same as `symlink` except the parameters are null-terminated pointers.
|
||||
@@ -2395,20 +2394,20 @@ pub const readlinkC = @compileError("deprecated: renamed to readlinkZ");
|
||||
pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {
|
||||
const w = windows;
|
||||
|
||||
const dir = if (std.fs.path.isAbsoluteWindowsW(file_path)) null else std.fs.cwd().fd;
|
||||
const handle = w.OpenAsReparsePoint(dir, file_path) catch |err| {
|
||||
const sharing = w.FILE_SHARE_DELETE | w.FILE_SHARE_READ | w.FILE_SHARE_WRITE;
|
||||
const disposition = w.OPEN_EXISTING;
|
||||
const flags = w.FILE_FLAG_BACKUP_SEMANTICS | w.FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
const handle = w.CreateFileW(file_path, 0, sharing, null, disposition, flags, null) catch |err| {
|
||||
switch (err) {
|
||||
error.SharingViolation => return error.AccessDenied,
|
||||
error.PipeBusy => unreachable,
|
||||
error.PathAlreadyExists => unreachable,
|
||||
error.NoDevice => return error.FileNotFound,
|
||||
else => |e| return e,
|
||||
}
|
||||
};
|
||||
|
||||
var reparse_buf: [w.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined;
|
||||
_ = try w.DeviceIoControl(handle, w.FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..], null);
|
||||
// std.debug.warn("\n\n{x}\n\n", .{reparse_buf});
|
||||
const reparse_struct = @ptrCast(*const w.REPARSE_DATA_BUFFER, @alignCast(@alignOf(w.REPARSE_DATA_BUFFER), &reparse_buf[0]));
|
||||
switch (reparse_struct.ReparseTag) {
|
||||
w.IO_REPARSE_TAG_SYMLINK => {
|
||||
@@ -2434,9 +2433,9 @@ pub fn readlinkW(file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8
|
||||
}
|
||||
|
||||
fn parseReadlinkPath(path: []const u16, is_relative: bool, out_buffer: []u8) []u8 {
|
||||
const out_len = std.unicode.utf16leToUtf8(out_buffer, path) catch unreachable;
|
||||
std.debug.warn("got symlink => utf8={}\n", .{out_buffer[0..out_len]});
|
||||
// TODO handle absolute paths and namespace prefix '/??/'
|
||||
const prefix = [_]u16{ '\\', '?', '?', '\\' };
|
||||
const start_index = if (mem.startsWith(u16, path, &prefix)) prefix.len else 0;
|
||||
const out_len = std.unicode.utf16leToUtf8(out_buffer, path[start_index..]) catch unreachable;
|
||||
return out_buffer[0..out_len];
|
||||
}
|
||||
|
||||
@@ -2502,6 +2501,18 @@ pub fn readlinkatWasi(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) Read
|
||||
/// Windows-only. Same as `readlinkat` except `file_path` is null-terminated, WTF16 encoded.
|
||||
/// See also `readlinkat`.
|
||||
pub fn readlinkatW(dirfd: fd_t, file_path: [*:0]const u16, out_buffer: []u8) ReadLinkError![]u8 {
|
||||
const w = windows;
|
||||
|
||||
const handle = w.OpenReparsePoint(dir, file_path) catch |err| {
|
||||
switch (err) {
|
||||
error.SharingViolation => return error.AccessDenied,
|
||||
error.PathAlreadyExists => unreachable,
|
||||
error.PipeBusy => unreachable,
|
||||
error.PathAlreadyExists => unreachable,
|
||||
error.NoDevice => return error.FileNotFound,
|
||||
else => |e| return e,
|
||||
}
|
||||
};
|
||||
@compileError("TODO implement on Windows");
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ test "readlink" {
|
||||
// now, read the link and verify
|
||||
var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
|
||||
const given = try os.readlink(symlink_path, buffer[0..]);
|
||||
std.debug.warn("given={}\n", .{given});
|
||||
expect(mem.eql(u8, symlink_path, given));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,43 +602,34 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 {
|
||||
return buffer[0..end_index];
|
||||
}
|
||||
|
||||
pub const CreateSymbolicLinkError = error{
|
||||
AccessDenied,
|
||||
PathAlreadyExists,
|
||||
FileNotFound,
|
||||
Unexpected
|
||||
};
|
||||
|
||||
pub const CreateSymbolicLinkFlags = enum(DWORD) {
|
||||
File = SYMBOLIC_LINK_FLAG_FILE,
|
||||
Directory = SYMBOLIC_LINK_FLAG_DIRECTORY,
|
||||
};
|
||||
pub const CreateSymbolicLinkError = error{ AccessDenied, PathAlreadyExists, FileNotFound, Unexpected };
|
||||
|
||||
pub fn CreateSymbolicLink(
|
||||
sym_link_path: []const u8,
|
||||
target_path: []const u8,
|
||||
flags: CreateSymbolicLinkFlags,
|
||||
is_directory: bool,
|
||||
) CreateSymbolicLinkError!void {
|
||||
const sym_link_path_w = try sliceToPrefixedFileW(sym_link_path);
|
||||
const target_path_w = try sliceToPrefixedFileW(target_path);
|
||||
return CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, flags);
|
||||
return CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, is_directory);
|
||||
}
|
||||
|
||||
pub fn CreateSymbolicLinkW(
|
||||
sym_link_path: [*:0]const u16,
|
||||
target_path: [*:0]const u16,
|
||||
flags: CreateSymbolicLinkFlags,
|
||||
is_directory: bool,
|
||||
) CreateSymbolicLinkError!void {
|
||||
// Previously, until Win 10 Creators Update, creating symbolic links required
|
||||
// SeCreateSymbolicLink privilege. Currently, this is no longer required if the
|
||||
// OS is in Developer Mode; however, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
|
||||
// must be added to the input flags.
|
||||
if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, @enumToInt(flags) | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) {
|
||||
const flags = if (is_directory) SYMBOLIC_LINK_FLAG_DIRECTORY else 0;
|
||||
if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) {
|
||||
switch (kernel32.GetLastError()) {
|
||||
.INVALID_PARAMETER => {
|
||||
// If we're on Windows pre Creators Update, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
|
||||
// flag is an invalid parameter, in which case repeat without the flag.
|
||||
if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, @enumToInt(flags)) == 0) {
|
||||
if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, flags) == 0) {
|
||||
switch (kernel32.GetLastError()) {
|
||||
.PRIVILEGE_NOT_HELD => return error.AccessDenied,
|
||||
.FILE_NOT_FOUND => return error.FileNotFound,
|
||||
@@ -1372,7 +1363,7 @@ pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
|
||||
return error.Unexpected;
|
||||
}
|
||||
|
||||
pub const OpenAsReparsePointError = error {
|
||||
pub const OpenReparsePointError = error{
|
||||
FileNotFound,
|
||||
NoDevice,
|
||||
SharingViolation,
|
||||
@@ -1384,10 +1375,10 @@ pub const OpenAsReparsePointError = error {
|
||||
};
|
||||
|
||||
/// Open file as a reparse point
|
||||
pub fn OpenAsReparsePoint(
|
||||
pub fn OpenReparsePoint(
|
||||
dir: ?HANDLE,
|
||||
sub_path_w: [*:0]const u16,
|
||||
) OpenAsReparsePointError!HANDLE {
|
||||
) OpenReparsePointError!HANDLE {
|
||||
const path_len_bytes = math.cast(u16, mem.lenZ(sub_path_w) * 2) catch |err| switch (err) {
|
||||
error.Overflow => return error.NameTooLong,
|
||||
};
|
||||
@@ -1440,4 +1431,4 @@ pub fn OpenAsReparsePoint(
|
||||
.FILE_IS_A_DIRECTORY => unreachable,
|
||||
else => return unexpectedStatus(rc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,8 +1568,7 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;
|
||||
pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
|
||||
pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c;
|
||||
pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;
|
||||
pub const SYMLINK_FLAG_RELATIVE: ULONG = 0x00000001;
|
||||
pub const SYMLINK_FLAG_RELATIVE: ULONG = 0x1;
|
||||
|
||||
pub const SYMBOLIC_LINK_FLAG_FILE: DWORD = 0x0;
|
||||
pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
|
||||
pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;
|
||||
|
||||
Reference in New Issue
Block a user