mirror of
https://github.com/weechat/weechat.git
synced 2026-07-10 11:43:13 +02:00
Fix bug with writing of configuration files when disk is full (bug #29331)
This commit is contained in:
+89
-58
@@ -153,13 +153,13 @@ config_file_new_section (struct t_config_file *config_file, const char *name,
|
||||
const char *option_name,
|
||||
const char *value),
|
||||
void *callback_read_data,
|
||||
void (*callback_write)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name),
|
||||
int (*callback_write)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name),
|
||||
void *callback_write_data,
|
||||
void (*callback_write_default)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name),
|
||||
int (*callback_write_default)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name),
|
||||
void *callback_write_default_data,
|
||||
int (*callback_create_option)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
@@ -1779,44 +1779,49 @@ config_file_option_color_default (struct t_config_option *option)
|
||||
|
||||
/*
|
||||
* config_file_write_option: write an option in a configuration file
|
||||
* return 1 if ok, 0 if error
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
config_file_write_option (struct t_config_file *config_file,
|
||||
struct t_config_option *option)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!config_file || !config_file->file || !option)
|
||||
return;
|
||||
|
||||
return 0;
|
||||
|
||||
rc = 1;
|
||||
|
||||
if (option->value)
|
||||
{
|
||||
switch (option->type)
|
||||
{
|
||||
case CONFIG_OPTION_TYPE_BOOLEAN:
|
||||
string_iconv_fprintf (config_file->file, "%s = %s\n",
|
||||
option->name,
|
||||
(CONFIG_BOOLEAN(option) == CONFIG_BOOLEAN_TRUE) ?
|
||||
"on" : "off");
|
||||
rc = string_iconv_fprintf (config_file->file, "%s = %s\n",
|
||||
option->name,
|
||||
(CONFIG_BOOLEAN(option) == CONFIG_BOOLEAN_TRUE) ?
|
||||
"on" : "off");
|
||||
break;
|
||||
case CONFIG_OPTION_TYPE_INTEGER:
|
||||
if (option->string_values)
|
||||
string_iconv_fprintf (config_file->file, "%s = %s\n",
|
||||
option->name,
|
||||
option->string_values[CONFIG_INTEGER(option)]);
|
||||
rc = string_iconv_fprintf (config_file->file, "%s = %s\n",
|
||||
option->name,
|
||||
option->string_values[CONFIG_INTEGER(option)]);
|
||||
else
|
||||
string_iconv_fprintf (config_file->file, "%s = %d\n",
|
||||
option->name,
|
||||
CONFIG_INTEGER(option));
|
||||
rc = string_iconv_fprintf (config_file->file, "%s = %d\n",
|
||||
option->name,
|
||||
CONFIG_INTEGER(option));
|
||||
break;
|
||||
case CONFIG_OPTION_TYPE_STRING:
|
||||
string_iconv_fprintf (config_file->file, "%s = \"%s\"\n",
|
||||
option->name,
|
||||
(char *)option->value);
|
||||
rc = string_iconv_fprintf (config_file->file, "%s = \"%s\"\n",
|
||||
option->name,
|
||||
(char *)option->value);
|
||||
break;
|
||||
case CONFIG_OPTION_TYPE_COLOR:
|
||||
string_iconv_fprintf (config_file->file, "%s = %s\n",
|
||||
option->name,
|
||||
gui_color_get_name (CONFIG_COLOR(option)));
|
||||
rc = string_iconv_fprintf (config_file->file, "%s = %s\n",
|
||||
option->name,
|
||||
gui_color_get_name (CONFIG_COLOR(option)));
|
||||
break;
|
||||
case CONFIG_NUM_OPTION_TYPES:
|
||||
break;
|
||||
@@ -1824,17 +1829,20 @@ config_file_write_option (struct t_config_file *config_file,
|
||||
}
|
||||
else
|
||||
{
|
||||
string_iconv_fprintf (config_file->file, "%s\n",
|
||||
option->name);
|
||||
rc = string_iconv_fprintf (config_file->file, "%s\n",
|
||||
option->name);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* config_file_write_line: write a line in a configuration file
|
||||
* if value is NULL, then write a section with [ ] around
|
||||
* return 1 if ok, 0 if error
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
config_file_write_line (struct t_config_file *config_file,
|
||||
const char *option_name, const char *value, ...)
|
||||
{
|
||||
@@ -1842,7 +1850,7 @@ config_file_write_line (struct t_config_file *config_file,
|
||||
va_list argptr;
|
||||
|
||||
if (!config_file || !option_name)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (value && value[0])
|
||||
{
|
||||
@@ -1852,14 +1860,13 @@ config_file_write_line (struct t_config_file *config_file,
|
||||
|
||||
if (buf[0])
|
||||
{
|
||||
string_iconv_fprintf (config_file->file, "%s = %s\n",
|
||||
option_name, buf);
|
||||
return;
|
||||
return (string_iconv_fprintf (config_file->file, "%s = %s\n",
|
||||
option_name, buf));
|
||||
}
|
||||
}
|
||||
|
||||
string_iconv_fprintf (config_file->file, "\n[%s]\n",
|
||||
option_name);
|
||||
return (string_iconv_fprintf (config_file->file, "\n[%s]\n",
|
||||
option_name));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1904,6 +1911,10 @@ config_file_write_internal (struct t_config_file *config_file,
|
||||
}
|
||||
snprintf (filename2, filename_length + 32, "%s.weechattmp", filename);
|
||||
|
||||
log_printf (_("Writing configuration file %s %s"),
|
||||
config_file->filename,
|
||||
(default_options) ? _("(default options)") : "");
|
||||
|
||||
/* open temp file in write mode */
|
||||
config_file->file = fopen (filename2, "w");
|
||||
if (!config_file->file)
|
||||
@@ -1912,20 +1923,16 @@ config_file_write_internal (struct t_config_file *config_file,
|
||||
_("%sError: cannot create file \"%s\""),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
filename2);
|
||||
free (filename);
|
||||
free (filename2);
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
log_printf (_("Writing configuration file %s %s"),
|
||||
config_file->filename,
|
||||
(default_options) ? _("(default options)") : "");
|
||||
|
||||
/* write header with version and date */
|
||||
string_iconv_fprintf (config_file->file, "#\n");
|
||||
string_iconv_fprintf (config_file->file,
|
||||
"# %s -- %s v%s\n#\n",
|
||||
config_file->filename, PACKAGE_NAME, PACKAGE_VERSION);
|
||||
if (!string_iconv_fprintf (config_file->file, "#\n"))
|
||||
goto error;
|
||||
if (!string_iconv_fprintf (config_file->file,
|
||||
"# %s -- %s v%s\n#\n",
|
||||
config_file->filename, PACKAGE_NAME, PACKAGE_VERSION))
|
||||
goto error;
|
||||
|
||||
/* write all sections */
|
||||
for (ptr_section = config_file->sections; ptr_section;
|
||||
@@ -1934,39 +1941,46 @@ config_file_write_internal (struct t_config_file *config_file,
|
||||
/* call write callback if defined for section */
|
||||
if (default_options && ptr_section->callback_write_default)
|
||||
{
|
||||
(void) (ptr_section->callback_write_default) (ptr_section->callback_write_default_data,
|
||||
config_file,
|
||||
ptr_section->name);
|
||||
if ((ptr_section->callback_write_default) (ptr_section->callback_write_default_data,
|
||||
config_file,
|
||||
ptr_section->name) != WEECHAT_CONFIG_WRITE_OK)
|
||||
goto error;
|
||||
}
|
||||
else if (!default_options && ptr_section->callback_write)
|
||||
{
|
||||
(void) (ptr_section->callback_write) (ptr_section->callback_write_data,
|
||||
config_file,
|
||||
ptr_section->name);
|
||||
if ((ptr_section->callback_write) (ptr_section->callback_write_data,
|
||||
config_file,
|
||||
ptr_section->name) != WEECHAT_CONFIG_WRITE_OK)
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* write all options for section */
|
||||
string_iconv_fprintf (config_file->file,
|
||||
"\n[%s]\n", ptr_section->name);
|
||||
if (!string_iconv_fprintf (config_file->file,
|
||||
"\n[%s]\n", ptr_section->name))
|
||||
goto error;
|
||||
for (ptr_option = ptr_section->options; ptr_option;
|
||||
ptr_option = ptr_option->next_option)
|
||||
{
|
||||
config_file_write_option (config_file, ptr_option);
|
||||
if (!config_file_write_option (config_file, ptr_option))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fflush (config_file->file) != 0)
|
||||
goto error;
|
||||
|
||||
/* close temp file */
|
||||
fclose (config_file->file);
|
||||
config_file->file = NULL;
|
||||
|
||||
|
||||
/* update file mode */
|
||||
chmod (filename2, 0600);
|
||||
|
||||
|
||||
/* remove target file */
|
||||
unlink (filename);
|
||||
|
||||
|
||||
/* rename temp file to target file */
|
||||
rc = rename (filename2, filename);
|
||||
|
||||
@@ -1977,6 +1991,23 @@ config_file_write_internal (struct t_config_file *config_file,
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
|
||||
return WEECHAT_CONFIG_WRITE_OK;
|
||||
|
||||
error:
|
||||
gui_chat_printf (NULL,
|
||||
_("%sError writing configuration file \"%s\""),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
filename);
|
||||
log_printf (_("%sError writing configuration file \"%s\""),
|
||||
"", config_file->filename);
|
||||
if (config_file->file)
|
||||
{
|
||||
fclose (config_file->file);
|
||||
config_file->file = NULL;
|
||||
}
|
||||
unlink (filename2);
|
||||
free (filename);
|
||||
free (filename2);
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+12
-12
@@ -70,12 +70,12 @@ struct t_config_section
|
||||
const char *option_name,
|
||||
const char *value);
|
||||
void *callback_read_data; /* data sent to read callback */
|
||||
void (*callback_write) /* called to write options */
|
||||
int (*callback_write) /* called to write options */
|
||||
(void *data, /* in config file (only for some */
|
||||
struct t_config_file *config_file, /* special sections) */
|
||||
const char *section_name);
|
||||
void *callback_write_data; /* data sent to write callback */
|
||||
void (*callback_write_default) /* called to write default */
|
||||
int (*callback_write_default) /* called to write default */
|
||||
(void *data, /* options in config file */
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name);
|
||||
@@ -158,13 +158,13 @@ extern struct t_config_section *config_file_new_section (struct t_config_file *c
|
||||
const char *option_name,
|
||||
const char *value),
|
||||
void *callback_read_data,
|
||||
void (*callback_write)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name),
|
||||
int (*callback_write)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name),
|
||||
void *callback_write_data,
|
||||
void (*callback_write_default)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name),
|
||||
int (*callback_write_default)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
const char *section_name),
|
||||
void *callback_write_default_data,
|
||||
int (*callback_create_option)(void *data,
|
||||
struct t_config_file *config_file,
|
||||
@@ -234,10 +234,10 @@ extern const char *config_file_option_string (struct t_config_option *option);
|
||||
extern const char *config_file_option_string_default (struct t_config_option *option);
|
||||
extern const char *config_file_option_color (struct t_config_option *option);
|
||||
extern const char *config_file_option_color_default (struct t_config_option *option);
|
||||
extern void config_file_write_option (struct t_config_file *config_file,
|
||||
struct t_config_option *option);
|
||||
extern void config_file_write_line (struct t_config_file *config_file,
|
||||
const char *option_name, const char *value, ...);
|
||||
extern int config_file_write_option (struct t_config_file *config_file,
|
||||
struct t_config_option *option);
|
||||
extern int config_file_write_line (struct t_config_file *config_file,
|
||||
const char *option_name, const char *value, ...);
|
||||
extern int config_file_write (struct t_config_file *config_files);
|
||||
extern int config_file_read (struct t_config_file *config_file);
|
||||
extern int config_file_reload (struct t_config_file *config_file);
|
||||
|
||||
+67
-38
@@ -807,33 +807,44 @@ config_weechat_layout_read_cb (void *data, struct t_config_file *config_file,
|
||||
* config_weechat_layout_write: write windows layout in configuration file
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
config_weechat_layout_write_tree (struct t_config_file *config_file,
|
||||
struct t_gui_layout_window *layout_window)
|
||||
{
|
||||
config_file_write_line (config_file, "window", "\"%d;%d;%d;%d;%s;%s\"",
|
||||
layout_window->internal_id,
|
||||
(layout_window->parent_node) ?
|
||||
layout_window->parent_node->internal_id : 0,
|
||||
layout_window->split_pct,
|
||||
layout_window->split_horiz,
|
||||
(layout_window->plugin_name) ?
|
||||
layout_window->plugin_name : "-",
|
||||
(layout_window->buffer_name) ?
|
||||
layout_window->buffer_name : "-");
|
||||
if (!config_file_write_line (config_file, "window", "\"%d;%d;%d;%d;%s;%s\"",
|
||||
layout_window->internal_id,
|
||||
(layout_window->parent_node) ?
|
||||
layout_window->parent_node->internal_id : 0,
|
||||
layout_window->split_pct,
|
||||
layout_window->split_horiz,
|
||||
(layout_window->plugin_name) ?
|
||||
layout_window->plugin_name : "-",
|
||||
(layout_window->buffer_name) ?
|
||||
layout_window->buffer_name : "-"))
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
|
||||
if (layout_window->child1)
|
||||
config_weechat_layout_write_tree (config_file, layout_window->child1);
|
||||
{
|
||||
if (config_weechat_layout_write_tree (config_file,
|
||||
layout_window->child1) != WEECHAT_CONFIG_WRITE_OK)
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
}
|
||||
|
||||
if (layout_window->child2)
|
||||
config_weechat_layout_write_tree (config_file, layout_window->child2);
|
||||
{
|
||||
if (config_weechat_layout_write_tree (config_file,
|
||||
layout_window->child2) != WEECHAT_CONFIG_WRITE_OK)
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
}
|
||||
|
||||
return WEECHAT_CONFIG_WRITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* config_weechat_layout_write_cb: write layout section in configuration file
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
config_weechat_layout_write_cb (void *data, struct t_config_file *config_file,
|
||||
const char *section_name)
|
||||
{
|
||||
@@ -842,19 +853,27 @@ config_weechat_layout_write_cb (void *data, struct t_config_file *config_file,
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
|
||||
config_file_write_line (config_file, section_name, NULL);
|
||||
if (!config_file_write_line (config_file, section_name, NULL))
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
|
||||
for (ptr_layout_buffer = gui_layout_buffers; ptr_layout_buffer;
|
||||
ptr_layout_buffer = ptr_layout_buffer->next_layout)
|
||||
{
|
||||
config_file_write_line (config_file, "buffer", "\"%s;%s;%d\"",
|
||||
ptr_layout_buffer->plugin_name,
|
||||
ptr_layout_buffer->buffer_name,
|
||||
ptr_layout_buffer->number);
|
||||
if (!config_file_write_line (config_file, "buffer", "\"%s;%s;%d\"",
|
||||
ptr_layout_buffer->plugin_name,
|
||||
ptr_layout_buffer->buffer_name,
|
||||
ptr_layout_buffer->number))
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
}
|
||||
|
||||
if (gui_layout_windows)
|
||||
config_weechat_layout_write_tree (config_file, gui_layout_windows);
|
||||
{
|
||||
if (config_weechat_layout_write_tree (config_file,
|
||||
gui_layout_windows) != WEECHAT_CONFIG_WRITE_OK)
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
}
|
||||
|
||||
return WEECHAT_CONFIG_WRITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1042,7 +1061,7 @@ config_weechat_filter_read_cb (void *data,
|
||||
* config_weechat_filter_write_cb: write filter section in configuration file
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
config_weechat_filter_write_cb (void *data, struct t_config_file *config_file,
|
||||
const char *section_name)
|
||||
{
|
||||
@@ -1051,21 +1070,25 @@ config_weechat_filter_write_cb (void *data, struct t_config_file *config_file,
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
|
||||
config_file_write_line (config_file, section_name, NULL);
|
||||
if (!config_file_write_line (config_file, section_name, NULL))
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
|
||||
for (ptr_filter = gui_filters; ptr_filter;
|
||||
ptr_filter = ptr_filter->next_filter)
|
||||
{
|
||||
config_file_write_line (config_file,
|
||||
ptr_filter->name,
|
||||
"%s;%s%s%s;%s;%s",
|
||||
(ptr_filter->enabled) ? "on" : "off",
|
||||
(ptr_filter->plugin_name) ? ptr_filter->plugin_name : "",
|
||||
(ptr_filter->plugin_name) ? "." : "",
|
||||
ptr_filter->buffer_name,
|
||||
ptr_filter->tags,
|
||||
ptr_filter->regex);
|
||||
if (!config_file_write_line (config_file,
|
||||
ptr_filter->name,
|
||||
"%s;%s%s%s;%s;%s",
|
||||
(ptr_filter->enabled) ? "on" : "off",
|
||||
(ptr_filter->plugin_name) ? ptr_filter->plugin_name : "",
|
||||
(ptr_filter->plugin_name) ? "." : "",
|
||||
ptr_filter->buffer_name,
|
||||
ptr_filter->tags,
|
||||
ptr_filter->regex))
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
}
|
||||
|
||||
return WEECHAT_CONFIG_WRITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1103,31 +1126,37 @@ config_weechat_key_read_cb (void *data, struct t_config_file *config_file,
|
||||
* config_weechat_key_write_cb: write key section in configuration file
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
config_weechat_key_write_cb (void *data, struct t_config_file *config_file,
|
||||
const char *section_name)
|
||||
{
|
||||
struct t_gui_key *ptr_key;
|
||||
char *expanded_name;
|
||||
int rc;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
|
||||
config_file_write_line (config_file, section_name, NULL);
|
||||
if (!config_file_write_line (config_file, section_name, NULL))
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
|
||||
for (ptr_key = gui_keys; ptr_key; ptr_key = ptr_key->next_key)
|
||||
{
|
||||
expanded_name = gui_keyboard_get_expanded_name (ptr_key->key);
|
||||
if (expanded_name)
|
||||
{
|
||||
config_file_write_line (config_file,
|
||||
(expanded_name) ?
|
||||
expanded_name : ptr_key->key,
|
||||
"\"%s\"",
|
||||
ptr_key->command);
|
||||
rc = config_file_write_line (config_file,
|
||||
(expanded_name) ?
|
||||
expanded_name : ptr_key->key,
|
||||
"\"%s\"",
|
||||
ptr_key->command);
|
||||
free (expanded_name);
|
||||
if (!rc)
|
||||
return WEECHAT_CONFIG_WRITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return WEECHAT_CONFIG_WRITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+10
-4
@@ -1217,28 +1217,34 @@ string_iconv_from_internal (const char *charset, const char *string)
|
||||
|
||||
/*
|
||||
* string_iconv_fprintf: encode to terminal charset, then call fprintf on a file
|
||||
* return 1 if ok, 0 if error
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
string_iconv_fprintf (FILE *file, const char *data, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char *buf, *buf2;
|
||||
|
||||
int rc, num_written;
|
||||
|
||||
buf = malloc (128 * 1024);
|
||||
if (!buf)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
va_start (argptr, data);
|
||||
vsnprintf (buf, 128 * 1024, data, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
buf2 = string_iconv_from_internal (NULL, buf);
|
||||
fprintf (file, "%s", (buf2) ? buf2 : buf);
|
||||
num_written = fprintf (file, "%s", (buf2) ? buf2 : buf);
|
||||
|
||||
rc = (num_written == (int)strlen ((buf2) ? buf2 : buf)) ? 1 : 0;
|
||||
|
||||
free (buf);
|
||||
if (buf2)
|
||||
free (buf2);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -54,7 +54,7 @@ extern char *string_iconv (int from_utf8, const char *from_code,
|
||||
extern char *string_iconv_to_internal (const char *charset, const char *string);
|
||||
extern char *string_iconv_from_internal (const char *charset,
|
||||
const char *string);
|
||||
extern void string_iconv_fprintf (FILE *file, const char *data, ...);
|
||||
extern int string_iconv_fprintf (FILE *file, const char *data, ...);
|
||||
extern char *string_format_size (unsigned long size);
|
||||
extern void string_encode_base64 (const char *from, int length, char *to);
|
||||
extern int string_decode_base64 (const char *from, char *to);
|
||||
|
||||
Reference in New Issue
Block a user