diff options
author | 2022-10-03 01:10:38 -0700 | |
---|---|---|
committer | 2022-10-03 01:10:38 -0700 | |
commit | d3ef6c330ab178026b9a9f447ed165832c99e358 (patch) | |
tree | c461c496540a621cf69a64049fad777cf468c354 | |
parent | 47007621326c5537b9d5d2a11eaa7dc086fc6a82 (diff) | |
download | bun-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.js | 13 | ||||
-rw-r--r-- | src/bun.js/node/node_fs.zig | 59 | ||||
-rw-r--r-- | src/bun.js/node/node_fs_binding.zig | 8 | ||||
-rw-r--r-- | src/bun.js/node/syscall.zig | 4 | ||||
-rw-r--r-- | src/darwin_c.zig | 23 |
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; |