2009-09-02 Chris Allegretta <chrisa@asty.org>

* Attempt to check file writability and emit a warning on the status bar
          if nano doesn't think the file can be written to.  Feature originally
          requested by Damien Jolders <madamien@skullsquad.com> et al.



git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4407 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
master
Chris Allegretta 2009-09-03 05:45:13 +00:00
parent 5687c3dfa6
commit f8f9027295
5 changed files with 96 additions and 19 deletions

View File

@ -1,3 +1,8 @@
2009-09-02 Chris Allegretta <chrisa@asty.org>
* Attempt to check file writability and emit a warning on the status bar
if nano doesn't think the file can be written to. Feature originally
requested by Damien Jolders <madamien@skullsquad.com> et al.
2009-08-29 Chris Allegretta <chrisa@asty.org> 2009-08-29 Chris Allegretta <chrisa@asty.org>
* Fix more soft wrapping issues, particularly with scrolling, * Fix more soft wrapping issues, particularly with scrolling,
discovered by Hannes <mr_creosote@mutantwatch.de>. discovered by Hannes <mr_creosote@mutantwatch.de>.

View File

@ -145,8 +145,8 @@ void open_buffer(const char *filename, bool undoable)
/* If we have a non-new file, read it in. Then, if the buffer has /* If we have a non-new file, read it in. Then, if the buffer has
* no stat, update the stat, if applicable. */ * no stat, update the stat, if applicable. */
if (rc == 0) { if (rc > 0) {
read_file(f, filename, undoable); read_file(f, rc, filename, undoable);
#ifndef NANO_TINY #ifndef NANO_TINY
if (openfile->current_stat == NULL) { if (openfile->current_stat == NULL) {
openfile->current_stat = openfile->current_stat =
@ -195,8 +195,8 @@ void replace_buffer(const char *filename)
initialize_buffer_text(); initialize_buffer_text();
/* If we have a non-new file, read it in. */ /* If we have a non-new file, read it in. */
if (rc == 0) if (rc > 0)
read_file(f, filename, FALSE); read_file(f, rc, filename, FALSE);
/* Move back to the beginning of the first line of the buffer. */ /* Move back to the beginning of the first line of the buffer. */
openfile->current = openfile->fileage; openfile->current = openfile->fileage;
@ -348,8 +348,10 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool
/* Read an open file into the current buffer. f should be set to the /* Read an open file into the current buffer. f should be set to the
* open file, and filename should be set to the name of the file. * open file, and filename should be set to the name of the file.
undoable means do we want to create undo records to try and undo this */ * undoable means do we want to create undo records to try and undo this.
void read_file(FILE *f, const char *filename, bool undoable) * Will also attempt to check file writability if fd > 0
*/
void read_file(FILE *f, int fd, const char *filename, bool undoable)
{ {
size_t num_lines = 0; size_t num_lines = 0;
/* The number of lines in the file. */ /* The number of lines in the file. */
@ -370,6 +372,8 @@ void read_file(FILE *f, const char *filename, bool undoable)
int input_int; int input_int;
/* The current value we read from the file, whether an input /* The current value we read from the file, whether an input
* character or EOF. */ * character or EOF. */
bool writable = TRUE;
/* Is the file writable (if we care) */
#ifndef NANO_TINY #ifndef NANO_TINY
int format = 0; int format = 0;
/* 0 = *nix, 1 = DOS, 2 = Mac, 3 = both DOS and Mac. */ /* 0 = *nix, 1 = DOS, 2 = Mac, 3 = both DOS and Mac. */
@ -469,6 +473,11 @@ void read_file(FILE *f, const char *filename, bool undoable)
if (ferror(f)) if (ferror(f))
nperror(filename); nperror(filename);
fclose(f); fclose(f);
if (fd > 0) {
int closecode = close(fd);
fprintf(stderr, "Closecode = %d\n", closecode);
writable = is_file_writable(filename);
}
#ifndef NANO_TINY #ifndef NANO_TINY
/* If file conversion isn't disabled and the last character in this /* If file conversion isn't disabled and the last character in this
@ -578,24 +587,45 @@ void read_file(FILE *f, const char *filename, bool undoable)
if (undoable) if (undoable)
update_undo(INSERT); update_undo(INSERT);
if (format == 3) if (format == 3) {
statusbar( if (writable)
statusbar(
P_("Read %lu line (Converted from DOS and Mac format)", P_("Read %lu line (Converted from DOS and Mac format)",
"Read %lu lines (Converted from DOS and Mac format)", "Read %lu lines (Converted from DOS and Mac format)",
(unsigned long)num_lines), (unsigned long)num_lines); (unsigned long)num_lines), (unsigned long)num_lines);
else if (format == 2) { else
statusbar(
P_("Read %lu line (Converted from DOS and Mac format - Warning: No write permission)",
"Read %lu lines (Converted from DOS and Mac format - Warning: No write permission)",
(unsigned long)num_lines), (unsigned long)num_lines);
} else if (format == 2) {
openfile->fmt = MAC_FILE; openfile->fmt = MAC_FILE;
statusbar(P_("Read %lu line (Converted from Mac format)", if (writable)
statusbar(P_("Read %lu line (Converted from Mac format)",
"Read %lu lines (Converted from Mac format)", "Read %lu lines (Converted from Mac format)",
(unsigned long)num_lines), (unsigned long)num_lines); (unsigned long)num_lines), (unsigned long)num_lines);
else
statusbar(P_("Read %lu line (Converted from Mac format - Warning: No write permission)",
"Read %lu lines (Converted from Mac format - Warning: No write permission)",
(unsigned long)num_lines), (unsigned long)num_lines);
} else if (format == 1) { } else if (format == 1) {
openfile->fmt = DOS_FILE; openfile->fmt = DOS_FILE;
statusbar(P_("Read %lu line (Converted from DOS format)", if (writable)
statusbar(P_("Read %lu line (Converted from DOS format)",
"Read %lu lines (Converted from DOS format)", "Read %lu lines (Converted from DOS format)",
(unsigned long)num_lines), (unsigned long)num_lines); (unsigned long)num_lines), (unsigned long)num_lines);
else
statusbar(P_("Read %lu line (Converted from DOS format - Warning: No write permission)",
"Read %lu lines (Converted from DOS format - Warning: No write permission)",
(unsigned long)num_lines), (unsigned long)num_lines);
} else } else
#endif #endif
statusbar(P_("Read %lu line", "Read %lu lines", if (writable)
statusbar(P_("Read %lu line", "Read %lu lines",
(unsigned long)num_lines), (unsigned long)num_lines);
else
statusbar(P_("Read %lu line ( Warning: No write permission)",
"Read %lu lines (Warning: No write permission)",
(unsigned long)num_lines), (unsigned long)num_lines); (unsigned long)num_lines), (unsigned long)num_lines);
} }
@ -603,9 +633,9 @@ void read_file(FILE *f, const char *filename, bool undoable)
* "New File" if the file is missing. Otherwise, say "[filename] not * "New File" if the file is missing. Otherwise, say "[filename] not
* found". * found".
* *
* Return -2 if we say "New File", -1 if the file isn't opened, and 0 * Return -2 if we say "New File", -1 if the file isn't opened, and the
* otherwise. The file might still have an error while reading with a 0 * fd opened otherwise. The file might still have an error while reading
* return value. *f is set to the opened file. */ * 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, FILE **f)
{ {
struct stat fileinfo, fileinfo2; struct stat fileinfo, fileinfo2;
@ -668,9 +698,51 @@ int open_file(const char *filename, bool newfie, FILE **f)
free(full_filename); free(full_filename);
return 0; return fd;
} }
/* A bit of a copy and paste from open_file(), is_file_writable()
* just checks whether the file is appendable as a quick
* permissions check, and we tend to err on the side of permissiveness
* (reporting TRUE when it might be wrong) to not fluster users
* editing on odd filesystems by printing incorrect warnings.
*/
int is_file_writable(const char *filename)
{
struct stat fileinfo, fileinfo2;
int fd;
FILE *f;
char *full_filename;
bool ans = TRUE;
if (ISSET(VIEW_MODE))
return TRUE;
assert(filename != NULL && f != NULL);
/* Get the specified file's full path. */
full_filename = get_full_path(filename);
/* Okay, if we can't stat the path due to a component's
permissions, just try the relative one */
if (full_filename == NULL
|| (stat(full_filename, &fileinfo) == -1 && stat(filename, &fileinfo2) != -1))
full_filename = mallocstrcpy(NULL, filename);
if ((fd = open(full_filename, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR |
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1
|| (f = fdopen(fd, "a")) == NULL)
ans = FALSE;
else
fclose(f);
close(fd);
free(full_filename);
return ans;
}
/* This function will return the name of the first available extension /* This function will return the name of the first available extension
* of a filename (starting with [name][suffix], then [name][suffix].1, * of a filename (starting with [name][suffix], then [name][suffix].1,
* etc.). Memory is allocated for the return value. If no writable * etc.). Memory is allocated for the return value. If no writable

View File

@ -1060,7 +1060,7 @@ void finish_stdin_pager(void)
if (f == NULL) if (f == NULL)
nperror("fopen"); nperror("fopen");
read_file(f, "stdin", TRUE); read_file(f, 0, "stdin", TRUE);
ttystdin = open("/dev/tty", O_RDONLY); ttystdin = open("/dev/tty", O_RDONLY);
if (!ttystdin) if (!ttystdin)
die(_("Couldn't reopen stdin from keyboard, sorry\n")); die(_("Couldn't reopen stdin from keyboard, sorry\n"));

View File

@ -270,7 +270,7 @@ bool close_buffer(void);
#endif #endif
filestruct *read_line(char *buf, filestruct *prevnode, bool filestruct *read_line(char *buf, filestruct *prevnode, bool
*first_line_ins, size_t buf_len); *first_line_ins, size_t buf_len);
void read_file(FILE *f, const char *filename, bool undoable); void read_file(FILE *f, int fd, const char *filename, bool undoable);
int open_file(const char *filename, bool newfie, FILE **f); int open_file(const char *filename, bool newfie, FILE **f);
char *get_next_filename(const char *name, const char *suffix); char *get_next_filename(const char *name, const char *suffix);
void do_insertfile( void do_insertfile(

View File

@ -812,7 +812,7 @@ bool execute_command(const char *command)
if (f == NULL) if (f == NULL)
nperror("fdopen"); nperror("fdopen");
read_file(f, "stdin", TRUE); read_file(f, 0, "stdin", TRUE);
if (wait(NULL) == -1) if (wait(NULL) == -1)
nperror("wait"); nperror("wait");