diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2020-07-19 23:18:20 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2020-07-22 08:51:22 +0200 |
| commit | 2c9c13f624a48e6a22ae84b236eb131c24ba2eb4 (patch) | |
| tree | 6d8520a5dd8599c33510f12c77e5df97960fc50a | |
| parent | e0b77a6b77614538d18b9f0b9e3e7e434ccee4ff (diff) | |
| download | zig-2c9c13f624a48e6a22ae84b236eb131c24ba2eb4.tar.gz zig-2c9c13f624a48e6a22ae84b236eb131c24ba2eb4.zip | |
Add various build fixes
Fix WASI build, fix atomicSymlink by using `cwd().symLink`, add
`Dir.symLink` on supported targets.
| -rw-r--r-- | lib/std/fs.zig | 77 | ||||
| -rw-r--r-- | lib/std/os.zig | 4 |
2 files changed, 64 insertions, 17 deletions
diff --git a/lib/std/fs.zig b/lib/std/fs.zig index a22b15b0fb..6e0a9defd7 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -66,7 +66,15 @@ pub const need_async_thread = std.io.is_async and switch (builtin.os.tag) { /// TODO remove the allocator requirement from this API pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path: []const u8) !void { - if (symLinkAbsolute(existing_path, new_path, .{})) { + const res = blk: { + // TODO this is just a temporary until Dir.symLink is implemented on Windows + if (builtin.os.tag == .windows) { + break :blk os.windows.CreateSymbolicLink(new_path, existing_path, false); + } else { + break :blk cwd().symLink(existing_path, new_path, .{}); + } + }; + if (res) { return; } else |err| switch (err) { error.PathAlreadyExists => {}, @@ -84,7 +92,15 @@ pub fn atomicSymLink(allocator: *Allocator, existing_path: []const u8, new_path: try crypto.randomBytes(rand_buf[0..]); base64_encoder.encode(tmp_path[dirname.len + 1 ..], &rand_buf); - if (symLinkAbsolute(existing_path, tmp_path, .{})) { + const res2 = blk: { + // TODO this is just a temporary until Dir.symLink is implemented on Windows + if (builtin.os.tag == .windows) { + break :blk os.windows.CreateSymbolicLink(tmp_path, existing_path, false); + } else { + break :blk cwd().symLink(existing_path, new_path, .{}); + } + }; + if (res2) { return rename(tmp_path, new_path); } else |err| switch (err) { error.PathAlreadyExists => continue, @@ -669,7 +685,7 @@ pub const Dir = struct { w.RIGHT_FD_FILESTAT_SET_TIMES | w.RIGHT_FD_FILESTAT_SET_SIZE; } - const fd = try os.openatWasi(self.fd, sub_path, 0x0, fdflags, base, 0x0); + const fd = try os.openatWasi(self.fd, sub_path, 0x0, 0x0, fdflags, base, 0x0); return File{ .handle = fd }; } @@ -789,7 +805,7 @@ pub const Dir = struct { if (flags.exclusive) { oflags |= w.O_EXCL; } - const fd = try os.openatWasi(self.fd, sub_path, oflags, 0x0, base, 0x0); + const fd = try os.openatWasi(self.fd, sub_path, 0x0, oflags, 0x0, base, 0x0); return File{ .handle = fd }; } @@ -952,7 +968,7 @@ pub const Dir = struct { /// of the result. It means the `iterate` function can be called. iterate: bool = false, - /// `true` means it won't dereference the symlink. + /// `true` means it won't dereference the symlinks. no_follow: bool = false, }; @@ -1001,7 +1017,7 @@ pub const Dir = struct { // TODO do we really need all the rights here? const inheriting: w.rights_t = w.RIGHT_ALL ^ w.RIGHT_SOCK_SHUTDOWN; - const result = os.openatWasi(self.fd, sub_path, w.O_DIRECTORY, symlink_flags, base, inheriting); + const result = os.openatWasi(self.fd, sub_path, symlink_flags, w.O_DIRECTORY, 0x0, base, inheriting); const fd = result catch |err| switch (err) { error.FileTooBig => unreachable, // can't happen for directories error.IsDir => unreachable, // we're providing O_DIRECTORY @@ -1211,6 +1227,38 @@ pub const Dir = struct { }; } + /// 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. + /// If `sym_link_path` exists, it will not be overwritten. + /// TODO add Windows support + pub fn symLink( + self: Dir, + target_path: []const u8, + sym_link_path: []const u8, + flags: SymLinkFlags, + ) !void { + if (builtin.os.tag == .wasi) { + return self.symLinkWasi(target_path, sym_link_path); + } + if (builtin.os.tag == .windows) { + @compileError("TODO implement Dir.symLink on Windows"); + } + const target_path_c = try os.toPosixPath(target_path); + const sym_link_path_c = try os.toPosixPath(sym_link_path); + return self.symLinkZ(&target_path_c, &sym_link_path_c, flags); + } + + /// WASI-only. Same as `symLink` except targeting WASI. + pub fn symLinkWasi(self: Dir, target_path: []const u8, sym_link_path: []const u8, flags: SymLinkFlags) !void { + return os.symlinkatWasi(target_path, self.fd, sym_link_path); + } + + /// Same as `symLink`, except the pathname parameters are null-terminated. + pub fn symLinkZ(self: Dir, target_path_c: [*:0]const u8, sym_link_path_c: [*:0]const u8, flags: SymLinkFlags) !void { + return os.symlinkatZ(target_path_c, self.fd, sym_link_path_c); + } + /// Read value of a symbolic link. /// The return value is a slice of `buffer`, from index `0`. /// Asserts that the path parameter has no null bytes. @@ -1305,7 +1353,6 @@ pub const Dir = struct { error.Unexpected, => |e| return e, } - var dir = self.openDir(sub_path, .{ .iterate = true, .no_follow = true }) catch |err| switch (err) { error.NotDir => { if (got_access_denied) { @@ -1718,7 +1765,7 @@ pub const readLinkC = @compileError("deprecated; use Dir.readLinkZ or readLinkAb /// or a directory. This value is ignored on all hosts except Windows where /// creating symlinks to different resource types, requires different flags. /// By default, `symLinkAbsolute` is assumed to point to a file. -pub const SymlinkFlags = struct { +pub const SymLinkFlags = struct { is_directory: bool = false, }; @@ -1727,9 +1774,9 @@ pub const SymlinkFlags = struct { /// one; the latter case is known as a dangling link. /// If `sym_link_path` exists, it will not be overwritten. /// See also `symLinkAbsoluteZ` and `symLinkAbsoluteW`. -pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags: SymlinkFlags) !void { +pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags: SymLinkFlags) !void { if (builtin.os.tag == .wasi) { - @compileError("symLinkAbsolute is not supported in WASI"); + @compileError("symLinkAbsolute is not supported in WASI; use Dir.symLinkWasi instead"); } assert(path.isAbsolute(target_path)); assert(path.isAbsolute(sym_link_path)); @@ -1741,9 +1788,9 @@ pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags /// Windows-only. Same as `symLinkAbsolute` 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, specify this with `SymlinkFlags{ .is_directory = true }`. +/// like to create a symbolic link to a directory, specify this with `SymLinkFlags{ .is_directory = true }`. /// See also `symLinkAbsolute`, `symLinkAbsoluteZ`. -pub fn symLinkAbsoluteW(target_path_w: [*:0]const u16, sym_link_path_w: [*:0]const u16, flags: SymlinkFlags) !void { +pub fn symLinkAbsoluteW(target_path_w: [*:0]const u16, sym_link_path_w: [*:0]const u16, flags: SymLinkFlags) !void { assert(path.isAbsoluteWindowsW(target_path_w)); assert(path.isAbsoluteWindowsW(sym_link_path_w)); return os.windows.CreateSymbolicLinkW(sym_link_path_w, target_path_w, flags.is_directory); @@ -1751,7 +1798,7 @@ pub fn symLinkAbsoluteW(target_path_w: [*:0]const u16, sym_link_path_w: [*:0]con /// Same as `symLinkAbsolute` except the parameters are null-terminated pointers. /// See also `symLinkAbsolute`. -pub fn symLinkAbsoluteZ(target_path_c: [*:0]const u8, sym_link_path_c: [*:0]const u8, flags: SymlinkFlags) !void { +pub fn symLinkAbsoluteZ(target_path_c: [*:0]const u8, sym_link_path_c: [*:0]const u8, flags: SymLinkFlags) !void { assert(path.isAbsoluteZ(target_path_c)); assert(path.isAbsoluteZ(sym_link_path_c)); if (builtin.os.tag == .windows) { @@ -1762,8 +1809,8 @@ pub fn symLinkAbsoluteZ(target_path_c: [*:0]const u8, sym_link_path_c: [*:0]cons return os.symlinkZ(target_path_c, sym_link_path_c); } -pub const symLink = @compileError("deprecated: use symLinkAbsolute"); -pub const symLinkC = @compileError("deprecated: use symLinkAbsoluteC"); +pub const symLink = @compileError("deprecated: use Dir.symLink or symLinkAbsolute"); +pub const symLinkC = @compileError("deprecated: use Dir.symLinkZ or symLinkAbsoluteZ"); pub const Walker = struct { stack: std.ArrayList(StackItem), diff --git a/lib/std/os.zig b/lib/std/os.zig index 86a5a7ad08..36f7669f66 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1109,10 +1109,10 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope } /// Open and possibly create a file in WASI. -pub fn openatWasi(dir_fd: fd_t, file_path: []const u8, oflags: oflags_t, fdflags: fdflags_t, base: rights_t, inheriting: rights_t) OpenError!fd_t { +pub fn openatWasi(dir_fd: fd_t, file_path: []const u8, lookup_flags: lookupflags_t, oflags: oflags_t, fdflags: fdflags_t, base: rights_t, inheriting: rights_t) OpenError!fd_t { while (true) { var fd: fd_t = undefined; - switch (wasi.path_open(dir_fd, 0x0, file_path.ptr, file_path.len, oflags, base, inheriting, fdflags, &fd)) { + switch (wasi.path_open(dir_fd, lookup_flags, file_path.ptr, file_path.len, oflags, base, inheriting, fdflags, &fd)) { wasi.ESUCCESS => return fd, wasi.EINTR => continue, |
