diff -Nru busybox-1.35.0/archival/dpkg.c busybox-1.36.1/archival/dpkg.c --- busybox-1.35.0/archival/dpkg.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/archival/dpkg.c 2023-01-03 14:14:43.000000000 +0000 @@ -1115,7 +1115,7 @@ if (package_edge->type == EDGE_PRE_DEPENDS || package_edge->type == EDGE_DEPENDS ) { - int result=1; + int result = 1; status_num = 0; /* If we are inside an alternative then check diff -Nru busybox-1.35.0/archival/libarchive/decompress_bunzip2.c busybox-1.36.1/archival/libarchive/decompress_bunzip2.c --- busybox-1.35.0/archival/libarchive/decompress_bunzip2.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/archival/libarchive/decompress_bunzip2.c 2023-01-03 14:14:43.000000000 +0000 @@ -654,7 +654,7 @@ /* Subtract the 1 copy we'd output anyway to get extras */ --bd->writeCopies; } - } /* for(;;) */ + } /* for (;;) */ /* Decompression of this input block completed successfully */ bd->writeCRC = CRC = ~CRC; diff -Nru busybox-1.35.0/archival/libarchive/get_header_tar.c busybox-1.36.1/archival/libarchive/get_header_tar.c --- busybox-1.35.0/archival/libarchive/get_header_tar.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/archival/libarchive/get_header_tar.c 2023-01-03 14:14:43.000000000 +0000 @@ -147,11 +147,13 @@ #endif } +#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS static void die_if_bad_fnamesize(off_t sz) { if ((uoff_t)sz > 0xfff) /* more than 4k?! no funny business please */ bb_simple_error_msg_and_die("bad archive"); } +#endif char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) { diff -Nru busybox-1.35.0/archival/unzip.c busybox-1.36.1/archival/unzip.c --- busybox-1.35.0/archival/unzip.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/archival/unzip.c 2023-03-28 15:42:00.000000000 +0000 @@ -56,7 +56,7 @@ //kbuild:lib-$(CONFIG_UNZIP) += unzip.o //usage:#define unzip_trivial_usage -//usage: "[-lnojpq] FILE[.zip] [FILE]... [-x FILE]... [-d DIR]" +//usage: "[-lnojpqK] FILE[.zip] [FILE]... [-x FILE]... [-d DIR]" //usage:#define unzip_full_usage "\n\n" //usage: "Extract FILEs from ZIP archive\n" //usage: "\n -l List contents (with -q for short form)" @@ -66,6 +66,7 @@ //usage: "\n -p Write to stdout" //usage: "\n -t Test" //usage: "\n -q Quiet" +//usage: "\n -K Do not clear SUID bit" //usage: "\n -x FILE Exclude FILEs" //usage: "\n -d DIR Extract into DIR" @@ -118,6 +119,8 @@ #define FIX_ENDIANNESS_ZIP(zip) \ do { if (BB_BIG_ENDIAN) { \ (zip).fmt.method = SWAP_LE16((zip).fmt.method ); \ + (zip).fmt.modtime = SWAP_LE16((zip).fmt.modtime ); \ + (zip).fmt.moddate = SWAP_LE16((zip).fmt.moddate ); \ (zip).fmt.crc32 = SWAP_LE32((zip).fmt.crc32 ); \ (zip).fmt.cmpsize = SWAP_LE32((zip).fmt.cmpsize ); \ (zip).fmt.ucmpsize = SWAP_LE32((zip).fmt.ucmpsize ); \ @@ -492,6 +495,7 @@ OPT_l = (1 << 0), OPT_x = (1 << 1), OPT_j = (1 << 2), + OPT_K = (1 << 3), }; unsigned opts; smallint quiet = 0; @@ -557,7 +561,7 @@ opts = 0; /* '-' makes getopt return 1 for non-options */ - while ((i = getopt(argc, argv, "-d:lnotpqxjv")) != -1) { + while ((i = getopt(argc, argv, "-d:lnotpqxjvK")) != -1) { switch (i) { case 'd': /* Extract to base directory */ base_dir = optarg; @@ -600,6 +604,10 @@ opts |= OPT_j; break; + case 'K': + opts |= OPT_K; + break; + case 1: if (!src_fn) { /* The zip file */ @@ -817,7 +825,10 @@ # endif if ((cdf.fmt.version_made_by >> 8) == 3) { /* This archive is created on Unix */ - dir_mode = file_mode = (cdf.fmt.external_attributes >> 16); + file_mode = (cdf.fmt.external_attributes >> 16); + if (!(opts & OPT_K)) + file_mode &= ~(mode_t)(S_ISUID | S_ISGID); + dir_mode = file_mode; } } #endif diff -Nru busybox-1.35.0/AUTHORS busybox-1.36.1/AUTHORS --- busybox-1.35.0/AUTHORS 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/AUTHORS 2023-01-03 14:14:43.000000000 +0000 @@ -181,3 +181,6 @@ Maxime Coste paste implementation + +Roger Knecht + tree diff -Nru busybox-1.35.0/busybox_ldscript.README.txt busybox-1.36.1/busybox_ldscript.README.txt --- busybox-1.35.0/busybox_ldscript.README.txt 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/busybox_ldscript.README.txt 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,47 @@ +/* Add SORT_BY_ALIGNMENT to linker script (found in busybox_unstripped.out): +## .rodata : { *(.rodata SORT_BY_ALIGNMENT(.rodata.*) .gnu.linkonce.r.*) } +## .data : { *(.data SORT_BY_ALIGNMENT(.data.*) .gnu.linkonce.d.*) } +## .bss : { *(.bss SORT_BY_ALIGNMENT(.bss.*) .gnu.linkonce.b.*) } +## This will eliminate most of the padding (~3kb). +## Hmm, "ld --sort-section alignment" should do it too. +## +## There is a ld hack which is meant to decrease disk usage +## at the cost of more RAM usage (??!!) in standard ld script: +## . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1)); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000); +## Replace it with: +## . = ALIGN (0x1000); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000); +## to unconditionally align .data to the next page boundary, +## instead of "next page, plus current offset in this page" +*/ + +/* To reduce the number of VMAs each bbox process has, +## move *(.bss SORT_BY_ALIGNMENT(.bss.*) ...) +## part from .bss : {...} block to .data : { ... } block. +## (This usually increases .data section by only one page). +## Result: +## +## text data bss dec hex filename +## 1050792 560 7580 1058932 102874 busybox.bss +## 1050792 8149 0 1058941 10287d busybox.nobss +## +## $ exec busybox.bss pmap $$ +## 0000000008048000 1028K r-xp /path/to/busybox.bss +## 0000000008149000 8K rw-p /path/to/busybox.bss +## 000000000814b000 4K rw-p [ anon ] <---- this VMA is eliminated +## 00000000085f5000 4K ---p [heap] +## 00000000085f6000 4K rw-p [heap] +## 00000000f7778000 8K rw-p [ anon ] +## 00000000f777a000 12K r--p [vvar] +## 00000000f777d000 8K r-xp [vdso] +## 00000000ff7e9000 132K rw-p [stack] +## +## $ exec busybox.nobss pmap $$ +## 0000000008048000 1028K r-xp /path/to/busybox.nobss +## 0000000008149000 12K rw-p /path/to/busybox.nobss +## 00000000086f0000 4K ---p [heap] +## 00000000086f1000 4K rw-p [heap] +## 00000000f7783000 8K rw-p [ anon ] +## 00000000f7785000 12K r--p [vvar] +## 00000000f7788000 8K r-xp [vdso] +## 00000000ffac0000 132K rw-p [stack] +*/ diff -Nru busybox-1.35.0/console-tools/reset.c busybox-1.36.1/console-tools/reset.c --- busybox-1.35.0/console-tools/reset.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/console-tools/reset.c 2023-01-03 14:14:43.000000000 +0000 @@ -21,7 +21,7 @@ //usage:#define reset_trivial_usage //usage: "" //usage:#define reset_full_usage "\n\n" -//usage: "Reset the screen" +//usage: "Reset terminal (ESC codes) and termios (signals, buffering, echo)" /* "Standard" version of this tool is in ncurses package */ @@ -36,7 +36,7 @@ int reset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int reset_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { - static const char *const args[] = { + static const char *const args[] ALIGN_PTR = { "stty", "sane", NULL }; diff -Nru busybox-1.35.0/coreutils/cut.c busybox-1.36.1/coreutils/cut.c --- busybox-1.35.0/coreutils/cut.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/cut.c 2023-01-03 14:14:43.000000000 +0000 @@ -167,7 +167,7 @@ if (!cl_pos && !dcount && !shoe) { if (option_mask32 & CUT_OPT_SUPPRESS_FLGS) goto next_line; - } else if (dcountdn_ino); -//TODO: -h should affect -s too: - if (opt & OPT_s) /* show allocated blocks */ - column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); + if (opt & OPT_s) { /* show allocated blocks */ + if (opt & OPT_h) { + column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", + /* print size, show one fractional, use suffixes */ + make_human_readable_str((off_t)dn->dn_blocks << 9, 1, 0) + ); + } else { + column += printf("%6"OFF_FMT"u ", (off_t)(dn->dn_blocks >> 1)); + } + } if (opt & OPT_l) { /* long listing: show mode */ char modestr[12]; diff -Nru busybox-1.35.0/coreutils/md5_sha1_sum.c busybox-1.36.1/coreutils/md5_sha1_sum.c --- busybox-1.35.0/coreutils/md5_sha1_sum.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/md5_sha1_sum.c 2023-01-03 14:14:43.000000000 +0000 @@ -151,10 +151,12 @@ return (unsigned char *)hex_value; } +#define BUFSZ (CONFIG_FEATURE_COPYBUF_KB < 4 ? 4096 : CONFIG_FEATURE_COPYBUF_KB * 1024) + #if !ENABLE_SHA3SUM -# define hash_file(f,w) hash_file(f) +# define hash_file(b,f,w) hash_file(b,f) #endif -static uint8_t *hash_file(const char *filename, unsigned sha3_width) +static uint8_t *hash_file(unsigned char *in_buf, const char *filename, unsigned sha3_width) { int src_fd, hash_len, count; union _ctx_ { @@ -227,8 +229,7 @@ } { - RESERVE_CONFIG_UBUFFER(in_buf, 4096); - while ((count = safe_read(src_fd, in_buf, 4096)) > 0) { + while ((count = safe_read(src_fd, in_buf, BUFSZ)) > 0) { update(&context, in_buf, count); } hash_value = NULL; @@ -238,7 +239,6 @@ final(&context, in_buf); hash_value = hash_bin_to_hex(in_buf, hash_len); } - RELEASE_CONFIG_BUFFER(in_buf); } if (src_fd != STDIN_FILENO) { @@ -251,6 +251,7 @@ int md5_sha1_sum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int md5_sha1_sum_main(int argc UNUSED_PARAM, char **argv) { + unsigned char *in_buf; int return_value = EXIT_SUCCESS; unsigned flags; #if ENABLE_SHA3SUM @@ -279,6 +280,12 @@ if (!*argv) *--argv = (char*)"-"; + /* The buffer is not alloc/freed for each input file: + * for big values of COPYBUF_KB, this helps to keep its pages + * pre-faulted and possibly even fully cached on local CPU. + */ + in_buf = xmalloc(BUFSZ); + do { if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && (flags & FLAG_CHECK)) { FILE *pre_computed_stream; @@ -293,12 +300,8 @@ char *filename_ptr; count_total++; - filename_ptr = strstr(line, " "); - /* handle format for binary checksums */ - if (filename_ptr == NULL) { - filename_ptr = strstr(line, " *"); - } - if (filename_ptr == NULL) { + filename_ptr = strchr(line, ' '); + if (!filename_ptr) { if (flags & FLAG_WARN) { bb_simple_error_msg("invalid format"); } @@ -307,10 +310,15 @@ free(line); continue; } - *filename_ptr = '\0'; - filename_ptr += 2; + *filename_ptr++ = '\0'; + /* coreutils 9.1 allows "HASH FILENAME" format, + * with only one space. Skip the 'correct' + * " " or " *" delimiter if it is there: + */ + if (*filename_ptr == ' ' || *filename_ptr == '*') + filename_ptr++; - hash_value = hash_file(filename_ptr, sha3_width); + hash_value = hash_file(in_buf, filename_ptr, sha3_width); if (hash_value && (strcmp((char*)hash_value, line) == 0)) { if (!(flags & FLAG_SILENT)) @@ -339,7 +347,7 @@ } fclose_if_not_stdin(pre_computed_stream); } else { - uint8_t *hash_value = hash_file(*argv, sha3_width); + uint8_t *hash_value = hash_file(in_buf, *argv, sha3_width); if (hash_value == NULL) { return_value = EXIT_FAILURE; } else { diff -Nru busybox-1.35.0/coreutils/mv.c busybox-1.36.1/coreutils/mv.c --- busybox-1.35.0/coreutils/mv.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/mv.c 2023-01-03 14:14:43.000000000 +0000 @@ -71,9 +71,9 @@ "no-target-directory\0" No_argument "T" "target-directory\0" Required_argument "t" IF_FEATURE_VERBOSE( - "verbose\0" No_argument "v", - &last + "verbose\0" No_argument "v" ) + , &last ); argc -= optind; argv += optind; diff -Nru busybox-1.35.0/coreutils/nice.c busybox-1.36.1/coreutils/nice.c --- busybox-1.35.0/coreutils/nice.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/nice.c 2023-01-03 14:14:43.000000000 +0000 @@ -33,7 +33,7 @@ if (!*++argv) { /* No args, so (GNU) output current nice value. */ printf("%d\n", old_priority); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } adjustment = 10; /* Set default adjustment. */ diff -Nru busybox-1.35.0/coreutils/od.c busybox-1.36.1/coreutils/od.c --- busybox-1.35.0/coreutils/od.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/od.c 2023-01-03 14:14:43.000000000 +0000 @@ -144,7 +144,7 @@ } } -static const char *const add_strings[] = { +static const char *const add_strings[] ALIGN_PTR = { "16/1 \"%3_u \" \"\\n\"", /* a */ "8/2 \" %06o \" \"\\n\"", /* B, o */ "16/1 \"%03o \" \"\\n\"", /* b */ diff -Nru busybox-1.35.0/coreutils/printf.c busybox-1.36.1/coreutils/printf.c --- busybox-1.35.0/coreutils/printf.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/coreutils/printf.c 2023-04-25 14:47:22.000000000 +0000 @@ -428,7 +428,7 @@ if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2]) argv++; if (!argv[1]) { - if (ENABLE_ASH_PRINTF + if ((ENABLE_ASH_PRINTF || ENABLE_HUSH_PRINTF) && applet_name[0] != 'p' ) { bb_simple_error_msg("usage: printf FORMAT [ARGUMENT...]"); diff -Nru busybox-1.35.0/coreutils/readlink.c busybox-1.36.1/coreutils/readlink.c --- busybox-1.35.0/coreutils/readlink.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/readlink.c 2023-01-03 14:14:43.000000000 +0000 @@ -96,5 +96,5 @@ printf((opt & 2) ? "%s" : "%s\n", buf); free(buf); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/coreutils/shuf.c busybox-1.36.1/coreutils/shuf.c --- busybox-1.35.0/coreutils/shuf.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/shuf.c 2023-01-03 14:14:43.000000000 +0000 @@ -171,5 +171,5 @@ printf("%s%c", lines[i], eol); } - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/coreutils/sleep.c busybox-1.36.1/coreutils/sleep.c --- busybox-1.35.0/coreutils/sleep.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/sleep.c 2023-04-25 14:47:22.000000000 +0000 @@ -37,6 +37,7 @@ //applet:IF_SLEEP(APPLET(sleep, BB_DIR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_SLEEP) += sleep.o +//kbuild:lib-$(CONFIG_ASH_SLEEP) += sleep.o /* BB_AUDIT SUSv3 compliant */ /* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */ @@ -64,15 +65,29 @@ { duration_t duration; + /* Note: sleep_main may be directly called from ash as a builtin. + * This brings some complications: + * + we can't use xfunc here + * + we can't use bb_show_usage + * + applet_name can be the name of the shell + */ ++argv; - if (!*argv) + if (!*argv) { + /* Without this, bare "sleep" in ash shows _ash_ --help */ + /* (ash can be the "sh" applet as well, so check 2nd char) */ + if (ENABLE_ASH_SLEEP && applet_name[1] != 'l') { + bb_simple_error_msg("sleep: missing operand"); + return EXIT_FAILURE; + } bb_show_usage(); + } /* GNU sleep accepts "inf", "INF", "infinity" and "INFINITY" */ if (strncasecmp(argv[0], "inf", 3) == 0) for (;;) sleep(INT_MAX); +//FIXME: in ash, "sleep 123qwerty" as a builtin aborts the shell #if ENABLE_FEATURE_FANCY_SLEEP duration = 0; do { diff -Nru busybox-1.35.0/coreutils/sort.c busybox-1.36.1/coreutils/sort.c --- busybox-1.35.0/coreutils/sort.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/sort.c 2023-01-03 14:14:43.000000000 +0000 @@ -18,7 +18,7 @@ //config: sort is used to sort lines of text in specified files. //config: //config:config FEATURE_SORT_BIG -//config: bool "Full SuSv3 compliant sort (support -ktcbdfiogM)" +//config: bool "Full SuSv3 compliant sort (support -ktcbdfioghM)" //config: default y //config: depends on SORT //config: help @@ -43,7 +43,7 @@ //usage:#define sort_trivial_usage //usage: "[-nru" -//usage: IF_FEATURE_SORT_BIG("gMcszbdfiokt] [-o FILE] [-k START[.OFS][OPTS][,END[.OFS][OPTS]] [-t CHAR") +//usage: IF_FEATURE_SORT_BIG("ghMcszbdfiokt] [-o FILE] [-k START[.OFS][OPTS][,END[.OFS][OPTS]] [-t CHAR") //usage: "] [FILE]..." //usage:#define sort_full_usage "\n\n" //usage: "Sort lines of text\n" @@ -59,6 +59,7 @@ //usage: "\n -n Sort numbers" //usage: IF_FEATURE_SORT_BIG( //usage: "\n -g General numerical sort" +//usage: "\n -h Sort human readable numbers (2K 1G)" //usage: "\n -M Sort month" //usage: "\n -V Sort version" //usage: "\n -t CHAR Field separator" @@ -94,31 +95,32 @@ enum { FLAG_n = 1 << 0, /* Numeric sort */ FLAG_g = 1 << 1, /* Sort using strtod() */ - FLAG_M = 1 << 2, /* Sort date */ - FLAG_V = 1 << 3, /* Sort version */ + FLAG_h = 1 << 2, /* Sort using strtod(), plus KMGT suffixes */ + FLAG_M = 1 << 3, /* Sort date */ + FLAG_V = 1 << 4, /* Sort version */ /* ucsz apply to root level only, not keys. b at root level implies bb */ - FLAG_u = 1 << 4, /* Unique */ - FLAG_c = 1 << 5, /* Check: no output, exit(!ordered) */ - FLAG_s = 1 << 6, /* Stable sort, no ascii fallback at end */ - FLAG_z = 1 << 7, /* Input and output is NUL terminated, not \n */ + FLAG_u = 1 << 5, /* Unique */ + FLAG_c = 1 << 6, /* Check: no output, exit(!ordered) */ + FLAG_s = 1 << 7, /* Stable sort, no ascii fallback at end */ + FLAG_z = 1 << 8, /* Input and output is NUL terminated, not \n */ /* These can be applied to search keys, the previous four can't */ - FLAG_b = 1 << 8, /* Ignore leading blanks */ - FLAG_r = 1 << 9, /* Reverse */ - FLAG_d = 1 << 10, /* Ignore !(isalnum()|isspace()) */ - FLAG_f = 1 << 11, /* Force uppercase */ - FLAG_i = 1 << 12, /* Ignore !isprint() */ - FLAG_m = 1 << 13, /* ignored: merge already sorted files; do not sort */ - FLAG_S = 1 << 14, /* ignored: -S, --buffer-size=SIZE */ - FLAG_T = 1 << 15, /* ignored: -T, --temporary-directory=DIR */ - FLAG_o = 1 << 16, - FLAG_k = 1 << 17, - FLAG_t = 1 << 18, + FLAG_b = 1 << 9, /* Ignore leading blanks */ + FLAG_r = 1 << 10, /* Reverse */ + FLAG_d = 1 << 11, /* Ignore !(isalnum()|isspace()) */ + FLAG_f = 1 << 12, /* Force uppercase */ + FLAG_i = 1 << 13, /* Ignore !isprint() */ + FLAG_m = 1 << 14, /* ignored: merge already sorted files; do not sort */ + FLAG_S = 1 << 15, /* ignored: -S, --buffer-size=SIZE */ + FLAG_T = 1 << 16, /* ignored: -T, --temporary-directory=DIR */ + FLAG_o = 1 << 17, + FLAG_k = 1 << 18, + FLAG_t = 1 << 19, FLAG_bb = 0x80000000, /* Ignore trailing blanks */ FLAG_no_tie_break = 0x40000000, }; static const char sort_opt_str[] ALIGN1 = "^" - "ngMVucszbrdfimS:T:o:k:*t:" + "nghMVucszbrdfimS:T:o:k:*t:" "\0" "o--o:t--t"/*-t, -o: at most one of each*/; /* * OPT_STR must not be string literal, needs to have stable address: @@ -253,6 +255,25 @@ #define GET_LINE(fp) xmalloc_fgetline(fp) #endif +#if ENABLE_FEATURE_SORT_BIG +static int scale_suffix(const char *tail) +{ + static const char suffix[] ALIGN1 = "kmgtpezy"; + const char *s; + int n; + + if (!tail[0]) + return -1; + s = strchr(suffix, tail[0] | 0x20); + if (!s) + return -1; + n = s - suffix; + if (n != 0 && tail[0] >= 'a') + return -1; /* mg... not accepted, only MG... */ + return n; +} +#endif + /* Iterate through keys list and perform comparisons */ static int compare_keys(const void *xarg, const void *yarg) { @@ -275,7 +296,7 @@ y = *(char **)yarg; #endif /* Perform actual comparison */ - switch (flags & (FLAG_n | FLAG_g | FLAG_M | FLAG_V)) { + switch (flags & (FLAG_n | FLAG_g | FLAG_h | FLAG_M | FLAG_V)) { default: bb_simple_error_msg_and_die("unknown sort type"); break; @@ -293,7 +314,8 @@ #endif break; #if ENABLE_FEATURE_SORT_BIG - case FLAG_g: { + case FLAG_g: + case FLAG_h: { char *xx, *yy; //TODO: needs setlocale(LC_NUMERIC, "C")? double dx = strtod(x, &xx); @@ -308,16 +330,26 @@ retval = (dy != dy) ? 0 : -1; else if (dy != dy) retval = 1; - /* Check for infinity. Could underflow, but it avoids libm. */ - else if (1.0 / dx == 0.0) { - if (dx < 0) - retval = (1.0 / dy == 0.0 && dy < 0) ? 0 : -1; + else { + if (flags & FLAG_h) { + int xs = scale_suffix(xx); + int ys = scale_suffix(yy); + if (xs != ys) { + retval = xs - ys; + break; + } + } + /* Check for infinity. Could underflow, but it avoids libm. */ + if (1.0 / dx == 0.0) { + if (dx < 0) + retval = (1.0 / dy == 0.0 && dy < 0) ? 0 : -1; + else + retval = (1.0 / dy == 0.0 && dy > 0) ? 0 : 1; + } else if (1.0 / dy == 0.0) + retval = (dy < 0) ? 1 : -1; else - retval = (1.0 / dy == 0.0 && dy > 0) ? 0 : 1; - } else if (1.0 / dy == 0.0) - retval = (dy < 0) ? 1 : -1; - else - retval = (dx > dy) ? 1 : ((dx < dy) ? -1 : 0); + retval = (dx > dy) ? 1 : ((dx < dy) ? -1 : 0); + } break; } case FLAG_M: { @@ -325,9 +357,9 @@ int dx; char *xx, *yy; - xx = strptime(x, "%b", &thyme); + xx = strptime(skip_whitespace(x), "%b", &thyme); dx = thyme.tm_mon; - yy = strptime(y, "%b", &thyme); + yy = strptime(skip_whitespace(y), "%b", &thyme); if (!xx) retval = (!yy) ? 0 : -1; else if (!yy) @@ -380,7 +412,9 @@ /* If x > y, 1, else -1 */ retval = (x32 > y32) * 2 - 1; - } else + /* Here, -r has no effect! */ + return retval; + } if (!(option_mask32 & FLAG_no_tie_break)) { /* fallback sort */ flags = option_mask32; @@ -474,6 +508,7 @@ FLAG_allowed_for_k = FLAG_n | /* Numeric sort */ FLAG_g | /* Sort using strtod() */ + FLAG_h | /* Sort using strtod(), plus KMGT suffixes */ FLAG_M | /* Sort date */ FLAG_b | /* Ignore leading blanks */ FLAG_r | /* Reverse */ @@ -617,11 +652,12 @@ /* Handle -u */ if (option_mask32 & FLAG_u) { int j = 0; - /* coreutils 6.3 drop lines for which only key is the same - * -- disabling last-resort compare, or else compare_keys() - * will be the same only for completely identical lines. + /* coreutils 6.3 drop lines for which only key is the same: + * - disabling last-resort compare, or else compare_keys() + * will be the same only for completely identical lines + * - disabling -s (same reasons) */ - option_mask32 |= FLAG_no_tie_break; + option_mask32 = (option_mask32 | FLAG_no_tie_break) & (~FLAG_s); for (i = 1; i < linecount; i++) { if (compare_keys(&lines[j], &lines[i]) == 0) free(lines[i]); @@ -644,5 +680,5 @@ printf("%s%c", lines[i], ch); } - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/coreutils/test.c busybox-1.36.1/coreutils/test.c --- busybox-1.35.0/coreutils/test.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/coreutils/test.c 2023-01-03 14:14:43.000000000 +0000 @@ -242,7 +242,7 @@ depth--; \ return __res; \ } while (0) -static const char *const TOKSTR[] = { +static const char *const TOKSTR[] ALIGN_PTR = { "EOI", "FILRD", "FILWR", @@ -859,7 +859,7 @@ if (check_operator(args[1]) != EOI) { /* if args[1] != NULL */ if (args[2]) { // coreutils also does this: - // if (args[3] && args[0]="-l" && args[2] is BINOP) + // if (args[3] && args[0] = "-l" && args[2] is BINOP) // return binop(1 /* prepended by -l */); if (last_operator->op_type == BINOP) unnest_msg_and_return(binop(), " COMMON_BUFSIZE); \ + G.nodes = NULL; \ + G.nodes_len = 0; \ +} while (0) + +static struct node * +get_node(const char *name) +{ + struct node *n; + unsigned a = 0; + unsigned b = G.nodes_len; + + /* Binary search for name */ + while (a != b) { + unsigned m = (a + b) / 2; + int cmp = strcmp(name, G.nodes[m]->name); + if (cmp == 0) + return G.nodes[m]; /* found */ + if (cmp < 0) { + b = m; + } else { + a = m + 1; + } + } + + /* Allocate new node */ + n = xzalloc(sizeof(*n) + strlen(name)); + //n->in_count = 0; + //n->out_count = 0; + //n->out = NULL; + strcpy(n->name, name); + + /* Insert to maintain sort */ + G.nodes = xrealloc(G.nodes, (G.nodes_len + 1) * sizeof(*G.nodes)); + memmove(&G.nodes[a + 1], &G.nodes[a], + (G.nodes_len - a) * sizeof(*G.nodes)); + G.nodes[a] = n; + G.nodes_len++; + return n; +} + +static void +add_edge(struct node *a, struct node *b) +{ + a->out = xrealloc_vector(a->out, 6, a->out_count); + a->out[a->out_count++] = b; + b->in_count++; +} + +int tsort_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int tsort_main(int argc UNUSED_PARAM, char **argv) +{ + char *line; + size_t linesz; + ssize_t len; + struct node *a; + int cycles; + + INIT_G(); + + if (argv[1]) { + if (argv[2]) + bb_show_usage(); + if (NOT_LONE_DASH(argv[1])) { + close(STDIN_FILENO); /* == 0 */ + xopen(argv[1], O_RDONLY); /* fd will be 0 */ + } + } + + /* Read in words separated by s */ + a = NULL; + line = NULL; + linesz = 0; + while ((len = getline(&line, &linesz, stdin)) != -1) { + char *s = line; + while (*(s = skip_whitespace(s)) != '\0') { + struct node *b; + char *word; + + word = s; + s = skip_non_whitespace(s); + if (*s) + *s++ = '\0'; + + /* Create nodes and edges for each word pair */ + b = get_node(word); + if (!a) { + a = b; + } else { + if (a != b) + add_edge(a, b); + a = NULL; + } + } + } +// Most other tools do not check for input read error (treat them as EOF) +// die_if_ferror(in, input_filename); + if (a) + bb_simple_error_msg_and_die("odd input"); + free(line); + + /* + * Kahn's algorithm: + * - find a node that has no incoming edges, print and remove it + * - repeat until the graph is empty + * - if any nodes are left, they form cycles. + */ + cycles = 0; + while (G.nodes_len) { + struct node *n; + unsigned i; + + /* Search for first node with no incoming edges */ + for (i = 0; i < G.nodes_len; i++) { + if (!G.nodes[i]->in_count) + break; + } + if (i == G.nodes_len) { + /* Must be a cycle; arbitraily break it at node 0 */ + cycles++; + i = 0; +#ifndef TINY + bb_error_msg("cycle at %s", G.nodes[i]->name); +#endif + } + + /* Remove the node (need no longer maintain sort) */ + n = G.nodes[i]; + G.nodes[i] = G.nodes[--G.nodes_len]; + + /* And remove its outgoing edges */ + for (i = 0; i < n->out_count; i++) + n->out[i]->in_count--; + free(n->out); + + puts(n->name); + free(n); + } + free(G.nodes); + + fflush_stdout_and_exit(cycles ? 1 : 0); +} diff -Nru busybox-1.35.0/coreutils/uname.c busybox-1.36.1/coreutils/uname.c --- busybox-1.35.0/coreutils/uname.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/uname.c 2023-01-03 14:14:43.000000000 +0000 @@ -209,5 +209,5 @@ #endif } - fflush_stdout_and_exit(EXIT_SUCCESS); /* coreutils-6.9 compat */ + fflush_stdout_and_exit_SUCCESS(); /* coreutils-6.9 compat */ } diff -Nru busybox-1.35.0/coreutils/uniq.c busybox-1.36.1/coreutils/uniq.c --- busybox-1.35.0/coreutils/uniq.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/uniq.c 2023-01-03 14:14:43.000000000 +0000 @@ -139,5 +139,5 @@ die_if_ferror(stdin, input_filename); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/coreutils/uudecode.c busybox-1.36.1/coreutils/uudecode.c --- busybox-1.35.0/coreutils/uudecode.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/coreutils/uudecode.c 2023-01-03 14:14:43.000000000 +0000 @@ -352,7 +352,7 @@ #undef src_buf } - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } #endif diff -Nru busybox-1.35.0/coreutils/uuencode.c busybox-1.36.1/coreutils/uuencode.c --- busybox-1.35.0/coreutils/uuencode.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/coreutils/uuencode.c 2023-01-03 14:14:43.000000000 +0000 @@ -78,5 +78,5 @@ } printf(tbl == bb_uuenc_tbl_std ? "\n`\nend\n" : "\n====\n"); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/debian/busybox-initramfs.install busybox-1.36.1/debian/busybox-initramfs.install --- busybox-1.35.0/debian/busybox-initramfs.install 2021-11-16 11:10:52.000000000 +0000 +++ busybox-1.36.1/debian/busybox-initramfs.install 2023-07-05 16:18:44.000000000 +0000 @@ -1 +1,2 @@ +b/initramfs/busybox /usr/lib/initramfs-tools/bin/ debian/tree/busybox-initramfs/* / diff -Nru busybox-1.35.0/debian/busybox.install busybox-1.36.1/debian/busybox.install --- busybox-1.35.0/debian/busybox.install 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/busybox.install 2023-07-05 16:18:19.000000000 +0000 @@ -0,0 +1 @@ +b/deb/busybox bin/ diff -Nru busybox-1.35.0/debian/busybox-static.install busybox-1.36.1/debian/busybox-static.install --- busybox-1.35.0/debian/busybox-static.install 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/busybox-static.install 2023-07-05 16:18:16.000000000 +0000 @@ -0,0 +1,2 @@ +b/static/busybox bin/ +b/static/docs/busybox.1 usr/share/man/man1/ diff -Nru busybox-1.35.0/debian/busybox-syslogd.busybox-klogd.init busybox-1.36.1/debian/busybox-syslogd.busybox-klogd.init --- busybox-1.35.0/debian/busybox-syslogd.busybox-klogd.init 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/busybox-syslogd.busybox-klogd.init 2023-07-05 16:04:48.000000000 +0000 @@ -1,9 +1,10 @@ -#!/bin/sh +#! /bin/busybox ash # # init.d script with LSB support. # # Copyright (c) 2007 Javier Fernandez-Sanguino # Copyright (c) 2008 Axel Beckert +# Copyright (c) 2023 Michael Tokarev # # This is free software; you may redistribute it and/or modify # it under the terms of the GNU General Public License as @@ -29,130 +30,71 @@ # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Starts klogd -# Description: Starts the busybox klogd +# Description: Starts the busybox kernel logger klogd ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin -NAME=klogd # Introduce the short server's name here -DAEMON=/sbin/$NAME # Introduce the server's location here -DESC="busybox' $NAME implementation" # Introduce a short description here -NEEDED_OPTS='' -DAEMON_USER='root' +NAME=klogd +DAEMON=/sbin/$NAME +DESC="busybox' $NAME implementation" test -x $DAEMON || exit 0 -# systemd provides klogd functions internally -test -d /run/systemd/system && exit 0 . /lib/lsb/init-functions -# Default options, these can be overriden by the information -# at /etc/default/$NAME -KLOG_OPTS="" # Additional options given to the server - -DIETIME=10 # Time to wait for the server to die, in seconds - # If this value is set too low you might not - # let some servers to die gracefully and - # 'restart' will not work - -STARTTIME=2 # Time to wait for the server to start, in seconds - # If this value is set each time the server is - # started (on start or restart) the script will - # stall to try to determine if it is running - # If it is not set and the server takes time - # to setup a pid file the log message might - # be a false positive (says it did not start - # when it actually did) - +KLOG_OPTS= # Additional options given to the server # Include defaults if available if [ -f /etc/default/busybox-syslogd ] ; then . /etc/default/busybox-syslogd fi -set -e - -start_server() { - start-stop-daemon --start --verbose --name $NAME \ - --exec $DAEMON -- $NEEDED_OPTS $KLOG_OPTS -} - -stop_server() { - start-stop-daemon --stop --verbose --name $NAME -} - -running() { - cut -d ' ' -f 1-2 /proc/[0-9]*/stat 2> /dev/null | grep -F "($NAME)" +server() { + case "$1" in + (start) args="-S -o" ;; + (stop) args="-K -o -q" ;; + (check) args="-K -t -q" ;; + esac + busybox start-stop-daemon $args -p /var/run/$NAME.pid \ + -x $DAEMON -- $KLOGD_OPTS } case "$1" in - start) + start) log_daemon_msg "Starting $DESC " "$NAME" - # Check if it's running first - if running ; then - log_progress_msg "apparently already running" - log_end_msg 0 - exit 0 - fi - if start_server ; then - # NOTE: Some servers might die some time after they start, - # this code will detect this issue if STARTTIME is set - # to a reasonable value - [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time - if running ; then - # It's ok, the server started and is running - log_end_msg 0 - else - # It is not running after we did start - log_end_msg 1 - fi - else - # Either we could not start it - log_end_msg 1 - fi + if server start ; then + log_end_msg 0 + else + log_end_msg 1 + exit 1 + fi ;; - - stop) - log_daemon_msg "Stopping $DESC" "$NAME" - if running ; then - # Only stop the server if we see it running - errcode=0 - stop_server || errcode=$? - log_end_msg $errcode - else - # If it's not running don't do anything - log_progress_msg "apparently not running" - log_end_msg 0 - exit 0 - fi - ;; - - restart|force-reload) - log_daemon_msg "Restarting $DESC" "$NAME" - errcode=0 - stop_server || errcode=$? - # Wait some sensible amount, some server need this - [ -n "$DIETIME" ] && sleep $DIETIME - start_server || errcode=$? - [ -n "$STARTTIME" ] && sleep $STARTTIME - running || errcode=$? - log_end_msg $errcode + stop) + log_daemon_msg "Stopping $DESC" "$NAME" + if server stop ; then + log_end_msg 0 + else + log_end_msg 1 + exit 1 + fi ;; - - status) - log_daemon_msg "Checking status of $DESC" "$NAME" - if running ; then - log_progress_msg "running" - log_end_msg 0 - else - log_progress_msg "apparently not running" - log_end_msg 1 - exit 1 - fi - ;; - - *) - N=/etc/init.d/$NAME - echo "Usage: $N {start|stop|restart|force-reload|status}" >&2 + restart|force-reload) + "$0" stop + exec "$0" start + ;; + status) + log_daemon_msg "Checking status of $DESC" "$NAME" + if server check ; then + log_progress_msg "running" + log_end_msg 0 + else + log_progress_msg "apparently not running" + log_end_msg 1 + exit 1 + fi + ;; + *) + echo "Usage: /etc/init.d/busybox-$NAME {start|stop|restart|force-reload|status}" >&2 exit 1 ;; esac diff -Nru busybox-1.35.0/debian/busybox-syslogd.busybox-klogd.service busybox-1.36.1/debian/busybox-syslogd.busybox-klogd.service --- busybox-1.35.0/debian/busybox-syslogd.busybox-klogd.service 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/busybox-syslogd.busybox-klogd.service 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,8 @@ +[Unit] +Description=Busybox Kernel Logging Service + +[Service] +ExecStart=/sbin/klogd -n + +[Install] +WantedBy=multi-user.target diff -Nru busybox-1.35.0/debian/busybox-syslogd.default busybox-1.36.1/debian/busybox-syslogd.default --- busybox-1.35.0/debian/busybox-syslogd.default 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/busybox-syslogd.default 2023-07-05 16:04:48.000000000 +0000 @@ -1,7 +1,9 @@ # Defaults for busybox-syslogd initscript -# This is a POSIX shell fragment sourced by /etc/init.d/busybox-syslogd +# This is a POSIX shell fragment sourced by +# /etc/init.d/busybox-syslogd and /etc/init.d/busybox-klogd -# Additional options that are passed to the daemons. Default is to log -# to ring buffer (to be read with logread(1)) and drop duplicates. +# Additional options that are passed to the daemons. +# Possible options, see: busybox syslogd -h SYSLOG_OPTS="-C128" +# Possible options, see: busybox klogd -h KLOG_OPTS="" diff -Nru busybox-1.35.0/debian/busybox-syslogd.docs busybox-1.36.1/debian/busybox-syslogd.docs --- busybox-1.35.0/debian/busybox-syslogd.docs 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/busybox-syslogd.docs 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1 @@ +docs/syslog.conf.txt diff -Nru busybox-1.35.0/debian/busybox-syslogd.init busybox-1.36.1/debian/busybox-syslogd.init --- busybox-1.35.0/debian/busybox-syslogd.init 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/busybox-syslogd.init 2023-07-05 16:04:48.000000000 +0000 @@ -1,9 +1,10 @@ -#!/bin/sh +#!/bin/busybox ash # # init.d script with LSB support. # # Copyright (c) 2007 Javier Fernandez-Sanguino # Copyright (c) 2008 Axel Beckert +# Copyright (c) 2023 Michael Tokarev # # This is free software; you may redistribute it and/or modify # it under the terms of the GNU General Public License as @@ -34,128 +35,73 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin -NAME=syslogd # Introduce the short server's name here -DAEMON=/sbin/$NAME # Introduce the server's location here -DESC="busybox' $NAME implementation" # Introduce a short description here -NEEDED_OPTS='' -DAEMON_USER='root' +NAME=syslogd +DAEMON=/sbin/$NAME +DESC="busybox' $NAME implementation" test -x $DAEMON || exit 0 . /lib/lsb/init-functions -# Default options, these can be overriden by the information -# at /etc/default/$NAME -SYSLOG_OPTS="" # Additional options given to the server - -DIETIME=10 # Time to wait for the server to die, in seconds - # If this value is set too low you might not - # let some servers to die gracefully and - # 'restart' will not work - -#STARTTIME=2 # Time to wait for the server to start, in seconds - # If this value is set each time the server is - # started (on start or restart) the script will - # stall to try to determine if it is running - # If it is not set and the server takes time - # to setup a pid file the log message might - # be a false positive (says it did not start - # when it actually did) - +SYSLOG_OPTS= # Additional options given to the server # Include defaults if available if [ -f /etc/default/busybox-syslogd ] ; then . /etc/default/busybox-syslogd fi -set -e - -start_server() { - start-stop-daemon --start --verbose --name $NAME \ - --exec $DAEMON -- $NEEDED_OPTS $SYSLOG_OPTS -} - -stop_server() { - start-stop-daemon --stop --quiet --name $NAME -} - -running() { - cut -d ' ' -f 1-2 /proc/[0-9]*/stat 2> /dev/null | grep -F "($NAME)" +server() { + case "$1" in + (start) args="-S -o" ;; + (stop) args="-K -o -q" ;; + (check) args="-K -t -q" ;; + esac + busybox start-stop-daemon $args -p /var/run/$NAME.pid \ + -x $DAEMON -- $SYSLOG_OPTS } case "$1" in - start) + start) log_daemon_msg "Starting $DESC " "$NAME" - # Check if it's running first - if running ; then - log_progress_msg "apparently already running" - log_end_msg 0 - exit 0 - fi - if start_server ; then - # NOTE: Some servers might die some time after they start, - # this code will detect this issue if STARTTIME is set - # to a reasonable value - [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time - if running ; then - # It's ok, the server started and is running - log_end_msg 0 - else - # It is not running after we did start - log_end_msg 1 - fi - else - # Either we could not start it - log_end_msg 1 - fi - ;; - stop) - log_daemon_msg "Stopping $DESC" "$NAME" - if running ; then - # Only stop the server if we see it running - errcode=0 - stop_server || errcode=$? - log_end_msg $errcode - else - # If it's not running don't do anything - log_progress_msg "apparently not running" - log_end_msg 0 - exit 0 - fi - ;; - restart|force-reload) - log_daemon_msg "Restarting $DESC" "$NAME" - errcode=0 - stop_server || errcode=$? - # Wait some sensible amount, some server need this - [ -n "$DIETIME" ] && sleep $DIETIME - start_server || errcode=$? - [ -n "$STARTTIME" ] && sleep $STARTTIME - running || errcode=$? - log_end_msg $errcode - ;; - status) - - log_daemon_msg "Checking status of $DESC" "$NAME" - if running ; then - log_progress_msg "running" - log_end_msg 0 - else - log_progress_msg "apparently not running" - log_end_msg 1 - exit 1 - fi - ;; - # daemon cannot reload - reload) - log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon" - log_warning_msg "cannot re-read the config file (use restart)." - ;; - - *) - N=/etc/init.d/$NAME - echo "Usage: $N {start|stop|restart|force-reload|status}" >&2 + if server start ; then + log_end_msg 0 + else + log_end_msg 1 + exit 1 + fi + ;; + stop) + log_daemon_msg "Stopping $DESC" "$NAME" + if server stop ; then + log_end_msg 0 + else + log_end_msg 1 + exit 1 + fi + ;; + restart|force-reload) + "$0" stop + exec "$0" start + ;; + status) + log_daemon_msg "Checking status of $DESC" "$NAME" + if server check ; then + log_progress_msg "running" + log_end_msg 0 + else + log_progress_msg "apparently not running" + log_end_msg 1 + exit 1 + fi + ;; + # daemon cannot reload + reload) + log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon" + log_warning_msg "cannot re-read the config file (use restart)." + ;; + *) + echo "Usage: /etc/init.d/busybox-$NAME {start|stop|restart|force-reload|status}" >&2 exit 1 - ;; + ;; esac exit 0 diff -Nru busybox-1.35.0/debian/busybox-syslogd.lintian-overrides busybox-1.36.1/debian/busybox-syslogd.lintian-overrides --- busybox-1.35.0/debian/busybox-syslogd.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/busybox-syslogd.lintian-overrides 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,2 @@ +busybox-syslogd: unusual-interpreter /bin/busybox [etc/init.d/busybox-klogd] +busybox-syslogd: unusual-interpreter /bin/busybox [etc/init.d/busybox-syslogd] diff -Nru busybox-1.35.0/debian/busybox-syslogd.service busybox-1.36.1/debian/busybox-syslogd.service --- busybox-1.35.0/debian/busybox-syslogd.service 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/busybox-syslogd.service 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,21 @@ +[Unit] +Description=Busybox syslogd system logging daemon +Documentation=man:busybox(1) +# Can use remote-fs.target and network.target as dependencies, +# to put logs to a remote filesystem or to log over network. +# For a small stand-alone system it is usually not needed. +#After=remote-fs.target +#After=network.target + +[Service] +Environment=SYSLOG_OPTS= +EnvironmentFile=-/etc/default/busybox-syslogd +# Assume "started" state begin after fork only. Do not use -n. +Type=forking +ExecStart=/sbin/syslogd $SYSLOG_OPTS +Restart=on-failure + +[Install] +WantedBy=multi-user.target +Alias=syslog.service +Also=busybox-klogd.service diff -Nru busybox-1.35.0/debian/busybox-udeb.install busybox-1.36.1/debian/busybox-udeb.install --- busybox-1.35.0/debian/busybox-udeb.install 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/busybox-udeb.install 2023-07-05 16:04:48.000000000 +0000 @@ -1 +1,2 @@ +b/udeb/busybox bin/ debian/tree/busybox-udeb/* / diff -Nru busybox-1.35.0/debian/changelog busybox-1.36.1/debian/changelog --- busybox-1.35.0/debian/changelog 2022-11-23 15:44:44.000000000 +0000 +++ busybox-1.36.1/debian/changelog 2023-07-06 00:03:13.000000000 +0000 @@ -1,3 +1,97 @@ +busybox (1:1.36.1-3ubuntu1) mantic; urgency=medium + + * Refresh d/config/pkg/initramfs for new upstream version. New values based + on 'deb' config. + * Drop delta to the udeb config + * Merge from Debian unstable. Remaining changes: + - test-bin.patch: Move test and friends to /bin. + - static-sh-alias.patch: Add static-sh alias name for ash, and install + /bin/static-sh symlink to busybox in busybox-static. + - Add busybox-initramfs. + - debian/config/pkg/deb + debian/config/pkg/static: + Enable chpasswd in standard and static builds (needed by LXC). + - Move zz-busybox to busybox-initramfs to ensure we get links to all + the tools we need, stop shipping it anywhere else. + - Prefer busybox commands over klibc commands where there is duplication. + - Add Ubuntu configuration for busybox binaries. + - Enable the new klibc utility implementations, nuke and run-init + in the initramfs package; and also enable reboot. Doesn't yet make + klibc-utils irrelevant - we still use ipconfig, fstype, and nfsmount + - but it moves us much closer and should save a little bit of disk + space. + - debian/config/pkg/initramfs: Enable the date applet with the same + options as the other variants for use in fixrtc and casper scripts. + - debian/config/pkg/initramfs + debian/tree/busybox/usr/share/initramfs-tools/hooks/zz-busybox: + Enable TLS in initramfs flavour of wget applet, requires openssl + - Add dirname from coreutils to the initramfs + + -- Dan Bungert Wed, 05 Jul 2023 18:03:13 -0600 + +busybox (1:1.36.1-3) unstable; urgency=medium + + * syslogd-avoid-nulling-devlog.patch - fix overriding dev/log + socket with dev/null in previous (upstream) patch. + + -- Michael Tokarev Thu, 15 Jun 2023 00:01:54 +0300 + +busybox (1:1.36.1-2) unstable; urgency=medium + + * replace syslog init patch with better version from upstream: + syslogd-decrease-stack-usage-50-bytes.patch (prep) + syslogd-daemonize-after-init-make-errs-visible.patch + * platform-linux.diff: nbd is also linux-only + * udhcpd: remove obsolete copy of udhcpd.conf, + use one from examples/udhcp/udhcpd.conf + * remove "remaining" parameter from udhcpd.conf.5 (Closes: #891757) + * d/*.lintian-overrides: add #!/bin/busybox overrides for the init scripts + + -- Michael Tokarev Wed, 14 Jun 2023 23:10:23 +0300 + +busybox (1:1.36.1-1) unstable; urgency=medium + + * new upstream release 1.36.0 (and bugfix release 1.36.1) + (Closes: CVE-2022-30065, use after free in awk) + * use-libresolv-on-non-linux-too.patch: remove for now + (upstream did it in a different, incomplete way) + * spelling.diff: remove hunks which are applied upstream + * fix-non-linux-build.patch: remove hunks which are applied upstream + * refresh configs: enable ash sleep builtin, sha1/sha256 hwaccel, + loop configure ioctl. + New applets (tsort, seedrngm, tree) are not enabled + * d/control: remove lsb-base from Depends of busybox-syslogd & udhcpd + lsb-base was in Depends becase it provided /lib/lsb/init-functions + file for the sysvinit initscripts in these packages. Now, sysvinit-utils + has eaten this file. But this package is essential, so there's no need + to depend on things providing init-functions anymore. + * move udhcpd files from debian/tree/udhcpd/ to debian/ + * deb,static: enable nbd-client applet (Closes: #893843) + * d/control: bump Standards-Version to 4.6.2 (no changes) + * deb,static: enable nbd-client applet (Closes: #893843) + * syslogd: + - deb,static: enable syslog.conf and log rotation support for syslogd + (Closes: #857760) + - +syslogd-fork-after-init-not-before.patch: + make syslogd init failures and error messages visible + - busybox-syslogd package: + - rewrite busybox-syslogd.init and busybox-klogd.init: + - provide simple busybox-syslogd.service and busybox-klogd.service + for systemd (Closes: #907189) + - ship simple /etc/syslog.conf and syslog.conf.txt in docs + * d/control: fix udhcpc & udhcpd names + * udhcpc & udhcpd: make them Architecture: all instead of (linux-)any. + The packages does not have any architecture-dependent parts at all + (just the startup scripts), the only reason to make them arch-any is + to exclude non-linux architectures. But it seems it isn't worth the + efforts really. Both packages becomes installable on non-linux but + will not work. + * udhcpd: rewrite the startup script + * d/rules: adjust arch/indep rules so it build just the required parts, + simplify install/link rules + + -- Michael Tokarev Thu, 08 Jun 2023 11:36:09 +0300 + busybox (1:1.35.0-4ubuntu1) lunar; urgency=low * Merge from Debian unstable. Remaining changes: diff -Nru busybox-1.35.0/debian/config/pkg/deb busybox-1.36.1/debian/config/pkg/deb --- busybox-1.35.0/debian/config/pkg/deb 2022-11-06 15:44:41.000000000 +0000 +++ busybox-1.36.1/debian/config/pkg/deb 2023-07-05 16:18:16.000000000 +0000 @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.35.0 +# Busybox version: 1.36.1 # CONFIG_HAVE_DOT_CONFIG=y CONFIG_PLATFORM_LINUX=y @@ -93,6 +93,9 @@ # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 +CONFIG_SHA1_SMALL=1 +CONFIG_SHA1_HWACCEL=y +CONFIG_SHA256_HWACCEL=y CONFIG_SHA3_SMALL=0 # CONFIG_FEATURE_NON_POSIX_CP is not set CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y @@ -123,6 +126,9 @@ # CONFIG_UNICODE_BIDI_SUPPORT is not set # CONFIG_UNICODE_NEUTRAL_TABLE is not set # CONFIG_UNICODE_PRESERVE_BROKEN is not set +# CONFIG_LOOP_CONFIGURE is not set +# CONFIG_NO_LOOP_CONFIGURE is not set +CONFIG_TRY_LOOP_CONFIGURE=y # # Applets @@ -338,6 +344,7 @@ CONFIG_FEATURE_TR_EQUIV=y CONFIG_TRUE=y CONFIG_TRUNCATE=y +# CONFIG_TSORT is not set CONFIG_TTY=y CONFIG_UNAME=y CONFIG_UNAME_OSNAME="GNU/Linux" @@ -831,10 +838,12 @@ # CONFIG_RFKILL is not set # CONFIG_RUNLEVEL is not set # CONFIG_RX is not set +# CONFIG_SEEDRNG is not set # CONFIG_SETFATTR is not set # CONFIG_SETSERIAL is not set CONFIG_STRINGS=y CONFIG_TIME=y +# CONFIG_TREE is not set CONFIG_TS=y # CONFIG_TTYSIZE is not set # CONFIG_UBIATTACH is not set @@ -936,7 +945,7 @@ # CONFIG_FAKEIDENTD is not set CONFIG_NAMEIF=y # CONFIG_FEATURE_NAMEIF_EXTENDED is not set -# CONFIG_NBDCLIENT is not set +CONFIG_NBDCLIENT=y CONFIG_NC=y # CONFIG_NETCAT is not set CONFIG_NC_SERVER=y @@ -1007,6 +1016,7 @@ CONFIG_FEATURE_UDHCPC_ARPING=y CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y CONFIG_UDHCPC_DEFAULT_SCRIPT="/etc/udhcpc/default.script" +CONFIG_UDHCPC6_DEFAULT_SCRIPT="" # CONFIG_UDHCPC6 is not set # CONFIG_FEATURE_UDHCPC6_RFC3646 is not set # CONFIG_FEATURE_UDHCPC6_RFC4704 is not set @@ -1141,6 +1151,7 @@ CONFIG_ASH_ECHO=y CONFIG_ASH_PRINTF=y CONFIG_ASH_TEST=y +CONFIG_ASH_SLEEP=y CONFIG_ASH_HELP=y CONFIG_ASH_GETOPTS=y CONFIG_ASH_CMDCMD=y @@ -1206,10 +1217,10 @@ CONFIG_LOGREAD=y # CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set CONFIG_SYSLOGD=y -# CONFIG_FEATURE_ROTATE_LOGFILE is not set +CONFIG_FEATURE_ROTATE_LOGFILE=y CONFIG_FEATURE_REMOTE_LOG=y -# CONFIG_FEATURE_SYSLOGD_DUP is not set -# CONFIG_FEATURE_SYSLOGD_CFG is not set +CONFIG_FEATURE_SYSLOGD_DUP=y +CONFIG_FEATURE_SYSLOGD_CFG=y # CONFIG_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS is not set CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=1024 CONFIG_FEATURE_IPC_SYSLOG=y diff -Nru busybox-1.35.0/debian/config/pkg/initramfs busybox-1.36.1/debian/config/pkg/initramfs --- busybox-1.35.0/debian/config/pkg/initramfs 2022-11-23 15:44:44.000000000 +0000 +++ busybox-1.36.1/debian/config/pkg/initramfs 2023-07-05 16:18:38.000000000 +0000 @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.35.0 +# Busybox version: 1.36.1 # CONFIG_HAVE_DOT_CONFIG=y CONFIG_PLATFORM_LINUX=y @@ -93,6 +93,9 @@ # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 +CONFIG_SHA1_SMALL=1 +CONFIG_SHA1_HWACCEL=y +CONFIG_SHA256_HWACCEL=y CONFIG_SHA3_SMALL=1 CONFIG_FEATURE_NON_POSIX_CP=y # CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set @@ -123,6 +126,9 @@ # CONFIG_UNICODE_BIDI_SUPPORT is not set # CONFIG_UNICODE_NEUTRAL_TABLE is not set # CONFIG_UNICODE_PRESERVE_BROKEN is not set +# CONFIG_LOOP_CONFIGURE is not set +# CONFIG_NO_LOOP_CONFIGURE is not set +CONFIG_TRY_LOOP_CONFIGURE=y # # Applets @@ -334,6 +340,7 @@ # CONFIG_FEATURE_TR_EQUIV is not set CONFIG_TRUE=y # CONFIG_TRUNCATE is not set +# CONFIG_TSORT is not set CONFIG_TTY=y CONFIG_UNAME=y CONFIG_UNAME_OSNAME="GNU/Linux" @@ -823,10 +830,12 @@ # CONFIG_RFKILL is not set # CONFIG_RUNLEVEL is not set # CONFIG_RX is not set +# CONFIG_SEEDRNG is not set # CONFIG_SETFATTR is not set # CONFIG_SETSERIAL is not set # CONFIG_STRINGS is not set # CONFIG_TIME is not set +# CONFIG_TREE is not set CONFIG_TS=y # CONFIG_TTYSIZE is not set # CONFIG_UBIATTACH is not set @@ -999,6 +1008,7 @@ # CONFIG_FEATURE_UDHCPC_ARPING is not set # CONFIG_FEATURE_UDHCPC_SANITIZEOPT is not set CONFIG_UDHCPC_DEFAULT_SCRIPT="" +CONFIG_UDHCPC6_DEFAULT_SCRIPT="" # CONFIG_UDHCPC6 is not set # CONFIG_FEATURE_UDHCPC6_RFC3646 is not set # CONFIG_FEATURE_UDHCPC6_RFC4704 is not set @@ -1129,6 +1139,7 @@ CONFIG_ASH_ECHO=y CONFIG_ASH_PRINTF=y CONFIG_ASH_TEST=y +CONFIG_ASH_SLEEP=y CONFIG_ASH_HELP=y CONFIG_ASH_GETOPTS=y CONFIG_ASH_CMDCMD=y diff -Nru busybox-1.35.0/debian/config/pkg/static busybox-1.36.1/debian/config/pkg/static --- busybox-1.35.0/debian/config/pkg/static 2022-11-06 15:44:41.000000000 +0000 +++ busybox-1.36.1/debian/config/pkg/static 2023-07-05 16:18:16.000000000 +0000 @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.35.0 +# Busybox version: 1.36.1 # CONFIG_HAVE_DOT_CONFIG=y CONFIG_PLATFORM_LINUX=y @@ -93,6 +93,9 @@ # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 +CONFIG_SHA1_SMALL=1 +CONFIG_SHA1_HWACCEL=y +CONFIG_SHA256_HWACCEL=y CONFIG_SHA3_SMALL=0 # CONFIG_FEATURE_NON_POSIX_CP is not set CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y @@ -123,6 +126,9 @@ # CONFIG_UNICODE_BIDI_SUPPORT is not set # CONFIG_UNICODE_NEUTRAL_TABLE is not set # CONFIG_UNICODE_PRESERVE_BROKEN is not set +# CONFIG_LOOP_CONFIGURE is not set +# CONFIG_NO_LOOP_CONFIGURE is not set +CONFIG_TRY_LOOP_CONFIGURE=y # # Applets @@ -338,6 +344,7 @@ CONFIG_FEATURE_TR_EQUIV=y CONFIG_TRUE=y CONFIG_TRUNCATE=y +# CONFIG_TSORT is not set CONFIG_TTY=y CONFIG_UNAME=y CONFIG_UNAME_OSNAME="GNU/Linux" @@ -831,10 +838,12 @@ # CONFIG_RFKILL is not set # CONFIG_RUNLEVEL is not set # CONFIG_RX is not set +# CONFIG_SEEDRNG is not set # CONFIG_SETFATTR is not set # CONFIG_SETSERIAL is not set CONFIG_STRINGS=y CONFIG_TIME=y +# CONFIG_TREE is not set CONFIG_TS=y # CONFIG_TTYSIZE is not set # CONFIG_UBIATTACH is not set @@ -936,7 +945,7 @@ # CONFIG_FAKEIDENTD is not set CONFIG_NAMEIF=y # CONFIG_FEATURE_NAMEIF_EXTENDED is not set -# CONFIG_NBDCLIENT is not set +CONFIG_NBDCLIENT=y CONFIG_NC=y # CONFIG_NETCAT is not set CONFIG_NC_SERVER=y @@ -1007,6 +1016,7 @@ CONFIG_FEATURE_UDHCPC_ARPING=y CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y CONFIG_UDHCPC_DEFAULT_SCRIPT="/etc/udhcpc/default.script" +CONFIG_UDHCPC6_DEFAULT_SCRIPT="" # CONFIG_UDHCPC6 is not set # CONFIG_FEATURE_UDHCPC6_RFC3646 is not set # CONFIG_FEATURE_UDHCPC6_RFC4704 is not set @@ -1141,6 +1151,7 @@ CONFIG_ASH_ECHO=y CONFIG_ASH_PRINTF=y CONFIG_ASH_TEST=y +CONFIG_ASH_SLEEP=y CONFIG_ASH_HELP=y CONFIG_ASH_GETOPTS=y CONFIG_ASH_CMDCMD=y @@ -1206,10 +1217,10 @@ CONFIG_LOGREAD=y # CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set CONFIG_SYSLOGD=y -# CONFIG_FEATURE_ROTATE_LOGFILE is not set +CONFIG_FEATURE_ROTATE_LOGFILE=y CONFIG_FEATURE_REMOTE_LOG=y -# CONFIG_FEATURE_SYSLOGD_DUP is not set -# CONFIG_FEATURE_SYSLOGD_CFG is not set +CONFIG_FEATURE_SYSLOGD_DUP=y +CONFIG_FEATURE_SYSLOGD_CFG=y # CONFIG_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS is not set CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=1024 CONFIG_FEATURE_IPC_SYSLOG=y diff -Nru busybox-1.35.0/debian/config/pkg/udeb busybox-1.36.1/debian/config/pkg/udeb --- busybox-1.35.0/debian/config/pkg/udeb 2022-11-06 15:44:41.000000000 +0000 +++ busybox-1.36.1/debian/config/pkg/udeb 2023-07-05 16:18:44.000000000 +0000 @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.35.0 +# Busybox version: 1.36.1 # CONFIG_HAVE_DOT_CONFIG=y CONFIG_PLATFORM_LINUX=y @@ -93,6 +93,9 @@ # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 +CONFIG_SHA1_SMALL=1 +CONFIG_SHA1_HWACCEL=y +CONFIG_SHA256_HWACCEL=y CONFIG_SHA3_SMALL=1 # CONFIG_FEATURE_NON_POSIX_CP is not set CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y @@ -123,6 +126,9 @@ # CONFIG_UNICODE_BIDI_SUPPORT is not set # CONFIG_UNICODE_NEUTRAL_TABLE is not set # CONFIG_UNICODE_PRESERVE_BROKEN is not set +# CONFIG_LOOP_CONFIGURE is not set +# CONFIG_NO_LOOP_CONFIGURE is not set +CONFIG_TRY_LOOP_CONFIGURE=y # # Applets @@ -293,7 +299,7 @@ # CONFIG_NL is not set # CONFIG_NOHUP is not set # CONFIG_NPROC is not set -CONFIG_OD=y +# CONFIG_OD is not set # CONFIG_PASTE is not set # CONFIG_PRINTENV is not set CONFIG_PRINTF=y @@ -313,8 +319,8 @@ # CONFIG_FEATURE_SORT_OPTIMIZE_MEMORY is not set # CONFIG_SPLIT is not set # CONFIG_FEATURE_SPLIT_FANCY is not set -CONFIG_STAT=y -CONFIG_FEATURE_STAT_FORMAT=y +# CONFIG_STAT is not set +# CONFIG_FEATURE_STAT_FORMAT is not set # CONFIG_FEATURE_STAT_FILESYSTEM is not set CONFIG_STTY=y # CONFIG_SUM is not set @@ -338,6 +344,7 @@ # CONFIG_FEATURE_TR_EQUIV is not set CONFIG_TRUE=y # CONFIG_TRUNCATE is not set +# CONFIG_TSORT is not set CONFIG_TTY=y CONFIG_UNAME=y CONFIG_UNAME_OSNAME="GNU/Linux" @@ -360,7 +367,7 @@ # # Console Utilities # -CONFIG_CHVT=y +# CONFIG_CHVT is not set # CONFIG_CLEAR is not set # CONFIG_DEALLOCVT is not set # CONFIG_DUMPKMAP is not set @@ -636,7 +643,7 @@ # CONFIG_IPCS is not set # CONFIG_LAST is not set # CONFIG_FEATURE_LAST_FANCY is not set -CONFIG_LOSETUP=y +# CONFIG_LOSETUP is not set # CONFIG_LSPCI is not set # CONFIG_LSUSB is not set # CONFIG_MDEV is not set @@ -661,7 +668,7 @@ CONFIG_MOUNT=y CONFIG_FEATURE_MOUNT_FAKE=y # CONFIG_FEATURE_MOUNT_VERBOSE is not set -CONFIG_FEATURE_MOUNT_HELPERS=y +# CONFIG_FEATURE_MOUNT_HELPERS is not set # CONFIG_FEATURE_MOUNT_LABEL is not set # CONFIG_FEATURE_MOUNT_NFS is not set # CONFIG_FEATURE_MOUNT_CIFS is not set @@ -823,10 +830,12 @@ # CONFIG_RFKILL is not set # CONFIG_RUNLEVEL is not set # CONFIG_RX is not set +# CONFIG_SEEDRNG is not set # CONFIG_SETFATTR is not set # CONFIG_SETSERIAL is not set # CONFIG_STRINGS is not set # CONFIG_TIME is not set +# CONFIG_TREE is not set # CONFIG_TS is not set # CONFIG_TTYSIZE is not set # CONFIG_UBIATTACH is not set @@ -999,6 +1008,7 @@ CONFIG_FEATURE_UDHCPC_ARPING=y CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y CONFIG_UDHCPC_DEFAULT_SCRIPT="/etc/udhcpc/default.script" +CONFIG_UDHCPC6_DEFAULT_SCRIPT="" # CONFIG_UDHCPC6 is not set # CONFIG_FEATURE_UDHCPC6_RFC3646 is not set # CONFIG_FEATURE_UDHCPC6_RFC4704 is not set @@ -1043,7 +1053,7 @@ # CONFIG_FUSER is not set # CONFIG_IOSTAT is not set CONFIG_KILL=y -CONFIG_KILLALL=y +# CONFIG_KILLALL is not set # CONFIG_KILLALL5 is not set # CONFIG_LSOF is not set # CONFIG_MPSTAT is not set @@ -1133,6 +1143,7 @@ CONFIG_ASH_ECHO=y CONFIG_ASH_PRINTF=y CONFIG_ASH_TEST=y +CONFIG_ASH_SLEEP=y CONFIG_ASH_HELP=y CONFIG_ASH_GETOPTS=y CONFIG_ASH_CMDCMD=y diff -Nru busybox-1.35.0/debian/control busybox-1.36.1/debian/control --- busybox-1.35.0/debian/control 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/control 2023-07-05 16:18:16.000000000 +0000 @@ -9,7 +9,7 @@ Michael Tokarev , Build-Depends: debhelper-compat (= 13), zip -Standards-Version: 4.1.5 +Standards-Version: 4.6.2 Vcs-Git: https://salsa.debian.org/installer-team/busybox.git Vcs-Browser: https://salsa.debian.org/installer-team/busybox Homepage: http://www.busybox.net @@ -32,7 +32,7 @@ This package installs the BusyBox binary but does not install symlinks for any of the supported utilities. Some of the utilities can be used in the system by installing the busybox-syslogd, - busybox-udhcpc or busybox-udhcpd packages. + udhcpc or udhcpd packages. Package: busybox-static Architecture: any @@ -97,7 +97,6 @@ Pre-Depends: ${misc:Pre-Depends} Depends: busybox (>> ${source:Upstream-Version}) | busybox-static (>> ${source:Upstream-Version}), - lsb-base, ${misc:Depends}, Provides: linux-kernel-log-daemon, system-log-daemon Conflicts: linux-kernel-log-daemon, system-log-daemon @@ -122,15 +121,15 @@ Package: udhcpc Section: net -Architecture: linux-any +# busybox dhcpc is linux-specific +Architecture: all Pre-Depends: ${misc:Pre-Depends} Depends: busybox (>> ${source:Upstream-Version}) | busybox-static (>> ${source:Upstream-Version}), ${misc:Depends}, -Multi-Arch: same Description: Provides the busybox DHCP client implementation Busybox contains a very small yet fully functional RFC compliant DHCP - client formerly known as udhcpc. + client udhcpc. . This package contains the glue to use the busybox udhcpc as DHCP client in the system by providing the appropriate symbolic links and @@ -138,16 +137,16 @@ Package: udhcpd Section: net -Architecture: linux-any +# busybox dhcpd is linux-specific +Architecture: all Pre-Depends: ${misc:Pre-Depends} Depends: busybox (>> ${source:Upstream-Version}) | busybox-static (>> ${source:Upstream-Version}), - lsb-base, ${misc:Depends}, Provides: dhcpd Description: Provides the busybox DHCP server implementation Busybox contains a very small yet fully function RFC compliant DHCP - server formerly known as udhcpd. + server udhcpd. . This package contains the glue to use the busybox udhcpd as DHCP server in the system by providing the appropriate symbolic links and diff -Nru busybox-1.35.0/debian/patches/fix-non-linux-build.patch busybox-1.36.1/debian/patches/fix-non-linux-build.patch --- busybox-1.35.0/debian/patches/fix-non-linux-build.patch 2022-11-04 16:59:00.000000000 +0000 +++ busybox-1.36.1/debian/patches/fix-non-linux-build.patch 2023-07-05 16:04:48.000000000 +0000 @@ -4,82 +4,6 @@ Some features are Linux-only. -Also, libresolv is used on all GNU platforms, notably GNU/Hurd and -GNU/kfreeBSD. - -diff --git a/coreutils/dd.c b/coreutils/dd.c -index 06c1b7b9c..3e034eb1e 100644 ---- a/coreutils/dd.c -+++ b/coreutils/dd.c -@@ -200,6 +200,7 @@ static void dd_output_status(int UNUSED_PARAM cur_signal) - } - - #if ENABLE_FEATURE_DD_IBS_OBS -+# ifdef O_DIRECT - static int clear_O_DIRECT(int fd) - { - if (errno == EINVAL) { -@@ -211,6 +212,7 @@ static int clear_O_DIRECT(int fd) - } - return 0; - } -+# endif - #endif - - static ssize_t dd_read(void *ibuf, size_t ibs) -@@ -225,8 +227,10 @@ static ssize_t dd_read(void *ibuf, size_t ibs) - #endif - n = safe_read(ifd, ibuf, ibs); - #if ENABLE_FEATURE_DD_IBS_OBS -+# ifdef O_DIRECT - if (n < 0 && (G.flags & FLAG_IDIRECT) && clear_O_DIRECT(ifd)) - goto read_again; -+# endif - #endif - return n; - } -@@ -239,8 +243,10 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs, - IF_FEATURE_DD_IBS_OBS(write_again:) - n = full_write(ofd, buf, len); - #if ENABLE_FEATURE_DD_IBS_OBS -+# ifdef O_DIRECT - if (n < 0 && (G.flags & FLAG_ODIRECT) && clear_O_DIRECT(ofd)) - goto write_again; -+# endif - #endif - - #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE -@@ -501,8 +507,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) - if (infile) { - int iflag = O_RDONLY; - #if ENABLE_FEATURE_DD_IBS_OBS -- if (G.flags & FLAG_IDIRECT) -+ if (G.flags & FLAG_IDIRECT) { -+# ifdef O_DIRECT - iflag |= O_DIRECT; -+# else -+ bb_error_msg_and_die("O_DIRECT not supported on this platform"); -+# endif -+ } - #endif - xmove_fd(xopen(infile, iflag), ifd); - } else { -@@ -516,8 +527,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) - if (G.flags & FLAG_APPEND) - oflag |= O_APPEND; - #if ENABLE_FEATURE_DD_IBS_OBS -- if (G.flags & FLAG_ODIRECT) -+ if (G.flags & FLAG_ODIRECT) { -+# ifdef O_DIRECT - oflag |= O_DIRECT; -+# else -+ bb_error_msg_and_die("O_DIRECT not supported on this platform"); -+# endif -+ } - #endif - xmove_fd(xopen(outfile, oflag), ofd); - - diff --git a/networking/traceroute.c b/networking/traceroute.c index 4bbe1ab8e..2ba990fd0 100644 --- a/networking/traceroute.c diff -Nru busybox-1.35.0/debian/patches/platform-linux.diff busybox-1.36.1/debian/patches/platform-linux.diff --- busybox-1.35.0/debian/patches/platform-linux.diff 2022-11-04 16:59:00.000000000 +0000 +++ busybox-1.36.1/debian/patches/platform-linux.diff 2023-07-05 16:04:48.000000000 +0000 @@ -1747,6 +1747,15 @@ //config: select LONG_OPTS //config: help //config: Run program with some namespaces unshared from parent. --- -2.30.2 - +diff --git a/networking/nbd-client.c b/networking/nbd-client.c +index 755b42ccd..c9960fbe6 100644 +--- a/networking/nbd-client.c ++++ b/networking/nbd-client.c +@@ -5,6 +5,7 @@ + */ + //config:config NBDCLIENT + //config: bool "nbd-client (6 kb)" ++//config: depends on PLATFORM_LINUX + //config: default y + //config: help + //config: Network block device client diff -Nru busybox-1.35.0/debian/patches/series busybox-1.36.1/debian/patches/series --- busybox-1.35.0/debian/patches/series 2022-11-21 18:50:51.000000000 +0000 +++ busybox-1.36.1/debian/patches/series 2023-07-05 16:18:16.000000000 +0000 @@ -17,4 +17,7 @@ static-sh-alias.patch platform-linux.diff fix-non-linux-build.patch -use-libresolv-on-non-linux-too.patch +# +syslogd-decrease-stack-usage-50-bytes.patch +syslogd-daemonize-after-init-make-errs-visible.patch +syslogd-avoid-nulling-devlog.patch diff -Nru busybox-1.35.0/debian/patches/spelling.diff busybox-1.36.1/debian/patches/spelling.diff --- busybox-1.35.0/debian/patches/spelling.diff 2022-11-21 18:56:26.000000000 +0000 +++ busybox-1.36.1/debian/patches/spelling.diff 2023-07-05 16:04:48.000000000 +0000 @@ -15,23 +15,3 @@ //usage: "\n -f LIST Print only these fields (-d is single char)" //usage: IF_FEATURE_CUT_REGEX( //usage: "\n -F LIST Print only these fields (-d is regex)" ---- a/networking/ping.c -+++ b/networking/ping.c -@@ -74,7 +74,7 @@ - //usage: "\n -c CNT Send only CNT pings" - //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" - //usage: "\n -i SECS Interval" --//usage: "\n -A Ping as soon as reply is recevied" -+//usage: "\n -A Ping as soon as reply is received" - //usage: "\n -t TTL Set TTL" - //usage: "\n -I IFACE/IP Source interface or IP address" - //usage: "\n -W SEC Seconds to wait for the first response (default 10)" -@@ -91,7 +91,7 @@ - //usage: "\n -c CNT Send only CNT pings" - //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" - //usage: "\n -i SECS Interval" --//usage: "\n -A Ping as soon as reply is recevied" -+//usage: "\n -A Ping as soon as reply is received" - ///////: "\n -t TTL Set TTL" - ///////^^^^^ -t not tested for IPv6, might be not working - //usage: "\n -I IFACE/IP Source interface or IP address" diff -Nru busybox-1.35.0/debian/patches/syslogd-avoid-nulling-devlog.patch busybox-1.36.1/debian/patches/syslogd-avoid-nulling-devlog.patch --- busybox-1.35.0/debian/patches/syslogd-avoid-nulling-devlog.patch 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/patches/syslogd-avoid-nulling-devlog.patch 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,28 @@ +--- busybox.orig/sysklogd/syslogd.c ++++ busybox/sysklogd/syslogd.c +@@ -1009,6 +1009,7 @@ static int try_to_resolve_remote(remoteH + static int NOINLINE syslogd_init(char **argv) + { + int opts; ++ int fd; + char OPTION_DECL; + #if ENABLE_FEATURE_REMOTE_LOG + llist_t *remoteAddrList = NULL; +@@ -1056,7 +1057,7 @@ static int NOINLINE syslogd_init(char ** + G.hostname = safe_gethostname(); + *strchrnul(G.hostname, '.') = '\0'; + +- xmove_fd(create_socket(), STDIN_FILENO); ++ fd = create_socket(); + + if (opts & OPT_circularlog) + ipcsyslog_init(); +@@ -1068,6 +1069,8 @@ static int NOINLINE syslogd_init(char ** + bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); + } + ++ xmove_fd(fd, STDIN_FILENO); ++ + /* Set up signal handlers (so that they interrupt read()) */ + signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo); + signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); diff -Nru busybox-1.35.0/debian/patches/syslogd-daemonize-after-init-make-errs-visible.patch busybox-1.36.1/debian/patches/syslogd-daemonize-after-init-make-errs-visible.patch --- busybox-1.35.0/debian/patches/syslogd-daemonize-after-init-make-errs-visible.patch 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/patches/syslogd-daemonize-after-init-make-errs-visible.patch 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,48 @@ +From 373f64eef3cc121d7531522ef654feb0a8068d5a Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Tue, 13 Jun 2023 16:25:13 +0200 +Subject: [PATCH] syslogd: daemonize _after_ init (so that init errors are + visible, if they occur) + +Signed-off-by: Denys Vlasenko +--- + sysklogd/syslogd.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c +index 20034e969..7711e467b 100644 +--- a/sysklogd/syslogd.c ++++ b/sysklogd/syslogd.c +@@ -1055,6 +1055,14 @@ static int NOINLINE syslogd_init(char **argv) + G.hostname = safe_gethostname(); + *strchrnul(G.hostname, '.') = '\0'; + ++ xmove_fd(create_socket(), STDIN_FILENO); ++ ++ if (opts & OPT_circularlog) ++ ipcsyslog_init(); ++ ++ if (opts & OPT_kmsg) ++ kmsg_init(); ++ + if (!(opts & OPT_nofork)) { + bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); + } +@@ -1068,14 +1076,6 @@ static int NOINLINE syslogd_init(char **argv) + signal(SIGALRM, do_mark); + alarm(G.markInterval); + #endif +- xmove_fd(create_socket(), STDIN_FILENO); +- +- if (opts & OPT_circularlog) +- ipcsyslog_init(); +- +- if (opts & OPT_kmsg) +- kmsg_init(); +- + return opts; + } + +-- +2.39.2 + diff -Nru busybox-1.35.0/debian/patches/syslogd-decrease-stack-usage-50-bytes.patch busybox-1.36.1/debian/patches/syslogd-decrease-stack-usage-50-bytes.patch --- busybox-1.35.0/debian/patches/syslogd-decrease-stack-usage-50-bytes.patch 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/patches/syslogd-decrease-stack-usage-50-bytes.patch 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,231 @@ +From 02378ce20c6d2df062357b6d60fc440609d203be Mon Sep 17 00:00:00 2001 +From: Denys Vlasenko +Date: Tue, 13 Jun 2023 16:16:37 +0200 +Subject: [PATCH] syslogd: decrease stack usage, ~50 bytes + +function old new delta +syslogd_init - 1007 +1007 +syslogd_main 1619 636 -983 +------------------------------------------------------------------------------ +(add/remove: 1/0 grow/shrink: 0/1 up/down: 1007/-983) Total: 24 bytes + +Signed-off-by: Denys Vlasenko +--- + sysklogd/syslogd.c | 156 +++++++++++++++++++++++---------------------- + 1 file changed, 81 insertions(+), 75 deletions(-) + +diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c +index 6ddfd771a..20034e969 100644 +--- a/sysklogd/syslogd.c ++++ b/sysklogd/syslogd.c +@@ -1002,20 +1002,63 @@ static int try_to_resolve_remote(remoteHost_t *rh) + } + #endif + +-static void do_syslogd(void) NORETURN; +-static void do_syslogd(void) ++/* By doing init in a separate function we decrease stack usage ++ * in main loop. ++ */ ++static int NOINLINE syslogd_init(char **argv) + { ++ int opts; ++ char OPTION_DECL; + #if ENABLE_FEATURE_REMOTE_LOG +- llist_t *item; ++ llist_t *remoteAddrList = NULL; + #endif +-#if ENABLE_FEATURE_SYSLOGD_DUP +- int last_sz = -1; +- char *last_buf; +- char *recvbuf = G.recvbuf; +-#else +-#define recvbuf (G.recvbuf) ++ ++ /* No non-option params */ ++ opts = getopt32(argv, "^"OPTION_STR"\0""=0", OPTION_PARAM); ++#if ENABLE_FEATURE_REMOTE_LOG ++ while (remoteAddrList) { ++ remoteHost_t *rh = xzalloc(sizeof(*rh)); ++ rh->remoteHostname = llist_pop(&remoteAddrList); ++ rh->remoteFD = -1; ++ rh->last_dns_resolve = monotonic_sec() - DNS_WAIT_SEC - 1; ++ llist_add_to(&G.remoteHosts, rh); ++ } + #endif + ++#ifdef SYSLOGD_MARK ++ if (opts & OPT_mark) // -m ++ G.markInterval = xatou_range(opt_m, 0, INT_MAX/60) * 60; ++#endif ++ //if (opts & OPT_nofork) // -n ++ //if (opts & OPT_outfile) // -O ++ if (opts & OPT_loglevel) // -l ++ G.logLevel = xatou_range(opt_l, 1, 8); ++ //if (opts & OPT_small) // -S ++#if ENABLE_FEATURE_ROTATE_LOGFILE ++ if (opts & OPT_filesize) // -s ++ G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024; ++ if (opts & OPT_rotatecnt) // -b ++ G.logFileRotate = xatou_range(opt_b, 0, 99); ++#endif ++#if ENABLE_FEATURE_IPC_SYSLOG ++ if (opt_C) // -Cn ++ G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; ++#endif ++ /* If they have not specified remote logging, then log locally */ ++ if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R ++ option_mask32 |= OPT_locallog; ++#if ENABLE_FEATURE_SYSLOGD_CFG ++ parse_syslogdcfg(opt_f); ++#endif ++ ++ /* Store away localhost's name before the fork */ ++ G.hostname = safe_gethostname(); ++ *strchrnul(G.hostname, '.') = '\0'; ++ ++ if (!(opts & OPT_nofork)) { ++ bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); ++ } ++ + /* Set up signal handlers (so that they interrupt read()) */ + signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo); + signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); +@@ -1027,15 +1070,39 @@ static void do_syslogd(void) + #endif + xmove_fd(create_socket(), STDIN_FILENO); + +- if (option_mask32 & OPT_circularlog) ++ if (opts & OPT_circularlog) + ipcsyslog_init(); + +- if (option_mask32 & OPT_kmsg) ++ if (opts & OPT_kmsg) + kmsg_init(); + ++ return opts; ++} ++ ++int syslogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; ++int syslogd_main(int argc UNUSED_PARAM, char **argv) ++{ ++ int opts; ++#if ENABLE_FEATURE_REMOTE_LOG ++ llist_t *item; ++#endif ++#if ENABLE_FEATURE_SYSLOGD_DUP ++ int last_sz = -1; ++ char *last_buf; ++ char *recvbuf; ++#else ++#define recvbuf (G.recvbuf) ++#endif ++ ++ INIT_G(); ++ opts = syslogd_init(argv); ++ + timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER); + write_pidfile_std_path_and_ext("syslogd"); + ++#if ENABLE_FEATURE_SYSLOGD_DUP ++ recvbuf = G.recvbuf; ++#endif + while (!bb_got_signal) { + ssize_t sz; + +@@ -1070,7 +1137,7 @@ static void do_syslogd(void) + sz--; + } + #if ENABLE_FEATURE_SYSLOGD_DUP +- if ((option_mask32 & OPT_dup) && (sz == last_sz)) ++ if ((opts & OPT_dup) && (sz == last_sz)) + if (memcmp(last_buf, recvbuf, sz) == 0) + continue; + last_sz = sz; +@@ -1111,7 +1178,7 @@ static void do_syslogd(void) + } + } + #endif +- if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) { ++ if (!ENABLE_FEATURE_REMOTE_LOG || (opts & OPT_locallog)) { + recvbuf[sz] = '\0'; /* ensure it *is* NUL terminated */ + split_escape_and_log(recvbuf, sz); + } +@@ -1120,73 +1187,12 @@ static void do_syslogd(void) + timestamp_and_log_internal("syslogd exiting"); + remove_pidfile_std_path_and_ext("syslogd"); + ipcsyslog_cleanup(); +- if (option_mask32 & OPT_kmsg) ++ if (opts & OPT_kmsg) + kmsg_cleanup(); + kill_myself_with_sig(bb_got_signal); + #undef recvbuf + } + +-int syslogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +-int syslogd_main(int argc UNUSED_PARAM, char **argv) +-{ +- int opts; +- char OPTION_DECL; +-#if ENABLE_FEATURE_REMOTE_LOG +- llist_t *remoteAddrList = NULL; +-#endif +- +- INIT_G(); +- +- /* No non-option params */ +- opts = getopt32(argv, "^"OPTION_STR"\0""=0", OPTION_PARAM); +-#if ENABLE_FEATURE_REMOTE_LOG +- while (remoteAddrList) { +- remoteHost_t *rh = xzalloc(sizeof(*rh)); +- rh->remoteHostname = llist_pop(&remoteAddrList); +- rh->remoteFD = -1; +- rh->last_dns_resolve = monotonic_sec() - DNS_WAIT_SEC - 1; +- llist_add_to(&G.remoteHosts, rh); +- } +-#endif +- +-#ifdef SYSLOGD_MARK +- if (opts & OPT_mark) // -m +- G.markInterval = xatou_range(opt_m, 0, INT_MAX/60) * 60; +-#endif +- //if (opts & OPT_nofork) // -n +- //if (opts & OPT_outfile) // -O +- if (opts & OPT_loglevel) // -l +- G.logLevel = xatou_range(opt_l, 1, 8); +- //if (opts & OPT_small) // -S +-#if ENABLE_FEATURE_ROTATE_LOGFILE +- if (opts & OPT_filesize) // -s +- G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024; +- if (opts & OPT_rotatecnt) // -b +- G.logFileRotate = xatou_range(opt_b, 0, 99); +-#endif +-#if ENABLE_FEATURE_IPC_SYSLOG +- if (opt_C) // -Cn +- G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; +-#endif +- /* If they have not specified remote logging, then log locally */ +- if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R +- option_mask32 |= OPT_locallog; +-#if ENABLE_FEATURE_SYSLOGD_CFG +- parse_syslogdcfg(opt_f); +-#endif +- +- /* Store away localhost's name before the fork */ +- G.hostname = safe_gethostname(); +- *strchrnul(G.hostname, '.') = '\0'; +- +- if (!(opts & OPT_nofork)) { +- bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); +- } +- +- do_syslogd(); +- /* return EXIT_SUCCESS; */ +-} +- + /* Clean up. Needed because we are included from syslogd_and_logger.c */ + #undef DEBUG + #undef SYSLOGD_MARK +-- +2.39.2 + diff -Nru busybox-1.35.0/debian/patches/use-libresolv-on-non-linux-too.patch busybox-1.36.1/debian/patches/use-libresolv-on-non-linux-too.patch --- busybox-1.35.0/debian/patches/use-libresolv-on-non-linux-too.patch 2022-11-04 16:59:00.000000000 +0000 +++ busybox-1.36.1/debian/patches/use-libresolv-on-non-linux-too.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -From: Michael Tokarev -Subject: use libresolv on non-linux too -Date: Fri, 04 Nov 2022 18:10:18 +0300 - -nslookup uses symbols from libresolv, no matter it is -on linux or not. This also eliminates hackish way to -detect linux. - -diff --git a/Makefile.flags b/Makefile.flags -index c34356230..f26ce719e 100644 ---- a/Makefile.flags -+++ b/Makefile.flags -@@ -186,6 +186,4 @@ endif - ifeq ($(CONFIG_FEATURE_NSLOOKUP_BIG),y) --ifneq (,$(findstring linux,$(shell $(CC) $(CFLAGS) -dumpmachine))) - LDLIBS += resolv --endif - endif - diff -Nru busybox-1.35.0/debian/rules busybox-1.36.1/debian/rules --- busybox-1.35.0/debian/rules 2022-11-23 15:44:44.000000000 +0000 +++ busybox-1.36.1/debian/rules 2023-07-05 16:18:44.000000000 +0000 @@ -154,47 +154,30 @@ override_dh_auto_install: -override_dh_install: $(patsubst %,$b/%/.stamp-build, ${flavours}) - dh_install - dh_install -pbusybox ${b}/deb/busybox /bin - dh_install -pbusybox-static ${b}/static/busybox /bin - dh_install -pbusybox-udeb ${b}/udeb/_install/* / +execute_after_dh_install: $(patsubst %,$b/%/.stamp-build, ${flavours}) + install -D debian/tree/busybox/usr/share/initramfs-tools/hooks/zz-busybox debian/busybox-initramfs/usr/share/initramfs-tools/hooks/zz-busybox-initramfs -override_dh_installdocs: - dh_installdocs +execute_after_dh_installdocs: dh_installdocs -pbusybox docs/syslog.conf.txt docs/mdev.txt dh_installdocs -pbusybox-static docs/syslog.conf.txt docs/mdev.txt - dh_install -pbusybox-static $b/static/busybox bin/ - dh_install -pbusybox-static $b/static/docs/busybox.1 usr/share/man/man1/ - dh_install -pbusybox-udeb $b/udeb/busybox bin/ +execute_after_dh_link-arch: # for udeb we also need links. But we can not easily use `make install' # (see comment above). So we run the install rules directly here: dh_link -pbusybox-udeb \ $$(grep -v sbin/init $b/udeb/busybox.links | sed 's|^|/bin/busybox |') -override_dh_installinit: - dh_installinit -pbusybox-syslogd - dh_installinit -pbusybox-syslogd --name=busybox-klogd - -# busybox-initramfs - dh_install -pbusybox-initramfs ${b}/initramfs/busybox /usr/lib/initramfs-tools/bin/ - install -D debian/tree/busybox/usr/share/initramfs-tools/hooks/zz-busybox debian/busybox-initramfs/usr/share/initramfs-tools/hooks/zz-busybox-initramfs - -ifeq (linux,$(DEB_HOST_ARCH_OS)) -# udhcpc -# udhcpd - dh_installinit -pudhcpd --onlyscripts -endif - -override_dh_gencontrol: +execute_before_dh_gencontrol-arch: # after shlibdeps finished, grab ${shlibs:Depends} from busybox package # and transform it into Built-Using field (also dpkg-query bug #588505) - if [ -f debian/busybox.substvars ]; then \ - pkgs=$$(sed -n -e's/([^)]*)//g' -e's/,//g' -e's/^shlibs:Depends=//p' debian/busybox.substvars); \ - srcs=; for p in $$pkgs; do \ - srcs="$$srcs $$(dpkg-query -f '$${source:Package} (= $${source:Version}),' -W $$p)"; \ - done ; \ - echo "built-using=$$srcs" >> debian/busybox-static.substvars ; \ - fi - dh_gencontrol + pkgs=$$(sed -n -e's/([^)]*)//g' -e's/,//g' -e's/^shlibs:Depends=//p' debian/busybox.substvars); \ + srcs=; for p in $$pkgs; do \ + srcs="$$srcs $$(dpkg-query -f '$${source:Package} (= $${source:Version}),' -W $$p)"; \ + done ; \ + echo "built-using=$$srcs" >> debian/busybox-static.substvars + +# install busybox-klogd startup scripts +execute_before_dh_installinit-indep: + dh_installinit -pbusybox-syslogd --name=busybox-klogd +execute_before_dh_installsystemd-indep: + dh_installsystemd -pbusybox-syslogd --name=busybox-klogd diff -Nru busybox-1.35.0/debian/tree/busybox-syslogd/etc/syslog.conf busybox-1.36.1/debian/tree/busybox-syslogd/etc/syslog.conf --- busybox-1.35.0/debian/tree/busybox-syslogd/etc/syslog.conf 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/tree/busybox-syslogd/etc/syslog.conf 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,18 @@ +# Sample config file for busybox syslogd +# Format: /usr/share/doc/busybox-syslogd/syslog.conf.txt + +auth,authpriv.* /var/log/auth.log +*.*;auth,authpriv,cron,mail.none \ + /var/log/syslog +cron.* /var/log/cron.log +daemon.* /var/log/daemon.log +kern.* /var/log/kern.log +mail.* /var/log/mail.log +user.* /var/log/user.log + +# Some catch-all logfiles: +*.=debug;auth,authpriv,news,mail.none\ + /var/log/debug +*.=info;*.=notice;*.=warn;\ +auth,authpriv,cron,daemon,mail,news.none\ + /var/log/messages diff -Nru busybox-1.35.0/debian/tree/udhcpd/etc/default/udhcpd busybox-1.36.1/debian/tree/udhcpd/etc/default/udhcpd --- busybox-1.35.0/debian/tree/udhcpd/etc/default/udhcpd 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/tree/udhcpd/etc/default/udhcpd 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -# Comment the following line to enable -DHCPD_ENABLED="no" - -# Options to pass to busybox' udhcpd. -# -# -S Log to syslog -# -f run in foreground - -DHCPD_OPTS="-S" diff -Nru busybox-1.35.0/debian/tree/udhcpd/etc/init.d/udhcpd busybox-1.36.1/debian/tree/udhcpd/etc/init.d/udhcpd --- busybox-1.35.0/debian/tree/udhcpd/etc/init.d/udhcpd 2022-11-06 15:44:41.000000000 +0000 +++ busybox-1.36.1/debian/tree/udhcpd/etc/init.d/udhcpd 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -#! /bin/sh -# -# Written by Miquel van Smoorenburg . -# Modified for Debian GNU/Linux by Ian Murdock -# and Axel Beckert . -# -### BEGIN INIT INFO -# Provides: udhcpd -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Start busybox udhcpd at boot time -### END INIT INFO - -PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin -DAEMON=/usr/sbin/udhcpd -NAME=udhcpd -DESC="very small Busybox based DHCP server" -DHCPD_OPTS="-S" # Additional options given to the server - -test -x $DAEMON || exit 0 - -. /lib/lsb/init-functions - -# Include defaults if available -if [ -f /etc/default/udhcpd ] ; then - . /etc/default/udhcpd -fi - -if [ "$DHCPD_ENABLED" = "no" ]; then - echo $NAME: Disabled. Edit /etc/default/udhcpd to enable it. - exit 0; -fi - -set -e - -case "$1" in - start) - echo -n "Starting $DESC: " - start-stop-daemon --start --verbose --pidfile /var/run/$NAME.pid \ - --oknodo --exec $DAEMON -- $DHCPD_OPTS - echo "$NAME." - ;; - stop) - echo -n "Stopping $DESC: " - start-stop-daemon --stop --verbose --pidfile /var/run/$NAME.pid \ - --oknodo --exec $DAEMON - echo "$NAME." - ;; - restart|force-reload) - $0 stop - sleep 1 - $0 start - ;; - *) - N=/etc/init.d/$NAME - echo "Usage: $N {start|stop|restart|force-reload}" >&2 - exit 1 - ;; -esac - -exit 0 diff -Nru busybox-1.35.0/debian/tree/udhcpd/etc/udhcpd.conf busybox-1.36.1/debian/tree/udhcpd/etc/udhcpd.conf --- busybox-1.35.0/debian/tree/udhcpd/etc/udhcpd.conf 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/tree/udhcpd/etc/udhcpd.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -# Sample udhcpd configuration file (/etc/udhcpd.conf) - -# The start and end of the IP lease block - -start 192.168.0.20 #default: 192.168.0.20 -end 192.168.0.254 #default: 192.168.0.254 - - -# The interface that udhcpd will use - -interface eth0 #default: eth0 - - -# The maximim number of leases (includes addressesd reserved -# by OFFER's, DECLINE's, and ARP conficts - -#max_leases 254 #default: 254 - - -# If remaining is true (default), udhcpd will store the time -# remaining for each lease in the udhcpd leases file. This is -# for embedded systems that cannot keep time between reboots. -# If you set remaining to no, the absolute time that the lease -# expires at will be stored in the dhcpd.leases file. - -#remaining yes #default: yes - - -# The time period at which udhcpd will write out a dhcpd.leases -# file. If this is 0, udhcpd will never automatically write a -# lease file. (specified in seconds) - -#auto_time 7200 #default: 7200 (2 hours) - - -# The amount of time that an IP will be reserved (leased) for if a -# DHCP decline message is received (seconds). - -#decline_time 3600 #default: 3600 (1 hour) - - -# The amount of time that an IP will be reserved (leased) for if an -# ARP conflct occurs. (seconds - -#conflict_time 3600 #default: 3600 (1 hour) - - -# How long an offered address is reserved (leased) in seconds - -#offer_time 60 #default: 60 (1 minute) - -# If a lease to be given is below this value, the full lease time is -# instead used (seconds). - -#min_lease 60 #defult: 60 - - -# The location of the leases file - -#lease_file /var/lib/misc/udhcpd.leases #defualt: /var/lib/misc/udhcpd.leases - -# The location of the pid file -#pidfile /var/run/udhcpd.pid #default: /var/run/udhcpd.pid - -# Everytime udhcpd writes a leases file, the below script will be called. -# Useful for writing the lease file to flash every few hours. - -#notify_file #default: (no script) - -#notify_file dumpleases # <--- useful for debugging - -# The following are bootp specific options, setable by udhcpd. - -#siaddr 192.168.0.22 #default: 0.0.0.0 - -#sname zorak #default: (none) - -#boot_file /var/nfs_root #default: (none) - -# The remainer of options are DHCP options and can be specifed with the -# keyword 'opt' or 'option'. If an option can take multiple items, such -# as the dns option, they can be listed on the same line, or multiple -# lines. The only option with a default is 'lease'. - -#Examles -opt dns 192.168.10.2 192.168.10.10 -option subnet 255.255.255.0 -opt router 192.168.10.2 -opt wins 192.168.10.10 -option dns 129.219.13.81 # appened to above DNS servers for a total of 3 -option domain local -option lease 864000 # 10 days of seconds - - -# Currently supported options, for more info, see options.c -#opt subnet -#opt timezone -#opt router -#opt timesrv -#opt namesrv -#opt dns -#opt logsrv -#opt cookiesrv -#opt lprsrv -#opt bootsize -#opt domain -#opt swapsrv -#opt rootpath -#opt ipttl -#opt mtu -#opt broadcast -#opt wins -#opt lease -#opt ntpsrv -#opt tftp -#opt bootfile -#opt wpad - -# Static leases map -#static_lease 00:60:08:11:CE:4E 192.168.0.54 -#static_lease 00:60:08:11:CE:3E 192.168.0.44 - - diff -Nru busybox-1.35.0/debian/tree/udhcpd/usr/share/man/man5/udhcpd.conf.5 busybox-1.36.1/debian/tree/udhcpd/usr/share/man/man5/udhcpd.conf.5 --- busybox-1.35.0/debian/tree/udhcpd/usr/share/man/man5/udhcpd.conf.5 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/tree/udhcpd/usr/share/man/man5/udhcpd.conf.5 1970-01-01 00:00:00.000000000 +0000 @@ -1,169 +0,0 @@ -.TH UDHCPD.CONF 5 2001-09-26 GNU/Linux "GNU/Linux Administrator's Manual" -.SH NAME -udhcpd.conf \- udhcp server configuration file -.SH DESCRIPTION -The file -.I /etc/udhcpd.conf -contains configuration information specific to the udhcp server. -It should contain one configuration keyword per line, followed by -appropriate configuration information. -.SH OPTIONS -.TP -.BI start\ ADDRESS -The starting address of the IP lease block is -.IR ADDRESS . -The default is -.BR 192.168.0.20 . -.TP -.BI end\ ADDRESS -The ending address of the IP lease block is -.IR ADDRESS . -The default is -.BR 192.168.0.254 . -.TP -.BI interface\ INTERFACE -The udhcp server should listen on -.IR INTERFACE . -The default is -.BR eth0 . -.TP -.BI max_leases\ LEASES -Offer at most -.I LEASES -leases (including those reserved by OFFERs, DECLINEs, and ARP -conflicts). The default is -.BR 254 . -.TP -.BI remaining\ REMAINING -If -.I REMAINING -is -.BR yes , -store the time remaining for each lease. If it is -.BR no , -store the expiration time for each lease. The default is -.BR yes . -.TP -.BI auto_time\ SECONDS -Write the lease information to a file every -.I SECONDS -seconds. The default is -.BR 7200 . -.TP -.BI decline_time\ SECONDS -Reserve an IP for -.I SECONDS -seconds if a DHCP decline message is received. The default is -.BR 3600 . -.TP -.BI conflict_time\ SECONDS -Reserve an IP for -.I SECONDS -seconds if an ARP conflict occurs. The default is -.BR 3600 . -.TP -.BI offer_time\ SECONDS -Reserve an IP for -.I SECONDS -seconds if it is offered. The default is -.BR 60 . -.TP -.BI min_lease\ SECONDS -Reserve an IP for the full lease time if the lease to be given is less than -.I SECONDS -seconds. The default is -.BR 60 . -.TP -.BI lease_file\ FILE -Write the lease information to -.IR FILE . -The default is -.BR /var/lib/misc/udhcpd.leases . -.TP -.BI pidfile\ FILE -Write the process ID to -.IR FILE . -The default is -.BR /var/run/udhcpd.pid . -.TP -.BI notify_file\ FILE -Execute -.I FILE -after the lease information is written. By default, no file is executed. -.TP -.BI siaddr\ ADDRESS -BOOTP specific option. The default is -.BR 0.0.0.0 . -.TP -.BI sname\ NAME -BOOTP specific option. There is no default. -.TP -.BI boot_file\ FILE -BOOTP specific option. There is no default. -.TP -.BI static_lease\ MACADDRESS\ IPADDRESS -Issue IPADDRESS statically to a requester with MACADDRESS. -.TP -.BI option\ OPTION -DHCP specific option. -.RS -.TP -.BI subnet\ ADDRESS -.TP -.BI timezone\ OFFSET -.TP -.BI router\ ADDRESS... -.TP -.BI timesvr\ ADDRESS... -.TP -.BI namesvr\ ADDRESS... -.TP -.BI dns\ ADDRESS... -.TP -.BI logsvr\ ADDRESS... -.TP -.BI cookiesvr\ ADDRESS... -.TP -.BI lprsvr\ ADDRESS... -.TP -.BI hostname\ HOSTNAME -.TP -.BI bootsize\ SIZE -.TP -.BI domain\ DOMAIN -.TP -.BI swapsvr\ ADDRESS -.TP -.BI rootpath\ PATH -.TP -.BI ipttl\ TTL -.TP -.BI mtu\ MTU -.TP -.BI broadcast\ ADDRESS -.TP -.BI ntpsrv\ ADDRESS... -.TP -.BI wins\ ADDRESS... -.TP -.BI requestip\ ADDRESS -.TP -.BI lease\ SECONDS -.TP -.BI dhcptype\ TYPE -.TP -.BI serverid\ ADDRESS -.TP -.BI tftp\ FILE -.TP -.BI wpad\ URL -.TP -.BI bootfile\ FILE -The default for -.B lease -is -.BR 864000 . -There are no defaults for the other options. -.RE -.SH SEE ALSO -.BR udhcpd (8). diff -Nru busybox-1.35.0/debian/udhcpd.conf.5 busybox-1.36.1/debian/udhcpd.conf.5 --- busybox-1.35.0/debian/udhcpd.conf.5 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/udhcpd.conf.5 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,159 @@ +.TH UDHCPD.CONF 5 2001-09-26 GNU/Linux "GNU/Linux Administrator's Manual" +.SH NAME +udhcpd.conf \- udhcp server configuration file +.SH DESCRIPTION +The file +.I /etc/udhcpd.conf +contains configuration information specific to the udhcp server. +It should contain one configuration keyword per line, followed by +appropriate configuration information. +.SH OPTIONS +.TP +.BI start\ ADDRESS +The starting address of the IP lease block is +.IR ADDRESS . +The default is +.BR 192.168.0.20 . +.TP +.BI end\ ADDRESS +The ending address of the IP lease block is +.IR ADDRESS . +The default is +.BR 192.168.0.254 . +.TP +.BI interface\ INTERFACE +The udhcp server should listen on +.IR INTERFACE . +The default is +.BR eth0 . +.TP +.BI max_leases\ LEASES +Offer at most +.I LEASES +leases (including those reserved by OFFERs, DECLINEs, and ARP +conflicts). The default is +.BR 254 . +.TP +.BI auto_time\ SECONDS +Write the lease information to a file every +.I SECONDS +seconds. The default is +.BR 7200 . +.TP +.BI decline_time\ SECONDS +Reserve an IP for +.I SECONDS +seconds if a DHCP decline message is received. The default is +.BR 3600 . +.TP +.BI conflict_time\ SECONDS +Reserve an IP for +.I SECONDS +seconds if an ARP conflict occurs. The default is +.BR 3600 . +.TP +.BI offer_time\ SECONDS +Reserve an IP for +.I SECONDS +seconds if it is offered. The default is +.BR 60 . +.TP +.BI min_lease\ SECONDS +Reserve an IP for the full lease time if the lease to be given is less than +.I SECONDS +seconds. The default is +.BR 60 . +.TP +.BI lease_file\ FILE +Write the lease information to +.IR FILE . +The default is +.BR /var/lib/misc/udhcpd.leases . +.TP +.BI pidfile\ FILE +Write the process ID to +.IR FILE . +The default is +.BR /var/run/udhcpd.pid . +.TP +.BI notify_file\ FILE +Execute +.I FILE +after the lease information is written. By default, no file is executed. +.TP +.BI siaddr\ ADDRESS +BOOTP specific option. The default is +.BR 0.0.0.0 . +.TP +.BI sname\ NAME +BOOTP specific option. There is no default. +.TP +.BI boot_file\ FILE +BOOTP specific option. There is no default. +.TP +.BI static_lease\ MACADDRESS\ IPADDRESS +Issue IPADDRESS statically to a requester with MACADDRESS. +.TP +.BI option\ OPTION +DHCP specific option. +.RS +.TP +.BI subnet\ ADDRESS +.TP +.BI timezone\ OFFSET +.TP +.BI router\ ADDRESS... +.TP +.BI timesvr\ ADDRESS... +.TP +.BI namesvr\ ADDRESS... +.TP +.BI dns\ ADDRESS... +.TP +.BI logsvr\ ADDRESS... +.TP +.BI cookiesvr\ ADDRESS... +.TP +.BI lprsvr\ ADDRESS... +.TP +.BI hostname\ HOSTNAME +.TP +.BI bootsize\ SIZE +.TP +.BI domain\ DOMAIN +.TP +.BI swapsvr\ ADDRESS +.TP +.BI rootpath\ PATH +.TP +.BI ipttl\ TTL +.TP +.BI mtu\ MTU +.TP +.BI broadcast\ ADDRESS +.TP +.BI ntpsrv\ ADDRESS... +.TP +.BI wins\ ADDRESS... +.TP +.BI requestip\ ADDRESS +.TP +.BI lease\ SECONDS +.TP +.BI dhcptype\ TYPE +.TP +.BI serverid\ ADDRESS +.TP +.BI tftp\ FILE +.TP +.BI wpad\ URL +.TP +.BI bootfile\ FILE +The default for +.B lease +is +.BR 864000 . +There are no defaults for the other options. +.RE +.SH SEE ALSO +.BR udhcpd (8). diff -Nru busybox-1.35.0/debian/udhcpd.default busybox-1.36.1/debian/udhcpd.default --- busybox-1.35.0/debian/udhcpd.default 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/udhcpd.default 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,9 @@ +# Comment the following line to enable +DHCPD_ENABLED="no" + +# Options to pass to busybox' udhcpd. +# +# -S Log to syslog +# -f run in foreground + +DHCPD_OPTS="-S" diff -Nru busybox-1.35.0/debian/udhcpd.init busybox-1.36.1/debian/udhcpd.init --- busybox-1.35.0/debian/udhcpd.init 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/udhcpd.init 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1,65 @@ +#! /bin/busybox ash +# +# Written by Miquel van Smoorenburg . +# Modified for Debian GNU/Linux by Ian Murdock +# and Axel Beckert . +# Entirely rewritten by Mjt in 2023, +# Copyright (c) 2023 Michael Tokarev +# +### BEGIN INIT INFO +# Provides: udhcpd +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start busybox udhcpd at boot time +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +NAME=udhcpd +DAEMON=/usr/sbin/$NAME +DESC="Busybox based DHCP server" + +test -x $DAEMON || exit 0 + +. /lib/lsb/init-functions + +DHCPD_OPTS="-S" # Additional options given to the server +# Include defaults if available +if [ -f /etc/default/udhcpd ] ; then + . /etc/default/udhcpd +fi +DAEMON_OPTS="$DHCP_OPTS" + +if [ "$DHCPD_ENABLED" = "no" ]; then + echo $NAME: Disabled. Edit /etc/default/udhcpd to enable it. + exit 0 +fi + +daemon() { + case "$1" in + (start) args="-S -o"; act="Starting" ;; + (stop) args="-K -o -q"; act="Stopping" ;; + (status) args="-K -t -q"; act="Checking" ;; + esac + log_daemon_msg "$act $DESC " "$NAME" + busybox start-stop-daemon $args -p /var/run/$NAME.pid \ + -x $DAEMON -- $DAEMON_OPTS + rc=$? + log_end_msg $? + return $? +} + +case "$1" in + (start|stop|status) + daemon $1 + ;; + (restart|force-reload) + daemon stop + daemon start + ;; + (*) + echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac diff -Nru busybox-1.35.0/debian/udhcpd.install busybox-1.36.1/debian/udhcpd.install --- busybox-1.35.0/debian/udhcpd.install 2022-11-06 15:44:40.000000000 +0000 +++ busybox-1.36.1/debian/udhcpd.install 2023-07-05 16:04:48.000000000 +0000 @@ -1 +1,2 @@ -debian/tree/udhcpd/* / +examples/udhcp/udhcpd.conf etc/ +debian/udhcpd.conf.5 usr/share/man/man5/ diff -Nru busybox-1.35.0/debian/udhcpd.lintian-overrides busybox-1.36.1/debian/udhcpd.lintian-overrides --- busybox-1.35.0/debian/udhcpd.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/debian/udhcpd.lintian-overrides 2023-07-05 16:04:48.000000000 +0000 @@ -0,0 +1 @@ +udhcpd: unusual-interpreter /bin/busybox [etc/init.d/udhcpd] diff -Nru busybox-1.35.0/debianutils/start_stop_daemon.c busybox-1.36.1/debianutils/start_stop_daemon.c --- busybox-1.35.0/debianutils/start_stop_daemon.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/debianutils/start_stop_daemon.c 2023-01-03 14:14:43.000000000 +0000 @@ -519,7 +519,7 @@ /* why _exit? the child may have changed the stack, * so "return 0" may do bad things */ - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } /* Child */ setsid(); /* detach from controlling tty */ @@ -531,7 +531,7 @@ */ pid = xvfork(); if (pid != 0) - _exit(EXIT_SUCCESS); /* Parent */ + _exit_SUCCESS(); /* Parent */ } if (opt & OPT_MAKEPID) { /* User wants _us_ to make the pidfile */ diff -Nru busybox-1.35.0/docs/posix_conformance.txt busybox-1.36.1/docs/posix_conformance.txt --- busybox-1.35.0/docs/posix_conformance.txt 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/docs/posix_conformance.txt 2023-01-03 14:14:43.000000000 +0000 @@ -24,7 +24,7 @@ gencat, getconf, iconv, join, link, locale, localedef, lp, m4, mailx, newgrp, nl, pathchk, pax, pr, qalter, qdel, qhold, qmove, qmsg, qrerun, qrls, qselect, qsig, qstat, qsub, tabs, talk, tput, - tsort, unlink, uucp, uustat, uux + unlink, uucp, uustat, uux POSIX Tools not supported (DEVELOPMENT): admin, cflow, ctags, cxref, delta, fort77, get, lex, make, nm, prs, rmdel, diff -Nru busybox-1.35.0/e2fsprogs/fsck.c busybox-1.36.1/e2fsprogs/fsck.c --- busybox-1.35.0/e2fsprogs/fsck.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/e2fsprogs/fsck.c 2023-01-03 14:14:43.000000000 +0000 @@ -190,7 +190,7 @@ * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3 * pathames. */ -static const char *const devfs_hier[] = { +static const char *const devfs_hier[] ALIGN_PTR = { "host", "bus", "target", "lun", NULL }; #endif diff -Nru busybox-1.35.0/editors/awk.c busybox-1.36.1/editors/awk.c --- busybox-1.35.0/editors/awk.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/editors/awk.c 2023-01-03 14:14:43.000000000 +0000 @@ -848,7 +848,7 @@ static char nextchar(char **s) { char c, *pps; - + again: c = *(*s)++; pps = *s; if (c == '\\') @@ -859,8 +859,11 @@ */ if (c == '\\' && *s == pps) { /* unrecognized \z? */ c = *(*s); /* yes, fetch z */ - if (c) - (*s)++; /* advance unless z = NUL */ + if (c) { /* advance unless z = NUL */ + (*s)++; + if (c == '\n') /* \? eat it */ + goto again; + } } return c; } @@ -882,7 +885,13 @@ static double my_strtod(char **pp) { char *cp = *pp; - if (ENABLE_DESKTOP && cp[0] == '0') { + return strtod(cp, pp); +} +#if ENABLE_DESKTOP +static double my_strtod_or_hexoct(char **pp) +{ + char *cp = *pp; + if (cp[0] == '0') { /* Might be hex or octal integer: 0x123abc or 07777 */ char c = (cp[1] | 0x20); if (c == 'x' || isdigit(cp[1])) { @@ -901,6 +910,9 @@ } return strtod(cp, pp); } +#else +# define my_strtod_or_hexoct(p) my_strtod(p) +#endif /* -------- working with variables (set/get/copy/etc) -------- */ @@ -1014,6 +1026,7 @@ if (s && *s) { debug_printf_eval("getvar_i: '%s'->", s); v->number = my_strtod(&s); + /* ^^^ hex/oct NOT allowed here! */ debug_printf_eval("%f (s:'%s')\n", v->number, s); if (v->type & VF_USER) { //TODO: skip_spaces() also skips backslash+newline, is it intended here? @@ -1125,10 +1138,10 @@ if (*p == '\0') { tc = TC_EOF; debug_printf_parse("%s: token found: TC_EOF\n", __func__); - } else if (*p == '\"') { + } else if (*p == '"') { /* it's a string */ char *s = t_string = ++p; - while (*p != '\"') { + while (*p != '"') { char *pp; if (*p == '\0' || *p == '\n') syntax_error(EMSG_UNEXP_EOS); @@ -1166,7 +1179,8 @@ } else if (*p == '.' || isdigit(*p)) { /* it's a number */ char *pp = p; - t_double = my_strtod(&pp); + t_double = my_strtod_or_hexoct(&pp); + /* ^^^ awk only allows hex/oct consts in _program_, not in _input_ */ p = pp; if (*p == '.') syntax_error(EMSG_UNEXP_TOKEN); @@ -3114,6 +3128,9 @@ case XC( OC_MOVE ): debug_printf_eval("MOVE\n"); + /* make sure that we never return a temp var */ + if (L.v == TMPVAR0) + L.v = res; /* if source is a temporary string, jusk relink it to dest */ if (R.v == TMPVAR1 && !(R.v->type & VF_NUMBER) @@ -3503,6 +3520,7 @@ i = (Ld == 0); break; } + debug_printf_eval("COMPARE result: %d\n", (i == 0) ^ (opn & 1)); setvar_i(res, (i == 0) ^ (opn & 1)); break; } diff -Nru busybox-1.35.0/editors/cmp.c busybox-1.36.1/editors/cmp.c --- busybox-1.35.0/editors/cmp.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/editors/cmp.c 2023-01-03 14:14:43.000000000 +0000 @@ -54,6 +54,7 @@ int retval = 0; int max_count = -1; +#if !ENABLE_LONG_OPTS opt = getopt32(argv, "^" OPT_STR "\0" "-1" @@ -62,6 +63,23 @@ ":l--s:s--l", &max_count ); +#else + static const char cmp_longopts[] ALIGN1 = + "bytes\0" Required_argument "n" + "quiet\0" No_argument "s" + "silent\0" No_argument "s" + "verbose\0" No_argument "l" + ; + opt = getopt32long(argv, "^" + OPT_STR + "\0" "-1" + IF_DESKTOP(":?4") + IF_NOT_DESKTOP(":?2") + ":l--s:s--l", + cmp_longopts, + &max_count + ); +#endif argv += optind; filename1 = *argv; diff -Nru busybox-1.35.0/editors/ed.c busybox-1.36.1/editors/ed.c --- busybox-1.35.0/editors/ed.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/editors/ed.c 2023-01-05 15:26:49.000000000 +0000 @@ -18,7 +18,7 @@ //applet:IF_ED(APPLET(ed, BB_DIR_BIN, BB_SUID_DROP)) -//usage:#define ed_trivial_usage "[-p PROMPT] [FILE]" +//usage:#define ed_trivial_usage "[-p PROMPT] [-s] [FILE]" //usage:#define ed_full_usage "" #include "libbb.h" @@ -71,6 +71,11 @@ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ } while (0) +#define OPTION_STR "sp:" +enum { + OPT_s = (1 << 0), +}; + static int bad_nums(int num1, int num2, const char *for_what) { if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { @@ -458,7 +463,8 @@ * in the following format: * "%d\n", */ - printf("%u\n", charCount); + if (!(option_mask32 & OPT_s)) + printf("%u\n", charCount); return TRUE; } @@ -510,7 +516,8 @@ * unless the -s option was specified, in the following format: * "%d\n", */ - printf("%u\n", charCount); + if (!(option_mask32 & OPT_s)) + printf("%u\n", charCount); return TRUE; } @@ -713,7 +720,7 @@ if (deltaLen <= 0) { memcpy(&lp->data[offset], newStr, newLen); if (deltaLen) { - memcpy(&lp->data[offset + newLen], + memmove(&lp->data[offset + newLen], &lp->data[offset + oldLen], lp->len - offset - oldLen); @@ -1005,7 +1012,7 @@ lines.prev = &lines; prompt = ""; /* no prompt by default */ - getopt32(argv, "p:", &prompt); + getopt32(argv, OPTION_STR, &prompt); argv += optind; if (argv[0]) { diff -Nru busybox-1.35.0/editors/patch.c busybox-1.36.1/editors/patch.c --- busybox-1.35.0/editors/patch.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/editors/patch.c 2023-01-03 14:14:43.000000000 +0000 @@ -138,9 +138,9 @@ { struct double_list *dlist = data; - if (TT.state>1 && *dlist->data != TT.state) + if (TT.state > 1 && *dlist->data != TT.state) fdprintf(TT.state == 2 ? 2 : TT.fileout, - "%s\n", dlist->data+(TT.state>3 ? 1 : 0)); + "%s\n", dlist->data + (TT.state > 3 ? 1 : 0)); if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); @@ -221,7 +221,7 @@ // Match EOF if there aren't as many ending context lines as beginning for (plist = TT.current_hunk; plist; plist = plist->next) { - if (plist->data[0]==' ') matcheof++; + if (plist->data[0] == ' ') matcheof++; else matcheof = 0; if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); } @@ -418,7 +418,7 @@ } // Loop through the lines in the patch - for(;;) { + for (;;) { char *patchline; patchline = xmalloc_fgetline(stdin); @@ -433,15 +433,15 @@ // Are we assembling a hunk? if (state >= 2) { - if (*patchline==' ' || *patchline=='+' || *patchline=='-') { + if (*patchline == ' ' || *patchline == '+' || *patchline == '-') { dlist_add(&TT.current_hunk, patchline); if (*patchline != '+') oldlen--; if (*patchline != '-') newlen--; // Context line? - if (*patchline==' ' && state==2) TT.context++; - else state=3; + if (*patchline == ' ' && state == 2) TT.context++; + else state = 3; // If we've consumed all expected hunk lines, apply the hunk. @@ -469,9 +469,9 @@ free(*name); // Trim date from end of filename (if any). We don't care. for (s = patchline+4; *s && *s!='\t'; s++) - if (*s=='\\' && s[1]) s++; + if (*s == '\\' && s[1]) s++; i = atoi(s); - if (i>1900 && i<=1970) + if (i > 1900 && i <= 1970) *name = xstrdup("/dev/null"); else { *s = 0; diff -Nru busybox-1.35.0/editors/patch_toybox.c busybox-1.36.1/editors/patch_toybox.c --- busybox-1.35.0/editors/patch_toybox.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/editors/patch_toybox.c 2023-01-03 14:14:43.000000000 +0000 @@ -79,7 +79,7 @@ else free(pop); // End doubly linked list too. - if (list==pop) break; + if (list == pop) break; } } @@ -137,11 +137,11 @@ long len = 0; for (;;) { - if (1>read(fd, &c, 1)) break; + if (1 > read(fd, &c, 1)) break; if (!(len & 63)) buf=xrealloc(buf, len+65); - if ((buf[len++]=c) == end) break; + if ((buf[len++] = c) == end) break; } - if (buf) buf[len]=0; + if (buf) buf[len] = 0; if (plen) *plen = len; return buf; @@ -153,7 +153,7 @@ long len; char *buf = get_rawline(fd, &len, '\n'); - if (buf && buf[--len]=='\n') buf[len]=0; + if (buf && buf[--len] == '\n') buf[len] = 0; return buf; } @@ -165,10 +165,10 @@ long len; char buf[4096]; - if (in<0) return; + if (in < 0) return; for (;;) { len = safe_read(in, buf, 4096); - if (len<1) break; + if (len < 1) break; xwrite(out, buf, len); } } @@ -179,7 +179,7 @@ { char *temp = xstrdup(*tempname); - temp[strlen(temp)-6]=0; + temp[strlen(temp)-6] = 0; if (fdin != -1) { xsendfile(fdin, fdout); xclose(fdin); @@ -263,9 +263,9 @@ { struct double_list *dlist = (struct double_list *)data; - if (TT.state>1 && *dlist->data != TT.state) + if (TT.state > 1 && *dlist->data != TT.state) fdprintf(TT.state == 2 ? 2 : TT.fileout, - "%s\n", dlist->data+(TT.state>3 ? 1 : 0)); + "%s\n", dlist->data + (TT.state > 3 ? 1 : 0)); if (PATCH_DEBUG) fdprintf(2, "DO %d: %s\n", TT.state, dlist->data); @@ -314,7 +314,7 @@ // Match EOF if there aren't as many ending context lines as beginning for (plist = TT.current_hunk; plist; plist = plist->next) { - if (plist->data[0]==' ') matcheof++; + if (plist->data[0] == ' ') matcheof++; else matcheof = 0; if (PATCH_DEBUG) fdprintf(2, "HUNK:%s\n", plist->data); } @@ -385,7 +385,7 @@ // If we've reached the end of the buffer without confirming a // match, read more lines. - if (check==buf) { + if (check == buf) { buf = 0; break; } @@ -441,7 +441,7 @@ TT.filein = TT.fileout = -1; // Loop through the lines in the patch - for(;;) { + for (;;) { char *patchline; patchline = get_line(TT.filepatch); @@ -456,15 +456,15 @@ // Are we assembling a hunk? if (state >= 2) { - if (*patchline==' ' || *patchline=='+' || *patchline=='-') { + if (*patchline == ' ' || *patchline == '+' || *patchline == '-') { dlist_add(&TT.current_hunk, patchline); if (*patchline != '+') TT.oldlen--; if (*patchline != '-') TT.newlen--; // Context line? - if (*patchline==' ' && state==2) TT.context++; - else state=3; + if (*patchline == ' ' && state == 2) TT.context++; + else state = 3; // If we've consumed all expected hunk lines, apply the hunk. @@ -491,9 +491,9 @@ // Trim date from end of filename (if any). We don't care. for (s = patchline+4; *s && *s!='\t'; s++) - if (*s=='\\' && s[1]) s++; + if (*s == '\\' && s[1]) s++; i = atoi(s); - if (i>1900 && i<=1970) + if (i > 1900 && i <= 1970) *name = xstrdup("/dev/null"); else { *s = 0; @@ -537,7 +537,7 @@ // handle -p path truncation. for (i=0, s = name; *s;) { if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) break; - if (*(s++)=='/') { + if (*(s++) == '/') { name = s; i++; } diff -Nru busybox-1.35.0/editors/sed.c busybox-1.36.1/editors/sed.c --- busybox-1.35.0/editors/sed.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/editors/sed.c 2023-01-03 14:14:43.000000000 +0000 @@ -97,6 +97,12 @@ OPT_in_place = 1 << 0, }; +struct sed_FILE { + struct sed_FILE *next; /* Next (linked list, NULL terminated) */ + char *fname; + FILE *fp; +}; + /* Each sed command turns into one of these structures. */ typedef struct sed_cmd_s { /* Ordered by alignment requirements: currently 36 bytes on x86 */ @@ -151,6 +157,11 @@ /* linked list of append lines */ llist_t *append_head; + /* linked list of FILEs opened for 'w' and s///w'. + * Needed to handle duplicate fnames: sed '/a/w F;/b/w F' + */ + struct sed_FILE *FILE_head; + char *add_cmd_line; struct pipeline { @@ -177,9 +188,6 @@ while (sed_cmd) { sed_cmd_t *sed_cmd_next = sed_cmd->next; - if (sed_cmd->sw_file) - fclose(sed_cmd->sw_file); - /* Used to free regexps, but now there is code * in get_address() which can reuse a regexp * for constructs as /regexp/cmd1;//cmd2 @@ -206,11 +214,39 @@ if (G.current_fp) fclose(G.current_fp); + + if (G.FILE_head) { + struct sed_FILE *cur = G.FILE_head; + do { + struct sed_FILE *p; + fclose(cur->fp); + free(cur->fname); + p = cur; + cur = cur->next; + free(p); + } while (cur); + } } #else void sed_free_and_close_stuff(void); #endif +static FILE *sed_xfopen_w(const char *fname) +{ + struct sed_FILE **pp = &G.FILE_head; + struct sed_FILE *cur; + while ((cur = *pp) != NULL) { + if (strcmp(cur->fname, fname) == 0) + return cur->fp; + pp = &cur->next; + } + *pp = cur = xzalloc(sizeof(*cur)); + /*cur->next = NULL; - already is */ + cur->fname = xstrdup(fname); + cur->fp = xfopen_for_write(fname); + return cur->fp; +} + /* If something bad happens during -i operation, delete temp file */ static void cleanup_outname(void) @@ -219,7 +255,6 @@ } /* strcpy, replacing "\from" with 'to'. If to is NUL, replacing "\any" with 'any' */ - static unsigned parse_escapes(char *dest, const char *string, int len, char from, char to) { char *d = dest; @@ -249,7 +284,7 @@ return d - dest; } -static char *copy_parsing_escapes(const char *string, int len) +static char *copy_parsing_escapes(const char *string, int len, char delim) { const char *s; char *dest = xmalloc(len + 1); @@ -260,10 +295,15 @@ len = parse_escapes(dest, string, len, s[1], s[0]); string = dest; } + if (delim) { + /* we additionally unescape any instances of escaped delimiter. + * For example, in 's+9\++X+' the pattern is "9+", not "9\+". + */ + len = parse_escapes(dest, string, len, delim, delim); + } return dest; } - /* * index_of_next_unescaped_regexp_delim - walks left to right through a string * beginning at a specified index and returns the index of the next regular @@ -320,12 +360,14 @@ /* save the match string */ idx = index_of_next_unescaped_regexp_delim(delimiter, cmdstr_ptr); - *match = copy_parsing_escapes(cmdstr_ptr, idx); - + *match = copy_parsing_escapes(cmdstr_ptr, idx, delimiter); /* save the replacement string */ cmdstr_ptr += idx + 1; idx = index_of_next_unescaped_regexp_delim(- (int)delimiter, cmdstr_ptr); - *replace = copy_parsing_escapes(cmdstr_ptr, idx); +//GNU sed 4.8: +// echo 789 | sed 's&8&\&&' - 7&9 ("\&" remained "\&") +// echo 789 | sed 's1\(8\)1\1\11' - 7119 ("\1\1" become "11") + *replace = copy_parsing_escapes(cmdstr_ptr, idx, delimiter != '&' ? delimiter : 0); return ((cmdstr_ptr - cmdstr) + idx); } @@ -353,7 +395,7 @@ delimiter = *++pos; next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); if (next != 0) { - temp = copy_parsing_escapes(pos, next); + temp = copy_parsing_escapes(pos, next, 0); G.previous_regex_ptr = *regex = xzalloc(sizeof(regex_t)); xregcomp(*regex, temp, G.regex_type); free(temp); @@ -446,7 +488,7 @@ { char *fname; idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname); - sed_cmd->sw_file = xfopen_for_write(fname); + sed_cmd->sw_file = sed_xfopen_w(fname); sed_cmd->sw_last_char = '\n'; free(fname); break; @@ -548,7 +590,7 @@ cmdstr++; } len = strlen(cmdstr); - sed_cmd->string = copy_parsing_escapes(cmdstr, len); + sed_cmd->string = copy_parsing_escapes(cmdstr, len, 0); cmdstr += len; /* "\anychar" -> "anychar" */ parse_escapes(sed_cmd->string, sed_cmd->string, -1, '\0', '\0'); @@ -561,7 +603,7 @@ } cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string); if (sed_cmd->cmd == 'w') { - sed_cmd->sw_file = xfopen_for_write(sed_cmd->string); + sed_cmd->sw_file = sed_xfopen_w(sed_cmd->string); sed_cmd->sw_last_char = '\n'; } } diff -Nru busybox-1.35.0/editors/vi.c busybox-1.36.1/editors/vi.c --- busybox-1.35.0/editors/vi.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/editors/vi.c 2023-01-03 14:14:43.000000000 +0000 @@ -224,6 +224,7 @@ #endif +#define isbackspace(c) ((c) == term_orig.c_cc[VERASE] || (c) == 8 || (c) == 127) enum { MAX_TABSTOP = 32, // sanity limit @@ -342,6 +343,7 @@ int last_modified_count; // = -1; int cmdline_filecnt; // how many file names on cmd line int cmdcnt; // repetition count + char *rstart; // start of text in Replace mode unsigned rows, columns; // the terminal screen is this size #if ENABLE_FEATURE_VI_ASK_TERMINAL int get_rowcol_error; @@ -378,7 +380,9 @@ char *last_search_pattern; // last pattern from a '/' or '?' search #endif #if ENABLE_FEATURE_VI_SETOPTS - int indentcol; // column of recently autoindent, 0 or -1 + int char_insert__indentcol; // column of recent autoindent or 0 + int newindent; // autoindent value for 'O'/'cc' commands + // or -1 to use indent from previous line #endif smallint cmd_error; @@ -474,6 +478,7 @@ #define last_modified_count (G.last_modified_count) #define cmdline_filecnt (G.cmdline_filecnt ) #define cmdcnt (G.cmdcnt ) +#define rstart (G.rstart ) #define rows (G.rows ) #define columns (G.columns ) #define crow (G.crow ) @@ -504,7 +509,8 @@ #define ioq_start (G.ioq_start ) #define dotcnt (G.dotcnt ) #define last_search_pattern (G.last_search_pattern) -#define indentcol (G.indentcol ) +#define char_insert__indentcol (G.char_insert__indentcol) +#define newindent (G.newindent ) #define cmd_error (G.cmd_error ) #define edit_file__cur_line (G.edit_file__cur_line) @@ -537,10 +543,11 @@ #define INIT_G() do { \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ - last_modified_count = -1; \ + last_modified_count--; \ /* "" but has space for 2 chars: */ \ IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \ tabstop = 8; \ + IF_FEATURE_VI_SETOPTS(newindent--;) \ } while (0) #if ENABLE_FEATURE_VI_CRASHME @@ -1122,7 +1129,7 @@ // on nonblocking stdin. // Note: read_key sets errno to 0 on success. again: - c = read_key(STDIN_FILENO, readbuffer, /*timeout:*/ -1); + c = safe_read_key(STDIN_FILENO, readbuffer, /*timeout:*/ -1); if (c == -1) { // EOF/error if (errno == EAGAIN) // paranoia goto again; @@ -1212,12 +1219,13 @@ c = get_one_char(); if (c == '\n' || c == '\r' || c == 27) break; // this is end of input - if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { + if (isbackspace(c)) { // user wants to erase prev char - write1("\b \b"); // erase char on screen buf[--i] = '\0'; + go_bottom_and_clear_to_eol(); if (i <= 0) // user backs up before b-o-l, exit break; + write1(buf); } else if (c > 0 && c < 256) { // exclude Unicode // (TODO: need to handle Unicode) buf[i] = c; @@ -2109,6 +2117,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' { #if ENABLE_FEATURE_VI_SETOPTS +# define indentcol char_insert__indentcol size_t len; int col, ntab, nspc; #endif @@ -2137,7 +2146,8 @@ #if ENABLE_FEATURE_VI_SETOPTS if (autoindent) { len = indent_len(bol); - if (len && get_column(bol + len) == indentcol && bol[len] == '\n') { + col = get_column(bol + len); + if (len && col == indentcol && bol[len] == '\n') { // remove autoindent from otherwise empty line text_hole_delete(bol, bol + len - 1, undo); p = bol; @@ -2174,8 +2184,16 @@ p += 1 + stupid_insert(p, ' '); } #endif - } else if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { // Is this a BS - if (p > text) { + } else if (isbackspace(c)) { + if (cmd_mode == 2) { + // special treatment for backspace in Replace mode + if (p > rstart) { + p--; +#if ENABLE_FEATURE_VI_UNDO + undo_pop(); +#endif + } + } else if (p > text) { p--; p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char } @@ -2198,24 +2216,31 @@ showmatching(p - 1); } if (autoindent && c == '\n') { // auto indent the new line - // use indent of current/previous line - bol = indentcol < 0 ? p : prev_line(p); - len = indent_len(bol); - col = get_column(bol + len); - - if (len && col == indentcol) { - // previous line was empty except for autoindent - // move the indent to the current line - memmove(bol + 1, bol, len); - *bol = '\n'; - return p; + if (newindent < 0) { + // use indent of previous line + bol = prev_line(p); + len = indent_len(bol); + col = get_column(bol + len); + + if (len && col == indentcol) { + // previous line was empty except for autoindent + // move the indent to the current line + memmove(bol + 1, bol, len); + *bol = '\n'; + return p; + } + } else { + // for 'O'/'cc' commands add indent before newly inserted NL + if (p != end - 1) // but not for 'cc' at EOF + p--; + col = newindent; } - if (indentcol < 0) - p--; // open above, indent before newly inserted NL - - if (len) { - indentcol = col; + if (col) { + // only record indent if in insert/replace mode or for + // the 'o'/'O'/'cc' commands, which are switched to + // insert mode early. + indentcol = cmd_mode != 0 ? col : 0; if (expandtab) { ntab = 0; nspc = col; @@ -2237,6 +2262,7 @@ } #if ENABLE_FEATURE_VI_SETOPTS indentcol = 0; +# undef indentcol #endif return p; } @@ -3703,9 +3729,9 @@ undo_queue_commit(); } else { if (1 <= c || Isprint(c)) { - if (c != 27) - dot = yank_delete(dot, dot, PARTIAL, YANKDEL, ALLOW_UNDO); // delete char - dot = char_insert(dot, c, ALLOW_UNDO_CHAIN); // insert new char + if (c != 27 && !isbackspace(c)) + dot = yank_delete(dot, dot, PARTIAL, YANKDEL, ALLOW_UNDO); + dot = char_insert(dot, c, ALLOW_UNDO_CHAIN); } goto dc1; } @@ -4205,6 +4231,9 @@ case 'i': // i- insert before current char case KEYCODE_INSERT: // Cursor Key Insert dc_i: +#if ENABLE_FEATURE_VI_SETOPTS + newindent = -1; +#endif cmd_mode = 1; // start inserting undo_queue_commit(); // commit queue when cmd_mode changes break; @@ -4247,12 +4276,16 @@ case 'O': // O- open an empty line above dot_begin(); #if ENABLE_FEATURE_VI_SETOPTS - indentcol = -1; + // special case: use indent of current line + newindent = get_column(dot + indent_len(dot)); #endif goto dc3; case 'o': // o- open an empty line below dot_end(); dc3: +#if ENABLE_FEATURE_VI_SETOPTS + cmd_mode = 1; // switch to insert mode early +#endif dot = char_insert(dot, '\n', ALLOW_UNDO); if (c == 'O' && !autoindent) { // done in char_insert() for 'O'+autoindent @@ -4264,6 +4297,7 @@ dc5: cmd_mode = 2; undo_queue_commit(); + rstart = dot; break; case KEYCODE_DELETE: if (dot < end - 1) @@ -4290,8 +4324,14 @@ goto dc_i; // start inserting break; case 'Z': // Z- if modified, {write}; exit - // ZZ means to save file (if necessary), then exit c1 = get_one_char(); + // ZQ means to exit without saving + if (c1 == 'Q') { + editing = 0; + optind = cmdline_filecnt; + break; + } + // ZZ means to save file (if necessary), then exit if (c1 != 'Z') { indicate_error(); break; @@ -4366,14 +4406,22 @@ if (buftype == WHOLE) { save_dot = p; // final cursor position is start of range p = begin_line(p); +#if ENABLE_FEATURE_VI_SETOPTS + if (c == 'c') // special case: use indent of current line + newindent = get_column(p + indent_len(p)); +#endif q = end_line(q); } dot = yank_delete(p, q, buftype, yf, ALLOW_UNDO); // delete word if (buftype == WHOLE) { if (c == 'c') { +#if ENABLE_FEATURE_VI_SETOPTS + cmd_mode = 1; // switch to insert mode early +#endif dot = char_insert(dot, '\n', ALLOW_UNDO_CHAIN); - // on the last line of file don't move to prev line - if (dot != (end-1)) { + // on the last line of file don't move to prev line, + // handled in char_insert() if autoindent is enabled + if (dot != (end-1) && !autoindent) { dot_prev(); } } else if (c == 'd') { @@ -4770,7 +4818,7 @@ uint64_t k; write1(ESC"[999;999H" ESC"[6n"); fflush_all(); - k = read_key(STDIN_FILENO, readbuffer, /*timeout_ms:*/ 100); + k = safe_read_key(STDIN_FILENO, readbuffer, /*timeout_ms:*/ 100); if ((int32_t)k == KEYCODE_CURSOR_POS) { uint32_t rc = (k >> 32); columns = (rc & 0x7fff); diff -Nru busybox-1.35.0/examples/shutdown-1.0/script/hardshutdown.c busybox-1.36.1/examples/shutdown-1.0/script/hardshutdown.c --- busybox-1.35.0/examples/shutdown-1.0/script/hardshutdown.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/examples/shutdown-1.0/script/hardshutdown.c 2023-01-03 14:14:43.000000000 +0000 @@ -102,7 +102,7 @@ REBOOT }; -int main(int argc, char *argv[]) +int main(int argc, char **argv) { struct timespec t = {0,0}; enum action_t action = SHUTDOWN; @@ -115,7 +115,7 @@ if (ptr) prog = ptr+1; - for (c=1; c < argc; c++) { + for (c = 1; c < argc; c++) { if (argv[c][0] >= '0' && argv[c][0] <= '9') { t.tv_sec = strtol(argv[c], NULL, 10); continue; @@ -124,7 +124,7 @@ usage(); return 1; } - for (i=1; argv[c][i]; i++) { + for (i = 1; argv[c][i]; i++) { switch (argv[c][i]) { case 'h': action = HALT; diff -Nru busybox-1.35.0/examples/var_service/dhcp_if/convert2ipconf busybox-1.36.1/examples/var_service/dhcp_if/convert2ipconf --- busybox-1.35.0/examples/var_service/dhcp_if/convert2ipconf 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/examples/var_service/dhcp_if/convert2ipconf 2023-01-03 14:14:43.000000000 +0000 @@ -19,7 +19,7 @@ #let cfg=cfg+1 #if[$cfg]=...; ip[$cfg]=...; ipmask[$cfg]=.../...; gw[$cfg]=...; net[$cfg]=... dns[$cfg]=... -exec >/dev/null +#exec >/dev/null #exec >"$0.out" # debug exec 2>&1 @@ -31,23 +31,31 @@ if ! test "$mask"; then case "$ip" in 10.*) + echo "mask assumed 8 for ip=$ip" mask=8;; - 192.168.*) - mask=16;; #172.16-31.x.x 172.1[6789].*) + echo "mask assumed 12 for ip=$ip" mask=12;; 172.2[0123456789].*) + echo "mask assumed 12 for ip=$ip" mask=12;; 172.3[01].*) + echo "mask assumed 12 for ip=$ip" mask=12;; + 192.168.*) + echo "mask assumed 16 for ip=$ip" + mask=16;; esac fi # some servers do not return router option. # assume DHCP server is the router. if ! test "$router"; then - test "$serverid" && router="$serverid" + if test "$serverid"; then + router="$serverid" + echo "No 'router' from the server, assuming 'serverid' is the router: $serverid" + fi fi { diff -Nru busybox-1.35.0/examples/var_service/dhcp_if/convert2ntpconf busybox-1.36.1/examples/var_service/dhcp_if/convert2ntpconf --- busybox-1.35.0/examples/var_service/dhcp_if/convert2ntpconf 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/examples/var_service/dhcp_if/convert2ntpconf 2023-01-03 14:14:43.000000000 +0000 @@ -19,7 +19,7 @@ #let cfg=cfg+1 #ntpip[$cfg]=... -exec >/dev/null +#exec >/dev/null #exec >"$0.out" # debug exec 2>&1 diff -Nru busybox-1.35.0/examples/var_service/dhcp_if/dhcp_handler busybox-1.36.1/examples/var_service/dhcp_if/dhcp_handler --- busybox-1.35.0/examples/var_service/dhcp_if/dhcp_handler 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/examples/var_service/dhcp_if/dhcp_handler 2023-01-03 14:14:43.000000000 +0000 @@ -38,12 +38,10 @@ dir_ipconf="/var/run/service/fw" dir_ntpconf="/var/run/service/ntpd" -exec >/dev/null -#exec >>"$0.out" #debug +#exec >/dev/null +#exec >"$0.out" #debug exec 2>&1 -echo "`date`: Params: $*" - if test x"$1" != x"bound" && test x"$1" != x"renew" ; then # Reconfigure network with this interface disabled echo "Deconfiguring" diff -Nru busybox-1.35.0/examples/var_service/dhcp_if/finish busybox-1.36.1/examples/var_service/dhcp_if/finish --- busybox-1.35.0/examples/var_service/dhcp_if/finish 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/examples/var_service/dhcp_if/finish 2023-01-03 14:14:43.000000000 +0000 @@ -1,5 +1,5 @@ #!/bin/sh -# executed when service is taken down ("sv d .") +# executed when service is taken down ("svc -d .") service=${PWD##*/} file_ipconf="$service.ipconf" diff -Nru busybox-1.35.0/findutils/grep.c busybox-1.36.1/findutils/grep.c --- busybox-1.35.0/findutils/grep.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/findutils/grep.c 2023-01-03 14:14:43.000000000 +0000 @@ -470,7 +470,7 @@ * "exit immediately with zero status * if any match is found, * even if errors were detected" */ - exit(EXIT_SUCCESS); + exit_SUCCESS(); } /* -l "print filenames with matches": stop after the first match */ if (option_mask32 & OPT_l) { diff -Nru busybox-1.35.0/findutils/xargs.c busybox-1.36.1/findutils/xargs.c --- busybox-1.35.0/findutils/xargs.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/findutils/xargs.c 2023-01-03 14:14:43.000000000 +0000 @@ -111,6 +111,8 @@ #endif const char *eof_str; int idx; + int fd_tty; + int fd_stdin; #if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL int running_procs; int max_procs; @@ -140,6 +142,42 @@ IF_FEATURE_XARGS_SUPPORT_QUOTES(G.process_stdin__q = '\0';) \ } while (0) +/* Correct regardless of combination of CONFIG_xxx */ +enum { + OPTBIT_VERBOSE = 0, + OPTBIT_NO_EMPTY, + OPTBIT_UPTO_NUMBER, + OPTBIT_UPTO_SIZE, + OPTBIT_EOF_STRING, + OPTBIT_EOF_STRING1, + OPTBIT_STDIN_TTY, + IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,) + IF_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,) + IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,) + IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR ,) + IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR1 ,) + + OPT_VERBOSE = 1 << OPTBIT_VERBOSE , + OPT_NO_EMPTY = 1 << OPTBIT_NO_EMPTY , + OPT_UPTO_NUMBER = 1 << OPTBIT_UPTO_NUMBER, + OPT_UPTO_SIZE = 1 << OPTBIT_UPTO_SIZE , + OPT_EOF_STRING = 1 << OPTBIT_EOF_STRING , /* GNU: -e[] */ + OPT_EOF_STRING1 = 1 << OPTBIT_EOF_STRING1, /* SUS: -E */ + OPT_STDIN_TTY = 1 << OPTBIT_STDIN_TTY, + OPT_INTERACTIVE = IF_FEATURE_XARGS_SUPPORT_CONFIRMATION((1 << OPTBIT_INTERACTIVE)) + 0, + OPT_TERMINATE = IF_FEATURE_XARGS_SUPPORT_TERMOPT( (1 << OPTBIT_TERMINATE )) + 0, + OPT_ZEROTERM = IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1 << OPTBIT_ZEROTERM )) + 0, + OPT_REPLSTR = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR )) + 0, + OPT_REPLSTR1 = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR1 )) + 0, +}; +#define OPTION_STR "+trn:s:e::E:o" \ + IF_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \ + IF_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \ + IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") \ + IF_FEATURE_XARGS_SUPPORT_REPL_STR( "I:i::") \ + IF_FEATURE_XARGS_SUPPORT_PARALLEL( "P:+") \ + IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( "a:") + /* * Returns 0 if xargs should continue (but may set G.xargs_exitcode to 123). @@ -151,6 +189,9 @@ { int status; + if (option_mask32 & OPT_STDIN_TTY) + xdup2(G.fd_tty, STDIN_FILENO); + #if !ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL status = spawn_and_wait(G.args); #else @@ -237,6 +278,8 @@ ret: if (status != 0) G.xargs_exitcode = status; + if (option_mask32 & OPT_STDIN_TTY) + xdup2(G.fd_stdin, STDIN_FILENO); return status; } @@ -542,6 +585,7 @@ //usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( //usage: "\n -a FILE Read from FILE instead of stdin" //usage: ) +//usage: "\n -o Reopen stdin as /dev/tty" //usage: "\n -r Don't run command if input is empty" //usage: "\n -t Print the command on stderr before execution" //usage: IF_FEATURE_XARGS_SUPPORT_CONFIRMATION( @@ -563,40 +607,6 @@ //usage: "$ ls | xargs gzip\n" //usage: "$ find . -name '*.c' -print | xargs rm\n" -/* Correct regardless of combination of CONFIG_xxx */ -enum { - OPTBIT_VERBOSE = 0, - OPTBIT_NO_EMPTY, - OPTBIT_UPTO_NUMBER, - OPTBIT_UPTO_SIZE, - OPTBIT_EOF_STRING, - OPTBIT_EOF_STRING1, - IF_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,) - IF_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,) - IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,) - IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR ,) - IF_FEATURE_XARGS_SUPPORT_REPL_STR( OPTBIT_REPLSTR1 ,) - - OPT_VERBOSE = 1 << OPTBIT_VERBOSE , - OPT_NO_EMPTY = 1 << OPTBIT_NO_EMPTY , - OPT_UPTO_NUMBER = 1 << OPTBIT_UPTO_NUMBER, - OPT_UPTO_SIZE = 1 << OPTBIT_UPTO_SIZE , - OPT_EOF_STRING = 1 << OPTBIT_EOF_STRING , /* GNU: -e[] */ - OPT_EOF_STRING1 = 1 << OPTBIT_EOF_STRING1, /* SUS: -E */ - OPT_INTERACTIVE = IF_FEATURE_XARGS_SUPPORT_CONFIRMATION((1 << OPTBIT_INTERACTIVE)) + 0, - OPT_TERMINATE = IF_FEATURE_XARGS_SUPPORT_TERMOPT( (1 << OPTBIT_TERMINATE )) + 0, - OPT_ZEROTERM = IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1 << OPTBIT_ZEROTERM )) + 0, - OPT_REPLSTR = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR )) + 0, - OPT_REPLSTR1 = IF_FEATURE_XARGS_SUPPORT_REPL_STR( (1 << OPTBIT_REPLSTR1 )) + 0, -}; -#define OPTION_STR "+trn:s:e::E:" \ - IF_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \ - IF_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \ - IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") \ - IF_FEATURE_XARGS_SUPPORT_REPL_STR( "I:i::") \ - IF_FEATURE_XARGS_SUPPORT_PARALLEL( "P:+") \ - IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( "a:") - int xargs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int xargs_main(int argc UNUSED_PARAM, char **argv) { @@ -726,6 +736,13 @@ store_param(argv[i]); } + if (opt & OPT_STDIN_TTY) { + G.fd_tty = xopen(CURRENT_TTY, O_RDONLY); + close_on_exec_on(G.fd_tty); + G.fd_stdin = dup(STDIN_FILENO); + close_on_exec_on(G.fd_stdin); + } + initial_idx = G.idx; while (1) { char *rem; diff -Nru busybox-1.35.0/include/libbb.h busybox-1.36.1/include/libbb.h --- busybox-1.35.0/include/libbb.h 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/include/libbb.h 2023-01-03 14:14:43.000000000 +0000 @@ -429,8 +429,8 @@ xrealloc_vector_helper((vector), (sizeof((vector)[0]) << 8) + (shift), (idx)) void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC; char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; -char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; -void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC; +char *xstrndup(const char *s, size_t n) FAST_FUNC RETURNS_MALLOC; +void *xmemdup(const void *s, size_t n) FAST_FUNC RETURNS_MALLOC; void *mmap_read(int fd, size_t size) FAST_FUNC; void *mmap_anon(size_t size) FAST_FUNC; void *xmmap_anon(size_t size) FAST_FUNC; @@ -645,6 +645,7 @@ void xsetuid(uid_t uid) FAST_FUNC; void xsetegid(gid_t egid) FAST_FUNC; void xseteuid(uid_t euid) FAST_FUNC; +int chdir_or_warn(const char *path) FAST_FUNC; void xchdir(const char *path) FAST_FUNC; void xfchdir(int fd) FAST_FUNC; void xchroot(const char *path) FAST_FUNC; @@ -1054,6 +1055,7 @@ void die_if_ferror_stdout(void) FAST_FUNC; int fflush_all(void) FAST_FUNC; void fflush_stdout_and_exit(int retval) NORETURN FAST_FUNC; +void fflush_stdout_and_exit_SUCCESS(void) NORETURN FAST_FUNC; int fclose_if_not_stdin(FILE *file) FAST_FUNC; FILE* xfopen(const char *filename, const char *mode) FAST_FUNC; /* Prints warning to stderr and returns NULL on failure: */ @@ -1277,6 +1279,8 @@ # define re_execed_comm() 0 # define set_task_comm(name) ((void)0) #endif +void exit_SUCCESS(void) NORETURN FAST_FUNC; +void _exit_SUCCESS(void) NORETURN FAST_FUNC; /* Helpers for daemonization. * @@ -1506,6 +1510,7 @@ int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE); /* If shell needs them, they exist even if not enabled as applets */ int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); +int sleep_main(int argc, char **argv) IF_SLEEP(MAIN_EXTERNALLY_VISIBLE); int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); int test_main(int argc, char **argv) #if ENABLE_TEST || ENABLE_TEST1 || ENABLE_TEST2 @@ -1723,15 +1728,16 @@ /* setup_environment: - * if chdir pw->pw_dir: ok: else if to_tmp == 1: goto /tmp else: goto / or die - * if clear_env = 1: cd(pw->pw_dir), clear environment, then set + * if SETUP_ENV_CHDIR: + * if cd(pw->pw_dir): ok: else if SETUP_ENV_TO_TMP: cd(/tmp) else: cd(/) or die + * if SETUP_ENV_CLEARENV: cd(pw->pw_dir), clear environment, then set * TERM=(old value) * USER=pw->pw_name, LOGNAME=pw->pw_name * PATH=bb_default_[root_]path * HOME=pw->pw_dir * SHELL=shell - * else if change_env = 1: - * if not root (if pw->pw_uid != 0): + * else if SETUP_ENV_CHANGEENV | SETUP_ENV_CHANGEENV_LOGNAME: + * if not root (if pw->pw_uid != 0) or if SETUP_ENV_CHANGEENV_LOGNAME: * USER=pw->pw_name, LOGNAME=pw->pw_name * HOME=pw->pw_dir * SHELL=shell @@ -1740,10 +1746,11 @@ * NB: CHANGEENV and CLEARENV use setenv() - this leaks memory! * If setup_environment() is used is vforked child, this leaks memory _in parent too_! */ -#define SETUP_ENV_CHANGEENV (1 << 0) -#define SETUP_ENV_CLEARENV (1 << 1) -#define SETUP_ENV_TO_TMP (1 << 2) -#define SETUP_ENV_NO_CHDIR (1 << 4) +#define SETUP_ENV_CHANGEENV (1 << 0) +#define SETUP_ENV_CHANGEENV_LOGNAME (1 << 1) +#define SETUP_ENV_CLEARENV (1 << 2) +#define SETUP_ENV_TO_TMP (1 << 3) +#define SETUP_ENV_CHDIR (1 << 4) void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC; void nuke_str(char *str) FAST_FUNC; #if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM @@ -1894,6 +1901,8 @@ * (unless fd is in non-blocking mode), * subsequent reads will time out after a few milliseconds. * Return of -1 means EOF or error (errno == 0 on EOF). + * Nonzero errno is not preserved across the call: + * if there was no error, errno will be cleared to 0. * buffer[0] is used as a counter of buffered chars and must be 0 * on first call. * timeout: @@ -1902,6 +1911,8 @@ * >=0: poll() for TIMEOUT milliseconds, return -1/EAGAIN on timeout */ int64_t read_key(int fd, char *buffer, int timeout) FAST_FUNC; +/* This version loops on EINTR: */ +int64_t safe_read_key(int fd, char *buffer, int timeout) FAST_FUNC; void read_key_ungets(char *buffer, const char *str, unsigned len) FAST_FUNC; @@ -1914,6 +1925,7 @@ # define MAX_HISTORY 0 # endif typedef const char *get_exe_name_t(int i) FAST_FUNC; +typedef const char *sh_get_var_t(const char *name) FAST_FUNC; typedef struct line_input_t { int flags; int timeout; @@ -1927,11 +1939,16 @@ # if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH /* function to fetch additional application-specific names to match */ get_exe_name_t *get_exe_name; -# define EDITING_HAS_get_exe_name 1 -# else -# define EDITING_HAS_get_exe_name 0 # endif # endif +# if (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) \ + && (ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH) + /* function to fetch value of shell variable */ + sh_get_var_t *sh_get_var; +# define EDITING_HAS_sh_get_var 1 +# else +# define EDITING_HAS_sh_get_var 0 +# endif # if MAX_HISTORY int cnt_history; int cur_history; @@ -1955,7 +1972,8 @@ USERNAME_COMPLETION = 4 * ENABLE_FEATURE_USERNAME_COMPLETION, VI_MODE = 8 * ENABLE_FEATURE_EDITING_VI, WITH_PATH_LOOKUP = 0x10, - FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION, + LI_INTERRUPTIBLE = 0x20, + FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION | LI_INTERRUPTIBLE, }; line_input_t *new_line_input_t(int flags) FAST_FUNC; #if ENABLE_FEATURE_EDITING_SAVEHISTORY @@ -1982,11 +2000,6 @@ read_line_input(prompt, command, maxsize) #endif -#ifndef EDITING_HAS_get_exe_name -# define EDITING_HAS_get_exe_name 0 -#endif - - #ifndef COMM_LEN # ifdef TASK_COMM_LEN enum { COMM_LEN = TASK_COMM_LEN }; @@ -2281,7 +2294,7 @@ /* '*const' ptr makes gcc optimize code much better. * Magic prevents ptr_to_globals from going into rodata. * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */ -extern struct globals *const ptr_to_globals; +extern struct globals *BB_GLOBAL_CONST ptr_to_globals; #define barrier() asm volatile ("":::"memory") diff -Nru busybox-1.35.0/include/platform.h busybox-1.36.1/include/platform.h --- busybox-1.35.0/include/platform.h 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/include/platform.h 2023-01-03 14:14:43.000000000 +0000 @@ -346,6 +346,7 @@ # define ALIGN4 #endif #define ALIGN8 __attribute__((aligned(8))) +#define ALIGN_INT __attribute__((aligned(sizeof(int)))) #define ALIGN_PTR __attribute__((aligned(sizeof(void*)))) /* diff -Nru busybox-1.35.0/init/init.c busybox-1.36.1/init/init.c --- busybox-1.35.0/init/init.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/init/init.c 2023-01-03 14:14:43.000000000 +0000 @@ -744,7 +744,7 @@ pid = vfork(); if (pid == 0) { /* child */ reboot(magic); - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } /* Used to have "while (1) sleep(1)" here. * However, in containers reboot() call is ignored, and with that loop @@ -752,7 +752,7 @@ */ waitpid(pid, NULL, 0); sleep1(); /* paranoia */ - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } static void run_shutdown_and_kill_processes(void) @@ -942,7 +942,7 @@ for (a = G.init_action_list; a; a = a->next) if (a->action_type == 0 && a->pid != 0) kill(a->pid, SIGKILL); - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } } #endif @@ -1105,10 +1105,14 @@ setsid(); /* Make sure environs is set to something sane */ - putenv((char *) "HOME=/"); putenv((char *) bb_PATH_root_path); putenv((char *) "SHELL=/bin/sh"); putenv((char *) "USER=root"); /* needed? why? */ + /* Linux kernel sets HOME="/" when execing init, + * and it can be overridden (but not unset?) on kernel's command line. + * We used to set it to "/" here, but now we do not: + */ + //putenv((char *) "HOME=/"); if (argv[1]) xsetenv("RUNLEVEL", argv[1]); diff -Nru busybox-1.35.0/libbb/appletlib.c busybox-1.36.1/libbb/appletlib.c --- busybox-1.35.0/libbb/appletlib.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/libbb/appletlib.c 2023-01-03 14:14:43.000000000 +0000 @@ -258,7 +258,6 @@ /* Redundant for busybox (run_applet_and_exit covers that case) * but needed for "individual applet" mode */ if (argv[1] - && !argv[2] && strcmp(argv[1], "--help") == 0 && !is_prefixed_with(applet, "busybox") ) { @@ -651,7 +650,7 @@ # if ENABLE_FEATURE_INSTALLER static const char usr_bin [] ALIGN1 = "/usr/bin/"; static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; -static const char *const install_dir[] = { +static const char *const install_dir[] ALIGN_PTR = { &usr_bin [8], /* "/" */ &usr_bin [4], /* "/bin/" */ &usr_sbin[4] /* "/sbin/" */ @@ -762,7 +761,7 @@ //usage:#define busybox_trivial_usage NOUSAGE_STR //usage:#define busybox_full_usage "" //applet:IF_BUSYBOX(IF_FEATURE_SH_STANDALONE(IF_FEATURE_TAB_COMPLETION(APPLET(busybox, BB_DIR_BIN, BB_SUID_MAYBE)))) -int busybox_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE; +int busybox_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; # else # define busybox_main(argc,argv) busybox_main(argv) static @@ -939,9 +938,12 @@ # if defined APPLET_NO_echo && applet_no != APPLET_NO_echo # endif +# if ENABLE_TEST1 || ENABLE_TEST2 + && argv[0][0] != '[' /* exclude [ --help ] and [[ --help ]] too */ +# endif ) { - if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0) { - /* Make "foo --help" exit with 0: */ + if (argv[1] && strcmp(argv[1], "--help") == 0) { + /* Make "foo --help [...]" exit with 0: */ xfunc_error_retval = 0; bb_show_usage(); } diff -Nru busybox-1.35.0/libbb/Config.src busybox-1.36.1/libbb/Config.src --- busybox-1.35.0/libbb/Config.src 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/libbb/Config.src 2023-01-03 14:14:43.000000000 +0000 @@ -42,21 +42,47 @@ default 1 # all "fast or small" options default to small range 0 3 help - Trade binary size versus speed for the md5sum algorithm. + Trade binary size versus speed for the md5 algorithm. Approximate values running uClibc and hashing linux-2.4.4.tar.bz2 were: - value user times (sec) text size (386) - 0 (fastest) 1.1 6144 - 1 1.4 5392 - 2 3.0 5088 - 3 (smallest) 5.1 4912 + value user times (sec) text size (386) + 0 (fastest) 1.1 6144 + 1 1.4 5392 + 2 3.0 5088 + 3 (smallest) 5.1 4912 + +config SHA1_SMALL + int "SHA1: Trade bytes for speed (0:fast, 3:slow)" + default 3 # all "fast or small" options default to small + range 0 3 + help + Trade binary size versus speed for the sha1 algorithm. + With FEATURE_COPYBUF_KB=64: + throughput MB/s size of sha1_process_block64 + value 486 x86-64 486 x86-64 + 0 440 485 3481 3502 + 1 265 265 641 696 + 2,3 220 210 342 364 + +config SHA1_HWACCEL + bool "SHA1: Use hardware accelerated instructions if possible" + default y + help + On x86, this adds ~590 bytes of code. Throughput + is about twice as fast as fully-unrolled generic code. + +config SHA256_HWACCEL + bool "SHA256: Use hardware accelerated instructions if possible" + default y + help + On x86, this adds ~1k bytes of code. config SHA3_SMALL int "SHA3: Trade bytes for speed (0:fast, 1:slow)" default 1 # all "fast or small" options default to small range 0 1 help - Trade binary size versus speed for the sha3sum algorithm. + Trade binary size versus speed for the sha3 algorithm. SHA3_SMALL=0 compared to SHA3_SMALL=1 (approximate): 64-bit x86: +270 bytes of code, 45% faster 32-bit x86: +450 bytes of code, 75% faster @@ -343,3 +369,25 @@ For example, this means that entering 'l', 's', ' ', 0xff, [Enter] at shell prompt will list file named 0xff (single char name with char value 255), not file named '?'. + +choice + prompt "Use LOOP_CONFIGURE for losetup and loop mounts" + default TRY_LOOP_CONFIGURE + help + LOOP_CONFIGURE is added to Linux 5.8 + https://lwn.net/Articles/820408/ + This allows userspace to completely setup a loop device with a single + ioctl, removing the in-between state where the device can be partially + configured - eg the loop device has a backing file associated with it, + but is reading from the wrong offset. + +config LOOP_CONFIGURE + bool "use LOOP_CONFIGURE, needs kernel >= 5.8" + +config NO_LOOP_CONFIGURE + bool "use LOOP_SET_FD + LOOP_SET_STATUS" + +config TRY_LOOP_CONFIGURE + bool "try LOOP_CONFIGURE, fall back to LOOP_SET_FD + LOOP_SET_STATUS" + +endchoice diff -Nru busybox-1.35.0/libbb/duration.c busybox-1.36.1/libbb/duration.c --- busybox-1.35.0/libbb/duration.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/libbb/duration.c 2023-04-25 14:47:22.000000000 +0000 @@ -76,10 +76,14 @@ ts.tv_sec = duration; ts.tv_nsec = (duration - ts.tv_sec) * 1000000000; } - do { - errno = 0; - nanosleep(&ts, &ts); - } while (errno == EINTR); + /* NB: ENABLE_ASH_SLEEP requires that we do NOT loop on EINTR here: + * otherwise, traps won't execute until we finish looping. + */ + //do { + // errno = 0; + // nanosleep(&ts, &ts); + //} while (errno == EINTR); + nanosleep(&ts, &ts); } #else duration_t FAST_FUNC parse_duration_str(char *str) diff -Nru busybox-1.35.0/libbb/fflush_stdout_and_exit.c busybox-1.36.1/libbb/fflush_stdout_and_exit.c --- busybox-1.35.0/libbb/fflush_stdout_and_exit.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/libbb/fflush_stdout_and_exit.c 2023-01-03 14:14:43.000000000 +0000 @@ -13,10 +13,15 @@ */ void FAST_FUNC fflush_stdout_and_exit(int retval) { - xfunc_error_retval = retval; if (fflush(stdout)) bb_simple_perror_msg_and_die(bb_msg_standard_output); + xfunc_error_retval = retval; /* In case we are in NOFORK applet. Do not exit() directly, * but use xfunc_die() */ xfunc_die(); } + +void FAST_FUNC fflush_stdout_and_exit_SUCCESS(void) +{ + fflush_stdout_and_exit(EXIT_SUCCESS); +} diff -Nru busybox-1.35.0/libbb/get_console.c busybox-1.36.1/libbb/get_console.c --- busybox-1.35.0/libbb/get_console.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/libbb/get_console.c 2023-01-03 14:14:43.000000000 +0000 @@ -37,7 +37,7 @@ */ int FAST_FUNC get_console_fd_or_die(void) { - static const char *const console_names[] = { + static const char *const console_names[] ALIGN_PTR = { DEV_CONSOLE, CURRENT_VC, CURRENT_TTY }; diff -Nru busybox-1.35.0/libbb/getopt32.c busybox-1.36.1/libbb/getopt32.c --- busybox-1.35.0/libbb/getopt32.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/libbb/getopt32.c 2023-01-03 14:14:43.000000000 +0000 @@ -296,7 +296,7 @@ /* Code here assumes that 'unsigned' is at least 32 bits wide */ -const char *const bb_argv_dash[] = { "-", NULL }; +const char *const bb_argv_dash[] ALIGN_PTR = { "-", NULL }; enum { PARAM_STRING, diff -Nru busybox-1.35.0/libbb/hash_md5_sha256_x86-32_shaNI.S busybox-1.36.1/libbb/hash_md5_sha256_x86-32_shaNI.S --- busybox-1.35.0/libbb/hash_md5_sha256_x86-32_shaNI.S 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/libbb/hash_md5_sha256_x86-32_shaNI.S 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,284 @@ +#if ENABLE_SHA256_HWACCEL && defined(__GNUC__) && defined(__i386__) +/* The code is adapted from Linux kernel's source */ + +// We use shorter insns, even though they are for "wrong" +// data type (fp, not int). +// For Intel, there is no penalty for doing it at all +// (CPUs which do have such penalty do not support SHA insns). +// For AMD, the penalty is one extra cycle +// (allegedly: I failed to find measurable difference). + +//#define mova128 movdqa +#define mova128 movaps +//#define movu128 movdqu +#define movu128 movups +//#define shuf128_32 pshufd +#define shuf128_32 shufps + +// pshufb and palignr are SSSE3 insns. +// We do not check SSSE3 in cpuid, +// all SHA-capable CPUs support it as well. + +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif + .section .text.sha256_process_block64_shaNI, "ax", @progbits + .globl sha256_process_block64_shaNI + .hidden sha256_process_block64_shaNI + .type sha256_process_block64_shaNI, @function + +#define DATA_PTR %eax + +#define SHA256CONSTANTS %ecx + +#define MSG %xmm0 +#define STATE0 %xmm1 +#define STATE1 %xmm2 +#define MSGTMP0 %xmm3 +#define MSGTMP1 %xmm4 +#define MSGTMP2 %xmm5 +#define MSGTMP3 %xmm6 + +#define XMMTMP %xmm7 + +#define SHUF(a,b,c,d) $(a+(b<<2)+(c<<4)+(d<<6)) + + .balign 8 # allow decoders to fetch at least 2 first insns +sha256_process_block64_shaNI: + + movu128 76+0*16(%eax), XMMTMP /* ABCD (little-endian dword order) */ + movu128 76+1*16(%eax), STATE1 /* EFGH */ +/* shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one */ + mova128 STATE1, STATE0 + /* --- -------------- ABCD -- EFGH */ + shufps SHUF(1,0,1,0), XMMTMP, STATE0 /* FEBA */ + shufps SHUF(3,2,3,2), XMMTMP, STATE1 /* HGDC */ + +/* XMMTMP holds flip mask from here... */ + mova128 PSHUFFLE_BSWAP32_FLIP_MASK, XMMTMP + movl $K256+8*16, SHA256CONSTANTS + + /* Rounds 0-3 */ + movu128 0*16(DATA_PTR), MSG + pshufb XMMTMP, MSG + mova128 MSG, MSGTMP0 + paddd 0*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + + /* Rounds 4-7 */ + movu128 1*16(DATA_PTR), MSG + pshufb XMMTMP, MSG + mova128 MSG, MSGTMP1 + paddd 1*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP1, MSGTMP0 + + /* Rounds 8-11 */ + movu128 2*16(DATA_PTR), MSG + pshufb XMMTMP, MSG + mova128 MSG, MSGTMP2 + paddd 2*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP2, MSGTMP1 + + /* Rounds 12-15 */ + movu128 3*16(DATA_PTR), MSG + pshufb XMMTMP, MSG +/* ...to here */ + mova128 MSG, MSGTMP3 + paddd 3*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP3, XMMTMP + palignr $4, MSGTMP2, XMMTMP + paddd XMMTMP, MSGTMP0 + sha256msg2 MSGTMP3, MSGTMP0 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP3, MSGTMP2 + + /* Rounds 16-19 */ + mova128 MSGTMP0, MSG + paddd 4*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP0, XMMTMP + palignr $4, MSGTMP3, XMMTMP + paddd XMMTMP, MSGTMP1 + sha256msg2 MSGTMP0, MSGTMP1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP0, MSGTMP3 + + /* Rounds 20-23 */ + mova128 MSGTMP1, MSG + paddd 5*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP1, XMMTMP + palignr $4, MSGTMP0, XMMTMP + paddd XMMTMP, MSGTMP2 + sha256msg2 MSGTMP1, MSGTMP2 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP1, MSGTMP0 + + /* Rounds 24-27 */ + mova128 MSGTMP2, MSG + paddd 6*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP2, XMMTMP + palignr $4, MSGTMP1, XMMTMP + paddd XMMTMP, MSGTMP3 + sha256msg2 MSGTMP2, MSGTMP3 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP2, MSGTMP1 + + /* Rounds 28-31 */ + mova128 MSGTMP3, MSG + paddd 7*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP3, XMMTMP + palignr $4, MSGTMP2, XMMTMP + paddd XMMTMP, MSGTMP0 + sha256msg2 MSGTMP3, MSGTMP0 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP3, MSGTMP2 + + /* Rounds 32-35 */ + mova128 MSGTMP0, MSG + paddd 8*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP0, XMMTMP + palignr $4, MSGTMP3, XMMTMP + paddd XMMTMP, MSGTMP1 + sha256msg2 MSGTMP0, MSGTMP1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP0, MSGTMP3 + + /* Rounds 36-39 */ + mova128 MSGTMP1, MSG + paddd 9*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP1, XMMTMP + palignr $4, MSGTMP0, XMMTMP + paddd XMMTMP, MSGTMP2 + sha256msg2 MSGTMP1, MSGTMP2 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP1, MSGTMP0 + + /* Rounds 40-43 */ + mova128 MSGTMP2, MSG + paddd 10*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP2, XMMTMP + palignr $4, MSGTMP1, XMMTMP + paddd XMMTMP, MSGTMP3 + sha256msg2 MSGTMP2, MSGTMP3 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP2, MSGTMP1 + + /* Rounds 44-47 */ + mova128 MSGTMP3, MSG + paddd 11*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP3, XMMTMP + palignr $4, MSGTMP2, XMMTMP + paddd XMMTMP, MSGTMP0 + sha256msg2 MSGTMP3, MSGTMP0 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP3, MSGTMP2 + + /* Rounds 48-51 */ + mova128 MSGTMP0, MSG + paddd 12*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP0, XMMTMP + palignr $4, MSGTMP3, XMMTMP + paddd XMMTMP, MSGTMP1 + sha256msg2 MSGTMP0, MSGTMP1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP0, MSGTMP3 + + /* Rounds 52-55 */ + mova128 MSGTMP1, MSG + paddd 13*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP1, XMMTMP + palignr $4, MSGTMP0, XMMTMP + paddd XMMTMP, MSGTMP2 + sha256msg2 MSGTMP1, MSGTMP2 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + + /* Rounds 56-59 */ + mova128 MSGTMP2, MSG + paddd 14*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP2, XMMTMP + palignr $4, MSGTMP1, XMMTMP + paddd XMMTMP, MSGTMP3 + sha256msg2 MSGTMP2, MSGTMP3 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + + /* Rounds 60-63 */ + mova128 MSGTMP3, MSG + paddd 15*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + + /* Write hash values back in the correct order */ + mova128 STATE0, XMMTMP +/* shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one */ + /* --- -------------- HGDC -- FEBA */ + shufps SHUF(3,2,3,2), STATE1, STATE0 /* ABCD */ + shufps SHUF(1,0,1,0), STATE1, XMMTMP /* EFGH */ + /* add current hash values to previous ones */ + movu128 76+1*16(%eax), STATE1 + paddd XMMTMP, STATE1 + movu128 STATE1, 76+1*16(%eax) + movu128 76+0*16(%eax), XMMTMP + paddd XMMTMP, STATE0 + movu128 STATE0, 76+0*16(%eax) + + ret + .size sha256_process_block64_shaNI, .-sha256_process_block64_shaNI + + .section .rodata.cst256.K256, "aM", @progbits, 256 + .balign 16 +K256: + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + + .section .rodata.cst16.PSHUFFLE_BSWAP32_FLIP_MASK, "aM", @progbits, 16 + .balign 16 +PSHUFFLE_BSWAP32_FLIP_MASK: + .octa 0x0c0d0e0f08090a0b0405060700010203 + +#endif diff -Nru busybox-1.35.0/libbb/hash_md5_sha256_x86-64_shaNI.S busybox-1.36.1/libbb/hash_md5_sha256_x86-64_shaNI.S --- busybox-1.35.0/libbb/hash_md5_sha256_x86-64_shaNI.S 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/libbb/hash_md5_sha256_x86-64_shaNI.S 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,290 @@ +#if ENABLE_SHA256_HWACCEL && defined(__GNUC__) && defined(__x86_64__) +/* The code is adapted from Linux kernel's source */ + +// We use shorter insns, even though they are for "wrong" +// data type (fp, not int). +// For Intel, there is no penalty for doing it at all +// (CPUs which do have such penalty do not support SHA insns). +// For AMD, the penalty is one extra cycle +// (allegedly: I failed to find measurable difference). + +//#define mova128 movdqa +#define mova128 movaps +//#define movu128 movdqu +#define movu128 movups +//#define shuf128_32 pshufd +#define shuf128_32 shufps + +// pshufb and palignr are SSSE3 insns. +// We do not check SSSE3 in cpuid, +// all SHA-capable CPUs support it as well. + +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif + .section .text.sha256_process_block64_shaNI, "ax", @progbits + .globl sha256_process_block64_shaNI + .hidden sha256_process_block64_shaNI + .type sha256_process_block64_shaNI, @function + +#define DATA_PTR %rdi + +#define SHA256CONSTANTS %rax + +#define MSG %xmm0 +#define STATE0 %xmm1 +#define STATE1 %xmm2 +#define MSGTMP0 %xmm3 +#define MSGTMP1 %xmm4 +#define MSGTMP2 %xmm5 +#define MSGTMP3 %xmm6 + +#define XMMTMP %xmm7 + +#define SAVE0 %xmm8 +#define SAVE1 %xmm9 + +#define SHUF(a,b,c,d) $(a+(b<<2)+(c<<4)+(d<<6)) + + .balign 8 # allow decoders to fetch at least 2 first insns +sha256_process_block64_shaNI: + + movu128 80+0*16(%rdi), XMMTMP /* ABCD (little-endian dword order) */ + movu128 80+1*16(%rdi), STATE1 /* EFGH */ +/* shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one */ + mova128 STATE1, STATE0 + /* --- -------------- ABCD -- EFGH */ + shufps SHUF(1,0,1,0), XMMTMP, STATE0 /* FEBA */ + shufps SHUF(3,2,3,2), XMMTMP, STATE1 /* HGDC */ + +/* XMMTMP holds flip mask from here... */ + mova128 PSHUFFLE_BSWAP32_FLIP_MASK(%rip), XMMTMP + leaq K256+8*16(%rip), SHA256CONSTANTS + + /* Save hash values for addition after rounds */ + mova128 STATE0, SAVE0 + mova128 STATE1, SAVE1 + + /* Rounds 0-3 */ + movu128 0*16(DATA_PTR), MSG + pshufb XMMTMP, MSG + mova128 MSG, MSGTMP0 + paddd 0*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + + /* Rounds 4-7 */ + movu128 1*16(DATA_PTR), MSG + pshufb XMMTMP, MSG + mova128 MSG, MSGTMP1 + paddd 1*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP1, MSGTMP0 + + /* Rounds 8-11 */ + movu128 2*16(DATA_PTR), MSG + pshufb XMMTMP, MSG + mova128 MSG, MSGTMP2 + paddd 2*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP2, MSGTMP1 + + /* Rounds 12-15 */ + movu128 3*16(DATA_PTR), MSG + pshufb XMMTMP, MSG +/* ...to here */ + mova128 MSG, MSGTMP3 + paddd 3*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP3, XMMTMP + palignr $4, MSGTMP2, XMMTMP + paddd XMMTMP, MSGTMP0 + sha256msg2 MSGTMP3, MSGTMP0 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP3, MSGTMP2 + + /* Rounds 16-19 */ + mova128 MSGTMP0, MSG + paddd 4*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP0, XMMTMP + palignr $4, MSGTMP3, XMMTMP + paddd XMMTMP, MSGTMP1 + sha256msg2 MSGTMP0, MSGTMP1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP0, MSGTMP3 + + /* Rounds 20-23 */ + mova128 MSGTMP1, MSG + paddd 5*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP1, XMMTMP + palignr $4, MSGTMP0, XMMTMP + paddd XMMTMP, MSGTMP2 + sha256msg2 MSGTMP1, MSGTMP2 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP1, MSGTMP0 + + /* Rounds 24-27 */ + mova128 MSGTMP2, MSG + paddd 6*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP2, XMMTMP + palignr $4, MSGTMP1, XMMTMP + paddd XMMTMP, MSGTMP3 + sha256msg2 MSGTMP2, MSGTMP3 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP2, MSGTMP1 + + /* Rounds 28-31 */ + mova128 MSGTMP3, MSG + paddd 7*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP3, XMMTMP + palignr $4, MSGTMP2, XMMTMP + paddd XMMTMP, MSGTMP0 + sha256msg2 MSGTMP3, MSGTMP0 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP3, MSGTMP2 + + /* Rounds 32-35 */ + mova128 MSGTMP0, MSG + paddd 8*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP0, XMMTMP + palignr $4, MSGTMP3, XMMTMP + paddd XMMTMP, MSGTMP1 + sha256msg2 MSGTMP0, MSGTMP1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP0, MSGTMP3 + + /* Rounds 36-39 */ + mova128 MSGTMP1, MSG + paddd 9*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP1, XMMTMP + palignr $4, MSGTMP0, XMMTMP + paddd XMMTMP, MSGTMP2 + sha256msg2 MSGTMP1, MSGTMP2 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP1, MSGTMP0 + + /* Rounds 40-43 */ + mova128 MSGTMP2, MSG + paddd 10*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP2, XMMTMP + palignr $4, MSGTMP1, XMMTMP + paddd XMMTMP, MSGTMP3 + sha256msg2 MSGTMP2, MSGTMP3 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP2, MSGTMP1 + + /* Rounds 44-47 */ + mova128 MSGTMP3, MSG + paddd 11*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP3, XMMTMP + palignr $4, MSGTMP2, XMMTMP + paddd XMMTMP, MSGTMP0 + sha256msg2 MSGTMP3, MSGTMP0 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP3, MSGTMP2 + + /* Rounds 48-51 */ + mova128 MSGTMP0, MSG + paddd 12*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP0, XMMTMP + palignr $4, MSGTMP3, XMMTMP + paddd XMMTMP, MSGTMP1 + sha256msg2 MSGTMP0, MSGTMP1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + sha256msg1 MSGTMP0, MSGTMP3 + + /* Rounds 52-55 */ + mova128 MSGTMP1, MSG + paddd 13*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP1, XMMTMP + palignr $4, MSGTMP0, XMMTMP + paddd XMMTMP, MSGTMP2 + sha256msg2 MSGTMP1, MSGTMP2 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + + /* Rounds 56-59 */ + mova128 MSGTMP2, MSG + paddd 14*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + mova128 MSGTMP2, XMMTMP + palignr $4, MSGTMP1, XMMTMP + paddd XMMTMP, MSGTMP3 + sha256msg2 MSGTMP2, MSGTMP3 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + + /* Rounds 60-63 */ + mova128 MSGTMP3, MSG + paddd 15*16-8*16(SHA256CONSTANTS), MSG + sha256rnds2 MSG, STATE0, STATE1 + shuf128_32 $0x0E, MSG, MSG + sha256rnds2 MSG, STATE1, STATE0 + + /* Add current hash values with previously saved */ + paddd SAVE0, STATE0 + paddd SAVE1, STATE1 + + /* Write hash values back in the correct order */ + mova128 STATE0, XMMTMP +/* shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one */ + /* --- -------------- HGDC -- FEBA */ + shufps SHUF(3,2,3,2), STATE1, STATE0 /* ABCD */ + shufps SHUF(1,0,1,0), STATE1, XMMTMP /* EFGH */ + movu128 STATE0, 80+0*16(%rdi) + movu128 XMMTMP, 80+1*16(%rdi) + + ret + .size sha256_process_block64_shaNI, .-sha256_process_block64_shaNI + + .section .rodata.cst256.K256, "aM", @progbits, 256 + .balign 16 +K256: + .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 + .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 + .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 + .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 + .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc + .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da + .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 + .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 + .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 + .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 + .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 + .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 + .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 + .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 + .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 + .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + + .section .rodata.cst16.PSHUFFLE_BSWAP32_FLIP_MASK, "aM", @progbits, 16 + .balign 16 +PSHUFFLE_BSWAP32_FLIP_MASK: + .octa 0x0c0d0e0f08090a0b0405060700010203 + +#endif diff -Nru busybox-1.35.0/libbb/hash_md5_sha.c busybox-1.36.1/libbb/hash_md5_sha.c --- busybox-1.35.0/libbb/hash_md5_sha.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/libbb/hash_md5_sha.c 2023-03-29 13:50:40.000000000 +0000 @@ -8,8 +8,32 @@ */ #include "libbb.h" +#define STR1(s) #s +#define STR(s) STR1(s) + #define NEED_SHA512 (ENABLE_SHA512SUM || ENABLE_USE_BB_CRYPT_SHA) +#if ENABLE_SHA1_HWACCEL || ENABLE_SHA256_HWACCEL +# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +static void cpuid(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) +{ + asm ("cpuid" + : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) + : "0"(*eax), "1"(*ebx), "2"(*ecx), "3"(*edx) + ); +} +static smallint shaNI; +void FAST_FUNC sha1_process_block64_shaNI(sha1_ctx_t *ctx); +void FAST_FUNC sha256_process_block64_shaNI(sha256_ctx_t *ctx); +# if defined(__i386__) +struct ASM_expects_76_shaNI { char t[1 - 2*(offsetof(sha256_ctx_t, hash) != 76)]; }; +# endif +# if defined(__x86_64__) +struct ASM_expects_80_shaNI { char t[1 - 2*(offsetof(sha256_ctx_t, hash) != 80)]; }; +# endif +# endif +#endif + /* gcc 4.2.1 optimizes rotr64 better with inline than with macro * (for rotX32, there is no difference). Why? My guess is that * macro requires clever common subexpression elimination heuristics @@ -390,7 +414,6 @@ OP(FI, D, A, B, C, 11, 10, 0xbd3af235); OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP(FI, B, C, D, A, 9, 21, 0xeb86d391); -# undef OP # endif /* Add checksum to the starting values */ ctx->hash[0] += A; @@ -399,6 +422,7 @@ ctx->hash[3] += D; #endif } +#undef OP #undef FF #undef FG #undef FH @@ -490,18 +514,410 @@ * then rebuild and compare "shaNNNsum bigfile" results. */ +#if CONFIG_SHA1_SMALL == 0 +# if defined(__GNUC__) && defined(__i386__) +static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx UNUSED_PARAM) +{ + BUILD_BUG_ON(offsetof(sha1_ctx_t, hash) != 76); + asm( +"\n\ + pushl %ebp # \n\ + pushl %edi # \n\ + pushl %esi # \n\ + pushl %ebx # \n\ + pushl %eax \n\ + movl $15, %edi \n\ +1: \n\ + movl (%eax,%edi,4), %esi \n\ + bswap %esi \n\ + pushl %esi \n\ + decl %edi \n\ + jns 1b \n\ + movl 80(%eax), %ebx # b = ctx->hash[1] \n\ + movl 84(%eax), %ecx # c = ctx->hash[2] \n\ + movl 88(%eax), %edx # d = ctx->hash[3] \n\ + movl 92(%eax), %ebp # e = ctx->hash[4] \n\ + movl 76(%eax), %eax # a = ctx->hash[0] \n\ +#Register and stack use: \n\ +# eax..edx: a..d \n\ +# ebp: e \n\ +# esi,edi: temps \n\ +# 4*n(%esp): W[n] \n\ +" +#define RD1As(a,b,c,d,e, n, RCONST) \ +"\n\ + ##movl 4*"n"(%esp), %esi # n=0, W[0] already in %esi \n\ + movl "c", %edi # c \n\ + xorl "d", %edi # ^d \n\ + andl "b", %edi # &b \n\ + xorl "d", %edi # (((c ^ d) & b) ^ d) \n\ + leal "RCONST"("e",%esi), "e" # e += RCONST + W[n] \n\ + addl %edi, "e" # e += (((c ^ d) & b) ^ d) \n\ + movl "a", %esi # \n\ + roll $5, %esi # rotl32(a,5) \n\ + addl %esi, "e" # e += rotl32(a,5) \n\ + rorl $2, "b" # b = rotl32(b,30) \n\ +" +#define RD1Bs(a,b,c,d,e, n, RCONST) \ +"\n\ + movl 4*"n"(%esp), %esi # W[n] \n\ + movl "c", %edi # c \n\ + xorl "d", %edi # ^d \n\ + andl "b", %edi # &b \n\ + xorl "d", %edi # (((c ^ d) & b) ^ d) \n\ + leal "RCONST"("e",%esi), "e" # e += RCONST + W[n] \n\ + addl %edi, "e" # e += (((c ^ d) & b) ^ d) \n\ + movl "a", %esi # \n\ + roll $5, %esi # rotl32(a,5) \n\ + addl %esi, "e" # e += rotl32(a,5) \n\ + rorl $2, "b" # b = rotl32(b,30) \n\ +" +#define RD1Cs(a,b,c,d,e, n13,n8,n2,n, RCONST) \ +"\n\ + movl 4*"n13"(%esp), %esi # W[(n+13) & 15] \n\ + xorl 4*"n8"(%esp), %esi # ^W[(n+8) & 15] \n\ + xorl 4*"n2"(%esp), %esi # ^W[(n+2) & 15] \n\ + xorl 4*"n"(%esp), %esi # ^W[n & 15] \n\ + roll %esi # \n\ + movl %esi, 4*"n"(%esp) # store to W[n & 15] \n\ + movl "c", %edi # c \n\ + xorl "d", %edi # ^d \n\ + andl "b", %edi # &b \n\ + xorl "d", %edi # (((c ^ d) & b) ^ d) \n\ + leal "RCONST"("e",%esi), "e" # e += RCONST + mixed_W \n\ + addl %edi, "e" # e += (((c ^ d) & b) ^ d) \n\ + movl "a", %esi # \n\ + roll $5, %esi # rotl32(a,5) \n\ + addl %esi, "e" # e += rotl32(a,5) \n\ + rorl $2, "b" # b = rotl32(b,30) \n\ +" +#define RD1A(a,b,c,d,e, n) RD1As("%e"STR(a),"%e"STR(b),"%e"STR(c),"%e"STR(d),"%e"STR(e), STR((n)), STR(RCONST)) +#define RD1B(a,b,c,d,e, n) RD1Bs("%e"STR(a),"%e"STR(b),"%e"STR(c),"%e"STR(d),"%e"STR(e), STR((n)), STR(RCONST)) +#define RD1C(a,b,c,d,e, n) RD1Cs("%e"STR(a),"%e"STR(b),"%e"STR(c),"%e"STR(d),"%e"STR(e), STR(((n+13)&15)), STR(((n+8)&15)), STR(((n+2)&15)), STR(((n)&15)), STR(RCONST)) +#undef RCONST +#define RCONST 0x5A827999 + RD1A(ax,bx,cx,dx,bp, 0) RD1B(bp,ax,bx,cx,dx, 1) RD1B(dx,bp,ax,bx,cx, 2) RD1B(cx,dx,bp,ax,bx, 3) RD1B(bx,cx,dx,bp,ax, 4) + RD1B(ax,bx,cx,dx,bp, 5) RD1B(bp,ax,bx,cx,dx, 6) RD1B(dx,bp,ax,bx,cx, 7) RD1B(cx,dx,bp,ax,bx, 8) RD1B(bx,cx,dx,bp,ax, 9) + RD1B(ax,bx,cx,dx,bp,10) RD1B(bp,ax,bx,cx,dx,11) RD1B(dx,bp,ax,bx,cx,12) RD1B(cx,dx,bp,ax,bx,13) RD1B(bx,cx,dx,bp,ax,14) + RD1B(ax,bx,cx,dx,bp,15) RD1C(bp,ax,bx,cx,dx,16) RD1C(dx,bp,ax,bx,cx,17) RD1C(cx,dx,bp,ax,bx,18) RD1C(bx,cx,dx,bp,ax,19) +#define RD2s(a,b,c,d,e, n13,n8,n2,n, RCONST) \ +"\n\ + movl 4*"n13"(%esp), %esi # W[(n+13) & 15] \n\ + xorl 4*"n8"(%esp), %esi # ^W[(n+8) & 15] \n\ + xorl 4*"n2"(%esp), %esi # ^W[(n+2) & 15] \n\ + xorl 4*"n"(%esp), %esi # ^W[n & 15] \n\ + roll %esi # \n\ + movl %esi, 4*"n"(%esp) # store to W[n & 15] \n\ + movl "c", %edi # c \n\ + xorl "d", %edi # ^d \n\ + xorl "b", %edi # ^b \n\ + leal "RCONST"("e",%esi), "e" # e += RCONST + mixed_W \n\ + addl %edi, "e" # e += (c ^ d ^ b) \n\ + movl "a", %esi # \n\ + roll $5, %esi # rotl32(a,5) \n\ + addl %esi, "e" # e += rotl32(a,5) \n\ + rorl $2, "b" # b = rotl32(b,30) \n\ +" +#define RD2(a,b,c,d,e, n) RD2s("%e"STR(a),"%e"STR(b),"%e"STR(c),"%e"STR(d),"%e"STR(e), STR(((20+n+13)&15)), STR(((20+n+8)&15)), STR(((20+n+2)&15)), STR(((20+n)&15)), STR(RCONST)) +#undef RCONST +#define RCONST 0x6ED9EBA1 + RD2(ax,bx,cx,dx,bp, 0) RD2(bp,ax,bx,cx,dx, 1) RD2(dx,bp,ax,bx,cx, 2) RD2(cx,dx,bp,ax,bx, 3) RD2(bx,cx,dx,bp,ax, 4) + RD2(ax,bx,cx,dx,bp, 5) RD2(bp,ax,bx,cx,dx, 6) RD2(dx,bp,ax,bx,cx, 7) RD2(cx,dx,bp,ax,bx, 8) RD2(bx,cx,dx,bp,ax, 9) + RD2(ax,bx,cx,dx,bp,10) RD2(bp,ax,bx,cx,dx,11) RD2(dx,bp,ax,bx,cx,12) RD2(cx,dx,bp,ax,bx,13) RD2(bx,cx,dx,bp,ax,14) + RD2(ax,bx,cx,dx,bp,15) RD2(bp,ax,bx,cx,dx,16) RD2(dx,bp,ax,bx,cx,17) RD2(cx,dx,bp,ax,bx,18) RD2(bx,cx,dx,bp,ax,19) + +#define RD3s(a,b,c,d,e, n13,n8,n2,n, RCONST) \ +"\n\ + movl "b", %edi # di: b \n\ + movl "b", %esi # si: b \n\ + orl "c", %edi # di: b | c \n\ + andl "c", %esi # si: b & c \n\ + andl "d", %edi # di: (b | c) & d \n\ + orl %esi, %edi # ((b | c) & d) | (b & c) \n\ + movl 4*"n13"(%esp), %esi # W[(n+13) & 15] \n\ + xorl 4*"n8"(%esp), %esi # ^W[(n+8) & 15] \n\ + xorl 4*"n2"(%esp), %esi # ^W[(n+2) & 15] \n\ + xorl 4*"n"(%esp), %esi # ^W[n & 15] \n\ + roll %esi # \n\ + movl %esi, 4*"n"(%esp) # store to W[n & 15] \n\ + addl %edi, "e" # += ((b | c) & d) | (b & c)\n\ + leal "RCONST"("e",%esi), "e" # e += RCONST + mixed_W \n\ + movl "a", %esi # \n\ + roll $5, %esi # rotl32(a,5) \n\ + addl %esi, "e" # e += rotl32(a,5) \n\ + rorl $2, "b" # b = rotl32(b,30) \n\ +" +#define RD3(a,b,c,d,e, n) RD3s("%e"STR(a),"%e"STR(b),"%e"STR(c),"%e"STR(d),"%e"STR(e), STR(((40+n+13)&15)), STR(((40+n+8)&15)), STR(((40+n+2)&15)), STR(((40+n)&15)), STR(RCONST)) +#undef RCONST +#define RCONST 0x8F1BBCDC + RD3(ax,bx,cx,dx,bp, 0) RD3(bp,ax,bx,cx,dx, 1) RD3(dx,bp,ax,bx,cx, 2) RD3(cx,dx,bp,ax,bx, 3) RD3(bx,cx,dx,bp,ax, 4) + RD3(ax,bx,cx,dx,bp, 5) RD3(bp,ax,bx,cx,dx, 6) RD3(dx,bp,ax,bx,cx, 7) RD3(cx,dx,bp,ax,bx, 8) RD3(bx,cx,dx,bp,ax, 9) + RD3(ax,bx,cx,dx,bp,10) RD3(bp,ax,bx,cx,dx,11) RD3(dx,bp,ax,bx,cx,12) RD3(cx,dx,bp,ax,bx,13) RD3(bx,cx,dx,bp,ax,14) + RD3(ax,bx,cx,dx,bp,15) RD3(bp,ax,bx,cx,dx,16) RD3(dx,bp,ax,bx,cx,17) RD3(cx,dx,bp,ax,bx,18) RD3(bx,cx,dx,bp,ax,19) + +#define RD4As(a,b,c,d,e, n13,n8,n2,n, RCONST) \ +"\n\ + movl 4*"n13"(%esp), %esi # W[(n+13) & 15] \n\ + xorl 4*"n8"(%esp), %esi # ^W[(n+8) & 15] \n\ + xorl 4*"n2"(%esp), %esi # ^W[(n+2) & 15] \n\ + xorl 4*"n"(%esp), %esi # ^W[n & 15] \n\ + roll %esi # \n\ + movl %esi, 4*"n"(%esp) # store to W[n & 15] \n\ + movl "c", %edi # c \n\ + xorl "d", %edi # ^d \n\ + xorl "b", %edi # ^b \n\ + leal "RCONST"("e",%esi), "e" # e += RCONST + mixed_W \n\ + addl %edi, "e" # e += (c ^ d ^ b) \n\ + movl "a", %esi # \n\ + roll $5, %esi # rotl32(a,5) \n\ + addl %esi, "e" # e += rotl32(a,5) \n\ + rorl $2, "b" # b = rotl32(b,30) \n\ +" +#define RD4Bs(a,b,c,d,e, n13,n8,n2,n, RCONST) \ +"\n\ + movl 4*"n13"(%esp), %esi # W[(n+13) & 15] \n\ + xorl 4*"n8"(%esp), %esi # ^W[(n+8) & 15] \n\ + xorl 4*"n2"(%esp), %esi # ^W[(n+2) & 15] \n\ + xorl 4*"n"(%esp), %esi # ^W[n & 15] \n\ + roll %esi # \n\ + ##movl %esi, 4*"n"(%esp) # store to W[n & 15] elided \n\ + movl "c", %edi # c \n\ + xorl "d", %edi # ^d \n\ + xorl "b", %edi # ^b \n\ + leal "RCONST"("e",%esi), "e" # e += RCONST + mixed_W \n\ + addl %edi, "e" # e += (c ^ d ^ b) \n\ + movl "a", %esi # \n\ + roll $5, %esi # rotl32(a,5) \n\ + addl %esi, "e" # e += rotl32(a,5) \n\ + rorl $2, "b" # b = rotl32(b,30) \n\ +" +#define RD4A(a,b,c,d,e, n) RD4As("%e"STR(a),"%e"STR(b),"%e"STR(c),"%e"STR(d),"%e"STR(e), STR(((60+n+13)&15)), STR(((60+n+8)&15)), STR(((60+n+2)&15)), STR(((60+n)&15)), STR(RCONST)) +#define RD4B(a,b,c,d,e, n) RD4Bs("%e"STR(a),"%e"STR(b),"%e"STR(c),"%e"STR(d),"%e"STR(e), STR(((60+n+13)&15)), STR(((60+n+8)&15)), STR(((60+n+2)&15)), STR(((60+n)&15)), STR(RCONST)) +#undef RCONST +#define RCONST 0xCA62C1D6 + RD4A(ax,bx,cx,dx,bp, 0) RD4A(bp,ax,bx,cx,dx, 1) RD4A(dx,bp,ax,bx,cx, 2) RD4A(cx,dx,bp,ax,bx, 3) RD4A(bx,cx,dx,bp,ax, 4) + RD4A(ax,bx,cx,dx,bp, 5) RD4A(bp,ax,bx,cx,dx, 6) RD4A(dx,bp,ax,bx,cx, 7) RD4A(cx,dx,bp,ax,bx, 8) RD4A(bx,cx,dx,bp,ax, 9) + RD4A(ax,bx,cx,dx,bp,10) RD4A(bp,ax,bx,cx,dx,11) RD4A(dx,bp,ax,bx,cx,12) RD4A(cx,dx,bp,ax,bx,13) RD4A(bx,cx,dx,bp,ax,14) + RD4A(ax,bx,cx,dx,bp,15) RD4A(bp,ax,bx,cx,dx,16) RD4B(dx,bp,ax,bx,cx,17) RD4B(cx,dx,bp,ax,bx,18) RD4B(bx,cx,dx,bp,ax,19) + +"\n\ + movl 4*16(%esp), %esi # \n\ + addl $4*(16+1), %esp # \n\ + addl %eax, 76(%esi) # ctx->hash[0] += a \n\ + addl %ebx, 80(%esi) # ctx->hash[1] += b \n\ + addl %ecx, 84(%esi) # ctx->hash[2] += c \n\ + addl %edx, 88(%esi) # ctx->hash[3] += d \n\ + addl %ebp, 92(%esi) # ctx->hash[4] += e \n\ + popl %ebx # \n\ + popl %esi # \n\ + popl %edi # \n\ + popl %ebp # \n\ +" + ); /* asm */ +#undef RCONST +} +# elif defined(__GNUC__) && defined(__x86_64__) + +/* in hash_md5_sha_x86-64.S */ +struct ASM_expects_80 { char t[1 - 2*(offsetof(sha1_ctx_t, hash) != 80)]; }; +void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx); + +# else +/* Fast, fully-unrolled SHA1. +3800 bytes of code on x86. + * It seems further speedup can be achieved by handling more than + * 64 bytes per one function call (coreutils does that). + */ +static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) +{ + static const uint32_t rconsts[] ALIGN4 = { + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 + }; + uint32_t W[16]; + uint32_t a, b, c, d, e; + + a = ctx->hash[0]; + b = ctx->hash[1]; + c = ctx->hash[2]; + d = ctx->hash[3]; + e = ctx->hash[4]; + +/* From kernel source comments: + * """ + * If you have 32 registers or more, the compiler can (and should) + * try to change the array[] accesses into registers. However, on + * machines with less than ~25 registers, that won't really work, + * and at least gcc will make an unholy mess of it. + * + * So to avoid that mess which just slows things down, we force + * the stores to memory to actually happen (we might be better off + * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as + * suggested by Artur Skawina - that will also make gcc unable to + * try to do the silly "optimize away loads" part because it won't + * see what the value will be). + * """ + */ +#if defined(__GNUC__) && defined(__i386__) +# define DO_NOT_TRY_PROPAGATING(m) asm("":"+m"(m)) +#else +# define DO_NOT_TRY_PROPAGATING(m) ((void)0) +#endif + +#undef OP +#define OP(A,B,C,D,E, n) \ + do { \ + uint32_t work = EXPR(B, C, D); \ + if (n <= 15) \ + work += W[n & 15] = SWAP_BE32(((uint32_t*)ctx->wbuffer)[n]); \ + if (n >= 16) \ + work += W[n & 15] = rotl32(W[(n+13) & 15] ^ W[(n+8) & 15] ^ W[(n+2) & 15] ^ W[n & 15], 1); \ + DO_NOT_TRY_PROPAGATING(W[n & 15]); \ + E += work + rotl32(A, 5) + rconsts[n / 20]; \ + B = rotl32(B, 30); \ + } while (0) +#define OP20(n) \ + OP(a,b,c,d,e, (n+ 0)); OP(e,a,b,c,d, (n+ 1)); OP(d,e,a,b,c, (n+ 2)); OP(c,d,e,a,b, (n+ 3)); OP(b,c,d,e,a, (n+ 4)); \ + OP(a,b,c,d,e, (n+ 5)); OP(e,a,b,c,d, (n+ 6)); OP(d,e,a,b,c, (n+ 7)); OP(c,d,e,a,b, (n+ 8)); OP(b,c,d,e,a, (n+ 9)); \ + OP(a,b,c,d,e, (n+10)); OP(e,a,b,c,d, (n+11)); OP(d,e,a,b,c, (n+12)); OP(c,d,e,a,b, (n+13)); OP(b,c,d,e,a, (n+14)); \ + OP(a,b,c,d,e, (n+15)); OP(e,a,b,c,d, (n+16)); OP(d,e,a,b,c, (n+17)); OP(c,d,e,a,b, (n+18)); OP(b,c,d,e,a, (n+19)) + + /* 4 rounds of 20 operations each */ +#define EXPR(b,c,d) (((c ^ d) & b) ^ d) + OP20(0); +#undef EXPR +#define EXPR(b,c,d) (c ^ d ^ b) + OP20(20); +#undef EXPR +#define EXPR(b,c,d) (((b | c) & d) | (b & c)) + OP20(40); +#undef EXPR +#define EXPR(b,c,d) (c ^ d ^ b) + OP20(60); + +#undef EXPR +#undef OP +#undef OP20 + + ctx->hash[0] += a; + ctx->hash[1] += b; + ctx->hash[2] += c; + ctx->hash[3] += d; + ctx->hash[4] += e; +} +# endif +#elif CONFIG_SHA1_SMALL == 1 +/* Middle-sized version, +300 bytes of code on x86. */ +static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) +{ + static const uint32_t rconsts[] ALIGN4 = { + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 + }; + int j; + int n; + uint32_t W[16+16]; + uint32_t a, b, c, d, e; + + a = ctx->hash[0]; + b = ctx->hash[1]; + c = ctx->hash[2]; + d = ctx->hash[3]; + e = ctx->hash[4]; + + /* 1st round of 20 operations */ + n = 0; + do { + uint32_t work = ((c ^ d) & b) ^ d; + W[n] = W[n+16] = SWAP_BE32(((uint32_t*)ctx->wbuffer)[n]); + work += W[n]; + work += e + rotl32(a, 5) + rconsts[0]; + /* Rotate by one for next time */ + e = d; + d = c; + c = rotl32(b, 30); + b = a; + a = work; + n = (n + 1) & 15; + } while (n != 0); + do { + uint32_t work = ((c ^ d) & b) ^ d; + W[n] = W[n+16] = rotl32(W[n+13] ^ W[n+8] ^ W[n+2] ^ W[n], 1); + work += W[n]; + work += e + rotl32(a, 5) + rconsts[0]; + e = d; + d = c; + c = rotl32(b, 30); + b = a; + a = work; + n = (n + 1) /* & 15*/; + } while (n != 4); + /* 2nd round of 20 operations */ + j = 19; + do { + uint32_t work = c ^ d ^ b; + W[n] = W[n+16] = rotl32(W[n+13] ^ W[n+8] ^ W[n+2] ^ W[n], 1); + work += W[n]; + work += e + rotl32(a, 5) + rconsts[1]; + e = d; + d = c; + c = rotl32(b, 30); + b = a; + a = work; + n = (n + 1) & 15; + } while (--j >= 0); + /* 3rd round */ + j = 19; + do { + uint32_t work = ((b | c) & d) | (b & c); + W[n] = W[n+16] = rotl32(W[n+13] ^ W[n+8] ^ W[n+2] ^ W[n], 1); + work += W[n]; + work += e + rotl32(a, 5) + rconsts[2]; + e = d; + d = c; + c = rotl32(b, 30); + b = a; + a = work; + n = (n + 1) & 15; + } while (--j >= 0); + /* 4th round */ + j = 19; + do { + uint32_t work = c ^ d ^ b; + W[n] = W[n+16] = rotl32(W[n+13] ^ W[n+8] ^ W[n+2] ^ W[n], 1); + work += W[n]; + work += e + rotl32(a, 5) + rconsts[3]; + e = d; + d = c; + c = rotl32(b, 30); + b = a; + a = work; + n = (n + 1) & 15; + } while (--j >= 0); + + ctx->hash[0] += a; + ctx->hash[1] += b; + ctx->hash[2] += c; + ctx->hash[3] += d; + ctx->hash[4] += e; +} +#else +/* Compact version, almost twice as slow as fully unrolled */ static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) { static const uint32_t rconsts[] ALIGN4 = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; int i, j; - int cnt; + int n; uint32_t W[16+16]; uint32_t a, b, c, d, e; /* On-stack work buffer frees up one register in the main loop - * which otherwise will be needed to hold ctx pointer */ + * which otherwise will be needed to hold ctx pointer. + * + * The compiler is not smart enough to realize it, though. :( + * If __attribute__((optimize("2"))) is added to the function, + * only then gcc-9.3.1 spills "ctx" to stack and uses the freed + * register (making code 6 bytes smaller, not just faster). + */ for (i = 0; i < 16; i++) W[i] = W[i+16] = SWAP_BE32(((uint32_t*)ctx->wbuffer)[i]); @@ -512,7 +928,7 @@ e = ctx->hash[4]; /* 4 rounds of 20 operations each */ - cnt = 0; + n = 0; for (i = 0; i < 4; i++) { j = 19; do { @@ -523,27 +939,24 @@ work = (work & b) ^ d; if (j <= 3) goto ge16; - /* Used to do SWAP_BE32 here, but this - * requires ctx (see comment above) */ - work += W[cnt]; } else { if (i == 2) work = ((b | c) & d) | (b & c); else /* i = 1 or 3 */ work ^= b; ge16: - W[cnt] = W[cnt+16] = rotl32(W[cnt+13] ^ W[cnt+8] ^ W[cnt+2] ^ W[cnt], 1); - work += W[cnt]; + W[n] = W[n+16] = rotl32(W[n+13] ^ W[n+8] ^ W[n+2] ^ W[n], 1); } + work += W[n]; work += e + rotl32(a, 5) + rconsts[i]; /* Rotate by one for next time */ e = d; d = c; - c = /* b = */ rotl32(b, 30); + c = rotl32(b, 30); b = a; a = work; - cnt = (cnt + 1) & 15; + n = (n + 1) & 15; } while (--j >= 0); } @@ -553,6 +966,7 @@ ctx->hash[3] += d; ctx->hash[4] += e; } +#endif /* Constants for SHA512 from FIPS 180-2:4.2.3. * SHA256 constants from FIPS 180-2:4.2.2 @@ -758,6 +1172,19 @@ ctx->hash[4] = 0xc3d2e1f0; ctx->total64 = 0; ctx->process_block = sha1_process_block64; +#if ENABLE_SHA1_HWACCEL +# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + { + if (!shaNI) { + unsigned eax = 7, ebx = ebx, ecx = 0, edx = edx; + cpuid(&eax, &ebx, &ecx, &edx); + shaNI = ((ebx >> 28) & 2) - 1; /* bit 29 -> 1 or -1 */ + } + if (shaNI > 0) + ctx->process_block = sha1_process_block64_shaNI; + } +# endif +#endif } static const uint32_t init256[] ALIGN4 = { @@ -799,6 +1226,19 @@ memcpy(&ctx->total64, init256, sizeof(init256)); /*ctx->total64 = 0; - done by prepending two 32-bit zeros to init256 */ ctx->process_block = sha256_process_block64; +#if ENABLE_SHA256_HWACCEL +# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + { + if (!shaNI) { + unsigned eax = 7, ebx = ebx, ecx = 0, edx = edx; + cpuid(&eax, &ebx, &ecx, &edx); + shaNI = ((ebx >> 28) & 2) - 1; /* bit 29 -> 1 or -1 */ + } + if (shaNI > 0) + ctx->process_block = sha256_process_block64_shaNI; + } +# endif +#endif } #if NEED_SHA512 diff -Nru busybox-1.35.0/libbb/hash_md5_sha_x86-32_shaNI.S busybox-1.36.1/libbb/hash_md5_sha_x86-32_shaNI.S --- busybox-1.35.0/libbb/hash_md5_sha_x86-32_shaNI.S 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/libbb/hash_md5_sha_x86-32_shaNI.S 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,234 @@ +#if ENABLE_SHA1_HWACCEL && defined(__GNUC__) && defined(__i386__) +/* The code is adapted from Linux kernel's source */ + +// We use shorter insns, even though they are for "wrong" +// data type (fp, not int). +// For Intel, there is no penalty for doing it at all +// (CPUs which do have such penalty do not support SHA insns). +// For AMD, the penalty is one extra cycle +// (allegedly: I failed to find measurable difference). + +//#define mova128 movdqa +#define mova128 movaps +//#define movu128 movdqu +#define movu128 movups +//#define xor128 pxor +#define xor128 xorps +//#define shuf128_32 pshufd +#define shuf128_32 shufps + +#define extr128_32 pextrd +//#define extr128_32 extractps # not shorter + +// pshufb is a SSSE3 insn. +// pinsrd, pextrd, extractps are SSE4.1 insns. +// We do not check SSSE3/SSE4.1 in cpuid, +// all SHA-capable CPUs support them as well. + +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif + .section .text.sha1_process_block64_shaNI, "ax", @progbits + .globl sha1_process_block64_shaNI + .hidden sha1_process_block64_shaNI + .type sha1_process_block64_shaNI, @function + +#define ABCD %xmm0 +#define E0 %xmm1 /* Need two E's b/c they ping pong */ +#define E1 %xmm2 +#define MSG0 %xmm3 +#define MSG1 %xmm4 +#define MSG2 %xmm5 +#define MSG3 %xmm6 + + .balign 8 # allow decoders to fetch at least 2 first insns +sha1_process_block64_shaNI: + /* load initial hash values */ + movu128 76(%eax), ABCD + xor128 E0, E0 + pinsrd $3, 76+4*4(%eax), E0 # load to uppermost 32-bit word + shuf128_32 $0x1B, ABCD, ABCD # DCBA -> ABCD + + mova128 PSHUFFLE_BYTE_FLIP_MASK, %xmm7 + + movu128 0*16(%eax), MSG0 + pshufb %xmm7, MSG0 + movu128 1*16(%eax), MSG1 + pshufb %xmm7, MSG1 + movu128 2*16(%eax), MSG2 + pshufb %xmm7, MSG2 + movu128 3*16(%eax), MSG3 + pshufb %xmm7, MSG3 + + /* Save hash values for addition after rounds */ + mova128 E0, %xmm7 + /*mova128 ABCD, %xmm8 - NOPE, 32bit has no xmm8 */ + + /* Rounds 0-3 */ + paddd MSG0, E0 + mova128 ABCD, E1 + sha1rnds4 $0, E0, ABCD + + /* Rounds 4-7 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1rnds4 $0, E1, ABCD + sha1msg1 MSG1, MSG0 + + /* Rounds 8-11 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1rnds4 $0, E0, ABCD + sha1msg1 MSG2, MSG1 + xor128 MSG2, MSG0 + + /* Rounds 12-15 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1msg2 MSG3, MSG0 + sha1rnds4 $0, E1, ABCD + sha1msg1 MSG3, MSG2 + xor128 MSG3, MSG1 + + /* Rounds 16-19 */ + sha1nexte MSG0, E0 + mova128 ABCD, E1 + sha1msg2 MSG0, MSG1 + sha1rnds4 $0, E0, ABCD + sha1msg1 MSG0, MSG3 + xor128 MSG0, MSG2 + + /* Rounds 20-23 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1msg2 MSG1, MSG2 + sha1rnds4 $1, E1, ABCD + sha1msg1 MSG1, MSG0 + xor128 MSG1, MSG3 + + /* Rounds 24-27 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1msg2 MSG2, MSG3 + sha1rnds4 $1, E0, ABCD + sha1msg1 MSG2, MSG1 + xor128 MSG2, MSG0 + + /* Rounds 28-31 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1msg2 MSG3, MSG0 + sha1rnds4 $1, E1, ABCD + sha1msg1 MSG3, MSG2 + xor128 MSG3, MSG1 + + /* Rounds 32-35 */ + sha1nexte MSG0, E0 + mova128 ABCD, E1 + sha1msg2 MSG0, MSG1 + sha1rnds4 $1, E0, ABCD + sha1msg1 MSG0, MSG3 + xor128 MSG0, MSG2 + + /* Rounds 36-39 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1msg2 MSG1, MSG2 + sha1rnds4 $1, E1, ABCD + sha1msg1 MSG1, MSG0 + xor128 MSG1, MSG3 + + /* Rounds 40-43 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1msg2 MSG2, MSG3 + sha1rnds4 $2, E0, ABCD + sha1msg1 MSG2, MSG1 + xor128 MSG2, MSG0 + + /* Rounds 44-47 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1msg2 MSG3, MSG0 + sha1rnds4 $2, E1, ABCD + sha1msg1 MSG3, MSG2 + xor128 MSG3, MSG1 + + /* Rounds 48-51 */ + sha1nexte MSG0, E0 + mova128 ABCD, E1 + sha1msg2 MSG0, MSG1 + sha1rnds4 $2, E0, ABCD + sha1msg1 MSG0, MSG3 + xor128 MSG0, MSG2 + + /* Rounds 52-55 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1msg2 MSG1, MSG2 + sha1rnds4 $2, E1, ABCD + sha1msg1 MSG1, MSG0 + xor128 MSG1, MSG3 + + /* Rounds 56-59 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1msg2 MSG2, MSG3 + sha1rnds4 $2, E0, ABCD + sha1msg1 MSG2, MSG1 + xor128 MSG2, MSG0 + + /* Rounds 60-63 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1msg2 MSG3, MSG0 + sha1rnds4 $3, E1, ABCD + sha1msg1 MSG3, MSG2 + xor128 MSG3, MSG1 + + /* Rounds 64-67 */ + sha1nexte MSG0, E0 + mova128 ABCD, E1 + sha1msg2 MSG0, MSG1 + sha1rnds4 $3, E0, ABCD + sha1msg1 MSG0, MSG3 + xor128 MSG0, MSG2 + + /* Rounds 68-71 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1msg2 MSG1, MSG2 + sha1rnds4 $3, E1, ABCD + xor128 MSG1, MSG3 + + /* Rounds 72-75 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1msg2 MSG2, MSG3 + sha1rnds4 $3, E0, ABCD + + /* Rounds 76-79 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1rnds4 $3, E1, ABCD + + /* Add current hash values with previously saved */ + sha1nexte %xmm7, E0 + /*paddd %xmm8, ABCD - 32-bit mode has no xmm8 */ + movu128 76(%eax), %xmm7 # get original ABCD (not shuffled)... + + /* Write hash values back in the correct order */ + shuf128_32 $0x1B, ABCD, ABCD + paddd %xmm7, ABCD # ...add it to final ABCD + movu128 ABCD, 76(%eax) + extr128_32 $3, E0, 76+4*4(%eax) + + ret + .size sha1_process_block64_shaNI, .-sha1_process_block64_shaNI + + .section .rodata.cst16.PSHUFFLE_BYTE_FLIP_MASK, "aM", @progbits, 16 + .balign 16 +PSHUFFLE_BYTE_FLIP_MASK: + .octa 0x000102030405060708090a0b0c0d0e0f + +#endif diff -Nru busybox-1.35.0/libbb/hash_md5_sha_x86-64.S busybox-1.36.1/libbb/hash_md5_sha_x86-64.S --- busybox-1.35.0/libbb/hash_md5_sha_x86-64.S 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/libbb/hash_md5_sha_x86-64.S 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,1489 @@ +### Generated by hash_md5_sha_x86-64.S.sh ### + +#if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif + .section .text.sha1_process_block64, "ax", @progbits + .globl sha1_process_block64 + .hidden sha1_process_block64 + .type sha1_process_block64, @function + + .balign 8 # allow decoders to fetch at least 5 first insns +sha1_process_block64: + pushq %rbp # 1 byte insn + pushq %rbx # 1 byte insn +# pushq %r15 # 2 byte insn + pushq %r14 # 2 byte insn + pushq %r13 # 2 byte insn + pushq %r12 # 2 byte insn + pushq %rdi # we need ctx at the end + +#Register and stack use: +# eax..edx: a..d +# ebp: e +# esi,edi,r8..r14: temps +# r15: unused +# xmm0..xmm3: W[] +# xmm4,xmm5: temps +# xmm6: current round constant +# xmm7: all round constants +# -64(%rsp): area for passing RCONST + W[] from vector to integer units + + movl 80(%rdi), %eax # a = ctx->hash[0] + movl 84(%rdi), %ebx # b = ctx->hash[1] + movl 88(%rdi), %ecx # c = ctx->hash[2] + movl 92(%rdi), %edx # d = ctx->hash[3] + movl 96(%rdi), %ebp # e = ctx->hash[4] + + movaps sha1const(%rip), %xmm7 + pshufd $0x00, %xmm7, %xmm6 + + # Load W[] to xmm0..3, byteswapping on the fly. + # + # For iterations 0..15, we pass W[] in rsi,r8..r14 + # for use in RD1As instead of spilling them to stack. + # We lose parallelized addition of RCONST, but LEA + # can do two additions at once, so it is probably a wash. + # (We use rsi instead of rN because this makes two + # LEAs in two first RD1As shorter by one byte). + movq 4*0(%rdi), %rsi + movq 4*2(%rdi), %r8 + bswapq %rsi + bswapq %r8 + rolq $32, %rsi # rsi = W[1]:W[0] + rolq $32, %r8 # r8 = W[3]:W[2] + movq %rsi, %xmm0 + movq %r8, %xmm4 + punpcklqdq %xmm4, %xmm0 # xmm0 = r8:rsi = (W[0],W[1],W[2],W[3]) +# movaps %xmm0, %xmm4 # add RCONST, spill to stack +# paddd %xmm6, %xmm4 +# movups %xmm4, -64+16*0(%rsp) + + movq 4*4(%rdi), %r9 + movq 4*6(%rdi), %r10 + bswapq %r9 + bswapq %r10 + rolq $32, %r9 # r9 = W[5]:W[4] + rolq $32, %r10 # r10 = W[7]:W[6] + movq %r9, %xmm1 + movq %r10, %xmm4 + punpcklqdq %xmm4, %xmm1 # xmm1 = r10:r9 = (W[4],W[5],W[6],W[7]) + + movq 4*8(%rdi), %r11 + movq 4*10(%rdi), %r12 + bswapq %r11 + bswapq %r12 + rolq $32, %r11 # r11 = W[9]:W[8] + rolq $32, %r12 # r12 = W[11]:W[10] + movq %r11, %xmm2 + movq %r12, %xmm4 + punpcklqdq %xmm4, %xmm2 # xmm2 = r12:r11 = (W[8],W[9],W[10],W[11]) + + movq 4*12(%rdi), %r13 + movq 4*14(%rdi), %r14 + bswapq %r13 + bswapq %r14 + rolq $32, %r13 # r13 = W[13]:W[12] + rolq $32, %r14 # r14 = W[15]:W[14] + movq %r13, %xmm3 + movq %r14, %xmm4 + punpcklqdq %xmm4, %xmm3 # xmm3 = r14:r13 = (W[12],W[13],W[14],W[15]) + +# 0 + leal 0x5A827999(%rbp,%rsi), %ebp # e += RCONST + W[n] + shrq $32, %rsi + movl %ecx, %edi # c + xorl %edx, %edi # ^d + andl %ebx, %edi # &b + xorl %edx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ebp # e += (((c ^ d) & b) ^ d) + movl %eax, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 1 + leal 0x5A827999(%rdx,%rsi), %edx # e += RCONST + W[n] + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + andl %eax, %edi # &b + xorl %ecx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %edx # e += (((c ^ d) & b) ^ d) + movl %ebp, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 2 + leal 0x5A827999(%rcx,%r8), %ecx # e += RCONST + W[n] + shrq $32, %r8 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + andl %ebp, %edi # &b + xorl %ebx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ecx # e += (((c ^ d) & b) ^ d) + movl %edx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 3 + leal 0x5A827999(%rbx,%r8), %ebx # e += RCONST + W[n] + movl %ebp, %edi # c + xorl %eax, %edi # ^d + andl %edx, %edi # &b + xorl %eax, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ebx # e += (((c ^ d) & b) ^ d) + movl %ecx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 4 + leal 0x5A827999(%rax,%r9), %eax # e += RCONST + W[n] + shrq $32, %r9 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + andl %ecx, %edi # &b + xorl %ebp, %edi # (((c ^ d) & b) ^ d) + addl %edi, %eax # e += (((c ^ d) & b) ^ d) + movl %ebx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 5 + leal 0x5A827999(%rbp,%r9), %ebp # e += RCONST + W[n] + movl %ecx, %edi # c + xorl %edx, %edi # ^d + andl %ebx, %edi # &b + xorl %edx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ebp # e += (((c ^ d) & b) ^ d) + movl %eax, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 6 + leal 0x5A827999(%rdx,%r10), %edx # e += RCONST + W[n] + shrq $32, %r10 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + andl %eax, %edi # &b + xorl %ecx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %edx # e += (((c ^ d) & b) ^ d) + movl %ebp, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 7 + leal 0x5A827999(%rcx,%r10), %ecx # e += RCONST + W[n] + movl %eax, %edi # c + xorl %ebx, %edi # ^d + andl %ebp, %edi # &b + xorl %ebx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ecx # e += (((c ^ d) & b) ^ d) + movl %edx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# PREP %xmm0 %xmm1 %xmm2 %xmm3 -64+16*0(%rsp) + movaps %xmm3, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm0, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm1, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm0, %xmm5 + shufps $0x4e, %xmm1, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm2, %xmm0 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm0 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm0, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm0, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm0, %xmm0 # shift left by 1 + psubd %xmm4, %xmm0 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm0 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm0 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm0, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*0(%rsp) +# 8 + leal 0x5A827999(%rbx,%r11), %ebx # e += RCONST + W[n] + shrq $32, %r11 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + andl %edx, %edi # &b + xorl %eax, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ebx # e += (((c ^ d) & b) ^ d) + movl %ecx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 9 + leal 0x5A827999(%rax,%r11), %eax # e += RCONST + W[n] + movl %edx, %edi # c + xorl %ebp, %edi # ^d + andl %ecx, %edi # &b + xorl %ebp, %edi # (((c ^ d) & b) ^ d) + addl %edi, %eax # e += (((c ^ d) & b) ^ d) + movl %ebx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 10 + leal 0x5A827999(%rbp,%r12), %ebp # e += RCONST + W[n] + shrq $32, %r12 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + andl %ebx, %edi # &b + xorl %edx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ebp # e += (((c ^ d) & b) ^ d) + movl %eax, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 11 + leal 0x5A827999(%rdx,%r12), %edx # e += RCONST + W[n] + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + andl %eax, %edi # &b + xorl %ecx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %edx # e += (((c ^ d) & b) ^ d) + movl %ebp, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) + pshufd $0x55, %xmm7, %xmm6 +# PREP %xmm1 %xmm2 %xmm3 %xmm0 -64+16*1(%rsp) + movaps %xmm0, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm1, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm2, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm1, %xmm5 + shufps $0x4e, %xmm2, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm3, %xmm1 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm1 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm1, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm1, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm1, %xmm1 # shift left by 1 + psubd %xmm4, %xmm1 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm1 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm1 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm1, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*1(%rsp) +# 12 + leal 0x5A827999(%rcx,%r13), %ecx # e += RCONST + W[n] + shrq $32, %r13 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + andl %ebp, %edi # &b + xorl %ebx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ecx # e += (((c ^ d) & b) ^ d) + movl %edx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 13 + leal 0x5A827999(%rbx,%r13), %ebx # e += RCONST + W[n] + movl %ebp, %edi # c + xorl %eax, %edi # ^d + andl %edx, %edi # &b + xorl %eax, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ebx # e += (((c ^ d) & b) ^ d) + movl %ecx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 14 + leal 0x5A827999(%rax,%r14), %eax # e += RCONST + W[n] + shrq $32, %r14 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + andl %ecx, %edi # &b + xorl %ebp, %edi # (((c ^ d) & b) ^ d) + addl %edi, %eax # e += (((c ^ d) & b) ^ d) + movl %ebx, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 15 + leal 0x5A827999(%rbp,%r14), %ebp # e += RCONST + W[n] + movl %ecx, %edi # c + xorl %edx, %edi # ^d + andl %ebx, %edi # &b + xorl %edx, %edi # (((c ^ d) & b) ^ d) + addl %edi, %ebp # e += (((c ^ d) & b) ^ d) + movl %eax, %edi # + roll $5, %edi # rotl32(a,5) + addl %edi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# PREP %xmm2 %xmm3 %xmm0 %xmm1 -64+16*2(%rsp) + movaps %xmm1, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm2, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm3, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm2, %xmm5 + shufps $0x4e, %xmm3, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm0, %xmm2 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm2 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm2, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm2, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm2, %xmm2 # shift left by 1 + psubd %xmm4, %xmm2 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm2 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm2 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm2, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*2(%rsp) +# 16 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + andl %eax, %edi # &b + xorl %ecx, %edi # (((c ^ d) & b) ^ d) + addl -64+4*0(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (((c ^ d) & b) ^ d) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 17 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + andl %ebp, %edi # &b + xorl %ebx, %edi # (((c ^ d) & b) ^ d) + addl -64+4*1(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (((c ^ d) & b) ^ d) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 18 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + andl %edx, %edi # &b + xorl %eax, %edi # (((c ^ d) & b) ^ d) + addl -64+4*2(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (((c ^ d) & b) ^ d) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 19 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + andl %ecx, %edi # &b + xorl %ebp, %edi # (((c ^ d) & b) ^ d) + addl -64+4*3(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (((c ^ d) & b) ^ d) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# PREP %xmm3 %xmm0 %xmm1 %xmm2 -64+16*3(%rsp) + movaps %xmm2, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm3, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm0, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm3, %xmm5 + shufps $0x4e, %xmm0, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm1, %xmm3 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm3 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm3, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm3, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm3, %xmm3 # shift left by 1 + psubd %xmm4, %xmm3 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm3 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm3 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm3, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*3(%rsp) +# 20 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + xorl %ebx, %edi # ^b + addl -64+4*4(%rsp), %ebp # e += RCONST + W[n & 15] + addl %edi, %ebp # e += (c ^ d ^ b) + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 21 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + xorl %eax, %edi # ^b + addl -64+4*5(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (c ^ d ^ b) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 22 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + xorl %ebp, %edi # ^b + addl -64+4*6(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (c ^ d ^ b) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 23 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + xorl %edx, %edi # ^b + addl -64+4*7(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (c ^ d ^ b) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# PREP %xmm0 %xmm1 %xmm2 %xmm3 -64+16*0(%rsp) + movaps %xmm3, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm0, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm1, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm0, %xmm5 + shufps $0x4e, %xmm1, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm2, %xmm0 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm0 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm0, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm0, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm0, %xmm0 # shift left by 1 + psubd %xmm4, %xmm0 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm0 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm0 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm0, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*0(%rsp) +# 24 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + xorl %ecx, %edi # ^b + addl -64+4*8(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (c ^ d ^ b) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 25 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + xorl %ebx, %edi # ^b + addl -64+4*9(%rsp), %ebp # e += RCONST + W[n & 15] + addl %edi, %ebp # e += (c ^ d ^ b) + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 26 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + xorl %eax, %edi # ^b + addl -64+4*10(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (c ^ d ^ b) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 27 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + xorl %ebp, %edi # ^b + addl -64+4*11(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (c ^ d ^ b) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# PREP %xmm1 %xmm2 %xmm3 %xmm0 -64+16*1(%rsp) + movaps %xmm0, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm1, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm2, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm1, %xmm5 + shufps $0x4e, %xmm2, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm3, %xmm1 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm1 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm1, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm1, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm1, %xmm1 # shift left by 1 + psubd %xmm4, %xmm1 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm1 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm1 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm1, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*1(%rsp) +# 28 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + xorl %edx, %edi # ^b + addl -64+4*12(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (c ^ d ^ b) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 29 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + xorl %ecx, %edi # ^b + addl -64+4*13(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (c ^ d ^ b) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 30 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + xorl %ebx, %edi # ^b + addl -64+4*14(%rsp), %ebp # e += RCONST + W[n & 15] + addl %edi, %ebp # e += (c ^ d ^ b) + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 31 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + xorl %eax, %edi # ^b + addl -64+4*15(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (c ^ d ^ b) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) + pshufd $0xaa, %xmm7, %xmm6 +# PREP %xmm2 %xmm3 %xmm0 %xmm1 -64+16*2(%rsp) + movaps %xmm1, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm2, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm3, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm2, %xmm5 + shufps $0x4e, %xmm3, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm0, %xmm2 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm2 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm2, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm2, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm2, %xmm2 # shift left by 1 + psubd %xmm4, %xmm2 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm2 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm2 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm2, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*2(%rsp) +# 32 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + xorl %ebp, %edi # ^b + addl -64+4*0(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (c ^ d ^ b) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 33 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + xorl %edx, %edi # ^b + addl -64+4*1(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (c ^ d ^ b) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 34 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + xorl %ecx, %edi # ^b + addl -64+4*2(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (c ^ d ^ b) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 35 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + xorl %ebx, %edi # ^b + addl -64+4*3(%rsp), %ebp # e += RCONST + W[n & 15] + addl %edi, %ebp # e += (c ^ d ^ b) + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# PREP %xmm3 %xmm0 %xmm1 %xmm2 -64+16*3(%rsp) + movaps %xmm2, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm3, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm0, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm3, %xmm5 + shufps $0x4e, %xmm0, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm1, %xmm3 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm3 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm3, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm3, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm3, %xmm3 # shift left by 1 + psubd %xmm4, %xmm3 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm3 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm3 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm3, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*3(%rsp) +# 36 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + xorl %eax, %edi # ^b + addl -64+4*4(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (c ^ d ^ b) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 37 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + xorl %ebp, %edi # ^b + addl -64+4*5(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (c ^ d ^ b) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 38 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + xorl %edx, %edi # ^b + addl -64+4*6(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (c ^ d ^ b) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 39 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + xorl %ecx, %edi # ^b + addl -64+4*7(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (c ^ d ^ b) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# PREP %xmm0 %xmm1 %xmm2 %xmm3 -64+16*0(%rsp) + movaps %xmm3, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm0, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm1, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm0, %xmm5 + shufps $0x4e, %xmm1, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm2, %xmm0 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm0 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm0, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm0, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm0, %xmm0 # shift left by 1 + psubd %xmm4, %xmm0 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm0 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm0 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm0, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*0(%rsp) +# 40 + movl %ebx, %edi # di: b + movl %ebx, %esi # si: b + orl %ecx, %edi # di: b | c + andl %ecx, %esi # si: b & c + andl %edx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ebp # += ((b | c) & d) | (b & c) + addl -64+4*8(%rsp), %ebp # e += RCONST + W[n & 15] + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 41 + movl %eax, %edi # di: b + movl %eax, %esi # si: b + orl %ebx, %edi # di: b | c + andl %ebx, %esi # si: b & c + andl %ecx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %edx # += ((b | c) & d) | (b & c) + addl -64+4*9(%rsp), %edx # e += RCONST + W[n & 15] + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 42 + movl %ebp, %edi # di: b + movl %ebp, %esi # si: b + orl %eax, %edi # di: b | c + andl %eax, %esi # si: b & c + andl %ebx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ecx # += ((b | c) & d) | (b & c) + addl -64+4*10(%rsp), %ecx # e += RCONST + W[n & 15] + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 43 + movl %edx, %edi # di: b + movl %edx, %esi # si: b + orl %ebp, %edi # di: b | c + andl %ebp, %esi # si: b & c + andl %eax, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ebx # += ((b | c) & d) | (b & c) + addl -64+4*11(%rsp), %ebx # e += RCONST + W[n & 15] + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# PREP %xmm1 %xmm2 %xmm3 %xmm0 -64+16*1(%rsp) + movaps %xmm0, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm1, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm2, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm1, %xmm5 + shufps $0x4e, %xmm2, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm3, %xmm1 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm1 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm1, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm1, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm1, %xmm1 # shift left by 1 + psubd %xmm4, %xmm1 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm1 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm1 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm1, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*1(%rsp) +# 44 + movl %ecx, %edi # di: b + movl %ecx, %esi # si: b + orl %edx, %edi # di: b | c + andl %edx, %esi # si: b & c + andl %ebp, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %eax # += ((b | c) & d) | (b & c) + addl -64+4*12(%rsp), %eax # e += RCONST + W[n & 15] + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 45 + movl %ebx, %edi # di: b + movl %ebx, %esi # si: b + orl %ecx, %edi # di: b | c + andl %ecx, %esi # si: b & c + andl %edx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ebp # += ((b | c) & d) | (b & c) + addl -64+4*13(%rsp), %ebp # e += RCONST + W[n & 15] + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 46 + movl %eax, %edi # di: b + movl %eax, %esi # si: b + orl %ebx, %edi # di: b | c + andl %ebx, %esi # si: b & c + andl %ecx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %edx # += ((b | c) & d) | (b & c) + addl -64+4*14(%rsp), %edx # e += RCONST + W[n & 15] + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 47 + movl %ebp, %edi # di: b + movl %ebp, %esi # si: b + orl %eax, %edi # di: b | c + andl %eax, %esi # si: b & c + andl %ebx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ecx # += ((b | c) & d) | (b & c) + addl -64+4*15(%rsp), %ecx # e += RCONST + W[n & 15] + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# PREP %xmm2 %xmm3 %xmm0 %xmm1 -64+16*2(%rsp) + movaps %xmm1, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm2, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm3, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm2, %xmm5 + shufps $0x4e, %xmm3, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm0, %xmm2 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm2 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm2, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm2, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm2, %xmm2 # shift left by 1 + psubd %xmm4, %xmm2 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm2 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm2 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm2, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*2(%rsp) +# 48 + movl %edx, %edi # di: b + movl %edx, %esi # si: b + orl %ebp, %edi # di: b | c + andl %ebp, %esi # si: b & c + andl %eax, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ebx # += ((b | c) & d) | (b & c) + addl -64+4*0(%rsp), %ebx # e += RCONST + W[n & 15] + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 49 + movl %ecx, %edi # di: b + movl %ecx, %esi # si: b + orl %edx, %edi # di: b | c + andl %edx, %esi # si: b & c + andl %ebp, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %eax # += ((b | c) & d) | (b & c) + addl -64+4*1(%rsp), %eax # e += RCONST + W[n & 15] + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 50 + movl %ebx, %edi # di: b + movl %ebx, %esi # si: b + orl %ecx, %edi # di: b | c + andl %ecx, %esi # si: b & c + andl %edx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ebp # += ((b | c) & d) | (b & c) + addl -64+4*2(%rsp), %ebp # e += RCONST + W[n & 15] + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 51 + movl %eax, %edi # di: b + movl %eax, %esi # si: b + orl %ebx, %edi # di: b | c + andl %ebx, %esi # si: b & c + andl %ecx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %edx # += ((b | c) & d) | (b & c) + addl -64+4*3(%rsp), %edx # e += RCONST + W[n & 15] + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) + pshufd $0xff, %xmm7, %xmm6 +# PREP %xmm3 %xmm0 %xmm1 %xmm2 -64+16*3(%rsp) + movaps %xmm2, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm3, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm0, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm3, %xmm5 + shufps $0x4e, %xmm0, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm1, %xmm3 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm3 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm3, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm3, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm3, %xmm3 # shift left by 1 + psubd %xmm4, %xmm3 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm3 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm3 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm3, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*3(%rsp) +# 52 + movl %ebp, %edi # di: b + movl %ebp, %esi # si: b + orl %eax, %edi # di: b | c + andl %eax, %esi # si: b & c + andl %ebx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ecx # += ((b | c) & d) | (b & c) + addl -64+4*4(%rsp), %ecx # e += RCONST + W[n & 15] + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 53 + movl %edx, %edi # di: b + movl %edx, %esi # si: b + orl %ebp, %edi # di: b | c + andl %ebp, %esi # si: b & c + andl %eax, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ebx # += ((b | c) & d) | (b & c) + addl -64+4*5(%rsp), %ebx # e += RCONST + W[n & 15] + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 54 + movl %ecx, %edi # di: b + movl %ecx, %esi # si: b + orl %edx, %edi # di: b | c + andl %edx, %esi # si: b & c + andl %ebp, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %eax # += ((b | c) & d) | (b & c) + addl -64+4*6(%rsp), %eax # e += RCONST + W[n & 15] + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 55 + movl %ebx, %edi # di: b + movl %ebx, %esi # si: b + orl %ecx, %edi # di: b | c + andl %ecx, %esi # si: b & c + andl %edx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ebp # += ((b | c) & d) | (b & c) + addl -64+4*7(%rsp), %ebp # e += RCONST + W[n & 15] + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# PREP %xmm0 %xmm1 %xmm2 %xmm3 -64+16*0(%rsp) + movaps %xmm3, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm0, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm1, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm0, %xmm5 + shufps $0x4e, %xmm1, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm2, %xmm0 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm0 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm0, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm0, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm0, %xmm0 # shift left by 1 + psubd %xmm4, %xmm0 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm0 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm0 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm0, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*0(%rsp) +# 56 + movl %eax, %edi # di: b + movl %eax, %esi # si: b + orl %ebx, %edi # di: b | c + andl %ebx, %esi # si: b & c + andl %ecx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %edx # += ((b | c) & d) | (b & c) + addl -64+4*8(%rsp), %edx # e += RCONST + W[n & 15] + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 57 + movl %ebp, %edi # di: b + movl %ebp, %esi # si: b + orl %eax, %edi # di: b | c + andl %eax, %esi # si: b & c + andl %ebx, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ecx # += ((b | c) & d) | (b & c) + addl -64+4*9(%rsp), %ecx # e += RCONST + W[n & 15] + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 58 + movl %edx, %edi # di: b + movl %edx, %esi # si: b + orl %ebp, %edi # di: b | c + andl %ebp, %esi # si: b & c + andl %eax, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %ebx # += ((b | c) & d) | (b & c) + addl -64+4*10(%rsp), %ebx # e += RCONST + W[n & 15] + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 59 + movl %ecx, %edi # di: b + movl %ecx, %esi # si: b + orl %edx, %edi # di: b | c + andl %edx, %esi # si: b & c + andl %ebp, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %eax # += ((b | c) & d) | (b & c) + addl -64+4*11(%rsp), %eax # e += RCONST + W[n & 15] + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# PREP %xmm1 %xmm2 %xmm3 %xmm0 -64+16*1(%rsp) + movaps %xmm0, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm1, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm2, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm1, %xmm5 + shufps $0x4e, %xmm2, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm3, %xmm1 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm1 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm1, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm1, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm1, %xmm1 # shift left by 1 + psubd %xmm4, %xmm1 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm1 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm1 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm1, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*1(%rsp) +# 60 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + xorl %ebx, %edi # ^b + addl -64+4*12(%rsp), %ebp # e += RCONST + W[n & 15] + addl %edi, %ebp # e += (c ^ d ^ b) + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 61 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + xorl %eax, %edi # ^b + addl -64+4*13(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (c ^ d ^ b) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 62 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + xorl %ebp, %edi # ^b + addl -64+4*14(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (c ^ d ^ b) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 63 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + xorl %edx, %edi # ^b + addl -64+4*15(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (c ^ d ^ b) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# PREP %xmm2 %xmm3 %xmm0 %xmm1 -64+16*2(%rsp) + movaps %xmm1, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm2, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm3, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm2, %xmm5 + shufps $0x4e, %xmm3, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm0, %xmm2 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm2 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm2, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm2, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm2, %xmm2 # shift left by 1 + psubd %xmm4, %xmm2 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm2 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm2 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm2, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*2(%rsp) +# 64 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + xorl %ecx, %edi # ^b + addl -64+4*0(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (c ^ d ^ b) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 65 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + xorl %ebx, %edi # ^b + addl -64+4*1(%rsp), %ebp # e += RCONST + W[n & 15] + addl %edi, %ebp # e += (c ^ d ^ b) + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 66 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + xorl %eax, %edi # ^b + addl -64+4*2(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (c ^ d ^ b) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 67 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + xorl %ebp, %edi # ^b + addl -64+4*3(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (c ^ d ^ b) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# PREP %xmm3 %xmm0 %xmm1 %xmm2 -64+16*3(%rsp) + movaps %xmm2, %xmm4 + psrldq $4, %xmm4 # rshift by 4 bytes: T1 = ([13],[14],[15],0) +# pshufd $0x4e, %xmm3, %xmm5 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq %xmm0, %xmm5 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps %xmm3, %xmm5 + shufps $0x4e, %xmm0, %xmm5 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + xorps %xmm1, %xmm3 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps %xmm4, %xmm5 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps %xmm5, %xmm3 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps %xmm3, %xmm5 + xorps %xmm4, %xmm4 # rol(W0,1): + pcmpgtd %xmm3, %xmm4 # ffffffff for elements <0 (ones with msb bit 1) + paddd %xmm3, %xmm3 # shift left by 1 + psubd %xmm4, %xmm3 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + pslldq $12, %xmm5 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps %xmm5, %xmm4 + pslld $2, %xmm5 + psrld $30, %xmm4 +# xorps %xmm4, %xmm5 # rol((0,0,0,unrotW[0]),2) + xorps %xmm4, %xmm3 # same result, but does not depend on/does not modify T2 + xorps %xmm5, %xmm3 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) + movaps %xmm3, %xmm5 + paddd %xmm6, %xmm5 + movups %xmm5, -64+16*3(%rsp) +# 68 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + xorl %edx, %edi # ^b + addl -64+4*4(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (c ^ d ^ b) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 69 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + xorl %ecx, %edi # ^b + addl -64+4*5(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (c ^ d ^ b) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 70 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + xorl %ebx, %edi # ^b + addl -64+4*6(%rsp), %ebp # e += RCONST + W[n & 15] + addl %edi, %ebp # e += (c ^ d ^ b) + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 71 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + xorl %eax, %edi # ^b + addl -64+4*7(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (c ^ d ^ b) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 72 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + xorl %ebp, %edi # ^b + addl -64+4*8(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (c ^ d ^ b) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 73 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + xorl %edx, %edi # ^b + addl -64+4*9(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (c ^ d ^ b) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 74 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + xorl %ecx, %edi # ^b + addl -64+4*10(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (c ^ d ^ b) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) +# 75 + movl %ecx, %edi # c + xorl %edx, %edi # ^d + xorl %ebx, %edi # ^b + addl -64+4*11(%rsp), %ebp # e += RCONST + W[n & 15] + addl %edi, %ebp # e += (c ^ d ^ b) + movl %eax, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebp # e += rotl32(a,5) + rorl $2, %ebx # b = rotl32(b,30) +# 76 + movl %ebx, %edi # c + xorl %ecx, %edi # ^d + xorl %eax, %edi # ^b + addl -64+4*12(%rsp), %edx # e += RCONST + W[n & 15] + addl %edi, %edx # e += (c ^ d ^ b) + movl %ebp, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %edx # e += rotl32(a,5) + rorl $2, %eax # b = rotl32(b,30) +# 77 + movl %eax, %edi # c + xorl %ebx, %edi # ^d + xorl %ebp, %edi # ^b + addl -64+4*13(%rsp), %ecx # e += RCONST + W[n & 15] + addl %edi, %ecx # e += (c ^ d ^ b) + movl %edx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ecx # e += rotl32(a,5) + rorl $2, %ebp # b = rotl32(b,30) +# 78 + movl %ebp, %edi # c + xorl %eax, %edi # ^d + xorl %edx, %edi # ^b + addl -64+4*14(%rsp), %ebx # e += RCONST + W[n & 15] + addl %edi, %ebx # e += (c ^ d ^ b) + movl %ecx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %ebx # e += rotl32(a,5) + rorl $2, %edx # b = rotl32(b,30) +# 79 + movl %edx, %edi # c + xorl %ebp, %edi # ^d + xorl %ecx, %edi # ^b + addl -64+4*15(%rsp), %eax # e += RCONST + W[n & 15] + addl %edi, %eax # e += (c ^ d ^ b) + movl %ebx, %esi # + roll $5, %esi # rotl32(a,5) + addl %esi, %eax # e += rotl32(a,5) + rorl $2, %ecx # b = rotl32(b,30) + + popq %rdi # + popq %r12 # + addl %eax, 80(%rdi) # ctx->hash[0] += a + popq %r13 # + addl %ebx, 84(%rdi) # ctx->hash[1] += b + popq %r14 # + addl %ecx, 88(%rdi) # ctx->hash[2] += c +# popq %r15 # + addl %edx, 92(%rdi) # ctx->hash[3] += d + popq %rbx # + addl %ebp, 96(%rdi) # ctx->hash[4] += e + popq %rbp # + + ret + .size sha1_process_block64, .-sha1_process_block64 + + .section .rodata.cst16.sha1const, "aM", @progbits, 16 + .balign 16 +sha1const: + .long 0x5A827999 + .long 0x6ED9EBA1 + .long 0x8F1BBCDC + .long 0xCA62C1D6 + +#endif diff -Nru busybox-1.35.0/libbb/hash_md5_sha_x86-64_shaNI.S busybox-1.36.1/libbb/hash_md5_sha_x86-64_shaNI.S --- busybox-1.35.0/libbb/hash_md5_sha_x86-64_shaNI.S 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/libbb/hash_md5_sha_x86-64_shaNI.S 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,232 @@ +#if ENABLE_SHA1_HWACCEL && defined(__GNUC__) && defined(__x86_64__) +/* The code is adapted from Linux kernel's source */ + +// We use shorter insns, even though they are for "wrong" +// data type (fp, not int). +// For Intel, there is no penalty for doing it at all +// (CPUs which do have such penalty do not support SHA insns). +// For AMD, the penalty is one extra cycle +// (allegedly: I failed to find measurable difference). + +//#define mova128 movdqa +#define mova128 movaps +//#define movu128 movdqu +#define movu128 movups +//#define xor128 pxor +#define xor128 xorps +//#define shuf128_32 pshufd +#define shuf128_32 shufps + +#define extr128_32 pextrd +//#define extr128_32 extractps # not shorter + +// pshufb is a SSSE3 insn. +// pinsrd, pextrd, extractps are SSE4.1 insns. +// We do not check SSSE3/SSE4.1 in cpuid, +// all SHA-capable CPUs support them as well. + +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif + .section .text.sha1_process_block64_shaNI, "ax", @progbits + .globl sha1_process_block64_shaNI + .hidden sha1_process_block64_shaNI + .type sha1_process_block64_shaNI, @function + +#define ABCD %xmm0 +#define E0 %xmm1 /* Need two E's b/c they ping pong */ +#define E1 %xmm2 +#define MSG0 %xmm3 +#define MSG1 %xmm4 +#define MSG2 %xmm5 +#define MSG3 %xmm6 + + .balign 8 # allow decoders to fetch at least 2 first insns +sha1_process_block64_shaNI: + /* load initial hash values */ + movu128 80(%rdi), ABCD + xor128 E0, E0 + pinsrd $3, 80+4*4(%rdi), E0 # load to uppermost 32-bit word + shuf128_32 $0x1B, ABCD, ABCD # DCBA -> ABCD + + mova128 PSHUFFLE_BYTE_FLIP_MASK(%rip), %xmm7 + + movu128 0*16(%rdi), MSG0 + pshufb %xmm7, MSG0 + movu128 1*16(%rdi), MSG1 + pshufb %xmm7, MSG1 + movu128 2*16(%rdi), MSG2 + pshufb %xmm7, MSG2 + movu128 3*16(%rdi), MSG3 + pshufb %xmm7, MSG3 + + /* Save hash values for addition after rounds */ + mova128 E0, %xmm7 + mova128 ABCD, %xmm8 + + /* Rounds 0-3 */ + paddd MSG0, E0 + mova128 ABCD, E1 + sha1rnds4 $0, E0, ABCD + + /* Rounds 4-7 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1rnds4 $0, E1, ABCD + sha1msg1 MSG1, MSG0 + + /* Rounds 8-11 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1rnds4 $0, E0, ABCD + sha1msg1 MSG2, MSG1 + xor128 MSG2, MSG0 + + /* Rounds 12-15 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1msg2 MSG3, MSG0 + sha1rnds4 $0, E1, ABCD + sha1msg1 MSG3, MSG2 + xor128 MSG3, MSG1 + + /* Rounds 16-19 */ + sha1nexte MSG0, E0 + mova128 ABCD, E1 + sha1msg2 MSG0, MSG1 + sha1rnds4 $0, E0, ABCD + sha1msg1 MSG0, MSG3 + xor128 MSG0, MSG2 + + /* Rounds 20-23 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1msg2 MSG1, MSG2 + sha1rnds4 $1, E1, ABCD + sha1msg1 MSG1, MSG0 + xor128 MSG1, MSG3 + + /* Rounds 24-27 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1msg2 MSG2, MSG3 + sha1rnds4 $1, E0, ABCD + sha1msg1 MSG2, MSG1 + xor128 MSG2, MSG0 + + /* Rounds 28-31 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1msg2 MSG3, MSG0 + sha1rnds4 $1, E1, ABCD + sha1msg1 MSG3, MSG2 + xor128 MSG3, MSG1 + + /* Rounds 32-35 */ + sha1nexte MSG0, E0 + mova128 ABCD, E1 + sha1msg2 MSG0, MSG1 + sha1rnds4 $1, E0, ABCD + sha1msg1 MSG0, MSG3 + xor128 MSG0, MSG2 + + /* Rounds 36-39 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1msg2 MSG1, MSG2 + sha1rnds4 $1, E1, ABCD + sha1msg1 MSG1, MSG0 + xor128 MSG1, MSG3 + + /* Rounds 40-43 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1msg2 MSG2, MSG3 + sha1rnds4 $2, E0, ABCD + sha1msg1 MSG2, MSG1 + xor128 MSG2, MSG0 + + /* Rounds 44-47 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1msg2 MSG3, MSG0 + sha1rnds4 $2, E1, ABCD + sha1msg1 MSG3, MSG2 + xor128 MSG3, MSG1 + + /* Rounds 48-51 */ + sha1nexte MSG0, E0 + mova128 ABCD, E1 + sha1msg2 MSG0, MSG1 + sha1rnds4 $2, E0, ABCD + sha1msg1 MSG0, MSG3 + xor128 MSG0, MSG2 + + /* Rounds 52-55 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1msg2 MSG1, MSG2 + sha1rnds4 $2, E1, ABCD + sha1msg1 MSG1, MSG0 + xor128 MSG1, MSG3 + + /* Rounds 56-59 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1msg2 MSG2, MSG3 + sha1rnds4 $2, E0, ABCD + sha1msg1 MSG2, MSG1 + xor128 MSG2, MSG0 + + /* Rounds 60-63 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1msg2 MSG3, MSG0 + sha1rnds4 $3, E1, ABCD + sha1msg1 MSG3, MSG2 + xor128 MSG3, MSG1 + + /* Rounds 64-67 */ + sha1nexte MSG0, E0 + mova128 ABCD, E1 + sha1msg2 MSG0, MSG1 + sha1rnds4 $3, E0, ABCD + sha1msg1 MSG0, MSG3 + xor128 MSG0, MSG2 + + /* Rounds 68-71 */ + sha1nexte MSG1, E1 + mova128 ABCD, E0 + sha1msg2 MSG1, MSG2 + sha1rnds4 $3, E1, ABCD + xor128 MSG1, MSG3 + + /* Rounds 72-75 */ + sha1nexte MSG2, E0 + mova128 ABCD, E1 + sha1msg2 MSG2, MSG3 + sha1rnds4 $3, E0, ABCD + + /* Rounds 76-79 */ + sha1nexte MSG3, E1 + mova128 ABCD, E0 + sha1rnds4 $3, E1, ABCD + + /* Add current hash values with previously saved */ + sha1nexte %xmm7, E0 + paddd %xmm8, ABCD + + /* Write hash values back in the correct order */ + shuf128_32 $0x1B, ABCD, ABCD + movu128 ABCD, 80(%rdi) + extr128_32 $3, E0, 80+4*4(%rdi) + + ret + .size sha1_process_block64_shaNI, .-sha1_process_block64_shaNI + + .section .rodata.cst16.PSHUFFLE_BYTE_FLIP_MASK, "aM", @progbits, 16 + .balign 16 +PSHUFFLE_BYTE_FLIP_MASK: + .octa 0x000102030405060708090a0b0c0d0e0f + +#endif diff -Nru busybox-1.35.0/libbb/hash_md5_sha_x86-64.S.sh busybox-1.36.1/libbb/hash_md5_sha_x86-64.S.sh --- busybox-1.35.0/libbb/hash_md5_sha_x86-64.S.sh 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/libbb/hash_md5_sha_x86-64.S.sh 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,478 @@ +#!/bin/sh + +# We don't regenerate it on every "make" invocation - only by hand. +# The reason is that the changes to generated code are difficult +# to visualize by looking only at this script, it helps when the commit +# also contains the diff of the generated file. +exec >hash_md5_sha_x86-64.S + +# Based on http://arctic.org/~dean/crypto/sha1.html. +# ("This SHA1 implementation is public domain.") +# +# x86-64 has at least SSE2 vector insns always available. +# We can use them without any CPUID checks (and without a need +# for a fallback code if needed insns are not available). +# This code uses them to calculate W[] ahead of time. +# +# Unfortunately, results are passed from vector unit to +# integer ALUs on the stack. MOVD/Q insns to move them directly +# from vector to integer registers are slower than store-to-load +# forwarding in LSU (on Skylake at least). +# +# The win against a purely integer code is small on Skylake, +# only about 7-8%. We offload about 1/3 of our operations to the vector unit. +# It can do 4 ops at once in one 128-bit register, +# but we have to use x2 of them because of W[0] complication, +# SSE2 has no "rotate each word by N bits" insns, +# moving data to/from vector unit is clunky, and Skylake +# has four integer ALUs unified with three vector ALUs, +# which makes pure integer code rather fast, and makes +# vector ops compete with integer ones. +# +# Zen3, with its separate vector ALUs, wins more, about 12%. + +xmmT1="%xmm4" +xmmT2="%xmm5" +xmmRCONST="%xmm6" +xmmALLRCONST="%xmm7" +T=`printf '\t'` + +# SSE instructions are longer than 4 bytes on average. +# Intel CPUs (up to Tiger Lake at least) can't decode +# more than 16 bytes of code in one cycle. +# By interleaving SSE code and integer code +# we mostly achieve a situation where 16-byte decode fetch window +# contains 4 (or more) insns. +# +# However. On Skylake, there was no observed difference, +# but on Zen3, non-interleaved code is ~3% faster +# (822 Mb/s versus 795 Mb/s hashing speed). +# Off for now: +interleave=false + +INTERLEAVE() { + $interleave || \ + { + # Generate non-interleaved code + # (it should work correctly too) + echo "$1" + echo "$2" + return + } + ( + echo "$1" | grep -v '^$' >"$0.temp1" + echo "$2" | grep -v '^$' >"$0.temp2" + exec 3<"$0.temp1" + exec 4<"$0.temp2" + IFS='' + while :; do + line1='' + line2='' + while :; do + read -r line1 <&3 + if test "${line1:0:1}" != "#" && test "${line1:0:2}" != "$T#"; then + break + fi + echo "$line1" + done + while :; do + read -r line2 <&4 + if test "${line2:0:4}" = "${T}lea"; then + # We use 7-8 byte long forms of LEA. + # Do not interleave them with SSE insns + # which are also long. + echo "$line2" + read -r line2 <&4 + echo "$line2" + continue + fi + if test "${line2:0:1}" != "#" && test "${line2:0:2}" != "$T#"; then + break + fi + echo "$line2" + done + test "$line1$line2" || break + echo "$line1" + echo "$line2" + done + rm "$0.temp1" "$0.temp2" + ) +} + +# movaps bswap32_mask(%rip), $xmmT1 +# Load W[] to xmm0..3, byteswapping on the fly. +# For iterations 0..15, we pass RCONST+W[] in rsi,r8..r14 +# for use in RD1As instead of spilling them to stack. +# (We use rsi instead of rN because this makes two +# ADDs in two first RD1As shorter by one byte). +# movups 16*0(%rdi), %xmm0 +# pshufb $xmmT1, %xmm0 #SSSE3 insn +# movaps %xmm0, $xmmT2 +# paddd $xmmRCONST, $xmmT2 +# movq $xmmT2, %rsi +# #pextrq \$1, $xmmT2, %r8 #SSE4.1 insn +# #movhpd $xmmT2, %r8 #can only move to mem, not to reg +# shufps \$0x0e, $xmmT2, $xmmT2 # have to use two-insn sequence +# movq $xmmT2, %r8 # instead +# ... +# +# ... +#- leal $RCONST(%r$e,%rsi), %e$e # e += RCONST + W[n] +#+ addl %esi, %e$e # e += RCONST + W[n] +# ^^^^^^^^^^^^^^^^^^^^^^^^ +# The above is -97 bytes of code... +# ...but pshufb is a SSSE3 insn. Can't use it. + +echo \ +"### Generated by hash_md5_sha_x86-64.S.sh ### + +#if CONFIG_SHA1_SMALL == 0 && defined(__GNUC__) && defined(__x86_64__) +#ifdef __linux__ + .section .note.GNU-stack, \"\", @progbits +#endif + .section .text.sha1_process_block64, \"ax\", @progbits + .globl sha1_process_block64 + .hidden sha1_process_block64 + .type sha1_process_block64, @function + + .balign 8 # allow decoders to fetch at least 5 first insns +sha1_process_block64: + pushq %rbp # 1 byte insn + pushq %rbx # 1 byte insn +# pushq %r15 # 2 byte insn + pushq %r14 # 2 byte insn + pushq %r13 # 2 byte insn + pushq %r12 # 2 byte insn + pushq %rdi # we need ctx at the end + +#Register and stack use: +# eax..edx: a..d +# ebp: e +# esi,edi,r8..r14: temps +# r15: unused +# xmm0..xmm3: W[] +# xmm4,xmm5: temps +# xmm6: current round constant +# xmm7: all round constants +# -64(%rsp): area for passing RCONST + W[] from vector to integer units + + movl 80(%rdi), %eax # a = ctx->hash[0] + movl 84(%rdi), %ebx # b = ctx->hash[1] + movl 88(%rdi), %ecx # c = ctx->hash[2] + movl 92(%rdi), %edx # d = ctx->hash[3] + movl 96(%rdi), %ebp # e = ctx->hash[4] + + movaps sha1const(%rip), $xmmALLRCONST + pshufd \$0x00, $xmmALLRCONST, $xmmRCONST + + # Load W[] to xmm0..3, byteswapping on the fly. + # + # For iterations 0..15, we pass W[] in rsi,r8..r14 + # for use in RD1As instead of spilling them to stack. + # We lose parallelized addition of RCONST, but LEA + # can do two additions at once, so it is probably a wash. + # (We use rsi instead of rN because this makes two + # LEAs in two first RD1As shorter by one byte). + movq 4*0(%rdi), %rsi + movq 4*2(%rdi), %r8 + bswapq %rsi + bswapq %r8 + rolq \$32, %rsi # rsi = W[1]:W[0] + rolq \$32, %r8 # r8 = W[3]:W[2] + movq %rsi, %xmm0 + movq %r8, $xmmT1 + punpcklqdq $xmmT1, %xmm0 # xmm0 = r8:rsi = (W[0],W[1],W[2],W[3]) +# movaps %xmm0, $xmmT1 # add RCONST, spill to stack +# paddd $xmmRCONST, $xmmT1 +# movups $xmmT1, -64+16*0(%rsp) + + movq 4*4(%rdi), %r9 + movq 4*6(%rdi), %r10 + bswapq %r9 + bswapq %r10 + rolq \$32, %r9 # r9 = W[5]:W[4] + rolq \$32, %r10 # r10 = W[7]:W[6] + movq %r9, %xmm1 + movq %r10, $xmmT1 + punpcklqdq $xmmT1, %xmm1 # xmm1 = r10:r9 = (W[4],W[5],W[6],W[7]) + + movq 4*8(%rdi), %r11 + movq 4*10(%rdi), %r12 + bswapq %r11 + bswapq %r12 + rolq \$32, %r11 # r11 = W[9]:W[8] + rolq \$32, %r12 # r12 = W[11]:W[10] + movq %r11, %xmm2 + movq %r12, $xmmT1 + punpcklqdq $xmmT1, %xmm2 # xmm2 = r12:r11 = (W[8],W[9],W[10],W[11]) + + movq 4*12(%rdi), %r13 + movq 4*14(%rdi), %r14 + bswapq %r13 + bswapq %r14 + rolq \$32, %r13 # r13 = W[13]:W[12] + rolq \$32, %r14 # r14 = W[15]:W[14] + movq %r13, %xmm3 + movq %r14, $xmmT1 + punpcklqdq $xmmT1, %xmm3 # xmm3 = r14:r13 = (W[12],W[13],W[14],W[15]) +" + +PREP() { +local xmmW0=$1 +local xmmW4=$2 +local xmmW8=$3 +local xmmW12=$4 +# the above must be %xmm0..3 in some permutation +local dstmem=$5 +#W[0] = rol(W[13] ^ W[8] ^ W[2] ^ W[0], 1); +#W[1] = rol(W[14] ^ W[9] ^ W[3] ^ W[1], 1); +#W[2] = rol(W[15] ^ W[10] ^ W[4] ^ W[2], 1); +#W[3] = rol( 0 ^ W[11] ^ W[5] ^ W[3], 1); +#W[3] ^= rol(W[0], 1); +echo "# PREP $@ + movaps $xmmW12, $xmmT1 + psrldq \$4, $xmmT1 # rshift by 4 bytes: T1 = ([13],[14],[15],0) + +# pshufd \$0x4e, $xmmW0, $xmmT2 # 01001110=2,3,0,1 shuffle, ([2],[3],x,x) +# punpcklqdq $xmmW4, $xmmT2 # T2 = W4[0..63]:T2[0..63] = ([2],[3],[4],[5]) +# same result as above, but shorter and faster: +# pshufd/shufps are subtly different: pshufd takes all dwords from source operand, +# shufps takes dwords 0,1 from *2nd* operand, and dwords 2,3 from 1st one! + movaps $xmmW0, $xmmT2 + shufps \$0x4e, $xmmW4, $xmmT2 # 01001110=(T2.dw[2], T2.dw[3], W4.dw[0], W4.dw[1]) = ([2],[3],[4],[5]) + + xorps $xmmW8, $xmmW0 # ([8],[9],[10],[11]) ^ ([0],[1],[2],[3]) + xorps $xmmT1, $xmmT2 # ([13],[14],[15],0) ^ ([2],[3],[4],[5]) + xorps $xmmT2, $xmmW0 # ^ + # W0 = unrotated (W[0]..W[3]), still needs W[3] fixup + movaps $xmmW0, $xmmT2 + + xorps $xmmT1, $xmmT1 # rol(W0,1): + pcmpgtd $xmmW0, $xmmT1 # ffffffff for elements <0 (ones with msb bit 1) + paddd $xmmW0, $xmmW0 # shift left by 1 + psubd $xmmT1, $xmmW0 # add 1 to those who had msb bit 1 + # W0 = rotated (W[0]..W[3]), still needs W[3] fixup + + pslldq \$12, $xmmT2 # lshift by 12 bytes: T2 = (0,0,0,unrotW[0]) + movaps $xmmT2, $xmmT1 + pslld \$2, $xmmT2 + psrld \$30, $xmmT1 +# xorps $xmmT1, $xmmT2 # rol((0,0,0,unrotW[0]),2) + xorps $xmmT1, $xmmW0 # same result, but does not depend on/does not modify T2 + + xorps $xmmT2, $xmmW0 # W0 = rol(W[0]..W[3],1) ^ (0,0,0,rol(unrotW[0],2)) +" +# movq $xmmW0, %r8 # high latency (~6 cycles) +# movaps $xmmW0, $xmmT1 +# psrldq \$8, $xmmT1 # rshift by 8 bytes: move upper 64 bits to lower +# movq $xmmT1, %r10 # high latency +# movq %r8, %r9 +# movq %r10, %r11 +# shrq \$32, %r9 +# shrq \$32, %r11 +# ^^^ slower than passing the results on stack (!!!) +echo " + movaps $xmmW0, $xmmT2 + paddd $xmmRCONST, $xmmT2 + movups $xmmT2, $dstmem +" +} + +# It's possible to interleave integer insns in rounds to mostly eliminate +# dependency chains, but this likely to only help old Pentium-based +# CPUs (ones without OOO, which can only simultaneously execute a pair +# of _adjacent_ insns). +# Testing on old-ish Silvermont CPU (which has OOO window of only +# about ~8 insns) shows very small (~1%) speedup. + +RD1A() { +local a=$1;local b=$2;local c=$3;local d=$4;local e=$5 +local n=$(($6)) +local n0=$(((n+0) & 15)) +local rN=$((7+n0/2)) +echo " +# $n +";test $n0 = 0 && echo " + leal $RCONST(%r$e,%rsi), %e$e # e += RCONST + W[n] + shrq \$32, %rsi +";test $n0 = 1 && echo " + leal $RCONST(%r$e,%rsi), %e$e # e += RCONST + W[n] +";test $n0 -ge 2 && test $((n0 & 1)) = 0 && echo " + leal $RCONST(%r$e,%r$rN), %e$e # e += RCONST + W[n] + shrq \$32, %r$rN +";test $n0 -ge 2 && test $((n0 & 1)) = 1 && echo " + leal $RCONST(%r$e,%r$rN), %e$e # e += RCONST + W[n] +";echo " + movl %e$c, %edi # c + xorl %e$d, %edi # ^d + andl %e$b, %edi # &b + xorl %e$d, %edi # (((c ^ d) & b) ^ d) + addl %edi, %e$e # e += (((c ^ d) & b) ^ d) + movl %e$a, %edi # + roll \$5, %edi # rotl32(a,5) + addl %edi, %e$e # e += rotl32(a,5) + rorl \$2, %e$b # b = rotl32(b,30) +" +} +RD1B() { +local a=$1;local b=$2;local c=$3;local d=$4;local e=$5 +local n=$(($6)) +local n13=$(((n+13) & 15)) +local n8=$(((n+8) & 15)) +local n2=$(((n+2) & 15)) +local n0=$(((n+0) & 15)) +echo " +# $n + movl %e$c, %edi # c + xorl %e$d, %edi # ^d + andl %e$b, %edi # &b + xorl %e$d, %edi # (((c ^ d) & b) ^ d) + addl -64+4*$n0(%rsp), %e$e # e += RCONST + W[n & 15] + addl %edi, %e$e # e += (((c ^ d) & b) ^ d) + movl %e$a, %esi # + roll \$5, %esi # rotl32(a,5) + addl %esi, %e$e # e += rotl32(a,5) + rorl \$2, %e$b # b = rotl32(b,30) +" +} + +RD2() { +local a=$1;local b=$2;local c=$3;local d=$4;local e=$5 +local n=$(($6)) +local n13=$(((n+13) & 15)) +local n8=$(((n+8) & 15)) +local n2=$(((n+2) & 15)) +local n0=$(((n+0) & 15)) +echo " +# $n + movl %e$c, %edi # c + xorl %e$d, %edi # ^d + xorl %e$b, %edi # ^b + addl -64+4*$n0(%rsp), %e$e # e += RCONST + W[n & 15] + addl %edi, %e$e # e += (c ^ d ^ b) + movl %e$a, %esi # + roll \$5, %esi # rotl32(a,5) + addl %esi, %e$e # e += rotl32(a,5) + rorl \$2, %e$b # b = rotl32(b,30) +" +} + +RD3() { +local a=$1;local b=$2;local c=$3;local d=$4;local e=$5 +local n=$(($6)) +local n13=$(((n+13) & 15)) +local n8=$(((n+8) & 15)) +local n2=$(((n+2) & 15)) +local n0=$(((n+0) & 15)) +echo " +# $n + movl %e$b, %edi # di: b + movl %e$b, %esi # si: b + orl %e$c, %edi # di: b | c + andl %e$c, %esi # si: b & c + andl %e$d, %edi # di: (b | c) & d + orl %esi, %edi # ((b | c) & d) | (b & c) + addl %edi, %e$e # += ((b | c) & d) | (b & c) + addl -64+4*$n0(%rsp), %e$e # e += RCONST + W[n & 15] + movl %e$a, %esi # + roll \$5, %esi # rotl32(a,5) + addl %esi, %e$e # e += rotl32(a,5) + rorl \$2, %e$b # b = rotl32(b,30) +" +} + +{ +# Round 1 +RCONST=0x5A827999 +RD1A ax bx cx dx bp 0; RD1A bp ax bx cx dx 1; RD1A dx bp ax bx cx 2; RD1A cx dx bp ax bx 3; +RD1A bx cx dx bp ax 4; RD1A ax bx cx dx bp 5; RD1A bp ax bx cx dx 6; RD1A dx bp ax bx cx 7; +a=`PREP %xmm0 %xmm1 %xmm2 %xmm3 "-64+16*0(%rsp)"` +b=`RD1A cx dx bp ax bx 8; RD1A bx cx dx bp ax 9; RD1A ax bx cx dx bp 10; RD1A bp ax bx cx dx 11;` +INTERLEAVE "$a" "$b" +a=`echo " pshufd \\$0x55, $xmmALLRCONST, $xmmRCONST" + PREP %xmm1 %xmm2 %xmm3 %xmm0 "-64+16*1(%rsp)"` +b=`RD1A dx bp ax bx cx 12; RD1A cx dx bp ax bx 13; RD1A bx cx dx bp ax 14; RD1A ax bx cx dx bp 15;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm2 %xmm3 %xmm0 %xmm1 "-64+16*2(%rsp)"` +b=`RD1B bp ax bx cx dx 16; RD1B dx bp ax bx cx 17; RD1B cx dx bp ax bx 18; RD1B bx cx dx bp ax 19;` +INTERLEAVE "$a" "$b" + +# Round 2 +RCONST=0x6ED9EBA1 +a=`PREP %xmm3 %xmm0 %xmm1 %xmm2 "-64+16*3(%rsp)"` +b=`RD2 ax bx cx dx bp 20; RD2 bp ax bx cx dx 21; RD2 dx bp ax bx cx 22; RD2 cx dx bp ax bx 23;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm0 %xmm1 %xmm2 %xmm3 "-64+16*0(%rsp)"` +b=`RD2 bx cx dx bp ax 24; RD2 ax bx cx dx bp 25; RD2 bp ax bx cx dx 26; RD2 dx bp ax bx cx 27;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm1 %xmm2 %xmm3 %xmm0 "-64+16*1(%rsp)"` +b=`RD2 cx dx bp ax bx 28; RD2 bx cx dx bp ax 29; RD2 ax bx cx dx bp 30; RD2 bp ax bx cx dx 31;` +INTERLEAVE "$a" "$b" +a=`echo " pshufd \\$0xaa, $xmmALLRCONST, $xmmRCONST" + PREP %xmm2 %xmm3 %xmm0 %xmm1 "-64+16*2(%rsp)"` +b=`RD2 dx bp ax bx cx 32; RD2 cx dx bp ax bx 33; RD2 bx cx dx bp ax 34; RD2 ax bx cx dx bp 35;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm3 %xmm0 %xmm1 %xmm2 "-64+16*3(%rsp)"` +b=`RD2 bp ax bx cx dx 36; RD2 dx bp ax bx cx 37; RD2 cx dx bp ax bx 38; RD2 bx cx dx bp ax 39;` +INTERLEAVE "$a" "$b" + +# Round 3 +RCONST=0x8F1BBCDC +a=`PREP %xmm0 %xmm1 %xmm2 %xmm3 "-64+16*0(%rsp)"` +b=`RD3 ax bx cx dx bp 40; RD3 bp ax bx cx dx 41; RD3 dx bp ax bx cx 42; RD3 cx dx bp ax bx 43;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm1 %xmm2 %xmm3 %xmm0 "-64+16*1(%rsp)"` +b=`RD3 bx cx dx bp ax 44; RD3 ax bx cx dx bp 45; RD3 bp ax bx cx dx 46; RD3 dx bp ax bx cx 47;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm2 %xmm3 %xmm0 %xmm1 "-64+16*2(%rsp)"` +b=`RD3 cx dx bp ax bx 48; RD3 bx cx dx bp ax 49; RD3 ax bx cx dx bp 50; RD3 bp ax bx cx dx 51;` +INTERLEAVE "$a" "$b" +a=`echo " pshufd \\$0xff, $xmmALLRCONST, $xmmRCONST" + PREP %xmm3 %xmm0 %xmm1 %xmm2 "-64+16*3(%rsp)"` +b=`RD3 dx bp ax bx cx 52; RD3 cx dx bp ax bx 53; RD3 bx cx dx bp ax 54; RD3 ax bx cx dx bp 55;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm0 %xmm1 %xmm2 %xmm3 "-64+16*0(%rsp)"` +b=`RD3 bp ax bx cx dx 56; RD3 dx bp ax bx cx 57; RD3 cx dx bp ax bx 58; RD3 bx cx dx bp ax 59;` +INTERLEAVE "$a" "$b" + +# Round 4 has the same logic as round 2, only n and RCONST are different +RCONST=0xCA62C1D6 +a=`PREP %xmm1 %xmm2 %xmm3 %xmm0 "-64+16*1(%rsp)"` +b=`RD2 ax bx cx dx bp 60; RD2 bp ax bx cx dx 61; RD2 dx bp ax bx cx 62; RD2 cx dx bp ax bx 63;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm2 %xmm3 %xmm0 %xmm1 "-64+16*2(%rsp)"` +b=`RD2 bx cx dx bp ax 64; RD2 ax bx cx dx bp 65; RD2 bp ax bx cx dx 66; RD2 dx bp ax bx cx 67;` +INTERLEAVE "$a" "$b" +a=`PREP %xmm3 %xmm0 %xmm1 %xmm2 "-64+16*3(%rsp)"` +b=`RD2 cx dx bp ax bx 68; RD2 bx cx dx bp ax 69; RD2 ax bx cx dx bp 70; RD2 bp ax bx cx dx 71;` +INTERLEAVE "$a" "$b" +RD2 dx bp ax bx cx 72; RD2 cx dx bp ax bx 73; RD2 bx cx dx bp ax 74; RD2 ax bx cx dx bp 75; +RD2 bp ax bx cx dx 76; RD2 dx bp ax bx cx 77; RD2 cx dx bp ax bx 78; RD2 bx cx dx bp ax 79; +} | grep -v '^$' + +echo " + popq %rdi # + popq %r12 # + addl %eax, 80(%rdi) # ctx->hash[0] += a + popq %r13 # + addl %ebx, 84(%rdi) # ctx->hash[1] += b + popq %r14 # + addl %ecx, 88(%rdi) # ctx->hash[2] += c +# popq %r15 # + addl %edx, 92(%rdi) # ctx->hash[3] += d + popq %rbx # + addl %ebp, 96(%rdi) # ctx->hash[4] += e + popq %rbp # + + ret + .size sha1_process_block64, .-sha1_process_block64 + + .section .rodata.cst16.sha1const, \"aM\", @progbits, 16 + .balign 16 +sha1const: + .long 0x5A827999 + .long 0x6ED9EBA1 + .long 0x8F1BBCDC + .long 0xCA62C1D6 + +#endif" diff -Nru busybox-1.35.0/libbb/Kbuild.src busybox-1.36.1/libbb/Kbuild.src --- busybox-1.35.0/libbb/Kbuild.src 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/libbb/Kbuild.src 2023-01-03 14:14:43.000000000 +0000 @@ -56,6 +56,11 @@ lib-y += make_directory.o lib-y += makedev.o lib-y += hash_md5_sha.o +lib-y += hash_md5_sha_x86-64.o +lib-y += hash_md5_sha_x86-64_shaNI.o +lib-y += hash_md5_sha_x86-32_shaNI.o +lib-y += hash_md5_sha256_x86-64_shaNI.o +lib-y += hash_md5_sha256_x86-32_shaNI.o # Alternative (disabled) MD5 implementation #lib-y += hash_md5prime.o lib-y += messages.o @@ -197,6 +202,7 @@ lib-$(CONFIG_PKILL) += xregcomp.o lib-$(CONFIG_DEVFSD) += xregcomp.o lib-$(CONFIG_FEATURE_FIND_REGEX) += xregcomp.o +lib-$(CONFIG_FEATURE_CUT_REGEX) += xregcomp.o # Add the experimental logging functionality, only used by zcip lib-$(CONFIG_ZCIP) += logenv.o diff -Nru busybox-1.35.0/libbb/lineedit.c busybox-1.36.1/libbb/lineedit.c --- busybox-1.35.0/libbb/lineedit.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/libbb/lineedit.c 2023-04-25 14:47:22.000000000 +0000 @@ -249,19 +249,31 @@ } } -static const char *get_username_str(void) +static NOINLINE const char *get_homedir_or_NULL(void) { + const char *home; + +# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH + home = state && state->sh_get_var ? state->sh_get_var("HOME") : getenv("HOME"); +# else + home = getenv("HOME"); +# endif + if (home != NULL && home[0] != '\0') + return home; + if (!got_user_strings) get_user_strings(); - return user_buf ? user_buf : ""; - /* btw, bash uses "I have no name!" string if uid has no entry */ + return home_pwd_buf; } +#endif -static NOINLINE const char *get_homedir_or_NULL(void) +#if ENABLE_FEATURE_EDITING_FANCY_PROMPT +static const char *get_username_str(void) { if (!got_user_strings) get_user_strings(); - return home_pwd_buf; + return user_buf ? user_buf : ""; + /* btw, bash uses "I have no name!" string if uid has no entry */ } #endif @@ -813,8 +825,8 @@ res[npth++] = tmp; } /* special case: "match subdirectories of the current directory" */ - /*res[npth++] = NULL; - filled by xzalloc() */ - return npth; + /*res[npth] = NULL; - filled by xzalloc() */ + return npth + 1; } /* Complete command, directory or file name. @@ -861,7 +873,7 @@ continue; } # endif -# if EDITING_HAS_get_exe_name +# if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH if (state->get_exe_name) { i = 0; for (;;) { @@ -2025,7 +2037,13 @@ case 'W': /* basename of cur dir */ if (!cwd_buf) { const char *home; +# if EDITING_HAS_sh_get_var + cwd_buf = state && state->sh_get_var + ? xstrdup(state->sh_get_var("PWD")) + : xrealloc_getcwd_or_warn(NULL); +# else cwd_buf = xrealloc_getcwd_or_warn(NULL); +# endif if (!cwd_buf) cwd_buf = (char *)bb_msg_unknown; else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { @@ -2155,17 +2173,41 @@ #endif fflush_all(); - while (1) { + for (;;) { /* Wait for input. TIMEOUT = -1 makes read_key wait even * on nonblocking stdin, TIMEOUT = 50 makes sure we won't * insist on full MB_CUR_MAX buffer to declare input like * "\xff\n",pause,"ls\n" invalid and thus won't lose "ls". * + * If LI_INTERRUPTIBLE, return -1 if got EINTR in poll() + * inside read_key, or if bb_got_signal != 0 (IOW: if signal + * arrived before poll() is reached). + * * Note: read_key sets errno to 0 on success. */ - IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;) - ic = read_key(STDIN_FILENO, read_key_buffer, timeout); - IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;) + for (;;) { + if ((state->flags & LI_INTERRUPTIBLE) && bb_got_signal) { + errno = EINTR; + return -1; + } +//FIXME: still races here with signals, but small window to poll() inside read_key + IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;) + /* errno = 0; - read_key does this itself */ + ic = read_key(STDIN_FILENO, read_key_buffer, timeout); + IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 0;) + if (errno != EINTR) + break; + if (state->flags & LI_INTERRUPTIBLE) { + /* LI_INTERRUPTIBLE bails out on EINTR, + * but nothing really guarantees that bb_got_signal + * is nonzero. Follow the least surprise principle: + */ + if (bb_got_signal == 0) + bb_got_signal = 255; + goto ret; + } + } + if (errno) { #if ENABLE_UNICODE_SUPPORT if (errno == EAGAIN && unicode_idx != 0) @@ -2233,7 +2275,7 @@ #endif break; } - + ret: return ic; } diff -Nru busybox-1.35.0/libbb/loop.c busybox-1.36.1/libbb/loop.c --- busybox-1.35.0/libbb/loop.c 2021-12-26 16:53:20.000000000 +0000 +++ busybox-1.36.1/libbb/loop.c 2023-01-03 14:14:43.000000000 +0000 @@ -71,7 +71,7 @@ fd = open(device, O_RDONLY); if (fd < 0) - return 1; + return fd; /* -1 */ rc = ioctl(fd, LOOP_CLR_FD, 0); close(fd); @@ -96,6 +96,97 @@ return loopdevno; /* can be -1 if error */ } +static int get_next_free_loop(char *dev, int id) +{ + int loopdevno; + + loopdevno = get_free_loop(); + if (loopdevno != -1) { + /* loopdevno is -2 (use id) or >= 0 (use id = loopdevno): */ + if (loopdevno >= 0) + id = loopdevno; + sprintf(dev, LOOP_FORMAT, id); + } + return loopdevno; +} + +#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_LOOP_CONFIGURE +# define LOOP_CONFIGURE 0x4C0A +struct bb_loop_config { + uint32_t fd; + uint32_t block_size; + struct loop_info64 info; + uint64_t __reserved[8]; +}; +#endif + +static int set_loopdev_params(int lfd, + int ffd, const char *file, + unsigned long long offset, + unsigned long long sizelimit, + unsigned flags) +{ + int rc; +#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_LOOP_CONFIGURE + struct bb_loop_config lconfig; +# define loopinfo lconfig.info +#else + bb_loop_info loopinfo; +#endif + + rc = ioctl(lfd, BB_LOOP_GET_STATUS, &loopinfo); + + /* If device is free, try to claim it */ + if (rc && errno == ENXIO) { +#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_LOOP_CONFIGURE + memset(&lconfig, 0, sizeof(lconfig)); +#else + memset(&loopinfo, 0, sizeof(loopinfo)); +#endif + safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); + loopinfo.lo_offset = offset; + loopinfo.lo_sizelimit = sizelimit; + /* + * LO_FLAGS_READ_ONLY is not set because RO is controlled + * by open type of the lfd. + */ + loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY); + +#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_LOOP_CONFIGURE + lconfig.fd = ffd; + rc = ioctl(lfd, LOOP_CONFIGURE, &lconfig); + if (rc == 0) + return rc; /* SUCCESS! */ +# if ENABLE_TRY_LOOP_CONFIGURE + if (errno != EINVAL) + return rc; /* error other than old kernel */ + /* Old kernel, fall through into old way to do it: */ +# endif +#endif +#if ENABLE_TRY_LOOP_CONFIGURE || ENABLE_NO_LOOP_CONFIGURE + /* Associate free loop device with file */ + rc = ioctl(lfd, LOOP_SET_FD, ffd); + if (rc != 0) { + /* Ouch... race: the device already has a fd */ + return rc; + } + rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); + if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) { + /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */ + /* (this code path is not tested) */ + loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR; + rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); + } + if (rc == 0) + return rc; /* SUCCESS! */ + /* failure, undo LOOP_SET_FD */ + ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary +#endif + } + return -1; +#undef loopinfo +} + /* Returns opened fd to the loop device, <0 on error. * *device is loop device to use, or if *device==NULL finds a loop device to * mount it on and sets *device to a strdup of that loop device name. @@ -105,7 +196,6 @@ { char dev[LOOP_NAMESIZE]; char *try; - bb_loop_info loopinfo; struct stat statbuf; int i, lfd, ffd, mode, rc; @@ -123,30 +213,27 @@ try = *device; if (!try) { - get_free_loopN: - i = get_free_loop(); - if (i == -1) { - close(ffd); - return -1; /* no free loop devices */ - } - if (i >= 0) { - try = xasprintf(LOOP_FORMAT, i); - goto open_lfd; - } - /* i == -2: no /dev/loop-control. Do an old-style search for a free device */ try = dev; } /* Find a loop device */ /* 0xfffff is a max possible minor number in Linux circa 2010 */ for (i = 0; i <= 0xfffff; i++) { - sprintf(dev, LOOP_FORMAT, i); + if (!*device) { + rc = get_next_free_loop(dev, i); + if (rc == -1) + break; /* no free loop devices (or other error in LOOP_CTL_GET_FREE) */ + if (rc >= 0) + /* /dev/loop-control gave us the next free /dev/loopN */ + goto open_lfd; + /* else: sequential /dev/loopN, needs to be tested/maybe_created */ + } IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;) if (stat(try, &statbuf) != 0 || !S_ISBLK(statbuf.st_mode)) { if (ENABLE_FEATURE_MOUNT_LOOP_CREATE && errno == ENOENT - && try == dev + && (!*device) ) { /* Node doesn't exist, try to create it */ if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0) @@ -172,55 +259,19 @@ goto try_next_loopN; } - rc = ioctl(lfd, BB_LOOP_GET_STATUS, &loopinfo); - - /* If device is free, try to claim it */ - if (rc && errno == ENXIO) { - /* Associate free loop device with file */ - if (ioctl(lfd, LOOP_SET_FD, ffd)) { - /* Ouch. Are we racing with other mount? */ - if (!*device /* yes */ - && try != dev /* tried a _kernel-offered_ loopN? */ - ) { - free(try); - close(lfd); -//TODO: add "if (--failcount != 0) ..."? - goto get_free_loopN; - } - goto close_and_try_next_loopN; - } - memset(&loopinfo, 0, sizeof(loopinfo)); - safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); - loopinfo.lo_offset = offset; - loopinfo.lo_sizelimit = sizelimit; - /* - * Used by mount to set LO_FLAGS_AUTOCLEAR. - * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file. - * Note that closing LO_FLAGS_AUTOCLEARed lfd before mount - * is wrong (would free the loop device!) + rc = set_loopdev_params(lfd, ffd, file, offset, sizelimit, flags); + if (rc == 0) { + /* SUCCESS! */ + if (!*device) + *device = xstrdup(dev); + /* Note: mount asks for LO_FLAGS_AUTOCLEAR loopdev. + * Closing LO_FLAGS_AUTOCLEARed lfd before mount + * is wrong (would free the loop device!), + * this is why we return without closing it. */ - loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY); - rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); - if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) { - /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */ - /* (this code path is not tested) */ - loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR; - rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); - } - if (rc == 0) { - /* SUCCESS! */ - if (try != dev) /* tried a kernel-offered free loopN? */ - *device = try; /* malloced */ - if (!*device) /* was looping in search of free "/dev/loopN"? */ - *device = xstrdup(dev); - rc = lfd; /* return this */ - break; - } - /* failure, undo LOOP_SET_FD */ - ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary + rc = lfd; /* return this */ + break; } - /* else: device is not free (rc == 0) or error other than ENXIO */ - close_and_try_next_loopN: close(lfd); try_next_loopN: rc = -1; diff -Nru busybox-1.35.0/libbb/perror_nomsg_and_die.c busybox-1.36.1/libbb/perror_nomsg_and_die.c --- busybox-1.35.0/libbb/perror_nomsg_and_die.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/libbb/perror_nomsg_and_die.c 2023-01-03 14:14:43.000000000 +0000 @@ -12,11 +12,11 @@ * instead of including libbb.h */ //#include "libbb.h" #include "platform.h" -extern void bb_simple_perror_msg_and_die(const char *s) FAST_FUNC; +extern void bb_perror_msg_and_die(const char *s, ...) FAST_FUNC; /* suppress gcc "no previous prototype" warning */ void FAST_FUNC bb_perror_nomsg_and_die(void); void FAST_FUNC bb_perror_nomsg_and_die(void) { - bb_simple_perror_msg_and_die(0); + bb_perror_msg_and_die(0); } diff -Nru busybox-1.35.0/libbb/perror_nomsg.c busybox-1.36.1/libbb/perror_nomsg.c --- busybox-1.35.0/libbb/perror_nomsg.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/libbb/perror_nomsg.c 2023-01-03 14:14:43.000000000 +0000 @@ -12,11 +12,11 @@ * instead of including libbb.h */ //#include "libbb.h" #include "platform.h" -extern void bb_simple_perror_msg(const char *s) FAST_FUNC; +extern void bb_perror_msg(const char *s, ...) FAST_FUNC; /* suppress gcc "no previous prototype" warning */ void FAST_FUNC bb_perror_nomsg(void); void FAST_FUNC bb_perror_nomsg(void) { - bb_simple_perror_msg(0); + bb_perror_msg(0); } diff -Nru busybox-1.35.0/libbb/read_key.c busybox-1.36.1/libbb/read_key.c --- busybox-1.35.0/libbb/read_key.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/libbb/read_key.c 2023-01-03 14:14:43.000000000 +0000 @@ -126,7 +126,10 @@ * if fd can be in non-blocking mode. */ if (timeout >= -1) { - if (safe_poll(&pfd, 1, timeout) == 0) { + n = poll(&pfd, 1, timeout); + if (n < 0 && errno == EINTR) + return n; + if (n == 0) { /* Timed out */ errno = EAGAIN; return -1; @@ -138,7 +141,7 @@ * When we were reading 3 bytes here, we were eating * "li" too, and cat was getting wrong input. */ - n = safe_read(fd, buffer, 1); + n = read(fd, buffer, 1); if (n <= 0) return -1; } @@ -284,6 +287,16 @@ goto start_over; } +int64_t FAST_FUNC safe_read_key(int fd, char *buffer, int timeout) +{ + int64_t r; + do { + /* errno = 0; - read_key does this itself */ + r = read_key(fd, buffer, timeout); + } while (errno == EINTR); + return r; +} + void FAST_FUNC read_key_ungets(char *buffer, const char *str, unsigned len) { unsigned cur_len = (unsigned char)buffer[0]; diff -Nru busybox-1.35.0/libbb/setup_environment.c busybox-1.36.1/libbb/setup_environment.c --- busybox-1.35.0/libbb/setup_environment.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/libbb/setup_environment.c 2023-01-03 14:14:43.000000000 +0000 @@ -36,9 +36,8 @@ /* Change the current working directory to be the home directory * of the user */ - if (!(flags & SETUP_ENV_NO_CHDIR)) { - if (chdir(pw->pw_dir) != 0) { - bb_error_msg("can't change directory to '%s'", pw->pw_dir); + if (flags & SETUP_ENV_CHDIR) { + if (chdir_or_warn(pw->pw_dir) != 0) { xchdir((flags & SETUP_ENV_TO_TMP) ? "/tmp" : "/"); } } @@ -54,15 +53,16 @@ xsetenv("TERM", term); xsetenv("PATH", (pw->pw_uid ? bb_default_path : bb_default_root_path)); goto shortcut; - // No, gcc (4.2.1) is not clever enougn to do it itself. + // No, gcc (4.2.1) is not clever enough to do it itself. //xsetenv("USER", pw->pw_name); //xsetenv("LOGNAME", pw->pw_name); //xsetenv("HOME", pw->pw_dir); //xsetenv("SHELL", shell); - } else if (flags & SETUP_ENV_CHANGEENV) { - /* Set HOME, SHELL, and if not becoming a super-user, - * USER and LOGNAME. */ - if (pw->pw_uid) { + } else + if (flags & (SETUP_ENV_CHANGEENV|SETUP_ENV_CHANGEENV_LOGNAME)) { + /* Set HOME, SHELL, and if not becoming a super-user + * or if SETUP_ENV_CHANGEENV_LOGNAME, USER and LOGNAME. */ + if ((flags & SETUP_ENV_CHANGEENV_LOGNAME) || pw->pw_uid != 0) { shortcut: xsetenv("USER", pw->pw_name); xsetenv("LOGNAME", pw->pw_name); diff -Nru busybox-1.35.0/libbb/vfork_daemon_rexec.c busybox-1.36.1/libbb/vfork_daemon_rexec.c --- busybox-1.35.0/libbb/vfork_daemon_rexec.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/libbb/vfork_daemon_rexec.c 2023-01-03 14:14:43.000000000 +0000 @@ -308,7 +308,7 @@ /* fflush_all(); - add it in fork_or_rexec() if necessary */ if (fork_or_rexec(argv)) - _exit(EXIT_SUCCESS); /* parent */ + _exit_SUCCESS(); /* parent */ /* if daemonizing, detach from stdio & ctty */ setsid(); dup2(fd, 0); @@ -320,7 +320,7 @@ // * Prevent this: stop being a session leader. // */ // if (fork_or_rexec(argv)) -// _exit(EXIT_SUCCESS); /* parent */ +// _exit_SUCCESS(); /* parent */ // } } while (fd > 2) { diff -Nru busybox-1.35.0/libbb/xfuncs.c busybox-1.36.1/libbb/xfuncs.c --- busybox-1.35.0/libbb/xfuncs.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/libbb/xfuncs.c 2023-01-03 14:14:43.000000000 +0000 @@ -423,3 +423,13 @@ return WTERMSIG(status) + 0x180; return 0; } + +void FAST_FUNC exit_SUCCESS(void) +{ + exit(EXIT_SUCCESS); +} + +void FAST_FUNC _exit_SUCCESS(void) +{ + _exit(EXIT_SUCCESS); +} diff -Nru busybox-1.35.0/libbb/xfuncs_printf.c busybox-1.36.1/libbb/xfuncs_printf.c --- busybox-1.35.0/libbb/xfuncs_printf.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/libbb/xfuncs_printf.c 2023-01-03 14:14:43.000000000 +0000 @@ -91,13 +91,10 @@ // Die if we can't allocate n+1 bytes (space for the null terminator) and copy // the (possibly truncated to length n) string into it. -char* FAST_FUNC xstrndup(const char *s, int n) +char* FAST_FUNC xstrndup(const char *s, size_t n) { char *t; - if (ENABLE_DEBUG && s == NULL) - bb_simple_error_msg_and_die("xstrndup bug"); - t = strndup(s, n); if (t == NULL) @@ -106,7 +103,7 @@ return t; } -void* FAST_FUNC xmemdup(const void *s, int n) +void* FAST_FUNC xmemdup(const void *s, size_t n) { return memcpy(xmalloc(n), s, n); } @@ -418,11 +415,18 @@ if (seteuid(euid)) bb_simple_perror_msg_and_die("seteuid"); } +int FAST_FUNC chdir_or_warn(const char *path) +{ + int r = chdir(path); + if (r != 0) + bb_perror_msg("can't change directory to '%s'", path); + return r; +} // Die if we can't chdir to a new path. void FAST_FUNC xchdir(const char *path) { - if (chdir(path)) - bb_perror_msg_and_die("can't change directory to '%s'", path); + if (chdir_or_warn(path) != 0) + xfunc_die(); } void FAST_FUNC xfchdir(int fd) diff -Nru busybox-1.35.0/libpwdgrp/pwd_grp.c busybox-1.36.1/libpwdgrp/pwd_grp.c --- busybox-1.35.0/libpwdgrp/pwd_grp.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/libpwdgrp/pwd_grp.c 2023-01-03 14:14:43.000000000 +0000 @@ -191,6 +191,9 @@ char *buf; while ((buf = xmalloc_fgetline(fp)) != NULL) { + int n; + char *field; + /* Skip empty lines, comment lines */ if (buf[0] == '\0' || buf[0] == '#') goto free_and_next; @@ -204,7 +207,16 @@ /* no key specified: sequential read, return a record */ break; } - if (strcmp(key, nth_string(buf, field_pos)) == 0) { + /* Can't use nth_string() here, it does not allow empty strings + * ("\0\0" terminates the list), and a valid passwd entry + * "user::UID:GID..." would be mishandled */ + n = field_pos; + field = buf; + while (n) { + n--; + field += strlen(field) + 1; + } + if (strcmp(key, field) == 0) { /* record found */ break; } diff -Nru busybox-1.35.0/loginutils/getty.c busybox-1.36.1/loginutils/getty.c --- busybox-1.35.0/loginutils/getty.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/loginutils/getty.c 2023-01-03 14:14:43.000000000 +0000 @@ -484,7 +484,7 @@ if (read(STDIN_FILENO, &c, 1) < 1) { finalize_tty_attrs(); if (errno == EINTR || errno == EIO) - exit(EXIT_SUCCESS); + exit_SUCCESS(); bb_simple_perror_msg_and_die(bb_msg_read_error); } @@ -511,7 +511,7 @@ case CTL('C'): case CTL('D'): finalize_tty_attrs(); - exit(EXIT_SUCCESS); + exit_SUCCESS(); case '\0': /* BREAK. If we have speeds to try, * return NULL (will switch speeds and return here) */ @@ -538,7 +538,7 @@ static void alarm_handler(int sig UNUSED_PARAM) { finalize_tty_attrs(); - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } static void sleep10(void) diff -Nru busybox-1.35.0/loginutils/login.c busybox-1.36.1/loginutils/login.c --- busybox-1.35.0/loginutils/login.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/loginutils/login.c 2023-01-03 14:14:43.000000000 +0000 @@ -312,7 +312,7 @@ /* unix API is brain damaged regarding O_NONBLOCK, * we should undo it, or else we can affect other processes */ ndelay_off(STDOUT_FILENO); - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } int login_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -564,7 +564,9 @@ change_identity(pw); setup_environment(pw->pw_shell, - (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + SETUP_ENV_CHANGEENV, + (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + + SETUP_ENV_CHANGEENV + + SETUP_ENV_CHDIR, pw); #if ENABLE_PAM @@ -608,7 +610,9 @@ * But without this, bash 3.0 will not enable ctrl-c either. * Maybe bash is buggy? * Need to find out what standards say about /bin/login - - * should we leave SIGINT etc enabled or disabled? */ + * should we leave SIGINT etc enabled or disabled? + * Also note: sulogin does not do it! Why? + */ signal(SIGINT, SIG_DFL); /* Exec login shell with no additional parameters */ diff -Nru busybox-1.35.0/loginutils/su.c busybox-1.36.1/loginutils/su.c --- busybox-1.35.0/loginutils/su.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/loginutils/su.c 2023-01-03 14:14:43.000000000 +0000 @@ -176,10 +176,9 @@ change_identity(pw); setup_environment(opt_shell, - ((flags & SU_OPT_l) / SU_OPT_l * SETUP_ENV_CLEARENV) - + (!(flags & SU_OPT_mp) * SETUP_ENV_CHANGEENV) - + (!(flags & SU_OPT_l) * SETUP_ENV_NO_CHDIR), - pw); + ((flags & SU_OPT_l) ? (SETUP_ENV_CLEARENV + SETUP_ENV_CHDIR) : 0) + + (!(flags & SU_OPT_mp) * SETUP_ENV_CHANGEENV), + pw); IF_SELINUX(set_current_security_context(NULL);) if (opt_command) { diff -Nru busybox-1.35.0/loginutils/sulogin.c busybox-1.36.1/loginutils/sulogin.c --- busybox-1.35.0/loginutils/sulogin.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/loginutils/sulogin.c 2023-01-03 14:14:43.000000000 +0000 @@ -20,7 +20,8 @@ //usage: "[-t N] [TTY]" //usage:#define sulogin_full_usage "\n\n" //usage: "Single user login\n" -//usage: "\n -t N Timeout" +//usage: "\n -p Start a login shell" +//usage: "\n -t SEC Timeout" #include "libbb.h" #include @@ -28,7 +29,9 @@ int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int sulogin_main(int argc UNUSED_PARAM, char **argv) { + int tsid; int timeout = 0; + unsigned opts; struct passwd *pwd; const char *shell; @@ -43,7 +46,7 @@ logmode = LOGMODE_BOTH; openlog(applet_name, 0, LOG_AUTH); - getopt32(argv, "t:+", &timeout); + opts = getopt32(argv, "pt:+", &timeout); argv += optind; if (argv[0]) { @@ -63,12 +66,13 @@ int r; r = ask_and_check_password_extended(pwd, timeout, - "Give root password for system maintenance\n" - "(or type Control-D for normal startup):" + "Give root password for maintenance\n" + "(or type Ctrl-D to continue): " ); if (r < 0) { /* ^D, ^C, timeout, or read error */ - bb_simple_info_msg("normal startup"); + /* util-linux 2.36.1 compat: no message */ + /*bb_simple_info_msg("normal startup");*/ return 0; } if (r > 0) { @@ -78,7 +82,8 @@ bb_simple_info_msg("Login incorrect"); } - bb_simple_info_msg("starting shell for system maintenance"); + /* util-linux 2.36.1 compat: no message */ + /*bb_simple_info_msg("starting shell for system maintenance");*/ IF_SELINUX(renew_current_security_context()); @@ -88,6 +93,36 @@ if (!shell) shell = pwd->pw_shell; - /* Exec login shell with no additional parameters. Never returns. */ - exec_login_shell(shell); + /* util-linux 2.36.1 compat: cd to root's HOME, set a few envvars */ + setup_environment(shell, 0 + + SETUP_ENV_CHANGEENV_LOGNAME + + SETUP_ENV_CHDIR + , pwd); + // no SETUP_ENV_CLEARENV + // SETUP_ENV_CHANGEENV_LOGNAME - set HOME, SHELL, USER,and LOGNAME + // SETUP_ENV_CHDIR - cd to $HOME + + /* util-linux 2.36.1 compat: steal ctty if we don't have it yet + * (yes, util-linux uses force=1) */ + tsid = tcgetsid(STDIN_FILENO); + if (tsid < 0 || getpid() != tsid) { + if (ioctl(STDIN_FILENO, TIOCSCTTY, /*force:*/ (long)1) != 0) { +// bb_perror_msg("TIOCSCTTY1 tsid:%d", tsid); + if (setsid() > 0) { +// bb_error_msg("done setsid()"); + /* If it still does not work, ignore */ + if (ioctl(STDIN_FILENO, TIOCSCTTY, /*force:*/ (long)1) != 0) { +// bb_perror_msg("TIOCSCTTY2 tsid:%d", tsid); + } + } + } + } + + /* + * Note: login does this (should we do it too?): + */ + /*signal(SIGINT, SIG_DFL);*/ + + /* Exec shell with no additional parameters. Never returns. */ + exec_shell(shell, /* -p? then shell is login:*/(opts & 1), NULL); } diff -Nru busybox-1.35.0/loginutils/vlock.c busybox-1.36.1/loginutils/vlock.c --- busybox-1.35.0/loginutils/vlock.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/loginutils/vlock.c 2023-01-03 14:14:43.000000000 +0000 @@ -128,5 +128,5 @@ ioctl(STDIN_FILENO, VT_SETMODE, &ovtm); #endif tcsetattr_stdin_TCSANOW(&oterm); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/Makefile busybox-1.36.1/Makefile --- busybox-1.35.0/Makefile 2021-12-26 16:55:55.000000000 +0000 +++ busybox-1.36.1/Makefile 2023-05-18 22:31:00.000000000 +0000 @@ -1,6 +1,6 @@ VERSION = 1 -PATCHLEVEL = 35 -SUBLEVEL = 0 +PATCHLEVEL = 36 +SUBLEVEL = 1 EXTRAVERSION = NAME = Unnamed @@ -1301,14 +1301,6 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))) cmd_rmfiles = rm -f $(rm-files) - -a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \ - $(NOSTDINC_FLAGS) $(CPPFLAGS) \ - $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o) - -quiet_cmd_as_o_S = AS $@ -cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< - # read all saved command lines targets := $(wildcard $(sort $(targets))) diff -Nru busybox-1.35.0/Makefile.flags busybox-1.36.1/Makefile.flags --- busybox-1.35.0/Makefile.flags 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/Makefile.flags 2023-01-03 14:14:43.000000000 +0000 @@ -87,14 +87,14 @@ #CFLAGS += $(call cc-option,-Wconversion,) ifneq ($(CONFIG_DEBUG),y) -CFLAGS += $(call cc-option,-Os,$(call cc-option,-O2,)) +CFLAGS += $(call cc-option,-Oz,$(call cc-option,-Os,$(call cc-option,-O2,))) else CFLAGS += $(call cc-option,-g,) #CFLAGS += "-D_FORTIFY_SOURCE=2" ifeq ($(CONFIG_DEBUG_PESSIMIZE),y) CFLAGS += $(call cc-option,-O0,) else -CFLAGS += $(call cc-option,-Os,$(call cc-option,-O2,)) +CFLAGS += $(call cc-option,-Oz,$(call cc-option,-Os,$(call cc-option,-O2,))) endif endif ifeq ($(CONFIG_DEBUG_SANITIZE),y) @@ -187,6 +187,9 @@ ifneq (,$(findstring linux,$(shell $(CC) $(CFLAGS) -dumpmachine))) LDLIBS += resolv endif +ifneq (,$(findstring gnu,$(shell $(CC) $(CFLAGS) -dumpmachine))) +LDLIBS += resolv +endif endif ifeq ($(CONFIG_EFENCE),y) diff -Nru busybox-1.35.0/miscutils/bc.c busybox-1.36.1/miscutils/bc.c --- busybox-1.35.0/miscutils/bc.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/miscutils/bc.c 2023-01-03 14:14:43.000000000 +0000 @@ -2892,6 +2892,8 @@ ) { xc_read_line(&G.input_buffer, G.prs.lex_input_fp); G.prs.lex_inbuf = G.input_buffer.v; + // lex_next_at may point to now-freed data, update it: + G.prs.lex_next_at = G.prs.lex_inbuf; if (G.input_buffer.len <= 1) // on EOF, len is 1 (NUL byte) G.prs.lex_input_fp = NULL; } @@ -3103,7 +3105,7 @@ continue; match: // buf starts with keyword bc_lex_kws[i] - if (isalnum(buf[j]) || buf[j]=='_') + if (isalnum(buf[j]) || buf[j] == '_') continue; // "ifz" does not match "if" keyword, "if." does p->lex = BC_LEX_KEY_1st_keyword + i; if (!keyword_is_POSIX(i)) { @@ -6011,7 +6013,7 @@ #endif if (ib || sc || left->t == XC_RESULT_OBASE) { - static const char *const msg[] = { + static const char *const msg[] ALIGN_PTR = { "bad ibase; must be [2,16]", //XC_RESULT_IBASE "bad obase; must be [2,"BC_MAX_OBASE_STR"]", //XC_RESULT_OBASE "bad scale; must be [0,"BC_MAX_SCALE_STR"]", //XC_RESULT_SCALE diff -Nru busybox-1.35.0/miscutils/crond.c busybox-1.36.1/miscutils/crond.c --- busybox-1.35.0/miscutils/crond.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/crond.c 2023-01-03 14:14:43.000000000 +0000 @@ -125,6 +125,7 @@ char *cl_mailto; /* whom to mail results, may be NULL */ #endif char *cl_shell; + char *cl_path; /* ordered by size, not in natural order. makes code smaller: */ char cl_Dow[7]; /* 0-6, beginning sunday */ char cl_Mons[12]; /* 0-11 */ @@ -421,6 +422,7 @@ char *mailTo = NULL; #endif char *shell = NULL; + char *path = NULL; delete_cronfile(fileName); @@ -470,7 +472,12 @@ shell = xstrdup(&tokens[0][6]); continue; } -//TODO: handle HOME= too? "man crontab" says: + if (is_prefixed_with(tokens[0], "PATH=")) { + free(path); + path = xstrdup(&tokens[0][5]); + continue; + } +//TODO: handle HOME= too? Better yet, handle arbitrary ENVVARs? "man crontab" says: //name = value // //where the spaces around the equal-sign (=) are optional, and any subsequent @@ -480,8 +487,8 @@ // //Several environment variables are set up automatically by the cron(8) daemon. //SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd -//line of the crontab's owner. HOME and SHELL may be overridden by settings -//in the crontab; LOGNAME may not. +//line of the crontab's owner. HOME, SHELL, and PATH may be overridden by +//settings in the crontab; LOGNAME may not. #if ENABLE_FEATURE_CROND_SPECIAL_TIMES if (tokens[0][0] == '@') { @@ -567,6 +574,7 @@ line->cl_mailto = xstrdup(mailTo); #endif line->cl_shell = xstrdup(shell); + line->cl_path = xstrdup(path); /* copy command */ line->cl_cmd = xstrdup(tokens[5]); pline = &line->cl_next; @@ -653,21 +661,22 @@ } #endif -static void set_env_vars(struct passwd *pas, const char *shell) +static void set_env_vars(struct passwd *pas, const char *shell, const char *path) { /* POSIX requires crond to set up at least HOME, LOGNAME, PATH, SHELL. - * We assume crond inherited suitable PATH. */ #if SETENV_LEAKS safe_setenv(&G.env_var_logname, "LOGNAME", pas->pw_name); safe_setenv(&G.env_var_user, "USER", pas->pw_name); safe_setenv(&G.env_var_home, "HOME", pas->pw_dir); safe_setenv(&G.env_var_shell, "SHELL", shell); + if (path) safe_setenv(&G.env_var_shell, "PATH", path); #else xsetenv("LOGNAME", pas->pw_name); xsetenv("USER", pas->pw_name); xsetenv("HOME", pas->pw_dir); xsetenv("SHELL", shell); + if (path) xsetenv("PATH", path); #endif } @@ -675,8 +684,7 @@ { /* careful: we're after vfork! */ change_identity(pas); /* - initgroups, setgid, setuid */ - if (chdir(pas->pw_dir) < 0) { - bb_error_msg("can't change directory to '%s'", pas->pw_dir); + if (chdir_or_warn(pas->pw_dir) != 0) { xchdir(CRON_DIR); } } @@ -702,7 +710,7 @@ shell = line->cl_shell ? line->cl_shell : G.default_shell; prog = run_sendmail ? SENDMAIL : shell; - set_env_vars(pas, shell); + set_env_vars(pas, shell, NULL); /* don't use crontab's PATH for sendmail */ sv_logmode = logmode; pid = vfork(); @@ -846,7 +854,7 @@ /* Prepare things before vfork */ shell = line->cl_shell ? line->cl_shell : G.default_shell; - set_env_vars(pas, shell); + set_env_vars(pas, shell, line->cl_path); /* Fork as the user in question and run program */ pid = vfork(); diff -Nru busybox-1.35.0/miscutils/crontab.c busybox-1.36.1/miscutils/crontab.c --- busybox-1.35.0/miscutils/crontab.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/crontab.c 2023-01-03 14:14:43.000000000 +0000 @@ -55,8 +55,8 @@ /* initgroups, setgid, setuid */ change_identity(pas); setup_environment(pas->pw_shell, - SETUP_ENV_CHANGEENV | SETUP_ENV_TO_TMP, - pas); + SETUP_ENV_CHANGEENV | SETUP_ENV_TO_TMP | SETUP_ENV_CHDIR, + pas); ptr = getenv("VISUAL"); if (!ptr) { ptr = getenv("EDITOR"); diff -Nru busybox-1.35.0/miscutils/devfsd.c busybox-1.36.1/miscutils/devfsd.c --- busybox-1.35.0/miscutils/devfsd.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/devfsd.c 2023-01-03 14:14:43.000000000 +0000 @@ -453,7 +453,7 @@ DEVFSD_PROTOCOL_REVISION_DAEMON, bb_msg_proto_rev, proto_rev); if (DEVFSD_PROTOCOL_REVISION_DAEMON != proto_rev) bb_error_msg_and_die("%s mismatch!", bb_msg_proto_rev); - exit(EXIT_SUCCESS); /* -v */ + exit_SUCCESS(); /* -v */ } /* Tell kernel we are special(i.e. we get to see hidden entries) */ xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, 0); @@ -474,7 +474,7 @@ dir_operation(SERVICE, mount_point, 0, NULL); if (ENABLE_DEVFSD_FG_NP && no_polling) - exit(EXIT_SUCCESS); + exit_SUCCESS(); if (ENABLE_DEVFSD_VERBOSE || ENABLE_DEBUG) logmode = LOGMODE_BOTH; @@ -928,7 +928,7 @@ unsigned int i; char rewind_; /* 1 to 5 "scsi/" , 6 to 9 "ide/host" */ - static const char *const fmt[] = { + static const char *const fmt[] ALIGN_PTR = { NULL , "sg/c%db%dt%du%d", /* scsi/generic */ "sd/c%db%dt%du%d", /* scsi/disc */ @@ -976,7 +976,7 @@ rewind_ = info->devname[info->namelen - 1]; if (rewind_ != 'n') rewind_ = '\0'; - mode=0; + mode = 0; if (ptr[2] == 'l' /*108*/ || ptr[2] == 'm'/*109*/) mode = ptr[2] - 107; /* 1 or 2 */ if (ptr[2] == 'a') @@ -1468,7 +1468,7 @@ const char *pty1; const char *pty2; /* 1 to 5 "scsi/" , 6 to 9 "ide/host", 10 sbp/, 11 vcc/, 12 pty/ */ - static const char *const fmt[] = { + static const char *const fmt[] ALIGN_PTR = { NULL , "sg%u", /* scsi/generic */ NULL, /* scsi/disc */ @@ -1595,11 +1595,11 @@ return buffer; } if ((major > 64) && (major < 72)) { - disc_index = ((major - 64) << 4) +(minor >> 4); + disc_index = ((major - 64) << 4) + (minor >> 4); if (disc_index < 26) sprintf(buffer, "sd%c%s", 'a' + disc_index, part); else - sprintf(buffer, "sd%c%c%s", 'a' +(disc_index / 26) - 1, 'a' + disc_index % 26, part); + sprintf(buffer, "sd%c%c%s", 'a' + (disc_index / 26) - 1, 'a' + disc_index % 26, part); return buffer; } return NULL; diff -Nru busybox-1.35.0/miscutils/devmem.c busybox-1.36.1/miscutils/devmem.c --- busybox-1.35.0/miscutils/devmem.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/devmem.c 2023-01-03 14:14:43.000000000 +0000 @@ -29,7 +29,6 @@ { void *map_base, *virt_addr; uint64_t read_result; - uint64_t writeval = writeval; /* for compiler */ off_t target; unsigned page_size, mapped_size, offset_in_page; int fd; @@ -64,9 +63,6 @@ width = strchrnul(bhwl, (argv[2][0] | 0x20)) - bhwl; width = sizes[width]; } - /* VALUE */ - if (argv[3]) - writeval = bb_strtoull(argv[3], NULL, 0); } else { /* argv[2] == NULL */ /* make argv[3] to be a valid thing to fetch */ argv--; @@ -96,28 +92,46 @@ virt_addr = (char*)map_base + offset_in_page; if (!argv[3]) { - switch (width) { - case 8: - read_result = *(volatile uint8_t*)virt_addr; - break; - case 16: - read_result = *(volatile uint16_t*)virt_addr; - break; - case 32: - read_result = *(volatile uint32_t*)virt_addr; - break; - case 64: - read_result = *(volatile uint64_t*)virt_addr; - break; - default: - bb_simple_error_msg_and_die("bad width"); +#ifdef __SIZEOF_INT128__ + if (width == 128) { + unsigned __int128 rd = + *(volatile unsigned __int128 *)virt_addr; + printf("0x%016llX%016llX\n", + (unsigned long long)(uint64_t)(rd >> 64), + (unsigned long long)(uint64_t)rd + ); + } else +#endif + { + switch (width) { + case 8: + read_result = *(volatile uint8_t*)virt_addr; + break; + case 16: + read_result = *(volatile uint16_t*)virt_addr; + break; + case 32: + read_result = *(volatile uint32_t*)virt_addr; + break; + case 64: + read_result = *(volatile uint64_t*)virt_addr; + break; + default: + bb_simple_error_msg_and_die("bad width"); + } +// printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n", +// target, virt_addr, +// (unsigned long long)read_result); + /* Zero-padded output shows the width of access just done */ + printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result); } -// printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n", -// target, virt_addr, -// (unsigned long long)read_result); - /* Zero-padded output shows the width of access just done */ - printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result); } else { + /* parse VALUE */ +#ifdef __SIZEOF_INT128__ + unsigned __int128 writeval = strtoumax(argv[3], NULL, 0); +#else + uint64_t writeval = bb_strtoull(argv[3], NULL, 0); +#endif switch (width) { case 8: *(volatile uint8_t*)virt_addr = writeval; @@ -135,6 +149,12 @@ *(volatile uint64_t*)virt_addr = writeval; // read_result = *(volatile uint64_t*)virt_addr; break; +#ifdef __SIZEOF_INT128__ + case 128: + *(volatile unsigned __int128 *)virt_addr = writeval; +// read_result = *(volatile uint64_t*)virt_addr; + break; +#endif default: bb_simple_error_msg_and_die("bad width"); } diff -Nru busybox-1.35.0/miscutils/hdparm.c busybox-1.36.1/miscutils/hdparm.c --- busybox-1.35.0/miscutils/hdparm.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/hdparm.c 2023-01-03 14:14:43.000000000 +0000 @@ -798,7 +798,7 @@ if (!(val[GEN_CONFIG] & NOT_ATA)) { dev = ATA_DEV; printf("ATA device, with "); - } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) { + } else if (val[GEN_CONFIG] == CFA_SUPPORT_VAL) { dev = ATA_DEV; like_std = 4; printf("CompactFlash ATA device, with "); @@ -819,13 +819,13 @@ * specific, it should be safe to check it now, even though we don't * know yet what standard this device is using. */ - if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) - || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) + if ((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == STBY_ID_VAL) + || (val[CONFIG] == PWRD_NID_VAL) || (val[CONFIG] == PWRD_ID_VAL) ) { like_std = 5; - if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)) + if ((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == STBY_ID_VAL)) puts("powers-up in standby; SET FEATURES subcmd spins-up."); - if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE)) + if (((val[CONFIG] == STBY_NID_VAL) || (val[CONFIG] == PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE)) puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n"); } @@ -853,7 +853,7 @@ printf("\n\tSupported: "); jj = val[MAJOR] << 1; kk = like_std >4 ? like_std-4: 0; - for (ii = 14; (ii >0)&&(ii>kk); ii--) { + for (ii = 14; (ii > 0) && (ii > kk); ii--) { if (jj & 0x8000) { printf("%u ", ii); if (like_std < ii) { @@ -943,7 +943,7 @@ for (ii = 1; ii < 15; ii++) { if (jj & 0x0001) printf("\t%s\n", nth_string(ata1_cfg_str, ii)); - jj >>=1; + jj >>= 1; } } if (dev == ATAPI_DEV) { @@ -952,7 +952,7 @@ else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL) strng = "<=10ms with INTRQ"; else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL) - strng ="50us"; + strng = "50us"; else strng = "unknown"; printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ @@ -1014,7 +1014,7 @@ } if (!bbbig) - bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */ + bbbig = (uint64_t)(ll > mm ? ll : mm); /* # 512 byte blocks */ printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11); bbbig = (bbbig << 9) / 1000000; printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig); @@ -1160,7 +1160,7 @@ jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; for (ii = 0; ii <= PIO_MODE_MAX; ii++) { if (jj & 0x0001) printf("pio%d ", ii); - jj >>=1; + jj >>= 1; } bb_putchar('\n'); } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) { @@ -1199,7 +1199,7 @@ } if (ii == 31) { if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL) - ii +=16; + ii += 16; } } } @@ -1220,7 +1220,7 @@ printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "", nth_string(secu_str, ii)); - jj >>=1; + jj >>= 1; } if (val[SECU_STATUS] & SECU_ENABLED) { printf("\tSecurity level %s\n", @@ -1271,7 +1271,7 @@ } } - exit(EXIT_SUCCESS); + exit_SUCCESS(); } #endif diff -Nru busybox-1.35.0/miscutils/hexedit.c busybox-1.36.1/miscutils/hexedit.c --- busybox-1.35.0/miscutils/hexedit.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/hexedit.c 2023-01-03 14:14:43.000000000 +0000 @@ -292,7 +292,7 @@ fflush_all(); G.in_read_key = 1; if (!bb_got_signal) - key = read_key(STDIN_FILENO, G.read_key_buffer, -1); + key = safe_read_key(STDIN_FILENO, G.read_key_buffer, -1); G.in_read_key = 0; if (bb_got_signal) key = CTRL('X'); diff -Nru busybox-1.35.0/miscutils/i2c_tools.c busybox-1.36.1/miscutils/i2c_tools.c --- busybox-1.35.0/miscutils/i2c_tools.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/i2c_tools.c 2023-01-03 14:14:43.000000000 +0000 @@ -120,6 +120,7 @@ return ioctl(fd, I2C_SMBUS, &args); } +#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CDETECT static int32_t i2c_smbus_read_byte(int fd) { union i2c_smbus_data data; @@ -131,6 +132,7 @@ return data.byte; } +#endif #if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP static int32_t i2c_smbus_write_byte(int fd, uint8_t val) @@ -1212,7 +1214,7 @@ } } - exit(EXIT_SUCCESS); + exit_SUCCESS(); } static void NORETURN no_support(const char *cmd) diff -Nru busybox-1.35.0/miscutils/less.c busybox-1.36.1/miscutils/less.c --- busybox-1.35.0/miscutils/less.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/less.c 2023-01-03 14:14:43.000000000 +0000 @@ -325,15 +325,18 @@ } /* Exit the program gracefully */ -static void less_exit(int code) +static void restore_tty(void) { set_tty_cooked(); if (!(G.kbd_fd_orig_flags & O_NONBLOCK)) ndelay_off(kbd_fd); clear_line(); - if (code < 0) - kill_myself_with_sig(- code); /* does not return */ - exit(code); +} + +static NOINLINE void less_exit(void) +{ + restore_tty(); + exit_SUCCESS(); } #if (ENABLE_FEATURE_LESS_DASHCMD && ENABLE_FEATURE_LESS_LINENUMS) \ @@ -913,7 +916,7 @@ ) { i = option_mask32 & FLAG_F ? 0 : cur_fline; if (max_fline - i <= max_displayed_line) - less_exit(EXIT_SUCCESS); + less_exit(); } status_print(); } @@ -1134,9 +1137,9 @@ #endif } - /* We have kbd_fd in O_NONBLOCK mode, read inside read_key() + /* We have kbd_fd in O_NONBLOCK mode, read inside safe_read_key() * would not block even if there is no input available */ - key64 = read_key(kbd_fd, kbd_input, /*timeout off:*/ -2); + key64 = safe_read_key(kbd_fd, kbd_input, /*timeout off:*/ -2); if ((int)key64 == -1) { if (errno == EAGAIN) { /* No keyboard input available. Since poll() did return, @@ -1146,7 +1149,7 @@ goto again; } /* EOF/error (ssh session got killed etc) */ - less_exit(EXIT_SUCCESS); + less_exit(); } set_tty_cooked(); return key64; @@ -1297,7 +1300,7 @@ change_file(-1); break; case 'q': - less_exit(EXIT_SUCCESS); + less_exit(); break; case 'x': change_file(0); @@ -1715,7 +1718,7 @@ buffer_line(cur_fline); break; case 'q': case 'Q': - less_exit(EXIT_SUCCESS); + less_exit(); break; #if ENABLE_FEATURE_LESS_MARKS case 'm': @@ -1793,7 +1796,8 @@ static void sig_catcher(int sig) { - less_exit(- sig); + restore_tty(); + kill_myself_with_sig(sig); /* does not return */ } #if ENABLE_FEATURE_LESS_WINCH diff -Nru busybox-1.35.0/miscutils/man.c busybox-1.36.1/miscutils/man.c --- busybox-1.35.0/miscutils/man.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/man.c 2023-01-03 14:14:43.000000000 +0000 @@ -303,7 +303,7 @@ config_close(parser); if (!man_path_list) { - static const char *const mpl[] = { "/usr/man", "/usr/share/man", NULL }; + static const char *const mpl[] ALIGN_PTR = { "/usr/man", "/usr/share/man", NULL }; man_path_list = (char**)mpl; /*count_mp = 2; - not used below anyway */ } diff -Nru busybox-1.35.0/miscutils/seedrng.c busybox-1.36.1/miscutils/seedrng.c --- busybox-1.35.0/miscutils/seedrng.c 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/miscutils/seedrng.c 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Copyright (C) 2022 Jason A. Donenfeld . All Rights Reserved. + * + * SeedRNG is a simple program made for seeding the Linux kernel random number + * generator from seed files. It is is useful in light of the fact that the + * Linux kernel RNG cannot be initialized from shell scripts, and new seeds + * cannot be safely generated from boot time shell scripts either. It should + * be run once at init time and once at shutdown time. It can be run at other + * times on a timer as well. Whenever it is run, it writes existing seed files + * into the RNG pool, and then creates a new seed file. If the RNG is + * initialized at the time of creating a new seed file, then that new seed file + * is marked as "creditable", which means it can be used to initialize the RNG. + * Otherwise, it is marked as "non-creditable", in which case it is still used + * to seed the RNG's pool, but will not initialize the RNG. In order to ensure + * that entropy only ever stays the same or increases from one seed file to the + * next, old seed values are hashed together with new seed values when writing + * new seed files. + * + * This is based on code from . + */ +//config:config SEEDRNG +//config: bool "seedrng (1.3 kb)" +//config: default y +//config: help +//config: Seed the kernel RNG from seed files, meant to be called +//config: once during startup, once during shutdown, and optionally +//config: at some periodic interval in between. + +//applet:IF_SEEDRNG(APPLET(seedrng, BB_DIR_USR_SBIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_SEEDRNG) += seedrng.o + +//usage:#define seedrng_trivial_usage +//usage: "[-d DIR] [-n]" +//usage:#define seedrng_full_usage "\n\n" +//usage: "Seed the kernel RNG from seed files" +//usage: "\n" +//usage: "\n -d DIR Use seed files in DIR (default: /var/lib/seedrng)" +//usage: "\n -n Do not credit randomness, even if creditable" + +#include "libbb.h" + +#include +#include +#include + +#ifndef GRND_INSECURE +#define GRND_INSECURE 0x0004 /* Apparently some headers don't ship with this yet. */ +#endif + +#define DEFAULT_SEED_DIR "/var/lib/seedrng" +#define CREDITABLE_SEED_NAME "seed.credit" +#define NON_CREDITABLE_SEED_NAME "seed.no-credit" + +enum { + MIN_SEED_LEN = SHA256_OUTSIZE, + /* kernels < 5.18 could return short reads from getrandom() + * if signal is pending and length is > 256. + * Let's limit our reads to 256 bytes. + */ + MAX_SEED_LEN = 256, +}; + +static size_t determine_optimal_seed_len(void) +{ + char poolsize_str[12]; + unsigned poolsize; + int n; + + n = open_read_close("/proc/sys/kernel/random/poolsize", poolsize_str, sizeof(poolsize_str) - 1); + if (n < 0) { + bb_perror_msg("can't determine pool size, assuming %u bits", MIN_SEED_LEN * 8); + return MIN_SEED_LEN; + } + poolsize_str[n] = '\0'; + poolsize = (bb_strtou(poolsize_str, NULL, 10) + 7) / 8; + return MAX(MIN(poolsize, MAX_SEED_LEN), MIN_SEED_LEN); +} + +static bool read_new_seed(uint8_t *seed, size_t len) +{ + bool is_creditable; + ssize_t ret; + + ret = getrandom(seed, len, GRND_NONBLOCK); + if (ret == (ssize_t)len) { + return true; + } + if (ret < 0 && errno == ENOSYS) { + int fd = xopen("/dev/random", O_RDONLY); + struct pollfd random_fd; + random_fd.fd = fd; + random_fd.events = POLLIN; + is_creditable = poll(&random_fd, 1, 0) == 1; +//This is racy. is_creditable can be set to true here, but other process +//can consume "good" random data from /dev/urandom before we do it below. + close(fd); + } else { + if (getrandom(seed, len, GRND_INSECURE) == (ssize_t)len) + return false; + is_creditable = false; + } + + /* Either getrandom() is not implemented, or + * getrandom(GRND_INSECURE) did not give us LEN bytes. + * Fallback to reading /dev/urandom. + */ + errno = 0; + if (open_read_close("/dev/urandom", seed, len) != (ssize_t)len) + bb_perror_msg_and_die("can't read '%s'", "/dev/urandom"); + return is_creditable; +} + +static void seed_from_file_if_exists(const char *filename, int dfd, bool credit, sha256_ctx_t *hash) +{ + struct { + int entropy_count; + int buf_size; + uint8_t buf[MAX_SEED_LEN]; + } req; + ssize_t seed_len; + + seed_len = open_read_close(filename, req.buf, sizeof(req.buf)); + if (seed_len < 0) { + if (errno != ENOENT) + bb_perror_msg_and_die("can't read '%s'", filename); + return; + } + xunlink(filename); + if (seed_len != 0) { + int fd; + + /* We are going to use this data to seed the RNG: + * we believe it to genuinely containing entropy. + * If this just-unlinked file survives + * (if machine crashes before deletion is recorded on disk) + * and we reuse it after reboot, this assumption + * would be violated, and RNG may end up generating + * the same data. fsync the directory + * to make sure file is gone: + */ + if (fsync(dfd) != 0) + bb_simple_perror_msg_and_die("I/O error"); + +//Length is not random, and taking its address spills variable to stack +// sha256_hash(hash, &seed_len, sizeof(seed_len)); + sha256_hash(hash, req.buf, seed_len); + + req.buf_size = seed_len; + seed_len *= 8; + req.entropy_count = credit ? seed_len : 0; + printf("Seeding %u bits %s crediting\n", + (unsigned)seed_len, credit ? "and" : "without"); + fd = xopen("/dev/urandom", O_RDONLY); + xioctl(fd, RNDADDENTROPY, &req); + if (ENABLE_FEATURE_CLEAN_UP) + close(fd); + } +} + +int seedrng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int seedrng_main(int argc UNUSED_PARAM, char **argv) +{ + const char *seed_dir; + int fd, dfd; + int i; + unsigned opts; + uint8_t new_seed[MAX_SEED_LEN]; + size_t new_seed_len; + bool new_seed_creditable; + struct timespec timestamp[2]; + sha256_ctx_t hash; + + enum { + OPT_n = (1 << 0), /* must be 1 */ + OPT_d = (1 << 1), + }; +#if ENABLE_LONG_OPTS + static const char longopts[] ALIGN1 = + "skip-credit\0" No_argument "n" + "seed-dir\0" Required_argument "d" + ; +#endif + + seed_dir = DEFAULT_SEED_DIR; + opts = getopt32long(argv, "nd:", longopts, &seed_dir); + umask(0077); + if (getuid() != 0) + bb_simple_error_msg_and_die(bb_msg_you_must_be_root); + + if (mkdir(seed_dir, 0700) < 0 && errno != EEXIST) + bb_perror_msg_and_die("can't create directory '%s'", seed_dir); + dfd = xopen(seed_dir, O_DIRECTORY | O_RDONLY); + xfchdir(dfd); + /* Concurrent runs of this tool might feed the same data to RNG twice. + * Avoid concurrent runs by taking a blocking lock on the directory. + * Not checking for errors. Looking at manpage, + * ENOLCK "The kernel ran out of memory for allocating lock records" + * seems to be the only one which is possible - and if that happens, + * machine is OOMing (much worse problem than inability to lock...). + * Also, typically configured Linux machines do not fail GFP_KERNEL + * allocations (they trigger memory reclaim instead). + */ + flock(dfd, LOCK_EX); /* blocks while another instance runs */ + + sha256_begin(&hash); +//Hashing in a constant string doesn't add any entropy +// sha256_hash(&hash, "SeedRNG v1 Old+New Prefix", 25); + clock_gettime(CLOCK_REALTIME, ×tamp[0]); + clock_gettime(CLOCK_BOOTTIME, ×tamp[1]); + sha256_hash(&hash, timestamp, sizeof(timestamp)); + + for (i = 0; i <= 1; i++) { + seed_from_file_if_exists( + i == 0 ? NON_CREDITABLE_SEED_NAME : CREDITABLE_SEED_NAME, + dfd, + /*credit?*/ (opts ^ OPT_n) & i, /* 0, then 1 unless -n */ + &hash); + } + + new_seed_len = determine_optimal_seed_len(); + new_seed_creditable = read_new_seed(new_seed, new_seed_len); +//Length is not random, and taking its address spills variable to stack +// sha256_hash(&hash, &new_seed_len, sizeof(new_seed_len)); + sha256_hash(&hash, new_seed, new_seed_len); + sha256_end(&hash, new_seed + new_seed_len - SHA256_OUTSIZE); + + printf("Saving %u bits of %screditable seed for next boot\n", + (unsigned)new_seed_len * 8, new_seed_creditable ? "" : "non-"); + fd = xopen3(NON_CREDITABLE_SEED_NAME, O_WRONLY | O_CREAT | O_TRUNC, 0400); + xwrite(fd, new_seed, new_seed_len); + if (new_seed_creditable) { + /* More paranoia when we create a file which we believe contains + * genuine entropy: make sure disk is not full, quota isn't exceeded, etc: + */ + if (fsync(fd) < 0) + bb_perror_msg_and_die("can't write '%s'", NON_CREDITABLE_SEED_NAME); + xrename(NON_CREDITABLE_SEED_NAME, CREDITABLE_SEED_NAME); + } + return EXIT_SUCCESS; +} diff -Nru busybox-1.35.0/miscutils/tree.c busybox-1.36.1/miscutils/tree.c --- busybox-1.35.0/miscutils/tree.c 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/miscutils/tree.c 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,131 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2022 Roger Knecht + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//config:config TREE +//config: bool "tree (0.6 kb)" +//config: default y +//config: help +//config: List files and directories in a tree structure. + +//applet:IF_TREE(APPLET(tree, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_TREE) += tree.o + +//usage:#define tree_trivial_usage NOUSAGE_STR +//usage:#define tree_full_usage "" + +#include "libbb.h" +#include "common_bufsiz.h" +#include "unicode.h" + +#define prefix_buf bb_common_bufsiz1 + +static void tree_print(unsigned count[2], const char* directory_name, char* prefix_pos) +{ + struct dirent **entries; + int index, size; + const char *bar = "| "; + const char *mid = "|-- "; + const char *end = "`-- "; + +#if ENABLE_UNICODE_SUPPORT + if (unicode_status == UNICODE_ON) { + bar = "│ "; + mid = "├── "; + end = "└── "; + } +#endif + + // read directory entries + size = scandir(directory_name, &entries, NULL, alphasort); + + if (size < 0) { + fputs_stdout(directory_name); + puts(" [error opening dir]"); + return; + } + + // print directory name + puts(directory_name); + + // switch to sub directory + xchdir(directory_name); + + // print all directory entries + for (index = 0; index < size;) { + struct dirent *dirent = entries[index++]; + + // filter hidden files and directories + if (dirent->d_name[0] != '.') { + int status; + struct stat statBuf; + +//TODO: when -l is implemented, use stat, not lstat, if -l + status = lstat(dirent->d_name, &statBuf); + + if (index == size) { + strcpy(prefix_pos, end); + } else { + strcpy(prefix_pos, mid); + } + fputs_stdout(prefix_buf); + + if (status == 0 && S_ISLNK(statBuf.st_mode)) { + // handle symlink + char* symlink_path = xmalloc_readlink(dirent->d_name); + printf("%s -> %s\n", dirent->d_name, symlink_path); + free(symlink_path); + count[1]++; + } else if (status == 0 && S_ISDIR(statBuf.st_mode) + && (prefix_pos - prefix_buf) < (COMMON_BUFSIZE - 16) + ) { + // handle directory + char* pos; + if (index == size) { + pos = stpcpy(prefix_pos, " "); + } else { + pos = stpcpy(prefix_pos, bar); + } + tree_print(count, dirent->d_name, pos); + count[0]++; + } else { + // handle file + puts(dirent->d_name); + count[1]++; + } + } + + // release directory entry + free(dirent); + } + + // release directory array + free(entries); + + // switch to parent directory + xchdir(".."); +} + +int tree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int tree_main(int argc UNUSED_PARAM, char **argv) +{ + unsigned count[2] = { 0, 0 }; + + setup_common_bufsiz(); + init_unicode(); + + if (!argv[1]) + *argv-- = (char*)"."; + + // list directories given as command line arguments + while (*(++argv)) + tree_print(count, *argv, prefix_buf); + + // print statistic + printf("\n%u directories, %u files\n", count[0], count[1]); + + return EXIT_SUCCESS; +} diff -Nru busybox-1.35.0/miscutils/watchdog.c busybox-1.36.1/miscutils/watchdog.c --- busybox-1.35.0/miscutils/watchdog.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/miscutils/watchdog.c 2023-01-03 14:14:43.000000000 +0000 @@ -76,7 +76,7 @@ { remove_pidfile_std_path_and_ext("watchdog"); shutdown_watchdog(); - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } static void watchdog_open(const char* device) diff -Nru busybox-1.35.0/modutils/modprobe-small.c busybox-1.36.1/modutils/modprobe-small.c --- busybox-1.35.0/modutils/modprobe-small.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/modutils/modprobe-small.c 2023-01-03 14:14:43.000000000 +0000 @@ -415,7 +415,7 @@ /* Load was successful, there is nothing else to do. * This can happen ONLY for "top-level" module load, * not a dep, because deps don't do dirscan. */ - exit(EXIT_SUCCESS); + exit_SUCCESS(); } } diff -Nru busybox-1.35.0/modutils/modutils-24.c busybox-1.36.1/modutils/modutils-24.c --- busybox-1.35.0/modutils/modutils-24.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/modutils/modutils-24.c 2023-01-03 14:14:43.000000000 +0000 @@ -981,7 +981,7 @@ (loc[1] & 0xFFFF); /* Add reloc offset */ - temp1+=v; + temp1 += v; /* Store back into code */ loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16; @@ -3458,7 +3458,7 @@ static void hide_special_symbols(struct obj_file *f) { - static const char *const specials[] = { + static const char *const specials[] ALIGN_PTR = { SPFX "cleanup_module", SPFX "init_module", SPFX "kernel_version", @@ -3484,7 +3484,7 @@ * linux/include/linux/module.h. Checking for leading "GPL" will not * work, somebody will use "GPL sucks, this is proprietary". */ - static const char *const gpl_licenses[] = { + static const char *const gpl_licenses[] ALIGN_PTR = { "GPL", "GPL v2", "GPL and additional rights", diff -Nru busybox-1.35.0/networking/arping.c busybox-1.36.1/networking/arping.c --- busybox-1.35.0/networking/arping.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/arping.c 2023-01-03 14:14:43.000000000 +0000 @@ -159,7 +159,7 @@ if (option_mask32 & DAD) exit(!!received); if (option_mask32 & UNSOLICITED) - exit(EXIT_SUCCESS); + exit_SUCCESS(); exit(!received); } diff -Nru busybox-1.35.0/networking/httpd.c busybox-1.36.1/networking/httpd.c --- busybox-1.35.0/networking/httpd.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/networking/httpd.c 2023-01-03 14:14:43.000000000 +0000 @@ -1667,8 +1667,7 @@ script = last_slash; if (script != url) { /* paranoia */ *script = '\0'; - if (chdir(url + 1) != 0) { - bb_perror_msg("can't change directory to '%s'", url + 1); + if (chdir_or_warn(url + 1) != 0) { goto error_execing_cgi; } // not needed: *script = '/'; diff -Nru busybox-1.35.0/networking/httpd_indexcgi.c busybox-1.36.1/networking/httpd_indexcgi.c --- busybox-1.35.0/networking/httpd_indexcgi.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/httpd_indexcgi.c 2023-01-03 14:14:43.000000000 +0000 @@ -211,7 +211,7 @@ fmt_02u(n % 100); } -int main(int argc, char *argv[]) +int main(int argc, char **argv) { dir_list_t *dir_list; dir_list_t *cdir; diff -Nru busybox-1.35.0/networking/httpd_ssi.c busybox-1.36.1/networking/httpd_ssi.c --- busybox-1.35.0/networking/httpd_ssi.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/httpd_ssi.c 2023-01-03 14:14:43.000000000 +0000 @@ -143,7 +143,7 @@ fclose(fp); } -int main(int argc, char *argv[]) +int main(int argc, char **argv) { if (!argv[1]) return 1; diff -Nru busybox-1.35.0/networking/ifplugd.c busybox-1.36.1/networking/ifplugd.c --- busybox-1.35.0/networking/ifplugd.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/networking/ifplugd.c 2023-01-03 14:14:43.000000000 +0000 @@ -28,6 +28,7 @@ //usage: "\n -a Don't up interface at each link probe" //usage: "\n -M Monitor creation/destruction of interface" //usage: "\n (otherwise it must exist)" +//usage: "\n -A Don't up newly appeared interface" //usage: "\n -r PROG Script to run" //usage: "\n -x ARG Extra argument for script" //usage: "\n -I Don't exit on nonzero exit code from script" @@ -94,7 +95,7 @@ #define IFPLUGD_ENV_CURRENT "IFPLUGD_CURRENT" enum { - FLAG_NO_AUTO = 1 << 0, // -a, Do not enable interface automatically + FLAG_NO_AUTO = 1 << 0, // -a, Don't up interface at each link probe FLAG_NO_DAEMON = 1 << 1, // -n, Do not daemonize FLAG_NO_SYSLOG = 1 << 2, // -s, Do not use syslog, use stderr instead FLAG_IGNORE_FAIL = 1 << 3, // -f, Ignore detection failure, retry instead (failure is treated as DOWN) @@ -111,14 +112,15 @@ FLAG_INITIAL_DOWN = 1 << 14, // -l, Run "down" script on startup if no cable is detected FLAG_EXTRA_ARG = 1 << 15, // -x, Specify an extra argument for action script FLAG_MONITOR = 1 << 16, // -M, Use interface monitoring + FLAG_NO_UP_NEW_IFACE = 1 << 17, // -A, Don't up newly appeared interface #if ENABLE_FEATURE_PIDFILE - FLAG_KILL = 1 << 17, // -k, Kill a running daemon + FLAG_KILL = 1 << 18, // -k, Kill a running daemon #endif }; #if ENABLE_FEATURE_PIDFILE -# define OPTION_STR "+ansfFi:r:It:+u:+d:+m:pqlx:Mk" +# define OPTION_STR "+ansfFi:r:It:+u:+d:+m:pqlx:MAk" #else -# define OPTION_STR "+ansfFi:r:It:+u:+d:+m:pqlx:M" +# define OPTION_STR "+ansfFi:r:It:+u:+d:+m:pqlx:MA" #endif enum { // interface status @@ -387,7 +389,7 @@ static void maybe_up_new_iface(void) { - if (!(option_mask32 & FLAG_NO_AUTO)) + if (!(option_mask32 & FLAG_NO_UP_NEW_IFACE)) up_iface(); #if 0 /* bloat */ diff -Nru busybox-1.35.0/networking/ifupdown.c busybox-1.36.1/networking/ifupdown.c --- busybox-1.35.0/networking/ifupdown.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/ifupdown.c 2023-01-03 14:14:43.000000000 +0000 @@ -532,7 +532,7 @@ } # endif -static const struct method_t methods6[] = { +static const struct method_t methods6[] ALIGN_PTR = { # if ENABLE_FEATURE_IFUPDOWN_IP { "v4tunnel" , v4tunnel_up , v4tunnel_down , }, # endif @@ -627,7 +627,7 @@ const char *stopcmd; }; -static const struct dhcp_client_t ext_dhcp_clients[] = { +static const struct dhcp_client_t ext_dhcp_clients[] ALIGN_PTR = { { "dhcpcd", "dhcpcd[[ -h %hostname%]][[ -i %vendor%]][[ -I %client%]][[ -l %leasetime%]] %iface%", "dhcpcd -k %iface%", @@ -774,7 +774,7 @@ "-p /var/run/wvdial.%iface% -s 2", ifd, exec); } -static const struct method_t methods[] = { +static const struct method_t methods[] ALIGN_PTR = { { "manual" , manual_up_down, manual_up_down, }, { "wvdial" , wvdial_up , wvdial_down , }, { "ppp" , ppp_up , ppp_down , }, @@ -797,7 +797,7 @@ return 1; } -static const struct method_t link_methods[] = { +static const struct method_t link_methods[] ALIGN_PTR = { { "none", link_up_down, link_up_down } }; diff -Nru busybox-1.35.0/networking/inetd.c busybox-1.36.1/networking/inetd.c --- busybox-1.35.0/networking/inetd.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/inetd.c 2023-01-03 14:14:43.000000000 +0000 @@ -1208,7 +1208,7 @@ close(sep->se_fd); } remove_pidfile_std_path_and_ext("inetd"); - exit(EXIT_SUCCESS); + exit_SUCCESS(); } int inetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -1538,7 +1538,7 @@ #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO \ || ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD # if !BB_MMU -static const char *const cat_args[] = { "cat", NULL }; +static const char *const cat_args[] ALIGN_PTR = { "cat", NULL }; # endif #endif diff -Nru busybox-1.35.0/networking/interface.c busybox-1.36.1/networking/interface.c --- busybox-1.35.0/networking/interface.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/interface.c 2023-01-03 14:14:43.000000000 +0000 @@ -446,13 +446,13 @@ * %n specifiers (even the size of integers may not match). */ #if INT_MAX == LONG_MAX -static const char *const ss_fmt[] = { +static const char *const ss_fmt[] ALIGN_PTR = { "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u", "%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u", "%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u" }; #else -static const char *const ss_fmt[] = { +static const char *const ss_fmt[] ALIGN_PTR = { "%n%llu%lu%lu%lu%lu%n%n%n%llu%lu%lu%lu%lu%lu", "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" @@ -731,7 +731,7 @@ #endif -static const struct hwtype *const hwtypes[] = { +static const struct hwtype *const hwtypes[] ALIGN_PTR = { &loop_hwtype, ðer_hwtype, &ppp_hwtype, diff -Nru busybox-1.35.0/networking/libiproute/ipaddress.c busybox-1.36.1/networking/libiproute/ipaddress.c --- busybox-1.35.0/networking/libiproute/ipaddress.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/libiproute/ipaddress.c 2023-01-03 14:14:43.000000000 +0000 @@ -58,7 +58,7 @@ static void print_link_flags(unsigned flags, unsigned mdown) { - static const int flag_masks[] = { + static const int flag_masks[] ALIGN_INT = { IFF_LOOPBACK, IFF_BROADCAST, IFF_POINTOPOINT, IFF_MULTICAST, IFF_NOARP, IFF_UP, IFF_LOWER_UP }; static const char flag_labels[] ALIGN1 = diff -Nru busybox-1.35.0/networking/nc.c busybox-1.36.1/networking/nc.c --- busybox-1.35.0/networking/nc.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/nc.c 2023-01-03 14:14:43.000000000 +0000 @@ -268,7 +268,7 @@ nread = safe_read(pfds[fdidx].fd, iobuf, COMMON_BUFSIZE); if (fdidx != 0) { if (nread < 1) - exit(EXIT_SUCCESS); + exit_SUCCESS(); ofd = STDOUT_FILENO; } else { if (nread < 1) { diff -Nru busybox-1.35.0/networking/ping.c busybox-1.36.1/networking/ping.c --- busybox-1.35.0/networking/ping.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/ping.c 2023-01-03 14:14:43.000000000 +0000 @@ -74,7 +74,7 @@ //usage: "\n -c CNT Send only CNT pings" //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" //usage: "\n -i SECS Interval" -//usage: "\n -A Ping as soon as reply is recevied" +//usage: "\n -A Ping as soon as reply is received" //usage: "\n -t TTL Set TTL" //usage: "\n -I IFACE/IP Source interface or IP address" //usage: "\n -W SEC Seconds to wait for the first response (default 10)" @@ -91,7 +91,7 @@ //usage: "\n -c CNT Send only CNT pings" //usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" //usage: "\n -i SECS Interval" -//usage: "\n -A Ping as soon as reply is recevied" +//usage: "\n -A Ping as soon as reply is received" ///////: "\n -t TTL Set TTL" ///////^^^^^ -t not tested for IPv6, might be not working //usage: "\n -I IFACE/IP Source interface or IP address" diff -Nru busybox-1.35.0/networking/route.c busybox-1.36.1/networking/route.c --- busybox-1.35.0/networking/route.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/route.c 2023-01-03 14:14:43.000000000 +0000 @@ -702,7 +702,7 @@ #endif bb_displayroutes(noresolve, opt & ROUTE_OPT_e); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } /* Check verb. At the moment, must be add, del, or delete. */ diff -Nru busybox-1.35.0/networking/tc.c busybox-1.36.1/networking/tc.c --- busybox-1.35.0/networking/tc.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/tc.c 2023-01-03 14:14:43.000000000 +0000 @@ -214,7 +214,7 @@ return 0; parse_rtattr_nested_compat(tb, TCA_PRIO_MAX, opt, qopt, sizeof(*qopt)); printf("bands %u priomap ", qopt->bands); - for (i=0; i<=TC_PRIO_MAX; i++) + for (i = 0; i <= TC_PRIO_MAX; i++) printf(" %d", qopt->priomap[i]); if (tb[TCA_PRIO_MQ]) diff -Nru busybox-1.35.0/networking/telnetd.c busybox-1.36.1/networking/telnetd.c --- busybox-1.35.0/networking/telnetd.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/telnetd.c 2023-01-03 14:14:43.000000000 +0000 @@ -582,7 +582,7 @@ struct tsession *t; if (option_mask32 & OPT_INETD) - exit(EXIT_SUCCESS); + exit_SUCCESS(); /* Unlink this telnet session from the session list */ t = G.sessions; diff -Nru busybox-1.35.0/networking/tls.c busybox-1.36.1/networking/tls.c --- busybox-1.35.0/networking/tls.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/networking/tls.c 2023-01-03 14:14:43.000000000 +0000 @@ -948,11 +948,46 @@ static const char *alert_text(int code) { + //10 unexpected_message + //20 bad_record_mac + //21 decryption_failed + //22 record_overflow + //30 decompression_failure + //40 handshake_failure + //41 no_certificate + //42 bad_certificate + //43 unsupported_certificate + //44 certificate_revoked + //45 certificate_expired + //46 certificate_unknown + //47 illegal_parameter + //48 unknown_ca + //49 access_denied + //50 decode_error + //51 decrypt_error + //52 too_many_cids_requested + //60 export_restriction + //70 protocol_version + //71 insufficient_security + //80 internal_error + //86 inappropriate_fallback + //90 user_canceled + //100 no_renegotiation + //109 missing_extension + //110 unsupported_extension + //111 certificate_unobtainable + //112 unrecognized_name + //113 bad_certificate_status_response + //114 bad_certificate_hash_value + //115 unknown_psk_identity + //116 certificate_required + //120 no_application_protocol switch (code) { case 20: return "bad MAC"; case 50: return "decode error"; - case 51: return "decrypt error"; case 40: return "handshake failure"; + case 51: return "decrypt error"; + case 80: return "internal error"; case 112: return "unrecognized name"; } return itoa(code); @@ -1531,27 +1566,6 @@ #endif 0x01,0x00, //not a cipher - comprtypes_len, comprtype }; - static const uint8_t supported_groups[] = { - 0x00,0x0a, //extension_type: "supported_groups" - 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len - 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len -#if ALLOW_CURVE_P256 - 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1) -#endif - //0x00,0x18, //curve_secp384r1 - //0x00,0x19, //curve_secp521r1 -#if ALLOW_CURVE_X25519 - 0x00,0x1d, //curve_x25519 (RFC 7748) -#endif - //0x00,0x1e, //curve_x448 (RFC 7748) - }; - //static const uint8_t signature_algorithms[] = { - // 000d - // 0020 - // 001e - // 0601 0602 0603 0501 0502 0503 0401 0402 0403 0301 0302 0303 0201 0202 0203 - //}; - struct client_hello { uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; @@ -1563,15 +1577,47 @@ uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ - /* Extensions (SNI shown): - * hi,lo // len of all extensions - * 00,00 // extension_type: "Server Name" - * 00,0e // list len (there can be more than one SNI) - * 00,0c // len of 1st Server Name Indication - * 00 // name type: host_name - * 00,09 // name len - * "localhost" // name - */ + }; + // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml + static const uint8_t extensions[] = { + // is.gd responds with "handshake failure" to our hello if there's no supported_groups + 0x00,0x0a, //extension_type: "supported_groups" + 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len + 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len +#if ALLOW_CURVE_P256 + 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1) +#endif + //0x00,0x18, //curve_secp384r1 + //0x00,0x19, //curve_secp521r1 +#if ALLOW_CURVE_X25519 + 0x00,0x1d, //curve_x25519 (RFC 7748) +#endif + //0x00,0x1e, //curve_x448 (RFC 7748) + + //0x00,0x0b,0x00,0x04,0x03,0x00,0x01,0x02, //extension_type: "ec_point_formats" + //0x00,0x16,0x00,0x00, //extension_type: "encrpypt-then-mac" + //0x00,0x17,0x00,0x00, //extension_type: "extended_master" + //0x00,0x23,0x00,0x00, //extension_type: "session_ticket" + + // kojipkgs.fedoraproject.org responds with alert code 80 ("internal error") + // to our hello without signature_algorithms. + // It is satisfied with just 0x04,0x01. + 0x00,0x0d, //extension_type: "signature_algorithms" (RFC5246 section 7.4.1.4.1): +#define SIGALGS (3 + 3 * ENABLE_FEATURE_TLS_SHA1) + 0x00,2 * (1 + SIGALGS), //ext len + 0x00,2 * (0 + SIGALGS), //list len + //Format: two bytes + // byte 1: 0:none,1:md5,2:sha1,3:sha224,4:sha256,5:sha384,6:sha512 + // byte 2: 1:rsa,2:dsa,3:ecdsa + // (note that TLS 1.3 changes this, see RFC8446 section 4.2.3) +#if ENABLE_FEATURE_TLS_SHA1 + 0x02,0x01, //sha1 + rsa + 0x02,0x02, //sha1 + dsa + 0x02,0x03, //sha1 + ecdsa +#endif + 0x04,0x01, //sha256 + rsa - kojipkgs.fedoraproject.org wants this + 0x04,0x02, //sha256 + dsa + 0x04,0x03, //sha256 + ecdsa // GNU Wget 1.18 to cdn.kernel.org sends these extensions: // 0055 // 0005 0005 0100000000 - status_request @@ -1591,8 +1637,7 @@ int sni_len = sni ? strnlen(sni, 127 - 5) : 0; ext_len = 0; - /* is.gd responds with "handshake failure" to our hello if there's no supported_groups element */ - ext_len += sizeof(supported_groups); + ext_len += sizeof(extensions); if (sni_len) ext_len += 9 + sni_len; @@ -1626,7 +1671,7 @@ ptr[8] = sni_len; //name len ptr = mempcpy(&ptr[9], sni, sni_len); } - memcpy(ptr, supported_groups, sizeof(supported_groups)); + memcpy(ptr, extensions, sizeof(extensions)); tls->hsd = xzalloc(sizeof(*tls->hsd)); /* HANDSHAKE HASH: ^^^ + len if need to save saved_client_hello */ diff -Nru busybox-1.35.0/networking/tls_sp_c32.c busybox-1.36.1/networking/tls_sp_c32.c --- busybox-1.35.0/networking/tls_sp_c32.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/networking/tls_sp_c32.c 2023-01-03 14:14:43.000000000 +0000 @@ -68,9 +68,6 @@ #define p256_mp_mod ((sp_digit)0x000001) -/* Normalize the values in each word to 32 bits - NOP */ -#define sp_256_norm_8(a) ((void)0) - /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 * @@ -83,8 +80,6 @@ int i; const uint64_t* r = (void*)rr; - sp_256_norm_8(rr); - r += 4; for (i = 0; i < 4; i++) { r--; @@ -97,8 +92,6 @@ { int i; - sp_256_norm_8(r); - r += 8; for (i = 0; i < 8; i++) { r--; @@ -641,7 +634,6 @@ int carry = 0; if (r[0] & 1) carry = sp_256_add_8(r, r, m); - sp_256_norm_8(r); sp_256_rshift1_8(r, carry); } @@ -652,10 +644,8 @@ // const sp_digit* m = p256_mod; int carry = sp_256_add_8(r, a, b); - sp_256_norm_8(r); if (carry) { sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } } @@ -667,10 +657,8 @@ int borrow; borrow = sp_256_sub_8(r, a, b); - sp_256_norm_8(r); if (borrow) { sp_256_add_8(r, r, m); - sp_256_norm_8(r); } } @@ -680,10 +668,8 @@ // const sp_digit* m = p256_mod; int carry = sp_256_add_8(r, a, a); - sp_256_norm_8(r); if (carry) sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } /* Triple a Montgomery form number (r = a + a + a % m) */ @@ -692,16 +678,12 @@ // const sp_digit* m = p256_mod; int carry = sp_256_add_8(r, a, a); - sp_256_norm_8(r); if (carry) { sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } carry = sp_256_add_8(r, r, a); - sp_256_norm_8(r); if (carry) { sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } } @@ -844,7 +826,6 @@ sp_512to256_mont_shift_8(r, aa); if (carry != 0) sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } #else /* Generic 32-bit version */ @@ -1003,8 +984,6 @@ * [In our case, it is (p256_mp_mod * a[1]) << 32.] * And so on. Eventually T is divisible by R, and after division by R * the algorithm is in the same place as the usual Montgomery reduction. - * - * TODO: Can conditionally use 64-bit (if bit-little-endian arch) logic? */ static void sp_512to256_mont_reduce_8(sp_digit* r, sp_digit* a/*, const sp_digit* m, sp_digit mp*/) { @@ -1032,7 +1011,6 @@ sp_512to256_mont_shift_8(r, a); if (word16th != 0) sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } else { /* Same code for explicit mp == 1 (which is always the case for P256) */ sp_digit word16th = 0; @@ -1052,7 +1030,6 @@ sp_512to256_mont_shift_8(r, a); if (word16th != 0) sp_256_sub_8_p256_mod(r); - sp_256_norm_8(r); } } #endif @@ -1208,14 +1185,12 @@ /* Reduce x to less than modulus */ if (sp_256_cmp_8(r->x, p256_mod) >= 0) sp_256_sub_8_p256_mod(r->x); - sp_256_norm_8(r->x); /* y /= z^3 */ sp_256_mont_mul_and_reduce_8(r->y, p->y, t1 /*, p256_mod, p256_mp_mod*/); /* Reduce y to less than modulus */ if (sp_256_cmp_8(r->y, p256_mod) >= 0) sp_256_sub_8_p256_mod(r->y); - sp_256_norm_8(r->y); memset(r->z, 0, sizeof(r->z)); r->z[0] = 1; @@ -1300,7 +1275,6 @@ /* Check double */ sp_256_sub_8(t1, p256_mod, q->y); - sp_256_norm_8(t1); if (sp_256_cmp_equal_8(p->x, q->x) && sp_256_cmp_equal_8(p->z, q->z) && (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_base_8(sp_point* r, sp_digit* k /*, int map*/) { /* Since this function is called only once, save space: - * don't have "static const sp_point p256_base = {...}", - * it would have more zeros than data. + * don't have "static const sp_point p256_base = {...}". */ static const uint8_t p256_base_bin[] = { /* x (big-endian) */ - 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, + 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, /* y */ - 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, + 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, /* z will be set to 1, infinity flag to "false" */ }; sp_point p256_base; diff -Nru busybox-1.35.0/networking/udhcp/common.c busybox-1.36.1/networking/udhcp/common.c --- busybox-1.35.0/networking/udhcp/common.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/networking/udhcp/common.c 2023-01-03 14:14:43.000000000 +0000 @@ -19,7 +19,7 @@ * See RFC2132 for more options. * OPTION_REQ: these options are requested by udhcpc (unless -o). */ -const struct dhcp_optflag dhcp_optflags[] = { +const struct dhcp_optflag dhcp_optflags[] ALIGN2 = { /* flags code */ { OPTION_IP | OPTION_REQ, 0x01 }, /* DHCP_SUBNET */ { OPTION_S32 , 0x02 }, /* DHCP_TIME_OFFSET */ diff -Nru busybox-1.35.0/networking/udhcp/common.h busybox-1.36.1/networking/udhcp/common.h --- busybox-1.35.0/networking/udhcp/common.h 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/networking/udhcp/common.h 2023-01-03 14:14:43.000000000 +0000 @@ -370,7 +370,8 @@ void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; int udhcp_sp_read(void) FAST_FUNC; -int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; +int udhcp_read_interface(const char *interface, + int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC; diff -Nru busybox-1.35.0/networking/udhcp/Config.src busybox-1.36.1/networking/udhcp/Config.src --- busybox-1.35.0/networking/udhcp/Config.src 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/udhcp/Config.src 2023-01-03 14:14:43.000000000 +0000 @@ -92,12 +92,17 @@ config UDHCPC_DEFAULT_SCRIPT string "Absolute path to config script" default "/usr/share/udhcpc/default.script" - depends on UDHCPC || UDHCPC6 + depends on UDHCPC help This script is called after udhcpc receives an answer. See examples/udhcp for a working example. Normally it is safe to leave this untouched. +config UDHCPC6_DEFAULT_SCRIPT + string "Absolute path to config script for IPv6" + default "/usr/share/udhcpc/default6.script" + depends on UDHCPC6 + # udhcpc6 config is inserted here: INSERT diff -Nru busybox-1.35.0/networking/udhcp/d6_common.h busybox-1.36.1/networking/udhcp/d6_common.h --- busybox-1.35.0/networking/udhcp/d6_common.h 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/udhcp/d6_common.h 2023-01-03 14:14:43.000000000 +0000 @@ -63,28 +63,45 @@ #define D6_OPT_CLIENTID 1 #define D6_OPT_SERVERID 2 +/* "Identity Association for Non-temporary Addresses", + * also known as a "network interface" in plain English */ #define D6_OPT_IA_NA 3 -#define D6_OPT_IA_TA 4 +/* "Identity Association for the Temporary Addresses". + * Presumably this is a "network interface with only link-local addresses". + * Why would DHCPv6 server assign such addresses, I have no idea. */ +//#define D6_OPT_IA_TA 4 +/* "IA Address", an IPv6 address */ #define D6_OPT_IAADDR 5 +/* Option "Option Request Option". From the owners of a doggy dog named Dog? */ #define D6_OPT_ORO 6 -#define D6_OPT_PREFERENCE 7 +//#define D6_OPT_PREFERENCE 7 #define D6_OPT_ELAPSED_TIME 8 -#define D6_OPT_RELAY_MSG 9 -#define D6_OPT_AUTH 11 -#define D6_OPT_UNICAST 12 +//#define D6_OPT_RELAY_MSG 9 +//#define D6_OPT_AUTH 11 +/* "The server sends this option to a client to indicate to the client + * that it is allowed to unicast messages to the server." + * Contains IPv6 address to send packets to. */ +//#define D6_OPT_UNICAST 12 +/* "A Status Code option may appear in the options field of a DHCP + * message and/or in the options field of another option." */ #define D6_OPT_STATUS_CODE 13 -#define D6_OPT_RAPID_COMMIT 14 -#define D6_OPT_USER_CLASS 15 -#define D6_OPT_VENDOR_CLASS 16 -#define D6_OPT_VENDOR_OPTS 17 -#define D6_OPT_INTERFACE_ID 18 -#define D6_OPT_RECONF_MSG 19 -#define D6_OPT_RECONF_ACCEPT 20 +/* "A client MAY include this option in a Solicit message if the client + * is prepared to perform the Solicit-Reply message exchange..." */ +//#define D6_OPT_RAPID_COMMIT 14 /* zero-length option */ +//#define D6_OPT_USER_CLASS 15 +//#define D6_OPT_VENDOR_CLASS 16 +//#define D6_OPT_VENDOR_OPTS 17 +//#define D6_OPT_INTERFACE_ID 18 +//#define D6_OPT_RECONF_MSG 19 +//#define D6_OPT_RECONF_ACCEPT 20 #define D6_OPT_DNS_SERVERS 23 #define D6_OPT_DOMAIN_LIST 24 +/* RFC 3633 "Identity Association for Prefix Delegation". + * This option says that client wants to get an IPv6 prefix */ #define D6_OPT_IA_PD 25 +/* Response from the server comes in this one */ #define D6_OPT_IAPREFIX 26 /* RFC 4704 "The DHCPv6 Client FQDN Option" diff -Nru busybox-1.35.0/networking/udhcp/d6_dhcpc.c busybox-1.36.1/networking/udhcp/d6_dhcpc.c --- busybox-1.35.0/networking/udhcp/d6_dhcpc.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/networking/udhcp/d6_dhcpc.c 2023-01-03 14:14:43.000000000 +0000 @@ -65,7 +65,7 @@ /* "struct client_data_t client_data" is in bb_common_bufsiz1 */ -static const struct dhcp_optflag d6_optflags[] = { +static const struct dhcp_optflag d6_optflags[] ALIGN2 = { #if ENABLE_FEATURE_UDHCPC6_RFC3646 { OPTION_6RD | OPTION_LIST | OPTION_REQ, D6_OPT_DNS_SERVERS }, { OPTION_DNS_STRING | OPTION_LIST | OPTION_REQ, D6_OPT_DOMAIN_LIST }, @@ -295,6 +295,7 @@ *new_env() = xasprintf("ipv6=%s", ipv6str); move_from_unaligned32(v32, option + 4 + 16 + 4); + v32 = ntohl(v32); *new_env() = xasprintf("lease=%u", (unsigned)v32); break; @@ -332,6 +333,7 @@ * +-+-+-+-+-+-+-+-+ */ move_from_unaligned32(v32, option + 4 + 4); + v32 = ntohl(v32); *new_env() = xasprintf("ipv6prefix_lease=%u", (unsigned)v32); sprint_nip6(ipv6str, option + 4 + 4 + 4 + 1); @@ -546,7 +548,7 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t *end) { /* FF02::1:2 is "All_DHCP_Relay_Agents_and_Servers" address */ - static const uint8_t FF02__1_2[16] = { + static const uint8_t FF02__1_2[16] ALIGNED(sizeof(long)) = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, }; @@ -842,7 +844,7 @@ uint8_t *opt_ptr; /* Fill in: msg type, xid, ELAPSED_TIME */ - opt_ptr = init_d6_packet(&packet, DHCPREQUEST); + opt_ptr = init_d6_packet(&packet, D6_MSG_RENEW); /* server id */ opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); @@ -888,7 +890,6 @@ if (client6_data.ia_pd) opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); /* Client-id */ -///vda ci = udhcp_find_option(client_data.options, D6_OPT_CLIENTID, /*dhcpv6:*/ 1); if (ci) opt_ptr = mempcpy(opt_ptr, ci->data, D6_OPT_DATA + 2+2 + 6); @@ -1081,7 +1082,7 @@ client_data.sockfd = -1; } if (new_mode == LISTEN_KERNEL) - client_data.sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT6, client_data.interface); + client_data.sockfd = d6_listen_socket(CLIENT_PORT6, client_data.interface); else if (new_mode != LISTEN_NONE) client_data.sockfd = d6_raw_socket(client_data.ifindex); /* else LISTEN_NONE: client_data.sockfd stays closed */ @@ -1133,7 +1134,7 @@ //usage:#define udhcpc6_full_usage "\n" //usage: "\n -i IFACE Interface to use (default "CONFIG_UDHCPC_DEFAULT_INTERFACE")" //usage: "\n -p FILE Create pidfile" -//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" +//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC6_DEFAULT_SCRIPT")" //usage: "\n -B Request broadcast replies" //usage: "\n -t N Send up to N discover packets" //usage: "\n -T SEC Pause between packets (default 3)" @@ -1199,7 +1200,7 @@ IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) IF_FEATURE_UDHCP_PORT(CLIENT_PORT6 = 546;) client_data.interface = CONFIG_UDHCPC_DEFAULT_INTERFACE; - client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; + client_data.script = CONFIG_UDHCPC6_DEFAULT_SCRIPT; client_data.sockfd = -1; /* Make sure fd 0,1,2 are open */ @@ -1487,6 +1488,7 @@ if (opt & OPT_l) send_d6_info_request(); else /* send a broadcast renew request */ +//TODO: send_d6_renew uses D6_MSG_RENEW message, should we use D6_MSG_REBIND here instead? send_d6_renew(/*server_ipv6:*/ NULL, requested_ipv6); timeout = discover_timeout; packet_num++; @@ -1615,6 +1617,16 @@ prefix_timeout = 0; option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); if (option && (option->data[0] | option->data[1]) != 0) { +///FIXME: +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | OPTION_STATUS_CODE | option-len | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | status-code | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +// . status-message . +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// so why do we think it's NAK if data[0] is zero but data[1] is not? That's wrong... +// we should also check that option->len is ok (i.e. not 0), right? /* return to init state */ bb_info_msg("received DHCP NAK (%u)", option->data[4]); d6_run_script(packet.d6_options, diff -Nru busybox-1.35.0/networking/udhcp/d6_packet.c busybox-1.36.1/networking/udhcp/d6_packet.c --- busybox-1.35.0/networking/udhcp/d6_packet.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/udhcp/d6_packet.c 2023-01-03 14:14:43.000000000 +0000 @@ -27,9 +27,8 @@ } #endif -int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 - UNUSED_PARAM - , struct d6_packet *packet, int fd) +int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 UNUSED_PARAM, + struct d6_packet *packet, int fd) { int bytes; @@ -81,12 +80,22 @@ dest_sll.sll_halen = 6; memcpy(dest_sll.sll_addr, dest_arp, 6); +//TODO: is bind() necessary? we sendto() to this destination, should work anyway if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) { msg = "bind(%s)"; goto ret_close; } packet.ip6.ip6_vfc = (6 << 4); /* 4 bits version, top 4 bits of tclass */ +// In case we have no IPv6 on our interface at all, we can try +// to fill "all hosts" mcast address as source: +// /* FF02::1 is Link-local "All_Nodes" address */ +// packet.ip6.ip6_dst.s6_addr[0] = 0xff; +// packet.ip6.ip6_dst.s6_addr[1] = 0x02; +// packet.ip6.ip6_dst.s6_addr[15] = 0x01; +// Maybe some servers will be able to respond to us this way? +// Users report that leaving ::0 address there makes servers try to reply to ::0, +// which doesn't work. if (src_ipv6) packet.ip6.ip6_src = *src_ipv6; /* struct copy */ packet.ip6.ip6_dst = *dst_ipv6; /* struct copy */ diff -Nru busybox-1.35.0/networking/udhcp/d6_socket.c busybox-1.36.1/networking/udhcp/d6_socket.c --- busybox-1.35.0/networking/udhcp/d6_socket.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/udhcp/d6_socket.c 2023-01-03 14:14:43.000000000 +0000 @@ -95,9 +95,6 @@ close(fd); } - if (retval == 0) - return retval; - if (retval & (1<<0)) bb_error_msg("can't get %s", "MAC"); if (retval & (1<<1)) @@ -109,18 +106,26 @@ { int fd; struct sockaddr_in6 addr; + char *colon; - log1("opening listen socket on *:%d %s", port, inf); + log2("opening listen socket on *:%d %s", port, inf); fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); setsockopt_reuseaddr(fd); if (setsockopt_broadcast(fd) == -1) bb_simple_perror_msg_and_die("SO_BROADCAST"); - /* NB: bug 1032 says this doesn't work on ethernet aliases (ethN:M) */ + /* SO_BINDTODEVICE doesn't work on ethernet aliases (ethN:M) */ + colon = strrchr(inf, ':'); + if (colon) + *colon = '\0'; + if (setsockopt_bindtodevice(fd, inf)) xfunc_die(); /* warning is already printed */ + if (colon) + *colon = ':'; + memset(&addr, 0, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_port = htons(port); diff -Nru busybox-1.35.0/networking/udhcp/packet.c busybox-1.36.1/networking/udhcp/packet.c --- busybox-1.35.0/networking/udhcp/packet.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/networking/udhcp/packet.c 2023-01-03 14:14:43.000000000 +0000 @@ -133,6 +133,7 @@ dest_sll.sll_halen = 6; memcpy(dest_sll.sll_addr, dest_arp, 6); +//TODO: is bind() necessary? we sendto() to this destination, should work anyway if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) { msg = "bind(%s)"; goto ret_close; diff -Nru busybox-1.35.0/printutils/lpd.c busybox-1.36.1/printutils/lpd.c --- busybox-1.35.0/printutils/lpd.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/printutils/lpd.c 2023-01-03 14:14:43.000000000 +0000 @@ -114,8 +114,8 @@ return xmalloc_reads(STDIN_FILENO, &max); } -int lpd_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE; -int lpd_main(int argc UNUSED_PARAM, char *argv[]) +int lpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int lpd_main(int argc UNUSED_PARAM, char **argv) { int spooling = spooling; // for compiler char *s, *queue; diff -Nru busybox-1.35.0/printutils/lpr.c busybox-1.36.1/printutils/lpr.c --- busybox-1.35.0/printutils/lpr.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/printutils/lpr.c 2023-01-03 14:14:43.000000000 +0000 @@ -78,8 +78,8 @@ } } -int lpqr_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE; -int lpqr_main(int argc UNUSED_PARAM, char *argv[]) +int lpqr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int lpqr_main(int argc UNUSED_PARAM, char **argv) { enum { OPT_P = 1 << 0, // -P queue[@host[:port]]. If no -P is given use $PRINTER, then "lp@localhost:515" diff -Nru busybox-1.35.0/procps/kill.c busybox-1.36.1/procps/kill.c --- busybox-1.35.0/procps/kill.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/procps/kill.c 2023-04-25 14:47:22.000000000 +0000 @@ -85,8 +85,8 @@ * This brings some complications: * * + we can't use xfunc here - * + we can't use applet_name * + we can't use bb_show_usage + * + applet_name can be the name of the shell * (doesn't apply for killall[5], still should be careful b/c NOFORK) * * kill %n gets translated into kill ' -' by shell (note space!) diff -Nru busybox-1.35.0/procps/nmeter.c busybox-1.36.1/procps/nmeter.c --- busybox-1.35.0/procps/nmeter.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/procps/nmeter.c 2023-01-03 14:14:43.000000000 +0000 @@ -27,6 +27,8 @@ //usage: "\n (displays: S:system U:user N:niced D:iowait I:irq i:softirq)" //usage: "\n %[nINTERFACE] Network INTERFACE" //usage: "\n %m Allocated memory" +//usage: "\n %[md] Dirty file-backed memory" +//usage: "\n %[mw] Memory being written to storage" //usage: "\n %[mf] Free memory" //usage: "\n %[mt] Total memory" //usage: "\n %s Allocated swap" @@ -68,7 +70,7 @@ smallint last_gen; } proc_file; -static const char *const proc_name[] = { +static const char *const proc_name[] ALIGN_PTR = { "stat", // Must match the order of proc_file's! "loadavg", "net/dev", @@ -208,7 +210,7 @@ // Reads decimal values from line. Values start after key, for example: // "cpu 649369 0 341297 4336769..." - key is "cpu" here. // Values are stored in vec[]. -// posbits is a bit lit of positions we are interested in. +// posbits is a bit list of positions we are interested in. // for example: 00100110 - we want 1st, 2nd and 5th value. // posbits.bit0 encodes conversion type. static int rdval(const char* p, const char* key, ullong *vec, long posbits) @@ -513,7 +515,7 @@ return; } - for (i=0; i<2; i++) { + for (i = 0; i < 2; i++) { ullong old = s->old[i]; if (data[i] < old) old = data[i]; //sanitize s->old[i] = data[i]; @@ -595,7 +597,7 @@ return; } - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { ullong old = s->old[i]; if (data[i] < old) old = data[i]; //sanitize s->old[i] = data[i]; @@ -661,13 +663,31 @@ //Hugepagesize: 4096 kB static void FAST_FUNC collect_mem(mem_stat *s) { - ullong m_total = 0; - ullong m_free = 0; - ullong m_bufs = 0; - ullong m_cached = 0; - ullong m_slab = 0; + ullong m_total; + ullong m_free; + ullong m_bufs; + ullong m_cached; + ullong m_slab; - if (rdval(get_file(&proc_meminfo), "MemTotal:", &m_total, 1 << 1)) { + const char *meminfo = get_file(&proc_meminfo); + + if (s->opt == 'd' /* dirty page cache */ + || s->opt == 'w' /* under writeback */ + ) { + m_total = 0; /* temporary reuse m_total */ + if (rdval(meminfo, + (s->opt == 'd' ? "Dirty:" : "Writeback:"), + &m_total, 1 << 1) + ) { + put_question_marks(4); + return; + } + scale(m_total << 10); + return; + } + + m_total = 0; + if (rdval(meminfo, "MemTotal:", &m_total, 1 << 1)) { put_question_marks(4); return; } @@ -676,10 +696,14 @@ return; } - if (rdval(proc_meminfo.file, "MemFree:", &m_free , 1 << 1) - || rdval(proc_meminfo.file, "Buffers:", &m_bufs , 1 << 1) - || rdval(proc_meminfo.file, "Cached:", &m_cached, 1 << 1) - || rdval(proc_meminfo.file, "Slab:", &m_slab , 1 << 1) + m_free = 0; + m_bufs = 0; + m_cached = 0; + m_slab = 0; + if (rdval(meminfo, "MemFree:", &m_free , 1 << 1) + || rdval(meminfo, "Buffers:", &m_bufs , 1 << 1) + || rdval(meminfo, "Cached:", &m_cached, 1 << 1) + || rdval(meminfo, "Slab:", &m_slab , 1 << 1) ) { put_question_marks(4); return; diff -Nru busybox-1.35.0/procps/pgrep.c busybox-1.36.1/procps/pgrep.c --- busybox-1.35.0/procps/pgrep.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/procps/pgrep.c 2023-01-03 14:14:43.000000000 +0000 @@ -44,7 +44,7 @@ //usage: "\n -P Match parent process ID" //usage: //usage:#define pkill_trivial_usage -//usage: "[-l|-SIGNAL] [-xfvno] [-s SID|-P PPID|PATTERN]" +//usage: "[-l|-SIGNAL] [-xfvnoe] [-s SID|-P PPID|PATTERN]" //usage:#define pkill_full_usage "\n\n" //usage: "Send signal to processes selected by regex PATTERN\n" //usage: "\n -l List all signals" @@ -55,6 +55,7 @@ //usage: "\n -v Negate the match" //usage: "\n -n Signal the newest process only" //usage: "\n -o Signal the oldest process only" +//usage: "\n -e Display name and PID of the process being killed" #include "libbb.h" #include "xregex.h" @@ -64,7 +65,7 @@ #define pkill (ENABLE_PKILL && (!ENABLE_PGREP || applet_name[1] == 'k')) enum { - /* "vlafxons:+P:+" */ + /* "vlafxones:+P:+" */ OPTBIT_V = 0, /* must be first, we need OPT_INVERT = 0/1 */ OPTBIT_L, OPTBIT_A, @@ -72,6 +73,7 @@ OPTBIT_X, OPTBIT_O, OPTBIT_N, + OPTBIT_E, /* should be pkill-only, do we care? */ OPTBIT_S, OPTBIT_P, }; @@ -83,6 +85,7 @@ #define OPT_ANCHOR (opt & (1 << OPTBIT_X)) #define OPT_FIRST (opt & (1 << OPTBIT_O)) #define OPT_LAST (opt & (1 << OPTBIT_N)) +#define OPT_ECHO (opt & (1 << OPTBIT_E)) #define OPT_SID (opt & (1 << OPTBIT_S)) #define OPT_PPID (opt & (1 << OPTBIT_P)) @@ -93,8 +96,12 @@ printf("%u %s\n", pid, cmd); else printf("%u\n", pid); - } else + } else { kill(pid, signo); + if (option_mask32 & (1 << OPTBIT_E)) { + printf("%s killed (pid %u)\n", cmd, pid); + } + } } int pgrep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -131,7 +138,7 @@ /* Parse remaining options */ ppid2match = -1; sid2match = -1; - opt = getopt32(argv, "vlafxons:+P:+", &sid2match, &ppid2match); + opt = getopt32(argv, "vlafxones:+P:+", &sid2match, &ppid2match); argv += optind; if (pkill && OPT_LIST) { /* -l: print the whole signal list */ diff -Nru busybox-1.35.0/procps/powertop.c busybox-1.36.1/procps/powertop.c --- busybox-1.35.0/procps/powertop.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/procps/powertop.c 2023-01-03 14:14:43.000000000 +0000 @@ -506,12 +506,9 @@ { /* EAX value specifies what information to return */ asm ( - " pushl %%ebx\n" /* Save EBX */ " cpuid\n" - " movl %%ebx, %1\n" /* Save content of EBX */ - " popl %%ebx\n" /* Restore EBX */ : "=a"(*eax), /* Output */ - "=r"(*ebx), + "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "0"(*eax), /* Input */ diff -Nru busybox-1.35.0/procps/top.c busybox-1.36.1/procps/top.c --- busybox-1.35.0/procps/top.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/procps/top.c 2023-01-03 14:14:43.000000000 +0000 @@ -689,6 +689,9 @@ lines_rem = ntop - G_scroll_ofs; s = top + G_scroll_ofs; while (--lines_rem >= 0) { + int n; + char *ppu; + char ppubuf[sizeof(int)*3 * 2 + 12]; char vsz_str_buf[8]; unsigned col; @@ -699,12 +702,36 @@ smart_ulltoa5(s->vsz, vsz_str_buf, " mgtpezy"); /* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */ + n = sprintf(ppubuf, "%5u %5u %-8.8s", s->pid, s->ppid, get_cached_username(s->uid)); + ppu = ppubuf; + if (n != 6+6+8) { + /* Format PID PPID USER part into 6+6+8 chars: + * shrink PID/PPID if possible, then truncate USER + */ + char *p, *pp; + if (*ppu == ' ') { + do { + ppu++, n--; + if (n == 6+6+8) + goto shortened; + } while (*ppu == ' '); + } + pp = p = skip_non_whitespace(ppu) + 1; + if (*p == ' ') { + do + p++, n--; + while (n != 6+6+8 && *p == ' '); + overlapping_strcpy(pp, p); /* shrink PPID */ + } + ppu[6+6+8] = '\0'; /* truncate USER */ + } + shortened: col = snprintf(line_buf, scr_width, - "\n" "%5u%6u %-8.8s %s %.5s" FMT + "\n" "%s %s %.5s" FMT IF_FEATURE_TOP_SMP_PROCESS(" %3d") IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT) " ", - s->pid, s->ppid, get_cached_username(s->uid), + ppu, s->state, vsz_str_buf, SHOW_STAT(pmem) IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) @@ -852,8 +879,11 @@ lines_rem = ntop - G_scroll_ofs; while (--lines_rem >= 0) { /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */ - ulltoa6_and_space(s->pid , &line_buf[0*6]); + int n = sprintf(line_buf, "%5u ", s->pid); ulltoa6_and_space(s->vsz , &line_buf[1*6]); + if (n > 7 || (n == 7 && line_buf[6] != ' ')) + /* PID and VSZ are clumped together, truncate PID */ + line_buf[5] = '.'; ulltoa6_and_space(s->vszrw , &line_buf[2*6]); ulltoa6_and_space(s->rss , &line_buf[3*6]); ulltoa6_and_space(s->rss_sh , &line_buf[4*6]); @@ -913,7 +943,7 @@ while (1) { int32_t c; - c = read_key(STDIN_FILENO, G.kbd_input, interval * 1000); + c = safe_read_key(STDIN_FILENO, G.kbd_input, interval * 1000); if (c == -1 && errno != EAGAIN) { /* error/EOF */ option_mask32 |= OPT_EOF; diff -Nru busybox-1.35.0/runit/runsv.c busybox-1.36.1/runit/runsv.c --- busybox-1.35.0/runit/runsv.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/runit/runsv.c 2023-01-03 14:14:43.000000000 +0000 @@ -700,7 +700,7 @@ if (svd[0].sd_want == W_EXIT && svd[0].state == S_DOWN) { if (svd[1].pid == 0) - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); if (svd[1].sd_want != W_EXIT) { svd[1].sd_want = W_EXIT; /* stopservice(&svd[1]); */ diff -Nru busybox-1.35.0/scripts/bb_release busybox-1.36.1/scripts/bb_release --- busybox-1.35.0/scripts/bb_release 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/scripts/bb_release 2023-01-03 14:14:43.000000000 +0000 @@ -17,7 +17,7 @@ zcat busybox-$VERSION.tar.gz | bzip2 > busybox-$VERSION.tar.bz2 for releasefile in busybox-$VERSION.tar.gz busybox-$VERSION.tar.bz2; do - test -f $releasefile || { echo "no $releasefile"; exit 1; } - gpg --detach-sign $releasefile - sha256sum $releasefile > $releasefile.sha256 + test -f $releasefile || { echo "no $releasefile"; exit 1; } + gpg --detach-sign $releasefile + sha256sum $releasefile > $releasefile.sha256 done diff -Nru busybox-1.35.0/scripts/echo.c busybox-1.36.1/scripts/echo.c --- busybox-1.35.0/scripts/echo.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/scripts/echo.c 2023-01-03 14:14:43.000000000 +0000 @@ -153,25 +153,32 @@ if (!eflag) { /* optimization for very common case */ fputs(arg, stdout); - } else while ((c = *arg++)) { - if (c == eflag) { /* Check for escape seq. */ + } else + while ((c = *arg++) != '\0') { + if (c == eflag) { + /* This is an "\x" sequence */ + if (*arg == 'c') { - /* '\c' means cancel newline and + /* "\c" means cancel newline and * ignore all subsequent chars. */ goto ret; } - { - /* Since SUSv3 mandates a first digit of 0, 4-digit octals - * of the form \0### are accepted. */ - if (*arg == '0') { - /* NB: don't turn "...\0" into "...\" */ - if (arg[1] && ((unsigned char)(arg[1]) - '0') < 8) { - arg++; - } + /* Since SUSv3 mandates a first digit of 0, 4-digit octals + * of the form \0### are accepted. */ + if (*arg == '0') { + if ((unsigned char)(arg[1] - '0') < 8) { + /* 2nd char is 0..7: skip leading '0' */ + arg++; } - /* bb_process_escape_sequence handles NUL correctly - * ("...\" case. */ - c = bb_process_escape_sequence(&arg); + } + /* bb_process_escape_sequence handles NUL correctly + * ("...\" case). */ + { + /* optimization: don't force arg to be on-stack, + * use another variable for that. ~30 bytes win */ + const char *z = arg; + c = bb_process_escape_sequence(&z); + arg = z; } } putchar(c); diff -Nru busybox-1.35.0/scripts/embedded_scripts busybox-1.36.1/scripts/embedded_scripts --- busybox-1.35.0/scripts/embedded_scripts 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/scripts/embedded_scripts 2023-01-03 14:14:43.000000000 +0000 @@ -23,6 +23,12 @@ exit 1 fi +bzip2 /dev/null +if test $? != 0; then + echo 'bzip2 is not installed' + exit 1 +fi + custom_scripts="" if [ -d "$custom_loc" ] then diff -Nru busybox-1.35.0/scripts/Makefile.lib busybox-1.36.1/scripts/Makefile.lib --- busybox-1.35.0/scripts/Makefile.lib 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/scripts/Makefile.lib 2023-01-03 14:14:43.000000000 +0000 @@ -113,6 +113,7 @@ $(basename_flags) $(modname_flags) a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \ + $(__c_flags) \ $(__a_flags) $(modkern_aflags) cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags) diff -Nru busybox-1.35.0/scripts/mkconfigs busybox-1.36.1/scripts/mkconfigs --- busybox-1.35.0/scripts/mkconfigs 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/scripts/mkconfigs 2023-01-03 14:14:43.000000000 +0000 @@ -28,6 +28,17 @@ config=.config +od -v -b /dev/null +if test $? != 0; then + echo 'od tool is not installed or cannot accept "-v -b" options' + exit 1 +fi +bzip2 /dev/null +if test $? != 0; then + echo 'bzip2 is not installed' + exit 1 +fi + { echo "\ #ifndef _BBCONFIGOPTS_H diff -Nru busybox-1.35.0/selinux/setenforce.c busybox-1.36.1/selinux/setenforce.c --- busybox-1.35.0/selinux/setenforce.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/selinux/setenforce.c 2023-01-03 14:14:43.000000000 +0000 @@ -26,7 +26,7 @@ /* These strings are arranged so that odd ones * result in security_setenforce(1) being done, * the rest will do security_setenforce(0) */ -static const char *const setenforce_cmd[] = { +static const char *const setenforce_cmd[] ALIGN_PTR = { "0", "1", "permissive", diff -Nru busybox-1.35.0/shell/ash.c busybox-1.36.1/shell/ash.c --- busybox-1.35.0/shell/ash.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/shell/ash.c 2023-04-25 14:47:22.000000000 +0000 @@ -134,6 +134,11 @@ //config: default y //config: depends on SHELL_ASH //config: +//config:config ASH_SLEEP +//config: bool "sleep builtin" +//config: default y +//config: depends on SHELL_ASH +//config: //config:config ASH_HELP //config: bool "help builtin" //config: default y @@ -313,7 +318,7 @@ /* ============ Shell options */ /* If you add/change options hare, update --help text too */ -static const char *const optletters_optnames[] = { +static const char *const optletters_optnames[] ALIGN_PTR = { "e" "errexit", "f" "noglob", /* bash has '-o ignoreeof', but no short synonym -I for it */ @@ -664,7 +669,7 @@ /* * Called when a SIGINT is received. (If the user specifies * that SIGINT is to be trapped or ignored using the trap builtin, then - * this routine is not called.) Suppressint is nonzero when interrupts + * this routine is not called.) suppress_int is nonzero when interrupts * are held using the INT_OFF macro. (The test for iflag is just * defensive programming.) */ @@ -695,13 +700,12 @@ } while (0) #endif -static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void +static IF_NOT_ASH_OPTIMIZE_FOR_SIZE(inline) void int_on(void) { barrier(); - if (--suppress_int == 0 && pending_int) { + if (--suppress_int == 0 && pending_int) raise_interrupt(); - } } #if DEBUG_INTONOFF # define INT_ON do { \ @@ -711,7 +715,7 @@ #else # define INT_ON int_on() #endif -static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void +static IF_NOT_ASH_OPTIMIZE_FOR_SIZE(inline) void force_int_on(void) { barrier(); @@ -3680,7 +3684,9 @@ if (!trap[SIGCHLD]) return; } - +#if ENABLE_FEATURE_EDITING + bb_got_signal = signo; /* for read_line_input: "we got a signal" */ +#endif gotsig[signo - 1] = 1; pending_sig = signo; @@ -5505,7 +5511,7 @@ ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); signal(SIGPIPE, SIG_DFL); xwrite(pip[1], p, len); - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } out: close(pip[1]); @@ -6531,9 +6537,7 @@ home = lookupvar("HOME"); } else { pw = getpwnam(name); - if (pw == NULL) - goto lose; - home = pw->pw_dir; + home = pw ? pw->pw_dir : NULL; } *p = c; if (!home) @@ -7029,6 +7033,7 @@ msg = umsg; } } + ifsfree(); ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail); } @@ -7080,6 +7085,10 @@ *repl = '\0'; break; } + if ((unsigned char)*repl == CTLENDVAR) { /* ${v/pattern} (no trailing /, no repl) */ + repl = NULL; + break; + } /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */ if ((unsigned char)*repl == CTLESC && repl[1]) repl++; @@ -7186,7 +7195,13 @@ len = orig_len - pos; if (!quotes) { - loc = mempcpy(startp, startp + pos, len); + /* want: loc = mempcpy(startp, startp + pos, len) + * but it does not allow overlapping arguments */ + loc = startp; + while (--len >= 0) { + *loc = loc[pos]; + loc++; + } } else { for (vstr = startp; pos != 0; pos--) { if ((unsigned char)*vstr == CTLESC) @@ -7314,13 +7329,15 @@ if (idx >= end) break; STPUTC(*idx, expdest); + if (stackblock() != restart_detect) + goto restart; if (quotes && (unsigned char)*idx == CTLESC) { idx++; len++; STPUTC(*idx, expdest); + if (stackblock() != restart_detect) + goto restart; } - if (stackblock() != restart_detect) - goto restart; idx++; len++; rmesc++; @@ -7345,6 +7362,13 @@ idx = loc; } + /* The STPUTC invocations above may resize and move the + * stack via realloc(3). Since repl is a pointer into the + * stack, we need to reconstruct it relative to stackblock(). + */ + if (slash_pos >= 0) + repl = (char *)stackblock() + strloc + slash_pos + 1; + //bb_error_msg("repl:'%s'", repl); for (loc = (char*)repl; *loc; loc++) { char *restart_detect = stackblock(); @@ -7444,6 +7468,7 @@ if (discard) return -1; + ifsfree(); raise_error_syntax("bad substitution"); } @@ -9711,7 +9736,7 @@ } /* setinteractive needs this forward reference */ -#if EDITING_HAS_get_exe_name +#if ENABLE_FEATURE_TAB_COMPLETION static const char *get_builtin_name(int i) FAST_FUNC; #endif @@ -9748,9 +9773,12 @@ #if ENABLE_FEATURE_EDITING if (!line_input_state) { line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP); -# if EDITING_HAS_get_exe_name +# if ENABLE_FEATURE_TAB_COMPLETION line_input_state->get_exe_name = get_builtin_name; # endif +# if EDITING_HAS_sh_get_var + line_input_state->sh_get_var = lookupvar; +# endif } #endif } @@ -9990,7 +10018,7 @@ setvareq(name, flags); else /* "local VAR" unsets VAR: */ - setvar0(name, NULL); + unsetvar(name); } } lvp->vp = vp; @@ -10136,6 +10164,9 @@ #if ENABLE_ASH_TEST || BASH_TEST2 static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } #endif +#if ENABLE_ASH_SLEEP +static int FAST_FUNC sleepcmd(int argc, char **argv) { return sleep_main(argc, argv); } +#endif /* Keep these in proper order since it is searched via bsearch() */ static const struct builtincmd builtintab[] = { @@ -10198,6 +10229,9 @@ { BUILTIN_SPEC_REG "return" , returncmd }, { BUILTIN_SPEC_REG "set" , setcmd }, { BUILTIN_SPEC_REG "shift" , shiftcmd }, +#if ENABLE_ASH_SLEEP + { BUILTIN_REGULAR "sleep" , sleepcmd }, +#endif #if BASH_SOURCE { BUILTIN_SPEC_REG "source" , dotcmd }, #endif @@ -10253,7 +10287,7 @@ return bp; } -#if EDITING_HAS_get_exe_name +#if ENABLE_FEATURE_TAB_COMPLETION static const char * FAST_FUNC get_builtin_name(int i) { @@ -10784,24 +10818,53 @@ line_input_state->path_lookup = pathval(); # endif reinit_unicode_for_ash(); + again: + /* For shell, LI_INTERRUPTIBLE is set: + * read_line_input will abort on either + * getting EINTR in poll(), or if it sees bb_got_signal != 0 + * (IOW: if signal arrives before poll() is reached). + * Interactive testcases: + * (while kill -INT $$; do sleep 1; done) & + * #^^^ prints ^C, prints prompt, repeats + * trap 'echo I' int; (while kill -INT $$; do sleep 1; done) & + * #^^^ prints ^C, prints "I", prints prompt, repeats + * trap 'echo T' term; (while kill $$; do sleep 1; done) & + * #^^^ prints "T", prints prompt, repeats + * #(bash 5.0.17 exits after first "T", looks like a bug) + */ + bb_got_signal = 0; + INT_OFF; /* no longjmp'ing out of read_line_input please */ nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ); + if (bb_got_signal == SIGINT) + write(STDOUT_FILENO, "^C\n", 3); + INT_ON; /* here non-blocked SIGINT will longjmp */ if (nr == 0) { /* ^C pressed, "convert" to SIGINT */ - write(STDOUT_FILENO, "^C", 2); - raise(SIGINT); + write(STDOUT_FILENO, "^C\n", 3); + raise(SIGINT); /* here non-blocked SIGINT will longjmp */ + /* raise(SIGINT) did not work! (e.g. if SIGINT + * is SIG_IGNed on startup, it stays SIG_IGNed) + */ if (trap[SIGINT]) { + empty_line_input: buf[0] = '\n'; buf[1] = '\0'; return 1; } exitstatus = 128 + SIGINT; - return -1; + /* bash behavior on ^C + ignored SIGINT: */ + goto again; } if (nr < 0) { if (errno == 0) { - /* Ctrl+D pressed */ + /* ^D pressed */ nr = 0; } + else if (errno == EINTR) { /* got signal? */ + if (bb_got_signal != SIGINT) + write(STDOUT_FILENO, "\n", 1); + goto empty_line_input; + } # if ENABLE_ASH_IDLE_TIMEOUT else if (errno == EAGAIN && timeout > 0) { puts("\007timed out waiting for input: auto-logout"); @@ -11201,8 +11264,8 @@ /* * Print appropriate message(s) if mail has arrived. * If mail_var_path_changed is set, - * then the value of MAIL has mail_var_path_changed, - * so we just update the values. + * then the value of MAIL has changed, + * so we just update the hash value. */ static void chkmail(void) @@ -11221,10 +11284,9 @@ int len; len = padvance_magic(&mpath, nullstr, 2); - if (!len) + if (len < 0) break; p = stackblock(); - break; if (*p == '\0') continue; for (q = p; *q; q++) @@ -11243,8 +11305,8 @@ if (!mail_var_path_changed && mailtime_hash != new_hash) { if (mailtime_hash != 0) out2str("you have mail\n"); - mailtime_hash = new_hash; } + mailtime_hash = new_hash; mail_var_path_changed = 0; popstackmark(&smark); } @@ -11358,7 +11420,7 @@ int val; int c; - if (login_sh) + if (login_sh != NULL) /* if we came from startup code */ minusc = NULL; while ((p = *argptr) != NULL) { c = *p++; @@ -11369,7 +11431,7 @@ if (c == '-') { val = 1; if (p[0] == '\0' || LONE_DASH(p)) { - if (!login_sh) { + if (login_sh == NULL) { /* we came from setcmd() */ /* "-" means turn off -x and -v */ if (p[0] == '\0') xflag = vflag = 0; @@ -11382,7 +11444,7 @@ } /* first char was + or - */ while ((c = *p++) != '\0') { - if (login_sh) { + if (login_sh != NULL) { /* if we came from startup code */ /* bash 3.2 indeed handles -c CMD and +c CMD the same */ if (c == 'c') { minusc = p; /* command is after shell args */ @@ -11406,6 +11468,9 @@ if (strcmp(p, "login") == 0) { *login_sh = 1; } +/* TODO: --noprofile: e.g. if I want to run emergency shell from sulogin, + * I want minimal/no shell init scripts - but it insists on running it as "-ash"... + */ break; } } diff -Nru busybox-1.35.0/shell/ash_test/ash-heredoc/heredoc_and_cmd.right busybox-1.36.1/shell/ash_test/ash-heredoc/heredoc_and_cmd.right --- busybox-1.35.0/shell/ash_test/ash-heredoc/heredoc_and_cmd.right 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/shell/ash_test/ash-heredoc/heredoc_and_cmd.right 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,2 @@ +./heredoc_and_cmd.tests: line 4: D: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Y diff -Nru busybox-1.35.0/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests busybox-1.36.1/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests --- busybox-1.35.0/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/shell/ash_test/ash-heredoc/heredoc_and_cmd.tests 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,8 @@ +# The bug was only happening with <. (^C works immediately) */ - r = read_line_input(G.line_input_state, prompt_str, + + bb_got_signal = 0; + if (!sigisemptyset(&G.pending_set)) { + /* Whoops, already got a signal, do not call read_line_input */ + bb_got_signal = r = -1; + } else { + /* For shell, LI_INTERRUPTIBLE is set: + * read_line_input will abort on either + * getting EINTR in poll(), or if it sees bb_got_signal != 0 + * (IOW: if signal arrives before poll() is reached). + * Interactive testcases: + * (while kill -INT $$; do sleep 1; done) & + * #^^^ prints ^C, prints prompt, repeats + * trap 'echo I' int; (while kill -INT $$; do sleep 1; done) & + * #^^^ prints ^C, prints "I", prints prompt, repeats + * trap 'echo T' term; (while kill $$; do sleep 1; done) & + * #^^^ prints "T", prints prompt, repeats + * #(bash 5.0.17 exits after first "T", looks like a bug) + */ + r = read_line_input(G.line_input_state, prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1 - ); - /* read_line_input intercepts ^C, "convert" it to SIGINT */ - if (r == 0) { - raise(SIGINT); + ); + /* read_line_input intercepts ^C, "convert" it to SIGINT */ + if (r == 0) + raise(SIGINT); + } + /* bash prints ^C (before running a trap, if any) + * both on keyboard ^C and on real SIGINT (non-kbd generated). + */ + if (sigismember(&G.pending_set, SIGINT)) { + write(STDOUT_FILENO, "^C\n", 3); + G.last_exitcode = 128 | SIGINT; } check_and_run_traps(); - if (r != 0 && !G.flag_SIGINT) - break; - /* ^C or SIGINT: repeat */ - /* bash prints ^C even on real SIGINT (non-kbd generated) */ - write(STDOUT_FILENO, "^C\n", 3); - G.last_exitcode = 128 | SIGINT; - } - if (r < 0) { - /* EOF/error detected */ - /* ^D on interactive input goes to next line before exiting: */ - write(STDOUT_FILENO, "\n", 1); - i->p = NULL; - i->peek_buf[0] = r = EOF; - return r; + if (r == 0) /* keyboard ^C? */ + continue; /* go back, read another input line */ + if (r > 0) /* normal input? (no ^C, no ^D, no signals) */ + break; + if (!bb_got_signal) { + /* r < 0: ^D/EOF/error detected (but not signal) */ + /* ^D on interactive input goes to next line before exiting: */ + write(STDOUT_FILENO, "\n", 1); + i->p = NULL; + i->peek_buf[0] = r = EOF; + return r; + } + /* it was a signal: go back, read another input line */ } i->p = G.user_input_buf; return (unsigned char)*i->p++; @@ -3655,7 +3687,7 @@ #ifndef debug_print_tree static void debug_print_tree(struct pipe *pi, int lvl) { - static const char *const PIPE[] = { + static const char *const PIPE[] ALIGN_PTR = { [PIPE_SEQ] = "SEQ", [PIPE_AND] = "AND", [PIPE_OR ] = "OR" , @@ -3690,7 +3722,7 @@ [RES_XXXX ] = "XXXX" , [RES_SNTX ] = "SNTX" , }; - static const char *const CMDTYPE[] = { + static const char *const CMDTYPE[] ALIGN_PTR = { "{}", "()", "[noglob]", @@ -6937,7 +6969,7 @@ val = NULL; } else { char *new_var = xasprintf("%s=%s", var, val); - set_local_var(new_var, /*flag:*/ 0); + set_local_var0(new_var); } } } @@ -7632,7 +7664,7 @@ if (is_prefixed_with(s, "trap") && skip_whitespace(s + 4)[0] == '\0' ) { - static const char *const argv[] = { NULL, NULL }; + static const char *const argv[] ALIGN_PTR = { NULL, NULL }; builtin_trap((char**)argv); fflush_all(); /* important */ _exit(0); @@ -8161,7 +8193,7 @@ return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); } -#if ENABLE_HUSH_JOB && EDITING_HAS_get_exe_name +#if ENABLE_HUSH_JOB && ENABLE_FEATURE_TAB_COMPLETION static const char * FAST_FUNC get_builtin_name(int i) { if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) { @@ -8587,7 +8619,7 @@ * expand_assignments(): think about ... | var=`sleep 1` | ... */ free_strings(new_env); - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } sv_shadowed = G.shadowed_vars_pp; @@ -8768,7 +8800,7 @@ /* Case when we are here: ... | >file */ debug_printf_exec("pseudo_exec'ed null command\n"); - _exit(EXIT_SUCCESS); + _exit_SUCCESS(); } #if ENABLE_HUSH_JOB @@ -9346,7 +9378,7 @@ } #endif debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p); - if (set_local_var(p, /*flag:*/ 0)) { + if (set_local_var0(p)) { /* assignment to readonly var / putenv error? */ rcode = 1; } @@ -9799,7 +9831,7 @@ static const char encoded_dollar_at[] ALIGN1 = { SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0' }; /* encoded representation of "$@" */ - static const char *const encoded_dollar_at_argv[] = { + static const char *const encoded_dollar_at_argv[] ALIGN_PTR = { encoded_dollar_at, NULL }; /* argv list with one element: "$@" */ char **vals; @@ -9829,7 +9861,7 @@ } /* Insert next value from for_lcur */ /* note: *for_lcur already has quotes removed, $var expanded, etc */ - set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0); + set_local_var_from_halves(pi->cmds[0].argv[0], *for_lcur++); continue; } if (rword == RES_IN) { @@ -10361,7 +10393,7 @@ //it ignores TERM: // bash -i -c 'kill $$; echo ALIVE' // ALIVE -//it resets SIG_INGed HUP to SIG_DFL: +//it resets SIG_IGNed HUP to SIG_DFL: // trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE' // Hangup [the message is not printed by bash, it's the shell which started it] //is talkative about jobs and exiting: @@ -10641,9 +10673,12 @@ # if ENABLE_FEATURE_EDITING G.line_input_state = new_line_input_t(FOR_SHELL); -# if EDITING_HAS_get_exe_name +# if ENABLE_FEATURE_TAB_COMPLETION G.line_input_state->get_exe_name = get_builtin_name; # endif +# if EDITING_HAS_sh_get_var + G.line_input_state->sh_get_var = get_local_var_value; +# endif # endif # if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0 { diff -Nru busybox-1.35.0/shell/hush_test/hush-heredoc/heredoc_and_cmd.right busybox-1.36.1/shell/hush_test/hush-heredoc/heredoc_and_cmd.right --- busybox-1.35.0/shell/hush_test/hush-heredoc/heredoc_and_cmd.right 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/shell/hush_test/hush-heredoc/heredoc_and_cmd.right 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,2 @@ +hush: D: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Y diff -Nru busybox-1.35.0/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests busybox-1.36.1/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests --- busybox-1.35.0/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/shell/hush_test/hush-heredoc/heredoc_and_cmd.tests 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,8 @@ +# The bug was only happening with <&1 && cat sed.output && rm sed.output" \ + "a\nc\n" \ + "" \ + "a\nb\nc\n" + + # testing "description" "commands" "result" "infile" "stdin" exit $FAILCOUNT diff -Nru busybox-1.35.0/testsuite/sha1sum.tests busybox-1.36.1/testsuite/sha1sum.tests --- busybox-1.35.0/testsuite/sha1sum.tests 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/testsuite/sha1sum.tests 2023-01-03 14:14:43.000000000 +0000 @@ -1,3 +1,15 @@ #!/bin/sh +. ./testing.sh + +# testing "test name" "cmd" "expected result" "file input" "stdin" +>EMPTY +optional FEATURE_MD5_SHA1_SUM_CHECK +testing "sha1sum: one-space separated input for -c" \ + 'echo "da39a3ee5e6b4b0d3255bfef95601890afd80709 EMPTY" | sha1sum -c' \ + "EMPTY: OK\n" \ + "" "" +SKIP= +rm EMPTY + . ./md5sum.tests sha1sum d41337e834377140ae7f98460d71d908598ef04f diff -Nru busybox-1.35.0/testsuite/sort.tests busybox-1.36.1/testsuite/sort.tests --- busybox-1.35.0/testsuite/sort.tests 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/testsuite/sort.tests 2023-01-03 14:14:43.000000000 +0000 @@ -175,6 +175,69 @@ 111 " "" +testing "sort -sr (stable and reverse) does NOT reverse 'stable' ordering" \ +"sort -k2 -r -s input" "\ +b 2 +d 2 +a 1 +c 1 +" "\ +a 1 +b 2 +c 1 +d 2 +" "" + +testing "sort -h" \ +"sort -h input" "\ +3e +4m +5y +1023 +1024 +1025 +3000 +2K +3k +1M +2E +1Y +" "\ +1Y +5y +1M +2E +3k +3e +2K +4m +1023 +1025 +3000 +1024 +" "" + # testing "description" "command(s)" "result" "infile" "stdin" +testing "sort -k2,2M" \ +"sort -k2,2M input" "\ +3 March +2 April +1 May +" "\ +2 April +1 May +3 March +" "" + +testing "sort -s -u" \ +"sort -s -u -k 2 input" "\ +z a +z b +" "\ +z b +a b +z a +a a" "" + exit $FAILCOUNT diff -Nru busybox-1.35.0/testsuite/tree.tests busybox-1.36.1/testsuite/tree.tests --- busybox-1.35.0/testsuite/tree.tests 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/testsuite/tree.tests 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,102 @@ +#!/bin/sh + +# Copyright 2022 by Roger Knecht +# Licensed under GPLv2, see file LICENSE in this source tree. + +. ./testing.sh -v + +# testing "description" "command" "result" "infile" "stdin" + +testing "tree error opening dir" \ + "tree tree.tempdir" \ + "\ +tree.tempdir [error opening dir]\n\ +\n\ +0 directories, 0 files\n" \ + "" "" + +mkdir -p tree2.tempdir +touch tree2.tempdir/testfile + +optional UNICODE_SUPPORT + +testing "tree single file" \ + "cd tree2.tempdir && tree" \ + "\ +.\n\ +└── testfile\n\ +\n\ +0 directories, 1 files\n" \ + "" "" + +mkdir -p tree3.tempdir/test1 \ + tree3.tempdir/test2/a \ + tree3.tempdir/test2/b \ + tree3.tempdir/test3/c \ + tree3.tempdir/test3/d + +touch tree3.tempdir/test2/a/testfile1 \ + tree3.tempdir/test2/a/testfile2 \ + tree3.tempdir/test2/a/testfile3 \ + tree3.tempdir/test2/b/testfile4 \ + tree3.tempdir/test3/c/testfile5 \ + tree3.tempdir/test3/d/testfile6 \ + tree3.tempdir/test3/d/.testfile7 + +(cd tree3.tempdir/test2/a && ln -s ../b/testfile4 .) +(cd tree3.tempdir/test2/b && ln -s ../../test3 .) + +testing "tree nested directories and files" \ + "cd tree3.tempdir && tree" \ + "\ +.\n\ +├── test1\n\ +├── test2\n\ +│ ├── a\n\ +│ │ ├── testfile1\n\ +│ │ ├── testfile2\n\ +│ │ ├── testfile3\n\ +│ │ └── testfile4 -> ../b/testfile4\n\ +│ └── b\n\ +│ ├── test3 -> ../../test3\n\ +│ └── testfile4\n\ +└── test3\n\ + ├── c\n\ + │ └── testfile5\n\ + └── d\n\ + └── testfile6\n\ +\n\ +7 directories, 8 files\n" \ + "" "" +#note: tree v2.0.1 says "8 directories, 7 files": +#it counts "test3 -> ../../test3" as a directory, even though it does not follow this symlink + +testing "tree multiple directories" \ + "tree tree2.tempdir tree3.tempdir" \ + "\ +tree2.tempdir\n\ +└── testfile\n\ +tree3.tempdir\n\ +├── test1\n\ +├── test2\n\ +│ ├── a\n\ +│ │ ├── testfile1\n\ +│ │ ├── testfile2\n\ +│ │ ├── testfile3\n\ +│ │ └── testfile4 -> ../b/testfile4\n\ +│ └── b\n\ +│ ├── test3 -> ../../test3\n\ +│ └── testfile4\n\ +└── test3\n\ + ├── c\n\ + │ └── testfile5\n\ + └── d\n\ + └── testfile6\n\ +\n\ +7 directories, 9 files\n" \ + "" "" +#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?) + +rm -rf tree.tempdir tree2.tempdir tree3.tempdir + +exit $FAILCOUNT diff -Nru busybox-1.35.0/testsuite/tsort.tests busybox-1.36.1/testsuite/tsort.tests --- busybox-1.35.0/testsuite/tsort.tests 1970-01-01 00:00:00.000000000 +0000 +++ busybox-1.36.1/testsuite/tsort.tests 2023-01-03 14:14:43.000000000 +0000 @@ -0,0 +1,110 @@ +#!/bin/sh + +# SUSv3 compliant sort tests. +# Public Domain, David Leonard 2022 + +. ./testing.sh + +# name cmd expected ./input stdin +testing "" "tsort" "a\n" "" "a a\n" +testing "" "tsort -" "a\n" "" "a a\n" +testing "" "tsort input" "a\n" "a a\n" "" +testing "tsort input (w/o eol)" "tsort input" "a\n" "a a" "" +testing "" "tsort /dev/null" "" "" "" + +testing "tsort empty" tsort "" "" "" +testing "tsort blank" tsort "" "" "\n" +testing "tsort blanks" tsort "" "" "\n\n \t\n " + +# simple inputs having exactly one solution +testing "tsort 1-edge" tsort "a\nb\n" "" "a b\n" +testing "tsort 2-edge" tsort "a\nb\nc\n" "" "a b b c\n" + + +# The following test helper accommodates future variable output because, as +# tsort is allowed to emit any total ordering that satisfies its input, +# should the implementation changes, these tests will remain valid. +# +# The idea is to verify that: +# - each input word is present EXACTLY ONCE in tsort's output +# - for each input pair 'a b', the occurrence of 'a' APPEARS BEFORE 'b' +# - the exit code is 0 + +tsort_test () { + fail= + name="$1"; shift + args="$*" + if [ $VERBOSE ]; then + echo "============" + echo "echo \"$args\" | tsort >actual" + fi + echo "$args" | tsort >actual + ec=$? + if [ $ec -ne 0 ]; then + fail "tsort exit $ec, expected 0" + fi + while [ $# -ne 0 ]; do + a=$1; shift + b=$1; shift + aline=$(grep -nxF "$a" /dev/null 2>/dev/null + ec=$? + if [ $ec -eq 0 ]; then + fail "$name: unexpected exit 0 ($*)" + fi + report "$name" +} + +fail () { + [ $VERBOSE ] && echo "ERROR: $*" + fail=1 +} + +report () { + if [ $fail ]; then + FAILCOUNT=$(($FAILCOUNT + 1)) + echo "FAIL: $*" + else + echo "PASS: $*" + fi +} + +tsort_test "tsort empty2" +tsort_test "tsort singleton" a a +tsort_test "tsort simple" a b b c +tsort_test "tsort 2singleton" a a b b +tsort_test "tsort medium" a b a b b c +tsort_test "tsort std.example" a b c c d e g g f g e f h h +tsort_test "tsort prefixes" a aa aa aaa aaaa aaaaa a aaaaa + +tsort_test_err "tsort odd" a +tsort_test_err "tsort odd2" a b c +tsort_test_err "tsort cycle" a b b a + +exit $FAILCOUNT diff -Nru busybox-1.35.0/testsuite/xxd.tests busybox-1.36.1/testsuite/xxd.tests --- busybox-1.35.0/testsuite/xxd.tests 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/testsuite/xxd.tests 2023-01-03 14:14:43.000000000 +0000 @@ -37,4 +37,27 @@ '' \ '30313233343536373736353433323130 30313233343536373736353433323130' +testing 'xxd -r skips leading whitespace and truncates at two spaces' \ + 'xxd -r' \ + '0123456789:;<=>?@' \ + '' "\ + 00000000: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? + 00000010: 40 @ +" + +testing 'xxd -p -r skips one bad char, truncates at two bad chars' \ + 'xxd -p -r' \ + '01' \ + '' "\ +30 !31 !!32 +" + +testing 'xxd -p -r ignores the nibble with 2nd char bad' \ + 'xxd -p -r' \ + '3C6' \ + '' "\ +33 3!4 3!!5 +36 +" + exit $FAILCOUNT diff -Nru busybox-1.35.0/util-linux/cal.c busybox-1.36.1/util-linux/cal.c --- busybox-1.35.0/util-linux/cal.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/cal.c 2023-01-03 14:14:43.000000000 +0000 @@ -233,7 +233,7 @@ } } - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } /* diff -Nru busybox-1.35.0/util-linux/chrt.c busybox-1.36.1/util-linux/chrt.c --- busybox-1.35.0/util-linux/chrt.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/util-linux/chrt.c 2023-01-03 14:14:43.000000000 +0000 @@ -110,7 +110,7 @@ show_min_max(SCHED_RR); show_min_max(SCHED_BATCH); show_min_max(SCHED_IDLE); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } //if (opt & OPT_r) // policy = SCHED_RR; - default, already set diff -Nru busybox-1.35.0/util-linux/fbset.c busybox-1.36.1/util-linux/fbset.c --- busybox-1.35.0/util-linux/fbset.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/util-linux/fbset.c 2023-01-03 14:14:43.000000000 +0000 @@ -518,7 +518,13 @@ case CMD_DEPTH: var_set.bits_per_pixel = xatou32(argv[1]); break; + case CMD_PIXCLOCK: + var_set.pixclock = xatou32(argv[1]); + break; #endif + default: + bb_perror_msg_and_die("option '%s' not handled", + g_cmdoptions[i].name); } switch (g_cmdoptions[i].code) { case CMD_FB: diff -Nru busybox-1.35.0/util-linux/fdisk.c busybox-1.36.1/util-linux/fdisk.c --- busybox-1.35.0/util-linux/fdisk.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/fdisk.c 2023-01-03 14:14:43.000000000 +0000 @@ -355,6 +355,7 @@ "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */ "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */ "\xf2" "DOS secondary", /* DOS 3.3+ secondary */ + "\xf8" "EBBR protective", /* Arm EBBR firmware protective partition */ "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with autodetect using persistent superblock */ @@ -665,7 +666,7 @@ sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer)); if (sz <= 0) - exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */ + exit_SUCCESS(); /* Ctrl-D or Ctrl-C */ if (line_buffer[sz-1] == '\n') line_buffer[--sz] = '\0'; @@ -2855,7 +2856,7 @@ if (ENABLE_FEATURE_CLEAN_UP) close_dev_fd(); bb_putchar('\n'); - exit(EXIT_SUCCESS); + exit_SUCCESS(); case 'r': return; case 's': diff -Nru busybox-1.35.0/util-linux/fdisk_osf.c busybox-1.36.1/util-linux/fdisk_osf.c --- busybox-1.35.0/util-linux/fdisk_osf.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/fdisk_osf.c 2023-01-03 14:14:43.000000000 +0000 @@ -383,7 +383,7 @@ if (xbsd_readlabel(NULL) == 0) if (xbsd_create_disklabel() == 0) - exit(EXIT_SUCCESS); + exit_SUCCESS(); #endif @@ -411,7 +411,7 @@ case 'q': if (ENABLE_FEATURE_CLEAN_UP) close_dev_fd(); - exit(EXIT_SUCCESS); + exit_SUCCESS(); case 'r': return; case 's': diff -Nru busybox-1.35.0/util-linux/fsck_minix.c busybox-1.36.1/util-linux/fsck_minix.c --- busybox-1.35.0/util-linux/fsck_minix.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/fsck_minix.c 2023-01-03 14:14:43.000000000 +0000 @@ -423,7 +423,7 @@ cont = ask("Do you really want to continue", 0); if (!cont) { puts("Check aborted"); - exit(EXIT_SUCCESS); + exit_SUCCESS(); } } } diff -Nru busybox-1.35.0/util-linux/hexdump.c busybox-1.36.1/util-linux/hexdump.c --- busybox-1.35.0/util-linux/hexdump.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/hexdump.c 2023-01-03 14:14:43.000000000 +0000 @@ -71,7 +71,7 @@ fclose(fp); } -static const char *const add_strings[] = { +static const char *const add_strings[] ALIGN_PTR = { "\"%07.7_ax \"16/1 \"%03o \"\"\n\"", /* b */ "\"%07.7_ax \"16/1 \"%3_c \"\"\n\"", /* c */ "\"%07.7_ax \"8/2 \" %05u \"\"\n\"", /* d */ diff -Nru busybox-1.35.0/util-linux/hexdump_xxd.c busybox-1.36.1/util-linux/hexdump_xxd.c --- busybox-1.35.0/util-linux/hexdump_xxd.c 2021-12-26 16:53:26.000000000 +0000 +++ busybox-1.36.1/util-linux/hexdump_xxd.c 2023-01-03 14:14:43.000000000 +0000 @@ -41,7 +41,7 @@ // -u use upper case hex letters. //usage:#define xxd_trivial_usage -//usage: "[-pri] [-g N] [-c N] [-n LEN] [-s OFS] [-o OFS] [FILE]" +//usage: "[-pri] [-g N] [-c N] [-l LEN] [-s OFS] [-o OFS] [FILE]" //usage:#define xxd_full_usage "\n\n" //usage: "Hex dump FILE (or stdin)\n" //usage: "\n -g N Bytes per group" @@ -55,6 +55,7 @@ //usage: "\n -r Reverse (with -p, assumes no offsets in input)" #include "libbb.h" +#include "common_bufsiz.h" #include "dump.h" /* This is a NOEXEC applet. Be very careful! */ @@ -69,61 +70,110 @@ #define OPT_c (1 << 7) #define OPT_o (1 << 8) -static void reverse(unsigned opt, const char *filename) +#define fillbuf bb_common_bufsiz1 + +static void write_zeros(off_t count) +{ + errno = 0; + do { + unsigned sz = count < COMMON_BUFSIZE ? (unsigned)count : COMMON_BUFSIZE; + if (fwrite(fillbuf, 1, sz, stdout) != sz) + bb_simple_perror_msg_and_die("write error"); + count -= sz; + } while (count != 0); +} + +static void reverse(unsigned opt, const char *filename, char *opt_s) { FILE *fp; char *buf; + off_t cur, opt_s_ofs; + + memset(fillbuf, 0, COMMON_BUFSIZE); + opt_s_ofs = cur = 0; + if (opt_s) { + opt_s_ofs = BB_STRTOOFF(opt_s, NULL, 0); + if (errno || opt_s_ofs < 0) + bb_error_msg_and_die("invalid number '%s'", opt_s); + } fp = filename ? xfopen_for_read(filename) : stdin; + get_new_line: while ((buf = xmalloc_fgetline(fp)) != NULL) { char *p; p = buf; if (!(opt & OPT_p)) { - /* skip address */ - while (isxdigit(*p)) p++; + char *end; + off_t ofs; + skip_address: + p = skip_whitespace(p); + ofs = BB_STRTOOFF(p, &end, 16); + if ((errno && errno != EINVAL) + || ofs < 0 + /* -s SEEK value should be added before seeking */ + || (ofs += opt_s_ofs) < 0 + ) { + bb_error_msg_and_die("invalid number '%s'", p); + } + if (ofs != cur) { + if (fseeko(stdout, ofs, SEEK_SET) != 0) { + if (ofs < cur) + bb_simple_perror_msg_and_die("cannot seek"); + write_zeros(ofs - cur); + } + cur = ofs; + } + p = end; /* NB: for xxd -r, first hex portion is address even without colon */ - /* If it's there, skip it: */ - if (*p == ':') p++; - -//TODO: seek (or zero-pad if unseekable) to the address position -//NOTE: -s SEEK value should be added to the address before seeking + /* But if colon is there, skip it: */ + if (*p == ':') + p++; } /* Process hex bytes optionally separated by whitespace */ for (;;) { uint8_t val, c; + int badchar = 0; nibble1: - p = skip_whitespace(p); - + if (opt & OPT_p) + p = skip_whitespace(p); c = *p++; if (isdigit(c)) val = c - '0'; else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') val = (c|0x20) - ('a' - 10); else { - /* xxd V1.10 is inconsistent here. + /* xxd V1.10 allows one non-hexnum char: * echo -e "31 !3 0a 0a" | xxd -r -p * is "10" (no ) - "!" is ignored, - * but + * but stops for more than one: * echo -e "31 !!343434\n30 0a" | xxd -r -p * is "10" - "!!" drops rest of the line. - * We will ignore all invalid chars: + * Note: this also covers whitespace chars: + * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? + * detects this ^ - skips this one space + * xxxxxxxx: 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f 0123456789:;<=>? + * detects this ^^ - skips the rest */ - if (c != '\0') - goto nibble1; - break; + if (c == '\0' || badchar) + break; + badchar++; + goto nibble1; } val <<= 4; - /* Works the same with xxd V1.10: - * echo "31 09 32 0a" | xxd -r -p - * echo "31 0 9 32 0a" | xxd -r -p - * thus allow whitespace even within the byte: - */ nibble2: - p = skip_whitespace(p); + if (opt & OPT_p) { + /* Works the same with xxd V1.10: + * echo "31 09 32 0a" | xxd -r -p + * echo "31 0 9 32 0a" | xxd -r -p + * thus allow whitespace (even multiple chars) + * after byte's 1st char: + */ + p = skip_whitespace(p); + } c = *p++; if (isdigit(c)) @@ -132,7 +182,16 @@ val |= (c|0x20) - ('a' - 10); else { if (c != '\0') { - /* "...3..." ignores both chars */ + /* "...3...": ignore "3", + * skip everything up to next hexchar or newline: + */ + while (!isxdigit(*p)) { + if (*p == '\0') { + free(buf); + goto get_new_line; + } + p++; + } goto nibble1; } /* Nibbles can join even through newline: @@ -143,14 +202,17 @@ p = buf = xmalloc_fgetline(fp); if (!buf) break; + if (!(opt & OPT_p)) /* -p and !-p: different behavior */ + goto skip_address; goto nibble2; } putchar(val); - } + cur++; + } /* for(;;) */ free(buf); } //fclose(fp); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } static void print_C_style(const char *p, const char *hdr) @@ -167,12 +229,15 @@ { char buf[80]; dumper_t *dumper; - char *opt_l, *opt_s, *opt_o; + char *opt_l, *opt_o; + char *opt_s = NULL; unsigned bytes = 2; unsigned cols = 0; unsigned opt; int r; + setup_common_bufsiz(); + dumper = alloc_dumper(); opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, @@ -200,7 +265,7 @@ } if (opt & OPT_r) { - reverse(opt, argv[0]); + reverse(opt, argv[0], opt_s); } if (opt & OPT_o) { diff -Nru busybox-1.35.0/util-linux/ipcs.c busybox-1.36.1/util-linux/ipcs.c --- busybox-1.35.0/util-linux/ipcs.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/ipcs.c 2023-01-03 14:14:43.000000000 +0000 @@ -600,15 +600,15 @@ id = xatoi(opt_i); if (opt & flag_shm) { print_shm(id); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } if (opt & flag_sem) { print_sem(id); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } if (opt & flag_msg) { print_msg(id); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } bb_show_usage(); } @@ -633,5 +633,5 @@ do_sem(format); bb_putchar('\n'); } - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/util-linux/last.c busybox-1.36.1/util-linux/last.c --- busybox-1.35.0/util-linux/last.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/last.c 2023-01-03 14:14:43.000000000 +0000 @@ -162,5 +162,5 @@ xlseek(file, pos, SEEK_SET); } - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/util-linux/last_fancy.c busybox-1.36.1/util-linux/last_fancy.c --- busybox-1.35.0/util-linux/last_fancy.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/last_fancy.c 2023-01-03 14:14:43.000000000 +0000 @@ -296,5 +296,5 @@ if (ENABLE_FEATURE_CLEAN_UP) close(file); - fflush_stdout_and_exit(EXIT_SUCCESS); + fflush_stdout_and_exit_SUCCESS(); } diff -Nru busybox-1.35.0/util-linux/mkfs_vfat.c busybox-1.36.1/util-linux/mkfs_vfat.c --- busybox-1.35.0/util-linux/mkfs_vfat.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/mkfs_vfat.c 2023-01-03 14:14:43.000000000 +0000 @@ -218,8 +218,11 @@ int mkfs_vfat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv) { + static const char NO_NAME_11[] = "NO NAME "; + struct stat st; - const char *volume_label = ""; + const char *arg_volume_label = NO_NAME_11; //default + char volume_label11[12]; char *buf; char *device_name; uoff_t volume_size_bytes; @@ -257,14 +260,17 @@ opts = getopt32(argv, "^" "Ab:cCf:F:h:Ii:l:m:n:r:R:s:S:v" "\0" "-1", //:b+:f+:F+:h+:r+:R+:s+:S+:vv:c--l:l--c - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, &volume_label, NULL, NULL, NULL, NULL); + /*b*/NULL, /*f*/NULL, /*F*/NULL, /*h*/NULL, /*i*/NULL, + /*l*/NULL, /*m*/NULL, /*n*/&arg_volume_label, + /*r*/NULL, /*R*/NULL, /*s*/NULL, /*S*/NULL); argv += optind; // cache device name device_name = argv[0]; // default volume ID = creation time volume_id = time(NULL); + // truncate to exactly 11 chars, pad with spaces + sprintf(volume_label11, "%-11.11s", arg_volume_label); dev = xopen(device_name, O_RDWR); xfstat(dev, &st, device_name); @@ -459,7 +465,7 @@ (int)media_byte, volume_size_sect, (int)total_clust, (int)sect_per_clust, sect_per_fat, - (int)volume_id, volume_label + (int)volume_id, volume_label11 ); } @@ -508,7 +514,7 @@ STORE_LE(boot_blk->vi.ext_boot_sign, 0x29); STORE_LE(boot_blk->vi.volume_id32, volume_id); memcpy(boot_blk->vi.fs_type, "FAT32 ", sizeof(boot_blk->vi.fs_type)); - strncpy(boot_blk->vi.volume_label, volume_label, sizeof(boot_blk->vi.volume_label)); + memcpy(boot_blk->vi.volume_label, volume_label11, 11); memcpy(boot_blk->boot_code, boot_code, sizeof(boot_code)); STORE_LE(boot_blk->boot_sign, BOOT_SIGN); @@ -545,15 +551,18 @@ // root directory // empty directory is just a set of zero bytes memset(buf, 0, sect_per_clust * bytes_per_sect); - if (volume_label[0]) { - // create dir entry for volume_label + // not "NO NAME", "NO NAME " etc? + // (mkfs.fat 4.1 won't create dir entry even with explicit -n 'NO NAME', + // but will create one with e.g. -n '', -n ' zZz') + if (strcmp(volume_label11, NO_NAME_11) != 0) { + // create dir entry for volume label struct msdos_dir_entry *de; #if 0 struct tm tm_time; uint16_t t, d; #endif de = (void*)buf; - strncpy(de->name, volume_label, sizeof(de->name)); + memcpy(de->name, volume_label11, 11); STORE_LE(de->attr, ATTR_VOLUME); #if 0 localtime_r(&create_time, &tm_time); diff -Nru busybox-1.35.0/util-linux/more.c busybox-1.36.1/util-linux/more.c --- busybox-1.35.0/util-linux/more.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/more.c 2023-01-03 14:14:43.000000000 +0000 @@ -84,11 +84,12 @@ /* Parse options */ /* Accepted but ignored: */ /* -d Display help instead of ringing bell */ + /* -e Exit immediately after writing the last line */ /* -f Count logical lines (IOW: long lines are not folded) */ /* -l Do not pause after any line containing a ^L (form feed) */ /* -s Squeeze blank lines into one */ /* -u Suppress underlining */ - getopt32(argv, "dflsu"); + getopt32(argv, "deflsu"); argv += optind; /* Another popular pager, most, detects when stdout diff -Nru busybox-1.35.0/util-linux/nsenter.c busybox-1.36.1/util-linux/nsenter.c --- busybox-1.35.0/util-linux/nsenter.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/nsenter.c 2023-01-03 14:14:43.000000000 +0000 @@ -93,7 +93,7 @@ * The user namespace comes first, so that it is entered first. * This gives an unprivileged user the potential to enter other namespaces. */ -static const struct namespace_descr ns_list[] = { +static const struct namespace_descr ns_list[] ALIGN_INT = { { CLONE_NEWUSER, "ns/user", }, { CLONE_NEWIPC, "ns/ipc", }, { CLONE_NEWUTS, "ns/uts", }, diff -Nru busybox-1.35.0/util-linux/taskset.c busybox-1.36.1/util-linux/taskset.c --- busybox-1.35.0/util-linux/taskset.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/taskset.c 2023-01-03 14:14:43.000000000 +0000 @@ -55,7 +55,6 @@ * Not yet implemented: * -a/--all-tasks (affect all threads) * needs to get TIDs from /proc/PID/task/ and use _them_ as "pid" in sched_setaffinity(pid) - * -c/--cpu-list (specify CPUs via "1,3,5-7") */ #include @@ -91,7 +90,7 @@ } #else #define TASKSET_PRINTF_MASK "%lx" -static unsigned long long from_mask(ul *mask, unsigned sz_in_bytes UNUSED_PARAM) +static unsigned long from_mask(ul *mask, unsigned sz_in_bytes UNUSED_PARAM) { return *mask; } diff -Nru busybox-1.35.0/util-linux/unshare.c busybox-1.36.1/util-linux/unshare.c --- busybox-1.35.0/util-linux/unshare.c 2021-12-26 16:53:21.000000000 +0000 +++ busybox-1.36.1/util-linux/unshare.c 2023-01-03 14:14:43.000000000 +0000 @@ -120,7 +120,7 @@ NS_USR_POS, /* OPT_user, NS_USR_POS, and ns_list[] index must match! */ NS_COUNT, }; -static const struct namespace_descr ns_list[] = { +static const struct namespace_descr ns_list[] ALIGN_INT = { { CLONE_NEWNS, "mnt" }, { CLONE_NEWUTS, "uts" }, { CLONE_NEWIPC, "ipc" },