| author | |
| committer | |
| log | 791795a63a34bc69af59717d5eff5d4c76349756 |
| tree | 27f9c879e10d04b7f0f444975358bc2f6812de9b |
| parent | 515c663cd6e31d5f8ae07e804f2b32b99d025895 |
3 files changed, 49 insertions(+), 5 deletions(-)
lib/std/os.zig+14-1| ... | @@ -1541,6 +1541,10 @@ pub const SymLinkError = error{ | ... | @@ -1541,6 +1541,10 @@ pub const SymLinkError = error{ |
| 1541 | /// Creates a symbolic link named `sym_link_path` which contains the string `target_path`. | 1541 | /// Creates a symbolic link named `sym_link_path` which contains the string `target_path`. |
| 1542 | /// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent | 1542 | /// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent |
| 1543 | /// one; the latter case is known as a dangling link. | 1543 | /// one; the latter case is known as a dangling link. |
| 1544 | /// On Windows, it is only legal to create a symbolic link to an existing resource. Furthermore, | ||
| 1545 | /// this function will by default try creating a symbolic link to a file. If you would like to | ||
| 1546 | /// create a symbolic link to a directory instead, see `symlinkW` for more information how to | ||
| 1547 | /// do that. | ||
| 1544 | /// If `sym_link_path` exists, it will not be overwritten. | 1548 | /// If `sym_link_path` exists, it will not be overwritten. |
| 1545 | /// See also `symlinkC` and `symlinkW`. | 1549 | /// See also `symlinkC` and `symlinkW`. |
| 1546 | pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void { | 1550 | 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! | ... | @@ -1550,7 +1554,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError! |
| 1550 | if (builtin.os.tag == .windows) { | 1554 | if (builtin.os.tag == .windows) { |
| 1551 | const target_path_w = try windows.sliceToPrefixedFileW(target_path); | 1555 | const target_path_w = try windows.sliceToPrefixedFileW(target_path); |
| 1552 | const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path); | 1556 | const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path); |
| 1553 | return windows.CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, 0); | 1557 | return symlinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr); |
| 1554 | } | 1558 | } |
| 1555 | const target_path_c = try toPosixPath(target_path); | 1559 | const target_path_c = try toPosixPath(target_path); |
| 1556 | const sym_link_path_c = try toPosixPath(sym_link_path); | 1560 | 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! | ... | @@ -1559,6 +1563,15 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError! |
| 1559 | 1563 | ||
| 1560 | pub const symlinkC = @compileError("deprecated: renamed to symlinkZ"); | 1564 | pub const symlinkC = @compileError("deprecated: renamed to symlinkZ"); |
| 1561 | 1565 | ||
| 1566 | /// Windows-only. Same as `symlink` except the parameters are null-terminated, WTF16 encoded. | ||
| 1567 | /// Note that this function will by default try creating a symbolic link to a file. If you would | ||
| 1568 | /// like to create a symbolic link to a directory, use `std.os.windows.CreateSymbolicLinkW` directly | ||
| 1569 | /// specifying as flags `std.os.windows.CreateSymbolicLinkFlags.Directory`. | ||
| 1570 | pub fn symlinkW(target_path: [*:0]const u16, sym_link_path: [*:0]const u16) SymLinkError!void { | ||
| 1571 | const flags = windows.CreateSymbolicLinkFlags.File; | ||
| 1572 | return windows.CreateSymbolicLinkW(sym_link_path, target_path, flags); | ||
| 1573 | } | ||
| 1574 | |||
| 1562 | /// This is the same as `symlink` except the parameters are null-terminated pointers. | 1575 | /// This is the same as `symlink` except the parameters are null-terminated pointers. |
| 1563 | /// See also `symlink`. | 1576 | /// See also `symlink`. |
| 1564 | pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLinkError!void { | 1577 | pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLinkError!void { |
lib/std/os/windows.zig+31-4| ... | @@ -601,12 +601,17 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 { | ... | @@ -601,12 +601,17 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 { |
| 601 | return buffer[0..end_index]; | 601 | return buffer[0..end_index]; |
| 602 | } | 602 | } |
| 603 | 603 | ||
| 604 | pub const CreateSymbolicLinkError = error{Unexpected}; | 604 | pub const CreateSymbolicLinkError = error{AccessDenied, FileNotFound, Unexpected}; |
| 605 | |||
| 606 | pub const CreateSymbolicLinkFlags = enum(DWORD) { | ||
| 607 | File = SYMBOLIC_LINK_FLAG_FILE, | ||
| 608 | Directory = SYMBOLIC_LINK_FLAG_DIRECTORY, | ||
| 609 | }; | ||
| 605 | 610 | ||
| 606 | pub fn CreateSymbolicLink( | 611 | pub fn CreateSymbolicLink( |
| 607 | sym_link_path: []const u8, | 612 | sym_link_path: []const u8, |
| 608 | target_path: []const u8, | 613 | target_path: []const u8, |
| 609 | flags: DWORD, | 614 | flags: CreateSymbolicLinkFlags, |
| 610 | ) CreateSymbolicLinkError!void { | 615 | ) CreateSymbolicLinkError!void { |
| 611 | const sym_link_path_w = try sliceToPrefixedFileW(sym_link_path); | 616 | const sym_link_path_w = try sliceToPrefixedFileW(sym_link_path); |
| 612 | const target_path_w = try sliceToPrefixedFileW(target_path); | 617 | const target_path_w = try sliceToPrefixedFileW(target_path); |
| ... | @@ -616,10 +621,32 @@ pub fn CreateSymbolicLink( | ... | @@ -616,10 +621,32 @@ pub fn CreateSymbolicLink( |
| 616 | pub fn CreateSymbolicLinkW( | 621 | pub fn CreateSymbolicLinkW( |
| 617 | sym_link_path: [*:0]const u16, | 622 | sym_link_path: [*:0]const u16, |
| 618 | target_path: [*:0]const u16, | 623 | target_path: [*:0]const u16, |
| 619 | flags: DWORD, | 624 | flags: CreateSymbolicLinkFlags, |
| 620 | ) CreateSymbolicLinkError!void { | 625 | ) CreateSymbolicLinkError!void { |
| 621 | if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, flags) == 0) { | 626 | // Previously, until Win 10 Creators Update, creating symbolic links required |
| 627 | // SeCreateSymbolicLink privilege. Currently, this is no longer required if the | ||
| 628 | // OS is in Developer Mode; however, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE | ||
| 629 | // must be added to the input flags. | ||
| 630 | if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, @enumToInt(flags) | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) { | ||
| 622 | switch (kernel32.GetLastError()) { | 631 | switch (kernel32.GetLastError()) { |
| 632 | .INVALID_PARAMETER => { | ||
| 633 | // If we're on Windows pre Creators Update, SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE | ||
| 634 | // flag is an invalid parameter, in which case repeat without the flag. | ||
| 635 | if (kernel32.CreateSymbolicLinkW(sym_link_path, target_path, @enumToInt(flags)) == 0) { | ||
| 636 | switch (kernel32.GetLastError()) { | ||
| 637 | .PRIVILEGE_NOT_HELD => return error.AccessDenied, | ||
| 638 | .FILE_NOT_FOUND => return error.FileNotFound, | ||
| 639 | .PATH_NOT_FOUND => return error.FileNotFound, | ||
| 640 | .ACCESS_DENIED => return error.AccessDenied, | ||
| 641 | else => |err| return unexpectedError(err), | ||
| 642 | } | ||
| 643 | } | ||
| 644 | return; | ||
| 645 | }, | ||
| 646 | .PRIVILEGE_NOT_HELD => return error.AccessDenied, | ||
| 647 | .FILE_NOT_FOUND => return error.FileNotFound, | ||
| 648 | .PATH_NOT_FOUND => return error.FileNotFound, | ||
| 649 | .ACCESS_DENIED => return error.AccessDenied, | ||
| 623 | else => |err| return unexpectedError(err), | 650 | else => |err| return unexpectedError(err), |
| 624 | } | 651 | } |
| 625 | } | 652 | } |
lib/std/os/windows/bits.zig+4| ... | @@ -1569,3 +1569,7 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; | ... | @@ -1569,3 +1569,7 @@ pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; |
| 1569 | pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8; | 1569 | pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8; |
| 1570 | pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c; | 1570 | pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c; |
| 1571 | pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003; | 1571 | pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003; |
| 1572 | |||
| 1573 | pub const SYMBOLIC_LINK_FLAG_FILE: DWORD = 0x0; | ||
| 1574 | pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; | ||
| 1575 | pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; | ||
| \ No newline at end of file | |||