Bladeren bron

libobs: Add obs_data funcs for safe file handling

obs_data_create_from_json_file_safe: Attempts to create an obs_data
object from a file, and if that fails and a backup file exists, deletes
the old file and tries to open it again.

obs_data_save_json_safe: Saves json data to a temporary file first,
optionally backs up the target file if the file exists and backup_ext is
valid (otherwise deletes it), and then renames the temporary file to the
target file.  This helps reduce the chance of json corruption on save.
jp9000 10 jaren geleden
bovenliggende
commit
e479d4d0dc
2 gewijzigde bestanden met toevoegingen van 49 en 0 verwijderingen
  1. 45 0
      libobs/obs-data.c
  2. 4 0
      libobs/obs-data.h

+ 45 - 0
libobs/obs-data.c

@@ -17,6 +17,7 @@
 
 #include "util/bmem.h"
 #include "util/threading.h"
+#include "util/dstr.h"
 #include "util/darray.h"
 #include "util/platform.h"
 #include "graphics/vec2.h"
@@ -655,6 +656,37 @@ obs_data_t *obs_data_create_from_json_file(const char *json_file)
 	return data;
 }
 
+obs_data_t *obs_data_create_from_json_file_safe(const char *json_file,
+		const char *backup_ext)
+{
+	obs_data_t *file_data = obs_data_create_from_json_file(json_file);
+	if (!file_data && backup_ext && *backup_ext) {
+		struct dstr backup_file = {0};
+
+		dstr_copy(&backup_file, json_file);
+		if (*backup_ext != '.')
+			dstr_cat(&backup_file, ".");
+		dstr_cat(&backup_file, backup_ext);
+
+		if (os_file_exists(backup_file.array)) {
+			blog(LOG_WARNING, "obs-data.c: "
+					"[obs_data_create_from_json_file_safe] "
+					"attempting backup file");
+
+			/* delete current file if corrupt to prevent it from
+			 * being backed up again */
+			os_unlink(json_file);
+			os_rename(backup_file.array, json_file);
+
+			file_data = obs_data_create_from_json_file(json_file);
+		}
+
+		dstr_free(&backup_file);
+	}
+
+	return file_data;
+}
+
 void obs_data_addref(obs_data_t *data)
 {
 	if (data)
@@ -711,6 +743,19 @@ bool obs_data_save_json(obs_data_t *data, const char *file)
 	return false;
 }
 
+bool obs_data_save_json_safe(obs_data_t *data, const char *file,
+		const char *temp_ext, const char *backup_ext)
+{
+	const char *json = obs_data_get_json(data);
+
+	if (json && *json) {
+		return os_quick_write_utf8_file_safe(file, json, strlen(json),
+				false, temp_ext, backup_ext);
+	}
+
+	return false;
+}
+
 static struct obs_data_item *get_item(struct obs_data *data, const char *name)
 {
 	if (!data) return NULL;

+ 4 - 0
libobs/obs-data.h

@@ -63,11 +63,15 @@ enum obs_data_number_type {
 EXPORT obs_data_t *obs_data_create();
 EXPORT obs_data_t *obs_data_create_from_json(const char *json_string);
 EXPORT obs_data_t *obs_data_create_from_json_file(const char *json_file);
+EXPORT obs_data_t *obs_data_create_from_json_file_safe(const char *json_file,
+		const char *backup_ext);
 EXPORT void obs_data_addref(obs_data_t *data);
 EXPORT void obs_data_release(obs_data_t *data);
 
 EXPORT const char *obs_data_get_json(obs_data_t *data);
 EXPORT bool obs_data_save_json(obs_data_t *data, const char *file);
+EXPORT bool obs_data_save_json_safe(obs_data_t *data, const char *file,
+		const char *temp_ext, const char *backup_ext);
 
 EXPORT void obs_data_apply(obs_data_t *target, obs_data_t *apply_data);