vi: make status line less confusing when we open non-readable files,

require rood to use w! when saving non-writable files.
Patch by Natanael Copa <natanael.copa@gmail.com>

update_ro_status                                       -      73     +73
edit_file                                            819     822      +3
colon                                               3440    3425     -15
.rodata                                           128090  128058     -32
file_insert                                          288     235     -53
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/3 up/down: 76/-100)           Total: -24 bytes
   text    data     bss     dec     hex filename
 673344    2740   13968  690052   a8784 busybox_old
 673320    2740   13968  690028   a876c busybox_unstripped
This commit is contained in:
Denis Vlasenko 2007-07-14 22:43:10 +00:00
parent fb79a2e2cf
commit 59a1f30450

View File

@ -229,7 +229,12 @@ static int mysleep(int); // sleep for 'h' 1/100 seconds
static char readit(void); // read (maybe cursor) key from stdin static char readit(void); // read (maybe cursor) key from stdin
static char get_one_char(void); // read 1 char from stdin static char get_one_char(void); // read 1 char from stdin
static int file_size(const char *); // what is the byte size of "fn" static int file_size(const char *); // what is the byte size of "fn"
static int file_insert(char *, char *, int); static int file_insert(char *, char *);
#if ENABLE_FEATURE_VI_READONLY
static void update_ro_status(const char *);
#else
static ALWAYS_INLINE void update_ro_status(const char *name) {}
#endif
static int file_write(char *, char *, char *); static int file_write(char *, char *, char *);
static void place_cursor(int, int, int); static void place_cursor(int, int, int);
static void screen_erase(void); static void screen_erase(void);
@ -419,7 +424,8 @@ static void edit_file(char * fn)
new_text(size); // get a text[] buffer new_text(size); // get a text[] buffer
screenbegin = dot = end = text; screenbegin = dot = end = text;
if (fn != 0) { if (fn != 0) {
ch = file_insert(fn, text, cnt); ch = file_insert(fn, text);
update_ro_status(fn);
} }
if (ch < 1) { if (ch < 1) {
char_insert(text, '\n'); // start empty buf with dummy line char_insert(text, '\n'); // start empty buf with dummy line
@ -654,7 +660,6 @@ static void colon(char * buf)
char *fn, cmd[MAX_LINELEN], args[MAX_LINELEN]; char *fn, cmd[MAX_LINELEN], args[MAX_LINELEN];
int i, l, li, ch, b, e; int i, l, li, ch, b, e;
int useforce = FALSE, forced = FALSE; int useforce = FALSE, forced = FALSE;
struct stat st_buf;
// :3154 // if (-e line 3154) goto it else stay put // :3154 // if (-e line 3154) goto it else stay put
// :4,33w! foo // write a portion of buffer to file "foo" // :4,33w! foo // write a portion of buffer to file "foo"
@ -758,6 +763,7 @@ static void colon(char * buf)
dot_skip_over_ws(); dot_skip_over_ws();
} else if (strncasecmp(cmd, "edit", i) == 0) { // Edit a file } else if (strncasecmp(cmd, "edit", i) == 0) { // Edit a file
int sr; int sr;
struct stat st_buf;
sr= 0; sr= 0;
// don't edit, if the current file has been modified // don't edit, if the current file has been modified
if (file_modified && ! useforce) { if (file_modified && ! useforce) {
@ -809,7 +815,8 @@ static void colon(char * buf)
screenbegin = dot = end = text; screenbegin = dot = end = text;
// insert new file // insert new file
ch = file_insert(fn, text, file_size(fn)); ch = file_insert(fn, text);
update_ro_status(fn);
if (ch < 1) { if (ch < 1) {
// start empty buf with dummy line // start empty buf with dummy line
@ -937,25 +944,15 @@ static void colon(char * buf)
// read after current line- unless user said ":0r foo" // read after current line- unless user said ":0r foo"
if (b != 0) if (b != 0)
q = next_line(q); q = next_line(q);
#if ENABLE_FEATURE_VI_READONLY ch = file_insert(fn, q);
l = readonly; // remember current files' status
#endif
ch = file_insert(fn, q, file_size(fn));
#if ENABLE_FEATURE_VI_READONLY
readonly = l;
#endif
if (ch < 0) if (ch < 0)
goto vc1; // nothing was inserted goto vc1; // nothing was inserted
// how many lines in text[]? // how many lines in text[]?
li = count_lines(q, q + ch - 1); li = count_lines(q, q + ch - 1);
psb("\"%s\"" psb("\"%s\""
#if ENABLE_FEATURE_VI_READONLY USE_FEATURE_VI_READONLY("%s")
"%s"
#endif
" %dL, %dC", fn, " %dL, %dC", fn,
#if ENABLE_FEATURE_VI_READONLY USE_FEATURE_VI_READONLY(((vi_readonly || readonly) ? " [Read only]" : ""),)
((vi_readonly || readonly) ? " [Read only]" : ""),
#endif
li, ch); li, ch);
if (ch > 0) { if (ch > 0) {
// if the insert is before "dot" then we need to update // if the insert is before "dot" then we need to update
@ -2399,37 +2396,22 @@ static char *get_input_line(const char * prompt) // get input line- use "status
static int file_size(const char * fn) // what is the byte size of "fn" static int file_size(const char * fn) // what is the byte size of "fn"
{ {
struct stat st_buf; struct stat st_buf;
int cnt, sr; int cnt;
if (!fn || !fn[0])
return -1;
cnt = -1; cnt = -1;
sr = stat(fn, &st_buf); // see if file exists if (fn && fn[0] && stat(fn, &st_buf) == 0) // see if file exists
if (sr >= 0) {
cnt = (int) st_buf.st_size; cnt = (int) st_buf.st_size;
}
return cnt; return cnt;
} }
static int file_insert(char * fn, char * p, int size) static int file_insert(char * fn, char * p)
{ {
int fd, cnt; int cnt = -1;
int fd, size;
cnt = -1; size = file_size(fn);
#if ENABLE_FEATURE_VI_READONLY
readonly = FALSE;
#endif
if (!fn || !fn[0]) {
psbs("No filename given");
goto fi0;
}
if (size == 0) {
// OK- this is just a no-op
cnt = 0;
goto fi0;
}
if (size < 0) { if (size < 0) {
psbs("Trying to insert a negative number (%d) of characters", size); psbs("File does not exist");
goto fi0; goto fi0;
} }
if (p < text || p > end) { if (p < text || p > end) {
@ -2437,26 +2419,12 @@ static int file_insert(char * fn, char * p, int size)
goto fi0; goto fi0;
} }
// see if we can open the file // read file to buffer
#if ENABLE_FEATURE_VI_READONLY fd = open(fn, O_RDONLY);
if (vi_readonly) goto fi1; // do not try write-mode
#endif
fd = open(fn, O_RDWR); // assume read & write
if (fd < 0) {
// could not open for writing- maybe file is read only
#if ENABLE_FEATURE_VI_READONLY
fi1:
#endif
fd = open(fn, O_RDONLY); // try read-only
if (fd < 0) { if (fd < 0) {
psbs("\"%s\" %s", fn, "cannot open file"); psbs("\"%s\" %s", fn, "cannot open file");
goto fi0; goto fi0;
} }
#if ENABLE_FEATURE_VI_READONLY
// got the file- read-only
readonly = TRUE;
#endif
}
p = text_hole_make(p, size); p = text_hole_make(p, size);
cnt = read(fd, p, size); cnt = read(fd, p, size);
close(fd); close(fd);
@ -2475,6 +2443,19 @@ static int file_insert(char * fn, char * p, int size)
return cnt; return cnt;
} }
#if ENABLE_FEATURE_VI_READONLY
static void update_ro_status(const char *fn)
{
struct stat sb;
if (stat(fn, &sb) == 0) {
readonly = vi_readonly || (access(fn, W_OK) < 0) ||
/* root will always have access()
* so we check fileperms too */
!(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH));
}
}
#endif
static int file_write(char * fn, char * first, char * last) static int file_write(char * fn, char * first, char * last)
{ {
int fd, cnt, charcnt; int fd, cnt, charcnt;