diff --git a/sysmisc.c b/sysmisc.c index 7f7420f..62c04fb 100644 --- a/sysmisc.c +++ b/sysmisc.c @@ -215,8 +215,7 @@ FILE* conf_file_open_for_reading(void) { Conf_save_start_error conf_save_start(Conf_save* p) { memset(p, 0, sizeof(Conf_save)); - oso *dir = NULL, *canonpath = NULL, *temppath = NULL; - FILE *origfile = NULL, *tempfile = NULL; + oso* dir = NULL; Conf_save_start_error err; if (try_get_conf_dir(&dir)) { err = Conf_save_start_no_home; @@ -226,53 +225,54 @@ Conf_save_start_error conf_save_start(Conf_save* p) { err = Conf_save_start_alloc_failed; goto cleanup; } - osoputoso(&canonpath, dir); - osocat(&canonpath, conf_file_name); - if (!canonpath) { + osoputoso(&p->canonpath, dir); + osocat(&p->canonpath, conf_file_name); + if (!p->canonpath) { err = Conf_save_start_alloc_failed; goto cleanup; } - osoputoso(&temppath, canonpath); - osocat(&temppath, ".tmp"); - if (!temppath) { + osoputoso(&p->temppath, p->canonpath); + osocat(&p->temppath, ".tmp"); + if (!p->temppath) { err = Conf_save_start_alloc_failed; goto cleanup; } // Remove old temp file if it exists. If it exists and we can't remove it, // error. - if (unlink(osoc(temppath)) == -1 && errno != ENOENT) { - err = Conf_save_start_old_temp_file_stuck; + if (unlink(osoc(p->temppath)) == -1 && errno != ENOENT) { + switch (errno) { + case ENOTDIR: + err = Conf_save_start_conf_dir_not_dir; + break; + case EACCES: + err = Conf_save_start_temp_file_perm_denied; + break; + default: + err = Conf_save_start_old_temp_file_stuck; + break; + } goto cleanup; } - tempfile = fopen(osoc(temppath), "w"); - if (!tempfile) { + p->tempfile = fopen(osoc(p->temppath), "w"); + if (!p->tempfile) { // Try to create config dir, in case it doesn't exist. (XDG says we should // do this, and use mode 0700.) mkdir(osoc(dir), 0700); - tempfile = fopen(osoc(temppath), "w"); + p->tempfile = fopen(osoc(p->temppath), "w"); } - if (!tempfile) { + if (!p->tempfile) { err = Conf_save_start_temp_file_open_failed; goto cleanup; } // This may be left as NULL. - origfile = fopen(osoc(canonpath), "r"); + p->origfile = fopen(osoc(p->canonpath), "r"); // We did it, boys. osofree(dir); - p->canonpath = canonpath; - p->temppath = temppath; - p->origfile = origfile; - p->tempfile = tempfile; return Conf_save_start_ok; cleanup: osofree(dir); - osofree(canonpath); - osofree(temppath); - if (origfile) - fclose(origfile); - if (tempfile) - fclose(tempfile); + conf_save_cancel(p); return err; } diff --git a/sysmisc.h b/sysmisc.h index 483088c..5103a3a 100644 --- a/sysmisc.h +++ b/sysmisc.h @@ -40,6 +40,8 @@ typedef enum { Conf_save_start_alloc_failed, Conf_save_start_no_home, Conf_save_start_mkdir_failed, + Conf_save_start_conf_dir_not_dir, + Conf_save_start_temp_file_perm_denied, Conf_save_start_old_temp_file_stuck, Conf_save_start_temp_file_open_failed, } Conf_save_start_error; diff --git a/tui_main.c b/tui_main.c index 22b6f73..9fe5495 100644 --- a/tui_main.c +++ b/tui_main.c @@ -2393,17 +2393,42 @@ static void put_conf_pair(FILE* file, char const* left, char const* right) { typedef enum { Prefs_save_ok = 0, - Prefs_save_start_failed, - Prefs_save_commit_failed, + Prefs_save_oom, + Prefs_save_no_home, + Prefs_save_mkdir_failed, + Prefs_save_conf_dir_not_dir, + Prefs_save_old_temp_file_stuck, + Prefs_save_temp_file_perm_denied, + Prefs_save_temp_open_failed, + Prefs_save_temp_fsync_failed, + Prefs_save_temp_close_failed, + Prefs_save_rename_failed, Prefs_save_line_too_long, Prefs_save_existing_read_error, + Prefs_save_unknown_error, } Prefs_save_error; Prefs_save_error save_prefs_to_disk(Midi_mode const* midi_mode) { Conf_save save; Conf_save_start_error starterr = conf_save_start(&save); - if (starterr) - return Prefs_save_start_failed; + switch (starterr) { + case Conf_save_start_ok: + break; + case Conf_save_start_alloc_failed: + return Prefs_save_oom; + case Conf_save_start_no_home: + return Prefs_save_no_home; + case Conf_save_start_mkdir_failed: + return Prefs_save_mkdir_failed; + case Conf_save_start_conf_dir_not_dir: + return Prefs_save_conf_dir_not_dir; + case Conf_save_start_old_temp_file_stuck: + return Prefs_save_old_temp_file_stuck; + case Conf_save_start_temp_file_perm_denied: + return Prefs_save_temp_file_perm_denied; + case Conf_save_start_temp_file_open_failed: + return Prefs_save_temp_open_failed; + } bool need_cancel_save = true; enum Midi_output_pref { Midi_output_pref_none = 0, @@ -2484,11 +2509,21 @@ done_reading_existing: } need_cancel_save = false; Conf_save_commit_error comerr = conf_save_commit(&save); - if (comerr) { - error = Prefs_save_commit_failed; - goto cleanup; + error = Prefs_save_unknown_error; + switch (comerr) { + case Conf_save_commit_ok: + error = Prefs_save_ok; + break; + case Conf_save_commit_temp_fsync_failed: + error = Prefs_save_temp_fsync_failed; + break; + case Conf_save_commit_temp_close_failed: + error = Prefs_save_temp_close_failed; + break; + case Conf_save_commit_rename_failed: + error = Prefs_save_rename_failed; + break; } - error = Prefs_save_ok; cleanup: if (need_cancel_save) conf_save_cancel(&save); @@ -2502,11 +2537,36 @@ void save_prefs_with_error_message(Midi_mode const* midi_mode) { switch (err) { case Prefs_save_ok: return; - case Prefs_save_start_failed: - msg = "Start failed"; + case Prefs_save_oom: + msg = "Out of memory"; + break; + case Prefs_save_no_home: + msg = "Unable to resolve $XDG_CONFIG_HOME or $HOME"; + break; + case Prefs_save_mkdir_failed: + msg = "Unable to create $XDG_CONFIG_HOME or $HOME/.config directory"; break; - case Prefs_save_commit_failed: - msg = "Failed to commit save file"; + case Prefs_save_conf_dir_not_dir: + msg = "Config directory path is not a directory"; + break; + case Prefs_save_old_temp_file_stuck: + msg = "Unable to remove old orca.conf.tmp file"; + break; + case Prefs_save_temp_file_perm_denied: + msg = "Permission denied for config directory"; + break; + case Prefs_save_temp_open_failed: + msg = "Unable to open orca.conf.tmp for writing"; + break; + case Prefs_save_temp_fsync_failed: + msg = "fsync() reported an when writing temp file.\n" + "Refusing to continue."; + break; + case Prefs_save_temp_close_failed: + msg = "Unable to close temp file"; + break; + case Prefs_save_rename_failed: + msg = "Unable to rename orca.conf.tmp to orca.conf"; break; case Prefs_save_line_too_long: msg = "Line in file is too long"; @@ -2514,6 +2574,8 @@ void save_prefs_with_error_message(Midi_mode const* midi_mode) { case Prefs_save_existing_read_error: msg = "Error when reading existing configuration file"; break; + case Prefs_save_unknown_error: + break; } qmsg_printf_push("Save Error", "Error when saving:\n%s", msg); }