From 89f063b900edf8b38c9dc05953887cf09b121378 Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Sun, 15 Nov 2020 20:25:09 +0100 Subject: chrt: support for musl C library musl "implements" several sched_xxx() functions by returning ENOSYS. As an alternative, either pthread_(g|s)etschedparam() or direct syscalls can be used. References: https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/commit/schedutils/chrt.c?id=fcc3078754291d2f5121797eb91b364f8e24b2f1 References: http://git.musl-libc.org/cgit/musl/commit/src/sched/sched_setscheduler.c?id=1e21e78bf7a5c24c217446d8760be7b7188711c2 Signed-off-by: Christian Eggers Signed-off-by: Denys Vlasenko --- util-linux/chrt.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/util-linux/chrt.c b/util-linux/chrt.c index 4dd78dabf..6e8f66741 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c @@ -39,6 +39,17 @@ # define SCHED_IDLE 5 #endif +//musl has no __MUSL__ or similar define to check for, +//but its has these lines: +// #define __NEED_fsblkcnt_t +// #define __NEED_fsfilcnt_t +#if defined(__linux__) && defined(__NEED_fsblkcnt_t) && defined(__NEED_fsfilcnt_t) +# define LIBC_IS_MUSL 1 +# include +#else +# define LIBC_IS_MUSL 0 +#endif + static const char *policy_name(int pol) { if (pol > 6) @@ -85,6 +96,7 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) char *priority = priority; /* for compiler */ const char *current_new; int policy = SCHED_RR; + int ret; opt = getopt32(argv, "^" "+" "mprfobi" @@ -132,7 +144,15 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_p) { int pol; print_rt_info: +#if LIBC_IS_MUSL + /* musl libc returns ENOSYS for its sched_getscheduler library + * function, because the sched_getscheduler Linux kernel system call + * does not conform to Posix; so we use the system call directly + */ + pol = syscall(SYS_sched_getscheduler, pid); +#else pol = sched_getscheduler(pid); +#endif if (pol < 0) bb_perror_msg_and_die("can't %cet pid %u's policy", 'g', (int)pid); #ifdef SCHED_RESET_ON_FORK @@ -149,7 +169,12 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) printf("pid %u's %s scheduling policy: SCHED_%s\n", pid, current_new, policy_name(pol) ); - if (sched_getparam(pid, &sp)) +#if LIBC_IS_MUSL + ret = syscall(SYS_sched_getparam, pid, &sp); +#else + ret = sched_getparam(pid, &sp); +#endif + if (ret) bb_perror_msg_and_die("can't get pid %u's attributes", (int)pid); printf("pid %u's %s scheduling priority: %d\n", (int)pid, current_new, sp.sched_priority @@ -168,7 +193,12 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) sched_get_priority_min(policy), sched_get_priority_max(policy) ); - if (sched_setscheduler(pid, policy, &sp) < 0) +#if LIBC_IS_MUSL + ret = syscall(SYS_sched_setscheduler, pid, policy, &sp); +#else + ret = sched_setscheduler(pid, policy, &sp); +#endif + if (ret) bb_perror_msg_and_die("can't %cet pid %u's policy", 's', (int)pid); if (!argv[0]) /* "-p PRIO PID [...]" */ -- cgit v1.2.3-55-g6feb From 5323af7f51808d5ff35c624ba70bdae4807f3717 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 16 Nov 2020 10:40:32 +0100 Subject: awk: fix dodgy multi-char separators splitting logic function old new delta awk_split 521 484 -37 Signed-off-by: Denys Vlasenko --- editors/awk.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/editors/awk.c b/editors/awk.c index f7451ae32..59dae4770 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -1765,10 +1765,9 @@ static void fsrealloc(int size) static int awk_split(const char *s, node *spl, char **slist) { - int l, n; + int n; char c[4]; char *s1; - regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... /* in worst case, each char would be a separate field */ *slist = s1 = xzalloc(strlen(s) * 2 + 3); @@ -1785,12 +1784,18 @@ static int awk_split(const char *s, node *spl, char **slist) return n; /* "": zero fields */ n++; /* at least one field will be there */ do { + int l; + regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... + l = strcspn(s, c+2); /* len till next NUL or \n */ if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0 && pmatch[0].rm_so <= l ) { l = pmatch[0].rm_so; if (pmatch[0].rm_eo == 0) { + /* For example, happens when FS can match + * an empthy string (awk -F ' *') + */ l++; pmatch[0].rm_eo++; } @@ -1800,14 +1805,16 @@ static int awk_split(const char *s, node *spl, char **slist) if (s[l]) pmatch[0].rm_eo++; } - memcpy(s1, s, l); - /* make sure we remove *all* of the separator chars */ - do { - s1[l] = '\0'; - } while (++l < pmatch[0].rm_eo); - nextword(&s1); + s1 = mempcpy(s1, s, l); + *s1++ = '\0'; s += pmatch[0].rm_eo; } while (*s); + + /* echo a-- | awk -F-- '{ print NF, length($NF), $NF }' + * should print "2 0 ": + */ + *s1 = '\0'; + return n; } if (c[0] == '\0') { /* null split */ @@ -2011,7 +2018,7 @@ static int ptest(node *pattern) static int awk_getline(rstream *rsm, var *v) { char *b; - regmatch_t pmatch[2]; + regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... int size, a, p, pp = 0; int fd, so, eo, r, rp; char c, *m, *s; -- cgit v1.2.3-55-g6feb From a4747230abfca9c5b5345d9e34574b4f3192be6a Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sat, 9 May 2020 13:03:55 +0200 Subject: login: update UTMP before forking /bin/login updates the preliminary UTMP record created by /bin/getty for $LOGNAME. However, if the PID of login is not the same as getty, then it will create a new entry. This causes GLIBC getlogin(3) to return the string 'LOGIN' (set by getty) instead of $LOGNAME. This affects tools like /usr/bin/logname but also various 3rd party PAM applications. Signed-off-by: Joachim Nilsson Signed-off-by: Denys Vlasenko --- loginutils/login.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/loginutils/login.c b/loginutils/login.c index 4e65b3a19..3531d1424 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -341,6 +341,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_LOGIN_SESSION_AS_CHILD pid_t child_pid; #endif + pid_t my_pid; INIT_G(); @@ -525,6 +526,9 @@ int login_main(int argc UNUSED_PARAM, char **argv) if (pw->pw_uid != 0) die_if_nologin(); + my_pid = getpid(); + update_utmp(my_pid, USER_PROCESS, short_tty, username, run_by_root ? opt_host : NULL); + #if ENABLE_LOGIN_SESSION_AS_CHILD child_pid = vfork(); if (child_pid != 0) { @@ -532,8 +536,8 @@ int login_main(int argc UNUSED_PARAM, char **argv) bb_simple_perror_msg("vfork"); else { wait_for_exitstatus(child_pid); - update_utmp_DEAD_PROCESS(child_pid); } + update_utmp_DEAD_PROCESS(my_pid); login_pam_end(pamh); return 0; } @@ -546,8 +550,6 @@ int login_main(int argc UNUSED_PARAM, char **argv) fchown(0, pw->pw_uid, pw->pw_gid); fchmod(0, 0600); - update_utmp(getpid(), USER_PROCESS, short_tty, username, run_by_root ? opt_host : NULL); - /* We trust environment only if we run by root */ if (ENABLE_LOGIN_SCRIPTS && run_by_root) run_login_script(pw, full_tty); -- cgit v1.2.3-55-g6feb From efe99b59c6cd3d9de91ebfc39f9870b8708e5b92 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sat, 9 May 2020 16:49:24 +0200 Subject: syslogd: delay PID file creation until syslogd is ready This patch moves the creation of the PID file until after syslogd has set up signal handlers and is ready. Signed-off-by: Joachim Nilsson Signed-off-by: Denys Vlasenko --- sysklogd/syslogd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index f61da9de5..598f28d0c 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -1034,6 +1034,7 @@ static void do_syslogd(void) kmsg_init(); timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER); + write_pidfile_std_path_and_ext("syslogd"); while (!bb_got_signal) { ssize_t sz; @@ -1182,9 +1183,6 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv) bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); } - //umask(0); - why?? - write_pidfile_std_path_and_ext("syslogd"); - do_syslogd(); /* return EXIT_SUCCESS; */ } -- cgit v1.2.3-55-g6feb From dc9c10a7b29c93a36ff17c562cb14e11eb169f19 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 16 Nov 2020 13:00:44 +0100 Subject: hush: make interactive ^C break out of PS2 mode function old new delta syntax_error_unterm_str - 26 +26 parse_stream 2238 2251 +13 fgetc_interactive 243 249 +6 parse_dollar 824 817 -7 syntax_error_unterm_ch 29 21 -8 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/2 up/down: 45/-15) Total: 30 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 86 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index ab7263381..f1a7e07ee 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -916,6 +916,9 @@ struct globals { char opt_c; #if ENABLE_HUSH_INTERACTIVE smallint promptmode; /* 0: PS1, 1: PS2 */ +# if ENABLE_FEATURE_EDITING + smallint flag_ctrlC; /* when set, suppresses syntax error messages */ +# endif #endif smallint flag_SIGINT; #if ENABLE_HUSH_LOOPS @@ -1425,7 +1428,10 @@ static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg) static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s) { - bb_error_msg("syntax error: unterminated %s", s); +#if ENABLE_FEATURE_EDITING + if (!G.flag_ctrlC) +#endif + bb_error_msg("syntax error: unterminated %s", s); //? source4.tests fails: in bash, echo ${^} in script does not terminate the script // die_if_script(); } @@ -2629,26 +2635,27 @@ static int get_user_input(struct in_str *i) # if ENABLE_FEATURE_EDITING for (;;) { reinit_unicode_for_hush(); - if (G.flag_SIGINT) { - /* There was ^C'ed, make it look prettier: */ - bb_putchar('\n'); - G.flag_SIGINT = 0; - } + G.flag_SIGINT = 0; /* buglet: SIGINT will not make new prompt to appear _at once_, * only after . (^C works immediately) */ 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) + if (r == 0) { + G.flag_ctrlC = 1; raise(SIGINT); + } check_and_run_traps(); if (r != 0 && !G.flag_SIGINT) break; - /* ^C or SIGINT: repeat */ + /* ^C or SIGINT: return EOF */ /* bash prints ^C even on real SIGINT (non-kbd generated) */ - write(STDOUT_FILENO, "^C", 2); + write(STDOUT_FILENO, "^C\n", 3); G.last_exitcode = 128 + SIGINT; + i->p = NULL; + i->peek_buf[0] = r = EOF; + return r; } if (r < 0) { /* EOF/error detected */ @@ -5260,22 +5267,31 @@ static struct pipe *parse_stream(char **pstring, ch, ch, !!(ctx.word.o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); if (ch == EOF) { struct pipe *pi; - +#if ENABLE_FEATURE_EDITING + if (G.flag_ctrlC) { + /* testcase: interactively entering + * 'qwe ^C + * should not leave input in PS2 mode, waiting to close single quote. + */ + G.flag_ctrlC = 0; + goto parse_error; + } +#endif if (heredoc_cnt) { syntax_error_unterm_str("here document"); - goto parse_error; + goto parse_error_exitcode1; } if (end_trigger == ')') { syntax_error_unterm_ch('('); - goto parse_error; + goto parse_error_exitcode1; } if (end_trigger == '}') { syntax_error_unterm_ch('{'); - goto parse_error; + goto parse_error_exitcode1; } if (done_word(&ctx)) { - goto parse_error; + goto parse_error_exitcode1; } o_free_and_set_NULL(&ctx.word); done_pipe(&ctx, PIPE_SEQ); @@ -5345,7 +5361,7 @@ static struct pipe *parse_stream(char **pstring, while (1) { if (ch == EOF) { syntax_error_unterm_ch('\''); - goto parse_error; + goto parse_error_exitcode1; } nommu_addchr(&ctx.as_string, ch); if (ch == '\'') @@ -5424,7 +5440,7 @@ static struct pipe *parse_stream(char **pstring, /* ch == last eaten whitespace char */ #endif if (done_word(&ctx)) { - goto parse_error; + goto parse_error_exitcode1; } if (ch == '\n') { /* Is this a case when newline is simply ignored? @@ -5467,7 +5483,7 @@ static struct pipe *parse_stream(char **pstring, if (heredoc_cnt) { heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input); if (heredoc_cnt != 0) - goto parse_error; + goto parse_error_exitcode1; } ctx.is_assignment = MAYBE_ASSIGNMENT; debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]); @@ -5517,7 +5533,7 @@ static struct pipe *parse_stream(char **pstring, #endif ) { if (done_word(&ctx)) { - goto parse_error; + goto parse_error_exitcode1; } done_pipe(&ctx, PIPE_SEQ); ctx.is_assignment = MAYBE_ASSIGNMENT; @@ -5538,7 +5554,7 @@ static struct pipe *parse_stream(char **pstring, /* Example: bare "{ }", "()" */ G.last_exitcode = 2; /* bash compat */ syntax_error_unexpected_ch(ch); - goto parse_error2; + goto parse_error; } if (heredoc_cnt_ptr) *heredoc_cnt_ptr = heredoc_cnt; @@ -5560,7 +5576,7 @@ static struct pipe *parse_stream(char **pstring, case '>': redir_fd = redirect_opt_num(&ctx.word); if (done_word(&ctx)) { - goto parse_error; + goto parse_error_exitcode1; } redir_style = REDIRECT_OVERWRITE; if (next == '>') { @@ -5571,16 +5587,16 @@ static struct pipe *parse_stream(char **pstring, #if 0 else if (next == '(') { syntax_error(">(process) not supported"); - goto parse_error; + goto parse_error_exitcode1; } #endif if (parse_redirect(&ctx, redir_fd, redir_style, input)) - goto parse_error; + goto parse_error_exitcode1; continue; /* get next char */ case '<': redir_fd = redirect_opt_num(&ctx.word); if (done_word(&ctx)) { - goto parse_error; + goto parse_error_exitcode1; } redir_style = REDIRECT_INPUT; if (next == '<') { @@ -5597,11 +5613,11 @@ static struct pipe *parse_stream(char **pstring, #if 0 else if (next == '(') { syntax_error("<(process) not supported"); - goto parse_error; + goto parse_error_exitcode1; } #endif if (parse_redirect(&ctx, redir_fd, redir_style, input)) - goto parse_error; + goto parse_error_exitcode1; continue; /* get next char */ case '#': if (ctx.word.length == 0 && !ctx.word.has_quoted_part) { @@ -5655,7 +5671,7 @@ static struct pipe *parse_stream(char **pstring, if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { debug_printf_parse("parse_stream parse error: " "parse_dollar returned 0 (error)\n"); - goto parse_error; + goto parse_error_exitcode1; } continue; /* get next char */ case '"': @@ -5671,7 +5687,7 @@ static struct pipe *parse_stream(char **pstring, if (ctx.is_assignment == NOT_ASSIGNMENT) ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; if (!encode_string(&ctx.as_string, &ctx.word, input, '"')) - goto parse_error; + goto parse_error_exitcode1; ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; continue; /* get next char */ #if ENABLE_HUSH_TICK @@ -5682,7 +5698,7 @@ static struct pipe *parse_stream(char **pstring, o_addchr(&ctx.word, '`'); USE_FOR_NOMMU(pos = ctx.word.length;) if (!add_till_backquote(&ctx.word, input, /*in_dquote:*/ 0)) - goto parse_error; + goto parse_error_exitcode1; # if !BB_MMU o_addstr(&ctx.as_string, ctx.word.data + pos); o_addchr(&ctx.as_string, '`'); @@ -5697,7 +5713,7 @@ static struct pipe *parse_stream(char **pstring, case_semi: #endif if (done_word(&ctx)) { - goto parse_error; + goto parse_error_exitcode1; } done_pipe(&ctx, PIPE_SEQ); #if ENABLE_HUSH_CASE @@ -5724,7 +5740,7 @@ static struct pipe *parse_stream(char **pstring, continue; /* get next char */ case '&': if (done_word(&ctx)) { - goto parse_error; + goto parse_error_exitcode1; } if (next == '&') { ch = i_getch(input); @@ -5736,7 +5752,7 @@ static struct pipe *parse_stream(char **pstring, goto new_cmd; case '|': if (done_word(&ctx)) { - goto parse_error; + goto parse_error_exitcode1; } #if ENABLE_HUSH_CASE if (ctx.ctx_res_w == RES_MATCH) @@ -5768,7 +5784,7 @@ static struct pipe *parse_stream(char **pstring, case '{': { int n = parse_group(&ctx, input, ch); if (n < 0) { - goto parse_error; + goto parse_error_exitcode1; } debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n); heredoc_cnt += n; @@ -5786,16 +5802,16 @@ static struct pipe *parse_stream(char **pstring, * and it will match } earlier (not here). */ G.last_exitcode = 2; syntax_error_unexpected_ch(ch); - goto parse_error2; + goto parse_error; default: if (HUSH_DEBUG) bb_error_msg_and_die("BUG: unexpected %c", ch); } } /* while (1) */ - parse_error: + parse_error_exitcode1: G.last_exitcode = 1; - parse_error2: + parse_error: { struct parse_context *pctx; IF_HAS_KEYWORDS(struct parse_context *p2;) -- cgit v1.2.3-55-g6feb From 4ac35a30db0c9badd9895c5eaa1d4d3a118b5259 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 16 Nov 2020 13:09:37 +0100 Subject: ash: make interactive ^C break out of PS2 mode Based on patch by Joachim Nilsson function old new delta pgetc 570 547 -23 Signed-off-by: Denys Vlasenko --- shell/ash.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 674a41bd3..d1ca3451d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10593,7 +10593,7 @@ preadfd(void) g_parsefile->next_to_pgetc = buf; #if ENABLE_FEATURE_EDITING - retry: + /* retry: */ if (!iflag || g_parsefile->pf_fd != STDIN_FILENO) nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1); else { @@ -10615,15 +10615,14 @@ preadfd(void) if (nr == 0) { /* ^C pressed, "convert" to SIGINT */ write(STDOUT_FILENO, "^C", 2); + raise(SIGINT); if (trap[SIGINT]) { buf[0] = '\n'; buf[1] = '\0'; - raise(SIGINT); return 1; } exitstatus = 128 + SIGINT; - bb_putchar('\n'); - goto retry; + return -1; } if (nr < 0) { if (errno == 0) { -- cgit v1.2.3-55-g6feb From bd46f64dcb2cf4f37c2cbfeb808f4e380d9d5931 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sat, 9 May 2020 13:31:33 +0200 Subject: archival: avoid std namespace for local includes Avoid using same include file naming pattern as available in GLIBC. Renamed to match grp_.h et al. Signed-off-by: Joachim Nilsson Signed-off-by: Denys Vlasenko --- archival/ar.c | 2 +- archival/libarchive/get_header_ar.c | 2 +- archival/libarchive/unpack_ar_archive.c | 2 +- include/ar.h | 26 -------------------------- include/ar_.h | 26 ++++++++++++++++++++++++++ 5 files changed, 29 insertions(+), 29 deletions(-) delete mode 100644 include/ar.h create mode 100644 include/ar_.h diff --git a/archival/ar.c b/archival/ar.c index f4edeb087..2839d85d5 100644 --- a/archival/ar.c +++ b/archival/ar.c @@ -60,7 +60,7 @@ #include "libbb.h" #include "bb_archive.h" -#include "ar.h" +#include "ar_.h" #if ENABLE_FEATURE_AR_CREATE /* filter out entries with same names as specified on the command line */ diff --git a/archival/libarchive/get_header_ar.c b/archival/libarchive/get_header_ar.c index b6ecd596c..3a19d6ff7 100644 --- a/archival/libarchive/get_header_ar.c +++ b/archival/libarchive/get_header_ar.c @@ -6,7 +6,7 @@ */ #include "libbb.h" #include "bb_archive.h" -#include "ar.h" +#include "ar_.h" /* WARNING: Clobbers str[len], so fields must be read in reverse order! */ static unsigned read_num(char *str, int base, int len) diff --git a/archival/libarchive/unpack_ar_archive.c b/archival/libarchive/unpack_ar_archive.c index 584c18ce8..125d424c9 100644 --- a/archival/libarchive/unpack_ar_archive.c +++ b/archival/libarchive/unpack_ar_archive.c @@ -4,7 +4,7 @@ */ #include "libbb.h" #include "bb_archive.h" -#include "ar.h" +#include "ar_.h" void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive) { diff --git a/include/ar.h b/include/ar.h deleted file mode 100644 index 386fe0456..000000000 --- a/include/ar.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * busybox ar archive data structures - * Licensed under GPLv2 or later, see file LICENSE in this source tree. - */ -#ifndef AR_H -#define AR_H - -PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN - -struct ar_header { - char name[16]; - char date[12]; - char uid[6]; - char gid[6]; - char mode[8]; - char size[10]; - char magic[2]; -}; - -#define AR_HEADER_LEN sizeof(struct ar_header) -#define AR_MAGIC "!" -#define AR_MAGIC_LEN 7 - -POP_SAVED_FUNCTION_VISIBILITY - -#endif diff --git a/include/ar_.h b/include/ar_.h new file mode 100644 index 000000000..386fe0456 --- /dev/null +++ b/include/ar_.h @@ -0,0 +1,26 @@ +/* + * busybox ar archive data structures + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ +#ifndef AR_H +#define AR_H + +PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN + +struct ar_header { + char name[16]; + char date[12]; + char uid[6]; + char gid[6]; + char mode[8]; + char size[10]; + char magic[2]; +}; + +#define AR_HEADER_LEN sizeof(struct ar_header) +#define AR_MAGIC "!" +#define AR_MAGIC_LEN 7 + +POP_SAVED_FUNCTION_VISIBILITY + +#endif -- cgit v1.2.3-55-g6feb From c20e42e320edcd3612cfdb71c8bea5277ebf9be2 Mon Sep 17 00:00:00 2001 From: Norbert Lange Date: Mon, 13 Jul 2020 17:22:27 +0200 Subject: util-linux: support erofs filesystem Add erofs to the known volume_ids. function old new delta volume_id_probe_erofs - 89 +89 fs1 24 28 +4 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 1/0 up/down: 93/0) Total: 93 bytes Signed-off-by: Norbert Lange Signed-off-by: Denys Vlasenko --- util-linux/volume_id/erofs.c | 67 +++++++++++++++++++++++++++++++ util-linux/volume_id/volume_id.c | 3 ++ util-linux/volume_id/volume_id_internal.h | 2 + 3 files changed, 72 insertions(+) create mode 100644 util-linux/volume_id/erofs.c diff --git a/util-linux/volume_id/erofs.c b/util-linux/volume_id/erofs.c new file mode 100644 index 000000000..a163a353d --- /dev/null +++ b/util-linux/volume_id/erofs.c @@ -0,0 +1,67 @@ +/* + * volume_id - reads filesystem label and uuid + * + * Copyright (C) 2020 Norbert Lange + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//config:config FEATURE_VOLUMEID_EROFS +//config: bool "erofs filesystem" +//config: default y +//config: depends on VOLUMEID +//config: help +//config: Erofs is a compressed readonly filesystem for Linux. + +//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EROFS) += erofs.o + +#include "volume_id_internal.h" + +#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 +#define EROFS_SUPER_OFFSET 1024 +#define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 + +/* 128-byte erofs on-disk super block */ +struct erofs_super_block { + uint32_t magic; /* file system magic number */ + uint32_t checksum; /* crc32c(super_block) */ + uint32_t feature_compat; + uint8_t blkszbits; /* support block_size == PAGE_SIZE only */ + uint8_t reserved; + + uint16_t root_nid; /* nid of root directory */ + uint64_t inos; /* total valid ino # (== f_files - f_favail) */ + + uint64_t build_time; /* inode v1 time derivation */ + uint32_t build_time_nsec; /* inode v1 time derivation in nano scale */ + uint32_t blocks; /* used for statfs */ + uint32_t meta_blkaddr; /* start block address of metadata area */ + uint32_t xattr_blkaddr; /* start block address of shared xattr area */ + uint8_t uuid[16]; /* 128-bit uuid for volume */ + uint8_t volume_name[16]; /* volume name */ + uint32_t feature_incompat; + uint8_t reserved2[44]; +} PACKED; + +int FAST_FUNC volume_id_probe_erofs(struct volume_id *id /*,uint64_t off*/) +{ + struct erofs_super_block *sb; + + BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128); + + dbg("erofs: probing at offset 0x%llx", EROFS_SUPER_OFFSET); + sb = volume_id_get_buffer(id, EROFS_SUPER_OFFSET, sizeof(*sb)); + if (!sb) + return -1; + + if (sb->magic != cpu_to_le32(EROFS_SUPER_MAGIC_V1)) + return -1; + + IF_FEATURE_BLKID_TYPE(id->type = "erofs"); + + volume_id_set_label_string(id, sb->volume_name, + MIN(sizeof(sb->volume_name), VOLUME_ID_LABEL_SIZE)); + + volume_id_set_uuid(id, sb->uuid, UUID_DCE); + + return 0; +} diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c index c3f07a741..99150a5b7 100644 --- a/util-linux/volume_id/volume_id.c +++ b/util-linux/volume_id/volume_id.c @@ -106,6 +106,9 @@ static const probe_fptr fs1[] = { #if ENABLE_FEATURE_VOLUMEID_SQUASHFS volume_id_probe_squashfs, #endif +#if ENABLE_FEATURE_VOLUMEID_EROFS + volume_id_probe_erofs, +#endif #if ENABLE_FEATURE_VOLUMEID_XFS volume_id_probe_xfs, #endif diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index ada18339d..609beb84e 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h @@ -215,6 +215,8 @@ int FAST_FUNC volume_id_probe_romfs(struct volume_id *id /*,uint64_t off*/); int FAST_FUNC volume_id_probe_squashfs(struct volume_id *id /*,uint64_t off*/); +int FAST_FUNC volume_id_probe_erofs(struct volume_id *id /*,uint64_t off*/); + int FAST_FUNC volume_id_probe_sysv(struct volume_id *id /*,uint64_t off*/); int FAST_FUNC volume_id_probe_udf(struct volume_id *id /*,uint64_t off*/); -- cgit v1.2.3-55-g6feb From ddfdf68ca1d925712a042700118e29f26137f9bd Mon Sep 17 00:00:00 2001 From: Cristian Ionescu-Idbohrn Date: Wed, 18 Nov 2020 10:41:14 +0100 Subject: fix warning: label 'out1' defined but not used Signed-off-by: Cristian Ionescu-Idbohrn Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/ash.c b/shell/ash.c index d1ca3451d..8c9a590d1 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7277,7 +7277,9 @@ subevalvar(char *start, char *str, int strloc, out: amount = loc - expdest; STADJUST(amount, expdest); +#if BASH_PATTERN_SUBST out1: +#endif /* Remove any recorded regions beyond start of variable */ removerecordregions(startloc); -- cgit v1.2.3-55-g6feb From 2c92d1ec5802084e3bab336c5cd5816df88cb44d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Nov 2020 13:58:25 +0100 Subject: volume_id: improve struct layout (smaller offesets, smaller insns on x86) function old new delta volume_id_probe_xfs 101 98 -3 volume_id_probe_vfat 827 824 -3 volume_id_probe_udf 541 538 -3 volume_id_probe_ubifs 67 64 -3 volume_id_probe_squashfs 86 83 -3 volume_id_probe_romfs 97 94 -3 volume_id_probe_reiserfs 246 243 -3 volume_id_probe_ocfs2 110 107 -3 volume_id_probe_ntfs 288 285 -3 volume_id_probe_nilfs 100 97 -3 volume_id_probe_minix 85 82 -3 volume_id_probe_luks 92 89 -3 volume_id_probe_linux_swap 251 248 -3 volume_id_probe_linux_raid 131 128 -3 volume_id_probe_lfs 62 59 -3 volume_id_probe_jfs 110 107 -3 volume_id_probe_iso9660 318 315 -3 volume_id_probe_f2fs 107 104 -3 volume_id_probe_exfat 285 282 -3 volume_id_probe_erofs 89 86 -3 volume_id_probe_cramfs 67 64 -3 volume_id_probe_btrfs 134 131 -3 volume_id_probe_bcache 107 104 -3 volume_id_probe_sysv 194 188 -6 volume_id_probe_hfs_hfsplus 518 512 -6 add_to_uuid_cache 271 265 -6 volume_id_probe_ext 131 122 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/27 up/down: 0/-96) Total: -96 bytes Signed-off-by: Denys Vlasenko --- util-linux/volume_id/volume_id_internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index 609beb84e..b1e44481f 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h @@ -66,6 +66,9 @@ struct volume_id { uint8_t *sbbuf; uint8_t *seekbuf; uint64_t seekbuf_off; +#if ENABLE_FEATURE_BLKID_TYPE + const char *type; +#endif #ifdef UNUSED_PARTITION_CODE struct volume_id_partition *partitions; size_t partition_count; @@ -80,9 +83,6 @@ struct volume_id { // char type_version[VOLUME_ID_FORMAT_SIZE]; // smallint usage_id; // const char *usage; -#if ENABLE_FEATURE_BLKID_TYPE - const char *type; -#endif }; struct volume_id* FAST_FUNC volume_id_open_node(int fd); -- cgit v1.2.3-55-g6feb From 4323ac861ee5bb46051fada403971576356c928c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 21 Nov 2020 17:23:13 +0100 Subject: libiproute: reuse string constants text data bss dec hex filename 1020826 559 5052 1026437 fa985 busybox_old 1020815 559 5052 1026426 fa97a busybox_unstripped Signed-off-by: Denys Vlasenko --- networking/libiproute/rtm_map.c | 53 +++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/networking/libiproute/rtm_map.c b/networking/libiproute/rtm_map.c index e94c99ab6..8b94c2f24 100644 --- a/networking/libiproute/rtm_map.c +++ b/networking/libiproute/rtm_map.c @@ -11,33 +11,55 @@ #include "rt_names.h" #include "utils.h" +static const char keywords[] ALIGN1 = + "local\0""nat\0""broadcast\0""brd\0""anycast\0" + "multicast\0""prohibit\0""unreachable\0""blackhole\0" + "xresolve\0""unicast\0""throw\0"; +enum { + ARG_local = 1, ARG_nat, ARG_broadcast, ARG_brd, ARG_anycast, + ARG_multicast, ARG_prohibit, ARG_unreachable, ARG_blackhole, + ARG_xresolve, ARG_unicast, ARG_throw +}; +#define str_local keywords +#define str_nat (str_local + sizeof("local")) +#define str_broadcast (str_nat + sizeof("nat")) +#define str_brd (str_broadcast + sizeof("broadcast")) +#define str_anycast (str_brd + sizeof("brd")) +#define str_multicast (str_anycast + sizeof("anycast")) +#define str_prohibit (str_multicast + sizeof("multicast")) +#define str_unreachable (str_prohibit + sizeof("prohibit")) +#define str_blackhole (str_unreachable + sizeof("unreachable")) +#define str_xresolve (str_blackhole + sizeof("blackhole")) +#define str_unicast (str_xresolve + sizeof("xresolve")) +#define str_throw (str_unicast + sizeof("unicast")) + const char* FAST_FUNC rtnl_rtntype_n2a(int id) { switch (id) { case RTN_UNSPEC: return "none"; case RTN_UNICAST: - return "unicast"; + return str_unicast; case RTN_LOCAL: - return "local"; + return str_local; case RTN_BROADCAST: - return "broadcast"; + return str_broadcast; case RTN_ANYCAST: - return "anycast"; + return str_anycast; case RTN_MULTICAST: - return "multicast"; + return str_multicast; case RTN_BLACKHOLE: - return "blackhole"; + return str_blackhole; case RTN_UNREACHABLE: - return "unreachable"; + return str_unreachable; case RTN_PROHIBIT: - return "prohibit"; + return str_prohibit; case RTN_THROW: - return "throw"; + return str_throw; case RTN_NAT: - return "nat"; + return str_nat; case RTN_XRESOLVE: - return "xresolve"; + return str_xresolve; default: return itoa(id); } @@ -45,15 +67,6 @@ const char* FAST_FUNC rtnl_rtntype_n2a(int id) int FAST_FUNC rtnl_rtntype_a2n(int *id, char *arg) { - static const char keywords[] ALIGN1 = - "local\0""nat\0""broadcast\0""brd\0""anycast\0" - "multicast\0""prohibit\0""unreachable\0""blackhole\0" - "xresolve\0""unicast\0""throw\0"; - enum { - ARG_local = 1, ARG_nat, ARG_broadcast, ARG_brd, ARG_anycast, - ARG_multicast, ARG_prohibit, ARG_unreachable, ARG_blackhole, - ARG_xresolve, ARG_unicast, ARG_throw - }; const smalluint key = index_in_substrings(keywords, arg) + 1; char *end; unsigned long res; -- cgit v1.2.3-55-g6feb From 9bf4499dd7c72db7636555ec386804540a3266fe Mon Sep 17 00:00:00 2001 From: Audun-Marius Gangstø Date: Sat, 21 Nov 2020 12:26:39 +0100 Subject: lineedit: fix unicode characters in prompt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit function old new delta parse_and_put_prompt 779 823 +44 Signed-off-by: Audun-Marius Gangstø Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index e40a72064..a3b798e3f 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2029,10 +2029,17 @@ static void parse_and_put_prompt(const char *prmt_ptr) if (c == '\n') cmdedit_prmt_len = 0; else if (flg_not_length != ']') { -#if 0 /*ENABLE_UNICODE_SUPPORT*/ -/* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */ -/* FIXME */ - cmdedit_prmt_len += unicode_strwidth(pbuf); +#if ENABLE_UNICODE_SUPPORT + if (n == 1) { + /* Only count single-byte characters and the first of multi-byte characters */ + if ((unsigned char)*pbuf < 0x80 /* single byte character */ + || (unsigned char)*pbuf >= 0xc0 /* first of multi-byte characters */ + ) { + cmdedit_prmt_len += n; + } + } else { + cmdedit_prmt_len += unicode_strwidth(pbuf); + } #else cmdedit_prmt_len += n; #endif -- cgit v1.2.3-55-g6feb From 12aa68d10fdcc5bd2d9385506d11aed3a0c2eaf1 Mon Sep 17 00:00:00 2001 From: Jan Klötzke Date: Mon, 16 Dec 2019 22:56:49 +0100 Subject: libbb: set netlink socket revbuf size before binding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As soon as the socket is bound it will receive messages. Make sure the recieve buffer size is increased before the first message is received. Signed-off-by: Jan Klötzke Signed-off-by: Denys Vlasenko --- libbb/xconnect.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/libbb/xconnect.c b/libbb/xconnect.c index e9a2470e4..5dd9cfd28 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c @@ -422,17 +422,14 @@ int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf) struct sockaddr_nl sa; int fd; - memset(&sa, 0, sizeof(sa)); - sa.nl_family = AF_NETLINK; - sa.nl_pid = getpid(); - sa.nl_groups = grp; fd = xsocket(AF_NETLINK, SOCK_DGRAM, proto); - xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); - close_on_exec_on(fd); + /* Set receive buffer size before binding the socket + * We want to have enough space before we start receiving messages. + */ if (rcvbuf != 0) { - // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl - setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, rcvbuf); + setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, rcvbuf); + /* SO_RCVBUFFORCE (root only) can go above net.core.rmem_max */ setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, rcvbuf); # if 0 { @@ -444,6 +441,13 @@ int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf) # endif } + memset(&sa, 0, sizeof(sa)); + sa.nl_family = AF_NETLINK; + sa.nl_pid = getpid(); + sa.nl_groups = grp; + xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); + close_on_exec_on(fd); + return fd; } #endif -- cgit v1.2.3-55-g6feb From 3cd55d49a2ee5d74f019b1a4c32ab28a9ce5e1d3 Mon Sep 17 00:00:00 2001 From: Jan Klötzke Date: Mon, 16 Dec 2019 22:56:50 +0100 Subject: mdev: increase netlink buffer sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The socket receive buffer turned out to be too small for real world systems. Use the same size as udevd to be on the safe side. As this is just a limit and the memory is not allocated by the kernel until really needed there is actually no memory wasted. Signed-off-by: Jan Klötzke Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 59dbcf0cd..8b06d3456 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -269,10 +269,6 @@ # define dbg3s(msg) ((void)0) #endif - -#ifndef SO_RCVBUFFORCE -#define SO_RCVBUFFORCE 33 -#endif static const char keywords[] ALIGN1 = "add\0remove\0"; // "change\0" enum { OP_add, OP_remove }; @@ -1152,15 +1148,27 @@ static void initial_scan(char *temp) #if ENABLE_FEATURE_MDEV_DAEMON -/* uevent applet uses 16k buffer, and mmaps it before every read */ -# define BUFFER_SIZE (2 * 1024) -# define RCVBUF (2 * 1024 * 1024) +/* + * The kernel (as of v5.4) will pass up to 32 environment variables with a + * total of 2kiB on each event. On top of that the action string and device + * path are added. Using a 3kiB buffer for the event should suffice in any + * case. + * + * As far as the socket receive buffer size is concerned 2MiB proved to be too + * small (see [1]). Udevd seems to use a whooping 128MiB. The socket receive + * buffer size is just a resource limit. The buffers are allocated lazily so + * the memory is not wasted. + * + * [1] http://lists.busybox.net/pipermail/busybox/2019-December/087665.html + */ +# define USER_RCVBUF (3 * 1024) +# define KERN_RCVBUF (128 * 1024 * 1024) # define MAX_ENV 32 static void daemon_loop(char *temp, int fd) { for (;;) { - char netbuf[BUFFER_SIZE]; + char netbuf[USER_RCVBUF]; char *env[MAX_ENV]; char *s, *end; ssize_t len; @@ -1237,7 +1245,7 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) * mdev -d * find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' */ - fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, RCVBUF); + fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, KERN_RCVBUF); /* * Make inital scan after the uevent socket is alive and -- cgit v1.2.3-55-g6feb From a569fd37fec970d8aeebca1c34a964502072d817 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Nov 2020 13:34:07 +0100 Subject: uevent: increase netlink buffer sizes Signed-off-by: Denys Vlasenko --- util-linux/uevent.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/util-linux/uevent.c b/util-linux/uevent.c index 57d9328ef..2f1135f0c 100644 --- a/util-linux/uevent.c +++ b/util-linux/uevent.c @@ -26,8 +26,6 @@ #include "common_bufsiz.h" #include -#define BUFFER_SIZE 16*1024 - #define env ((char **)bb_common_bufsiz1) #define INIT_G() do { setup_common_bufsiz(); } while (0) enum { @@ -37,10 +35,16 @@ enum { */ }; -#ifndef SO_RCVBUFFORCE -#define SO_RCVBUFFORCE 33 -#endif -enum { RCVBUF = 2 * 1024 * 1024 }; +enum { + /* socket receive buffer of 2MiB proved to be too small: + * http://lists.busybox.net/pipermail/busybox/2019-December/087665.html + * Udevd seems to use a whooping 128MiB. + * The socket receive buffer size is just a resource limit. + * The buffers are allocated lazily so the memory is not wasted. + */ + KERN_RCVBUF = 128 * 1024 * 1024, + USER_RCVBUF = 16 * 1024, +}; int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int uevent_main(int argc UNUSED_PARAM, char **argv) @@ -57,7 +61,7 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) // Reproducer: // uevent mdev & // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' - fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, RCVBUF); + fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, KERN_RCVBUF); for (;;) { char *netbuf; @@ -69,7 +73,7 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) // for a new uevent notification to come in. // We use a fresh mmap so that buffer is not allocated // until kernel actually starts filling it. - netbuf = mmap(NULL, BUFFER_SIZE, + netbuf = mmap(NULL, USER_RCVBUF, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, /* ignored: */ -1, 0); @@ -77,7 +81,7 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) bb_simple_perror_msg_and_die("mmap"); // Here we block, possibly for a very long time - len = safe_read(fd, netbuf, BUFFER_SIZE - 1); + len = safe_read(fd, netbuf, USER_RCVBUF - 1); if (len < 0) bb_simple_perror_msg_and_die("read"); end = netbuf + len; @@ -108,7 +112,7 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) while (env[idx]) bb_unsetenv(env[idx++]); } - munmap(netbuf, BUFFER_SIZE); + munmap(netbuf, USER_RCVBUF); } return 0; // not reached -- cgit v1.2.3-55-g6feb From e3f4759019544673d654ad8a1ea256ed481fa5e3 Mon Sep 17 00:00:00 2001 From: Jan Klötzke Date: Sun, 22 Nov 2020 14:17:56 +0100 Subject: mdev: move daemon setup to dedicated function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Klötzke Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 8b06d3456..4c00a2d7e 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -1165,6 +1165,29 @@ static void initial_scan(char *temp) # define KERN_RCVBUF (128 * 1024 * 1024) # define MAX_ENV 32 +static int daemon_init(char *temp) +{ + int fd; + + /* Subscribe for UEVENT kernel messages */ + /* Without a sufficiently big RCVBUF, a ton of simultaneous events + * can trigger ENOBUFS on read, which is unrecoverable. + * Reproducer: + * mdev -d + * find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' + */ + fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, KERN_RCVBUF); + + /* + * Make inital scan after the uevent socket is alive and + * _before_ we fork away. Already open mdev.log because we work + * in daemon mode. + */ + initial_scan(temp); + + return fd; +} + static void daemon_loop(char *temp, int fd) { for (;;) { @@ -1234,24 +1257,11 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_MDEV_DAEMON if (opt & MDEV_OPT_DAEMON) { /* - * Daemon mode listening on uevent netlink socket. - */ - int fd; - - /* Subscribe for UEVENT kernel messages */ - /* Without a sufficiently big RCVBUF, a ton of simultaneous events - * can trigger ENOBUFS on read, which is unrecoverable. - * Reproducer: - * mdev -d - * find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' - */ - fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, KERN_RCVBUF); - - /* - * Make inital scan after the uevent socket is alive and - * _before_ we fork away. + * Daemon mode listening on uevent netlink socket. Fork away + * after initial scan so that caller can be sure everything + * is up-to-date when mdev process returns. */ - initial_scan(temp); + int fd = daemon_init(temp); if (!(opt & MDEV_OPT_FOREGROUND)) bb_daemonize_or_rexec(0, argv); -- cgit v1.2.3-55-g6feb From d560030548cb237f9ef09a82fd6f372836655306 Mon Sep 17 00:00:00 2001 From: Jan Klötzke Date: Mon, 16 Dec 2019 22:56:52 +0100 Subject: mdev: re-initialize if uevent messages were lost MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the netlink read() failed with ENOBUFS we know that we have missed at least one message due to a socket receive buffer overrun. The only way how to recover is to drop the old socket, open a fresh one and make a cold-plug scan of the current system state. Signed-off-by: Jan Klötzke Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 4c00a2d7e..d4f06c128 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -1199,6 +1199,16 @@ static void daemon_loop(char *temp, int fd) len = safe_read(fd, netbuf, sizeof(netbuf) - 1); if (len < 0) { + if (errno == ENOBUFS) { + /* + * We ran out of socket receive buffer space. + * Start from scratch. + */ + dbg1s("uevent overrun, rescanning"); + close(fd); + fd = daemon_init(temp); + continue; + } bb_simple_perror_msg_and_die("read"); } end = netbuf + len; -- cgit v1.2.3-55-g6feb From e9003caf6dce05034147bb6382b17154d428f575 Mon Sep 17 00:00:00 2001 From: Jan Klötzke Date: Mon, 16 Dec 2019 22:56:53 +0100 Subject: mdev: add syslog logging mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If mdev is run as daemon it should be possible to forward the debug messages to syslog. This feature might be useful if mdev is run with -s during boot too. OTOH it makes no sense for the daemon to log to mdev.log. This can be handled by a syslog daemon way better. If the daemon stays in the foreground due to -f, the messages are still written to stderr as before. Signed-off-by: Jan Klötzke Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index d4f06c128..a67baf32e 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -80,7 +80,7 @@ //kbuild:lib-$(CONFIG_MDEV) += mdev.o //usage:#define mdev_trivial_usage -//usage: "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df]") +//usage: "[-S] " IF_FEATURE_MDEV_DAEMON("[") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df]]") //usage:#define mdev_full_usage "\n\n" //usage: "mdev -s is to be run during boot to scan /sys and populate /dev.\n" //usage: IF_FEATURE_MDEV_DAEMON( @@ -88,6 +88,9 @@ //usage: " -f: stay in foreground.\n" //usage: ) //usage: "\n" +//usage: "optional arguments:\n" +//usage: " -S: Log to syslog too\n" +//usage: "\n" //usage: "Bare mdev is a kernel hotplug helper. To activate it:\n" //usage: " echo /sbin/mdev >/proc/sys/kernel/hotplug\n" //usage: IF_FEATURE_MDEV_CONF( @@ -113,6 +116,7 @@ #include "common_bufsiz.h" #include "xregex.h" #include +#include /* "mdev -s" scans /sys/class/xxx, looking for directories which have dev * file (it is of the form "M:m\n"). Example: /sys/class/tty/tty0/dev @@ -1237,8 +1241,9 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) { enum { MDEV_OPT_SCAN = 1 << 0, - MDEV_OPT_DAEMON = 1 << 1, - MDEV_OPT_FOREGROUND = 1 << 2, + MDEV_OPT_SYSLOG = 1 << 1, + MDEV_OPT_DAEMON = 1 << 2, + MDEV_OPT_FOREGROUND = 1 << 3, }; int opt; RESERVE_CONFIG_BUFFER(temp, PATH_MAX + SCRATCH_SIZE); @@ -1254,7 +1259,7 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) xchdir("/dev"); - opt = getopt32(argv, "s" IF_FEATURE_MDEV_DAEMON("df")); + opt = getopt32(argv, "sS" IF_FEATURE_MDEV_DAEMON("df")); #if ENABLE_FEATURE_MDEV_CONF G.filename = "/etc/mdev.conf"; @@ -1264,8 +1269,17 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) } #endif + if (opt & MDEV_OPT_SYSLOG) { + openlog(applet_name, LOG_PID, LOG_DAEMON); + logmode |= LOGMODE_SYSLOG; + } + #if ENABLE_FEATURE_MDEV_DAEMON if (opt & MDEV_OPT_DAEMON) { + // there is no point in write()ing to /dev/null + if (!(opt & MDEV_OPT_FOREGROUND)) + logmode &= ~LOGMODE_STDIO; + /* * Daemon mode listening on uevent netlink socket. Fork away * after initial scan so that caller can be sure everything @@ -1276,8 +1290,6 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) if (!(opt & MDEV_OPT_FOREGROUND)) bb_daemonize_or_rexec(0, argv); - open_mdev_log(NULL, getpid()); - daemon_loop(temp, fd); } #endif -- cgit v1.2.3-55-g6feb From 768153bf8cc84a1a53166a9fe538de9484cdc8d1 Mon Sep 17 00:00:00 2001 From: Jan Klötzke Date: Mon, 16 Dec 2019 22:56:54 +0100 Subject: mdev: add -v to increase log verbosity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If logging to stderr and/or syslog the -v option can be given one or more times to increase the log verbosity. If mdev is used as hotplug helper the log level is fixed set to 2 if mdev.log is found an appended because there is no possiblity to pass arguments to the hotplug helper. Signed-off-by: Jan Klötzke Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index a67baf32e..66cff6e9c 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -80,7 +80,7 @@ //kbuild:lib-$(CONFIG_MDEV) += mdev.o //usage:#define mdev_trivial_usage -//usage: "[-S] " IF_FEATURE_MDEV_DAEMON("[") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df]]") +//usage: "[-Sv] " IF_FEATURE_MDEV_DAEMON("[") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df]]") //usage:#define mdev_full_usage "\n\n" //usage: "mdev -s is to be run during boot to scan /sys and populate /dev.\n" //usage: IF_FEATURE_MDEV_DAEMON( @@ -90,6 +90,7 @@ //usage: "\n" //usage: "optional arguments:\n" //usage: " -S: Log to syslog too\n" +//usage: " -v: Increase log verbosity\n" //usage: "\n" //usage: "Bare mdev is a kernel hotplug helper. To activate it:\n" //usage: " echo /sbin/mdev >/proc/sys/kernel/hotplug\n" @@ -297,7 +298,7 @@ struct rule { struct globals { int root_major, root_minor; - smallint verbose; + int verbose; char *subsystem; char *subsys_env; /* for putenv("SUBSYSTEM=subsystem") */ #if ENABLE_FEATURE_MDEV_CONF @@ -1259,7 +1260,11 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) xchdir("/dev"); - opt = getopt32(argv, "sS" IF_FEATURE_MDEV_DAEMON("df")); + opt = getopt32(argv, "^" + "sS" IF_FEATURE_MDEV_DAEMON("df") "v" + "\0" + "vv", + &G.verbose); #if ENABLE_FEATURE_MDEV_CONF G.filename = "/etc/mdev.conf"; -- cgit v1.2.3-55-g6feb From 1c9cd9b71b777bcd23879ac5ad24f391307182c7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Nov 2020 14:43:35 +0100 Subject: mdev: clean up Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 66cff6e9c..2cf98b1a4 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -80,18 +80,16 @@ //kbuild:lib-$(CONFIG_MDEV) += mdev.o //usage:#define mdev_trivial_usage -//usage: "[-Sv] " IF_FEATURE_MDEV_DAEMON("[") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df]]") +//usage: "[-vS] " IF_FEATURE_MDEV_DAEMON("{ ") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df] }") //usage:#define mdev_full_usage "\n\n" -//usage: "mdev -s is to be run during boot to scan /sys and populate /dev.\n" +//usage: " -v verbose\n" +//usage: " -S log to syslog too\n" +//usage: " -s scan /sys and populate /dev\n" //usage: IF_FEATURE_MDEV_DAEMON( -//usage: "mdev -d[f]: daemon, listen on netlink.\n" -//usage: " -f: stay in foreground.\n" +//usage: " -d daemon, listen on netlink\n" +//usage: " -f stay in foreground\n" //usage: ) //usage: "\n" -//usage: "optional arguments:\n" -//usage: " -S: Log to syslog too\n" -//usage: " -v: Increase log verbosity\n" -//usage: "\n" //usage: "Bare mdev is a kernel hotplug helper. To activate it:\n" //usage: " echo /sbin/mdev >/proc/sys/kernel/hotplug\n" //usage: IF_FEATURE_MDEV_CONF( @@ -1281,7 +1279,9 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_MDEV_DAEMON if (opt & MDEV_OPT_DAEMON) { - // there is no point in write()ing to /dev/null + int fd; + + /* there is no point in write()ing to /dev/null */ if (!(opt & MDEV_OPT_FOREGROUND)) logmode &= ~LOGMODE_STDIO; @@ -1290,7 +1290,7 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) * after initial scan so that caller can be sure everything * is up-to-date when mdev process returns. */ - int fd = daemon_init(temp); + fd = daemon_init(temp); if (!(opt & MDEV_OPT_FOREGROUND)) bb_daemonize_or_rexec(0, argv); -- cgit v1.2.3-55-g6feb From cb143b9793a8a17a753a215ddfe42a57490c65f7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Nov 2020 16:22:16 +0100 Subject: uevent: make it survive ENOBUFS function old new delta uevent_main 285 337 +52 Signed-off-by: Denys Vlasenko --- util-linux/uevent.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/util-linux/uevent.c b/util-linux/uevent.c index 2f1135f0c..045b35432 100644 --- a/util-linux/uevent.c +++ b/util-linux/uevent.c @@ -30,19 +30,19 @@ #define INIT_G() do { setup_common_bufsiz(); } while (0) enum { MAX_ENV = COMMON_BUFSIZE / sizeof(char*) - 1, - /* sizeof(env[0]) instead of sizeof(char*) - * makes gcc-6.3.0 emit "strict-aliasing" warning. - */ -}; - -enum { - /* socket receive buffer of 2MiB proved to be too small: - * http://lists.busybox.net/pipermail/busybox/2019-December/087665.html - * Udevd seems to use a whooping 128MiB. - * The socket receive buffer size is just a resource limit. - * The buffers are allocated lazily so the memory is not wasted. - */ + // ^^^sizeof(env[0]) instead of sizeof(char*) + // makes gcc-6.3.0 emit "strict-aliasing" warning. + + // socket receive buffer of 2MiB proved to be too small: + // http://lists.busybox.net/pipermail/busybox/2019-December/087665.html + // udevd seems to use a whooping 128MiB. + // The socket receive buffer size is just a resource limit. + // The buffers are allocated lazily so the memory is not wasted. KERN_RCVBUF = 128 * 1024 * 1024, + + // Might be made smaller: the kernel v5.4 passes up to 32 environment + // variables with a total of 2kb on each event. + // On top of that the action string and device path are added. USER_RCVBUF = 16 * 1024, }; @@ -61,6 +61,7 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) // Reproducer: // uevent mdev & // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' + reopen: fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, KERN_RCVBUF); for (;;) { @@ -82,8 +83,16 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) // Here we block, possibly for a very long time len = safe_read(fd, netbuf, USER_RCVBUF - 1); - if (len < 0) + if (len < 0) { + if (errno == ENOBUFS) { + // Ran out of socket receive buffer + bb_simple_error_msg("uevent overrun"); + close(fd); + munmap(netbuf, USER_RCVBUF); + goto reopen; + } bb_simple_perror_msg_and_die("read"); + } end = netbuf + len; *end = '\0'; -- cgit v1.2.3-55-g6feb From 03eb6eba436ca6198e5346ebb9d22a30d2f527a4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Nov 2020 16:35:56 +0100 Subject: mdev: clear LOGMODE_STDIO only directly before daemonizing Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 2cf98b1a4..9a8c14456 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -1279,21 +1279,17 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_MDEV_DAEMON if (opt & MDEV_OPT_DAEMON) { - int fd; - - /* there is no point in write()ing to /dev/null */ - if (!(opt & MDEV_OPT_FOREGROUND)) - logmode &= ~LOGMODE_STDIO; - - /* - * Daemon mode listening on uevent netlink socket. Fork away + /* Daemon mode listening on uevent netlink socket. Fork away * after initial scan so that caller can be sure everything * is up-to-date when mdev process returns. */ - fd = daemon_init(temp); + int fd = daemon_init(temp); - if (!(opt & MDEV_OPT_FOREGROUND)) + if (!(opt & MDEV_OPT_FOREGROUND)) { + /* there is no point in logging to /dev/null */ + logmode &= ~LOGMODE_STDIO; bb_daemonize_or_rexec(0, argv); + } daemon_loop(temp, fd); } -- cgit v1.2.3-55-g6feb From 20900489a1fff2a563999d90e24239206f202b21 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 25 Nov 2020 22:47:00 +0100 Subject: base32: new applet function old new delta baseNUM_main - 568 +568 decode_base32 - 275 +275 bb_uuenc_tbl_base32 - 34 +34 read_base64 218 236 +18 applet_names 2732 2739 +7 applet_main 1580 1584 +4 packed_usage 33480 33478 -2 base64_main 208 - -208 ------------------------------------------------------------------------------ (add/remove: 3/1 grow/shrink: 3/1 up/down: 906/-210) Total: 696 bytes Signed-off-by: Denys Vlasenko --- coreutils/uudecode.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++----- include/libbb.h | 3 ++ libbb/uuencode.c | 84 ++++++++++++++++++++++++++++++++++-- 3 files changed, 192 insertions(+), 13 deletions(-) diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 5b2edd649..e4fb0d48b 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -168,9 +168,11 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) } #endif -//applet:IF_BASE64(APPLET(base64, BB_DIR_BIN, BB_SUID_DROP)) - -//kbuild:lib-$(CONFIG_BASE64) += uudecode.o +//config:config BASE32 +//config: bool "base32 (4.9 kb)" +//config: default y +//config: help +//config: Base32 encode and decode //config:config BASE64 //config: bool "base64 (4.9 kb)" @@ -178,6 +180,14 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) //config: help //config: Base64 encode and decode +//usage:#define base32_trivial_usage +//usage: "[-d] [FILE]" +//usage:#define base32_full_usage "\n\n" +//usage: "Base32 encode or decode FILE to standard output" +//usage: "\n -d Decode data" +////usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" +////usage: "\n -i When decoding, ignore non-alphabet characters" + //usage:#define base64_trivial_usage //usage: "[-d] [FILE]" //usage:#define base64_full_usage "\n\n" @@ -186,9 +196,77 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) ////usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" ////usage: "\n -i When decoding, ignore non-alphabet characters" -#if ENABLE_BASE64 -int base64_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int base64_main(int argc UNUSED_PARAM, char **argv) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_BASE32(APPLET_ODDNAME(base32, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base32)) +//applet:IF_BASE64(APPLET_ODDNAME(base64, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base64)) + +//kbuild:lib-$(CONFIG_BASE64) += uudecode.o +//kbuild:lib-$(CONFIG_BASE32) += uudecode.o + +#if ENABLE_BASE32 || ENABLE_BASE64 + +# if ENABLE_BASE32 +static void bb_b32encode(char *p, const void *src, int length) +{ +#define tbl bb_uuenc_tbl_base32 + const unsigned char *s = src; + + /* Transform 5x8 bits to 8x5 bits */ + while (length > 0) { + unsigned cur, next; + + length--; + cur = *s++; + *p++ = tbl[cur >> 3]; // xxxxx--- -------- -------- -------- -------- + cur &= 7; + + next = 0; + if (--length >= 0) + next = *s++; + *p++ = tbl[(cur << 2) + (next >> 6)]; // -----xxx xx------ -------- -------- -------- + cur = next & 0x3f; + + *p++ = tbl[cur >> 1]; // -------- --xxxxx- -------- -------- -------- + cur &= 1; + + next = 0; + if (--length >= 0) + next = *s++; + *p++ = tbl[(cur << 4) + (next >> 4)]; // -------- -------x xxxx---- -------- -------- + cur = next & 0xf; + + next = 0; + if (--length >= 0) + next = *s++; + *p++ = tbl[(cur << 1) + (next >> 7)]; // -------- -------- ----xxxx x------- -------- + cur = next & 0x7f; + + *p++ = tbl[cur >> 2]; // -------- -------- -------- -xxxxx-- -------- + cur &= 3; + + next = 0; + if (--length >= 0) + next = *s++; + *p++ = tbl[(cur << 3) + (next >> 5)]; // -------- -------- -------- ------xx xxx----- + cur = next & 0x1f; + + *p++ = tbl[cur]; // -------- -------- -------- -------- ---xxxxx + } +#undef tbl + /* Zero-terminate */ + *p = '\0'; + /* Pad as necessary */ + length = ((-length) * 3) >> 1; /* -4 => 6 pad chars, -3 => 4, -2 => 3, -1 => 1 */ + while (length--) { + *--p = '='; + } +} +# else +void bb_b32encode(char *p, const void *src, int length); /* undefined */ +# endif + +int baseNUM_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int baseNUM_main(int argc UNUSED_PARAM, char **argv) { FILE *src_stream; unsigned opts; @@ -200,7 +278,10 @@ int base64_main(int argc UNUSED_PARAM, char **argv) *--argv = (char*)"-"; src_stream = xfopen_stdin(argv[0]); if (opts) { - read_base64(src_stream, stdout, /*flags:*/ (unsigned char)EOF); + int flags = (unsigned char)EOF; + if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) + flags = ((unsigned char)EOF) | BASE64_32; + read_base64(src_stream, stdout, flags); } else { enum { SRC_BUF_SIZE = 76 / 4 * 3, /* this *MUST* be a multiple of 3 */ @@ -210,14 +291,31 @@ int base64_main(int argc UNUSED_PARAM, char **argv) char dst_buf[DST_BUF_SIZE + 1]; int src_fd = fileno(src_stream); while (1) { - size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE); + size_t size; + if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) + size = 72 / 8 * 5; +//FIXME: wrong, default width of base32 is not 72, but 76 chars +//(not a multiple of 8 - requires adding wrapping logic) +//when this is fixed, can implement -w COL too + else + size = SRC_BUF_SIZE; + + size = full_read(src_fd, src_buf, size); if (!size) break; if ((ssize_t)size < 0) bb_simple_perror_msg_and_die(bb_msg_read_error); + /* Encode the buffer we just read in */ - bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); - xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3)); + if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) { + bb_b32encode(dst_buf, src_buf, size); + size = 8 * ((size + 4) / 5); + } else { + bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); + size = 4 * ((size + 2) / 3); + } + + xwrite(STDOUT_FILENO, dst_buf, size); bb_putchar('\n'); fflush(stdout); } diff --git a/include/libbb.h b/include/libbb.h index 1b7c0b83a..ef4a34f07 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2026,14 +2026,17 @@ char *percent_decode_in_place(char *str, int strict) FAST_FUNC; extern const char bb_uuenc_tbl_base64[] ALIGN1; +extern const char bb_uuenc_tbl_base32[] ALIGN1; extern const char bb_uuenc_tbl_std[] ALIGN1; void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; enum { BASE64_FLAG_UU_STOP = 0x100, + BASE64_32 = 0x200, /* base32 */ /* Sign-extends to a value which never matches fgetc result: */ BASE64_FLAG_NO_STOP_CHAR = 0x80, }; const char *decode_base64(char **pp_dst, const char *src) FAST_FUNC; +const char *decode_base32(char **pp_dst, const char *src) FAST_FUNC; void read_base64(FILE *src_stream, FILE *dst_stream, int flags) FAST_FUNC; typedef struct md5_ctx_t { diff --git a/libbb/uuencode.c b/libbb/uuencode.c index d36b34f63..b4ee20c20 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -8,7 +8,8 @@ */ #include "libbb.h" -/* Conversion table. for base 64 */ +/* Conversion tables */ +/* for base 64 */ const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', @@ -21,7 +22,16 @@ const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { '=' /* termination character */, '\0' /* needed for uudecode.c only */ }; - +#if ENABLE_BASE32 +const char bb_uuenc_tbl_base32[33 + 1] ALIGN1 = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '2', '3', '4', '5', '6', '7', + '=', + '\0' +}; +#endif const char bb_uuenc_tbl_std[65] ALIGN1 = { '`', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', @@ -153,6 +163,68 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) return src_tail; } +#if ENABLE_BASE32 +const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) +{ + char *dst = *pp_dst; + const char *src_tail; + + while (1) { + unsigned char five_bit[8]; + int count = 0; + + /* Fetch up to eight 5-bit values */ + src_tail = src; + while (count < 8) { + char *table_ptr; + int ch; + + /* Get next _valid_ character. + * bb_uuenc_tbl_base32[] contains this string: + * 0 1 2 3 + * 01234567890123456789012345678901 + * "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=" + */ + do { + ch = *src; + if (ch == '\0') { + if (count == 0) { + src_tail = src; + } + goto ret; + } + src++; + table_ptr = strchr(bb_uuenc_tbl_base32, toupper(ch)); + } while (!table_ptr); + + /* Convert encoded character to decimal */ + ch = table_ptr - bb_uuenc_tbl_base32; + + /* ch is 32 if char was '=', otherwise 0..31 */ + if (ch == 32) + break; + five_bit[count] = ch; + count++; + } + + /* Transform 5-bit values to 8-bit ones */ + if (count > 1) // xxxxx xxx-- ----- ----- ----- ----- ----- ----- + *dst++ = five_bit[0] << 3 | five_bit[1] >> 2; + if (count > 3) // ----- ---xx xxxxx x---- ----- ----- ----- ----- + *dst++ = five_bit[1] << 6 | five_bit[2] << 1 | five_bit[3] >> 4; + if (count > 4) // ----- ----- ----- -xxxx xxxx- ----- ----- ----- + *dst++ = five_bit[3] << 4 | five_bit[4] >> 1; + if (count > 6) // ----- ----- ----- ----- ----x xxxxx xx--- ----- + *dst++ = five_bit[4] << 7 | five_bit[5] << 2 | five_bit[6] >> 3; + if (count > 7) // ----- ----- ----- ----- ----- ----- --xxx xxxxx + *dst++ = five_bit[6] << 5 | five_bit[7]; + } /* while (1) */ + ret: + *pp_dst = dst; + return src_tail; +} +#endif + /* * Decode base64 encoded stream. * Can stop on EOF, specified char, or on uuencode-style "====" line: @@ -163,6 +235,7 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) /* Note that EOF _can_ be passed as exit_char too */ #define exit_char ((int)(signed char)flags) #define uu_style_end (flags & BASE64_FLAG_UU_STOP) +#define base32 (flags & BASE64_32) /* uuencoded files have 61 byte lines. Use 64 byte buffer * to process line at a time. @@ -204,7 +277,12 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) return; out_tail = out_buf; - in_tail = decode_base64(&out_tail, in_buf); +#if ENABLE_BASE32 + if (base32) + in_tail = decode_base32(&out_tail, in_buf); + else +#endif + in_tail = decode_base64(&out_tail, in_buf); fwrite(out_buf, (out_tail - out_buf), 1, dst_stream); -- cgit v1.2.3-55-g6feb From fc63549352c371617e68fcf7ecbe4978fa207c6a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 27 Nov 2020 12:40:31 +0100 Subject: free: code shrink function old new delta free_main 664 657 -7 Signed-off-by: Denys Vlasenko --- procps/free.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/procps/free.c b/procps/free.c index b33506b9e..0adef501f 100644 --- a/procps/free.c +++ b/procps/free.c @@ -97,10 +97,10 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) case 'k': /* 2^10 */ /* G.unit_steps = 10; - already is */ break; - case 'm': /* 2^(2*10) */ + case 'm': /* 2^20 */ G.unit_steps = 20; break; - case 'g': /* 2^(3*10) */ + case 'g': /* 2^30 */ G.unit_steps = 30; break; default: @@ -117,16 +117,24 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) ); sysinfo(&info); - /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ - G.mem_unit = (info.mem_unit ? info.mem_unit : 1); /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */ seen_available = parse_meminfo(&G); + G.mem_unit = (info.mem_unit ? info.mem_unit : 1); /* kernels < 2.4.x return mem_unit==0, so cope */ available = ((unsigned long long) G.available_kb * 1024) / G.mem_unit; cached = ((unsigned long long) G.cached_kb * 1024) / G.mem_unit; cached += info.bufferram; cached += ((unsigned long long) G.reclaimable_kb * 1024) / G.mem_unit; cached_plus_free = cached + info.freeram; +/* In case (long long * G.mem_unit) can overflow, this can be used to reduce the chances */ +#if 0 //ENABLE_DESKTOP + while (!(G.mem_unit & 1) && G.unit_steps != 0) { + G.mem_unit >>= 1; + G.unit_steps--; + //bb_error_msg("mem_unit:%d unit_steps:%d", G.mem_unit, G.unit_steps); + } +#endif + #define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" #define FIELDS_3 (FIELDS_6 + 6 + 7 + 7) #define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7) -- cgit v1.2.3-55-g6feb From c8b3d9a145d2db95869f0ae8081d85c0378f0aef Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 27 Nov 2020 15:25:31 +0100 Subject: base32/64: implement -w COL function old new delta baseNUM_main 568 655 +87 packed_usage 33478 33533 +55 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 142/0) Total: 142 bytes Signed-off-by: Denys Vlasenko --- coreutils/uudecode.c | 56 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index e4fb0d48b..751976a87 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -181,19 +181,19 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) //config: Base64 encode and decode //usage:#define base32_trivial_usage -//usage: "[-d] [FILE]" +//usage: "[-d] [-w COL] [FILE]" //usage:#define base32_full_usage "\n\n" //usage: "Base32 encode or decode FILE to standard output" //usage: "\n -d Decode data" -////usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" +//usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" ////usage: "\n -i When decoding, ignore non-alphabet characters" //usage:#define base64_trivial_usage -//usage: "[-d] [FILE]" +//usage: "[-d] [-w COL] [FILE]" //usage:#define base64_full_usage "\n\n" //usage: "Base64 encode or decode FILE to standard output" //usage: "\n -d Decode data" -////usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" +//usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" ////usage: "\n -i When decoding, ignore non-alphabet characters" // APPLET_ODDNAME:name main location suid_type help @@ -270,41 +270,37 @@ int baseNUM_main(int argc UNUSED_PARAM, char **argv) { FILE *src_stream; unsigned opts; + unsigned col = 76; - opts = getopt32(argv, "^" "d" "\0" "?1"/* 1 arg max*/); + opts = getopt32(argv, "^" "dw:+" "\0" "?1"/* 1 arg max*/, &col); argv += optind; if (!argv[0]) *--argv = (char*)"-"; src_stream = xfopen_stdin(argv[0]); - if (opts) { + if (opts & 1) { int flags = (unsigned char)EOF; if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) flags = ((unsigned char)EOF) | BASE64_32; read_base64(src_stream, stdout, flags); } else { enum { - SRC_BUF_SIZE = 76 / 4 * 3, /* this *MUST* be a multiple of 3 */ + SRC_BUF_SIZE = 3 * 5 * 32, /* this *MUST* be a multiple of 3 and 5 */ DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), }; char src_buf[SRC_BUF_SIZE]; char dst_buf[DST_BUF_SIZE + 1]; int src_fd = fileno(src_stream); + int rem = 0; + while (1) { - size_t size; - if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) - size = 72 / 8 * 5; -//FIXME: wrong, default width of base32 is not 72, but 76 chars -//(not a multiple of 8 - requires adding wrapping logic) -//when this is fixed, can implement -w COL too - else - size = SRC_BUF_SIZE; - - size = full_read(src_fd, src_buf, size); - if (!size) - break; + size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE); if ((ssize_t)size < 0) bb_simple_perror_msg_and_die(bb_msg_read_error); + if (size == 0) { + if (rem != 0) bb_putchar('\n'); + break; + } /* Encode the buffer we just read in */ if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) { @@ -315,9 +311,25 @@ int baseNUM_main(int argc UNUSED_PARAM, char **argv) size = 4 * ((size + 2) / 3); } - xwrite(STDOUT_FILENO, dst_buf, size); - bb_putchar('\n'); - fflush(stdout); + if (col == 0) { + fputs(dst_buf, stdout); + } else { + char *result = dst_buf; + if (rem == 0) + rem = col; + while (1) { + int out = size < rem ? size : rem; + rem -= out; + printf(rem != 0 ? "%.*s" : "%.*s\n", out, result); + if (rem != 0) + break; + size -= out; + if (size == 0) + break; + result += out; + rem = col; + } + } } } -- cgit v1.2.3-55-g6feb From cdab3c4fac76bcf941e55e309b061ac97925f9b0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 27 Nov 2020 15:39:23 +0100 Subject: base32/64: decode in-place Signed-off-by: Denys Vlasenko --- coreutils/uudecode.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 751976a87..10e5a55de 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -286,13 +286,19 @@ int baseNUM_main(int argc UNUSED_PARAM, char **argv) } else { enum { SRC_BUF_SIZE = 3 * 5 * 32, /* this *MUST* be a multiple of 3 and 5 */ - DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), + DST_BUF_SIZE = 8 * ((SRC_BUF_SIZE + 4) / 5), /* max growth on decode (base32 case) */ }; - char src_buf[SRC_BUF_SIZE]; - char dst_buf[DST_BUF_SIZE + 1]; - int src_fd = fileno(src_stream); - int rem = 0; + /* Use one buffer for both input and output: + * decoding reads input "left-to-right", + * it's safe to place source at the end of the buffer and + * overwrite it while decoding, just be careful to have a gap. + */ + char dst_buf[((DST_BUF_SIZE + /*gap:*/ 16) /*round up to 16:*/ | 0xf) + 1]; +#define src_buf (dst_buf + sizeof(dst_buf) - SRC_BUF_SIZE) + int src_fd, rem; + src_fd = fileno(src_stream); + rem = 0; while (1) { size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE); if ((ssize_t)size < 0) @@ -331,6 +337,7 @@ int baseNUM_main(int argc UNUSED_PARAM, char **argv) } } } +#undef src_buf } fflush_stdout_and_exit(EXIT_SUCCESS); -- cgit v1.2.3-55-g6feb From dc68a5ddac23e34fe00299d55501043bd83ae817 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 27 Nov 2020 15:55:46 +0100 Subject: sha3sum: fix --help: -a does not depend on FEATURE_MD5_SHA1_SUM_CHECK Signed-off-by: Denys Vlasenko --- coreutils/md5_sha1_sum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index ba26c985a..4efa23061 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c @@ -117,8 +117,8 @@ //usage: "\n -c Check sums against list in FILEs" //usage: "\n -s Don't output anything, status code shows success" //usage: "\n -w Warn about improperly formatted checksum lines" -//usage: "\n -a BITS 224 (default), 256, 384, 512" //usage: ) +//usage: "\n -a BITS 224 (default), 256, 384, 512" //FIXME: GNU coreutils 8.25 has no -s option, it has only these two long opts: // --quiet don't print OK for each successfully verified file -- cgit v1.2.3-55-g6feb From 170b8628fabff2d81606cac052a35f8cf91cc7b2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 27 Nov 2020 20:44:55 +0100 Subject: libbb: smaller and faster decode_base64() function old new delta decode_base64 195 180 -15 Signed-off-by: Denys Vlasenko --- libbb/uuencode.c | 100 +++++++++++++++++++---------------------------------- networking/httpd.c | 37 -------------------- 2 files changed, 36 insertions(+), 101 deletions(-) diff --git a/libbb/uuencode.c b/libbb/uuencode.c index b4ee20c20..2e9edb219 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -82,7 +82,7 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl } /* - * Decode base64 encoded string. Stops on '\0'. + * Decode base64 encoded string. Stops on NUL after terminating "=" or "==". * * Returns: pointer to the undecoded part of source. * If points to '\0', then the source was fully decoded. @@ -91,76 +91,48 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) { char *dst = *pp_dst; - const char *src_tail; - - while (1) { - unsigned char six_bit[4]; - int count = 0; + unsigned ch = 0; + int i = 0; - /* Fetch up to four 6-bit values */ - src_tail = src; - while (count < 4) { - char *table_ptr; - int ch; + while (*src) { + int t = (unsigned char)*src++; - /* Get next _valid_ character. - * bb_uuenc_tbl_base64[] contains this string: - * 0 1 2 3 4 5 6 - * 01234567890123456789012345678901234567890123456789012345678901234 - * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" - */ - do { - ch = *src; - if (ch == '\0') { - if (count == 0) { - /* Example: - * If we decode "QUJD ", we want - * to return ptr to NUL, not to ' ', - * because we did fully decode - * the string (to "ABC"). - */ - src_tail = src; - } - goto ret; - } - src++; - table_ptr = strchr(bb_uuenc_tbl_base64, ch); + /* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */ + if (t >= '0' && t <= '9') + t = t - '0' + 52; + else if (t >= 'A' && t <= 'Z') + t = t - 'A'; + else if (t >= 'a' && t <= 'z') + t = t - 'a' + 26; + else if (t == '+') + t = 62; + else if (t == '/') + t = 63; + else if (t == '=' && (i == 3 || (i == 2 && *src == '='))) + /* the above disallows "==AA", "A===", "AA=A" etc */ + t = 0x1000000; + else //TODO: add BASE64_FLAG_foo to die on bad char? - } while (!table_ptr); - - /* Convert encoded character to decimal */ - ch = table_ptr - bb_uuenc_tbl_base64; + continue; - /* ch is 64 if char was '=', otherwise 0..63 */ - if (ch == 64) + ch = (ch << 6) | t; + if (++i == 4) { + *dst++ = (char) (ch >> 16); + *dst++ = (char) (ch >> 8); + *dst++ = (char) ch; + i = 0; + if (ch & 0x1000000) { /* was last input char '='? */ + dst--; + if (ch & (0x1000000 << 6)) /* was it "=="? */ + dst--; break; - six_bit[count] = ch; - count++; + } + ch = 0; } - - /* Transform 6-bit values to 8-bit ones. - * count can be < 4 when we decode the tail: - * "eQ==" -> "y", not "y NUL NUL". - * Note that (count > 1) is always true, - * "x===" encoding is not valid: - * even a single zero byte encodes as "AA==". - * However, with current logic we come here with count == 1 - * when we decode "==" tail. - */ - if (count > 1) - *dst++ = six_bit[0] << 2 | six_bit[1] >> 4; - if (count > 2) - *dst++ = six_bit[1] << 4 | six_bit[2] >> 2; - if (count > 3) - *dst++ = six_bit[2] << 6 | six_bit[3]; - /* Note that if we decode "AA==" and ate first '=', - * we just decoded one char (count == 2) and now we'll - * do the loop once more to decode second '='. - */ - } /* while (1) */ - ret: + } *pp_dst = dst; - return src_tail; + /* i should be zero here if full 4-char block was decoded */ + return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ } #if ENABLE_BASE32 diff --git a/networking/httpd.c b/networking/httpd.c index 961f8cab4..4ffd89c48 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -1017,46 +1017,9 @@ static char *encodeString(const char *string) */ static void decodeBase64(char *Data) { -# if ENABLE_BASE64 || ENABLE_UUDECODE - /* Call decode_base64() from uuencode.c */ char *eptr = Data; decode_base64(&eptr, Data); *eptr = '\0'; -# else - const unsigned char *in = (const unsigned char *)Data; - /* The decoded size will be at most 3/4 the size of the encoded */ - unsigned ch = 0; - int i = 0; - - while (*in) { - int t = *in++; - - if (t >= '0' && t <= '9') - t = t - '0' + 52; - else if (t >= 'A' && t <= 'Z') - t = t - 'A'; - else if (t >= 'a' && t <= 'z') - t = t - 'a' + 26; - else if (t == '+') - t = 62; - else if (t == '/') - t = 63; - else if (t == '=') - t = 0; - else - continue; - - ch = (ch << 6) | t; - i++; - if (i == 4) { - *Data++ = (char) (ch >> 16); - *Data++ = (char) (ch >> 8); - *Data++ = (char) ch; - i = 0; - } - } - *Data = '\0'; -# endif } #endif -- cgit v1.2.3-55-g6feb From 2cd37d65e221f7267e97360d21f55a2318b25355 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 27 Nov 2020 21:25:34 +0100 Subject: libbb: faster and smaller decode_base32() function old new delta decode_base32 275 224 -51 Signed-off-by: Denys Vlasenko --- libbb/uuencode.c | 84 +++++++++++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 50 deletions(-) diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 2e9edb219..7c7f1cf1c 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -82,7 +82,7 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl } /* - * Decode base64 encoded string. Stops on NUL after terminating "=" or "==". + * Decode base64 encoded string. * * Returns: pointer to the undecoded part of source. * If points to '\0', then the source was fully decoded. @@ -139,61 +139,45 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) { char *dst = *pp_dst; - const char *src_tail; - - while (1) { - unsigned char five_bit[8]; - int count = 0; - - /* Fetch up to eight 5-bit values */ - src_tail = src; - while (count < 8) { - char *table_ptr; - int ch; + uint64_t ch = 0; + int i = 0; - /* Get next _valid_ character. - * bb_uuenc_tbl_base32[] contains this string: - * 0 1 2 3 - * 01234567890123456789012345678901 - * "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=" - */ - do { - ch = *src; - if (ch == '\0') { - if (count == 0) { - src_tail = src; - } - goto ret; - } - src++; - table_ptr = strchr(bb_uuenc_tbl_base32, toupper(ch)); - } while (!table_ptr); + while (*src) { + int t = (unsigned char)*src++; - /* Convert encoded character to decimal */ - ch = table_ptr - bb_uuenc_tbl_base32; + /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */ + if (t >= '2' && t <= '7') + t = t - '2' + 26; + else if ((t|0x20) >= 'a' && (t|0x20) <= 'z') + t = (t|0x20) - 'a'; + else if (t == '=' && i > 1) + t = 0; + else +//TODO: add BASE64_FLAG_foo to die on bad char? + continue; - /* ch is 32 if char was '=', otherwise 0..31 */ - if (ch == 32) + ch = (ch << 5) | t; + if (++i == 8) { + *dst++ = (char) (ch >> 32); + *dst++ = (char) (ch >> 24); + *dst++ = (char) (ch >> 16); + *dst++ = (char) (ch >> 8); + *dst++ = (char) ch; + if (t == 0 && src[-1] == '=') { /* was last input char '='? */ + const char *s = src; + while (*--s == '=' && --i != 0) + continue; + i = 8 - i; /* count of =, must be 1, 3, 4 or 6 */ + dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */ + i = 0; break; - five_bit[count] = ch; - count++; + } + i = 0; } - - /* Transform 5-bit values to 8-bit ones */ - if (count > 1) // xxxxx xxx-- ----- ----- ----- ----- ----- ----- - *dst++ = five_bit[0] << 3 | five_bit[1] >> 2; - if (count > 3) // ----- ---xx xxxxx x---- ----- ----- ----- ----- - *dst++ = five_bit[1] << 6 | five_bit[2] << 1 | five_bit[3] >> 4; - if (count > 4) // ----- ----- ----- -xxxx xxxx- ----- ----- ----- - *dst++ = five_bit[3] << 4 | five_bit[4] >> 1; - if (count > 6) // ----- ----- ----- ----- ----x xxxxx xx--- ----- - *dst++ = five_bit[4] << 7 | five_bit[5] << 2 | five_bit[6] >> 3; - if (count > 7) // ----- ----- ----- ----- ----- ----- --xxx xxxxx - *dst++ = five_bit[6] << 5 | five_bit[7]; - } /* while (1) */ - ret: + } *pp_dst = dst; - return src_tail; + /* i should be zero here if full 8-char block was decoded */ + return src - i; } #endif -- cgit v1.2.3-55-g6feb From 7467e905e558228aab992f85406382518f2e1666 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 09:50:14 +0100 Subject: base32/64: code shrink function old new delta decode_base64 180 178 -2 decode_base32 224 217 -7 read_base64 236 222 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-23) Total: -23 bytes Signed-off-by: Denys Vlasenko --- libbb/uuencode.c | 75 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 7c7f1cf1c..0e6fc8a3c 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -93,9 +93,10 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) char *dst = *pp_dst; unsigned ch = 0; int i = 0; + int t; - while (*src) { - int t = (unsigned char)*src++; + while ((t = (unsigned char)*src) != '\0') { + src++; /* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */ if (t >= '0' && t <= '9') @@ -131,7 +132,7 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) } } *pp_dst = dst; - /* i should be zero here if full 4-char block was decoded */ + /* i is zero here if full 4-char block was decoded */ return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ } @@ -141,9 +142,10 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) char *dst = *pp_dst; uint64_t ch = 0; int i = 0; + int t; - while (*src) { - int t = (unsigned char)*src++; + while ((t = (unsigned char)*src) != '\0') { + src++; /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */ if (t >= '2' && t <= '7') @@ -156,27 +158,35 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) //TODO: add BASE64_FLAG_foo to die on bad char? continue; - ch = (ch << 5) | t; + ch = (ch << 5) | (unsigned)t; /* cast prevents pointless sign-extension of t */ if (++i == 8) { + /* testcase: + * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d + * IOW, decoding of + * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI== + * ==== + * should correctly stitch together the tail. + */ + if (t == 0) { + const char *s = src; + while (*--s == '=') + t--; + } *dst++ = (char) (ch >> 32); *dst++ = (char) (ch >> 24); *dst++ = (char) (ch >> 16); *dst++ = (char) (ch >> 8); *dst++ = (char) ch; - if (t == 0 && src[-1] == '=') { /* was last input char '='? */ - const char *s = src; - while (*--s == '=' && --i != 0) - continue; - i = 8 - i; /* count of =, must be 1, 3, 4 or 6 */ - dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */ - i = 0; - break; - } i = 0; + if (t < 0) /* was last input char '='? */ + break; } } + if (t < 0) /* was last input char '='? */ + /* -t is the count of =, must be 1, 3, 4 or 6 */ + dst -= (-t + 1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */ *pp_dst = dst; - /* i should be zero here if full 8-char block was decoded */ + /* i is zero here if full 8-char block was decoded */ return src - i; } #endif @@ -193,19 +203,20 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) #define uu_style_end (flags & BASE64_FLAG_UU_STOP) #define base32 (flags & BASE64_32) - /* uuencoded files have 61 byte lines. Use 64 byte buffer - * to process line at a time. + /* uuencoded files have 61 byte lines. + * base32/64 have 76 byte lines by default. + * Use 80 byte buffer to process one line at a time. */ - enum { BUFFER_SIZE = 64 }; - - char in_buf[BUFFER_SIZE + 2]; - char out_buf[BUFFER_SIZE / 4 * 3 + 2]; - char *out_tail; - const char *in_tail; + enum { BUFFER_SIZE = 80 }; + /* decoded data is shorter than input, can use single buffer for both */ + char buf[BUFFER_SIZE + 2]; int term_seen = 0; int in_count = 0; while (1) { + char *out_tail; + const char *in_tail; + while (in_count < BUFFER_SIZE) { int ch = fgetc(src_stream); if (ch == exit_char) { @@ -224,23 +235,23 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) */ if (ch <= ' ') break; - in_buf[in_count++] = ch; + buf[in_count++] = ch; } - in_buf[in_count] = '\0'; + buf[in_count] = '\0'; /* Did we encounter "====" line? */ - if (uu_style_end && strcmp(in_buf, "====") == 0) + if (uu_style_end && strcmp(buf, "====") == 0) return; - out_tail = out_buf; + out_tail = buf; #if ENABLE_BASE32 if (base32) - in_tail = decode_base32(&out_tail, in_buf); + in_tail = decode_base32(&out_tail, buf); else #endif - in_tail = decode_base64(&out_tail, in_buf); + in_tail = decode_base64(&out_tail, buf); - fwrite(out_buf, (out_tail - out_buf), 1, dst_stream); + fwrite(buf, (out_tail - buf), 1, dst_stream); if (term_seen) { /* Did we consume ALL characters? */ @@ -252,6 +263,6 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) /* It was partial decode */ in_count = strlen(in_tail); - memmove(in_buf, in_tail, in_count); + memmove(buf, in_tail, in_count); } } -- cgit v1.2.3-55-g6feb From f140b49f5f631b09acf7811933d843fe17f06343 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 12:33:50 +0100 Subject: base32/64: code shrink function old new delta decode_base64 178 173 -5 decode_base32 217 186 -31 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-36) Total: -36 bytes Signed-off-by: Denys Vlasenko --- libbb/uuencode.c | 66 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 0e6fc8a3c..6205af261 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -92,8 +92,8 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) { char *dst = *pp_dst; unsigned ch = 0; + unsigned t; int i = 0; - int t; while ((t = (unsigned char)*src) != '\0') { src++; @@ -117,11 +117,11 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) continue; ch = (ch << 6) | t; - if (++i == 4) { + i = (i + 1) & 3; + if (i == 0) { *dst++ = (char) (ch >> 16); *dst++ = (char) (ch >> 8); *dst++ = (char) ch; - i = 0; if (ch & 0x1000000) { /* was last input char '='? */ dst--; if (ch & (0x1000000 << 6)) /* was it "=="? */ @@ -140,9 +140,9 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) { char *dst = *pp_dst; - uint64_t ch = 0; + int64_t ch = 0; + unsigned t; int i = 0; - int t; while ((t = (unsigned char)*src) != '\0') { src++; @@ -150,44 +150,52 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */ if (t >= '2' && t <= '7') t = t - '2' + 26; - else if ((t|0x20) >= 'a' && (t|0x20) <= 'z') - t = (t|0x20) - 'a'; else if (t == '=' && i > 1) t = 0; - else + else { + t = (t | 0x20) - 'a'; + if (t > 25) //TODO: add BASE64_FLAG_foo to die on bad char? - continue; + continue; + } - ch = (ch << 5) | (unsigned)t; /* cast prevents pointless sign-extension of t */ - if (++i == 8) { - /* testcase: - * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d - * IOW, decoding of - * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI== - * ==== - * should correctly stitch together the tail. - */ - if (t == 0) { - const char *s = src; - while (*--s == '=') - t--; - } + ch = (ch << 5) | t; + i = (i + 1) & 7; + if (i == 0) { *dst++ = (char) (ch >> 32); + if (src[-1] == '=') /* was last input char '='? */ + goto tail; *dst++ = (char) (ch >> 24); *dst++ = (char) (ch >> 16); *dst++ = (char) (ch >> 8); *dst++ = (char) ch; - i = 0; - if (t < 0) /* was last input char '='? */ - break; } } - if (t < 0) /* was last input char '='? */ - /* -t is the count of =, must be 1, 3, 4 or 6 */ - dst -= (-t + 1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */ *pp_dst = dst; /* i is zero here if full 8-char block was decoded */ return src - i; + tail: + { + const char *s = src; + while (*--s == '=') + i++; + /* Why duplicate the below code? Testcase: + * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d + * IOW, decoding of + * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI== + * ==== + * must correctly stitch together the tail, must not overwrite + * the tail before it is analyzed! (we can be decoding in-place) + * Else testcase fails, prints trailing extra NUL bytes. + */ + *dst++ = (char) (ch >> 24); + *dst++ = (char) (ch >> 16); + *dst++ = (char) (ch >> 8); + *dst++ = (char) ch; + dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */ + } + *pp_dst = dst; + return src; } #endif -- cgit v1.2.3-55-g6feb From fc6faac84e978c9482106f53e711ab971a0ce188 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 12:48:34 +0100 Subject: libbb: trim base32/64 tables function old new delta bb_uuenc_tbl_base64 66 65 -1 bb_uuenc_tbl_base32 34 32 -2 Signed-off-by: Denys Vlasenko --- libbb/uuencode.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 6205af261..139c60bd5 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -9,8 +9,17 @@ #include "libbb.h" /* Conversion tables */ +#if ENABLE_BASE32 +const char bb_uuenc_tbl_base32[] ALIGN1 = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '2', '3', '4', '5', '6', '7', + /* unused: '=', */ +}; +#endif /* for base 64 */ -const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { +const char bb_uuenc_tbl_base64[] ALIGN1 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', @@ -20,19 +29,8 @@ const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=' /* termination character */, - '\0' /* needed for uudecode.c only */ }; -#if ENABLE_BASE32 -const char bb_uuenc_tbl_base32[33 + 1] ALIGN1 = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '2', '3', '4', '5', '6', '7', - '=', - '\0' -}; -#endif -const char bb_uuenc_tbl_std[65] ALIGN1 = { +const char bb_uuenc_tbl_std[] ALIGN1 = { '`', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', -- cgit v1.2.3-55-g6feb From 885121e25db2ec9a8191a406085d91790a133d20 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 13:26:44 +0100 Subject: libbb: change decode_base32/64 API to return the end of _dst_, not _src_. function old new delta decode_base64 173 178 +5 read_base64 222 220 -2 decode_base32 186 182 -4 handle_incoming_and_exit 2263 2239 -24 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 5/-30) Total: -25 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 ++-- libbb/uuencode.c | 29 +++++++++++++++-------------- networking/httpd.c | 6 ++---- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index ef4a34f07..e56fff3e8 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2035,8 +2035,8 @@ enum { /* Sign-extends to a value which never matches fgetc result: */ BASE64_FLAG_NO_STOP_CHAR = 0x80, }; -const char *decode_base64(char **pp_dst, const char *src) FAST_FUNC; -const char *decode_base32(char **pp_dst, const char *src) FAST_FUNC; +char *decode_base64(char *dst, const char **pp_src) FAST_FUNC; +char *decode_base32(char *dst, const char **pp_src) FAST_FUNC; void read_base64(FILE *src_stream, FILE *dst_stream, int flags) FAST_FUNC; typedef struct md5_ctx_t { diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 139c60bd5..6e63bfc6a 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -86,9 +86,9 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl * If points to '\0', then the source was fully decoded. * (*pp_dst): advanced past the last written byte. */ -const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) +char* FAST_FUNC decode_base64(char *dst, const char **pp_src) { - char *dst = *pp_dst; + const char *src = pp_src ? *pp_src : dst; /* for httpd.c, support NULL 2nd param */ unsigned ch = 0; unsigned t; int i = 0; @@ -129,16 +129,17 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) ch = 0; } } - *pp_dst = dst; /* i is zero here if full 4-char block was decoded */ - return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ + if (pp_src) + *pp_src = src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ + return dst; } #if ENABLE_BASE32 -const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) +char* FAST_FUNC decode_base32(char *dst, const char **pp_src) { - char *dst = *pp_dst; - int64_t ch = 0; + const char *src = *pp_src; + uint64_t ch = 0; unsigned t; int i = 0; @@ -169,9 +170,9 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) *dst++ = (char) ch; } } - *pp_dst = dst; /* i is zero here if full 8-char block was decoded */ - return src - i; + *pp_src = src - i; + return dst; tail: { const char *s = src; @@ -192,8 +193,8 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src) *dst++ = (char) ch; dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */ } - *pp_dst = dst; - return src; + *pp_src = src; + return dst; } #endif @@ -249,13 +250,13 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) if (uu_style_end && strcmp(buf, "====") == 0) return; - out_tail = buf; + in_tail = buf; #if ENABLE_BASE32 if (base32) - in_tail = decode_base32(&out_tail, buf); + out_tail = decode_base32(buf, &in_tail); else #endif - in_tail = decode_base64(&out_tail, buf); + out_tail = decode_base64(buf, &in_tail); fwrite(buf, (out_tail - buf), 1, dst_stream); diff --git a/networking/httpd.c b/networking/httpd.c index 4ffd89c48..4346141ee 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -1015,11 +1015,9 @@ static char *encodeString(const char *string) * Parameter: a pointer to a base64 encoded string. * Decoded data is stored in-place. */ -static void decodeBase64(char *Data) +static void decodeBase64(char *data) { - char *eptr = Data; - decode_base64(&eptr, Data); - *eptr = '\0'; + decode_base64(data, NULL)[0] = '\0'; } #endif -- cgit v1.2.3-55-g6feb From ae04ce82cf4352c0d0ecd993b586c10b6b8f80af Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 13:39:05 +0100 Subject: base32/64: "truncated base64 input" -> "truncated input" text data bss dec hex filename 1021739 559 5052 1027350 fad16 busybox_old 1021732 559 5052 1027343 fad0f busybox_unstripped Signed-off-by: Denys Vlasenko --- libbb/uuencode.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libbb/uuencode.c b/libbb/uuencode.c index 6e63bfc6a..21af7a8c9 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c @@ -28,7 +28,7 @@ const char bb_uuenc_tbl_base64[] ALIGN1 = { 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', - '=' /* termination character */, + '=' /* termination character */ }; const char bb_uuenc_tbl_std[] ALIGN1 = { '`', '!', '"', '#', '$', '%', '&', '\'', @@ -38,7 +38,7 @@ const char bb_uuenc_tbl_std[] ALIGN1 = { '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + 'X', 'Y', 'Z', '[', '\\',']', '^', '_', '`' /* termination character */ }; @@ -82,9 +82,10 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl /* * Decode base64 encoded string. * - * Returns: pointer to the undecoded part of source. + * Returns: pointer past the last written output byte, + * the result is not NUL-terminated. + * (*pp_src) is advanced past the last read byte. * If points to '\0', then the source was fully decoded. - * (*pp_dst): advanced past the last written byte. */ char* FAST_FUNC decode_base64(char *dst, const char **pp_src) { @@ -131,7 +132,7 @@ char* FAST_FUNC decode_base64(char *dst, const char **pp_src) } /* i is zero here if full 4-char block was decoded */ if (pp_src) - *pp_src = src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ + *pp_src = src - i; /* -i signals truncation: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ return dst; } @@ -265,7 +266,7 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) if (*in_tail == '\0') return; /* No */ - bb_simple_error_msg_and_die("truncated base64 input"); + bb_simple_error_msg_and_die("truncated input"); } /* It was partial decode */ -- cgit v1.2.3-55-g6feb From 818a4aa2efdfa81315129b04fc24d86d02d12bca Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 14:22:52 +0100 Subject: fix comments Signed-off-by: Denys Vlasenko --- coreutils/uudecode.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 10e5a55de..164b208ea 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -279,6 +279,7 @@ int baseNUM_main(int argc UNUSED_PARAM, char **argv) *--argv = (char*)"-"; src_stream = xfopen_stdin(argv[0]); if (opts & 1) { + /* -d: decode */ int flags = (unsigned char)EOF; if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) flags = ((unsigned char)EOF) | BASE64_32; @@ -286,12 +287,12 @@ int baseNUM_main(int argc UNUSED_PARAM, char **argv) } else { enum { SRC_BUF_SIZE = 3 * 5 * 32, /* this *MUST* be a multiple of 3 and 5 */ - DST_BUF_SIZE = 8 * ((SRC_BUF_SIZE + 4) / 5), /* max growth on decode (base32 case) */ + DST_BUF_SIZE = 8 * ((SRC_BUF_SIZE + 4) / 5), /* max growth on encode (base32 case) */ }; /* Use one buffer for both input and output: - * decoding reads input "left-to-right", + * encoding reads input "left-to-right", * it's safe to place source at the end of the buffer and - * overwrite it while decoding, just be careful to have a gap. + * overwrite it while encoding, just be careful to have a gap. */ char dst_buf[((DST_BUF_SIZE + /*gap:*/ 16) /*round up to 16:*/ | 0xf) + 1]; #define src_buf (dst_buf + sizeof(dst_buf) - SRC_BUF_SIZE) -- cgit v1.2.3-55-g6feb From ab6991c6f59ff2960885bbdec57892e9d0f89598 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 20:58:42 +0100 Subject: date: for -uR and -uIh, timezone still have to be shown at +hhmm, not as abbreviation function old new delta date_main 963 941 -22 Signed-off-by: Denys Vlasenko --- coreutils/date.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/coreutils/date.c b/coreutils/date.c index d84e1c31a..d8a2e8618 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -320,18 +320,16 @@ int date_main(int argc UNUSED_PARAM, char **argv) i = 8 + 3 * ifmt; if (ifmt != 0) { /* TODO: if (ifmt==4) i += sprintf(&fmt_dt2str[i], ",%09u", nanoseconds); */ - format_utc: fmt_dt2str[i++] = '%'; - fmt_dt2str[i++] = (opt & OPT_UTC) ? 'Z' : 'z'; + fmt_dt2str[i++] = 'z'; + /* FIXME: %z prints "+hhmm" timezone, but coreutils-8.30 prints "+hh:mm" */ } fmt_dt2str[i] = '\0'; } else if (opt & OPT_RFC2822) { /* -R. undo busybox.c setlocale */ if (ENABLE_LOCALE_SUPPORT) setlocale(LC_TIME, "C"); - strcpy(fmt_dt2str, "%a, %d %b %Y %H:%M:%S "); - i = sizeof("%a, %d %b %Y %H:%M:%S ")-1; - goto format_utc; + strcpy(fmt_dt2str, "%a, %d %b %Y %H:%M:%S %z"); } else { /* default case */ fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; } -- cgit v1.2.3-55-g6feb From 900eae17384e52cd31d166c09d038cc6e1b64019 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 21:44:58 +0100 Subject: date: support -Ins, more compatible timezone display in -I function old new delta date_main 941 1016 +75 static.isoformats 28 31 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 78/0) Total: 78 bytes Signed-off-by: Denys Vlasenko --- coreutils/date.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/coreutils/date.c b/coreutils/date.c index d8a2e8618..7fead01bd 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -208,7 +208,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) ifmt = 0; /* default is date */ if (isofmt_arg) { static const char isoformats[] ALIGN1 = - "date\0""hours\0""minutes\0""seconds\0"; /* ns? */ + "date\0""hours\0""minutes\0""seconds\0ns\0"; ifmt = index_in_substrings(isoformats, isofmt_arg); if (ifmt < 0) bb_show_usage(); @@ -315,21 +315,33 @@ int date_main(int argc UNUSED_PARAM, char **argv) int i; fmt_dt2str = buf_fmt_dt2str; if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) { - /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds */ + /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds 4:ns*/ strcpy(fmt_dt2str, "%Y-%m-%dT%H:%M:%S"); i = 8 + 3 * ifmt; if (ifmt != 0) { - /* TODO: if (ifmt==4) i += sprintf(&fmt_dt2str[i], ",%09u", nanoseconds); */ - fmt_dt2str[i++] = '%'; - fmt_dt2str[i++] = 'z'; - /* FIXME: %z prints "+hhmm" timezone, but coreutils-8.30 prints "+hh:mm" */ + int n; + if (ifmt == 4) { + i -= 3; + i += sprintf(&fmt_dt2str[i], ",%09u", (unsigned)ts.tv_nsec); + } + /* %z prints "+hhmm" timezone, but coreutils-8.30 prints "+hh:mm"! */ + /* ...therefore this atrocity: */ + n = strftime(&fmt_dt2str[i], 8, "%z", &tm_time); + i += n; + if (n == 5 && (fmt_dt2str[i-5] == '+' || fmt_dt2str[i-5] == '-')) { + /* "mm" -> ":mm" */ + fmt_dt2str[i ] = fmt_dt2str[i - 1]; + fmt_dt2str[i - 1] = fmt_dt2str[i - 2]; + fmt_dt2str[i - 2] = ':'; + i++; + } } fmt_dt2str[i] = '\0'; } else if (opt & OPT_RFC2822) { /* -R. undo busybox.c setlocale */ if (ENABLE_LOCALE_SUPPORT) setlocale(LC_TIME, "C"); - strcpy(fmt_dt2str, "%a, %d %b %Y %H:%M:%S %z"); + fmt_dt2str = (char*)"%a, %d %b %Y %H:%M:%S %z"; } else { /* default case */ fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; } -- cgit v1.2.3-55-g6feb From f26c5660c2f4b6e096eca69f1de342fe3871ccf1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 22:01:15 +0100 Subject: date: trim --help (no need to show long opts) Signed-off-by: Denys Vlasenko --- coreutils/date.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/coreutils/date.c b/coreutils/date.c index 7fead01bd..3a3344b90 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -96,30 +96,20 @@ //usage: "[OPTIONS] [+FMT] [TIME]" //usage:#define date_full_usage "\n\n" //usage: "Display time (using +FMT), or set time\n" -//usage: IF_NOT_LONG_OPTS( -//usage: "\n [-s] TIME Set time to TIME" //usage: "\n -u Work in UTC (don't convert to local time)" -//usage: "\n -R Output RFC-2822 compliant date string" -//usage: ) IF_LONG_OPTS( -//usage: "\n [-s,--set] TIME Set time to TIME" -//usage: "\n -u,--utc Work in UTC (don't convert to local time)" -//usage: "\n -R,--rfc-2822 Output RFC-2822 compliant date string" -//usage: ) +//usage: "\n [-s] TIME Set time to TIME" +//usage: "\n -d TIME Display TIME, not 'now'" //usage: IF_FEATURE_DATE_ISOFMT( -//usage: "\n -I[SPEC] Output ISO-8601 compliant date string" -//usage: "\n SPEC='date' (default) for date only," -//usage: "\n 'hours', 'minutes', or 'seconds' for date and" -//usage: "\n time to the indicated precision" +//usage: "\n -D FMT Use FMT (strptime format) for -d TIME conversion" +//////// ^^^^^^ busybox invention, not compat //usage: ) -//usage: IF_NOT_LONG_OPTS( //usage: "\n -r FILE Display last modification time of FILE" -//usage: "\n -d TIME Display TIME, not 'now'" -//usage: ) IF_LONG_OPTS( -//usage: "\n -r,--reference FILE Display last modification time of FILE" -//usage: "\n -d,--date TIME Display TIME, not 'now'" -//usage: ) +//usage: "\n -R Output RFC-2822 date" //usage: IF_FEATURE_DATE_ISOFMT( -//usage: "\n -D FMT Use FMT (strptime format) for -d TIME conversion" +//usage: "\n -I[SPEC] Output ISO-8601 date" +//usage: "\n SPEC='date' (default) for date only," +//usage: "\n 'hours', 'minutes', 'seconds' or 'ns'" +//usage: "\n for date and time" //usage: ) //usage: "\n" //usage: "\nRecognized TIME formats:" -- cgit v1.2.3-55-g6feb From 56a5731a1a06ab785fc327b2a864466325fd262e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 22:07:00 +0100 Subject: date: remove non-standard special-casing of date '+%f' git log did not reveal why it is there. function old new delta date_main 1016 995 -21 Signed-off-by: Denys Vlasenko --- coreutils/date.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/coreutils/date.c b/coreutils/date.c index 3a3344b90..585866fd2 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -383,10 +383,6 @@ int date_main(int argc UNUSED_PARAM, char **argv) /* With no format string, just print a blank line */ date_buf[0] = '\0'; } else { - /* Handle special conversions */ - if (is_prefixed_with(fmt_dt2str, "%f")) { - fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S"; - } /* Generate output string */ strftime(date_buf, COMMON_BUFSIZE, fmt_dt2str, &tm_time); } -- cgit v1.2.3-55-g6feb From 4dee01605996be88ec247256eb47d2686f6b7104 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 23:04:09 +0100 Subject: date: tweak --help: -D FMT is used for -s TIME as well Signed-off-by: Denys Vlasenko --- coreutils/date.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/coreutils/date.c b/coreutils/date.c index 585866fd2..dfc1c7663 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -93,23 +93,21 @@ */ //usage:#define date_trivial_usage -//usage: "[OPTIONS] [+FMT] [TIME]" +//usage: "[OPTIONS] [+FMT] [[-s] TIME]" //usage:#define date_full_usage "\n\n" //usage: "Display time (using +FMT), or set time\n" //usage: "\n -u Work in UTC (don't convert to local time)" //usage: "\n [-s] TIME Set time to TIME" //usage: "\n -d TIME Display TIME, not 'now'" //usage: IF_FEATURE_DATE_ISOFMT( -//usage: "\n -D FMT Use FMT (strptime format) for -d TIME conversion" -//////// ^^^^^^ busybox invention, not compat +//usage: "\n -D FMT FMT (strptime format) for -s/-d TIME conversion" +////////^^^^^^^^^^^^^^^^^^^^^^ busybox invention, not compat //usage: ) //usage: "\n -r FILE Display last modification time of FILE" //usage: "\n -R Output RFC-2822 date" //usage: IF_FEATURE_DATE_ISOFMT( //usage: "\n -I[SPEC] Output ISO-8601 date" -//usage: "\n SPEC='date' (default) for date only," -//usage: "\n 'hours', 'minutes', 'seconds' or 'ns'" -//usage: "\n for date and time" +//usage: "\n SPEC=date (default), hours, minutes, seconds or ns" //usage: ) //usage: "\n" //usage: "\nRecognized TIME formats:" @@ -137,8 +135,8 @@ enum { OPT_UTC = (1 << 2), /* u */ OPT_DATE = (1 << 3), /* d */ OPT_REFERENCE = (1 << 4), /* r */ - OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ - OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ + OPT_ISO8601 = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ + OPT_STR2DT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ }; #if ENABLE_LONG_OPTS @@ -160,12 +158,6 @@ static const char date_longopts[] ALIGN1 = * - after xasprintf we use other xfuncs */ -static void maybe_set_utc(int opt) -{ - if (opt & OPT_UTC) - putenv((char*)"TZ=UTC0"); -} - int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int date_main(int argc UNUSED_PARAM, char **argv) { @@ -173,7 +165,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) struct tm tm_time; char buf_fmt_dt2str[64]; unsigned opt; - int ifmt = -1; + int isofmt = -1; char *date_str; char *fmt_dt2str; char *fmt_str2dt; @@ -192,15 +184,16 @@ int date_main(int argc UNUSED_PARAM, char **argv) ); argv += optind; - maybe_set_utc(opt); + if (opt & OPT_UTC) + putenv((char*)"TZ=UTC0"); - if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_TIMESPEC)) { - ifmt = 0; /* default is date */ + if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_ISO8601)) { + isofmt = 0; /* default is date */ if (isofmt_arg) { static const char isoformats[] ALIGN1 = "date\0""hours\0""minutes\0""seconds\0ns\0"; - ifmt = index_in_substrings(isoformats, isofmt_arg); - if (ifmt < 0) + isofmt = index_in_substrings(isoformats, isofmt_arg); + if (isofmt < 0) bb_show_usage(); } } @@ -210,7 +203,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) fmt_dt2str = &argv[0][1]; /* skip over the '+' */ argv++; } - if (!(opt & (OPT_SET | OPT_DATE))) { + if (!(opt & (OPT_SET | OPT_DATE))) { /* neither -s TIME nor -d TIME? */ opt |= OPT_SET; date_str = argv[0]; /* can be NULL */ if (date_str) { @@ -278,7 +271,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) tm_time.tm_hour = 0; /* Process any date input to UNIX time since 1 Jan 1970 */ - if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_HINT)) { + if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_STR2DT)) { if (strptime(date_str, fmt_str2dt, &tm_time) == NULL) bb_error_msg_and_die(bb_msg_invalid_date, date_str); } else { @@ -304,13 +297,13 @@ int date_main(int argc UNUSED_PARAM, char **argv) if (fmt_dt2str == NULL) { int i; fmt_dt2str = buf_fmt_dt2str; - if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) { + if (ENABLE_FEATURE_DATE_ISOFMT && isofmt >= 0) { /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds 4:ns*/ strcpy(fmt_dt2str, "%Y-%m-%dT%H:%M:%S"); - i = 8 + 3 * ifmt; - if (ifmt != 0) { + i = 8 + 3 * isofmt; + if (isofmt != 0) { int n; - if (ifmt == 4) { + if (isofmt == 4) { i -= 3; i += sprintf(&fmt_dt2str[i], ",%09u", (unsigned)ts.tv_nsec); } -- cgit v1.2.3-55-g6feb From 32a8f70ac1caa4037b63747c0c0a5086953ea668 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Nov 2020 23:21:13 +0100 Subject: libbb: in @SECONDS date format, use 64-bit time if libc allows function old new delta packed_usage 33472 33486 +14 parse_datestr 919 916 -3 Signed-off-by: Denys Vlasenko --- coreutils/date.c | 1 + libbb/time.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/coreutils/date.c b/coreutils/date.c index dfc1c7663..7061f1719 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -111,6 +111,7 @@ //usage: ) //usage: "\n" //usage: "\nRecognized TIME formats:" +//usage: "\n @seconds_since_1970" //usage: "\n hh:mm[:ss]" //usage: "\n [YYYY.]MM.DD-hh:mm[:ss]" //usage: "\n YYYY-MM-DD hh:mm[:ss]" diff --git a/libbb/time.c b/libbb/time.c index e66a9cba8..86b88a414 100644 --- a/libbb/time.c +++ b/libbb/time.c @@ -90,7 +90,11 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ } else if (date_str[0] == '@') { - time_t t = bb_strtol(date_str + 1, NULL, 10); + time_t t; + if (sizeof(t) <= sizeof(long)) + t = bb_strtol(date_str + 1, NULL, 10); + else /* time_t is 64 bits but longs are smaller */ + t = bb_strtoll(date_str + 1, NULL, 10); if (!errno) { struct tm *lt = localtime(&t); if (lt) { -- cgit v1.2.3-55-g6feb From 87bd558f3f0452ed62f2686472e03a1be4a6e36d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Nov 2020 11:32:48 +0100 Subject: libbb: bb_do_delay(3) -> pause_after_failed_login(), and stop looping there function old new delta pause_after_failed_login - 9 +9 vlock_main 358 353 -5 sulogin_main 252 247 -5 su_main 484 479 -5 passwd_main 936 931 -5 login_main 967 962 -5 bb_do_delay 68 - -68 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/5 up/down: 9/-93) Total: -84 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 7 ++++--- libbb/bb_do_delay.c | 22 ++++++++++++++++------ loginutils/login.c | 2 +- loginutils/passwd.c | 2 +- loginutils/su.c | 2 +- loginutils/sulogin.c | 2 +- loginutils/vlock.c | 2 +- networking/pscan.c | 2 +- 8 files changed, 26 insertions(+), 15 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index e56fff3e8..6b822016e 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1604,9 +1604,10 @@ char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC; #ifndef LOGIN_FAIL_DELAY #define LOGIN_FAIL_DELAY 3 #endif -extern void bb_do_delay(int seconds) FAST_FUNC; -extern void change_identity(const struct passwd *pw) FAST_FUNC; -extern void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; +void pause_after_failed_login(void) FAST_FUNC; +void bb_do_delay(int seconds) FAST_FUNC; +void change_identity(const struct passwd *pw) FAST_FUNC; +void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; /* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL. * Note that getpwuid result might need xstrdup'ing diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c index 65541704b..29343305d 100644 --- a/libbb/bb_do_delay.c +++ b/libbb/bb_do_delay.c @@ -8,13 +8,23 @@ */ #include "libbb.h" -void FAST_FUNC bb_do_delay(int seconds) +/* void FAST_FUNC bb_do_delay(int seconds) { ... } - no users yet */ + +#ifndef LOGIN_FAIL_DELAY +#define LOGIN_FAIL_DELAY 3 +#endif +void FAST_FUNC pause_after_failed_login(void) { - time_t start, now; +#if 0 /* over-engineered madness */ + time_t end, diff; - start = time(NULL); + end = time(NULL) + LOGIN_FAIL_DELAY; + diff = LOGIN_FAIL_DELAY; do { - sleep(seconds); - now = time(NULL); - } while ((now - start) < seconds); + sleep(diff); + diff = end - time(NULL); + } while (diff > 0); +#else + sleep(LOGIN_FAIL_DELAY); +#endif } diff --git a/loginutils/login.c b/loginutils/login.c index 3531d1424..c3a835180 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -505,7 +505,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) #endif /* ENABLE_PAM */ auth_failed: opt &= ~LOGIN_OPT_f; - bb_do_delay(LOGIN_FAIL_DELAY); + pause_after_failed_login(); /* TODO: doesn't sound like correct English phrase to me */ puts("Login incorrect"); if (++count == 3) { diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 6c643d3d0..770acf58a 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c @@ -57,7 +57,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */ if (strcmp(encrypted, pw->pw_passwd) != 0) { syslog(LOG_WARNING, "incorrect password for %s", pw->pw_name); - bb_do_delay(LOGIN_FAIL_DELAY); + pause_after_failed_login(); puts("Incorrect password"); goto err_ret; } diff --git a/loginutils/su.c b/loginutils/su.c index 7c1fc69c5..6f91039f9 100644 --- a/loginutils/su.c +++ b/loginutils/su.c @@ -146,7 +146,7 @@ int su_main(int argc UNUSED_PARAM, char **argv) if (ENABLE_FEATURE_SU_SYSLOG) syslog(LOG_NOTICE, "%c %s %s:%s", '-', tty, old_user, opt_username); - bb_do_delay(LOGIN_FAIL_DELAY); + pause_after_failed_login(); bb_simple_error_msg_and_die("incorrect password"); } diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 099085340..48dafd186 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c @@ -74,7 +74,7 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) if (r > 0) { break; } - bb_do_delay(LOGIN_FAIL_DELAY); + pause_after_failed_login(); bb_simple_info_msg("Login incorrect"); } diff --git a/loginutils/vlock.c b/loginutils/vlock.c index 9e319fe61..334b7d2ad 100644 --- a/loginutils/vlock.c +++ b/loginutils/vlock.c @@ -120,7 +120,7 @@ int vlock_main(int argc UNUSED_PARAM, char **argv) if (ask_and_check_password(pw) > 0) { break; } - bb_do_delay(LOGIN_FAIL_DELAY); + pause_after_failed_login(); puts("Incorrect password"); } diff --git a/networking/pscan.c b/networking/pscan.c index 2715ef2df..e114e55d2 100644 --- a/networking/pscan.c +++ b/networking/pscan.c @@ -139,7 +139,7 @@ int pscan_main(int argc UNUSED_PARAM, char **argv) * We check rtt BEFORE we usleep, otherwise * on localhost we'll have no writes done (!) * before we exceed (rather small) rtt */ - usleep(rtt_4/8); + usleep(rtt_4 / 8); open: diff = MONOTONIC_US() - start; DMSG("write to port %u @%u", port, diff - start); -- cgit v1.2.3-55-g6feb From ec16c030bd5527137f95a1c30e6a1f3c9054dcf7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Nov 2020 11:37:34 +0100 Subject: libbb: introduce and use sleep1() function old new delta sleep1 - 9 +9 run_shutdown_and_kill_processes 97 95 -2 restore_state_and_exit 116 114 -2 reread_partition_table 67 65 -2 flush_buffer_cache 80 78 -2 chat_main 1302 1300 -2 timeout_main 310 307 -3 telnet_main 1235 1232 -3 stop_handler 86 83 -3 process_action 1078 1075 -3 nbdclient_main 1185 1182 -3 init_main 789 786 -3 getty_main 1541 1538 -3 do_time 410 407 -3 runsv_main 1682 1677 -5 pause_and_low_level_reboot 59 54 -5 inetd_main 1917 1911 -6 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/16 up/down: 9/-50) Total: -41 bytes Signed-off-by: Denys Vlasenko --- coreutils/timeout.c | 2 +- e2fsprogs/fsck.c | 2 +- include/libbb.h | 4 +--- init/halt.c | 4 ++-- init/init.c | 12 ++++++------ libbb/bb_do_delay.c | 6 ++++++ loginutils/getty.c | 2 +- miscutils/chat.c | 2 +- miscutils/hdparm.c | 4 ++-- networking/ifplugd.c | 2 +- networking/inetd.c | 4 ++-- networking/nbd-client.c | 2 +- networking/nc_bloaty.c | 2 +- networking/slattach.c | 2 +- networking/telnet.c | 2 +- runit/runsv.c | 4 ++-- sysklogd/logread.c | 2 +- util-linux/fdisk.c | 2 +- util-linux/mdev.c | 2 +- 19 files changed, 33 insertions(+), 29 deletions(-) diff --git a/coreutils/timeout.c b/coreutils/timeout.c index 8b7bc2eaa..2a628b71d 100644 --- a/coreutils/timeout.c +++ b/coreutils/timeout.c @@ -105,7 +105,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) grandchild: /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ while (1) { - sleep(1); + sleep1(); if (--timeout <= 0) break; if (kill(parent, 0)) { diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index fc53a9043..96c1e51e0 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c @@ -480,7 +480,7 @@ static int wait_one(int flags) * time to set up the signal handler */ if (inst2->start_time >= time(NULL) - 1) - sleep(1); + sleep1(); kill(inst2->pid, SIGUSR1); inst2->flags |= FLAG_PROGRESS; break; diff --git a/include/libbb.h b/include/libbb.h index 6b822016e..9fa0ce90d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1601,11 +1601,9 @@ char *bb_simplify_path(const char *path) FAST_FUNC; /* Returns ptr to NUL */ char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC; -#ifndef LOGIN_FAIL_DELAY -#define LOGIN_FAIL_DELAY 3 -#endif void pause_after_failed_login(void) FAST_FUNC; void bb_do_delay(int seconds) FAST_FUNC; +void sleep1(void) FAST_FUNC; void change_identity(const struct passwd *pw) FAST_FUNC; void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; diff --git a/init/halt.c b/init/halt.c index 785c38130..2070eaa4d 100644 --- a/init/halt.c +++ b/init/halt.c @@ -144,14 +144,14 @@ static int init_was_not_there(void) */ #if 0 while (kill(1, 0) != 0 && --cnt >= 0) - sleep(1); + sleep1(); #endif /* ... so let's wait for some evidence a usual startup event, * mounting of /proc, happened. By that time init should be ready * for signals. */ while (access("/proc/meminfo", F_OK) != 0 && --cnt >= 0) - sleep(1); + sleep1(); /* Does it look like init wasn't there? */ return (cnt != initial - 1); diff --git a/init/init.c b/init/init.c index 28775a65c..efab5dcb4 100644 --- a/init/init.c +++ b/init/init.c @@ -736,7 +736,7 @@ static void pause_and_low_level_reboot(unsigned magic) pid_t pid; /* Allow time for last message to reach serial console, etc */ - sleep(1); + sleep1(); /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS) * in linux/kernel/sys.c, which can cause the machine to panic when @@ -751,7 +751,7 @@ static void pause_and_low_level_reboot(unsigned magic) * we would eternally sleep here - not what we want. */ waitpid(pid, NULL, 0); - sleep(1); /* paranoia */ + sleep1(); /* paranoia */ _exit(EXIT_SUCCESS); } @@ -768,12 +768,12 @@ static void run_shutdown_and_kill_processes(void) kill(-1, SIGTERM); message(L_CONSOLE, "Sent SIG%s to all processes", "TERM"); sync(); - sleep(1); + sleep1(); kill(-1, SIGKILL); message(L_CONSOLE, "Sent SIG%s to all processes", "KILL"); sync(); - /*sleep(1); - callers take care about making a pause */ + /*sleep1(); - callers take care about making a pause */ } /* Signal handling by init: @@ -904,7 +904,7 @@ static void stop_handler(int sig UNUSED_PARAM) wpid = wait_any_nohang(NULL); mark_terminated(wpid); if (wpid <= 0) /* no processes exited? sleep a bit */ - sleep(1); + sleep1(); } signal(SIGCONT, SIG_DFL); @@ -1209,7 +1209,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) } /* Don't consume all CPU time - sleep a bit */ - sleep(1); + sleep1(); } /* while (1) */ } diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c index 29343305d..3a86dc2ae 100644 --- a/libbb/bb_do_delay.c +++ b/libbb/bb_do_delay.c @@ -28,3 +28,9 @@ void FAST_FUNC pause_after_failed_login(void) sleep(LOGIN_FAIL_DELAY); #endif } + +void FAST_FUNC sleep1(void) +{ + sleep(1); +} + diff --git a/loginutils/getty.c b/loginutils/getty.c index 7393a3d1c..99af72f68 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c @@ -434,7 +434,7 @@ static void auto_baud(void) * Wait for a while, then read everything the modem has said so far and * try to extract the speed of the dial-in call. */ - sleep(1); + sleep1(); nread = safe_read(STDIN_FILENO, G.line_buf, sizeof(G.line_buf) - 1); if (nread > 0) { int speed; diff --git a/miscutils/chat.c b/miscutils/chat.c index a04565063..a7faaf284 100644 --- a/miscutils/chat.c +++ b/miscutils/chat.c @@ -473,7 +473,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv) if ('\\' == c) { c = *++buf; if ('d' == c) { - sleep(1); + sleep1(); len--; continue; } diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index d25a2466e..431a0ad96 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c @@ -1436,7 +1436,7 @@ static void flush_buffer_cache(/*int fd*/ void) fsync(fd); /* flush buffers */ ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */ #ifdef HDIO_DRIVE_CMD - sleep(1); + sleep1(); if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) { /* await completion */ if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */ bb_simple_perror_msg("HDIO_DRIVE_CMD"); @@ -1511,7 +1511,7 @@ static void do_time(int cache /*,int fd*/) * NB: *small* delay. User is expected to have a clue and to not run * heavy io in parallel with measurements. */ sync(); - sleep(1); + sleep1(); if (cache) { /* Time cache */ seek_to_zero(); read_big_block(buf); diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 0d17b7d8c..60916eae6 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c @@ -735,7 +735,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv) delay_time += G.delay_down; #if 0 /* if you are back in 1970... */ if (delay_time == 0) { - sleep(1); + sleep1(); delay_time = 1; } #endif diff --git a/networking/inetd.c b/networking/inetd.c index 3cd2b11f0..44b1ac700 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -1305,7 +1305,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) if (ready_fd_cnt < 0) { if (errno != EINTR) { bb_simple_perror_msg("select"); - sleep(1); + sleep1(); } continue; } @@ -1406,7 +1406,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) if (pid < 0) { /* fork error */ bb_simple_perror_msg("vfork"+1); - sleep(1); + sleep1(); restore_sigmask(&omask); maybe_close(new_udp_fd); maybe_close(accepted_fd); diff --git a/networking/nbd-client.c b/networking/nbd-client.c index 3db3b46f9..755b42ccd 100644 --- a/networking/nbd-client.c +++ b/networking/nbd-client.c @@ -270,7 +270,7 @@ int nbdclient_main(int argc, char **argv) close(fd); break; } - sleep(1); + sleep1(); } open(device, O_RDONLY); return 0; diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 88eda6b28..25b95246f 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c @@ -196,7 +196,7 @@ enum { /* Debug: squirt whatever message and sleep a bit so we can see it go by. */ /* Beware: writes to stdOUT... */ #if 0 -#define Debug(...) do { printf(__VA_ARGS__); printf("\n"); fflush_all(); sleep(1); } while (0) +#define Debug(...) do { printf(__VA_ARGS__); printf("\n"); fflush_all(); sleep1(); } while (0) #else #define Debug(...) do { } while (0) #endif diff --git a/networking/slattach.c b/networking/slattach.c index 51fbc1f49..6d2a252fc 100644 --- a/networking/slattach.c +++ b/networking/slattach.c @@ -76,7 +76,7 @@ static void restore_state_and_exit(int exitcode) cfsetispeed(&state, B0); cfsetospeed(&state, B0); exitcode |= tcsetattr_serial_or_warn(&state); - sleep(1); + sleep1(); /* Restore line status */ if (tcsetattr_serial_or_warn(&G.saved_state)) diff --git a/networking/telnet.c b/networking/telnet.c index 9fc85050b..19a414b30 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -673,7 +673,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) if (bb_got_signal) con_escape(); else - sleep(1); + sleep1(); continue; } diff --git a/runit/runsv.c b/runit/runsv.c index 36d85101e..7e22862cd 100644 --- a/runit/runsv.c +++ b/runit/runsv.c @@ -651,7 +651,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) gettimeofday_ns(&svd[0].start); update_status(&svd[0]); if (LESS(svd[0].start.tv_sec, deadline)) - sleep(1); + sleep1(); } if (haslog) { if (child == svd[1].pid) { @@ -664,7 +664,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv) gettimeofday_ns(&svd[1].start); update_status(&svd[1]); if (LESS(svd[1].start.tv_sec, deadline)) - sleep(1); + sleep1(); } } } /* for (;;) */ diff --git a/sysklogd/logread.c b/sysklogd/logread.c index 1e1f1347f..b52dc9cac 100644 --- a/sysklogd/logread.c +++ b/sysklogd/logread.c @@ -180,7 +180,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv) if (cur == shbuf_tail) { sem_up(log_semid); fflush_all(); - sleep(1); /* TODO: replace me with a sleep_on */ + sleep1(); /* TODO: replace me with a sleep_on */ continue; } } diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 0fb2e3e17..0df3ebf7d 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -2667,7 +2667,7 @@ reread_partition_table(int leave) /* Users with slow external USB disks on a 320MHz ARM system (year 2011) * report that sleep is needed, otherwise BLKRRPART may fail with -EIO: */ - sleep(1); + sleep1(); i = ioctl_or_perror(dev_fd, BLKRRPART, NULL, "WARNING: rereading partition table " "failed, kernel still uses old table"); diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 9a8c14456..ebf83d1a3 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -920,7 +920,7 @@ static void load_firmware(const char *firmware, const char *sysfs_path) loading_fd = open("loading", O_WRONLY); if (loading_fd >= 0) goto loading; - sleep(1); + sleep1(); } goto out; -- cgit v1.2.3-55-g6feb From b86a9ed699e2c4693167d6ead00ac307bd9c01c6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Nov 2020 11:49:37 +0100 Subject: use write_str() functions where appropriate function old new delta chat_main 1300 1295 -5 finalize_tty_attrs 80 70 -10 getty_main 1538 1519 -19 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-34) Total: -34 bytes Signed-off-by: Denys Vlasenko --- loginutils/getty.c | 6 +++--- miscutils/chat.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/loginutils/getty.c b/loginutils/getty.c index 99af72f68..6c6d409f4 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c @@ -404,7 +404,7 @@ static void finalize_tty_attrs(void) set_tty_attrs(); /* Now the newline character should be properly written */ - full_write(STDOUT_FILENO, "\n", 1); + full_write1_str("\n"); } /* extract baud rate from modem status message */ @@ -498,13 +498,13 @@ static char *get_logname(void) case 0x7f: G.tty_attrs.c_cc[VERASE] = c; if (bp > G.line_buf) { - full_write(STDOUT_FILENO, "\010 \010", 3); + full_write1_str("\010 \010"); bp--; } break; case CTL('U'): while (bp > G.line_buf) { - full_write(STDOUT_FILENO, "\010 \010", 3); + full_write1_str("\010 \010"); bp--; } break; diff --git a/miscutils/chat.c b/miscutils/chat.c index a7faaf284..86a114df6 100644 --- a/miscutils/chat.c +++ b/miscutils/chat.c @@ -379,7 +379,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv) // dump device input if ECHO ON if (echo) { // if (buf[buf_len] < ' ') { -// full_write(STDERR_FILENO, "^", 1); +// full_write2_str("^"); // buf[buf_len] += '@'; // } full_write(STDERR_FILENO, buf+buf_len, 1); @@ -509,7 +509,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_CHAT_IMPLICIT_CR // or terminate command with \r (if not inhibited) else if (!nocr) - xwrite(STDOUT_FILENO, "\r", 1); + xwrite_str(STDOUT_FILENO, "\r"); #endif // bail out unless we sent command successfully if (exitcode) -- cgit v1.2.3-55-g6feb From 6a55b4e403979ba299261816a7ec1bb55bbf3f2b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Nov 2020 12:40:25 +0100 Subject: libbb: introduce and use msleep() function old new delta msleep - 45 +45 watchdog_main 271 266 -5 common_traceroute_main 3546 3530 -16 beep_main 277 248 -29 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/3 up/down: 45/-50) Total: -5 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 3 ++- libbb/bb_do_delay.c | 15 ++++++++++++++- miscutils/beep.c | 4 ++-- miscutils/watchdog.c | 2 +- networking/traceroute.c | 2 +- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 9fa0ce90d..18dc9f935 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1602,7 +1602,8 @@ char *bb_simplify_path(const char *path) FAST_FUNC; char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC; void pause_after_failed_login(void) FAST_FUNC; -void bb_do_delay(int seconds) FAST_FUNC; +void bb_do_delay(unsigned seconds) FAST_FUNC; +void msleep(unsigned ms) FAST_FUNC; void sleep1(void) FAST_FUNC; void change_identity(const struct passwd *pw) FAST_FUNC; void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c index 3a86dc2ae..3dbf032db 100644 --- a/libbb/bb_do_delay.c +++ b/libbb/bb_do_delay.c @@ -8,7 +8,7 @@ */ #include "libbb.h" -/* void FAST_FUNC bb_do_delay(int seconds) { ... } - no users yet */ +/* void FAST_FUNC bb_do_delay(unsigned seconds) { ... } - no users yet */ #ifndef LOGIN_FAIL_DELAY #define LOGIN_FAIL_DELAY 3 @@ -34,3 +34,16 @@ void FAST_FUNC sleep1(void) sleep(1); } +void FAST_FUNC msleep(unsigned ms) +{ + /* 1. usleep(n) is not guaranteed by standards to accept n >= 1000000 + * 2. multiplication in usleep(ms * 1000) can overflow if ms > 4294967 + * (sleep of ~71.5 minutes) + * Let's play safe and loop: + */ + while (ms > 500) { + usleep(500000); + ms -= 500; + } + usleep(ms * 1000); +} diff --git a/miscutils/beep.c b/miscutils/beep.c index 1669332fd..7c60aed08 100644 --- a/miscutils/beep.c +++ b/miscutils/beep.c @@ -114,10 +114,10 @@ int beep_main(int argc, char **argv) while (rep) { //bb_error_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay); xioctl(speaker, KIOCSOUND, (void*)(uintptr_t)tickrate_div_freq); - usleep(1000 * length); + msleep(length); ioctl(speaker, KIOCSOUND, (void*)0); if (--rep) - usleep(1000 * delay); + msleep(delay); } } diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c index 8c8d7217f..971b777a3 100644 --- a/miscutils/watchdog.c +++ b/miscutils/watchdog.c @@ -143,7 +143,7 @@ int watchdog_main(int argc UNUSED_PARAM, char **argv) * as the counter value is undefined at this point -- PFM */ write(3, "", 1); /* write zero byte */ - usleep(stimer_duration * 1000L); + msleep(stimer_duration); } return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */ } diff --git a/networking/traceroute.c b/networking/traceroute.c index 1c4dc3e4a..34d2a09dd 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -1071,7 +1071,7 @@ common_traceroute_main(int op, char **argv) fflush_all(); if (probe != 0 && pausemsecs > 0) - usleep(pausemsecs * 1000); + msleep(pausemsecs); send_probe(++seq, ttl); t2 = t1 = monotonic_us(); -- cgit v1.2.3-55-g6feb From eb773054e47a30c78a82ed80ad4da7abe9bfb09b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Nov 2020 14:24:14 +0100 Subject: libbb: code shrink function old new delta generate_uuid 124 103 -21 Signed-off-by: Denys Vlasenko --- libbb/xfuncs_printf.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index f1cf7aeed..fcc798662 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c @@ -633,14 +633,11 @@ void FAST_FUNC generate_uuid(uint8_t *buf) pid_t pid; int i; - i = open("/dev/urandom", O_RDONLY); - if (i >= 0) { - read(i, buf, 16); - close(i); - } + open_read_close("/dev/urandom", buf, 16); /* Paranoia. /dev/urandom may be missing. * rand() is guaranteed to generate at least [0, 2^15) range, - * but lowest bits in some libc are not so "random". */ + * but lowest bits in some libc are not so "random". + */ srand(monotonic_us()); /* pulls in printf */ pid = getpid(); while (1) { -- cgit v1.2.3-55-g6feb From 33e955ab91d2f76bd8ea6e12fce215d863f4d7d7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Nov 2020 11:18:00 +0100 Subject: unicode: fix handling of short 1-4 char tables function old new delta in_uint16_table 92 107 +15 Signed-off-by: Denys Vlasenko --- libbb/time.c | 1 - libbb/unicode.c | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libbb/time.c b/libbb/time.c index 86b88a414..74a69eefb 100644 --- a/libbb/time.c +++ b/libbb/time.c @@ -250,7 +250,6 @@ char* FAST_FUNC strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) #if ENABLE_MONOTONIC_SYSCALL -#include /* Old glibc (< 2.3.4) does not provide this constant. We use syscall * directly so this definition is safe. */ #ifndef CLOCK_MONOTONIC diff --git a/libbb/unicode.c b/libbb/unicode.c index 79481f159..bfeaef895 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c @@ -306,8 +306,10 @@ static int in_uint16_table(unsigned ucs, const uint16_t *table, unsigned max) unsigned first, last; first = table[0] >> 2; - last = first + (table[0] & 3); - if (ucs < first || ucs > last) + if (ucs < first) + return 0; + last = (table[max] >> 2) + (table[max] & 3); + if (ucs > last) return 0; min = 0; -- cgit v1.2.3-55-g6feb From 2fba2f5bb99145eaa1635fe5a162426158d56a2c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Nov 2020 11:30:17 +0100 Subject: unicode: relax array alignment for tables text data bss dec hex filename 1022075 559 5052 1027686 fae66 busybox_old 1021988 559 5052 1027599 fae0f busybox_unstripped Signed-off-by: Denys Vlasenko --- libbb/unicode.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libbb/unicode.c b/libbb/unicode.c index bfeaef895..e98cbbf35 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c @@ -25,7 +25,7 @@ uint8_t unicode_status; void FAST_FUNC reinit_unicode(const char *LANG) { - static const char unicode_0x394[] = { 0xce, 0x94, 0 }; + static const char unicode_0x394[] ALIGN1 = { 0xce, 0x94, 0 }; size_t width; /* We pass "" instead of "C" because some libc's have @@ -589,12 +589,12 @@ int FAST_FUNC wcwidth(unsigned ucs) BIG_(0xFE20, 0xFE23) \ BIG_(0xFEFF, 0xFEFF) \ BIG_(0xFFF9, 0xFFFB) - static const struct interval combining[] = { ARRAY }; + static const struct interval combining[] ALIGN4 = { ARRAY }; # undef BIG_ # undef PAIR # define BIG_(a,b) # define PAIR(a,b) (a << 2) | (b-a), - static const uint16_t combining1[] = { ARRAY }; + static const uint16_t combining1[] ALIGN2 = { ARRAY }; # undef BIG_ # undef PAIR # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; @@ -648,7 +648,7 @@ int FAST_FUNC wcwidth(unsigned ucs) # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x10000 if (ucs >= 0x10000) { /* Combining chars in Supplementary Multilingual Plane 0x1xxxx */ - static const struct interval combining0x10000[] = { + static const struct interval combining0x10000[] ALIGN4 = { { 0x0A01, 0x0A03 }, { 0x0A05, 0x0A06 }, { 0x0A0C, 0x0A0F }, { 0x0A38, 0x0A3A }, { 0x0A3F, 0x0A3F }, { 0xD167, 0xD169 }, { 0xD173, 0xD182 }, { 0xD185, 0xD18B }, { 0xD1AA, 0xD1AD }, @@ -759,12 +759,12 @@ int FAST_FUNC unicode_bidi_isrtl(wint_t wc) {0x10E7F, 0x10FFF}, {0x1E800, 0x1EFFF} */ - static const struct interval rtl_b[] = { ARRAY }; + static const struct interval rtl_b[] ALIGN4 = { ARRAY }; # undef BIG_ # undef PAIR # define BIG_(a,b) # define PAIR(a,b) (a << 2) | (b-a), - static const uint16_t rtl_p[] = { ARRAY }; + static const uint16_t rtl_p[] ALIGN2 = { ARRAY }; # undef BIG_ # undef PAIR # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; @@ -963,12 +963,12 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) {0x1F030, 0x1F093}, {0x1F100, 0x1F10A} */ - static const struct interval neutral_b[] = { ARRAY }; + static const struct interval neutral_b[] ALIGN4 = { ARRAY }; # undef BIG_ # undef PAIR # define BIG_(a,b) # define PAIR(a,b) (a << 2) | (b-a), - static const uint16_t neutral_p[] = { ARRAY }; + static const uint16_t neutral_p[] ALIGN2 = { ARRAY }; # undef BIG_ # undef PAIR # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; -- cgit v1.2.3-55-g6feb From 965b795b87c59ed45cc7f16a62301dbae65b1627 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Nov 2020 13:03:03 +0100 Subject: decrease paddign: gcc-9.3.1 slaps 32-byte alignment on arrays willy-nilly text data bss dec hex filename 1021988 559 5052 1027599 fae0f busybox_old 1021236 559 5052 1026847 fab1f busybox_unstripped Signed-off-by: Denys Vlasenko --- archival/dpkg.c | 2 +- archival/libarchive/bz/blocksort.c | 2 +- archival/libarchive/data_extract_to_command.c | 2 +- coreutils/od_bloaty.c | 4 ++-- coreutils/split.c | 2 +- coreutils/stat.c | 2 +- coreutils/stty.c | 4 ++-- coreutils/test.c | 2 +- e2fsprogs/e2fs_lib.c | 2 +- editors/awk.c | 2 +- findutils/find.c | 2 +- include/libbb.h | 3 ++- include/platform.h | 2 ++ libbb/capability.c | 2 +- libbb/duration.c | 2 +- libbb/hash_md5_sha.c | 22 +++++++++++----------- libbb/mode_string.c | 2 +- libbb/pw_encrypt_des.c | 15 +++++++-------- libbb/speed_table.c | 2 +- libbb/xatonum.c | 6 +++--- miscutils/crond.c | 2 +- miscutils/dc.c | 2 +- miscutils/hdparm.c | 2 +- miscutils/i2c_tools.c | 15 +++++---------- miscutils/mt.c | 2 +- miscutils/setserial.c | 3 +-- miscutils/ubi_tools.c | 2 +- miscutils/watchdog.c | 2 +- modutils/modinfo.c | 2 +- networking/ifplugd.c | 2 +- networking/interface.c | 2 +- networking/ip.c | 2 +- networking/libiproute/rt_names.c | 2 +- networking/route.c | 6 +++--- networking/tls.c | 2 +- networking/udhcp/dhcpd.c | 2 +- procps/nmeter.c | 2 +- procps/ps.c | 2 +- runit/svlogd.c | 2 +- shell/ash.c | 6 +++--- shell/hush.c | 12 ++++++------ shell/shell_common.c | 2 +- util-linux/acpid.c | 4 ++-- util-linux/fbset.c | 2 +- util-linux/fdisk.c | 2 +- util-linux/fdisk_osf.c | 4 ++-- util-linux/fdisk_sgi.c | 2 +- util-linux/fdisk_sun.c | 4 ++-- util-linux/mkfs_ext2.c | 2 +- util-linux/mount.c | 2 +- util-linux/volume_id/volume_id.c | 8 ++++---- 51 files changed, 92 insertions(+), 96 deletions(-) diff --git a/archival/dpkg.c b/archival/dpkg.c index 68a40bf6e..bf070a001 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -1304,7 +1304,7 @@ postrm abort-install postrm abort-upgrade postrm disappear */ -static const char *const all_control_files[] = { +static const char *const all_control_files[] ALIGN_PTR = { "preinst", "postinst", "prerm", "postrm", "list", "md5sums", "shlibs", "conffiles", "config", "templates" diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 92d6d8251..062fd0f54 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -459,7 +459,7 @@ int mainGtU(EState* state, * usually small, typically <= 20. */ static -const uint32_t incs[14] = { +const uint32_t incs[14] ALIGN4 = { 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484 diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c index 0fcabb4a9..f8b2ff8d2 100644 --- a/archival/libarchive/data_extract_to_command.c +++ b/archival/libarchive/data_extract_to_command.c @@ -20,7 +20,7 @@ enum { TAR_MAX, }; -static const char *const tar_var[] = { +static const char *const tar_var[] ALIGN_PTR = { // "FILETYPE", "MODE", "FILENAME", diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index e9c071f3a..d5bd7bfe8 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c @@ -627,7 +627,7 @@ decode_one_format(const char *s_orig, const char *s, struct tspec *tspec) bytes_to_unsigned_dec_digits, bytes_to_hex_digits, }; - static const char doux_fmtstring[][sizeof(" %%0%u%s")] = { + static const char doux_fmtstring[][sizeof(" %%0%u%s")] ALIGN1 = { " %%%u%s", " %%0%u%s", " %%%u%s", @@ -1148,7 +1148,7 @@ dump_strings(off_t address, off_t end_offset) static int parse_old_offset(const char *s, off_t *offset) { - static const struct suffix_mult Bb[] = { + static const struct suffix_mult Bb[] ALIGN_SUFFIX = { { "B", 1024 }, { "b", 512 }, { "", 0 } diff --git a/coreutils/split.c b/coreutils/split.c index ecbc9d2d8..3fcfd95f2 100644 --- a/coreutils/split.c +++ b/coreutils/split.c @@ -44,7 +44,7 @@ #include "common_bufsiz.h" #if ENABLE_FEATURE_SPLIT_FANCY -static const struct suffix_mult split_suffixes[] = { +static const struct suffix_mult split_suffixes[] ALIGN_SUFFIX = { { "b", 512 }, { "k", 1024 }, { "m", 1024*1024 }, diff --git a/coreutils/stat.c b/coreutils/stat.c index 8a23d687b..ee5e03edd 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c @@ -208,7 +208,7 @@ FS_TYPE(0x62656572, "sysfs") static const char *human_fstype(uint32_t f_type) { # define FS_TYPE(type, name) type, - static const uint32_t fstype[] = { + static const uint32_t fstype[] ALIGN4 = { FS_TYPE_LIST }; # undef FS_TYPE diff --git a/coreutils/stty.c b/coreutils/stty.c index 40e812799..19253964c 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c @@ -487,7 +487,7 @@ static const char mode_name[] ALIGN1 = #undef MI_ENTRY #define MI_ENTRY(N,T,F,B,M) { T, F, M, B }, -static const struct mode_info mode_info[] = { +static const struct mode_info mode_info[] ALIGN4 = { /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */ MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) @@ -905,7 +905,7 @@ static void display_window_size(int fancy) } } -static const struct suffix_mult stty_suffixes[] = { +static const struct suffix_mult stty_suffixes[] ALIGN_SUFFIX = { { "b", 512 }, { "k", 1024 }, { "B", 1024 }, diff --git a/coreutils/test.c b/coreutils/test.c index ac7b546a3..7c6574334 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -306,7 +306,7 @@ struct operator_t { unsigned char op_num, op_type; }; -static const struct operator_t ops_table[] = { +static const struct operator_t ops_table[] ALIGN2 = { { /* "-r" */ FILRD , UNOP }, { /* "-w" */ FILWR , UNOP }, { /* "-x" */ FILEX , UNOP }, diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c index 6ce655be3..8bd4da622 100644 --- a/e2fsprogs/e2fs_lib.c +++ b/e2fsprogs/e2fs_lib.c @@ -127,7 +127,7 @@ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_f /* Print file attributes on an ext2 file system */ -const uint32_t e2attr_flags_value[] = { +const uint32_t e2attr_flags_value[] ALIGN4 = { #ifdef ENABLE_COMPRESSION EXT2_COMPRBLK_FL, EXT2_DIRTY_FL, diff --git a/editors/awk.c b/editors/awk.c index 59dae4770..d56d6330d 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -405,7 +405,7 @@ static const char tokenlist[] ALIGN1 = #define OC_B OC_BUILTIN -static const uint32_t tokeninfo[] = { +static const uint32_t tokeninfo[] ALIGN4 = { 0, 0, OC_REGEXP, diff --git a/findutils/find.c b/findutils/find.c index e2947afb4..a8c3fa346 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -1441,7 +1441,7 @@ static action*** parse_params(char **argv) #else #define XATOU_SFX xatoul_sfx #endif - static const struct suffix_mult find_suffixes[] = { + static const struct suffix_mult find_suffixes[] ALIGN_SUFFIX = { { "c", 1 }, { "w", 2 }, { "", 512 }, diff --git a/include/libbb.h b/include/libbb.h index 18dc9f935..9872dc1fb 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1026,8 +1026,9 @@ void generate_uuid(uint8_t *buf) FAST_FUNC; /* Last element is marked by mult == 0 */ struct suffix_mult { char suffix[4]; - unsigned mult; + uint32_t mult; }; +#define ALIGN_SUFFIX ALIGN4 extern const struct suffix_mult bkm_suffixes[]; #define km_suffixes (bkm_suffixes + 1) extern const struct suffix_mult cwbkMG_suffixes[]; diff --git a/include/platform.h b/include/platform.h index 43bb391bd..085387fd8 100644 --- a/include/platform.h +++ b/include/platform.h @@ -342,6 +342,8 @@ typedef unsigned smalluint; # define ALIGN2 # define ALIGN4 #endif +#define ALIGN8 __attribute__((aligned(8))) +#define ALIGN_PTR __attribute__((aligned(sizeof(void*)))) /* * For 0.9.29 and svn, __ARCH_USE_MMU__ indicates no-mmu reliably. diff --git a/libbb/capability.c b/libbb/capability.c index 23afd8eb9..e3c252a5a 100644 --- a/libbb/capability.c +++ b/libbb/capability.c @@ -17,7 +17,7 @@ extern int capget(cap_user_header_t header, const cap_user_data_t data); // This way, libcap needs not be installed in build environment. #include "libbb.h" -static const char *const capabilities[] = { +static const char *const capabilities[] ALIGN_PTR = { "chown", "dac_override", "dac_read_search", diff --git a/libbb/duration.c b/libbb/duration.c index 22b209f4d..086da15fb 100644 --- a/libbb/duration.c +++ b/libbb/duration.c @@ -21,7 +21,7 @@ #include "libbb.h" -static const struct suffix_mult duration_suffixes[] = { +static const struct suffix_mult duration_suffixes[] ALIGN_SUFFIX = { { "s", 1 }, { "m", 60 }, { "h", 60*60 }, diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index d8f210173..e0db8ce67 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -111,7 +111,7 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx) They are defined in RFC 1321 as T[i] = (int)(2^32 * fabs(sin(i))), i=1..64 */ - static const uint32_t C_array[] = { + static const uint32_t C_array[] ALIGN4 = { /* round 1 */ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, @@ -492,7 +492,7 @@ unsigned FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) { - static const uint32_t rconsts[] = { + static const uint32_t rconsts[] ALIGN4 = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; int i, j; @@ -567,7 +567,7 @@ typedef uint64_t sha_K_int; typedef uint32_t sha_K_int; # define K(v) (uint32_t)(v >> 32) #endif -static const sha_K_int sha_K[] = { +static const sha_K_int sha_K[] ALIGN8 = { K(0x428a2f98d728ae22ULL), K(0x7137449123ef65cdULL), K(0xb5c0fbcfec4d3b2fULL), K(0xe9b5dba58189dbbcULL), K(0x3956c25bf348b538ULL), K(0x59f111f1b605d019ULL), @@ -760,7 +760,7 @@ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx) ctx->process_block = sha1_process_block64; } -static const uint32_t init256[] = { +static const uint32_t init256[] ALIGN4 = { 0, 0, 0x6a09e667, @@ -773,7 +773,7 @@ static const uint32_t init256[] = { 0x5be0cd19, }; #if NEED_SHA512 -static const uint32_t init512_lo[] = { +static const uint32_t init512_lo[] ALIGN4 = { 0, 0, 0xf3bcc908, @@ -1009,7 +1009,7 @@ static void sha3_process_block72(uint64_t *state) #if OPTIMIZE_SHA3_FOR_32 /* - static const uint32_t IOTA_CONST_0[NROUNDS] = { + static const uint32_t IOTA_CONST_0[NROUNDS] ALIGN4 = { 0x00000001UL, 0x00000000UL, 0x00000000UL, @@ -1038,7 +1038,7 @@ static void sha3_process_block72(uint64_t *state) ** bits are in lsb: 0101 0000 1111 0100 1111 0001 */ uint32_t IOTA_CONST_0bits = (uint32_t)(0x0050f4f1); - static const uint32_t IOTA_CONST_1[NROUNDS] = { + static const uint32_t IOTA_CONST_1[NROUNDS] ALIGN4 = { 0x00000000UL, 0x00000089UL, 0x8000008bUL, @@ -1174,7 +1174,7 @@ static void sha3_process_block72(uint64_t *state) combine_halves(state); #else /* Native 64-bit algorithm */ - static const uint16_t IOTA_CONST[NROUNDS] = { + static const uint16_t IOTA_CONST[NROUNDS] ALIGN2 = { /* Elements should be 64-bit, but top half is always zero * or 0x80000000. We encode 63rd bits in a separate word below. * Same is true for 31th bits, which lets us use 16-bit table @@ -1210,15 +1210,15 @@ static void sha3_process_block72(uint64_t *state) /* bit for CONST[0] is in msb: 0001 0110 0011 1000 0001 1011 */ const uint32_t IOTA_CONST_bit31 = (uint32_t)(0x16381b00); - static const uint8_t ROT_CONST[24] = { + static const uint8_t ROT_CONST[24] ALIGN1 = { 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, }; - static const uint8_t PI_LANE[24] = { + static const uint8_t PI_LANE[24] ALIGN1 = { 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, }; - /*static const uint8_t MOD5[10] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/ + /*static const uint8_t MOD5[10] ALIGN1 = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/ unsigned x; unsigned round; diff --git a/libbb/mode_string.c b/libbb/mode_string.c index 5ffd5683e..9a286f3ff 100644 --- a/libbb/mode_string.c +++ b/libbb/mode_string.c @@ -27,7 +27,7 @@ #define mode_t unsigned short #endif -static const mode_t mode_flags[] = { +static const mode_t mode_flags[] ALIGN4 = { S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID, S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID, S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX diff --git a/libbb/pw_encrypt_des.c b/libbb/pw_encrypt_des.c index 19a9ab15b..c6fc328d8 100644 --- a/libbb/pw_encrypt_des.c +++ b/libbb/pw_encrypt_des.c @@ -65,25 +65,25 @@ /* A pile of data */ -static const uint8_t IP[64] = { +static const uint8_t IP[64] ALIGN1 = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 }; -static const uint8_t key_perm[56] = { +static const uint8_t key_perm[56] ALIGN1 = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 }; -static const uint8_t key_shifts[16] = { +static const uint8_t key_shifts[16] ALIGN1 = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; -static const uint8_t comp_perm[48] = { +static const uint8_t comp_perm[48] ALIGN1 = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, @@ -181,13 +181,12 @@ static const uint8_t u_sbox[8][32] = { }; #endif -static const uint8_t pbox[32] = { +static const uint8_t pbox[32] ALIGN1 = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 }; -static const uint32_t bits32[32] = -{ +static const uint32_t bits32[32] ALIGN4 = { 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000, 0x00800000, 0x00400000, 0x00200000, 0x00100000, @@ -198,7 +197,7 @@ static const uint32_t bits32[32] = 0x00000008, 0x00000004, 0x00000002, 0x00000001 }; -static const uint8_t bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; +static const uint8_t bits8[8] ALIGN1 = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static int diff --git a/libbb/speed_table.c b/libbb/speed_table.c index 967cf8de8..cf7101e64 100644 --- a/libbb/speed_table.c +++ b/libbb/speed_table.c @@ -28,7 +28,7 @@ struct speed_map { }; /* On Linux, Bxx constants are 0..15 (up to B38400) and 0x1001..0x100f */ -static const struct speed_map speeds[] = { +static const struct speed_map speeds[] ALIGN4 = { {B0, 0}, {B50, 50}, {B75, 75}, diff --git a/libbb/xatonum.c b/libbb/xatonum.c index 7639a62aa..36b06c849 100644 --- a/libbb/xatonum.c +++ b/libbb/xatonum.c @@ -68,14 +68,14 @@ uint16_t FAST_FUNC xatou16(const char *numstr) return xatou_range(numstr, 0, 0xffff); } -const struct suffix_mult bkm_suffixes[] = { +const struct suffix_mult bkm_suffixes[] ALIGN_SUFFIX = { { "b", 512 }, { "k", 1024 }, { "m", 1024*1024 }, { "", 0 } }; -const struct suffix_mult cwbkMG_suffixes[] = { +const struct suffix_mult cwbkMG_suffixes[] ALIGN_SUFFIX = { { "c", 1 }, { "w", 2 }, { "b", 512 }, @@ -96,7 +96,7 @@ const struct suffix_mult cwbkMG_suffixes[] = { { "", 0 } }; -const struct suffix_mult kmg_i_suffixes[] = { +const struct suffix_mult kmg_i_suffixes[] ALIGN_SUFFIX = { { "KiB", 1024 }, { "kiB", 1024 }, { "K", 1024 }, diff --git a/miscutils/crond.c b/miscutils/crond.c index 2e8ca8b68..fb3adc180 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -492,7 +492,7 @@ static void load_crontab(const char *fileName) const char *name; const char tokens[8]; } SpecialEntry; - static const SpecialEntry SpecAry[] = { + static const SpecialEntry SpecAry[] ALIGN8 = { /* hour day month weekday */ { "yearly", "0\0" "1\0" "1\0" "*" }, { "annually", "0\0" "1\0" "1\0" "*" }, diff --git a/miscutils/dc.c b/miscutils/dc.c index ef93c20ba..51376dd75 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c @@ -195,7 +195,7 @@ struct op { void (*function) (void); }; -static const struct op operators[] = { +static const struct op operators[] ALIGN_PTR = { #if ENABLE_FEATURE_DC_LIBM {"^", power}, // {"exp", power}, diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index 431a0ad96..01b4e8e2e 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c @@ -1366,7 +1366,7 @@ static NOINLINE void dump_identity(const struct hd_driveid *id) } if (id->capability & 1) { if (id->dma_1word | id->dma_mword) { - static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 }; + static const int dma_wmode_masks[] ALIGN4 = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 }; printf("\n DMA modes: "); print_flags_separated(dma_wmode_masks, "*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0", diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index cc8b99a92..09364e396 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1053,18 +1053,13 @@ struct adap_desc { }; static const struct adap_desc adap_descs[] = { - { .funcs = "dummy", - .algo = "Dummy bus", }, - { .funcs = "isa", - .algo = "ISA bus", }, - { .funcs = "i2c", - .algo = "I2C adapter", }, - { .funcs = "smbus", - .algo = "SMBus adapter", }, + { .funcs = "dummy", .algo = "Dummy bus", }, + { .funcs = "isa", .algo = "ISA bus", }, + { .funcs = "i2c", .algo = "I2C adapter", }, + { .funcs = "smbus", .algo = "SMBus adapter", }, }; -struct i2c_func -{ +struct i2c_func { long value; const char* name; }; diff --git a/miscutils/mt.c b/miscutils/mt.c index 9f1aecfca..dbb8c13ad 100644 --- a/miscutils/mt.c +++ b/miscutils/mt.c @@ -30,7 +30,7 @@ #include /* missing: eod/seod, stoptions, stwrthreshold, densities */ -static const short opcode_value[] = { +static const short opcode_value[] ALIGN2 = { MTBSF, MTBSFM, MTBSR, diff --git a/miscutils/setserial.c b/miscutils/setserial.c index 1e75bf433..2006861e2 100644 --- a/miscutils/setserial.c +++ b/miscutils/setserial.c @@ -381,8 +381,7 @@ static bool cmd_needs_arg(int cmd) # error "Unexpected flags size" #endif -static const uint16_t setbits[CMD_FLAG_LAST + 1] = -{ +static const uint16_t setbits[CMD_FLAG_LAST + 1] ALIGN2 = { 0, ASYNC_SPD_HI, ASYNC_SPD_VHI, diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c index 94a637eee..69ead7a13 100644 --- a/miscutils/ubi_tools.c +++ b/miscutils/ubi_tools.c @@ -97,7 +97,7 @@ static unsigned get_num_from_file(const char *path, unsigned max) int ubi_tools_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int ubi_tools_main(int argc UNUSED_PARAM, char **argv) { - static const struct suffix_mult size_suffixes[] = { + static const struct suffix_mult size_suffixes[] ALIGN_SUFFIX = { { "KiB", 1024 }, { "MiB", 1024*1024 }, { "GiB", 1024*1024*1024 }, diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c index 971b777a3..0ed10bcf1 100644 --- a/miscutils/watchdog.c +++ b/miscutils/watchdog.c @@ -88,7 +88,7 @@ int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int watchdog_main(int argc UNUSED_PARAM, char **argv) { static const int enable = WDIOS_ENABLECARD; - static const struct suffix_mult suffixes[] = { + static const struct suffix_mult suffixes[] ALIGN_SUFFIX = { { "ms", 1 }, { "", 1000 }, { "", 0 } diff --git a/modutils/modinfo.c b/modutils/modinfo.c index c5cdc7980..d15772f0d 100644 --- a/modutils/modinfo.c +++ b/modutils/modinfo.c @@ -20,7 +20,7 @@ #include "libbb.h" #include "modutils.h" -static const char *const shortcuts[] = { +static const char *const shortcuts[] ALIGN_PTR = { "filename", // -n "author", // -a "description", // -d diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 60916eae6..18dcaff96 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c @@ -304,7 +304,7 @@ static const char api_modes[] ALIGN1 = "empwia"; static const struct { const char *name; smallint (*func)(void); -} method_table[] = { +} method_table[] ALIGN_PTR = { { "SIOCETHTOOL" , &detect_link_ethtool }, { "SIOCGMIIPHY" , &detect_link_mii }, { "SIOCDEVPRIVATE" , &detect_link_priv }, diff --git a/networking/interface.c b/networking/interface.c index e5e55d8d4..ea6a2c8a8 100644 --- a/networking/interface.c +++ b/networking/interface.c @@ -746,7 +746,7 @@ static const struct hwtype *const hwtypes[] = { }; #ifdef IFF_PORTSEL -static const char *const if_port_text[] = { +static const char *const if_port_text[] ALIGN_PTR = { /* Keep in step with */ "unknown", "10base2", diff --git a/networking/ip.c b/networking/ip.c index 33bea5f49..85b1ba080 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -400,7 +400,7 @@ int ip_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_IP_RULE("rule\0") IF_FEATURE_IP_NEIGH("neigh\0") ; - static const ip_func_ptr_t ip_func_ptrs[] = { + static const ip_func_ptr_t ip_func_ptrs[] ALIGN_PTR = { ip_print_help, IF_FEATURE_IP_ADDRESS(do_ipaddr,) IF_FEATURE_IP_ROUTE(do_iproute,) diff --git a/networking/libiproute/rt_names.c b/networking/libiproute/rt_names.c index 51f2e9bdb..3c2fad912 100644 --- a/networking/libiproute/rt_names.c +++ b/networking/libiproute/rt_names.c @@ -77,7 +77,7 @@ static rtnl_tab_t *rtnl_rtprot_tab; static void rtnl_rtprot_initialize(void) { - static const char *const init_tab[] = { + static const char *const init_tab[] ALIGN_PTR = { "none", "redirect", "kernel", diff --git a/networking/route.c b/networking/route.c index 4d9aad6cc..4901109f1 100644 --- a/networking/route.c +++ b/networking/route.c @@ -460,9 +460,9 @@ static NOINLINE void INET6_setroute(int action, char **args) #endif static const -IF_NOT_FEATURE_IPV6(uint16_t) -IF_FEATURE_IPV6(unsigned) -flagvals[] = { /* Must agree with flagchars[]. */ +IF_NOT_FEATURE_IPV6(uint16_t flagvals[] ALIGN2 = ) +IF_FEATURE_IPV6(uint32_t flagvals[] ALIGN4 = ) +{ /* Must agree with flagchars[]. */ RTF_UP, RTF_GATEWAY, RTF_HOST, diff --git a/networking/tls.c b/networking/tls.c index 341225207..e34acd69f 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1953,7 +1953,7 @@ static void send_client_key_exchange(tls_state_t *tls) premaster_size = sizeof(rsa_premaster); } else { /* ECDHE */ - static const uint8_t basepoint9[CURVE25519_KEYSIZE] = {9}; + static const uint8_t basepoint9[CURVE25519_KEYSIZE] ALIGN1 = {9}; uint8_t privkey[CURVE25519_KEYSIZE]; //[32] if (!(tls->flags & GOT_EC_KEY)) diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index acfdaa8c3..de16cf955 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -398,7 +398,7 @@ struct config_keyword { #define OFS(field) offsetof(struct server_data_t, field) -static const struct config_keyword keywords[] = { +static const struct config_keyword keywords[] ALIGN_PTR = { /* keyword handler variable address default */ {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"}, {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"}, diff --git a/procps/nmeter.c b/procps/nmeter.c index 856ce0202..07b7abe2f 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -838,7 +838,7 @@ static void FAST_FUNC collect_info(s_stat *s) typedef s_stat* init_func(const char *param); static const char options[] ALIGN1 = "ncmsfixptTbr"; -static init_func *const init_functions[] = { +static init_func *const init_functions[] ALIGN_PTR = { init_if, init_cpu, init_mem, diff --git a/procps/ps.c b/procps/ps.c index 48f96209f..711b180a0 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -375,7 +375,7 @@ static void func_pcpu(char *buf, int size, const procps_status_t *ps) } */ -static const ps_out_t out_spec[] = { +static const ps_out_t out_spec[] ALIGN_PTR = { /* Mandated by http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html: */ { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, { 8 , "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, diff --git a/runit/svlogd.c b/runit/svlogd.c index a250058a1..040e71104 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c @@ -775,7 +775,7 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn) ld->nmin = xatoi_positive(&s[1]); break; case 't': { - static const struct suffix_mult mh_suffixes[] = { + static const struct suffix_mult mh_suffixes[] ALIGN_SUFFIX = { { "m", 60 }, { "h", 60*60 }, /*{ "d", 24*60*60 },*/ diff --git a/shell/ash.c b/shell/ash.c index 8c9a590d1..40695dee0 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2091,7 +2091,7 @@ static const struct { int flags; const char *var_text; void (*var_func)(const char *) FAST_FUNC; -} varinit_data[] = { +} varinit_data[] ALIGN_PTR = { /* * Note: VEXPORT would not work correctly here for NOFORK applets: * some environment strings may be constant. @@ -4811,7 +4811,7 @@ static char *cmdnextc; static void cmdputs(const char *s) { - static const char vstype[VSTYPE + 1][3] = { + static const char vstype[VSTYPE + 1][3] ALIGN1 = { "", "}", "-", "+", "?", "=", "%", "%%", "#", "##" IF_BASH_SUBSTR(, ":") @@ -8510,7 +8510,7 @@ enum { , /* thus far 29 bits used */ }; -static const char *const tokname_array[] = { +static const char *const tokname_array[] ALIGN_PTR = { "end of file", "newline", "redirection", diff --git a/shell/hush.c b/shell/hush.c index f1a7e07ee..b6d9d7abb 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -596,10 +596,10 @@ typedef struct in_str { /* The descrip member of this structure is only used to make * debugging output pretty */ static const struct { - int mode; + int32_t mode; signed char default_fd; char descrip[3]; -} redir_table[] = { +} redir_table[] ALIGN4 = { { O_RDONLY, 0, "<" }, { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" }, { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" }, @@ -1143,7 +1143,7 @@ struct built_in_command { #endif }; -static const struct built_in_command bltins1[] = { +static const struct built_in_command bltins1[] ALIGN_PTR = { BLTIN("." , builtin_source , "Run commands in file"), BLTIN(":" , builtin_true , NULL), #if ENABLE_HUSH_JOB @@ -1228,7 +1228,7 @@ static const struct built_in_command bltins1[] = { /* These builtins won't be used if we are on NOMMU and need to re-exec * (it's cheaper to run an external program in this case): */ -static const struct built_in_command bltins2[] = { +static const struct built_in_command bltins2[] ALIGN_PTR = { #if ENABLE_HUSH_TEST BLTIN("[" , builtin_test , NULL), #endif @@ -3895,7 +3895,7 @@ struct reserved_combo { char literal[6]; unsigned char res; unsigned char assignment_flag; - int flag; + uint32_t flag; }; enum { FLAG_END = (1 << RES_NONE ), @@ -3928,7 +3928,7 @@ static const struct reserved_combo* match_reserved_word(o_string *word) * to turn the compound list into a command. * FLAG_START means the word must start a new compound list. */ - static const struct reserved_combo reserved_list[] = { + static const struct reserved_combo reserved_list[] ALIGN4 = { # if ENABLE_HUSH_IF { "!", RES_NONE, NOT_ASSIGNMENT , 0 }, { "if", RES_IF, MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START }, diff --git a/shell/shell_common.c b/shell/shell_common.c index 42c4c9c97..dcbe0d109 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -324,7 +324,7 @@ struct limits { uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */ }; -static const struct limits limits_tbl[] = { +static const struct limits limits_tbl[] ALIGN2 = { { RLIMIT_CORE, 9, }, // -c { RLIMIT_DATA, 10, }, // -d { RLIMIT_NICE, 0, }, // -e diff --git a/util-linux/acpid.c b/util-linux/acpid.c index d473e24fc..00613f8e3 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -99,7 +99,7 @@ struct acpi_event { const char *desc; }; -static const struct acpi_event f_evt_tab[] = { +static const struct acpi_event f_evt_tab[] ALIGN_PTR = { { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" }, { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" }, { "EV_SW", 0x05, "SW_LID", 0x00, 1, "button/lid LID0 00000080" }, @@ -110,7 +110,7 @@ struct acpi_action { const char *action; }; -static const struct acpi_action f_act_tab[] = { +static const struct acpi_action f_act_tab[] ALIGN_PTR = { { "PWRF", "PWRF/00000080" }, { "LID0", "LID/00000080" }, }; diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 0b9a9a6bc..cc5413b40 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c @@ -193,7 +193,7 @@ static const struct cmdoptions_t { const char name[9]; const unsigned char param_count; const unsigned char code; -} g_cmdoptions[] = { +} g_cmdoptions[] ALIGN1 = { /*"12345678" + NUL */ //TODO: convert to index_in_strings() { "fb" , 1, CMD_FB }, diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 0df3ebf7d..6454baab8 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -303,7 +303,7 @@ static sector_t get_nr_sects(const struct partition *p); /* DOS partition types */ -static const char *const i386_sys_types[] = { +static const char *const i386_sys_types[] ALIGN_PTR = { "\x00" "Empty", "\x01" "FAT12", "\x04" "FAT16 <32M", diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c index 92180b2bc..765740ff1 100644 --- a/util-linux/fdisk_osf.c +++ b/util-linux/fdisk_osf.c @@ -144,7 +144,7 @@ struct xbsd_disklabel { #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */ #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */ -static const char *const xbsd_dktypenames[] = { +static const char *const xbsd_dktypenames[] ALIGN_PTR = { "unknown", "SMD", "MSCP", @@ -190,7 +190,7 @@ static const char *const xbsd_dktypenames[] = { #define BSD_FS_MSDOS 8 /* MS-DOS file system */ #endif -static const char *const xbsd_fstypes[] = { +static const char *const xbsd_fstypes[] ALIGN_PTR = { "\x00" "unused", /* BSD_FS_UNUSED */ "\x01" "swap", /* BSD_FS_SWAP */ "\x02" "Version 6", /* BSD_FS_V6 */ diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c index c90c801e2..acb438ac0 100644 --- a/util-linux/fdisk_sgi.c +++ b/util-linux/fdisk_sgi.c @@ -174,7 +174,7 @@ isinfreelist(unsigned int b) * end of free blocks section */ -static const char *const sgi_sys_types[] = { +static const char *const sgi_sys_types[] ALIGN_PTR = { /* SGI_VOLHDR */ "\x00" "SGI volhdr" , /* 0x01 */ "\x01" "SGI trkrepl" , /* 0x02 */ "\x02" "SGI secrepl" , diff --git a/util-linux/fdisk_sun.c b/util-linux/fdisk_sun.c index 29d7c283a..427b9487b 100644 --- a/util-linux/fdisk_sun.c +++ b/util-linux/fdisk_sun.c @@ -61,7 +61,7 @@ guess_device_type(void) } } -static const char *const sun_sys_types[] = { +static const char *const sun_sys_types[] ALIGN_PTR = { "\x00" "Empty" , /* 0 */ "\x01" "Boot" , /* 1 */ "\x02" "SunOS root" , /* 2 */ @@ -133,7 +133,7 @@ static const struct sun_predefined_drives { unsigned short ntrks; unsigned short nsect; unsigned short rspeed; -} sun_drives[] = { +} sun_drives[] ALIGN_PTR = { { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662}, { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662}, { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600}, diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c index 1f525d75b..fcf374b2d 100644 --- a/util-linux/mkfs_ext2.c +++ b/util-linux/mkfs_ext2.c @@ -131,7 +131,7 @@ static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32 static uint32_t has_super(uint32_t x) { // 0, 1 and powers of 3, 5, 7 up to 2^32 limit - static const uint32_t supers[] = { + static const uint32_t supers[] ALIGN4 = { 0, 1, 3, 5, 7, 9, 25, 27, 49, 81, 125, 243, 343, 625, 729, 2187, 2401, 3125, 6561, 15625, 16807, 19683, 59049, 78125, 117649, 177147, 390625, 531441, 823543, 1594323, 1953125, diff --git a/util-linux/mount.c b/util-linux/mount.c index fc5161d7f..aa38847ec 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -323,7 +323,7 @@ enum { // Standard mount options (from -o options or --options), // with corresponding flags -static const int32_t mount_options[] = { +static const int32_t mount_options[] ALIGN4 = { // MS_FLAGS set a bit. ~MS_FLAGS disable that bit. 0 flags are NOPs. IF_FEATURE_MOUNT_LOOP( diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c index 99150a5b7..8ceb61bde 100644 --- a/util-linux/volume_id/volume_id.c +++ b/util-linux/volume_id/volume_id.c @@ -49,7 +49,7 @@ typedef int FAST_FUNC (*raid_probe_fptr)(struct volume_id *id, /*uint64_t off,*/ uint64_t size); typedef int FAST_FUNC (*probe_fptr)(struct volume_id *id /*, uint64_t off*/); -static const raid_probe_fptr raid1[] = { +static const raid_probe_fptr raid1[] ALIGN_PTR = { #if ENABLE_FEATURE_VOLUMEID_LINUXRAID volume_id_probe_linux_raid, #endif @@ -76,7 +76,7 @@ static const raid_probe_fptr raid1[] = { #endif }; -static const probe_fptr raid2[] = { +static const probe_fptr raid2[] ALIGN_PTR = { #if ENABLE_FEATURE_VOLUMEID_LVM volume_id_probe_lvm1, volume_id_probe_lvm2, @@ -90,7 +90,7 @@ static const probe_fptr raid2[] = { }; /* signature in the first block, only small buffer needed */ -static const probe_fptr fs1[] = { +static const probe_fptr fs1[] ALIGN_PTR = { #if ENABLE_FEATURE_VOLUMEID_FAT volume_id_probe_vfat, #endif @@ -118,7 +118,7 @@ static const probe_fptr fs1[] = { }; /* fill buffer with maximum */ -static const probe_fptr fs2[] = { +static const probe_fptr fs2[] ALIGN_PTR = { #if ENABLE_FEATURE_VOLUMEID_LINUXSWAP volume_id_probe_linux_swap, #endif -- cgit v1.2.3-55-g6feb From 6cc4962b60d451e918e338ccca98afda99f49f6e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Nov 2020 14:58:02 +0100 Subject: decrease padding: gcc-9.3.1 slaps 32-byte alignment on arrays willy-nilly text data bss dec hex filename 1021236 559 5052 1026847 fab1f busybox_old 1021120 559 5052 1026731 faaab busybox_unstripped Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_gunzip.c | 4 ++-- miscutils/bc.c | 2 +- miscutils/i2c_tools.c | 4 ++-- networking/ifconfig.c | 4 ++-- networking/inetd.c | 2 +- networking/netstat.c | 2 +- networking/nslookup.c | 4 ++-- networking/traceroute.c | 4 ++-- util-linux/blockdev.c | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 03049cc9b..eb3b64930 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c @@ -194,14 +194,14 @@ struct cp_ext { }; /* Copy lengths and extra bits for literal codes 257..285 */ /* note: see note #13 above about the 258 in this list. */ -static const struct cp_ext lit = { +static const struct cp_ext lit ALIGN2 = { /*257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 */ /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 */ { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 } /* 99 == invalid */ }; /* Copy offsets and extra bits for distance codes 0..29 */ -static const struct cp_ext dist = { +static const struct cp_ext dist ALIGN2 = { /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 */ { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 } diff --git a/miscutils/bc.c b/miscutils/bc.c index 4d987325e..f339b895c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -517,7 +517,7 @@ struct BcLexKeyword { }; #define LEX_KW_ENTRY(a, b) \ { .name8 = a /*, .posix = b */ } -static const struct BcLexKeyword bc_lex_kws[20] = { +static const struct BcLexKeyword bc_lex_kws[20] ALIGN8 = { LEX_KW_ENTRY("auto" , 1), // 0 LEX_KW_ENTRY("break" , 1), // 1 LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 09364e396..57cac5d47 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1052,7 +1052,7 @@ struct adap_desc { const char *algo; }; -static const struct adap_desc adap_descs[] = { +static const struct adap_desc adap_descs[] ALIGN_PTR = { { .funcs = "dummy", .algo = "Dummy bus", }, { .funcs = "isa", .algo = "ISA bus", }, { .funcs = "i2c", .algo = "I2C adapter", }, @@ -1064,7 +1064,7 @@ struct i2c_func { const char* name; }; -static const struct i2c_func i2c_funcs_tab[] = { +static const struct i2c_func i2c_funcs_tab[] ALIGN_PTR = { { .value = I2C_FUNC_I2C, .name = "I2C" }, { .value = I2C_FUNC_SMBUS_QUICK, diff --git a/networking/ifconfig.c b/networking/ifconfig.c index 3c9a2dfb3..c3e448be0 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c @@ -247,7 +247,7 @@ struct options { * Set up the tables. Warning! They must have corresponding order! */ -static const struct arg1opt Arg1Opt[] = { +static const struct arg1opt Arg1Opt[] ALIGN_PTR = { { "SIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric) }, { "SIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu) }, { "SIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen) }, @@ -277,7 +277,7 @@ static const struct arg1opt Arg1Opt[] = { { "SIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr) }, }; -static const struct options OptArray[] = { +static const struct options OptArray[] ALIGN_PTR = { { "metric", N_ARG, ARG_METRIC, 0 }, { "mtu", N_ARG, ARG_MTU, 0 }, { "txqueuelen", N_ARG, ARG_TXQUEUELEN, 0 }, diff --git a/networking/inetd.c b/networking/inetd.c index 44b1ac700..9f5a436d6 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -361,7 +361,7 @@ struct builtin { void (*bi_dgram_fn)(int, servtab_t *) FAST_FUNC; }; -static const struct builtin builtins[] = { +static const struct builtin builtins[] ALIGN_PTR = { #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO { "echo", 1, echo_stream, echo_dg }, #endif diff --git a/networking/netstat.c b/networking/netstat.c index 3ab7b0d21..807800a62 100644 --- a/networking/netstat.c +++ b/networking/netstat.c @@ -114,7 +114,7 @@ enum { TCP_CLOSING, /* now a valid state */ }; -static const char *const tcp_state[] = { +static const char *const tcp_state[] ALIGN_PTR = { "", "ESTABLISHED", "SYN_SENT", diff --git a/networking/nslookup.c b/networking/nslookup.c index 759de5c83..dda22de0e 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c @@ -273,7 +273,7 @@ struct query { static const struct { unsigned char type; char name[7]; -} qtypes[] = { +} qtypes[] ALIGN1 = { { ns_t_soa, "SOA" }, { ns_t_ns, "NS" }, { ns_t_a, "A" }, @@ -288,7 +288,7 @@ static const struct { { ns_t_any, "ANY" }, }; -static const char *const rcodes[] = { +static const char *const rcodes[] ALIGN_PTR = { "NOERROR", // 0 "FORMERR", // 1 "SERVFAIL", // 2 diff --git a/networking/traceroute.c b/networking/traceroute.c index 34d2a09dd..7dde10524 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -536,7 +536,7 @@ send_probe(int seq, int ttl) static const char * pr_type(unsigned char t) { - static const char *const ttab[] = { + static const char *const ttab[] ALIGN_PTR = { "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", "Source Quench", "Redirect", "ICMP 6", "ICMP 7", "Echo", "Router Advert", "Router Solicit", "Time Exceeded", @@ -544,7 +544,7 @@ pr_type(unsigned char t) "Info Reply", "Mask Request", "Mask Reply" }; # if ENABLE_TRACEROUTE6 - static const char *const ttab6[] = { + static const char *const ttab6[] ALIGN_PTR = { [0] = "Error", "Dest Unreachable", "Packet Too Big", "Time Exceeded", [4] = "Param Problem", [8] = "Echo Request", "Echo Reply", "Membership Query", "Membership Report", diff --git a/util-linux/blockdev.c b/util-linux/blockdev.c index e60bbe609..20a031377 100644 --- a/util-linux/blockdev.c +++ b/util-linux/blockdev.c @@ -60,7 +60,7 @@ static const char bdcmd_names[] ALIGN1 = "flushbufs" "\0" "rereadpt" "\0" ; -static const uint32_t bdcmd_ioctl[] = { +static const uint32_t bdcmd_ioctl[] ALIGN4 = { BLKROSET, //setro BLKROSET, //setrw BLKROGET, //getro -- cgit v1.2.3-55-g6feb From 6599e380ed5e1b1272a5e0e26183471d8b4b2051 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Nov 2020 15:10:43 +0100 Subject: mount: make filesystems[] array byte-aligned text data bss dec hex filename 1021120 559 5052 1026731 faaab busybox_old 1021092 559 5052 1026703 faa8f busybox_unstripped Signed-off-by: Denys Vlasenko --- util-linux/mount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/mount.c b/util-linux/mount.c index aa38847ec..cfb6b570f 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -641,7 +641,7 @@ static unsigned long parse_mount_options(char *options, char **unrecognized) // Return a list of all block device backed filesystems static llist_t *get_block_backed_filesystems(void) { - static const char filesystems[2][sizeof("/proc/filesystems")] = { + static const char filesystems[2][sizeof("/proc/filesystems")] ALIGN1 = { "/etc/filesystems", "/proc/filesystems", }; -- cgit v1.2.3-55-g6feb From 50ead33c45919abffde35313daac4c2dfd8641ca Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Dec 2020 17:47:16 +0100 Subject: login: log to syslog every bad password, not only 3rd Signed-off-by: Denys Vlasenko --- loginutils/login.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/loginutils/login.c b/loginutils/login.c index c3a835180..f0bce50ce 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -508,13 +508,11 @@ int login_main(int argc UNUSED_PARAM, char **argv) pause_after_failed_login(); /* TODO: doesn't sound like correct English phrase to me */ puts("Login incorrect"); + syslog(LOG_WARNING, "invalid password for '%s'%s", + username, fromhost); if (++count == 3) { - syslog(LOG_WARNING, "invalid password for '%s'%s", - username, fromhost); - if (ENABLE_FEATURE_CLEAN_UP) free(fromhost); - return EXIT_FAILURE; } username[0] = '\0'; -- cgit v1.2.3-55-g6feb From 665a65953076ea21be49250b8279ddb1f0f99f38 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Dec 2020 19:07:31 +0100 Subject: awk: FS regex matches only non-empty separators (gawk compat) function old new delta awk_split 484 553 +69 Signed-off-by: Denys Vlasenko --- editors/awk.c | 33 +++++++++++++++++++++++++-------- testsuite/awk.tests | 7 +++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/editors/awk.c b/editors/awk.c index d56d6330d..2c15f9e4e 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -1763,6 +1763,29 @@ static void fsrealloc(int size) nfields = size; } +static int regexec1_nonempty(const regex_t *preg, const char *s, regmatch_t pmatch[]) +{ + int r = regexec(preg, s, 1, pmatch, 0); + if (r == 0 && pmatch[0].rm_eo == 0) { + /* For example, happens when FS can match + * an empty string (awk -F ' *'). Logically, + * this should split into one-char fields. + * However, gawk 5.0.1 searches for first + * _non-empty_ separator string match: + */ + size_t ofs = 0; + do { + ofs++; + if (!s[ofs]) + return REG_NOMATCH; + regexec(preg, s + ofs, 1, pmatch, 0); + } while (pmatch[0].rm_eo == 0); + pmatch[0].rm_so += ofs; + pmatch[0].rm_eo += ofs; + } + return r; +} + static int awk_split(const char *s, node *spl, char **slist) { int n; @@ -1788,17 +1811,11 @@ static int awk_split(const char *s, node *spl, char **slist) regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough... l = strcspn(s, c+2); /* len till next NUL or \n */ - if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0 + if (regexec1_nonempty(icase ? spl->r.ire : spl->l.re, s, pmatch) == 0 && pmatch[0].rm_so <= l ) { + /* if (pmatch[0].rm_eo == 0) ... - impossible */ l = pmatch[0].rm_so; - if (pmatch[0].rm_eo == 0) { - /* For example, happens when FS can match - * an empthy string (awk -F ' *') - */ - l++; - pmatch[0].rm_eo++; - } n++; /* we saw yet another delimiter */ } else { pmatch[0].rm_eo = l; diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 87f6b5007..06a531d96 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -398,5 +398,12 @@ testing 'awk do not allow "str"++' \ '' \ 'anything' +#gawk compat: FS regex matches only non-empty separators: +#with -*, the splitting is NOT f o o b a r, but foo bar: +testing 'awk FS regex which can match empty string' \ + "awk -F '-*' '{print \$1 \"-\" \$2 \"=\" \$3 \"*\" \$4}'" \ + "foo-bar=*\n" \ + '' \ + 'foo--bar' exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From b4f93f562d261a163113cd15cc252c53d2fa27bb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Dec 2020 19:10:22 +0100 Subject: mount: do not guess bind mounts as nfs Fails as follows: $ mount -o bind /dev/disk/by-path/pci-0000:13:00.0-scsi-0:0:3:0 /dir mount: bad address '/dev/disk/by-path/pci-0000' function old new delta singlemount 1256 1273 +17 Signed-off-by: Denys Vlasenko --- util-linux/mount.c | 1 + 1 file changed, 1 insertion(+) diff --git a/util-linux/mount.c b/util-linux/mount.c index cfb6b570f..dba583544 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -2066,6 +2066,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) // Might this be an NFS filesystem? if ((!mp->mnt_type || is_prefixed_with(mp->mnt_type, "nfs")) && strchr(mp->mnt_fsname, ':') != NULL + && !(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE)) ) { if (!mp->mnt_type) mp->mnt_type = (char*)"nfs"; -- cgit v1.2.3-55-g6feb From 2075aa93e007863c6b680994a7a0ba420181034f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Dec 2020 21:28:47 +0100 Subject: libbb: rename run_shell() to exec_shell() Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 ++-- libbb/executable.c | 9 --------- libbb/run_shell.c | 13 +++++++++++-- loginutils/login.c | 2 +- loginutils/su.c | 2 +- loginutils/sulogin.c | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 9872dc1fb..c23018f17 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1140,7 +1140,6 @@ int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC; #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) #endif void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; -void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC; /* xvfork() can't be a _function_, return after vfork in child mangles stack * in the parent. It must be a macro. */ @@ -1607,7 +1606,8 @@ void bb_do_delay(unsigned seconds) FAST_FUNC; void msleep(unsigned ms) FAST_FUNC; void sleep1(void) FAST_FUNC; void change_identity(const struct passwd *pw) FAST_FUNC; -void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; +void exec_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; +void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC; /* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL. * Note that getpwuid result might need xstrdup'ing diff --git a/libbb/executable.c b/libbb/executable.c index 29d2a2c85..a033b74d9 100644 --- a/libbb/executable.c +++ b/libbb/executable.c @@ -91,12 +91,3 @@ void FAST_FUNC BB_EXECVP_or_die(char **argv) xfunc_error_retval = (errno == ENOENT) ? 127 : 126; bb_perror_msg_and_die("can't execute '%s'", argv[0]); } - -/* Typical idiom for applets which exec *optional* PROG [ARGS] */ -void FAST_FUNC exec_prog_or_SHELL(char **argv) -{ - if (argv[0]) { - BB_EXECVP_or_die(argv); - } - run_shell(getenv("SHELL"), /*login:*/ 1, NULL); -} diff --git a/libbb/run_shell.c b/libbb/run_shell.c index a0420d982..c2ff69651 100644 --- a/libbb/run_shell.c +++ b/libbb/run_shell.c @@ -48,10 +48,10 @@ void FAST_FUNC set_current_security_context(security_context_t sid) #endif -/* Run SHELL, or DEFAULT_SHELL if SHELL is "" or NULL. +/* Exec SHELL, or DEFAULT_SHELL if SHELL is "" or NULL. * If ADDITIONAL_ARGS is not NULL, pass them to the shell. */ -void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additional_args) +void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additional_args) { const char **args; @@ -84,3 +84,12 @@ void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additio execv(shell, (char **) args); bb_perror_msg_and_die("can't execute '%s'", shell); } + +/* Typical idiom for applets which exec *optional* PROG [ARGS] */ +void FAST_FUNC exec_prog_or_SHELL(char **argv) +{ + if (argv[0]) { + BB_EXECVP_or_die(argv); + } + exec_shell(getenv("SHELL"), /*login:*/ 1, NULL); +} diff --git a/loginutils/login.c b/loginutils/login.c index f0bce50ce..aacd47241 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -602,7 +602,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) signal(SIGINT, SIG_DFL); /* Exec login shell with no additional parameters */ - run_shell(pw->pw_shell, 1, NULL); + exec_shell(pw->pw_shell, 1, NULL); /* return EXIT_FAILURE; - not reached */ } diff --git a/loginutils/su.c b/loginutils/su.c index 6f91039f9..784a53552 100644 --- a/loginutils/su.c +++ b/loginutils/su.c @@ -204,7 +204,7 @@ int su_main(int argc UNUSED_PARAM, char **argv) */ /* Never returns */ - run_shell(opt_shell, flags & SU_OPT_l, (const char**)argv); + exec_shell(opt_shell, flags & SU_OPT_l, (const char**)argv); /* return EXIT_FAILURE; - not reached */ } diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 48dafd186..127aa1de9 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c @@ -89,5 +89,5 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) shell = pwd->pw_shell; /* Exec login shell with no additional parameters. Never returns. */ - run_shell(shell, 1, NULL); + exec_shell(shell, 1, NULL); } -- cgit v1.2.3-55-g6feb From 0622416fece00507cf0ac53a2aa17ca3b1e565b2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Dec 2020 21:35:32 +0100 Subject: libbb: code shrink in exec_shell() function old new delta exec_shell 129 120 -9 Signed-off-by: Denys Vlasenko --- libbb/run_shell.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libbb/run_shell.c b/libbb/run_shell.c index c2ff69651..9bec43b7c 100644 --- a/libbb/run_shell.c +++ b/libbb/run_shell.c @@ -59,7 +59,7 @@ void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additi while (args && *args) args++; - args = xmalloc(sizeof(char*) * (2 + (args - additional_args))); + args = xzalloc(sizeof(args[0]) * (2 + (args - additional_args))); if (!shell || !shell[0]) shell = DEFAULT_SHELL; @@ -67,12 +67,11 @@ void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additi args[0] = bb_get_last_path_component_nostrip(shell); if (loginshell) args[0] = xasprintf("-%s", args[0]); - args[1] = NULL; + /*args[1] = NULL; - already is */ if (additional_args) { - int cnt = 1; - for (;;) - if ((args[cnt++] = *additional_args++) == NULL) - break; + int cnt = 0; + while (*additional_args) + args[++cnt] = *additional_args++; } #if ENABLE_SELINUX @@ -91,5 +90,8 @@ void FAST_FUNC exec_prog_or_SHELL(char **argv) if (argv[0]) { BB_EXECVP_or_die(argv); } + /* Why login=1? Both users (nsenter and unshare) do indeed exec + * a _login_ shell (with dash in argv[0])! + */ exec_shell(getenv("SHELL"), /*login:*/ 1, NULL); } -- cgit v1.2.3-55-g6feb From f4f6e5144b9af71dc687dc14dba4a6caf8c28361 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Dec 2020 21:51:08 +0100 Subject: libbb: exec_login_shell() - new function function old new delta exec_login_shell - 12 +12 sulogin_main 247 240 -7 login_main 960 953 -7 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 12/-14) Total: -2 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/run_shell.c | 9 +++++++-- loginutils/login.c | 2 +- loginutils/sulogin.c | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index c23018f17..8f1ee7eec 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1607,6 +1607,7 @@ void msleep(unsigned ms) FAST_FUNC; void sleep1(void) FAST_FUNC; void change_identity(const struct passwd *pw) FAST_FUNC; void exec_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC; +void exec_login_shell(const char *shell) NORETURN FAST_FUNC; void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC; /* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL. diff --git a/libbb/run_shell.c b/libbb/run_shell.c index 9bec43b7c..c22bba87b 100644 --- a/libbb/run_shell.c +++ b/libbb/run_shell.c @@ -84,14 +84,19 @@ void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additi bb_perror_msg_and_die("can't execute '%s'", shell); } +void FAST_FUNC exec_login_shell(const char *shell) +{ + exec_shell(shell, 1, NULL); +} + /* Typical idiom for applets which exec *optional* PROG [ARGS] */ void FAST_FUNC exec_prog_or_SHELL(char **argv) { if (argv[0]) { BB_EXECVP_or_die(argv); } - /* Why login=1? Both users (nsenter and unshare) do indeed exec + /* Both users (nsenter and unshare) do indeed exec * a _login_ shell (with dash in argv[0])! */ - exec_shell(getenv("SHELL"), /*login:*/ 1, NULL); + exec_login_shell(getenv("SHELL")); } diff --git a/loginutils/login.c b/loginutils/login.c index aacd47241..de05631d2 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -602,7 +602,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) signal(SIGINT, SIG_DFL); /* Exec login shell with no additional parameters */ - exec_shell(pw->pw_shell, 1, NULL); + exec_login_shell(pw->pw_shell); /* return EXIT_FAILURE; - not reached */ } diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 127aa1de9..69d8b5ec7 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c @@ -89,5 +89,5 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) shell = pwd->pw_shell; /* Exec login shell with no additional parameters. Never returns. */ - exec_shell(shell, 1, NULL); + exec_login_shell(shell); } -- cgit v1.2.3-55-g6feb From 758c2bd58e0a23cdf19be8bd7c963074aff54b50 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Dec 2020 19:00:06 +0100 Subject: awk: add a test that $NF is empty Signed-off-by: Denys Vlasenko --- testsuite/awk.tests | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 06a531d96..92c83d719 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -398,12 +398,19 @@ testing 'awk do not allow "str"++' \ '' \ 'anything' -#gawk compat: FS regex matches only non-empty separators: -#with -*, the splitting is NOT f o o b a r, but foo bar: +# gawk compat: FS regex matches only non-empty separators: +# with -*, the splitting is NOT f o o b a r, but foo bar: testing 'awk FS regex which can match empty string' \ "awk -F '-*' '{print \$1 \"-\" \$2 \"=\" \$3 \"*\" \$4}'" \ "foo-bar=*\n" \ '' \ 'foo--bar' +# last+1 field should be empty (had a bug where it wasn't) +testing 'awk $NF is empty' \ + "awk -F '=+' '{print \$NF}'" \ + "\n" \ + '' \ + 'a=====123=' + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From b1eedfcfa1d2281b2e1b8773ab0130c5196b4505 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 5 Dec 2020 14:14:11 +0100 Subject: mount: do not guess mount as NFS if "hostname:" contains slashes function old new delta singlemount 1273 1295 +22 Signed-off-by: Denys Vlasenko --- util-linux/mount.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/util-linux/mount.c b/util-linux/mount.c index dba583544..7625d8424 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -2064,14 +2064,18 @@ static int singlemount(struct mntent *mp, int ignore_busy) } // Might this be an NFS filesystem? - if ((!mp->mnt_type || is_prefixed_with(mp->mnt_type, "nfs")) - && strchr(mp->mnt_fsname, ':') != NULL - && !(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE)) + if (!(vfsflags & (MS_BIND | MS_MOVE)) + && (!mp->mnt_type || is_prefixed_with(mp->mnt_type, "nfs")) ) { - if (!mp->mnt_type) - mp->mnt_type = (char*)"nfs"; - rc = nfsmount(mp, vfsflags, filteropts); - goto report_error; + char *colon = strchr(mp->mnt_fsname, ':'); + if (colon /* looks like "hostname:..." */ + && strchrnul(mp->mnt_fsname, '/') > colon /* "hostname:" has no slashes */ + ) { + if (!mp->mnt_type) + mp->mnt_type = (char*)"nfs"; + rc = nfsmount(mp, vfsflags, filteropts); + goto report_error; + } } // Look at the file. (Not found isn't a failure for remount, or for -- cgit v1.2.3-55-g6feb From 696c38ddca99f6d40ee6c4bd1d253a987989bd95 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 6 Dec 2020 20:59:41 +0100 Subject: mount: add -o nostrictatime and -o [no]lazytime function old new delta mount_option_str 345 379 +34 mount_options 176 188 +12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 46/0) Total: 46 bytes Signed-off-by: Denys Vlasenko --- util-linux/mount.c | 58 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/util-linux/mount.c b/util-linux/mount.c index 7625d8424..25d884a24 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -216,12 +216,16 @@ #ifndef MS_SHARED # define MS_SHARED (1 << 20) #endif + #ifndef MS_RELATIME # define MS_RELATIME (1 << 21) #endif #ifndef MS_STRICTATIME # define MS_STRICTATIME (1 << 24) #endif +#ifndef MS_LAZYTIME +# define MS_LAZYTIME (1 << 25) +#endif /* Any ~MS_FOO value has this bit set: */ #define BB_MS_INVERTED_VALUE (1u << 31) @@ -358,15 +362,18 @@ static const int32_t mount_options[] ALIGN4 = { /* "noatime" */ MS_NOATIME, /* "diratime" */ ~MS_NODIRATIME, /* "nodiratime" */ MS_NODIRATIME, - /* "mand" */ MS_MANDLOCK, - /* "nomand" */ ~MS_MANDLOCK, /* "relatime" */ MS_RELATIME, /* "norelatime" */ ~MS_RELATIME, /* "strictatime" */ MS_STRICTATIME, - /* "loud" */ ~MS_SILENT, - /* "rbind" */ MS_BIND|MS_RECURSIVE, + /* "nostrictatime"*/ ~MS_STRICTATIME, + /* "lazytime" */ MS_LAZYTIME, + /* "nolazytime" */ ~MS_LAZYTIME, + /* "mand" */ MS_MANDLOCK, + /* "nomand" */ ~MS_MANDLOCK, + /* "loud" */ ~MS_SILENT, // action flags + /* "rbind" */ MS_BIND|MS_RECURSIVE, /* "union" */ MS_UNION, /* "bind" */ MS_BIND, /* "move" */ MS_MOVE, @@ -404,28 +411,31 @@ static const char mount_option_str[] ALIGN1 = ) IF_FEATURE_MOUNT_FLAGS( // vfs flags - "nosuid\0" - "suid\0" - "dev\0" - "nodev\0" - "exec\0" - "noexec\0" - "sync\0" - "dirsync\0" - "async\0" - "atime\0" - "noatime\0" - "diratime\0" - "nodiratime\0" - "mand\0" - "nomand\0" - "relatime\0" - "norelatime\0" - "strictatime\0" - "loud\0" - "rbind\0" + "nosuid" "\0" + "suid" "\0" + "dev" "\0" + "nodev" "\0" + "exec" "\0" + "noexec" "\0" + "sync" "\0" + "dirsync" "\0" + "async" "\0" + "atime" "\0" + "noatime" "\0" + "diratime" "\0" + "nodiratime" "\0" + "relatime" "\0" + "norelatime" "\0" + "strictatime" "\0" + "nostrictatime""\0" + "lazytime" "\0" + "nolazytime" "\0" + "mand" "\0" + "nomand" "\0" + "loud" "\0" // action flags + "rbind\0" "union\0" "bind\0" "move\0" -- cgit v1.2.3-55-g6feb From 34c5115a7fb2adb7562b5638264112f5d83bf6cf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 6 Dec 2020 21:47:24 +0100 Subject: mount: implement -o nosymfollow, remove bogus -o union The (1 << 8) MS_ flag is MS_NOSYMFOLLOW, not MS_UNION. As far as I see in git history of kernel and util-linux, MS_UNION did not ever exist. Why did it appear in our tree in 2009?... function old new delta mount_option_str 379 385 +6 Signed-off-by: Denys Vlasenko --- util-linux/mount.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util-linux/mount.c b/util-linux/mount.c index 25d884a24..2eadee88b 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -188,8 +188,8 @@ #ifndef MS_DIRSYNC # define MS_DIRSYNC (1 << 7) // Directory modifications are synchronous #endif -#ifndef MS_UNION -# define MS_UNION (1 << 8) +#ifndef MS_NOSYMFOLLOW +# define MS_NOSYMFOLLOW (1 << 8) #endif #ifndef MS_BIND # define MS_BIND (1 << 12) @@ -368,13 +368,13 @@ static const int32_t mount_options[] ALIGN4 = { /* "nostrictatime"*/ ~MS_STRICTATIME, /* "lazytime" */ MS_LAZYTIME, /* "nolazytime" */ ~MS_LAZYTIME, + /* "nosymfollow" */ MS_NOSYMFOLLOW, /* "mand" */ MS_MANDLOCK, /* "nomand" */ ~MS_MANDLOCK, /* "loud" */ ~MS_SILENT, // action flags /* "rbind" */ MS_BIND|MS_RECURSIVE, - /* "union" */ MS_UNION, /* "bind" */ MS_BIND, /* "move" */ MS_MOVE, /* "shared" */ MS_SHARED, @@ -430,13 +430,13 @@ static const char mount_option_str[] ALIGN1 = "nostrictatime""\0" "lazytime" "\0" "nolazytime" "\0" + "nosymfollow" "\0" "mand" "\0" "nomand" "\0" "loud" "\0" // action flags "rbind\0" - "union\0" "bind\0" "move\0" "make-shared\0" -- cgit v1.2.3-55-g6feb From c9b93cf2908c845c60ad70cbed0074c4c0903208 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Dec 2020 16:46:41 +0100 Subject: tar: expand --help function old new delta packed_usage 33486 33590 +104 Signed-off-by: Denys Vlasenko --- archival/tar.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/archival/tar.c b/archival/tar.c index 93184cc2a..9d4c7b662 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -775,7 +775,7 @@ static llist_t *append_file_list_to_list(llist_t *list) //usage: IF_FEATURE_TAR_NOPRESERVE_TIME("m") //usage: "vokO] " //usage: "[-f TARFILE] [-C DIR] " -//usage: IF_FEATURE_TAR_FROM("[-T FILE] [-X FILE] "IF_FEATURE_TAR_LONG_OPTIONS("[--exclude PATTERN]... ")) +//usage: IF_FEATURE_TAR_FROM("[-T FILE] [-X FILE] "IF_FEATURE_TAR_LONG_OPTIONS("[OPTION]... ")) //usage: "[FILE]..." //usage:#define tar_full_usage "\n\n" //usage: IF_FEATURE_TAR_CREATE("Create, extract, ") @@ -809,6 +809,11 @@ static llist_t *append_file_list_to_list(llist_t *list) //usage: IF_FEATURE_SEAMLESS_BZ2( //usage: "\n -j (De)compress using bzip2" //usage: ) +//usage: IF_FEATURE_SEAMLESS_LZMA( +//usage: IF_FEATURE_TAR_LONG_OPTIONS( +//usage: "\n --lzma (De)compress using lzma" +//usage: ) +//usage: ) //usage: "\n -a (De)compress based on extension" //usage: IF_FEATURE_TAR_CREATE( //usage: "\n -h Follow symlinks" @@ -820,21 +825,21 @@ static llist_t *append_file_list_to_list(llist_t *list) //usage: "\n --exclude PATTERN Glob pattern to exclude" //usage: ) //usage: ) +//usage: IF_FEATURE_TAR_LONG_OPTIONS( +//usage: "\n --overwrite Replace existing files" +//usage: "\n --strip-components NUM NUM of leading components to strip" +//usage: "\n --no-recursion Don't descend in directories" +//usage: "\n --numeric-owner Use numeric user:group" +//usage: "\n --no-same-permissions Don't restore access permissions" +//usage: IF_FEATURE_TAR_TO_COMMAND( +//usage: "\n --to-command COMMAND Pipe files to COMMAND" +//usage: ) +//usage: ) //usage: //usage:#define tar_example_usage //usage: "$ zcat /tmp/tarball.tar.gz | tar -xf -\n" //usage: "$ tar -cf /tmp/tarball.tar /usr/local\n" -// Supported but aren't in --help: -// lzma -// no-recursion -// numeric-owner -// no-same-permissions -// overwrite -//IF_FEATURE_TAR_TO_COMMAND( -// to-command -//) - enum { OPTBIT_KEEP_OLD = 8, IF_FEATURE_TAR_CREATE( OPTBIT_CREATE ,) -- cgit v1.2.3-55-g6feb From abaee4aada7c91da6a43a83e9a73f98916a803a4 Mon Sep 17 00:00:00 2001 From: Xabier Oneca Date: Tue, 1 Dec 2020 23:14:59 +0100 Subject: mkdtemp: proper error detection on mktemp On error, mktemp returns an empty string, not NULL. Signed-off-by: Xabier Oneca Signed-off-by: Denys Vlasenko --- libbb/platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libbb/platform.c b/libbb/platform.c index 03bbb798b..d2b263a6d 100644 --- a/libbb/platform.c +++ b/libbb/platform.c @@ -107,7 +107,8 @@ void* FAST_FUNC memrchr(const void *s, int c, size_t n) /* This is now actually part of POSIX.1, but was only added in 2008 */ char* FAST_FUNC mkdtemp(char *template) { - if (mktemp(template) == NULL || mkdir(template, 0700) != 0) + /* NB: on error, mktemp returns an empty string, not NULL */ + if (mktemp(template)[0] == '\0' || mkdir(template, 0700) != 0) return NULL; return template; } -- cgit v1.2.3-55-g6feb From e7d853b4eb080dd8ea6433d010378e119e5a4cb3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Dec 2020 19:06:28 +0100 Subject: wget: do not ftruncate if -O- is used, closes 13351 function old new delta wget_main 2558 2571 +13 retrieve_file_data 612 621 +9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 22/0) Total: 22 bytes Signed-off-by: Denys Vlasenko --- networking/wget.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index ea60c18b2..ff0df4ca0 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -287,6 +287,8 @@ enum { WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + /* hijack this bit for other than opts purposes: */ + WGET_NO_FTRUNCATE = (1 << 31) }; enum { @@ -1052,8 +1054,13 @@ static void NOINLINE retrieve_file_data(FILE *dfp) */ { off_t pos = lseek(G.output_fd, 0, SEEK_CUR); - if (pos != (off_t)-1) - ftruncate(G.output_fd, pos); + if (pos != (off_t)-1) { + /* do not truncate if -O- is in use, a user complained about + * "wget -qO- 'http://example.com/empty' >>FILE" truncating FILE. + */ + if (!(option_mask32 & WGET_NO_FTRUNCATE)) + ftruncate(G.output_fd, pos); + } } if (!(option_mask32 & WGET_OPT_QUIET)) { @@ -1566,7 +1573,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") if (G.fname_out) { /* -O FILE ? */ if (LONE_DASH(G.fname_out)) { /* -O - ? */ G.output_fd = 1; - option_mask32 &= ~WGET_OPT_CONTINUE; + option_mask32 = (option_mask32 & (~WGET_OPT_CONTINUE)) | WGET_NO_FTRUNCATE; } /* compat with wget: -O FILE can overwrite */ G.o_flags = O_WRONLY | O_CREAT | O_TRUNC; -- cgit v1.2.3-55-g6feb From 56ee5765074b2f2389066f3234a4da21501d3eaa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 9 Dec 2020 20:56:43 +0100 Subject: mount: fix incorrect "success" exitcode if loop device setup fails When mounting, in parallel, multiple loop devices (squashfs for the submitter's case), the following behavior can be observed: stat64(/path/to/image, {st_mode=S_IFREG|0644, st_size=4096, ...}) = 0 openat(AT_FDCWD, /path/to/image, O_RDWR|O_LARGEFILE) = 3 openat(AT_FDCWD, /dev/loop-control, O_RDWR|O_LARGEFILE|O_CLOEXEC) = 4 ioctl(4, LOOP_CTL_GET_FREE) = 12 close(4) = 0 openat(AT_FDCWD, /dev/loop12, O_RDWR|O_LARGEFILE) = 4 ioctl(4, LOOP_GET_STATUS64, {lo_offset=0, lo_number=12, lo_flags=LO_FLAGS_AUTOCLEAR, lo_file_name=/path/to/image, ...}) = 0 close(4) = 0 close(3) = 0 write(2, "mount: can't setup loop device\n", 31mount: can't setup loop device ) = 31 exit_group(0) = ? +++ exited with 0 +++ The ioctl LOOP_CTL_GET_FREE has resulted in the same result for a competing mount process. The subsequent ioctl LOOP_GET_STATUS64 fails, having succeeded for the competing mount process. Signed-off-by: Denys Vlasenko --- util-linux/mount.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util-linux/mount.c b/util-linux/mount.c index 2eadee88b..0814a5256 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -2078,8 +2078,8 @@ static int singlemount(struct mntent *mp, int ignore_busy) && (!mp->mnt_type || is_prefixed_with(mp->mnt_type, "nfs")) ) { char *colon = strchr(mp->mnt_fsname, ':'); - if (colon /* looks like "hostname:..." */ - && strchrnul(mp->mnt_fsname, '/') > colon /* "hostname:" has no slashes */ + if (colon // looks like "hostname:..." + && strchrnul(mp->mnt_fsname, '/') > colon // "hostname:" has no slashes ) { if (!mp->mnt_type) mp->mnt_type = (char*)"nfs"; @@ -2125,7 +2125,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) bb_simple_error_msg(bb_msg_perm_denied_are_you_root); else bb_simple_perror_msg("can't setup loop device"); - return errno; + return loopfd; // was "return errno", but it can be 0 here } // Autodetect bind mounts -- cgit v1.2.3-55-g6feb From 030fe31760169783537162b83af89e551bf120f6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 11 Dec 2020 16:48:47 +0100 Subject: libbb: make msleep() result in only one syscall instead of looping function old new delta msleep 45 52 +7 Signed-off-by: Denys Vlasenko --- libbb/bb_do_delay.c | 18 ++++++++++++++++++ libbb/platform.c | 1 - networking/ifupdown.c | 6 +++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c index 3dbf032db..9a84fa24b 100644 --- a/libbb/bb_do_delay.c +++ b/libbb/bb_do_delay.c @@ -36,6 +36,7 @@ void FAST_FUNC sleep1(void) void FAST_FUNC msleep(unsigned ms) { +#if 0 /* 1. usleep(n) is not guaranteed by standards to accept n >= 1000000 * 2. multiplication in usleep(ms * 1000) can overflow if ms > 4294967 * (sleep of ~71.5 minutes) @@ -46,4 +47,21 @@ void FAST_FUNC msleep(unsigned ms) ms -= 500; } usleep(ms * 1000); +#else +//usleep is often implemented as a call to nanosleep. +//Simply do the same to implement msleep. +//it's marginally larger, but wakes your CPU less often: +//function old new delta +//msleep 45 52 +7 + struct timespec ts; + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000; + /* + * If a signal has non-default handler, nanosleep returns early. + * Our version of msleep doesn't return early + * if interrupted by such signals: + */ + while (nanosleep(&ts, &ts) != 0) + continue; +#endif } diff --git a/libbb/platform.c b/libbb/platform.c index d2b263a6d..329b0237e 100644 --- a/libbb/platform.c +++ b/libbb/platform.c @@ -27,7 +27,6 @@ int FAST_FUNC usleep(unsigned usec) * If a signal has non-default handler, nanosleep returns early. * Our version of usleep doesn't return early * if interrupted by such signals: - * */ while (nanosleep(&ts, &ts) != 0) continue; diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 60ceb5a1f..fedf05aaf 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -1357,15 +1357,15 @@ static FILE *open_new_state_file(void) IFSTATE_FILE_PATH".new"); } /* Someone else created the .new file */ - if (cnt > 30 * 1000) { + if (cnt > 30) { /* Waited for 30*30/2 = 450 milliseconds, still EEXIST. * Assuming a stale file, rewriting it. */ flags = (O_WRONLY | O_CREAT | O_TRUNC); continue; } - usleep(cnt); - cnt += 1000; + msleep(cnt); + cnt++; } return xfdopen_for_write(fd); -- cgit v1.2.3-55-g6feb From ef2366cdca45941f943f4970ac57a4008181fca9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Dec 2020 08:44:32 +0100 Subject: nsenter: stop option parsing on 1st non-option "nsenter ls -l" gives: invalid option -- 'l' Signed-off-by: Denys Vlasenko --- findutils/find.c | 2 +- util-linux/nsenter.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/findutils/find.c b/findutils/find.c index a8c3fa346..34e11ae26 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -1522,7 +1522,7 @@ int find_main(int argc UNUSED_PARAM, char **argv) } *past_HLP = NULL; /* "+": stop on first non-option */ - i = getopt32(argv, "+HLP"); + i = getopt32(argv, "+""HLP"); if (i & (1<<0)) G.recurse_flags |= ACTION_FOLLOWLINKS_L0 | ACTION_DANGLING_OK; if (i & (1<<1)) diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index c48dcf885..9cfbf21e4 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c @@ -103,8 +103,9 @@ static const struct namespace_descr ns_list[] = { }; /* * Upstream nsenter doesn't support the short option for --preserve-credentials + * "+": stop on first non-option */ -static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t:+S:+G:+r::w::F"; +static const char opt_str[] ALIGN1 = "+""U::i::u::n::p::m::""t:+S:+G:+r::w::F"; #if ENABLE_LONG_OPTS static const char nsenter_longopts[] ALIGN1 = -- cgit v1.2.3-55-g6feb From 3978adc4458eccfcd3720a6ec1199b255156e344 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Dec 2020 16:38:43 +0100 Subject: traceroute: fix traceroute6 -I (icmp mode) function old new delta common_traceroute_main 3530 3544 +14 Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 206 +++++++++++++++++++++++++++++++----------------- 1 file changed, 135 insertions(+), 71 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index 7dde10524..ddde922bf 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -414,9 +414,32 @@ struct globals { waittime = 5; \ } while (0) -#define outicmp ((struct icmp *)(outip + 1)) -#define outudp ((struct udphdr *)(outip + 1)) - +#define outudp ((struct udphdr *)(outip + 1)) +#define outudp6 ((struct udphdr *)(((struct ip6_hdr*)outip) + 1)) +#define outicmp ((struct icmp *)(outip + 1)) +#define outicmp6 ((struct icmp *)(((struct ip6_hdr*)outip) + 1)) +/* NB: for icmp echo, IPv4 and IPv6 fields are the same size and offset: + * struct icmp: + * uint8_t icmp_type; + * uint8_t icmp_code; + * uint16_t icmp_cksum; + * uint16_t icmp_id; + * uint16_t icmp_seq; + * struct icmp6_hdr: + * uint8_t icmp6_type; + * uint8_t icmp6_code; + * uint16_t icmp6_cksum; + * uint16_t icmp6_id; + * uint16_t icmp6_seq; + * therefore both outicmp and outicmp6 are pointers to *IPv4* icmp struct. + * SIZEOF_ICMP_HDR == 8 is the same for both, as well. + * However, values of these pointers are not the same (since IPv6 IP header is larger), + * and icmp_type constants are not the same: + * #define ICMP_ECHO 8 + * #define ICMP_ECHOREPLY 0 + * #define ICMP6_ECHO_REQUEST 128 + * #define ICMP6_ECHO_REPLY 129 + */ static int wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms) @@ -446,14 +469,16 @@ send_probe(int seq, int ttl) { int len, res; void *out; + struct icmp *icp; /* Payload */ #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { - struct outdata6_t *pkt = (struct outdata6_t *) outdata; + struct outdata6_t *pkt = (void *) outdata; pkt->ident6 = htonl(ident); pkt->seq6 = htonl(seq); /*gettimeofday(&pkt->tv, &tz);*/ + icp = outicmp6; } else #endif { @@ -461,19 +486,23 @@ send_probe(int seq, int ttl) outdata->ttl = ttl; // UNUSED: was storing gettimeofday's result there, but never ever checked it /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ - - if (option_mask32 & OPT_USE_ICMP) { - outicmp->icmp_seq = htons(seq); - - /* Always calculate checksum for icmp packets */ - outicmp->icmp_cksum = 0; - outicmp->icmp_cksum = inet_cksum( - outicmp, - ((char*)outip + packlen) - (char*)outicmp - ); - if (outicmp->icmp_cksum == 0) - outicmp->icmp_cksum = 0xffff; - } + icp = outicmp; + } + out = outdata; + if (option_mask32 & OPT_USE_ICMP) { + out = icp; + /*icp->icmp_type = ICMP[6]_ECHO; - already set */ + /*icp->icmp_code = 0; - already set */ + /*icp->icmp_id = ident; - already set */ + icp->icmp_seq = htons(seq); + /* Always calculate checksum for icmp packets */ + icp->icmp_cksum = 0; + icp->icmp_cksum = inet_cksum( + icp, + ((char*)outip + packlen) - (char*)icp + ); + if (icp->icmp_cksum == 0) + icp->icmp_cksum = 0xffff; } //BUG! verbose is (x & OPT_VERBOSE), not a counter! @@ -502,7 +531,6 @@ send_probe(int seq, int ttl) } #endif - out = outdata; #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); @@ -516,8 +544,6 @@ send_probe(int seq, int ttl) if (res != 0) bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); #endif - if (option_mask32 & OPT_USE_ICMP) - out = outicmp; } if (!(option_mask32 & OPT_USE_ICMP)) { @@ -579,7 +605,12 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) int hlen; const struct ip *ip; + /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket + * return the entire IP packet (IOW: they do not strip IP header). + * This differs from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) sockets!? + */ ip = (struct ip *) recv_pkt; + hlen = ip->ip_hl << 2; if (read_len < hlen + ICMP_MINLEN) { #if ENABLE_FEATURE_TRACEROUTE_VERBOSE @@ -598,9 +629,20 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) if (code == ICMP_UNREACH_NEEDFRAG) pmtu = ntohs(icp->icmp_nextmtu); + if ((option_mask32 & OPT_USE_ICMP) + && type == ICMP_ECHOREPLY + && icp->icmp_id == htons(ident) + && icp->icmp_seq == htons(seq) + ) { + /* In UDP mode, when we reach the machine, we (usually) + * would get "port unreachable" - in ICMP we got "echo reply". + * Simulate "port unreachable" for caller: + */ + return ICMP_UNREACH_PORT+1; + } + if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || type == ICMP_UNREACH - || type == ICMP_ECHOREPLY ) { const struct ip *hip; const struct udphdr *up; @@ -610,14 +652,6 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) if (option_mask32 & OPT_USE_ICMP) { struct icmp *hicmp; - /* XXX */ - if (type == ICMP_ECHOREPLY - && icp->icmp_id == htons(ident) - && icp->icmp_seq == htons(seq) - ) { - return ICMP_UNREACH_PORT+1; - } - hicmp = (struct icmp *)((unsigned char *)hip + hlen); if (hlen + SIZEOF_ICMP_HDR <= read_len && hip->ip_p == IPPROTO_ICMP @@ -648,6 +682,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) printf("\n%d bytes from %s to " "%s: icmp type %d (%s) code %d\n", read_len, inet_ntoa(from->sin_addr), +//BUG: inet_ntoa() returns static buf! x2 is NONO! inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); for (i = 4; i < read_len; i += sizeof(*lp)) @@ -673,11 +708,27 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, if (from_lsa->u.sa.sa_family == AF_INET) return packet4_ok(read_len, &from_lsa->u.sin, seq); + /* NB: reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) socket + * return only ICMP packet (IOW: they strip IPv6 header). + * This differs from (AF_INET, SOCK_RAW, IPPROTO_ICMP) sockets!? + */ icp = (struct icmp6_hdr *) recv_pkt; type = icp->icmp6_type; code = icp->icmp6_code; + if ((option_mask32 & OPT_USE_ICMP) + && type == ICMP6_ECHO_REPLY + && icp->icmp6_id == htons(ident) + && icp->icmp6_seq == htons(seq) + ) { + /* In UDP mode, when we reach the machine, we (usually) + * would get "port unreachable" - in ICMP we got "echo reply". + * Simulate "port unreachable" for caller: + */ + return (ICMP6_DST_UNREACH_NOPORT << 8) + 1; + } + if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) || type == ICMP6_DST_UNREACH ) { @@ -787,8 +838,13 @@ print(int read_len, const struct sockaddr *from, const struct sockaddr *to) if (verbose) { char *ina = xmalloc_sockaddr2dotted_noport(to); #if ENABLE_TRACEROUTE6 + /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket + * return the entire IP packet (IOW: they do not strip IP header). + * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6 + * header and return only ICMP6 packet. Weird. + */ if (to->sa_family == AF_INET6) { - read_len -= sizeof(struct ip6_hdr); + /* read_len -= sizeof(struct ip6_hdr); - WRONG! */ } else #endif { @@ -844,6 +900,9 @@ common_traceroute_main(int op, char **argv) struct sockaddr *lastaddr; struct sockaddr *to; + /* Ensure the socket fds won't be 0, 1 or 2 */ + bb_sanitize_stdio(); + INIT_G(); op |= getopt32(argv, "^" @@ -885,12 +944,14 @@ common_traceroute_main(int op, char **argv) /* Process destination and optional packet size */ minpacket = sizeof(struct ip) - + SIZEOF_ICMP_HDR + + sizeof(struct udphdr) + sizeof(struct outdata_t); - if (!(op & OPT_USE_ICMP)) + if (op & OPT_USE_ICMP) { minpacket = sizeof(struct ip) - + sizeof(struct udphdr) + + SIZEOF_ICMP_HDR + sizeof(struct outdata_t); + port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */ + } #if ENABLE_TRACEROUTE6 af = AF_UNSPEC; if (op & OPT_IPV4) @@ -899,10 +960,15 @@ common_traceroute_main(int op, char **argv) af = AF_INET6; dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); af = dest_lsa->u.sa.sa_family; - if (af == AF_INET6) + if (af == AF_INET6) { minpacket = sizeof(struct ip6_hdr) - + sizeof(struct udphdr) - + sizeof(struct outdata6_t); + + sizeof(struct udphdr) + + sizeof(struct outdata6_t); + if (op & OPT_USE_ICMP) + minpacket = sizeof(struct ip6_hdr) + + SIZEOF_ICMP_HDR + + sizeof(struct outdata6_t); + } #else dest_lsa = xhost2sockaddr(argv[0], port); #endif @@ -910,13 +976,10 @@ common_traceroute_main(int op, char **argv) if (argv[1]) packlen = xatoul_range(argv[1], minpacket, 32 * 1024); - /* Ensure the socket fds won't be 0, 1 or 2 */ - bb_sanitize_stdio(); - #if ENABLE_TRACEROUTE6 if (af == AF_INET6) { xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); - setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); + setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); //why? } else #endif { @@ -934,7 +997,10 @@ common_traceroute_main(int op, char **argv) if (af == AF_INET6) { if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); - xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock); + if (op & OPT_USE_ICMP) + xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), sndsock); + else + xmove_fd(xsocket(AF_INET6, SOCK_DGRAM, 0), sndsock); } else #endif { @@ -943,6 +1009,7 @@ common_traceroute_main(int op, char **argv) else xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); } +//TODO xmove_fd to here! #ifdef SO_SNDBUF if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) { @@ -970,21 +1037,25 @@ common_traceroute_main(int op, char **argv) ident = getpid(); if (!ENABLE_TRACEROUTE6 || af == AF_INET) { + outdata = (void*)(outudp + 1); if (op & OPT_USE_ICMP) { ident |= 0x8000; outicmp->icmp_type = ICMP_ECHO; + /*outicmp->icmp_code = 0; - set by xzalloc */ outicmp->icmp_id = htons(ident); - outdata = (struct outdata_t *)((char *)outicmp + SIZEOF_ICMP_HDR); - } else { - outdata = (struct outdata_t *)(outudp + 1); + outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR); } } #if ENABLE_TRACEROUTE6 if (af == AF_INET6) { - outdata = (void*)((char*)outip - + sizeof(struct ip6_hdr) - + sizeof(struct udphdr) - ); + outdata = (void*)(outudp6 + 1); + if (op & OPT_USE_ICMP) { + ident |= 0x8000; + outicmp6->icmp_type = ICMP6_ECHO_REQUEST; + /*outicmp->icmp_code = 0; - set by xzalloc */ + outicmp6->icmp_id = htons(ident); + outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR); + } } #endif @@ -1013,26 +1084,16 @@ common_traceroute_main(int op, char **argv) //TODO: why we don't do it for IPv4? len_and_sockaddr *source_lsa; - int probe_fd = xsocket(af, SOCK_DGRAM, 0); - if (op & OPT_DEVICE) - setsockopt_bindtodevice(probe_fd, device); - set_nport(&dest_lsa->u.sa, htons(1025)); - /* dummy connect. makes kernel pick source IP (and port) */ - xconnect(probe_fd, &dest_lsa->u.sa, dest_lsa->len); set_nport(&dest_lsa->u.sa, htons(port)); - - /* read IP and port */ - source_lsa = get_sock_lsa(probe_fd); + /* Connect makes kernel pick source IP and port */ + xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len); + /* Read IP and port */ + source_lsa = get_sock_lsa(sndsock); if (source_lsa == NULL) bb_simple_error_msg_and_die("can't get probe addr"); - - close(probe_fd); - - /* bind our sockets to this IP (but not port) */ + /* bind our recv socket to this IP (but not port) */ set_nport(&source_lsa->u.sa, 0); - xbind(sndsock, &source_lsa->u.sa, source_lsa->len); xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); - free(source_lsa); } #endif @@ -1067,10 +1128,9 @@ common_traceroute_main(int op, char **argv) unsigned t1; unsigned t2; int left_ms; - struct ip *ip; fflush_all(); - if (probe != 0 && pausemsecs > 0) + if (probe != 0) msleep(pausemsecs); send_probe(++seq, ttl); @@ -1099,15 +1159,18 @@ common_traceroute_main(int op, char **argv) } print_delta_ms(t1, t2); - ip = (struct ip *)recv_pkt; - if (from_lsa->u.sa.sa_family == AF_INET) - if (op & OPT_TTL_FLAG) + if (from_lsa->u.sa.sa_family == AF_INET) { + if (op & OPT_TTL_FLAG) { + struct ip *ip = (struct ip *)recv_pkt; printf(" (%d)", ip->ip_ttl); + } + } - /* time exceeded in transit */ + /* Got a "time exceeded in transit" icmp message? */ if (icmp_code == -1) break; + icmp_code--; switch (icmp_code) { #if ENABLE_TRACEROUTE6 @@ -1115,12 +1178,13 @@ common_traceroute_main(int op, char **argv) got_there = 1; break; #endif - case ICMP_UNREACH_PORT: + case ICMP_UNREACH_PORT: { + struct ip *ip = (struct ip *)recv_pkt; if (ip->ip_ttl <= 1) printf(" !"); got_there = 1; break; - + } case ICMP_UNREACH_NET: #if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET) case ICMP6_DST_UNREACH_NOROUTE << 8: -- cgit v1.2.3-55-g6feb From d0dea17900267ec9644aa72721d2f0473338651c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Dec 2020 17:24:17 +0100 Subject: traceroute: code shrink Do not byteswap ident (why we were doing it?) function old new delta common_traceroute_main 3544 3426 -118 Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 107 ++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index ddde922bf..764d66ef8 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -475,7 +475,7 @@ send_probe(int seq, int ttl) #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { struct outdata6_t *pkt = (void *) outdata; - pkt->ident6 = htonl(ident); + pkt->ident6 = ident; pkt->seq6 = htonl(seq); /*gettimeofday(&pkt->tv, &tz);*/ icp = outicmp6; @@ -631,7 +631,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) if ((option_mask32 & OPT_USE_ICMP) && type == ICMP_ECHOREPLY - && icp->icmp_id == htons(ident) + && icp->icmp_id == ident && icp->icmp_seq == htons(seq) ) { /* In UDP mode, when we reach the machine, we (usually) @@ -655,7 +655,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) hicmp = (struct icmp *)((unsigned char *)hip + hlen); if (hlen + SIZEOF_ICMP_HDR <= read_len && hip->ip_p == IPPROTO_ICMP - && hicmp->icmp_id == htons(ident) + && hicmp->icmp_id == ident && hicmp->icmp_seq == htons(seq) ) { return (type == ICMP_TIMXCEED ? -1 : code + 1); @@ -667,7 +667,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) // Off: since we do not form the entire IP packet, // but defer it to kernel, we can't set source port, // and thus can't check it here in the reply - /* && up->source == htons(ident) */ + /* && up->source == ident */ && up->dest == htons(port + seq) ) { return (type == ICMP_TIMXCEED ? -1 : code + 1); @@ -679,10 +679,10 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) int i; uint32_t *lp = (uint32_t *)&icp->icmp_ip; - printf("\n%d bytes from %s to " - "%s: icmp type %d (%s) code %d\n", - read_len, inet_ntoa(from->sin_addr), -//BUG: inet_ntoa() returns static buf! x2 is NONO! + printf("\n%d bytes from %s", + read_len, inet_ntoa(from->sin_addr)); + /* Two separate printf() because inet_ntoa() returns static string */ + printf(" to %s: icmp type %d (%s) code %d\n", inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); for (i = 4; i < read_len; i += sizeof(*lp)) @@ -693,21 +693,19 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) } #if ENABLE_TRACEROUTE6 + # if !ENABLE_FEATURE_TRACEROUTE_VERBOSE -#define packet_ok(read_len, from_lsa, to, seq) \ - packet_ok(read_len, from_lsa, seq) +#define packet6_ok(read_len, from_lsa, to, seq) \ + packet6_ok(read_len, from_lsa, seq) # endif static int -packet_ok(int read_len, len_and_sockaddr *from_lsa, +packet6_ok(int read_len, const struct sockaddr_in6 *from, struct sockaddr *to, int seq) { const struct icmp6_hdr *icp; unsigned char type, code; - if (from_lsa->u.sa.sa_family == AF_INET) - return packet4_ok(read_len, &from_lsa->u.sin, seq); - /* NB: reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) socket * return only ICMP packet (IOW: they strip IPv6 header). * This differs from (AF_INET, SOCK_RAW, IPPROTO_ICMP) sockets!? @@ -719,7 +717,7 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, if ((option_mask32 & OPT_USE_ICMP) && type == ICMP6_ECHO_REPLY - && icp->icmp6_id == htons(ident) + && icp->icmp6_id == ident && icp->icmp6_seq == htons(seq) ) { /* In UDP mode, when we reach the machine, we (usually) @@ -749,7 +747,7 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, pkt = (struct outdata6_t *) (up + 1); - if (ntohl(pkt->ident6) == ident + if (pkt->ident6 == ident && ntohl(pkt->seq6) == seq ) { return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1); @@ -763,17 +761,17 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, # define MAXHOSTNAMELEN 80 # endif unsigned char *p; - char pa1[MAXHOSTNAMELEN]; - char pa2[MAXHOSTNAMELEN]; + char pa[MAXHOSTNAMELEN]; int i; p = (unsigned char *) (icp + 1); - printf("\n%d bytes from %s to " - "%s: icmp type %d (%s) code %d\n", + printf("\n%d bytes from %s", read_len, - inet_ntop(AF_INET6, &from_lsa->u.sin6.sin6_addr, pa1, sizeof(pa1)), - inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa2, sizeof(pa2)), + inet_ntop(AF_INET6, &from->sin6_addr, pa, sizeof(pa))); + /* Two printf() instead of one - reuse string constants */ + printf(" to %s: icmp type %d (%s) code %d\n", + inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa, sizeof(pa)), type, pr_type(type), icp->icmp6_code); read_len -= sizeof(struct icmp6_hdr); @@ -792,7 +790,22 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, return 0; } +# if !ENABLE_FEATURE_TRACEROUTE_VERBOSE +#define packet_ok(read_len, from_lsa, to, seq) \ + packet_ok(read_len, from_lsa, seq) +# endif +static int +packet_ok(int read_len, len_and_sockaddr *from_lsa, + struct sockaddr *to, + int seq) +{ + if (from_lsa->u.sa.sa_family == AF_INET) + return packet4_ok(read_len, &from_lsa->u.sin, seq); + return packet6_ok(read_len, &from_lsa->u.sin6, to, seq); +} + #else /* !ENABLE_TRACEROUTE6 */ + static ALWAYS_INLINE int packet_ok(int read_len, len_and_sockaddr *from_lsa IF_NOT_FEATURE_TRACEROUTE_VERBOSE(UNUSED_PARAM), @@ -801,6 +814,7 @@ packet_ok(int read_len, { return packet4_ok(read_len, &from_lsa->u.sin, seq); } + #endif /* @@ -927,14 +941,6 @@ common_traceroute_main(int op, char **argv) port = xatou16(port_str); if (op & OPT_NPROBES) nprobes = xatou_range(nprobes_str, 1, INT_MAX); - if (op & OPT_SOURCE) { - /* - * set the ip source address of the outbound - * probe (e.g., on a multi-homed host). - */ - if (getuid() != 0) - bb_simple_error_msg_and_die(bb_msg_you_must_be_root); - } if (op & OPT_WAITTIME) waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); if (op & OPT_PAUSE_MS) @@ -993,23 +999,26 @@ common_traceroute_main(int op, char **argv) if (op & OPT_BYPASS_ROUTE) setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE); + { + int snd; #if ENABLE_TRACEROUTE6 - if (af == AF_INET6) { - if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) - bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); - if (op & OPT_USE_ICMP) - xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), sndsock); - else - xmove_fd(xsocket(AF_INET6, SOCK_DGRAM, 0), sndsock); - } else + if (af == AF_INET6) { + if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) + bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); + if (op & OPT_USE_ICMP) + snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + else + snd = xsocket(AF_INET6, SOCK_DGRAM, 0); + } else #endif - { - if (op & OPT_USE_ICMP) - xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock); - else - xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); + { + if (op & OPT_USE_ICMP) + snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + else + snd = xsocket(AF_INET, SOCK_DGRAM, 0); + } + xmove_fd(snd, sndsock); } -//TODO xmove_fd to here! #ifdef SO_SNDBUF if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) { @@ -1036,13 +1045,12 @@ common_traceroute_main(int op, char **argv) ident = getpid(); + outdata = (void*)(outudp + 1); if (!ENABLE_TRACEROUTE6 || af == AF_INET) { - outdata = (void*)(outudp + 1); if (op & OPT_USE_ICMP) { - ident |= 0x8000; outicmp->icmp_type = ICMP_ECHO; /*outicmp->icmp_code = 0; - set by xzalloc */ - outicmp->icmp_id = htons(ident); + outicmp->icmp_id = ident; outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR); } } @@ -1050,10 +1058,9 @@ common_traceroute_main(int op, char **argv) if (af == AF_INET6) { outdata = (void*)(outudp6 + 1); if (op & OPT_USE_ICMP) { - ident |= 0x8000; outicmp6->icmp_type = ICMP6_ECHO_REQUEST; /*outicmp->icmp_code = 0; - set by xzalloc */ - outicmp6->icmp_id = htons(ident); + outicmp6->icmp_id = ident; outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR); } } @@ -1069,6 +1076,8 @@ common_traceroute_main(int op, char **argv) #else len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0); #endif + if (getuid() != 0) + bb_simple_error_msg_and_die(bb_msg_you_must_be_root); /* Ping4 does this (why?) */ if (af == AF_INET) if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF, -- cgit v1.2.3-55-g6feb From 70726640b33e50d0802f297c5a3f18494a488c8d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Dec 2020 17:45:49 +0100 Subject: traceroute: code shrink Do not pass "from" and "to" addresses as parameters, keep them in globals function old new delta common_traceroute_main 3426 3391 -35 Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 84 +++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index 764d66ef8..588570fcb 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -389,6 +389,8 @@ struct globals { struct outdata_t *outdata; len_and_sockaddr *dest_lsa; + len_and_sockaddr *from_lsa; /* response came from this address */ + struct sockaddr *to; /* response came to this (local) address */ int packlen; /* total length of packet */ int pmtu; /* Path MTU Discovery (RFC1191) */ uint32_t ident; @@ -442,7 +444,7 @@ struct globals { */ static int -wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms) +wait_for_reply(unsigned *timestamp_us, int *left_ms) { struct pollfd pfd[1]; int read_len = 0; @@ -455,7 +457,7 @@ wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timest read_len = recv_from_to(rcvsock, recv_pkt, sizeof(recv_pkt), /*flags:*/ MSG_DONTWAIT, - &from_lsa->u.sa, to, from_lsa->len); + &G.from_lsa->u.sa, G.to, G.from_lsa->len); t = monotonic_us(); *left_ms -= (t - *timestamp_us) / 1000; *timestamp_us = t; @@ -598,7 +600,7 @@ pr_type(unsigned char t) packet4_ok(read_len, seq) #endif static int -packet4_ok(int read_len, const struct sockaddr_in *from, int seq) +packet4_ok(int read_len, int seq) { const struct icmp *icp; unsigned char type, code; @@ -616,7 +618,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) #if ENABLE_FEATURE_TRACEROUTE_VERBOSE if (verbose) printf("packet too short (%d bytes) from %s\n", read_len, - inet_ntoa(from->sin_addr)); + inet_ntoa(G.from_lsa->u.sin.sin_addr)); #endif return 0; } @@ -680,7 +682,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) uint32_t *lp = (uint32_t *)&icp->icmp_ip; printf("\n%d bytes from %s", - read_len, inet_ntoa(from->sin_addr)); + read_len, inet_ntoa(G.from_lsa->u.sin.sin_addr)); /* Two separate printf() because inet_ntoa() returns static string */ printf(" to %s: icmp type %d (%s) code %d\n", inet_ntoa(ip->ip_dst), @@ -694,14 +696,8 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) #if ENABLE_TRACEROUTE6 -# if !ENABLE_FEATURE_TRACEROUTE_VERBOSE -#define packet6_ok(read_len, from_lsa, to, seq) \ - packet6_ok(read_len, from_lsa, seq) -# endif static int -packet6_ok(int read_len, const struct sockaddr_in6 *from, - struct sockaddr *to, - int seq) +packet6_ok(int read_len, int seq) { const struct icmp6_hdr *icp; unsigned char type, code; @@ -757,21 +753,18 @@ packet6_ok(int read_len, const struct sockaddr_in6 *from, # if ENABLE_FEATURE_TRACEROUTE_VERBOSE if (verbose) { -# ifndef MAXHOSTNAMELEN -# define MAXHOSTNAMELEN 80 -# endif unsigned char *p; - char pa[MAXHOSTNAMELEN]; + char pa[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + 4]; int i; p = (unsigned char *) (icp + 1); printf("\n%d bytes from %s", read_len, - inet_ntop(AF_INET6, &from->sin6_addr, pa, sizeof(pa))); + inet_ntop(AF_INET6, &G.from_lsa->u.sin6.sin6_addr, pa, sizeof(pa))); /* Two printf() instead of one - reuse string constants */ printf(" to %s: icmp type %d (%s) code %d\n", - inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa, sizeof(pa)), + inet_ntop(AF_INET6, &((struct sockaddr_in6*)G.to)->sin6_addr, pa, sizeof(pa)), type, pr_type(type), icp->icmp6_code); read_len -= sizeof(struct icmp6_hdr); @@ -790,29 +783,21 @@ packet6_ok(int read_len, const struct sockaddr_in6 *from, return 0; } -# if !ENABLE_FEATURE_TRACEROUTE_VERBOSE -#define packet_ok(read_len, from_lsa, to, seq) \ - packet_ok(read_len, from_lsa, seq) -# endif + static int -packet_ok(int read_len, len_and_sockaddr *from_lsa, - struct sockaddr *to, - int seq) +packet_ok(int read_len, int seq) { - if (from_lsa->u.sa.sa_family == AF_INET) - return packet4_ok(read_len, &from_lsa->u.sin, seq); - return packet6_ok(read_len, &from_lsa->u.sin6, to, seq); + if (G.from_lsa->u.sa.sa_family == AF_INET) + return packet4_ok(read_len, seq); + return packet6_ok(read_len, seq); } #else /* !ENABLE_TRACEROUTE6 */ static ALWAYS_INLINE int -packet_ok(int read_len, - len_and_sockaddr *from_lsa IF_NOT_FEATURE_TRACEROUTE_VERBOSE(UNUSED_PARAM), - struct sockaddr *to UNUSED_PARAM, - int seq) +packet_ok(int read_len, int seq) { - return packet4_ok(read_len, &from_lsa->u.sin, seq); + return packet4_ok(read_len, seq); } #endif @@ -845,19 +830,19 @@ print_inetname(const struct sockaddr *from) } static void -print(int read_len, const struct sockaddr *from, const struct sockaddr *to) +print(int read_len) { - print_inetname(from); + print_inetname(&G.from_lsa->u.sa); if (verbose) { - char *ina = xmalloc_sockaddr2dotted_noport(to); + char *ina = xmalloc_sockaddr2dotted_noport(G.to); #if ENABLE_TRACEROUTE6 /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket * return the entire IP packet (IOW: they do not strip IP header). * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6 * header and return only ICMP6 packet. Weird. */ - if (to->sa_family == AF_INET6) { + if (G.to->sa_family == AF_INET6) { /* read_len -= sizeof(struct ip6_hdr); - WRONG! */ } else #endif @@ -910,9 +895,7 @@ common_traceroute_main(int op, char **argv) #endif int ttl; int seq; - len_and_sockaddr *from_lsa; struct sockaddr *lastaddr; - struct sockaddr *to; /* Ensure the socket fds won't be 0, 1 or 2 */ bb_sanitize_stdio(); @@ -1121,9 +1104,9 @@ common_traceroute_main(int op, char **argv) printf(" from %s", source); printf(", %d hops max, %d byte packets\n", max_ttl, packlen); - from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); lastaddr = xzalloc(dest_lsa->len); - to = xzalloc(dest_lsa->len); + G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); + G.to = xzalloc(dest_lsa->len); seq = 0; for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { int probe; @@ -1146,7 +1129,10 @@ common_traceroute_main(int op, char **argv) t2 = t1 = monotonic_us(); left_ms = waittime * 1000; - while ((read_len = wait_for_reply(from_lsa, to, &t2, &left_ms)) != 0) { + /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" + * with "where it came from" and "to which local address it arrived". + */ + while ((read_len = wait_for_reply(&t2, &left_ms)) != 0) { int icmp_code; /* Recv'ed a packet, or read error */ @@ -1154,22 +1140,22 @@ common_traceroute_main(int op, char **argv) if (read_len < 0) continue; - icmp_code = packet_ok(read_len, from_lsa, to, seq); + icmp_code = packet_ok(read_len, seq); /* Skip short packet */ if (icmp_code == 0) continue; if (!gotlastaddr - || (memcmp(lastaddr, &from_lsa->u.sa, from_lsa->len) != 0) + || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0) ) { - print(read_len, &from_lsa->u.sa, to); - memcpy(lastaddr, &from_lsa->u.sa, from_lsa->len); + print(read_len); + memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len); gotlastaddr = 1; } print_delta_ms(t1, t2); - if (from_lsa->u.sa.sa_family == AF_INET) { + if (G.from_lsa->u.sa.sa_family == AF_INET) { if (op & OPT_TTL_FLAG) { struct ip *ip = (struct ip *)recv_pkt; printf(" (%d)", ip->ip_ttl); @@ -1276,9 +1262,9 @@ common_traceroute_main(int op, char **argv) } if (ENABLE_FEATURE_CLEAN_UP) { - free(to); + free(G.to); free(lastaddr); - free(from_lsa); + free(G.from_lsa); } return 0; -- cgit v1.2.3-55-g6feb From cc55bbef75f0e1760bb881ab59775d26b93b3afe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Dec 2020 18:05:09 +0100 Subject: traceroute: code shrink Move init code to a separate function. function old new delta traceroute_init - 1203 +1203 common_traceroute_main 3391 2141 -1250 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 1203/-1250) Total: -47 bytes Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 70 ++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index 588570fcb..e6afdd8b9 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -394,8 +394,12 @@ struct globals { int packlen; /* total length of packet */ int pmtu; /* Path MTU Discovery (RFC1191) */ uint32_t ident; - uint16_t port; // 33434; /* start udp dest port # for probe packets */ - int waittime; // 5; /* time to wait for response (in seconds) */ + uint16_t port; /* start udp dest port # for probe packets */ + int waittime; /* time to wait for response (in seconds) */ + int first_ttl; + int nprobes; + unsigned pausemsecs; + int max_ttl; unsigned char recv_pkt[512]; /* last inbound (icmp) packet */ }; @@ -412,8 +416,6 @@ struct globals { #define gwlist (G.gwlist ) #define INIT_G() do { \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ - port = 33434; \ - waittime = 5; \ } while (0) #define outudp ((struct udphdr *)(outip + 1)) @@ -862,22 +864,16 @@ print_delta_ms(unsigned t1p, unsigned t2p) printf(" %u.%03u ms", tt / 1000, tt % 1000); } -/* - * Usage: [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl] - * [-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos] - * [-w waittime] [-z pausemsecs] host [packetlen]" +/* Keeping init code in a separate (not inlined!) function + * for stack use reduction and better register allocation in main loop. */ -static int -common_traceroute_main(int op, char **argv) +static NOINLINE void +traceroute_init(int op, char **argv) { int minpacket; #ifdef IP_TOS int tos = 0; #endif - int max_ttl = 30; - int nprobes = 3; - int first_ttl = 1; - unsigned pausemsecs = 0; char *source; char *device; char *tos_str; @@ -893,14 +889,16 @@ common_traceroute_main(int op, char **argv) #else enum { af = AF_INET }; #endif - int ttl; - int seq; - struct sockaddr *lastaddr; /* Ensure the socket fds won't be 0, 1 or 2 */ bb_sanitize_stdio(); INIT_G(); + port = 33434; + waittime = 5; + G.first_ttl = 1; + G.nprobes = 3; + G.max_ttl = 30; op |= getopt32(argv, "^" OPT_STRING @@ -919,17 +917,17 @@ common_traceroute_main(int op, char **argv) tos = xatou_range(tos_str, 0, 255); #endif if (op & OPT_MAX_TTL) - max_ttl = xatou_range(max_ttl_str, 1, 255); + G.max_ttl = xatou_range(max_ttl_str, 1, 255); if (op & OPT_PORT) port = xatou16(port_str); if (op & OPT_NPROBES) - nprobes = xatou_range(nprobes_str, 1, INT_MAX); + G.nprobes = xatou_range(nprobes_str, 1, INT_MAX); if (op & OPT_WAITTIME) waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); if (op & OPT_PAUSE_MS) - pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); + G.pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); if (op & OPT_FIRST_TTL) - first_ttl = xatou_range(first_ttl_str, 1, max_ttl); + G.first_ttl = xatou_range(first_ttl_str, 1, G.max_ttl); /* Process destination and optional packet size */ minpacket = sizeof(struct ip) @@ -961,6 +959,9 @@ common_traceroute_main(int op, char **argv) #else dest_lsa = xhost2sockaddr(argv[0], port); #endif + G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); + G.to = xzalloc(dest_lsa->len); + packlen = minpacket; if (argv[1]) packlen = xatoul_range(argv[1], minpacket, 32 * 1024); @@ -1102,20 +1103,28 @@ common_traceroute_main(int op, char **argv) if (op & OPT_SOURCE) printf(" from %s", source); - printf(", %d hops max, %d byte packets\n", max_ttl, packlen); + printf(", %d hops max, %d byte packets\n", G.max_ttl, packlen); +} + +static int +common_traceroute_main(int op, char **argv) +{ + int ttl; + int seq; + struct sockaddr *lastaddr; + + traceroute_init(op, argv); lastaddr = xzalloc(dest_lsa->len); - G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); - G.to = xzalloc(dest_lsa->len); seq = 0; - for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { + for (ttl = G.first_ttl; ttl <= G.max_ttl; ++ttl) { int probe; int unreachable = 0; /* counter */ int gotlastaddr = 0; /* flags */ int got_there = 0; printf("%2d", ttl); - for (probe = 0; probe < nprobes; ++probe) { + for (probe = 0; probe < G.nprobes; ++probe) { int read_len; unsigned t1; unsigned t2; @@ -1123,14 +1132,15 @@ common_traceroute_main(int op, char **argv) fflush_all(); if (probe != 0) - msleep(pausemsecs); + msleep(G.pausemsecs); send_probe(++seq, ttl); t2 = t1 = monotonic_us(); left_ms = waittime * 1000; - /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" - * with "where it came from" and "to which local address it arrived". + /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with + * "where it came from" and "what local address it arrived to" + * addresses. */ while ((read_len = wait_for_reply(&t2, &left_ms)) != 0) { int icmp_code; @@ -1255,7 +1265,7 @@ common_traceroute_main(int op, char **argv) bb_putchar('\n'); if (got_there - || (unreachable > 0 && unreachable >= nprobes - 1) + || (unreachable > 0 && unreachable >= G.nprobes - 1) ) { break; } -- cgit v1.2.3-55-g6feb From df5c5394b081d5b6a374a5025082c88fc05d0951 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Dec 2020 20:08:36 +0100 Subject: traceroute: set IP_PKTINFO to see correct local IP of received pkt (fixes -v display) Also, assorted code shrink: function old new delta traceroute_init 1210 1172 -38 common_traceroute_main 2141 2091 -50 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-88) Total: -88 bytes Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 105 +++++++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 64 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index e6afdd8b9..cf2b3cc64 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -413,7 +413,6 @@ struct globals { #define port (G.port ) #define waittime (G.waittime ) #define recv_pkt (G.recv_pkt ) -#define gwlist (G.gwlist ) #define INIT_G() do { \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ } while (0) @@ -683,12 +682,15 @@ packet4_ok(int read_len, int seq) int i; uint32_t *lp = (uint32_t *)&icp->icmp_ip; - printf("\n%d bytes from %s", - read_len, inet_ntoa(G.from_lsa->u.sin.sin_addr)); - /* Two separate printf() because inet_ntoa() returns static string */ - printf(" to %s: icmp type %d (%s) code %d\n", + printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n", + read_len, + /* inet_ntoa(G.from_lsa->u.sin.sin_addr) - two calls of inet_ntoa() + * are unsafe (use the same buffer), using this instead: + */ + auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), inet_ntoa(ip->ip_dst), - type, pr_type(type), icp->icmp_code); + type, pr_type(type), icp->icmp_code + ); for (i = 4; i < read_len; i += sizeof(*lp)) printf("%2d: x%8.8x\n", i, *lp++); } @@ -756,19 +758,16 @@ packet6_ok(int read_len, int seq) # if ENABLE_FEATURE_TRACEROUTE_VERBOSE if (verbose) { unsigned char *p; - char pa[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + 4]; int i; p = (unsigned char *) (icp + 1); - printf("\n%d bytes from %s", + printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n", read_len, - inet_ntop(AF_INET6, &G.from_lsa->u.sin6.sin6_addr, pa, sizeof(pa))); - /* Two printf() instead of one - reuse string constants */ - printf(" to %s: icmp type %d (%s) code %d\n", - inet_ntop(AF_INET6, &((struct sockaddr_in6*)G.to)->sin6_addr, pa, sizeof(pa)), - type, pr_type(type), icp->icmp6_code); - + auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), + auto_string(xmalloc_sockaddr2dotted_noport(G.to)), + type, pr_type(type), icp->icmp6_code + ); read_len -= sizeof(struct icmp6_hdr); for (i = 0; i < read_len; i++) { if (i % 16 == 0) @@ -796,55 +795,36 @@ packet_ok(int read_len, int seq) #else /* !ENABLE_TRACEROUTE6 */ -static ALWAYS_INLINE int -packet_ok(int read_len, int seq) -{ - return packet4_ok(read_len, seq); -} +# define packet_ok(read_len, seq) packet4_ok(read_len, seq) #endif -/* - * Construct an Internet address representation. - * If the -n flag has been supplied, give - * numeric value, otherwise try for symbolic name. - */ static void -print_inetname(const struct sockaddr *from) +print(int read_len) { - char *ina = xmalloc_sockaddr2dotted_noport(from); + char *ina = auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)); if (option_mask32 & OPT_ADDR_NUM) { printf(" %s", ina); } else { char *n = NULL; - - if (from->sa_family != AF_INET - || ((struct sockaddr_in*)from)->sin_addr.s_addr != INADDR_ANY + if (G.from_lsa->u.sa.sa_family != AF_INET + || G.from_lsa->u.sin.sin_addr.s_addr != INADDR_ANY ) { /* Try to reverse resolve if it is not 0.0.0.0 */ - n = xmalloc_sockaddr2host_noport((struct sockaddr*)from); + n = auto_string(xmalloc_sockaddr2host_noport(&G.from_lsa->u.sa)); } printf(" %s (%s)", (n ? n : ina), ina); - free(n); } - free(ina); -} - -static void -print(int read_len) -{ - print_inetname(&G.from_lsa->u.sa); if (verbose) { - char *ina = xmalloc_sockaddr2dotted_noport(G.to); #if ENABLE_TRACEROUTE6 /* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket * return the entire IP packet (IOW: they do not strip IP header). * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6 * header and return only ICMP6 packet. Weird. */ - if (G.to->sa_family == AF_INET6) { + if (G.from_lsa->u.sa.sa_family == AF_INET6) { /* read_len -= sizeof(struct ip6_hdr); - WRONG! */ } else #endif @@ -852,8 +832,9 @@ print(int read_len) struct ip *ip4packet = (struct ip*)recv_pkt; read_len -= ip4packet->ip_hl << 2; } - printf(" %d bytes to %s", read_len, ina); - free(ina); + printf(" %d bytes to %s", read_len, + auto_string(xmalloc_sockaddr2dotted_noport(G.to)) + ); } } @@ -870,10 +851,6 @@ print_delta_ms(unsigned t1p, unsigned t2p) static NOINLINE void traceroute_init(int op, char **argv) { - int minpacket; -#ifdef IP_TOS - int tos = 0; -#endif char *source; char *device; char *tos_str; @@ -911,10 +888,6 @@ traceroute_init(int op, char **argv) #if 0 /* IGNORED */ if (op & OPT_IP_CHKSUM) bb_error_msg("warning: ip checksums disabled"); -#endif -#ifdef IP_TOS - if (op & OPT_TOS) - tos = xatou_range(tos_str, 0, 255); #endif if (op & OPT_MAX_TTL) G.max_ttl = xatou_range(max_ttl_str, 1, 255); @@ -930,11 +903,11 @@ traceroute_init(int op, char **argv) G.first_ttl = xatou_range(first_ttl_str, 1, G.max_ttl); /* Process destination and optional packet size */ - minpacket = sizeof(struct ip) + packlen = sizeof(struct ip) + sizeof(struct udphdr) + sizeof(struct outdata_t); if (op & OPT_USE_ICMP) { - minpacket = sizeof(struct ip) + packlen = sizeof(struct ip) + SIZEOF_ICMP_HDR + sizeof(struct outdata_t); port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */ @@ -948,11 +921,11 @@ traceroute_init(int op, char **argv) dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); af = dest_lsa->u.sa.sa_family; if (af == AF_INET6) { - minpacket = sizeof(struct ip6_hdr) + packlen = sizeof(struct ip6_hdr) + sizeof(struct udphdr) + sizeof(struct outdata6_t); if (op & OPT_USE_ICMP) - minpacket = sizeof(struct ip6_hdr) + packlen = sizeof(struct ip6_hdr) + SIZEOF_ICMP_HDR + sizeof(struct outdata6_t); } @@ -961,19 +934,20 @@ traceroute_init(int op, char **argv) #endif G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); G.to = xzalloc(dest_lsa->len); - - packlen = minpacket; if (argv[1]) - packlen = xatoul_range(argv[1], minpacket, 32 * 1024); + packlen = xatoul_range(argv[1], packlen, 32 * 1024); #if ENABLE_TRACEROUTE6 if (af == AF_INET6) { xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); - setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); //why? + /* want recvmsg to report target local address (for -v) */ + setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); } else #endif { xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock); + /* want recvmsg to report target local address (for -v) */ + setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO); } #if TRACEROUTE_SO_DEBUG @@ -1010,8 +984,10 @@ traceroute_init(int op, char **argv) } #endif #ifdef IP_TOS - if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) { - bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos); + if (op & OPT_TOS) { + int tos = xatou_range(tos_str, 0, 255); + if (setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) + bb_perror_msg_and_die("setsockopt(%s,%d)", "TOS", tos); } #endif #ifdef IP_DONTFRAG @@ -1070,7 +1046,8 @@ traceroute_init(int op, char **argv) //TODO: we can query source port we bound to, // and check it in replies... if we care enough xbind(sndsock, &source_lsa->u.sa, source_lsa->len); - free(source_lsa); + if (ENABLE_FEATURE_CLEAN_UP) + free(source_lsa); } #if ENABLE_TRACEROUTE6 else if (af == AF_INET6) { @@ -1087,7 +1064,8 @@ traceroute_init(int op, char **argv) /* bind our recv socket to this IP (but not port) */ set_nport(&source_lsa->u.sa, 0); xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); - free(source_lsa); + if (ENABLE_FEATURE_CLEAN_UP) + free(source_lsa); } #endif @@ -1097,9 +1075,8 @@ traceroute_init(int op, char **argv) dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa); printf("traceroute to %s (%s)", argv[0], dest_str); - if (ENABLE_FEATURE_CLEAN_UP) { + if (ENABLE_FEATURE_CLEAN_UP) free(dest_str); - } if (op & OPT_SOURCE) printf(" from %s", source); -- cgit v1.2.3-55-g6feb From e76f03b267aed3c7c9a247ef4b27e1bb1c56e024 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Dec 2020 21:09:21 +0100 Subject: traceroute: commonalize verbose printing function old new delta hexdump - 274 +274 traceroute_init 1172 1147 -25 pr_type 79 - -79 common_traceroute_main 2091 1785 -306 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/2 up/down: 274/-410) Total: -136 bytes Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 145 +++++++++++++++++++++--------------------------- 1 file changed, 62 insertions(+), 83 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index cf2b3cc64..0fb01ff5b 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -358,7 +358,11 @@ enum { OPT_IPV4 = (1 << 17), /* 4 */ OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */ }; -#define verbose (option_mask32 & OPT_VERBOSE) +#if ENABLE_FEATURE_TRACEROUTE_VERBOSE +# define verbose (option_mask32 & OPT_VERBOSE) +#else +# define verbose 0 +#endif enum { SIZEOF_ICMP_HDR = 8, @@ -559,9 +563,7 @@ send_probe(int seq, int ttl) } #if ENABLE_FEATURE_TRACEROUTE_VERBOSE -/* - * Convert an ICMP "type" field to a printable string. - */ +/* Convert an ICMP "type" field to a printable string */ static const char * pr_type(unsigned char t) { @@ -594,12 +596,35 @@ pr_type(unsigned char t) return ttab[t]; } +static void +hexdump(const struct icmp *icp, int len) +{ + const unsigned char *p; + int i; + + printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n", + len, + auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), + auto_string(xmalloc_sockaddr2dotted_noport(G.to)), + icp->icmp_type, pr_type(icp->icmp_type), + icp->icmp_code + ); + p = (const void *)icp; + for (i = 0; i < len; i++) { + if (i % 16 == 0) + printf("%04x:", i); + if (i % 4 == 0) + bb_putchar(' '); + printf("%02x", p[i]); + if ((i % 16 == 15) && (i + 1 < len)) + bb_putchar('\n'); + } + bb_putchar('\n'); +} +#else +# define hexdump(...) ((void)0) #endif -#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE -#define packet4_ok(read_len, from, seq) \ - packet4_ok(read_len, seq) -#endif static int packet4_ok(int read_len, int seq) { @@ -616,11 +641,9 @@ packet4_ok(int read_len, int seq) hlen = ip->ip_hl << 2; if (read_len < hlen + ICMP_MINLEN) { -#if ENABLE_FEATURE_TRACEROUTE_VERBOSE if (verbose) printf("packet too short (%d bytes) from %s\n", read_len, inet_ntoa(G.from_lsa->u.sin.sin_addr)); -#endif return 0; } read_len -= hlen; @@ -677,24 +700,8 @@ packet4_ok(int read_len, int seq) } } } -#if ENABLE_FEATURE_TRACEROUTE_VERBOSE - if (verbose) { - int i; - uint32_t *lp = (uint32_t *)&icp->icmp_ip; - - printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n", - read_len, - /* inet_ntoa(G.from_lsa->u.sin.sin_addr) - two calls of inet_ntoa() - * are unsafe (use the same buffer), using this instead: - */ - auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), - inet_ntoa(ip->ip_dst), - type, pr_type(type), icp->icmp_code - ); - for (i = 4; i < read_len; i += sizeof(*lp)) - printf("%2d: x%8.8x\n", i, *lp++); - } -#endif + if (verbose) + hexdump(icp, read_len); return 0; } @@ -754,34 +761,9 @@ packet6_ok(int read_len, int seq) } } } - -# if ENABLE_FEATURE_TRACEROUTE_VERBOSE - if (verbose) { - unsigned char *p; - int i; - - p = (unsigned char *) (icp + 1); - - printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n", - read_len, - auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), - auto_string(xmalloc_sockaddr2dotted_noport(G.to)), - type, pr_type(type), icp->icmp6_code - ); - read_len -= sizeof(struct icmp6_hdr); - for (i = 0; i < read_len; i++) { - if (i % 16 == 0) - printf("%04x:", i); - if (i % 4 == 0) - bb_putchar(' '); - printf("%02x", p[i]); - if ((i % 16 == 15) && (i + 1 < read_len)) - bb_putchar('\n'); - } - bb_putchar('\n'); - } -# endif - + if (verbose) + /* cast is safe since the beginning of icmp4 and icmp6 layouts match */ + hexdump((const struct icmp *)icp, read_len); return 0; } @@ -910,7 +892,7 @@ traceroute_init(int op, char **argv) packlen = sizeof(struct ip) + SIZEOF_ICMP_HDR + sizeof(struct outdata_t); - port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */ + port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL! */ } #if ENABLE_TRACEROUTE6 af = AF_UNSPEC; @@ -932,23 +914,24 @@ traceroute_init(int op, char **argv) #else dest_lsa = xhost2sockaddr(argv[0], port); #endif +//TODO: make sure af == AF_INET[6]? (FEATURE_UNIX_LOCAL=y allows "local:/PATH" to be translated to AF_UNIX) G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); G.to = xzalloc(dest_lsa->len); if (argv[1]) packlen = xatoul_range(argv[1], packlen, 32 * 1024); + if (af == AF_INET) { + xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock); + /* want recvmsg to report target local address (for -v) */ + setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO); + } #if ENABLE_TRACEROUTE6 - if (af == AF_INET6) { + else { xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); /* want recvmsg to report target local address (for -v) */ setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); - } else -#endif - { - xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock); - /* want recvmsg to report target local address (for -v) */ - setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO); } +#endif #if TRACEROUTE_SO_DEBUG if (op & OPT_DEBUG) @@ -959,22 +942,22 @@ traceroute_init(int op, char **argv) { int snd; + if (af == AF_INET) { + if (op & OPT_USE_ICMP) + snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + else + snd = xsocket(AF_INET, SOCK_DGRAM, 0); + } #if ENABLE_TRACEROUTE6 - if (af == AF_INET6) { + else { if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); if (op & OPT_USE_ICMP) snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); else snd = xsocket(AF_INET6, SOCK_DGRAM, 0); - } else -#endif - { - if (op & OPT_USE_ICMP) - snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); - else - snd = xsocket(AF_INET, SOCK_DGRAM, 0); } +#endif xmove_fd(snd, sndsock); } @@ -1006,7 +989,7 @@ traceroute_init(int op, char **argv) ident = getpid(); outdata = (void*)(outudp + 1); - if (!ENABLE_TRACEROUTE6 || af == AF_INET) { + if (af == AF_INET) { if (op & OPT_USE_ICMP) { outicmp->icmp_type = ICMP_ECHO; /*outicmp->icmp_code = 0; - set by xzalloc */ @@ -1015,7 +998,7 @@ traceroute_init(int op, char **argv) } } #if ENABLE_TRACEROUTE6 - if (af == AF_INET6) { + else { outdata = (void*)(outudp6 + 1); if (op & OPT_USE_ICMP) { outicmp6->icmp_type = ICMP6_ECHO_REQUEST; @@ -1048,26 +1031,22 @@ traceroute_init(int op, char **argv) xbind(sndsock, &source_lsa->u.sa, source_lsa->len); if (ENABLE_FEATURE_CLEAN_UP) free(source_lsa); - } -#if ENABLE_TRACEROUTE6 - else if (af == AF_INET6) { -//TODO: why we don't do it for IPv4? + } else { len_and_sockaddr *source_lsa; set_nport(&dest_lsa->u.sa, htons(port)); - /* Connect makes kernel pick source IP and port */ + /* Connect makes kernel pick source IP (and port if UDP) */ xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len); /* Read IP and port */ source_lsa = get_sock_lsa(sndsock); if (source_lsa == NULL) - bb_simple_error_msg_and_die("can't get probe addr"); - /* bind our recv socket to this IP (but not port) */ - set_nport(&source_lsa->u.sa, 0); + bb_simple_perror_msg_and_die("getsockname"); + /* bind our recv ICMP socket to this IP (but not port, ICMP has no ports) */ + //set_nport(&source_lsa->u.sa, 0); - paranoia, seems to work without this for both ipv4 and ipv6 xbind(rcvsock, &source_lsa->u.sa, source_lsa->len); if (ENABLE_FEATURE_CLEAN_UP) free(source_lsa); } -#endif /* Revert to non-privileged user after opening sockets */ xsetgid(getgid()); -- cgit v1.2.3-55-g6feb From 724c7df683b8f3d0c487ce3d3cdcc1f6e762c181 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 12 Dec 2020 21:44:32 +0100 Subject: traceroute: untangle main loop function old new delta common_traceroute_main 1785 1730 -55 Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 218 +++++++++++++++++++++++------------------------- 1 file changed, 106 insertions(+), 112 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index 0fb01ff5b..1e96a73cf 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -463,6 +463,8 @@ wait_for_reply(unsigned *timestamp_us, int *left_ms) recv_pkt, sizeof(recv_pkt), /*flags:*/ MSG_DONTWAIT, &G.from_lsa->u.sa, G.to, G.from_lsa->len); + if (read_len < 0) + bb_perror_msg_and_die("recv"); t = monotonic_us(); *left_ms -= (t - *timestamp_us) / 1000; *timestamp_us = t; @@ -1076,147 +1078,139 @@ common_traceroute_main(int op, char **argv) for (ttl = G.first_ttl; ttl <= G.max_ttl; ++ttl) { int probe; int unreachable = 0; /* counter */ - int gotlastaddr = 0; /* flags */ int got_there = 0; printf("%2d", ttl); for (probe = 0; probe < G.nprobes; ++probe) { - int read_len; unsigned t1; unsigned t2; int left_ms; + int read_len; + int icmp_code; fflush_all(); if (probe != 0) msleep(G.pausemsecs); send_probe(++seq, ttl); - t2 = t1 = monotonic_us(); + t2 = t1 = monotonic_us(); left_ms = waittime * 1000; - /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with - * "where it came from" and "what local address it arrived to" - * addresses. - */ - while ((read_len = wait_for_reply(&t2, &left_ms)) != 0) { - int icmp_code; - - /* Recv'ed a packet, or read error */ - /* t2 = monotonic_us() - set by wait_for_reply */ - - if (read_len < 0) - continue; - icmp_code = packet_ok(read_len, seq); - /* Skip short packet */ - if (icmp_code == 0) - continue; - - if (!gotlastaddr - || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0) - ) { - print(read_len); - memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len); - gotlastaddr = 1; + for (;;) { + /* NB: wait_for_reply() fills "G.from_lsa" and "G.to" with + * "where it came from" and "what local address it arrived to" + * addresses. Sets t2 = monotonic_us(), updates left_ms. + */ + read_len = wait_for_reply(&t2, &left_ms); + + if (read_len == 0) { /* there was no packet at all? */ + printf(" *"); + goto next_probe; } + icmp_code = packet_ok(read_len, seq); + if (icmp_code != 0) + break; /* got a good response */ + /* unrecognized type/code or too short, back to recv */ + } - print_delta_ms(t1, t2); - - if (G.from_lsa->u.sa.sa_family == AF_INET) { - if (op & OPT_TTL_FLAG) { - struct ip *ip = (struct ip *)recv_pkt; - printf(" (%d)", ip->ip_ttl); - } + if (probe == 0 + || (memcmp(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len) != 0) + ) { + print(read_len); + memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len); + } + print_delta_ms(t1, t2); + if (G.from_lsa->u.sa.sa_family == AF_INET) { + if (op & OPT_TTL_FLAG) { + struct ip *ip = (struct ip *)recv_pkt; + printf(" (%d)", ip->ip_ttl); } + } - /* Got a "time exceeded in transit" icmp message? */ - if (icmp_code == -1) - break; + /* Got a "time exceeded in transit" icmp message? */ + if (icmp_code == -1) + continue; - icmp_code--; - switch (icmp_code) { + icmp_code--; + switch (icmp_code) { #if ENABLE_TRACEROUTE6 - case ICMP6_DST_UNREACH_NOPORT << 8: - got_there = 1; - break; + case ICMP6_DST_UNREACH_NOPORT << 8: + got_there = 1; + break; #endif - case ICMP_UNREACH_PORT: { - struct ip *ip = (struct ip *)recv_pkt; - if (ip->ip_ttl <= 1) - printf(" !"); - got_there = 1; - break; - } - case ICMP_UNREACH_NET: + case ICMP_UNREACH_PORT: { + struct ip *ip = (struct ip *)recv_pkt; + if (ip->ip_ttl <= 1) + printf(" !"); + got_there = 1; + break; + } + case ICMP_UNREACH_NET: #if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET) - case ICMP6_DST_UNREACH_NOROUTE << 8: + case ICMP6_DST_UNREACH_NOROUTE << 8: #endif - printf(" !N"); - ++unreachable; - break; - case ICMP_UNREACH_HOST: + printf(" !N"); + ++unreachable; + break; + case ICMP_UNREACH_HOST: #if ENABLE_TRACEROUTE6 - case ICMP6_DST_UNREACH_ADDR << 8: + case ICMP6_DST_UNREACH_ADDR << 8: #endif - printf(" !H"); - ++unreachable; - break; - case ICMP_UNREACH_PROTOCOL: - printf(" !P"); - got_there = 1; - break; - case ICMP_UNREACH_NEEDFRAG: - printf(" !F-%d", pmtu); - ++unreachable; - break; - case ICMP_UNREACH_SRCFAIL: + printf(" !H"); + ++unreachable; + break; + case ICMP_UNREACH_PROTOCOL: + printf(" !P"); + got_there = 1; + break; + case ICMP_UNREACH_NEEDFRAG: + printf(" !F-%d", pmtu); + ++unreachable; + break; + case ICMP_UNREACH_SRCFAIL: #if ENABLE_TRACEROUTE6 - case ICMP6_DST_UNREACH_ADMIN << 8: + case ICMP6_DST_UNREACH_ADMIN << 8: #endif - printf(" !S"); - ++unreachable; - break; - case ICMP_UNREACH_FILTER_PROHIB: - case ICMP_UNREACH_NET_PROHIB: /* misuse */ - printf(" !A"); - ++unreachable; - break; - case ICMP_UNREACH_HOST_PROHIB: - printf(" !C"); - ++unreachable; - break; - case ICMP_UNREACH_HOST_PRECEDENCE: - printf(" !V"); - ++unreachable; - break; - case ICMP_UNREACH_PRECEDENCE_CUTOFF: - printf(" !C"); - ++unreachable; - break; - case ICMP_UNREACH_NET_UNKNOWN: - case ICMP_UNREACH_HOST_UNKNOWN: - printf(" !U"); - ++unreachable; - break; - case ICMP_UNREACH_ISOLATED: - printf(" !I"); - ++unreachable; - break; - case ICMP_UNREACH_TOSNET: - case ICMP_UNREACH_TOSHOST: - printf(" !T"); - ++unreachable; - break; - default: - printf(" !<%d>", icmp_code); - ++unreachable; - break; - } + printf(" !S"); + ++unreachable; break; - } /* while (wait and read a packet) */ - - /* there was no packet at all? */ - if (read_len == 0) - printf(" *"); + case ICMP_UNREACH_FILTER_PROHIB: + case ICMP_UNREACH_NET_PROHIB: /* misuse */ + printf(" !A"); + ++unreachable; + break; + case ICMP_UNREACH_HOST_PROHIB: + printf(" !C"); + ++unreachable; + break; + case ICMP_UNREACH_HOST_PRECEDENCE: + printf(" !V"); + ++unreachable; + break; + case ICMP_UNREACH_PRECEDENCE_CUTOFF: + printf(" !C"); + ++unreachable; + break; + case ICMP_UNREACH_NET_UNKNOWN: + case ICMP_UNREACH_HOST_UNKNOWN: + printf(" !U"); + ++unreachable; + break; + case ICMP_UNREACH_ISOLATED: + printf(" !I"); + ++unreachable; + break; + case ICMP_UNREACH_TOSNET: + case ICMP_UNREACH_TOSHOST: + printf(" !T"); + ++unreachable; + break; + default: + printf(" !<%d>", icmp_code); + ++unreachable; + break; + } + next_probe: ; } /* for (nprobes) */ bb_putchar('\n'); -- cgit v1.2.3-55-g6feb From 80551731288a6abf9657e07e82d55a23bc5a970e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 14:18:05 +0100 Subject: traceroute: don't set SO_DONTROUTE on recv socket, it only affects send function old new delta traceroute_init 1147 1131 -16 Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index 1e96a73cf..8e13238bf 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -934,13 +934,10 @@ traceroute_init(int op, char **argv) setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); } #endif - #if TRACEROUTE_SO_DEBUG if (op & OPT_DEBUG) setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG); #endif - if (op & OPT_BYPASS_ROUTE) - setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE); { int snd; -- cgit v1.2.3-55-g6feb From b4b182807687a872c49a89b840754a553c00f8a1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 14:58:11 +0100 Subject: traceroute: make "ipv4 or ipv6?" cheaper to find out function old new delta traceroute_init 1131 1135 +4 hexdump 274 270 -4 common_traceroute_main 1730 1715 -15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 4/-19) Total: -15 bytes Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index 8e13238bf..4d0ebc3b7 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -324,7 +324,6 @@ #ifndef IPPROTO_IP # define IPPROTO_IP 0 #endif - /* Some operating systems, like GNU/Hurd, don't define SOL_RAW, but do have * IPPROTO_RAW. Since the IPPROTO definitions are also valid to use for * setsockopt (and take the same value as their corresponding SOL definitions, @@ -391,19 +390,24 @@ struct globals { struct ip *outip; /* Pointer to ICMP or UDP payload (not header): */ struct outdata_t *outdata; - len_and_sockaddr *dest_lsa; len_and_sockaddr *from_lsa; /* response came from this address */ struct sockaddr *to; /* response came to this (local) address */ - int packlen; /* total length of packet */ - int pmtu; /* Path MTU Discovery (RFC1191) */ uint32_t ident; uint16_t port; /* start udp dest port # for probe packets */ +#if ENABLE_TRACEROUTE6 + smallint ipv6; +# define G_ipv6 G.ipv6 +#else +# define G_ipv6 0 +#endif + int packlen; /* total length of packet */ + int pmtu; /* Path MTU Discovery (RFC1191) */ int waittime; /* time to wait for response (in seconds) */ int first_ttl; int nprobes; - unsigned pausemsecs; int max_ttl; + unsigned pausemsecs; unsigned char recv_pkt[512]; /* last inbound (icmp) packet */ }; @@ -482,7 +486,7 @@ send_probe(int seq, int ttl) /* Payload */ #if ENABLE_TRACEROUTE6 - if (dest_lsa->u.sa.sa_family == AF_INET6) { + if (G_ipv6) { struct outdata6_t *pkt = (void *) outdata; pkt->ident6 = ident; pkt->seq6 = htonl(seq); @@ -541,7 +545,7 @@ send_probe(int seq, int ttl) #endif #if ENABLE_TRACEROUTE6 - if (dest_lsa->u.sa.sa_family == AF_INET6) { + if (G_ipv6) { res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); if (res != 0) bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); @@ -585,7 +589,7 @@ pr_type(unsigned char t) [16] = "Neighbor Advert", "Redirect", }; - if (dest_lsa->u.sa.sa_family == AF_INET6) { + if (G_ipv6) { if (t < 5) return ttab6[t]; if (t < 128 || t > ND_REDIRECT) @@ -772,7 +776,7 @@ packet6_ok(int read_len, int seq) static int packet_ok(int read_len, int seq) { - if (G.from_lsa->u.sa.sa_family == AF_INET) + if (!G_ipv6) return packet4_ok(read_len, seq); return packet6_ok(read_len, seq); } @@ -792,10 +796,10 @@ print(int read_len) printf(" %s", ina); } else { char *n = NULL; - if (G.from_lsa->u.sa.sa_family != AF_INET + if (G_ipv6 || G.from_lsa->u.sin.sin_addr.s_addr != INADDR_ANY ) { - /* Try to reverse resolve if it is not 0.0.0.0 */ + /* Reverse resolve if IPV6 or not 0.0.0.0 */ n = auto_string(xmalloc_sockaddr2host_noport(&G.from_lsa->u.sa)); } printf(" %s (%s)", (n ? n : ina), ina); @@ -808,7 +812,7 @@ print(int read_len) * Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6 * header and return only ICMP6 packet. Weird. */ - if (G.from_lsa->u.sa.sa_family == AF_INET6) { + if (G_ipv6) { /* read_len -= sizeof(struct ip6_hdr); - WRONG! */ } else #endif @@ -904,7 +908,9 @@ traceroute_init(int op, char **argv) af = AF_INET6; dest_lsa = xhost_and_af2sockaddr(argv[0], port, af); af = dest_lsa->u.sa.sa_family; +//TODO: make sure af == AF_INET[6]? (FEATURE_UNIX_LOCAL=y allows "local:/PATH" to be translated to AF_UNIX) if (af == AF_INET6) { + G_ipv6 = 1; packlen = sizeof(struct ip6_hdr) + sizeof(struct udphdr) + sizeof(struct outdata6_t); @@ -914,9 +920,9 @@ traceroute_init(int op, char **argv) + sizeof(struct outdata6_t); } #else - dest_lsa = xhost2sockaddr(argv[0], port); + /* accept only IPv4 addresses */ + dest_lsa = xhost_and_af2sockaddr(argv[0], port, AF_INET); #endif -//TODO: make sure af == AF_INET[6]? (FEATURE_UNIX_LOCAL=y allows "local:/PATH" to be translated to AF_UNIX) G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); G.to = xzalloc(dest_lsa->len); if (argv[1]) @@ -1117,7 +1123,7 @@ common_traceroute_main(int op, char **argv) memcpy(lastaddr, &G.from_lsa->u.sa, G.from_lsa->len); } print_delta_ms(t1, t2); - if (G.from_lsa->u.sa.sa_family == AF_INET) { + if (!G_ipv6) { if (op & OPT_TTL_FLAG) { struct ip *ip = (struct ip *)recv_pkt; printf(" (%d)", ip->ip_ttl); -- cgit v1.2.3-55-g6feb From d067acb0052c20edbfe7f13c99b8947ce8911eb7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 15:10:07 +0100 Subject: traceroute: simpler hexdump() function old new delta hexdump 270 239 -31 Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index 4d0ebc3b7..8ab4caefe 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -608,7 +608,7 @@ hexdump(const struct icmp *icp, int len) const unsigned char *p; int i; - printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n", + printf("\n%d bytes from %s to %s: icmp type %u (%s) code %u\n", len, auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), auto_string(xmalloc_sockaddr2dotted_noport(G.to)), @@ -617,13 +617,9 @@ hexdump(const struct icmp *icp, int len) ); p = (const void *)icp; for (i = 0; i < len; i++) { - if (i % 16 == 0) - printf("%04x:", i); - if (i % 4 == 0) - bb_putchar(' '); - printf("%02x", p[i]); - if ((i % 16 == 15) && (i + 1 < len)) - bb_putchar('\n'); + if (!(i & 0xf)) + printf("\n%04x:" + (i==0), i); + printf(" %02x", p[i]); } bb_putchar('\n'); } @@ -706,7 +702,7 @@ packet4_ok(int read_len, int seq) } } } - if (verbose) + if (verbose) /* testcase: traceroute -vI 127.0.0.1 (sees its own echo requests) */ hexdump(icp, read_len); return 0; } -- cgit v1.2.3-55-g6feb From 623e55a396597be7d6f3be332f28c2f0e3b09a1d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 15:53:06 +0100 Subject: traceroute: even with -v, don't show other ping processes reply's function old new delta traceroute_init 1135 1151 +16 common_ping_main 1919 1935 +16 common_traceroute_main 1715 1668 -47 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 32/-47) Total: -15 bytes Signed-off-by: Denys Vlasenko --- networking/ping.c | 10 ++++++++++ networking/traceroute.c | 13 +++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/networking/ping.c b/networking/ping.c index 5f7e5b9b5..318d561bb 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -332,6 +332,11 @@ static int common_ping_main(sa_family_t af, char **argv) create_icmp_socket(lsa); G.myid = (uint16_t) getpid(); + /* we can use native-endian ident, but other Unix ping/traceroute + * utils use *big-endian pid*, and e.g. traceroute on our machine may be + * *not* from busybox, idents may collide. Follow the convention: + */ + G.myid = htons(G.myid); #if ENABLE_PING6 if (lsa->u.sa.sa_family == AF_INET6) ping6(lsa); @@ -927,6 +932,11 @@ static int common_ping_main(int opt, char **argv) G.interval_us = interval * 1000000; myid = (uint16_t) getpid(); + /* we can use native-endian ident, but other Unix ping/traceroute + * utils use *big-endian pid*, and e.g. traceroute on our machine may be + * *not* from busybox, idents may collide. Follow the convention: + */ + myid = htons(myid); hostname = argv[optind]; #if ENABLE_PING6 { diff --git a/networking/traceroute.c b/networking/traceroute.c index 8ab4caefe..c1eb2d92e 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -659,9 +659,11 @@ packet4_ok(int read_len, int seq) if ((option_mask32 & OPT_USE_ICMP) && type == ICMP_ECHOREPLY - && icp->icmp_id == ident && icp->icmp_seq == htons(seq) ) { + if (icp->icmp_id != ident) + /* reply to another ping/traceroute from this box? */ + return 0; /* ignore, silently */ /* In UDP mode, when we reach the machine, we (usually) * would get "port unreachable" - in ICMP we got "echo reply". * Simulate "port unreachable" for caller: @@ -726,9 +728,11 @@ packet6_ok(int read_len, int seq) if ((option_mask32 & OPT_USE_ICMP) && type == ICMP6_ECHO_REPLY - && icp->icmp6_id == ident && icp->icmp6_seq == htons(seq) ) { + if (icp->icmp6_id != ident) + /* reply to another ping/traceroute from this box? */ + return 0; /* ignore, silently */ /* In UDP mode, when we reach the machine, we (usually) * would get "port unreachable" - in ICMP we got "echo reply". * Simulate "port unreachable" for caller: @@ -988,6 +992,11 @@ traceroute_init(int op, char **argv) outip = xzalloc(packlen); ident = getpid(); + /* we can use native-endian ident, but other Unix ping/traceroute + * utils use *big-endian pid*, and e.g. ping on our machine may be + * *not* from busybox, idents may collide. Follow the convention: + */ + ident = htons(ident); outdata = (void*)(outudp + 1); if (af == AF_INET) { -- cgit v1.2.3-55-g6feb From 6c5f4296dca1d836695d3ec77e7429bd40ca5ce3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 15:58:47 +0100 Subject: traceroute: code shrink function old new delta hexdump_if_verbose - 255 +255 common_traceroute_main 1668 1644 -24 hexdump 239 - -239 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/1 up/down: 255/-263) Total: -8 bytes Signed-off-by: Denys Vlasenko --- networking/traceroute.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/networking/traceroute.c b/networking/traceroute.c index c1eb2d92e..2f4d6bb43 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -602,12 +602,15 @@ pr_type(unsigned char t) return ttab[t]; } -static void -hexdump(const struct icmp *icp, int len) +static int +hexdump_if_verbose(const struct icmp *icp, int len) { const unsigned char *p; int i; + if (!verbose) + return 0; + printf("\n%d bytes from %s to %s: icmp type %u (%s) code %u\n", len, auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)), @@ -622,9 +625,10 @@ hexdump(const struct icmp *icp, int len) printf(" %02x", p[i]); } bb_putchar('\n'); + return 0; } #else -# define hexdump(...) ((void)0) +# define hexdump_if_verbose(...) 0 #endif static int @@ -704,9 +708,8 @@ packet4_ok(int read_len, int seq) } } } - if (verbose) /* testcase: traceroute -vI 127.0.0.1 (sees its own echo requests) */ - hexdump(icp, read_len); - return 0; + /* testcase: traceroute -vI 127.0.0.1 (sees its own echo requests) */ + return hexdump_if_verbose(icp, read_len); } #if ENABLE_TRACEROUTE6 @@ -767,10 +770,8 @@ packet6_ok(int read_len, int seq) } } } - if (verbose) - /* cast is safe since the beginning of icmp4 and icmp6 layouts match */ - hexdump((const struct icmp *)icp, read_len); - return 0; + /* cast is safe since the beginning of icmp4 and icmp6 layouts match */ + return hexdump_if_verbose((const struct icmp *)icp, read_len); } static int -- cgit v1.2.3-55-g6feb From 31df5a3eee74862312bbf89449d223aeae13aaf7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 16:36:28 +0100 Subject: ash: reset SIGHUP earlier: allows HUP traps in .profile, closes 13371 function old new delta ash_main 1188 1203 +15 Signed-off-by: Denys Vlasenko --- shell/ash.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 40695dee0..b271dd031 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -14340,6 +14340,17 @@ procargs(char **argv) shellparam.nparam++; xargv++; } + + /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry. + * Try: + * trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect + * trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed + * NB: must do it before setting up signals (in optschanged()) + * and reading .profile etc (after we return from here): + */ + if (iflag) + signal(SIGHUP, SIG_DFL); + optschanged(); return login_sh; @@ -14510,14 +14521,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } #endif state4: /* XXX ??? - why isn't this before the "if" statement */ - - /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry. - * Try: - * trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect - * trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed - */ - signal(SIGHUP, SIG_DFL); - cmdloop(1); } #if PROFILE -- cgit v1.2.3-55-g6feb From 9cabd17e555db8f1a48e1cd5db0a8a7a947bced9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 18:24:11 +0100 Subject: hush: fix -c SCRIPT handling function old new delta hush_main 1763 1759 -4 Signed-off-by: Denys Vlasenko --- shell/hush.c | 114 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 63 insertions(+), 51 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index b6d9d7abb..219158f18 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -10096,6 +10096,19 @@ int hush_main(int argc, char **argv) * PS4='+ ' */ +#if NUM_SCRIPTS > 0 + if (argc < 0) { + char *script = get_script_content(-argc - 1); + G.global_argv = argv; + G.global_argc = string_array_len(argv); + G.root_pid = getpid(); + G.root_ppid = getppid(); + //install_special_sighandlers(); - needed? + parse_and_run_string(script); + goto final_return; + } +#endif + /* Initialize some more globals to non-zero values */ die_func = restore_ttypgrp_and__exit; @@ -10110,16 +10123,8 @@ int hush_main(int argc, char **argv) /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0; builtin_argc = 0; -#if NUM_SCRIPTS > 0 - if (argc < 0) { - optarg = get_script_content(-argc - 1); - optind = 0; - argc = string_array_len(argv); - goto run_script; - } -#endif while (1) { - int opt = getopt(argc, argv, "+c:exinsl" + int opt = getopt(argc, argv, "+cexinsl" #if !BB_MMU "<:$:R:V:" # if ENABLE_HUSH_FUNCTIONS @@ -10131,50 +10136,11 @@ int hush_main(int argc, char **argv) break; switch (opt) { case 'c': - /* Possibilities: - * sh ... -c 'script' - * sh ... -c 'script' ARG0 [ARG1...] - * On NOMMU, if builtin_argc != 0, - * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...] - * "" needs to be replaced with NULL - * and BARGV vector fed to builtin function. - * Note: the form without ARG0 never happens: - * sh ... -c 'builtin' BARGV... "" + /* Note: -c is not a param with option! + * "hush -c -l SCRIPT" is valid. "hush -cSCRIPT" is not. */ -#if NUM_SCRIPTS > 0 - run_script: -#endif - if (!G.root_pid) { - G.root_pid = getpid(); - G.root_ppid = getppid(); - } - G.global_argv = argv + optind; - G.global_argc = argc - optind; - if (builtin_argc) { - /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */ - const struct built_in_command *x; - - install_special_sighandlers(); - x = find_builtin(optarg); - if (x) { /* paranoia */ - G.global_argc -= builtin_argc; /* skip [BARGV...] "" */ - G.global_argv += builtin_argc; - G.global_argv[-1] = NULL; /* replace "" */ - fflush_all(); - G.last_exitcode = x->b_function(argv + optind - 1); - } - goto final_return; - } G.opt_c = 1; - if (!G.global_argv[0]) { - /* -c 'script' (no params): prevent empty $0 */ - G.global_argv--; /* points to argv[i] of 'script' */ - G.global_argv[0] = argv[0]; - G.global_argc++; - } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */ - install_special_sighandlers(); - parse_and_run_string(optarg); - goto final_return; + break; case 'i': /* Well, we cannot just declare interactiveness, * we have to have some stuff (ctty, etc) */ @@ -10290,6 +10256,52 @@ int hush_main(int argc, char **argv) */ } + /* -c takes effect *after* -l */ + if (G.opt_c) { + /* Possibilities: + * sh ... -c 'script' + * sh ... -c 'script' ARG0 [ARG1...] + * On NOMMU, if builtin_argc != 0, + * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...] + * "" needs to be replaced with NULL + * and BARGV vector fed to builtin function. + * Note: the form without ARG0 never happens: + * sh ... -c 'builtin' BARGV... "" + */ + char *script; + + install_special_sighandlers(); + + G.global_argc--; + G.global_argv++; + if (builtin_argc) { + /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */ + const struct built_in_command *x; + x = find_builtin(G.global_argv[0]); + if (x) { /* paranoia */ + argv = G.global_argv; + G.global_argc -= builtin_argc + 1; /* skip [BARGV...] "" */ + G.global_argv += builtin_argc + 1; + G.global_argv[-1] = NULL; /* replace "" */ + G.last_exitcode = x->b_function(argv); + } + goto final_return; + } + + script = G.global_argv[0]; + if (!script) + bb_error_msg_and_die(bb_msg_requires_arg, "-c"); + if (!G.global_argv[1]) { + /* -c 'script' (no params): prevent empty $0 */ + G.global_argv[0] = argv[0]; + } else { /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */ + G.global_argc--; + G.global_argv++; + } + parse_and_run_string(script); + goto final_return; + } + /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */ if (!G.opt_s && G.global_argv[1]) { HFILE *input; -- cgit v1.2.3-55-g6feb From 49142d48bd12c87d52e1316050f5cf4749e64e51 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 18:44:07 +0100 Subject: hush: NOMMU fix for hush-psubst/tick6.tests function old new delta hush_main 1759 1766 +7 Signed-off-by: Denys Vlasenko --- shell/hush.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index 219158f18..f9b5623fd 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -10187,6 +10187,11 @@ int hush_main(int argc, char **argv) optarg++; G.depth_of_loop = bb_strtou(optarg, &optarg, 16); # endif + /* Suppress "killed by signal" message, -$ hack is used + * for subshells: echo `sh -c 'kill -9 $$'` + * should be silent. + */ + IF_HUSH_JOB(G.run_list_level = 1;) # if ENABLE_HUSH_FUNCTIONS /* nommu uses re-exec trick for "... | func | ...", * should allow "return". @@ -10274,6 +10279,7 @@ int hush_main(int argc, char **argv) G.global_argc--; G.global_argv++; +#if !BB_MMU if (builtin_argc) { /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */ const struct built_in_command *x; @@ -10287,6 +10293,7 @@ int hush_main(int argc, char **argv) } goto final_return; } +#endif script = G.global_argv[0]; if (!script) -- cgit v1.2.3-55-g6feb From 11f1a2553e49c9ff2235688a41875ff8751517ce Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 19:04:19 +0100 Subject: help text tweaks function old new delta packed_usage 33547 33545 -2 Signed-off-by: Denys Vlasenko --- archival/ar.c | 2 +- archival/bzip2.c | 2 +- coreutils/id.c | 2 +- coreutils/mkdir.c | 2 +- coreutils/rmdir.c | 2 +- coreutils/stat.c | 2 +- loginutils/passwd.c | 2 +- miscutils/crond.c | 2 +- miscutils/mt.c | 2 +- networking/ifconfig.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/archival/ar.c b/archival/ar.c index 2839d85d5..af9793f23 100644 --- a/archival/ar.c +++ b/archival/ar.c @@ -49,7 +49,7 @@ //kbuild:lib-$(CONFIG_AR) += ar.o //usage:#define ar_trivial_usage -//usage: "[-o] [-v] [-p] [-t] [-x] ARCHIVE FILES" +//usage: "[-optxv] ARCHIVE FILES" //usage:#define ar_full_usage "\n\n" //usage: "Extract or list FILES from an ar archive\n" //usage: "\n -o Preserve original dates" diff --git a/archival/bzip2.c b/archival/bzip2.c index d0390a92a..ac5db0880 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c @@ -50,7 +50,7 @@ //kbuild:lib-$(CONFIG_BZIP2) += bzip2.o //usage:#define bzip2_trivial_usage -//usage: "[OPTIONS] [FILE]..." +//usage: "[-cfk" IF_FEATURE_BZIP2_DECOMPRESS("dt") "123456789] [FILE]..." //usage:#define bzip2_full_usage "\n\n" //usage: "Compress FILEs (or stdin) with bzip2 algorithm\n" //usage: "\n -1..9 Compression level" diff --git a/coreutils/id.c b/coreutils/id.c index f20cd7d09..78d5f2a50 100644 --- a/coreutils/id.c +++ b/coreutils/id.c @@ -33,7 +33,7 @@ /* BB_AUDIT SUSv3 compliant. */ //usage:#define id_trivial_usage -//usage: "[OPTIONS] [USER]" +//usage: "[-ugGnr"IF_SELINUX("Z")"] [USER]" //usage:#define id_full_usage "\n\n" //usage: "Print information about USER or the current user\n" //usage: IF_SELINUX( diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index 0ee1d1f72..d5e0f512b 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c @@ -27,7 +27,7 @@ /* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */ //usage:#define mkdir_trivial_usage -//usage: "[OPTIONS] DIRECTORY..." +//usage: "[-m MODE] [-p] DIRECTORY..." //usage:#define mkdir_full_usage "\n\n" //usage: "Create DIRECTORY\n" //usage: "\n -m MODE Mode" diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c index 5092a5dfc..addf41188 100644 --- a/coreutils/rmdir.c +++ b/coreutils/rmdir.c @@ -20,7 +20,7 @@ /* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */ //usage:#define rmdir_trivial_usage -//usage: "[OPTIONS] DIRECTORY..." +//usage: "[-p] DIRECTORY..." //usage:#define rmdir_full_usage "\n\n" //usage: "Remove DIRECTORY if it is empty\n" //usage: "\n -p Include parents" diff --git a/coreutils/stat.c b/coreutils/stat.c index ee5e03edd..073b2c67b 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c @@ -40,7 +40,7 @@ //kbuild:lib-$(CONFIG_STAT) += stat.o //usage:#define stat_trivial_usage -//usage: "[OPTIONS] FILE..." +//usage: "[-lt"IF_FEATURE_STAT_FILESYSTEM("f")"] "IF_FEATURE_STAT_FORMAT("[-c FMT] ")"FILE..." //usage:#define stat_full_usage "\n\n" //usage: "Display file" //usage: IF_FEATURE_STAT_FILESYSTEM(" (default) or filesystem") diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 770acf58a..acc942275 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c @@ -28,7 +28,7 @@ //kbuild:lib-$(CONFIG_PASSWD) += passwd.o //usage:#define passwd_trivial_usage -//usage: "[OPTIONS] [USER]" +//usage: "[-a ALG] [-dlu] [USER]" //usage:#define passwd_full_usage "\n\n" //usage: "Change USER's password (default: current user)" //usage: "\n" diff --git a/miscutils/crond.c b/miscutils/crond.c index fb3adc180..b74427351 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -63,7 +63,7 @@ //kbuild:lib-$(CONFIG_CROND) += crond.o //usage:#define crond_trivial_usage -//usage: "-fbS -l N " IF_FEATURE_CROND_D("-d N ") "-L LOGFILE -c DIR" +//usage: "[-fbS] [-l N] " IF_FEATURE_CROND_D("[-d N] ") "[-L LOGFILE] [-c DIR]" //usage:#define crond_full_usage "\n\n" //usage: " -f Foreground" //usage: "\n -b Background (default)" diff --git a/miscutils/mt.c b/miscutils/mt.c index dbb8c13ad..1a4214664 100644 --- a/miscutils/mt.c +++ b/miscutils/mt.c @@ -15,7 +15,7 @@ //kbuild:lib-$(CONFIG_MT) += mt.o //usage:#define mt_trivial_usage -//usage: "[-f device] opcode value" +//usage: "[-f DEVICE] OPCODE VALUE" //usage:#define mt_full_usage "\n\n" //usage: "Control magnetic tape drive operation\n" //usage: "\n" diff --git a/networking/ifconfig.c b/networking/ifconfig.c index c3e448be0..9ee232a66 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c @@ -76,7 +76,7 @@ //kbuild:lib-$(CONFIG_IFCONFIG) += ifconfig.o interface.o //usage:#define ifconfig_trivial_usage -//usage: IF_FEATURE_IFCONFIG_STATUS("[-a]") " interface [address]" +//usage: IF_FEATURE_IFCONFIG_STATUS("[-a]") " [IFACE] [ADDRESS]" //usage:#define ifconfig_full_usage "\n\n" //usage: "Configure a network interface\n" //usage: "\n" -- cgit v1.2.3-55-g6feb From 5d553bc5580455cfb89705caf5d3a6ab327880bc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 19:18:28 +0100 Subject: more --help text tweaks function old new delta packed_usage 33545 33581 +36 Signed-off-by: Denys Vlasenko --- miscutils/adjtimex.c | 2 +- networking/hostname.c | 4 ++-- util-linux/hexdump.c | 2 +- util-linux/hexdump_xxd.c | 3 +-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/miscutils/adjtimex.c b/miscutils/adjtimex.c index a9de0f9aa..209d1d560 100644 --- a/miscutils/adjtimex.c +++ b/miscutils/adjtimex.c @@ -22,7 +22,7 @@ //kbuild:lib-$(CONFIG_ADJTIMEX) += adjtimex.o //usage:#define adjtimex_trivial_usage -//usage: "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]" +//usage: "[-q] [-o OFS] [-f FREQ] [-p TCONST] [-t TICK]" //usage:#define adjtimex_full_usage "\n\n" //usage: "Read or set kernel time variables. See adjtimex(2)\n" //usage: "\n -q Quiet" diff --git a/networking/hostname.c b/networking/hostname.c index f96daed95..549103485 100644 --- a/networking/hostname.c +++ b/networking/hostname.c @@ -29,9 +29,9 @@ //kbuild: lib-$(CONFIG_DNSDOMAINNAME) += hostname.o //usage:#define hostname_trivial_usage -//usage: "[OPTIONS] [HOSTNAME | -F FILE]" +//usage: "[-sidf] [HOSTNAME | -F FILE]" //usage:#define hostname_full_usage "\n\n" -//usage: "Get or set hostname or DNS domain name\n" +//usage: "Show or set hostname or DNS domain name\n" //usage: "\n -s Short" //usage: "\n -i Addresses for the hostname" //usage: "\n -d DNS domain name" diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 2174c3008..57e7e8db7 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c @@ -28,7 +28,7 @@ //kbuild:lib-$(CONFIG_HD) += hexdump.o //usage:#define hexdump_trivial_usage -//usage: "[-bcCdefnosvx] [FILE]..." +//usage: "[-bcdoxCv] [-e FMT] [-f FMT_FILE] [-n LEN] [-s OFS] [FILE]..." //usage:#define hexdump_full_usage "\n\n" //usage: "Display FILEs (or stdin) in a user specified format\n" //usage: "\n -b 1-byte octal display" diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index d2f4b6ed8..29bbc6633 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -41,7 +41,7 @@ // -u use upper case hex letters. //usage:#define xxd_trivial_usage -//usage: "[OPTIONS] [FILE]" +//usage: "[-pr] [-g N] [-c N] [-n LEN] [-s OFS] [FILE]" //usage:#define xxd_full_usage "\n\n" //usage: "Hex dump FILE (or stdin)\n" //usage: "\n -g N Bytes per group" @@ -51,7 +51,6 @@ //usage: "\n -l LENGTH Show only first LENGTH bytes" //usage: "\n -s OFFSET Skip OFFSET bytes" //usage: "\n -r Reverse (with -p, assumes no offsets in input)" -// TODO: implement -r (see hexdump -R) #include "libbb.h" #include "dump.h" -- cgit v1.2.3-55-g6feb From 1b367cbeda9447d771b09831c1e9c83cadbee55e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 21:35:26 +0100 Subject: examples: remove /sbin/ prefixes, system should be configured with $PATH to find utilities Signed-off-by: Denys Vlasenko --- examples/inetd.conf | 2 +- examples/udhcp/sample.bound | 8 ++++---- examples/udhcp/sample.deconfig | 2 +- examples/udhcp/sample.renew | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/inetd.conf b/examples/inetd.conf index ca7e3d8e1..78b10e3ac 100644 --- a/examples/inetd.conf +++ b/examples/inetd.conf @@ -31,7 +31,7 @@ time dgram udp wait root internal #ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd #telnet stream tcp nowait root /sbin/telnetd /sbin/telnetd #nntp stream tcp nowait root tcpd in.nntpd -#smtp stream tcp nowait root tcpd sendmail -v +#smtp stream tcp nowait root tcpd sendmail -v # # Shell, login, exec and talk are BSD protocols. # diff --git a/examples/udhcp/sample.bound b/examples/udhcp/sample.bound index efd98cf15..15a7775e9 100755 --- a/examples/udhcp/sample.bound +++ b/examples/udhcp/sample.bound @@ -6,12 +6,12 @@ RESOLV_CONF="/etc/udhcpc/resolv.conf" [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" [ -n "$subnet" ] && NETMASK="netmask $subnet" -/sbin/ifconfig $interface $ip $BROADCAST $NETMASK +ifconfig $interface $ip $BROADCAST $NETMASK if [ -n "$router" ] then echo "deleting routers" - while /sbin/route del default gw 0.0.0.0 dev $interface + while route del default gw 0.0.0.0 dev $interface do : done @@ -23,9 +23,9 @@ then # /32 instructs kernel to always use routing for all outgoing packets # (they can never be sent to local subnet - there is no local subnet for /32). # Used in datacenters, avoids the need for private ip-addresses between two hops. - /sbin/ip route add $i dev $interface + ip route add $i dev $interface fi - /sbin/route add default gw $i dev $interface metric $((metric++)) + route add default gw $i dev $interface metric $((metric++)) done fi diff --git a/examples/udhcp/sample.deconfig b/examples/udhcp/sample.deconfig index b221bcf12..a893de83f 100755 --- a/examples/udhcp/sample.deconfig +++ b/examples/udhcp/sample.deconfig @@ -1,4 +1,4 @@ #!/bin/sh # Sample udhcpc deconfig script -/sbin/ifconfig $interface 0.0.0.0 +ifconfig $interface 0.0.0.0 diff --git a/examples/udhcp/sample.renew b/examples/udhcp/sample.renew index efd98cf15..15a7775e9 100755 --- a/examples/udhcp/sample.renew +++ b/examples/udhcp/sample.renew @@ -6,12 +6,12 @@ RESOLV_CONF="/etc/udhcpc/resolv.conf" [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" [ -n "$subnet" ] && NETMASK="netmask $subnet" -/sbin/ifconfig $interface $ip $BROADCAST $NETMASK +ifconfig $interface $ip $BROADCAST $NETMASK if [ -n "$router" ] then echo "deleting routers" - while /sbin/route del default gw 0.0.0.0 dev $interface + while route del default gw 0.0.0.0 dev $interface do : done @@ -23,9 +23,9 @@ then # /32 instructs kernel to always use routing for all outgoing packets # (they can never be sent to local subnet - there is no local subnet for /32). # Used in datacenters, avoids the need for private ip-addresses between two hops. - /sbin/ip route add $i dev $interface + ip route add $i dev $interface fi - /sbin/route add default gw $i dev $interface metric $((metric++)) + route add default gw $i dev $interface metric $((metric++)) done fi -- cgit v1.2.3-55-g6feb From 63139b531f7f1d71d8274810b163da1a78d4609e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 22:00:56 +0100 Subject: hush: if login shell, also source ~/.profile function old new delta hush_main 1101 1151 +50 Signed-off-by: Denys Vlasenko --- shell/hush.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index f9b5623fd..ba9540c98 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -9992,7 +9992,9 @@ int hush_main(int argc, char **argv) OPT_login = (1 << 0), }; unsigned flags; - unsigned builtin_argc; +#if !BB_MMU + unsigned builtin_argc = 0; +#endif char **e; struct variable *cur_var; struct variable *shell_ver; @@ -10122,7 +10124,6 @@ int hush_main(int argc, char **argv) /* Parse options */ /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0; - builtin_argc = 0; while (1) { int opt = getopt(argc, argv, "+cexinsl" #if !BB_MMU @@ -10222,13 +10223,7 @@ int hush_main(int argc, char **argv) if (set_mode(1, opt, NULL) == 0) /* no error */ break; default: -#ifndef BB_VER - fprintf(stderr, "Usage: sh [FILE]...\n" - " or: sh -c command [args]...\n\n"); - exit(EXIT_FAILURE); -#else bb_show_usage(); -#endif } } /* option parsing loop */ @@ -10244,9 +10239,12 @@ int hush_main(int argc, char **argv) /* If we are login shell... */ if (flags & OPT_login) { + const char *hp = NULL; HFILE *input; + debug_printf("sourcing /etc/profile\n"); input = hfopen("/etc/profile"); + run_profile: if (input != NULL) { install_special_sighandlers(); parse_and_run_file(input); @@ -10259,6 +10257,16 @@ int hush_main(int argc, char **argv) * bash also sources ~/.bash_logout on exit. * If called as sh, skips .bash_XXX files. */ + if (!hp) { /* unless we looped on the "goto" already */ + hp = get_local_var_value("HOME"); + if (hp && hp[0]) { + debug_printf("sourcing ~/.profile\n"); + hp = concat_path_file(hp, ".profile"); + input = hfopen(hp); + free((char*)hp); + goto run_profile; + } + } } /* -c takes effect *after* -l */ -- cgit v1.2.3-55-g6feb From 84d5eddb25930ee8a5ff96536ca6f707d793eb24 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 13 Dec 2020 22:34:05 +0100 Subject: help text: replace [OPTIONS] with actual options (if not too long) function old new delta packed_usage 33620 33665 +45 Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 2 +- coreutils/ln.c | 4 ++-- coreutils/nl.c | 2 +- coreutils/paste.c | 2 +- editors/patch.c | 2 +- editors/vi.c | 2 +- loginutils/cryptpw.c | 10 +--------- modutils/insmod.c | 2 +- networking/ipcalc.c | 2 +- procps/fuser.c | 2 +- procps/pidof.c | 2 +- sysklogd/logger.c | 2 +- util-linux/fstrim.c | 8 -------- util-linux/umount.c | 8 ++++---- 14 files changed, 17 insertions(+), 33 deletions(-) diff --git a/coreutils/cp.c b/coreutils/cp.c index cfeb19fc4..9b9b8f7bf 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -38,7 +38,7 @@ /* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */ //usage:#define cp_trivial_usage -//usage: "[OPTIONS] SOURCE... DEST" +//usage: "[-arPLHpfilsTu] SOURCE... DEST" //usage:#define cp_full_usage "\n\n" //usage: "Copy SOURCE(s) to DEST\n" //usage: "\n -a Same as -dpR" diff --git a/coreutils/ln.c b/coreutils/ln.c index 5591e8335..2dcf79c07 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c @@ -21,14 +21,14 @@ /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */ //usage:#define ln_trivial_usage -//usage: "[OPTIONS] TARGET... LINK|DIR" +//usage: "[-sfnbtv] [-S SUF] TARGET... LINK|DIR" //usage:#define ln_full_usage "\n\n" //usage: "Create a link LINK or DIR/TARGET to the specified TARGET(s)\n" //usage: "\n -s Make symlinks instead of hardlinks" //usage: "\n -f Remove existing destinations" //usage: "\n -n Don't dereference symlinks - treat like normal file" //usage: "\n -b Make a backup of the target (if exists) before link operation" -//usage: "\n -S suf Use suffix instead of ~ when making backup files" +//usage: "\n -S SUF Use suffix instead of ~ when making backup files" //usage: "\n -T Treat LINK as a file, not DIR" //usage: "\n -v Verbose" //usage: diff --git a/coreutils/nl.c b/coreutils/nl.c index aea019c56..800b73c26 100644 --- a/coreutils/nl.c +++ b/coreutils/nl.c @@ -19,7 +19,7 @@ //usage:#define nl_full_usage "\n\n" //usage: "Write FILEs to standard output with line numbers added\n" //usage: "\n -b STYLE Which lines to number - a: all, t: nonempty, n: none" -//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^TODO: support "pBRE": number only lines thatmatch regexp BRE" +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^TODO: support "pBRE": number only lines that match regexp BRE" ////usage: "\n -f STYLE footer lines" ////usage: "\n -h STYLE header lines" ////usage: "\n -d CC use CC for separating logical pages" diff --git a/coreutils/paste.c b/coreutils/paste.c index 11743297a..fd2aa5027 100644 --- a/coreutils/paste.c +++ b/coreutils/paste.c @@ -18,7 +18,7 @@ //kbuild:lib-$(CONFIG_PASTE) += paste.o //usage:#define paste_trivial_usage -//usage: "[OPTIONS] [FILE]..." +//usage: "[-d LIST] [-s] [FILE]..." //usage:#define paste_full_usage "\n\n" //usage: "Paste lines from each input file, separated with tab\n" //usage: "\n -d LIST Use delimiters from LIST, not tab" diff --git a/editors/patch.c b/editors/patch.c index aaa253591..110176630 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -31,7 +31,7 @@ //kbuild:lib-$(CONFIG_PATCH) += patch.o //usage:#define patch_trivial_usage -//usage: "[OPTIONS] [ORIGFILE [PATCHFILE]]" +//usage: "[-RNE] [-p N] [-i DIFF] [ORIGFILE [PATCHFILE]]" //usage:#define patch_full_usage "\n\n" //usage: " -p N Strip N leading components from file names" //usage: "\n -i DIFF Read DIFF instead of stdin" diff --git a/editors/vi.c b/editors/vi.c index 1dd0b6fb6..01597fa5e 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -166,7 +166,7 @@ //kbuild:lib-$(CONFIG_VI) += vi.o //usage:#define vi_trivial_usage -//usage: "[OPTIONS] [FILE]..." +//usage: IF_FEATURE_VI_COLON("[-c CMD] ")IF_FEATURE_VI_READONLY("[-R] ")"[FILE]..." //usage:#define vi_full_usage "\n\n" //usage: "Edit FILE\n" //usage: IF_FEATURE_VI_COLON( diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index fbb7f0515..645f1bb09 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c @@ -32,22 +32,14 @@ //kbuild:lib-$(CONFIG_MKPASSWD) += cryptpw.o //usage:#define cryptpw_trivial_usage -//usage: "[OPTIONS] [PASSWORD] [SALT]" +//usage: "[-s] [-p N] [-m TYPE] [-S SALT] [PASSWORD] [SALT]" /* We do support -s, we just don't mention it */ //usage:#define cryptpw_full_usage "\n\n" //usage: "Print crypt(3) hashed PASSWORD\n" -//usage: IF_LONG_OPTS( -//usage: "\n -P,--password-fd N Read password from fd N" -/* //usage: "\n -s,--stdin Use stdin; like -P0" */ -//usage: "\n -m,--method TYPE "CRYPT_METHODS_HELP_STR -//usage: "\n -S,--salt SALT" -//usage: ) -//usage: IF_NOT_LONG_OPTS( //usage: "\n -P N Read password from fd N" /* //usage: "\n -s Use stdin; like -P0" */ //usage: "\n -m TYPE "CRYPT_METHODS_HELP_STR //usage: "\n -S SALT" -//usage: ) #include "libbb.h" diff --git a/modutils/insmod.c b/modutils/insmod.c index bd79a0f26..8f7163e25 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -26,7 +26,7 @@ //usage:#if !ENABLE_MODPROBE_SMALL //usage:#define insmod_trivial_usage -//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE") +//usage: IF_FEATURE_2_4_MODULES("[-fkvqLx] MODULE") //usage: IF_NOT_FEATURE_2_4_MODULES("FILE") //usage: IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...") //usage:#define insmod_full_usage "\n\n" diff --git a/networking/ipcalc.c b/networking/ipcalc.c index 09b146872..e82e35dd5 100644 --- a/networking/ipcalc.c +++ b/networking/ipcalc.c @@ -36,7 +36,7 @@ //kbuild:lib-$(CONFIG_IPCALC) += ipcalc.o //usage:#define ipcalc_trivial_usage -//usage: "[OPTIONS] ADDRESS" +//usage: "[-bnm"IF_FEATURE_IPCALC_FANCY("phs")"] ADDRESS" //usage: IF_FEATURE_IPCALC_FANCY("[/PREFIX]") " [NETMASK]" //usage:#define ipcalc_full_usage "\n\n" //usage: "Calculate and display network settings from IP address\n" diff --git a/procps/fuser.c b/procps/fuser.c index 418f57b57..191746751 100644 --- a/procps/fuser.c +++ b/procps/fuser.c @@ -19,7 +19,7 @@ //kbuild:lib-$(CONFIG_FUSER) += fuser.o //usage:#define fuser_trivial_usage -//usage: "[OPTIONS] FILE or PORT/PROTO" +//usage: "[-msk46] [-SIGNAL] FILE or PORT/PROTO" //usage:#define fuser_full_usage "\n\n" //usage: "Find processes which use FILEs or PORTs\n" //usage: "\n -m Find processes which use same fs as FILEs" diff --git a/procps/pidof.c b/procps/pidof.c index 5595e3421..b81709a81 100644 --- a/procps/pidof.c +++ b/procps/pidof.c @@ -39,7 +39,7 @@ //usage:#if (ENABLE_FEATURE_PIDOF_SINGLE || ENABLE_FEATURE_PIDOF_OMIT) //usage:#define pidof_trivial_usage -//usage: "[OPTIONS] [NAME]..." +//usage: IF_FEATURE_PIDOF_SINGLE("[-s] ")IF_FEATURE_PIDOF_OMIT("[-o PID] ")"[NAME]..." //usage:#define USAGE_PIDOF "\n" //usage:#else //usage:#define pidof_trivial_usage diff --git a/sysklogd/logger.c b/sysklogd/logger.c index 4d692d6fc..9422b6ea7 100644 --- a/sysklogd/logger.c +++ b/sysklogd/logger.c @@ -21,7 +21,7 @@ //kbuild:lib-$(CONFIG_LOGGER) += syslogd_and_logger.o //usage:#define logger_trivial_usage -//usage: "[OPTIONS] [MESSAGE]" +//usage: "[-s] [-t TAG] [-p PRIO] [MESSAGE]" //usage:#define logger_full_usage "\n\n" //usage: "Write MESSAGE (or stdin) to syslog\n" //usage: "\n -s Log to stderr as well as the system log" diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c index 8d29a6d54..6d673002f 100644 --- a/util-linux/fstrim.c +++ b/util-linux/fstrim.c @@ -20,18 +20,10 @@ //usage:#define fstrim_trivial_usage //usage: "[OPTIONS] MOUNTPOINT" //usage:#define fstrim_full_usage "\n\n" -//usage: IF_LONG_OPTS( -//usage: " -o,--offset OFFSET Offset in bytes to discard from" -//usage: "\n -l,--length LEN Bytes to discard" -//usage: "\n -m,--minimum MIN Minimum extent length" -//usage: "\n -v,--verbose Print number of discarded bytes" -//usage: ) -//usage: IF_NOT_LONG_OPTS( //usage: " -o OFFSET Offset in bytes to discard from" //usage: "\n -l LEN Bytes to discard" //usage: "\n -m MIN Minimum extent length" //usage: "\n -v Print number of discarded bytes" -//usage: ) #include "libbb.h" #include diff --git a/util-linux/umount.c b/util-linux/umount.c index 63a3bf504..23da32868 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c @@ -41,16 +41,16 @@ //kbuild:lib-$(CONFIG_UMOUNT) += umount.o //usage:#define umount_trivial_usage -//usage: "[OPTIONS] FILESYSTEM|DIRECTORY" +//usage: "[-rlf"IF_FEATURE_MTAB_SUPPORT("m")IF_FEATURE_MOUNT_LOOP("d")IF_FEATURE_UMOUNT_ALL("a")"] [-t FSTYPE] FILESYSTEM|DIRECTORY" //usage:#define umount_full_usage "\n\n" -//usage: "Unmount file systems\n" +//usage: "Unmount filesystems\n" //usage: IF_FEATURE_UMOUNT_ALL( -//usage: "\n -a Unmount all file systems" IF_FEATURE_MTAB_SUPPORT(" in /etc/mtab") +//usage: "\n -a Unmount all filesystems" IF_FEATURE_MTAB_SUPPORT(" in /etc/mtab") //usage: ) //usage: IF_FEATURE_MTAB_SUPPORT( //usage: "\n -n Don't erase /etc/mtab entries" //usage: ) -//usage: "\n -r Try to remount devices as read-only if mount is busy" +//usage: "\n -r Remount devices read-only if mount is busy" //usage: "\n -l Lazy umount (detach filesystem)" //usage: "\n -f Force umount (i.e., unreachable NFS server)" //usage: IF_FEATURE_MOUNT_LOOP( -- cgit v1.2.3-55-g6feb From a8e19608fc9d2f775a4f81eaf9c38a5844684237 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 14 Dec 2020 03:52:54 +0100 Subject: hush: code shrink function old new delta run_applet_main - 20 +20 builtin_kill 296 288 -8 builtin_test 19 10 -9 builtin_printf 19 10 -9 builtin_echo 19 10 -9 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/4 up/down: 20/-35) Total: -15 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index ba9540c98..3ccc18146 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -10499,7 +10499,7 @@ static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM) } #if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL -static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv)) +static NOINLINE int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv)) { int argc = string_array_len(argv); return applet_main_func(argc, argv); -- cgit v1.2.3-55-g6feb From db793480cb8ec3e5f878d1ec18b6ed5010c85e85 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 14 Dec 2020 05:53:45 +0100 Subject: build system: combat gcc zealotry in data alignment text data bss dec hex filename 1020934 559 5052 1026545 fa9f1 busybox_old 1020750 559 5052 1026361 fa939 busybox_unstripped Signed-off-by: Denys Vlasenko --- arch/i386/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 425361fd9..2fa008fa7 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -11,3 +11,11 @@ ifeq ($(CONFIG_STACK_OPTIMIZATION_386),y) # from aligning stack to 16 bytes. (Which is gcc's way of supporting SSE). CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2,) endif + +# "Control how GCC aligns variables. +# Supported values for type are compat uses increased alignment value +# compatible uses GCC 4.8 and earlier, abi uses alignment value as specified by the psABI, +# and cacheline uses increased alignment value to match the cache line size. +# compat is the default." +# "abi" seems to be somewhat successful in preventing oversealous data alignment. +CFLAGS += $(call cc-option,-malign-data=abi,) -- cgit v1.2.3-55-g6feb From fd3c512f88d43e6633bd3c3110cfa0bb321adaa8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 14 Dec 2020 18:25:28 +0100 Subject: libbb: create and use mmap() helpers function old new delta mmap_anon - 22 +22 mmap_read - 21 +21 xmmap_anon - 16 +16 rpm_gettags 465 447 -18 bb_full_fd_action 498 480 -18 uevent_main 337 310 -27 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 0/3 up/down: 59/-63) Total: -4 bytes Signed-off-by: Denys Vlasenko --- archival/rpm.c | 2 +- include/libbb.h | 3 +++ libbb/copyfd.c | 5 +---- libbb/xfuncs_printf.c | 21 +++++++++++++++++++++ modutils/modutils.c | 2 +- util-linux/uevent.c | 7 +------ 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/archival/rpm.c b/archival/rpm.c index 68afba914..a4d850b46 100644 --- a/archival/rpm.c +++ b/archival/rpm.c @@ -145,7 +145,7 @@ static int rpm_gettags(const char *filename) /* remember size for munmap */ G.mapsize = storepos; /* some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */ - G.map = mmap(0, storepos, PROT_READ, MAP_PRIVATE, fd, 0); + G.map = mmap_read(fd, storepos); if (G.map == MAP_FAILED) bb_perror_msg_and_die("mmap '%s'", filename); diff --git a/include/libbb.h b/include/libbb.h index 8f1ee7eec..a74b3119f 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -387,6 +387,9 @@ void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) F 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; +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; //TODO: supply a pointer to char[11] buffer (avoid statics)? diff --git a/libbb/copyfd.c b/libbb/copyfd.c index d41fd10f0..7f9d92ea9 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c @@ -75,10 +75,7 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) goto use_small_buf; /* We want page-aligned buffer, just in case kernel is clever * and can do page-aligned io more efficiently */ - buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - /* ignored: */ -1, 0); + buffer = mmap_anon(CONFIG_FEATURE_COPYBUF_KB * 1024); buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; if (buffer == MAP_FAILED) { use_small_buf: diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index fcc798662..db40e996b 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c @@ -111,6 +111,27 @@ void* FAST_FUNC xmemdup(const void *s, int n) return memcpy(xmalloc(n), s, n); } +void* FAST_FUNC mmap_read(int fd, size_t size) +{ + return mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); +} + +void* FAST_FUNC mmap_anon(size_t size) +{ + return mmap(NULL, size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + /* ignored: */ -1, 0); +} + +void* FAST_FUNC xmmap_anon(size_t size) +{ + void *p = mmap_anon(size); + if (p == MAP_FAILED) + bb_die_memory_exhausted(); + return p; +} + // Die if we can't open a file and return a FILE* to it. // Notice we haven't got xfread(), This is for use with fscanf() and friends. FILE* FAST_FUNC xfopen(const char *path, const char *mode) diff --git a/modutils/modutils.c b/modutils/modutils.c index 6f7cd9721..f7ad5e805 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c @@ -169,7 +169,7 @@ void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p) /* st.st_size is off_t, we can't just pass it to mmap */ if (st.st_size <= *image_size_p) { size_t image_size = st.st_size; - image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0); + image = mmap_read(fd, image_size); if (image == MAP_FAILED) { image = NULL; } else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) { diff --git a/util-linux/uevent.c b/util-linux/uevent.c index 045b35432..015f1ee78 100644 --- a/util-linux/uevent.c +++ b/util-linux/uevent.c @@ -74,12 +74,7 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) // for a new uevent notification to come in. // We use a fresh mmap so that buffer is not allocated // until kernel actually starts filling it. - netbuf = mmap(NULL, USER_RCVBUF, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - /* ignored: */ -1, 0); - if (netbuf == MAP_FAILED) - bb_simple_perror_msg_and_die("mmap"); + netbuf = xmmap_anon(USER_RCVBUF); // Here we block, possibly for a very long time len = safe_read(fd, netbuf, USER_RCVBUF - 1); -- cgit v1.2.3-55-g6feb From c7b858ff8d2e8b2d785f74b2d319bc9c839f4faa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 14 Dec 2020 18:49:23 +0100 Subject: libbb: add and use infrastructure for fixed page size optimization function old new delta procps_scan 1121 1118 -3 getpagesize 6 - -6 rpm_main 1037 1027 -10 rpm2cpio_main 120 110 -10 ptok 38 21 -17 time_main 1282 1261 -21 mkswap_main 317 278 -39 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 0/6 up/down: 0/-106) Total: -106 bytes Signed-off-by: Denys Vlasenko --- archival/rpm.c | 10 ++++++---- include/libbb.h | 18 ++++++++++++++++++ libbb/procps.c | 4 ++-- miscutils/devmem.c | 2 +- miscutils/hexedit.c | 14 +++----------- miscutils/time.c | 7 ++++++- util-linux/mkswap.c | 2 +- 7 files changed, 37 insertions(+), 20 deletions(-) diff --git a/archival/rpm.c b/archival/rpm.c index a4d850b46..af8db99a6 100644 --- a/archival/rpm.c +++ b/archival/rpm.c @@ -83,7 +83,9 @@ struct globals { void *map; rpm_index *mytags; int tagcount; - unsigned mapsize, pagesize; + unsigned mapsize; + IF_VARIABLE_ARCH_PAGESIZE(unsigned pagesize;) +#define G_pagesize cached_pagesize(G.pagesize) } FIX_ALIASING; #define G (*(struct globals*)bb_common_bufsiz1) #define INIT_G() do { setup_common_bufsiz(); } while (0) @@ -141,7 +143,7 @@ static int rpm_gettags(const char *filename) G.mytags = tags; /* Map the store */ - storepos = (storepos + G.pagesize) & -(int)G.pagesize; + storepos = (storepos + G_pagesize) & -(int)G_pagesize; /* remember size for munmap */ G.mapsize = storepos; /* some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */ @@ -356,7 +358,7 @@ int rpm_main(int argc, char **argv) int opt, func = 0; INIT_G(); - G.pagesize = getpagesize(); + INIT_PAGESIZE(G.pagesize); while ((opt = getopt(argc, argv, "iqpldc")) != -1) { switch (opt) { @@ -523,7 +525,7 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) int rpm_fd; INIT_G(); - G.pagesize = getpagesize(); + INIT_PAGESIZE(G.pagesize); rpm_fd = rpm_gettags(argv[1]); diff --git a/include/libbb.h b/include/libbb.h index a74b3119f..db5bf7a51 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -391,6 +391,24 @@ 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; +#if defined(__x86_64__) || defined(i386) +# define BB_ARCH_FIXED_PAGESIZE 4096 +#else /* if defined(ARCH) */ +/* add you favorite arch today! */ +#endif + +#if defined BB_ARCH_FIXED_PAGESIZE +# define IF_VARIABLE_ARCH_PAGESIZE(...) /*nothing*/ +# define bb_getpagesize() BB_ARCH_FIXED_PAGESIZE +# define INIT_PAGESIZE(var) ((void)0) +# define cached_pagesize(var) BB_ARCH_FIXED_PAGESIZE +#else +# define IF_VARIABLE_ARCH_PAGESIZE(...) __VA_ARGS__ +# define bb_getpagesize() getpagesize() +# define INIT_PAGESIZE(var) ((var) = getpagesize()) +# define cached_pagesize(var) (var) +#endif + //TODO: supply a pointer to char[11] buffer (avoid statics)? extern const char *bb_mode_string(mode_t mode) FAST_FUNC; diff --git a/libbb/procps.c b/libbb/procps.c index 4cc3cb2a1..975e0d4dc 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -94,15 +94,15 @@ static int read_to_buf(const char *filename, void *buf) static procps_status_t* FAST_FUNC alloc_procps_scan(void) { - unsigned n = getpagesize(); procps_status_t* sp = xzalloc(sizeof(procps_status_t)); - sp->dir = xopendir("/proc"); + unsigned n = bb_getpagesize(); while (1) { n >>= 1; if (!n) break; sp->shift_pages_to_bytes++; } sp->shift_pages_to_kb = sp->shift_pages_to_bytes - 10; + sp->dir = xopendir("/proc"); return sp; } diff --git a/miscutils/devmem.c b/miscutils/devmem.c index e8dce5225..f9f0276bc 100644 --- a/miscutils/devmem.c +++ b/miscutils/devmem.c @@ -75,7 +75,7 @@ int devmem_main(int argc UNUSED_PARAM, char **argv) bb_show_usage(); /* one of bb_strtouXX failed */ fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC)); - mapped_size = page_size = getpagesize(); + mapped_size = page_size = bb_getpagesize(); offset_in_page = (unsigned)target & (page_size - 1); if (offset_in_page + width > page_size) { /* This access spans pages. diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index 898d77376..f8ff9b62b 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c @@ -31,7 +31,8 @@ struct globals { int fd; unsigned height; unsigned row; - unsigned pagesize; + IF_VARIABLE_ARCH_PAGESIZE(unsigned pagesize;) +#define G_pagesize cached_pagesize(G.pagesize) uint8_t *baseaddr; uint8_t *current_byte; uint8_t *eof_byte; @@ -46,15 +47,6 @@ struct globals { SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ } while (0) -//TODO: move to libbb -#if defined(__x86_64__) || defined(i386) -# define G_pagesize 4096 -# define INIT_PAGESIZE() ((void)0) -#else -# define G_pagesize (G.pagesize) -# define INIT_PAGESIZE() ((void)(G.pagesize = getpagesize())) -#endif - /* hopefully there aren't arches with PAGE_SIZE > 64k */ #define G_mapsize (64*1024) @@ -262,7 +254,7 @@ int hexedit_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int hexedit_main(int argc UNUSED_PARAM, char **argv) { INIT_G(); - INIT_PAGESIZE(); + INIT_PAGESIZE(G.pagesize); get_terminal_width_height(-1, NULL, &G.height); if (1) { diff --git a/miscutils/time.c b/miscutils/time.c index d15d363f3..0006c59d8 100644 --- a/miscutils/time.c +++ b/miscutils/time.c @@ -111,6 +111,10 @@ static void printargv(char *const *argv) This is funky since the pagesize could be less than 1K. Note: Some machines express getrusage statistics in terms of K, others in terms of pages. */ +#ifdef BB_ARCH_FIXED_PAGESIZE +# define pagesize BB_ARCH_FIXED_PAGESIZE +# define ptok(pagesize, pages) ptok(pages) +#endif static unsigned long ptok(const unsigned pagesize, const unsigned long pages) { unsigned long tmp; @@ -124,6 +128,7 @@ static unsigned long ptok(const unsigned pagesize, const unsigned long pages) tmp = pages * pagesize; /* Larger first, */ return tmp / 1024; /* then smaller. */ } +#undef pagesize /* summarize: Report on the system use of a command. @@ -177,7 +182,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) { unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ unsigned cpu_ticks; /* Same, in "CPU ticks" */ - unsigned pagesize = getpagesize(); + unsigned pagesize = bb_getpagesize(); /* Impossible: we do not use WUNTRACED flag in wait()... if (WIFSTOPPED(resp->waitstatus)) diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c index 9e51a1dcc..8fe5d0293 100644 --- a/util-linux/mkswap.c +++ b/util-linux/mkswap.c @@ -128,7 +128,7 @@ int mkswap_main(int argc UNUSED_PARAM, char **argv) /* Figure out how big the device is */ len = get_volume_size_in_bytes(fd, argv[1], 1024, /*extend:*/ 1); - pagesize = getpagesize(); + pagesize = bb_getpagesize(); len -= pagesize; /* Announce our intentions */ -- cgit v1.2.3-55-g6feb From 2aaacc1453e98bd24341e7dc6edd8e7fdf84e576 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 14 Dec 2020 20:27:57 +0100 Subject: dd: support for O_DIRECT i/o Based on patch by Akash Hadke function old new delta dd_read - 66 +66 clear_O_DIRECT - 55 +55 write_and_stats 102 135 +33 dd_main 1578 1601 +23 static.oflag_words 19 26 +7 static.iflag_words 22 29 +7 packed_usage 33665 33668 +3 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 5/0 up/down: 194/0) Total: 194 bytes Signed-off-by: Denys Vlasenko --- coreutils/dd.c | 111 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 31 deletions(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index b5f3cbec5..24d7f0b84 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -59,7 +59,7 @@ //usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n" //usage: IF_FEATURE_DD_IBS_OBS( //usage: " [conv=notrunc|noerror|sync|fsync]\n" -//usage: " [iflag=skip_bytes|fullblock] [oflag=seek_bytes|append]" +//usage: " [iflag=skip_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]" //usage: ) //usage:#define dd_full_usage "\n\n" //usage: "Copy a file with converting and formatting\n" @@ -82,9 +82,11 @@ //usage: "\n conv=fsync Physically write data out before finishing" //usage: "\n conv=swab Swap every pair of bytes" //usage: "\n iflag=skip_bytes skip=N is in bytes" -//usage: "\n iflag=fullblock Read full blocks" //usage: "\n oflag=seek_bytes seek=N is in bytes" -//usage: "\n oflag=append Open output file in append mode" +//usage: "\n iflag=direct O_DIRECT input" +//usage: "\n oflag=direct O_DIRECT output" +//usage: "\n iflag=fullblock Read full blocks" +//usage: "\n oflag=append Open output in append mode" //usage: ) //usage: IF_FEATURE_DD_STATUS( //usage: "\n status=noxfer Suppress rate output" @@ -137,16 +139,18 @@ enum { FLAG_IFLAG_SHIFT = 5, FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_IDIRECT = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, /* end of input flags */ /* start of output flags */ - FLAG_OFLAG_SHIFT = 7, - FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_APPEND = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_OFLAG_SHIFT = 8, + FLAG_SEEK_BYTES = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_APPEND = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_ODIRECT = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS, /* end of output flags */ - FLAG_TWOBUFS = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_COUNT = 1 << 10, - FLAG_STATUS_NONE = 1 << 11, - FLAG_STATUS_NOXFER = 1 << 12, + FLAG_TWOBUFS = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_COUNT = 1 << 12, + FLAG_STATUS_NONE = 1 << 13, + FLAG_STATUS_NOXFER = 1 << 14, }; static void dd_output_status(int UNUSED_PARAM cur_signal) @@ -192,12 +196,50 @@ static void dd_output_status(int UNUSED_PARAM cur_signal) #endif } +#if ENABLE_FEATURE_DD_IBS_OBS +static int clear_O_DIRECT(int fd) +{ + if (errno == EINVAL) { + int fl = fcntl(fd, F_GETFL); + if (fl & O_DIRECT) { + fcntl(fd, F_SETFL, fl & ~O_DIRECT); + return 1; + } + } + return 0; +} +#endif + +static ssize_t dd_read(void *ibuf, size_t ibs) +{ + ssize_t n; + +#if ENABLE_FEATURE_DD_IBS_OBS + read_again: + if (G.flags & FLAG_FULLBLOCK) + n = full_read(ifd, ibuf, ibs); + else +#endif + n = safe_read(ifd, ibuf, ibs); +#if ENABLE_FEATURE_DD_IBS_OBS + if (n < 0 && (G.flags & FLAG_IDIRECT) && clear_O_DIRECT(ifd)) + goto read_again; +#endif + return n; +} + static bool write_and_stats(const void *buf, size_t len, size_t obs, const char *filename) { ssize_t n; + IF_FEATURE_DD_IBS_OBS(write_again:) n = full_write(ofd, buf, len); +#if ENABLE_FEATURE_DD_IBS_OBS + if (n < 0 && (G.flags & FLAG_ODIRECT) && clear_O_DIRECT(ofd)) + goto write_again; +#endif + #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE if (n > 0) G.total_bytes += n; @@ -254,6 +296,14 @@ static int parse_comma_flags(char *val, const char *words, const char *error_in) } #endif +static void *alloc_buf(size_t size) +{ + /* Important for "{i,o}flag=direct" - buffers must be page aligned */ + if (size >= bb_getpagesize()) + return xmmap_anon(size); + return xmalloc(size); +} + int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dd_main(int argc UNUSED_PARAM, char **argv) { @@ -267,9 +317,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv) static const char conv_words[] ALIGN1 = "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; static const char iflag_words[] ALIGN1 = - "skip_bytes\0""fullblock\0"; + "skip_bytes\0""fullblock\0""direct\0"; static const char oflag_words[] ALIGN1 = - "seek_bytes\0append\0"; + "seek_bytes\0append\0""direct\0"; #endif #if ENABLE_FEATURE_DD_STATUS static const char status_words[] ALIGN1 = @@ -310,7 +360,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv) //swab swap every pair of input bytes: will abort on non-even reads OP_iflag_skip_bytes, OP_iflag_fullblock, + OP_iflag_direct, OP_oflag_seek_bytes, + OP_oflag_direct, #endif }; smallint exitcode = EXIT_FAILURE; @@ -426,13 +478,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) #endif } /* end of "for (argv[i])" */ -//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever - ibuf = xmalloc(ibs); + ibuf = alloc_buf(ibs); obuf = ibuf; #if ENABLE_FEATURE_DD_IBS_OBS if (ibs != obs) { G.flags |= FLAG_TWOBUFS; - obuf = xmalloc(obs); + obuf = alloc_buf(obs); } #endif @@ -444,7 +495,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) #endif if (infile) { - xmove_fd(xopen(infile, O_RDONLY), ifd); + int iflag = O_RDONLY; +#if ENABLE_FEATURE_DD_IBS_OBS + if (G.flags & FLAG_IDIRECT) + iflag |= O_DIRECT; +#endif + xmove_fd(xopen(infile, iflag), ifd); } else { infile = bb_msg_standard_input; } @@ -455,7 +511,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) oflag |= O_TRUNC; if (G.flags & FLAG_APPEND) oflag |= O_APPEND; - +#if ENABLE_FEATURE_DD_IBS_OBS + if (G.flags & FLAG_ODIRECT) + oflag |= O_DIRECT; +#endif xmove_fd(xopen(outfile, oflag), ofd); if (seek && !(G.flags & FLAG_NOTRUNC)) { @@ -478,13 +537,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { do { - ssize_t n; -#if ENABLE_FEATURE_DD_IBS_OBS - if (G.flags & FLAG_FULLBLOCK) - n = full_read(ifd, ibuf, blocksz); - else -#endif - n = safe_read(ifd, ibuf, blocksz); + ssize_t n = dd_read(ibuf, blocksz); if (n < 0) goto die_infile; if (n == 0) @@ -499,13 +552,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) } while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { - ssize_t n; -#if ENABLE_FEATURE_DD_IBS_OBS - if (G.flags & FLAG_FULLBLOCK) - n = full_read(ifd, ibuf, ibs); - else -#endif - n = safe_read(ifd, ibuf, ibs); + ssize_t n = dd_read(ibuf, ibs); if (n == 0) break; if (n < 0) { @@ -600,11 +647,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) dd_output_status(0); +#if 0 /* can't just free(), they can be mmap()ed */ if (ENABLE_FEATURE_CLEAN_UP) { free(obuf); if (G.flags & FLAG_TWOBUFS) free(ibuf); } +#endif return exitcode; } -- cgit v1.2.3-55-g6feb From fad8d6b6c0290e92b89cd18493c0c336f3619ee1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 15 Dec 2020 18:39:05 +0100 Subject: build system: combat gcc zealotry in data alignment, now for x86_64 too function old new delta .rodata 182928 182620 -308 Signed-off-by: Denys Vlasenko --- arch/x86_64/Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 arch/x86_64/Makefile diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile new file mode 100644 index 000000000..16576fb81 --- /dev/null +++ b/arch/x86_64/Makefile @@ -0,0 +1,11 @@ +# ========================================================================== +# Build system +# ========================================================================== + +# "Control how GCC aligns variables. +# Supported values for type are compat uses increased alignment value +# compatible uses GCC 4.8 and earlier, abi uses alignment value as specified by the psABI, +# and cacheline uses increased alignment value to match the cache line size. +# compat is the default." +# "abi" seems to be somewhat successful in preventing oversealous data alignment. +CFLAGS += $(call cc-option,-malign-data=abi,) -- cgit v1.2.3-55-g6feb From 4a9ec95565d8ebf315144a67320e77b08adb51a1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 15 Dec 2020 18:47:25 +0100 Subject: tls: code shrink in AES code function old new delta aes_cbc_decrypt 862 847 -15 Signed-off-by: Denys Vlasenko --- networking/tls_aes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/tls_aes.c b/networking/tls_aes.c index 5400ad9b5..feb618fb7 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c @@ -313,15 +313,15 @@ static void InvMixColumns(unsigned astate[16]) d = astate[i + 3]; x = (a << 1) ^ (a << 2) ^ (a << 3) ^ b ^ (b << 1) ^ (b << 3) /***/ ^ c ^ (c << 2) ^ (c << 3) ^ d ^ (d << 3); + astate[i + 0] = Multiply(x); y = a ^ (a << 3) ^ (b << 1) ^ (b << 2) ^ (b << 3) /***/ ^ c ^ (c << 1) ^ (c << 3) ^ d ^ (d << 2) ^ (d << 3); + astate[i + 1] = Multiply(y); z = a ^ (a << 2) ^ (a << 3) ^ b ^ (b << 3) /***/ ^ (c << 1) ^ (c << 2) ^ (c << 3) ^ d ^ (d << 1) ^ (d << 3); + astate[i + 2] = Multiply(z); t = a ^ (a << 1) ^ (a << 3) ^ b ^ (b << 2) ^ (b << 3) /***/ ^ c ^ (c << 3) ^ (d << 1) ^ (d << 2) ^ (d << 3); - astate[i + 0] = Multiply(x); - astate[i + 1] = Multiply(y); - astate[i + 2] = Multiply(z); astate[i + 3] = Multiply(t); } } -- cgit v1.2.3-55-g6feb From 01004f9796fd7a5223a40802026d2023e3f9cf28 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 15 Dec 2020 21:24:04 +0100 Subject: libbb: enable fixed 4k pagesize for 32bit ARM Signed-off-by: Denys Vlasenko --- include/libbb.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/libbb.h b/include/libbb.h index db5bf7a51..202e3f39c 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -393,8 +393,13 @@ void *xmmap_anon(size_t size) FAST_FUNC; #if defined(__x86_64__) || defined(i386) # define BB_ARCH_FIXED_PAGESIZE 4096 +#elif defined(__arm__) /* only 32bit, 64bit ARM has variable page size */ +# define BB_ARCH_FIXED_PAGESIZE 4096 #else /* if defined(ARCH) */ /* add you favorite arch today! */ +//From Linux kernel inspection: +//xtenza,s390[x],riscv,nios2,csky,sparc32: fixed 4k pages +//sparc64,alpha,openrisc: fixed 8k pages #endif #if defined BB_ARCH_FIXED_PAGESIZE -- cgit v1.2.3-55-g6feb From b817699e6c5c8efe4fce45e910d66133c9d8c482 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Tue, 15 Dec 2020 09:53:40 +0000 Subject: udhcp: bind to device even for ucast packets There are cases where binding to source IP and destination IP is insufficient to guarantee sane xmit netdev. One case where this can fail is when route-matching netdev carrier is down (cable unplugged, wifi disconnected), or the netdev is admin down. Then all the IP based bindings (bind() + connect()) will seemingly succeed but the actual packet can go out through a default gw path. Depending on the network this happens on it can create issues or false alarms. It can also leak some subnet info across networks that shouldn't be routed. As such better be safe than sorry and bind to a netdev to be sure it's used for xmit. function old new delta udhcp_send_kernel_packet 293 336 +43 send_packet 182 188 +6 bcast_or_ucast 37 43 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 55/0) Total: 55 bytes Signed-off-by: Michal Kazior Signed-off-by: Denys Vlasenko --- networking/udhcp/common.h | 3 ++- networking/udhcp/dhcpc.c | 3 ++- networking/udhcp/dhcpd.c | 3 ++- networking/udhcp/packet.c | 18 +++++++++++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 3cbd2d3c8..cc0abd269 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -343,7 +343,8 @@ int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, - uint32_t dest_nip, int dest_port) FAST_FUNC; + uint32_t dest_nip, int dest_port, + const char *ifname) FAST_FUNC; void udhcp_sp_setup(void) FAST_FUNC; void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 66aa38c20..98720b45b 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -702,7 +702,8 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t if (server) return udhcp_send_kernel_packet(packet, ciaddr, CLIENT_PORT, - server, SERVER_PORT); + server, SERVER_PORT, + client_data.interface); return raw_bcast_from_client_data_ifindex(packet, ciaddr); } diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index de16cf955..9e950ca1f 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -612,7 +612,8 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) udhcp_send_kernel_packet(dhcp_pkt, server_data.server_nip, SERVER_PORT, - dhcp_pkt->gateway_nip, SERVER_PORT); + dhcp_pkt->gateway_nip, SERVER_PORT, + server_data.interface); } static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 51374646d..4d8e005d4 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -189,7 +189,8 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, /* Let the kernel do all the work for packet generation */ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, - uint32_t dest_nip, int dest_port) + uint32_t dest_nip, int dest_port, + const char *ifname) { struct sockaddr_in sa; unsigned padding; @@ -204,6 +205,21 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, } setsockopt_reuseaddr(fd); + /* If interface carrier goes down, unless we + * bind socket to a particular netdev, the packet + * can go out through another interface, eg. via + * default route despite being bound to a specific + * source IP. As such, bind to device hard and fail + * otherwise. Sending renewal packets on foreign + * interfaces makes no sense. + */ + if (ifname) { + if (setsockopt_bindtodevice(fd, ifname) < 0) { + msg = "bindtodevice"; + goto ret_close; + } + } + memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(source_port); -- cgit v1.2.3-55-g6feb From f3d6711c971cde8ed3890a47020c5083a383e606 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 15 Dec 2020 21:55:15 +0100 Subject: udhcpc6: code shrink - sending functions do not need ifindex parameter function old new delta d6_send_raw_packet_from_client_data_ifindex - 427 +427 d6_send_kernel_packet_from_client_data_ifindex - 275 +275 send_d6_renew 182 176 -6 perform_d6_release 246 240 -6 d6_mcast_from_client_data_ifindex 45 39 -6 d6_send_kernel_packet 274 - -274 d6_send_raw_packet 429 - -429 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 0/3 up/down: 702/-721) Total: -19 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_common.h | 10 ++++------ networking/udhcp/d6_dhcpc.c | 15 ++++++--------- networking/udhcp/d6_packet.c | 19 +++++++++---------- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index 688f5d6c7..9dfde7709 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h @@ -159,18 +159,16 @@ int FAST_FUNC d6_recv_kernel_packet( struct d6_packet *packet, int fd ); -int FAST_FUNC d6_send_raw_packet( +int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, - struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp, - int ifindex + struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp ); -int FAST_FUNC d6_send_kernel_packet( +int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, - struct in6_addr *dst_ipv6, int dest_port, - int ifindex + struct in6_addr *dst_ipv6, int dest_port ); #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index ac8af91d3..744448cee 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -558,11 +558,10 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t * 0x33, 0x33, 0x00, 0x01, 0x00, 0x02, }; - return d6_send_raw_packet( + return d6_send_raw_packet_from_client_data_ifindex( packet, (end - (uint8_t*) packet), /*src*/ &client6_data.ll_ip6, CLIENT_PORT6, - /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR, - client_data.ifindex + /*dst*/ (struct in6_addr*)FF02__1_2, SERVER_PORT6, MAC_DHCP6MCAST_ADDR ); } @@ -864,11 +863,10 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st bb_info_msg("sending %s", "renew"); if (server_ipv6) - return d6_send_kernel_packet( + return d6_send_kernel_packet_from_client_data_ifindex( &packet, (opt_ptr - (uint8_t*) &packet), our_cur_ipv6, CLIENT_PORT6, - server_ipv6, SERVER_PORT6, - client_data.ifindex + server_ipv6, SERVER_PORT6 ); return d6_mcast_from_client_data_ifindex(&packet, opt_ptr); } @@ -893,11 +891,10 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); bb_info_msg("sending %s", "release"); - return d6_send_kernel_packet( + return d6_send_kernel_packet_from_client_data_ifindex( &packet, (opt_ptr - (uint8_t*) &packet), our_cur_ipv6, CLIENT_PORT6, - server_ipv6, SERVER_PORT6, - client_data.ifindex + server_ipv6, SERVER_PORT6 ); } diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c index 167a813e3..172f8e1ab 100644 --- a/networking/udhcp/d6_packet.c +++ b/networking/udhcp/d6_packet.c @@ -6,6 +6,7 @@ */ #include "common.h" #include "d6_common.h" +#include "dhcpc.h" #include "dhcpd.h" #include #include @@ -50,11 +51,10 @@ int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6 } /* Construct a ipv6+udp header for a packet, send packet */ -int FAST_FUNC d6_send_raw_packet( +int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, - struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp, - int ifindex) + struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp) { struct sockaddr_ll dest_sll; struct ip6_udp_d6_packet packet; @@ -74,7 +74,7 @@ int FAST_FUNC d6_send_raw_packet( dest_sll.sll_family = AF_PACKET; dest_sll.sll_protocol = htons(ETH_P_IPV6); - dest_sll.sll_ifindex = ifindex; + dest_sll.sll_ifindex = client_data.ifindex; /*dest_sll.sll_hatype = ARPHRD_???;*/ /*dest_sll.sll_pkttype = PACKET_???;*/ dest_sll.sll_halen = 6; @@ -103,8 +103,8 @@ int FAST_FUNC d6_send_raw_packet( */ packet.ip6.ip6_hlim = IPPROTO_UDP; packet.udp.check = inet_cksum( - (uint8_t *)&packet + 4, - offsetof(struct ip6_udp_d6_packet, data) - 4 + d6_pkt_size + (uint8_t *)&packet + 4, + offsetof(struct ip6_udp_d6_packet, data) - 4 + d6_pkt_size ); /* fix 'hop limit' and 'next header' after UDP checksumming */ packet.ip6.ip6_hlim = 1; /* observed Windows machines to use hlim=1 */ @@ -126,11 +126,10 @@ int FAST_FUNC d6_send_raw_packet( } /* Let the kernel do all the work for packet generation */ -int FAST_FUNC d6_send_kernel_packet( +int FAST_FUNC d6_send_kernel_packet_from_client_data_ifindex( struct d6_packet *d6_pkt, unsigned d6_pkt_size, struct in6_addr *src_ipv6, int source_port, - struct in6_addr *dst_ipv6, int dest_port, - int ifindex) + struct in6_addr *dst_ipv6, int dest_port) { struct sockaddr_in6 sa; int fd; @@ -157,7 +156,7 @@ int FAST_FUNC d6_send_kernel_packet( sa.sin6_family = AF_INET6; sa.sin6_port = htons(dest_port); sa.sin6_addr = *dst_ipv6; /* struct copy */ - sa.sin6_scope_id = ifindex; + sa.sin6_scope_id = client_data.ifindex; if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { msg = "connect"; goto ret_close; -- cgit v1.2.3-55-g6feb From 73d93d9f83180a6149f363aaca131e281d2a52ff Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 15 Dec 2020 23:19:22 +0100 Subject: libbb: make pw_encrypt() die if supplied salt is bad (e.g. emply) Fished from 520-loginutils-handle-crypt-failures.patch in openwrt function old new delta pw_encrypt 913 927 +14 des_crypt 1327 1318 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 14/-9) Total: 5 bytes Signed-off-by: Denys Vlasenko --- libbb/pw_encrypt.c | 11 ++++++++--- libbb/pw_encrypt_des.c | 25 +++++++++++-------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c index 47c20690f..a60c33c35 100644 --- a/libbb/pw_encrypt.c +++ b/libbb/pw_encrypt.c @@ -120,6 +120,7 @@ static char *my_crypt(const char *key, const char *salt) if (!des_cctx) des_cctx = const_des_init(); des_ctx = des_init(des_ctx, des_cctx); + /* Can return NULL if salt is bad ("" or "") */ return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); } @@ -137,6 +138,8 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) char *encrypted; encrypted = my_crypt(clear, salt); + if (!encrypted) + bb_simple_error_msg_and_die("bad salt"); if (cleanup) my_crypt_cleanup(); @@ -148,14 +151,16 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) { - char *s; + char *encrypted; - s = crypt(clear, salt); + encrypted = crypt(clear, salt); /* * glibc used to return "" on malformed salts (for example, ""), * but since 2.17 it returns NULL. */ - return xstrdup(s ? s : ""); + if (!encrypted || !encrypted[0]) + bb_simple_error_msg_and_die("bad salt"); + return xstrdup(encrypted); } #endif diff --git a/libbb/pw_encrypt_des.c b/libbb/pw_encrypt_des.c index c6fc328d8..dcd3521e2 100644 --- a/libbb/pw_encrypt_des.c +++ b/libbb/pw_encrypt_des.c @@ -713,11 +713,15 @@ to64_msb_first(char *s, unsigned v) static char * NOINLINE des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], - const unsigned char *key, const unsigned char *setting) + const unsigned char *key, const unsigned char *salt_str) { uint32_t salt, r0, r1, keybuf[2]; uint8_t *q; + /* Bad salt? Mimic crypt() API - return NULL */ + if (!salt_str[0] || !salt_str[1]) + return NULL; + /* * Copy the key, shifting each character up by one bit * and padding with zeros. @@ -732,22 +736,15 @@ des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], des_setkey(ctx, (char *)keybuf); /* - * setting - 2 bytes of salt + * salt_str - 2 bytes of salt * key - up to 8 characters */ - salt = (ascii_to_bin(setting[1]) << 6) - | ascii_to_bin(setting[0]); - - output[0] = setting[0]; - /* - * If the encrypted password that the salt was extracted from - * is only 1 character long, the salt will be corrupted. We - * need to ensure that the output string doesn't have an extra - * NUL in it! - */ - output[1] = setting[1] ? setting[1] : output[0]; - + output[0] = salt_str[0]; + output[1] = salt_str[1]; + salt = (ascii_to_bin(salt_str[1]) << 6) + | ascii_to_bin(salt_str[0]); setup_salt(ctx, salt); + /* Do it. */ do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */); -- cgit v1.2.3-55-g6feb From 9b44deac01d61929a734a3ee4f739e95b024bfec Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 15 Dec 2020 23:22:47 +0100 Subject: ntpd: allow non-root to run it (e.g. with -w option) This is safe: it's not a setuid applet, the attempt to set time will simply fail if attempted by non-root From openwrt 600-allow-ntpd-non-root.patch function old new delta ntp_init 1049 1005 -44 Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 44e711232..032dc51ac 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -2462,9 +2462,6 @@ static NOINLINE void ntp_init(char **argv) srand(getpid()); - if (getuid()) - bb_simple_error_msg_and_die(bb_msg_you_must_be_root); - /* Set some globals */ G.discipline_jitter = G_precision_sec; G.stratum = MAXSTRAT; -- cgit v1.2.3-55-g6feb From caba1a16ec4a883376d53e5921917bb8485b5f49 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 16 Dec 2020 01:19:08 +0100 Subject: tweak help texts function old new delta packed_usage 33650 33605 -45 Signed-off-by: Denys Vlasenko --- loginutils/chpasswd.c | 10 +--------- networking/udhcp/dumpleases.c | 8 -------- selinux/chcon.c | 8 ++++---- util-linux/hwclock.c | 11 +++++------ util-linux/rtcwake.c | 18 ++++++------------ 5 files changed, 16 insertions(+), 39 deletions(-) diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c index 4e70b2557..a032abbed 100644 --- a/loginutils/chpasswd.c +++ b/loginutils/chpasswd.c @@ -24,21 +24,13 @@ //kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o //usage:#define chpasswd_trivial_usage -//usage: IF_LONG_OPTS("[--md5|--encrypted|--crypt-method|--root]") IF_NOT_LONG_OPTS("[-m|-e|-c|-R]") +//usage: "[-me] [-c ALG] [-R DIR]" //usage:#define chpasswd_full_usage "\n\n" //usage: "Read user:password from stdin and update /etc/passwd\n" -//usage: IF_LONG_OPTS( -//usage: "\n -e,--encrypted Supplied passwords are in encrypted form" -//usage: "\n -m,--md5 Encrypt using md5, not des" -//usage: "\n -c,--crypt-method ALG "CRYPT_METHODS_HELP_STR -//usage: "\n -R,--root DIR Directory to chroot into" -//usage: ) -//usage: IF_NOT_LONG_OPTS( //usage: "\n -e Supplied passwords are in encrypted form" //usage: "\n -m Encrypt using md5, not des" //usage: "\n -c ALG "CRYPT_METHODS_HELP_STR //usage: "\n -R DIR Directory to chroot into" -//usage: ) #include "libbb.h" diff --git a/networking/udhcp/dumpleases.c b/networking/udhcp/dumpleases.c index 70d2d1434..1e9405205 100644 --- a/networking/udhcp/dumpleases.c +++ b/networking/udhcp/dumpleases.c @@ -10,18 +10,10 @@ //usage: "[-r|-a] [-d] [-f LEASEFILE]" //usage:#define dumpleases_full_usage "\n\n" //usage: "Display DHCP leases granted by udhcpd\n" -//usage: IF_LONG_OPTS( -//usage: "\n -f,--file FILE Lease file" -//usage: "\n -r,--remaining Show remaining time" -//usage: "\n -a,--absolute Show expiration time" -//usage: "\n -d,--decimal Show time in seconds" -//usage: ) -//usage: IF_NOT_LONG_OPTS( //usage: "\n -f FILE Lease file" //usage: "\n -r Show remaining time" //usage: "\n -a Show expiration time" //usage: "\n -d Show time in seconds" -//usage: ) #include "common.h" #include "dhcpd.h" diff --git a/selinux/chcon.c b/selinux/chcon.c index 9b13679b8..2e4f94c0f 100644 --- a/selinux/chcon.c +++ b/selinux/chcon.c @@ -19,10 +19,10 @@ //kbuild:lib-$(CONFIG_CHCON) += chcon.o //usage:#define chcon_trivial_usage -//usage: "[OPTIONS] CONTEXT FILE..." -//usage: "\n chcon [OPTIONS] [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE..." +//usage: "[-chfRv] CONTEXT FILE..." +//usage: "\n chcon [-chfRv] [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE..." //usage: IF_LONG_OPTS( -//usage: "\n chcon [OPTIONS] --reference=RFILE FILE..." +//usage: "\n chcon [-chfRv] --reference=RFILE FILE..." //usage: ) //usage: //usage:#define chcon_full_usage "\n\n" @@ -37,7 +37,7 @@ //usage: "\n -u USER Set user/role/type/range in the target security context" //usage: "\n -r ROLE" //usage: "\n -t TYPE" -//usage: "\n -l RNG" +//usage: "\n -l RANGE" //usage: "\n -R Recurse" #include diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index e85bca2b2..791525fc2 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -296,16 +296,15 @@ static void set_system_clock_timezone(int utc) //usage:#define hwclock_trivial_usage //usage: IF_LONG_OPTS( -//usage: "[-r|--show] [-s|--hctosys] [-w|--systohc] [--systz]" -//usage: " [--localtime] [-u|--utc]" -//usage: " [-f|--rtc FILE]" +//usage: "[-swu] [--systz] [--localtime] [-f FILE]" //usage: ) //usage: IF_NOT_LONG_OPTS( -//usage: "[-r] [-s] [-w] [-t] [-l] [-u] [-f FILE]" +//usage: "[-swtlu] [-f FILE]" //usage: ) //usage:#define hwclock_full_usage "\n\n" -//usage: "Query and set hardware clock (RTC)\n" -//usage: "\n -r Show hardware clock time" +//usage: "Show or set hardware clock (RTC)\n" +///////: "\n -r Show hardware clock time" +///////-r is default, don't bother showing it in help //usage: "\n -s Set system time from hardware clock" //usage: "\n -w Set hardware clock from system time" //usage: IF_LONG_OPTS( diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index 823e55662..be7e95099 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c @@ -32,28 +32,22 @@ //kbuild:lib-$(CONFIG_RTCWAKE) += rtcwake.o +//usage:#if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS +//usage:# define ADJTIME_PATH "/var/lib/hwclock/adjtime" +//usage:#else +//usage:# define ADJTIME_PATH "/etc/adjtime" +//usage:#endif //usage:#define rtcwake_trivial_usage //usage: "[-a | -l | -u] [-d DEV] [-m MODE] [-s SEC | -t TIME]" //usage:#define rtcwake_full_usage "\n\n" //usage: "Enter a system sleep state until specified wakeup time\n" -//usage: IF_LONG_OPTS( -//usage: "\n -a,--auto Read clock mode from adjtime" -//usage: "\n -l,--local Clock is set to local time" -//usage: "\n -u,--utc Clock is set to UTC time" -//usage: "\n -d,--device DEV Specify the RTC device" -//usage: "\n -m,--mode MODE Set sleep state (default: standby)" -//usage: "\n -s,--seconds SEC Set timeout in SEC seconds from now" -//usage: "\n -t,--time TIME Set timeout to TIME seconds from epoch" -//usage: ) -//usage: IF_NOT_LONG_OPTS( -//usage: "\n -a Read clock mode from adjtime" +//usage: "\n -a Read clock mode from "ADJTIME_PATH" (default)" //usage: "\n -l Clock is set to local time" //usage: "\n -u Clock is set to UTC time" //usage: "\n -d DEV Specify the RTC device" //usage: "\n -m MODE Set sleep state (default: standby)" //usage: "\n -s SEC Set timeout in SEC seconds from now" //usage: "\n -t TIME Set timeout to TIME seconds from epoch" -//usage: ) #include "libbb.h" #include "rtc_.h" -- cgit v1.2.3-55-g6feb From 8506dd673030539b2890dd617f885ec20f1e8a7d Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 10 Dec 2020 14:44:57 +0000 Subject: lineedit: omit directories when tab-completing from PATH Only files should be matched when using PATH for tab-completion. function old new delta complete_cmd_dir_file 883 894 +11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 11/0) Total: 11 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index a3b798e3f..d64d7d0c2 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -871,6 +871,9 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) strcpy(found, name_found); if (S_ISDIR(st.st_mode)) { + /* skip directories if searching PATH */ + if (type == FIND_EXE_ONLY && !dirbuf) + goto cont; /* name is a directory, add slash */ found[len] = '/'; found[len + 1] = '\0'; -- cgit v1.2.3-55-g6feb From 8baa643a3445882ec9c39dfcabb7374081c13aee Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 11 Dec 2020 12:34:21 +0000 Subject: lineedit: match local directories when searching PATH When tab-completing a command we search PATH if the partial text doesn't include a slash. Also match subdirectories of the current directory, in case the user intends to run a binary from one of them. function old new delta complete_cmd_dir_file 894 917 +23 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 23/0) Total: 23 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index d64d7d0c2..5eb701f00 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -753,7 +753,7 @@ static int path_parse(char ***p) return 1; tmp = (char*)pth; - npth = 1; /* path component count */ + npth = 2; /* path component count */ while (1) { tmp = strchr(tmp, ':'); if (!tmp) @@ -776,6 +776,8 @@ static int path_parse(char ***p) break; /* : */ res[npth++] = tmp; } + /* special case: match subdirectories of the current directory */ + res[npth++] = NULL; return npth; } @@ -843,6 +845,11 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) struct stat st; char *found; + if (paths[i] == NULL) { + type = FIND_DIR_ONLY; + paths[i] = (char *)"."; + } + dir = opendir(paths[i]); if (!dir) continue; /* don't print an error */ -- cgit v1.2.3-55-g6feb From eaced1ec85315b9e11226f9a4ab935066e6946a0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 16 Dec 2020 10:01:21 +0100 Subject: lineedit: remove ->path_lookup if ash is not configured Signed-off-by: Denys Vlasenko --- include/libbb.h | 16 +++++++++++----- libbb/lineedit.c | 2 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 202e3f39c..6b7141456 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1863,14 +1863,20 @@ typedef const char *get_exe_name_t(int i) FAST_FUNC; typedef struct line_input_t { int flags; int timeout; +# if ENABLE_FEATURE_TAB_COMPLETION +# if ENABLE_SHELL_ASH const char *path_lookup; -# if ENABLE_FEATURE_TAB_COMPLETION \ -&& (ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \ -|| ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH \ -) +# define EDITING_HAS_path_lookup 1 +# else +# define EDITING_HAS_path_lookup 0 +# endif +# 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 +# define EDITING_HAS_get_exe_name 1 +# else +# define EDITING_HAS_get_exe_name 0 +# endif # endif # if MAX_HISTORY int cnt_history; diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 5eb701f00..1a3f29656 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -743,9 +743,11 @@ static int path_parse(char ***p) char *tmp; char **res; +#if EDITING_HAS_path_lookup if (state->flags & WITH_PATH_LOOKUP) pth = state->path_lookup; else +#endif pth = getenv("PATH"); /* PATH="" or PATH=":"? */ -- cgit v1.2.3-55-g6feb From 1d180cd7493f0a88fa39229cddcb30a0e44ade4c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 16 Dec 2020 10:59:20 +0100 Subject: lineedit: use strncmp instead of is_prefixed_with (we know the length) Also: add comments, rename some variables Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 1a3f29656..0c48e8179 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -736,9 +736,9 @@ enum { FIND_FILE_ONLY = 2, }; -static int path_parse(char ***p) +static unsigned path_parse(char ***p) { - int npth; + unsigned npth; const char *pth; char *tmp; char **res; @@ -755,7 +755,7 @@ static int path_parse(char ***p) return 1; tmp = (char*)pth; - npth = 2; /* path component count */ + npth = 1; /* path component count */ while (1) { tmp = strchr(tmp, ':'); if (!tmp) @@ -766,7 +766,7 @@ static int path_parse(char ***p) npth++; } - *p = res = xmalloc(npth * sizeof(res[0])); + *p = res = xzalloc((npth + 1) * sizeof(res[0])); res[0] = tmp = xstrdup(pth); npth = 1; while (1) { @@ -778,8 +778,8 @@ static int path_parse(char ***p) break; /* : */ res[npth++] = tmp; } - /* special case: match subdirectories of the current directory */ - res[npth++] = NULL; + /* special case: "match subdirectories of the current directory" */ + /*res[npth++] = NULL; - filled by xzalloc() */ return npth; } @@ -790,38 +790,38 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) { char *path1[1]; char **paths = path1; - int npaths; - int i; - unsigned pf_len; - const char *pfind; + unsigned npaths; + unsigned i; + unsigned baselen; + const char *basecmd; char *dirbuf = NULL; npaths = 1; path1[0] = (char*)"."; - pfind = strrchr(command, '/'); - if (!pfind) { + basecmd = strrchr(command, '/'); + if (!basecmd) { if (type == FIND_EXE_ONLY) npaths = path_parse(&paths); - pfind = command; + basecmd = command; } else { /* point to 'l' in "..../last_component" */ - pfind++; + basecmd++; /* dirbuf = ".../.../.../" */ - dirbuf = xstrndup(command, pfind - command); + dirbuf = xstrndup(command, basecmd - command); # if ENABLE_FEATURE_USERNAME_COMPLETION if (dirbuf[0] == '~') /* ~/... or ~user/... */ dirbuf = username_path_completion(dirbuf); # endif path1[0] = dirbuf; } - pf_len = strlen(pfind); + baselen = strlen(basecmd); if (type == FIND_EXE_ONLY && !dirbuf) { # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 const char *p = applet_names; while (*p) { - if (strncmp(pfind, p, pf_len) == 0) + if (strncmp(basecmd, p, baselen) == 0) add_match(xstrdup(p)); while (*p++ != '\0') continue; @@ -834,7 +834,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) const char *b = state->get_exe_name(i++); if (!b) break; - if (strncmp(pfind, b, pf_len) == 0) + if (strncmp(basecmd, b, baselen) == 0) add_match(xstrdup(b)); } } @@ -847,7 +847,10 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) struct stat st; char *found; - if (paths[i] == NULL) { + if (paths[i] == NULL) { /* path_parse()'s last component? */ + /* in PATH completion, current dir's subdir names + * can be completions (but only subdirs, not files). + */ type = FIND_DIR_ONLY; paths[i] = (char *)"."; } @@ -861,10 +864,10 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) const char *name_found = next->d_name; /* .../: bash 3.2.0 shows dotfiles, but not . and .. */ - if (!pfind[0] && DOT_OR_DOTDOT(name_found)) + if (!basecmd[0] && DOT_OR_DOTDOT(name_found)) continue; /* match? */ - if (!is_prefixed_with(name_found, pfind)) + if (strncmp(basecmd, name_found, baselen) != 0) continue; /* no */ found = concat_path_file(paths[i], name_found); @@ -906,7 +909,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) } free(dirbuf); - return pf_len; + return baselen; } /* build_match_prefix: -- cgit v1.2.3-55-g6feb From a97a795dcb41943943b8ecfe039e23673365af55 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 16 Dec 2020 11:14:08 +0100 Subject: lineedit: disable completion and fancy prompts if no shells are selected function old new delta get_previous_history 51 56 +5 get_next_history 47 52 +5 null_str 1 - -1 beep 10 - -10 bb_msg_unknown 10 - -10 bb_internal_setpwent 24 - -24 remove_chunk 30 - -30 goto_new_line 33 - -33 bb_internal_endpwent 36 - -36 deinit_S 51 - -51 free_tab_completion_data 54 - -54 read_line_input 3171 3114 -57 rewind 68 - -68 add_match 70 - -70 complete_username 77 - -77 quote_special_chars 78 - -78 build_match_prefix 557 - -557 complete_cmd_dir_file 697 - -697 parse_and_put_prompt 823 53 -770 input_tab 926 - -926 ------------------------------------------------------------------------------ (add/remove: 0/17 grow/shrink: 2/2 up/down: 10/-3549) Total: -3539 bytes Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 0c48e8179..c3b5738e2 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -57,12 +57,23 @@ #if ENABLE_FEATURE_EDITING +#if !ENABLE_SHELL_ASH && !ENABLE_SHELL_HUSH +/* so far only shells use these features */ +# undef ENABLE_FEATURE_EDITING_FANCY_PROMPT +# undef ENABLE_FEATURE_TAB_COMPLETION +# undef ENABLE_FEATURE_USERNAME_COMPLETION +# define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0 +# define ENABLE_FEATURE_TAB_COMPLETION 0 +# define ENABLE_FEATURE_USERNAME_COMPLETION 0 +#endif + + #define ENABLE_USERNAME_OR_HOMEDIR \ (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) -#define IF_USERNAME_OR_HOMEDIR(...) #if ENABLE_USERNAME_OR_HOMEDIR -# undef IF_USERNAME_OR_HOMEDIR # define IF_USERNAME_OR_HOMEDIR(...) __VA_ARGS__ +#else +# define IF_USERNAME_OR_HOMEDIR(...) /*nothing*/ #endif @@ -743,11 +754,11 @@ static unsigned path_parse(char ***p) char *tmp; char **res; -#if EDITING_HAS_path_lookup +# if EDITING_HAS_path_lookup if (state->flags & WITH_PATH_LOOKUP) pth = state->path_lookup; else -#endif +# endif pth = getenv("PATH"); /* PATH="" or PATH=":"? */ @@ -1885,9 +1896,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) { int prmt_size = 0; char *prmt_mem_ptr = xzalloc(1); -# if ENABLE_USERNAME_OR_HOMEDIR char *cwd_buf = NULL; -# endif char flg_not_length = '['; char cbuf[2]; @@ -1954,11 +1963,9 @@ static void parse_and_put_prompt(const char *prmt_ptr) c = *prmt_ptr++; switch (c) { -# if ENABLE_USERNAME_OR_HOMEDIR case 'u': pbuf = user_buf ? user_buf : (char*)""; break; -# endif case 'H': case 'h': pbuf = free_me = safe_gethostname(); @@ -1976,7 +1983,6 @@ static void parse_and_put_prompt(const char *prmt_ptr) strftime_HHMMSS(timebuf, sizeof(timebuf), NULL)[-3] = '\0'; pbuf = timebuf; break; -# if ENABLE_USERNAME_OR_HOMEDIR case 'w': /* current dir */ case 'W': /* basename of cur dir */ if (!cwd_buf) { @@ -2003,7 +2009,6 @@ static void parse_and_put_prompt(const char *prmt_ptr) if (cp) pbuf = (char*)cp + 1; break; -# endif // bb_process_escape_sequence does this now: // case 'e': case 'E': /* \e \E = \033 */ // c = '\033'; @@ -2064,10 +2069,8 @@ static void parse_and_put_prompt(const char *prmt_ptr) free(free_me); } /* while */ -# if ENABLE_USERNAME_OR_HOMEDIR if (cwd_buf != (char *)bb_msg_unknown) free(cwd_buf); -# endif /* see comment (above this function) about multiline prompt redrawing */ cmdedit_prompt = prompt_last_line = prmt_mem_ptr; prmt_ptr = strrchr(cmdedit_prompt, '\n'); @@ -2075,7 +2078,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) prompt_last_line = prmt_ptr + 1; put_prompt(); } -#endif +#endif /* FEATURE_EDITING_FANCY_PROMPT */ #if ENABLE_FEATURE_EDITING_WINCH static void cmdedit_setwidth(void) -- cgit v1.2.3-55-g6feb From 9e262f13c2e53490d69d3112ffd718c27de04d1f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 16 Dec 2020 13:49:10 +0100 Subject: hwclock: fix musl breakage of settimeofday(tz) function old new delta set_kernel_timezone_and_clock - 119 +119 set_kernel_tz - 28 +28 hwclock_main 480 301 -179 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/1 up/down: 147/-179) Total: -32 bytes Signed-off-by: Denys Vlasenko --- util-linux/hwclock.c | 128 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 53 deletions(-) diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 791525fc2..44cb4794e 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -36,6 +36,19 @@ #include #include "rtc_.h" + +//musl has no __MUSL__ or similar define to check for, +//but its has these lines: +// #define __NEED_fsblkcnt_t +// #define __NEED_fsfilcnt_t +#if defined(__linux__) && defined(__NEED_fsblkcnt_t) && defined(__NEED_fsfilcnt_t) +# define LIBC_IS_MUSL 1 +# include +#else +# define LIBC_IS_MUSL 0 +#endif + + /* diff code is disabled: it's not sys/hw clock diff, it's some useless * "time between hwclock was started and we saw CMOS tick" quantity. * It's useless since hwclock is started at a random moment, @@ -116,26 +129,73 @@ static void show_clock(const char **pp_rtcname, int utc) #endif } -static void to_sys_clock(const char **pp_rtcname, int utc) +static void set_kernel_tz(const struct timezone *tz) { - struct timeval tv; - struct timezone tz; - - tz.tz_minuteswest = timezone / 60; - /* ^^^ used to also subtract 60*daylight, but it's wrong: - * daylight!=0 means "this timezone has some DST - * during the year", not "DST is in effect now". +#if LIBC_IS_MUSL + /* musl libc does not pass tz argument to syscall + * because "it's deprecated by POSIX, therefore it's fine + * if we gratuitously break stuff" :( */ - tz.tz_dsttime = 0; - - /* glibc v2.31+ returns an error if both args are non-NULL */ - if (settimeofday(NULL, &tz)) +#if !defined(SYS_settimeofday) && defined(SYS_settimeofday_time32) +# define SYS_settimeofday SYS_settimeofday_time32 +#endif + int ret = syscall(SYS_settimeofday, NULL, tz); +#else + int ret = settimeofday(NULL, tz); +#endif + if (ret) bb_simple_perror_msg_and_die("settimeofday"); +} + +/* + * At system boot, kernel may set system time from RTC, + * but it knows nothing about timezones. If RTC is in local time, + * then system time is wrong - it is offset by timezone. + * --systz option corrects system time if RTC is in local time, + * and (always) sets in-kernel timezone. + * + * This is an alternate option to --hctosys that does not read the + * hardware clock. + * + * util-linux's code has this comment: + * RTC | settimeofday calls + * ------|------------------------------------------------- + * Local | 1) warps system time*, sets PCIL* and kernel tz + * UTC | 1st) locks warp_clock 2nd) sets kernel tz + * * only on first call after boot + * (PCIL is "persistent_clock_is_local" kernel internal flag, + * it makes kernel save RTC in local time, not UTC.) + */ +static void set_kernel_timezone_and_clock(int utc, const struct timeval *hctosys) +{ + time_t cur; + struct tm *broken; + struct timezone tz = { 0 }; + + /* if --utc, prevent kernel's warp_clock() with a dummy call */ + if (utc) + set_kernel_tz(&tz); + + /* Set kernel's timezone offset based on userspace one */ + cur = time(NULL); + broken = localtime(&cur); + tz.tz_minuteswest = -broken->tm_gmtoff / 60; + /*tz.tz_dsttime = 0; already is */ + set_kernel_tz(&tz); /* MIGHT warp_clock() if 1st call since boot */ + + if (hctosys) { /* it's --hctosys: set time too */ + if (settimeofday(hctosys, NULL)) + bb_simple_perror_msg_and_die("settimeofday"); + } +} + +static void to_sys_clock(const char **pp_rtcname, int utc) +{ + struct timeval tv; tv.tv_sec = read_rtc(pp_rtcname, NULL, utc); tv.tv_usec = 0; - if (settimeofday(&tv, NULL)) - bb_simple_perror_msg_and_die("settimeofday"); + return set_kernel_timezone_and_clock(utc, &tv); } static void from_sys_clock(const char **pp_rtcname, int utc) @@ -261,39 +321,6 @@ static void from_sys_clock(const char **pp_rtcname, int utc) close(rtc); } -/* - * At system boot, kernel may set system time from RTC, - * but it knows nothing about timezones. If RTC is in local time, - * then system time is wrong - it is offset by timezone. - * This option corrects system time if RTC is in local time, - * and (always) sets in-kernel timezone. - * - * This is an alternate option to --hctosys that does not read the - * hardware clock. - */ -static void set_system_clock_timezone(int utc) -{ - struct timeval tv; - struct tm *broken; - struct timezone tz; - - gettimeofday(&tv, NULL); - broken = localtime(&tv.tv_sec); - tz.tz_minuteswest = timezone / 60; - if (broken->tm_isdst > 0) - tz.tz_minuteswest -= 60; - tz.tz_dsttime = 0; - gettimeofday(&tv, NULL); - if (!utc) - tv.tv_sec += tz.tz_minuteswest * 60; - - /* glibc v2.31+ returns an error if both args are non-NULL */ - if (settimeofday(NULL, &tz)) - bb_simple_perror_msg_and_die("settimeofday"); - if (settimeofday(&tv, NULL)) - bb_simple_perror_msg_and_die("settimeofday"); -} - //usage:#define hwclock_trivial_usage //usage: IF_LONG_OPTS( //usage: "[-swu] [--systz] [--localtime] [-f FILE]" @@ -333,7 +360,6 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) const char *rtcname = NULL; unsigned opt; int utc; - #if ENABLE_LONG_OPTS static const char hwclock_longopts[] ALIGN1 = "localtime\0" No_argument "l" /* short opt is non-standard */ @@ -345,10 +371,6 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) "rtc\0" Required_argument "f" ; #endif - - /* Initialize "timezone" (libc global variable) */ - tzset(); - opt = getopt32long(argv, "^lurswtf:" "\0" "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l", hwclock_longopts, @@ -366,7 +388,7 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) else if (opt & HWCLOCK_OPT_SYSTOHC) from_sys_clock(&rtcname, utc); else if (opt & HWCLOCK_OPT_SYSTZ) - set_system_clock_timezone(utc); + set_kernel_timezone_and_clock(utc, NULL); else /* default HWCLOCK_OPT_SHOW */ show_clock(&rtcname, utc); -- cgit v1.2.3-55-g6feb From d3c36882dc5bc5fcede9a45a6bc7a39570fba7d0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 16 Dec 2020 20:55:30 +0100 Subject: hwclock: improve --help (-l is a compatible shortcut for --localtime) function old new delta packed_usage 33605 33568 -37 Signed-off-by: Denys Vlasenko --- util-linux/hwclock.c | 69 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 44cb4794e..77aa2d7c3 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -153,14 +153,12 @@ static void set_kernel_tz(const struct timezone *tz) * then system time is wrong - it is offset by timezone. * --systz option corrects system time if RTC is in local time, * and (always) sets in-kernel timezone. - * - * This is an alternate option to --hctosys that does not read the - * hardware clock. + * (Unlike --hctosys, it does not read the RTC). * * util-linux's code has this comment: * RTC | settimeofday calls * ------|------------------------------------------------- - * Local | 1) warps system time*, sets PCIL* and kernel tz + * Local | 1st) warps system time*, sets PCIL* and kernel tz * UTC | 1st) locks warp_clock 2nd) sets kernel tz * * only on first call after boot * (PCIL is "persistent_clock_is_local" kernel internal flag, @@ -177,6 +175,9 @@ static void set_kernel_timezone_and_clock(int utc, const struct timeval *hctosys set_kernel_tz(&tz); /* Set kernel's timezone offset based on userspace one */ +//It's tempting to call tzset() and use libc global "timezone" variable +//...but it does NOT include DST shift (IOW: it's WRONG, usually by one hour, +//if DST is in effect!) Thus this ridiculous dance: cur = time(NULL); broken = localtime(&cur); tz.tz_minuteswest = -broken->tm_gmtoff / 60; @@ -321,30 +322,58 @@ static void from_sys_clock(const char **pp_rtcname, int utc) close(rtc); } +// hwclock from util-linux 2.36.1 +// hwclock [function] [option...] +//Functions: +// -r, --show display the RTC time +// --get display drift corrected RTC time +// --set set the RTC according to --date +// -s, --hctosys set the system time from the RTC +// -w, --systohc set the RTC from the system time +// --systz send timescale configurations to the kernel +// -a, --adjust adjust the RTC to account for systematic drift +// --predict predict the drifted RTC time according to --date +//Options: +// -u, --utc the RTC timescale is UTC +// -l, --localtime the RTC timescale is Local +// -f, --rtc use an alternate file to /dev/rtc0 +// --directisa use the ISA bus instead of /dev/rtc0 access +// --date