| author | |
| committer | |
| log | 9ccd68de0b79c3723bd11071fd836bc24ff25b33 |
| tree | 3441f2a7030f40a6b625f4ff9fc7d719a60a32d3 |
| parent | 7f5bb118d4d90e2b883ee66e17592ac8d7808ac8 |
and delete the unit tests that called fork()
no forking allowed in the std lib, including unit tests, except to implement child process spawning.21 files changed, 167 insertions(+), 248 deletions(-)
lib/compiler/translate-c/main.zig+1-1| ... | @@ -253,7 +253,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration | ... | @@ -253,7 +253,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration |
| 253 | if (d.output_name) |path| blk: { | 253 | if (d.output_name) |path| blk: { |
| 254 | if (std.mem.eql(u8, path, "-")) break :blk; | 254 | if (std.mem.eql(u8, path, "-")) break :blk; |
| 255 | if (std.fs.path.dirname(path)) |dirname| { | 255 | if (std.fs.path.dirname(path)) |dirname| { |
| 256 | Io.Dir.cwd().makePath(dirname) catch |err| | 256 | Io.Dir.cwd().makePath(io, dirname) catch |err| |
| 257 | return d.fatal("failed to create path to '{s}': {s}", .{ path, aro.Driver.errorDescription(err) }); | 257 | return d.fatal("failed to create path to '{s}': {s}", .{ path, aro.Driver.errorDescription(err) }); |
| 258 | } | 258 | } |
| 259 | out_file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| { | 259 | out_file = Io.Dir.cwd().createFile(io, path, .{}) catch |err| { |
lib/std/Build.zig+4-5| ... | @@ -1706,7 +1706,7 @@ pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.MakeError || Io.Di | ... | @@ -1706,7 +1706,7 @@ pub fn truncateFile(b: *Build, dest_path: []const u8) (Io.Dir.MakeError || Io.Di |
| 1706 | var src_file = cwd.createFile(io, dest_path, .{}) catch |err| switch (err) { | 1706 | var src_file = cwd.createFile(io, dest_path, .{}) catch |err| switch (err) { |
| 1707 | error.FileNotFound => blk: { | 1707 | error.FileNotFound => blk: { |
| 1708 | if (fs.path.dirname(dest_path)) |dirname| { | 1708 | if (fs.path.dirname(dest_path)) |dirname| { |
| 1709 | try cwd.makePath(dirname); | 1709 | try cwd.makePath(io, dirname); |
| 1710 | } | 1710 | } |
| 1711 | break :blk try cwd.createFile(io, dest_path, .{}); | 1711 | break :blk try cwd.createFile(io, dest_path, .{}); |
| 1712 | }, | 1712 | }, |
| ... | @@ -2634,13 +2634,12 @@ pub const InstallDir = union(enum) { | ... | @@ -2634,13 +2634,12 @@ pub const InstallDir = union(enum) { |
| 2634 | /// source of API breakage in the future, so keep that in mind when using this | 2634 | /// source of API breakage in the future, so keep that in mind when using this |
| 2635 | /// function. | 2635 | /// function. |
| 2636 | pub fn makeTempPath(b: *Build) []const u8 { | 2636 | pub fn makeTempPath(b: *Build) []const u8 { |
| 2637 | const io = b.graph.io; | ||
| 2637 | const rand_int = std.crypto.random.int(u64); | 2638 | const rand_int = std.crypto.random.int(u64); |
| 2638 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); | 2639 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); |
| 2639 | const result_path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch @panic("OOM"); | 2640 | const result_path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch @panic("OOM"); |
| 2640 | b.cache_root.handle.makePath(tmp_dir_sub_path) catch |err| { | 2641 | b.cache_root.handle.makePath(io, tmp_dir_sub_path) catch |err| { |
| 2641 | std.debug.print("unable to make tmp path '{s}': {s}\n", .{ | 2642 | std.debug.print("unable to make tmp path '{s}': {t}\n", .{ result_path, err }); |
| 2642 | result_path, @errorName(err), | ||
| 2643 | }); | ||
| 2644 | }; | 2643 | }; |
| 2645 | return result_path; | 2644 | return result_path; |
| 2646 | } | 2645 | } |
lib/std/Build/Cache/Path.zig+2-2| ... | @@ -128,14 +128,14 @@ pub fn access(p: Path, sub_path: []const u8, flags: Io.Dir.AccessOptions) !void | ... | @@ -128,14 +128,14 @@ pub fn access(p: Path, sub_path: []const u8, flags: Io.Dir.AccessOptions) !void |
| 128 | return p.root_dir.handle.access(joined_path, flags); | 128 | return p.root_dir.handle.access(joined_path, flags); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | pub fn makePath(p: Path, sub_path: []const u8) !void { | 131 | pub fn makePath(p: Path, io: Io, sub_path: []const u8) !void { |
| 132 | var buf: [fs.max_path_bytes]u8 = undefined; | 132 | var buf: [fs.max_path_bytes]u8 = undefined; |
| 133 | const joined_path = if (p.sub_path.len == 0) sub_path else p: { | 133 | const joined_path = if (p.sub_path.len == 0) sub_path else p: { |
| 134 | break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ | 134 | break :p std.fmt.bufPrint(&buf, "{s}" ++ fs.path.sep_str ++ "{s}", .{ |
| 135 | p.sub_path, sub_path, | 135 | p.sub_path, sub_path, |
| 136 | }) catch return error.NameTooLong; | 136 | }) catch return error.NameTooLong; |
| 137 | }; | 137 | }; |
| 138 | return p.root_dir.handle.makePath(joined_path); | 138 | return p.root_dir.handle.makePath(io, joined_path); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 { | 141 | pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 { |
lib/std/Build/Step/ConfigHeader.zig+2-1| ... | @@ -184,6 +184,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -184,6 +184,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 184 | 184 | ||
| 185 | const gpa = b.allocator; | 185 | const gpa = b.allocator; |
| 186 | const arena = b.allocator; | 186 | const arena = b.allocator; |
| 187 | const io = b.graph.io; | ||
| 187 | 188 | ||
| 188 | var man = b.graph.cache.obtain(); | 189 | var man = b.graph.cache.obtain(); |
| 189 | defer man.deinit(); | 190 | defer man.deinit(); |
| ... | @@ -257,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -257,7 +258,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 257 | const sub_path = b.pathJoin(&.{ "o", &digest, config_header.include_path }); | 258 | const sub_path = b.pathJoin(&.{ "o", &digest, config_header.include_path }); |
| 258 | const sub_path_dirname = std.fs.path.dirname(sub_path).?; | 259 | const sub_path_dirname = std.fs.path.dirname(sub_path).?; |
| 259 | 260 | ||
| 260 | b.cache_root.handle.makePath(sub_path_dirname) catch |err| { | 261 | b.cache_root.handle.makePath(io, sub_path_dirname) catch |err| { |
| 261 | return step.fail("unable to make path '{f}{s}': {s}", .{ | 262 | return step.fail("unable to make path '{f}{s}': {s}", .{ |
| 262 | b.cache_root, sub_path_dirname, @errorName(err), | 263 | b.cache_root, sub_path_dirname, @errorName(err), |
| 263 | }); | 264 | }); |
lib/std/Build/Step/ObjCopy.zig+2-1| ... | @@ -143,6 +143,7 @@ pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath { | ... | @@ -143,6 +143,7 @@ pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath { |
| 143 | fn make(step: *Step, options: Step.MakeOptions) !void { | 143 | fn make(step: *Step, options: Step.MakeOptions) !void { |
| 144 | const prog_node = options.progress_node; | 144 | const prog_node = options.progress_node; |
| 145 | const b = step.owner; | 145 | const b = step.owner; |
| 146 | const io = b.graph.io; | ||
| 146 | const objcopy: *ObjCopy = @fieldParentPtr("step", step); | 147 | const objcopy: *ObjCopy = @fieldParentPtr("step", step); |
| 147 | try step.singleUnchangingWatchInput(objcopy.input_file); | 148 | try step.singleUnchangingWatchInput(objcopy.input_file); |
| 148 | 149 | ||
| ... | @@ -176,7 +177,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -176,7 +177,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 176 | const cache_path = "o" ++ fs.path.sep_str ++ digest; | 177 | const cache_path = "o" ++ fs.path.sep_str ++ digest; |
| 177 | const full_dest_path = try b.cache_root.join(b.allocator, &.{ cache_path, objcopy.basename }); | 178 | const full_dest_path = try b.cache_root.join(b.allocator, &.{ cache_path, objcopy.basename }); |
| 178 | const full_dest_path_debug = try b.cache_root.join(b.allocator, &.{ cache_path, b.fmt("{s}.debug", .{objcopy.basename}) }); | 179 | const full_dest_path_debug = try b.cache_root.join(b.allocator, &.{ cache_path, b.fmt("{s}.debug", .{objcopy.basename}) }); |
| 179 | b.cache_root.handle.makePath(cache_path) catch |err| { | 180 | b.cache_root.handle.makePath(io, cache_path) catch |err| { |
| 180 | return step.fail("unable to make path {s}: {s}", .{ cache_path, @errorName(err) }); | 181 | return step.fail("unable to make path {s}: {s}", .{ cache_path, @errorName(err) }); |
| 181 | }; | 182 | }; |
| 182 | 183 |
lib/std/Build/Step/Run.zig+4-3| ... | @@ -973,7 +973,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -973,7 +973,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 973 | .output_directory => output_sub_path, | 973 | .output_directory => output_sub_path, |
| 974 | else => unreachable, | 974 | else => unreachable, |
| 975 | }; | 975 | }; |
| 976 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { | 976 | b.cache_root.handle.makePath(io, output_sub_dir_path) catch |err| { |
| 977 | return step.fail("unable to make path '{f}{s}': {s}", .{ | 977 | return step.fail("unable to make path '{f}{s}': {s}", .{ |
| 978 | b.cache_root, output_sub_dir_path, @errorName(err), | 978 | b.cache_root, output_sub_dir_path, @errorName(err), |
| 979 | }); | 979 | }); |
| ... | @@ -1005,7 +1005,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -1005,7 +1005,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 1005 | .output_directory => output_sub_path, | 1005 | .output_directory => output_sub_path, |
| 1006 | else => unreachable, | 1006 | else => unreachable, |
| 1007 | }; | 1007 | }; |
| 1008 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { | 1008 | b.cache_root.handle.makePath(io, output_sub_dir_path) catch |err| { |
| 1009 | return step.fail("unable to make path '{f}{s}': {s}", .{ | 1009 | return step.fail("unable to make path '{f}{s}': {s}", .{ |
| 1010 | b.cache_root, output_sub_dir_path, @errorName(err), | 1010 | b.cache_root, output_sub_dir_path, @errorName(err), |
| 1011 | }); | 1011 | }); |
| ... | @@ -1241,6 +1241,7 @@ fn runCommand( | ... | @@ -1241,6 +1241,7 @@ fn runCommand( |
| 1241 | const b = step.owner; | 1241 | const b = step.owner; |
| 1242 | const arena = b.allocator; | 1242 | const arena = b.allocator; |
| 1243 | const gpa = options.gpa; | 1243 | const gpa = options.gpa; |
| 1244 | const io = b.graph.io; | ||
| 1244 | 1245 | ||
| 1245 | const cwd: ?[]const u8 = if (run.cwd) |lazy_cwd| lazy_cwd.getPath2(b, step) else null; | 1246 | const cwd: ?[]const u8 = if (run.cwd) |lazy_cwd| lazy_cwd.getPath2(b, step) else null; |
| 1246 | 1247 | ||
| ... | @@ -1470,7 +1471,7 @@ fn runCommand( | ... | @@ -1470,7 +1471,7 @@ fn runCommand( |
| 1470 | 1471 | ||
| 1471 | const sub_path = b.pathJoin(&output_components); | 1472 | const sub_path = b.pathJoin(&output_components); |
| 1472 | const sub_path_dirname = fs.path.dirname(sub_path).?; | 1473 | const sub_path_dirname = fs.path.dirname(sub_path).?; |
| 1473 | b.cache_root.handle.makePath(sub_path_dirname) catch |err| { | 1474 | b.cache_root.handle.makePath(io, sub_path_dirname) catch |err| { |
| 1474 | return step.fail("unable to make path '{f}{s}': {s}", .{ | 1475 | return step.fail("unable to make path '{f}{s}': {s}", .{ |
| 1475 | b.cache_root, sub_path_dirname, @errorName(err), | 1476 | b.cache_root, sub_path_dirname, @errorName(err), |
| 1476 | }); | 1477 | }); |
lib/std/Build/Step/UpdateSourceFiles.zig+1-1| ... | @@ -78,7 +78,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -78,7 +78,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 78 | var any_miss = false; | 78 | var any_miss = false; |
| 79 | for (usf.output_source_files.items) |output_source_file| { | 79 | for (usf.output_source_files.items) |output_source_file| { |
| 80 | if (fs.path.dirname(output_source_file.sub_path)) |dirname| { | 80 | if (fs.path.dirname(output_source_file.sub_path)) |dirname| { |
| 81 | b.build_root.handle.makePath(dirname) catch |err| { | 81 | b.build_root.handle.makePath(io, dirname) catch |err| { |
| 82 | return step.fail("unable to make path '{f}{s}': {t}", .{ b.build_root, dirname, err }); | 82 | return step.fail("unable to make path '{f}{s}': {t}", .{ b.build_root, dirname, err }); |
| 83 | }; | 83 | }; |
| 84 | } | 84 | } |
lib/std/Build/Step/WriteFile.zig+3-3| ... | @@ -268,7 +268,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -268,7 +268,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 268 | 268 | ||
| 269 | for (write_file.files.items) |file| { | 269 | for (write_file.files.items) |file| { |
| 270 | if (fs.path.dirname(file.sub_path)) |dirname| { | 270 | if (fs.path.dirname(file.sub_path)) |dirname| { |
| 271 | cache_dir.makePath(dirname) catch |err| { | 271 | cache_dir.makePath(io, dirname) catch |err| { |
| 272 | return step.fail("unable to make path '{f}{s}{c}{s}': {t}", .{ | 272 | return step.fail("unable to make path '{f}{s}{c}{s}': {t}", .{ |
| 273 | b.cache_root, cache_path, fs.path.sep, dirname, err, | 273 | b.cache_root, cache_path, fs.path.sep, dirname, err, |
| 274 | }); | 274 | }); |
| ... | @@ -303,7 +303,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -303,7 +303,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 303 | const dest_dirname = dir.sub_path; | 303 | const dest_dirname = dir.sub_path; |
| 304 | 304 | ||
| 305 | if (dest_dirname.len != 0) { | 305 | if (dest_dirname.len != 0) { |
| 306 | cache_dir.makePath(dest_dirname) catch |err| { | 306 | cache_dir.makePath(io, dest_dirname) catch |err| { |
| 307 | return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{ | 307 | return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{ |
| 308 | b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err), | 308 | b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err), |
| 309 | }); | 309 | }); |
| ... | @@ -318,7 +318,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -318,7 +318,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 318 | const src_entry_path = try src_dir_path.join(arena, entry.path); | 318 | const src_entry_path = try src_dir_path.join(arena, entry.path); |
| 319 | const dest_path = b.pathJoin(&.{ dest_dirname, entry.path }); | 319 | const dest_path = b.pathJoin(&.{ dest_dirname, entry.path }); |
| 320 | switch (entry.kind) { | 320 | switch (entry.kind) { |
| 321 | .directory => try cache_dir.makePath(dest_path), | 321 | .directory => try cache_dir.makePath(io, dest_path), |
| 322 | .file => { | 322 | .file => { |
| 323 | const prev_status = Io.Dir.updateFile( | 323 | const prev_status = Io.Dir.updateFile( |
| 324 | src_entry_path.root_dir.handle, | 324 | src_entry_path.root_dir.handle, |
lib/std/debug.zig+7-5| ... | @@ -522,7 +522,7 @@ pub fn defaultPanic( | ... | @@ -522,7 +522,7 @@ pub fn defaultPanic( |
| 522 | } | 522 | } |
| 523 | @trap(); | 523 | @trap(); |
| 524 | }, | 524 | }, |
| 525 | .cuda, .amdhsa => std.posix.abort(), | 525 | .cuda, .amdhsa => std.process.abort(), |
| 526 | .plan9 => { | 526 | .plan9 => { |
| 527 | var status: [std.os.plan9.ERRMAX]u8 = undefined; | 527 | var status: [std.os.plan9.ERRMAX]u8 = undefined; |
| 528 | const len = @min(msg.len, status.len - 1); | 528 | const len = @min(msg.len, status.len - 1); |
| ... | @@ -575,12 +575,13 @@ pub fn defaultPanic( | ... | @@ -575,12 +575,13 @@ pub fn defaultPanic( |
| 575 | // A panic happened while trying to print a previous panic message. | 575 | // A panic happened while trying to print a previous panic message. |
| 576 | // We're still holding the mutex but that's fine as we're going to | 576 | // We're still holding the mutex but that's fine as we're going to |
| 577 | // call abort(). | 577 | // call abort(). |
| 578 | File.stderr().writeStreamingAll("aborting due to recursive panic\n") catch {}; | 578 | const stderr, _ = lockStderrWriter(&.{}); |
| 579 | stderr.writeAll("aborting due to recursive panic\n") catch {}; | ||
| 579 | }, | 580 | }, |
| 580 | else => {}, // Panicked while printing the recursive panic message. | 581 | else => {}, // Panicked while printing the recursive panic message. |
| 581 | } | 582 | } |
| 582 | 583 | ||
| 583 | posix.abort(); | 584 | std.process.abort(); |
| 584 | } | 585 | } |
| 585 | 586 | ||
| 586 | /// Must be called only after adding 1 to `panicking`. There are three callsites. | 587 | /// Must be called only after adding 1 to `panicking`. There are three callsites. |
| ... | @@ -1596,7 +1597,8 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex | ... | @@ -1596,7 +1597,8 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex |
| 1596 | // A segfault happened while trying to print a previous panic message. | 1597 | // A segfault happened while trying to print a previous panic message. |
| 1597 | // We're still holding the mutex but that's fine as we're going to | 1598 | // We're still holding the mutex but that's fine as we're going to |
| 1598 | // call abort(). | 1599 | // call abort(). |
| 1599 | File.stderr().writeAll("aborting due to recursive panic\n") catch {}; | 1600 | const stderr, _ = lockStderrWriter(&.{}); |
| 1601 | stderr().writeAll("aborting due to recursive panic\n") catch {}; | ||
| 1600 | }, | 1602 | }, |
| 1601 | else => {}, // Panicked while printing the recursive panic message. | 1603 | else => {}, // Panicked while printing the recursive panic message. |
| 1602 | } | 1604 | } |
| ... | @@ -1604,7 +1606,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex | ... | @@ -1604,7 +1606,7 @@ pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContex |
| 1604 | // We cannot allow the signal handler to return because when it runs the original instruction | 1606 | // We cannot allow the signal handler to return because when it runs the original instruction |
| 1605 | // again, the memory may be mapped and undefined behavior would occur rather than repeating | 1607 | // again, the memory may be mapped and undefined behavior would occur rather than repeating |
| 1606 | // the segfault. So we simply abort here. | 1608 | // the segfault. So we simply abort here. |
| 1607 | posix.abort(); | 1609 | std.process.abort(); |
| 1608 | } | 1610 | } |
| 1609 | 1611 | ||
| 1610 | pub fn dumpStackPointerAddr(prefix: []const u8) void { | 1612 | pub fn dumpStackPointerAddr(prefix: []const u8) void { |
lib/std/fs/test.zig+27-18| ... | @@ -674,7 +674,7 @@ test "Dir.Iterator but dir is deleted during iteration" { | ... | @@ -674,7 +674,7 @@ test "Dir.Iterator but dir is deleted during iteration" { |
| 674 | var iterator = subdir.iterate(); | 674 | var iterator = subdir.iterate(); |
| 675 | 675 | ||
| 676 | // Create something to iterate over within the subdir | 676 | // Create something to iterate over within the subdir |
| 677 | try tmp.dir.makePath("subdir" ++ fs.path.sep_str ++ "b"); | 677 | try tmp.dir.makePath(io, "subdir" ++ fs.path.sep_str ++ "b"); |
| 678 | 678 | ||
| 679 | // Then, before iterating, delete the directory that we're iterating. | 679 | // Then, before iterating, delete the directory that we're iterating. |
| 680 | // This is a contrived reproduction, but this could happen outside of the program, in another thread, etc. | 680 | // This is a contrived reproduction, but this could happen outside of the program, in another thread, etc. |
| ... | @@ -1196,7 +1196,7 @@ test "deleteTree does not follow symlinks" { | ... | @@ -1196,7 +1196,7 @@ test "deleteTree does not follow symlinks" { |
| 1196 | var tmp = tmpDir(.{}); | 1196 | var tmp = tmpDir(.{}); |
| 1197 | defer tmp.cleanup(); | 1197 | defer tmp.cleanup(); |
| 1198 | 1198 | ||
| 1199 | try tmp.dir.makePath("b"); | 1199 | try tmp.dir.makePath(io, "b"); |
| 1200 | { | 1200 | { |
| 1201 | var a = try tmp.dir.makeOpenPath("a", .{}); | 1201 | var a = try tmp.dir.makeOpenPath("a", .{}); |
| 1202 | defer a.close(io); | 1202 | defer a.close(io); |
| ... | @@ -1211,6 +1211,8 @@ test "deleteTree does not follow symlinks" { | ... | @@ -1211,6 +1211,8 @@ test "deleteTree does not follow symlinks" { |
| 1211 | } | 1211 | } |
| 1212 | 1212 | ||
| 1213 | test "deleteTree on a symlink" { | 1213 | test "deleteTree on a symlink" { |
| 1214 | const io = testing.io; | ||
| 1215 | |||
| 1214 | var tmp = tmpDir(.{}); | 1216 | var tmp = tmpDir(.{}); |
| 1215 | defer tmp.cleanup(); | 1217 | defer tmp.cleanup(); |
| 1216 | 1218 | ||
| ... | @@ -1223,7 +1225,7 @@ test "deleteTree on a symlink" { | ... | @@ -1223,7 +1225,7 @@ test "deleteTree on a symlink" { |
| 1223 | try tmp.dir.access("file", .{}); | 1225 | try tmp.dir.access("file", .{}); |
| 1224 | 1226 | ||
| 1225 | // Symlink to a directory | 1227 | // Symlink to a directory |
| 1226 | try tmp.dir.makePath("dir"); | 1228 | try tmp.dir.makePath(io, "dir"); |
| 1227 | try setupSymlink(tmp.dir, "dir", "dirlink", .{ .is_directory = true }); | 1229 | try setupSymlink(tmp.dir, "dir", "dirlink", .{ .is_directory = true }); |
| 1228 | 1230 | ||
| 1229 | try tmp.dir.deleteTree("dirlink"); | 1231 | try tmp.dir.deleteTree("dirlink"); |
| ... | @@ -1238,7 +1240,7 @@ test "makePath, put some files in it, deleteTree" { | ... | @@ -1238,7 +1240,7 @@ test "makePath, put some files in it, deleteTree" { |
| 1238 | const allocator = ctx.arena.allocator(); | 1240 | const allocator = ctx.arena.allocator(); |
| 1239 | const dir_path = try ctx.transformPath("os_test_tmp"); | 1241 | const dir_path = try ctx.transformPath("os_test_tmp"); |
| 1240 | 1242 | ||
| 1241 | try ctx.dir.makePath(try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); | 1243 | try ctx.dir.makePath(io, try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); |
| 1242 | try ctx.dir.writeFile(.{ | 1244 | try ctx.dir.writeFile(.{ |
| 1243 | .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), | 1245 | .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), |
| 1244 | .data = "nonsense", | 1246 | .data = "nonsense", |
| ... | @@ -1261,7 +1263,7 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { | ... | @@ -1261,7 +1263,7 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { |
| 1261 | const allocator = ctx.arena.allocator(); | 1263 | const allocator = ctx.arena.allocator(); |
| 1262 | const dir_path = try ctx.transformPath("os_test_tmp"); | 1264 | const dir_path = try ctx.transformPath("os_test_tmp"); |
| 1263 | 1265 | ||
| 1264 | try ctx.dir.makePath(try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); | 1266 | try ctx.dir.makePath(io, try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c" })); |
| 1265 | try ctx.dir.writeFile(.{ | 1267 | try ctx.dir.writeFile(.{ |
| 1266 | .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), | 1268 | .sub_path = try fs.path.join(allocator, &.{ "os_test_tmp", "b", "c", "file.txt" }), |
| 1267 | .data = "nonsense", | 1269 | .data = "nonsense", |
| ... | @@ -1280,21 +1282,25 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { | ... | @@ -1280,21 +1282,25 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { |
| 1280 | test "makePath in a directory that no longer exists" { | 1282 | test "makePath in a directory that no longer exists" { |
| 1281 | if (native_os == .windows) return error.SkipZigTest; // Windows returns FileBusy if attempting to remove an open dir | 1283 | if (native_os == .windows) return error.SkipZigTest; // Windows returns FileBusy if attempting to remove an open dir |
| 1282 | 1284 | ||
| 1285 | const io = testing.io; | ||
| 1286 | |||
| 1283 | var tmp = tmpDir(.{}); | 1287 | var tmp = tmpDir(.{}); |
| 1284 | defer tmp.cleanup(); | 1288 | defer tmp.cleanup(); |
| 1285 | try tmp.parent_dir.deleteTree(&tmp.sub_path); | 1289 | try tmp.parent_dir.deleteTree(&tmp.sub_path); |
| 1286 | 1290 | ||
| 1287 | try testing.expectError(error.FileNotFound, tmp.dir.makePath("sub-path")); | 1291 | try testing.expectError(error.FileNotFound, tmp.dir.makePath(io, "sub-path")); |
| 1288 | } | 1292 | } |
| 1289 | 1293 | ||
| 1290 | test "makePath but sub_path contains pre-existing file" { | 1294 | test "makePath but sub_path contains pre-existing file" { |
| 1295 | const io = testing.io; | ||
| 1296 | |||
| 1291 | var tmp = tmpDir(.{}); | 1297 | var tmp = tmpDir(.{}); |
| 1292 | defer tmp.cleanup(); | 1298 | defer tmp.cleanup(); |
| 1293 | 1299 | ||
| 1294 | try tmp.dir.makeDir("foo"); | 1300 | try tmp.dir.makeDir("foo"); |
| 1295 | try tmp.dir.writeFile(.{ .sub_path = "foo/bar", .data = "" }); | 1301 | try tmp.dir.writeFile(.{ .sub_path = "foo/bar", .data = "" }); |
| 1296 | 1302 | ||
| 1297 | try testing.expectError(error.NotDir, tmp.dir.makePath("foo/bar/baz")); | 1303 | try testing.expectError(error.NotDir, tmp.dir.makePath(io, "foo/bar/baz")); |
| 1298 | } | 1304 | } |
| 1299 | 1305 | ||
| 1300 | fn expectDir(io: Io, dir: Dir, path: []const u8) !void { | 1306 | fn expectDir(io: Io, dir: Dir, path: []const u8) !void { |
| ... | @@ -1314,7 +1320,7 @@ test "makepath existing directories" { | ... | @@ -1314,7 +1320,7 @@ test "makepath existing directories" { |
| 1314 | try tmpA.makeDir("B"); | 1320 | try tmpA.makeDir("B"); |
| 1315 | 1321 | ||
| 1316 | const testPath = "A" ++ fs.path.sep_str ++ "B" ++ fs.path.sep_str ++ "C"; | 1322 | const testPath = "A" ++ fs.path.sep_str ++ "B" ++ fs.path.sep_str ++ "C"; |
| 1317 | try tmp.dir.makePath(testPath); | 1323 | try tmp.dir.makePath(io, testPath); |
| 1318 | 1324 | ||
| 1319 | try expectDir(io, tmp.dir, testPath); | 1325 | try expectDir(io, tmp.dir, testPath); |
| 1320 | } | 1326 | } |
| ... | @@ -1328,7 +1334,7 @@ test "makepath through existing valid symlink" { | ... | @@ -1328,7 +1334,7 @@ test "makepath through existing valid symlink" { |
| 1328 | try tmp.dir.makeDir("realfolder"); | 1334 | try tmp.dir.makeDir("realfolder"); |
| 1329 | try setupSymlink(tmp.dir, "." ++ fs.path.sep_str ++ "realfolder", "working-symlink", .{}); | 1335 | try setupSymlink(tmp.dir, "." ++ fs.path.sep_str ++ "realfolder", "working-symlink", .{}); |
| 1330 | 1336 | ||
| 1331 | try tmp.dir.makePath("working-symlink" ++ fs.path.sep_str ++ "in-realfolder"); | 1337 | try tmp.dir.makePath(io, "working-symlink" ++ fs.path.sep_str ++ "in-realfolder"); |
| 1332 | 1338 | ||
| 1333 | try expectDir(io, tmp.dir, "realfolder" ++ fs.path.sep_str ++ "in-realfolder"); | 1339 | try expectDir(io, tmp.dir, "realfolder" ++ fs.path.sep_str ++ "in-realfolder"); |
| 1334 | } | 1340 | } |
| ... | @@ -1344,7 +1350,7 @@ test "makepath relative walks" { | ... | @@ -1344,7 +1350,7 @@ test "makepath relative walks" { |
| 1344 | }); | 1350 | }); |
| 1345 | defer testing.allocator.free(relPath); | 1351 | defer testing.allocator.free(relPath); |
| 1346 | 1352 | ||
| 1347 | try tmp.dir.makePath(relPath); | 1353 | try tmp.dir.makePath(io, relPath); |
| 1348 | 1354 | ||
| 1349 | // How .. is handled is different on Windows than non-Windows | 1355 | // How .. is handled is different on Windows than non-Windows |
| 1350 | switch (native_os) { | 1356 | switch (native_os) { |
| ... | @@ -1383,7 +1389,7 @@ test "makepath ignores '.'" { | ... | @@ -1383,7 +1389,7 @@ test "makepath ignores '.'" { |
| 1383 | }); | 1389 | }); |
| 1384 | defer testing.allocator.free(expectedPath); | 1390 | defer testing.allocator.free(expectedPath); |
| 1385 | 1391 | ||
| 1386 | try tmp.dir.makePath(dotPath); | 1392 | try tmp.dir.makePath(io, dotPath); |
| 1387 | 1393 | ||
| 1388 | try expectDir(io, tmp.dir, expectedPath); | 1394 | try expectDir(io, tmp.dir, expectedPath); |
| 1389 | } | 1395 | } |
| ... | @@ -1550,10 +1556,11 @@ test "setEndPos" { | ... | @@ -1550,10 +1556,11 @@ test "setEndPos" { |
| 1550 | test "access file" { | 1556 | test "access file" { |
| 1551 | try testWithAllSupportedPathTypes(struct { | 1557 | try testWithAllSupportedPathTypes(struct { |
| 1552 | fn impl(ctx: *TestContext) !void { | 1558 | fn impl(ctx: *TestContext) !void { |
| 1559 | const io = ctx.io; | ||
| 1553 | const dir_path = try ctx.transformPath("os_test_tmp"); | 1560 | const dir_path = try ctx.transformPath("os_test_tmp"); |
| 1554 | const file_path = try ctx.transformPath("os_test_tmp" ++ fs.path.sep_str ++ "file.txt"); | 1561 | const file_path = try ctx.transformPath("os_test_tmp" ++ fs.path.sep_str ++ "file.txt"); |
| 1555 | 1562 | ||
| 1556 | try ctx.dir.makePath(dir_path); | 1563 | try ctx.dir.makePath(io, dir_path); |
| 1557 | try testing.expectError(error.FileNotFound, ctx.dir.access(file_path, .{})); | 1564 | try testing.expectError(error.FileNotFound, ctx.dir.access(file_path, .{})); |
| 1558 | 1565 | ||
| 1559 | try ctx.dir.writeFile(.{ .sub_path = file_path, .data = "" }); | 1566 | try ctx.dir.writeFile(.{ .sub_path = file_path, .data = "" }); |
| ... | @@ -1569,7 +1576,7 @@ test "sendfile" { | ... | @@ -1569,7 +1576,7 @@ test "sendfile" { |
| 1569 | var tmp = tmpDir(.{}); | 1576 | var tmp = tmpDir(.{}); |
| 1570 | defer tmp.cleanup(); | 1577 | defer tmp.cleanup(); |
| 1571 | 1578 | ||
| 1572 | try tmp.dir.makePath("os_test_tmp"); | 1579 | try tmp.dir.makePath(io, "os_test_tmp"); |
| 1573 | 1580 | ||
| 1574 | var dir = try tmp.dir.openDir(io, "os_test_tmp", .{}); | 1581 | var dir = try tmp.dir.openDir(io, "os_test_tmp", .{}); |
| 1575 | defer dir.close(io); | 1582 | defer dir.close(io); |
| ... | @@ -1616,7 +1623,7 @@ test "sendfile with buffered data" { | ... | @@ -1616,7 +1623,7 @@ test "sendfile with buffered data" { |
| 1616 | var tmp = tmpDir(.{}); | 1623 | var tmp = tmpDir(.{}); |
| 1617 | defer tmp.cleanup(); | 1624 | defer tmp.cleanup(); |
| 1618 | 1625 | ||
| 1619 | try tmp.dir.makePath("os_test_tmp"); | 1626 | try tmp.dir.makePath(io, "os_test_tmp"); |
| 1620 | 1627 | ||
| 1621 | var dir = try tmp.dir.openDir(io, "os_test_tmp", .{}); | 1628 | var dir = try tmp.dir.openDir(io, "os_test_tmp", .{}); |
| 1622 | defer dir.close(io); | 1629 | defer dir.close(io); |
| ... | @@ -1894,7 +1901,7 @@ test "walker" { | ... | @@ -1894,7 +1901,7 @@ test "walker" { |
| 1894 | }); | 1901 | }); |
| 1895 | 1902 | ||
| 1896 | for (expected_paths.keys()) |key| { | 1903 | for (expected_paths.keys()) |key| { |
| 1897 | try tmp.dir.makePath(key); | 1904 | try tmp.dir.makePath(io, key); |
| 1898 | } | 1905 | } |
| 1899 | 1906 | ||
| 1900 | var walker = try tmp.dir.walk(testing.allocator); | 1907 | var walker = try tmp.dir.walk(testing.allocator); |
| ... | @@ -1956,7 +1963,7 @@ test "selective walker, skip entries that start with ." { | ... | @@ -1956,7 +1963,7 @@ test "selective walker, skip entries that start with ." { |
| 1956 | }); | 1963 | }); |
| 1957 | 1964 | ||
| 1958 | for (paths_to_create) |path| { | 1965 | for (paths_to_create) |path| { |
| 1959 | try tmp.dir.makePath(path); | 1966 | try tmp.dir.makePath(io, path); |
| 1960 | } | 1967 | } |
| 1961 | 1968 | ||
| 1962 | var walker = try tmp.dir.walkSelectively(testing.allocator); | 1969 | var walker = try tmp.dir.walkSelectively(testing.allocator); |
| ... | @@ -1991,6 +1998,8 @@ test "selective walker, skip entries that start with ." { | ... | @@ -1991,6 +1998,8 @@ test "selective walker, skip entries that start with ." { |
| 1991 | } | 1998 | } |
| 1992 | 1999 | ||
| 1993 | test "walker without fully iterating" { | 2000 | test "walker without fully iterating" { |
| 2001 | const io = testing.io; | ||
| 2002 | |||
| 1994 | var tmp = tmpDir(.{ .iterate = true }); | 2003 | var tmp = tmpDir(.{ .iterate = true }); |
| 1995 | defer tmp.cleanup(); | 2004 | defer tmp.cleanup(); |
| 1996 | 2005 | ||
| ... | @@ -2000,8 +2009,8 @@ test "walker without fully iterating" { | ... | @@ -2000,8 +2009,8 @@ test "walker without fully iterating" { |
| 2000 | // Create 2 directories inside the tmp directory, but then only iterate once before breaking. | 2009 | // Create 2 directories inside the tmp directory, but then only iterate once before breaking. |
| 2001 | // This ensures that walker doesn't try to close the initial directory when not fully iterating. | 2010 | // This ensures that walker doesn't try to close the initial directory when not fully iterating. |
| 2002 | 2011 | ||
| 2003 | try tmp.dir.makePath("a"); | 2012 | try tmp.dir.makePath(io, "a"); |
| 2004 | try tmp.dir.makePath("b"); | 2013 | try tmp.dir.makePath(io, "b"); |
| 2005 | 2014 | ||
| 2006 | var num_walked: usize = 0; | 2015 | var num_walked: usize = 0; |
| 2007 | while (try walker.next()) |_| { | 2016 | while (try walker.next()) |_| { |
lib/std/os/linux/IoUring.zig-26| ... | @@ -4090,32 +4090,6 @@ test "openat_direct/close_direct" { | ... | @@ -4090,32 +4090,6 @@ test "openat_direct/close_direct" { |
| 4090 | try ring.unregister_files(); | 4090 | try ring.unregister_files(); |
| 4091 | } | 4091 | } |
| 4092 | 4092 | ||
| 4093 | test "waitid" { | ||
| 4094 | try skipKernelLessThan(.{ .major = 6, .minor = 7, .patch = 0 }); | ||
| 4095 | |||
| 4096 | var ring = IoUring.init(16, 0) catch |err| switch (err) { | ||
| 4097 | error.SystemOutdated => return error.SkipZigTest, | ||
| 4098 | error.PermissionDenied => return error.SkipZigTest, | ||
| 4099 | else => return err, | ||
| 4100 | }; | ||
| 4101 | defer ring.deinit(); | ||
| 4102 | |||
| 4103 | const pid = try posix.fork(); | ||
| 4104 | if (pid == 0) { | ||
| 4105 | posix.exit(7); | ||
| 4106 | } | ||
| 4107 | |||
| 4108 | var siginfo: posix.siginfo_t = undefined; | ||
| 4109 | _ = try ring.waitid(0, .PID, pid, &siginfo, posix.W.EXITED, 0); | ||
| 4110 | |||
| 4111 | try testing.expectEqual(1, try ring.submit()); | ||
| 4112 | |||
| 4113 | const cqe_waitid = try ring.copy_cqe(); | ||
| 4114 | try testing.expectEqual(0, cqe_waitid.res); | ||
| 4115 | try testing.expectEqual(pid, siginfo.fields.common.first.piduid.pid); | ||
| 4116 | try testing.expectEqual(7, siginfo.fields.common.second.sigchld.status); | ||
| 4117 | } | ||
| 4118 | |||
| 4119 | /// For use in tests. Returns SkipZigTest if kernel version is less than required. | 4093 | /// For use in tests. Returns SkipZigTest if kernel version is less than required. |
| 4120 | inline fn skipKernelLessThan(required: std.SemanticVersion) !void { | 4094 | inline fn skipKernelLessThan(required: std.SemanticVersion) !void { |
| 4121 | if (!is_linux) return error.SkipZigTest; | 4095 | if (!is_linux) return error.SkipZigTest; |
lib/std/posix.zig-87| ... | @@ -615,66 +615,6 @@ fn getRandomBytesDevURandom(buf: []u8) GetRandomError!void { | ... | @@ -615,66 +615,6 @@ fn getRandomBytesDevURandom(buf: []u8) GetRandomError!void { |
| 615 | } | 615 | } |
| 616 | } | 616 | } |
| 617 | 617 | ||
| 618 | /// Causes abnormal process termination. | ||
| 619 | /// If linking against libc, this calls the abort() libc function. Otherwise | ||
| 620 | /// it raises SIGABRT followed by SIGKILL and finally lo | ||
| 621 | /// Invokes the current signal handler for SIGABRT, if any. | ||
| 622 | pub fn abort() noreturn { | ||
| 623 | @branchHint(.cold); | ||
| 624 | // MSVCRT abort() sometimes opens a popup window which is undesirable, so | ||
| 625 | // even when linking libc on Windows we use our own abort implementation. | ||
| 626 | // See https://github.com/ziglang/zig/issues/2071 for more details. | ||
| 627 | if (native_os == .windows) { | ||
| 628 | if (builtin.mode == .Debug and windows.peb().BeingDebugged != 0) { | ||
| 629 | @breakpoint(); | ||
| 630 | } | ||
| 631 | windows.ntdll.RtlExitUserProcess(3); | ||
| 632 | } | ||
| 633 | if (!builtin.link_libc and native_os == .linux) { | ||
| 634 | // The Linux man page says that the libc abort() function | ||
| 635 | // "first unblocks the SIGABRT signal", but this is a footgun | ||
| 636 | // for user-defined signal handlers that want to restore some state in | ||
| 637 | // some program sections and crash in others. | ||
| 638 | // So, the user-installed SIGABRT handler is run, if present. | ||
| 639 | raise(.ABRT) catch {}; | ||
| 640 | |||
| 641 | // Disable all signal handlers. | ||
| 642 | const filledset = linux.sigfillset(); | ||
| 643 | sigprocmask(SIG.BLOCK, &filledset, null); | ||
| 644 | |||
| 645 | // Only one thread may proceed to the rest of abort(). | ||
| 646 | if (!builtin.single_threaded) { | ||
| 647 | const global = struct { | ||
| 648 | var abort_entered: bool = false; | ||
| 649 | }; | ||
| 650 | while (@cmpxchgWeak(bool, &global.abort_entered, false, true, .seq_cst, .seq_cst)) |_| {} | ||
| 651 | } | ||
| 652 | |||
| 653 | // Install default handler so that the tkill below will terminate. | ||
| 654 | const sigact = Sigaction{ | ||
| 655 | .handler = .{ .handler = SIG.DFL }, | ||
| 656 | .mask = sigemptyset(), | ||
| 657 | .flags = 0, | ||
| 658 | }; | ||
| 659 | sigaction(.ABRT, &sigact, null); | ||
| 660 | |||
| 661 | _ = linux.tkill(linux.gettid(), .ABRT); | ||
| 662 | |||
| 663 | var sigabrtmask = sigemptyset(); | ||
| 664 | sigaddset(&sigabrtmask, .ABRT); | ||
| 665 | sigprocmask(SIG.UNBLOCK, &sigabrtmask, null); | ||
| 666 | |||
| 667 | // Beyond this point should be unreachable. | ||
| 668 | @as(*allowzero volatile u8, @ptrFromInt(0)).* = 0; | ||
| 669 | raise(.KILL) catch {}; | ||
| 670 | exit(127); // Pid 1 might not be signalled in some containers. | ||
| 671 | } | ||
| 672 | switch (native_os) { | ||
| 673 | .uefi, .wasi, .emscripten, .cuda, .amdhsa => @trap(), | ||
| 674 | else => system.abort(), | ||
| 675 | } | ||
| 676 | } | ||
| 677 | |||
| 678 | pub const RaiseError = UnexpectedError; | 618 | pub const RaiseError = UnexpectedError; |
| 679 | 619 | ||
| 680 | pub fn raise(sig: SIG) RaiseError!void { | 620 | pub fn raise(sig: SIG) RaiseError!void { |
| ... | @@ -715,33 +655,6 @@ pub fn kill(pid: pid_t, sig: SIG) KillError!void { | ... | @@ -715,33 +655,6 @@ pub fn kill(pid: pid_t, sig: SIG) KillError!void { |
| 715 | } | 655 | } |
| 716 | } | 656 | } |
| 717 | 657 | ||
| 718 | /// Exits all threads of the program with the specified status code. | ||
| 719 | pub fn exit(status: u8) noreturn { | ||
| 720 | if (builtin.link_libc) { | ||
| 721 | std.c.exit(status); | ||
| 722 | } | ||
| 723 | if (native_os == .windows) { | ||
| 724 | windows.ntdll.RtlExitUserProcess(status); | ||
| 725 | } | ||
| 726 | if (native_os == .wasi) { | ||
| 727 | wasi.proc_exit(status); | ||
| 728 | } | ||
| 729 | if (native_os == .linux and !builtin.single_threaded) { | ||
| 730 | linux.exit_group(status); | ||
| 731 | } | ||
| 732 | if (native_os == .uefi) { | ||
| 733 | const uefi = std.os.uefi; | ||
| 734 | // exit() is only available if exitBootServices() has not been called yet. | ||
| 735 | // This call to exit should not fail, so we catch-ignore errors. | ||
| 736 | if (uefi.system_table.boot_services) |bs| { | ||
| 737 | bs.exit(uefi.handle, @enumFromInt(status), null) catch {}; | ||
| 738 | } | ||
| 739 | // If we can't exit, reboot the system instead. | ||
| 740 | uefi.system_table.runtime_services.resetSystem(.cold, @enumFromInt(status), null); | ||
| 741 | } | ||
| 742 | system.exit(status); | ||
| 743 | } | ||
| 744 | |||
| 745 | pub const ReadError = std.Io.File.Reader.Error; | 658 | pub const ReadError = std.Io.File.Reader.Error; |
| 746 | 659 | ||
| 747 | /// Returns the number of bytes that were read, which can be less than | 660 | /// Returns the number of bytes that were read, which can be less than |
lib/std/posix/test.zig-67| ... | @@ -667,73 +667,6 @@ test "writev longer than IOV_MAX" { | ... | @@ -667,73 +667,6 @@ test "writev longer than IOV_MAX" { |
| 667 | try testing.expectEqual(@as(usize, posix.IOV_MAX), amt); | 667 | try testing.expectEqual(@as(usize, posix.IOV_MAX), amt); |
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | test "POSIX file locking with fcntl" { | ||
| 671 | if (native_os == .windows or native_os == .wasi) { | ||
| 672 | // Not POSIX. | ||
| 673 | return error.SkipZigTest; | ||
| 674 | } | ||
| 675 | |||
| 676 | if (true) { | ||
| 677 | // https://github.com/ziglang/zig/issues/11074 | ||
| 678 | return error.SkipZigTest; | ||
| 679 | } | ||
| 680 | |||
| 681 | const io = testing.io; | ||
| 682 | |||
| 683 | var tmp = tmpDir(.{}); | ||
| 684 | defer tmp.cleanup(); | ||
| 685 | |||
| 686 | // Create a temporary lock file | ||
| 687 | var file = try tmp.dir.createFile(io, "lock", .{ .read = true }); | ||
| 688 | defer file.close(io); | ||
| 689 | try file.setEndPos(2); | ||
| 690 | const fd = file.handle; | ||
| 691 | |||
| 692 | // Place an exclusive lock on the first byte, and a shared lock on the second byte: | ||
| 693 | var struct_flock = std.mem.zeroInit(posix.Flock, .{ .type = posix.F.WRLCK }); | ||
| 694 | _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); | ||
| 695 | struct_flock.start = 1; | ||
| 696 | struct_flock.type = posix.F.RDLCK; | ||
| 697 | _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); | ||
| 698 | |||
| 699 | // Check the locks in a child process: | ||
| 700 | const pid = try posix.fork(); | ||
| 701 | if (pid == 0) { | ||
| 702 | // child expects be denied the exclusive lock: | ||
| 703 | struct_flock.start = 0; | ||
| 704 | struct_flock.type = posix.F.WRLCK; | ||
| 705 | try expectError(error.Locked, posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock))); | ||
| 706 | // child expects to get the shared lock: | ||
| 707 | struct_flock.start = 1; | ||
| 708 | struct_flock.type = posix.F.RDLCK; | ||
| 709 | _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); | ||
| 710 | // child waits for the exclusive lock in order to test deadlock: | ||
| 711 | struct_flock.start = 0; | ||
| 712 | struct_flock.type = posix.F.WRLCK; | ||
| 713 | _ = try posix.fcntl(fd, posix.F.SETLKW, @intFromPtr(&struct_flock)); | ||
| 714 | // child exits without continuing: | ||
| 715 | posix.exit(0); | ||
| 716 | } else { | ||
| 717 | // parent waits for child to get shared lock: | ||
| 718 | std.Thread.sleep(1 * std.time.ns_per_ms); | ||
| 719 | // parent expects deadlock when attempting to upgrade the shared lock to exclusive: | ||
| 720 | struct_flock.start = 1; | ||
| 721 | struct_flock.type = posix.F.WRLCK; | ||
| 722 | try expectError(error.DeadLock, posix.fcntl(fd, posix.F.SETLKW, @intFromPtr(&struct_flock))); | ||
| 723 | // parent releases exclusive lock: | ||
| 724 | struct_flock.start = 0; | ||
| 725 | struct_flock.type = posix.F.UNLCK; | ||
| 726 | _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); | ||
| 727 | // parent releases shared lock: | ||
| 728 | struct_flock.start = 1; | ||
| 729 | struct_flock.type = posix.F.UNLCK; | ||
| 730 | _ = try posix.fcntl(fd, posix.F.SETLK, @intFromPtr(&struct_flock)); | ||
| 731 | // parent waits for child: | ||
| 732 | const result = posix.waitpid(pid, 0); | ||
| 733 | try expect(result.status == 0 * 256); | ||
| 734 | } | ||
| 735 | } | ||
| 736 | |||
| 737 | test "rename smoke test" { | 670 | test "rename smoke test" { |
| 738 | if (native_os == .wasi) return error.SkipZigTest; | 671 | if (native_os == .wasi) return error.SkipZigTest; |
| 739 | if (native_os == .windows) return error.SkipZigTest; | 672 | if (native_os == .windows) return error.SkipZigTest; |
lib/std/process.zig+84-2| ... | @@ -16,8 +16,6 @@ const unicode = std.unicode; | ... | @@ -16,8 +16,6 @@ const unicode = std.unicode; |
| 16 | const max_path_bytes = std.fs.max_path_bytes; | 16 | const max_path_bytes = std.fs.max_path_bytes; |
| 17 | 17 | ||
| 18 | pub const Child = @import("process/Child.zig"); | 18 | pub const Child = @import("process/Child.zig"); |
| 19 | pub const abort = posix.abort; | ||
| 20 | pub const exit = posix.exit; | ||
| 21 | pub const changeCurDir = posix.chdir; | 19 | pub const changeCurDir = posix.chdir; |
| 22 | pub const changeCurDirZ = posix.chdirZ; | 20 | pub const changeCurDirZ = posix.chdirZ; |
| 23 | 21 | ||
| ... | @@ -2208,3 +2206,87 @@ pub const OpenExecutableError = File.OpenError || ExecutablePathError || File.Lo | ... | @@ -2208,3 +2206,87 @@ pub const OpenExecutableError = File.OpenError || ExecutablePathError || File.Lo |
| 2208 | pub fn openExecutable(io: Io, flags: File.OpenFlags) OpenExecutableError!File { | 2206 | pub fn openExecutable(io: Io, flags: File.OpenFlags) OpenExecutableError!File { |
| 2209 | return io.vtable.processExecutableOpen(io.userdata, flags); | 2207 | return io.vtable.processExecutableOpen(io.userdata, flags); |
| 2210 | } | 2208 | } |
| 2209 | |||
| 2210 | /// Causes abnormal process termination. | ||
| 2211 | /// | ||
| 2212 | /// If linking against libc, this calls `std.c.abort`. Otherwise it raises | ||
| 2213 | /// SIGABRT followed by SIGKILL. | ||
| 2214 | /// | ||
| 2215 | /// Invokes the current signal handler for SIGABRT, if any. | ||
| 2216 | pub fn abort() noreturn { | ||
| 2217 | @branchHint(.cold); | ||
| 2218 | // MSVCRT abort() sometimes opens a popup window which is undesirable, so | ||
| 2219 | // even when linking libc on Windows we use our own abort implementation. | ||
| 2220 | // See https://github.com/ziglang/zig/issues/2071 for more details. | ||
| 2221 | if (native_os == .windows) { | ||
| 2222 | if (builtin.mode == .Debug and windows.peb().BeingDebugged != 0) { | ||
| 2223 | @breakpoint(); | ||
| 2224 | } | ||
| 2225 | windows.ntdll.RtlExitUserProcess(3); | ||
| 2226 | } | ||
| 2227 | if (!builtin.link_libc and native_os == .linux) { | ||
| 2228 | // The Linux man page says that the libc abort() function | ||
| 2229 | // "first unblocks the SIGABRT signal", but this is a footgun | ||
| 2230 | // for user-defined signal handlers that want to restore some state in | ||
| 2231 | // some program sections and crash in others. | ||
| 2232 | // So, the user-installed SIGABRT handler is run, if present. | ||
| 2233 | posix.raise(.ABRT) catch {}; | ||
| 2234 | |||
| 2235 | // Disable all signal handlers. | ||
| 2236 | const filledset = std.os.linux.sigfillset(); | ||
| 2237 | posix.sigprocmask(posix.SIG.BLOCK, &filledset, null); | ||
| 2238 | |||
| 2239 | // Only one thread may proceed to the rest of abort(). | ||
| 2240 | if (!builtin.single_threaded) { | ||
| 2241 | const global = struct { | ||
| 2242 | var abort_entered: bool = false; | ||
| 2243 | }; | ||
| 2244 | while (@cmpxchgWeak(bool, &global.abort_entered, false, true, .seq_cst, .seq_cst)) |_| {} | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | // Install default handler so that the tkill below will terminate. | ||
| 2248 | const sigact: posix.Sigaction = .{ | ||
| 2249 | .handler = .{ .handler = posix.SIG.DFL }, | ||
| 2250 | .mask = posix.sigemptyset(), | ||
| 2251 | .flags = 0, | ||
| 2252 | }; | ||
| 2253 | posix.sigaction(.ABRT, &sigact, null); | ||
| 2254 | |||
| 2255 | _ = std.os.linux.tkill(std.os.linux.gettid(), .ABRT); | ||
| 2256 | |||
| 2257 | var sigabrtmask = posix.sigemptyset(); | ||
| 2258 | posix.sigaddset(&sigabrtmask, .ABRT); | ||
| 2259 | posix.sigprocmask(posix.SIG.UNBLOCK, &sigabrtmask, null); | ||
| 2260 | |||
| 2261 | // Beyond this point should be unreachable. | ||
| 2262 | @as(*allowzero volatile u8, @ptrFromInt(0)).* = 0; | ||
| 2263 | posix.raise(.KILL) catch {}; | ||
| 2264 | exit(127); // Pid 1 might not be signalled in some containers. | ||
| 2265 | } | ||
| 2266 | switch (native_os) { | ||
| 2267 | .uefi, .wasi, .emscripten, .cuda, .amdhsa => @trap(), | ||
| 2268 | else => posix.system.abort(), | ||
| 2269 | } | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | /// Exits all threads of the program with the specified status code. | ||
| 2273 | pub fn exit(status: u8) noreturn { | ||
| 2274 | if (builtin.link_libc) { | ||
| 2275 | std.c.exit(status); | ||
| 2276 | } else switch (native_os) { | ||
| 2277 | .windows => windows.ntdll.RtlExitUserProcess(status), | ||
| 2278 | .wasi => std.os.wasi.proc_exit(status), | ||
| 2279 | .linux => if (!builtin.single_threaded) std.os.linux.exit_group(status), | ||
| 2280 | .uefi => { | ||
| 2281 | const uefi = std.os.uefi; | ||
| 2282 | // exit() is only available if exitBootServices() has not been called yet. | ||
| 2283 | // This call to exit should not fail, so we catch-ignore errors. | ||
| 2284 | if (uefi.system_table.boot_services) |bs| { | ||
| 2285 | bs.exit(uefi.handle, @enumFromInt(status), null) catch {}; | ||
| 2286 | } | ||
| 2287 | // If we can't exit, reboot the system instead. | ||
| 2288 | uefi.system_table.runtime_services.resetSystem(.cold, @enumFromInt(status), null); | ||
| 2289 | }, | ||
| 2290 | else => posix.system.exit(status), | ||
| 2291 | } | ||
| 2292 | } |
lib/std/process/Child.zig+1-1| ... | @@ -1050,7 +1050,7 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { | ... | @@ -1050,7 +1050,7 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { |
| 1050 | // The _exit(2) function does nothing but make the exit syscall, unlike exit(3) | 1050 | // The _exit(2) function does nothing but make the exit syscall, unlike exit(3) |
| 1051 | std.c._exit(1); | 1051 | std.c._exit(1); |
| 1052 | } | 1052 | } |
| 1053 | posix.exit(1); | 1053 | posix.system.exit(1); |
| 1054 | } | 1054 | } |
| 1055 | 1055 | ||
| 1056 | fn writeIntFd(fd: i32, value: ErrInt) !void { | 1056 | fn writeIntFd(fd: i32, value: ErrInt) !void { |
lib/std/start.zig+3-3| ... | @@ -110,7 +110,7 @@ fn main2() callconv(.c) c_int { | ... | @@ -110,7 +110,7 @@ fn main2() callconv(.c) c_int { |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | fn _start2() callconv(.withStackAlign(.c, 1)) noreturn { | 112 | fn _start2() callconv(.withStackAlign(.c, 1)) noreturn { |
| 113 | std.posix.exit(callMain()); | 113 | std.process.exit(callMain()); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | fn spirvMain2() callconv(.kernel) void { | 116 | fn spirvMain2() callconv(.kernel) void { |
| ... | @@ -118,7 +118,7 @@ fn spirvMain2() callconv(.kernel) void { | ... | @@ -118,7 +118,7 @@ fn spirvMain2() callconv(.kernel) void { |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | fn wWinMainCRTStartup2() callconv(.c) noreturn { | 120 | fn wWinMainCRTStartup2() callconv(.c) noreturn { |
| 121 | std.posix.exit(callMain()); | 121 | std.process.exit(callMain()); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | //////////////////////////////////////////////////////////////////////////////// | 124 | //////////////////////////////////////////////////////////////////////////////// |
| ... | @@ -627,7 +627,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { | ... | @@ -627,7 +627,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { |
| 627 | for (slice) |func| func(); | 627 | for (slice) |func| func(); |
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | std.posix.exit(callMainWithArgs(argc, argv, envp)); | 630 | std.process.exit(callMainWithArgs(argc, argv, envp)); |
| 631 | } | 631 | } |
| 632 | 632 | ||
| 633 | fn expandStackSize(phdrs: []elf.Phdr) void { | 633 | fn expandStackSize(phdrs: []elf.Phdr) void { |
lib/std/tar.zig+8-8| ... | @@ -606,7 +606,7 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp | ... | @@ -606,7 +606,7 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp |
| 606 | switch (file.kind) { | 606 | switch (file.kind) { |
| 607 | .directory => { | 607 | .directory => { |
| 608 | if (file_name.len > 0 and !options.exclude_empty_directories) { | 608 | if (file_name.len > 0 and !options.exclude_empty_directories) { |
| 609 | try dir.makePath(file_name); | 609 | try dir.makePath(io, file_name); |
| 610 | } | 610 | } |
| 611 | }, | 611 | }, |
| 612 | .file => { | 612 | .file => { |
| ... | @@ -625,7 +625,7 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp | ... | @@ -625,7 +625,7 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp |
| 625 | }, | 625 | }, |
| 626 | .sym_link => { | 626 | .sym_link => { |
| 627 | const link_name = file.link_name; | 627 | const link_name = file.link_name; |
| 628 | createDirAndSymlink(dir, link_name, file_name) catch |err| { | 628 | createDirAndSymlink(io, dir, link_name, file_name) catch |err| { |
| 629 | const d = options.diagnostics orelse return error.UnableToCreateSymLink; | 629 | const d = options.diagnostics orelse return error.UnableToCreateSymLink; |
| 630 | try d.errors.append(d.allocator, .{ .unable_to_create_sym_link = .{ | 630 | try d.errors.append(d.allocator, .{ .unable_to_create_sym_link = .{ |
| 631 | .code = err, | 631 | .code = err, |
| ... | @@ -642,7 +642,7 @@ fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, mode: Io.File.Mo | ... | @@ -642,7 +642,7 @@ fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, mode: Io.File.Mo |
| 642 | const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }) catch |err| { | 642 | const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }) catch |err| { |
| 643 | if (err == error.FileNotFound) { | 643 | if (err == error.FileNotFound) { |
| 644 | if (std.fs.path.dirname(file_name)) |dir_name| { | 644 | if (std.fs.path.dirname(file_name)) |dir_name| { |
| 645 | try dir.makePath(dir_name); | 645 | try dir.makePath(io, dir_name); |
| 646 | return try dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }); | 646 | return try dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }); |
| 647 | } | 647 | } |
| 648 | } | 648 | } |
| ... | @@ -652,11 +652,11 @@ fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, mode: Io.File.Mo | ... | @@ -652,11 +652,11 @@ fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, mode: Io.File.Mo |
| 652 | } | 652 | } |
| 653 | 653 | ||
| 654 | // Creates a symbolic link at path `file_name` which points to `link_name`. | 654 | // Creates a symbolic link at path `file_name` which points to `link_name`. |
| 655 | fn createDirAndSymlink(dir: Io.Dir, link_name: []const u8, file_name: []const u8) !void { | 655 | fn createDirAndSymlink(io: Io, dir: Io.Dir, link_name: []const u8, file_name: []const u8) !void { |
| 656 | dir.symLink(link_name, file_name, .{}) catch |err| { | 656 | dir.symLink(link_name, file_name, .{}) catch |err| { |
| 657 | if (err == error.FileNotFound) { | 657 | if (err == error.FileNotFound) { |
| 658 | if (std.fs.path.dirname(file_name)) |dir_name| { | 658 | if (std.fs.path.dirname(file_name)) |dir_name| { |
| 659 | try dir.makePath(dir_name); | 659 | try dir.makePath(io, dir_name); |
| 660 | return try dir.symLink(link_name, file_name, .{}); | 660 | return try dir.symLink(link_name, file_name, .{}); |
| 661 | } | 661 | } |
| 662 | } | 662 | } |
| ... | @@ -885,15 +885,15 @@ test "create file and symlink" { | ... | @@ -885,15 +885,15 @@ test "create file and symlink" { |
| 885 | file = try createDirAndFile(io, root.dir, "a/b/c/file2", default_mode); | 885 | file = try createDirAndFile(io, root.dir, "a/b/c/file2", default_mode); |
| 886 | file.close(io); | 886 | file.close(io); |
| 887 | 887 | ||
| 888 | createDirAndSymlink(root.dir, "a/b/c/file2", "symlink1") catch |err| { | 888 | createDirAndSymlink(io, root.dir, "a/b/c/file2", "symlink1") catch |err| { |
| 889 | // On Windows when developer mode is not enabled | 889 | // On Windows when developer mode is not enabled |
| 890 | if (err == error.AccessDenied) return error.SkipZigTest; | 890 | if (err == error.AccessDenied) return error.SkipZigTest; |
| 891 | return err; | 891 | return err; |
| 892 | }; | 892 | }; |
| 893 | try createDirAndSymlink(root.dir, "../../../file1", "d/e/f/symlink2"); | 893 | try createDirAndSymlink(io, root.dir, "../../../file1", "d/e/f/symlink2"); |
| 894 | 894 | ||
| 895 | // Danglink symlnik, file created later | 895 | // Danglink symlnik, file created later |
| 896 | try createDirAndSymlink(root.dir, "../../../g/h/i/file4", "j/k/l/symlink3"); | 896 | try createDirAndSymlink(io, root.dir, "../../../g/h/i/file4", "j/k/l/symlink3"); |
| 897 | file = try createDirAndFile(io, root.dir, "g/h/i/file4", default_mode); | 897 | file = try createDirAndFile(io, root.dir, "g/h/i/file4", default_mode); |
| 898 | file.close(io); | 898 | file.close(io); |
| 899 | } | 899 | } |
lib/std/zip.zig+3-3| ... | @@ -464,6 +464,8 @@ pub const Iterator = struct { | ... | @@ -464,6 +464,8 @@ pub const Iterator = struct { |
| 464 | filename_buf: []u8, | 464 | filename_buf: []u8, |
| 465 | dest: Io.Dir, | 465 | dest: Io.Dir, |
| 466 | ) !void { | 466 | ) !void { |
| 467 | const io = stream.io; | ||
| 468 | |||
| 467 | if (filename_buf.len < self.filename_len) | 469 | if (filename_buf.len < self.filename_len) |
| 468 | return error.ZipInsufficientBuffer; | 470 | return error.ZipInsufficientBuffer; |
| 469 | switch (self.compression_method) { | 471 | switch (self.compression_method) { |
| ... | @@ -552,12 +554,10 @@ pub const Iterator = struct { | ... | @@ -552,12 +554,10 @@ pub const Iterator = struct { |
| 552 | if (filename[filename.len - 1] == '/') { | 554 | if (filename[filename.len - 1] == '/') { |
| 553 | if (self.uncompressed_size != 0) | 555 | if (self.uncompressed_size != 0) |
| 554 | return error.ZipBadDirectorySize; | 556 | return error.ZipBadDirectorySize; |
| 555 | try dest.makePath(filename[0 .. filename.len - 1]); | 557 | try dest.makePath(io, filename[0 .. filename.len - 1]); |
| 556 | return; | 558 | return; |
| 557 | } | 559 | } |
| 558 | 560 | ||
| 559 | const io = stream.io; | ||
| 560 | |||
| 561 | const out_file = blk: { | 561 | const out_file = blk: { |
| 562 | if (std.fs.path.dirname(filename)) |dirname| { | 562 | if (std.fs.path.dirname(filename)) |dirname| { |
| 563 | var parent_dir = try dest.makeOpenPath(dirname, .{}); | 563 | var parent_dir = try dest.makeOpenPath(dirname, .{}); |
src/Compilation.zig+6-4| ... | @@ -3180,7 +3180,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE | ... | @@ -3180,7 +3180,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE |
| 3180 | const s = fs.path.sep_str; | 3180 | const s = fs.path.sep_str; |
| 3181 | const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int); | 3181 | const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int); |
| 3182 | const o_sub_path = "o" ++ s ++ hex_digest; | 3182 | const o_sub_path = "o" ++ s ++ hex_digest; |
| 3183 | renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| { | 3183 | renameTmpIntoCache(io, comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| { |
| 3184 | return comp.setMiscFailure( | 3184 | return comp.setMiscFailure( |
| 3185 | .rename_results, | 3185 | .rename_results, |
| 3186 | "failed to rename compilation results ('{f}{s}') into local cache ('{f}{s}'): {t}", | 3186 | "failed to rename compilation results ('{f}{s}') into local cache ('{f}{s}'): {t}", |
| ... | @@ -3399,17 +3399,19 @@ fn flush( | ... | @@ -3399,17 +3399,19 @@ fn flush( |
| 3399 | /// implementation at the bottom of this function. | 3399 | /// implementation at the bottom of this function. |
| 3400 | /// This function is only called when CacheMode is `whole`. | 3400 | /// This function is only called when CacheMode is `whole`. |
| 3401 | fn renameTmpIntoCache( | 3401 | fn renameTmpIntoCache( |
| 3402 | io: Io, | ||
| 3402 | cache_directory: Cache.Directory, | 3403 | cache_directory: Cache.Directory, |
| 3403 | tmp_dir_sub_path: []const u8, | 3404 | tmp_dir_sub_path: []const u8, |
| 3404 | o_sub_path: []const u8, | 3405 | o_sub_path: []const u8, |
| 3405 | ) !void { | 3406 | ) !void { |
| 3406 | var seen_eaccess = false; | 3407 | var seen_eaccess = false; |
| 3407 | while (true) { | 3408 | while (true) { |
| 3408 | fs.rename( | 3409 | Io.Dir.rename( |
| 3409 | cache_directory.handle, | 3410 | cache_directory.handle, |
| 3410 | tmp_dir_sub_path, | 3411 | tmp_dir_sub_path, |
| 3411 | cache_directory.handle, | 3412 | cache_directory.handle, |
| 3412 | o_sub_path, | 3413 | o_sub_path, |
| 3414 | io, | ||
| 3413 | ) catch |err| switch (err) { | 3415 | ) catch |err| switch (err) { |
| 3414 | // On Windows, rename fails with `AccessDenied` rather than `PathAlreadyExists`. | 3416 | // On Windows, rename fails with `AccessDenied` rather than `PathAlreadyExists`. |
| 3415 | // See https://github.com/ziglang/zig/issues/8362 | 3417 | // See https://github.com/ziglang/zig/issues/8362 |
| ... | @@ -3427,7 +3429,7 @@ fn renameTmpIntoCache( | ... | @@ -3427,7 +3429,7 @@ fn renameTmpIntoCache( |
| 3427 | continue; | 3429 | continue; |
| 3428 | }, | 3430 | }, |
| 3429 | error.FileNotFound => { | 3431 | error.FileNotFound => { |
| 3430 | try cache_directory.handle.makePath("o"); | 3432 | try cache_directory.handle.makePath(io, "o"); |
| 3431 | continue; | 3433 | continue; |
| 3432 | }, | 3434 | }, |
| 3433 | else => |e| return e, | 3435 | else => |e| return e, |
| ... | @@ -5816,7 +5818,7 @@ pub fn translateC( | ... | @@ -5816,7 +5818,7 @@ pub fn translateC( |
| 5816 | const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; | 5818 | const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; |
| 5817 | 5819 | ||
| 5818 | if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path }); | 5820 | if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path }); |
| 5819 | try renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path); | 5821 | try renameTmpIntoCache(io, comp.dirs.local_cache, tmp_sub_path, o_sub_path); |
| 5820 | 5822 | ||
| 5821 | return .{ | 5823 | return .{ |
| 5822 | .digest = bin_digest, | 5824 | .digest = bin_digest, |
src/Package/Fetch.zig+3-2| ... | @@ -1414,6 +1414,7 @@ fn unpackGitPack(f: *Fetch, out_dir: Io.Dir, resource: *Resource.Git) anyerror!U | ... | @@ -1414,6 +1414,7 @@ fn unpackGitPack(f: *Fetch, out_dir: Io.Dir, resource: *Resource.Git) anyerror!U |
| 1414 | 1414 | ||
| 1415 | fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void { | 1415 | fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void { |
| 1416 | const gpa = f.arena.child_allocator; | 1416 | const gpa = f.arena.child_allocator; |
| 1417 | const io = f.job_queue.io; | ||
| 1417 | // Recursive directory copy. | 1418 | // Recursive directory copy. |
| 1418 | var it = try dir.walk(gpa); | 1419 | var it = try dir.walk(gpa); |
| 1419 | defer it.deinit(); | 1420 | defer it.deinit(); |
| ... | @@ -1428,7 +1429,7 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void | ... | @@ -1428,7 +1429,7 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void |
| 1428 | .{}, | 1429 | .{}, |
| 1429 | ) catch |err| switch (err) { | 1430 | ) catch |err| switch (err) { |
| 1430 | error.FileNotFound => { | 1431 | error.FileNotFound => { |
| 1431 | if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.makePath(dirname); | 1432 | if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.makePath(io, dirname); |
| 1432 | try dir.copyFile(entry.path, tmp_dir, entry.path, .{}); | 1433 | try dir.copyFile(entry.path, tmp_dir, entry.path, .{}); |
| 1433 | }, | 1434 | }, |
| 1434 | else => |e| return e, | 1435 | else => |e| return e, |
| ... | @@ -1441,7 +1442,7 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void | ... | @@ -1441,7 +1442,7 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void |
| 1441 | // the destination directory, fail with an error instead. | 1442 | // the destination directory, fail with an error instead. |
| 1442 | tmp_dir.symLink(link_name, entry.path, .{}) catch |err| switch (err) { | 1443 | tmp_dir.symLink(link_name, entry.path, .{}) catch |err| switch (err) { |
| 1443 | error.FileNotFound => { | 1444 | error.FileNotFound => { |
| 1444 | if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.makePath(dirname); | 1445 | if (fs.path.dirname(entry.path)) |dirname| try tmp_dir.makePath(io, dirname); |
| 1445 | try tmp_dir.symLink(link_name, entry.path, .{}); | 1446 | try tmp_dir.symLink(link_name, entry.path, .{}); |
| 1446 | }, | 1447 | }, |
| 1447 | else => |e| return e, | 1448 | else => |e| return e, |
src/main.zig+6-5| ... | @@ -3382,7 +3382,7 @@ fn buildOutputType( | ... | @@ -3382,7 +3382,7 @@ fn buildOutputType( |
| 3382 | const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{ | 3382 | const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{ |
| 3383 | std.crypto.random.int(u64), ext.canonicalName(target), | 3383 | std.crypto.random.int(u64), ext.canonicalName(target), |
| 3384 | }); | 3384 | }); |
| 3385 | try dirs.local_cache.handle.makePath("tmp"); | 3385 | try dirs.local_cache.handle.makePath(io, "tmp"); |
| 3386 | 3386 | ||
| 3387 | // Note that in one of the happy paths, execve() is used to switch to | 3387 | // Note that in one of the happy paths, execve() is used to switch to |
| 3388 | // clang in which case any cleanup logic that exists for this temporary | 3388 | // clang in which case any cleanup logic that exists for this temporary |
| ... | @@ -4773,7 +4773,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! | ... | @@ -4773,7 +4773,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! |
| 4773 | var ok_count: usize = 0; | 4773 | var ok_count: usize = 0; |
| 4774 | 4774 | ||
| 4775 | for (template_paths) |template_path| { | 4775 | for (template_paths) |template_path| { |
| 4776 | if (templates.write(arena, Io.Dir.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { | 4776 | if (templates.write(arena, io, Io.Dir.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { |
| 4777 | std.log.info("created {s}", .{template_path}); | 4777 | std.log.info("created {s}", .{template_path}); |
| 4778 | ok_count += 1; | 4778 | ok_count += 1; |
| 4779 | } else |err| switch (err) { | 4779 | } else |err| switch (err) { |
| ... | @@ -7394,20 +7394,21 @@ const Templates = struct { | ... | @@ -7394,20 +7394,21 @@ const Templates = struct { |
| 7394 | fn write( | 7394 | fn write( |
| 7395 | templates: *Templates, | 7395 | templates: *Templates, |
| 7396 | arena: Allocator, | 7396 | arena: Allocator, |
| 7397 | io: Io, | ||
| 7397 | out_dir: Io.Dir, | 7398 | out_dir: Io.Dir, |
| 7398 | root_name: []const u8, | 7399 | root_name: []const u8, |
| 7399 | template_path: []const u8, | 7400 | template_path: []const u8, |
| 7400 | fingerprint: Package.Fingerprint, | 7401 | fingerprint: Package.Fingerprint, |
| 7401 | ) !void { | 7402 | ) !void { |
| 7402 | if (fs.path.dirname(template_path)) |dirname| { | 7403 | if (fs.path.dirname(template_path)) |dirname| { |
| 7403 | out_dir.makePath(dirname) catch |err| { | 7404 | out_dir.makePath(io, dirname) catch |err| { |
| 7404 | fatal("unable to make path '{s}': {s}", .{ dirname, @errorName(err) }); | 7405 | fatal("unable to make path '{s}': {t}", .{ dirname, err }); |
| 7405 | }; | 7406 | }; |
| 7406 | } | 7407 | } |
| 7407 | 7408 | ||
| 7408 | const max_bytes = 10 * 1024 * 1024; | 7409 | const max_bytes = 10 * 1024 * 1024; |
| 7409 | const contents = templates.dir.readFileAlloc(template_path, arena, .limited(max_bytes)) catch |err| { | 7410 | const contents = templates.dir.readFileAlloc(template_path, arena, .limited(max_bytes)) catch |err| { |
| 7410 | fatal("unable to read template file '{s}': {s}", .{ template_path, @errorName(err) }); | 7411 | fatal("unable to read template file '{s}': {t}", .{ template_path, err }); |
| 7411 | }; | 7412 | }; |
| 7412 | templates.buffer.clearRetainingCapacity(); | 7413 | templates.buffer.clearRetainingCapacity(); |
| 7413 | try templates.buffer.ensureUnusedCapacity(contents.len); | 7414 | try templates.buffer.ensureUnusedCapacity(contents.len); |