From e479d4d0dc61ef2bb352ed52ea44583804516f91 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Fri, 21 Aug 2015 17:49:07 -0700 Subject: [PATCH] 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. --- libobs/obs-data.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ libobs/obs-data.h | 4 ++++ 2 files changed, 49 insertions(+) diff --git a/libobs/obs-data.c b/libobs/obs-data.c index b6bb3edd8..05f9fe659 100644 --- a/libobs/obs-data.c +++ b/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; diff --git a/libobs/obs-data.h b/libobs/obs-data.h index c8d7c4c65..29c79a57e 100644 --- a/libobs/obs-data.h +++ b/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);