Repositories / jai.git

jai.git

Clone (read-only): git clone http://git.guha-anderson.com/git/jai.git

Branch

don't use O_TMPFILE for configuration not all file systems support it.

Author
David Mazieres <dm@uun.org>
Date
2026-03-18 22:41:36 -0700
Commit
6ca6829721c5e215906d9a80d0901df3c0a52a41
fs.cc
index dcc140b..3ca3f0e 100644
--- a/fs.cc
+++ b/fs.cc
@@ -449,22 +449,23 @@ ensure_file(int dfd, path file, std::string_view contents, int mode)
     if (errno != ENOENT)
       syserr("{}", fdpath(dfd, file));
 
-    auto pp = file.parent_path();
-    if (pp.empty())
-      pp = ".";
-    Fd fd = xopenat(dfd, pp, O_TMPFILE | O_RDWR | O_CLOEXEC);
+    path tmp = cat(file, std::format("~{}~", getpid()));
+    unlinkat(dfd, tmp.c_str(), 0);
+    Defer cleanup{[dfd, &tmp] { unlinkat(dfd, tmp.c_str(), 0); }};
+
+    Fd fd = xopenat(dfd, tmp.c_str(), O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC);
     for (size_t i = 0; i < contents.size();) {
       if (auto n = write(*fd, contents.data() + i, contents.size() - i); n < 0)
         syserr(R"(write(O_TMPFILE for "{}"))", fdpath(dfd, file));
       else
         i += n;
     }
-
-    if (linkat(*fd, "", dfd, file.c_str(), AT_EMPTY_PATH) == 0)
-      return fd;
-    if (errno != EEXIST)
-      syserr(R"(linkat(O_TMPFILE -> "{}"))", fdpath(dfd, file));
-    if (!S_ISREG(xfstat(dfd, file).st_mode))
-      err("{}: not a regular file", fdpath(dfd, file));
+    if (fsync(*fd))
+      syserr("fsync(\"{}\")", fdpath(*fd));
+    if (renameat(dfd, tmp.c_str(), dfd, file.c_str()))
+      syserr(R"(rename("{}" -> "{}") in "{}")", tmp.string(), file.string(),
+             fdpath(*fd));
+    cleanup.release();
+    return fd;
   }
 }