From 131d4b0988f319736bb36760cee300934bf9bc12 Mon Sep 17 00:00:00 2001 From: astyanax Date: Wed, 14 Jan 2015 02:36:30 +0000 Subject: [PATCH 1/6] 2015-01-13 Chris Allegretta * src/files.c (open_buffer): Check here for locking and properly handle choosing to not open a file when locked instead of in open_file(). Fixes Savannah bug 42373 reported by Benno Schulenberg git-svn-id: file:///home/kdudka/git/nano-svn/nano@5104 ac9c2fa3-95a5-41e5-9206-2167041ecc6c --- src/files.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/files.c b/src/files.c index a195e6f..e027d69 100644 --- a/src/files.c +++ b/src/files.c @@ -355,9 +355,25 @@ void open_buffer(const char *filename, bool undoable) /* If we're loading into a new buffer, add a new entry to * openfile. */ - if (new_buffer) + if (new_buffer) { make_new_buffer(); +#ifndef NANO_TINY + if (ISSET(LOCKING) && filename[0] != '\0') { + int lockstatus = do_lockfile(filename); + if (lockstatus < 0) { + if (openfile->next) { + close_buffer(); + statusbar(_("Cancelled")); + return; + } else + filename = ""; + } + } +#endif + } + + /* If the filename isn't blank, and we are not in NOREAD_MODE, * open the file. Otherwise, treat it as a new file. */ rc = (filename[0] != '\0' && !ISSET(NOREAD_MODE)) ? @@ -920,16 +936,6 @@ int open_file(const char *filename, bool newfie, FILE **f) full_filename = mallocstrcpy(NULL, filename); -#ifndef NANO_TINY - if (ISSET(LOCKING)) { - int lockstatus = do_lockfile(full_filename); - if (lockstatus < 0) - return -1; - else if (lockstatus == 0) - quiet = 1; - } -#endif - if (stat(full_filename, &fileinfo) == -1) { /* Well, maybe we can open the file even if the OS says it's * not there. */ -- 2.1.0 From f47060c02f57279445281e9f23079f2bdccdca3a Mon Sep 17 00:00:00 2001 From: astyanax Date: Tue, 20 Jan 2015 06:15:34 +0000 Subject: [PATCH 2/6] Take 2 at file locking fixes. New args to close_buffer() and switch_to_prevnext_buffer() to support message passthrough when trying to lock files using multibuffer. git-svn-id: file:///home/kdudka/git/nano-svn/nano@5105 ac9c2fa3-95a5-41e5-9206-2167041ecc6c --- src/files.c | 66 ++++++++++++++++++++++++++++++++++++------------------------- src/nano.c | 2 +- src/proto.h | 6 +++--- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/files.c b/src/files.c index e027d69..faa2e62 100644 --- a/src/files.c +++ b/src/files.c @@ -126,6 +126,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi pid_t mypid; uid_t myuid; struct passwd *mypwuid; + struct stat fileinfo; char *lockdata = charalloc(1024); char myhostname[32]; ssize_t lockdatalen = 1024; @@ -145,8 +146,10 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi return -1; } - if (delete_lockfile(lockfilename) < 0) - return -1; + /* Check if the lock exists before we try to delete it...*/ + if (stat(lockfilename, &fileinfo) != -1) + if (delete_lockfile(lockfilename) < 0) + return -1; if (ISSET(INSECURE_BACKUP)) cflags = O_WRONLY | O_CREAT | O_APPEND; @@ -156,11 +159,13 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi fd = open(lockfilename, cflags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - /* Maybe we just don't have write access. Don't stop us from - * opening the file at all, just don't set the lock_filename and - * return success. */ - if (fd < 0 && errno == EACCES) - return 1; + /* Maybe we just don't have write access. Print an error message + and continue. */ + if (fd < 0) { + statusbar(_("Error writing lock file %s: %s"), lockfilename, + strerror(errno)); + return 0; + } /* Now we've got a safe file stream. If the previous open() call * failed, this will return NULL. */ @@ -229,8 +234,8 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi int delete_lockfile(const char *lockfilename) { if (unlink(lockfilename) < 0 && errno != ENOENT) { - statusbar(_("Error deleting lock file %s: %s"), lockfilename, - strerror(errno)); + statusbar(_("Error deleting lock file %s: %s"), lockfilename, + strerror(errno)); return -1; } return 1; @@ -332,6 +337,7 @@ void stat_if_needed(const char *filename, struct stat **pstat) * necessary, and then open and read the file, if applicable. */ void open_buffer(const char *filename, bool undoable) { + bool quiet = FALSE; bool new_buffer = (openfile == NULL #ifndef DISABLE_MULTIBUFFER || ISSET(MULTIBUFFER) @@ -362,12 +368,14 @@ void open_buffer(const char *filename, bool undoable) if (ISSET(LOCKING) && filename[0] != '\0') { int lockstatus = do_lockfile(filename); if (lockstatus < 0) { +#ifndef DISABLE_MULTIBUFFER if (openfile->next) { - close_buffer(); - statusbar(_("Cancelled")); + close_buffer(TRUE); return; - } else - filename = ""; + } +#endif + } else if (lockstatus == 0) { + quiet = TRUE; } } #endif @@ -377,7 +385,7 @@ void open_buffer(const char *filename, bool undoable) /* If the filename isn't blank, and we are not in NOREAD_MODE, * open the file. Otherwise, treat it as a new file. */ rc = (filename[0] != '\0' && !ISSET(NOREAD_MODE)) ? - open_file(filename, new_buffer, &f) : -2; + open_file(filename, new_buffer, quiet, &f) : -2; /* If we have a file, and we're loading into a new buffer, update * the filename. */ @@ -425,7 +433,7 @@ void replace_buffer(const char *filename) /* If the filename isn't blank, open the file. Otherwise, treat it * as a new file. */ - rc = (filename[0] != '\0') ? open_file(filename, TRUE, &f) : -2; + rc = (filename[0] != '\0') ? open_file(filename, TRUE, FALSE, &f) : -2; /* Reinitialize the text of the current buffer. */ free_filestruct(openfile->fileage); @@ -461,14 +469,15 @@ void display_buffer(void) #ifndef DISABLE_MULTIBUFFER /* Switch to the next file buffer if next_buf is TRUE. Otherwise, * switch to the previous file buffer. */ -void switch_to_prevnext_buffer(bool next_buf) +void switch_to_prevnext_buffer(bool next_buf, bool quiet) { assert(openfile != NULL); /* If only one file buffer is open, indicate it on the statusbar and * get out. */ if (openfile == openfile->next) { - statusbar(_("No more open file buffers")); + if (quiet == FALSE) + statusbar(_("No more open file buffers")); return; } @@ -484,9 +493,10 @@ void switch_to_prevnext_buffer(bool next_buf) display_buffer(); /* Indicate the switch on the statusbar. */ - statusbar(_("Switched to %s"), - ((openfile->filename[0] == '\0') ? _("New Buffer") : - openfile->filename)); + if (quiet == FALSE) + statusbar(_("Switched to %s"), + ((openfile->filename[0] == '\0') ? _("New Buffer") : + openfile->filename)); #ifdef DEBUG dump_filestruct(openfile->current); @@ -497,19 +507,21 @@ void switch_to_prevnext_buffer(bool next_buf) /* Switch to the previous entry in the openfile filebuffer. */ void switch_to_prev_buffer_void(void) { - switch_to_prevnext_buffer(FALSE); + switch_to_prevnext_buffer(FALSE, FALSE); } /* Switch to the next entry in the openfile filebuffer. */ void switch_to_next_buffer_void(void) { - switch_to_prevnext_buffer(TRUE); + switch_to_prevnext_buffer(TRUE, FALSE); } /* Delete an entry from the openfile filebuffer, and switch to the one * after it. Return TRUE on success, or FALSE if there are no more open - * file buffers. */ -bool close_buffer(void) + * file buffers. + * quiet - should we print messages switching bufers + */ +bool close_buffer(bool quiet) { assert(openfile != NULL); @@ -522,7 +534,7 @@ bool close_buffer(void) #endif /* Switch to the next file buffer. */ - switch_to_next_buffer_void(); + switch_to_prevnext_buffer(TRUE, quiet); /* Close the file buffer we had open before. */ unlink_opennode(openfile->prev); @@ -918,10 +930,10 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw * Return -2 if we say "New File", -1 if the file isn't opened, and the * fd opened otherwise. The file might still have an error while reading * with a 0 return value. *f is set to the opened file. */ -int open_file(const char *filename, bool newfie, FILE **f) +int open_file(const char *filename, bool newfie, bool quiet, FILE **f) { struct stat fileinfo, fileinfo2; - int fd, quiet = 0; + int fd; char *full_filename; assert(filename != NULL && f != NULL); diff --git a/src/nano.c b/src/nano.c index 6c655bc..9635c24 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1152,7 +1152,7 @@ void do_exit(void) #ifndef DISABLE_MULTIBUFFER /* Exit only if there are no more open file buffers. */ - if (!close_buffer()) + if (!close_buffer(FALSE)) #endif finish(); /* If the user canceled, we go on. */ diff --git a/src/proto.h b/src/proto.h index 20f1fdb..579e6cf 100644 --- a/src/proto.h +++ b/src/proto.h @@ -283,15 +283,15 @@ void replace_buffer(const char *filename); #endif void display_buffer(void); #ifndef DISABLE_MULTIBUFFER -void switch_to_prevnext_buffer(bool next); +void switch_to_prevnext_buffer(bool next, bool quiet); void switch_to_prev_buffer_void(void); void switch_to_next_buffer_void(void); -bool close_buffer(void); +bool close_buffer(bool quiet); #endif filestruct *read_line(char *buf, filestruct *prevnode, bool *first_line_ins, size_t buf_len); void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkwritable); -int open_file(const char *filename, bool newfie, FILE **f); +int open_file(const char *filename, bool newfie, bool quiet, FILE **f); char *get_next_filename(const char *name, const char *suffix); void do_insertfile( #ifndef NANO_TINY -- 2.1.0 From 7fa511ffbd45975e0638ea3497b49081f99c4bc9 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 26 Jan 2015 14:55:39 +0100 Subject: [PATCH 3/6] avoid writing uninitialized bytes to the lock file The call to null_at() would not initialize the buffer: Syscall param write(buf) points to uninitialised byte(s) at 0x3EA76F0EB0: __write_nocancel (syscall-template.S:81) by 0x3EA767949C: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1302) by 0x3EA767A948: new_do_write (fileops.c:537) by 0x3EA767A948: _IO_do_write@@GLIBC_2.2.5 (fileops.c:510) by 0x3EA767A22F: _IO_file_close_it@@GLIBC_2.2.5 (fileops.c:166) by 0x3EA766E2C1: fclose@@GLIBC_2.2.5 (iofclose.c:59) by 0x40814C: write_lockfile (files.c:221) by 0x40847C: do_lockfile (files.c:314) by 0x40BC5E: open_buffer (files.c:351) by 0x4041D7: main (nano.c:2761) Address 0x4c1900c is not stack'd, malloc'd or (recently) free'd --- src/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/files.c b/src/files.c index faa2e62..1d0f0a8 100644 --- a/src/files.c +++ b/src/files.c @@ -195,7 +195,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi * our lockfile' message in here... * * This is likely very wrong, so this is a WIP. */ - null_at(&lockdata, lockdatalen); + memset(lockdata, 0, lockdatalen); lockdata[0] = 0x62; lockdata[1] = 0x30; lockdata[24] = mypid % 256; -- 2.1.0 From 0a7248ead64691a1f5f33dd1c7a4a55889110a92 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Tue, 27 Jan 2015 17:40:02 +0100 Subject: [PATCH 4/6] do_lockfile: make sure that lockprog and lockuser are terminated strncpy() does not guarantee that on its own! --- src/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/files.c b/src/files.c index 1d0f0a8..4468b4a 100644 --- a/src/files.c +++ b/src/files.c @@ -253,7 +253,7 @@ int do_lockfile(const char *filename) + strlen(locking_suffix) + 3; char *lockfilename = charalloc(lockfilesize); char *lockfiledir = NULL; - char lockprog[12], lockuser[16]; + static char lockprog[11], lockuser[17]; struct stat fileinfo; int lockfd, lockpid; -- 2.1.0 From f3e979d92659d19eb1f67c75f728cb979061901d Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Tue, 27 Jan 2015 17:30:28 +0100 Subject: [PATCH 5/6] do_lockfile: avoid printing wrong PID in status bar ... due to treating serialized PID bytes as singed integers Bug: https://bugzilla.redhat.com/1186384 Reported-by: Don Swaner --- src/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/files.c b/src/files.c index 4468b4a..8c832ff 100644 --- a/src/files.c +++ b/src/files.c @@ -284,7 +284,7 @@ int do_lockfile(const char *filename) return -1; } strncpy(lockprog, &lockbuf[2], 10); - lockpid = lockbuf[25] * 256 + lockbuf[24]; + lockpid = (unsigned char)lockbuf[25] * 256 + (unsigned char)lockbuf[24]; strncpy(lockuser, &lockbuf[28], 16); #ifdef DEBUG fprintf(stderr, "lockpid = %d\n", lockpid); -- 2.1.0 From a7f011d98358cd8dc0566494c51b8e37269b6752 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Tue, 27 Jan 2015 17:27:44 +0100 Subject: [PATCH 6/6] write_filelock: do not trim nano version ... as snprintf() counts the trailing zero into the size limit --- src/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/files.c b/src/files.c index 8c832ff..18be123 100644 --- a/src/files.c +++ b/src/files.c @@ -200,7 +200,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi lockdata[1] = 0x30; lockdata[24] = mypid % 256; lockdata[25] = mypid / 256; - snprintf(&lockdata[2], 10, "nano %s", VERSION); + snprintf(&lockdata[2], 11, "nano %s", VERSION); strncpy(&lockdata[28], mypwuid->pw_name, 16); strncpy(&lockdata[68], myhostname, 31); strncpy(&lockdata[108], origfilename, 768); -- 2.1.0