summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2000-10-15 19:21:21 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2000-10-15 19:21:21 +0000
commita2cac63e56d88101cd101f0e37c4b8c741467599 (patch)
tree7334640e8f7fc0a17e381d676b3a807b21bc0355
parent228c1d7f366c0d103b00188a7945797068e4c741 (diff)
downloadirssi-a2cac63e56d88101cd101f0e37c4b8c741467599.zip
Irssi won't automatically overwrite configuration files if they're
changed while irssi is running: - /SAVE asks whether to save it or not - autosave at quit saves it to config.autosave file git-svn-id: http://svn.irssi.org/repos/irssi/trunk@762 dbcabf3a-b0e7-0310-adc4-f8d773084564
-rw-r--r--src/core/settings.c93
-rw-r--r--src/core/settings.h1
-rw-r--r--src/fe-common/core/fe-settings.c32
-rw-r--r--src/fe-common/core/module-formats.c1
-rw-r--r--src/fe-common/core/module-formats.h3
5 files changed, 115 insertions, 15 deletions
diff --git a/src/core/settings.c b/src/core/settings.c
index 96663c3b..80406261 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -35,6 +35,10 @@ static GHashTable *settings;
static char *last_error_msg;
static int timeout_tag;
+static time_t config_last_mtime;
+static long config_last_size;
+static unsigned int config_last_checksum;
+
static const char *settings_get_default_str(const char *key)
{
SETTINGS_REC *rec;
@@ -212,6 +216,51 @@ void sig_term(int n)
raise(SIGTERM);
}
+/* Yes, this is my own stupid checksum generator, some "real" algorithm
+ would be nice but would just take more space without much real benefit */
+static unsigned int file_checksum(const char *fname)
+{
+ FILE *f;
+ int n = 0;
+ unsigned int checksum = 0;
+
+ f = fopen(fname, "rb");
+ while (!feof(f))
+ checksum += fgetc(f) << ((n++ & 3)*8);
+ fclose(f);
+ return checksum;
+}
+
+static void irssi_config_save_state(const char *fname)
+{
+ struct stat statbuf;
+
+ g_return_if_fail(fname != NULL);
+
+ if (stat(fname, &statbuf) != 0)
+ return;
+
+ /* save modify time, file size and checksum */
+ config_last_mtime = statbuf.st_mtime;
+ config_last_size = statbuf.st_size;
+ config_last_checksum = file_checksum(fname);
+}
+
+int irssi_config_is_changed(const char *fname)
+{
+ struct stat statbuf;
+
+ if (fname == NULL)
+ fname = mainconfig->fname;
+
+ if (stat(fname, &statbuf) != 0)
+ return FALSE;
+
+ return config_last_mtime != statbuf.st_mtime &&
+ (config_last_size != statbuf.st_size ||
+ config_last_checksum != file_checksum(fname));
+}
+
static CONFIG_REC *parse_configfile(const char *fname)
{
CONFIG_REC *config;
@@ -239,6 +288,7 @@ static CONFIG_REC *parse_configfile(const char *fname)
config_change_file_name(config, real_fname, 0660);
}
+ irssi_config_save_state(real_fname);
g_free(real_fname);
return config;
}
@@ -323,22 +373,44 @@ int settings_reread(const char *fname)
int settings_save(const char *fname)
{
char *str;
+ int error;
- if (config_write(mainconfig, fname, 0660) == 0)
- return TRUE;
+ if (fname == NULL)
+ fname = mainconfig->fname;
- /* error */
- str = g_strdup_printf(_("Couldn't save configuration file: %s"),
- config_last_error(mainconfig));
- signal_emit("gui dialog", 2, "error", str);
- g_free(str);
- return FALSE;
+ error = config_write(mainconfig, fname, 0660) != 0;
+ irssi_config_save_state(fname);
+ if (error) {
+ str = g_strdup_printf(_("Couldn't save "
+ "configuration file: %s"),
+ config_last_error(mainconfig));
+ signal_emit("gui dialog", 2, "error", str);
+ g_free(str);
+ }
+ return !error;
}
static void sig_autosave(void)
{
- if (settings_get_bool("settings_autosave"))
- settings_save(NULL);
+ char *fname, *str;
+
+ if (!settings_get_bool("settings_autosave"))
+ return;
+
+ if (!irssi_config_is_changed(NULL))
+ settings_save(NULL);
+ else {
+ fname = g_strconcat(mainconfig->fname, ".autosave", NULL);
+ str = g_strdup_printf(_("Configuration file was modified "
+ "while irssi was running. Saving "
+ "configuration to file '%s' instead"),
+ fname);
+ signal_emit("gui dialog", 2, "warning", str);
+ g_free(str);
+
+ settings_save(fname);
+ g_free(fname);
+ }
}
void settings_init(void)
@@ -346,6 +418,7 @@ void settings_init(void)
settings = g_hash_table_new((GHashFunc) g_str_hash,
(GCompareFunc) g_str_equal);
+ config_last_mtime = 0;
init_configfile();
settings_add_bool("misc", "settings_autosave", TRUE);
diff --git a/src/core/settings.h b/src/core/settings.h
index a887797a..8409f607 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -57,6 +57,7 @@ SETTINGS_REC *settings_get_record(const char *key);
/* if `fname' is NULL, the default is used */
int settings_reread(const char *fname);
int settings_save(const char *fname);
+int irssi_config_is_changed(const char *fname);
void settings_init(void);
void settings_deinit(void);
diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c
index 4c2bf823..4d8266dd 100644
--- a/src/fe-common/core/fe-settings.c
+++ b/src/fe-common/core/fe-settings.c
@@ -245,14 +245,38 @@ static void cmd_reload(const char *data)
g_free(fname);
}
+static void settings_save_fe(const char *fname)
+{
+ if (settings_save(fname)) {
+ printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ IRCTXT_CONFIG_SAVED, fname);
+ }
+}
+
+static void settings_save_confirm(const char *line, char *fname)
+{
+ if (toupper(*line) == 'Y')
+ settings_save_fe(fname);
+ g_free(fname);
+}
+
/* SYNTAX: SAVE [<file>] */
static void cmd_save(const char *data)
{
- if (settings_save(*data != '\0' ? data : NULL)) {
- printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
- IRCTXT_CONFIG_SAVED, *data != '\0' ? data :
- mainconfig->fname);
+ if (*data == '\0')
+ data = mainconfig->fname;
+
+ if (!irssi_config_is_changed(data)) {
+ settings_save_fe(data);
+ return;
}
+
+ printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ IRCTXT_CONFIG_MODIFIED, data);
+ signal_emit("gui entry redirect", 4,
+ settings_save_confirm,
+ _("Overwrite config (y/N)?"),
+ GINT_TO_POINTER(FALSE), g_strdup(data));
}
void fe_settings_init(void)
diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c
index ee4c99d8..ec555ecb 100644
--- a/src/fe-common/core/module-formats.c
+++ b/src/fe-common/core/module-formats.c
@@ -202,6 +202,7 @@ FORMAT_REC fecommon_core_formats[] = {
{ "bind_unknown_id", "Unknown bind action: $0", 1, { 0 } },
{ "config_saved", "Saved configuration to file $0", 1, { 0 } },
{ "config_reloaded", "Reloaded configuration", 1, { 0 } },
+ { "config_modified", "Configuration file was modified since irssi was last started - do you want to overwrite the possible changes?", 1, { 0 } },
{ NULL, NULL, 0 }
};
diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h
index 01390a15..362b9074 100644
--- a/src/fe-common/core/module-formats.h
+++ b/src/fe-common/core/module-formats.h
@@ -167,7 +167,8 @@ enum {
IRCTXT_BIND_KEY,
IRCTXT_BIND_UNKNOWN_ID,
IRCTXT_CONFIG_SAVED,
- IRCTXT_CONFIG_RELOADED
+ IRCTXT_CONFIG_RELOADED,
+ IRCTXT_CONFIG_MODIFIED
};
extern FORMAT_REC fecommon_core_formats[];