Properly handle saving of renamed studio; create backups on save; Closes #5
This commit is contained in:
parent
99da9acaf2
commit
9c4be0e919
110
daemon/studio.c
110
daemon/studio.c
|
@ -780,36 +780,47 @@ void escape(const char ** src_ptr, char ** dst_ptr)
|
||||||
*dst_ptr = dst;
|
*dst_ptr = dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool maybe_compose_filename(void)
|
static bool compose_filename(const char * name, char ** filename_ptr_ptr, char ** backup_filename_ptr_ptr)
|
||||||
{
|
{
|
||||||
size_t len_dir;
|
size_t len_dir;
|
||||||
char * p;
|
char * p;
|
||||||
const char * src;
|
const char * src;
|
||||||
|
char * filename_ptr;
|
||||||
if (g_studio.filename != NULL)
|
char * backup_filename_ptr;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
len_dir = strlen(g_studios_dir);
|
len_dir = strlen(g_studios_dir);
|
||||||
|
|
||||||
g_studio.filename = malloc(len_dir + 1 + strlen(g_studio.name) * 3 + 4);
|
filename_ptr = malloc(len_dir + 1 + strlen(name) * 3 + 4 + 1);
|
||||||
if (g_studio.filename == NULL)
|
if (filename_ptr == NULL)
|
||||||
{
|
{
|
||||||
lash_error("malloc failed to allocate memory for studio file path");
|
lash_error("malloc failed to allocate memory for studio file path");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = g_studio.filename;
|
backup_filename_ptr = malloc(len_dir + 1 + strlen(name) * 3 + 4 + 4 + 1);
|
||||||
|
if (backup_filename_ptr == NULL)
|
||||||
|
{
|
||||||
|
lash_error("malloc failed to allocate memory for studio backup file path");
|
||||||
|
free(filename_ptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = filename_ptr;
|
||||||
memcpy(p, g_studios_dir, len_dir);
|
memcpy(p, g_studios_dir, len_dir);
|
||||||
p += len_dir;
|
p += len_dir;
|
||||||
|
|
||||||
*p++ = '/';
|
*p++ = '/';
|
||||||
|
|
||||||
src = g_studio.name;
|
src = name;
|
||||||
escape(&src, &p);
|
escape(&src, &p);
|
||||||
strcpy(p, ".xml");
|
strcpy(p, ".xml");
|
||||||
|
|
||||||
|
strcpy(backup_filename_ptr, filename_ptr);
|
||||||
|
strcat(backup_filename_ptr, ".bak");
|
||||||
|
|
||||||
|
*filename_ptr_ptr = filename_ptr;
|
||||||
|
*backup_filename_ptr_ptr = backup_filename_ptr;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,6 +937,10 @@ bool studio_save(void * call_ptr)
|
||||||
time_t timestamp;
|
time_t timestamp;
|
||||||
char timestamp_str[26];
|
char timestamp_str[26];
|
||||||
bool ret;
|
bool ret;
|
||||||
|
char * filename; /* filename */
|
||||||
|
char * bak_filename; /* filename of the backup file */
|
||||||
|
char * old_filename; /* filename where studio was persisted before save */
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
time(×tamp);
|
time(×tamp);
|
||||||
ctime_r(×tamp, timestamp_str);
|
ctime_r(×tamp, timestamp_str);
|
||||||
|
@ -933,19 +948,64 @@ bool studio_save(void * call_ptr)
|
||||||
|
|
||||||
ret = false;
|
ret = false;
|
||||||
|
|
||||||
if (!maybe_compose_filename())
|
if (!compose_filename(g_studio.name, &filename, &bak_filename))
|
||||||
{
|
{
|
||||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "failed to compose studio filename");
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "failed to compose studio filename");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_studio.filename == NULL)
|
||||||
|
{
|
||||||
|
/* saving studio for first time */
|
||||||
|
g_studio.filename = filename;
|
||||||
|
free(bak_filename);
|
||||||
|
bak_filename = NULL;
|
||||||
|
old_filename = NULL;
|
||||||
|
}
|
||||||
|
else if (strcmp(g_studio.filename, filename) == 0)
|
||||||
|
{
|
||||||
|
/* saving already persisted studio that was not renamed */
|
||||||
|
old_filename = filename;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* saving renamed studio */
|
||||||
|
old_filename = g_studio.filename;
|
||||||
|
g_studio.filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = NULL;
|
||||||
|
assert(g_studio.filename != NULL);
|
||||||
|
assert(g_studio.filename != old_filename);
|
||||||
|
assert(g_studio.filename != bak_filename);
|
||||||
|
|
||||||
|
if (bak_filename != NULL)
|
||||||
|
{
|
||||||
|
assert(old_filename != NULL);
|
||||||
|
|
||||||
|
if (stat(old_filename, &st) == 0) /* if old filename does not exist, rename with fail */
|
||||||
|
{
|
||||||
|
if (rename(old_filename, bak_filename) != 0)
|
||||||
|
{
|
||||||
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "rename(%s, %s) failed: %d (%s)", old_filename, bak_filename, errno, strerror(errno));
|
||||||
|
goto free_filenames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* mark that there is no backup file */
|
||||||
|
free(bak_filename);
|
||||||
|
bak_filename = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lash_info("saving studio... (%s)", g_studio.filename);
|
lash_info("saving studio... (%s)", g_studio.filename);
|
||||||
|
|
||||||
fd = open(g_studio.filename, O_WRONLY | O_TRUNC | O_CREAT, 0700);
|
fd = open(g_studio.filename, O_WRONLY | O_TRUNC | O_CREAT, 0700);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "open(\"%s\") failed: %d (%s)", g_studio.filename, errno, strerror(errno));
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "open(%s) failed: %d (%s)", g_studio.filename, errno, strerror(errno));
|
||||||
goto exit;
|
goto rename_back;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!write_string(fd, "<?xml version=\"1.0\"?>\n", call_ptr))
|
if (!write_string(fd, "<?xml version=\"1.0\"?>\n", call_ptr))
|
||||||
|
@ -1030,6 +1090,30 @@ bool studio_save(void * call_ptr)
|
||||||
close:
|
close:
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
rename_back:
|
||||||
|
if (!ret && bak_filename != NULL)
|
||||||
|
{
|
||||||
|
/* save failed - try to rename the backup file back */
|
||||||
|
if (rename(bak_filename, g_studio.filename) != 0)
|
||||||
|
{
|
||||||
|
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "rename(%s, %s) failed: %d (%s)", bak_filename, g_studio.filename, errno, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free_filenames:
|
||||||
|
if (bak_filename != NULL)
|
||||||
|
{
|
||||||
|
free(bak_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_filename != NULL)
|
||||||
|
{
|
||||||
|
free(old_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(filename == NULL);
|
||||||
|
assert(g_studio.filename != NULL);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue