Hi,

Attatched is a patch that will fix a bug in vi, enhance functionality a
bit, reduce size and make the code a bit more readable. Testcase
follows.

  echo "this file is readonly" > file1
  chmod 400 file1
  sudo chown root file

Before patch:

  ./busybox_old vi file1

File is empty (user has no read permissions) and statusline says:

  - file1 1/1 100%

Note that there is no indication of error or [Read-only]

After patch:

  ./busybox vi file1

File is still empty (user has no read permissions) but status line says:

  - file1 [Read-only] 1/1 100%

Original vim shows "permission denied" but "Read-only" is better than
nothing.

Try edit file and save as root. Old behaviour let user do this even if
file is write protected.

After patch file will be marked as [Read-only]. root will need to save
file with :wq!

Make bloatcheck:

function                                             old     new   delta
update_ro_status                                       -      86     +86
edit_file                                            921     919      -2
colon                                               3798    3778     -20
file_insert                                          336     260     -76
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/3 up/down: 86/-98)            Total: -12
bytes
   text    data     bss     dec     hex filename
 706447    4728   14528  725703   b12c7 busybox_old
 706439    4728   14528  725695   b12bf busybox_unstripped


Natanael Copa
Index: editors/vi.c
===================================================================
--- editors/vi.c	(revision 19069)
+++ editors/vi.c	(working copy)
@@ -229,7 +229,8 @@
 static char readit(void);	// read (maybe cursor) key 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_insert(char *, char *, int);
+static int file_insert(char *, char *);
+USE_FEATURE_VI_READONLY(static void update_ro_status(const char *));
 static int file_write(char *, char *, char *);
 static void place_cursor(int, int, int);
 static void screen_erase(void);
@@ -419,8 +420,9 @@
 	new_text(size);		// get a text[] buffer
 	screenbegin = dot = end = text;
 	if (fn != 0) {
-		ch = file_insert(fn, text, cnt);
-	}
+		ch = file_insert(fn, text);
+		USE_FEATURE_VI_READONLY(update_ro_status(fn));
+	} 
 	if (ch < 1) {
 		char_insert(text, '\n');	// start empty buf with dummy line
 	}
@@ -654,7 +656,6 @@
 	char *fn, cmd[MAX_LINELEN], args[MAX_LINELEN];
 	int i, l, li, ch, b, e;
 	int useforce = FALSE, forced = FALSE;
-	struct stat st_buf;
 
 	// :3154	// if (-e line 3154) goto it  else stay put
 	// :4,33w! foo	// write a portion of buffer to file "foo"
@@ -758,6 +759,7 @@
 		dot_skip_over_ws();
 	} else if (strncasecmp(cmd, "edit", i) == 0) {	// Edit a file
 		int sr;
+		struct stat st_buf;
 		sr= 0;
 		// don't edit, if the current file has been modified
 		if (file_modified && ! useforce) {
@@ -809,7 +811,8 @@
 		screenbegin = dot = end = text;
 
 		// insert new file
-		ch = file_insert(fn, text, file_size(fn));
+		ch = file_insert(fn, text);
+		USE_FEATURE_VI_READONLY(update_ro_status(fn));
 
 		if (ch < 1) {
 			// start empty buf with dummy line
@@ -937,25 +940,15 @@
 		// read after current line- unless user said ":0r foo"
 		if (b != 0)
 			q = next_line(q);
-#if ENABLE_FEATURE_VI_READONLY
-		l = readonly;			// remember current files' status
-#endif
-		ch = file_insert(fn, q, file_size(fn));
-#if ENABLE_FEATURE_VI_READONLY
-		readonly = l;
-#endif
+		ch = file_insert(fn, q);
 		if (ch < 0)
 			goto vc1;	// nothing was inserted
 		// how many lines in text[]?
 		li = count_lines(q, q + ch - 1);
 		psb("\"%s\""
-#if ENABLE_FEATURE_VI_READONLY
-			"%s"
-#endif
+			USE_FEATURE_VI_READONLY("%s")
 			" %dL, %dC", fn,
-#if ENABLE_FEATURE_VI_READONLY
-			((vi_readonly || readonly) ? " [Read only]" : ""),
-#endif
+			USE_FEATURE_VI_READONLY(((vi_readonly || readonly) ? " [Read only]" : ""),)
 			li, ch);
 		if (ch > 0) {
 			// if the insert is before "dot" then we need to update
@@ -2399,37 +2392,22 @@
 static int file_size(const char * fn) // what is the byte size of "fn"
 {
 	struct stat st_buf;
-	int cnt, sr;
+	int cnt;
 
-	if (!fn || !fn[0])
-		return -1;
 	cnt = -1;
-	sr = stat(fn, &st_buf);	// see if file exists
-	if (sr >= 0) {
+	if (fn && fn[0] && stat(fn, &st_buf) == 0)	// see if file exists
 		cnt = (int) st_buf.st_size;
-	}
 	return cnt;
 }
 
-static int file_insert(char * fn, char * p, int size)
+static int file_insert(char * fn, char * p) 
 {
-	int fd, cnt;
-
-	cnt = -1;
-#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;
-	}
+	int cnt = -1;
+	int fd, size;
+	
+	size = file_size(fn);
 	if (size < 0) {
-		psbs("Trying to insert a negative number (%d) of characters", size);
+		psbs("File does not exist");
 		goto fi0;
 	}
 	if (p < text || p > end) {
@@ -2437,25 +2415,11 @@
 		goto fi0;
 	}
 
-	// see if we can open the file
-#if ENABLE_FEATURE_VI_READONLY
-	if (vi_readonly) goto fi1;		// do not try write-mode
-#endif
-	fd = open(fn, O_RDWR);			// assume read & write
+	// read file to buffer
+	fd = open(fn, O_RDONLY);
 	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) {
-			psbs("\"%s\" %s", fn, "cannot open file");
-			goto fi0;
-		}
-#if ENABLE_FEATURE_VI_READONLY
-		// got the file- read-only
-		readonly = TRUE;
-#endif
+		psbs("\"%s\" %s", fn, "cannot open file");
+		goto fi0;
 	}
 	p = text_hole_make(p, size);
 	cnt = read(fd, p, size);
@@ -2475,6 +2439,18 @@
 	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)
 {
 	int fd, cnt, charcnt;
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to