Parcourir la source

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 il y a 10 ans
Parent
commit
e479d4d0dc
2 fichiers modifiés avec 49 ajouts et 0 suppressions
  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);