diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2015-07-31 16:42:20 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2015-07-31 16:42:20 +0200 |
commit | 9dc526d0f91c37ecdf6280c2cd69107c6102076e (patch) | |
tree | f55255e96215b8a444c77c157be6858f32df3e07 | |
parent | 1ecb996fd2641e6ad3fdf07e78781823c71fcf13 (diff) | |
download | busybox-w32-9dc526d0f91c37ecdf6280c2cd69107c6102076e.tar.gz busybox-w32-9dc526d0f91c37ecdf6280c2cd69107c6102076e.tar.bz2 busybox-w32-9dc526d0f91c37ecdf6280c2cd69107c6102076e.zip |
less: improve regular file detection in line counting code
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/less.c | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index b38fcf766..be8d20e66 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -165,12 +165,6 @@ enum { | |||
165 | enum { pattern_valid = 0 }; | 165 | enum { pattern_valid = 0 }; |
166 | #endif | 166 | #endif |
167 | 167 | ||
168 | enum { | ||
169 | READING_FILE = -1, | ||
170 | READING_STDIN = -2, | ||
171 | READING_NONREG = -3 | ||
172 | }; | ||
173 | |||
174 | struct globals { | 168 | struct globals { |
175 | int cur_fline; /* signed */ | 169 | int cur_fline; /* signed */ |
176 | int kbd_fd; /* fd to get input from */ | 170 | int kbd_fd; /* fd to get input from */ |
@@ -195,7 +189,10 @@ struct globals { | |||
195 | char *filename; | 189 | char *filename; |
196 | char **files; | 190 | char **files; |
197 | #if ENABLE_FEATURE_LESS_FLAGS | 191 | #if ENABLE_FEATURE_LESS_FLAGS |
198 | int num_lines; /* input source if < 0, line count if >= 0 */ | 192 | int num_lines; /* a flag if < 0, line count if >= 0 */ |
193 | # define REOPEN_AND_COUNT (-1) | ||
194 | # define REOPEN_STDIN (-2) | ||
195 | # define NOT_REGULAR_FILE (-3) | ||
199 | #endif | 196 | #endif |
200 | #if ENABLE_FEATURE_LESS_MARKS | 197 | #if ENABLE_FEATURE_LESS_MARKS |
201 | unsigned num_marks; | 198 | unsigned num_marks; |
@@ -622,14 +619,29 @@ static void update_num_lines(void) | |||
622 | char buf[4096]; | 619 | char buf[4096]; |
623 | 620 | ||
624 | /* only do this for regular files */ | 621 | /* only do this for regular files */ |
625 | if (num_lines == READING_FILE) { | 622 | if (num_lines != NOT_REGULAR_FILE) { |
626 | count = 0; | 623 | count = 0; |
627 | fd = open(filename, O_RDONLY); | 624 | fd = open("/proc/self/fd/0", O_RDONLY); |
625 | if (fd < 0 && num_lines == REOPEN_AND_COUNT) { | ||
626 | /* "filename" is valid only if REOPEN_AND_COUNT */ | ||
627 | fd = open(filename, O_RDONLY); | ||
628 | } | ||
628 | if (fd < 0) { | 629 | if (fd < 0) { |
629 | /* somebody stole my file! */ | 630 | /* somebody stole my file! */ |
630 | num_lines = READING_NONREG; | 631 | num_lines = NOT_REGULAR_FILE; |
631 | return; | 632 | return; |
632 | } | 633 | } |
634 | #if ENABLE_FEATURE_LESS_FLAGS | ||
635 | { | ||
636 | struct stat stbuf; | ||
637 | if (fstat(fd, &stbuf) != 0 | ||
638 | || !S_ISREG(stbuf.st_mode) | ||
639 | ) { | ||
640 | num_lines = NOT_REGULAR_FILE; | ||
641 | goto do_close; | ||
642 | } | ||
643 | } | ||
644 | #endif | ||
633 | while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { | 645 | while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { |
634 | for (i = 0; i < len; ++i) { | 646 | for (i = 0; i < len; ++i) { |
635 | if (buf[i] == '\n' && ++count == MAXLINES) | 647 | if (buf[i] == '\n' && ++count == MAXLINES) |
@@ -638,6 +650,7 @@ static void update_num_lines(void) | |||
638 | } | 650 | } |
639 | done: | 651 | done: |
640 | num_lines = count; | 652 | num_lines = count; |
653 | do_close: | ||
641 | close(fd); | 654 | close(fd); |
642 | } | 655 | } |
643 | } | 656 | } |
@@ -991,18 +1004,17 @@ static void buffer_lineno(int lineno) | |||
991 | static void open_file_and_read_lines(void) | 1004 | static void open_file_and_read_lines(void) |
992 | { | 1005 | { |
993 | if (filename) { | 1006 | if (filename) { |
1007 | xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO); | ||
994 | #if ENABLE_FEATURE_LESS_FLAGS | 1008 | #if ENABLE_FEATURE_LESS_FLAGS |
995 | struct stat stbuf; | 1009 | num_lines = REOPEN_AND_COUNT; |
996 | |||
997 | xstat(filename, &stbuf); | ||
998 | if (!S_ISREG(stbuf.st_mode)) | ||
999 | num_lines = READING_NONREG; | ||
1000 | #endif | 1010 | #endif |
1001 | xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO); | ||
1002 | } else { | 1011 | } else { |
1003 | /* "less" with no arguments in argv[] */ | 1012 | /* "less" with no arguments in argv[] */ |
1004 | /* For status line only */ | 1013 | /* For status line only */ |
1005 | filename = xstrdup(bb_msg_standard_input); | 1014 | filename = xstrdup(bb_msg_standard_input); |
1015 | #if ENABLE_FEATURE_LESS_FLAGS | ||
1016 | num_lines = REOPEN_STDIN; | ||
1017 | #endif | ||
1006 | } | 1018 | } |
1007 | readpos = 0; | 1019 | readpos = 0; |
1008 | readeof = 0; | 1020 | readeof = 0; |
@@ -1026,9 +1038,6 @@ static void reinitialize(void) | |||
1026 | max_fline = -1; | 1038 | max_fline = -1; |
1027 | cur_fline = 0; | 1039 | cur_fline = 0; |
1028 | max_lineno = 0; | 1040 | max_lineno = 0; |
1029 | #if ENABLE_FEATURE_LESS_FLAGS | ||
1030 | num_lines = filename ? READING_FILE : READING_STDIN; | ||
1031 | #endif | ||
1032 | open_file_and_read_lines(); | 1041 | open_file_and_read_lines(); |
1033 | #if ENABLE_FEATURE_LESS_ASK_TERMINAL | 1042 | #if ENABLE_FEATURE_LESS_ASK_TERMINAL |
1034 | if (G.winsize_err) | 1043 | if (G.winsize_err) |