1
0
mirror of https://github.com/irssi/irssi.git synced 2024-09-01 04:14:16 -04:00

Merge pull request #871 from dequis/atomic-config-write

Make config_write more atomic to prevent truncation when out of space
This commit is contained in:
ailin-nemui 2018-04-24 13:58:15 +02:00 committed by GitHub
commit 0caf884e92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -301,30 +301,67 @@ int config_write(CONFIG_REC *rec, const char *fname, int create_mode)
{
int ret;
int fd;
int save_errno;
char *tmp_name;
const char *dest_name;
g_return_val_if_fail(rec != NULL, -1);
g_return_val_if_fail(fname != NULL || rec->fname != NULL, -1);
g_return_val_if_fail(create_mode != -1 || rec->create_mode != -1, -1);
fd = open(fname != NULL ? fname : rec->fname,
dest_name = fname != NULL ? fname : rec->fname;
tmp_name = g_strdup_printf("%s.XXXXXX", dest_name);
fd = g_mkstemp_full(tmp_name,
O_WRONLY | O_TRUNC | O_CREAT,
create_mode != -1 ? create_mode : rec->create_mode);
if (fd == -1)
return config_error(rec, g_strerror(errno));
if (fd == -1) {
config_error(rec, g_strerror(errno));
ret = -1;
goto out;
}
rec->handle = g_io_channel_unix_new(fd);
g_io_channel_set_encoding(rec->handle, NULL, NULL);
g_io_channel_set_close_on_unref(rec->handle, TRUE);
rec->tmp_indent_level = 0;
rec->tmp_last_lf = TRUE;
ret = config_write_block(rec, rec->mainnode, FALSE, TRUE);
save_errno = errno;
if (ret == -1) {
/* write error */
config_error(rec, errno == 0 ? "bug" : g_strerror(errno));
unlink(tmp_name);
config_error(rec, save_errno == 0 ? "bug" : g_strerror(save_errno));
goto out;
}
ret = fsync(fd);
save_errno = errno;
if (ret == -1) {
unlink(tmp_name);
config_error(rec, g_strerror(errno));
goto out;
}
g_io_channel_unref(rec->handle);
rec->handle = NULL;
if (rename(tmp_name, dest_name) == -1) {
unlink(tmp_name);
config_error(rec, g_strerror(errno));
goto out;
}
out:
if (rec->handle) {
g_io_channel_unref(rec->handle);
rec->handle = NULL;
}
g_free(tmp_name);
return ret;
}