aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-06-07 11:34:06 +0100
committerRon Yorston <rmy@pobox.com>2021-06-07 11:34:06 +0100
commitabe872e2a0342357a5608342cb2892e94027b3e7 (patch)
tree297cdccf332fbb5e4eb31b1eac643180059f9b5f /coreutils
parent1f33f42d7bcb019b268d938df643a7a785dc19ab (diff)
parent4d983dcddeee94892d3072e84c7c9a01d4696055 (diff)
downloadbusybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.tar.gz
busybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.tar.bz2
busybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/head.c13
-rw-r--r--coreutils/ls.c30
-rw-r--r--coreutils/tail.c67
3 files changed, 65 insertions, 45 deletions
diff --git a/coreutils/head.c b/coreutils/head.c
index efb023c6f..9586f869f 100644
--- a/coreutils/head.c
+++ b/coreutils/head.c
@@ -29,17 +29,18 @@
29//usage:#define head_trivial_usage 29//usage:#define head_trivial_usage
30//usage: "[OPTIONS] [FILE]..." 30//usage: "[OPTIONS] [FILE]..."
31//usage:#define head_full_usage "\n\n" 31//usage:#define head_full_usage "\n\n"
32//usage: "Print first 10 lines of FILEs (or stdin) to stdout.\n" 32//usage: "Print first 10 lines of FILEs (or stdin).\n"
33//usage: "With more than one FILE, precede each with a filename header.\n" 33//usage: "With more than one FILE, precede each with a filename header.\n"
34//usage: "\n -n N[kbm] Print first N lines" 34//usage: "\n -n N[bkm] Print first N lines"
35//usage: IF_FEATURE_FANCY_HEAD(
36//usage: "\n -n -N[bkm] Print all except N last lines"
37//usage: "\n -c [-]N[bkm] Print first N bytes"
38//usage: )
39//usage: "\n (b:*512 k:*1024 m:*1024^2)"
35//usage: IF_FEATURE_FANCY_HEAD( 40//usage: IF_FEATURE_FANCY_HEAD(
36//usage: "\n -n -N[kbm] Print all except N last lines"
37//usage: "\n -c [-]N[kbm] Print first N bytes"
38//usage: "\n -q Never print headers" 41//usage: "\n -q Never print headers"
39//usage: "\n -v Always print headers" 42//usage: "\n -v Always print headers"
40//usage: ) 43//usage: )
41//usage: "\n"
42//usage: "\nN may be suffixed by k (x1024), b (x512), or m (x1024^2)."
43//usage: 44//usage:
44//usage:#define head_example_usage 45//usage:#define head_example_usage
45//usage: "$ head -n 2 /etc/passwd\n" 46//usage: "$ head -n 2 /etc/passwd\n"
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 67f6c8c56..0330f62df 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -109,11 +109,11 @@
109//usage:#define ls_full_usage "\n\n" 109//usage:#define ls_full_usage "\n\n"
110//usage: "List directory contents\n" 110//usage: "List directory contents\n"
111//usage: "\n -1 One column output" 111//usage: "\n -1 One column output"
112//usage: "\n -a Include entries which start with ." 112//usage: "\n -a Include names starting with ."
113//usage: "\n -A Like -a, but exclude . and .." 113//usage: "\n -A Like -a, but exclude . and .."
114////usage: "\n -C List by columns" - don't show, this is a default anyway 114////usage: "\n -C List by columns" - don't show, this is a default anyway
115//usage: "\n -x List by lines" 115//usage: "\n -x List by lines"
116//usage: "\n -d List directory entries instead of contents" 116//usage: "\n -d List directory names, not contents"
117//usage: IF_FEATURE_LS_FOLLOWLINKS( 117//usage: IF_FEATURE_LS_FOLLOWLINKS(
118//usage: "\n -L Follow symlinks" 118//usage: "\n -L Follow symlinks"
119//usage: "\n -H Follow symlinks on command line" 119//usage: "\n -H Follow symlinks on command line"
@@ -122,10 +122,10 @@
122//usage: "\n -R Recurse" 122//usage: "\n -R Recurse"
123//usage: ) 123//usage: )
124//usage: IF_FEATURE_LS_FILETYPES( 124//usage: IF_FEATURE_LS_FILETYPES(
125//usage: "\n -p Append / to dir entries" 125//usage: "\n -p Append / to directory names"
126//usage: "\n -F Append indicator (one of */=@|) to entries" 126//usage: "\n -F Append indicator (one of */=@|) to names"
127//usage: ) 127//usage: )
128//usage: "\n -l Long listing format" 128//usage: "\n -l Long format"
129//usage: "\n -i List inode numbers" 129//usage: "\n -i List inode numbers"
130//usage: "\n -n List numeric UIDs and GIDs instead of names" 130//usage: "\n -n List numeric UIDs and GIDs instead of names"
131//usage: "\n -s List allocated blocks" 131//usage: "\n -s List allocated blocks"
@@ -134,7 +134,7 @@
134//usage: "\n -lu List atime" 134//usage: "\n -lu List atime"
135//usage: ) 135//usage: )
136//usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS( 136//usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS(
137//usage: "\n --full-time List full date and time" 137//usage: "\n --full-time List full date/time"
138//usage: )) 138//usage: ))
139//usage: IF_FEATURE_HUMAN_READABLE( 139//usage: IF_FEATURE_HUMAN_READABLE(
140//usage: "\n -h Human readable sizes (1K 243M 2G)" 140//usage: "\n -h Human readable sizes (1K 243M 2G)"
@@ -160,7 +160,7 @@
160//usage: "\n -w N Format N columns wide" 160//usage: "\n -w N Format N columns wide"
161//usage: ) 161//usage: )
162//usage: IF_FEATURE_LS_COLOR( 162//usage: IF_FEATURE_LS_COLOR(
163//usage: "\n --color[={always,never,auto}] Control coloring" 163//usage: "\n --color[={always,never,auto}]"
164//usage: ) 164//usage: )
165 165
166#include "libbb.h" 166#include "libbb.h"
@@ -187,7 +187,7 @@
187 187
188 188
189enum { 189enum {
190TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ 190TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */
191 191
192SPLIT_FILE = 0, 192SPLIT_FILE = 0,
193SPLIT_DIR = 1, 193SPLIT_DIR = 1,
@@ -298,7 +298,7 @@ struct dnode {
298// but there are invisible fields as well 298// but there are invisible fields as well
299// (such as nanosecond-resolution timespamps) 299// (such as nanosecond-resolution timespamps)
300// and padding, which we also don't want to store. 300// and padding, which we also don't want to store.
301// We also can pre-parse dev_t dn_rdev (in glibc, it's huge). 301// We also pre-parse dev_t dn_rdev (in glibc, it's huge).
302// On 32-bit uclibc: dnode size went from 112 to 84 bytes. 302// On 32-bit uclibc: dnode size went from 112 to 84 bytes.
303// 303//
304 /* Same names as in struct stat, but with dn_ instead of st_ pfx: */ 304 /* Same names as in struct stat, but with dn_ instead of st_ pfx: */
@@ -1182,11 +1182,15 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1182 1182
1183#if ENABLE_FEATURE_LS_COLOR 1183#if ENABLE_FEATURE_LS_COLOR
1184 /* set G_show_color = 1/0 */ 1184 /* set G_show_color = 1/0 */
1185 if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && isatty(STDOUT_FILENO)) { 1185 if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && !is_TERM_dumb()) {
1186 char *p = getenv("LS_COLORS"); 1186 char *p = getenv("LS_COLORS");
1187 /* LS_COLORS is unset, or (not empty && not "none") ? */ 1187 /* LS_COLORS is unset, or (not empty && not "none") ? */
1188 if (!p || (p[0] && strcmp(p, "none") != 0)) 1188 if (!p || (p[0] && strcmp(p, "none") != 0)) {
1189 G_show_color = 1; 1189 if (isatty(STDOUT_FILENO)) {
1190 /* check isatty() last because it's expensive (syscall) */
1191 G_show_color = 1;
1192 }
1193 }
1190 } 1194 }
1191 if (opt & OPT_color) { 1195 if (opt & OPT_color) {
1192 if (color_opt[0] == 'n') 1196 if (color_opt[0] == 'n')
@@ -1195,7 +1199,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1195 case 3: 1199 case 3:
1196 case 4: 1200 case 4:
1197 case 5: 1201 case 5:
1198 if (isatty(STDOUT_FILENO)) { 1202 if (!is_TERM_dumb() && isatty(STDOUT_FILENO)) {
1199 case 0: 1203 case 0:
1200 case 1: 1204 case 1:
1201 case 2: 1205 case 2:
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 08fde6cdd..6201eb023 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -48,19 +48,20 @@
48//usage:#define tail_trivial_usage 48//usage:#define tail_trivial_usage
49//usage: "[OPTIONS] [FILE]..." 49//usage: "[OPTIONS] [FILE]..."
50//usage:#define tail_full_usage "\n\n" 50//usage:#define tail_full_usage "\n\n"
51//usage: "Print last 10 lines of FILEs (or stdin) to stdout.\n" 51//usage: "Print last 10 lines of FILEs (or stdin) to.\n"
52//usage: "With more than one FILE, precede each with a filename header.\n" 52//usage: "With more than one FILE, precede each with a filename header.\n"
53//usage: "\n -f Print data as file grows" 53//usage: "\n -c [+]N[bkm] Print last N bytes"
54//usage: "\n -c [+]N[kbm] Print last N bytes" 54//usage: "\n -n N[bkm] Print last N lines"
55//usage: "\n -n N[kbm] Print last N lines" 55//usage: "\n -n +N[bkm] Start on Nth line and print the rest"
56//usage: "\n -n +N[kbm] Start on Nth line and print the rest" 56//usage: "\n (b:*512 k:*1024 m:*1024^2)"
57//usage: IF_FEATURE_FANCY_TAIL( 57//usage: IF_FEATURE_FANCY_TAIL(
58//usage: "\n -q Never print headers" 58//usage: "\n -q Never print headers"
59//usage: "\n -s SECONDS Wait SECONDS between reads with -f"
60//usage: "\n -v Always print headers" 59//usage: "\n -v Always print headers"
60//usage: )
61//usage: "\n -f Print data as file grows"
62//usage: IF_FEATURE_FANCY_TAIL(
61//usage: "\n -F Same as -f, but keep retrying" 63//usage: "\n -F Same as -f, but keep retrying"
62//usage: "\n" 64//usage: "\n -s SECONDS Wait SECONDS between reads with -f"
63//usage: "\nN may be suffixed by k (x1024), b (x512), or m (x1024^2)."
64//usage: ) 65//usage: )
65//usage: 66//usage:
66//usage:#define tail_example_usage 67//usage:#define tail_example_usage
@@ -118,7 +119,7 @@ int tail_main(int argc, char **argv)
118 119
119 char *tailbuf; 120 char *tailbuf;
120 size_t tailbufsize; 121 size_t tailbufsize;
121 unsigned header_threshhold = 1; 122 unsigned header_threshold = 1;
122 unsigned nfiles; 123 unsigned nfiles;
123 int i, opt; 124 int i, opt;
124 125
@@ -151,10 +152,10 @@ int tail_main(int argc, char **argv)
151 if (opt & 0x2) count = eat_num(str_c); // -c 152 if (opt & 0x2) count = eat_num(str_c); // -c
152 if (opt & 0x4) count = eat_num(str_n); // -n 153 if (opt & 0x4) count = eat_num(str_n); // -n
153#if ENABLE_FEATURE_FANCY_TAIL 154#if ENABLE_FEATURE_FANCY_TAIL
154 /* q: make it impossible for nfiles to be > header_threshhold */ 155 /* q: make it impossible for nfiles to be > header_threshold */
155 if (opt & 0x8) header_threshhold = UINT_MAX; // -q 156 if (opt & 0x8) header_threshold = UINT_MAX; // -q
156 //if (opt & 0x10) // -s 157 //if (opt & 0x10) // -s
157 if (opt & 0x20) header_threshhold = 0; // -v 158 if (opt & 0x20) header_threshold = 0; // -v
158# define FOLLOW_RETRY (opt & 0x40) 159# define FOLLOW_RETRY (opt & 0x40)
159#else 160#else
160# define FOLLOW_RETRY 0 161# define FOLLOW_RETRY 0
@@ -215,7 +216,7 @@ int tail_main(int argc, char **argv)
215 if (ENABLE_FEATURE_FANCY_TAIL && fd < 0) 216 if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
216 continue; /* may happen with -F */ 217 continue; /* may happen with -F */
217 218
218 if (nfiles > header_threshhold) { 219 if (nfiles > header_threshold) {
219 tail_xprint_header(fmt, argv[i]); 220 tail_xprint_header(fmt, argv[i]);
220 fmt = header_fmt_str; 221 fmt = header_fmt_str;
221 } 222 }
@@ -345,9 +346,11 @@ int tail_main(int argc, char **argv)
345 int nread; 346 int nread;
346 const char *filename = argv[i]; 347 const char *filename = argv[i];
347 int fd = fds[i]; 348 int fd = fds[i];
349 int new_fd = -1;
350 struct stat sbuf;
348 351
349 if (FOLLOW_RETRY) { 352 if (FOLLOW_RETRY) {
350 struct stat sbuf, fsbuf; 353 struct stat fsbuf;
351 354
352 if (fd < 0 355 if (fd < 0
353 || fstat(fd, &fsbuf) < 0 356 || fstat(fd, &fsbuf) < 0
@@ -355,39 +358,51 @@ int tail_main(int argc, char **argv)
355 || fsbuf.st_dev != sbuf.st_dev 358 || fsbuf.st_dev != sbuf.st_dev
356 || fsbuf.st_ino != sbuf.st_ino 359 || fsbuf.st_ino != sbuf.st_ino
357 ) { 360 ) {
358 int new_fd; 361 /* Looks like file has been created/renamed/deleted */
359
360 if (fd >= 0)
361 close(fd);
362 new_fd = open(filename, O_RDONLY); 362 new_fd = open(filename, O_RDONLY);
363 if (new_fd >= 0) { 363 if (new_fd >= 0) {
364 bb_error_msg("%s has %s; following end of new file", 364 bb_error_msg("%s has %s; following end of new file",
365 filename, (fd < 0) ? "appeared" : "been replaced" 365 filename, (fd < 0) ? "appeared" : "been replaced"
366 ); 366 );
367 if (fd < 0) {
368 /* No previously open fd for this file,
369 * start using new_fd immediately. */
370 fds[i] = fd = new_fd;
371 new_fd = -1;
372 }
367 } else if (fd >= 0) { 373 } else if (fd >= 0) {
368 bb_perror_msg("%s has become inaccessible", filename); 374 bb_perror_msg("%s has been renamed or deleted", filename);
369 } 375 }
370 fds[i] = fd = new_fd;
371 } 376 }
372 } 377 }
373 if (ENABLE_FEATURE_FANCY_TAIL && fd < 0) 378 if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
374 continue; 379 continue;
375 if (nfiles > header_threshhold) { 380 if (nfiles > header_threshold) {
376 fmt = header_fmt_str; 381 fmt = header_fmt_str;
377 } 382 }
378 for (;;) { 383 for (;;) {
379 /* tail -f keeps following files even if they are truncated */ 384 /* tail -f keeps following files even if they are truncated */
380 struct stat sbuf;
381 /* /proc files report zero st_size, don't lseek them */ 385 /* /proc files report zero st_size, don't lseek them */
382 if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { 386 if (fstat(fd, &sbuf) == 0
387 /* && S_ISREG(sbuf.st_mode) TODO? */
388 && sbuf.st_size > 0
389 ) {
383 off_t current = lseek(fd, 0, SEEK_CUR); 390 off_t current = lseek(fd, 0, SEEK_CUR);
384 if (sbuf.st_size < current) 391 if (sbuf.st_size < current) {
392 //bb_perror_msg("%s: file truncated", filename); - says coreutils 8.32
385 xlseek(fd, 0, SEEK_SET); 393 xlseek(fd, 0, SEEK_SET);
394 }
386 } 395 }
387 396
388 nread = tail_read(fd, tailbuf, BUFSIZ); 397 nread = tail_read(fd, tailbuf, BUFSIZ);
389 if (nread <= 0) 398 if (nread <= 0) {
390 break; 399 if (new_fd < 0)
400 break;
401 /* Switch to "tail -F"ing the new file */
402 xmove_fd(new_fd, fd);
403 new_fd = -1;
404 continue;
405 }
391 if (fmt && (fd != prev_fd)) { 406 if (fmt && (fd != prev_fd)) {
392 tail_xprint_header(fmt, filename); 407 tail_xprint_header(fmt, filename);
393 fmt = NULL; 408 fmt = NULL;