diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 4c8e2ea2f..d276bd786 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -167,7 +167,7 @@ void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd) txn.commit(); } - writeFile(schemaPath, fmt("%d", nixCASchemaVersion), 0666, true); + writeFileAndSync(schemaPath, fmt("%d", nixCASchemaVersion), 0666); lockFile(lockFd.get(), ltRead, true); } } @@ -304,7 +304,7 @@ LocalStore::LocalStore(const Params & params) else if (curSchema == 0) { /* new store */ curSchema = nixSchemaVersion; openDB(*state, true); - writeFile(schemaPath, fmt("%1%", nixSchemaVersion), 0666, true); + writeFileAndSync(schemaPath, fmt("%1%", nixSchemaVersion), 0666); } else if (curSchema < nixSchemaVersion) { @@ -353,7 +353,7 @@ LocalStore::LocalStore(const Params & params) txn.commit(); } - writeFile(schemaPath, fmt("%1%", nixSchemaVersion), 0666, true); + writeFileAndSync(schemaPath, fmt("%1%", nixSchemaVersion), 0666); lockFile(globalLock.get(), ltRead, true); } diff --git a/src/libutil/file-system.cc b/src/libutil/file-system.cc index 631cf076b..39ba7699e 100644 --- a/src/libutil/file-system.cc +++ b/src/libutil/file-system.cc @@ -311,17 +311,47 @@ Generator readFileSource(const Path & path) } -void writeFile(const Path & path, std::string_view s, mode_t mode, bool sync) +void writeFile(const Path & path, std::string_view s, mode_t mode) { AutoCloseFD fd{open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode)}; if (!fd) throw SysError("opening file '%1%'", path); + + writeFile(fd, s, mode); + + /* Close explicitly to propagate the exceptions. */ + fd.close(); +} + +void writeFile(AutoCloseFD & fd, std::string_view s, mode_t mode) +{ + assert(fd); try { writeFull(fd.get(), s); } catch (Error & e) { - e.addTrace({}, "writing file '%1%'", path); + e.addTrace({}, "writing file '%1%'", fd.guessOrInventPath()); throw; } +} + +void writeFileAndSync(const Path & path, std::string_view s, mode_t mode) +{ + { + AutoCloseFD fd{open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode)}; + if (!fd) + throw SysError("opening file '%1%'", path); + + writeFile(fd, s, mode); + fd.fsync(); + /* Close explicitly to ensure that exceptions are propagated. */ + fd.close(); + } + + syncParent(path); +} + +static void closeForWrite(const Path & path, AutoCloseFD & fd, bool sync) +{ if (sync) fd.fsync(); // Explicitly close to make sure exceptions are propagated. @@ -330,8 +360,7 @@ void writeFile(const Path & path, std::string_view s, mode_t mode, bool sync) syncParent(path); } - -void writeFile(const Path & path, Source & source, mode_t mode, bool sync) +void writeFile(const Path & path, Source & source, mode_t mode) { AutoCloseFD fd{open(path.c_str(), O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode)}; if (!fd) @@ -350,12 +379,8 @@ void writeFile(const Path & path, Source & source, mode_t mode, bool sync) e.addTrace({}, "writing file '%1%'", path); throw; } - if (sync) - fd.fsync(); - // Explicitly close to make sure exceptions are propagated. - fd.close(); - if (sync) - syncParent(path); + + closeForWrite(path, fd, false); } void syncParent(const Path & path) diff --git a/src/libutil/file-system.hh b/src/libutil/file-system.hh index e49323e84..d3b6d2608 100644 --- a/src/libutil/file-system.hh +++ b/src/libutil/file-system.hh @@ -164,9 +164,16 @@ Generator readFileSource(const Path & path); /** * Write a string to a file. */ -void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool sync = false); +void writeFile(const Path & path, std::string_view s, mode_t mode = 0666); -void writeFile(const Path & path, Source & source, mode_t mode = 0666, bool sync = false); +void writeFile(const Path & path, Source & source, mode_t mode = 0666); + +void writeFile(AutoCloseFD & fd, std::string_view s, mode_t mode = 0666); + +/** + * Write a string to a file and flush the file and its parents direcotry to disk. + */ +void writeFileAndSync(const Path & path, std::string_view s, mode_t mode = 0666); /** * Flush a file's parent directory to disk