Resolves: #1183320 - fix the file locking feature of nano

This commit is contained in:
Kamil Dudka 2015-01-26 15:10:26 +01:00
parent b620c02cb2
commit 967942c742
2 changed files with 346 additions and 1 deletions

338
nano-2.3.6-lockfile.patch Normal file
View File

@ -0,0 +1,338 @@
From 131d4b0988f319736bb36760cee300934bf9bc12 Mon Sep 17 00:00:00 2001
From: astyanax <astyanax@ac9c2fa3-95a5-41e5-9206-2167041ecc6c>
Date: Wed, 14 Jan 2015 02:36:30 +0000
Subject: [PATCH 1/3] 2015-01-13 Chris Allegretta <chrisa@asty.org> *
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 <astyanax@ac9c2fa3-95a5-41e5-9206-2167041ecc6c>
Date: Tue, 20 Jan 2015 06:15:34 +0000
Subject: [PATCH 2/3] 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 <kdudka@redhat.com>
Date: Mon, 26 Jan 2015 14:55:39 +0100
Subject: [PATCH 3/3] 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

View File

@ -1,7 +1,7 @@
Summary: A small text editor
Name: nano
Version: 2.3.6
Release: 4%{?dist}
Release: 5%{?dist}
License: GPLv3+
Group: Applications/Editors
URL: http://www.nano-editor.org
@ -15,6 +15,9 @@ Patch1: 0001-check-stat-s-result-and-avoid-calling-stat-on-a-NULL.patch
# http://lists.gnu.org/archive/html/nano-devel/2010-08/msg00005.html
Patch2: 0002-use-futimens-if-available-instead-of-utime.patch
# fix the file locking feature of nano (#1183320)
Patch3: nano-2.3.6-lockfile.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: file-devel
BuildRequires: gettext-devel
@ -34,6 +37,7 @@ GNU nano is a small and friendly text editor.
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
for f in doc/man/fr/{nano.1,nanorc.5,rnano.1} ; do
iconv -f iso-8859-1 -t utf-8 -o $f.tmp $f && mv $f.tmp $f
@ -89,6 +93,9 @@ exit 0
%{_datadir}/nano
%changelog
* Mon Jan 26 2015 Kamil Dudka <kdudka@redhat.com> - 2.3.6-5
- fix the file locking feature of nano (#1183320)
* Mon Jan 05 2015 Kamil Dudka <kdudka@redhat.com> - 2.3.6-4
- drop BR for autoconf, which is no longer needed