summaryrefslogtreecommitdiff
path: root/src/temp_file.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/temp_file.zig')
-rw-r--r--src/temp_file.zig84
1 files changed, 0 insertions, 84 deletions
diff --git a/src/temp_file.zig b/src/temp_file.zig
deleted file mode 100644
index a6174efd..00000000
--- a/src/temp_file.zig
+++ /dev/null
@@ -1,84 +0,0 @@
-//! Native-shell ownership of `New`'s one filesystem operation.
-//!
-//! The core asks for a temporary file by effect and receives only its path.
-//! `mkstemp` creates and opens the name atomically with mode 0600, so there is
-//! no name-then-open race and repeated requests cannot collide. A file the
-//! core declines is unlinked here immediately; an adopted file becomes an
-//! ordinary Pardes document and is deliberately left on disk when its pane is
-//! closed, just like every other document (and so a dump remains restorable).
-const std = @import("std");
-const libc = std.c;
-
-extern "c" fn mkstemp(template: [*:0]u8) c_int;
-extern "c" fn lseek(fd: c_int, offset: libc.off_t, whence: c_int) libc.off_t;
-
-pub const Created = struct {
- fd: c_int,
- path: [:0]u8,
-
- /// The core copied the path and now owns the document. Close our creation
- /// handle; Save and watching reopen/use the pathname through their normal
- /// seams.
- pub fn adopt(f: Created) void {
- _ = libc.close(f.fd);
- }
-
- /// Creation succeeded but the request became stale or the core could not
- /// allocate a pane. Nothing user-visible owns this name, so remove it.
- pub fn discard(f: Created) void {
- _ = libc.close(f.fd);
- _ = libc.unlink(f.path);
- }
-};
-
-/// Create in the platform's conventional temporary directory. TMPDIR is a
-/// shell concern (environment + filesystem), intentionally outside the core.
-pub fn create(buf: *[4096:0]u8) ?Created {
- const env = libc.getenv("TMPDIR");
- const dir = if (env) |p| std.mem.span(p) else "/tmp";
- return createIn(buf, if (dir.len > 0) dir else "/tmp");
-}
-
-/// Split out for a hermetic failure test and to keep template construction
-/// independently checkable. The six Xs are consumed by mkstemp itself.
-pub fn createIn(buf: *[4096:0]u8, dir_arg: []const u8) ?Created {
- const dir = std.mem.trimEnd(u8, dir_arg, "/");
- const path = std.fmt.bufPrintSentinel(
- buf,
- "{s}{s}pardes-XXXXXX",
- .{ if (dir.len == 0) "/" else dir, if (dir.len == 0) "" else "/" },
- 0,
- ) catch return null;
- const fd = mkstemp(path.ptr);
- if (fd < 0) return null;
- return .{ .fd = fd, .path = path };
-}
-
-test "mkstemp creates distinct empty files and rejected files are removable" {
- var abuf: [4096:0]u8 = undefined;
- var bbuf: [4096:0]u8 = undefined;
- const a = createIn(&abuf, "/tmp") orelse return error.TempCreateFailed;
- const b = createIn(&bbuf, "/tmp") orelse return error.TempCreateFailed;
- defer b.discard();
-
- try std.testing.expect(!std.mem.eql(u8, a.path, b.path));
- try std.testing.expectEqual(@as(libc.off_t, 0), lseek(a.fd, 0, 2)); // SEEK_END
- try std.testing.expectEqual(@as(libc.off_t, 0), lseek(b.fd, 0, 2));
-
- a.discard();
- try std.testing.expect(libc.unlink(a.path) < 0); // already removed
-}
-
-test "an adopted tempfile remains named for the document" {
- var buf: [4096:0]u8 = undefined;
- const made = createIn(&buf, "/tmp") orelse return error.TempCreateFailed;
- made.adopt();
- // Adoption closes only the creation handle. The ordinary file document
- // keeps this path for Save, watch, Del and dump/restore.
- try std.testing.expectEqual(@as(c_int, 0), libc.unlink(made.path));
-}
-
-test "mkstemp failure creates no candidate file" {
- var buf: [4096:0]u8 = undefined;
- try std.testing.expect(createIn(&buf, "/definitely/not/a/pardes/temp/directory") == null);
-}