[git commit] less: improve regular file detection in line counting code

Denys Vlasenko vda.linux at googlemail.com
Fri Jul 31 14:42:20 UTC 2015


commit: http://git.busybox.net/busybox/commit/?id=9dc526d0f91c37ecdf6280c2cd69107c6102076e
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 miscutils/less.c |   47 ++++++++++++++++++++++++++++-------------------
 1 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/miscutils/less.c b/miscutils/less.c
index b38fcf7..be8d20e 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -165,12 +165,6 @@ enum {
 enum { pattern_valid = 0 };
 #endif
 
-enum {
-	READING_FILE = -1,
-	READING_STDIN = -2,
-	READING_NONREG = -3
-};
-
 struct globals {
 	int cur_fline; /* signed */
 	int kbd_fd;  /* fd to get input from */
@@ -195,7 +189,10 @@ struct globals {
 	char *filename;
 	char **files;
 #if ENABLE_FEATURE_LESS_FLAGS
-	int num_lines; /* input source if < 0, line count if >= 0 */
+	int num_lines; /* a flag if < 0, line count if >= 0 */
+# define REOPEN_AND_COUNT (-1)
+# define REOPEN_STDIN     (-2)
+# define NOT_REGULAR_FILE (-3)
 #endif
 #if ENABLE_FEATURE_LESS_MARKS
 	unsigned num_marks;
@@ -622,14 +619,29 @@ static void update_num_lines(void)
 	char buf[4096];
 
 	/* only do this for regular files */
-	if (num_lines == READING_FILE) {
+	if (num_lines != NOT_REGULAR_FILE) {
 		count = 0;
-		fd = open(filename, O_RDONLY);
+		fd = open("/proc/self/fd/0", O_RDONLY);
+		if (fd < 0 && num_lines == REOPEN_AND_COUNT) {
+			/* "filename" is valid only if REOPEN_AND_COUNT */
+			fd = open(filename, O_RDONLY);
+		}
 		if (fd < 0) {
 			/* somebody stole my file! */
-			num_lines = READING_NONREG;
+			num_lines = NOT_REGULAR_FILE;
 			return;
 		}
+#if ENABLE_FEATURE_LESS_FLAGS
+		{
+			struct stat stbuf;
+			if (fstat(fd, &stbuf) != 0
+			 || !S_ISREG(stbuf.st_mode)
+			) {
+				num_lines = NOT_REGULAR_FILE;
+				goto do_close;
+			}
+		}
+#endif
 		while ((len = safe_read(fd, buf, sizeof(buf))) > 0) {
 			for (i = 0; i < len; ++i) {
 				if (buf[i] == '\n' && ++count == MAXLINES)
@@ -638,6 +650,7 @@ static void update_num_lines(void)
 		}
  done:
 		num_lines = count;
+ do_close:
 		close(fd);
 	}
 }
@@ -991,18 +1004,17 @@ static void buffer_lineno(int lineno)
 static void open_file_and_read_lines(void)
 {
 	if (filename) {
+		xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
 #if ENABLE_FEATURE_LESS_FLAGS
-		struct stat stbuf;
-
-		xstat(filename, &stbuf);
-		if (!S_ISREG(stbuf.st_mode))
-			num_lines = READING_NONREG;
+		num_lines = REOPEN_AND_COUNT;
 #endif
-		xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
 	} else {
 		/* "less" with no arguments in argv[] */
 		/* For status line only */
 		filename = xstrdup(bb_msg_standard_input);
+#if ENABLE_FEATURE_LESS_FLAGS
+		num_lines = REOPEN_STDIN;
+#endif
 	}
 	readpos = 0;
 	readeof = 0;
@@ -1026,9 +1038,6 @@ static void reinitialize(void)
 	max_fline = -1;
 	cur_fline = 0;
 	max_lineno = 0;
-#if ENABLE_FEATURE_LESS_FLAGS
-	num_lines = filename ? READING_FILE : READING_STDIN;
-#endif
 	open_file_and_read_lines();
 #if ENABLE_FEATURE_LESS_ASK_TERMINAL
 	if (G.winsize_err)


More information about the busybox-cvs mailing list