|
@@ -236,6 +236,52 @@ bool os_quick_write_utf8_file(const char *path, const char *str, size_t len,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+bool os_quick_write_utf8_file_safe(const char *path, const char *str,
|
|
|
+ size_t len, bool marker, const char *temp_ext,
|
|
|
+ const char *backup_ext)
|
|
|
+{
|
|
|
+ struct dstr backup_path = {0};
|
|
|
+ struct dstr temp_path = {0};
|
|
|
+ bool success = false;
|
|
|
+
|
|
|
+ if (!temp_ext || !*temp_ext) {
|
|
|
+ blog(LOG_ERROR, "os_quick_write_utf8_file_safe: invalid "
|
|
|
+ "temporary extension specified");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ dstr_copy(&temp_path, path);
|
|
|
+ if (*temp_ext != '.')
|
|
|
+ dstr_cat(&temp_path, ".");
|
|
|
+ dstr_cat(&temp_path, temp_ext);
|
|
|
+
|
|
|
+ if (!os_quick_write_utf8_file(temp_path.array, str, len, marker)) {
|
|
|
+ goto cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (backup_ext && *backup_ext) {
|
|
|
+ dstr_copy(&backup_path, path);
|
|
|
+ if (*backup_ext != '.')
|
|
|
+ dstr_cat(&backup_path, ".");
|
|
|
+ dstr_cat(&backup_path, backup_ext);
|
|
|
+
|
|
|
+ os_unlink(backup_path.array);
|
|
|
+ os_rename(path, backup_path.array);
|
|
|
+
|
|
|
+ dstr_free(&backup_path);
|
|
|
+ } else {
|
|
|
+ os_unlink(path);
|
|
|
+ }
|
|
|
+
|
|
|
+ os_rename(temp_path.array, path);
|
|
|
+ success = true;
|
|
|
+
|
|
|
+cleanup:
|
|
|
+ dstr_free(&backup_path);
|
|
|
+ dstr_free(&temp_path);
|
|
|
+ return success;
|
|
|
+}
|
|
|
+
|
|
|
size_t os_mbs_to_wcs(const char *str, size_t len, wchar_t *dst, size_t dst_size)
|
|
|
{
|
|
|
size_t out_len;
|