aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-08-30 08:37:51 +0100
committerRon Yorston <rmy@pobox.com>2021-08-30 08:37:51 +0100
commitbdb10f66af52bbd4f9d9340f2cf8ca73adbaee91 (patch)
tree306810231da90fb758cacb38ee9f8a7c4adf0d7c
parent6a42f73dcac55a6b5dde810ad60cee7c120a2db7 (diff)
parenta51d953b95a7cc6b40a6b3a5bfd95f3154acf5e2 (diff)
downloadbusybox-w32-bdb10f66af52bbd4f9d9340f2cf8ca73adbaee91.tar.gz
busybox-w32-bdb10f66af52bbd4f9d9340f2cf8ca73adbaee91.tar.bz2
busybox-w32-bdb10f66af52bbd4f9d9340f2cf8ca73adbaee91.zip
Merge branch 'busybox' into merge
-rw-r--r--archival/chksum_and_xwrite_tar_header.c2
-rw-r--r--archival/cpio.c2
-rw-r--r--archival/libarchive/bz/bzlib.c7
-rw-r--r--archival/libarchive/bz/bzlib_private.h11
-rw-r--r--coreutils/shuf.c76
-rw-r--r--editors/vi.c132
-rw-r--r--findutils/grep.c2
-rw-r--r--findutils/xargs.c2
-rw-r--r--util-linux/mount.c30
9 files changed, 165 insertions, 99 deletions
diff --git a/archival/chksum_and_xwrite_tar_header.c b/archival/chksum_and_xwrite_tar_header.c
index 25934f898..f2d46b9ef 100644
--- a/archival/chksum_and_xwrite_tar_header.c
+++ b/archival/chksum_and_xwrite_tar_header.c
@@ -15,7 +15,7 @@ void FAST_FUNC chksum_and_xwrite_tar_header(int fd, struct tar_header_t *hp)
15 * (Sun and HP-UX gets it wrong... more details in 15 * (Sun and HP-UX gets it wrong... more details in
16 * GNU tar source) */ 16 * GNU tar source) */
17 const unsigned char *cp; 17 const unsigned char *cp;
18 int chksum, size; 18 unsigned int chksum, size;
19 19
20 strcpy(hp->magic, "ustar "); 20 strcpy(hp->magic, "ustar ");
21 21
diff --git a/archival/cpio.c b/archival/cpio.c
index d84f6937d..f525419b8 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -74,7 +74,7 @@
74//usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file" 74//usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file"
75//usage: "\n -R USER[:GRP] Set owner of created files" 75//usage: "\n -R USER[:GRP] Set owner of created files"
76//usage: "\n -L Dereference symlinks" 76//usage: "\n -L Dereference symlinks"
77//usage: "\n -0 Input is separated by NULs" 77//usage: "\n -0 NUL terminated input"
78 78
79/* GNU cpio 2.9 --help (abridged): 79/* GNU cpio 2.9 --help (abridged):
80 80
diff --git a/archival/libarchive/bz/bzlib.c b/archival/libarchive/bz/bzlib.c
index 9af2f026d..ef19ae165 100644
--- a/archival/libarchive/bz/bzlib.c
+++ b/archival/libarchive/bz/bzlib.c
@@ -99,9 +99,8 @@ void BZ2_bzCompressInit(bz_stream *strm, int blockSize100k)
99 s->ptr = (uint32_t*)s->arr1; 99 s->ptr = (uint32_t*)s->arr1;
100 s->arr2 = xmalloc((n + BZ_N_OVERSHOOT) * sizeof(uint32_t)); 100 s->arr2 = xmalloc((n + BZ_N_OVERSHOOT) * sizeof(uint32_t));
101 s->block = (uint8_t*)s->arr2; 101 s->block = (uint8_t*)s->arr2;
102 s->ftab = xmalloc(65537 * sizeof(uint32_t));
103 102
104 s->crc32table = crc32_filltable(NULL, 1); 103 crc32_filltable(s->crc32table, 1);
105 104
106 s->state = BZ_S_INPUT; 105 s->state = BZ_S_INPUT;
107 s->mode = BZ_M_RUNNING; 106 s->mode = BZ_M_RUNNING;
@@ -369,8 +368,8 @@ void BZ2_bzCompressEnd(bz_stream *strm)
369 s = strm->state; 368 s = strm->state;
370 free(s->arr1); 369 free(s->arr1);
371 free(s->arr2); 370 free(s->arr2);
372 free(s->ftab); 371 //free(s->ftab); // made it array member of s
373 free(s->crc32table); 372 //free(s->crc32table); // ditto
374 free(s); 373 free(s);
375} 374}
376 375
diff --git a/archival/libarchive/bz/bzlib_private.h b/archival/libarchive/bz/bzlib_private.h
index ea0f29b7c..650444a5c 100644
--- a/archival/libarchive/bz/bzlib_private.h
+++ b/archival/libarchive/bz/bzlib_private.h
@@ -134,7 +134,7 @@ typedef struct EState {
134 /* for doing the block sorting */ 134 /* for doing the block sorting */
135 uint32_t *arr1; 135 uint32_t *arr1;
136 uint32_t *arr2; 136 uint32_t *arr2;
137 uint32_t *ftab; 137 //uint32_t *ftab; //moved into this struct, see below
138 138
139 uint16_t *quadrant; 139 uint16_t *quadrant;
140 int32_t budget; 140 int32_t budget;
@@ -160,9 +160,6 @@ typedef struct EState {
160 uint32_t bsBuff; 160 uint32_t bsBuff;
161 int32_t bsLive; 161 int32_t bsLive;
162 162
163 /* guess what */
164 uint32_t *crc32table;
165
166 /* block and combined CRCs */ 163 /* block and combined CRCs */
167 uint32_t blockCRC; 164 uint32_t blockCRC;
168 uint32_t combinedCRC; 165 uint32_t combinedCRC;
@@ -185,6 +182,12 @@ typedef struct EState {
185 182
186 uint8_t len[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; 183 uint8_t len[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
187 184
185 /* guess what */
186 uint32_t crc32table[256];
187
188 /* for doing the block sorting */
189 uint32_t ftab[65537];
190
188 /* stack-saving measures: these can be local, but they are too big */ 191 /* stack-saving measures: these can be local, but they are too big */
189 int32_t sendMTFValues__code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; 192 int32_t sendMTFValues__code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
190 int32_t sendMTFValues__rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; 193 int32_t sendMTFValues__rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
diff --git a/coreutils/shuf.c b/coreutils/shuf.c
index fdbd3e9b2..77f8a8ff9 100644
--- a/coreutils/shuf.c
+++ b/coreutils/shuf.c
@@ -17,14 +17,14 @@
17//kbuild:lib-$(CONFIG_SHUF) += shuf.o 17//kbuild:lib-$(CONFIG_SHUF) += shuf.o
18 18
19//usage:#define shuf_trivial_usage 19//usage:#define shuf_trivial_usage
20//usage: "[-e|-i L-H] [-n NUM] [-o FILE] [-z] [FILE|ARG...]" 20//usage: "[-n NUM] [-o FILE] [-z] [FILE | -e [ARG...] | -i L-H]"
21//usage:#define shuf_full_usage "\n\n" 21//usage:#define shuf_full_usage "\n\n"
22//usage: "Randomly permute lines\n" 22//usage: "Randomly permute lines\n"
23//usage: "\n -e Treat ARGs as lines"
24//usage: "\n -i L-H Treat numbers L-H as lines"
25//usage: "\n -n NUM Output at most NUM lines" 23//usage: "\n -n NUM Output at most NUM lines"
26//usage: "\n -o FILE Write to FILE, not standard output" 24//usage: "\n -o FILE Write to FILE, not standard output"
27//usage: "\n -z End lines with zero byte, not newline" 25//usage: "\n -z NUL terminated output"
26//usage: "\n -e Treat ARGs as lines"
27//usage: "\n -i L-H Treat numbers L-H as lines"
28 28
29#include "libbb.h" 29#include "libbb.h"
30 30
@@ -39,8 +39,10 @@
39 39
40/* 40/*
41 * Use the Fisher-Yates shuffle algorithm on an array of lines. 41 * Use the Fisher-Yates shuffle algorithm on an array of lines.
42 * If the required number of output lines is less than the total
43 * we can stop shuffling early.
42 */ 44 */
43static void shuffle_lines(char **lines, unsigned numlines) 45static void shuffle_lines(char **lines, unsigned numlines, unsigned outlines)
44{ 46{
45 unsigned i; 47 unsigned i;
46 unsigned r; 48 unsigned r;
@@ -48,7 +50,7 @@ static void shuffle_lines(char **lines, unsigned numlines)
48 50
49 srand(monotonic_us()); 51 srand(monotonic_us());
50 52
51 for (i = numlines-1; i > 0; i--) { 53 for (i = numlines - 1; outlines > 0; i--, outlines--) {
52 r = rand(); 54 r = rand();
53 /* RAND_MAX can be as small as 32767 */ 55 /* RAND_MAX can be as small as 32767 */
54 if (i > RAND_MAX) 56 if (i > RAND_MAX)
@@ -67,7 +69,7 @@ int shuf_main(int argc, char **argv)
67 char *opt_i_str, *opt_n_str, *opt_o_str; 69 char *opt_i_str, *opt_n_str, *opt_o_str;
68 unsigned i; 70 unsigned i;
69 char **lines; 71 char **lines;
70 unsigned numlines; 72 unsigned numlines, outlines;
71 char eol; 73 char eol;
72 74
73 opts = getopt32(argv, "^" 75 opts = getopt32(argv, "^"
@@ -88,15 +90,27 @@ int shuf_main(int argc, char **argv)
88 if (opts & OPT_i) { 90 if (opts & OPT_i) {
89 /* create a range of numbers */ 91 /* create a range of numbers */
90 char *dash; 92 char *dash;
91 unsigned lo, hi; 93 uintptr_t lo, hi;
94
95 if (argv[0])
96 bb_show_usage();
92 97
93 dash = strchr(opt_i_str, '-'); 98 dash = strchr(opt_i_str, '-');
94 if (!dash) { 99 if (!dash) {
95 bb_error_msg_and_die("bad range '%s'", opt_i_str); 100 bb_error_msg_and_die("bad range '%s'", opt_i_str);
96 } 101 }
97 *dash = '\0'; 102 *dash = '\0';
98 lo = xatou(opt_i_str); 103 if (sizeof(lo) == sizeof(int)) {
99 hi = xatou(dash + 1); 104 lo = xatou(opt_i_str);
105 hi = xatou(dash + 1);
106 } else
107 if (sizeof(lo) == sizeof(long)) {
108 lo = xatoul(opt_i_str);
109 hi = xatoul(dash + 1);
110 } else {
111 lo = xatoull(opt_i_str);
112 hi = xatoull(dash + 1);
113 }
100 *dash = '-'; 114 *dash = '-';
101 if (hi < lo) { 115 if (hi < lo) {
102 bb_error_msg_and_die("bad range '%s'", opt_i_str); 116 bb_error_msg_and_die("bad range '%s'", opt_i_str);
@@ -105,17 +119,21 @@ int shuf_main(int argc, char **argv)
105 numlines = (hi+1) - lo; 119 numlines = (hi+1) - lo;
106 lines = xmalloc(numlines * sizeof(lines[0])); 120 lines = xmalloc(numlines * sizeof(lines[0]));
107 for (i = 0; i < numlines; i++) { 121 for (i = 0; i < numlines; i++) {
108 lines[i] = (char*)(uintptr_t)lo; 122 lines[i] = (char*)lo;
109 lo++; 123 lo++;
110 } 124 }
111 } else { 125 } else {
112 /* default - read lines from stdin or the input file */ 126 /* default - read lines from stdin or the input file */
113 FILE *fp; 127 FILE *fp;
128 const char *fname = "-";
114 129
115 if (argc > 1) 130 if (argv[0]) {
116 bb_show_usage(); 131 if (argv[1])
132 bb_show_usage();
133 fname = argv[0];
134 }
117 135
118 fp = xfopen_stdin(argv[0] ? argv[0] : "-"); 136 fp = xfopen_stdin(fname);
119 lines = NULL; 137 lines = NULL;
120 numlines = 0; 138 numlines = 0;
121 for (;;) { 139 for (;;) {
@@ -128,27 +146,31 @@ int shuf_main(int argc, char **argv)
128 fclose_if_not_stdin(fp); 146 fclose_if_not_stdin(fp);
129 } 147 }
130 148
131 if (numlines != 0) 149 outlines = numlines;
132 shuffle_lines(lines, numlines); 150 if (opts & OPT_n) {
151 outlines = xatou(opt_n_str);
152 if (outlines > numlines)
153 outlines = numlines;
154 }
155
156 shuffle_lines(lines, numlines, outlines);
133 157
134 if (opts & OPT_o) 158 if (opts & OPT_o)
135 xmove_fd(xopen(opt_o_str, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO); 159 xmove_fd(xopen(opt_o_str, O_WRONLY|O_CREAT|O_TRUNC), STDOUT_FILENO);
136 160
137 if (opts & OPT_n) {
138 unsigned maxlines;
139 maxlines = xatou(opt_n_str);
140 if (numlines > maxlines)
141 numlines = maxlines;
142 }
143
144 eol = '\n'; 161 eol = '\n';
145 if (opts & OPT_z) 162 if (opts & OPT_z)
146 eol = '\0'; 163 eol = '\0';
147 164
148 for (i = 0; i < numlines; i++) { 165 for (i = numlines - outlines; i < numlines; i++) {
149 if (opts & OPT_i) 166 if (opts & OPT_i) {
150 printf("%u%c", (unsigned)(uintptr_t)lines[i], eol); 167 if (sizeof(lines[0]) == sizeof(int))
151 else 168 printf("%u%c", (unsigned)(uintptr_t)lines[i], eol);
169 else if (sizeof(lines[0]) == sizeof(long))
170 printf("%lu%c", (unsigned long)(uintptr_t)lines[i], eol);
171 else
172 printf("%llu%c", (unsigned long long)(uintptr_t)lines[i], eol);
173 } else
152 printf("%s%c", lines[i], eol); 174 printf("%s%c", lines[i], eol);
153 } 175 }
154 176
diff --git a/editors/vi.c b/editors/vi.c
index a0a046272..2c1048a4c 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2524,26 +2524,38 @@ static char *char_search(char *p, const char *pat, int dir_and_range)
2524 2524
2525//----- The Colon commands ------------------------------------- 2525//----- The Colon commands -------------------------------------
2526#if ENABLE_FEATURE_VI_COLON 2526#if ENABLE_FEATURE_VI_COLON
2527static char *get_one_address(char *p, int *result) // get colon addr, if present 2527// Evaluate colon address expression. Returns a pointer to the
2528// next character or NULL on error. If 'result' contains a valid
2529// address 'valid' is TRUE.
2530static char *get_one_address(char *p, int *result, int *valid)
2528{ 2531{
2529 int st, num, sign, addr, new_addr; 2532 int num, sign, addr, got_addr;
2530# if ENABLE_FEATURE_VI_YANKMARK || ENABLE_FEATURE_VI_SEARCH 2533# if ENABLE_FEATURE_VI_YANKMARK || ENABLE_FEATURE_VI_SEARCH
2531 char *q, c; 2534 char *q, c;
2532# endif 2535# endif
2533 IF_FEATURE_VI_SEARCH(int dir;) 2536 IF_FEATURE_VI_SEARCH(int dir;)
2534 2537
2535 addr = -1; // assume no addr 2538 got_addr = FALSE;
2539 addr = count_lines(text, dot); // default to current line
2536 sign = 0; 2540 sign = 0;
2537 for (;;) { 2541 for (;;) {
2538 new_addr = -1;
2539 if (isblank(*p)) { 2542 if (isblank(*p)) {
2543 if (got_addr) {
2544 addr += sign;
2545 sign = 0;
2546 }
2547 p++;
2548 } else if (!got_addr && *p == '.') { // the current line
2540 p++; 2549 p++;
2541 } else if (*p == '.') { // the current line 2550 //addr = count_lines(text, dot);
2551 got_addr = TRUE;
2552 } else if (!got_addr && *p == '$') { // the last line in file
2542 p++; 2553 p++;
2543 new_addr = count_lines(text, dot); 2554 addr = count_lines(text, end - 1);
2555 got_addr = TRUE;
2544 } 2556 }
2545# if ENABLE_FEATURE_VI_YANKMARK 2557# if ENABLE_FEATURE_VI_YANKMARK
2546 else if (*p == '\'') { // is this a mark addr 2558 else if (!got_addr && *p == '\'') { // is this a mark addr
2547 p++; 2559 p++;
2548 c = tolower(*p); 2560 c = tolower(*p);
2549 p++; 2561 p++;
@@ -2553,13 +2565,16 @@ static char *get_one_address(char *p, int *result) // get colon addr, if present
2553 c = c - 'a'; 2565 c = c - 'a';
2554 q = mark[(unsigned char) c]; 2566 q = mark[(unsigned char) c];
2555 } 2567 }
2556 if (q == NULL) // is mark valid 2568 if (q == NULL) { // is mark valid
2569 status_line_bold("Mark not set");
2557 return NULL; 2570 return NULL;
2558 new_addr = count_lines(text, q); 2571 }
2572 addr = count_lines(text, q);
2573 got_addr = TRUE;
2559 } 2574 }
2560# endif 2575# endif
2561# if ENABLE_FEATURE_VI_SEARCH 2576# if ENABLE_FEATURE_VI_SEARCH
2562 else if (*p == '/' || *p == '?') { // a search pattern 2577 else if (!got_addr && (*p == '/' || *p == '?')) { // a search pattern
2563 c = *p; 2578 c = *p;
2564 q = strchrnul(p + 1, c); 2579 q = strchrnul(p + 1, c);
2565 if (p + 1 != q) { 2580 if (p + 1 != q) {
@@ -2582,40 +2597,41 @@ static char *get_one_address(char *p, int *result) // get colon addr, if present
2582 // no match, continue from other end of file 2597 // no match, continue from other end of file
2583 q = char_search(dir > 0 ? text : end - 1, 2598 q = char_search(dir > 0 ? text : end - 1,
2584 last_search_pattern + 1, dir); 2599 last_search_pattern + 1, dir);
2585 if (q == NULL) 2600 if (q == NULL) {
2601 status_line_bold("Pattern not found");
2586 return NULL; 2602 return NULL;
2603 }
2587 } 2604 }
2588 new_addr = count_lines(text, q); 2605 addr = count_lines(text, q);
2606 got_addr = TRUE;
2589 } 2607 }
2590# endif 2608# endif
2591 else if (*p == '$') { // the last line in file 2609 else if (isdigit(*p)) {
2592 p++; 2610 num = 0;
2593 new_addr = count_lines(text, end - 1); 2611 while (isdigit(*p))
2594 } else if (isdigit(*p)) { 2612 num = num * 10 + *p++ -'0';
2595 sscanf(p, "%d%n", &num, &st); 2613 if (!got_addr) { // specific line number
2596 p += st;
2597 if (addr < 0) { // specific line number
2598 addr = num; 2614 addr = num;
2615 got_addr = TRUE;
2599 } else { // offset from current addr 2616 } else { // offset from current addr
2600 addr += sign >= 0 ? num : -num; 2617 addr += sign >= 0 ? num : -num;
2601 } 2618 }
2602 sign = 0; 2619 sign = 0;
2603 } else if (*p == '-' || *p == '+') { 2620 } else if (*p == '-' || *p == '+') {
2604 sign = *p++ == '-' ? -1 : 1; 2621 if (!got_addr) { // default address is dot
2605 if (addr < 0) { // default address is dot 2622 //addr = count_lines(text, dot);
2606 addr = count_lines(text, dot); 2623 got_addr = TRUE;
2624 } else {
2625 addr += sign;
2607 } 2626 }
2627 sign = *p++ == '-' ? -1 : 1;
2608 } else { 2628 } else {
2609 addr += sign; // consume unused trailing sign 2629 addr += sign; // consume unused trailing sign
2610 break; 2630 break;
2611 } 2631 }
2612 if (new_addr >= 0) {
2613 if (addr >= 0) // only one new address per expression
2614 return NULL;
2615 addr = new_addr;
2616 }
2617 } 2632 }
2618 *result = addr; 2633 *result = addr;
2634 *valid = got_addr;
2619 return p; 2635 return p;
2620} 2636}
2621 2637
@@ -2624,34 +2640,40 @@ static char *get_one_address(char *p, int *result) // get colon addr, if present
2624 2640
2625// Read line addresses for a colon command. The user can enter as 2641// Read line addresses for a colon command. The user can enter as
2626// many as they like but only the last two will be used. 2642// many as they like but only the last two will be used.
2627static char *get_address(char *p, int *b, int *e) 2643static char *get_address(char *p, int *b, int *e, unsigned int *got)
2628{ 2644{
2629 int state = GET_ADDRESS; 2645 int state = GET_ADDRESS;
2646 int valid;
2647 int addr;
2630 char *save_dot = dot; 2648 char *save_dot = dot;
2631 2649
2632 //----- get the address' i.e., 1,3 'a,'b ----- 2650 //----- get the address' i.e., 1,3 'a,'b -----
2633 for (;;) { 2651 for (;;) {
2634 if (isblank(*p)) { 2652 if (isblank(*p)) {
2635 p++; 2653 p++;
2636 } else if (*p == '%' && state == GET_ADDRESS) { // alias for 1,$ 2654 } else if (state == GET_ADDRESS && *p == '%') { // alias for 1,$
2637 p++; 2655 p++;
2638 *b = 1; 2656 *b = 1;
2639 *e = count_lines(text, end-1); 2657 *e = count_lines(text, end-1);
2658 *got = 3;
2659 state = GET_SEPARATOR;
2660 } else if (state == GET_ADDRESS) {
2661 valid = FALSE;
2662 p = get_one_address(p, &addr, &valid);
2663 // Quit on error or if the address is invalid and isn't of
2664 // the form ',$' or '1,' (in which case it defaults to dot).
2665 if (p == NULL || !(valid || *p == ',' || *p == ';' || *got & 1))
2666 break;
2667 *b = *e;
2668 *e = addr;
2669 *got = (*got << 1) | 1;
2640 state = GET_SEPARATOR; 2670 state = GET_SEPARATOR;
2641 } else if (state == GET_SEPARATOR && (*p == ',' || *p == ';')) { 2671 } else if (state == GET_SEPARATOR && (*p == ',' || *p == ';')) {
2642 if (*p == ';') 2672 if (*p == ';')
2643 dot = find_line(*e); 2673 dot = find_line(*e);
2644 p++; 2674 p++;
2645 *b = *e;
2646 state = GET_ADDRESS; 2675 state = GET_ADDRESS;
2647 } else if (state == GET_ADDRESS) {
2648 p = get_one_address(p, e);
2649 if (p == NULL)
2650 break;
2651 state = GET_SEPARATOR;
2652 } else { 2676 } else {
2653 if (state == GET_SEPARATOR && *b >= 0 && *e < 0)
2654 *e = count_lines(text, dot);
2655 break; 2677 break;
2656 } 2678 }
2657 } 2679 }
@@ -2865,9 +2887,14 @@ static void colon(char *buf)
2865 not_implemented(p); 2887 not_implemented(p);
2866#else 2888#else
2867 2889
2890// check how many addresses we got
2891# define GOT_ADDRESS (got & 1)
2892# define GOT_RANGE ((got & 3) == 3)
2893
2868 char c, *buf1, *q, *r; 2894 char c, *buf1, *q, *r;
2869 char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args, *exp = NULL; 2895 char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args, *exp = NULL;
2870 int i, l, li, b, e; 2896 int i, l, li, b, e;
2897 unsigned int got;
2871 int useforce; 2898 int useforce;
2872 2899
2873 // :3154 // if (-e line 3154) goto it else stay put 2900 // :3154 // if (-e line 3154) goto it else stay put
@@ -2894,14 +2921,13 @@ static void colon(char *buf)
2894 2921
2895 li = i = 0; 2922 li = i = 0;
2896 b = e = -1; 2923 b = e = -1;
2924 got = 0;
2897 li = count_lines(text, end - 1); 2925 li = count_lines(text, end - 1);
2898 fn = current_filename; 2926 fn = current_filename;
2899 2927
2900 // look for optional address(es) :. :1 :1,9 :'q,'a :% 2928 // look for optional address(es) :. :1 :1,9 :'q,'a :%
2901 buf1 = buf; 2929 buf = get_address(buf, &b, &e, &got);
2902 buf = get_address(buf, &b, &e);
2903 if (buf == NULL) { 2930 if (buf == NULL) {
2904 status_line_bold("Bad address: %s", buf1);
2905 goto ret; 2931 goto ret;
2906 } 2932 }
2907 2933
@@ -2924,13 +2950,17 @@ static void colon(char *buf)
2924 } 2950 }
2925 // assume the command will want a range, certain commands 2951 // assume the command will want a range, certain commands
2926 // (read, substitute) need to adjust these assumptions 2952 // (read, substitute) need to adjust these assumptions
2927 if (e < 0) { 2953 if (!GOT_ADDRESS) {
2928 q = text; // no addr, use 1,$ for the range 2954 q = text; // no addr, use 1,$ for the range
2929 r = end - 1; 2955 r = end - 1;
2930 } else { 2956 } else {
2931 // at least one addr was given, get its details 2957 // at least one addr was given, get its details
2958 if (e < 0 || e > li) {
2959 status_line_bold("Invalid range");
2960 goto ret;
2961 }
2932 q = r = find_line(e); 2962 q = r = find_line(e);
2933 if (b < 0) { 2963 if (!GOT_RANGE) {
2934 // if there is only one addr, then it's the line 2964 // if there is only one addr, then it's the line
2935 // number of the single line the user wants. 2965 // number of the single line the user wants.
2936 // Reset the end pointer to the end of that line. 2966 // Reset the end pointer to the end of that line.
@@ -2939,6 +2969,10 @@ static void colon(char *buf)
2939 } else { 2969 } else {
2940 // we were given two addrs. change the 2970 // we were given two addrs. change the
2941 // start pointer to the addr given by user. 2971 // start pointer to the addr given by user.
2972 if (b < 0 || b > li || b > e) {
2973 status_line_bold("Invalid range");
2974 goto ret;
2975 }
2942 q = find_line(b); // what line is #b 2976 q = find_line(b); // what line is #b
2943 r = end_line(r); 2977 r = end_line(r);
2944 li = e - b + 1; 2978 li = e - b + 1;
@@ -2969,12 +3003,12 @@ static void colon(char *buf)
2969 } 3003 }
2970# endif 3004# endif
2971 else if (cmd[0] == '=' && !cmd[1]) { // where is the address 3005 else if (cmd[0] == '=' && !cmd[1]) { // where is the address
2972 if (e < 0) { // no addr given- use defaults 3006 if (!GOT_ADDRESS) { // no addr given- use defaults
2973 e = count_lines(text, dot); 3007 e = count_lines(text, dot);
2974 } 3008 }
2975 status_line("%d", e); 3009 status_line("%d", e);
2976 } else if (strncmp(cmd, "delete", i) == 0) { // delete lines 3010 } else if (strncmp(cmd, "delete", i) == 0) { // delete lines
2977 if (e < 0) { // no addr given- use defaults 3011 if (!GOT_ADDRESS) { // no addr given- use defaults
2978 q = begin_line(dot); // assume .,. for the range 3012 q = begin_line(dot); // assume .,. for the range
2979 r = end_line(dot); 3013 r = end_line(dot);
2980 } 3014 }
@@ -3046,7 +3080,7 @@ static void colon(char *buf)
3046 rawmode(); 3080 rawmode();
3047 Hit_Return(); 3081 Hit_Return();
3048 } else if (strncmp(cmd, "list", i) == 0) { // literal print line 3082 } else if (strncmp(cmd, "list", i) == 0) { // literal print line
3049 if (e < 0) { // no addr given- use defaults 3083 if (!GOT_ADDRESS) { // no addr given- use defaults
3050 q = begin_line(dot); // assume .,. for the range 3084 q = begin_line(dot); // assume .,. for the range
3051 r = end_line(dot); 3085 r = end_line(dot);
3052 } 3086 }
@@ -3129,7 +3163,7 @@ static void colon(char *buf)
3129 if (e == 0) { // user said ":0r foo" 3163 if (e == 0) { // user said ":0r foo"
3130 q = text; 3164 q = text;
3131 } else { // read after given line or current line if none given 3165 } else { // read after given line or current line if none given
3132 q = next_line(e > 0 ? find_line(e) : dot); 3166 q = next_line(GOT_ADDRESS ? find_line(e) : dot);
3133 // read after last line 3167 // read after last line
3134 if (q == end-1) 3168 if (q == end-1)
3135 ++q; 3169 ++q;
@@ -3250,11 +3284,11 @@ static void colon(char *buf)
3250 len_F = strlen(F); 3284 len_F = strlen(F);
3251 } 3285 }
3252 3286
3253 if (e < 0) { // no addr given 3287 if (!GOT_ADDRESS) { // no addr given
3254 q = begin_line(dot); // start with cur line 3288 q = begin_line(dot); // start with cur line
3255 r = end_line(dot); 3289 r = end_line(dot);
3256 b = e = count_lines(text, q); // cur line number 3290 b = e = count_lines(text, q); // cur line number
3257 } else if (b < 0) { // one addr given 3291 } else if (!GOT_RANGE) { // one addr given
3258 b = e; 3292 b = e;
3259 } 3293 }
3260 3294
@@ -3425,7 +3459,7 @@ static void colon(char *buf)
3425 } 3459 }
3426# if ENABLE_FEATURE_VI_YANKMARK 3460# if ENABLE_FEATURE_VI_YANKMARK
3427 } else if (strncmp(cmd, "yank", i) == 0) { // yank lines 3461 } else if (strncmp(cmd, "yank", i) == 0) { // yank lines
3428 if (b < 0) { // no addr given- use defaults 3462 if (!GOT_ADDRESS) { // no addr given- use defaults
3429 q = begin_line(dot); // assume .,. for the range 3463 q = begin_line(dot); // assume .,. for the range
3430 r = end_line(dot); 3464 r = end_line(dot);
3431 } 3465 }
diff --git a/findutils/grep.c b/findutils/grep.c
index be4362ed0..8600d72fa 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -83,7 +83,7 @@
83//usage: "\n -F PATTERN is a literal (not regexp)" 83//usage: "\n -F PATTERN is a literal (not regexp)"
84//usage: "\n -E PATTERN is an extended regexp" 84//usage: "\n -E PATTERN is an extended regexp"
85//usage: IF_EXTRA_COMPAT( 85//usage: IF_EXTRA_COMPAT(
86//usage: "\n -z Input is NUL terminated" 86//usage: "\n -z NUL terminated input"
87//usage: ) 87//usage: )
88//usage: "\n -m N Match up to N times per file" 88//usage: "\n -m N Match up to N times per file"
89//usage: IF_FEATURE_GREP_CONTEXT( 89//usage: IF_FEATURE_GREP_CONTEXT(
diff --git a/findutils/xargs.c b/findutils/xargs.c
index 1f8d95168..a0ba89c1e 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -623,7 +623,7 @@ static int xargs_ask_confirmation(void)
623//usage:#define xargs_full_usage "\n\n" 623//usage:#define xargs_full_usage "\n\n"
624//usage: "Run PROG on every item given by stdin\n" 624//usage: "Run PROG on every item given by stdin\n"
625//usage: IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( 625//usage: IF_FEATURE_XARGS_SUPPORT_ZERO_TERM(
626//usage: "\n -0 Input is separated by NULs" 626//usage: "\n -0 NUL terminated input"
627//usage: ) 627//usage: )
628//usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( 628//usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE(
629//usage: "\n -a FILE Read from FILE instead of stdin" 629//usage: "\n -a FILE Read from FILE instead of stdin"
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 831dab9e2..44afdbcff 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -562,9 +562,9 @@ static void append_mount_options(char **oldopts, const char *newopts)
562 // Do not insert options which are already there 562 // Do not insert options which are already there
563 while (newopts[0]) { 563 while (newopts[0]) {
564 char *p; 564 char *p;
565 int len = strlen(newopts); 565 int len;
566 p = strchr(newopts, ','); 566
567 if (p) len = p - newopts; 567 len = strchrnul(newopts, ',') - newopts;
568 p = *oldopts; 568 p = *oldopts;
569 while (1) { 569 while (1) {
570 if (!strncmp(p, newopts, len) 570 if (!strncmp(p, newopts, len)
@@ -579,7 +579,7 @@ static void append_mount_options(char **oldopts, const char *newopts)
579 *oldopts = p; 579 *oldopts = p;
580 skip: 580 skip:
581 newopts += len; 581 newopts += len;
582 while (newopts[0] == ',') newopts++; 582 while (*newopts == ',') newopts++;
583 } 583 }
584 } else { 584 } else {
585 if (ENABLE_FEATURE_CLEAN_UP) free(*oldopts); 585 if (ENABLE_FEATURE_CLEAN_UP) free(*oldopts);
@@ -713,10 +713,12 @@ static int mount_it_now(struct mntent *mp, unsigned long vfsflags, char *filtero
713 errno = 0; 713 errno = 0;
714 rc = verbose_mount(mp->mnt_fsname, mp->mnt_dir, mp->mnt_type, 714 rc = verbose_mount(mp->mnt_fsname, mp->mnt_dir, mp->mnt_type,
715 vfsflags, filteropts); 715 vfsflags, filteropts);
716 if (rc == 0)
717 goto mtab; // success
716 718
717 // If mount failed, try 719 // mount failed, try helper program
718 // helper program mount.<mnt_type> 720 // mount.<mnt_type>
719 if (HELPERS_ALLOWED && rc && mp->mnt_type) { 721 if (HELPERS_ALLOWED && mp->mnt_type) {
720 char *args[8]; 722 char *args[8];
721 int errno_save = errno; 723 int errno_save = errno;
722 args[0] = xasprintf("mount.%s", mp->mnt_type); 724 args[0] = xasprintf("mount.%s", mp->mnt_type);
@@ -734,13 +736,19 @@ static int mount_it_now(struct mntent *mp, unsigned long vfsflags, char *filtero
734 args[rc] = NULL; 736 args[rc] = NULL;
735 rc = spawn_and_wait(args); 737 rc = spawn_and_wait(args);
736 free(args[0]); 738 free(args[0]);
737 if (!rc) 739 if (rc == 0)
738 break; 740 goto mtab; // success
739 errno = errno_save; 741 errno = errno_save;
740 } 742 }
741 743
742 if (!rc || (vfsflags & MS_RDONLY) || (errno != EACCES && errno != EROFS)) 744 // Should we retry read-only mount?
743 break; 745 if (vfsflags & MS_RDONLY)
746 break; // no, already was tried
747 if (option_mask32 & OPT_w)
748 break; // no, "mount -w" never falls back to RO
749 if (errno != EACCES && errno != EROFS)
750 break; // no, error isn't hinting that RO may work
751
744 if (!(vfsflags & MS_SILENT)) 752 if (!(vfsflags & MS_SILENT))
745 bb_error_msg("%s is write-protected, mounting read-only", 753 bb_error_msg("%s is write-protected, mounting read-only",
746 mp->mnt_fsname); 754 mp->mnt_fsname);