From 217cfbf362703b3e32d228822e1a8c932bc0abb0 Mon Sep 17 00:00:00 2001 From: Viorel Bota Date: Wed, 27 Sep 2017 23:42:48 +0300 Subject: [PATCH] files: check for a changed disk file also for 'savefile' and --tempfile Before writing a file out, nano should check that the file on disk hasn't been modified since it was read -- not only for the normal "Write Out" action (^O), but also for "Save File" (future ^S) and for "Save and Exit" (^X when --tempfile is used). When writing fails and --tempfile is in effect, don't go on to prompt for a file name; instead let the user decide what she wants to do. This fixes https://savannah.gnu.org/bugs/?51040. Signed-off-by: Viorel Bota Signed-off-by: Benno Schulenberg --- src/files.c | 47 +++++++++++++++++++++++++++++++---------------- src/nano.c | 2 +- src/proto.h | 2 +- src/text.c | 2 +- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/files.c b/src/files.c index 5c8d86f5..c895538a 100644 --- a/src/files.c +++ b/src/files.c @@ -2017,9 +2017,9 @@ bool write_marked_file(const char *name, FILE *f_open, bool tmp, * to disk regardless of whether the mark is on, and without prompting if * the TEMP_FILE flag is set and the current file has a name. Return 0 * on error, 1 on success, and 2 when the buffer is to be discarded. */ -int do_writeout(bool exiting) +int do_writeout(bool exiting, bool withprompt) { - int i; + int i = 0; bool result = FALSE; kind_of_writing_type method = OVERWRITE; char *given; @@ -2033,12 +2033,6 @@ int do_writeout(bool exiting) /* Display newlines in filenames as ^J. */ as_an_at = FALSE; - if (exiting && ISSET(TEMP_FILE) && openfile->filename[0] != '\0') { - if (write_file(openfile->filename, NULL, FALSE, OVERWRITE, FALSE)) - return 1; - /* If writing the file failed, go on to prompt for a new name. */ - } - given = mallocstrcpy(NULL, #ifndef NANO_TINY (openfile->mark_set && !exiting) ? "" : @@ -2073,6 +2067,11 @@ int do_writeout(bool exiting) present_path = mallocstrcpy(present_path, "./"); + /* When we shouldn't prompt, use the existing filename. */ + if ((!withprompt || (ISSET(TEMP_FILE) && exiting)) && + openfile->filename[0] != '\0') + answer = mallocstrcpy(answer, openfile->filename); + else { /* If we're using restricted mode, and the filename isn't blank, * disable tab completion. */ i = do_prompt(!ISSET(RESTRICTED) || openfile->filename[0] == '\0', @@ -2087,6 +2086,7 @@ int do_writeout(bool exiting) "", "" #endif ); + } if (i < 0) { statusbar(_("Cancelled")); @@ -2216,12 +2216,29 @@ int do_writeout(bool exiting) (openfile->current_stat->st_mtime < st.st_mtime || openfile->current_stat->st_dev != st.st_dev || openfile->current_stat->st_ino != st.st_ino)) { + int response; warn_and_shortly_pause(_("File on disk has changed")); - if (do_yesno_prompt(FALSE, _("File was modified since " - "you opened it; continue saving? ")) < 1) - continue; + response = do_yesno_prompt(FALSE, _("File was modified " + "since you opened it; continue saving? ")); + blank_statusbar(); + + /* When in tool mode and not called by 'savefile', + * overwrite the file right here when requested. */ + if (ISSET(TEMP_FILE) && withprompt) { + free(given); + if (response == 1) + return write_file(openfile->filename, + NULL, FALSE, OVERWRITE, FALSE); + else if (response == 0) + return 2; + else + return 0; + } else if (response != 1) { + free(given); + return 1; + } } #endif } @@ -2250,7 +2267,7 @@ int do_writeout(bool exiting) void do_writeout_void(void) { /* If the user chose to discard the buffer, close it. */ - if (do_writeout(FALSE) == 2) + if (do_writeout(FALSE, TRUE) == 2) close_and_go(); } @@ -2258,10 +2275,8 @@ void do_writeout_void(void) /* If it has a name, write the current file to disk without prompting. */ void do_savefile(void) { - if (openfile->filename[0] != '\0') - write_file(openfile->filename, NULL, FALSE, OVERWRITE, FALSE); - else - do_writeout_void(); + if (do_writeout(FALSE, FALSE) == 2) + close_and_go(); } #endif diff --git a/src/nano.c b/src/nano.c index 412b17ee..aa2faee6 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1081,7 +1081,7 @@ void do_exit(void) /* If the user chose not to save, or if the user chose to save and * the save succeeded, we're ready to exit. */ - if (i == 0 || (i == 1 && do_writeout(TRUE))) + if (i == 0 || (i == 1 && do_writeout(TRUE, TRUE) > 0)) close_and_go(); else if (i != 1) statusbar(_("Cancelled")); diff --git a/src/proto.h b/src/proto.h index 71c12d40..5199fd53 100644 --- a/src/proto.h +++ b/src/proto.h @@ -307,7 +307,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, bool write_marked_file(const char *name, FILE *f_open, bool tmp, kind_of_writing_type method); #endif -int do_writeout(bool exiting); +int do_writeout(bool exiting, bool withprompt); void do_writeout_void(void); #ifndef NANO_TINY void do_savefile(void); diff --git a/src/text.c b/src/text.c index 1cc867d4..d09d7c4f 100644 --- a/src/text.c +++ b/src/text.c @@ -3084,7 +3084,7 @@ void do_linter(void) if (i == -1) { statusbar(_("Cancelled")); return; - } else if (i == 1 && (do_writeout(FALSE) != TRUE)) + } else if (i == 1 && (do_writeout(FALSE, FALSE) != 1)) return; }