aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bench/copyfile/node.mitata.mjs51
m---------src/bun.js/WebKit0
-rw-r--r--src/bun.js/node/node_fs.zig92
-rw-r--r--src/bun.js/node/syscall.zig2
4 files changed, 127 insertions, 18 deletions
diff --git a/bench/copyfile/node.mitata.mjs b/bench/copyfile/node.mitata.mjs
index 93833cfcf..aa77245e1 100644
--- a/bench/copyfile/node.mitata.mjs
+++ b/bench/copyfile/node.mitata.mjs
@@ -1,23 +1,40 @@
-import { copyFileSync, writeFileSync } from "node:fs";
+import { copyFileSync, writeFileSync, readFileSync, statSync } from "node:fs";
import { bench, run } from "mitata";
-const size = parseInt(process.env.FILE_SIZE, 10) || 1024 * 16;
-const rand = new Float64Array(size);
-for (let i = 0; i < size; i++) {
- rand[i] = Math.random();
+function runner(ready) {
+ for (let size of [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]) {
+ const rand = new Int32Array(size);
+ for (let i = 0; i < size; i++) {
+ rand[i] = (Math.random() * 1024 * 1024) | 0;
+ }
+ const dest = `/tmp/fs-test-copy-file-${(
+ (Math.random() * 10000000 + 100) |
+ 0
+ ).toString(32)}`;
+ const src = `/tmp/fs-test-copy-file-${(
+ (Math.random() * 10000000 + 100) |
+ 0
+ ).toString(32)}`;
+ writeFileSync(src, Buffer.from(rand.buffer), { encoding: "buffer" });
+ const { size: fileSize } = statSync(src);
+ if (fileSize !== rand.byteLength) {
+ throw new Error("size mismatch");
+ }
+ ready(src, dest, new Uint8Array(rand.buffer));
+ }
}
-const dest = `/tmp/fs-test-copy-file-${(Math.random() * 100000 + 100).toString(
- 32
-)}`;
-const src = `/tmp/fs-test-copy-file-${(Math.random() * 100000 + 100).toString(
- 32
-)}`;
-writeFileSync(src, new Buffer(rand.buffer));
+runner((src, dest, rand) =>
+ bench(`copyFileSync(${rand.buffer.byteLength} bytes)`, () => {
+ copyFileSync(src, dest);
+ // const output = readFileSync(dest).buffer;
-const srcBuf = new TextEncoder().encode(src);
-const destBuf = new TextEncoder().encode(dest);
-bench(`copyFileSync(${rand.buffer.byteLength} bytes)`, () =>
- copyFileSync(srcBuf, destBuf)
+ // for (let i = 0; i < output.length; i++) {
+ // if (output[i] !== rand[i]) {
+ // throw new Error(
+ // "Files are not equal" + " " + output[i] + " " + rand[i] + " " + i
+ // );
+ // }
+ // }
+ })
);
-
await run();
diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit
-Subproject 4d6ee41032866e63aa43ba007616c632ed1c90a
+Subproject 7d9e2ffa4365e676a4aa96a9941154a68e54f0f
diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig
index 440527e8f..af6e95d26 100644
--- a/src/bun.js/node/node_fs.zig
+++ b/src/bun.js/node/node_fs.zig
@@ -2419,6 +2419,98 @@ pub const NodeFS = struct {
if (args.mode.isForceClone()) {
// https://www.manpagez.com/man/2/clonefile/
return ret.errnoSysP(C.clonefile(src, dest, 0), .clonefile, src) orelse ret.success;
+ } else {
+ const stat_ = switch (Syscall.stat(src)) {
+ .result => |result| result,
+ .err => |err| return Maybe(Return.CopyFile){ .err = err.withPath(src) },
+ };
+
+ if (!os.S.ISREG(stat_.mode)) {
+ return Maybe(Return.CopyFile){ .err = .{ .errno = @enumToInt(C.SystemErrno.ENOTSUP) } };
+ }
+
+ if (stat_.size > 128 * 1024) {
+ if (!args.mode.shouldntOverwrite()) {
+ // clonefile() will fail if it already exists
+ _ = Syscall.unlink(dest);
+ }
+
+ if (ret.errnoSysP(C.clonefile(src, dest, 0), .clonefile, src) == null) {
+ _ = C.chmod(dest, stat_.mode);
+ return ret.success;
+ }
+ } else {
+ const src_fd = switch (Syscall.open(src, std.os.O.RDONLY, 0644)) {
+ .result => |result| result,
+ .err => |err| return .{ .err = err.withPath(args.src.slice()) },
+ };
+ defer {
+ _ = Syscall.close(src_fd);
+ }
+
+ var flags: Mode = std.os.O.CREAT | std.os.O.WRONLY;
+ var wrote: usize = 0;
+ if (args.mode.shouldntOverwrite()) {
+ flags |= std.os.O.EXCL;
+ }
+
+ const dest_fd = switch (Syscall.open(dest, flags, JSC.Node.default_permission)) {
+ .result => |result| result,
+ .err => |err| return Maybe(Return.CopyFile){ .err = err },
+ };
+ defer {
+ _ = std.c.ftruncate(dest_fd, @intCast(std.c.off_t, @truncate(u63, wrote)));
+
+ _ = Syscall.close(dest_fd);
+ }
+
+ var buf: [16384]u8 = undefined;
+ var remain = @intCast(u64, @maximum(stat_.size, 0));
+ toplevel: while (remain > 0) {
+ const amt = switch (Syscall.read(src_fd, buf[0..@minimum(buf.len, remain)])) {
+ .result => |result| result,
+ .err => |err| return Maybe(Return.CopyFile){ .err = err.withPath(src) },
+ };
+ if (amt == 0) {
+ break :toplevel;
+ }
+ wrote += amt;
+ remain -|= amt;
+
+ var slice = buf[0..amt];
+ while (slice.len > 0) {
+ const written = switch (Syscall.write(dest_fd, slice)) {
+ .result => |result| result,
+ .err => |err| return Maybe(Return.CopyFile){ .err = err.withPath(dest) },
+ };
+ if (written == 0) break :toplevel;
+ slice = slice[written..];
+ }
+ } else {
+ outer: while (true) {
+ const amt = switch (Syscall.read(src_fd, &buf)) {
+ .result => |result| result,
+ .err => |err| return Maybe(Return.CopyFile){ .err = err.withPath(src) },
+ };
+ if (amt == 0) {
+ break;
+ }
+ wrote += amt;
+
+ var slice = buf[0..amt];
+ while (slice.len > 0) {
+ const written = switch (Syscall.write(dest_fd, slice)) {
+ .result => |result| result,
+ .err => |err| return Maybe(Return.CopyFile){ .err = err.withPath(dest) },
+ };
+ slice = slice[written..];
+ if (written == 0) break :outer;
+ }
+ }
+ }
+ _ = C.fchmod(dest_fd, stat_.mode);
+ return ret.success;
+ }
}
var mode: Mode = C.darwin.COPYFILE_ACL | C.darwin.COPYFILE_DATA;
diff --git a/src/bun.js/node/syscall.zig b/src/bun.js/node/syscall.zig
index 4378a4762..1f74753d2 100644
--- a/src/bun.js/node/syscall.zig
+++ b/src/bun.js/node/syscall.zig
@@ -419,7 +419,7 @@ pub fn fcopyfile(fd_in: std.os.fd_t, fd_out: std.os.fd_t, flags: u32) Maybe(void
pub fn unlink(from: [:0]const u8) Maybe(void) {
while (true) {
- if (Maybe(void).errno(sys.unlink(from), .unlink)) |err| {
+ if (Maybe(void).errnoSys(sys.unlink(from), .unlink)) |err| {
if (err.getErrno() == .INTR) continue;
return err;
}