summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dump.zig39
1 files changed, 34 insertions, 5 deletions
diff --git a/src/dump.zig b/src/dump.zig
index 45a5e0eb..fca88a2d 100644
--- a/src/dump.zig
+++ b/src/dump.zig
@@ -47,11 +47,40 @@ pub fn outPath(buf: *[1024:0]u8, dir_setting: []const u8) ?[:0]const u8 {
const yd = es.getEpochDay().calculateYearDay();
const md = yd.calculateMonthDay();
const ds = es.getDaySeconds();
- return std.fmt.bufPrintSentinel(buf, "{s}/pardes-{d:0>4}{d:0>2}{d:0>2}-{d:0>2}{d:0>2}{d:0>2}.zon", .{
- dir, yd.year, md.month.numeric(),
- @as(u8, md.day_index) + 1, ds.getHoursIntoDay(), ds.getMinutesIntoHour(),
- ds.getSecondsIntoMinute(),
- }, 0) catch null;
+ var stamp: [32]u8 = undefined;
+ const base = std.fmt.bufPrint(&stamp, "pardes-{d:0>4}{d:0>2}{d:0>2}-{d:0>2}{d:0>2}{d:0>2}", .{
+ yd.year, md.month.numeric(), @as(u8, md.day_index) + 1,
+ ds.getHoursIntoDay(), ds.getMinutesIntoHour(), ds.getSecondsIntoMinute(),
+ }) catch return null;
+ return uniqueIn(buf, dir, base);
+}
+
+/// `<dir>/<base>.zon`, or `<base>-2.zon` and on when two dumps land in one
+/// second: a dump never overwrites another.
+fn uniqueIn(buf: *[1024:0]u8, dir: []const u8, base: []const u8) ?[:0]const u8 {
+ var n: usize = 1;
+ while (n < 1000) : (n += 1) {
+ const path = (if (n == 1)
+ std.fmt.bufPrintSentinel(buf, "{s}/{s}.zon", .{ dir, base }, 0)
+ else
+ std.fmt.bufPrintSentinel(buf, "{s}/{s}-{d}.zon", .{ dir, base, n }, 0)) catch return null;
+ if (comptime !pardes.hosted) return path;
+ if (std.c.access(path.ptr, std.c.F_OK) != 0) return path;
+ }
+ return null;
+}
+
+test "two dumps in one second get names of their own" {
+ var tmp = std.testing.tmpDir(.{});
+ defer tmp.cleanup();
+ var dir_buf: [900]u8 = undefined;
+ const dir = dir_buf[0..try tmp.dir.realPath(std.testing.io, &dir_buf)];
+ var buf: [1024:0]u8 = undefined;
+ const first = try std.testing.allocator.dupe(u8, uniqueIn(&buf, dir, "pardes-x").?);
+ defer std.testing.allocator.free(first);
+ try std.testing.expect(std.mem.endsWith(u8, first, "/pardes-x.zon"));
+ try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "pardes-x.zon", .data = "" });
+ try std.testing.expect(std.mem.endsWith(u8, uniqueIn(&buf, dir, "pardes-x").?, "/pardes-x-2.zon"));
}
/// The host's environment; a freestanding core (web, the board) has none
/// and no libc to ask, so only a DumpDir with no `~/` names a directory there.