authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-15 09:06:01+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-22 08:51:22+02:00
log30f1176a545111e8bdce3362d6bdbf7ef75dce2a
tree1a069f08114d0756dab54ea450328a799df8f961
parent4894de2b326363c9a157411bf555d73b661c74c4

Add SymlinkFlags needed to create symlinks to dirs on Win


3 files changed, 19 insertions(+), 16 deletions(-)

lib/std/fs.zig+2-2
...@@ -69,7 +69,7 @@ pub const need_async_thread = std.io.is_async and switch (builtin.os.tag) {...@@ -69,7 +69,7 @@ pub const need_async_thread = std.io.is_async and switch (builtin.os.tag) {
6969
70/// TODO remove the allocator requirement from this API70/// TODO remove the allocator requirement from this API
71pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path: []const u8) !void {71pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path: []const u8) !void {
72 if (symLink(existing_path, new_path)) {72 if (symLink(existing_path, new_path, .{})) {
73 return;73 return;
74 } else |err| switch (err) {74 } else |err| switch (err) {
75 error.PathAlreadyExists => {},75 error.PathAlreadyExists => {},
...@@ -87,7 +87,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:...@@ -87,7 +87,7 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path:
87 try crypto.randomBytes(rand_buf[0..]);87 try crypto.randomBytes(rand_buf[0..]);
88 base64_encoder.encode(tmp_path[dirname.len + 1 ..], &rand_buf);88 base64_encoder.encode(tmp_path[dirname.len + 1 ..], &rand_buf);
8989
90 if (symLink(existing_path, tmp_path)) {90 if (symLink(existing_path, tmp_path, .{})) {
91 return rename(tmp_path, new_path);91 return rename(tmp_path, new_path);
92 } else |err| switch (err) {92 } else |err| switch (err) {
93 error.PathAlreadyExists => continue,93 error.PathAlreadyExists => continue,
lib/std/os.zig+15-12
...@@ -1520,6 +1520,14 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {...@@ -1520,6 +1520,14 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
1520 }1520 }
1521}1521}
15221522
1523/// Use with `symlink` to specify whether the symlink will point to a file
1524/// or a directory. This value is ignored on all hosts except Windows where
1525/// creating symlinks to different resource types, requires different flags.
1526/// By default, symlink is assumed to point to a file.
1527pub const SymlinkFlags = struct{
1528 is_directory: bool = false,
1529};
1530
1523pub const SymLinkError = error{1531pub const SymLinkError = error{
1524 /// In WASI, this error may occur when the file descriptor does1532 /// In WASI, this error may occur when the file descriptor does
1525 /// not hold the required rights to create a new symbolic link relative to it.1533 /// not hold the required rights to create a new symbolic link relative to it.
...@@ -1541,39 +1549,34 @@ pub const SymLinkError = error{...@@ -1541,39 +1549,34 @@ pub const SymLinkError = error{
1541/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`.1549/// 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 nonexistent1550/// 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.1551/// 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.
1548/// If `sym_link_path` exists, it will not be overwritten.1552/// If `sym_link_path` exists, it will not be overwritten.
1549/// See also `symlinkC` and `symlinkW`.1553/// See also `symlinkC` and `symlinkW`.
1550pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void {1554pub fn symlink(target_path: []const u8, sym_link_path: []const u8, flags: SymlinkFlags) SymLinkError!void {
1551 if (builtin.os.tag == .wasi) {1555 if (builtin.os.tag == .wasi) {
1552 @compileError("symlink is not supported in WASI; use symlinkat instead");1556 @compileError("symlink is not supported in WASI; use symlinkat instead");
1553 }1557 }
1554 if (builtin.os.tag == .windows) {1558 if (builtin.os.tag == .windows) {
1555 const target_path_w = try windows.sliceToPrefixedFileW(target_path);1559 const target_path_w = try windows.sliceToPrefixedFileW(target_path);
1556 const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);1560 const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);
1557 return symlinkW(target_path_w.span().ptr, sym_link_path_w.span().ptr);1561 return symlinkW(target_path_w.span().ptr, sym_link_path_w.span().ptr, flags);
1558 }1562 }
1559 const target_path_c = try toPosixPath(target_path);1563 const target_path_c = try toPosixPath(target_path);
1560 const sym_link_path_c = try toPosixPath(sym_link_path);1564 const sym_link_path_c = try toPosixPath(sym_link_path);
1561 return symlinkZ(&target_path_c, &sym_link_path_c);1565 return symlinkZ(&target_path_c, &sym_link_path_c, flags);
1562}1566}
15631567
1564pub const symlinkC = @compileError("deprecated: renamed to symlinkZ");1568pub const symlinkC = @compileError("deprecated: renamed to symlinkZ");
15651569
1566/// Windows-only. Same as `symlink` except the parameters are null-terminated, WTF16 encoded.1570/// 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 would1571/// 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` directly1572/// like to create a symbolic link to a directory, specify this with `SymlinkFlags{ .is_directory = true }`.
1569/// specifying as flags `std.os.windows.CreateSymbolicLinkFlags.Directory`.1573pub fn symlinkW(target_path: [*:0]const u16, sym_link_path: [*:0]const u16, flags: SymlinkFlags) SymLinkError!void {
1570pub fn symlinkW(target_path: [*:0]const u16, sym_link_path: [*:0]const u16) SymLinkError!void {1574 return windows.CreateSymbolicLinkW(sym_link_path, target_path, flags.is_directory);
1571 return windows.CreateSymbolicLinkW(sym_link_path, target_path, false);
1572}1575}
15731576
1574/// This is the same as `symlink` except the parameters are null-terminated pointers.1577/// This is the same as `symlink` except the parameters are null-terminated pointers.
1575/// See also `symlink`.1578/// See also `symlink`.
1576pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLinkError!void {1579pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8, flags: SymlinkFlags) SymLinkError!void {
1577 if (builtin.os.tag == .windows) {1580 if (builtin.os.tag == .windows) {
1578 const target_path_w = try windows.cStrToPrefixedFileW(target_path);1581 const target_path_w = try windows.cStrToPrefixedFileW(target_path);
1579 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);1582 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
lib/std/os/test.zig+2-2
...@@ -48,7 +48,7 @@ test "readlink" {...@@ -48,7 +48,7 @@ test "readlink" {
48 {48 {
49 var cwd = fs.cwd();49 var cwd = fs.cwd();
50 try cwd.writeFile("file.txt", "nonsense");50 try cwd.writeFile("file.txt", "nonsense");
51 try os.symlink("file.txt", "symlinked");51 try os.symlink("file.txt", "symlinked", .{});
5252
53 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;53 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
54 const given = try os.readlink("symlinked", buffer[0..]);54 const given = try os.readlink("symlinked", buffer[0..]);
...@@ -81,7 +81,7 @@ test "readlink" {...@@ -81,7 +81,7 @@ test "readlink" {
81 std.debug.warn("symlink_path={}\n", .{symlink_path});81 std.debug.warn("symlink_path={}\n", .{symlink_path});
8282
83 // create symbolic link by path83 // create symbolic link by path
84 try os.symlink(target_path, symlink_path);84 try os.symlink(target_path, symlink_path, .{});
8585
86 // now, read the link and verify86 // now, read the link and verify
87 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;87 var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;