diff options
author | Ron Yorston <rmy@pobox.com> | 2021-06-07 11:34:06 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-06-07 11:34:06 +0100 |
commit | abe872e2a0342357a5608342cb2892e94027b3e7 (patch) | |
tree | 297cdccf332fbb5e4eb31b1eac643180059f9b5f /coreutils | |
parent | 1f33f42d7bcb019b268d938df643a7a785dc19ab (diff) | |
parent | 4d983dcddeee94892d3072e84c7c9a01d4696055 (diff) | |
download | busybox-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.c | 13 | ||||
-rw-r--r-- | coreutils/ls.c | 30 | ||||
-rw-r--r-- | coreutils/tail.c | 67 |
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 | ||
189 | enum { | 189 | enum { |
190 | TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ | 190 | TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ |
191 | 191 | ||
192 | SPLIT_FILE = 0, | 192 | SPLIT_FILE = 0, |
193 | SPLIT_DIR = 1, | 193 | SPLIT_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; |