| 79 | } |
| 80 | |
| 81 | static void write_file(const std::string & fname, const std::string & content) { |
| 82 | const std::string fname_tmp = fname + ".tmp"; |
| 83 | std::ofstream file(fname_tmp); |
| 84 | if (!file) { |
| 85 | throw std::runtime_error(string_format("error: failed to open file '%s'\n", fname.c_str())); |
| 86 | } |
| 87 | |
| 88 | try { |
| 89 | file << content; |
| 90 | file.close(); |
| 91 | |
| 92 | // Makes write atomic |
| 93 | if (rename(fname_tmp.c_str(), fname.c_str()) != 0) { |
| 94 | LOG_ERR("%s: unable to rename file: %s to %s\n", __func__, fname_tmp.c_str(), fname.c_str()); |
| 95 | // If rename fails, try to delete the temporary file |
| 96 | if (remove(fname_tmp.c_str()) != 0) { |
| 97 | LOG_ERR("%s: unable to delete temporary file: %s\n", __func__, fname_tmp.c_str()); |
| 98 | } |
| 99 | } |
| 100 | } catch (...) { |
| 101 | // If anything fails, try to delete the temporary file |
| 102 | if (remove(fname_tmp.c_str()) != 0) { |
| 103 | LOG_ERR("%s: unable to delete temporary file: %s\n", __func__, fname_tmp.c_str()); |
| 104 | } |
| 105 | |
| 106 | throw std::runtime_error(string_format("error: failed to write file '%s'\n", fname.c_str())); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | static void write_etag(const std::string & path, const std::string & etag) { |
| 111 | const std::string etag_path = path + ".etag"; |
no test coverage detected