aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-10-03 01:10:38 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-10-03 01:10:38 -0700
commitd3ef6c330ab178026b9a9f447ed165832c99e358 (patch)
treec461c496540a621cf69a64049fad777cf468c354
parent47007621326c5537b9d5d2a11eaa7dc086fc6a82 (diff)
downloadbun-d3ef6c330ab178026b9a9f447ed165832c99e358.tar.gz
bun-d3ef6c330ab178026b9a9f447ed165832c99e358.tar.zst
bun-d3ef6c330ab178026b9a9f447ed165832c99e358.zip
`node:fs` implement `rm` on macOS
no linux yet
-rw-r--r--src/bun.js/fs.exports.js13
-rw-r--r--src/bun.js/node/node_fs.zig59
-rw-r--r--src/bun.js/node/node_fs_binding.zig8
-rw-r--r--src/bun.js/node/syscall.zig4
-rw-r--r--src/darwin_c.zig23
5 files changed, 101 insertions, 6 deletions
diff --git a/src/bun.js/fs.exports.js b/src/bun.js/fs.exports.js
index b11deca2c..f8e44f330 100644
--- a/src/bun.js/fs.exports.js
+++ b/src/bun.js/fs.exports.js
@@ -9,6 +9,9 @@ export var appendFile = function appendFile(...args) {
export var close = function close(...args) {
callbackify(fs.closeSync, args);
};
+export var rm = function rm(...args) {
+ callbackify(fs.rmSync, args);
+};
export var copyFile = function copyFile(...args) {
callbackify(fs.copyFileSync, args);
};
@@ -186,6 +189,7 @@ export var truncateSync = fs.truncateSync.bind(fs);
export var unlinkSync = fs.unlinkSync.bind(fs);
export var utimesSync = fs.utimesSync.bind(fs);
export var lutimesSync = fs.lutimesSync.bind(fs);
+export var rmSync = fs.rmSync.bind(fs);
export var createReadStream = fs.createReadStream.bind(fs);
export var createWriteStream = fs.createWriteStream.bind(fs);
@@ -224,6 +228,7 @@ export var promises = {
unlink: promisify(fs.unlinkSync),
utimes: promisify(fs.utimesSync),
lutimes: promisify(fs.lutimesSync),
+ rm: promisify(fs.rmSync),
};
promises.readFile = promises.readfile = promisify(fs.readFileSync);
@@ -232,7 +237,8 @@ promises.readFile = promises.readfile = promisify(fs.readFileSync);
realpath.native = realpath;
realpathSync.native = realpathSync;
-var object = {
+export default {
+ [Symbol.for("CommonJS")]: 0,
access,
appendFile,
close,
@@ -292,6 +298,7 @@ var object = {
readdirSync,
readFileSync,
writeFileSync,
+ rmSync,
readlinkSync,
realpathSync,
renameSync,
@@ -306,7 +313,3 @@ var object = {
constants,
promises,
};
-
-var CJSInterop = () => object;
-CJSInterop[Symbol.for("CommonJS")] = true;
-export default CJSInterop;
diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig
index 8374e1c77..5fb03f9b6 100644
--- a/src/bun.js/node/node_fs.zig
+++ b/src/bun.js/node/node_fs.zig
@@ -773,6 +773,37 @@ const Arguments = struct {
max_retries: u32 = 0,
recursive: bool = false,
retry_delay: c_uint = 100,
+
+ pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?RmDir {
+ const path = PathLike.fromJS(ctx, arguments, exception) orelse {
+ if (exception.* == null) {
+ JSC.throwInvalidArguments(
+ "path must be a string or TypedArray",
+ .{},
+ ctx,
+ exception,
+ );
+ }
+ return null;
+ };
+
+ if (exception.* != null) return null;
+ var recursive = false;
+ if (arguments.next()) |val| {
+ arguments.eat();
+
+ if (val.isObject()) {
+ if (val.getIfPropertyExists(ctx.ptr(), "recursive")) |recursive_| {
+ recursive = recursive_.toBoolean();
+ }
+ }
+ }
+
+ return RmDir{
+ .path = path,
+ .recursive = recursive,
+ };
+ }
};
/// https://github.com/nodejs/node/blob/master/lib/fs.js#L1285
@@ -3601,7 +3632,10 @@ pub const NodeFS = struct {
switch (comptime flavor) {
.sync => {
var dir = args.old_path.sliceZ(&this.sync_error_buf);
- _ = dir;
+ switch (Syscall.getErrno(system.rmdir(dir))) {
+ .SUCCESS => return Maybe(Return.Rmdir).success,
+ else => |err| return Maybe(Return.Rmdir).errnoSys(err, .rmdir),
+ }
},
else => {},
}
@@ -3614,6 +3648,29 @@ pub const NodeFS = struct {
_ = args;
_ = this;
_ = flavor;
+ switch (comptime flavor) {
+ .sync => {
+ var dest = args.path.sliceZ(&this.sync_error_buf);
+
+ if (comptime Environment.isMac) {
+ var flags: u32 = 0;
+ if (args.recursive) {
+ flags |= bun.C.darwin.RemoveFileFlags.cross_mount;
+ flags |= bun.C.darwin.RemoveFileFlags.allow_long_paths;
+ flags |= bun.C.darwin.RemoveFileFlags.recursive;
+ }
+
+ switch (bun.C.darwin.removefileat(std.os.AT.FDCWD, dest, null, flags)) {
+ 0 => return Maybe(Return.Rm).success,
+ else => |err| return Maybe(Return.Rm).errnoSys(err, .unlink).?,
+ }
+ } else if (comptime Environment.isLinux) {
+ // TODO:
+ }
+ },
+ else => {},
+ }
+
return Maybe(Return.Rm).todo;
}
pub fn stat(this: *NodeFS, args: Arguments.Stat, comptime flavor: Flavor) Maybe(Return.Stat) {
diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig
index 298727fb9..d4d97e9a9 100644
--- a/src/bun.js/node/node_fs_binding.zig
+++ b/src/bun.js/node/node_fs_binding.zig
@@ -239,6 +239,10 @@ pub const NodeFSBindings = JSC.NewClass(
.name = "readlink",
.rfn = call(.readlink),
},
+ .rm = .{
+ .name = "rm",
+ .rfn = call(.rm),
+ },
.realpath = .{
.name = "realpath",
.rfn = call(.realpath),
@@ -418,6 +422,10 @@ pub const NodeFSBindings = JSC.NewClass(
.name = "lutimesSync",
.rfn = callSync(.lutimes),
},
+ .rmSync = .{
+ .name = "rmSync",
+ .rfn = callSync(.rm),
+ },
},
.{},
);
diff --git a/src/bun.js/node/syscall.zig b/src/bun.js/node/syscall.zig
index d677a4510..fddd0a8df 100644
--- a/src/bun.js/node/syscall.zig
+++ b/src/bun.js/node/syscall.zig
@@ -566,6 +566,10 @@ pub const Error = struct {
syscall: Syscall.Tag = @intToEnum(Syscall.Tag, 0),
path: []const u8 = "",
+ pub inline fn isRetry(this: *const Error) bool {
+ return this.getErrno() == .AGAIN;
+ }
+
pub fn fromCode(errno: os.E, syscall: Syscall.Tag) Error {
return .{ .errno = @truncate(Int, @enumToInt(errno)), .syscall = syscall };
}
diff --git a/src/darwin_c.zig b/src/darwin_c.zig
index 94d7f12ea..b798801fe 100644
--- a/src/darwin_c.zig
+++ b/src/darwin_c.zig
@@ -705,3 +705,26 @@ const IO_CTL_RELATED = struct {
};
pub usingnamespace IO_CTL_RELATED;
+
+pub const RemoveFileFlags = struct {
+ /// If path is a directory, recurse (depth first traversal)
+ pub const recursive: u32 = (1 << 0);
+ /// Remove contents but not directory itself
+ pub const keep_parent: u32 = (1 << 1);
+ /// 7 pass DoD algorithm
+ pub const secure_7_pass: u32 = (1 << 2);
+ /// 35-pass Gutmann algorithm (overrides REMOVEFILE_SECURE_7_PASS)
+ pub const secure_35_pass: u32 = (1 << 3);
+ /// 1 pass single overwrite),
+ pub const secure_1_pass: u32 = (1 << 4);
+ /// 3 pass overwrite
+ pub const secure_3_pass: u32 = (1 << 5);
+ /// Single-pass overwrite, with 0 instead of random data
+ pub const secure_1_pass_zero: u32 = (1 << 6);
+ /// Cross mountpoints when deleting recursively. << 6),
+ pub const cross_mount: u32 = (1 << 7);
+ /// Paths may be longer than PATH_MAX - requires temporarily changing cwd
+ pub const allow_long_paths: u32 = (1 << 8);
+};
+pub const removefile_state_t = opaque {};
+pub extern fn removefileat(fd: c_int, path: [*c]const u8, state: ?*removefile_state_t, flags: u32) c_int;