aboutsummaryrefslogtreecommitdiff
path: root/src/c.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-10-04 15:35:08 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-10-04 15:35:08 -0700
commite8dab9bfcf4b7822253eaf290cf2f72291b39167 (patch)
tree815f39bcf9e7591b0076a87bbcaa981bd812a68c /src/c.zig
parentdc3eee44a928239524133177740addcb14b1b0a4 (diff)
downloadbun-e8dab9bfcf4b7822253eaf290cf2f72291b39167.tar.gz
bun-e8dab9bfcf4b7822253eaf290cf2f72291b39167.tar.zst
bun-e8dab9bfcf4b7822253eaf290cf2f72291b39167.zip
Fix moving files across mount points
Diffstat (limited to '')
-rw-r--r--src/c.zig28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/c.zig b/src/c.zig
index 967d1dea6..9e07f3082 100644
--- a/src/c.zig
+++ b/src/c.zig
@@ -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);
+}