aboutsummaryrefslogtreecommitdiff
path: root/src/fs.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs.zig')
-rw-r--r--src/fs.zig47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/fs.zig b/src/fs.zig
index 8a6d4e5f7..0b28fa9b7 100644
--- a/src/fs.zig
+++ b/src/fs.zig
@@ -513,6 +513,53 @@ pub const FileSystem = struct {
return file;
}
+ pub const Tmpfile = struct {
+ fd: std.os.fd_t = 0,
+ dir_fd: std.os.fd_t = 0,
+
+ pub inline fn dir(this: *Tmpfile) std.fs.Dir {
+ return std.fs.Dir{
+ .fd = this.dir_fd,
+ };
+ }
+
+ pub inline fn file(this: *Tmpfile) std.fs.File {
+ return std.fs.File{
+ .handle = this.fd,
+ };
+ }
+
+ pub fn close(this: *Tmpfile) void {
+ if (this.fd != 0) std.os.close(this.fd);
+ }
+
+ pub fn create(this: *Tmpfile, rfs: *RealFS, name: [*:0]const u8) !void {
+ var tmpdir_ = try rfs.openTmpDir();
+
+ const flags = std.os.O_CREAT | std.os.O_RDWR | std.os.O_CLOEXEC;
+ this.dir_fd = tmpdir_.fd;
+ this.fd = try std.os.openatZ(tmpdir_.fd, name, flags, std.os.S_IRWXO);
+ }
+
+ pub fn promote(this: *Tmpfile, from_name: [*:0]const u8, destination_fd: std.os.fd_t, name: [*:0]const u8) !void {
+ std.debug.assert(this.fd != 0);
+ std.debug.assert(this.dir_fd != 0);
+
+ try C.moveFileZWithHandle(this.fd, this.dir_fd, from_name, destination_fd, name);
+ this.close();
+ }
+
+ pub fn closeAndDelete(this: *Tmpfile, name: [*:0]const u8) void {
+ this.close();
+
+ if (comptime !Environment.isLinux) {
+ if (this.dir_fd == 0) return;
+
+ this.dir().deleteFileZ(name) catch {};
+ }
+ }
+ };
+
inline fn _fetchCacheFile(fs: *RealFS, basename: string) !std.fs.File {
var parts = [_]string{ "node_modules", ".cache", basename };
var path = fs.parent_fs.join(&parts);