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.
This commit is contained in:
jp9000 2015-08-21 17:49:07 -07:00
parent 40988f7e1d
commit e479d4d0dc
2 changed files with 49 additions and 0 deletions

View file

@ -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;

View file

@ -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);