Fix moving files across mount points

This commit is contained in:
Jarred Sumner
2021-10-04 15:35:08 -07:00
parent dc3eee44a9
commit e8dab9bfcf
2 changed files with 29 additions and 1 deletions

View File

@@ -1112,7 +1112,7 @@ pub const Bundler = struct {
// chmod 777
0000010 | 0000100 | 0000001 | 0001000 | 0000040 | 0000004 | 0000002 | 0000400 | 0000200 | 0000020,
);
try std.os.renameatZ(tmpdir.fd, tmpname, top_dir.fd, destination);
try C.moveFileZ(tmpdir.fd, tmpname, top_dir.fd, destination);
// Print any errors at the end
// try this.log.print(Output.errorWriter());
return javascript_bundle_container;

View File

@@ -1,4 +1,5 @@
const std = @import("std");
const Enviroment = @import("./env.zig");
pub usingnamespace switch (std.Target.current.os.tag) {
.macos => @import("./darwin_c.zig"),
@@ -89,3 +90,30 @@ pub fn lstat_absolute(path: [:0]const u8) StatError!Stat {
.ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
};
}
// renameatZ fails when renaming across mount points
// we assume that this is relatively uncommon
pub fn moveFileZ(from_dir: std.os.fd_t, filename: [*:0]const u8, to_dir: std.os.fd_t, destination: [*:0]const u8) !void {
std.os.renameatZ(from_dir, filename, to_dir, destination) catch |err| {
switch (err) {
error.RenameAcrossMountPoints => {
try moveFileZSlow(from_dir, filename, to_dir, destination);
},
else => {
return err;
},
}
};
}
// On Linux, this will be fast because sendfile() supports copying between two file descriptors on disk
// On macOS & BSDs, this will be slow because it will attempt to copy with sendfile, fail, and then fallback to a copy loop
pub fn moveFileZSlow(from_dir: std.os.fd_t, filename: [*:0]const u8, to_dir: std.os.fd_t, destination: [*:0]const u8) !void {
const flags = std.os.O_RDWR;
const in_handle = try std.os.openatZ(from_dir, filename, flags, 0777);
defer std.os.close(in_handle);
const out_handle = try std.os.openatZ(to_dir, filename, flags | std.os.O_CREAT, 0777);
defer std.os.close(out_handle);
const written = try std.os.sendfile(out_handle, in_handle, 0, 0, &[_]std.c.iovec_const{}, &[_]std.c.iovec_const{}, 0);
try std.os.ftruncate(out_handle, written);
}