aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2022-10-12 10:43:26 +0100
committerRon Yorston <rmy@pobox.com>2022-10-12 10:43:26 +0100
commit49c6f079acb4edae84b4496bd941cdbb5048ba01 (patch)
treeac54ecaad45050f7bfe274a11db29882aa32a9a8
parenta55cf07365ec2ff51749a77e09ae9edac79a99fe (diff)
parentc8c1fcdba163f264a503380bc63485aacd09214c (diff)
downloadbusybox-w32-49c6f079acb4edae84b4496bd941cdbb5048ba01.tar.gz
busybox-w32-49c6f079acb4edae84b4496bd941cdbb5048ba01.tar.bz2
busybox-w32-49c6f079acb4edae84b4496bd941cdbb5048ba01.zip
Merge branch 'busybox' into merge
-rw-r--r--AUTHORS3
-rw-r--r--archival/dpkg.c2
-rw-r--r--coreutils/cut.c2
-rw-r--r--coreutils/md5_sha1_sum.c13
-rw-r--r--coreutils/sleep.c1
-rw-r--r--coreutils/sort.c13
-rw-r--r--coreutils/test.c2
-rw-r--r--editors/awk.c3
-rw-r--r--editors/patch.c16
-rw-r--r--editors/patch_toybox.c36
-rw-r--r--editors/vi.c8
-rw-r--r--examples/shutdown-1.0/script/hardshutdown.c4
-rw-r--r--include/libbb.h1
-rw-r--r--libbb/appletlib.c8
-rw-r--r--libbb/duration.c6
-rw-r--r--libbb/hash_md5_sha256_x86-32_shaNI.S3
-rw-r--r--libbb/hash_md5_sha256_x86-64_shaNI.S3
-rw-r--r--libbb/hash_md5_sha_x86-32_shaNI.S3
-rw-r--r--libbb/hash_md5_sha_x86-64.S3
-rwxr-xr-xlibbb/hash_md5_sha_x86-64.S.sh3
-rw-r--r--libbb/hash_md5_sha_x86-64_shaNI.S3
-rw-r--r--libbb/lineedit.c6
-rw-r--r--miscutils/bc.c4
-rw-r--r--miscutils/devfsd.c6
-rw-r--r--miscutils/devmem.c68
-rw-r--r--miscutils/hdparm.c24
-rw-r--r--miscutils/tree.c131
-rw-r--r--modutils/modutils-24.c2
-rw-r--r--networking/ping.c4
-rw-r--r--networking/tc.c2
-rw-r--r--networking/tls.c113
-rw-r--r--networking/tls_sp_c32.c35
-rw-r--r--networking/udhcp/d6_dhcpc.c7
-rw-r--r--networking/udhcp/d6_socket.c2
-rw-r--r--procps/nmeter.c4
-rw-r--r--shell/ash.c26
-rw-r--r--shell/ash_test/ash-heredoc/heredoc_and_cmd.right2
-rwxr-xr-xshell/ash_test/ash-heredoc/heredoc_and_cmd.tests8
-rw-r--r--shell/hush_test/hush-heredoc/heredoc_and_cmd.right2
-rwxr-xr-xshell/hush_test/hush-heredoc/heredoc_and_cmd.tests8
-rwxr-xr-xtestsuite/awk.tests6
-rwxr-xr-xtestsuite/sha1sum.tests10
-rwxr-xr-xtestsuite/sort.tests21
-rwxr-xr-xtestsuite/tree.tests100
-rwxr-xr-xtestsuite/xxd.tests23
-rw-r--r--util-linux/hexdump_xxd.c114
46 files changed, 678 insertions, 186 deletions
diff --git a/AUTHORS b/AUTHORS
index 5c9a634c9..9ec0e2ee4 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -181,3 +181,6 @@ Jie Zhang <jie.zhang@analog.com>
181 181
182Maxime Coste <mawww@kakoune.org> 182Maxime Coste <mawww@kakoune.org>
183 paste implementation 183 paste implementation
184
185Roger Knecht <rknecht@pm.me>
186 tree
diff --git a/archival/dpkg.c b/archival/dpkg.c
index 8e1f9431d..a6a8333a8 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -1120,7 +1120,7 @@ static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count
1120 if (package_edge->type == EDGE_PRE_DEPENDS 1120 if (package_edge->type == EDGE_PRE_DEPENDS
1121 || package_edge->type == EDGE_DEPENDS 1121 || package_edge->type == EDGE_DEPENDS
1122 ) { 1122 ) {
1123 int result=1; 1123 int result = 1;
1124 status_num = 0; 1124 status_num = 0;
1125 1125
1126 /* If we are inside an alternative then check 1126 /* If we are inside an alternative then check
diff --git a/coreutils/cut.c b/coreutils/cut.c
index 7009e74cf..55bdd9386 100644
--- a/coreutils/cut.c
+++ b/coreutils/cut.c
@@ -167,7 +167,7 @@ static void cut_file(FILE *file, const char *delim, const char *odelim,
167 if (!cl_pos && !dcount && !shoe) { 167 if (!cl_pos && !dcount && !shoe) {
168 if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) 168 if (option_mask32 & CUT_OPT_SUPPRESS_FLGS)
169 goto next_line; 169 goto next_line;
170 } else if (dcount<cut_lists[cl_pos].startpos) 170 } else if (dcount < cut_lists[cl_pos].startpos)
171 start = linelen; 171 start = linelen;
172 end = linelen; 172 end = linelen;
173 } else { 173 } else {
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c
index 0e57673f1..b4bdc262c 100644
--- a/coreutils/md5_sha1_sum.c
+++ b/coreutils/md5_sha1_sum.c
@@ -301,9 +301,7 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv)
301 301
302 count_total++; 302 count_total++;
303 filename_ptr = strchr(line, ' '); 303 filename_ptr = strchr(line, ' ');
304 if (filename_ptr == NULL 304 if (!filename_ptr) {
305 || (filename_ptr[1] != ' ' && filename_ptr[1] != '*')
306 ) {
307 if (flags & FLAG_WARN) { 305 if (flags & FLAG_WARN) {
308 bb_simple_error_msg("invalid format"); 306 bb_simple_error_msg("invalid format");
309 } 307 }
@@ -312,8 +310,13 @@ int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv)
312 free(line); 310 free(line);
313 continue; 311 continue;
314 } 312 }
315 *filename_ptr = '\0'; 313 *filename_ptr++ = '\0';
316 filename_ptr += 2; 314 /* coreutils 9.1 allows "HASH FILENAME" format,
315 * with only one space. Skip the 'correct'
316 * " " or " *" delimiter if it is there:
317 */
318 if (*filename_ptr == ' ' || *filename_ptr == '*')
319 filename_ptr++;
317 320
318 hash_value = hash_file(in_buf, filename_ptr, sha3_width); 321 hash_value = hash_file(in_buf, filename_ptr, sha3_width);
319 322
diff --git a/coreutils/sleep.c b/coreutils/sleep.c
index 2658e84df..442841210 100644
--- a/coreutils/sleep.c
+++ b/coreutils/sleep.c
@@ -37,6 +37,7 @@
37//applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP)) 37//applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP))
38 38
39//kbuild:lib-$(CONFIG_SLEEP) += sleep.o 39//kbuild:lib-$(CONFIG_SLEEP) += sleep.o
40//kbuild:lib-$(CONFIG_ASH_SLEEP) += sleep.o
40 41
41/* BB_AUDIT SUSv3 compliant */ 42/* BB_AUDIT SUSv3 compliant */
42/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */ 43/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */
diff --git a/coreutils/sort.c b/coreutils/sort.c
index 9aac656fe..01b7c44e5 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -357,9 +357,9 @@ static int compare_keys(const void *xarg, const void *yarg)
357 int dx; 357 int dx;
358 char *xx, *yy; 358 char *xx, *yy;
359 359
360 xx = strptime(x, "%b", &thyme); 360 xx = strptime(skip_whitespace(x), "%b", &thyme);
361 dx = thyme.tm_mon; 361 dx = thyme.tm_mon;
362 yy = strptime(y, "%b", &thyme); 362 yy = strptime(skip_whitespace(y), "%b", &thyme);
363 if (!xx) 363 if (!xx)
364 retval = (!yy) ? 0 : -1; 364 retval = (!yy) ? 0 : -1;
365 else if (!yy) 365 else if (!yy)
@@ -652,11 +652,12 @@ int sort_main(int argc UNUSED_PARAM, char **argv)
652 /* Handle -u */ 652 /* Handle -u */
653 if (option_mask32 & FLAG_u) { 653 if (option_mask32 & FLAG_u) {
654 int j = 0; 654 int j = 0;
655 /* coreutils 6.3 drop lines for which only key is the same 655 /* coreutils 6.3 drop lines for which only key is the same:
656 * -- disabling last-resort compare, or else compare_keys() 656 * - disabling last-resort compare, or else compare_keys()
657 * will be the same only for completely identical lines. 657 * will be the same only for completely identical lines
658 * - disabling -s (same reasons)
658 */ 659 */
659 option_mask32 |= FLAG_no_tie_break; 660 option_mask32 = (option_mask32 | FLAG_no_tie_break) & (~FLAG_s);
660 for (i = 1; i < linecount; i++) { 661 for (i = 1; i < linecount; i++) {
661 if (compare_keys(&lines[j], &lines[i]) == 0) 662 if (compare_keys(&lines[j], &lines[i]) == 0)
662 free(lines[i]); 663 free(lines[i]);
diff --git a/coreutils/test.c b/coreutils/test.c
index 840a0daaf..1d1e6d18b 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -859,7 +859,7 @@ static number_t primary(enum token n)
859 if (check_operator(args[1]) != EOI) { /* if args[1] != NULL */ 859 if (check_operator(args[1]) != EOI) { /* if args[1] != NULL */
860 if (args[2]) { 860 if (args[2]) {
861 // coreutils also does this: 861 // coreutils also does this:
862 // if (args[3] && args[0]="-l" && args[2] is BINOP) 862 // if (args[3] && args[0] = "-l" && args[2] is BINOP)
863 // return binop(1 /* prepended by -l */); 863 // return binop(1 /* prepended by -l */);
864 if (last_operator->op_type == BINOP) 864 if (last_operator->op_type == BINOP)
865 unnest_msg_and_return(binop(), "<primary: binop:%lld\n"); 865 unnest_msg_and_return(binop(), "<primary: binop:%lld\n");
diff --git a/editors/awk.c b/editors/awk.c
index 9b4d4dc3d..eedb7aa84 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -3147,6 +3147,9 @@ static var *evaluate(node *op, var *res)
3147 3147
3148 case XC( OC_MOVE ): 3148 case XC( OC_MOVE ):
3149 debug_printf_eval("MOVE\n"); 3149 debug_printf_eval("MOVE\n");
3150 /* make sure that we never return a temp var */
3151 if (L.v == TMPVAR0)
3152 L.v = res;
3150 /* if source is a temporary string, jusk relink it to dest */ 3153 /* if source is a temporary string, jusk relink it to dest */
3151 if (R.v == TMPVAR1 3154 if (R.v == TMPVAR1
3152 && !(R.v->type & VF_NUMBER) 3155 && !(R.v->type & VF_NUMBER)
diff --git a/editors/patch.c b/editors/patch.c
index aebb5073e..f90d6854d 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -138,9 +138,9 @@ static void do_line(void *data)
138{ 138{
139 struct double_list *dlist = data; 139 struct double_list *dlist = data;
140 140
141 if (TT.state>1 && *dlist->data != TT.state) 141 if (TT.state > 1 && *dlist->data != TT.state)
142 fdprintf(TT.state == 2 ? 2 : TT.fileout, 142 fdprintf(TT.state == 2 ? 2 : TT.fileout,
143 "%s\n", dlist->data+(TT.state>3 ? 1 : 0)); 143 "%s\n", dlist->data + (TT.state > 3 ? 1 : 0));
144 144
145 if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); 145 if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data);
146 146
@@ -221,7 +221,7 @@ static int apply_one_hunk(void)
221 221
222 // Match EOF if there aren't as many ending context lines as beginning 222 // Match EOF if there aren't as many ending context lines as beginning
223 for (plist = TT.current_hunk; plist; plist = plist->next) { 223 for (plist = TT.current_hunk; plist; plist = plist->next) {
224 if (plist->data[0]==' ') matcheof++; 224 if (plist->data[0] == ' ') matcheof++;
225 else matcheof = 0; 225 else matcheof = 0;
226 if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); 226 if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data);
227 } 227 }
@@ -433,15 +433,15 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
433 433
434 // Are we assembling a hunk? 434 // Are we assembling a hunk?
435 if (state >= 2) { 435 if (state >= 2) {
436 if (*patchline==' ' || *patchline=='+' || *patchline=='-') { 436 if (*patchline == ' ' || *patchline == '+' || *patchline == '-') {
437 dlist_add(&TT.current_hunk, patchline); 437 dlist_add(&TT.current_hunk, patchline);
438 438
439 if (*patchline != '+') oldlen--; 439 if (*patchline != '+') oldlen--;
440 if (*patchline != '-') newlen--; 440 if (*patchline != '-') newlen--;
441 441
442 // Context line? 442 // Context line?
443 if (*patchline==' ' && state==2) TT.context++; 443 if (*patchline == ' ' && state == 2) TT.context++;
444 else state=3; 444 else state = 3;
445 445
446 // If we've consumed all expected hunk lines, apply the hunk. 446 // If we've consumed all expected hunk lines, apply the hunk.
447 447
@@ -469,9 +469,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
469 free(*name); 469 free(*name);
470 // Trim date from end of filename (if any). We don't care. 470 // Trim date from end of filename (if any). We don't care.
471 for (s = patchline+4; *s && *s!='\t'; s++) 471 for (s = patchline+4; *s && *s!='\t'; s++)
472 if (*s=='\\' && s[1]) s++; 472 if (*s == '\\' && s[1]) s++;
473 i = atoi(s); 473 i = atoi(s);
474 if (i>1900 && i<=1970) 474 if (i > 1900 && i <= 1970)
475 *name = xstrdup("/dev/null"); 475 *name = xstrdup("/dev/null");
476 else { 476 else {
477 *s = 0; 477 *s = 0;
diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c
index 69a508b2e..5478ece7d 100644
--- a/editors/patch_toybox.c
+++ b/editors/patch_toybox.c
@@ -79,7 +79,7 @@ void TOY_llist_free(void *list, void (*freeit)(void *data))
79 else free(pop); 79 else free(pop);
80 80
81 // End doubly linked list too. 81 // End doubly linked list too.
82 if (list==pop) break; 82 if (list == pop) break;
83 } 83 }
84} 84}
85 85
@@ -137,11 +137,11 @@ char *get_rawline(int fd, long *plen, char end)
137 long len = 0; 137 long len = 0;
138 138
139 for (;;) { 139 for (;;) {
140 if (1>read(fd, &c, 1)) break; 140 if (1 > read(fd, &c, 1)) break;
141 if (!(len & 63)) buf=xrealloc(buf, len+65); 141 if (!(len & 63)) buf=xrealloc(buf, len+65);
142 if ((buf[len++]=c) == end) break; 142 if ((buf[len++] = c) == end) break;
143 } 143 }
144 if (buf) buf[len]=0; 144 if (buf) buf[len] = 0;
145 if (plen) *plen = len; 145 if (plen) *plen = len;
146 146
147 return buf; 147 return buf;
@@ -153,7 +153,7 @@ char *get_line(int fd)
153 long len; 153 long len;
154 char *buf = get_rawline(fd, &len, '\n'); 154 char *buf = get_rawline(fd, &len, '\n');
155 155
156 if (buf && buf[--len]=='\n') buf[len]=0; 156 if (buf && buf[--len] == '\n') buf[len] = 0;
157 157
158 return buf; 158 return buf;
159} 159}
@@ -165,10 +165,10 @@ void xsendfile(int in, int out)
165 long len; 165 long len;
166 char buf[4096]; 166 char buf[4096];
167 167
168 if (in<0) return; 168 if (in < 0) return;
169 for (;;) { 169 for (;;) {
170 len = safe_read(in, buf, 4096); 170 len = safe_read(in, buf, 4096);
171 if (len<1) break; 171 if (len < 1) break;
172 xwrite(out, buf, len); 172 xwrite(out, buf, len);
173 } 173 }
174} 174}
@@ -179,7 +179,7 @@ void replace_tempfile(int fdin, int fdout, char **tempname)
179{ 179{
180 char *temp = xstrdup(*tempname); 180 char *temp = xstrdup(*tempname);
181 181
182 temp[strlen(temp)-6]=0; 182 temp[strlen(temp)-6] = 0;
183 if (fdin != -1) { 183 if (fdin != -1) {
184 xsendfile(fdin, fdout); 184 xsendfile(fdin, fdout);
185 xclose(fdin); 185 xclose(fdin);
@@ -263,9 +263,9 @@ static void do_line(void *data)
263{ 263{
264 struct double_list *dlist = (struct double_list *)data; 264 struct double_list *dlist = (struct double_list *)data;
265 265
266 if (TT.state>1 && *dlist->data != TT.state) 266 if (TT.state > 1 && *dlist->data != TT.state)
267 fdprintf(TT.state == 2 ? 2 : TT.fileout, 267 fdprintf(TT.state == 2 ? 2 : TT.fileout,
268 "%s\n", dlist->data+(TT.state>3 ? 1 : 0)); 268 "%s\n", dlist->data + (TT.state > 3 ? 1 : 0));
269 269
270 if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); 270 if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data);
271 271
@@ -314,7 +314,7 @@ static int apply_one_hunk(void)
314 314
315 // Match EOF if there aren't as many ending context lines as beginning 315 // Match EOF if there aren't as many ending context lines as beginning
316 for (plist = TT.current_hunk; plist; plist = plist->next) { 316 for (plist = TT.current_hunk; plist; plist = plist->next) {
317 if (plist->data[0]==' ') matcheof++; 317 if (plist->data[0] == ' ') matcheof++;
318 else matcheof = 0; 318 else matcheof = 0;
319 if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); 319 if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data);
320 } 320 }
@@ -385,7 +385,7 @@ static int apply_one_hunk(void)
385 385
386 // If we've reached the end of the buffer without confirming a 386 // If we've reached the end of the buffer without confirming a
387 // match, read more lines. 387 // match, read more lines.
388 if (check==buf) { 388 if (check == buf) {
389 buf = 0; 389 buf = 0;
390 break; 390 break;
391 } 391 }
@@ -456,15 +456,15 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
456 456
457 // Are we assembling a hunk? 457 // Are we assembling a hunk?
458 if (state >= 2) { 458 if (state >= 2) {
459 if (*patchline==' ' || *patchline=='+' || *patchline=='-') { 459 if (*patchline == ' ' || *patchline == '+' || *patchline == '-') {
460 dlist_add(&TT.current_hunk, patchline); 460 dlist_add(&TT.current_hunk, patchline);
461 461
462 if (*patchline != '+') TT.oldlen--; 462 if (*patchline != '+') TT.oldlen--;
463 if (*patchline != '-') TT.newlen--; 463 if (*patchline != '-') TT.newlen--;
464 464
465 // Context line? 465 // Context line?
466 if (*patchline==' ' && state==2) TT.context++; 466 if (*patchline == ' ' && state == 2) TT.context++;
467 else state=3; 467 else state = 3;
468 468
469 // If we've consumed all expected hunk lines, apply the hunk. 469 // If we've consumed all expected hunk lines, apply the hunk.
470 470
@@ -491,9 +491,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
491 491
492 // Trim date from end of filename (if any). We don't care. 492 // Trim date from end of filename (if any). We don't care.
493 for (s = patchline+4; *s && *s!='\t'; s++) 493 for (s = patchline+4; *s && *s!='\t'; s++)
494 if (*s=='\\' && s[1]) s++; 494 if (*s == '\\' && s[1]) s++;
495 i = atoi(s); 495 i = atoi(s);
496 if (i>1900 && i<=1970) 496 if (i > 1900 && i <= 1970)
497 *name = xstrdup("/dev/null"); 497 *name = xstrdup("/dev/null");
498 else { 498 else {
499 *s = 0; 499 *s = 0;
@@ -537,7 +537,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
537 // handle -p path truncation. 537 // handle -p path truncation.
538 for (i=0, s = name; *s;) { 538 for (i=0, s = name; *s;) {
539 if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) break; 539 if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) break;
540 if (*(s++)=='/') { 540 if (*(s++) == '/') {
541 name = s; 541 name = s;
542 i++; 542 i++;
543 } 543 }
diff --git a/editors/vi.c b/editors/vi.c
index b813747d1..574feb465 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -4480,8 +4480,14 @@ static void do_cmd(int c)
4480 goto dc_i; // start inserting 4480 goto dc_i; // start inserting
4481 break; 4481 break;
4482 case 'Z': // Z- if modified, {write}; exit 4482 case 'Z': // Z- if modified, {write}; exit
4483 // ZZ means to save file (if necessary), then exit
4484 c1 = get_one_char(); 4483 c1 = get_one_char();
4484 // ZQ means to exit without saving
4485 if (c1 == 'Q') {
4486 editing = 0;
4487 optind = cmdline_filecnt;
4488 break;
4489 }
4490 // ZZ means to save file (if necessary), then exit
4485 if (c1 != 'Z') { 4491 if (c1 != 'Z') {
4486 indicate_error(); 4492 indicate_error();
4487 break; 4493 break;
diff --git a/examples/shutdown-1.0/script/hardshutdown.c b/examples/shutdown-1.0/script/hardshutdown.c
index b4af26f0f..c90f55396 100644
--- a/examples/shutdown-1.0/script/hardshutdown.c
+++ b/examples/shutdown-1.0/script/hardshutdown.c
@@ -115,7 +115,7 @@ int main(int argc, char **argv)
115 if (ptr) 115 if (ptr)
116 prog = ptr+1; 116 prog = ptr+1;
117 117
118 for (c=1; c < argc; c++) { 118 for (c = 1; c < argc; c++) {
119 if (argv[c][0] >= '0' && argv[c][0] <= '9') { 119 if (argv[c][0] >= '0' && argv[c][0] <= '9') {
120 t.tv_sec = strtol(argv[c], NULL, 10); 120 t.tv_sec = strtol(argv[c], NULL, 10);
121 continue; 121 continue;
@@ -124,7 +124,7 @@ int main(int argc, char **argv)
124 usage(); 124 usage();
125 return 1; 125 return 1;
126 } 126 }
127 for (i=1; argv[c][i]; i++) { 127 for (i = 1; argv[c][i]; i++) {
128 switch (argv[c][i]) { 128 switch (argv[c][i]) {
129 case 'h': 129 case 'h':
130 action = HALT; 130 action = HALT;
diff --git a/include/libbb.h b/include/libbb.h
index c5691c76d..1b1e5cab1 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1568,6 +1568,7 @@ int ash_main(int argc, char** argv) IF_SHELL_ASH(MAIN_EXTERNALLY_VISIBLE);
1568int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE); 1568int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE);
1569/* If shell needs them, they exist even if not enabled as applets */ 1569/* If shell needs them, they exist even if not enabled as applets */
1570int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); 1570int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE);
1571int sleep_main(int argc, char **argv) IF_SLEEP(MAIN_EXTERNALLY_VISIBLE);
1571int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); 1572int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE);
1572int test_main(int argc, char **argv) 1573int test_main(int argc, char **argv)
1573#if ENABLE_TEST || ENABLE_TEST1 || ENABLE_TEST2 1574#if ENABLE_TEST || ENABLE_TEST1 || ENABLE_TEST2
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 99f0cb89c..a90d0cdb5 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -319,7 +319,6 @@ void lbb_prepare(const char *applet
319 /* Redundant for busybox (run_applet_and_exit covers that case) 319 /* Redundant for busybox (run_applet_and_exit covers that case)
320 * but needed for "individual applet" mode */ 320 * but needed for "individual applet" mode */
321 if (argv[1] 321 if (argv[1]
322 && !argv[2]
323 && strcmp(argv[1], "--help") == 0 322 && strcmp(argv[1], "--help") == 0
324 && !is_prefixed_with(applet, "busybox") 323 && !is_prefixed_with(applet, "busybox")
325 ) { 324 ) {
@@ -1115,12 +1114,15 @@ void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv)
1115# if defined APPLET_NO_echo 1114# if defined APPLET_NO_echo
1116 && applet_no != APPLET_NO_echo 1115 && applet_no != APPLET_NO_echo
1117# endif 1116# endif
1117# if ENABLE_TEST1 || ENABLE_TEST2
1118 && argv[0][0] != '[' /* exclude [ --help ] and [[ --help ]] too */
1119# endif
1118# if ENABLE_PLATFORM_MINGW32 && defined APPLET_NO_busybox 1120# if ENABLE_PLATFORM_MINGW32 && defined APPLET_NO_busybox
1119 && applet_no != APPLET_NO_busybox 1121 && applet_no != APPLET_NO_busybox
1120# endif 1122# endif
1121 ) { 1123 ) {
1122 if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0) { 1124 if (argv[1] && strcmp(argv[1], "--help") == 0) {
1123 /* Make "foo --help" exit with 0: */ 1125 /* Make "foo --help [...]" exit with 0: */
1124 xfunc_error_retval = 0; 1126 xfunc_error_retval = 0;
1125 bb_show_usage(); 1127 bb_show_usage();
1126 } 1128 }
diff --git a/libbb/duration.c b/libbb/duration.c
index a6a29ddae..793d02f42 100644
--- a/libbb/duration.c
+++ b/libbb/duration.c
@@ -76,6 +76,12 @@ void FAST_FUNC sleep_for_duration(duration_t duration)
76 ts.tv_sec = duration; 76 ts.tv_sec = duration;
77 ts.tv_nsec = (duration - ts.tv_sec) * 1000000000; 77 ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
78 } 78 }
79 /* NB: if ENABLE_ASH_SLEEP, we end up here if "sleep N"
80 * is run in ash. ^C will still work, because ash's signal handler
81 * does not return (it longjumps), the below loop
82 * will not continue looping.
83 * (This wouldn't work in hush)
84 */
79 do { 85 do {
80 errno = 0; 86 errno = 0;
81 nanosleep(&ts, &ts); 87 nanosleep(&ts, &ts);
diff --git a/libbb/hash_md5_sha256_x86-32_shaNI.S b/libbb/hash_md5_sha256_x86-32_shaNI.S
index 3905bad9a..a0e4a571a 100644
--- a/libbb/hash_md5_sha256_x86-32_shaNI.S
+++ b/libbb/hash_md5_sha256_x86-32_shaNI.S
@@ -19,6 +19,9 @@
19// We do not check SSSE3 in cpuid, 19// We do not check SSSE3 in cpuid,
20// all SHA-capable CPUs support it as well. 20// all SHA-capable CPUs support it as well.
21 21
22#ifdef __linux__
23 .section .note.GNU-stack, "", @progbits
24#endif
22 .section .text.sha256_process_block64_shaNI, "ax", @progbits 25 .section .text.sha256_process_block64_shaNI, "ax", @progbits
23 .globl sha256_process_block64_shaNI 26 .globl sha256_process_block64_shaNI
24 .hidden sha256_process_block64_shaNI 27 .hidden sha256_process_block64_shaNI
diff --git a/libbb/hash_md5_sha256_x86-64_shaNI.S b/libbb/hash_md5_sha256_x86-64_shaNI.S
index 082ceafe4..172c2eae2 100644
--- a/libbb/hash_md5_sha256_x86-64_shaNI.S
+++ b/libbb/hash_md5_sha256_x86-64_shaNI.S
@@ -19,6 +19,9 @@
19// We do not check SSSE3 in cpuid, 19// We do not check SSSE3 in cpuid,
20// all SHA-capable CPUs support it as well. 20// all SHA-capable CPUs support it as well.
21 21
22#ifdef __linux__
23 .section .note.GNU-stack, "", @progbits
24#endif
22 .section .text.sha256_process_block64_shaNI, "ax", @progbits 25 .section .text.sha256_process_block64_shaNI, "ax", @progbits
23 .globl sha256_process_block64_shaNI 26 .globl sha256_process_block64_shaNI
24 .hidden sha256_process_block64_shaNI 27 .hidden sha256_process_block64_shaNI
diff --git a/libbb/hash_md5_sha_x86-32_shaNI.S b/libbb/hash_md5_sha_x86-32_shaNI.S
index 2366b046a..7455a29f0 100644
--- a/libbb/hash_md5_sha_x86-32_shaNI.S
+++ b/libbb/hash_md5_sha_x86-32_shaNI.S
@@ -25,6 +25,9 @@
25// We do not check SSSE3/SSE4.1 in cpuid, 25// We do not check SSSE3/SSE4.1 in cpuid,
26// all SHA-capable CPUs support them as well. 26// all SHA-capable CPUs support them as well.
27 27
28#ifdef __linux__
29 .section .note.GNU-stack, "", @progbits
30#endif
28 .section .text.sha1_process_block64_shaNI, "ax", @progbits 31 .section .text.sha1_process_block64_shaNI, "ax", @progbits
29 .globl sha1_process_block64_shaNI 32 .globl sha1_process_block64_shaNI
30 .hidden sha1_process_block64_shaNI 33 .hidden sha1_process_block64_shaNI
diff --git a/libbb/hash_md5_sha_x86-64.S b/libbb/hash_md5_sha_x86-64.S
index 1d55b91f8..2cdd22015 100644
--- a/libbb/hash_md5_sha_x86-64.S
+++ b/libbb/hash_md5_sha_x86-64.S
@@ -1,6 +1,9 @@
1### Generated by hash_md5_sha_x86-64.S.sh ### 1### Generated by hash_md5_sha_x86-64.S.sh ###
2 2
3#if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) 3#if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__)
4#ifdef __linux__
5 .section .note.GNU-stack, "", @progbits
6#endif
4 .section .text.sha1_process_block64, "ax", @progbits 7 .section .text.sha1_process_block64, "ax", @progbits
5 .globl sha1_process_block64 8 .globl sha1_process_block64
6 .hidden sha1_process_block64 9 .hidden sha1_process_block64
diff --git a/libbb/hash_md5_sha_x86-64.S.sh b/libbb/hash_md5_sha_x86-64.S.sh
index 40c979d35..653fe4989 100755
--- a/libbb/hash_md5_sha_x86-64.S.sh
+++ b/libbb/hash_md5_sha_x86-64.S.sh
@@ -127,6 +127,9 @@ echo \
127"### Generated by hash_md5_sha_x86-64.S.sh ### 127"### Generated by hash_md5_sha_x86-64.S.sh ###
128 128
129#if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) 129#if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__)
130#ifdef __linux__
131 .section .note.GNU-stack, \"\", @progbits
132#endif
130 .section .text.sha1_process_block64, \"ax\", @progbits 133 .section .text.sha1_process_block64, \"ax\", @progbits
131 .globl sha1_process_block64 134 .globl sha1_process_block64
132 .hidden sha1_process_block64 135 .hidden sha1_process_block64
diff --git a/libbb/hash_md5_sha_x86-64_shaNI.S b/libbb/hash_md5_sha_x86-64_shaNI.S
index 794e97040..2f03e1ce4 100644
--- a/libbb/hash_md5_sha_x86-64_shaNI.S
+++ b/libbb/hash_md5_sha_x86-64_shaNI.S
@@ -25,6 +25,9 @@
25// We do not check SSSE3/SSE4.1 in cpuid, 25// We do not check SSSE3/SSE4.1 in cpuid,
26// all SHA-capable CPUs support them as well. 26// all SHA-capable CPUs support them as well.
27 27
28#ifdef __linux__
29 .section .note.GNU-stack, "", @progbits
30#endif
28 .section .text.sha1_process_block64_shaNI, "ax", @progbits 31 .section .text.sha1_process_block64_shaNI, "ax", @progbits
29 .globl sha1_process_block64_shaNI 32 .globl sha1_process_block64_shaNI
30 .hidden sha1_process_block64_shaNI 33 .hidden sha1_process_block64_shaNI
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 6994d1da7..c5d5808f5 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2154,7 +2154,13 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2154 case 'W': /* basename of cur dir */ 2154 case 'W': /* basename of cur dir */
2155 if (!cwd_buf) { 2155 if (!cwd_buf) {
2156 const char *home; 2156 const char *home;
2157#if ENABLE_SHELL_ASH
2158 cwd_buf = state->sh_get_var
2159 ? xstrdup(state->sh_get_var("PWD"))
2160 : xrealloc_getcwd_or_warn(NULL);
2161#else
2157 cwd_buf = xrealloc_getcwd_or_warn(NULL); 2162 cwd_buf = xrealloc_getcwd_or_warn(NULL);
2163#endif
2158 if (!cwd_buf) 2164 if (!cwd_buf)
2159 cwd_buf = (char *)bb_msg_unknown; 2165 cwd_buf = (char *)bb_msg_unknown;
2160 else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { 2166 else if ((home = get_homedir_or_NULL()) != NULL && home[0]) {
diff --git a/miscutils/bc.c b/miscutils/bc.c
index fe555d018..01402b311 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -2892,6 +2892,8 @@ static char peek_inbuf(void)
2892 ) { 2892 ) {
2893 xc_read_line(&G.input_buffer, G.prs.lex_input_fp); 2893 xc_read_line(&G.input_buffer, G.prs.lex_input_fp);
2894 G.prs.lex_inbuf = G.input_buffer.v; 2894 G.prs.lex_inbuf = G.input_buffer.v;
2895 // lex_next_at may point to now-freed data, update it:
2896 G.prs.lex_next_at = G.prs.lex_inbuf;
2895 if (G.input_buffer.len <= 1) // on EOF, len is 1 (NUL byte) 2897 if (G.input_buffer.len <= 1) // on EOF, len is 1 (NUL byte)
2896 G.prs.lex_input_fp = NULL; 2898 G.prs.lex_input_fp = NULL;
2897 } 2899 }
@@ -3103,7 +3105,7 @@ static BC_STATUS zbc_lex_identifier(void)
3103 continue; 3105 continue;
3104 match: 3106 match:
3105 // buf starts with keyword bc_lex_kws[i] 3107 // buf starts with keyword bc_lex_kws[i]
3106 if (isalnum(buf[j]) || buf[j]=='_') 3108 if (isalnum(buf[j]) || buf[j] == '_')
3107 continue; // "ifz" does not match "if" keyword, "if." does 3109 continue; // "ifz" does not match "if" keyword, "if." does
3108 p->lex = BC_LEX_KEY_1st_keyword + i; 3110 p->lex = BC_LEX_KEY_1st_keyword + i;
3109 if (!keyword_is_POSIX(i)) { 3111 if (!keyword_is_POSIX(i)) {
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c
index fb9ebcf60..297693f8c 100644
--- a/miscutils/devfsd.c
+++ b/miscutils/devfsd.c
@@ -976,7 +976,7 @@ static void action_compat(const struct devfsd_notify_struct *info, unsigned int
976 rewind_ = info->devname[info->namelen - 1]; 976 rewind_ = info->devname[info->namelen - 1];
977 if (rewind_ != 'n') 977 if (rewind_ != 'n')
978 rewind_ = '\0'; 978 rewind_ = '\0';
979 mode=0; 979 mode = 0;
980 if (ptr[2] == 'l' /*108*/ || ptr[2] == 'm'/*109*/) 980 if (ptr[2] == 'l' /*108*/ || ptr[2] == 'm'/*109*/)
981 mode = ptr[2] - 107; /* 1 or 2 */ 981 mode = ptr[2] - 107; /* 1 or 2 */
982 if (ptr[2] == 'a') 982 if (ptr[2] == 'a')
@@ -1595,11 +1595,11 @@ static char *write_old_sd_name(char *buffer,
1595 return buffer; 1595 return buffer;
1596 } 1596 }
1597 if ((major > 64) && (major < 72)) { 1597 if ((major > 64) && (major < 72)) {
1598 disc_index = ((major - 64) << 4) +(minor >> 4); 1598 disc_index = ((major - 64) << 4) + (minor >> 4);
1599 if (disc_index < 26) 1599 if (disc_index < 26)
1600 sprintf(buffer, "sd%c%s", 'a' + disc_index, part); 1600 sprintf(buffer, "sd%c%s", 'a' + disc_index, part);
1601 else 1601 else
1602 sprintf(buffer, "sd%c%c%s", 'a' +(disc_index / 26) - 1, 'a' + disc_index % 26, part); 1602 sprintf(buffer, "sd%c%c%s", 'a' + (disc_index / 26) - 1, 'a' + disc_index % 26, part);
1603 return buffer; 1603 return buffer;
1604 } 1604 }
1605 return NULL; 1605 return NULL;
diff --git a/miscutils/devmem.c b/miscutils/devmem.c
index f9f0276bc..f21621bd6 100644
--- a/miscutils/devmem.c
+++ b/miscutils/devmem.c
@@ -29,7 +29,6 @@ int devmem_main(int argc UNUSED_PARAM, char **argv)
29{ 29{
30 void *map_base, *virt_addr; 30 void *map_base, *virt_addr;
31 uint64_t read_result; 31 uint64_t read_result;
32 uint64_t writeval = writeval; /* for compiler */
33 off_t target; 32 off_t target;
34 unsigned page_size, mapped_size, offset_in_page; 33 unsigned page_size, mapped_size, offset_in_page;
35 int fd; 34 int fd;
@@ -64,9 +63,6 @@ int devmem_main(int argc UNUSED_PARAM, char **argv)
64 width = strchrnul(bhwl, (argv[2][0] | 0x20)) - bhwl; 63 width = strchrnul(bhwl, (argv[2][0] | 0x20)) - bhwl;
65 width = sizes[width]; 64 width = sizes[width];
66 } 65 }
67 /* VALUE */
68 if (argv[3])
69 writeval = bb_strtoull(argv[3], NULL, 0);
70 } else { /* argv[2] == NULL */ 66 } else { /* argv[2] == NULL */
71 /* make argv[3] to be a valid thing to fetch */ 67 /* make argv[3] to be a valid thing to fetch */
72 argv--; 68 argv--;
@@ -96,28 +92,46 @@ int devmem_main(int argc UNUSED_PARAM, char **argv)
96 virt_addr = (char*)map_base + offset_in_page; 92 virt_addr = (char*)map_base + offset_in_page;
97 93
98 if (!argv[3]) { 94 if (!argv[3]) {
99 switch (width) { 95#ifdef __SIZEOF_INT128__
100 case 8: 96 if (width == 128) {
101 read_result = *(volatile uint8_t*)virt_addr; 97 unsigned __int128 rd =
102 break; 98 *(volatile unsigned __int128 *)virt_addr;
103 case 16: 99 printf("0x%016llX%016llX\n",
104 read_result = *(volatile uint16_t*)virt_addr; 100 (unsigned long long)(uint64_t)(rd >> 64),
105 break; 101 (unsigned long long)(uint64_t)rd
106 case 32: 102 );
107 read_result = *(volatile uint32_t*)virt_addr; 103 } else
108 break; 104#endif
109 case 64: 105 {
110 read_result = *(volatile uint64_t*)virt_addr; 106 switch (width) {
111 break; 107 case 8:
112 default: 108 read_result = *(volatile uint8_t*)virt_addr;
113 bb_simple_error_msg_and_die("bad width"); 109 break;
110 case 16:
111 read_result = *(volatile uint16_t*)virt_addr;
112 break;
113 case 32:
114 read_result = *(volatile uint32_t*)virt_addr;
115 break;
116 case 64:
117 read_result = *(volatile uint64_t*)virt_addr;
118 break;
119 default:
120 bb_simple_error_msg_and_die("bad width");
121 }
122// printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n",
123// target, virt_addr,
124// (unsigned long long)read_result);
125 /* Zero-padded output shows the width of access just done */
126 printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result);
114 } 127 }
115// printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n",
116// target, virt_addr,
117// (unsigned long long)read_result);
118 /* Zero-padded output shows the width of access just done */
119 printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result);
120 } else { 128 } else {
129 /* parse VALUE */
130#ifdef __SIZEOF_INT128__
131 unsigned __int128 writeval = strtoumax(argv[3], NULL, 0);
132#else
133 uint64_t writeval = bb_strtoull(argv[3], NULL, 0);
134#endif
121 switch (width) { 135 switch (width) {
122 case 8: 136 case 8:
123 *(volatile uint8_t*)virt_addr = writeval; 137 *(volatile uint8_t*)virt_addr = writeval;
@@ -135,6 +149,12 @@ int devmem_main(int argc UNUSED_PARAM, char **argv)
135 *(volatile uint64_t*)virt_addr = writeval; 149 *(volatile uint64_t*)virt_addr = writeval;
136// read_result = *(volatile uint64_t*)virt_addr; 150// read_result = *(volatile uint64_t*)virt_addr;
137 break; 151 break;
152#ifdef __SIZEOF_INT128__
153 case 128:
154 *(volatile unsigned __int128 *)virt_addr = writeval;
155// read_result = *(volatile uint64_t*)virt_addr;
156 break;
157#endif
138 default: 158 default:
139 bb_simple_error_msg_and_die("bad width"); 159 bb_simple_error_msg_and_die("bad width");
140 } 160 }
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index d8d8f6166..83e2f8d53 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -798,7 +798,7 @@ static void identify(uint16_t *val)
798 if (!(val[GEN_CONFIG] & NOT_ATA)) { 798 if (!(val[GEN_CONFIG] & NOT_ATA)) {
799 dev = ATA_DEV; 799 dev = ATA_DEV;
800 printf("ATA device, with "); 800 printf("ATA device, with ");
801 } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) { 801 } else if (val[GEN_CONFIG] == CFA_SUPPORT_VAL) {
802 dev = ATA_DEV; 802 dev = ATA_DEV;
803 like_std = 4; 803 like_std = 4;
804 printf("CompactFlash ATA device, with "); 804 printf("CompactFlash ATA device, with ");
@@ -819,13 +819,13 @@ static void identify(uint16_t *val)
819 * specific, it should be safe to check it now, even though we don't 819 * specific, it should be safe to check it now, even though we don't
820 * know yet what standard this device is using. 820 * know yet what standard this device is using.
821 */ 821 */
822 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) 822 if ((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == STBY_ID_VAL)
823 || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) 823 || (val[CONFIG] == PWRD_NID_VAL) || (val[CONFIG] == PWRD_ID_VAL)
824 ) { 824 ) {
825 like_std = 5; 825 like_std = 5;
826 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)) 826 if ((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == STBY_ID_VAL))
827 puts("powers-up in standby; SET FEATURES subcmd spins-up."); 827 puts("powers-up in standby; SET FEATURES subcmd spins-up.");
828 if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE)) 828 if (((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
829 puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n"); 829 puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n");
830 } 830 }
831 831
@@ -853,7 +853,7 @@ static void identify(uint16_t *val)
853 printf("\n\tSupported: "); 853 printf("\n\tSupported: ");
854 jj = val[MAJOR] << 1; 854 jj = val[MAJOR] << 1;
855 kk = like_std >4 ? like_std-4: 0; 855 kk = like_std >4 ? like_std-4: 0;
856 for (ii = 14; (ii >0)&&(ii>kk); ii--) { 856 for (ii = 14; (ii > 0) && (ii > kk); ii--) {
857 if (jj & 0x8000) { 857 if (jj & 0x8000) {
858 printf("%u ", ii); 858 printf("%u ", ii);
859 if (like_std < ii) { 859 if (like_std < ii) {
@@ -943,7 +943,7 @@ static void identify(uint16_t *val)
943 for (ii = 1; ii < 15; ii++) { 943 for (ii = 1; ii < 15; ii++) {
944 if (jj & 0x0001) 944 if (jj & 0x0001)
945 printf("\t%s\n", nth_string(ata1_cfg_str, ii)); 945 printf("\t%s\n", nth_string(ata1_cfg_str, ii));
946 jj >>=1; 946 jj >>= 1;
947 } 947 }
948 } 948 }
949 if (dev == ATAPI_DEV) { 949 if (dev == ATAPI_DEV) {
@@ -952,7 +952,7 @@ static void identify(uint16_t *val)
952 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL) 952 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL)
953 strng = "<=10ms with INTRQ"; 953 strng = "<=10ms with INTRQ";
954 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL) 954 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL)
955 strng ="50us"; 955 strng = "50us";
956 else 956 else
957 strng = "unknown"; 957 strng = "unknown";
958 printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ 958 printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */
@@ -1014,7 +1014,7 @@ static void identify(uint16_t *val)
1014 } 1014 }
1015 1015
1016 if (!bbbig) 1016 if (!bbbig)
1017 bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */ 1017 bbbig = (uint64_t)(ll > mm ? ll : mm); /* # 512 byte blocks */
1018 printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11); 1018 printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11);
1019 bbbig = (bbbig << 9) / 1000000; 1019 bbbig = (bbbig << 9) / 1000000;
1020 printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig); 1020 printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig);
@@ -1160,7 +1160,7 @@ static void identify(uint16_t *val)
1160 jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; 1160 jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007;
1161 for (ii = 0; ii <= PIO_MODE_MAX; ii++) { 1161 for (ii = 0; ii <= PIO_MODE_MAX; ii++) {
1162 if (jj & 0x0001) printf("pio%d ", ii); 1162 if (jj & 0x0001) printf("pio%d ", ii);
1163 jj >>=1; 1163 jj >>= 1;
1164 } 1164 }
1165 bb_putchar('\n'); 1165 bb_putchar('\n');
1166 } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) { 1166 } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) {
@@ -1199,7 +1199,7 @@ static void identify(uint16_t *val)
1199 } 1199 }
1200 if (ii == 31) { 1200 if (ii == 31) {
1201 if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL) 1201 if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL)
1202 ii +=16; 1202 ii += 16;
1203 } 1203 }
1204 } 1204 }
1205 } 1205 }
@@ -1220,7 +1220,7 @@ static void identify(uint16_t *val)
1220 printf("\t%s\t%s\n", 1220 printf("\t%s\t%s\n",
1221 (!(jj & 0x0001)) ? "not" : "", 1221 (!(jj & 0x0001)) ? "not" : "",
1222 nth_string(secu_str, ii)); 1222 nth_string(secu_str, ii));
1223 jj >>=1; 1223 jj >>= 1;
1224 } 1224 }
1225 if (val[SECU_STATUS] & SECU_ENABLED) { 1225 if (val[SECU_STATUS] & SECU_ENABLED) {
1226 printf("\tSecurity level %s\n", 1226 printf("\tSecurity level %s\n",
diff --git a/miscutils/tree.c b/miscutils/tree.c
new file mode 100644
index 000000000..fa55696c6
--- /dev/null
+++ b/miscutils/tree.c
@@ -0,0 +1,131 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2022 Roger Knecht <rknecht@pm.me>
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7//config:config TREE
8//config: bool "tree (0.6 kb)"
9//config: default y
10//config: help
11//config: List files and directories in a tree structure.
12
13//applet:IF_TREE(APPLET(tree, BB_DIR_USR_BIN, BB_SUID_DROP))
14
15//kbuild:lib-$(CONFIG_TREE) += tree.o
16
17//usage:#define tree_trivial_usage NOUSAGE_STR
18//usage:#define tree_full_usage ""
19
20#include "libbb.h"
21#include "common_bufsiz.h"
22#include "unicode.h"
23
24#define prefix_buf bb_common_bufsiz1
25
26static void tree_print(unsigned count[2], const char* directory_name, char* prefix_pos)
27{
28 struct dirent **entries;
29 int index, size;
30 const char *bar = "| ";
31 const char *mid = "|-- ";
32 const char *end = "`-- ";
33
34#if ENABLE_UNICODE_SUPPORT
35 if (unicode_status == UNICODE_ON) {
36 bar = "│ ";
37 mid = "├── ";
38 end = "└── ";
39 }
40#endif
41
42 // read directory entries
43 size = scandir(directory_name, &entries, NULL, alphasort);
44
45 if (size < 0) {
46 fputs_stdout(directory_name);
47 puts(" [error opening dir]");
48 return;
49 }
50
51 // print directory name
52 puts(directory_name);
53
54 // switch to sub directory
55 xchdir(directory_name);
56
57 // print all directory entries
58 for (index = 0; index < size;) {
59 struct dirent *dirent = entries[index++];
60
61 // filter hidden files and directories
62 if (dirent->d_name[0] != '.') {
63 int status;
64 struct stat statBuf;
65
66//TODO: when -l is implemented, use stat, not lstat, if -l
67 status = lstat(dirent->d_name, &statBuf);
68
69 if (index == size) {
70 strcpy(prefix_pos, end);
71 } else {
72 strcpy(prefix_pos, mid);
73 }
74 fputs_stdout(prefix_buf);
75
76 if (status == 0 && S_ISLNK(statBuf.st_mode)) {
77 // handle symlink
78 char* symlink_path = xmalloc_readlink(dirent->d_name);
79 printf("%s -> %s\n", dirent->d_name, symlink_path);
80 free(symlink_path);
81 count[1]++;
82 } else if (status == 0 && S_ISDIR(statBuf.st_mode)
83 && (prefix_pos - prefix_buf) < (COMMON_BUFSIZE - 16)
84 ) {
85 // handle directory
86 char* pos;
87 if (index == size) {
88 pos = stpcpy(prefix_pos, " ");
89 } else {
90 pos = stpcpy(prefix_pos, bar);
91 }
92 tree_print(count, dirent->d_name, pos);
93 count[0]++;
94 } else {
95 // handle file
96 puts(dirent->d_name);
97 count[1]++;
98 }
99 }
100
101 // release directory entry
102 free(dirent);
103 }
104
105 // release directory array
106 free(entries);
107
108 // switch to parent directory
109 xchdir("..");
110}
111
112int tree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
113int tree_main(int argc UNUSED_PARAM, char **argv)
114{
115 unsigned count[2] = { 0, 0 };
116
117 setup_common_bufsiz();
118 init_unicode();
119
120 if (!argv[1])
121 *argv-- = (char*)".";
122
123 // list directories given as command line arguments
124 while (*(++argv))
125 tree_print(count, *argv, prefix_buf);
126
127 // print statistic
128 printf("\n%u directories, %u files\n", count[0], count[1]);
129
130 return EXIT_SUCCESS;
131}
diff --git a/modutils/modutils-24.c b/modutils/modutils-24.c
index d0bc2a6ef..37c303f90 100644
--- a/modutils/modutils-24.c
+++ b/modutils/modutils-24.c
@@ -981,7 +981,7 @@ arch_apply_relocation(struct obj_file *f,
981 (loc[1] & 0xFFFF); 981 (loc[1] & 0xFFFF);
982 982
983 /* Add reloc offset */ 983 /* Add reloc offset */
984 temp1+=v; 984 temp1 += v;
985 985
986 /* Store back into code */ 986 /* Store back into code */
987 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16; 987 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
diff --git a/networking/ping.c b/networking/ping.c
index 86d8088de..9805695a1 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -74,7 +74,7 @@
74//usage: "\n -c CNT Send only CNT pings" 74//usage: "\n -c CNT Send only CNT pings"
75//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" 75//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)"
76//usage: "\n -i SECS Interval" 76//usage: "\n -i SECS Interval"
77//usage: "\n -A Ping as soon as reply is recevied" 77//usage: "\n -A Ping as soon as reply is received"
78//usage: "\n -t TTL Set TTL" 78//usage: "\n -t TTL Set TTL"
79//usage: "\n -I IFACE/IP Source interface or IP address" 79//usage: "\n -I IFACE/IP Source interface or IP address"
80//usage: "\n -W SEC Seconds to wait for the first response (default 10)" 80//usage: "\n -W SEC Seconds to wait for the first response (default 10)"
@@ -91,7 +91,7 @@
91//usage: "\n -c CNT Send only CNT pings" 91//usage: "\n -c CNT Send only CNT pings"
92//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" 92//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)"
93//usage: "\n -i SECS Interval" 93//usage: "\n -i SECS Interval"
94//usage: "\n -A Ping as soon as reply is recevied" 94//usage: "\n -A Ping as soon as reply is received"
95///////: "\n -t TTL Set TTL" 95///////: "\n -t TTL Set TTL"
96///////^^^^^ -t not tested for IPv6, might be not working 96///////^^^^^ -t not tested for IPv6, might be not working
97//usage: "\n -I IFACE/IP Source interface or IP address" 97//usage: "\n -I IFACE/IP Source interface or IP address"
diff --git a/networking/tc.c b/networking/tc.c
index 46ad23d8b..43187f7ee 100644
--- a/networking/tc.c
+++ b/networking/tc.c
@@ -214,7 +214,7 @@ static int prio_print_opt(struct rtattr *opt)
214 return 0; 214 return 0;
215 parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt)); 215 parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt));
216 printf("bands %u priomap ", qopt->bands); 216 printf("bands %u priomap ", qopt->bands);
217 for (i=0; i<=TC_PRIO_MAX; i++) 217 for (i = 0; i <= TC_PRIO_MAX; i++)
218 printf(" %d", qopt->priomap[i]); 218 printf(" %d", qopt->priomap[i]);
219 219
220 if (tb[TCA_PRIO_MQ]) 220 if (tb[TCA_PRIO_MQ])
diff --git a/networking/tls.c b/networking/tls.c
index 5f40aec70..9f1dd67ec 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -948,11 +948,46 @@ static int tls_has_buffered_record(tls_state_t *tls)
948 948
949static const char *alert_text(int code) 949static const char *alert_text(int code)
950{ 950{
951 //10 unexpected_message
952 //20 bad_record_mac
953 //21 decryption_failed
954 //22 record_overflow
955 //30 decompression_failure
956 //40 handshake_failure
957 //41 no_certificate
958 //42 bad_certificate
959 //43 unsupported_certificate
960 //44 certificate_revoked
961 //45 certificate_expired
962 //46 certificate_unknown
963 //47 illegal_parameter
964 //48 unknown_ca
965 //49 access_denied
966 //50 decode_error
967 //51 decrypt_error
968 //52 too_many_cids_requested
969 //60 export_restriction
970 //70 protocol_version
971 //71 insufficient_security
972 //80 internal_error
973 //86 inappropriate_fallback
974 //90 user_canceled
975 //100 no_renegotiation
976 //109 missing_extension
977 //110 unsupported_extension
978 //111 certificate_unobtainable
979 //112 unrecognized_name
980 //113 bad_certificate_status_response
981 //114 bad_certificate_hash_value
982 //115 unknown_psk_identity
983 //116 certificate_required
984 //120 no_application_protocol
951 switch (code) { 985 switch (code) {
952 case 20: return "bad MAC"; 986 case 20: return "bad MAC";
953 case 50: return "decode error"; 987 case 50: return "decode error";
954 case 51: return "decrypt error";
955 case 40: return "handshake failure"; 988 case 40: return "handshake failure";
989 case 51: return "decrypt error";
990 case 80: return "internal error";
956 case 112: return "unrecognized name"; 991 case 112: return "unrecognized name";
957 } 992 }
958 return itoa(code); 993 return itoa(code);
@@ -1531,27 +1566,6 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1531#endif 1566#endif
1532 0x01,0x00, //not a cipher - comprtypes_len, comprtype 1567 0x01,0x00, //not a cipher - comprtypes_len, comprtype
1533 }; 1568 };
1534 static const uint8_t supported_groups[] = {
1535 0x00,0x0a, //extension_type: "supported_groups"
1536 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len
1537 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len
1538#if ALLOW_CURVE_P256
1539 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1)
1540#endif
1541 //0x00,0x18, //curve_secp384r1
1542 //0x00,0x19, //curve_secp521r1
1543#if ALLOW_CURVE_X25519
1544 0x00,0x1d, //curve_x25519 (RFC 7748)
1545#endif
1546 //0x00,0x1e, //curve_x448 (RFC 7748)
1547 };
1548 //static const uint8_t signature_algorithms[] = {
1549 // 000d
1550 // 0020
1551 // 001e
1552 // 0601 0602 0603 0501 0502 0503 0401 0402 0403 0301 0302 0303 0201 0202 0203
1553 //};
1554
1555 struct client_hello { 1569 struct client_hello {
1556 uint8_t type; 1570 uint8_t type;
1557 uint8_t len24_hi, len24_mid, len24_lo; 1571 uint8_t len24_hi, len24_mid, len24_lo;
@@ -1563,15 +1577,47 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1563 uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ 1577 uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */
1564 uint8_t comprtypes_len; 1578 uint8_t comprtypes_len;
1565 uint8_t comprtypes[1]; /* actually variable */ 1579 uint8_t comprtypes[1]; /* actually variable */
1566 /* Extensions (SNI shown): 1580 };
1567 * hi,lo // len of all extensions 1581 // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
1568 * 00,00 // extension_type: "Server Name" 1582 static const uint8_t extensions[] = {
1569 * 00,0e // list len (there can be more than one SNI) 1583 // is.gd responds with "handshake failure" to our hello if there's no supported_groups
1570 * 00,0c // len of 1st Server Name Indication 1584 0x00,0x0a, //extension_type: "supported_groups"
1571 * 00 // name type: host_name 1585 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len
1572 * 00,09 // name len 1586 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len
1573 * "localhost" // name 1587#if ALLOW_CURVE_P256
1574 */ 1588 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1)
1589#endif
1590 //0x00,0x18, //curve_secp384r1
1591 //0x00,0x19, //curve_secp521r1
1592#if ALLOW_CURVE_X25519
1593 0x00,0x1d, //curve_x25519 (RFC 7748)
1594#endif
1595 //0x00,0x1e, //curve_x448 (RFC 7748)
1596
1597 //0x00,0x0b,0x00,0x04,0x03,0x00,0x01,0x02, //extension_type: "ec_point_formats"
1598 //0x00,0x16,0x00,0x00, //extension_type: "encrpypt-then-mac"
1599 //0x00,0x17,0x00,0x00, //extension_type: "extended_master"
1600 //0x00,0x23,0x00,0x00, //extension_type: "session_ticket"
1601
1602 // kojipkgs.fedoraproject.org responds with alert code 80 ("internal error")
1603 // to our hello without signature_algorithms.
1604 // It is satisfied with just 0x04,0x01.
1605 0x00,0x0d, //extension_type: "signature_algorithms" (RFC5246 section 7.4.1.4.1):
1606#define SIGALGS (3 + 3 * ENABLE_FEATURE_TLS_SHA1)
1607 0x00,2 * (1 + SIGALGS), //ext len
1608 0x00,2 * (0 + SIGALGS), //list len
1609 //Format: two bytes
1610 // byte 1: 0:none,1:md5,2:sha1,3:sha224,4:sha256,5:sha384,6:sha512
1611 // byte 2: 1:rsa,2:dsa,3:ecdsa
1612 // (note that TLS 1.3 changes this, see RFC8446 section 4.2.3)
1613#if ENABLE_FEATURE_TLS_SHA1
1614 0x02,0x01, //sha1 + rsa
1615 0x02,0x02, //sha1 + dsa
1616 0x02,0x03, //sha1 + ecdsa
1617#endif
1618 0x04,0x01, //sha256 + rsa - kojipkgs.fedoraproject.org wants this
1619 0x04,0x02, //sha256 + dsa
1620 0x04,0x03, //sha256 + ecdsa
1575// GNU Wget 1.18 to cdn.kernel.org sends these extensions: 1621// GNU Wget 1.18 to cdn.kernel.org sends these extensions:
1576// 0055 1622// 0055
1577// 0005 0005 0100000000 - status_request 1623// 0005 0005 0100000000 - status_request
@@ -1591,8 +1637,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1591 int sni_len = sni ? strnlen(sni, 127 - 5) : 0; 1637 int sni_len = sni ? strnlen(sni, 127 - 5) : 0;
1592 1638
1593 ext_len = 0; 1639 ext_len = 0;
1594 /* is.gd responds with "handshake failure" to our hello if there's no supported_groups element */ 1640 ext_len += sizeof(extensions);
1595 ext_len += sizeof(supported_groups);
1596 if (sni_len) 1641 if (sni_len)
1597 ext_len += 9 + sni_len; 1642 ext_len += 9 + sni_len;
1598 1643
@@ -1626,7 +1671,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1626 ptr[8] = sni_len; //name len 1671 ptr[8] = sni_len; //name len
1627 ptr = mempcpy(&ptr[9], sni, sni_len); 1672 ptr = mempcpy(&ptr[9], sni, sni_len);
1628 } 1673 }
1629 memcpy(ptr, supported_groups, sizeof(supported_groups)); 1674 memcpy(ptr, extensions, sizeof(extensions));
1630 1675
1631 tls->hsd = xzalloc(sizeof(*tls->hsd)); 1676 tls->hsd = xzalloc(sizeof(*tls->hsd));
1632 /* HANDSHAKE HASH: ^^^ + len if need to save saved_client_hello */ 1677 /* HANDSHAKE HASH: ^^^ + len if need to save saved_client_hello */
diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c
index 292dda24e..a593c5c40 100644
--- a/networking/tls_sp_c32.c
+++ b/networking/tls_sp_c32.c
@@ -68,9 +68,6 @@ static const sp_digit p256_mod[8] ALIGNED(8) = {
68 68
69#define p256_mp_mod ((sp_digit)0x000001) 69#define p256_mp_mod ((sp_digit)0x000001)
70 70
71/* Normalize the values in each word to 32 bits - NOP */
72#define sp_256_norm_8(a) ((void)0)
73
74/* Write r as big endian to byte array. 71/* Write r as big endian to byte array.
75 * Fixed length number of bytes written: 32 72 * Fixed length number of bytes written: 32
76 * 73 *
@@ -83,8 +80,6 @@ static void sp_256_to_bin_8(const sp_digit* rr, uint8_t* a)
83 int i; 80 int i;
84 const uint64_t* r = (void*)rr; 81 const uint64_t* r = (void*)rr;
85 82
86 sp_256_norm_8(rr);
87
88 r += 4; 83 r += 4;
89 for (i = 0; i < 4; i++) { 84 for (i = 0; i < 4; i++) {
90 r--; 85 r--;
@@ -97,8 +92,6 @@ static void sp_256_to_bin_8(const sp_digit* r, uint8_t* a)
97{ 92{
98 int i; 93 int i;
99 94
100 sp_256_norm_8(r);
101
102 r += 8; 95 r += 8;
103 for (i = 0; i < 8; i++) { 96 for (i = 0; i < 8; i++) {
104 r--; 97 r--;
@@ -641,7 +634,6 @@ static void sp_256_div2_8(sp_digit* r /*, const sp_digit* m*/)
641 int carry = 0; 634 int carry = 0;
642 if (r[0] & 1) 635 if (r[0] & 1)
643 carry = sp_256_add_8(r, r, m); 636 carry = sp_256_add_8(r, r, m);
644 sp_256_norm_8(r);
645 sp_256_rshift1_8(r, carry); 637 sp_256_rshift1_8(r, carry);
646} 638}
647 639
@@ -652,10 +644,8 @@ static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b
652// const sp_digit* m = p256_mod; 644// const sp_digit* m = p256_mod;
653 645
654 int carry = sp_256_add_8(r, a, b); 646 int carry = sp_256_add_8(r, a, b);
655 sp_256_norm_8(r);
656 if (carry) { 647 if (carry) {
657 sp_256_sub_8_p256_mod(r); 648 sp_256_sub_8_p256_mod(r);
658 sp_256_norm_8(r);
659 } 649 }
660} 650}
661 651
@@ -667,10 +657,8 @@ static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b
667 657
668 int borrow; 658 int borrow;
669 borrow = sp_256_sub_8(r, a, b); 659 borrow = sp_256_sub_8(r, a, b);
670 sp_256_norm_8(r);
671 if (borrow) { 660 if (borrow) {
672 sp_256_add_8(r, r, m); 661 sp_256_add_8(r, r, m);
673 sp_256_norm_8(r);
674 } 662 }
675} 663}
676 664
@@ -680,10 +668,8 @@ static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a /*, const sp_digit*
680// const sp_digit* m = p256_mod; 668// const sp_digit* m = p256_mod;
681 669
682 int carry = sp_256_add_8(r, a, a); 670 int carry = sp_256_add_8(r, a, a);
683 sp_256_norm_8(r);
684 if (carry) 671 if (carry)
685 sp_256_sub_8_p256_mod(r); 672 sp_256_sub_8_p256_mod(r);
686 sp_256_norm_8(r);
687} 673}
688 674
689/* Triple a Montgomery form number (r = a + a + a % m) */ 675/* Triple a Montgomery form number (r = a + a + a % m) */
@@ -692,16 +678,12 @@ static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a /*, const sp_digit*
692// const sp_digit* m = p256_mod; 678// const sp_digit* m = p256_mod;
693 679
694 int carry = sp_256_add_8(r, a, a); 680 int carry = sp_256_add_8(r, a, a);
695 sp_256_norm_8(r);
696 if (carry) { 681 if (carry) {
697 sp_256_sub_8_p256_mod(r); 682 sp_256_sub_8_p256_mod(r);
698 sp_256_norm_8(r);
699 } 683 }
700 carry = sp_256_add_8(r, r, a); 684 carry = sp_256_add_8(r, r, a);
701 sp_256_norm_8(r);
702 if (carry) { 685 if (carry) {
703 sp_256_sub_8_p256_mod(r); 686 sp_256_sub_8_p256_mod(r);
704 sp_256_norm_8(r);
705 } 687 }
706} 688}
707 689
@@ -844,7 +826,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* aa/*, const sp_digi
844 sp_512to256_mont_shift_8(r, aa); 826 sp_512to256_mont_shift_8(r, aa);
845 if (carry != 0) 827 if (carry != 0)
846 sp_256_sub_8_p256_mod(r); 828 sp_256_sub_8_p256_mod(r);
847 sp_256_norm_8(r);
848} 829}
849 830
850#else /* Generic 32-bit version */ 831#else /* Generic 32-bit version */
@@ -1003,8 +984,6 @@ static int sp_256_mul_add_8(sp_digit* r /*, const sp_digit* a, sp_digit b*/)
1003 * [In our case, it is (p256_mp_mod * a[1]) << 32.] 984 * [In our case, it is (p256_mp_mod * a[1]) << 32.]
1004 * And so on. Eventually T is divisible by R, and after division by R 985 * And so on. Eventually T is divisible by R, and after division by R
1005 * the algorithm is in the same place as the usual Montgomery reduction. 986 * the algorithm is in the same place as the usual Montgomery reduction.
1006 *
1007 * TODO: Can conditionally use 64-bit (if bit-little-endian arch) logic?
1008 */ 987 */
1009static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit* m, sp_digit mp*/) 988static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit* m, sp_digit mp*/)
1010{ 989{
@@ -1032,7 +1011,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit
1032 sp_512to256_mont_shift_8(r, a); 1011 sp_512to256_mont_shift_8(r, a);
1033 if (word16th != 0) 1012 if (word16th != 0)
1034 sp_256_sub_8_p256_mod(r); 1013 sp_256_sub_8_p256_mod(r);
1035 sp_256_norm_8(r);
1036 } 1014 }
1037 else { /* Same code for explicit mp == 1 (which is always the case for P256) */ 1015 else { /* Same code for explicit mp == 1 (which is always the case for P256) */
1038 sp_digit word16th = 0; 1016 sp_digit word16th = 0;
@@ -1052,7 +1030,6 @@ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit
1052 sp_512to256_mont_shift_8(r, a); 1030 sp_512to256_mont_shift_8(r, a);
1053 if (word16th != 0) 1031 if (word16th != 0)
1054 sp_256_sub_8_p256_mod(r); 1032 sp_256_sub_8_p256_mod(r);
1055 sp_256_norm_8(r);
1056 } 1033 }
1057} 1034}
1058#endif 1035#endif
@@ -1208,14 +1185,12 @@ static void sp_256_map_8(sp_point* r, sp_point* p)
1208 /* Reduce x to less than modulus */ 1185 /* Reduce x to less than modulus */
1209 if (sp_256_cmp_8(r->x, p256_mod) >= 0) 1186 if (sp_256_cmp_8(r->x, p256_mod) >= 0)
1210 sp_256_sub_8_p256_mod(r->x); 1187 sp_256_sub_8_p256_mod(r->x);
1211 sp_256_norm_8(r->x);
1212 1188
1213 /* y /= z^3 */ 1189 /* y /= z^3 */
1214 sp_256_mont_mul_and_reduce_8(r->y, p->y, t1 /*, p256_mod, p256_mp_mod*/); 1190 sp_256_mont_mul_and_reduce_8(r->y, p->y, t1 /*, p256_mod, p256_mp_mod*/);
1215 /* Reduce y to less than modulus */ 1191 /* Reduce y to less than modulus */
1216 if (sp_256_cmp_8(r->y, p256_mod) >= 0) 1192 if (sp_256_cmp_8(r->y, p256_mod) >= 0)
1217 sp_256_sub_8_p256_mod(r->y); 1193 sp_256_sub_8_p256_mod(r->y);
1218 sp_256_norm_8(r->y);
1219 1194
1220 memset(r->z, 0, sizeof(r->z)); 1195 memset(r->z, 0, sizeof(r->z));
1221 r->z[0] = 1; 1196 r->z[0] = 1;
@@ -1300,7 +1275,6 @@ static NOINLINE void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point*
1300 1275
1301 /* Check double */ 1276 /* Check double */
1302 sp_256_sub_8(t1, p256_mod, q->y); 1277 sp_256_sub_8(t1, p256_mod, q->y);
1303 sp_256_norm_8(t1);
1304 if (sp_256_cmp_equal_8(p->x, q->x) 1278 if (sp_256_cmp_equal_8(p->x, q->x)
1305 && sp_256_cmp_equal_8(p->z, q->z) 1279 && sp_256_cmp_equal_8(p->z, q->z)
1306 && (sp_256_cmp_equal_8(p->y, q->y) || sp_256_cmp_equal_8(p->y, t1)) 1280 && (sp_256_cmp_equal_8(p->y, q->y) || sp_256_cmp_equal_8(p->y, t1))
@@ -1422,14 +1396,15 @@ static void sp_256_ecc_mulmod_8(sp_point* r, const sp_point* g, const sp_digit*
1422static void sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k /*, int map*/) 1396static void sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k /*, int map*/)
1423{ 1397{
1424 /* Since this function is called only once, save space: 1398 /* Since this function is called only once, save space:
1425 * don't have "static const sp_point p256_base = {...}", 1399 * don't have "static const sp_point p256_base = {...}".
1426 * it would have more zeros than data.
1427 */ 1400 */
1428 static const uint8_t p256_base_bin[] = { 1401 static const uint8_t p256_base_bin[] = {
1429 /* x (big-endian) */ 1402 /* x (big-endian) */
1430 0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2,0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96, 1403 0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2,
1404 0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96,
1431 /* y */ 1405 /* y */
1432 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16,0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5, 1406 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16,
1407 0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5,
1433 /* z will be set to 1, infinity flag to "false" */ 1408 /* z will be set to 1, infinity flag to "false" */
1434 }; 1409 };
1435 sp_point p256_base; 1410 sp_point p256_base;
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 9fc690315..c7f130a70 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -295,6 +295,7 @@ static void option_to_env(const uint8_t *option, const uint8_t *option_end)
295 *new_env() = xasprintf("ipv6=%s", ipv6str); 295 *new_env() = xasprintf("ipv6=%s", ipv6str);
296 296
297 move_from_unaligned32(v32, option + 4 + 16 + 4); 297 move_from_unaligned32(v32, option + 4 + 16 + 4);
298 v32 = ntohl(v32);
298 *new_env() = xasprintf("lease=%u", (unsigned)v32); 299 *new_env() = xasprintf("lease=%u", (unsigned)v32);
299 break; 300 break;
300 301
@@ -332,6 +333,7 @@ static void option_to_env(const uint8_t *option, const uint8_t *option_end)
332 * +-+-+-+-+-+-+-+-+ 333 * +-+-+-+-+-+-+-+-+
333 */ 334 */
334 move_from_unaligned32(v32, option + 4 + 4); 335 move_from_unaligned32(v32, option + 4 + 4);
336 v32 = ntohl(v32);
335 *new_env() = xasprintf("ipv6prefix_lease=%u", (unsigned)v32); 337 *new_env() = xasprintf("ipv6prefix_lease=%u", (unsigned)v32);
336 338
337 sprint_nip6(ipv6str, option + 4 + 4 + 4 + 1); 339 sprint_nip6(ipv6str, option + 4 + 4 + 4 + 1);
@@ -842,7 +844,7 @@ static NOINLINE int send_d6_renew(struct in6_addr *server_ipv6, struct in6_addr
842 uint8_t *opt_ptr; 844 uint8_t *opt_ptr;
843 845
844 /* Fill in: msg type, xid, ELAPSED_TIME */ 846 /* Fill in: msg type, xid, ELAPSED_TIME */
845 opt_ptr = init_d6_packet(&packet, DHCPREQUEST); 847 opt_ptr = init_d6_packet(&packet, D6_MSG_RENEW);
846 848
847 /* server id */ 849 /* server id */
848 opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); 850 opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2);
@@ -1081,7 +1083,7 @@ static void change_listen_mode(int new_mode)
1081 client_data.sockfd = -1; 1083 client_data.sockfd = -1;
1082 } 1084 }
1083 if (new_mode == LISTEN_KERNEL) 1085 if (new_mode == LISTEN_KERNEL)
1084 client_data.sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_data.interface); 1086 client_data.sockfd = d6_listen_socket(CLIENT_PORT6, client_data.interface);
1085 else if (new_mode != LISTEN_NONE) 1087 else if (new_mode != LISTEN_NONE)
1086 client_data.sockfd = d6_raw_socket(client_data.ifindex); 1088 client_data.sockfd = d6_raw_socket(client_data.ifindex);
1087 /* else LISTEN_NONE: client_data.sockfd stays closed */ 1089 /* else LISTEN_NONE: client_data.sockfd stays closed */
@@ -1487,6 +1489,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1487 if (opt & OPT_l) 1489 if (opt & OPT_l)
1488 send_d6_info_request(); 1490 send_d6_info_request();
1489 else /* send a broadcast renew request */ 1491 else /* send a broadcast renew request */
1492//TODO: send_d6_renew uses D6_MSG_RENEW message, should we use D6_MSG_REBIND here instead?
1490 send_d6_renew(/*server_ipv6:*/ NULL, requested_ipv6); 1493 send_d6_renew(/*server_ipv6:*/ NULL, requested_ipv6);
1491 timeout = discover_timeout; 1494 timeout = discover_timeout;
1492 packet_num++; 1495 packet_num++;
diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c
index 8ddee5a8e..21cf61c6e 100644
--- a/networking/udhcp/d6_socket.c
+++ b/networking/udhcp/d6_socket.c
@@ -110,7 +110,7 @@ int FAST_FUNC d6_listen_socket(int port, const char *inf)
110 int fd; 110 int fd;
111 struct sockaddr_in6 addr; 111 struct sockaddr_in6 addr;
112 112
113 log1("opening listen socket on *:%d %s", port, inf); 113 log2("opening listen socket on *:%d %s", port, inf);
114 fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 114 fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
115 115
116 setsockopt_reuseaddr(fd); 116 setsockopt_reuseaddr(fd);
diff --git a/procps/nmeter.c b/procps/nmeter.c
index 088d366bf..68e6f3325 100644
--- a/procps/nmeter.c
+++ b/procps/nmeter.c
@@ -515,7 +515,7 @@ static void FAST_FUNC collect_blk(blk_stat *s)
515 return; 515 return;
516 } 516 }
517 517
518 for (i=0; i<2; i++) { 518 for (i = 0; i < 2; i++) {
519 ullong old = s->old[i]; 519 ullong old = s->old[i];
520 if (data[i] < old) old = data[i]; //sanitize 520 if (data[i] < old) old = data[i]; //sanitize
521 s->old[i] = data[i]; 521 s->old[i] = data[i];
@@ -597,7 +597,7 @@ static void FAST_FUNC collect_if(if_stat *s)
597 return; 597 return;
598 } 598 }
599 599
600 for (i=0; i<4; i++) { 600 for (i = 0; i < 4; i++) {
601 ullong old = s->old[i]; 601 ullong old = s->old[i];
602 if (data[i] < old) old = data[i]; //sanitize 602 if (data[i] < old) old = data[i]; //sanitize
603 s->old[i] = data[i]; 603 s->old[i] = data[i];
diff --git a/shell/ash.c b/shell/ash.c
index 28c7fe2db..8497538b1 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -149,6 +149,11 @@
149//config: default y 149//config: default y
150//config: depends on SHELL_ASH 150//config: depends on SHELL_ASH
151//config: 151//config:
152//config:config ASH_SLEEP
153//config: bool "sleep builtin"
154//config: default y
155//config: depends on SHELL_ASH
156//config:
152//config:config ASH_HELP 157//config:config ASH_HELP
153//config: bool "help builtin" 158//config: bool "help builtin"
154//config: default y 159//config: default y
@@ -7702,6 +7707,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags)
7702 msg = umsg; 7707 msg = umsg;
7703 } 7708 }
7704 } 7709 }
7710 ifsfree();
7705 ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail); 7711 ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
7706} 7712}
7707 7713
@@ -7997,13 +8003,15 @@ subevalvar(char *start, char *str, int strloc,
7997 if (idx >= end) 8003 if (idx >= end)
7998 break; 8004 break;
7999 STPUTC(*idx, expdest); 8005 STPUTC(*idx, expdest);
8006 if (stackblock() != restart_detect)
8007 goto restart;
8000 if (quotes && (unsigned char)*idx == CTLESC) { 8008 if (quotes && (unsigned char)*idx == CTLESC) {
8001 idx++; 8009 idx++;
8002 len++; 8010 len++;
8003 STPUTC(*idx, expdest); 8011 STPUTC(*idx, expdest);
8012 if (stackblock() != restart_detect)
8013 goto restart;
8004 } 8014 }
8005 if (stackblock() != restart_detect)
8006 goto restart;
8007 idx++; 8015 idx++;
8008 len++; 8016 len++;
8009 rmesc++; 8017 rmesc++;
@@ -8028,6 +8036,13 @@ subevalvar(char *start, char *str, int strloc,
8028 idx = loc; 8036 idx = loc;
8029 } 8037 }
8030 8038
8039 /* The STPUTC invocations above may resize and move the
8040 * stack via realloc(3). Since repl is a pointer into the
8041 * stack, we need to reconstruct it relative to stackblock().
8042 */
8043 if (slash_pos >= 0)
8044 repl = (char *)stackblock() + strloc + slash_pos + 1;
8045
8031 //bb_error_msg("repl:'%s'", repl); 8046 //bb_error_msg("repl:'%s'", repl);
8032 for (loc = (char*)repl; *loc; loc++) { 8047 for (loc = (char*)repl; *loc; loc++) {
8033 char *restart_detect = stackblock(); 8048 char *restart_detect = stackblock();
@@ -8127,6 +8142,7 @@ varvalue(char *name, int varflags, int flags, int quoted)
8127 if (discard) 8142 if (discard)
8128 return -1; 8143 return -1;
8129 8144
8145 ifsfree();
8130 raise_error_syntax("bad substitution"); 8146 raise_error_syntax("bad substitution");
8131 } 8147 }
8132 8148
@@ -11039,6 +11055,9 @@ static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc,
11039#if ENABLE_ASH_TEST || BASH_TEST2 11055#if ENABLE_ASH_TEST || BASH_TEST2
11040static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } 11056static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); }
11041#endif 11057#endif
11058#if ENABLE_ASH_SLEEP
11059static int FAST_FUNC sleepcmd(int argc, char **argv) { return sleep_main(argc, argv); }
11060#endif
11042 11061
11043/* Keep these in proper order since it is searched via bsearch() */ 11062/* Keep these in proper order since it is searched via bsearch() */
11044static const struct builtincmd builtintab[] = { 11063static const struct builtincmd builtintab[] = {
@@ -11101,6 +11120,9 @@ static const struct builtincmd builtintab[] = {
11101 { BUILTIN_SPEC_REG "return" , returncmd }, 11120 { BUILTIN_SPEC_REG "return" , returncmd },
11102 { BUILTIN_SPEC_REG "set" , setcmd }, 11121 { BUILTIN_SPEC_REG "set" , setcmd },
11103 { BUILTIN_SPEC_REG "shift" , shiftcmd }, 11122 { BUILTIN_SPEC_REG "shift" , shiftcmd },
11123#if ENABLE_ASH_SLEEP
11124 { BUILTIN_REGULAR "sleep" , sleepcmd },
11125#endif
11104#if BASH_SOURCE 11126#if BASH_SOURCE
11105 { BUILTIN_SPEC_REG "source" , dotcmd }, 11127 { BUILTIN_SPEC_REG "source" , dotcmd },
11106#endif 11128#endif
diff --git a/shell/ash_test/ash-heredoc/heredoc_and_cmd.right b/shell/ash_test/ash-heredoc/heredoc_and_cmd.right
new file mode 100644
index 000000000..25ae70561
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc_and_cmd.right
@@ -0,0 +1,2 @@
1./heredoc_and_cmd.tests: line 4: D: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
2Y
diff --git a/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests b/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests
new file mode 100755
index 000000000..197542de7
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests
@@ -0,0 +1,8 @@
1# The bug was only happening with <<REDIR;CMD form below:
2M='AAAAAAAAAAAAAAAAA'
3fff(){
4date <<000; echo Y
5${D?$M$M$M$M$M$M}
6000
7}
8fff
diff --git a/shell/hush_test/hush-heredoc/heredoc_and_cmd.right b/shell/hush_test/hush-heredoc/heredoc_and_cmd.right
new file mode 100644
index 000000000..5c19a0621
--- /dev/null
+++ b/shell/hush_test/hush-heredoc/heredoc_and_cmd.right
@@ -0,0 +1,2 @@
1hush: D: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
2Y
diff --git a/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests b/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests
new file mode 100755
index 000000000..197542de7
--- /dev/null
+++ b/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests
@@ -0,0 +1,8 @@
1# The bug was only happening with <<REDIR;CMD form below:
2M='AAAAAAAAAAAAAAAAA'
3fff(){
4date <<000; echo Y
5${D?$M$M$M$M$M$M}
6000
7}
8fff
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index 93e25d8c1..bbf0fbff1 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -479,4 +479,10 @@ testing 'awk backslash+newline eaten with no trace' \
479 "Hello world\n" \ 479 "Hello world\n" \
480 '' '' 480 '' ''
481 481
482testing 'awk assign while test' \
483 "awk '\$1==\$1=\"foo\" {print \$1}'" \
484 "foo\n" \
485 "" \
486 "foo"
487
482exit $FAILCOUNT 488exit $FAILCOUNT
diff --git a/testsuite/sha1sum.tests b/testsuite/sha1sum.tests
index a968fa87c..7ad1334c3 100755
--- a/testsuite/sha1sum.tests
+++ b/testsuite/sha1sum.tests
@@ -1,3 +1,13 @@
1#!/bin/sh 1#!/bin/sh
2 2
3. ./testing.sh
4
5# testing "test name" "cmd" "expected result" "file input" "stdin"
6>EMPTY
7testing "sha1sum: one-space separated input for -c" \
8 'echo "da39a3ee5e6b4b0d3255bfef95601890afd80709 EMPTY" | sha1sum -c' \
9 "EMPTY: OK\n" \
10 "" ""
11rm EMPTY
12
3. ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f 13. ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f
diff --git a/testsuite/sort.tests b/testsuite/sort.tests
index ff33e21b4..8dbadbdae 100755
--- a/testsuite/sort.tests
+++ b/testsuite/sort.tests
@@ -219,4 +219,25 @@ testing "sort -h" \
219 219
220# testing "description" "command(s)" "result" "infile" "stdin" 220# testing "description" "command(s)" "result" "infile" "stdin"
221 221
222testing "sort -k2,2M" \
223"sort -k2,2M input" "\
2243 March
2252 April
2261 May
227" "\
2282 April
2291 May
2303 March
231" ""
232
233testing "sort -s -u" \
234"sort -s -u -k 2 input" "\
235z a
236z b
237" "\
238z b
239a b
240z a
241a a" ""
242
222exit $FAILCOUNT 243exit $FAILCOUNT
diff --git a/testsuite/tree.tests b/testsuite/tree.tests
new file mode 100755
index 000000000..4f4a9e30b
--- /dev/null
+++ b/testsuite/tree.tests
@@ -0,0 +1,100 @@
1#!/bin/sh
2
3# Copyright 2022 by Roger Knecht <rknecht@pm.me>
4# Licensed under GPLv2, see file LICENSE in this source tree.
5
6. ./testing.sh -v
7
8# testing "description" "command" "result" "infile" "stdin"
9
10testing "tree error opening dir" \
11 "tree tree.tempdir" \
12 "\
13tree.tempdir [error opening dir]\n\
14\n\
150 directories, 0 files\n" \
16 "" ""
17
18mkdir -p tree2.tempdir
19touch tree2.tempdir/testfile
20
21testing "tree single file" \
22 "cd tree2.tempdir && tree" \
23 "\
24.\n\
25└── testfile\n\
26\n\
270 directories, 1 files\n" \
28 "" ""
29
30mkdir -p tree3.tempdir/test1 \
31 tree3.tempdir/test2/a \
32 tree3.tempdir/test2/b \
33 tree3.tempdir/test3/c \
34 tree3.tempdir/test3/d
35
36touch tree3.tempdir/test2/a/testfile1 \
37 tree3.tempdir/test2/a/testfile2 \
38 tree3.tempdir/test2/a/testfile3 \
39 tree3.tempdir/test2/b/testfile4 \
40 tree3.tempdir/test3/c/testfile5 \
41 tree3.tempdir/test3/d/testfile6 \
42 tree3.tempdir/test3/d/.testfile7
43
44(cd tree3.tempdir/test2/a && ln -s ../b/testfile4 .)
45(cd tree3.tempdir/test2/b && ln -s ../../test3 .)
46
47testing "tree nested directories and files" \
48 "cd tree3.tempdir && tree" \
49 "\
50.\n\
51├── test1\n\
52├── test2\n\
53│   ├── a\n\
54│   │   ├── testfile1\n\
55│   │   ├── testfile2\n\
56│   │   ├── testfile3\n\
57│   │   └── testfile4 -> ../b/testfile4\n\
58│   └── b\n\
59│   ├── test3 -> ../../test3\n\
60│   └── testfile4\n\
61└── test3\n\
62 ├── c\n\
63 │   └── testfile5\n\
64 └── d\n\
65 └── testfile6\n\
66\n\
677 directories, 8 files\n" \
68 "" ""
69#note: tree v2.0.1 says "8 directories, 7 files":
70#it counts "test3 -> ../../test3" as a directory, even though it does not follow this symlink
71
72testing "tree multiple directories" \
73 "tree tree2.tempdir tree3.tempdir" \
74 "\
75tree2.tempdir\n\
76└── testfile\n\
77tree3.tempdir\n\
78├── test1\n\
79├── test2\n\
80│   ├── a\n\
81│   │   ├── testfile1\n\
82│   │   ├── testfile2\n\
83│   │   ├── testfile3\n\
84│   │   └── testfile4 -> ../b/testfile4\n\
85│   └── b\n\
86│   ├── test3 -> ../../test3\n\
87│   └── testfile4\n\
88└── test3\n\
89 ├── c\n\
90 │   └── testfile5\n\
91 └── d\n\
92 └── testfile6\n\
93\n\
947 directories, 9 files\n" \
95 "" ""
96#note: tree v2.0.1 says "8 directories, 7 files" (not "8 files", probably a/testfile4 -> ../b/testfile4 and b/testfile4 are counted as one file, not 2?)
97
98rm -rf tree.tempdir tree2.tempdir tree3.tempdir
99
100exit $FAILCOUNT
diff --git a/testsuite/xxd.tests b/testsuite/xxd.tests
index 76fa96af9..2c740abc8 100755
--- a/testsuite/xxd.tests
+++ b/testsuite/xxd.tests
@@ -37,4 +37,27 @@ testing 'xxd -p -r' \
37 '' \ 37 '' \
38 '30313233343536373736353433323130 30313233343536373736353433323130' 38 '30313233343536373736353433323130 30313233343536373736353433323130'
39 39
40testing 'xxd -r skips leading whitespace and truncates at two spaces' \
41 'xxd -r' \
42 '0123456789:;<=>?@' \
43 '' "\
44 00000000: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>?
45 00000010: 40 @
46"
47
48testing 'xxd -p -r skips one bad char, truncates at two bad chars' \
49 'xxd -p -r' \
50 '01' \
51 '' "\
5230 !31 !!32
53"
54
55testing 'xxd -p -r ignores the nibble with 2nd char bad' \
56 'xxd -p -r' \
57 '3C6' \
58 '' "\
5933 3!4 3!!5
6036
61"
62
40exit $FAILCOUNT 63exit $FAILCOUNT
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c
index 4372ac770..6629407de 100644
--- a/util-linux/hexdump_xxd.c
+++ b/util-linux/hexdump_xxd.c
@@ -55,6 +55,7 @@
55//usage: "\n -r Reverse (with -p, assumes no offsets in input)" 55//usage: "\n -r Reverse (with -p, assumes no offsets in input)"
56 56
57#include "libbb.h" 57#include "libbb.h"
58#include "common_bufsiz.h"
58#include "dump.h" 59#include "dump.h"
59 60
60/* This is a NOEXEC applet. Be very careful! */ 61/* This is a NOEXEC applet. Be very careful! */
@@ -69,61 +70,110 @@
69#define OPT_c (1 << 7) 70#define OPT_c (1 << 7)
70#define OPT_o (1 << 8) 71#define OPT_o (1 << 8)
71 72
72static void reverse(unsigned opt, const char *filename) 73#define fillbuf bb_common_bufsiz1
74
75static void write_zeros(off_t count)
76{
77 errno = 0;
78 do {
79 unsigned sz = count < COMMON_BUFSIZE ? (unsigned)count : COMMON_BUFSIZE;
80 if (fwrite(fillbuf, 1, sz, stdout) != sz)
81 bb_perror_msg_and_die("write error");
82 count -= sz;
83 } while (count != 0);
84}
85
86static void reverse(unsigned opt, const char *filename, char *opt_s)
73{ 87{
74 FILE *fp; 88 FILE *fp;
75 char *buf; 89 char *buf;
90 off_t cur, opt_s_ofs;
91
92 memset(fillbuf, 0, COMMON_BUFSIZE);
93 opt_s_ofs = cur = 0;
94 if (opt_s) {
95 opt_s_ofs = BB_STRTOOFF(opt_s, NULL, 0);
96 if (errno || opt_s_ofs < 0)
97 bb_error_msg_and_die("invalid number '%s'", opt_s);
98 }
76 99
77 fp = filename ? xfopen_for_read(filename) : stdin; 100 fp = filename ? xfopen_for_read(filename) : stdin;
78 101
102 get_new_line:
79 while ((buf = xmalloc_fgetline(fp)) != NULL) { 103 while ((buf = xmalloc_fgetline(fp)) != NULL) {
80 char *p; 104 char *p;
81 105
82 p = buf; 106 p = buf;
83 if (!(opt & OPT_p)) { 107 if (!(opt & OPT_p)) {
84 /* skip address */ 108 char *end;
85 while (isxdigit(*p)) p++; 109 off_t ofs;
110 skip_address:
111 p = skip_whitespace(p);
112 ofs = BB_STRTOOFF(p, &end, 16);
113 if ((errno && errno != EINVAL)
114 || ofs < 0
115 /* -s SEEK value should be added before seeking */
116 || (ofs += opt_s_ofs) < 0
117 ) {
118 bb_error_msg_and_die("invalid number '%s'", p);
119 }
120 if (ofs != cur) {
121 if (fseeko(stdout, ofs, SEEK_SET) != 0) {
122 if (ofs < cur)
123 bb_perror_msg_and_die("cannot seek");
124 write_zeros(ofs - cur);
125 }
126 cur = ofs;
127 }
128 p = end;
86 /* NB: for xxd -r, first hex portion is address even without colon */ 129 /* NB: for xxd -r, first hex portion is address even without colon */
87 /* If it's there, skip it: */ 130 /* But if colon is there, skip it: */
88 if (*p == ':') p++; 131 if (*p == ':')
89 132 p++;
90//TODO: seek (or zero-pad if unseekable) to the address position
91//NOTE: -s SEEK value should be added to the address before seeking
92 } 133 }
93 134
94 /* Process hex bytes optionally separated by whitespace */ 135 /* Process hex bytes optionally separated by whitespace */
95 for (;;) { 136 for (;;) {
96 uint8_t val, c; 137 uint8_t val, c;
138 int badchar = 0;
97 nibble1: 139 nibble1:
98 p = skip_whitespace(p); 140 if (opt & OPT_p)
99 141 p = skip_whitespace(p);
100 c = *p++; 142 c = *p++;
101 if (isdigit(c)) 143 if (isdigit(c))
102 val = c - '0'; 144 val = c - '0';
103 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') 145 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
104 val = (c|0x20) - ('a' - 10); 146 val = (c|0x20) - ('a' - 10);
105 else { 147 else {
106 /* xxd V1.10 is inconsistent here. 148 /* xxd V1.10 allows one non-hexnum char:
107 * echo -e "31 !3 0a 0a" | xxd -r -p 149 * echo -e "31 !3 0a 0a" | xxd -r -p
108 * is "10<a0>" (no <cr>) - "!" is ignored, 150 * is "10<a0>" (no <cr>) - "!" is ignored,
109 * but 151 * but stops for more than one:
110 * echo -e "31 !!343434\n30 0a" | xxd -r -p 152 * echo -e "31 !!343434\n30 0a" | xxd -r -p
111 * is "10<cr>" - "!!" drops rest of the line. 153 * is "10<cr>" - "!!" drops rest of the line.
112 * We will ignore all invalid chars: 154 * Note: this also covers whitespace chars:
155 * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>?
156 * detects this ^ - skips this one space
157 * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>?
158 * detects this ^^ - skips the rest
113 */ 159 */
114 if (c != '\0') 160 if (c == '\0' || badchar)
115 goto nibble1; 161 break;
116 break; 162 badchar++;
163 goto nibble1;
117 } 164 }
118 val <<= 4; 165 val <<= 4;
119 166
120 /* Works the same with xxd V1.10:
121 * echo "31 09 32 0a" | xxd -r -p
122 * echo "31 0 9 32 0a" | xxd -r -p
123 * thus allow whitespace even within the byte:
124 */
125 nibble2: 167 nibble2:
126 p = skip_whitespace(p); 168 if (opt & OPT_p) {
169 /* Works the same with xxd V1.10:
170 * echo "31 09 32 0a" | xxd -r -p
171 * echo "31 0 9 32 0a" | xxd -r -p
172 * thus allow whitespace (even multiple chars)
173 * after byte's 1st char:
174 */
175 p = skip_whitespace(p);
176 }
127 177
128 c = *p++; 178 c = *p++;
129 if (isdigit(c)) 179 if (isdigit(c))
@@ -132,7 +182,16 @@ static void reverse(unsigned opt, const char *filename)
132 val |= (c|0x20) - ('a' - 10); 182 val |= (c|0x20) - ('a' - 10);
133 else { 183 else {
134 if (c != '\0') { 184 if (c != '\0') {
135 /* "...3<not_hex_char>..." ignores both chars */ 185 /* "...3<not_hex_char>...": ignore "3",
186 * skip everything up to next hexchar or newline:
187 */
188 while (!isxdigit(*p)) {
189 if (*p == '\0') {
190 free(buf);
191 goto get_new_line;
192 }
193 p++;
194 }
136 goto nibble1; 195 goto nibble1;
137 } 196 }
138 /* Nibbles can join even through newline: 197 /* Nibbles can join even through newline:
@@ -143,10 +202,13 @@ static void reverse(unsigned opt, const char *filename)
143 p = buf = xmalloc_fgetline(fp); 202 p = buf = xmalloc_fgetline(fp);
144 if (!buf) 203 if (!buf)
145 break; 204 break;
205 if (!(opt & OPT_p)) /* -p and !-p: different behavior */
206 goto skip_address;
146 goto nibble2; 207 goto nibble2;
147 } 208 }
148 putchar(val); 209 putchar(val);
149 } 210 cur++;
211 } /* for(;;) */
150 free(buf); 212 free(buf);
151 } 213 }
152 //fclose(fp); 214 //fclose(fp);
@@ -173,6 +235,8 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
173 unsigned opt; 235 unsigned opt;
174 int r; 236 int r;
175 237
238 setup_common_bufsiz();
239
176 dumper = alloc_dumper(); 240 dumper = alloc_dumper();
177 241
178 opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, 242 opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */,
@@ -200,7 +264,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
200 } 264 }
201 265
202 if (opt & OPT_r) { 266 if (opt & OPT_r) {
203 reverse(opt, argv[0]); 267 reverse(opt, argv[0], opt_s);
204 } 268 }
205 269
206 if (opt & OPT_o) { 270 if (opt & OPT_o) {