mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
Finish symlink implementation on Windows
This commit is contained in:
parent
515c663cd6
commit
791795a63a
@ -1541,6 +1541,10 @@ pub const SymLinkError = error{
|
||||
/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`.
|
||||
/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent
|
||||
/// one; the latter case is known as a dangling link.
|
||||
/// On Windows, it is only legal to create a symbolic link to an existing resource. Furthermore,
|
||||
/// this function will by default try creating a symbolic link to a file. If you would like to
|
||||
/// create a symbolic link to a directory instead, see `symlinkW` for more information how to
|
||||
/// do that.
|
||||
/// If `sym_link_path` exists, it will not be overwritten.
|
||||
/// See also `symlinkC` and `symlinkW`.
|
||||
pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void {
|
||||
@ -1550,7 +1554,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!
|
||||
if (builtin.os.tag == .windows) {
|
||||
const target_path_w = try windows.sliceToPrefixedFileW(target_path);
|
||||
const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);
|
||||
return windows.CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, 0);
|
||||
return symlinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr);
|
||||
}
|
||||
const target_path_c = try toPosixPath(target_path);
|
||||
const sym_link_path_c = try toPosixPath(sym_link_path);
|
||||
@ -1559,6 +1563,15 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!
|
||||
|
||||
pub const symlinkC = @compileError("deprecated: renamed to symlinkZ");
|
||||
|
||||
/// Windows-only. Same as `symlink` except the parameters are null-terminated, WTF16 encoded.
|
||||
/// Note that this function will by default try creating a symbolic link to a file. If you would
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// This is the same as `symlink` except the parameters are null-terminated pointers.
|
||||
/// See also `symlink`.
|
||||
pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLinkError!void {
|
||||
|
||||
@ -601,12 +601,17 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 {
|
||||
return buffer[0..end_index];
|
||||
}
|
||||
|
||||
pub const CreateSymbolicLinkError = error{Unexpected};
|
||||
pub const CreateSymbolicLinkError = error{AccessDenied, FileNotFound, Unexpected};
|
||||
|
||||
pub const CreateSymbolicLinkFlags = enum(DWORD) {
|
||||
File = SYMBOLIC_LINK_FLAG_FILE,
|
||||
Directory = SYMBOLIC_LINK_FLAG_DIRECTORY,
|
||||
};
|
||||
|
||||
pub fn CreateSymbolicLink(
|
||||
sym_link_path: []const u8,
|
||||
target_path: []const u8,
|
||||
flags: DWORD,
|
||||
flags: CreateSymbolicLinkFlags,
|
||||
) CreateSymbolicLinkError!void {
|
||||
const sym_link_path_w = try sliceToPrefixedFileW(sym_link_path);
|
||||
const target_path_w = try sliceToPrefixedFileW(target_path);
|
||||
@ -616,10 +621,32 @@ pub fn CreateSymbolicLink(
|
||||
pub fn CreateSymbolicLinkW(
|
||||
sym_link_path: [*:0]const u16,
|
||||
target_path: [*:0]const u16,
|
||||
flags: DWORD,
|
||||
flags: CreateSymbolicLinkFlags,
|
||||
) CreateSymbolicLinkError!void {
|
||||
if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, flags) == 0) {
|
||||
// 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) {
|
||||
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) {
|
||||
switch (kernel32.GetLastError()) {
|
||||
.PRIVILEGE_NOT_HELD => return error.AccessDenied,
|
||||
.FILE_NOT_FOUND => return error.FileNotFound,
|
||||
.PATH_NOT_FOUND => return error.FileNotFound,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
else => |err| return unexpectedError(err),
|
||||
}
|
||||
}
|
||||
return;
|
||||
},
|
||||
.PRIVILEGE_NOT_HELD => return error.AccessDenied,
|
||||
.FILE_NOT_FOUND => return error.FileNotFound,
|
||||
.PATH_NOT_FOUND => return error.FileNotFound,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
else => |err| return unexpectedError(err),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1569,3 +1569,7 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 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 SYMBOLIC_LINK_FLAG_FILE: DWORD = 0x0;
|
||||
pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
|
||||
pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;
|
||||
Loading…
x
Reference in New Issue
Block a user