diff options
author | 2021-10-04 15:35:08 -0700 | |
---|---|---|
committer | 2021-10-04 15:35:08 -0700 | |
commit | e8dab9bfcf4b7822253eaf290cf2f72291b39167 (patch) | |
tree | 815f39bcf9e7591b0076a87bbcaa981bd812a68c | |
parent | dc3eee44a928239524133177740addcb14b1b0a4 (diff) | |
download | bun-e8dab9bfcf4b7822253eaf290cf2f72291b39167.tar.gz bun-e8dab9bfcf4b7822253eaf290cf2f72291b39167.tar.zst bun-e8dab9bfcf4b7822253eaf290cf2f72291b39167.zip |
Fix moving files across mount points
-rw-r--r-- | src/bundler.zig | 2 | ||||
-rw-r--r-- | src/c.zig | 28 |
2 files changed, 29 insertions, 1 deletions
diff --git a/src/bundler.zig b/src/bundler.zig index d1b530c82..472b8bd9f 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -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; @@ -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); +} |