// This source code is released into the public domain. export module nihil.posix:write_file; import nihil.std; import nihil.error; import nihil.monad; import nihil.util; import :fd; import :open; import :rename; import :unlink; namespace nihil { // Write the contents of a range to a file. Returns the number of bytes // written. export [[nodiscard]] auto write_file(std::filesystem::path const &filename, std::ranges::contiguous_range auto &&range, int mode = 0777) -> std::expected { auto file = co_await open(filename, open_write | open_create, mode); auto nbytes = co_await write(file, range); co_return nbytes; } // Utility wrapper for non-contiguous ranges. export [[nodiscard]] auto write_file(std::filesystem::path const &filename, std::ranges::range auto &&range) -> std::expected requires(!std::ranges::contiguous_range) { return write_file(filename, std::vector(std::from_range, range)); } // Write the contents of a range to a file safely. The data will be written // to ".tmp", and if the write succeeds, the temporary file will be // renamed to the target filename. If an error occurs, the target file will // not be modified. export [[nodiscard]] auto safe_write_file(std::filesystem::path const &filename, std::ranges::range auto &&range) -> std::expected { auto tmpfile = filename; tmpfile.remove_filename(); tmpfile /= (filename.filename().native() + ".tmp"); auto tmpfile_guard = guard([&tmpfile] { std::ignore = unlink(tmpfile.c_str()); }); co_await write_file(tmpfile, range); co_await rename(tmpfile, filename); tmpfile_guard.release(); co_return {}; } } // namespace nihil