From 8d8ee910f0a624fefd2a4aaefeb406003dea7807 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 25 Dec 2017 21:36:05 +0100 Subject: env: -u option fails due to typo The -u option is supposed to be allowed to appear multiple times; the option string supplied to getopt32long requires it to be followed by a nonnegative integer. Reported-by: Keith Maxwell Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- coreutils/env.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/env.c b/coreutils/env.c index 20453e871..0aebead1b 100644 --- a/coreutils/env.c +++ b/coreutils/env.c @@ -54,7 +54,7 @@ int env_main(int argc UNUSED_PARAM, char **argv) unsigned opts; llist_t *unset_env = NULL; - opts = getopt32long(argv, "+iu:+", + opts = getopt32long(argv, "+iu:*", "ignore-environment\0" No_argument "i" "unset\0" Required_argument "u" , &unset_env -- cgit v1.2.3-55-g6feb From 36acc4631c94bb0f43ecaac5d61dc773ef773e91 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Dec 2017 20:19:37 +0100 Subject: ntpd: do run the script at leat once in 11 minutes function old new delta ntpd_main 1197 1226 +29 Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 0b60d003b..17e5c7da6 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -2362,7 +2362,9 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) /* Nothing between here and poll() blocks for any significant time */ - nextaction = G.cur_time + 3600; + nextaction = G.last_script_run + (11*60); + if (nextaction < G.cur_time + 1) + nextaction = G.cur_time + 1; i = 0; #if ENABLE_FEATURE_NTPD_SERVER -- cgit v1.2.3-55-g6feb From 82d1c1f84ae23793d81b50aa0a753ad7c4db4f51 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 31 Dec 2017 17:30:02 +0100 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- coreutils/cat.c | 5 ++++- coreutils/ls.c | 5 ++--- coreutils/stat.c | 7 +++++-- coreutils/uname.c | 6 ++---- libbb/Kbuild.src | 1 + libbb/lineedit.c | 3 ++- loginutils/addgroup.c | 7 ++++++- make_single_applets.sh | 3 ++- networking/tftp.c | 3 ++- procps/kill.c | 7 ++++++- scripts/randomtest.loop | 1 + shell/ash.c | 2 +- shell/hush.c | 13 ++++++++----- 13 files changed, 42 insertions(+), 21 deletions(-) diff --git a/coreutils/cat.c b/coreutils/cat.c index 7e35fa5ee..5f02233ca 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -168,9 +168,12 @@ static int catv(unsigned opts, char **argv) int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int cat_main(int argc UNUSED_PARAM, char **argv) { +#if ENABLE_FEATURE_CATV || ENABLE_FEATURE_CATN unsigned opts; - opts = getopt32(argv, IF_FEATURE_CATV("^") + opts = +#endif + getopt32(argv, IF_FEATURE_CATV("^") /* -u is ignored ("unbuffered") */ IF_FEATURE_CATV("etvA")IF_FEATURE_CATN("nb")"u" IF_FEATURE_CATV("\0" "Aetv" /* -A == -vet */) diff --git a/coreutils/ls.c b/coreutils/ls.c index a4e324b00..4be499088 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -482,12 +482,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn) int opt; #if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR struct stat statbuf; - char append; #endif - #if ENABLE_FEATURE_LS_FILETYPES - append = append_char(dn->dn_mode); + char append = append_char(dn->dn_mode); #endif + opt = option_mask32; /* Do readlink early, so that if it fails, error message diff --git a/coreutils/stat.c b/coreutils/stat.c index dafbd4e9f..7ba3db155 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c @@ -759,10 +759,13 @@ int stat_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_STAT_FORMAT(char *format = NULL;) int i; int ok; - unsigned opts; statfunc_ptr statfunc = do_stat; +#if ENABLE_FEATURE_STAT_FILESYSTEM || ENABLE_SELINUX + unsigned opts; - opts = getopt32(argv, "^" + opts = +#endif + getopt32(argv, "^" "tL" IF_FEATURE_STAT_FILESYSTEM("f") IF_SELINUX("Z") diff --git a/coreutils/uname.c b/coreutils/uname.c index 57039b1bf..765809658 100644 --- a/coreutils/uname.c +++ b/coreutils/uname.c @@ -127,11 +127,9 @@ int uname_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { uname_info_t uname_info; IF_UNAME(const char *unknown_str = "unknown";) - unsigned toprint; - - toprint = (1 << 4); /* "arch" = "uname -m" */ - #if ENABLE_UNAME + unsigned toprint = (1 << 4); /* "arch" = "uname -m" */ + if (!ENABLE_BB_ARCH || applet_name[0] == 'u') { # if ENABLE_LONG_OPTS static const char uname_longopts[] ALIGN1 = diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 73201a6bd..6e6d71ad5 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -124,6 +124,7 @@ lib-$(CONFIG_UNICODE_SUPPORT) += unicode.o lib-$(CONFIG_FEATURE_CHECK_NAMES) += die_if_bad_username.o lib-$(CONFIG_NC) += udp_io.o +lib-$(CONFIG_NETCAT) += udp_io.o lib-$(CONFIG_DNSD) += udp_io.o lib-$(CONFIG_NTPD) += udp_io.o lib-$(CONFIG_TFTP) += udp_io.o diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 5624a7fc3..896bbc88c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -90,7 +90,8 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } # define CHAR_T char # define BB_isspace(c) isspace(c) # if ENABLE_FEATURE_EDITING_VI -static bool BB_isalnum_or_underscore(CHAR_T c) { +static bool BB_isalnum_or_underscore(CHAR_T c) +{ return ((unsigned)c < 256 && isalnum(c)) || c == '_'; } # endif diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index ec11b30ca..6839eafbd 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c @@ -142,7 +142,9 @@ static const char addgroup_longopts[] ALIGN1 = int addgroup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int addgroup_main(int argc UNUSED_PARAM, char **argv) { +#if ENABLE_FEATURE_ADDUSER_TO_GROUP unsigned opts; +#endif const char *gid = "0"; /* need to be root */ @@ -154,7 +156,10 @@ int addgroup_main(int argc UNUSED_PARAM, char **argv) * addgroup --gid num group * addgroup user group * Check for min, max and missing args */ - opts = getopt32long(argv, "^" "g:S" "\0" "-1:?2", addgroup_longopts, +#if ENABLE_FEATURE_ADDUSER_TO_GROUP + opts = +#endif + getopt32long(argv, "^" "g:S" "\0" "-1:?2", addgroup_longopts, &gid ); /* move past the commandline options */ diff --git a/make_single_applets.sh b/make_single_applets.sh index 329a27d32..aa1ace265 100755 --- a/make_single_applets.sh +++ b/make_single_applets.sh @@ -12,8 +12,9 @@ makeopts="-j9" test -f include/applets.h || { echo "No include/applets.h file"; exit 1; } apps="` grep ^IF_ include/applets.h \ -| grep -v ^IF_FEATURE_ \ +| grep -v '^IF_FEATURE_' \ | sed 's/IF_\([A-Z0-9._-]*\)(.*/\1/' \ +| grep -v '^BUSYBOX$' \ | sort | uniq `" diff --git a/networking/tftp.c b/networking/tftp.c index 73a9829aa..4cd39186a 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -208,7 +208,7 @@ struct globals { #define G_error_pkt_reason (G.error_pkt[3]) #define G_error_pkt_str ((char*)(G.error_pkt + 4)) -#if ENABLE_FEATURE_TFTP_PROGRESS_BAR +#if ENABLE_FEATURE_TFTP_PROGRESS_BAR && ENABLE_FEATURE_TFTP_BLOCKSIZE static void tftp_progress_update(void) { bb_progress_update(&G.pmt, 0, G.pos, G.size); @@ -227,6 +227,7 @@ static void tftp_progress_done(void) } } #else +# define tftp_progress_update() ((void)0) # define tftp_progress_init() ((void)0) # define tftp_progress_done() ((void)0) #endif diff --git a/procps/kill.c b/procps/kill.c index 24cc903fc..c95afb8b3 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -108,7 +108,10 @@ int kill_main(int argc UNUSED_PARAM, char **argv) { char *arg; pid_t pid; - int signo = SIGTERM, errors = 0, quiet = 0; + int signo = SIGTERM, errors = 0; +#if ENABLE_KILL || ENABLE_KILLALL + int quiet = 0; +#endif #if KILL_APPLET_CNT == 1 # define is_killall ENABLE_KILLALL @@ -170,7 +173,9 @@ int kill_main(int argc UNUSED_PARAM, char **argv) /* The -q quiet option */ if (is_killall && arg[1] == 'q' && arg[2] == '\0') { +#if ENABLE_KILL || ENABLE_KILLALL quiet = 1; +#endif arg = *++argv; if (!arg) bb_show_usage(); diff --git a/scripts/randomtest.loop b/scripts/randomtest.loop index 4d14b652f..edfbc5c58 100755 --- a/scripts/randomtest.loop +++ b/scripts/randomtest.loop @@ -66,6 +66,7 @@ while sleep 1; do continue fi fi + grep -i 'warning:' "$dir/make.log" rm -rf -- "$dir" let cnt++ done diff --git a/shell/ash.c b/shell/ash.c index e69ddb4ff..dfb7d4d8e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9952,7 +9952,7 @@ evalcommand(union node *cmd, int flags) switch (cmdentry.cmdtype) { default: { -#if ENABLE_FEATURE_SH_NOFORK +#if ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1 /* (1) BUG: if variables are set, we need to fork, or save/restore them * around run_nofork_applet() call. * (2) Should this check also be done in forkshell()? diff --git a/shell/hush.c b/shell/hush.c index 708555ac4..df1b046ab 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2278,7 +2278,7 @@ static int unset_local_var_len(const char *name, int name_len) return EXIT_SUCCESS; } -#if ENABLE_HUSH_UNSET +#if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS static int unset_local_var(const char *name) { return unset_local_var_len(name, strlen(name)); @@ -2300,7 +2300,7 @@ static void unset_vars(char **strings) free(strings); } -#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ +#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ || ENABLE_HUSH_GETOPTS static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) { char *var = xasprintf("%s=%s", name, val); @@ -5534,7 +5534,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha static char *encode_then_expand_string(const char *str, int process_bkslash, int do_unbackslash) { #if !BASH_PATTERN_SUBST - const int do_unbackslash = 1; + enum { do_unbackslash = 1 }; #endif char *exp_str; struct in_str input; @@ -8139,7 +8139,7 @@ static NOINLINE int run_pipe(struct pipe *pi) return rcode; } - if (ENABLE_FEATURE_SH_NOFORK) { + if (ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1) { int n = find_applet_by_name(argv_expanded[0]); if (n >= 0 && APPLET_IS_NOFORK(n)) { rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, &squirrel, argv_expanded); @@ -8387,7 +8387,10 @@ static int run_list(struct pipe *pi) rword, cond_code, last_rword); sv_errexit_depth = G.errexit_depth; - if (IF_HAS_KEYWORDS(rword == RES_IF || rword == RES_ELIF ||) + if ( +#if ENABLE_HUSH_IF + rword == RES_IF || rword == RES_ELIF || +#endif pi->followup != PIPE_SEQ ) { G.errexit_depth++; -- cgit v1.2.3-55-g6feb From b013bec31bbfdfb264f3fd30990d956ebf73379c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 31 Dec 2017 17:59:16 +0100 Subject: chown: fix a mistake in opt_complementary change Signed-off-by: Denys Vlasenko --- coreutils/chown.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coreutils/chown.c b/coreutils/chown.c index 985d18d6f..6429fd030 100644 --- a/coreutils/chown.c +++ b/coreutils/chown.c @@ -128,9 +128,9 @@ int chown_main(int argc UNUSED_PARAM, char **argv) struct param_t param; #if ENABLE_FEATURE_CHOWN_LONG_OPTIONS - opt = getopt32long(argv, "^" OPT_STR "\0" "=2", chown_longopts); + opt = getopt32long(argv, "^" OPT_STR "\0" "-2", chown_longopts); #else - opt = getopt32(argv, "^" OPT_STR "\0" "=2"); + opt = getopt32(argv, "^" OPT_STR "\0" "-2"); #endif argv += optind; -- cgit v1.2.3-55-g6feb From 9c9a742e80f0d288a1e1a91ea913a3d33f2dac35 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 31 Dec 2017 20:31:05 +0100 Subject: scripts/randomtest: do not try building static libbysubox Signed-off-by: Denys Vlasenko --- scripts/randomtest | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/randomtest b/scripts/randomtest index 1809838a4..635978338 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -52,6 +52,7 @@ echo '# CONFIG_RFKILL is not set' >>.config if test x"$LIBC" = x"glibc"; then cat .config \ | grep -v CONFIG_STATIC \ + | grep -v CONFIG_FEATURE_LIBBUSYBOX_STATIC \ \ | grep -v CONFIG_FEATURE_2_4_MODULES \ | grep -v CONFIG_FEATURE_USE_BSS_TAIL \ @@ -59,6 +60,7 @@ if test x"$LIBC" = x"glibc"; then >.config.new mv .config.new .config echo '# CONFIG_STATIC is not set' >>.config + echo '# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set' >>.config # newer glibc (at least 2.23) no longer supply query_module() ABI. # People who target 2.4 kernels would likely use older glibc (and older bbox). echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config -- cgit v1.2.3-55-g6feb From c0fab1ba496e27168898c0e74d8e3d11b9902999 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Jan 2018 06:07:28 +0100 Subject: Bump version to 1.28.0 Signed-off-by: Denys Vlasenko --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 56d05ce16..569c94a47 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 PATCHLEVEL = 28 SUBLEVEL = 0 -EXTRAVERSION = .git +EXTRAVERSION = NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From d75f9081d4a0e76bf4118232de3aef80116d5e0f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Jan 2018 06:11:19 +0100 Subject: Start 1.29.0 development cycle Signed-off-by: Denys Vlasenko --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 569c94a47..03a57adf3 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 -PATCHLEVEL = 28 +PATCHLEVEL = 29 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = .git NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From a034cab0952bcb93cfbe8b2a333c59615dfa7e90 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 4 Jan 2018 10:27:51 +0100 Subject: tc: enables this applet function old new delta tc_main - 946 +946 cbq_print_opt - 517 +517 print_qdisc - 475 +475 print_class - 359 +359 llproto_names - 264 +264 packed_usage 31853 32066 +213 ll_proto_a2n - 112 +112 llproto_ids - 86 +86 print_tc_classid - 82 +82 static.objects - 20 +20 static._q_ - 16 +16 applet_main 1564 1568 +4 print_filter - 3 +3 applet_names 2708 2711 +3 ------------------------------------------------------------------------------ (add/remove: 13/0 grow/shrink: 3/0 up/down: 3100/0) Total: 3100 bytes Signed-off-by: Denys Vlasenko --- networking/tc.c | 106 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 31 deletions(-) diff --git a/networking/tc.c b/networking/tc.c index 23abf636c..4e375a066 100644 --- a/networking/tc.c +++ b/networking/tc.c @@ -6,22 +6,20 @@ * * Bernhard Reutner-Fischer adjusted for busybox */ +//config:config TC +//config: bool "tc (3.1 kb)" +//config: default y +//config: help +//config: Show / manipulate traffic control settings +//config: +//config:config FEATURE_TC_INGRESS +//config: bool "Enable ingress" +//config: default y +//config: depends on TC -/* Was disabled in 2008 by Bernhard, not known why. ---//config:#config TC ---//config:# bool "tc" ---//config:# default y ---//config:# help ---//config:# Show / manipulate traffic control settings ---//config:# ---//config:#config FEATURE_TC_INGRESS ---//config:# default y ---//config:# depends on TC --- ---//applet:IF_TC(APPLET(tc, BB_DIR_SBIN, BB_SUID_DROP)) --- ---//kbuild:lib-$(CONFIG_TC) += tc.o -*/ +//applet:IF_TC(APPLET(tc, BB_DIR_SBIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_TC) += tc.o //usage:#define tc_trivial_usage /* //usage: "[OPTIONS] OBJECT CMD [dev STRING]" */ @@ -52,6 +50,17 @@ #include "libiproute/rt_names.h" #include /* for the TC_H_* macros */ +/* This is the deprecated multiqueue interface */ +#ifndef TCA_PRIO_MAX +enum +{ + TCA_PRIO_UNSPEC, + TCA_PRIO_MQ, + __TCA_PRIO_MAX +}; +#define TCA_PRIO_MAX (__TCA_PRIO_MAX - 1) +#endif + #define parse_rtattr_nested(tb, max, rta) \ (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta))) @@ -184,11 +193,13 @@ static void print_rate(char *buf, int len, uint32_t rate) } } +#if 0 /* This is "pfifo_fast". */ static int prio_parse_opt(int argc, char **argv, struct nlmsghdr *n) { return 0; } +#endif static int prio_print_opt(struct rtattr *opt) { int i; @@ -211,11 +222,13 @@ static int prio_print_opt(struct rtattr *opt) return 0; } +#if 0 /* Class Based Queue */ static int cbq_parse_opt(int argc, char **argv, struct nlmsghdr *n) { return 0; } +#endif static int cbq_print_opt(struct rtattr *opt) { struct rtattr *tb[TCA_CBQ_MAX+1]; @@ -308,8 +321,10 @@ static int cbq_print_opt(struct rtattr *opt) return 0; } -static int print_qdisc(const struct sockaddr_nl *who UNUSED_PARAM, - struct nlmsghdr *hdr, void *arg UNUSED_PARAM) +static FAST_FUNC int print_qdisc( + const struct sockaddr_nl *who UNUSED_PARAM, + struct nlmsghdr *hdr, + void *arg UNUSED_PARAM) { struct tcmsg *msg = NLMSG_DATA(hdr); int len = hdr->nlmsg_len; @@ -364,8 +379,10 @@ static int print_qdisc(const struct sockaddr_nl *who UNUSED_PARAM, return 0; } -static int print_class(const struct sockaddr_nl *who UNUSED_PARAM, - struct nlmsghdr *hdr, void *arg UNUSED_PARAM) +static FAST_FUNC int print_class( + const struct sockaddr_nl *who UNUSED_PARAM, + struct nlmsghdr *hdr, + void *arg UNUSED_PARAM) { struct tcmsg *msg = NLMSG_DATA(hdr); int len = hdr->nlmsg_len; @@ -432,8 +449,10 @@ static int print_class(const struct sockaddr_nl *who UNUSED_PARAM, return 0; } -static int print_filter(const struct sockaddr_nl *who UNUSED_PARAM, - struct nlmsghdr *hdr, void *arg UNUSED_PARAM) +static FAST_FUNC int print_filter( + const struct sockaddr_nl *who UNUSED_PARAM, + struct nlmsghdr *hdr UNUSED_PARAM, + void *arg UNUSED_PARAM) { return 0; } @@ -451,6 +470,12 @@ int tc_main(int argc UNUSED_PARAM, char **argv) "replace\0" "show\0""list\0" ; + enum { + CMD_add = 0, CMD_del, CMD_change, + CMD_link, + CMD_replace, + CMD_show + }; static const char args[] ALIGN1 = "dev\0" /* qdisc, class, filter */ "root\0" /* class, filter */ @@ -460,9 +485,15 @@ int tc_main(int argc UNUSED_PARAM, char **argv) "classid\0" /* change: for class use "handle" */ "preference\0""priority\0""protocol\0" /* filter */ ; - enum { CMD_add = 0, CMD_del, CMD_change, CMD_link, CMD_replace, CMD_show }; - enum { ARG_dev = 0, ARG_root, ARG_parent, ARG_qdisc, - ARG_handle, ARG_classid, ARG_pref, ARG_prio, ARG_proto}; + enum { + ARG_dev = 0, + ARG_root, + ARG_parent, + ARG_qdisc, + ARG_handle, + ARG_classid, + ARG_pref, ARG_prio, ARG_proto + }; struct rtnl_handle rth; struct tcmsg msg; int ret, obj, cmd, arg; @@ -487,9 +518,12 @@ int tc_main(int argc UNUSED_PARAM, char **argv) invarg_1_to_2(*argv, argv[-1]); argv++; } + memset(&msg, 0, sizeof(msg)); - msg.tcm_family = AF_UNSPEC; + if (AF_UNSPEC != 0) + msg.tcm_family = AF_UNSPEC; ll_init_map(&rth); + while (*argv) { arg = index_in_substrings(args, *argv); if (arg == ARG_dev) { @@ -526,7 +560,8 @@ int tc_main(int argc UNUSED_PARAM, char **argv) msg.tcm_parent = TC_H_ROOT; if (obj == OBJ_filter) filter_parent = TC_H_ROOT; - } else if (arg == ARG_parent) { + } else + if (arg == ARG_parent) { uint32_t handle; if (msg.tcm_parent) duparg(*argv, "parent"); @@ -535,23 +570,31 @@ int tc_main(int argc UNUSED_PARAM, char **argv) msg.tcm_parent = handle; if (obj == OBJ_filter) filter_parent = handle; - } else if (arg == ARG_handle) { /* filter::list */ + } else + if (arg == ARG_handle) { /* filter::list */ if (msg.tcm_handle) duparg(*argv, "handle"); /* reject LONG_MIN || LONG_MAX */ /* TODO: for fw slash = strchr(handle, '/'); if (slash != NULL) - *slash = '\0'; + *slash = '\0'; */ msg.tcm_handle = get_u32(*argv, "handle"); /* if (slash) {if (get_u32(uint32_t &mask, slash+1, NULL)) inv mask; addattr32(n, MAX_MSG, TCA_FW_MASK, mask); */ - } else if (arg == ARG_classid && obj == OBJ_class && cmd == CMD_change){ - } else if (arg == ARG_pref || arg == ARG_prio) { /* filter::list */ + } else + if (arg == ARG_classid + && obj == OBJ_class + && cmd == CMD_change + ) { + /* TODO */ + } else + if (arg == ARG_pref || arg == ARG_prio) { /* filter::list */ if (filter_prio) duparg(*argv, "priority"); filter_prio = get_u32(*argv, "priority"); - } else if (arg == ARG_proto) { /* filter::list */ + } else + if (arg == ARG_proto) { /* filter::list */ uint16_t tmp; if (filter_proto) duparg(*argv, "protocol"); @@ -560,6 +603,7 @@ int tc_main(int argc UNUSED_PARAM, char **argv) filter_proto = tmp; } } + if (cmd >= CMD_show) { /* show or list */ if (obj == OBJ_filter) msg.tcm_info = TC_H_MAKE(filter_prio<<16, filter_proto); -- cgit v1.2.3-55-g6feb From 84be5ce0d814780918771727e494fe4a2eb46636 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Thu, 28 Dec 2017 23:49:47 +0100 Subject: applets/install: respect noclobber for script wrappers too Simplify the handling of --noclobber so that it applies to all types of installation types, even to script wrappers. Signed-off-by: Yann E. MORIN Signed-off-by: Denys Vlasenko --- applets/install.sh | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/applets/install.sh b/applets/install.sh index f6c097e57..4b70df96e 100755 --- a/applets/install.sh +++ b/applets/install.sh @@ -77,6 +77,10 @@ install -m 755 busybox "$prefix/bin/busybox" || exit 1 for i in $h; do appdir=`dirname "$i"` app=`basename "$i"` + if [ "$noclobber" = "1" ] && [ -e "$prefix/$i" ]; then + echo " $prefix/$i already exists" + continue + fi mkdir -p "$prefix/$appdir" || exit 1 if [ "$scriptwrapper" = "y" ]; then if [ "$swrapall" != "y" ] && [ "$i" = "/bin/sh" ]; then @@ -90,12 +94,8 @@ for i in $h; do elif [ "$binaries" = "y" ]; then # Copy the binary over rather if [ -e $sharedlib_dir/$app ]; then - if [ "$noclobber" = "0" ] || [ ! -e "$prefix/$i" ]; then - echo " Copying $sharedlib_dir/$app to $prefix/$i" - cp -pPR $sharedlib_dir/$app $prefix/$i || exit 1 - else - echo " $prefix/$i already exists" - fi + echo " Copying $sharedlib_dir/$app to $prefix/$i" + cp -pPR $sharedlib_dir/$app $prefix/$i || exit 1 else echo "Error: Could not find $sharedlib_dir/$app" exit 1 @@ -123,12 +123,8 @@ for i in $h; do ;; esac fi - if [ "$noclobber" = "0" ] || [ ! -e "$prefix/$i" ]; then - echo " $prefix/$i -> $bb_path" - ln $linkopts "$bb_path" "$prefix/$i" || exit 1 - else - echo " $prefix/$i already exists" - fi + echo " $prefix/$i -> $bb_path" + ln $linkopts "$bb_path" "$prefix/$i" || exit 1 fi done -- cgit v1.2.3-55-g6feb From 952d5a6024e7b2a6d5a351a8d1329bd985da3c76 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Thu, 28 Dec 2017 23:49:48 +0100 Subject: applets/install: accept more than one install option Currently, it is impossible to pass more than one option to the isntall script, so it totally prevents using --noclobber. Signed-off-by: Yann E. MORIN Signed-off-by: Denys Vlasenko --- applets/install.sh | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/applets/install.sh b/applets/install.sh index 4b70df96e..ae99381d7 100755 --- a/applets/install.sh +++ b/applets/install.sh @@ -8,6 +8,7 @@ if [ -z "$prefix" ]; then echo "usage: applets/install.sh DESTINATION [--symlinks/--hardlinks/--binaries/--scriptwrapper]" exit 1 fi +shift # Keep only remaining options # Source the configuration . ./.config @@ -21,18 +22,21 @@ scriptwrapper="n" binaries="n" cleanup="0" noclobber="0" -case "$2" in - --hardlinks) linkopts="-f";; - --symlinks) linkopts="-fs";; - --binaries) binaries="y";; - --scriptwrapper) scriptwrapper="y";swrapall="y";; - --sw-sh-hard) scriptwrapper="y";linkopts="-f";; - --sw-sh-sym) scriptwrapper="y";linkopts="-fs";; - --cleanup) cleanup="1";; - --noclobber) noclobber="1";; - "") h="";; - *) echo "Unknown install option: $2"; exit 1;; -esac +while [ ${#} -gt 0 ]; do + case "$1" in + --hardlinks) linkopts="-f";; + --symlinks) linkopts="-fs";; + --binaries) binaries="y";; + --scriptwrapper) scriptwrapper="y"; swrapall="y";; + --sw-sh-hard) scriptwrapper="y"; linkopts="-f";; + --sw-sh-sym) scriptwrapper="y"; linkopts="-fs";; + --cleanup) cleanup="1";; + --noclobber) noclobber="1";; + "") h="";; + *) echo "Unknown install option: $1"; exit 1;; + esac + shift +done if [ -n "$DO_INSTALL_LIBS" ] && [ "$DO_INSTALL_LIBS" != "n" ]; then # get the target dir for the libs -- cgit v1.2.3-55-g6feb From a47375de8c7b0f4dcb95097c8119ea47b6e2636c Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Thu, 28 Dec 2017 23:49:49 +0100 Subject: build system: add rule to install without cloberring existing utilities Signed-off-by: Yann E. MORIN Signed-off-by: Denys Vlasenko --- Makefile.custom | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.custom b/Makefile.custom index 891c9ced7..28d0ef7bc 100644 --- a/Makefile.custom +++ b/Makefile.custom @@ -46,6 +46,9 @@ ifeq ($(strip $(CONFIG_FEATURE_SUID)),y) @echo endif +install-noclobber: INSTALL_OPTS+=--noclobber +install-noclobber: install + uninstall: busybox.links rm -f $(CONFIG_PREFIX)/bin/busybox for i in `cat busybox.links` ; do rm -f $(CONFIG_PREFIX)$$i; done -- cgit v1.2.3-55-g6feb From 7367a949a6a81d71d524f0635a212371120df4e0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 4 Jan 2018 15:21:25 +0100 Subject: libbb: compile obscure() only if FEATURE_PASSWD_WEAK_CHECK=y Signed-off-by: Denys Vlasenko --- libbb/Kbuild.src | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 6e6d71ad5..8c9ba8cca 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -143,7 +143,8 @@ lib-$(CONFIG_DELGROUP) += update_passwd.o lib-$(CONFIG_DELUSER) += update_passwd.o lib-$(CONFIG_FTPD) += pw_encrypt.o correct_password.o -lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o +lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o +lib-$(CONFIG_FEATURE_PASSWD_WEAK_CHECK) += obscure.o lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o lib-$(CONFIG_CRYPTPW) += pw_encrypt.o lib-$(CONFIG_MKPASSWD) += pw_encrypt.o -- cgit v1.2.3-55-g6feb From 6f4a785bd1bd0e6973b5c27b34b86655b1d7a602 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 7 Jan 2018 01:19:08 +0100 Subject: awk: fix 'delete array[var--]' decrementing var twice function old new delta evaluate 3395 3390 -5 Signed-off-by: Denys Vlasenko --- editors/awk.c | 54 ++++++++++++++++++++++++++++++----------------------- testsuite/awk.tests | 19 +++++++++++++++++++ 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/editors/awk.c b/editors/awk.c index d40c7816a..8f523ea28 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -2514,6 +2514,32 @@ static var *evaluate(node *op, var *res) op1 = op->l.n; debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn); + /* "delete" is special: + * "delete array[var--]" must evaluate index expr only once, + * must not evaluate it in "execute inevitable things" part. + */ + if (XC(opinfo & OPCLSMASK) == XC(OC_DELETE)) { + uint32_t info = op1->info & OPCLSMASK; + var *v; + + debug_printf_eval("DELETE\n"); + if (info == OC_VAR) { + v = op1->l.v; + } else if (info == OC_FNARG) { + v = &fnargs[op1->l.aidx]; + } else { + syntax_error(EMSG_NOT_ARRAY); + } + if (op1->r.n) { /* array ref? */ + const char *s; + s = getvar_s(evaluate(op1->r.n, v1)); + hash_remove(iamarray(v), s); + } else { + clear_array(iamarray(v)); + } + goto next; + } + /* execute inevitable things */ if (opinfo & OF_RES1) L.v = evaluate(op1, v1); @@ -2621,28 +2647,7 @@ static var *evaluate(node *op, var *res) break; } - case XC( OC_DELETE ): { - uint32_t info = op1->info & OPCLSMASK; - var *v; - - if (info == OC_VAR) { - v = op1->l.v; - } else if (info == OC_FNARG) { - v = &fnargs[op1->l.aidx]; - } else { - syntax_error(EMSG_NOT_ARRAY); - } - - if (op1->r.n) { - const char *s; - clrvar(L.v); - s = getvar_s(evaluate(op1->r.n, v1)); - hash_remove(iamarray(v), s); - } else { - clear_array(iamarray(v)); - } - break; - } + /* case XC( OC_DELETE ): - moved to happen before arg evaluation */ case XC( OC_NEWSOURCE ): g_progname = op->l.new_progname; @@ -2666,12 +2671,14 @@ static var *evaluate(node *op, var *res) /* -- recursive node type -- */ case XC( OC_VAR ): + debug_printf_eval("VAR\n"); L.v = op->l.v; if (L.v == intvar[NF]) split_f0(); goto v_cont; case XC( OC_FNARG ): + debug_printf_eval("FNARG[%d]\n", op->l.aidx); L.v = &fnargs[op->l.aidx]; v_cont: res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v; @@ -3035,7 +3042,8 @@ static var *evaluate(node *op, var *res) default: syntax_error(EMSG_POSSIBLE_ERROR); - } + } /* switch */ + next: if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS) op = op->a.n; if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS) diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 82937bc10..ad0583afb 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests @@ -261,6 +261,25 @@ end d " \ "" "" +prg=' +BEGIN{ +cnt = 0 +a[cnt] = "zeroth" +a[++cnt] = "first" +delete a[cnt--] +print cnt +print "[0]:" a[0] +print "[1]:" a[1] +}' +testing "awk 'delete a[v--]' evaluates v-- once" \ + "awk '$prg'" \ + "\ +0 +[0]:zeroth +[1]: +" \ + "" "" + testing "awk handles empty ()" \ "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" "" -- cgit v1.2.3-55-g6feb From 9c8e94bc0a3836dd6b8acbcf1fa88283a0a3c148 Mon Sep 17 00:00:00 2001 From: Ingo van Lil Date: Fri, 5 Jan 2018 15:04:23 +0100 Subject: ash: fail if 'shift' operand is out of range If the numeric argument passed to ash's 'shift' built-in is greater than '$#' the command performs no operation and exits successfully. It should return a non-zero exit code instead: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#shift This is consistent with bash and hush. function old new delta shiftcmd 122 120 -2 Signed-off-by: Ingo van Lil Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index dfb7d4d8e..b73a79975 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10858,7 +10858,7 @@ shiftcmd(int argc UNUSED_PARAM, char **argv) if (argv[1]) n = number(argv[1]); if (n > shellparam.nparam) - n = 0; /* bash compat, was = shellparam.nparam; */ + return 1; INT_OFF; shellparam.nparam -= n; for (ap1 = shellparam.p; --n >= 0; ap1++) { -- cgit v1.2.3-55-g6feb From 844a6c5abdcb5a189e91cb7ca3742bcaed25a4da Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 7 Jan 2018 14:39:34 +0100 Subject: awk: code shrink function old new delta awk_main 955 948 -7 Signed-off-by: Denys Vlasenko --- editors/awk.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/editors/awk.c b/editors/awk.c index 8f523ea28..d54249bfd 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -3149,7 +3149,7 @@ static rstream *next_input_file(void) } int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int awk_main(int argc, char **argv) +int awk_main(int argc UNUSED_PARAM, char **argv) { unsigned opt; char *opt_F; @@ -3218,7 +3218,7 @@ int awk_main(int argc, char **argv) } opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL); argv += optind; - argc -= optind; + //argc -= optind; if (opt & OPT_W) bb_error_msg("warning: option -W is ignored"); if (opt & OPT_F) { @@ -3255,15 +3255,14 @@ int awk_main(int argc, char **argv) if (!*argv) bb_show_usage(); parse_program(*argv++); - argc--; } /* fill in ARGV array */ - setvar_i(intvar[ARGC], argc + 1); setari_u(intvar[ARGV], 0, "awk"); i = 0; while (*argv) setari_u(intvar[ARGV], ++i, *argv++); + setvar_i(intvar[ARGC], i + 1); evaluate(beginseq.first, &tv); if (!mainseq.first && !endseq.first) -- cgit v1.2.3-55-g6feb From cb9c3894e50ecd5e940bb8a248fdb49da8e0c918 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Jan 2018 09:43:51 +0100 Subject: *: make "argc UNUSED_PARAM" consistent Signed-off-by: Denys Vlasenko --- procps/mpstat.c | 2 +- procps/powertop.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/procps/mpstat.c b/procps/mpstat.c index 7ead1fa7d..ed678f456 100644 --- a/procps/mpstat.c +++ b/procps/mpstat.c @@ -840,7 +840,7 @@ static int get_irqcpu_nr(const char *f, int max_irqs) //usage: "\n -u Report CPU utilization" int mpstat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int mpstat_main(int UNUSED_PARAM argc, char **argv) +int mpstat_main(int argc UNUSED_PARAM, char **argv) { char *opt_irq_fmt; char *opt_set_cpu; diff --git a/procps/powertop.c b/procps/powertop.c index 2872035cf..004b4ce19 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -686,7 +686,7 @@ static void show_timerstats(void) //usage: "Analyze power consumption on Intel-based laptops" int powertop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) +int powertop_main(int argc UNUSED_PARAM, char UNUSED_PARAM **argv) { ullong cur_usage[MAX_CSTATE_COUNT]; ullong cur_duration[MAX_CSTATE_COUNT]; -- cgit v1.2.3-55-g6feb From c9807d787d2d9ee5ed9f614c74573e47c8b359ab Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Jan 2018 10:13:11 +0100 Subject: nice: code shrink function old new delta nice_main 157 152 -5 Signed-off-by: Denys Vlasenko --- coreutils/nice.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/coreutils/nice.c b/coreutils/nice.c index d6818cf00..aa8b06cce 100644 --- a/coreutils/nice.c +++ b/coreutils/nice.c @@ -26,7 +26,7 @@ #include "libbb.h" int nice_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int nice_main(int argc, char **argv) +int nice_main(int argc UNUSED_PARAM, char **argv) { int old_priority, adjustment; @@ -40,18 +40,21 @@ int nice_main(int argc, char **argv) adjustment = 10; /* Set default adjustment. */ if (argv[0][0] == '-') { - if (argv[0][1] == 'n') { /* -n */ - if (argv[0][2]) { /* -nNNNN (w/o space) */ - argv[0] += 2; argv--; argc++; + char *nnn = argv[0] + 1; + if (nnn[0] == 'n') { /* -n */ + nnn += 1; + if (!nnn[0]) { /* "-n NNN" */ + nnn = *++argv; } - } else { /* -NNN (NNN may be negative) == -n NNN */ - argv[0] += 1; argv--; argc++; + /* else: "-nNNN" (w/o space) */ } - if (argc < 4) { /* Missing priority and/or utility! */ + /* else: "-NNN" (NNN may be negative) - same as "-n NNN" */ + + if (!nnn || !argv[1]) { /* Missing priority or PROG! */ bb_show_usage(); } - adjustment = xatoi_range(argv[1], INT_MIN/2, INT_MAX/2); - argv += 2; + adjustment = xatoi_range(nnn, INT_MIN/2, INT_MAX/2); + argv++; } { /* Set our priority. */ -- cgit v1.2.3-55-g6feb From 562f63e9a4583c887012dff782924110b1d1fd6b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Jan 2018 10:14:17 +0100 Subject: dhcprelay: code shrink function old new delta dhcprelay_main 961 958 -3 Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcprelay.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/udhcp/dhcprelay.c b/networking/udhcp/dhcprelay.c index 4d5644093..86dcb1af0 100644 --- a/networking/udhcp/dhcprelay.c +++ b/networking/udhcp/dhcprelay.c @@ -254,7 +254,7 @@ static void pass_to_client(struct dhcp_packet *p, int packet_len, int *fds) } int dhcprelay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int dhcprelay_main(int argc, char **argv) +int dhcprelay_main(int argc UNUSED_PARAM, char **argv) { struct sockaddr_in server_addr; char **iface_list; @@ -269,11 +269,11 @@ int dhcprelay_main(int argc, char **argv) server_addr.sin_port = htons(SERVER_PORT); /* dhcprelay CLIENT_IFACE1[,CLIENT_IFACE2...] SERVER_IFACE [SERVER_IP] */ - if (argc == 4) { + if (!argv[1] || !argv[2]) + bb_show_usage(); + if (argv[3]) { if (!inet_aton(argv[3], &server_addr.sin_addr)) bb_perror_msg_and_die("bad server IP"); - } else if (argc != 3) { - bb_show_usage(); } iface_list = make_iface_list(argv + 1, &num_sockets); -- cgit v1.2.3-55-g6feb From 83c99ab4469e0f8a9a0e84ec506a8bc101cdcb91 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Jan 2018 10:27:23 +0100 Subject: less: code shrink function old new delta less_main 2471 2464 -7 Signed-off-by: Denys Vlasenko --- miscutils/less.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index 82092f600..d60e6d920 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -255,7 +255,6 @@ struct globals { SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ less_gets_pos = -1; \ empty_line_marker = "~"; \ - num_files = 1; \ current_file = 1; \ eof_error = 1; \ terminated = 1; \ @@ -1773,9 +1772,8 @@ int less_main(int argc, char **argv) * (used by some setups for manpage display) */ getopt32(argv, "EMmN~I" IF_FEATURE_LESS_TRUNCATE("S") /*ignored:*/"s"); - argc -= optind; argv += optind; - num_files = argc; + num_files = argc - optind; files = argv; /* Another popular pager, most, detects when stdout -- cgit v1.2.3-55-g6feb From 2f55404bbc7f56deca193995b7c373d129297a94 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Jan 2018 11:22:37 +0100 Subject: mknod: better --help, much clearer code function old new delta packed_usage 32066 32091 +25 mknod_main 173 174 +1 Signed-off-by: Denys Vlasenko --- coreutils/mknod.c | 56 +++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/coreutils/mknod.c b/coreutils/mknod.c index 565b33d20..d57167f7d 100644 --- a/coreutils/mknod.c +++ b/coreutils/mknod.c @@ -20,7 +20,7 @@ /* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ //usage:#define mknod_trivial_usage -//usage: "[-m MODE] " IF_SELINUX("[-Z] ") "NAME TYPE MAJOR MINOR" +//usage: "[-m MODE] " IF_SELINUX("[-Z] ") "NAME TYPE [MAJOR MINOR]" //usage:#define mknod_full_usage "\n\n" //usage: "Create a special file (block, character, or pipe)\n" //usage: "\n -m MODE Creation mode (default a=rw)" @@ -30,7 +30,7 @@ //usage: "\nTYPE:" //usage: "\n b Block device" //usage: "\n c or u Character device" -//usage: "\n p Named pipe (MAJOR and MINOR are ignored)" +//usage: "\n p Named pipe (MAJOR MINOR must be omitted)" //usage: //usage:#define mknod_example_usage //usage: "$ mknod /dev/fd0 b 2 0\n" @@ -47,40 +47,40 @@ static const char modes_chars[] ALIGN1 = { 'p', 'c', 'u', 'b', 0, 1, 1, 2 }; static const mode_t modes_cubp[] = { S_IFIFO, S_IFCHR, S_IFBLK }; int mknod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int mknod_main(int argc, char **argv) +int mknod_main(int argc UNUSED_PARAM, char **argv) { mode_t mode; dev_t dev; - const char *name; + const char *type, *arg; mode = getopt_mk_fifo_nod(argv); argv += optind; - argc -= optind; + //argc -= optind; - if (argc >= 2) { - name = strchr(modes_chars, argv[1][0]); - if (name != NULL) { - mode |= modes_cubp[(int)(name[4])]; + if (!argv[0] || !argv[1]) + bb_show_usage(); + type = strchr(modes_chars, argv[1][0]); + if (!type) + bb_show_usage(); - dev = 0; - if (*name != 'p') { - argc -= 2; - if (argc == 2) { - /* Autodetect what the system supports; these macros should - * optimize out to two constants. */ - dev = makedev(xatoul_range(argv[2], 0, major(UINT_MAX)), - xatoul_range(argv[3], 0, minor(UINT_MAX))); - } - } + mode |= modes_cubp[(int)(type[4])]; - if (argc == 2) { - name = *argv; - if (mknod(name, mode, dev) == 0) { - return EXIT_SUCCESS; - } - bb_simple_perror_msg_and_die(name); - } - } + dev = 0; + arg = argv[2]; + if (*type != 'p') { + if (!argv[2] || !argv[3]) + bb_show_usage(); + /* Autodetect what the system supports; these macros should + * optimize out to two constants. */ + dev = makedev(xatoul_range(argv[2], 0, major(UINT_MAX)), + xatoul_range(argv[3], 0, minor(UINT_MAX))); + arg = argv[4]; } - bb_show_usage(); + if (arg) + bb_show_usage(); + + if (mknod(argv[0], mode, dev) != 0) { + bb_simple_perror_msg_and_die(argv[0]); + } + return EXIT_SUCCESS; } -- cgit v1.2.3-55-g6feb From 426134128112738c97a665170b21153ef0764b7d Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Mon, 8 Jan 2018 13:31:58 +0100 Subject: umount: ignore -c "-c, --no-canonicalize: Do not canonicalize paths." As busybox doesn't canonicalize paths in the first place it is safe to ignore this option. See https://github.com/systemd/systemd/issues/7786 Signed-off-by: Shawn Landden Signed-off-by: Denys Vlasenko --- util-linux/umount.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util-linux/umount.c b/util-linux/umount.c index a6405dfcc..b45cd8a6b 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c @@ -81,8 +81,8 @@ static struct mntent *getmntent_r(FILE* stream, struct mntent* result, } #endif -/* ignored: -v -t -i */ -#define OPTION_STRING "fldnra" "vt:i" +/* ignored: -c -v -t -i */ +#define OPTION_STRING "fldnra" "cvt:i" #define OPT_FORCE (1 << 0) // Same as MNT_FORCE #define OPT_LAZY (1 << 1) // Same as MNT_DETACH #define OPT_FREELOOP (1 << 2) -- cgit v1.2.3-55-g6feb From 740058b42bbfdab225706f8284e8d72b74a5df3b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 9 Jan 2018 17:01:00 +0100 Subject: ash: fix var_bash5.tests - ${VAR/pattern/repl} construct function old new delta subevalvar 1198 1279 +81 rmescapes 308 330 +22 preglob 8 10 +2 parsefname 152 154 +2 expandarg 973 975 +2 argstr 1144 1146 +2 mklocal 290 288 -2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 6/1 up/down: 111/-2) Total: 109 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 97 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 25 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index b73a79975..5381f34eb 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5811,7 +5811,6 @@ ash_arith(const char *s) #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ -#define RMESCAPE_SLASH 0x20 /* Stop globbing after slash */ /* Add CTLESC when necessary. */ #define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT) @@ -5992,8 +5991,12 @@ esclen(const char *start, const char *p) /* * Remove any CTLESC characters from a string. */ +#if !BASH_PATTERN_SUBST +#define rmescapes(str, flag, slash_position) \ + rmescapes(str, flag) +#endif static char * -rmescapes(char *str, int flag) +rmescapes(char *str, int flag, int *slash_position) { static const char qchars[] ALIGN1 = { IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' }; @@ -6002,9 +6005,8 @@ rmescapes(char *str, int flag) unsigned inquotes; unsigned protect_against_glob; unsigned globbing; - IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;) - p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash)); + p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position)); if (!p) return str; @@ -6084,10 +6086,11 @@ rmescapes(char *str, int flag) goto copy; } #if BASH_PATTERN_SUBST - else if (*p == '/' && slash) { - /* stop handling globbing and mark location of slash */ - globbing = slash = 0; - *p = CTLESC; + else if (slash_position && p == str + *slash_position) { + /* stop handling globbing */ + globbing = 0; + *slash_position = q - r; + slash_position = NULL; } #endif protect_against_glob = globbing; @@ -6111,7 +6114,7 @@ rmescapes(char *str, int flag) static char * preglob(const char *pattern, int flag) { - return rmescapes((char *)pattern, flag | RMESCAPE_GLOB); + return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL); } /* @@ -6454,7 +6457,7 @@ expari(int flag) expdest = p; if (flag & QUOTES_ESC) - rmescapes(p + 1, 0); + rmescapes(p + 1, 0, NULL); len = cvtnum(ash_arith(p + 1)); @@ -6742,20 +6745,57 @@ subevalvar(char *p, char *varname, int strloc, int subtype, char *rmesc, *rmescend; char *str; int amount, resetloc; + int argstr_flags; IF_BASH_PATTERN_SUBST(int workloc;) - IF_BASH_PATTERN_SUBST(char *repl = NULL;) + IF_BASH_PATTERN_SUBST(int slash_pos;) + IF_BASH_PATTERN_SUBST(char *repl;) int zero; char *(*scan)(char*, char*, char*, char*, int, int); //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)", // p, varname, strloc, subtype, startloc, varflags, quotes); - argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? - (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0) - ); +#if BASH_PATTERN_SUBST + repl = NULL; + if (subtype == VSREPLACE || subtype == VSREPLACEALL) { + /* Find '/' and replace with NUL */ + repl = p; + for (;;) { + /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */ + if (*repl == '\0') { + repl = NULL; + break; + } + if (*repl == '/') { + *repl = '\0'; + break; + } + if ((unsigned char)*repl == CTLESC + && repl[1] + ) { + repl++; + } + repl++; + } + } +#endif + argstr_flags = EXP_TILDE; + if (subtype != VSASSIGN && subtype != VSQUESTION) + argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE); + argstr(p, argstr_flags); +#if BASH_PATTERN_SUBST + slash_pos = -1; + if (repl) { + slash_pos = expdest - ((char *)stackblock() + strloc); + STPUTC('/', expdest); + argstr(repl + 1, argstr_flags); + *repl = '/'; + } +#endif STPUTC('\0', expdest); argbackq = saveargbackq; startp = (char *)stackblock() + startloc; + //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc); switch (subtype) { case VSASSIGN: @@ -6853,6 +6893,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype, resetloc = expdest - (char *)stackblock(); #if BASH_PATTERN_SUBST + repl = NULL; + /* We'll comeback here if we grow the stack while handling * a VSREPLACE or VSREPLACEALL, since our pointers into the * stack will need rebasing, and we'll need to remove our work @@ -6867,8 +6909,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype, rmesc = startp; rmescend = (char *)stackblock() + strloc; + //bb_error_msg("str7:'%s'", rmescend); if (quotes) { - rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW); +//TODO: how to handle slash_pos here if string changes (shortens?) + rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL); if (rmesc != startp) { rmescend = expdest; startp = (char *)stackblock() + startloc; @@ -6881,12 +6925,13 @@ subevalvar(char *p, char *varname, int strloc, int subtype, * The result is a_\_z_c (not a\_\_z_c)! * * The search pattern and replace string treat backslashes differently! - * RMESCAPE_SLASH causes preglob to work differently on the pattern + * "&slash_pos" causes rmescapes() to work differently on the pattern * and string. It's only used on the first call. */ - preglob(str, IF_BASH_PATTERN_SUBST( - (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? - RMESCAPE_SLASH : ) 0); + //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos); + rmescapes(str, RMESCAPE_GLOB, + repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos) + ); #if BASH_PATTERN_SUBST workloc = expdest - (char *)stackblock(); @@ -6895,11 +6940,13 @@ subevalvar(char *p, char *varname, int strloc, int subtype, char *idx, *end; if (!repl) { - repl = strchr(str, CTLESC); - if (repl) + //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos); + if (slash_pos >= 0) { + repl = str + slash_pos; *repl++ = '\0'; - else + } else { repl = nullstr; + } } //bb_error_msg("str:'%s' repl:'%s'", str, repl); @@ -7419,7 +7466,7 @@ expandmeta(struct strlist *str /*, int flag*/) INT_ON; nometa: *exparg.lastp = str; - rmescapes(str->text, 0); + rmescapes(str->text, 0, NULL); exparg.lastp = &str->next; break; default: /* GLOB_NOSPACE */ @@ -7648,7 +7695,7 @@ expandmeta(struct strlist *str /*, int flag*/) */ nometa: *exparg.lastp = str; - rmescapes(str->text, 0); + rmescapes(str->text, 0, NULL); exparg.lastp = &str->next; } else { *exparg.lastp = NULL; @@ -11328,7 +11375,7 @@ parsefname(void) if (quoteflag == 0) n->type = NXHERE; TRACE(("Here document %d\n", n->type)); - rmescapes(wordtext, 0); + rmescapes(wordtext, 0, NULL); here->eofmark = wordtext; here->next = NULL; if (heredoclist == NULL) -- cgit v1.2.3-55-g6feb From d1df1a709f05a737d2477a08eea8c743e83f8f8f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 9 Jan 2018 17:25:58 +0100 Subject: ash: add comment explaining last change Signed-off-by: Denys Vlasenko --- shell/ash.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 5381f34eb..83a8e77f9 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6756,6 +6756,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype, // p, varname, strloc, subtype, startloc, varflags, quotes); #if BASH_PATTERN_SUBST + /* For "${v/pattern/repl}", we must find the delimiter _before_ + * argstr() call expands possible variable references in pattern: + * think about "v=a; a=a/; echo ${v/$a/r}" case. + */ repl = NULL; if (subtype == VSREPLACE || subtype == VSREPLACEALL) { /* Find '/' and replace with NUL */ @@ -6770,11 +6774,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype, *repl = '\0'; break; } - if ((unsigned char)*repl == CTLESC - && repl[1] - ) { + if ((unsigned char)*repl == CTLESC && repl[1]) repl++; - } repl++; } } @@ -6941,11 +6942,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype, if (!repl) { //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos); + repl = nullstr; if (slash_pos >= 0) { repl = str + slash_pos; *repl++ = '\0'; - } else { - repl = nullstr; } } //bb_error_msg("str:'%s' repl:'%s'", str, repl); -- cgit v1.2.3-55-g6feb From 5afd63a631f49112ac305ea1532dd226e9c39d12 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 10 Jan 2018 10:58:55 +0100 Subject: dd: exit with 1 if last write was incomplete $ busybox dd if=/dev/zero of=/dev/loop0 bs=100M count=8; echo $? 8+0 records in 7+1 records out 805220352 bytes (767.9MB) copied, 0.464010 seconds, 1.6GB/s 1 <=========== FIXED function old new delta write_and_stats 96 97 +1 Signed-off-by: Denys Vlasenko --- coreutils/dd.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index d302f35d3..9d173cc13 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -195,14 +195,16 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs, ssize_t n = full_write_or_warn(buf, len, filename); if (n < 0) return 1; - if ((size_t)n == obs) - G.out_full++; - else if (n) /* > 0 */ - G.out_part++; #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE G.total_bytes += n; #endif - return 0; + if ((size_t)n == obs) { + G.out_full++; + return 0; + } + if (n) /* > 0 */ + G.out_part++; + return 1; } #if ENABLE_LFS -- cgit v1.2.3-55-g6feb From 2c876774a90ddb7478937ead096937f64e6bd7ec Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 10 Jan 2018 11:04:09 +0100 Subject: dd: fixed partial count logic $ busybox dd if=/dev/zero of=/dev/loop0 bs=100M count=8; echo $? 8+0 records in 7+0 records out <=========== FIXED, was 7+1 805220352 bytes (767.9MB) copied, 0.464010 seconds, 1.6GB/s 1 function old new delta write_and_stats 97 99 +2 Signed-off-by: Denys Vlasenko --- coreutils/dd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index 9d173cc13..38b2a6aa1 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -202,8 +202,10 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs, G.out_full++; return 0; } - if (n) /* > 0 */ + if ((size_t)n == len) { G.out_part++; + return 0; + } return 1; } -- cgit v1.2.3-55-g6feb From baa41c785551ae0580526298aa6fadf4534fc8c0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 10 Jan 2018 13:22:25 +0100 Subject: ash: make ${v:N:M} more robust for very large M by clamping to MIN/MAX_INT Before this patch, "${v:2:0x100000001}" = "${v:2:1}", and similarly, constructs like "${v:2:9999999999}" may give wrong result due to int overflows. function old new delta substr_atoi - 43 +43 Signed-off-by: Denys Vlasenko --- shell/ash.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 83a8e77f9..a7f330c11 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5780,6 +5780,26 @@ ash_arith(const char *s) return result; } #endif +#if BASH_SUBSTR +# if ENABLE_FEATURE_SH_MATH +static int substr_atoi(const char *s) +{ + arith_t t = ash_arith(s); + if (sizeof(t) > sizeof(int)) { + /* clamp very large or very large negative nums for ${v:N:M}: + * else "${v:0:0x100000001}" would work as "${v:0:1}" + */ + if (t > INT_MAX) + t = INT_MAX; + if (t < INT_MIN) + t = INT_MIN; + } + return t; +} +# else +# define substr_atoi(s) number(s) +# endif +#endif /* * expandarg flags @@ -6816,13 +6836,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype, loc = str = stackblock() + strloc; -# if !ENABLE_FEATURE_SH_MATH -# define ash_arith number -# endif /* Read POS in ${var:POS:LEN} */ colon = strchr(loc, ':'); if (colon) *colon = '\0'; - pos = ash_arith(loc); + pos = substr_atoi(loc); if (colon) *colon = ':'; /* Read LEN in ${var:POS:LEN} */ @@ -6830,7 +6847,6 @@ subevalvar(char *p, char *varname, int strloc, int subtype, /* *loc != '\0', guaranteed by parser */ if (quotes) { char *ptr; - /* Adjust the length by the number of escapes */ for (ptr = startp; ptr < (str - 1); ptr++) { if ((unsigned char)*ptr == CTLESC) { @@ -6842,19 +6858,15 @@ subevalvar(char *p, char *varname, int strloc, int subtype, orig_len = len; if (*loc++ == ':') { /* ${var::LEN} */ - len = ash_arith(loc); + len = substr_atoi(loc); } else { /* Skip POS in ${var:POS:LEN} */ len = orig_len; - while (*loc && *loc != ':') { + while (*loc && *loc != ':') loc++; - } - if (*loc++ == ':') { - len = ash_arith(loc); - } + if (*loc++ == ':') + len = substr_atoi(loc); } -# undef ash_arith - if (pos < 0) { /* ${VAR:$((-n)):l} starts n chars from the end */ pos = orig_len + pos; -- cgit v1.2.3-55-g6feb From f2539c78d2e507150dea06e8702c5ab8713d2b49 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 10 Jan 2018 13:32:20 +0100 Subject: init: stop using static data function old new delta init_action_list 4 - -4 new_init_action 148 142 -6 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/1 up/down: 0/-10) Total: -10 bytes text data bss dec hex filename 927839 481 6832 935152 e44f0 busybox_old 927833 481 6824 935138 e44e2 busybox_unstripped Signed-off-by: Denys Vlasenko --- init/init.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/init/init.c b/init/init.c index 6f3374eac..cac165fc7 100644 --- a/init/init.c +++ b/init/init.c @@ -128,6 +128,7 @@ #define DEBUG_SEGV_HANDLER 0 #include "libbb.h" +#include "common_bufsiz.h" #include #include #ifdef __linux__ @@ -203,7 +204,6 @@ */ #define RESTART 0x80 - /* A linked list of init_actions, to be read from inittab */ struct init_action { struct init_action *next; @@ -213,11 +213,17 @@ struct init_action { char command[1]; }; -static struct init_action *init_action_list = NULL; - +struct globals { + struct init_action *init_action_list; #if !ENABLE_FEATURE_INIT_SYSLOG -static const char *log_console = VC_5; + const char *log_console; #endif +} FIX_ALIASING; +#define G (*(struct globals*)bb_common_bufsiz1) +#define INIT_G() do { \ + setup_common_bufsiz(); \ + IF_NOT_FEATURE_INIT_SYSLOG(G.log_console = VC_5;) \ +} while (0) enum { L_LOG = 0x1, @@ -265,10 +271,10 @@ static void message(int where, const char *fmt, ...) if (log_fd < 0) { log_fd = STDERR_FILENO; - if (log_console) { - log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY); + if (G.log_console) { + log_fd = device_open(G.log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY); if (log_fd < 0) { - bb_error_msg("can't log to %s", log_console); + bb_error_msg("can't log to %s", G.log_console); where = L_CONSOLE; } else { close_on_exec_on(log_fd); @@ -328,7 +334,7 @@ static void console_init(void) if (!s || strcmp(s, "linux") == 0) putenv((char*)"TERM=vt102"); # if !ENABLE_FEATURE_INIT_SYSLOG - log_console = NULL; + G.log_console = NULL; # endif } else #endif @@ -562,7 +568,7 @@ static struct init_action *mark_terminated(pid_t pid) if (pid > 0) { update_utmp_DEAD_PROCESS(pid); - for (a = init_action_list; a; a = a->next) { + for (a = G.init_action_list; a; a = a->next) { if (a->pid == pid) { a->pid = 0; return a; @@ -596,7 +602,7 @@ static void run_actions(int action_type) { struct init_action *a; - for (a = init_action_list; a; a = a->next) { + for (a = G.init_action_list; a; a = a->next) { if (!(a->action_type & action_type)) continue; @@ -630,7 +636,7 @@ static void new_init_action(uint8_t action_type, const char *command, const char * To achieve that, if we find a matching entry, we move it * to the end. */ - nextp = &init_action_list; + nextp = &G.init_action_list; while ((a = *nextp) != NULL) { /* Don't enter action if it's already in the list. * This prevents losing running RESPAWNs. @@ -845,7 +851,7 @@ static void exec_restart_action(void) { struct init_action *a; - for (a = init_action_list; a; a = a->next) { + for (a = G.init_action_list; a; a = a->next) { if (!(a->action_type & RESTART)) continue; @@ -923,7 +929,7 @@ static void reload_inittab(void) message(L_LOG, "reloading /etc/inittab"); /* Disable old entries */ - for (a = init_action_list; a; a = a->next) + for (a = G.init_action_list; a; a = a->next) a->action_type = 0; /* Append new entries, or modify existing entries @@ -936,14 +942,14 @@ static void reload_inittab(void) #if ENABLE_FEATURE_KILL_REMOVED /* Kill stale entries */ /* Be nice and send SIGTERM first */ - for (a = init_action_list; a; a = a->next) + for (a = G.init_action_list; a; a = a->next) if (a->action_type == 0 && a->pid != 0) kill(a->pid, SIGTERM); if (CONFIG_FEATURE_KILL_DELAY) { /* NB: parent will wait in NOMMU case */ if ((BB_MMU ? fork() : vfork()) == 0) { /* child */ sleep(CONFIG_FEATURE_KILL_DELAY); - for (a = init_action_list; a; a = a->next) + for (a = G.init_action_list; a; a = a->next) if (a->action_type == 0 && a->pid != 0) kill(a->pid, SIGKILL); _exit(EXIT_SUCCESS); @@ -955,7 +961,7 @@ static void reload_inittab(void) * We never rerun SYSINIT entries anyway, * removing them too saves a few bytes */ - nextp = &init_action_list; + nextp = &G.init_action_list; while ((a = *nextp) != NULL) { /* * Why pid == 0 check? @@ -1046,6 +1052,8 @@ static void sleep_much(void) int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int init_main(int argc UNUSED_PARAM, char **argv) { + INIT_G(); + if (argv[1] && strcmp(argv[1], "-q") == 0) { return kill(1, SIGHUP); } -- cgit v1.2.3-55-g6feb From 03c36e0be1fa64dd248741dc21af2db28e70c186 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 10 Jan 2018 15:18:35 +0100 Subject: ash: ALWAYS_INLINE grabstackblock() function old new delta grabstackblock 5 - -5 Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index a7f330c11..8c0f3bd8d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -1532,7 +1532,7 @@ sstrdup(const char *p) return memcpy(stalloc(len), p, len); } -static inline void +static ALWAYS_INLINE void grabstackblock(size_t len) { stalloc(len); -- cgit v1.2.3-55-g6feb From aaf7a2e24d4c284328569eff44e67e29b223822b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 11 Jan 2018 11:19:00 +0100 Subject: hush: remove dead code function old new delta done_word 761 711 -50 Signed-off-by: Denys Vlasenko --- shell/hush.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index df1b046ab..6c47be885 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -3840,21 +3840,6 @@ static int done_word(o_string *word, struct parse_context *ctx) word->o_assignment = MAYBE_ASSIGNMENT; } debug_printf_parse("word->o_assignment='%s'\n", assignment_flag[word->o_assignment]); - - if (word->has_quoted_part - /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */ - && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL) - /* (otherwise it's known to be not empty and is already safe) */ - ) { - /* exclude "$@" - it can expand to no word despite "" */ - char *p = word->data; - while (p[0] == SPECIAL_VAR_SYMBOL - && (p[1] & 0x7f) == '@' - && p[2] == SPECIAL_VAR_SYMBOL - ) { - p += 3; - } - } command->argv = add_string_to_strings(command->argv, xstrdup(word->data)); debug_print_strings("word appended to argv", command->argv); } -- cgit v1.2.3-55-g6feb From 932b9971d05d26e353f56bdd93daec3c9f764312 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 11 Jan 2018 12:39:48 +0100 Subject: hush: fix handling of raw ^C in scripts: "echo ^C" function old new delta expand_vars_to_list 1133 1187 +54 parse_stream 2690 2719 +29 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/control_char1.right | 2 ++ shell/ash_test/ash-misc/control_char1.tests | 2 ++ shell/hush.c | 23 +++++++++++++++++++---- shell/hush_test/hush-misc/control_char1.right | 2 ++ shell/hush_test/hush-misc/control_char1.tests | 2 ++ 5 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 shell/ash_test/ash-misc/control_char1.right create mode 100755 shell/ash_test/ash-misc/control_char1.tests create mode 100644 shell/hush_test/hush-misc/control_char1.right create mode 100755 shell/hush_test/hush-misc/control_char1.tests diff --git a/shell/ash_test/ash-misc/control_char1.right b/shell/ash_test/ash-misc/control_char1.right new file mode 100644 index 000000000..9498b420d --- /dev/null +++ b/shell/ash_test/ash-misc/control_char1.right @@ -0,0 +1,2 @@ + +Done:0 diff --git a/shell/ash_test/ash-misc/control_char1.tests b/shell/ash_test/ash-misc/control_char1.tests new file mode 100755 index 000000000..a2ebeba1b --- /dev/null +++ b/shell/ash_test/ash-misc/control_char1.tests @@ -0,0 +1,2 @@ +echo  +echo Done:$? diff --git a/shell/hush.c b/shell/hush.c index 6c47be885..48f503cb6 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -462,7 +462,10 @@ # define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3) #endif -#define SPECIAL_VAR_SYMBOL 3 +#define SPECIAL_VAR_SYMBOL_STR "\3" +#define SPECIAL_VAR_SYMBOL 3 +/* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */ +#define SPECIAL_VAR_QUOTED_SVS 1 struct variable; @@ -4899,7 +4902,8 @@ static struct pipe *parse_stream(char **pstring, next = i_peek(input); is_special = "{}<>;&|()#'" /* special outside of "str" */ - "\\$\"" IF_HUSH_TICK("`"); /* always special */ + "\\$\"" IF_HUSH_TICK("`") /* always special */ + SPECIAL_VAR_SYMBOL_STR; /* Are { and } special here? */ if (ctx.command->argv /* word [word]{... - non-special */ || dest.length /* word{... - non-special */ @@ -5171,8 +5175,14 @@ static struct pipe *parse_stream(char **pstring, /* Note: nommu_addchr(&ctx.as_string, ch) is already done */ switch (ch) { - case '#': /* non-comment #: "echo a#b" etc */ - o_addQchr(&dest, ch); + case SPECIAL_VAR_SYMBOL: + /* Convert raw ^C to corresponding special variable reference */ + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + o_addchr(&dest, SPECIAL_VAR_QUOTED_SVS); + /* fall through */ + case '#': + /* non-comment #: "echo a#b" etc */ + o_addchr(&dest, ch); break; case '\\': if (next == EOF) { @@ -6026,6 +6036,11 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) arg++; cant_be_null = 0x80; break; + case SPECIAL_VAR_QUOTED_SVS: + /* */ + arg++; + val = SPECIAL_VAR_SYMBOL_STR; + break; #if ENABLE_HUSH_TICK case '`': /* `cmd */ *p = '\0'; /* replace trailing */ diff --git a/shell/hush_test/hush-misc/control_char1.right b/shell/hush_test/hush-misc/control_char1.right new file mode 100644 index 000000000..9498b420d --- /dev/null +++ b/shell/hush_test/hush-misc/control_char1.right @@ -0,0 +1,2 @@ + +Done:0 diff --git a/shell/hush_test/hush-misc/control_char1.tests b/shell/hush_test/hush-misc/control_char1.tests new file mode 100755 index 000000000..a2ebeba1b --- /dev/null +++ b/shell/hush_test/hush-misc/control_char1.tests @@ -0,0 +1,2 @@ +echo  +echo Done:$? -- cgit v1.2.3-55-g6feb From 1f1911239c0874d49a31d0ef2e618d0a1086a8df Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 11 Jan 2018 13:17:30 +0100 Subject: hush: fix handling of ^C in eval function old new delta run_list 1044 1259 +215 builtin_eval 45 126 +81 expand_strvec_to_string 91 - -91 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 2/0 up/down: 296/-91) Total: 205 bytes Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/control_char2.right | 2 ++ shell/ash_test/ash-misc/control_char2.tests | 3 +++ shell/hush.c | 30 +++++++++++++++++++++++---- shell/hush_test/hush-misc/control_char2.right | 2 ++ shell/hush_test/hush-misc/control_char2.tests | 3 +++ 5 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 shell/ash_test/ash-misc/control_char2.right create mode 100755 shell/ash_test/ash-misc/control_char2.tests create mode 100644 shell/hush_test/hush-misc/control_char2.right create mode 100755 shell/hush_test/hush-misc/control_char2.tests diff --git a/shell/ash_test/ash-misc/control_char2.right b/shell/ash_test/ash-misc/control_char2.right new file mode 100644 index 000000000..9498b420d --- /dev/null +++ b/shell/ash_test/ash-misc/control_char2.right @@ -0,0 +1,2 @@ + +Done:0 diff --git a/shell/ash_test/ash-misc/control_char2.tests b/shell/ash_test/ash-misc/control_char2.tests new file mode 100755 index 000000000..e77d7a1a6 --- /dev/null +++ b/shell/ash_test/ash-misc/control_char2.tests @@ -0,0 +1,3 @@ +c=`printf '\3'` +eval "echo $c" +echo Done:$? diff --git a/shell/hush.c b/shell/hush.c index 48f503cb6..c2b987f49 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6199,7 +6199,7 @@ static char *expand_string_to_string(const char *str, int do_unbackslash) return (char*)list; } -/* Used for "eval" builtin and case string */ +#if ENABLE_HUSH_CASE static char* expand_strvec_to_string(char **argv) { char **list; @@ -6221,6 +6221,7 @@ static char* expand_strvec_to_string(char **argv) debug_printf_expand("strvec_to_string='%s'\n", (char*)list); return (char*)list; } +#endif static char **expand_assignments(char **argv, int count) { @@ -9349,13 +9350,34 @@ static int FAST_FUNC builtin_eval(char **argv) int rcode = EXIT_SUCCESS; argv = skip_dash_dash(argv); - if (*argv) { - char *str = expand_strvec_to_string(argv); + if (argv[0]) { + char *str = NULL; + + if (argv[1]) { + /* "The eval utility shall construct a command by + * concatenating arguments together, separating + * each with a character." + */ + char *p; + unsigned len = 0; + char **pp = argv; + do + len += strlen(*pp) + 1; + while (*++pp); + str = p = xmalloc(len); + pp = argv; + do { + p = stpcpy(p, *pp); + *p++ = ' '; + } while (*++pp); + p[-1] = '\0'; + } + /* bash: * eval "echo Hi; done" ("done" is syntax error): * "echo Hi" will not execute too. */ - parse_and_run_string(str); + parse_and_run_string(str ? str : argv[0]); free(str); rcode = G.last_exitcode; } diff --git a/shell/hush_test/hush-misc/control_char2.right b/shell/hush_test/hush-misc/control_char2.right new file mode 100644 index 000000000..9498b420d --- /dev/null +++ b/shell/hush_test/hush-misc/control_char2.right @@ -0,0 +1,2 @@ + +Done:0 diff --git a/shell/hush_test/hush-misc/control_char2.tests b/shell/hush_test/hush-misc/control_char2.tests new file mode 100755 index 000000000..e77d7a1a6 --- /dev/null +++ b/shell/hush_test/hush-misc/control_char2.tests @@ -0,0 +1,3 @@ +c=`printf '\3'` +eval "echo $c" +echo Done:$? -- cgit v1.2.3-55-g6feb From 3bb3e1d0a1eed01306e22e59db8de6c2d945165a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 11 Jan 2018 18:05:05 +0100 Subject: hush: implement "command" builtin (no options are supported yet) function old new delta pseudo_exec_argv 194 231 +37 Signed-off-by: Denys Vlasenko --- shell/hush.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index c2b987f49..93779ba1e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -58,6 +58,7 @@ * (can use this to override standalone shell as well) * -p: use default $PATH * command BLTIN: disables special-ness (e.g. errors do not abort) + * NB: so far, only naked "command CMD" is implemented. * fc -l[nr] [BEG] [END]: list range of commands in history * fc [-e EDITOR] [BEG] [END]: edit/rerun range of commands * fc -s [PAT=REP] [CMD]: rerun CMD, replacing PAT with REP @@ -253,6 +254,11 @@ //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: +//config:config HUSH_COMMAND +//config: bool "command builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: //config:config HUSH_TRAP //config: bool "trap builtin" //config: default y @@ -7406,11 +7412,20 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, * if this is one of those cases. */ { + const struct built_in_command *x; + +#if ENABLE_HUSH_COMMAND + /* This loop effectively makes "command BAR" run BAR without + * looking it up among functions. + */ + while (strcmp(argv[0], "command") == 0 && argv[1]) + argv++; +//TODO: implement -Vvp and "disable dying if BAR is a builtin" behavior +#endif /* On NOMMU, it is more expensive to re-execute shell * just in order to run echo or test builtin. * It's better to skip it here and run corresponding * non-builtin later. */ - const struct built_in_command *x; x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]); if (x) { exec_builtin(&nommu_save->argv_from_re_execing, x, argv); -- cgit v1.2.3-55-g6feb From cca7c611f26d98415c0f986e5a5e731ab5e379ff Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 12 Jan 2018 13:21:33 +0100 Subject: which: fix TODO with NOFORK+malloc_failure misbehaving function old new delta find_executable 86 104 +18 which_main 202 194 -8 executable_exists 66 51 -15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 18/-23) Total: -5 bytes Signed-off-by: Denys Vlasenko --- debianutils/which.c | 16 ++++++++-------- include/libbb.h | 12 +++++++++--- libbb/executable.c | 18 ++++++++++-------- libbb/messages.c | 8 +------- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/debianutils/which.c b/debianutils/which.c index 3bd54ac42..02f77a216 100644 --- a/debianutils/which.c +++ b/debianutils/which.c @@ -30,12 +30,15 @@ int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int which_main(int argc UNUSED_PARAM, char **argv) { - const char *env_path; + char *env_path; int status = 0; + /* This sizeof(): bb_default_root_path is shorter than BB_PATH_ROOT_PATH */ + char buf[sizeof(BB_PATH_ROOT_PATH)]; env_path = getenv("PATH"); if (!env_path) - env_path = bb_default_root_path; + /* env_path must be writable, and must not alloc, so... */ + env_path = strcpy(buf, bb_default_root_path); getopt32(argv, "^" "a" "\0" "-1"/*at least one arg*/); argv += optind; @@ -51,20 +54,17 @@ int which_main(int argc UNUSED_PARAM, char **argv) } } else { char *path; - char *tmp; char *p; - path = tmp = xstrdup(env_path); -//NOFORK FIXME: nested xmallocs (one is inside find_executable()) -//can leak memory on failure - while ((p = find_executable(*argv, &tmp)) != NULL) { + path = env_path; + /* NOFORK NB: xmalloc inside find_executable(), must have no allocs above! */ + while ((p = find_executable(*argv, &path)) != NULL) { missing = 0; puts(p); free(p); if (!option_mask32) /* -a not set */ break; } - free(path); } status |= missing; } while (*++argv); diff --git a/include/libbb.h b/include/libbb.h index daccf154a..5f25b5dde 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2005,10 +2005,16 @@ extern const char bb_path_wtmp_file[] ALIGN1; #define bb_dev_null "/dev/null" extern const char bb_busybox_exec_path[] ALIGN1; -/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, - * but I want to save a few bytes here */ -extern const char bb_PATH_root_path[] ALIGN1; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */ +/* allow default system PATH to be extended via CFLAGS */ +#ifndef BB_ADDITIONAL_PATH +#define BB_ADDITIONAL_PATH "" +#endif +#define BB_PATH_ROOT_PATH "PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH +extern const char bb_PATH_root_path[] ALIGN1; /* BB_PATH_ROOT_PATH */ #define bb_default_root_path (bb_PATH_root_path + sizeof("PATH")) +/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, + * but I want to save a few bytes here: + */ #define bb_default_path (bb_PATH_root_path + sizeof("PATH=/sbin:/usr/sbin")) extern const int const_int_0; diff --git a/libbb/executable.c b/libbb/executable.c index 325dd0107..29d2a2c85 100644 --- a/libbb/executable.c +++ b/libbb/executable.c @@ -25,7 +25,8 @@ int FAST_FUNC file_is_executable(const char *name) * you may call find_executable again with this PATHp to continue * (if it's not NULL). * return NULL otherwise; (PATHp is undefined) - * in all cases (*PATHp) contents will be trashed (s/:/NUL/). + * in all cases (*PATHp) contents are temporarily modified + * but are restored on return (s/:/NUL/ and back). */ char* FAST_FUNC find_executable(const char *filename, char **PATHp) { @@ -41,14 +42,17 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp) p = *PATHp; while (p) { + int ex; + n = strchr(p, ':'); - if (n) - *n++ = '\0'; + if (n) *n = '\0'; p = concat_path_file( p[0] ? p : ".", /* handle "::" case */ filename ); - if (file_is_executable(p)) { + ex = file_is_executable(p); + if (n) *n++ = ':'; + if (ex) { *PATHp = n; return p; } @@ -64,10 +68,8 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp) */ int FAST_FUNC executable_exists(const char *filename) { - char *path = xstrdup(getenv("PATH")); - char *tmp = path; - char *ret = find_executable(filename, &tmp); - free(path); + char *path = getenv("PATH"); + char *ret = find_executable(filename, &path); free(ret); return ret != NULL; } diff --git a/libbb/messages.c b/libbb/messages.c index 0a6cf3bf8..6914d5701 100644 --- a/libbb/messages.c +++ b/libbb/messages.c @@ -6,11 +6,6 @@ */ #include "libbb.h" -/* allow default system PATH to be extended via CFLAGS */ -#ifndef BB_ADDITIONAL_PATH -#define BB_ADDITIONAL_PATH "" -#endif - /* allow version to be extended, via CFLAGS */ #ifndef BB_EXTRA_VERSION #define BB_EXTRA_VERSION " ("AUTOCONF_TIMESTAMP")" @@ -36,8 +31,7 @@ const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, * but I want to save a few bytes here. Check libbb.h before changing! */ -const char bb_PATH_root_path[] ALIGN1 = - "PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH; +const char bb_PATH_root_path[] ALIGN1 = BB_PATH_ROOT_PATH; //const int const_int_1 = 1; -- cgit v1.2.3-55-g6feb From 5700029c65f2218b5fceca77a9140aff6d882aab Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 12 Jan 2018 14:41:45 +0100 Subject: hush: implement "command -v -V" function old new delta pseudo_exec_argv 231 374 +143 if_command_vV_print_and_exit - 127 +127 builtin_set 267 273 +6 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/0 up/down: 276/0) Total: 276 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 115 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 31 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 93779ba1e..196bdbe97 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -47,18 +47,13 @@ * follow IFS rules more precisely, including update semantics * tilde expansion * aliases - * builtins mandated by standards we don't support: - * [un]alias, command, fc: - * command -v CMD: print "/path/to/CMD" - * prints "CMD" for builtins - * prints "alias ALIAS='EXPANSION'" for aliases - * prints nothing and sets $? to 1 if not found - * command -V CMD: print "CMD is /path/CMD|a shell builtin|etc" - * command [-p] CMD: run CMD, even if a function CMD also exists - * (can use this to override standalone shell as well) - * -p: use default $PATH + * "command" missing features: + * command -p CMD: run CMD using default $PATH + * (can use this to override standalone shell as well?) * command BLTIN: disables special-ness (e.g. errors do not abort) - * NB: so far, only naked "command CMD" is implemented. + * command -V CMD1 CMD2 CMD3 (multiple args) (not in standard) + * builtins mandated by standards we don't support: + * [un]alias, fc: * fc -l[nr] [BEG] [END]: list range of commands in history * fc [-e EDITOR] [BEG] [END]: edit/rerun range of commands * fc -s [PAT=REP] [CMD]: rerun CMD, replacing PAT with REP @@ -7337,6 +7332,30 @@ static void dump_cmd_in_x_mode(char **argv) # define dump_cmd_in_x_mode(argv) ((void)0) #endif +#if ENABLE_HUSH_COMMAND +static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *explanation) +{ + char *to_free; + if (!opt_vV) + return; + + to_free = NULL; + if (!explanation) { + char *path = getenv("PATH"); + explanation = to_free = find_executable(cmd, &path); /* path == NULL is ok */ + if (opt_vV != 'V') + cmd = to_free; /* -v PROG prints "/path/to/PROG" */ + } + if (explanation) + printf((opt_vV == 'V') ? "%s is %s\n" : "%s\n", cmd, explanation); + free(to_free); + fflush_all(); + _exit(explanation == NULL); /* exit 1 if PROG was not found */ +} +#else +# define if_command_vV_print_and_exit(a,b,c) ((void)0) +#endif + #if BB_MMU #define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \ pseudo_exec_argv(argv, assignment_cnt, argv_expanded) @@ -7357,7 +7376,11 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded) { + const struct built_in_command *x; char **new_env; +#if ENABLE_HUSH_COMMAND + char opt_vV = 0; +#endif new_env = expand_assignments(argv, assignment_cnt); dump_cmd_in_x_mode(new_env); @@ -7406,30 +7429,58 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, } #endif +#if ENABLE_HUSH_COMMAND + /* "command BAR": run BAR without looking it up among functions + * "command -v BAR": print "BAR" or "/path/to/BAR"; or exit 1 + * "command -V BAR": print "BAR is {a function,a shell builtin,/path/to/BAR}" + */ + while (strcmp(argv[0], "command") == 0 && argv[1]) { + char *p; + + argv++; + p = *argv; + if (p[0] != '-' || !p[1]) + continue; /* bash allows "command command command [-OPT] BAR" */ + + for (;;) { + p++; + switch (*p) { + case '\0': + argv++; + p = *argv; + if (p[0] != '-' || !p[1]) + goto after_opts; + continue; /* next arg is also -opts, process it too */ + case 'v': + case 'V': + opt_vV = *p; + continue; + default: + bb_error_msg_and_die("%s: %s: invalid option", "command", argv[0]); + } + } + } + after_opts: +# if ENABLE_HUSH_FUNCTIONS + if (opt_vV && find_function(argv[0])) + if_command_vV_print_and_exit(opt_vV, argv[0], "a function"); +# endif +#endif + /* Check if the command matches any of the builtins. * Depending on context, this might be redundant. But it's * easier to waste a few CPU cycles than it is to figure out * if this is one of those cases. */ - { - const struct built_in_command *x; - -#if ENABLE_HUSH_COMMAND - /* This loop effectively makes "command BAR" run BAR without - * looking it up among functions. - */ - while (strcmp(argv[0], "command") == 0 && argv[1]) - argv++; -//TODO: implement -Vvp and "disable dying if BAR is a builtin" behavior -#endif - /* On NOMMU, it is more expensive to re-execute shell - * just in order to run echo or test builtin. - * It's better to skip it here and run corresponding - * non-builtin later. */ - x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]); - if (x) { - exec_builtin(&nommu_save->argv_from_re_execing, x, argv); - } + /* Why "BB_MMU ? :" difference in logic? - + * On NOMMU, it is more expensive to re-execute shell + * just in order to run echo or test builtin. + * It's better to skip it here and run corresponding + * non-builtin later. */ + x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]); + if (x) { + if_command_vV_print_and_exit(opt_vV, argv[0], "a shell builtin"); + exec_builtin(&nommu_save->argv_from_re_execing, x, argv); } #if ENABLE_FEATURE_SH_STANDALONE @@ -7437,6 +7488,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, { int a = find_applet_by_name(argv[0]); if (a >= 0) { + if_command_vV_print_and_exit(opt_vV, argv[0], "an applet"); # if BB_MMU /* see above why on NOMMU it is not allowed */ if (APPLET_IS_NOEXEC(a)) { /* Do not leak open fds from opened script files etc. @@ -7466,6 +7518,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save, #if ENABLE_FEATURE_SH_STANDALONE || BB_MMU skip: #endif + if_command_vV_print_and_exit(opt_vV, argv[0], NULL); execvp_or_die(argv); } @@ -9895,7 +9948,7 @@ static int FAST_FUNC builtin_set(char **argv) /* Nothing known, so abort */ error: - bb_error_msg("set: %s: invalid option", arg); + bb_error_msg("%s: %s: invalid option", "set", arg); return EXIT_FAILURE; } #endif -- cgit v1.2.3-55-g6feb From afb73a25ea9b046f0fb2fa83a6d75b15bd952716 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 12 Jan 2018 16:17:59 +0100 Subject: hush: tweak command -vV printing code, no logic changes Signed-off-by: Denys Vlasenko --- shell/hush.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 196bdbe97..fc8940d3d 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7336,6 +7336,7 @@ static void dump_cmd_in_x_mode(char **argv) static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *explanation) { char *to_free; + if (!opt_vV) return; @@ -7343,14 +7344,15 @@ static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *exp if (!explanation) { char *path = getenv("PATH"); explanation = to_free = find_executable(cmd, &path); /* path == NULL is ok */ + if (!explanation) + _exit(1); /* PROG was not found */ if (opt_vV != 'V') cmd = to_free; /* -v PROG prints "/path/to/PROG" */ } - if (explanation) - printf((opt_vV == 'V') ? "%s is %s\n" : "%s\n", cmd, explanation); + printf((opt_vV == 'V') ? "%s is %s\n" : "%s\n", cmd, explanation); free(to_free); fflush_all(); - _exit(explanation == NULL); /* exit 1 if PROG was not found */ + _exit(0); } #else # define if_command_vV_print_and_exit(a,b,c) ((void)0) -- cgit v1.2.3-55-g6feb From 6606c519efa9a74c53bf05e53e07a8d8f0eb37c7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 12 Jan 2018 17:58:20 +0100 Subject: hush: add command2.tests from ash tests Signed-off-by: Denys Vlasenko --- shell/hush_test/hush-misc/command2.right | 2 ++ shell/hush_test/hush-misc/command2.tests | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 shell/hush_test/hush-misc/command2.right create mode 100755 shell/hush_test/hush-misc/command2.tests diff --git a/shell/hush_test/hush-misc/command2.right b/shell/hush_test/hush-misc/command2.right new file mode 100644 index 000000000..e3214f0a9 --- /dev/null +++ b/shell/hush_test/hush-misc/command2.right @@ -0,0 +1,2 @@ +test1 +hush: can't execute './test2.sh': Permission denied diff --git a/shell/hush_test/hush-misc/command2.tests b/shell/hush_test/hush-misc/command2.tests new file mode 100755 index 000000000..9d9de9a89 --- /dev/null +++ b/shell/hush_test/hush-misc/command2.tests @@ -0,0 +1,6 @@ +echo "echo test1; ./test2.sh" >test1.sh +echo "echo test2" >test2.sh + +command . ./test1.sh + +rm -f test1.sh test2.sh -- cgit v1.2.3-55-g6feb From 9809a82b5983ac3184906fff2df48765dab372c8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 13 Jan 2018 19:14:27 +0100 Subject: hush: fix raw ^C handlisg in single-quoted strings function old new delta parse_stream 2719 2754 +35 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/control_char1.right | 1 + shell/ash_test/ash-misc/control_char1.tests | 1 + shell/ash_test/ash-misc/for_with_bslashes.right | 1 + shell/ash_test/ash-misc/for_with_bslashes.tests | 8 ++------ shell/hush.c | 5 +++++ shell/hush_test/hush-misc/control_char1.right | 1 + shell/hush_test/hush-misc/control_char1.tests | 1 + shell/hush_test/hush-misc/for_with_bslashes.right | 1 + shell/hush_test/hush-misc/for_with_bslashes.tests | 8 ++------ 9 files changed, 15 insertions(+), 12 deletions(-) diff --git a/shell/ash_test/ash-misc/control_char1.right b/shell/ash_test/ash-misc/control_char1.right index 9498b420d..6f8c2533c 100644 --- a/shell/ash_test/ash-misc/control_char1.right +++ b/shell/ash_test/ash-misc/control_char1.right @@ -1,2 +1,3 @@  +b#c Done:0 diff --git a/shell/ash_test/ash-misc/control_char1.tests b/shell/ash_test/ash-misc/control_char1.tests index a2ebeba1b..0cfe60141 100755 --- a/shell/ash_test/ash-misc/control_char1.tests +++ b/shell/ash_test/ash-misc/control_char1.tests @@ -1,2 +1,3 @@ echo  +echo 'b#c' echo Done:$? diff --git a/shell/ash_test/ash-misc/for_with_bslashes.right b/shell/ash_test/ash-misc/for_with_bslashes.right index 02d96692c..cd8501050 100644 --- a/shell/ash_test/ash-misc/for_with_bslashes.right +++ b/shell/ash_test/ash-misc/for_with_bslashes.right @@ -5,4 +5,5 @@ b"c b'c b$c b`true`c +b#c Zero:0 diff --git a/shell/ash_test/ash-misc/for_with_bslashes.tests b/shell/ash_test/ash-misc/for_with_bslashes.tests index 363f3d85b..8acd9808a 100755 --- a/shell/ash_test/ash-misc/for_with_bslashes.tests +++ b/shell/ash_test/ash-misc/for_with_bslashes.tests @@ -1,9 +1,5 @@ -# UNFIXED BUG. -# commented-out words contain ^C character. -# It's a SPECIAL_VAR_SYMBOL, for now hush does not escape it. -# When it is fixed, update this test. - -for a in 'a' 'b\c' 'b\\c' 'b"c' "b'c" 'b$c' 'b`true`c' ### 'b#c' +# last word contains ^C character. +for a in 'a' 'b\c' 'b\\c' 'b"c' "b'c" 'b$c' 'b`true`c' 'b#c' do echo $a done diff --git a/shell/hush.c b/shell/hush.c index fc8940d3d..79d7a53dd 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5225,6 +5225,11 @@ static struct pipe *parse_stream(char **pstring, nommu_addchr(&ctx.as_string, ch); if (ch == '\'') break; + if (ch == SPECIAL_VAR_SYMBOL) { + /* Convert raw ^C to corresponding special variable reference */ + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + o_addchr(&dest, SPECIAL_VAR_QUOTED_SVS); + } o_addqchr(&dest, ch); } } diff --git a/shell/hush_test/hush-misc/control_char1.right b/shell/hush_test/hush-misc/control_char1.right index 9498b420d..6f8c2533c 100644 --- a/shell/hush_test/hush-misc/control_char1.right +++ b/shell/hush_test/hush-misc/control_char1.right @@ -1,2 +1,3 @@  +b#c Done:0 diff --git a/shell/hush_test/hush-misc/control_char1.tests b/shell/hush_test/hush-misc/control_char1.tests index a2ebeba1b..0cfe60141 100755 --- a/shell/hush_test/hush-misc/control_char1.tests +++ b/shell/hush_test/hush-misc/control_char1.tests @@ -1,2 +1,3 @@ echo  +echo 'b#c' echo Done:$? diff --git a/shell/hush_test/hush-misc/for_with_bslashes.right b/shell/hush_test/hush-misc/for_with_bslashes.right index 02d96692c..cd8501050 100644 --- a/shell/hush_test/hush-misc/for_with_bslashes.right +++ b/shell/hush_test/hush-misc/for_with_bslashes.right @@ -5,4 +5,5 @@ b"c b'c b$c b`true`c +b#c Zero:0 diff --git a/shell/hush_test/hush-misc/for_with_bslashes.tests b/shell/hush_test/hush-misc/for_with_bslashes.tests index 363f3d85b..8acd9808a 100755 --- a/shell/hush_test/hush-misc/for_with_bslashes.tests +++ b/shell/hush_test/hush-misc/for_with_bslashes.tests @@ -1,9 +1,5 @@ -# UNFIXED BUG. -# commented-out words contain ^C character. -# It's a SPECIAL_VAR_SYMBOL, for now hush does not escape it. -# When it is fixed, update this test. - -for a in 'a' 'b\c' 'b\\c' 'b"c' "b'c" 'b$c' 'b`true`c' ### 'b#c' +# last word contains ^C character. +for a in 'a' 'b\c' 'b\\c' 'b"c' "b'c" 'b$c' 'b`true`c' 'b#c' do echo $a done -- cgit v1.2.3-55-g6feb From aea52e7b2d8a44e1c84575f5a83b36126a07ef6b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 13 Jan 2018 19:28:19 +0100 Subject: shell: echo ${?:0} was fixed sometime ago, enable it in tests Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-vars/param_expand_bash_substring.right | 1 + shell/ash_test/ash-vars/param_expand_bash_substring.tests | 2 +- shell/hush_test/hush-vars/param_expand_bash_substring.right | 1 + shell/hush_test/hush-vars/param_expand_bash_substring.tests | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/ash_test/ash-vars/param_expand_bash_substring.right b/shell/ash_test/ash-vars/param_expand_bash_substring.right index 9ad6dbcad..687dd9002 100644 --- a/shell/ash_test/ash-vars/param_expand_bash_substring.right +++ b/shell/ash_test/ash-vars/param_expand_bash_substring.right @@ -3,6 +3,7 @@ SHELL: line 1: syntax error: bad substitution SHELL: line 1: syntax error: bad substitution SHELL: line 1: syntax error: bad substitution SHELL: line 1: syntax error: missing '}' +0 1 =|| 1:1 =|| 1:1:2=|| diff --git a/shell/ash_test/ash-vars/param_expand_bash_substring.tests b/shell/ash_test/ash-vars/param_expand_bash_substring.tests index cce9f123e..512da351b 100755 --- a/shell/ash_test/ash-vars/param_expand_bash_substring.tests +++ b/shell/ash_test/ash-vars/param_expand_bash_substring.tests @@ -11,7 +11,7 @@ export var=0123456789 "$THIS_SH" -c 'echo ${var:}' SHELL # then some funky ones -# UNFIXED BUG: this should work: "$THIS_SH" -c 'echo ${?:0}' +"$THIS_SH" -c 'echo ${?:0}' SHELL # now some valid ones set --; echo "1 =|${1}|" diff --git a/shell/hush_test/hush-vars/param_expand_bash_substring.right b/shell/hush_test/hush-vars/param_expand_bash_substring.right index 2f4c51d06..a3cb549f7 100644 --- a/shell/hush_test/hush-vars/param_expand_bash_substring.right +++ b/shell/hush_test/hush-vars/param_expand_bash_substring.right @@ -3,6 +3,7 @@ hush: syntax error: unterminated ${name} hush: syntax error: unterminated ${name} hush: syntax error: unterminated ${name} 0123456789 +0 1 =|| 1:1 =|| 1:1:2=|| diff --git a/shell/hush_test/hush-vars/param_expand_bash_substring.tests b/shell/hush_test/hush-vars/param_expand_bash_substring.tests index cce9f123e..512da351b 100755 --- a/shell/hush_test/hush-vars/param_expand_bash_substring.tests +++ b/shell/hush_test/hush-vars/param_expand_bash_substring.tests @@ -11,7 +11,7 @@ export var=0123456789 "$THIS_SH" -c 'echo ${var:}' SHELL # then some funky ones -# UNFIXED BUG: this should work: "$THIS_SH" -c 'echo ${?:0}' +"$THIS_SH" -c 'echo ${?:0}' SHELL # now some valid ones set --; echo "1 =|${1}|" -- cgit v1.2.3-55-g6feb From 12714ffa279275ac333f82368aa8cac1a740d5de Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 13 Jan 2018 21:37:20 +0100 Subject: tc: fix single-applet build Signed-off-by: Denys Vlasenko --- networking/libiproute/Kbuild.src | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/networking/libiproute/Kbuild.src b/networking/libiproute/Kbuild.src index 056a58540..d94e4c6e5 100644 --- a/networking/libiproute/Kbuild.src +++ b/networking/libiproute/Kbuild.src @@ -12,6 +12,12 @@ INSERT lib-$(CONFIG_SLATTACH) += \ utils.o +lib-$(CONFIG_TC) += \ + libnetlink.o \ + ll_map.o \ + ll_proto.o \ + utils.o + lib-$(CONFIG_IP) += \ ip_parse_common_args.o \ libnetlink.o \ -- cgit v1.2.3-55-g6feb From 38da4c4420ea6d7b3cf120c0902458e7d8256560 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 12:03:33 +0100 Subject: config: add size estimations for a few applets Signed-off-by: Denys Vlasenko --- klibc-utils/nuke.c | 2 +- klibc-utils/resume.c | 2 +- klibc-utils/run-init.c | 2 +- miscutils/hexedit.c | 2 +- miscutils/setfattr.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/klibc-utils/nuke.c b/klibc-utils/nuke.c index 6b65f705f..60a5f7145 100644 --- a/klibc-utils/nuke.c +++ b/klibc-utils/nuke.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config NUKE -//config: bool "nuke" +//config: bool "nuke (2.4 kb)" //config: default y //config: help //config: Alias to "rm -rf". diff --git a/klibc-utils/resume.c b/klibc-utils/resume.c index f85384853..3424f076b 100644 --- a/klibc-utils/resume.c +++ b/klibc-utils/resume.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config RESUME -//config: bool "resume" +//config: bool "resume (3.3 kb)" //config: default y //config: help //config: Resume from saved "suspend-to-disk" image diff --git a/klibc-utils/run-init.c b/klibc-utils/run-init.c index a70d1bfbf..61c16fd0b 100644 --- a/klibc-utils/run-init.c +++ b/klibc-utils/run-init.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config RUN_INIT -//config: bool "run-init" +//config: bool "run-init (7.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index bafb834b5..95c930d12 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config HEXEDIT -//config: bool "hexedit" +//config: bool "hexedit (20 kb)" //config: default y //config: help //config: Edit file in hexadecimal. diff --git a/miscutils/setfattr.c b/miscutils/setfattr.c index f0ef227cb..12eebc56e 100644 --- a/miscutils/setfattr.c +++ b/miscutils/setfattr.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SETFATTR -//config: bool "setfattr" +//config: bool "setfattr (3.6 kb)" //config: default y //config: help //config: Set/delete extended attributes on files -- cgit v1.2.3-55-g6feb From 36495af81fb9d312bb04250fba3ea7fa2c209c81 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 12:13:16 +0100 Subject: size_single_applets.sh: fix a bug which mishandles e.g. "udhcpc6" name Signed-off-by: Denys Vlasenko --- size_single_applets.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/size_single_applets.sh b/size_single_applets.sh index 0fa56e09e..ee16d4de7 100755 --- a/size_single_applets.sh +++ b/size_single_applets.sh @@ -22,7 +22,7 @@ for app; do } test $mintext -gt $text && { mintext=$text - echo "New mintext from $app: $mintext" + echo "# New mintext from $app: $mintext" } eval "text_${app}=$text" done @@ -31,7 +31,7 @@ for app; do b="busybox_${app}" test -f "$b" || continue eval "text=\$text_${app}" - echo "$app adds $((text-mintext))" + echo "# $app adds $((text-mintext))" done grep ^IF_ include/applets.h \ @@ -60,7 +60,7 @@ grep ^IF_ include/applets.h \ sz_frac=$(( (sz - sz_kb*1000) )) sz_f=$((sz_frac / 100)) - echo -n "sed 's/bool \"$name *(*[0-9tinykbytes .]*)*\"/" + echo -n "sed 's/bool \"$name"'[" ](*[0-9tinykbytes .]*)*"*$/' if test "$sz_kb" -ge 10; then echo -n "bool \"$name (${sz_kb} kb)\"" elif test "$sz_kb" -gt 0 -a "$sz_f" = 0; then -- cgit v1.2.3-55-g6feb From 586f1ee7cfcb442caf467a4ea5fb9351ef3c0d11 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 13:43:31 +0100 Subject: nandwrite: cope with old headers which have no MTD_FILE_MODE_RAW Signed-off-by: Denys Vlasenko --- miscutils/nandwrite.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index 72f028ed3..29c800612 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c @@ -53,6 +53,15 @@ #include "libbb.h" #include +/* Old headers call it MTD_MODE_RAW. + * FIXME: In kernel headers, MTD_FILE_MODE_RAW is not a define, + * it's an enum. How I can test for existence of an enum? + */ +#if !defined(MTD_FILE_MODE_RAW) +# define MTD_FILE_MODE_RAW 3 +#endif + + #define IS_NANDDUMP (ENABLE_NANDDUMP && (!ENABLE_NANDWRITE || (applet_name[4] == 'd'))) #define IS_NANDWRITE (ENABLE_NANDWRITE && (!ENABLE_NANDDUMP || (applet_name[4] != 'd'))) -- cgit v1.2.3-55-g6feb From cbdc37cae079d6b52ca39fb6c1dd6eadab48b617 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 14:32:11 +0100 Subject: cal: make it NOEXEC Signed-off-by: Denys Vlasenko --- NOFORK_NOEXEC.lst | 2 +- util-linux/cal.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/NOFORK_NOEXEC.lst b/NOFORK_NOEXEC.lst index 72c33ddd7..21a3b41fa 100644 --- a/NOFORK_NOEXEC.lst +++ b/NOFORK_NOEXEC.lst @@ -72,7 +72,7 @@ brctl - noexec bunzip2 - runner bzcat - runner bzip2 - runner -cal - runner: cal -n9999 +cal - noexec. can be runner: cal -n9999 cat - runner: cat HUGEFILE chat - longterm (when used as intended - talking to modem over stdin/out) chattr - noexec. runner diff --git a/util-linux/cal.c b/util-linux/cal.c index 10df0ae8b..a4a20d5f0 100644 --- a/util-linux/cal.c +++ b/util-linux/cal.c @@ -16,7 +16,8 @@ //config: help //config: cal is used to display a monthly calendar. -//applet:IF_CAL(APPLET(cal, BB_DIR_USR_BIN, BB_SUID_DROP)) +//applet:IF_CAL(APPLET_NOEXEC(cal, cal, BB_DIR_USR_BIN, BB_SUID_DROP, cal)) +/* NOEXEC despite rare cases when it can be a "runner" (e.g. cal -n12000 takes you into years 30xx) */ //kbuild:lib-$(CONFIG_CAL) += cal.o -- cgit v1.2.3-55-g6feb From 88663e481f3284225ea0ceaf97f3904adedb21a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 14:41:52 +0100 Subject: mv: make it NOEXEC Signed-off-by: Denys Vlasenko --- NOFORK_NOEXEC.lst | 4 ++-- coreutils/cp.c | 1 + coreutils/mv.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/NOFORK_NOEXEC.lst b/NOFORK_NOEXEC.lst index 21a3b41fa..055f9fb24 100644 --- a/NOFORK_NOEXEC.lst +++ b/NOFORK_NOEXEC.lst @@ -89,7 +89,7 @@ clear - NOFORK cmp - runner comm - runner conspy - interactive, longterm -cp - noexec. runner +cp - noexec. sometimes runner cpio - runner crond - daemon crontab - longterm (runs $EDITOR), leaks: open+xasprintf @@ -255,7 +255,7 @@ mount - suid mountpoint - noexec. leaks: option -n "print dev name": find_block_device -> readdir+xstrdup mpstat - longterm: "mpstat 1" runs indefinitely mt - hardware -mv - noexec candidate, runner +mv - noexec. sometimes runner nameif - noexec. openlog(), leaks: config_open2+ioctl_or_perror_and_die nbd-client - noexec nc - runner diff --git a/coreutils/cp.c b/coreutils/cp.c index 5b34c27e7..05c725cd0 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -26,6 +26,7 @@ //config: Also add support for --parents option. //applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) +/* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */ //kbuild:lib-$(CONFIG_CP) += cp.o diff --git a/coreutils/mv.c b/coreutils/mv.c index 10cbc506f..aeafd1e40 100644 --- a/coreutils/mv.c +++ b/coreutils/mv.c @@ -17,7 +17,8 @@ //config: help //config: mv is used to move or rename files or directories. -//applet:IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP)) +//applet:IF_MV(APPLET_NOEXEC(mv, mv, BB_DIR_BIN, BB_SUID_DROP, mv)) +/* NOEXEC despite cases when it can be a "runner" (mv LARGE_DIR OTHER_FS) */ //kbuild:lib-$(CONFIG_MV) += mv.o -- cgit v1.2.3-55-g6feb From 6f1c942a31fc517e0be53ccc55d5162b2c7806aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 14:44:30 +0100 Subject: NOFORK_NOEXEC.sh: a script to find "interesting" applets Signed-off-by: Denys Vlasenko --- NOFORK_NOEXEC.sh | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 NOFORK_NOEXEC.sh diff --git a/NOFORK_NOEXEC.sh b/NOFORK_NOEXEC.sh new file mode 100755 index 000000000..f4eeeef87 --- /dev/null +++ b/NOFORK_NOEXEC.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +exec >NOFORK_NOEXEC.lst1 + +false && grep -Fv 'NOFORK' NOFORK_NOEXEC.lst \ +| grep -v 'noexec.' | grep -v 'noexec$' \ +| grep -v ' suid' \ +| grep -v ' daemon' \ +| grep -v ' longterm' \ +| grep rare + +echo === nofork candidate +grep -F 'nofork candidate' NOFORK_NOEXEC.lst \ + +echo === noexec candidate +grep -F 'noexec candidate' NOFORK_NOEXEC.lst \ + +echo === ^C +grep -F '^C' NOFORK_NOEXEC.lst \ +| grep -F ' - ' \ + +echo === talks +grep -F 'talks' NOFORK_NOEXEC.lst \ +| grep -F ' - ' \ + +echo === +grep -Fv 'NOFORK' NOFORK_NOEXEC.lst \ +| grep '^[^ ][^ ]* - ' \ +| grep -v 'noexec.' | grep -v ' - noexec$' \ +| grep -v ' suid' \ +| grep -v ' daemon' \ +| grep -v 'longterm' \ +| grep -v 'interactive' \ +| grep -v 'hardware' \ -- cgit v1.2.3-55-g6feb From 996797855170685eccf0c3d9e56f819e94045938 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 19:05:02 +0100 Subject: renice: use BUILD_BUG_ON() Signed-off-by: Denys Vlasenko --- util-linux/renice.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/util-linux/renice.c b/util-linux/renice.c index 70c494b3d..65a80001b 100644 --- a/util-linux/renice.c +++ b/util-linux/renice.c @@ -42,10 +42,6 @@ #include "libbb.h" #include -void BUG_bad_PRIO_PROCESS(void); -void BUG_bad_PRIO_PGRP(void); -void BUG_bad_PRIO_USER(void); - int renice_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int renice_main(int argc UNUSED_PARAM, char **argv) { @@ -59,12 +55,9 @@ int renice_main(int argc UNUSED_PARAM, char **argv) char *arg; /* Yes, they are not #defines in glibc 2.4! #if won't work */ - if (PRIO_PROCESS < CHAR_MIN || PRIO_PROCESS > CHAR_MAX) - BUG_bad_PRIO_PROCESS(); - if (PRIO_PGRP < CHAR_MIN || PRIO_PGRP > CHAR_MAX) - BUG_bad_PRIO_PGRP(); - if (PRIO_USER < CHAR_MIN || PRIO_USER > CHAR_MAX) - BUG_bad_PRIO_USER(); + BUILD_BUG_ON(PRIO_PROCESS < CHAR_MIN || PRIO_PROCESS > CHAR_MAX); + BUILD_BUG_ON(PRIO_PGRP < CHAR_MIN || PRIO_PGRP > CHAR_MAX); + BUILD_BUG_ON(PRIO_USER < CHAR_MIN || PRIO_USER > CHAR_MAX); arg = *++argv; -- cgit v1.2.3-55-g6feb From c4144ca3a51cf5bfe7dfa5a796ae53e9ae33126c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 19:40:00 +0100 Subject: renice: add comment about getpwnam/NOFORK interaction Signed-off-by: Denys Vlasenko --- util-linux/renice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/renice.c b/util-linux/renice.c index 65a80001b..46704591f 100644 --- a/util-linux/renice.c +++ b/util-linux/renice.c @@ -6,7 +6,6 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ - /* Notes: * Setting an absolute priority was obsoleted in SUSv2 and removed * in SUSv3. However, the common linux version of renice does @@ -95,6 +94,7 @@ int renice_main(int argc UNUSED_PARAM, char **argv) /* Process an ID arg. */ if (which == PRIO_USER) { struct passwd *p; + /* NB: use of getpwnam makes it risky to be NOFORK, switch to getpwnam_r? */ p = getpwnam(arg); if (!p) { bb_error_msg("unknown user %s", arg); -- cgit v1.2.3-55-g6feb From cefdd4be1ff58923117a3b3f5168558875052a48 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 14 Jan 2018 20:48:14 +0100 Subject: popmaildir: tweak help text Signed-off-by: Denys Vlasenko --- mailutils/popmaildir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index 5756eaa76..a4aad3662 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c @@ -45,8 +45,8 @@ //usage: "\n -k Keep retrieved messages on the server" //usage: "\n -t SEC Network timeout" //usage: IF_FEATURE_POPMAILDIR_DELIVERY( -//usage: "\n -F \"PROG ARGS\" Filter program (may be repeated)" -//usage: "\n -M \"PROG ARGS\" Delivery program" +//usage: "\n -F 'PROG ARGS' Filter program (may be repeated)" +//usage: "\n -M 'PROG ARGS' Delivery program" //usage: ) //usage: "\n" //usage: "\nFetch from plain POP3 server:" -- cgit v1.2.3-55-g6feb From 1750d3afc142f467b78ca3557dcf735b5988cf74 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 15 Jan 2018 00:41:04 +0100 Subject: ash: a bit of NOFORK code should only be active if FEATURE_SH_STANDALONE=y function old new delta evalcommand 1546 1420 -126 Signed-off-by: Denys Vlasenko --- shell/ash.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 8c0f3bd8d..8211c766f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10011,7 +10011,9 @@ evalcommand(union node *cmd, int flags) switch (cmdentry.cmdtype) { default: { -#if ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1 +#if ENABLE_FEATURE_SH_STANDALONE \ + && ENABLE_FEATURE_SH_NOFORK \ + && NUM_APPLETS > 1 /* (1) BUG: if variables are set, we need to fork, or save/restore them * around run_nofork_applet() call. * (2) Should this check also be done in forkshell()? -- cgit v1.2.3-55-g6feb From 688cb3bc1979bad4236315517a7c7bb3a51289f1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 16 Jan 2018 16:00:13 +0100 Subject: udhcpc6: fix ipv6prefix[_lease] envvar value in script invocation Based on a patch by DannyAAM . Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 37ffd064d..65ff5deab 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -277,11 +277,11 @@ static void option_to_env(uint8_t *option, uint8_t *option_end) * | | * +-+-+-+-+-+-+-+-+ */ - //move_from_unaligned32(v32, option + 4 + 4); - //*new_env() = xasprintf("lease=%u", (unsigned)v32); + move_from_unaligned32(v32, option + 4 + 4); + *new_env() = xasprintf("ipv6prefix_lease=%u", (unsigned)v32); - sprint_nip6(ipv6str, option + 4 + 4 + 1); - *new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4])); + sprint_nip6(ipv6str, option + 4 + 4 + 4 + 1); + *new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4 + 4])); break; #if ENABLE_FEATURE_UDHCPC6_RFC3646 case D6_OPT_DNS_SERVERS: { -- cgit v1.2.3-55-g6feb From 1e8d79ba12d715d4375856418173c5375fbfce40 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 16 Jan 2018 21:35:39 +0100 Subject: udhcpc6: preparatory patch, no code changes Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 74 ++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 65ff5deab..57ad968cd 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1589,44 +1589,44 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) * . . * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - free(client6_data.ia_na); - client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA); - if (!client6_data.ia_na) { - bb_error_msg("no %s option, ignoring packet", "IA_NA"); - continue; - } - if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) { - bb_error_msg("IA_NA option is too short:%d bytes", client6_data.ia_na->len); - continue; - } - iaaddr = d6_find_option(client6_data.ia_na->data + 4 + 4 + 4, - client6_data.ia_na->data + client6_data.ia_na->len, - D6_OPT_IAADDR - ); - if (!iaaddr) { - bb_error_msg("no %s option, ignoring packet", "IAADDR"); - continue; - } - if (iaaddr->len < (16 + 4 + 4)) { - bb_error_msg("IAADDR option is too short:%d bytes", iaaddr->len); - continue; - } - /* Note: the address is sufficiently aligned for cast: - * we _copied_ IA-NA, and copy is always well-aligned. - */ - requested_ipv6 = (struct in6_addr*) iaaddr->data; - move_from_unaligned32(lease_seconds, iaaddr->data + 16 + 4); - lease_seconds = ntohl(lease_seconds); - /* paranoia: must not be too small and not prone to overflows */ - if (lease_seconds < 0x10) - lease_seconds = 0x10; + free(client6_data.ia_na); + client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA); + if (!client6_data.ia_na) { + bb_error_msg("no %s option, ignoring packet", "IA_NA"); + continue; + } + if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) { + bb_error_msg("IA_NA option is too short:%d bytes", client6_data.ia_na->len); + continue; + } + iaaddr = d6_find_option(client6_data.ia_na->data + 4 + 4 + 4, + client6_data.ia_na->data + client6_data.ia_na->len, + D6_OPT_IAADDR + ); + if (!iaaddr) { + bb_error_msg("no %s option, ignoring packet", "IAADDR"); + continue; + } + if (iaaddr->len < (16 + 4 + 4)) { + bb_error_msg("IAADDR option is too short:%d bytes", iaaddr->len); + continue; + } + /* Note: the address is sufficiently aligned for cast: + * we _copied_ IA-NA, and copy is always well-aligned. + */ + requested_ipv6 = (struct in6_addr*) iaaddr->data; + move_from_unaligned32(lease_seconds, iaaddr->data + 16 + 4); + lease_seconds = ntohl(lease_seconds); + /* paranoia: must not be too small and not prone to overflows */ + if (lease_seconds < 0x10) + lease_seconds = 0x10; /// TODO: check for 0 lease time? - if (lease_seconds > 0x7fffffff / 1000) - lease_seconds = 0x7fffffff / 1000; - /* enter bound state */ - timeout = lease_seconds / 2; - bb_error_msg("lease obtained, lease time %u", - /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); + if (lease_seconds > 0x7fffffff / 1000) + lease_seconds = 0x7fffffff / 1000; + /* enter bound state */ + timeout = lease_seconds / 2; + bb_error_msg("lease obtained, lease time %u", + /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); d6_run_script(&packet, state == REQUESTING ? "bound" : "renew"); state = BOUND; -- cgit v1.2.3-55-g6feb From ef5207f093216fe6cf6f1bc7a098bcab5f435a98 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 16 Jan 2018 21:39:14 +0100 Subject: udhcpc6: add support of prefix delegation Based on patch by DannyAAM Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_common.h | 1 + networking/udhcp/d6_dhcpc.c | 122 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 101 insertions(+), 22 deletions(-) diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index 310550371..e9c0397ae 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h @@ -133,6 +133,7 @@ struct d6_option { struct client6_data_t { struct d6_option *server_id; struct d6_option *ia_na; + struct d6_option *ia_pd; char **env_ptr; unsigned env_idx; /* link-local IPv6 address */ diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 57ad968cd..cfb2dcc5a 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -96,6 +96,7 @@ static const char udhcpc6_longopts[] ALIGN1 = "quit\0" No_argument "q" "release\0" No_argument "R" "request\0" Required_argument "r" + "requestprefix\0" No_argument "d" "script\0" Required_argument "s" "timeout\0" Required_argument "T" "retries\0" Required_argument "t" @@ -128,8 +129,9 @@ enum { OPT_o = 1 << 12, OPT_x = 1 << 13, OPT_f = 1 << 14, + OPT_d = 1 << 15, /* The rest has variable bit positions, need to be clever */ - OPTBIT_f = 14, + OPTBIT_d = 15, USE_FOR_MMU( OPTBIT_b,) ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) IF_FEATURE_UDHCP_PORT( OPTBIT_P,) @@ -561,18 +563,33 @@ static NOINLINE int send_d6_discover(uint32_t xid, struct in6_addr *requested_ip /* Create new IA_NA, optionally with included IAADDR with requested IP */ free(client6_data.ia_na); - len = requested_ipv6 ? 2+2+4+4+4 + 2+2+16+4+4 : 2+2+4+4+4; - client6_data.ia_na = xzalloc(len); - client6_data.ia_na->code = D6_OPT_IA_NA; - client6_data.ia_na->len = len - 4; - *(uint32_t*)client6_data.ia_na->data = rand(); /* IAID */ - if (requested_ipv6) { - struct d6_option *iaaddr = (void*)(client6_data.ia_na->data + 4+4+4); - iaaddr->code = D6_OPT_IAADDR; - iaaddr->len = 16+4+4; - memcpy(iaaddr->data, requested_ipv6, 16); + client6_data.ia_na = NULL; + if (option_mask32 & OPT_r) { + len = requested_ipv6 ? 2+2+4+4+4 + 2+2+16+4+4 : 2+2+4+4+4; + client6_data.ia_na = xzalloc(len); + client6_data.ia_na->code = D6_OPT_IA_NA; + client6_data.ia_na->len = len - 4; + *(uint32_t*)client6_data.ia_na->data = rand(); /* IAID */ + if (requested_ipv6) { + struct d6_option *iaaddr = (void*)(client6_data.ia_na->data + 4+4+4); + iaaddr->code = D6_OPT_IAADDR; + iaaddr->len = 16+4+4; + memcpy(iaaddr->data, requested_ipv6, 16); + } + opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, len); + } + + /* IA_PD */ + free(client6_data.ia_pd); + client6_data.ia_pd = NULL; + if (option_mask32 & OPT_d) { + len = 2+2+4+4+4; + client6_data.ia_pd = xzalloc(len); + client6_data.ia_pd->code = D6_OPT_IA_PD; + client6_data.ia_pd->len = len - 4; + *(uint32_t*)client6_data.ia_pd->data = rand(); /* IAID */ + opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, len); } - opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, len); /* Add options: * "param req" option according to -O, options specified with -x @@ -625,7 +642,11 @@ static NOINLINE int send_d6_select(uint32_t xid) /* server id */ opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); /* IA NA (contains requested IP) */ - opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); + if (client6_data.ia_na) + opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); + /* IA PD */ + if (client6_data.ia_pd) + opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); /* Add options: * "param req" option according to -O, options specified with -x @@ -694,7 +715,11 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st /* server id */ opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); /* IA NA (contains requested IP) */ - opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); + if (client6_data.ia_na) + opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); + /* IA PD */ + if (client6_data.ia_pd) + opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); /* Add options: * "param req" option according to -O, options specified with -x @@ -725,7 +750,11 @@ static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cu /* server id */ opt_ptr = mempcpy(opt_ptr, client6_data.server_id, client6_data.server_id->len + 2+2); /* IA NA (contains our current IP) */ - opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); + if (client6_data.ia_na) + opt_ptr = mempcpy(opt_ptr, client6_data.ia_na, client6_data.ia_na->len + 2+2); + /* IA PD */ + if (client6_data.ia_pd) + opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); bb_error_msg("sending %s", "release"); return d6_send_kernel_packet( @@ -1028,7 +1057,8 @@ static void client_background(void) ////usage: ) //usage: "\n -O,--request-option OPT Request option OPT from server (cumulative)" //usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" -//usage: "\n -r,--request IP Request this IP address" +//usage: "\n -r,--request IP Request this IP address ('no' to not request any IP)" +//usage: "\n -d,--requestprefix Request prefix" //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" //usage: "\n Examples of string, numeric, and hex byte opts:" //usage: "\n -x hostname:bbox - option 12" @@ -1062,7 +1092,8 @@ static void client_background(void) ////usage: ) //usage: "\n -O OPT Request option OPT from server (cumulative)" //usage: "\n -o Don't request any options (unless -O is given)" -//usage: "\n -r IP Request this IP address" +//usage: "\n -r IP Request this IP address ('no' to not request any IP)" +//usage: "\n -d Request prefix" //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" //usage: "\n Examples of string, numeric, and hex byte opts:" //usage: "\n -x hostname:bbox - option 12" @@ -1109,7 +1140,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) /* Parse command line */ opt = getopt32long(argv, "^" /* O,x: list; -T,-t,-A take numeric param */ - "i:np:qRr:s:T:+t:+SA:+O:*ox:*f" + "i:np:qRr:s:T:+t:+SA:+O:*ox:*fd" USE_FOR_MMU("b") ///IF_FEATURE_UDHCPC_ARPING("a") IF_FEATURE_UDHCP_PORT("P:") @@ -1125,10 +1156,15 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) IF_UDHCP_VERBOSE(, &dhcp_verbose) ); requested_ipv6 = NULL; + option_mask32 |= OPT_r; if (opt & OPT_r) { - if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0) - bb_error_msg_and_die("bad IPv6 address '%s'", str_r); - requested_ipv6 = &ipv6_buf; + if (strcmp(str_r, "no") == 0) { + option_mask32 -= OPT_r; + } else { + if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0) + bb_error_msg_and_die("bad IPv6 address '%s'", str_r); + requested_ipv6 = &ipv6_buf; + } } #if ENABLE_FEATURE_UDHCP_PORT if (opt & OPT_P) { @@ -1466,6 +1502,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) if (packet.d6_msg_type == D6_MSG_REPLY) { uint32_t lease_seconds; struct d6_option *option, *iaaddr; + int address_timeout = 0; + int prefix_timeout = 0; type_is_ok: option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); if (option && (option->data[0] | option->data[1]) != 0) { @@ -1589,6 +1627,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) * . . * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + if (option_mask32 & OPT_r) { free(client6_data.ia_na); client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA); if (!client6_data.ia_na) { @@ -1624,9 +1663,48 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) if (lease_seconds > 0x7fffffff / 1000) lease_seconds = 0x7fffffff / 1000; /* enter bound state */ - timeout = lease_seconds / 2; + address_timeout = lease_seconds / 2; bb_error_msg("lease obtained, lease time %u", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); + } + if (option_mask32 & OPT_d) { + struct d6_option *iaprefix; + + free(client6_data.ia_pd); + client6_data.ia_pd = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_PD); + if (!client6_data.ia_pd) { + bb_error_msg("no %s option, ignoring packet", "IA_PD"); + continue; + } + if (client6_data.ia_pd->len < (4 + 4 + 4) + (2 + 2 + 4 + 4 + 1 + 16)) { + bb_error_msg("IA_PD option is too short:%d bytes", client6_data.ia_pd->len); + continue; + } + iaprefix = d6_find_option(client6_data.ia_pd->data + 4 + 4 + 4, + client6_data.ia_pd->data + client6_data.ia_pd->len, + D6_OPT_IAPREFIX + ); + if (!iaprefix) { + bb_error_msg("no %s option, ignoring packet", "IAPREFIX"); + continue; + } + if (iaprefix->len < (4 + 4 + 1 + 16)) { + bb_error_msg("IAPREFIX option is too short:%d bytes", iaprefix->len); + continue; + } + move_from_unaligned32(lease_seconds, iaprefix->data + 4); + lease_seconds = ntohl(lease_seconds); + /* paranoia: must not be too small and not prone to overflows */ + if (lease_seconds < 0x10) + lease_seconds = 0x10; + if (lease_seconds > 0x7fffffff / 1000) + lease_seconds = 0x7fffffff / 1000; + /* enter bound state */ + prefix_timeout = lease_seconds / 2; + bb_error_msg("prefix obtained, lease time %u", + /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); + } + timeout = address_timeout > prefix_timeout ? prefix_timeout : address_timeout; d6_run_script(&packet, state == REQUESTING ? "bound" : "renew"); state = BOUND; -- cgit v1.2.3-55-g6feb From 14f13205efda0d1dc09d97ffab036162c13b94d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 16 Jan 2018 21:47:10 +0100 Subject: udhcpc6: code shrink function old new delta udhcpc6_main 2723 2727 +4 .rodata 128695 128561 -134 Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index cfb2dcc5a..3e200eb21 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1501,10 +1501,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) case REBINDING: if (packet.d6_msg_type == D6_MSG_REPLY) { uint32_t lease_seconds; - struct d6_option *option, *iaaddr; - int address_timeout = 0; - int prefix_timeout = 0; + struct d6_option *option; + int address_timeout; + int prefix_timeout; type_is_ok: + address_timeout = 0; + prefix_timeout = 0; option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); if (option && (option->data[0] | option->data[1]) != 0) { /* return to init state */ @@ -1628,6 +1630,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ if (option_mask32 & OPT_r) { + struct d6_option *iaaddr; + free(client6_data.ia_na); client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA); if (!client6_data.ia_na) { @@ -1635,7 +1639,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) continue; } if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) { - bb_error_msg("IA_NA option is too short:%d bytes", client6_data.ia_na->len); + bb_error_msg("%s option is too short:%d bytes", + "IA_NA", client6_data.ia_na->len); continue; } iaaddr = d6_find_option(client6_data.ia_na->data + 4 + 4 + 4, @@ -1647,7 +1652,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) continue; } if (iaaddr->len < (16 + 4 + 4)) { - bb_error_msg("IAADDR option is too short:%d bytes", iaaddr->len); + bb_error_msg("%s option is too short:%d bytes", + "IAADDR", iaaddr->len); continue; } /* Note: the address is sufficiently aligned for cast: @@ -1656,16 +1662,13 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) requested_ipv6 = (struct in6_addr*) iaaddr->data; move_from_unaligned32(lease_seconds, iaaddr->data + 16 + 4); lease_seconds = ntohl(lease_seconds); - /* paranoia: must not be too small and not prone to overflows */ - if (lease_seconds < 0x10) - lease_seconds = 0x10; /// TODO: check for 0 lease time? + /* paranoia: must not be prone to overflows */ if (lease_seconds > 0x7fffffff / 1000) lease_seconds = 0x7fffffff / 1000; - /* enter bound state */ address_timeout = lease_seconds / 2; - bb_error_msg("lease obtained, lease time %u", - /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); + bb_error_msg("%s obtained, lease time %u", + "IPv6", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); } if (option_mask32 & OPT_d) { struct d6_option *iaprefix; @@ -1677,7 +1680,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) continue; } if (client6_data.ia_pd->len < (4 + 4 + 4) + (2 + 2 + 4 + 4 + 1 + 16)) { - bb_error_msg("IA_PD option is too short:%d bytes", client6_data.ia_pd->len); + bb_error_msg("%s option is too short:%d bytes", + "IA_PD", client6_data.ia_pd->len); continue; } iaprefix = d6_find_option(client6_data.ia_pd->data + 4 + 4 + 4, @@ -1689,22 +1693,24 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) continue; } if (iaprefix->len < (4 + 4 + 1 + 16)) { - bb_error_msg("IAPREFIX option is too short:%d bytes", iaprefix->len); + bb_error_msg("%s option is too short:%d bytes", + "IAPREFIX", iaprefix->len); continue; } move_from_unaligned32(lease_seconds, iaprefix->data + 4); lease_seconds = ntohl(lease_seconds); - /* paranoia: must not be too small and not prone to overflows */ - if (lease_seconds < 0x10) - lease_seconds = 0x10; + /* paranoia: must not be prone to overflows */ if (lease_seconds > 0x7fffffff / 1000) lease_seconds = 0x7fffffff / 1000; - /* enter bound state */ prefix_timeout = lease_seconds / 2; - bb_error_msg("prefix obtained, lease time %u", - /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); + bb_error_msg("%s obtained, lease time %u", + "prefix", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); } timeout = address_timeout > prefix_timeout ? prefix_timeout : address_timeout; + /* paranoia: must not be too small */ + if (timeout < 0x10) + timeout = 0x10; + /* enter bound state */ d6_run_script(&packet, state == REQUESTING ? "bound" : "renew"); state = BOUND; -- cgit v1.2.3-55-g6feb From 6e9e6d8fbe70d7b432dd3cca30d9974dee422890 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 16 Jan 2018 21:52:23 +0100 Subject: udhcpc6: fix lease time staying very small because -d was not specified Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 3e200eb21..f6a01333c 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1706,6 +1706,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) bb_error_msg("%s obtained, lease time %u", "prefix", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); } + if (!address_timeout) + address_timeout = prefix_timeout; + if (!prefix_timeout) + prefix_timeout = address_timeout; timeout = address_timeout > prefix_timeout ? prefix_timeout : address_timeout; /* paranoia: must not be too small */ if (timeout < 0x10) -- cgit v1.2.3-55-g6feb From 438c72ece4b4241f1318994b9770877f2ab863a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 16 Jan 2018 22:10:12 +0100 Subject: udhcpc6: show only short opts in --help text function old new delta packed_usage 26028 25966 -62 Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index f6a01333c..d0d8e5c55 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1033,42 +1033,6 @@ static void client_background(void) //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" //usage: " [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") //usage:#define udhcpc6_full_usage "\n" -//usage: IF_LONG_OPTS( -//usage: "\n -i,--interface IFACE Interface to use (default eth0)" -//usage: "\n -p,--pidfile FILE Create pidfile" -//usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" -//usage: "\n -B,--broadcast Request broadcast replies" -//usage: "\n -t,--retries N Send up to N discover packets" -//usage: "\n -T,--timeout N Pause between packets (default 3 seconds)" -//usage: "\n -A,--tryagain N Wait N seconds after failure (default 20)" -//usage: "\n -f,--foreground Run in foreground" -//usage: USE_FOR_MMU( -//usage: "\n -b,--background Background if lease is not obtained" -//usage: ) -//usage: "\n -n,--now Exit if lease is not obtained" -//usage: "\n -q,--quit Exit after obtaining lease" -//usage: "\n -R,--release Release IP on exit" -//usage: "\n -S,--syslog Log to syslog too" -//usage: IF_FEATURE_UDHCP_PORT( -//usage: "\n -P,--client-port N Use port N (default 546)" -//usage: ) -////usage: IF_FEATURE_UDHCPC_ARPING( -////usage: "\n -a,--arping Use arping to validate offered address" -////usage: ) -//usage: "\n -O,--request-option OPT Request option OPT from server (cumulative)" -//usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" -//usage: "\n -r,--request IP Request this IP address ('no' to not request any IP)" -//usage: "\n -d,--requestprefix Request prefix" -//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" -//usage: "\n Examples of string, numeric, and hex byte opts:" -//usage: "\n -x hostname:bbox - option 12" -//usage: "\n -x lease:3600 - option 51 (lease time)" -//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" -//usage: IF_UDHCP_VERBOSE( -//usage: "\n -v Verbose" -//usage: ) -//usage: ) -//usage: IF_NOT_LONG_OPTS( //usage: "\n -i IFACE Interface to use (default eth0)" //usage: "\n -p FILE Create pidfile" //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" @@ -1102,7 +1066,6 @@ static void client_background(void) //usage: IF_UDHCP_VERBOSE( //usage: "\n -v Verbose" //usage: ) -//usage: ) //usage: "\nSignals:" //usage: "\n USR1 Renew lease" //usage: "\n USR2 Release lease" -- cgit v1.2.3-55-g6feb From 64211ce6fa9222de0c6f52c50ff7caf1bfbd301e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 16 Jan 2018 22:23:38 +0100 Subject: udhcpc6: --help fixes Signed-off-by: Denys Vlasenko --- networking/udhcp/Config.src | 2 +- networking/udhcp/d6_dhcpc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 8ab8d30ce..50bff2e8c 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -94,7 +94,7 @@ config FEATURE_UDHCPC_SANITIZEOPT config UDHCPC_DEFAULT_SCRIPT string "Absolute path to config script" default "/usr/share/udhcpc/default.script" - depends on UDHCPC + depends on UDHCPC || UDHCPC6 help This script is called after udhcpc receives an answer. See examples/udhcp for a working example. Normally it is safe diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index d0d8e5c55..460f3d9a4 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1030,7 +1030,7 @@ static void client_background(void) //usage:# define IF_UDHCP_VERBOSE(...) //usage:#endif //usage:#define udhcpc6_trivial_usage -//usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" +//usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"odR] [-i IFACE] [-r IPv6] [-s PROG] [-p PIDFILE]\n" //usage: " [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") //usage:#define udhcpc6_full_usage "\n" //usage: "\n -i IFACE Interface to use (default eth0)" @@ -1056,7 +1056,7 @@ static void client_background(void) ////usage: ) //usage: "\n -O OPT Request option OPT from server (cumulative)" //usage: "\n -o Don't request any options (unless -O is given)" -//usage: "\n -r IP Request this IP address ('no' to not request any IP)" +//usage: "\n -r IPv6 Request this address ('no' to not request any IP)" //usage: "\n -d Request prefix" //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" //usage: "\n Examples of string, numeric, and hex byte opts:" -- cgit v1.2.3-55-g6feb From 7c44b600f9b2ca545421cb88147275e1351ba81f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 17 Jan 2018 13:55:51 +0100 Subject: udhcpc[6]: remove overzealous timeout clamping code function old new delta udhcpc_main 2840 2826 -14 udhcpc6_main 2699 2670 -29 Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 17 ++++++----------- networking/udhcp/dhcpc.c | 6 ++++-- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 460f3d9a4..f3a7b827c 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1465,8 +1465,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) if (packet.d6_msg_type == D6_MSG_REPLY) { uint32_t lease_seconds; struct d6_option *option; - int address_timeout; - int prefix_timeout; + unsigned address_timeout; + unsigned prefix_timeout; type_is_ok: address_timeout = 0; prefix_timeout = 0; @@ -1626,12 +1626,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) move_from_unaligned32(lease_seconds, iaaddr->data + 16 + 4); lease_seconds = ntohl(lease_seconds); /// TODO: check for 0 lease time? - /* paranoia: must not be prone to overflows */ - if (lease_seconds > 0x7fffffff / 1000) - lease_seconds = 0x7fffffff / 1000; - address_timeout = lease_seconds / 2; bb_error_msg("%s obtained, lease time %u", "IPv6", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); + address_timeout = lease_seconds; } if (option_mask32 & OPT_d) { struct d6_option *iaprefix; @@ -1662,18 +1659,16 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) } move_from_unaligned32(lease_seconds, iaprefix->data + 4); lease_seconds = ntohl(lease_seconds); - /* paranoia: must not be prone to overflows */ - if (lease_seconds > 0x7fffffff / 1000) - lease_seconds = 0x7fffffff / 1000; - prefix_timeout = lease_seconds / 2; bb_error_msg("%s obtained, lease time %u", "prefix", /*inet_ntoa(temp_addr),*/ (unsigned)lease_seconds); + prefix_timeout = lease_seconds; } if (!address_timeout) address_timeout = prefix_timeout; if (!prefix_timeout) prefix_timeout = address_timeout; - timeout = address_timeout > prefix_timeout ? prefix_timeout : address_timeout; + /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */ + timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2; /* paranoia: must not be too small */ if (timeout < 0x10) timeout = 0x10; diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 55f21c187..385fc4998 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1732,8 +1732,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* paranoia: must not be too small and not prone to overflows */ if (lease_seconds < 0x10) lease_seconds = 0x10; - if (lease_seconds > 0x7fffffff / 1000) - lease_seconds = 0x7fffffff / 1000; + //if (lease_seconds > 0x7fffffff) + // lease_seconds = 0x7fffffff; + //^^^not necessary since "timeout = lease_seconds / 2" + //does not overflow even for 0xffffffff. } #if ENABLE_FEATURE_UDHCPC_ARPING if (opt & OPT_a) { -- cgit v1.2.3-55-g6feb From 6aad1ddcc9d8fe2303cc444b6ddea2af1fc1dd30 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 19 Jan 2018 15:37:04 +0100 Subject: hush: implement $LINENO bashism function old new delta run_pipe 1697 1774 +77 unset_local_var_len 258 301 +43 hush_main 1009 1051 +42 set_local_var 516 554 +38 parse_and_run_file 42 75 +33 i_getch 96 116 +20 .rodata 18858 18876 +18 done_command 106 122 +16 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 8/0 up/down: 287/0) Total: 287 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 56 +++++++++++++++++++++++++++-- shell/hush_test/hush-vars/var_LINENO1.right | 8 +++++ shell/hush_test/hush-vars/var_LINENO1.tests | 6 ++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 shell/hush_test/hush-vars/var_LINENO1.right create mode 100755 shell/hush_test/hush-vars/var_LINENO1.tests diff --git a/shell/hush.c b/shell/hush.c index 79d7a53dd..8ba48de95 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -361,6 +361,7 @@ #define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT #define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT #define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT +#define BASH_LINENO_VAR ENABLE_HUSH_BASH_COMPAT #define BASH_TEST2 (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST) #define BASH_READ_D ENABLE_HUSH_BASH_COMPAT @@ -612,6 +613,9 @@ typedef enum redir_type { struct command { pid_t pid; /* 0 if exited */ int assignment_cnt; /* how many argv[i] are assignments? */ +#if BASH_LINENO_VAR + unsigned lineno; +#endif smallint cmd_type; /* CMD_xxx */ #define CMD_NORMAL 0 #define CMD_SUBSHELL 1 @@ -930,6 +934,13 @@ struct globals { unsigned count_SIGCHLD; unsigned handled_SIGCHLD; smallint we_have_children; +#endif +#if BASH_LINENO_VAR + unsigned lineno; + char *lineno_var; +# define G_lineno_var G.lineno_var +#else +# define G_lineno_var ((char*)NULL) #endif struct FILE_list *FILE_list; /* Which signals have non-DFL handler (even with no traps set)? @@ -2135,6 +2146,13 @@ static int set_local_var(char *str, unsigned flags) } name_len = eq_sign - str + 1; /* including '=' */ +#if BASH_LINENO_VAR + if (G.lineno_var) { + if (name_len == 7 && strncmp("LINENO", str, 6) == 0) + G.lineno_var = NULL; + } +#endif + var_pp = &G.top_var; while ((cur = *var_pp) != NULL) { if (strncmp(cur->varstr, str, name_len) != 0) { @@ -2256,10 +2274,16 @@ static int unset_local_var_len(const char *name, int name_len) if (!name) return EXIT_SUCCESS; + #if ENABLE_HUSH_GETOPTS if (name_len == 6 && strncmp(name, "OPTIND", 6) == 0) G.getopt_count = 0; #endif +#if BASH_LINENO_VAR + if (name_len == 6 && G.lineno_var && strncmp(name, "LINENO", 6) == 0) + G.lineno_var = NULL; +#endif + var_pp = &G.top_var; while ((cur = *var_pp) != NULL) { if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { @@ -2578,6 +2602,10 @@ static int i_getch(struct in_str *i) out: debug_printf("file_get: got '%c' %d\n", ch, ch); i->last_char = ch; +#if BASH_LINENO_VAR + if (ch == '\n') + G.lineno++; +#endif return ch; } @@ -3460,6 +3488,9 @@ static int done_command(struct parse_context *ctx) ctx->command = command = &pi->cmds[pi->num_cmds]; clear_and_ret: memset(command, 0, sizeof(*command)); +#if BASH_LINENO_VAR + command->lineno = G.lineno; +#endif return pi->num_cmds; /* used only for 0/nonzero check */ } @@ -6520,8 +6551,13 @@ static void parse_and_run_string(const char *s) static void parse_and_run_file(FILE *f) { struct in_str input; + unsigned sv; + setup_file_in_str(&input, f); + sv = G.lineno; + G.lineno = 1; parse_and_run_stream(&input, ';'); + G.lineno = sv; } #if ENABLE_HUSH_TICK @@ -8068,6 +8104,9 @@ static NOINLINE int run_pipe(struct pipe *pi) char **new_env = NULL; struct variable *old_vars = NULL; + if (G_lineno_var) + strcpy(G_lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); + if (argv[command->assignment_cnt] == NULL) { /* Assignments, but no command */ /* Ensure redirects take effect (that is, create files). @@ -8272,6 +8311,9 @@ static NOINLINE int run_pipe(struct pipe *pi) if (cmd_no < pi->num_cmds) xpiped_pair(pipefds); + if (G_lineno_var) + strcpy(G_lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); + command->pid = BB_MMU ? fork() : vfork(); if (!command->pid) { /* child */ #if ENABLE_HUSH_JOB @@ -8907,17 +8949,19 @@ int hush_main(int argc, char **argv) #if !BB_MMU G.argv0_for_re_execing = argv[0]; #endif + /* Deal with HUSH_VERSION */ + debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); + unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ shell_ver = xzalloc(sizeof(*shell_ver)); shell_ver->flg_export = 1; shell_ver->flg_read_only = 1; /* Code which handles ${var...} needs writable values for all variables, * therefore we xstrdup: */ shell_ver->varstr = xstrdup(hush_version_str); + /* Create shell local variables from the values * currently living in the environment */ - debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); - unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ G.top_var = shell_ver; cur_var = G.top_var; e = environ; @@ -8983,6 +9027,14 @@ int hush_main(int argc, char **argv) */ #endif +#if BASH_LINENO_VAR + if (BASH_LINENO_VAR) { + char *p = xasprintf("LINENO=%*s", (int)(sizeof(int)*3), ""); + set_local_var(p, /*flags*/ 0); + G.lineno_var = p; /* can't assign before set_local_var("LINENO=...") */ + } +#endif + #if ENABLE_FEATURE_EDITING G.line_input_state = new_line_input_t(FOR_SHELL); #endif diff --git a/shell/hush_test/hush-vars/var_LINENO1.right b/shell/hush_test/hush-vars/var_LINENO1.right new file mode 100644 index 000000000..31e1a4478 --- /dev/null +++ b/shell/hush_test/hush-vars/var_LINENO1.right @@ -0,0 +1,8 @@ +2:2 +3:3 +4:4 +5:5 +2:2 +3:3 +4:4 +5:5 diff --git a/shell/hush_test/hush-vars/var_LINENO1.tests b/shell/hush_test/hush-vars/var_LINENO1.tests new file mode 100755 index 000000000..851b52cf5 --- /dev/null +++ b/shell/hush_test/hush-vars/var_LINENO1.tests @@ -0,0 +1,6 @@ +env | grep LINENO +echo 2:$LINENO +echo 3:$LINENO >&2 \ +| { sleep 0.1; echo 4:$LINENO; } +echo 5:$LINENO +test "$1" || . ./var_LINENO1.tests norepeat -- cgit v1.2.3-55-g6feb From b8d076b00bad9da87e6dcaf4f36dfd06e2d2e5e8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 19 Jan 2018 16:00:57 +0100 Subject: hush: fix build if !BASH_LINENO_VAR Signed-off-by: Denys Vlasenko --- shell/hush.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 8ba48de95..85526a9f0 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -938,9 +938,6 @@ struct globals { #if BASH_LINENO_VAR unsigned lineno; char *lineno_var; -# define G_lineno_var G.lineno_var -#else -# define G_lineno_var ((char*)NULL) #endif struct FILE_list *FILE_list; /* Which signals have non-DFL handler (even with no traps set)? @@ -6551,13 +6548,17 @@ static void parse_and_run_string(const char *s) static void parse_and_run_file(FILE *f) { struct in_str input; +#if BASH_LINENO_VAR unsigned sv; - setup_file_in_str(&input, f); sv = G.lineno; G.lineno = 1; +#endif + setup_file_in_str(&input, f); parse_and_run_stream(&input, ';'); +#if BASH_LINENO_VAR G.lineno = sv; +#endif } #if ENABLE_HUSH_TICK @@ -8104,8 +8105,10 @@ static NOINLINE int run_pipe(struct pipe *pi) char **new_env = NULL; struct variable *old_vars = NULL; - if (G_lineno_var) - strcpy(G_lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); +#if BASH_LINENO_VAR + if (G.lineno_var) + strcpy(G.lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); +#endif if (argv[command->assignment_cnt] == NULL) { /* Assignments, but no command */ @@ -8311,8 +8314,10 @@ static NOINLINE int run_pipe(struct pipe *pi) if (cmd_no < pi->num_cmds) xpiped_pair(pipefds); - if (G_lineno_var) - strcpy(G_lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); +#if BASH_LINENO_VAR + if (G.lineno_var) + strcpy(G.lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); +#endif command->pid = BB_MMU ? fork() : vfork(); if (!command->pid) { /* child */ -- cgit v1.2.3-55-g6feb From 46f839c3f7476cb9016c4787729f64a2c24509d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 19 Jan 2018 16:58:44 +0100 Subject: hush: fix a case where EXIT trap may modify its code mid-flight function old new delta hush_exit 93 99 +6 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 85526a9f0..7b83c736c 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1936,7 +1936,7 @@ static void hush_exit(int exitcode) if (G.exiting <= 0 && G_traps && G_traps[0] && G_traps[0][0]) { char *argv[3]; /* argv[0] is unused */ - argv[1] = G_traps[0]; + argv[1] = xstrdup(G_traps[0]); /* copy, since EXIT trap handler may modify G_traps[0] */ argv[2] = NULL; G.exiting = 1; /* prevent EXIT trap recursion */ /* Note: G_traps[0] is not cleared! -- cgit v1.2.3-55-g6feb From f6dd9e02155430a608e1b38036e355c045772d04 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 19 Jan 2018 18:44:19 +0100 Subject: udhcpc6: fix for ppp interface type function old new delta d6_read_interface 454 600 +146 Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 4 ++-- networking/udhcp/d6_socket.c | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index f3a7b827c..07a8b11c1 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1093,6 +1093,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) int retval; setup_common_bufsiz(); + /* We want random_xid to be random */ + srand(monotonic_us()); /* Default options */ IF_FEATURE_UDHCP_PORT(SERVER_PORT6 = 547;) @@ -1207,8 +1209,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) bb_error_msg("started, v"BB_VER); /* Set up the signal pipe */ udhcp_sp_setup(); - /* We want random_xid to be random... */ - srand(monotonic_us()); state = INIT_SELECTING; d6_run_script(NULL, "deconfig"); diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c index d00c217d6..f9082ee9d 100644 --- a/networking/udhcp/d6_socket.c +++ b/networking/udhcp/d6_socket.c @@ -16,7 +16,6 @@ int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_ struct ifaddrs *ifap, *ifa; getifaddrs(&ifap); - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { struct sockaddr_in6 *sip6; @@ -29,9 +28,9 @@ int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_ struct sockaddr_ll *sll = (struct sockaddr_ll*)(ifa->ifa_addr); memcpy(mac, sll->sll_addr, 6); log2("MAC %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - log2("ifindex %d", sll->sll_ifindex); *ifindex = sll->sll_ifindex; - retval &= (0xf - (1<<0)); + log2("ifindex %d", *ifindex); + retval &= (3 - (1<<0)); } #if 0 if (ifa->ifa_addr->sa_family == AF_INET) { @@ -54,11 +53,29 @@ int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_ nip6->s6_addr[12], nip6->s6_addr[13], nip6->s6_addr[14], nip6->s6_addr[15] ); - retval &= (0xf - (1<<1)); + retval &= (3 - (1<<1)); } } - freeifaddrs(ifap); + + if (retval & (1<<0)) { + /* This iface has no MAC (e.g. ppp), generate a random one */ + struct ifreq ifr; + int fd; + + memset(&ifr, 0, sizeof(ifr)); + strncpy_IFNAMSIZ(ifr.ifr_name, interface); + fd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_RAW); + if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) { + *ifindex = ifr.ifr_ifindex; + log2("ifindex %d", *ifindex); + ((uint32_t*)mac)[0] = rand(); + ((uint16_t*)mac)[2] = rand(); + retval &= (3 - (1<<0)); + } + close(fd); + } + if (retval == 0) return retval; -- cgit v1.2.3-55-g6feb From e411cd071a2b6456c653f1a7179b83bef810bb72 Mon Sep 17 00:00:00 2001 From: Sven-Göran Bergh Date: Fri, 19 Jan 2018 20:36:15 +0100 Subject: volume_id: add LittleFS detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for LittleFS to blkid. Not included if FEATURE_BLKID_TYPE is not selected (neither UUID nor label). LittleFS is a small fail-safe filesystem designed for embedded systems. It has strong copy-on-write guarantees and storage on disk is always kept in a valid state. It also provides a form of dynamic wear levelling for systems that can not fit a full flash translation layer. (https://github.com/geky/littlefs) ARM has introduced it in its Mbed OS 5.7, so it starts to gain focus. (https://os.mbed.com/blog/entry/littlefs-high-integrity-embedded-fs/) function old new delta volume_id_probe_lfs - 62 +62 fs1 20 24 +4 Signed-off-by: Sven-Göran Bergh Signed-off-by: Denys Vlasenko --- util-linux/volume_id/lfs.c | 62 +++++++++++++++++++++++++++++++ util-linux/volume_id/volume_id.c | 3 ++ util-linux/volume_id/volume_id_internal.h | 2 + 3 files changed, 67 insertions(+) create mode 100644 util-linux/volume_id/lfs.c diff --git a/util-linux/volume_id/lfs.c b/util-linux/volume_id/lfs.c new file mode 100644 index 000000000..1a2a2987f --- /dev/null +++ b/util-linux/volume_id/lfs.c @@ -0,0 +1,62 @@ +/* + * volume_id - reads filesystem label and uuid + * + * Copyright (C) 2018 Sven-Göran Bergh + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//config:config FEATURE_VOLUMEID_LFS +//config: bool "LittleFS filesystem" +//config: default y +//config: depends on VOLUMEID && FEATURE_BLKID_TYPE +//config: help +//config: LittleFS is a small fail-safe filesystem designed for embedded +//config: systems. It has strong copy-on-write guarantees and storage on disk +//config: is always kept in a valid state. It also provides a form of dynamic +//config: wear levelling for systems that can not fit a full flash translation +//config: layer. + +//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LFS) += lfs.o + +#include "volume_id_internal.h" + +#define LFS_SB1_OFFSET 0x10 +#define LFS_MAGIC_NAME "littlefs" +#define LFS_MAGIC_LEN 8 + +// The superblock is stored in the first metadata pair, i.e the first two blocks. +struct lfs_super_block { // A block in a metadata pair +// /* 0x00 */ uint32_t rev_count; // Revision count +// /* 0x04 */ uint32_t dir_size; // Directory size +// /* 0x08 */ uint64_t tail_ptr; // Tail pointer +/* 0x10 */ uint8_t entry_type; // Entry type +/* 0x11 */ uint8_t entry_len; // Entry length +/* 0x12 */ uint8_t att_len; // Attribute length +/* 0x13 */ uint8_t name_len; // Name length +/* 0x14 */ uint64_t root_dir; // Root directory +/* 0x1C */ uint32_t block_size; // Block size +/* 0x20 */ uint32_t block_count; // Block count +/* 0x24 */ uint16_t ver_major; // Version major +/* 0x26 */ uint16_t ver_minor; // Version minor +/* 0x28 */ uint8_t magic[LFS_MAGIC_LEN]; // Magic string "littlefs" +// /* 0x30 */ uint32_t crc; // CRC-32 checksum +} PACKED; + +int FAST_FUNC volume_id_probe_lfs(struct volume_id *id /*,uint64_t off*/) +{ + struct lfs_super_block *sb; + + // Go for primary super block (ignore second sb) + dbg("lfs: probing at offset 0x%x", LFS_SB1_OFFSET); + sb = volume_id_get_buffer(id, LFS_SB1_OFFSET, sizeof(*sb)); + + if (!sb) + return -1; + + if (memcmp(sb->magic, LFS_MAGIC_NAME, LFS_MAGIC_LEN) != 0) + return -1; + + IF_FEATURE_BLKID_TYPE(id->type = LFS_MAGIC_NAME); + + return 0; +} diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c index 85315ced6..c3f07a741 100644 --- a/util-linux/volume_id/volume_id.c +++ b/util-linux/volume_id/volume_id.c @@ -97,6 +97,9 @@ static const probe_fptr fs1[] = { #if ENABLE_FEATURE_VOLUMEID_EXFAT volume_id_probe_exfat, #endif +#if ENABLE_FEATURE_VOLUMEID_LFS + volume_id_probe_lfs, +#endif #if ENABLE_FEATURE_VOLUMEID_MAC volume_id_probe_mac_partition_map, #endif diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index 0eaea9b34..ada18339d 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h @@ -187,6 +187,8 @@ int FAST_FUNC volume_id_probe_iso9660(struct volume_id *id /*,uint64_t off*/); int FAST_FUNC volume_id_probe_jfs(struct volume_id *id /*,uint64_t off*/); +int FAST_FUNC volume_id_probe_lfs(struct volume_id *id /*,uint64_t off*/); + int FAST_FUNC volume_id_probe_linux_swap(struct volume_id *id /*,uint64_t off*/); int FAST_FUNC volume_id_probe_luks(struct volume_id *id /*,uint64_t off*/); -- cgit v1.2.3-55-g6feb From 8528d3d4f8240ab4715f671aa819fe034f0fc285 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Jan 2018 14:38:51 +0100 Subject: less: optional support of -R Based on patches by Lubomir Rintel function old new delta read_lines 653 722 +69 less_main 2464 2531 +67 packed_usage 32202 32239 +37 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 173/0) Total: 173 bytes Signed-off-by: Denys Vlasenko --- miscutils/less.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/miscutils/less.c b/miscutils/less.c index d60e6d920..c3221a49f 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -99,6 +99,22 @@ //config: bool "Enable -N (dynamic switching of line numbers)" //config: default y //config: depends on FEATURE_LESS_DASHCMD +//config: +//config:config FEATURE_LESS_RAW +//config: bool "Enable -R ('raw control characters')" +//config: default y +//config: depends on FEATURE_LESS_DASHCMD +//config: help +//config: This is essential for less applet to work with tools that use colors +//config: and paging, such as git, systemd tools or nmcli. +//config: +//config:config FEATURE_LESS_ENV +//config: bool "Take options from $LESS environment variable" +//config: default y +//config: depends on FEATURE_LESS_DASHCMD +//config: help +//config: This is essential for less applet to work with tools that use colors +//config: and paging, such as git, systemd tools or nmcli. //applet:IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP)) @@ -106,7 +122,7 @@ //usage:#define less_trivial_usage //usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm") -//usage: "N" IF_FEATURE_LESS_TRUNCATE("S") "h~] [FILE]..." +//usage: "N" IF_FEATURE_LESS_TRUNCATE("S") IF_FEATURE_LESS_TRUNCATE("R") "h~] [FILE]..." //usage:#define less_full_usage "\n\n" //usage: "View FILE (or stdin) one screenful at a time\n" //usage: "\n -E Quit once the end of a file is reached" @@ -121,6 +137,9 @@ //usage: IF_FEATURE_LESS_TRUNCATE( //usage: "\n -S Truncate long lines" //usage: ) +//usage: IF_FEATURE_LESS_RAW( +//usage: "\n -R Remove color escape codes in input" +//usage: ) //usage: "\n -~ Suppress ~s displayed past EOF" #include /* sched_yield() */ @@ -157,6 +176,7 @@ enum { FLAG_TILDE = 1 << 4, FLAG_I = 1 << 5, FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_TRUNCATE, + FLAG_R = (1 << 7) * ENABLE_FEATURE_LESS_RAW, /* hijack command line options variable for internal state vars */ LESS_STATE_MATCH_BACKWARDS = 1 << 15, }; @@ -207,6 +227,9 @@ struct globals { regex_t pattern; smallint pattern_valid; #endif +#if ENABLE_FEATURE_LESS_RAW + smallint in_escape; +#endif #if ENABLE_FEATURE_LESS_ASK_TERMINAL smallint winsize_err; #endif @@ -513,6 +536,26 @@ static void read_lines(void) *--p = '\0'; continue; } +#if ENABLE_FEATURE_LESS_RAW + if (option_mask32 & FLAG_R) { + if (c == '\033') + goto discard; + if (G.in_escape) { + if (isdigit(c) + || c == '[' + || c == ';' + || c == 'm' + ) { + discard: + G.in_escape = (c != 'm'); + readpos++; + continue; + } + /* Hmm, unexpected end of "ESC [ N ; N m" sequence */ + G.in_escape = 0; + } + } +#endif { size_t new_last_line_pos = last_line_pos + 1; if (c == '\t') { @@ -1776,6 +1819,25 @@ int less_main(int argc, char **argv) num_files = argc - optind; files = argv; + /* Tools typically pass LESS="FRSXMK". + * The options we don't understand are ignored. */ + if (ENABLE_FEATURE_LESS_ENV) { + char *c = getenv("LESS"); + if (c) while (*c) switch (*c++) { + case 'M': + option_mask32 |= FLAG_M; + break; + case 'R': + option_mask32 |= FLAG_R; + break; + case 'S': + option_mask32 |= FLAG_S; + break; + default: + break; + } + } + /* Another popular pager, most, detects when stdout * is not a tty and turns into cat. This makes sense. */ if (!isatty(STDOUT_FILENO)) -- cgit v1.2.3-55-g6feb From 2b9a45b9e87c1c935cf0a992303313d62e72dc67 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 23 Jan 2018 14:49:12 +0100 Subject: od_bloaty: fix debug code Signed-off-by: Denys Vlasenko --- coreutils/od_bloaty.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index f19875c42..c9bb3b85f 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c @@ -1371,9 +1371,13 @@ int od_main(int argc UNUSED_PARAM, char **argv) } #ifdef DEBUG - for (i = 0; i < G.n_specs; i++) { - printf("%d: fmt=\"%s\" width=%d\n", - i, spec[i].fmt_string, width_bytes[spec[i].size]); + { + int i; + for (i = 0; i < G.n_specs; i++) { + printf("%d: fmt='%s' width=%d\n", + i, G.spec[i].fmt_string, + width_bytes[G.spec[i].size]); + } } #endif -- cgit v1.2.3-55-g6feb From 1616fb8aca23fd7ba6b379b0fb38d3327d1e31d1 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sat, 13 Jan 2018 23:26:39 +0200 Subject: chrt: add support for SCHED_BATCH Signed-off-by: Povilas Kanapickas Signed-off-by: Denys Vlasenko --- util-linux/chrt.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/util-linux/chrt.c b/util-linux/chrt.c index 2712ea3e3..e7abd4f5a 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c @@ -17,13 +17,14 @@ //kbuild:lib-$(CONFIG_CHRT) += chrt.o //usage:#define chrt_trivial_usage -//usage: "[-prfom] [PRIO] [PID | PROG ARGS]" +//usage: "[-prfomb] [PRIO] [PID | PROG ARGS]" //usage:#define chrt_full_usage "\n\n" //usage: "Change scheduling priority and class for a process\n" //usage: "\n -p Operate on PID" //usage: "\n -r Set SCHED_RR class" //usage: "\n -f Set SCHED_FIFO class" //usage: "\n -o Set SCHED_OTHER class" +//usage: "\n -b Set SCHED_BATCH class" //usage: "\n -m Show min/max priorities" //usage: //usage:#define chrt_example_usage @@ -40,11 +41,11 @@ static const struct { } policies[] = { {SCHED_OTHER, "SCHED_OTHER"}, {SCHED_FIFO, "SCHED_FIFO"}, - {SCHED_RR, "SCHED_RR"} + {SCHED_RR, "SCHED_RR"}, + {SCHED_BATCH, "SCHED_BATCH"} }; //TODO: add -// -b, SCHED_BATCH // -i, SCHED_IDLE static void show_min_max(int pol) @@ -64,6 +65,7 @@ static void show_min_max(int pol) #define OPT_r (1<<2) #define OPT_f (1<<3) #define OPT_o (1<<4) +#define OPT_b (1<<5) int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int chrt_main(int argc UNUSED_PARAM, char **argv) @@ -77,11 +79,12 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) int policy = SCHED_RR; /* only one policy accepted */ - opt = getopt32(argv, "^+" "mprfo" "\0" "r--fo:f--ro:o--rf"); + opt = getopt32(argv, "^+" "mprfob" "\0" "r--fob:f--rob:o--rfb:b--rfo"); if (opt & OPT_m) { /* print min/max and exit */ show_min_max(SCHED_FIFO); show_min_max(SCHED_RR); show_min_max(SCHED_OTHER); + show_min_max(SCHED_BATCH); fflush_stdout_and_exit(EXIT_SUCCESS); } if (opt & OPT_r) @@ -90,6 +93,8 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) policy = SCHED_FIFO; if (opt & OPT_o) policy = SCHED_OTHER; + if (opt & OPT_b) + policy = SCHED_BATCH; argv += optind; if (!argv[0]) @@ -136,7 +141,8 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) [...] SCHED_OTHER or SCHED_BATCH must be assigned static priority 0. [...] SCHED_FIFO or SCHED_RR can have static priority in 1..99 range. */ - sp.sched_priority = xstrtou_range(priority, 0, policy != SCHED_OTHER ? 1 : 0, 99); + sp.sched_priority = xstrtou_range(priority, 0, + (policy != SCHED_OTHER && policy != SCHED_BATCH) ? 1 : 0, 99); if (sched_setscheduler(pid, policy, &sp) < 0) bb_perror_msg_and_die("can't %cet pid %d's policy", 's', (int)pid); -- cgit v1.2.3-55-g6feb From 0f6e4350b3c36b3b4533d0ea910481e28d5f81ab Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sat, 13 Jan 2018 23:27:37 +0200 Subject: chrt: add support for SCHED_IDLE Signed-off-by: Povilas Kanapickas Signed-off-by: Denys Vlasenko --- util-linux/chrt.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/util-linux/chrt.c b/util-linux/chrt.c index e7abd4f5a..bbd6e2deb 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c @@ -17,7 +17,7 @@ //kbuild:lib-$(CONFIG_CHRT) += chrt.o //usage:#define chrt_trivial_usage -//usage: "[-prfomb] [PRIO] [PID | PROG ARGS]" +//usage: "[-prfombi] [PRIO] [PID | PROG ARGS]" //usage:#define chrt_full_usage "\n\n" //usage: "Change scheduling priority and class for a process\n" //usage: "\n -p Operate on PID" @@ -25,6 +25,7 @@ //usage: "\n -f Set SCHED_FIFO class" //usage: "\n -o Set SCHED_OTHER class" //usage: "\n -b Set SCHED_BATCH class" +//usage: "\n -i Set SCHED_IDLE class" //usage: "\n -m Show min/max priorities" //usage: //usage:#define chrt_example_usage @@ -42,12 +43,11 @@ static const struct { {SCHED_OTHER, "SCHED_OTHER"}, {SCHED_FIFO, "SCHED_FIFO"}, {SCHED_RR, "SCHED_RR"}, - {SCHED_BATCH, "SCHED_BATCH"} + {SCHED_BATCH, "SCHED_BATCH"}, + {0 /* unused */, ""}, + {SCHED_IDLE, "SCHED_IDLE"} }; -//TODO: add -// -i, SCHED_IDLE - static void show_min_max(int pol) { const char *fmt = "%s min/max priority\t: %u/%u\n"; @@ -66,6 +66,7 @@ static void show_min_max(int pol) #define OPT_f (1<<3) #define OPT_o (1<<4) #define OPT_b (1<<5) +#define OPT_i (1<<6) int chrt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int chrt_main(int argc UNUSED_PARAM, char **argv) @@ -79,12 +80,13 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) int policy = SCHED_RR; /* only one policy accepted */ - opt = getopt32(argv, "^+" "mprfob" "\0" "r--fob:f--rob:o--rfb:b--rfo"); + opt = getopt32(argv, "^+" "mprfobi" "\0" "r--fobi:f--robi:o--rfbi:b--rfoi:i--rfob"); if (opt & OPT_m) { /* print min/max and exit */ show_min_max(SCHED_FIFO); show_min_max(SCHED_RR); show_min_max(SCHED_OTHER); show_min_max(SCHED_BATCH); + show_min_max(SCHED_IDLE); fflush_stdout_and_exit(EXIT_SUCCESS); } if (opt & OPT_r) @@ -95,6 +97,8 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) policy = SCHED_OTHER; if (opt & OPT_b) policy = SCHED_BATCH; + if (opt & OPT_i) + policy = SCHED_IDLE; argv += optind; if (!argv[0]) @@ -138,11 +142,12 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) /* from the manpage of sched_getscheduler: [...] sched_priority can have a value in the range 0 to 99. - [...] SCHED_OTHER or SCHED_BATCH must be assigned static priority 0. + [...] SCHED_OTHER, SCHED_BATCH or SCHED_IDLE must be assigned static + priority 0. [...] SCHED_FIFO or SCHED_RR can have static priority in 1..99 range. */ sp.sched_priority = xstrtou_range(priority, 0, - (policy != SCHED_OTHER && policy != SCHED_BATCH) ? 1 : 0, 99); + (policy != SCHED_OTHER && policy != SCHED_BATCH && policy != SCHED_IDLE) ? 1 : 0, 99); if (sched_setscheduler(pid, policy, &sp) < 0) bb_perror_msg_and_die("can't %cet pid %d's policy", 's', (int)pid); -- cgit v1.2.3-55-g6feb From 66ad9be6031a3c5c0491b0040270b3f9ff591cdf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 23 Jan 2018 16:01:13 +0100 Subject: chrt: use correct min/max priorities function old new delta chrt_main 369 432 +63 policies 48 96 +48 packed_usage 32239 32249 +10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 121/0) Total: 121 bytes Signed-off-by: Denys Vlasenko --- util-linux/chrt.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/util-linux/chrt.c b/util-linux/chrt.c index bbd6e2deb..27c8f43cc 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c @@ -35,6 +35,9 @@ #include #include "libbb.h" +#ifndef SCHED_IDLE +# define SCHED_IDLE 5 +#endif static const struct { int policy; @@ -79,18 +82,22 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) const char *current_new; int policy = SCHED_RR; - /* only one policy accepted */ - opt = getopt32(argv, "^+" "mprfobi" "\0" "r--fobi:f--robi:o--rfbi:b--rfoi:i--rfob"); + opt = getopt32(argv, "^" + "+" "mprfobi" + "\0" + /* only one policy accepted: */ + "r--fobi:f--robi:o--rfbi:b--rfoi:i--rfob" + ); if (opt & OPT_m) { /* print min/max and exit */ + show_min_max(SCHED_OTHER); show_min_max(SCHED_FIFO); show_min_max(SCHED_RR); - show_min_max(SCHED_OTHER); show_min_max(SCHED_BATCH); show_min_max(SCHED_IDLE); fflush_stdout_and_exit(EXIT_SUCCESS); } - if (opt & OPT_r) - policy = SCHED_RR; + //if (opt & OPT_r) + // policy = SCHED_RR; - default, already set if (opt & OPT_f) policy = SCHED_FIFO; if (opt & OPT_o) @@ -140,14 +147,9 @@ int chrt_main(int argc UNUSED_PARAM, char **argv) current_new += 8; } - /* from the manpage of sched_getscheduler: - [...] sched_priority can have a value in the range 0 to 99. - [...] SCHED_OTHER, SCHED_BATCH or SCHED_IDLE must be assigned static - priority 0. - [...] SCHED_FIFO or SCHED_RR can have static priority in 1..99 range. - */ sp.sched_priority = xstrtou_range(priority, 0, - (policy != SCHED_OTHER && policy != SCHED_BATCH && policy != SCHED_IDLE) ? 1 : 0, 99); + sched_get_priority_min(policy), sched_get_priority_max(policy) + ); if (sched_setscheduler(pid, policy, &sp) < 0) bb_perror_msg_and_die("can't %cet pid %d's policy", 's', (int)pid); -- cgit v1.2.3-55-g6feb From 30b290f996366e9370eadc0321cb59ec4eb85181 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 23 Jan 2018 16:46:31 +0100 Subject: udhcpc6: additional fix for ppp interface type Invent a fictitious MAC only once Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_socket.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/networking/udhcp/d6_socket.c b/networking/udhcp/d6_socket.c index f9082ee9d..315c8d98a 100644 --- a/networking/udhcp/d6_socket.c +++ b/networking/udhcp/d6_socket.c @@ -69,8 +69,12 @@ int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_ if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) { *ifindex = ifr.ifr_ifindex; log2("ifindex %d", *ifindex); - ((uint32_t*)mac)[0] = rand(); - ((uint16_t*)mac)[2] = rand(); + if (((uint32_t*)mac)[0] == 0) { + /* invent a fictitious MAC (once) */ + ((uint32_t*)mac)[0] = rand(); + ((uint16_t*)mac)[2] = rand(); + mac[0] &= 0xfc; /* make sure it's not bcast */ + } retval &= (3 - (1<<0)); } close(fd); -- cgit v1.2.3-55-g6feb From 14bc965ea9c869716f6b42814b140571f50c5f18 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Jan 2018 16:47:08 +0100 Subject: less: fix help text conditional for -R Signed-off-by: Denys Vlasenko --- miscutils/less.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/less.c b/miscutils/less.c index c3221a49f..97ab1e6f8 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -122,7 +122,7 @@ //usage:#define less_trivial_usage //usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm") -//usage: "N" IF_FEATURE_LESS_TRUNCATE("S") IF_FEATURE_LESS_TRUNCATE("R") "h~] [FILE]..." +//usage: "N" IF_FEATURE_LESS_TRUNCATE("S") IF_FEATURE_LESS_RAW("R") "h~] [FILE]..." //usage:#define less_full_usage "\n\n" //usage: "View FILE (or stdin) one screenful at a time\n" //usage: "\n -E Quit once the end of a file is reached" -- cgit v1.2.3-55-g6feb From d8fd88a0915364c30769ec5c5a6b542517fd55f3 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Wed, 24 Jan 2018 18:33:18 +0100 Subject: ash: add support for command_not_found_handle hook function (bashism) This implements support for the command_not_found_handle hook function, which is useful for allowing package managers to suggest packages which could provide the command. Unlike bash, however, we ignore exit codes from the hook function and always return the correct POSIX error code (EX_NOTFOUND). function old new delta find_command 911 990 +79 Signed-off-by: William Pitcock Signed-off-by: Denys Vlasenko --- shell/ash.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 8211c766f..865159d20 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -51,6 +51,15 @@ //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: +//config:config ASH_BASH_NOT_FOUND_HOOK +//config: bool "command_not_found_handle hook support" +//config: default y +//config: depends ASH_BASH_COMPAT +//config: help +//config: Enable support for the 'command_not_found_handle' hook function, +//config: from GNU bash, which allows for alternative command not found +//config: handling. +//config: //config:config ASH_JOB_CONTROL //config: bool "Job control" //config: default y @@ -13227,8 +13236,21 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) /* We failed. If there was an entry for this command, delete it */ if (cmdp && updatetbl) delete_cmd_entry(); - if (act & DO_ERR) + if (act & DO_ERR) { +#if ENABLE_ASH_BASH_NOT_FOUND_HOOK + struct tblentry *hookp = cmdlookup("command_not_found_handle", 0); + if (hookp && hookp->cmdtype == CMDFUNCTION) { + char *argv[3]; + argv[0] = (char*) "command_not_found_handle"; + argv[1] = name; + argv[2] = NULL; + evalfun(hookp->param.func, 2, argv, 0); + entry->cmdtype = CMDUNKNOWN; + return; + } +#endif ash_msg("%s: %s", name, errmsg(e, "not found")); + } entry->cmdtype = CMDUNKNOWN; return; -- cgit v1.2.3-55-g6feb From a497231f537352c7ff7a80c07ef6191b00e7e30e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 25 Jan 2018 09:34:23 +0100 Subject: chrt: code shrink function old new delta show_min_max 60 59 -1 policies 96 72 -24 Signed-off-by: Denys Vlasenko --- util-linux/chrt.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/util-linux/chrt.c b/util-linux/chrt.c index 27c8f43cc..45459d940 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c @@ -9,7 +9,7 @@ //config: bool "chrt (4.4 kb)" //config: default y //config: help -//config: manipulate real-time attributes of a process. +//config: Manipulate real-time attributes of a process. //config: This requires sched_{g,s}etparam support in your libc. //applet:IF_CHRT(APPLET_NOEXEC(chrt, chrt, BB_DIR_USR_BIN, BB_SUID_DROP, chrt)) @@ -40,15 +40,15 @@ #endif static const struct { - int policy; char name[sizeof("SCHED_OTHER")]; } policies[] = { - {SCHED_OTHER, "SCHED_OTHER"}, - {SCHED_FIFO, "SCHED_FIFO"}, - {SCHED_RR, "SCHED_RR"}, - {SCHED_BATCH, "SCHED_BATCH"}, - {0 /* unused */, ""}, - {SCHED_IDLE, "SCHED_IDLE"} + { "SCHED_OTHER" }, /* 0:SCHED_OTHER */ + { "SCHED_FIFO" }, /* 1:SCHED_FIFO */ + { "SCHED_RR" }, /* 2:SCHED_RR */ + { "SCHED_BATCH" }, /* 3:SCHED_BATCH */ + { "" }, /* 4:SCHED_ISO */ + { "SCHED_IDLE" }, /* 5:SCHED_IDLE */ + /* 6:SCHED_DEADLINE */ }; static void show_min_max(int pol) -- cgit v1.2.3-55-g6feb From 0ca3198f9333b363ced46bfabf51c0d6b111c875 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 25 Jan 2018 13:20:50 +0100 Subject: hush: fix handling of $_ (so far it's an ordinary variable, no special meaning) function old new delta parse_dollar 820 779 -41 Signed-off-by: Denys Vlasenko --- shell/hush.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 7b83c736c..a9183c82f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4520,9 +4520,10 @@ static int parse_dollar(o_string *as_string, debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); if (isalpha(ch)) { + make_var: ch = i_getch(input); nommu_addchr(as_string, ch); - make_var: + /*make_var1:*/ o_addchr(dest, SPECIAL_VAR_SYMBOL); while (1) { debug_printf_parse(": '%c'\n", ch); @@ -4715,19 +4716,22 @@ static int parse_dollar(o_string *as_string, } #endif case '_': + goto make_var; +#if 0 + /* TODO: $_ and $-: */ + /* $_ Shell or shell script name; or last argument of last command + * (if last command wasn't a pipe; if it was, bash sets $_ to ""); + * but in command's env, set to full pathname used to invoke it */ + /* $- Option flags set by set builtin or shell options (-i etc) */ ch = i_getch(input); nommu_addchr(as_string, ch); ch = i_peek_and_eat_bkslash_nl(input); if (isalnum(ch)) { /* it's $_name or $_123 */ ch = '_'; - goto make_var; + goto make_var1; } /* else: it's $_ */ - /* TODO: $_ and $-: */ - /* $_ Shell or shell script name; or last argument of last command - * (if last command wasn't a pipe; if it was, bash sets $_ to ""); - * but in command's env, set to full pathname used to invoke it */ - /* $- Option flags set by set builtin or shell options (-i etc) */ +#endif default: o_addQchr(dest, '$'); } @@ -5669,9 +5673,9 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c */ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp) { - const char *val = NULL; - char *to_be_freed = NULL; - char *p = *pp; + const char *val; + char *to_be_freed; + char *p; char *var; char first_char; char exp_op; @@ -5680,6 +5684,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha char *exp_word = exp_word; /* for compiler */ char arg0; + val = NULL; + to_be_freed = NULL; + p = *pp; *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */ var = arg; exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL; -- cgit v1.2.3-55-g6feb From cba79a87f86f4f8d3c5b21ff7024b392402cf287 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 25 Jan 2018 14:07:40 +0100 Subject: hush: fix two corner cases in ${v/pattern/repl}. Closes 10686 function old new delta expand_one_var 1592 1618 +26 Signed-off-by: Denys Vlasenko --- shell/hush.c | 13 +++++++++++-- shell/hush_test/hush-vars/var_bash_repl_empty_pattern.right | 2 ++ shell/hush_test/hush-vars/var_bash_repl_empty_pattern.tests | 3 +++ shell/hush_test/hush-vars/var_bash_repl_empty_var.right | 2 ++ shell/hush_test/hush-vars/var_bash_repl_empty_var.tests | 3 +++ 5 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 shell/hush_test/hush-vars/var_bash_repl_empty_pattern.right create mode 100755 shell/hush_test/hush-vars/var_bash_repl_empty_pattern.tests create mode 100644 shell/hush_test/hush-vars/var_bash_repl_empty_var.right create mode 100755 shell/hush_test/hush-vars/var_bash_repl_empty_var.tests diff --git a/shell/hush.c b/shell/hush.c index a9183c82f..cf3c731bc 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5643,6 +5643,10 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c unsigned res_len = 0; unsigned repl_len = strlen(repl); + /* Null pattern never matches, including if "var" is empty */ + if (!pattern[0]) + return result; /* NULL, no replaces happened */ + while (1) { int size; char *s = strstr_pattern(val, pattern, &size); @@ -5809,8 +5813,6 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha * and if // is used, it is encoded as \: * var\patternrepl */ - /* Empty variable always gives nothing: */ - // "v=''; echo ${v/*/w}" prints "", not "w" if (val && val[0]) { /* pattern uses non-standard expansion. * repl should be unbackslashed and globbed @@ -5846,6 +5848,13 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha val = to_be_freed; free(pattern); free(repl); + } else { + /* Empty variable always gives nothing */ + // "v=''; echo ${v/*/w}" prints "", not "w" + /* Just skip "replace" part */ + *p++ = SPECIAL_VAR_SYMBOL; + p = strchr(p, SPECIAL_VAR_SYMBOL); + *p = '\0'; } } #endif /* BASH_PATTERN_SUBST */ diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.right b/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.right new file mode 100644 index 000000000..d400a7e31 --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.right @@ -0,0 +1,2 @@ +v +Ok:0 diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.tests b/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.tests new file mode 100755 index 000000000..6e8aa2afa --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash_repl_empty_pattern.tests @@ -0,0 +1,3 @@ +v=v +echo ${v//} +echo Ok:$? diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_var.right b/shell/hush_test/hush-vars/var_bash_repl_empty_var.right new file mode 100644 index 000000000..892916783 --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash_repl_empty_var.right @@ -0,0 +1,2 @@ + +Ok:0 diff --git a/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests b/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests new file mode 100755 index 000000000..73a43d38e --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash_repl_empty_var.tests @@ -0,0 +1,3 @@ +v='' +echo ${v/*/w} +echo Ok:$? -- cgit v1.2.3-55-g6feb From 043be556916ab0fbbece9d406cef199d397f8455 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 25 Jan 2018 14:09:06 +0100 Subject: ash testsuite: add two hush tests from last commit Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-vars/var_bash_repl_empty_pattern.right | 2 ++ shell/ash_test/ash-vars/var_bash_repl_empty_pattern.tests | 3 +++ shell/ash_test/ash-vars/var_bash_repl_empty_var.right | 2 ++ shell/ash_test/ash-vars/var_bash_repl_empty_var.tests | 3 +++ 4 files changed, 10 insertions(+) create mode 100644 shell/ash_test/ash-vars/var_bash_repl_empty_pattern.right create mode 100755 shell/ash_test/ash-vars/var_bash_repl_empty_pattern.tests create mode 100644 shell/ash_test/ash-vars/var_bash_repl_empty_var.right create mode 100755 shell/ash_test/ash-vars/var_bash_repl_empty_var.tests diff --git a/shell/ash_test/ash-vars/var_bash_repl_empty_pattern.right b/shell/ash_test/ash-vars/var_bash_repl_empty_pattern.right new file mode 100644 index 000000000..d400a7e31 --- /dev/null +++ b/shell/ash_test/ash-vars/var_bash_repl_empty_pattern.right @@ -0,0 +1,2 @@ +v +Ok:0 diff --git a/shell/ash_test/ash-vars/var_bash_repl_empty_pattern.tests b/shell/ash_test/ash-vars/var_bash_repl_empty_pattern.tests new file mode 100755 index 000000000..6e8aa2afa --- /dev/null +++ b/shell/ash_test/ash-vars/var_bash_repl_empty_pattern.tests @@ -0,0 +1,3 @@ +v=v +echo ${v//} +echo Ok:$? diff --git a/shell/ash_test/ash-vars/var_bash_repl_empty_var.right b/shell/ash_test/ash-vars/var_bash_repl_empty_var.right new file mode 100644 index 000000000..892916783 --- /dev/null +++ b/shell/ash_test/ash-vars/var_bash_repl_empty_var.right @@ -0,0 +1,2 @@ + +Ok:0 diff --git a/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests b/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests new file mode 100755 index 000000000..73a43d38e --- /dev/null +++ b/shell/ash_test/ash-vars/var_bash_repl_empty_var.tests @@ -0,0 +1,3 @@ +v='' +echo ${v/*/w} +echo Ok:$? -- cgit v1.2.3-55-g6feb From 77a6678c427db5ea15d6d0005a579f441277df06 Mon Sep 17 00:00:00 2001 From: Nicholas Clark Date: Thu, 25 Jan 2018 19:00:19 +0100 Subject: dd: add 'fullblock' iflag Adds a fullblock iflag for improved compatibility with GNU dd. The new iflag can be used to ensure that dd calls retrieve the expected amount of data when reading from pipes or unusual filesystems. function old new delta packed_usage 32249 32334 +85 dd_main 1582 1632 +50 static.iflag_words 12 22 +10 ------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 145/0) Total: 145 bytes Signed-off-by: Nicholas Clark Signed-off-by: Denys Vlasenko --- coreutils/dd.c | 33 +++++++++++++++++++++++---------- docs/posix_conformance.txt | 5 +++-- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index 38b2a6aa1..0f130bcad 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -37,7 +37,7 @@ //config: elapsed time and speed. //config: //config:config FEATURE_DD_IBS_OBS -//config: bool "Enable ibs, obs and conv options" +//config: bool "Enable ibs, obs, iflag and conv options" //config: default y //config: depends on DD //config: help @@ -57,7 +57,7 @@ //usage:#define dd_trivial_usage //usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" -//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes]") +//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes|fullblock]") //usage:#define dd_full_usage "\n\n" //usage: "Copy a file with converting and formatting\n" //usage: "\n if=FILE Read from FILE instead of stdin" @@ -79,6 +79,7 @@ //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: ) //usage: IF_FEATURE_DD_STATUS( //usage: "\n status=noxfer Suppress rate output" @@ -130,11 +131,12 @@ enum { /* start of input flags */ FLAG_IFLAG_SHIFT = 5, FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, /* end of input flags */ - FLAG_TWOBUFS = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_COUNT = 1 << 7, - FLAG_STATUS_NONE = 1 << 8, - FLAG_STATUS_NOXFER = 1 << 9, + FLAG_TWOBUFS = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_COUNT = 1 << 8, + FLAG_STATUS_NONE = 1 << 9, + FLAG_STATUS_NOXFER = 1 << 10, }; static void dd_output_status(int UNUSED_PARAM cur_signal) @@ -255,7 +257,7 @@ 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"; + "skip_bytes\0""fullblock\0"; #endif #if ENABLE_FEATURE_DD_STATUS static const char status_words[] ALIGN1 = @@ -294,6 +296,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) /* Partially implemented: */ //swab swap every pair of input bytes: will abort on non-even reads OP_iflag_skip_bytes, + OP_iflag_fullblock, #endif }; smallint exitcode = EXIT_FAILURE; @@ -454,7 +457,13 @@ 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 = safe_read(ifd, ibuf, blocksz); + 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); if (n < 0) goto die_infile; if (n == 0) @@ -469,8 +478,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { ssize_t n; - - n = safe_read(ifd, ibuf, ibs); +#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); if (n == 0) break; if (n < 0) { diff --git a/docs/posix_conformance.txt b/docs/posix_conformance.txt index 8b9112020..cdf89b744 100644 --- a/docs/posix_conformance.txt +++ b/docs/posix_conformance.txt @@ -178,9 +178,10 @@ dd POSIX options: conv=noerror | yes | | conv=notrunc | yes | | conv=sync | yes | | +dd compatibility options: + conv=fsync | yes | | iflag=skip_bytes| yes | | -dd Busybox specific options: - conv=fsync + iflag=fullblock | yes | | df POSIX options option | exists | compliant | remarks -- cgit v1.2.3-55-g6feb From e50396298118b1076511f86af373434292102960 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 26 Jan 2018 00:21:25 +0100 Subject: gzip: fix debug code. Closes 10681 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index ac6633044..2a5288cce 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -114,6 +114,7 @@ aa: 85.1% -- replaced with aa.gz //#define DEBUG 1 /* Diagnostic functions */ #ifdef DEBUG +static int verbose; # define Assert(cond,msg) { if (!(cond)) bb_error_msg(msg); } # define Trace(x) fprintf x # define Tracev(x) {if (verbose) fprintf x; } @@ -1538,7 +1539,7 @@ static int build_bl_tree(void) } /* Update opt_len to include the bit length tree and counts */ G2.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", G2.opt_len, G2.static_len)); + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", (long)G2.opt_len, (long)G2.static_len)); return max_blindex; } @@ -1564,13 +1565,13 @@ static void send_all_trees(int lcodes, int dcodes, int blcodes) Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(G2.bl_tree[bl_order[rank]].Len, 3); } - Tracev((stderr, "\nbl tree: sent %ld", G1.bits_sent)); + Tracev((stderr, "\nbl tree: sent %ld", (long)G1.bits_sent)); send_tree((ct_data *) G2.dyn_ltree, lcodes - 1); /* send the literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", G1.bits_sent)); + Tracev((stderr, "\nlit tree: sent %ld", (long)G1.bits_sent)); send_tree((ct_data *) G2.dyn_dtree, dcodes - 1); /* send the distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", G1.bits_sent)); + Tracev((stderr, "\ndist tree: sent %ld", (long)G1.bits_sent)); } @@ -1619,7 +1620,8 @@ static int ct_tally(int dist, int lc) out_length >>= 3; Trace((stderr, "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", - G2.last_lit, G2.last_dist, in_length, out_length, + G2.last_lit, G2.last_dist, + (long)in_length, (long)out_length, 100L - out_length * 100L / in_length)); if (G2.last_dist < G2.last_lit / 2 && out_length < in_length / 2) return 1; @@ -1694,10 +1696,10 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) /* Construct the literal and distance trees */ build_tree(&G2.l_desc); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", G2.opt_len, G2.static_len)); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", (long)G2.opt_len, (long)G2.static_len)); build_tree(&G2.d_desc); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", G2.opt_len, G2.static_len)); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", (long)G2.opt_len, (long)G2.static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ @@ -1713,7 +1715,9 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", - opt_lenb, G2.opt_len, static_lenb, G2.static_len, stored_len, + (unsigned long)opt_lenb, (unsigned long)G2.opt_len, + (unsigned long)static_lenb, (unsigned long)G2.static_len, + (unsigned long)stored_len, G2.last_lit, G2.last_dist)); if (static_lenb <= opt_lenb) @@ -1761,8 +1765,9 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) bi_windup(); G2.compressed_len += 7; /* align on byte boundary */ } - Tracev((stderr, "\ncomprlen %lu(%lu) ", G2.compressed_len >> 3, - G2.compressed_len - 7 * eof)); + Tracev((stderr, "\ncomprlen %lu(%lu) ", + (unsigned long)G2.compressed_len >> 3, + (unsigned long)G2.compressed_len - 7 * eof)); return G2.compressed_len >> 3; } @@ -1900,7 +1905,7 @@ static ulg deflate(void) G1.strstart++; G1.lookahead--; } - Assert(G1.strstart <= G1.isize && lookahead <= G1.isize, "a bit too far"); + Assert(G1.strstart <= G1.isize && G1.lookahead <= G1.isize, "a bit too far"); /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes -- cgit v1.2.3-55-g6feb From 01f7b9e182e257c12f7a7dec76c6b4168605ecd2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 26 Jan 2018 15:15:43 +0100 Subject: ash: introduce a config option to search current directory for sourced files Signed-off-by: Denys Vlasenko --- shell/ash.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 865159d20..d2c937283 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -51,6 +51,13 @@ //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: +//config:config ASH_BASH_SOURCE_CURDIR +//config: bool "'source' and '.' builtins search current directory after $PATH" +//config: default n # do not encourage non-standard behavior +//config: depends ASH_BASH_COMPAT +//config: help +//config: This is not compliant with standards. Avoid if possible. +//config: //config:config ASH_BASH_NOT_FOUND_HOOK //config: bool "command_not_found_handle hook support" //config: default y @@ -12978,10 +12985,14 @@ find_dot_file(char *name) if (fullname != name) stunalloc(fullname); } + /* not found in PATH */ - /* not found in the PATH */ +#if ENABLE_ASH_BASH_SOURCE_CURDIR + return name; +#else ash_msg_and_raise_error("%s: not found", name); /* NOTREACHED */ +#endif } static int FAST_FUNC -- cgit v1.2.3-55-g6feb From bb373dbc3297748623dec26798a631a4530122ec Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 27 Jan 2018 19:04:08 +0100 Subject: tar: accomodate non-terminated tar.chksum fields as seen from github.com function old new delta get_header_tar 1783 1696 -87 Signed-off-by: Denys Vlasenko --- archival/libarchive/get_header_tar.c | 49 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index aeb54190f..5c495e14e 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c @@ -152,6 +152,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) file_header_t *file_header = archive_handle->file_header; struct tar_header_t tar; char *cp; + int tar_typeflag; /* can be "char", "int" seems give smaller code */ int i, sum_u, sum; #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY int sum_s; @@ -253,10 +254,10 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) * POSIX says that checksum is done on unsigned bytes, but * Sun and HP-UX gets it wrong... more details in * GNU tar source. */ + sum_u = ' ' * sizeof(tar.chksum); #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY - sum_s = ' ' * sizeof(tar.chksum); + sum_s = sum_u; #endif - sum_u = ' ' * sizeof(tar.chksum); for (i = 0; i < 148; i++) { sum_u += ((unsigned char*)&tar)[i]; #if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY @@ -269,27 +270,22 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) sum_s += ((signed char*)&tar)[i]; #endif } - /* This field does not need special treatment (getOctal) */ - { - char *endp; /* gcc likes temp var for &endp */ - sum = strtoul(tar.chksum, &endp, 8); - if ((*endp != '\0' && *endp != ' ') - || (sum_u != sum IF_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum)) - ) { - bb_error_msg_and_die("invalid tar header checksum"); - } - } - /* don't use xstrtoul, tar.chksum may have leading spaces */ - sum = strtoul(tar.chksum, NULL, 8); - if (sum_u != sum IF_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum)) { + /* Most tarfiles have tar.chksum NUL or space terminated, but + * github.com decided to be "special" and have unterminated field: + * 0090: 30343300 30303031 33323731 30000000 |043.000132710...| + * ^^^^^^^^| + * Need to use GET_OCTAL. This overwrites tar.typeflag ---+ + * (the '0' char immediately after chksum in example above) with NUL. + */ + tar_typeflag = (uint8_t)tar.typeflag; /* save it */ + sum = GET_OCTAL(tar.chksum); + if (sum_u != sum + IF_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum) + ) { bb_error_msg_and_die("invalid tar header checksum"); } - /* 0 is reserved for high perf file, treat as normal file */ - if (!tar.typeflag) tar.typeflag = '0'; - parse_names = (tar.typeflag >= '0' && tar.typeflag <= '7'); - - /* getOctal trashes subsequent field, therefore we call it + /* GET_OCTAL trashes subsequent field, therefore we call it * on fields in reverse order */ if (tar.devmajor[0]) { char t = tar.prefix[0]; @@ -299,6 +295,11 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) file_header->device = makedev(major, minor); tar.prefix[0] = t; } + + /* 0 is reserved for high perf file, treat as normal file */ + if (tar_typeflag == '\0') tar_typeflag = '0'; + parse_names = (tar_typeflag >= '0' && tar_typeflag <= '7'); + file_header->link_target = NULL; if (!p_linkname && parse_names && tar.linkname[0]) { file_header->link_target = xstrndup(tar.linkname, sizeof(tar.linkname)); @@ -332,7 +333,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) /* Set bits 12-15 of the files mode */ /* (typeflag was not trashed because chksum does not use getOctal) */ - switch (tar.typeflag) { + switch (tar_typeflag) { case '1': /* hardlink */ /* we mark hardlinks as regular files with zero size and a link name */ file_header->mode |= S_IFREG; @@ -381,7 +382,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) case 'x': { /* pax extended header */ if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ goto skip_ext_hdr; - process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g')); + process_pax_hdr(archive_handle, file_header->size, (tar_typeflag == 'g')); goto again_after_align; #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS /* See http://www.gnu.org/software/tar/manual/html_node/Extensions.html */ @@ -419,7 +420,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) skip_ext_hdr: { off_t sz; - bb_error_msg("warning: skipping header '%c'", tar.typeflag); + bb_error_msg("warning: skipping header '%c'", tar_typeflag); sz = (file_header->size + 511) & ~(off_t)511; archive_handle->offset += sz; sz >>= 9; /* sz /= 512 but w/o contortions for signed div */ @@ -429,7 +430,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) goto again_after_align; } default: - bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag); + bb_error_msg_and_die("unknown typeflag: 0x%x", tar_typeflag); } #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS -- cgit v1.2.3-55-g6feb From f7e0feaf977ea5fef0f0819ba67a47dbef9b2e1a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 27 Jan 2018 19:05:59 +0100 Subject: hush: fix dot builtin to not search current directory function old new delta builtin_source 182 209 +27 Signed-off-by: Denys Vlasenko --- shell/hush.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index cf3c731bc..2d1cc5ca6 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -10211,6 +10211,11 @@ static int FAST_FUNC builtin_source(char **argv) arg_path = find_in_path(filename); if (arg_path) filename = arg_path; + else /* add "if (!HUSH_BASH_SOURCE_CURDIR)" if users want bash-compat */ { + errno = ENOENT; + bb_simple_perror_msg(filename); + return EXIT_FAILURE; + } } input = remember_FILE(fopen_or_warn(filename, "r")); free(arg_path); -- cgit v1.2.3-55-g6feb From 54c2111781e15b1c70bea43593aa67207f9ea118 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 27 Jan 2018 20:46:45 +0100 Subject: hush: add HUSH_BASH_SOURCE_CURDIR config option, to be on par with ash Signed-off-by: Denys Vlasenko --- shell/ash.c | 4 ++-- shell/hush.c | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index d2c937283..3fff88168 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -54,14 +54,14 @@ //config:config ASH_BASH_SOURCE_CURDIR //config: bool "'source' and '.' builtins search current directory after $PATH" //config: default n # do not encourage non-standard behavior -//config: depends ASH_BASH_COMPAT +//config: depends on ASH_BASH_COMPAT //config: help //config: This is not compliant with standards. Avoid if possible. //config: //config:config ASH_BASH_NOT_FOUND_HOOK //config: bool "command_not_found_handle hook support" //config: default y -//config: depends ASH_BASH_COMPAT +//config: depends on ASH_BASH_COMPAT //config: help //config: Enable support for the 'command_not_found_handle' hook function, //config: from GNU bash, which allows for alternative command not found diff --git a/shell/hush.c b/shell/hush.c index 2d1cc5ca6..ddf377355 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -120,6 +120,13 @@ //config: help //config: Enable {abc,def} extension. //config: +//config:config HUSH_BASH_SOURCE_CURDIR +//config: bool "'source' and '.' builtins search current directory after $PATH" +//config: default n # do not encourage non-standard behavior +//config: depends on HUSH_BASH_COMPAT +//config: help +//config: This is not compliant with standards. Avoid if possible. +//config: //config:config HUSH_INTERACTIVE //config: bool "Interactive mode" //config: default y @@ -10211,7 +10218,7 @@ static int FAST_FUNC builtin_source(char **argv) arg_path = find_in_path(filename); if (arg_path) filename = arg_path; - else /* add "if (!HUSH_BASH_SOURCE_CURDIR)" if users want bash-compat */ { + else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) { errno = ENOENT; bb_simple_perror_msg(filename); return EXIT_FAILURE; -- cgit v1.2.3-55-g6feb From 675d24aeaff29dbce6dc116a4b7c9f6026ed5069 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 27 Jan 2018 22:02:05 +0100 Subject: ash: add LINENO support This patch is a backport from dash of the combination of: [SHELL] Add preliminary LINENO support [VAR] Fix varinit ordering that broke fc [SHELL] Improve LINENO support function old new delta parse_command 1604 1677 +73 calcsize 156 223 +67 copynode 196 258 +62 evalcommand 1546 1606 +60 ash_main 1046 1103 +57 lookupvar 51 106 +55 evalcase 269 317 +48 evaltree 501 547 +46 evalfor 156 200 +44 evalsubshell 156 195 +39 raise_error_syntax 11 29 +18 varinit_data 120 132 +12 evalfun 270 280 +10 funcline - 4 +4 cmdtxt 569 572 +3 trapcmd 306 304 -2 ash_vmsg 153 150 -3 startlinno 4 - -4 funcnest 4 - -4 xxreadtoken 263 250 -13 readtoken1 2645 2602 -43 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 14/4 up/down: 598/-69) Total: 529 bytes text data bss dec hex filename 932834 481 6864 940179 e5893 busybox_old 933375 481 6856 940712 e5aa8 busybox_unstripped Signed-off-by: Denys Vlasenko --- shell/ash.c | 127 ++++++-- shell/ash_LINENO.patch | 498 ------------------------------ shell/ash_test/ash-psubst/emptytick.right | 4 +- shell/ash_test/ash-quoting/mode_x.right | 4 +- 4 files changed, 99 insertions(+), 534 deletions(-) delete mode 100644 shell/ash_LINENO.patch diff --git a/shell/ash.c b/shell/ash.c index 3fff88168..6b7386f79 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -328,6 +328,8 @@ struct globals_misc { /* shell level: 0 for the main shell, 1 for its children, and so on */ int shlvl; #define rootshell (!shlvl) + int errlinno; + char *minusc; /* argument to -c option */ char *curdir; // = nullstr; /* current working directory */ @@ -405,6 +407,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; #define job_warning (G_misc.job_warning) #define rootpid (G_misc.rootpid ) #define shlvl (G_misc.shlvl ) +#define errlinno (G_misc.errlinno ) #define minusc (G_misc.minusc ) #define curdir (G_misc.curdir ) #define physdir (G_misc.physdir ) @@ -739,6 +742,7 @@ union node; struct ncmd { smallint type; /* Nxxxx */ + int linno; union node *assign; union node *args; union node *redirect; @@ -752,6 +756,7 @@ struct npipe { struct nredir { smallint type; + int linno; union node *n; union node *redirect; }; @@ -771,6 +776,7 @@ struct nif { struct nfor { smallint type; + int linno; union node *args; union node *body; char *var; @@ -778,6 +784,7 @@ struct nfor { struct ncase { smallint type; + int linno; union node *expr; union node *cases; }; @@ -789,6 +796,13 @@ struct nclist { union node *body; }; +struct ndefun { + smallint type; + int linno; + char *text; + union node *body; +}; + struct narg { smallint type; union node *next; @@ -840,6 +854,7 @@ union node { struct nfor nfor; struct ncase ncase; struct nclist nclist; + struct ndefun ndefun; struct narg narg; struct nfile nfile; struct ndup ndup; @@ -1269,7 +1284,6 @@ struct parsefile { static struct parsefile basepf; /* top level input file */ static struct parsefile *g_parsefile = &basepf; /* current input file */ -static int startlinno; /* line # where last token started */ static char *commandname; /* currently executing command */ @@ -1283,7 +1297,7 @@ ash_vmsg(const char *msg, va_list ap) if (strcmp(arg0, commandname)) fprintf(stderr, "%s: ", commandname); if (!iflag || g_parsefile->pf_fd > 0) - fprintf(stderr, "line %d: ", startlinno); + fprintf(stderr, "line %d: ", errlinno); } vfprintf(stderr, msg, ap); newline_and_flush(stderr); @@ -1336,6 +1350,7 @@ static void raise_error_syntax(const char *) NORETURN; static void raise_error_syntax(const char *msg) { + errlinno = g_parsefile->linno; ash_msg_and_raise_error("syntax error: %s", msg); /* NOTREACHED */ } @@ -2023,6 +2038,7 @@ static const struct { #if ENABLE_ASH_GETOPTS { VSTRFIXED|VTEXTFIXED , defoptindvar, getoptsreset }, #endif + { VSTRFIXED|VTEXTFIXED , NULL /* inited to linenovar */, NULL }, #if ENABLE_ASH_RANDOM_SUPPORT { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random }, #endif @@ -2043,6 +2059,8 @@ struct globals_var { int preverrout_fd; /* stderr fd: usually 2, unless redirect moved it */ struct var *vartab[VTABSIZE]; struct var varinit[ARRAY_SIZE(varinit_data)]; + int lineno; + char linenovar[sizeof("LINENO=") + sizeof(int)*3]; }; extern struct globals_var *const ash_ptr_to_globals_var; #define G_var (*ash_ptr_to_globals_var) @@ -2051,17 +2069,8 @@ extern struct globals_var *const ash_ptr_to_globals_var; #define preverrout_fd (G_var.preverrout_fd) #define vartab (G_var.vartab ) #define varinit (G_var.varinit ) -#define INIT_G_var() do { \ - unsigned i; \ - (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \ - barrier(); \ - for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ - varinit[i].flags = varinit_data[i].flags; \ - varinit[i].var_text = varinit_data[i].var_text; \ - varinit[i].var_func = varinit_data[i].var_func; \ - } \ -} while (0) - +#define lineno (G_var.lineno ) +#define linenovar (G_var.linenovar ) #define vifs varinit[0] #if ENABLE_ASH_MAIL # define vmail (&vifs)[1] @@ -2075,14 +2084,28 @@ extern struct globals_var *const ash_ptr_to_globals_var; #define vps4 (&vps2)[1] #if ENABLE_ASH_GETOPTS # define voptind (&vps4)[1] +# define vlineno (&voptind)[1] # if ENABLE_ASH_RANDOM_SUPPORT -# define vrandom (&voptind)[1] +# define vrandom (&vlineno)[1] # endif #else +# define vlineno (&vps4)[1] # if ENABLE_ASH_RANDOM_SUPPORT -# define vrandom (&vps4)[1] +# define vrandom (&vlineno)[1] # endif #endif +#define INIT_G_var() do { \ + unsigned i; \ + (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \ + barrier(); \ + for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ + varinit[i].flags = varinit_data[i].flags; \ + varinit[i].var_text = varinit_data[i].var_text; \ + varinit[i].var_func = varinit_data[i].var_func; \ + } \ + strcpy(linenovar, "LINENO="); \ + vlineno.var_text = linenovar; \ +} while (0) /* * The following macros access the values of the above variables. @@ -2218,8 +2241,12 @@ lookupvar(const char *name) if (v->flags & VDYNAMIC) v->var_func(NULL); #endif - if (!(v->flags & VUNSET)) + if (!(v->flags & VUNSET)) { + if (v == &vlineno && v->var_text == linenovar) { + fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno); + } return var_end(v->var_text); + } } return NULL; } @@ -4823,7 +4850,7 @@ cmdtxt(union node *n) p = "; done"; goto dodo; case NDEFUN: - cmdputs(n->narg.text); + cmdputs(n->ndefun.text); p = "() { ... }"; goto dotail2; case NCMD: @@ -8650,6 +8677,9 @@ calcsize(int funcblocksize, union node *n) funcblocksize = calcsize(funcblocksize, n->nclist.next); break; case NDEFUN: + funcblocksize = calcsize(funcblocksize, n->ndefun.body); + funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1); + break; case NARG: funcblocksize = sizenodelist(funcblocksize, n->narg.backquote); funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */ @@ -8725,6 +8755,7 @@ copynode(union node *n) new->ncmd.redirect = copynode(n->ncmd.redirect); new->ncmd.args = copynode(n->ncmd.args); new->ncmd.assign = copynode(n->ncmd.assign); + new->ncmd.linno = n->ncmd.linno; break; case NPIPE: new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); @@ -8735,6 +8766,7 @@ copynode(union node *n) case NSUBSHELL: new->nredir.redirect = copynode(n->nredir.redirect); new->nredir.n = copynode(n->nredir.n); + new->nredir.linno = n->nredir.linno; break; case NAND: case NOR: @@ -8753,10 +8785,12 @@ copynode(union node *n) new->nfor.var = nodeckstrdup(n->nfor.var); new->nfor.body = copynode(n->nfor.body); new->nfor.args = copynode(n->nfor.args); + new->nfor.linno = n->nfor.linno; break; case NCASE: new->ncase.cases = copynode(n->ncase.cases); new->ncase.expr = copynode(n->ncase.expr); + new->ncase.linno = n->ncase.linno; break; case NCLIST: new->nclist.body = copynode(n->nclist.body); @@ -8764,6 +8798,10 @@ copynode(union node *n) new->nclist.next = copynode(n->nclist.next); break; case NDEFUN: + new->ndefun.body = copynode(n->ndefun.body); + new->ndefun.text = nodeckstrdup(n->ndefun.text); + new->ndefun.linno = n->ndefun.linno; + break; case NARG: new->narg.backquote = copynodelist(n->narg.backquote); new->narg.text = nodeckstrdup(n->narg.text); @@ -8832,7 +8870,7 @@ defun(union node *func) INT_OFF; entry.cmdtype = CMDFUNCTION; entry.u.func = copyfunc(func); - addcmdentry(func->narg.text, &entry); + addcmdentry(func->ndefun.text, &entry); INT_ON; } @@ -8842,8 +8880,8 @@ defun(union node *func) #define SKIPFUNC (1 << 2) static smallint evalskip; /* set to SKIPxxx if we are skipping commands */ static int skipcount; /* number of levels to skip */ -static int funcnest; /* depth of function calls */ static int loopnest; /* current loop nesting level */ +static int funcline; /* starting line number of current function, or 0 if not in a function */ /* Forward decl way out to parsing code - dotrap needs it */ static int evalstring(char *s, int flags); @@ -8938,6 +8976,9 @@ evaltree(union node *n, int flags) status = !evaltree(n->nnot.com, EV_TESTED); goto setstatus; case NREDIR: + errlinno = lineno = n->nredir.linno; + if (funcline) + lineno -= funcline - 1; expredir(n->nredir.redirect); pushredir(n->nredir.redirect); status = redirectsafe(n->nredir.redirect, REDIR_PUSH); @@ -9092,6 +9133,10 @@ evalfor(union node *n, int flags) struct stackmark smark; int status = 0; + errlinno = lineno = n->ncase.linno; + if (funcline) + lineno -= funcline - 1; + setstackmark(&smark); arglist.list = NULL; arglist.lastp = &arglist.list; @@ -9123,6 +9168,10 @@ evalcase(union node *n, int flags) struct stackmark smark; int status = 0; + errlinno = lineno = n->ncase.linno; + if (funcline) + lineno -= funcline - 1; + setstackmark(&smark); arglist.list = NULL; arglist.lastp = &arglist.list; @@ -9157,6 +9206,10 @@ evalsubshell(union node *n, int flags) int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */ int status; + errlinno = lineno = n->nredir.linno; + if (funcline) + lineno -= funcline - 1; + expredir(n->nredir.redirect); if (!backgnd && (flags & EV_EXIT) && !may_have_traps) goto nofork; @@ -9464,8 +9517,10 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) struct jmploc *volatile savehandler; struct jmploc jmploc; int e; + int savefuncline; saveparam = shellparam; + savefuncline = funcline; savehandler = exception_handler; e = setjmp(jmploc.loc); if (e) { @@ -9475,7 +9530,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) exception_handler = &jmploc; shellparam.malloced = 0; func->count++; - funcnest++; + funcline = func->n.ndefun.linno; INT_ON; shellparam.nparam = argc - 1; shellparam.p = argv + 1; @@ -9484,11 +9539,11 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) shellparam.optoff = -1; #endif pushlocalvars(); - evaltree(func->n.narg.next, flags & EV_TESTED); + evaltree(func->n.ndefun.body, flags & EV_TESTED); poplocalvars(0); funcdone: INT_OFF; - funcnest--; + funcline = savefuncline; freefunc(func); freeparam(&shellparam); shellparam = saveparam; @@ -9852,6 +9907,10 @@ evalcommand(union node *cmd, int flags) char **nargv; smallint cmd_is_exec; + errlinno = lineno = cmd->ncmd.linno; + if (funcline) + lineno -= funcline - 1; + /* First expand the arguments. */ TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); setstackmark(&smark); @@ -9897,7 +9956,7 @@ evalcommand(union node *cmd, int flags) *nargv = NULL; lastarg = NULL; - if (iflag && funcnest == 0 && argc > 0) + if (iflag && funcline == 0 && argc > 0) lastarg = nargv[-1]; expredir(cmd->ncmd.redirect); @@ -11430,6 +11489,7 @@ simplecmd(void) union node *vars, **vpp; union node **rpp, *redir; int savecheckkwd; + int savelinno; #if BASH_TEST2 smallint double_brackets_flag = 0; #endif @@ -11443,6 +11503,7 @@ simplecmd(void) rpp = &redir; savecheckkwd = CHKALIAS; + savelinno = g_parsefile->linno; for (;;) { int t; checkkwd = savecheckkwd; @@ -11532,7 +11593,9 @@ simplecmd(void) } n->type = NDEFUN; checkkwd = CHKNL | CHKKWD | CHKALIAS; - n->narg.next = parse_command(); + n->ndefun.text = n->narg.text; + n->ndefun.linno = g_parsefile->linno; + n->ndefun.body = parse_command(); return n; } IF_BASH_FUNCTION(function_flag = 0;) @@ -11548,6 +11611,7 @@ simplecmd(void) *rpp = NULL; n = stzalloc(sizeof(struct ncmd)); n->type = NCMD; + n->ncmd.linno = savelinno; n->ncmd.args = args; n->ncmd.assign = vars; n->ncmd.redirect = redir; @@ -11563,10 +11627,13 @@ parse_command(void) union node *redir, **rpp; union node **rpp2; int t; + int savelinno; redir = NULL; rpp2 = &redir; + savelinno = g_parsefile->linno; + switch (readtoken()) { default: raise_error_unexpected_syntax(-1); @@ -11617,6 +11684,7 @@ parse_command(void) raise_error_syntax("bad for loop variable"); n1 = stzalloc(sizeof(struct nfor)); n1->type = NFOR; + n1->nfor.linno = savelinno; n1->nfor.var = wordtext; checkkwd = CHKNL | CHKKWD | CHKALIAS; if (readtoken() == TIN) { @@ -11657,6 +11725,7 @@ parse_command(void) case TCASE: n1 = stzalloc(sizeof(struct ncase)); n1->type = NCASE; + n1->ncase.linno = savelinno; if (readtoken() != TWORD) raise_error_unexpected_syntax(TWORD); n1->ncase.expr = n2 = stzalloc(sizeof(struct narg)); @@ -11708,6 +11777,7 @@ parse_command(void) case TLP: n1 = stzalloc(sizeof(struct nredir)); n1->type = NSUBSHELL; + n1->nredir.linno = savelinno; n1->nredir.n = list(0); /*n1->nredir.redirect = NULL; - stzalloc did it */ t = TRP; @@ -11741,6 +11811,7 @@ parse_command(void) if (n1->type != NSUBSHELL) { n2 = stzalloc(sizeof(struct nredir)); n2->type = NREDIR; + n2->nredir.linno = savelinno; n2->nredir.n = n1; n1 = n2; } @@ -11839,10 +11910,8 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */ IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ int dqvarnest; /* levels of variables expansion within double quotes */ - IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;) - startlinno = g_parsefile->linno; bqlist = NULL; quotef = 0; IF_FEATURE_SH_MATH(prevsyntax = 0;) @@ -12019,7 +12088,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) if (syntax != BASESYNTAX && eofmark == NULL) raise_error_syntax("unterminated quoted string"); if (varnest != 0) { - startlinno = g_parsefile->linno; /* { */ raise_error_syntax("missing '}'"); } @@ -12411,7 +12479,6 @@ parsebackq: { case PEOF: IF_ASH_ALIAS(case PEOA:) - startlinno = g_parsefile->linno; raise_error_syntax("EOF in backquote substitution"); case '\n': @@ -12493,8 +12560,6 @@ parsearith: { * quoted. * If the token is TREDIR, then we set redirnode to a structure containing * the redirection. - * In all cases, the variable startlinno is set to the number of the line - * on which the token starts. * * [Change comment: here documents and internal procedures] * [Readtoken shouldn't have any arguments. Perhaps we should make the @@ -12532,7 +12597,6 @@ xxreadtoken(void) return lasttoken; } setprompt_if(needprompt, 2); - startlinno = g_parsefile->linno; for (;;) { /* until token or start of word found */ c = pgetc(); if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) @@ -12593,7 +12657,6 @@ xxreadtoken(void) return lasttoken; } setprompt_if(needprompt, 2); - startlinno = g_parsefile->linno; for (;;) { /* until token or start of word found */ c = pgetc(); switch (c) { diff --git a/shell/ash_LINENO.patch b/shell/ash_LINENO.patch deleted file mode 100644 index a71549d6a..000000000 --- a/shell/ash_LINENO.patch +++ /dev/null @@ -1,498 +0,0 @@ -This patch is a backport from dash of the combination of: - [SHELL] Add preliminary LINENO support - [VAR] Fix varinit ordering that broke fc - [SHELL] Improve LINENO support - -Applies cleanly on top of: - commit 9832bbaba966f0e52e183f10cd93fad7f8f643fe - Date: Tue Aug 15 15:44:41 2017 +0200 - -Testsuite needs some tweaks (line numbers in some messages change). - -Unfortunately, it is somewhat big: - -function old new delta -parse_command 1581 1658 +77 -calcsize 203 272 +69 -copynode 195 257 +62 -lookupvar 59 108 +49 -evaltree 494 534 +40 -evalfor 152 187 +35 -evalcase 278 313 +35 -evalcommand 1547 1581 +34 -evalsubshell 169 199 +30 -linenovar - 22 +22 -raise_error_syntax 11 29 +18 -evalfun 266 280 +14 -varinit_data 96 108 +12 -cmdtxt 626 631 +5 -lineno - 4 +4 -funcline - 4 +4 -ash_vmsg 144 141 -3 -startlinno 4 - -4 -funcnest 4 - -4 -xxreadtoken 272 259 -13 -readtoken1 2635 2594 -41 ------------------------------------------------------------------------------- -(add/remove: 3/2 grow/shrink: 13/3 up/down: 510/-65) Total: 445 bytes - text data bss dec hex filename - 912030 563 5844 918437 e03a5 busybox_old - 912473 587 5844 918904 e0578 busybox_unstripped - -diff --git a/shell/ash.c b/shell/ash.c -index 703802f..93a3814 100644 ---- a/shell/ash.c -+++ b/shell/ash.c -@@ -312,6 +312,8 @@ struct globals_misc { - /* shell level: 0 for the main shell, 1 for its children, and so on */ - int shlvl; - #define rootshell (!shlvl) -+ int errlinno; -+ - char *minusc; /* argument to -c option */ - - char *curdir; // = nullstr; /* current working directory */ -@@ -389,6 +391,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; - #define job_warning (G_misc.job_warning) - #define rootpid (G_misc.rootpid ) - #define shlvl (G_misc.shlvl ) -+#define errlinno (G_misc.errlinno ) - #define minusc (G_misc.minusc ) - #define curdir (G_misc.curdir ) - #define physdir (G_misc.physdir ) -@@ -723,6 +726,7 @@ union node; - - struct ncmd { - smallint type; /* Nxxxx */ -+ int linno; - union node *assign; - union node *args; - union node *redirect; -@@ -736,6 +740,7 @@ struct npipe { - - struct nredir { - smallint type; -+ int linno; - union node *n; - union node *redirect; - }; -@@ -755,6 +760,7 @@ struct nif { - - struct nfor { - smallint type; -+ int linno; - union node *args; - union node *body; - char *var; -@@ -762,6 +768,7 @@ struct nfor { - - struct ncase { - smallint type; -+ int linno; - union node *expr; - union node *cases; - }; -@@ -773,6 +780,13 @@ struct nclist { - union node *body; - }; - -+struct ndefun { -+ smallint type; -+ int linno; -+ char *text; -+ union node *body; -+}; -+ - struct narg { - smallint type; - union node *next; -@@ -824,6 +838,7 @@ union node { - struct nfor nfor; - struct ncase ncase; - struct nclist nclist; -+ struct ndefun ndefun; - struct narg narg; - struct nfile nfile; - struct ndup ndup; -@@ -1253,7 +1268,6 @@ struct parsefile { - - static struct parsefile basepf; /* top level input file */ - static struct parsefile *g_parsefile = &basepf; /* current input file */ --static int startlinno; /* line # where last token started */ - static char *commandname; /* currently executing command */ - - -@@ -1267,7 +1281,7 @@ ash_vmsg(const char *msg, va_list ap) - if (strcmp(arg0, commandname)) - fprintf(stderr, "%s: ", commandname); - if (!iflag || g_parsefile->pf_fd > 0) -- fprintf(stderr, "line %d: ", startlinno); -+ fprintf(stderr, "line %d: ", errlinno); - } - vfprintf(stderr, msg, ap); - newline_and_flush(stderr); -@@ -1327,6 +1341,7 @@ static void raise_error_syntax(const char *) NORETURN; - static void - raise_error_syntax(const char *msg) - { -+ errlinno = g_parsefile->linno; - ash_msg_and_raise_error("syntax error: %s", msg); - /* NOTREACHED */ - } -@@ -1993,6 +2008,9 @@ static void changepath(const char *) FAST_FUNC; - static void change_random(const char *) FAST_FUNC; - #endif - -+static int lineno; -+static char linenovar[sizeof("LINENO=%d") + sizeof(int)*3] = "LINENO="; -+ - static const struct { - int flags; - const char *var_text; -@@ -2014,6 +2032,7 @@ static const struct { - #if ENABLE_ASH_GETOPTS - { VSTRFIXED|VTEXTFIXED , defoptindvar, getoptsreset }, - #endif -+ { VSTRFIXED|VTEXTFIXED , linenovar , NULL }, - #if ENABLE_ASH_RANDOM_SUPPORT - { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random }, - #endif -@@ -2066,12 +2085,14 @@ extern struct globals_var *const ash_ptr_to_globals_var; - #define vps4 (&vps2)[1] - #if ENABLE_ASH_GETOPTS - # define voptind (&vps4)[1] -+# define vlineno (&voptind)[1] - # if ENABLE_ASH_RANDOM_SUPPORT --# define vrandom (&voptind)[1] -+# define vrandom (&vlineno)[1] - # endif - #else -+# define vlineno (&vps4)[1] - # if ENABLE_ASH_RANDOM_SUPPORT --# define vrandom (&vps4)[1] -+# define vrandom (&vlineno)[1] - # endif - #endif - -@@ -2209,8 +2230,12 @@ lookupvar(const char *name) - if (v->flags & VDYNAMIC) - v->var_func(NULL); - #endif -- if (!(v->flags & VUNSET)) -+ if (!(v->flags & VUNSET)) { -+ if (v == &vlineno && v->var_text == linenovar) { -+ fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno); -+ } - return var_end(v->var_text); -+ } - } - return NULL; - } -@@ -4783,7 +4808,7 @@ cmdtxt(union node *n) - p = "; done"; - goto dodo; - case NDEFUN: -- cmdputs(n->narg.text); -+ cmdputs(n->ndefun.text); - p = "() { ... }"; - goto dotail2; - case NCMD: -@@ -8551,6 +8576,9 @@ calcsize(int funcblocksize, union node *n) - funcblocksize = calcsize(funcblocksize, n->nclist.next); - break; - case NDEFUN: -+ funcblocksize = calcsize(funcblocksize, n->ndefun.body); -+ funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1); -+ break; - case NARG: - funcblocksize = sizenodelist(funcblocksize, n->narg.backquote); - funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */ -@@ -8626,6 +8654,7 @@ copynode(union node *n) - new->ncmd.redirect = copynode(n->ncmd.redirect); - new->ncmd.args = copynode(n->ncmd.args); - new->ncmd.assign = copynode(n->ncmd.assign); -+ new->ncmd.linno = n->ncmd.linno; - break; - case NPIPE: - new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); -@@ -8636,6 +8665,7 @@ copynode(union node *n) - case NSUBSHELL: - new->nredir.redirect = copynode(n->nredir.redirect); - new->nredir.n = copynode(n->nredir.n); -+ new->nredir.linno = n->nredir.linno; - break; - case NAND: - case NOR: -@@ -8654,10 +8684,12 @@ copynode(union node *n) - new->nfor.var = nodeckstrdup(n->nfor.var); - new->nfor.body = copynode(n->nfor.body); - new->nfor.args = copynode(n->nfor.args); -+ new->nfor.linno = n->nfor.linno; - break; - case NCASE: - new->ncase.cases = copynode(n->ncase.cases); - new->ncase.expr = copynode(n->ncase.expr); -+ new->ncase.linno = n->ncase.linno; - break; - case NCLIST: - new->nclist.body = copynode(n->nclist.body); -@@ -8665,6 +8697,10 @@ copynode(union node *n) - new->nclist.next = copynode(n->nclist.next); - break; - case NDEFUN: -+ new->ndefun.body = copynode(n->ndefun.body); -+ new->ndefun.text = nodeckstrdup(n->ndefun.text); -+ new->ndefun.linno = n->ndefun.linno; -+ break; - case NARG: - new->narg.backquote = copynodelist(n->narg.backquote); - new->narg.text = nodeckstrdup(n->narg.text); -@@ -8733,7 +8769,7 @@ defun(union node *func) - INT_OFF; - entry.cmdtype = CMDFUNCTION; - entry.u.func = copyfunc(func); -- addcmdentry(func->narg.text, &entry); -+ addcmdentry(func->ndefun.text, &entry); - INT_ON; - } - -@@ -8743,8 +8779,8 @@ defun(union node *func) - #define SKIPFUNC (1 << 2) - static smallint evalskip; /* set to SKIPxxx if we are skipping commands */ - static int skipcount; /* number of levels to skip */ --static int funcnest; /* depth of function calls */ - static int loopnest; /* current loop nesting level */ -+static int funcline; /* starting line number of current function, or 0 if not in a function */ - - /* Forward decl way out to parsing code - dotrap needs it */ - static int evalstring(char *s, int flags); -@@ -8839,6 +8875,9 @@ evaltree(union node *n, int flags) - status = !evaltree(n->nnot.com, EV_TESTED); - goto setstatus; - case NREDIR: -+ errlinno = lineno = n->nredir.linno; -+ if (funcline) -+ lineno -= funcline - 1; - expredir(n->nredir.redirect); - pushredir(n->nredir.redirect); - status = redirectsafe(n->nredir.redirect, REDIR_PUSH); -@@ -8993,6 +9032,10 @@ evalfor(union node *n, int flags) - struct stackmark smark; - int status = 0; - -+ errlinno = lineno = n->ncase.linno; -+ if (funcline) -+ lineno -= funcline - 1; -+ - setstackmark(&smark); - arglist.list = NULL; - arglist.lastp = &arglist.list; -@@ -9024,6 +9067,10 @@ evalcase(union node *n, int flags) - struct stackmark smark; - int status = 0; - -+ errlinno = lineno = n->ncase.linno; -+ if (funcline) -+ lineno -= funcline - 1; -+ - setstackmark(&smark); - arglist.list = NULL; - arglist.lastp = &arglist.list; -@@ -9058,6 +9105,10 @@ evalsubshell(union node *n, int flags) - int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */ - int status; - -+ errlinno = lineno = n->nredir.linno; -+ if (funcline) -+ lineno -= funcline - 1; -+ - expredir(n->nredir.redirect); - if (!backgnd && (flags & EV_EXIT) && !may_have_traps) - goto nofork; -@@ -9365,8 +9416,10 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) - struct jmploc *volatile savehandler; - struct jmploc jmploc; - int e; -+ int savefuncline; - - saveparam = shellparam; -+ savefuncline = funcline; - savehandler = exception_handler; - e = setjmp(jmploc.loc); - if (e) { -@@ -9376,7 +9429,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) - exception_handler = &jmploc; - shellparam.malloced = 0; - func->count++; -- funcnest++; -+ funcline = func->n.ndefun.linno; - INT_ON; - shellparam.nparam = argc - 1; - shellparam.p = argv + 1; -@@ -9385,11 +9438,11 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) - shellparam.optoff = -1; - #endif - pushlocalvars(); -- evaltree(func->n.narg.next, flags & EV_TESTED); -+ evaltree(func->n.ndefun.body, flags & EV_TESTED); - poplocalvars(0); - funcdone: - INT_OFF; -- funcnest--; -+ funcline = savefuncline; - freefunc(func); - freeparam(&shellparam); - shellparam = saveparam; -@@ -9753,6 +9806,10 @@ evalcommand(union node *cmd, int flags) - char **nargv; - smallint cmd_is_exec; - -+ errlinno = lineno = cmd->ncmd.linno; -+ if (funcline) -+ lineno -= funcline - 1; -+ - /* First expand the arguments. */ - TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); - setstackmark(&smark); -@@ -9798,7 +9855,7 @@ evalcommand(union node *cmd, int flags) - *nargv = NULL; - - lastarg = NULL; -- if (iflag && funcnest == 0 && argc > 0) -+ if (iflag && funcline == 0 && argc > 0) - lastarg = nargv[-1]; - - expredir(cmd->ncmd.redirect); -@@ -11317,6 +11374,7 @@ simplecmd(void) - union node *vars, **vpp; - union node **rpp, *redir; - int savecheckkwd; -+ int savelinno; - #if BASH_TEST2 - smallint double_brackets_flag = 0; - #endif -@@ -11330,6 +11388,7 @@ simplecmd(void) - rpp = &redir; - - savecheckkwd = CHKALIAS; -+ savelinno = g_parsefile->linno; - for (;;) { - int t; - checkkwd = savecheckkwd; -@@ -11419,7 +11478,9 @@ simplecmd(void) - } - n->type = NDEFUN; - checkkwd = CHKNL | CHKKWD | CHKALIAS; -- n->narg.next = parse_command(); -+ n->ndefun.text = n->narg.text; -+ n->ndefun.linno = g_parsefile->linno; -+ n->ndefun.body = parse_command(); - return n; - } - IF_BASH_FUNCTION(function_flag = 0;) -@@ -11435,6 +11496,7 @@ simplecmd(void) - *rpp = NULL; - n = stzalloc(sizeof(struct ncmd)); - n->type = NCMD; -+ n->ncmd.linno = savelinno; - n->ncmd.args = args; - n->ncmd.assign = vars; - n->ncmd.redirect = redir; -@@ -11450,10 +11512,13 @@ parse_command(void) - union node *redir, **rpp; - union node **rpp2; - int t; -+ int savelinno; - - redir = NULL; - rpp2 = &redir; - -+ savelinno = g_parsefile->linno; -+ - switch (readtoken()) { - default: - raise_error_unexpected_syntax(-1); -@@ -11504,6 +11569,7 @@ parse_command(void) - raise_error_syntax("bad for loop variable"); - n1 = stzalloc(sizeof(struct nfor)); - n1->type = NFOR; -+ n1->nfor.linno = savelinno; - n1->nfor.var = wordtext; - checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (readtoken() == TIN) { -@@ -11544,6 +11610,7 @@ parse_command(void) - case TCASE: - n1 = stzalloc(sizeof(struct ncase)); - n1->type = NCASE; -+ n1->ncase.linno = savelinno; - if (readtoken() != TWORD) - raise_error_unexpected_syntax(TWORD); - n1->ncase.expr = n2 = stzalloc(sizeof(struct narg)); -@@ -11595,6 +11662,7 @@ parse_command(void) - case TLP: - n1 = stzalloc(sizeof(struct nredir)); - n1->type = NSUBSHELL; -+ n1->nredir.linno = savelinno; - n1->nredir.n = list(0); - /*n1->nredir.redirect = NULL; - stzalloc did it */ - t = TRP; -@@ -11628,6 +11696,7 @@ parse_command(void) - if (n1->type != NSUBSHELL) { - n2 = stzalloc(sizeof(struct nredir)); - n2->type = NREDIR; -+ n2->nredir.linno = savelinno; - n2->nredir.n = n1; - n1 = n2; - } -@@ -11726,10 +11795,8 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) - IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */ - IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ - int dqvarnest; /* levels of variables expansion within double quotes */ -- - IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;) - -- startlinno = g_parsefile->linno; - bqlist = NULL; - quotef = 0; - IF_FEATURE_SH_MATH(prevsyntax = 0;) -@@ -11906,7 +11973,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) - if (syntax != BASESYNTAX && eofmark == NULL) - raise_error_syntax("unterminated quoted string"); - if (varnest != 0) { -- startlinno = g_parsefile->linno; - /* { */ - raise_error_syntax("missing '}'"); - } -@@ -12298,7 +12364,6 @@ parsebackq: { - - case PEOF: - IF_ASH_ALIAS(case PEOA:) -- startlinno = g_parsefile->linno; - raise_error_syntax("EOF in backquote substitution"); - - case '\n': -@@ -12380,8 +12445,6 @@ parsearith: { - * quoted. - * If the token is TREDIR, then we set redirnode to a structure containing - * the redirection. -- * In all cases, the variable startlinno is set to the number of the line -- * on which the token starts. - * - * [Change comment: here documents and internal procedures] - * [Readtoken shouldn't have any arguments. Perhaps we should make the -@@ -12419,7 +12482,6 @@ xxreadtoken(void) - return lasttoken; - } - setprompt_if(needprompt, 2); -- startlinno = g_parsefile->linno; - for (;;) { /* until token or start of word found */ - c = pgetc(); - if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) -@@ -12480,7 +12542,6 @@ xxreadtoken(void) - return lasttoken; - } - setprompt_if(needprompt, 2); -- startlinno = g_parsefile->linno; - for (;;) { /* until token or start of word found */ - c = pgetc(); - switch (c) { diff --git a/shell/ash_test/ash-psubst/emptytick.right b/shell/ash_test/ash-psubst/emptytick.right index 7629deba6..459c4f735 100644 --- a/shell/ash_test/ash-psubst/emptytick.right +++ b/shell/ash_test/ash-psubst/emptytick.right @@ -1,8 +1,8 @@ 0 0 -./emptytick.tests: line 3: : Permission denied +./emptytick.tests: line 1: : Permission denied 127 -./emptytick.tests: line 4: : Permission denied +./emptytick.tests: line 1: : Permission denied 127 0 0 diff --git a/shell/ash_test/ash-quoting/mode_x.right b/shell/ash_test/ash-quoting/mode_x.right index c2dd3550c..d1f670af6 100644 --- a/shell/ash_test/ash-quoting/mode_x.right +++ b/shell/ash_test/ash-quoting/mode_x.right @@ -3,8 +3,8 @@ + true '%s\n' one 'two '"'"'three' four + this=command + 'this=command' -./mode_x.tests: line 1: this=command: not found +./mode_x.tests: line 10: this=command: not found + true + true + 'if' true -./mode_x.tests: line 1: if: not found +./mode_x.tests: line 14: if: not found -- cgit v1.2.3-55-g6feb From f19e3c1c6c96e3c709ac732ff70c586521f792d3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 28 Jan 2018 20:13:33 +0100 Subject: shell: handle $((NUM++...) like bash does. Closes 10706 function old new delta evaluate_string 680 729 +49 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-postinc.right | 5 +++++ shell/ash_test/ash-arith/arith-postinc.tests | 5 +++++ shell/ash_test/ash-arith/arith.right | 4 ++++ shell/ash_test/ash-arith/arith2.sub | 12 ++++++------ shell/hush_test/hush-arith/arith-postinc.right | 5 +++++ shell/hush_test/hush-arith/arith-postinc.tests | 5 +++++ shell/hush_test/hush-arith/arith.right | 4 ++++ shell/hush_test/hush-arith/arith2.sub | 12 ++++++------ shell/math.c | 19 +++++++++++++++++-- 9 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 shell/ash_test/ash-arith/arith-postinc.right create mode 100755 shell/ash_test/ash-arith/arith-postinc.tests create mode 100644 shell/hush_test/hush-arith/arith-postinc.right create mode 100755 shell/hush_test/hush-arith/arith-postinc.tests diff --git a/shell/ash_test/ash-arith/arith-postinc.right b/shell/ash_test/ash-arith/arith-postinc.right new file mode 100644 index 000000000..c95ce02bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-postinc.right @@ -0,0 +1,5 @@ +1 1 +1 1 +1 1 +1 1 +Ok:0 diff --git a/shell/ash_test/ash-arith/arith-postinc.tests b/shell/ash_test/ash-arith/arith-postinc.tests new file mode 100755 index 000000000..3fd9bfed5 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-postinc.tests @@ -0,0 +1,5 @@ +echo 1 $((0++1)) +echo 1 $((0--1)) +x=-1; echo 1 $((0-$x)) +x=+1; echo 1 $((0+$x)) +echo Ok:$? diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 9b9ca8e2f..6936f1269 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right @@ -126,6 +126,10 @@ ghi ./arith2.sub: line 5: arithmetic syntax error 5 5 1 1 +6 6 +2 2 +3 3 +1 1 4 4 0 0 ./arith2.sub: line 42: arithmetic syntax error diff --git a/shell/ash_test/ash-arith/arith2.sub b/shell/ash_test/ash-arith/arith2.sub index f7e3c9235..9105059db 100755 --- a/shell/ash_test/ash-arith/arith2.sub +++ b/shell/ash_test/ash-arith/arith2.sub @@ -23,14 +23,14 @@ echo 5 $(( 4 + ++a )) echo 1 $a -# ash doesn't handle it right... -#ash# echo 6 $(( 4+++a )) -#ash# echo 2 $a +# this is treated as 4 + ++a +echo 6 $(( 4+++a )) +echo 2 $a a=2 -# ash doesn't handle it right... -#ash# echo 3 $(( 4---a )) -#ash# echo 1 $a +# this is treated as 4 - --a +echo 3 $(( 4---a )) +echo 1 $a a=1 echo 4 $(( 4 - -- a )) diff --git a/shell/hush_test/hush-arith/arith-postinc.right b/shell/hush_test/hush-arith/arith-postinc.right new file mode 100644 index 000000000..c95ce02bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-postinc.right @@ -0,0 +1,5 @@ +1 1 +1 1 +1 1 +1 1 +Ok:0 diff --git a/shell/hush_test/hush-arith/arith-postinc.tests b/shell/hush_test/hush-arith/arith-postinc.tests new file mode 100755 index 000000000..3fd9bfed5 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-postinc.tests @@ -0,0 +1,5 @@ +echo 1 $((0++1)) +echo 1 $((0--1)) +x=-1; echo 1 $((0-$x)) +x=+1; echo 1 $((0+$x)) +echo Ok:$? diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index 8a201fb3b..c48e468a5 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right @@ -135,6 +135,10 @@ hush: arithmetic syntax error hush: arithmetic syntax error 5 5 1 1 +6 6 +2 2 +3 3 +1 1 4 4 0 0 hush: arithmetic syntax error diff --git a/shell/hush_test/hush-arith/arith2.sub b/shell/hush_test/hush-arith/arith2.sub index f7e3c9235..9105059db 100755 --- a/shell/hush_test/hush-arith/arith2.sub +++ b/shell/hush_test/hush-arith/arith2.sub @@ -23,14 +23,14 @@ echo 5 $(( 4 + ++a )) echo 1 $a -# ash doesn't handle it right... -#ash# echo 6 $(( 4+++a )) -#ash# echo 2 $a +# this is treated as 4 + ++a +echo 6 $(( 4+++a )) +echo 2 $a a=2 -# ash doesn't handle it right... -#ash# echo 3 $(( 4---a )) -#ash# echo 1 $a +# this is treated as 4 - --a +echo 3 $(( 4---a )) +echo 1 $a a=1 echo 4 $(( 4 - -- a )) diff --git a/shell/math.c b/shell/math.c index f01f24362..611b3beab 100644 --- a/shell/math.c +++ b/shell/math.c @@ -598,10 +598,24 @@ evaluate_string(arith_state_t *math_state, const char *expr) } /* Should be an operator */ + + /* Special case: NUM-- and NUM++ are not recognized if NUM + * is a literal number, not a variable. IOW: + * "a+++v" is a++ + v. + * "7+++v" is 7 + ++v, not 7++ + v. + */ + if (lasttok == TOK_NUM && !numstackptr[-1].var /* number literal */ + && (expr[0] == '+' || expr[0] == '-') + && (expr[1] == expr[0]) + ) { + //bb_error_msg("special %c%c", expr[0], expr[0]); + op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); + expr += 1; + goto tok_found1; + } + p = op_tokens; while (1) { -// TODO: bash allows 7+++v, treats it as 7 + ++v -// we treat it as 7++ + v and reject /* Compare expr to current op_tokens[] element */ const char *e = expr; while (1) { @@ -627,6 +641,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) } tok_found: op = p[1]; /* fetch TOK_foo value */ + tok_found1: /* NB: expr now points past the operator */ /* post grammar: a++ reduce to num */ -- cgit v1.2.3-55-g6feb From 6f9442ff30f2fa7b66395935b0f59b01ecc89f0e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 28 Jan 2018 20:41:23 +0100 Subject: ash: make it possible to disable "const global ptr" optimization Signed-off-by: Denys Vlasenko --- shell/ash.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 6b7386f79..4c1b5e409 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -263,6 +263,19 @@ typedef long arith_t; # error "Do not even bother, ash will not run on NOMMU machine" #endif +/* We use a trick to have more optimized code (fewer pointer reloads): + * ash.c: extern struct globals *const ash_ptr_to_globals; + * ash_ptr_hack.c: struct globals *ash_ptr_to_globals; + * This way, compiler in ash.c knows the pointer can not change. + * + * However, this may break on weird arches or toolchains. In this case, + * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable + * this optimization. + */ +#ifndef BB_GLOBAL_CONST +# define BB_GLOBAL_CONST const +#endif + /* ============ Hash table sizes. Configurable. */ @@ -400,7 +413,7 @@ struct globals_misc { #endif pid_t backgndpid; /* pid of last background process */ }; -extern struct globals_misc *const ash_ptr_to_globals_misc; +extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc; #define G_misc (*ash_ptr_to_globals_misc) #define exitstatus (G_misc.exitstatus ) #define back_exitstatus (G_misc.back_exitstatus ) @@ -1473,7 +1486,7 @@ struct globals_memstack { size_t g_stacknleft; // = MINSIZE; struct stack_block stackbase; }; -extern struct globals_memstack *const ash_ptr_to_globals_memstack; +extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack; #define G_memstack (*ash_ptr_to_globals_memstack) #define g_stackp (G_memstack.g_stackp ) #define g_stacknxt (G_memstack.g_stacknxt ) @@ -2062,7 +2075,7 @@ struct globals_var { int lineno; char linenovar[sizeof("LINENO=") + sizeof(int)*3]; }; -extern struct globals_var *const ash_ptr_to_globals_var; +extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; #define G_var (*ash_ptr_to_globals_var) #define shellparam (G_var.shellparam ) //#define redirlist (G_var.redirlist ) -- cgit v1.2.3-55-g6feb From 749575d3c52c32f57f46f2cbb2942a2204d333ee Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Jan 2018 04:29:03 +0100 Subject: hush: protect against self-modifying trap code function old new delta check_and_run_traps 211 236 +25 Signed-off-by: Denys Vlasenko --- shell/hush.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index ddf377355..585c51bd5 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2004,10 +2004,12 @@ static int check_and_run_traps(void) smalluint save_rcode; char *argv[3]; /* argv[0] is unused */ - argv[1] = G_traps[sig]; + argv[1] = xstrdup(G_traps[sig]); + /* why strdup? trap can modify itself: trap 'trap "echo oops" INT' INT */ argv[2] = NULL; save_rcode = G.last_exitcode; builtin_eval(argv); + free(argv[1]); //FIXME: shouldn't it be set to 128 + sig instead? G.last_exitcode = save_rcode; last_sig = sig; -- cgit v1.2.3-55-g6feb From c6d2a26fac47eafc08f291dab78bbca3088f8ca2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Jan 2018 17:39:57 +0100 Subject: gzip: code shrink (consolidate zeroing on reinit) function old new delta deflate - 938 +938 pack_gzip 1903 923 -980 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 125 +++++++++++++++++++++++++------------------------------- 1 file changed, 55 insertions(+), 70 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 2a5288cce..10eda7aa3 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -15,21 +15,6 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -/* big objects in bss: - * 00000020 b bl_count - * 00000074 b base_length - * 00000078 b base_dist - * 00000078 b static_dtree - * 0000009c b bl_tree - * 000000f4 b dyn_dtree - * 00000100 b length_code - * 00000200 b dist_code - * 0000023d b depth - * 00000400 b flag_buf - * 0000047a b heap - * 00000480 b static_ltree - * 000008f4 b dyn_ltree - */ /* TODO: full support for -v for DESKTOP * "/usr/bin/gzip -v a bogus aa" should say: a: 85.1% -- replaced with a.gz @@ -351,6 +336,44 @@ struct globals { unsigned match_start; /* start of matching string */ unsigned lookahead; /* number of valid bytes ahead in window */ +/* number of input bytes */ + ulg isize; /* only 32 bits stored in .gz file */ + +/* bbox always use stdin/stdout */ +#define ifd STDIN_FILENO /* input file descriptor */ +#define ofd STDOUT_FILENO /* output file descriptor */ + +#ifdef DEBUG + unsigned insize; /* valid bytes in l_buf */ +#endif + unsigned outcnt; /* bytes in output buffer */ + + smallint eofile; /* flag set at end of input file */ + +/* =========================================================================== + * Local data used by the "bit string" routines. + */ + + unsigned short bi_buf; + +/* Output buffer. bits are inserted starting at the bottom (least significant + * bits). + */ +#undef BUF_SIZE +#define BUF_SIZE (8 * sizeof(G1.bi_buf)) + +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + int bi_valid; + +#ifdef DEBUG + ulg bits_sent; /* bit length of the compressed data */ +#endif + + /*uint32_t *crc_32_tab;*/ + uint32_t crc; /* shift register contents */ + /* =========================================================================== */ #define DECLARE(type, array, size) \ @@ -390,47 +413,6 @@ struct globals { /* Heads of the hash chains or 0. */ /* DECLARE(Pos, head, 1< Date: Tue, 30 Jan 2018 18:15:39 +0100 Subject: gzip: code shrink function old new delta fill_window_if_needed - 238 +238 deflate 924 907 -17 pack_gzip 809 790 -19 fill_window 216 - -216 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/2 up/down: 238/-252) Total: -14 bytes Signed-off-by: Denys Vlasenko --- archival/gzip.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 10eda7aa3..8ef66390a 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -312,25 +312,24 @@ struct globals { #define nice_match (G1.nice_match) #endif - lng block_start; - /* window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ + lng block_start; + unsigned ins_h; /* hash index of string to be inserted */ -#define H_SHIFT ((HASH_BITS+MIN_MATCH-1) / MIN_MATCH) /* Number of bits by which ins_h and del_h must be shifted at each * input step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * H_SHIFT * MIN_MATCH >= HASH_BITS */ - - unsigned prev_length; +#define H_SHIFT ((HASH_BITS+MIN_MATCH-1) / MIN_MATCH) /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ + unsigned prev_length; unsigned strstart; /* start of string to insert */ unsigned match_start; /* start of matching string */ @@ -347,18 +346,17 @@ struct globals { unsigned insize; /* valid bytes in l_buf */ #endif unsigned outcnt; /* bytes in output buffer */ - smallint eofile; /* flag set at end of input file */ /* =========================================================================== * Local data used by the "bit string" routines. */ - unsigned short bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least significant * bits). */ + unsigned short bi_buf; + #undef BUF_SIZE #define BUF_SIZE (8 * sizeof(G1.bi_buf)) @@ -368,7 +366,7 @@ struct globals { int bi_valid; #ifdef DEBUG - ulg bits_sent; /* bit length of the compressed data */ + ulg bits_sent; /* bit length of the compressed data */ #endif /*uint32_t *crc_32_tab;*/ @@ -662,6 +660,12 @@ static void fill_window(void) } } } +/* Both users fill window with the same loop: */ +static void fill_window_if_needed(void) +{ + while (G1.lookahead < MIN_LOOKAHEAD && !G1.eofile) + fill_window(); +} /* =========================================================================== @@ -1894,8 +1898,7 @@ static NOINLINE ulg deflate(void) * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ - while (G1.lookahead < MIN_LOOKAHEAD && !G1.eofile) - fill_window(); + fill_window_if_needed(); } if (match_available) ct_tally(0, G1.window[G1.strstart - 1]); @@ -1948,8 +1951,7 @@ static void lm_init(ush * flagsp) /* Make sure that we always have enough lookahead. This is important * if input comes from a device such as a tty. */ - while (G1.lookahead < MIN_LOOKAHEAD && !G1.eofile) - fill_window(); + fill_window_if_needed(); //G1.ins_h = 0; // globals are zeroed in pack_gzip() for (j = 0; j < MIN_MATCH - 1; j++) -- cgit v1.2.3-55-g6feb From e4c4e6ddc365d8e9b5409e2f929116624c932c1d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Jan 2018 22:37:06 +0100 Subject: gzip: code shrink function old new delta send_bits 92 70 -22 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 8ef66390a..efc5a0eea 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -358,7 +358,7 @@ struct globals { unsigned short bi_buf; #undef BUF_SIZE -#define BUF_SIZE (8 * sizeof(G1.bi_buf)) +#define BUF_SIZE (int)(8 * sizeof(G1.bi_buf)) /* Number of bits used within bi_buf. (bi_buf might be implemented on * more than 16 bits on some systems.) @@ -522,24 +522,29 @@ static unsigned file_read(void *buf, unsigned size) */ static void send_bits(int value, int length) { + unsigned new_buf; + int remain; + #ifdef DEBUG Tracev((stderr, " l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); G1.bits_sent += length; #endif - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (G1.bi_valid > (int) BUF_SIZE - length) { - G1.bi_buf |= (value << G1.bi_valid); - put_16bit(G1.bi_buf); - G1.bi_buf = (ush) value >> (BUF_SIZE - G1.bi_valid); - G1.bi_valid += length - BUF_SIZE; - } else { - G1.bi_buf |= value << G1.bi_valid; - G1.bi_valid += length; + + new_buf = G1.bi_buf | (value << G1.bi_valid); + remain = BUF_SIZE - G1.bi_valid; + /* If not enough room in bi_buf */ + if (length > remain) { + /* ...use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, + * leaving (width - (16-bi_valid)) unused bits in value. + */ + put_16bit(new_buf); + new_buf = (ush) value >> remain; + length -= BUF_SIZE; } + G1.bi_buf = new_buf; + G1.bi_valid += length; } -- cgit v1.2.3-55-g6feb From 6ba6a6f28e456c0148abece678eab1c1194632f2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Jan 2018 23:47:45 +0100 Subject: gzip: use wider (32-bit, not 16) bi_buf function old new delta bi_windup 76 74 -2 send_bits 70 62 -8 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index efc5a0eea..4a3fe976a 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -355,7 +355,7 @@ struct globals { /* Output buffer. bits are inserted starting at the bottom (least significant * bits). */ - unsigned short bi_buf; + unsigned bi_buf; /* was unsigned short */ #undef BUF_SIZE #define BUF_SIZE (int)(8 * sizeof(G1.bi_buf)) @@ -530,17 +530,25 @@ static void send_bits(int value, int length) Assert(length > 0 && length <= 15, "invalid length"); G1.bits_sent += length; #endif + BUILD_BUG_ON(BUF_SIZE != 32 && BUF_SIZE != 16); new_buf = G1.bi_buf | (value << G1.bi_valid); + /* NB: the above may sometimes do "<< 32" shift (undefined) + * if check below is changed to "length > remain" instead of >= */ remain = BUF_SIZE - G1.bi_valid; - /* If not enough room in bi_buf */ - if (length > remain) { + + /* If bi_buf is full */ + if (length >= remain) { /* ...use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, - * leaving (width - (16-bi_valid)) unused bits in value. + * (BUF_SIZE - bi_valid) bits from value, + * leaving (width - (BUF_SIZE-bi_valid)) unused bits in value. */ - put_16bit(new_buf); - new_buf = (ush) value >> remain; + if (BUF_SIZE == 32) { + put_32bit(new_buf); /* maybe unroll to 2*put_16bit()? */ + } else { /* 16 */ + put_16bit(new_buf); + } + new_buf = (unsigned) value >> remain; length -= BUF_SIZE; } G1.bi_buf = new_buf; @@ -571,10 +579,13 @@ static unsigned bi_reverse(unsigned code, int len) */ static void bi_windup(void) { - if (G1.bi_valid > 8) { - put_16bit(G1.bi_buf); - } else if (G1.bi_valid > 0) { - put_8bit(G1.bi_buf); + unsigned bits = G1.bi_buf; + int cnt = G1.bi_valid; + + while (cnt > 0) { + put_8bit(bits); + bits >>= 8; + cnt -= 8; } G1.bi_buf = 0; G1.bi_valid = 0; -- cgit v1.2.3-55-g6feb From d7500f856d856716fd228935bb5e84c897c9daa8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Jan 2018 23:53:38 +0100 Subject: gzip: use "unsigned" type for bit fields and bit counts This does not change any logic, those values should always be positive. Signed-off-by: Denys Vlasenko --- archival/gzip.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 4a3fe976a..f253a217a 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -363,7 +363,7 @@ struct globals { /* Number of bits used within bi_buf. (bi_buf might be implemented on * more than 16 bits on some systems.) */ - int bi_valid; + unsigned bi_valid; #ifdef DEBUG ulg bits_sent; /* bit length of the compressed data */ @@ -520,10 +520,10 @@ static unsigned file_read(void *buf, unsigned size) * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ -static void send_bits(int value, int length) +static void send_bits(unsigned value, unsigned length) { unsigned new_buf; - int remain; + unsigned remain; #ifdef DEBUG Tracev((stderr, " l %2d v %4x ", length, value)); @@ -548,7 +548,7 @@ static void send_bits(int value, int length) } else { /* 16 */ put_16bit(new_buf); } - new_buf = (unsigned) value >> remain; + new_buf = value >> remain; length -= BUF_SIZE; } G1.bi_buf = new_buf; -- cgit v1.2.3-55-g6feb From b7dfbbcdaaae5267259e2272b1cdfde6daad44a0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 00:01:06 +0100 Subject: gzip: speed up send_bits() Replace one RMW op with store. This speeds up gzip of a png file by ~2%. function old new delta send_bits 62 66 +4 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index f253a217a..08633d667 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -523,7 +523,6 @@ static unsigned file_read(void *buf, unsigned size) static void send_bits(unsigned value, unsigned length) { unsigned new_buf; - unsigned remain; #ifdef DEBUG Tracev((stderr, " l %2d v %4x ", length, value)); @@ -534,25 +533,26 @@ static void send_bits(unsigned value, unsigned length) new_buf = G1.bi_buf | (value << G1.bi_valid); /* NB: the above may sometimes do "<< 32" shift (undefined) - * if check below is changed to "length > remain" instead of >= */ - remain = BUF_SIZE - G1.bi_valid; + * if check below is changed to "length > BUF_SIZE" instead of >= */ + length += G1.bi_valid; /* If bi_buf is full */ - if (length >= remain) { + if (length >= BUF_SIZE) { /* ...use (valid) bits from bi_buf and * (BUF_SIZE - bi_valid) bits from value, * leaving (width - (BUF_SIZE-bi_valid)) unused bits in value. */ + value >>= (BUF_SIZE - G1.bi_valid); if (BUF_SIZE == 32) { put_32bit(new_buf); /* maybe unroll to 2*put_16bit()? */ } else { /* 16 */ put_16bit(new_buf); } - new_buf = value >> remain; + new_buf = value; length -= BUF_SIZE; } G1.bi_buf = new_buf; - G1.bi_valid += length; + G1.bi_valid = length; } -- cgit v1.2.3-55-g6feb From 631c16855a05f0699149502bba93a3ad8f88608e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 00:42:29 +0100 Subject: gzip: optionally faster put_32bit() function old new delta put_32bit 22 55 +33 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 08633d667..5812f4b27 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -454,7 +454,7 @@ static void put_16bit(ush w) if (outcnt < OUTBUFSIZ-2) { /* Common case */ ush *dst16 = (void*) dst; - *dst16 = w; /* unalinged LSB 16-bit store */ + *dst16 = w; /* unaligned LSB 16-bit store */ G1.outcnt = outcnt + 2; return; } @@ -480,6 +480,18 @@ static void put_16bit(ush w) static void put_32bit(ulg n) { +#if CONFIG_GZIP_FAST > 0 \ + && BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN + unsigned outcnt = G1.outcnt; + if (outcnt < OUTBUFSIZ-4) { + /* Common case */ + uch *dst = &G1.outbuf[outcnt]; + ulg *dst32 = (void*) dst; + *dst32 = n; /* unaligned LSB 32-bit store */ + G1.outcnt = outcnt + 4; + return; + } +#endif put_16bit(n); put_16bit(n >> 16); } @@ -544,7 +556,7 @@ static void send_bits(unsigned value, unsigned length) */ value >>= (BUF_SIZE - G1.bi_valid); if (BUF_SIZE == 32) { - put_32bit(new_buf); /* maybe unroll to 2*put_16bit()? */ + put_32bit(new_buf); } else { /* 16 */ put_16bit(new_buf); } -- cgit v1.2.3-55-g6feb From 468731a86b850f6f1430a81b87cd7e2288300101 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 15:32:32 +0100 Subject: gzip: code shrink and speedup function old new delta pack_gzip 908 861 -47 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 5812f4b27..fa7a79b04 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -478,15 +478,14 @@ static void put_16bit(ush w) put_8bit(w); } +#define OPTIMIZED_PUT_32BIT (CONFIG_GZIP_FAST > 0 && BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN) static void put_32bit(ulg n) { -#if CONFIG_GZIP_FAST > 0 \ - && BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN +#if OPTIMIZED_PUT_32BIT unsigned outcnt = G1.outcnt; if (outcnt < OUTBUFSIZ-4) { /* Common case */ - uch *dst = &G1.outbuf[outcnt]; - ulg *dst32 = (void*) dst; + ulg *dst32 = (void*) &G1.outbuf[outcnt]; *dst32 = n; /* unaligned LSB 32-bit store */ G1.outcnt = outcnt + 4; return; @@ -1951,7 +1950,7 @@ static void bi_init(void) /* =========================================================================== * Initialize the "longest match" routines for a new file */ -static void lm_init(ush * flagsp) +static void lm_init(unsigned *flags16p) { unsigned j; @@ -1960,7 +1959,7 @@ static void lm_init(ush * flagsp) /* prev will be initialized on the fly */ /* speed options for the general purpose bit flag */ - *flagsp |= 2; /* FAST 4, SLOW 2 */ + *flags16p |= 2; /* FAST 4, SLOW 2 */ /* ??? reduce max_chain_length for binary files */ //G1.strstart = 0; // globals are zeroed in pack_gzip() @@ -2044,9 +2043,8 @@ static void ct_init(void) Assert(dist == 256, "ct_init: 256+dist != 512"); /* Construct the codes of the static literal tree */ - /* already zeroed - it's in bss - for (n = 0; n <= MAX_BITS; n++) - G2.bl_count[n] = 0; */ + //for (n = 0; n <= MAX_BITS; n++) // globals are zeroed in pack_gzip() + // G2.bl_count[n] = 0; n = 0; while (n <= 143) { @@ -2088,7 +2086,7 @@ static void ct_init(void) */ static void zip(void) { - ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */ + unsigned deflate_flags; //G1.outcnt = 0; // globals are zeroed in pack_gzip() @@ -2104,10 +2102,17 @@ static void zip(void) bi_init(); ct_init(); + deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */ lm_init(&deflate_flags); - put_8bit(deflate_flags); /* extra flags */ - put_8bit(3); /* OS identifier = 3 (Unix) */ + put_16bit(deflate_flags | 0x300); /* extra flags. OS id = 3 (Unix) */ + +#if OPTIMIZED_PUT_32BIT + /* put_32bit() performs 32bit stores. If we use it in send_bits()... */ + if (BUF_SIZE > 16) + /* then all stores are misaligned, unless we flush the buffer now */ + flush_outbuf(); +#endif deflate(); -- cgit v1.2.3-55-g6feb From 8fd35a1fa629daed5e4e580e72993df7654f0a5e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 15:42:45 +0100 Subject: gzip: code shrink function old new delta pack_gzip 861 838 -23 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index fa7a79b04..d52167f84 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -2049,20 +2049,24 @@ static void ct_init(void) n = 0; while (n <= 143) { G2.static_ltree[n++].Len = 8; - G2.bl_count[8]++; + //G2.bl_count[8]++; } + //G2.bl_count[8] = 143 + 1; while (n <= 255) { G2.static_ltree[n++].Len = 9; - G2.bl_count[9]++; + //G2.bl_count[9]++; } + G2.bl_count[9] = 255 - 143; while (n <= 279) { G2.static_ltree[n++].Len = 7; - G2.bl_count[7]++; + //G2.bl_count[7]++; } + G2.bl_count[7] = 279 - 255; while (n <= 287) { G2.static_ltree[n++].Len = 8; - G2.bl_count[8]++; + //G2.bl_count[8]++; } + G2.bl_count[8] = 287 - 279 + (143 + 1); /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) -- cgit v1.2.3-55-g6feb From 05251986c7c00b07a5a7ff0f70258e53a3f3de9e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 16:11:44 +0100 Subject: gzip: code shrink Use one memset to clear part of G1, and all of G2. function old new delta pack_gzip 838 828 -10 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 108 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index d52167f84..9dc31e30b 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -300,6 +300,50 @@ enum { struct globals { +/* =========================================================================== */ +/* global buffers, allocated once */ + +#define DECLARE(type, array, size) \ + type * array +#define ALLOC(type, array, size) \ + array = xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type)) +#define FREE(array) \ + do { free(array); array = NULL; } while (0) + + /* buffer for literals or lengths */ + /* DECLARE(uch, l_buf, LIT_BUFSIZE); */ + DECLARE(uch, l_buf, INBUFSIZ); + + DECLARE(ush, d_buf, DIST_BUFSIZE); + DECLARE(uch, outbuf, OUTBUFSIZ); + +/* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least WSIZE + * bytes. With this organization, matches are limited to a distance of + * WSIZE-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: limit the window size to WSIZE+BSZ if SMALL_MEM (the code would + * be less efficient). + */ + DECLARE(uch, window, 2L * WSIZE); + +/* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + /* DECLARE(Pos, prev, WSIZE); */ + DECLARE(ush, prev, 1L << BITS); + +/* Heads of the hash chains or 0. */ + /* DECLARE(Pos, head, 1<>= 8; + G1.outcnt = ++outcnt; #else *dst = (uch)w; w >>= 8; @@ -469,13 +471,13 @@ static void put_16bit(ush w) G1.outcnt = outcnt + 2; return; } + G1.outcnt = ++outcnt; #endif /* Slowpath: we will need to do flush_outbuf() */ - G1.outcnt = ++outcnt; if (outcnt == OUTBUFSIZ) - flush_outbuf(); - put_8bit(w); + flush_outbuf(); /* here */ + put_8bit(w); /* or here */ } #define OPTIMIZED_PUT_32BIT (CONFIG_GZIP_FAST > 0 && BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN) @@ -2056,17 +2058,20 @@ static void ct_init(void) G2.static_ltree[n++].Len = 9; //G2.bl_count[9]++; } - G2.bl_count[9] = 255 - 143; + //G2.bl_count[9] = 255 - 143; while (n <= 279) { G2.static_ltree[n++].Len = 7; //G2.bl_count[7]++; } - G2.bl_count[7] = 279 - 255; + //G2.bl_count[7] = 279 - 255; while (n <= 287) { G2.static_ltree[n++].Len = 8; //G2.bl_count[8]++; } - G2.bl_count[8] = 287 - 279 + (143 + 1); + //G2.bl_count[8] += 287 - 279; + G2.bl_count[7] = 279 - 255; + G2.bl_count[8] = (143 + 1) + (287 - 279); + G2.bl_count[9] = 255 - 143; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) @@ -2132,8 +2137,8 @@ static void zip(void) static IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED_PARAM) { - /* Reinit G1.xxx except pointers to allocated buffers */ - memset(&G1, 0, offsetof(struct globals, l_buf)); + /* Reinit G1.xxx except pointers to allocated buffers, and entire G2 */ + memset(&G1.crc, 0, (sizeof(G1) - offsetof(struct globals, crc)) + sizeof(G2)); /* Clear input and output buffers */ //G1.outcnt = 0; @@ -2143,7 +2148,6 @@ IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED //G1.isize = 0; /* Reinit G2.xxx */ - memset(&G2, 0, sizeof(G2)); G2.l_desc.dyn_tree = G2.dyn_ltree; G2.l_desc.static_tree = G2.static_ltree; G2.l_desc.extra_bits = extra_lbits; -- cgit v1.2.3-55-g6feb From 26eea71c87bb5b39fb77eb8b1a6c69ea82e8e879 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 16:36:17 +0100 Subject: gzip: code shrink function old new delta flush_block 668 665 -3 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 9dc31e30b..c94fec48d 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -617,8 +617,8 @@ static void copy_block(char *buf, unsigned len, int header) bi_windup(); /* align on byte boundary */ if (header) { - put_16bit(len); - put_16bit(~len); + unsigned v = ((uint16_t)len) | ((~len) << 16); + put_32bit(v); #ifdef DEBUG G1.bits_sent += 2 * 16; #endif @@ -1747,8 +1747,8 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) if (buf == NULL) bb_error_msg("block vanished"); - copy_block(buf, (unsigned) stored_len, 0); /* without header */ G2.compressed_len = stored_len << 3; + copy_block(buf, (unsigned) stored_len, 0); /* without header */ } else if (stored_len + 4 <= opt_lenb && buf != NULL) { /* 4: two words for the lengths */ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. @@ -1758,9 +1758,8 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) * transform a block into a stored block. */ send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */ - G2.compressed_len = (G2.compressed_len + 3 + 7) & ~7L; - G2.compressed_len += (stored_len + 4) << 3; - + G2.compressed_len = ((G2.compressed_len + 3 + 7) & ~7L) + + ((stored_len + 4) << 3); copy_block(buf, (unsigned) stored_len, 1); /* with header */ } else if (static_lenb == opt_lenb) { send_bits((STATIC_TREES << 1) + eof, 3); -- cgit v1.2.3-55-g6feb From ba63d70e2d3a24670813dc33fca4450a25b281b6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 17:00:41 +0100 Subject: gzip: make debugging of bits_sent less ugly, no code changes Signed-off-by: Denys Vlasenko --- archival/gzip.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index c94fec48d..6083cde88 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -411,6 +411,9 @@ struct globals { #ifdef DEBUG ulg bits_sent; /* bit length of the compressed data */ +# define DEBUG_bits_sent(v) (void)(G1.bits_sent v) +#else +# define DEBUG_bits_sent(v) ((void)0) #endif }; @@ -540,7 +543,7 @@ static void send_bits(unsigned value, unsigned length) #ifdef DEBUG Tracev((stderr, " l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); - G1.bits_sent += length; + DEBUG_bits_sent(+= length); #endif BUILD_BUG_ON(BUF_SIZE != 32 && BUF_SIZE != 16); @@ -602,9 +605,7 @@ static void bi_windup(void) } G1.bi_buf = 0; G1.bi_valid = 0; -#ifdef DEBUG - G1.bits_sent = (G1.bits_sent + 7) & ~7; -#endif + DEBUG_bits_sent(= (G1.bits_sent + 7) & ~7); } @@ -619,13 +620,9 @@ static void copy_block(char *buf, unsigned len, int header) if (header) { unsigned v = ((uint16_t)len) | ((~len) << 16); put_32bit(v); -#ifdef DEBUG - G1.bits_sent += 2 * 16; -#endif + DEBUG_bits_sent(+= 2 * 16); } -#ifdef DEBUG - G1.bits_sent += (ulg) len << 3; -#endif + DEBUG_bits_sent(+= (ulg) len << 3); while (len--) { put_8bit(*buf++); } @@ -1942,9 +1939,7 @@ static void bi_init(void) { //G1.bi_buf = 0; // globals are zeroed in pack_gzip() //G1.bi_valid = 0; // globals are zeroed in pack_gzip() -#ifdef DEBUG - //G1.bits_sent = 0L; // globals are zeroed in pack_gzip() -#endif + //DEBUG_bits_sent(= 0L); // globals are zeroed in pack_gzip() } -- cgit v1.2.3-55-g6feb From f21ebeece53687b17d64fa444ceb3648439f5a8a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 17:19:59 +0100 Subject: gzip: flush output buffer after stored blocks, they are not 32-bit aligned function old new delta flush_block 665 671 +6 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 6083cde88..7df38c2bc 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -486,19 +486,26 @@ static void put_16bit(ush w) #define OPTIMIZED_PUT_32BIT (CONFIG_GZIP_FAST > 0 && BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN) static void put_32bit(ulg n) { -#if OPTIMIZED_PUT_32BIT - unsigned outcnt = G1.outcnt; - if (outcnt < OUTBUFSIZ-4) { - /* Common case */ - ulg *dst32 = (void*) &G1.outbuf[outcnt]; - *dst32 = n; /* unaligned LSB 32-bit store */ - G1.outcnt = outcnt + 4; - return; + if (OPTIMIZED_PUT_32BIT) { + unsigned outcnt = G1.outcnt; + if (outcnt < OUTBUFSIZ-4) { + /* Common case */ + ulg *dst32 = (void*) &G1.outbuf[outcnt]; + *dst32 = n; /* unaligned LSB 32-bit store */ + //bb_error_msg("%p", dst32); // store alignment debugging + G1.outcnt = outcnt + 4; + return; + } } -#endif put_16bit(n); put_16bit(n >> 16); } +static ALWAYS_INLINE void flush_outbuf_if_32bit_optimized(void) +{ + /* If put_32bit() performs 32bit stores && it is used in send_bits() */ + if (OPTIMIZED_PUT_32BIT && BUF_SIZE > 16) + flush_outbuf(); +} /* =========================================================================== * Run a set of bytes through the crc shift register. If s is a NULL @@ -626,6 +633,8 @@ static void copy_block(char *buf, unsigned len, int header) while (len--) { put_8bit(*buf++); } + /* The above can 32-bit misalign outbuf */ + flush_outbuf_if_32bit_optimized(); } @@ -2110,12 +2119,8 @@ static void zip(void) put_16bit(deflate_flags | 0x300); /* extra flags. OS id = 3 (Unix) */ -#if OPTIMIZED_PUT_32BIT - /* put_32bit() performs 32bit stores. If we use it in send_bits()... */ - if (BUF_SIZE > 16) - /* then all stores are misaligned, unless we flush the buffer now */ - flush_outbuf(); -#endif + /* The above 32-bit misaligns outbuf (10 bytes are stored), flush it */ + flush_outbuf_if_32bit_optimized(); deflate(); -- cgit v1.2.3-55-g6feb From 919bc9d43c47a206e632c1b4c80c5f23e307b176 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 17:37:32 +0100 Subject: gzip: flush output buffer after stored blocks only if necessary function old new delta flush_block 671 680 +9 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/archival/gzip.c b/archival/gzip.c index 7df38c2bc..92130e7fb 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -634,7 +634,8 @@ static void copy_block(char *buf, unsigned len, int header) put_8bit(*buf++); } /* The above can 32-bit misalign outbuf */ - flush_outbuf_if_32bit_optimized(); + if (G1.outcnt & 3) /* syscalls are expensive, is it really misaligned? */ + flush_outbuf_if_32bit_optimized(); } -- cgit v1.2.3-55-g6feb From a142926029e468ece87892e8364fe4458b12f128 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 18:16:34 +0100 Subject: gzip: remove unnecessary forward declarations, no code changes Signed-off-by: Denys Vlasenko --- archival/gzip.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 92130e7fb..6241b782a 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -1081,15 +1081,6 @@ struct globals2 { /* =========================================================================== */ -static void gen_codes(ct_data * tree, int max_code); -static void build_tree(tree_desc * desc); -static void scan_tree(ct_data * tree, int max_code); -static void send_tree(ct_data * tree, int max_code); -static int build_bl_tree(void); -static void send_all_trees(int lcodes, int dcodes, int blcodes); -static void compress_block(ct_data * ltree, ct_data * dtree); - - #ifndef DEBUG /* Send a code of the given tree. c and tree must not have side effects */ # define SEND_CODE(c, tree) send_bits(tree[c].Code, tree[c].Len) -- cgit v1.2.3-55-g6feb From 54a174eb015e786e8097d6e0fdba3ebfe3b27a9d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 31 Jan 2018 23:26:11 +0100 Subject: gzip: "compressed_len" is unused, stop wasting code and time calculating it function old new delta flush_block 595 523 -72 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 93 +++++++++++++++++++-------------------------------------- 1 file changed, 31 insertions(+), 62 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 6241b782a..d6737b492 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -93,7 +93,6 @@ aa: 85.1% -- replaced with aa.gz #include "libbb.h" #include "bb_archive.h" - /* =========================================================================== */ //#define DEBUG 1 @@ -115,7 +114,6 @@ static int verbose; # define Tracecv(c,x) #endif - /* =========================================================================== */ #if CONFIG_GZIP_FAST == 0 @@ -211,7 +209,6 @@ static int verbose; # define MAX_SUFFIX 30 #endif - /* =========================================================================== * Compile with MEDIUM_MEM to reduce the memory requirements or * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the @@ -220,15 +217,14 @@ static int verbose; * affects the compression ratio. The compressed output * is still correct, and might even be smaller in some cases. */ - #ifdef SMALL_MEM -# define HASH_BITS 13 /* Number of bits used to hash strings */ +# define HASH_BITS 13 /* Number of bits used to hash strings */ #endif #ifdef MEDIUM_MEM -# define HASH_BITS 14 +# define HASH_BITS 14 #endif #ifndef HASH_BITS -# define HASH_BITS 15 +# define HASH_BITS 15 /* For portability to 16 bit machines, do not use values above 15. */ #endif @@ -241,7 +237,6 @@ static int verbose; #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - /* =========================================================================== * These types are not really 'char', 'short' and 'long' */ @@ -298,7 +293,6 @@ enum { #endif /* ENABLE_FEATURE_GZIP_LEVELS */ }; - struct globals { /* =========================================================================== */ /* global buffers, allocated once */ @@ -419,7 +413,6 @@ struct globals { #define G1 (*(ptr_to_globals - 1)) - /* =========================================================================== * Write the output buffer outbuf[0..outcnt-1] and update bytes_out. * (used for the compressed data only) @@ -433,7 +426,6 @@ static void flush_outbuf(void) G1.outcnt = 0; } - /* =========================================================================== */ /* put_8bit is used for the compressed output */ @@ -517,7 +509,6 @@ static void updcrc(uch * s, unsigned n) G1.crc = crc32_block_endian0(G1.crc, s, n, global_crc32_table /*G1.crc_32_tab*/); } - /* =========================================================================== * Read a new buffer from the current input file, perform end-of-line * translation, and update the crc and input file size. @@ -538,7 +529,6 @@ static unsigned file_read(void *buf, unsigned size) return len; } - /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. @@ -578,7 +568,6 @@ static void send_bits(unsigned value, unsigned length) G1.bi_valid = length; } - /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) @@ -596,7 +585,6 @@ static unsigned bi_reverse(unsigned code, int len) } } - /* =========================================================================== * Write out any remaining bits in an incomplete byte. */ @@ -615,7 +603,6 @@ static void bi_windup(void) DEBUG_bits_sent(= (G1.bits_sent + 7) & ~7); } - /* =========================================================================== * Copy a stored block to the zip file, storing first the length and its * one's complement if requested. @@ -638,7 +625,6 @@ static void copy_block(char *buf, unsigned len, int header) flush_outbuf_if_32bit_optimized(); } - /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead, and sets eofile if end of input file. @@ -703,7 +689,6 @@ static void fill_window_if_needed(void) fill_window(); } - /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, @@ -793,7 +778,6 @@ static int longest_match(IPos cur_match) return best_len; } - #ifdef DEBUG /* =========================================================================== * Check that the match at match_start is indeed a match. @@ -1072,13 +1056,12 @@ struct globals2 { ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ - ulg compressed_len; /* total bit length of compressed file */ +// ulg compressed_len; /* total bit length of compressed file */ }; #define G2ptr ((struct globals2*)(ptr_to_globals)) #define G2 (*G2ptr) - /* =========================================================================== */ #ifndef DEBUG @@ -1100,7 +1083,6 @@ struct globals2 { * The arguments must not have side effects. */ - /* =========================================================================== * Initialize a new block. */ @@ -1123,7 +1105,6 @@ static void init_block(void) G2.flag_bit = 1; } - /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping @@ -1161,7 +1142,6 @@ static void pqdownheap(ct_data * tree, int k) G2.heap[k] = v; } - /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. @@ -1259,7 +1239,6 @@ static void gen_bitlen(tree_desc * desc) } } - /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). @@ -1303,7 +1282,6 @@ static void gen_codes(ct_data * tree, int max_code) } } - /* =========================================================================== * Construct one Huffman tree and assigns the code bit strings and lengths. * Update the total bit length for the current block. @@ -1410,7 +1388,6 @@ static void build_tree(tree_desc * desc) gen_codes((ct_data *) tree, max_code); } - /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. Updates opt_len to take into account the repeat @@ -1465,7 +1442,6 @@ static void scan_tree(ct_data * tree, int max_code) } } - /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. @@ -1523,7 +1499,6 @@ static void send_tree(ct_data * tree, int max_code) } } - /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. @@ -1557,7 +1532,6 @@ static int build_bl_tree(void) return max_blindex; } - /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. @@ -1587,7 +1561,6 @@ static void send_all_trees(int lcodes, int dcodes, int blcodes) Tracev((stderr, "\ndist tree: sent %ld", (long)G1.bits_sent)); } - /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. @@ -1694,13 +1667,12 @@ static void compress_block(ct_data * ltree, ct_data * dtree) SEND_CODE(END_BLOCK, ltree); } - /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. This function * returns the total compressed length for the file so far. */ -static ulg flush_block(char *buf, ulg stored_len, int eof) +static void flush_block(char *buf, ulg stored_len, int eof) { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex; /* index of last bit length code of non zero freq */ @@ -1740,14 +1712,17 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) * and if the zip file can be seeked (to rewrite the local header), * the whole file is transformed into a stored file: */ - if (stored_len <= opt_lenb && eof && G2.compressed_len == 0L && seekable()) { - /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ - if (buf == NULL) - bb_error_msg("block vanished"); - - G2.compressed_len = stored_len << 3; - copy_block(buf, (unsigned) stored_len, 0); /* without header */ - } else if (stored_len + 4 <= opt_lenb && buf != NULL) { +// seekable() is constant FALSE in busybox, and G2.compressed_len is disabled +// (this was the only user) +// if (stored_len <= opt_lenb && eof && G2.compressed_len == 0L && seekable()) { +// /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ +// if (buf == NULL) +// bb_error_msg("block vanished"); +// +// G2.compressed_len = stored_len << 3; +// copy_block(buf, (unsigned) stored_len, 0); /* without header */ +// } else + if (stored_len + 4 <= opt_lenb && buf != NULL) { /* 4: two words for the lengths */ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since @@ -1756,35 +1731,35 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) * transform a block into a stored block. */ send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */ - G2.compressed_len = ((G2.compressed_len + 3 + 7) & ~7L) - + ((stored_len + 4) << 3); +// G2.compressed_len = ((G2.compressed_len + 3 + 7) & ~7L) +// + ((stored_len + 4) << 3); copy_block(buf, (unsigned) stored_len, 1); /* with header */ - } else if (static_lenb == opt_lenb) { + } else + if (static_lenb == opt_lenb) { send_bits((STATIC_TREES << 1) + eof, 3); compress_block((ct_data *) G2.static_ltree, (ct_data *) G2.static_dtree); - G2.compressed_len += 3 + G2.static_len; +// G2.compressed_len += 3 + G2.static_len; } else { send_bits((DYN_TREES << 1) + eof, 3); send_all_trees(G2.l_desc.max_code + 1, G2.d_desc.max_code + 1, max_blindex + 1); compress_block((ct_data *) G2.dyn_ltree, (ct_data *) G2.dyn_dtree); - G2.compressed_len += 3 + G2.opt_len; +// G2.compressed_len += 3 + G2.opt_len; } - Assert(G2.compressed_len == G1.bits_sent, "bad compressed size"); +// Assert(G2.compressed_len == G1.bits_sent, "bad compressed size"); init_block(); if (eof) { bi_windup(); - G2.compressed_len += 7; /* align on byte boundary */ +// G2.compressed_len += 7; /* align on byte boundary */ } - Tracev((stderr, "\ncomprlen %lu(%lu) ", - (unsigned long)G2.compressed_len >> 3, - (unsigned long)G2.compressed_len - 7 * eof)); +// Tracev((stderr, "\ncomprlen %lu(%lu) ", +// (unsigned long)G2.compressed_len >> 3, +// (unsigned long)G2.compressed_len - 7 * eof)); - return G2.compressed_len >> 3; + return; /* was "return G2.compressed_len >> 3;" */ } - /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to UPDATE_HASH are made with consecutive @@ -1793,7 +1768,6 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) */ #define UPDATE_HASH(h, c) (h = (((h)< Date: Thu, 1 Feb 2018 01:00:58 +0100 Subject: bzip2: code shrink, stop using global data variable function old new delta compressStream 523 538 +15 level 1 - -1 bzip2_main 110 73 -37 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 15/-38) Total: -23 bytes Signed-off-by: Denys Vlasenko --- archival/bzip2.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/archival/bzip2.c b/archival/bzip2.c index d6fd9296d..c3969a9e8 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c @@ -83,15 +83,13 @@ /* No point in being shy and having very small buffer here. * bzip2 internal buffers are much bigger anyway, hundreds of kbytes. * If iobuf is several pages long, malloc() may use mmap, - * making iobuf is page aligned and thus (maybe) have one memcpy less + * making iobuf page aligned and thus (maybe) have one memcpy less * if kernel is clever enough. */ enum { IOBUF_SIZE = 8 * 1024 }; -static uint8_t level; - /* NB: compressStream() has to return -1 on errors, not die. * bbunpack() will correctly clean up in this case * (delete incomplete .bz2 file) @@ -143,6 +141,7 @@ static IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_state_t *xstate UNUSED_PARAM) { IF_DESKTOP(long long) int total; + unsigned opt, level; ssize_t count; bz_stream bzs; /* it's small */ #define strm (&bzs) @@ -151,6 +150,16 @@ IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_state_t *xstate U #define wbuf (iobuf + IOBUF_SIZE) iobuf = xmalloc(2 * IOBUF_SIZE); + + opt = option_mask32 >> (sizeof("cfkvq" IF_FEATURE_BZIP2_DECOMPRESS("dt") "zs") - 1); + opt |= 0x100; /* if nothing else, assume -9 */ + level = 0; + for (;;) { + level++; + if (opt & 1) break; + opt >>= 1; + } + BZ2_bzCompressInit(strm, level); while (1) { @@ -197,25 +206,18 @@ int bzip2_main(int argc UNUSED_PARAM, char **argv) opt = getopt32(argv, "^" /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ - "cfkv" IF_FEATURE_BZIP2_DECOMPRESS("dt") "123456789qzs" + "cfkvq" IF_FEATURE_BZIP2_DECOMPRESS("dt") "zs123456789" "\0" "s2" /* -s means -2 (compatibility) */ ); #if ENABLE_FEATURE_BZIP2_DECOMPRESS /* bunzip2_main may not be visible... */ - if (opt & 0x30) // -d and/or -t + if (opt & (3 << 5)) /* -d and/or -t */ return bunzip2_main(argc, argv); - opt >>= 6; #else - opt >>= 4; + /* clear "decompress" and "test" bits (or bbunpack() can get confused) */ + /* in !BZIP2_DECOMPRESS config, these bits are -zs and are unused */ + option_mask32 = opt & ~(3 << 5); #endif - opt = (uint8_t)opt; /* isolate bits for -1..-8 */ - opt |= 0x100; /* if nothing else, assume -9 */ - level = 1; - while (!(opt & 1)) { - level++; - opt >>= 1; - } argv += optind; - option_mask32 &= 0xf; /* ignore all except -cfkv */ return bbunpack(argv, compressStream, append_ext, "bz2"); } -- cgit v1.2.3-55-g6feb From 97058d0585c29ed5fd57196f71642a419a53e546 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Feb 2018 01:03:50 +0100 Subject: unlzop: fix --help: it has -U instead of -k Signed-off-by: Denys Vlasenko --- archival/lzop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archival/lzop.c b/archival/lzop.c index 92411c23f..da09b7a82 100644 --- a/archival/lzop.c +++ b/archival/lzop.c @@ -80,7 +80,7 @@ //usage: "\n -F Don't verify checksum" //usage: //usage:#define unlzop_trivial_usage -//usage: "[-cfkvF] [FILE]..." +//usage: "[-cfUvF] [FILE]..." //usage:#define unlzop_full_usage "\n\n" //usage: " -c Write to stdout" //usage: "\n -f Force" -- cgit v1.2.3-55-g6feb From 99ac1759dd429bd7995feff33dc683589c016c8e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Feb 2018 01:41:31 +0100 Subject: lzop: code shrink function old new delta lzo_decompress 526 524 -2 lzo_compress 473 470 -3 Signed-off-by: Denys Vlasenko --- archival/libarchive/lzo1x_d.c | 3 +-- archival/lzop.c | 9 ++++----- include/liblzo_interface.h | 6 ++---- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/archival/libarchive/lzo1x_d.c b/archival/libarchive/lzo1x_d.c index 40b167e68..43cf4a04e 100644 --- a/archival/libarchive/lzo1x_d.c +++ b/archival/libarchive/lzo1x_d.c @@ -31,8 +31,7 @@ ************************************************************************/ /* safe decompression with overrun testing */ int lzo1x_decompress_safe(const uint8_t* in, unsigned in_len, - uint8_t* out, unsigned* out_len, - void* wrkmem UNUSED_PARAM) + uint8_t* out, unsigned* out_len /*, void* wrkmem */) { register uint8_t* op; register const uint8_t* ip; diff --git a/archival/lzop.c b/archival/lzop.c index da09b7a82..ba27aeff0 100644 --- a/archival/lzop.c +++ b/archival/lzop.c @@ -141,8 +141,7 @@ static void copy3(uint8_t* ip, const uint8_t* m_pos, unsigned off) #define TEST_OP (op <= op_end) static NOINLINE int lzo1x_optimize(uint8_t *in, unsigned in_len, - uint8_t *out, unsigned *out_len, - void* wrkmem UNUSED_PARAM) + uint8_t *out, unsigned *out_len /*, void* wrkmem */) { uint8_t* op; uint8_t* ip; @@ -724,7 +723,7 @@ static NOINLINE int lzo_compress(const header_t *h) /* optimize */ if (h->method == M_LZO1X_999) { unsigned new_len = src_len; - r = lzo1x_optimize(b2, dst_len, b1, &new_len, NULL); + r = lzo1x_optimize(b2, dst_len, b1, &new_len /*, NULL*/); if (r != 0 /*LZO_E_OK*/ || new_len != src_len) bb_error_msg_and_die("internal error - optimization failed"); } @@ -859,9 +858,9 @@ static NOINLINE int lzo_decompress(const header_t *h) /* decompress */ // if (option_mask32 & OPT_F) -// r = lzo1x_decompress(b1, src_len, b2, &d, NULL); +// r = lzo1x_decompress(b1, src_len, b2, &d /*, NULL*/); // else - r = lzo1x_decompress_safe(b1, src_len, b2, &d, NULL); + r = lzo1x_decompress_safe(b1, src_len, b2, &d /*, NULL*/); if (r != 0 /*LZO_E_OK*/ || dst_len != d) { bb_error_msg_and_die("corrupted data"); diff --git a/include/liblzo_interface.h b/include/liblzo_interface.h index b7f1b639b..1e194b944 100644 --- a/include/liblzo_interface.h +++ b/include/liblzo_interface.h @@ -49,12 +49,10 @@ int lzo1x_999_compress_level(const uint8_t* in, unsigned in_len, /* decompression */ //int lzo1x_decompress(const uint8_t* src, unsigned src_len, -// uint8_t* dst, unsigned* dst_len, -// void* wrkmem /* NOT USED */); +// uint8_t* dst, unsigned* dst_len /*, void* wrkmem */); /* safe decompression with overrun testing */ int lzo1x_decompress_safe(const uint8_t* src, unsigned src_len, - uint8_t* dst, unsigned* dst_len, - void* wrkmem /* NOT USED */); + uint8_t* dst, unsigned* dst_len /*, void* wrkmem */); #define LZO_E_OK 0 #define LZO_E_ERROR (-1) -- cgit v1.2.3-55-g6feb From d6f0f03b68fc4cf9ffb8006e192e36f0ebf51ea6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Feb 2018 09:13:14 +0100 Subject: libarchive: move bbunpack constants to bb_archive.h Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 57 ++++++++++++++++++++-------------------------------- archival/bzip2.c | 11 +++++----- archival/gzip.c | 10 ++++----- include/bb_archive.h | 15 ++++++++++++++ 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 944b397b3..a2ce0a13c 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -21,19 +21,6 @@ #include "libbb.h" #include "bb_archive.h" -/* Note: must be kept in sync with archival/lzop.c */ -enum { - OPT_STDOUT = 1 << 0, - OPT_FORCE = 1 << 1, - /* only some decompressors: */ - OPT_KEEP = 1 << 2, - OPT_VERBOSE = 1 << 3, - OPT_QUIET = 1 << 4, - OPT_DECOMPRESS = 1 << 5, - OPT_TEST = 1 << 6, - SEAMLESS_MAGIC = (1 << 31) * ENABLE_ZCAT * SEAMLESS_COMPRESSION, -}; - static int open_to_or_warn(int to_fd, const char *filename, int flags, int mode) { @@ -72,7 +59,7 @@ int FAST_FUNC bbunpack(char **argv, /* Open src */ if (filename) { - if (!(option_mask32 & SEAMLESS_MAGIC)) { + if (!(option_mask32 & BBUNPK_SEAMLESS_MAGIC)) { if (stat(filename, &stat_buf) != 0) { err_name: bb_simple_perror_msg(filename); @@ -91,15 +78,15 @@ int FAST_FUNC bbunpack(char **argv, xmove_fd(fd, STDIN_FILENO); } } else - if (option_mask32 & SEAMLESS_MAGIC) { + if (option_mask32 & BBUNPK_SEAMLESS_MAGIC) { /* "clever zcat" on stdin */ if (setup_unzip_on_fd(STDIN_FILENO, /*fail_if_not_compressed*/ 1)) goto err; } /* Special cases: test, stdout */ - if (option_mask32 & (OPT_STDOUT|OPT_TEST)) { - if (option_mask32 & OPT_TEST) + if (option_mask32 & (BBUNPK_OPT_STDOUT|BBUNPK_OPT_TEST)) { + if (option_mask32 & BBUNPK_OPT_TEST) if (open_to_or_warn(STDOUT_FILENO, bb_dev_null, O_WRONLY, 0)) xfunc_die(); filename = NULL; @@ -114,7 +101,7 @@ int FAST_FUNC bbunpack(char **argv, } /* -f: overwrite existing output files */ - if (option_mask32 & OPT_FORCE) { + if (option_mask32 & BBUNPK_OPT_FORCE) { unlink(new_name); } @@ -126,12 +113,12 @@ int FAST_FUNC bbunpack(char **argv, } /* Check that the input is sane */ - if (!(option_mask32 & OPT_FORCE) && isatty(STDIN_FILENO)) { + if (!(option_mask32 & BBUNPK_OPT_FORCE) && isatty(STDIN_FILENO)) { bb_error_msg_and_die("compressed data not read from terminal, " "use -f to force it"); } - if (!(option_mask32 & SEAMLESS_MAGIC)) { + if (!(option_mask32 & BBUNPK_SEAMLESS_MAGIC)) { init_transformer_state(&xstate); /*xstate.signature_skipped = 0; - already is */ /*xstate.src_fd = STDIN_FILENO; - already is */ @@ -145,7 +132,7 @@ int FAST_FUNC bbunpack(char **argv, xfunc_die(); } - if (!(option_mask32 & OPT_STDOUT)) + if (!(option_mask32 & BBUNPK_OPT_STDOUT)) xclose(STDOUT_FILENO); /* with error check! */ if (filename) { @@ -176,7 +163,7 @@ int FAST_FUNC bbunpack(char **argv, } /* Extreme bloat for gunzip compat */ /* Some users do want this info... */ - if (ENABLE_DESKTOP && (option_mask32 & OPT_VERBOSE)) { + if (ENABLE_DESKTOP && (option_mask32 & BBUNPK_OPT_VERBOSE)) { unsigned percent = status ? ((uoff_t)stat_buf.st_size * 100u / (unsigned long long)status) : 0; @@ -188,7 +175,7 @@ int FAST_FUNC bbunpack(char **argv, } /* Delete _source_ file */ del = filename; - if (option_mask32 & OPT_KEEP) /* ... unless -k */ + if (option_mask32 & BBUNPK_OPT_KEEP) /* ... unless -k */ del = NULL; } if (del) @@ -199,7 +186,7 @@ int FAST_FUNC bbunpack(char **argv, } } while (*argv && *++argv); - if (option_mask32 & OPT_STDOUT) + if (option_mask32 & BBUNPK_OPT_STDOUT) xclose(STDOUT_FILENO); /* with error check! */ return exitcode; @@ -389,9 +376,9 @@ int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int gunzip_main(int argc UNUSED_PARAM, char **argv) { #if ENABLE_FEATURE_GUNZIP_LONG_OPTIONS - getopt32long(argv, "cfkvqdtn", gunzip_longopts); + getopt32long(argv, BBUNPK_OPTSTR "dtn", gunzip_longopts); #else - getopt32(argv, "cfkvqdtn"); + getopt32(argv, BBUNPK_OPTSTR "dtn"); #endif argv += optind; @@ -400,7 +387,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) * But if seamless magic is enabled, then we are much more clever. */ if (ENABLE_ZCAT && (!ENABLE_GUNZIP || applet_name[1] == 'c')) - option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; + option_mask32 |= BBUNPK_OPT_STDOUT | BBUNPK_SEAMLESS_MAGIC; return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); } @@ -453,10 +440,10 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bunzip2_main(int argc UNUSED_PARAM, char **argv) { - getopt32(argv, "cfkvqdt"); + getopt32(argv, BBUNPK_OPTSTR "dt"); argv += optind; if (ENABLE_BZCAT && (!ENABLE_BUNZIP2 || applet_name[2] == 'c')) /* bzcat */ - option_mask32 |= OPT_STDOUT; + option_mask32 |= BBUNPK_OPT_STDOUT; return bbunpack(argv, unpack_bz2_stream, make_new_name_generic, "bz2"); } @@ -526,15 +513,15 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int unlzma_main(int argc UNUSED_PARAM, char **argv) { - IF_LZMA(int opts =) getopt32(argv, "cfkvqdt"); + IF_LZMA(int opts =) getopt32(argv, BBUNPK_OPTSTR "dt"); # if ENABLE_LZMA /* lzma without -d or -t? */ - if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) + if (applet_name[2] == 'm' && !(opts & (BBUNPK_OPT_DECOMPRESS|BBUNPK_OPT_TEST))) bb_show_usage(); # endif /* lzcat? */ if (ENABLE_LZCAT && applet_name[2] == 'c') - option_mask32 |= OPT_STDOUT; + option_mask32 |= BBUNPK_OPT_STDOUT; argv += optind; return bbunpack(argv, unpack_lzma_stream, make_new_name_generic, "lzma"); @@ -594,15 +581,15 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int unxz_main(int argc UNUSED_PARAM, char **argv) { - IF_XZ(int opts =) getopt32(argv, "cfkvqdt"); + IF_XZ(int opts =) getopt32(argv, BBUNPK_OPTSTR "dt"); # if ENABLE_XZ /* xz without -d or -t? */ - if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) + if (applet_name[2] == '\0' && !(opts & (BBUNPK_OPT_DECOMPRESS|BBUNPK_OPT_TEST))) bb_show_usage(); # endif /* xzcat? */ if (ENABLE_XZCAT && applet_name[2] == 'c') - option_mask32 |= OPT_STDOUT; + option_mask32 |= BBUNPK_OPT_STDOUT; argv += optind; return bbunpack(argv, unpack_xz_stream, make_new_name_generic, "xz"); diff --git a/archival/bzip2.c b/archival/bzip2.c index c3969a9e8..fa906150f 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c @@ -151,7 +151,8 @@ IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_state_t *xstate U iobuf = xmalloc(2 * IOBUF_SIZE); - opt = option_mask32 >> (sizeof("cfkvq" IF_FEATURE_BZIP2_DECOMPRESS("dt") "zs") - 1); + opt = option_mask32 >> (BBUNPK_OPTSTRLEN IF_FEATURE_BZIP2_DECOMPRESS(+ 2) + 2); + /* skipped BBUNPK_OPTSTR, "dt" and "zs" bits */ opt |= 0x100; /* if nothing else, assume -9 */ level = 0; for (;;) { @@ -205,17 +206,17 @@ int bzip2_main(int argc UNUSED_PARAM, char **argv) */ opt = getopt32(argv, "^" - /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ - "cfkvq" IF_FEATURE_BZIP2_DECOMPRESS("dt") "zs123456789" + /* Must match BBUNPK_foo constants! */ + BBUNPK_OPTSTR IF_FEATURE_BZIP2_DECOMPRESS("dt") "zs123456789" "\0" "s2" /* -s means -2 (compatibility) */ ); #if ENABLE_FEATURE_BZIP2_DECOMPRESS /* bunzip2_main may not be visible... */ - if (opt & (3 << 5)) /* -d and/or -t */ + if (opt & (BBUNPK_OPT_DECOMPRESS|BBUNPK_OPT_TEST)) /* -d and/or -t */ return bunzip2_main(argc, argv); #else /* clear "decompress" and "test" bits (or bbunpack() can get confused) */ /* in !BZIP2_DECOMPRESS config, these bits are -zs and are unused */ - option_mask32 = opt & ~(3 << 5); + option_mask32 = opt & ~(BBUNPK_OPT_DECOMPRESS|BBUNPK_OPT_TEST); #endif argv += optind; diff --git a/archival/gzip.c b/archival/gzip.c index d6737b492..e3dd79291 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -2211,16 +2211,16 @@ int gzip_main(int argc UNUSED_PARAM, char **argv) /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ #if ENABLE_FEATURE_GZIP_LONG_OPTIONS - opt = getopt32long(argv, "cfkv" IF_FEATURE_GZIP_DECOMPRESS("dt") "qn123456789", gzip_longopts); + opt = getopt32long(argv, BBUNPK_OPTSTR IF_FEATURE_GZIP_DECOMPRESS("dt") "n123456789", gzip_longopts); #else - opt = getopt32(argv, "cfkv" IF_FEATURE_GZIP_DECOMPRESS("dt") "qn123456789"); + opt = getopt32(argv, BBUNPK_OPTSTR IF_FEATURE_GZIP_DECOMPRESS("dt") "n123456789"); #endif #if ENABLE_FEATURE_GZIP_DECOMPRESS /* gunzip_main may not be visible... */ - if (opt & 0x30) // -d and/or -t + if (opt & (BBUNPK_OPT_DECOMPRESS|BBUNPK_OPT_TEST)) /* -d and/or -t */ return gunzip_main(argc, argv); #endif #if ENABLE_FEATURE_GZIP_LEVELS - opt >>= ENABLE_FEATURE_GZIP_DECOMPRESS ? 8 : 6; /* drop cfkv[dt]qn bits */ + opt >>= (BBUNPK_OPTSTRLEN IF_FEATURE_GZIP_DECOMPRESS(+ 2) + 1); /* drop cfkvq[dt]n bits */ if (opt == 0) opt = 1 << 6; /* default: 6 */ opt = ffs(opt >> 4); /* Maps -1..-4 to [0], -5 to [1] ... -9 to [5] */ @@ -2229,7 +2229,7 @@ int gzip_main(int argc UNUSED_PARAM, char **argv) max_lazy_match = gzip_level_config[opt].lazy2 * 2; nice_match = gzip_level_config[opt].nice2 * 2; #endif - option_mask32 &= 0xf; /* retain only -cfkv */ + option_mask32 &= BBUNPK_OPTSTRMASK; /* retain only -cfkvq */ /* Allocate all global buffers (for DYN_ALLOC option) */ ALLOC(uch, G1.l_buf, INBUFSIZ); diff --git a/include/bb_archive.h b/include/bb_archive.h index d3a02cf18..8ed20d70e 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -250,6 +250,21 @@ int bbunpack(char **argv, char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), const char *expected_ext ) FAST_FUNC; +#define BBUNPK_OPTSTR "cfkvq" +#define BBUNPK_OPTSTRLEN 5 +#define BBUNPK_OPTSTRMASK ((1 << BBUNPK_OPTSTRLEN) - 1) +enum { + BBUNPK_OPT_STDOUT = 1 << 0, + BBUNPK_OPT_FORCE = 1 << 1, + /* only some decompressors: */ + BBUNPK_OPT_KEEP = 1 << 2, + BBUNPK_OPT_VERBOSE = 1 << 3, + BBUNPK_OPT_QUIET = 1 << 4, + /* not included in BBUNPK_OPTSTR: */ + BBUNPK_OPT_DECOMPRESS = 1 << 5, + BBUNPK_OPT_TEST = 1 << 6, + BBUNPK_SEAMLESS_MAGIC = (1 << 31) * ENABLE_ZCAT * SEAMLESS_COMPRESSION, +}; void check_errors_in_children(int signo); #if BB_MMU -- cgit v1.2.3-55-g6feb From d15d7a0a4b07a55268546f0d32b6a3ed78a2ac77 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 1 Feb 2018 09:29:05 +0100 Subject: cp: implement -T Implement "cp -T". Some Linux kernel Makefiles started using this recently, so allow also building on systems using busybox cp. function old new delta cp_main 360 428 +68 copy_file 1678 1676 -2 packed_usage 32290 32259 -31 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 76/-39) Total: 35 bytes Signed-off-by: Aaro Koskinen Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 15 +++++++++++++-- include/libbb.h | 7 ++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/coreutils/cp.c b/coreutils/cp.c index 05c725cd0..8d93c6fe4 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -48,6 +48,7 @@ //usage: "\n -f Overwrite" //usage: "\n -i Prompt before overwrite" //usage: "\n -l,-s Create (sym)links" +//usage: "\n -T Treat DEST as a normal file" //usage: "\n -u Copy only newer files" #include "libbb.h" @@ -93,6 +94,7 @@ int cp_main(int argc, char **argv) "no-dereference\0" No_argument "P" "recursive\0" No_argument "R" "symbolic-link\0" No_argument "s" + "no-target-directory\0" No_argument "T" "verbose\0" No_argument "v" "update\0" No_argument "u" "remove-destination\0" No_argument "\xff" @@ -122,6 +124,8 @@ int cp_main(int argc, char **argv) * remove each existing destination file before attempting to open * --parents * use full source file name under DIRECTORY + * -T, --no-target-directory + * treat DEST as a normal file * NOT SUPPORTED IN BBOX: * --backup[=CONTROL] * make a backup of each existing destination file @@ -140,8 +144,6 @@ int cp_main(int argc, char **argv) * override the usual backup suffix * -t, --target-directory=DIRECTORY * copy all SOURCE arguments into DIRECTORY - * -T, --no-target-directory - * treat DEST as a normal file * -x, --one-file-system * stay on this file system * -Z, --context=CONTEXT @@ -176,6 +178,12 @@ int cp_main(int argc, char **argv) if (d_flags < 0) return EXIT_FAILURE; + if (flags & FILEUTILS_NO_TARGET_DIR) { /* -T */ + if (!(s_flags & 2) && (d_flags & 2)) + /* cp -T NOTDIR DIR */ + bb_error_msg_and_die("'%s' is a directory", last); + } + #if ENABLE_FEATURE_CP_LONG_OPTIONS //bb_error_msg("flags:%x FILEUTILS_RMDEST:%x OPT_parents:%x", // flags, FILEUTILS_RMDEST, OPT_parents); @@ -193,11 +201,14 @@ int cp_main(int argc, char **argv) if (!((s_flags | d_flags) & 2) /* ...or: recursing, the 1st is a directory, and the 2nd doesn't exist... */ || ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags) + || (flags & FILEUTILS_NO_TARGET_DIR) ) { /* Do a simple copy */ dest = last; goto DO_COPY; /* NB: argc==2 -> *++argv==last */ } + } else if (flags & FILEUTILS_NO_TARGET_DIR) { + bb_error_msg_and_die("too many arguments"); } while (1) { diff --git a/include/libbb.h b/include/libbb.h index 5f25b5dde..a93864020 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -404,10 +404,11 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th /* -P = -d (mapped in cp.c) */ FILEUTILS_VERBOSE = (1 << 12) * ENABLE_FEATURE_VERBOSE, /* -v */ FILEUTILS_UPDATE = 1 << 13, /* -u */ + FILEUTILS_NO_TARGET_DIR = 1 << 14, /* -T */ #if ENABLE_SELINUX - FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 14, /* -c */ + FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 15, /* -c */ #endif - FILEUTILS_RMDEST = 1 << (15 - !ENABLE_SELINUX), /* --remove-destination */ + FILEUTILS_RMDEST = 1 << (16 - !ENABLE_SELINUX), /* --remove-destination */ /* * Hole. cp may have some bits set here, * they should not affect remove_file()/copy_file() @@ -417,7 +418,7 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th #endif FILEUTILS_IGNORE_CHMOD_ERR = 1 << 31, }; -#define FILEUTILS_CP_OPTSTR "pdRfilsLHarPvu" IF_SELINUX("c") +#define FILEUTILS_CP_OPTSTR "pdRfilsLHarPvuT" IF_SELINUX("c") extern int remove_file(const char *path, int flags) FAST_FUNC; /* NB: without FILEUTILS_RECUR in flags, it will basically "cat" * the source, not copy (unless "source" is a directory). -- cgit v1.2.3-55-g6feb From 06076494da41755893a6e072bbd9889581a9e9d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Feb 2018 10:41:14 +0100 Subject: udhcpd: use ptr_to_globals for its lone global data (g_leases) function old new delta udhcpd_main 1461 1463 +2 add_lease 320 318 -2 g_leases 4 - -4 write_leases 223 214 -9 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/2 up/down: 2/-15) Total: -13 bytes text data bss dec hex filename 933232 481 6856 940569 e5a19 busybox_old 933223 481 6852 940556 e5a0c busybox_unstripped Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 238542bb0..ff7450739 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -45,7 +45,7 @@ #include "dhcpd.h" /* globals */ -struct dyn_lease *g_leases; +#define g_leases ((struct dyn_lease*)ptr_to_globals) /* struct server_config_t server_config is in bb_common_bufsiz1 */ /* Takes the address of the pointer to the static_leases linked list, @@ -880,7 +880,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) server_config.max_leases = num_ips; } - g_leases = xzalloc(server_config.max_leases * sizeof(g_leases[0])); + /* this sets g_leases */ + SET_PTR_TO_GLOBALS(xzalloc(server_config.max_leases * sizeof(g_leases[0]))); + read_leases(server_config.lease_file); if (udhcp_read_interface(server_config.interface, -- cgit v1.2.3-55-g6feb From ddacb03e875dd4c1a79421d030da9cdc4f081e6e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Feb 2018 10:56:19 +0100 Subject: libbb: commonalize a bit of little-endian CRC32 table generation code function old new delta global_crc32_new_table_le - 11 +11 crc32_new_table_le - 9 +9 inflate_unzip_internal 560 556 -4 flash_eraseall_main 823 819 -4 unpack_xz_stream 2403 2394 -9 lzop_main 121 112 -9 gzip_main 187 178 -9 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/5 up/down: 20/-35) Total: -15 bytes Signed-off-by: Denys Vlasenko --- archival/gzip.c | 2 +- archival/libarchive/decompress_gunzip.c | 2 +- archival/libarchive/decompress_unxz.c | 2 +- archival/lzop.c | 2 +- include/libbb.h | 2 ++ libbb/crc32.c | 10 ++++++++++ miscutils/flash_eraseall.c | 2 +- util-linux/fdisk_gpt.c | 2 +- 8 files changed, 18 insertions(+), 6 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index e3dd79291..c5a1fe9b4 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -2239,7 +2239,7 @@ int gzip_main(int argc UNUSED_PARAM, char **argv) ALLOC(ush, G1.prev, 1L << BITS); /* Initialize the CRC32 table */ - global_crc32_table = crc32_filltable(NULL, 0); + global_crc32_new_table_le(); argv += optind; return bbunpack(argv, pack_gzip, append_ext, "gz"); diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index c8245d736..edff7e0e5 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c @@ -1000,7 +1000,7 @@ inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate) gunzip_bb = 0; /* Create the crc table */ - gunzip_crc_table = crc32_filltable(NULL, 0); + gunzip_crc_table = crc32_new_table_le(); gunzip_crc = ~0; error_msg = "corrupted data"; diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 0be85500c..8ae7a275b 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c @@ -52,7 +52,7 @@ unpack_xz_stream(transformer_state_t *xstate) IF_DESKTOP(long long) int total = 0; if (!global_crc32_table) - global_crc32_table = crc32_filltable(NULL, /*endian:*/ 0); + global_crc32_new_table_le(); memset(&iobuf, 0, sizeof(iobuf)); membuf = xmalloc(2 * BUFSIZ); diff --git a/archival/lzop.c b/archival/lzop.c index ba27aeff0..fef8cdba3 100644 --- a/archival/lzop.c +++ b/archival/lzop.c @@ -1148,6 +1148,6 @@ int lzop_main(int argc UNUSED_PARAM, char **argv) if (ENABLE_UNLZOP && applet_name[4] == 'o') option_mask32 |= OPT_DECOMPRESS; - global_crc32_table = crc32_filltable(NULL, 0); + global_crc32_new_table_le(); return bbunpack(argv, pack_lzop, make_new_name_lzop, /*unused:*/ NULL); } diff --git a/include/libbb.h b/include/libbb.h index a93864020..2bb364366 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1928,6 +1928,8 @@ typedef struct md5_ctx_t md5sha_ctx_t; extern uint32_t *global_crc32_table; uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; +uint32_t *crc32_new_table_le(void) FAST_FUNC; +uint32_t *global_crc32_new_table_le(void) FAST_FUNC; uint32_t crc32_block_endian1(uint32_t val, const void *buf, unsigned len, uint32_t *crc_table) FAST_FUNC; uint32_t crc32_block_endian0(uint32_t val, const void *buf, unsigned len, uint32_t *crc_table) FAST_FUNC; diff --git a/libbb/crc32.c b/libbb/crc32.c index b00b580d0..728bcb736 100644 --- a/libbb/crc32.c +++ b/libbb/crc32.c @@ -41,6 +41,16 @@ uint32_t* FAST_FUNC crc32_filltable(uint32_t *crc_table, int endian) return crc_table - 256; } +/* Common uses: */ +uint32_t* FAST_FUNC crc32_new_table_le(void) +{ + return crc32_filltable(NULL, 0); +} +uint32_t* FAST_FUNC global_crc32_new_table_le(void) +{ + global_crc32_table = crc32_new_table_le(); + return global_crc32_table; +} uint32_t FAST_FUNC crc32_block_endian1(uint32_t val, const void *buf, unsigned len, uint32_t *crc_table) { diff --git a/miscutils/flash_eraseall.c b/miscutils/flash_eraseall.c index fab21291c..8e93060ca 100644 --- a/miscutils/flash_eraseall.c +++ b/miscutils/flash_eraseall.c @@ -101,7 +101,7 @@ int flash_eraseall_main(int argc UNUSED_PARAM, char **argv) if (flags & OPTION_J) { uint32_t *crc32_table; - crc32_table = crc32_filltable(NULL, 0); + crc32_table = crc32_new_table_le(); cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); diff --git a/util-linux/fdisk_gpt.c b/util-linux/fdisk_gpt.c index 45d2aa6e7..cdb90627d 100644 --- a/util-linux/fdisk_gpt.c +++ b/util-linux/fdisk_gpt.c @@ -177,7 +177,7 @@ check_gpt_label(void) init_unicode(); if (!global_crc32_table) { - global_crc32_table = crc32_filltable(NULL, 0); + global_crc32_new_table_le(); } crc = SWAP_LE32(gpt_hdr->hdr_crc32); -- cgit v1.2.3-55-g6feb From da49e7057a6efada17ba43d046770c95d0bd71a6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Feb 2018 11:44:52 +0100 Subject: cksum: code shrink function old new delta cksum_main 281 262 -19 Signed-off-by: Denys Vlasenko --- coreutils/cksum.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/coreutils/cksum.c b/coreutils/cksum.c index 059a33310..e46e249f2 100644 --- a/coreutils/cksum.c +++ b/coreutils/cksum.c @@ -31,9 +31,6 @@ int cksum_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int cksum_main(int argc UNUSED_PARAM, char **argv) { uint32_t *crc32_table = crc32_filltable(NULL, 1); - uint32_t crc; - off_t length, filesize; - int bytes_read; int exit_code = EXIT_SUCCESS; #if ENABLE_DESKTOP @@ -45,38 +42,42 @@ int cksum_main(int argc UNUSED_PARAM, char **argv) setup_common_bufsiz(); do { + uint32_t crc; + off_t filesize; int fd = open_or_warn_stdin(*argv ? *argv : bb_msg_standard_input); if (fd < 0) { exit_code = EXIT_FAILURE; continue; } - crc = 0; - length = 0; + crc = 0; + filesize = 0; #define read_buf bb_common_bufsiz1 - while ((bytes_read = safe_read(fd, read_buf, COMMON_BUFSIZE)) > 0) { - length += bytes_read; + for (;;) { + uoff_t t; + int bytes_read = safe_read(fd, read_buf, COMMON_BUFSIZE); + if (bytes_read > 0) { + filesize += bytes_read; + } else { + /* Checksum filesize bytes, LSB first, and exit */ + close(fd); + fd = -1; /* break flag */ + t = filesize; + bytes_read = 0; + while (t != 0) { + read_buf[bytes_read++] = (uint8_t)t; + t >>= 8; + } + } crc = crc32_block_endian1(crc, read_buf, bytes_read, crc32_table); + if (fd < 0) + break; } - close(fd); - - filesize = length; - while (length) { - crc = (crc << 8) ^ crc32_table[(uint8_t)(crc >> 24) ^ (uint8_t)length]; - /* must ensure that shift is unsigned! */ - if (sizeof(length) <= sizeof(unsigned)) - length = (unsigned)length >> 8; - else if (sizeof(length) <= sizeof(unsigned long)) - length = (unsigned long)length >> 8; - else - length = (unsigned long long)length >> 8; - } crc = ~crc; - - printf((*argv ? "%"PRIu32" %"OFF_FMT"i %s\n" : "%"PRIu32" %"OFF_FMT"i\n"), - crc, filesize, *argv); + printf((*argv ? "%u %"OFF_FMT"u %s\n" : "%u %"OFF_FMT"u\n"), + (unsigned)crc, filesize, *argv); } while (*argv && *++argv); fflush_stdout_and_exit(exit_code); -- cgit v1.2.3-55-g6feb From 125c3ff4b10ee36b757924b3c55b3ac34e902120 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 Feb 2018 20:59:28 +0100 Subject: bzip2: code shrink function old new delta bsW16 - 59 +59 sendMTFValues 2116 2111 -5 bsPutU16 36 - -36 bsPutU32 76 31 -45 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/2 up/down: 59/-86) Total: -27 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 2d994685c..c640173e5 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -75,25 +75,39 @@ void bsW(EState* s, int32_t n, uint32_t v) s->bsBuff |= (v << (32 - s->bsLive - n)); s->bsLive += n; } +/* Same with n == 16: */ +static +#if CONFIG_BZIP2_FAST >= 5 +ALWAYS_INLINE +#endif +void bsW16(EState* s, uint32_t v) +{ + while (s->bsLive >= 8) { + s->zbits[s->numZ] = (uint8_t)(s->bsBuff >> 24); + s->numZ++; + s->bsBuff <<= 8; + s->bsLive -= 8; + } + s->bsBuff |= (v << (16 - s->bsLive)); + s->bsLive += 16; +} /*---------------------------------------------------*/ -static -void bsPutU32(EState* s, unsigned u) +static ALWAYS_INLINE +void bsPutU16(EState* s, unsigned u) { - bsW(s, 8, (u >> 24) & 0xff); - bsW(s, 8, (u >> 16) & 0xff); - bsW(s, 8, (u >> 8) & 0xff); - bsW(s, 8, u & 0xff); + bsW16(s, u); } /*---------------------------------------------------*/ static -void bsPutU16(EState* s, unsigned u) +void bsPutU32(EState* s, unsigned u) { - bsW(s, 8, (u >> 8) & 0xff); - bsW(s, 8, u & 0xff); + //bsW(s, 32, u); // can't use: may try "uint32 << -n" + bsW16(s, (u >> 16) & 0xffff); + bsW16(s, u & 0xffff); } @@ -509,7 +523,7 @@ void sendMTFValues(EState* s) } } - bsW(s, 16, inUse16); + bsW16(s, inUse16); inUse16 <<= (sizeof(int)*8 - 16); /* move 15th bit into sign bit */ for (i = 0; i < 16; i++) { @@ -517,7 +531,7 @@ void sendMTFValues(EState* s) unsigned v16 = 0; for (j = 0; j < 16; j++) v16 = v16*2 + s->inUse[i * 16 + j]; - bsW(s, 16, v16); + bsW16(s, v16); } inUse16 <<= 1; } -- cgit v1.2.3-55-g6feb From e594fb2171a40d6d8f438140440b6c6b1dad5c41 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 01:30:12 +0100 Subject: bzip2: code shrink function old new delta BZ2_compressBlock 225 230 +5 handle_compress 356 355 -1 bsW16 59 56 -3 bsW 64 61 -3 bsFinishWrite 37 32 -5 prepare_new_block 48 34 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/5 up/down: 5/-26) Total: -21 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/bzlib.c | 18 +++++++++--------- archival/libarchive/bz/bzlib_private.h | 5 +++-- archival/libarchive/bz/compress.c | 13 ++++++------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/archival/libarchive/bz/bzlib.c b/archival/libarchive/bz/bzlib.c index 5f7db747a..3572474f4 100644 --- a/archival/libarchive/bz/bzlib.c +++ b/archival/libarchive/bz/bzlib.c @@ -55,8 +55,9 @@ void prepare_new_block(EState* s) { int i; s->nblock = 0; - s->numZ = 0; - s->state_out_pos = 0; + //indexes inot s->zbits[], initialzation moved to init of s->zbits + //s->posZ = s->zbits; // was: s->numZ = 0; + //s->state_out_pos = s->zbits; BZ_INITIALISE_CRC(s->blockCRC); /* inlined memset would be nice to have here */ for (i = 0; i < 256; i++) @@ -237,11 +238,10 @@ void /*Bool*/ copy_output_until_stop(EState* s) if (s->strm->avail_out == 0) break; /*-- block done? --*/ - if (s->state_out_pos >= s->numZ) break; + if (s->state_out_pos >= s->posZ) break; /*progress_out = True;*/ - *(s->strm->next_out) = s->zbits[s->state_out_pos]; - s->state_out_pos++; + *(s->strm->next_out) = *s->state_out_pos++; s->strm->avail_out--; s->strm->next_out++; s->strm->total_out++; @@ -261,7 +261,7 @@ void /*Bool*/ handle_compress(bz_stream *strm) while (1) { if (s->state == BZ_S_OUTPUT) { /*progress_out |=*/ copy_output_until_stop(s); - if (s->state_out_pos < s->numZ) break; + if (s->state_out_pos < s->posZ) break; if (s->mode == BZ_M_FINISHING //# && s->avail_in_expect == 0 && s->strm->avail_in == 0 @@ -336,7 +336,7 @@ int BZ2_bzCompress(bz_stream *strm, int action) /*if (s->avail_in_expect != s->strm->avail_in) return BZ_SEQUENCE_ERROR;*/ /*progress =*/ handle_compress(strm); - if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ) + if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->posZ) return BZ_FLUSH_OK; s->mode = BZ_M_RUNNING; return BZ_RUN_OK; @@ -349,9 +349,9 @@ int BZ2_bzCompress(bz_stream *strm, int action) return BZ_SEQUENCE_ERROR;*/ /*progress =*/ handle_compress(strm); /*if (!progress) return BZ_SEQUENCE_ERROR;*/ - //#if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ) + //#if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->posZ) //# return BZ_FINISH_OK; - if (s->strm->avail_in > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ) + if (s->strm->avail_in > 0 || !isempty_RL(s) || s->state_out_pos < s->posZ) return BZ_FINISH_OK; /*s->mode = BZ_M_IDLE;*/ return BZ_STREAM_END; diff --git a/archival/libarchive/bz/bzlib_private.h b/archival/libarchive/bz/bzlib_private.h index 43e674bec..8e44a8e64 100644 --- a/archival/libarchive/bz/bzlib_private.h +++ b/archival/libarchive/bz/bzlib_private.h @@ -150,8 +150,9 @@ typedef struct EState { /* input and output limits and current posns */ int32_t nblock; int32_t nblockMAX; - int32_t numZ; - int32_t state_out_pos; + //int32_t numZ; // index into s->zbits[], replaced by pointer: + uint8_t *posZ; + uint8_t *state_out_pos; /* the buffer for bit stream creation */ uint32_t bsBuff; diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index c640173e5..534cf665a 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -50,8 +50,7 @@ static NOINLINE void bsFinishWrite(EState* s) { while (s->bsLive > 0) { - s->zbits[s->numZ] = (uint8_t)(s->bsBuff >> 24); - s->numZ++; + *s->posZ++ = (uint8_t)(s->bsBuff >> 24); s->bsBuff <<= 8; s->bsLive -= 8; } @@ -67,8 +66,7 @@ ALWAYS_INLINE void bsW(EState* s, int32_t n, uint32_t v) { while (s->bsLive >= 8) { - s->zbits[s->numZ] = (uint8_t)(s->bsBuff >> 24); - s->numZ++; + *s->posZ++ = (uint8_t)(s->bsBuff >> 24); s->bsBuff <<= 8; s->bsLive -= 8; } @@ -83,8 +81,7 @@ ALWAYS_INLINE void bsW16(EState* s, uint32_t v) { while (s->bsLive >= 8) { - s->zbits[s->numZ] = (uint8_t)(s->bsBuff >> 24); - s->numZ++; + *s->posZ++ = (uint8_t)(s->bsBuff >> 24); s->bsBuff <<= 8; s->bsLive -= 8; } @@ -624,12 +621,14 @@ void BZ2_compressBlock(EState* s, int is_last_block) s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31); s->combinedCRC ^= s->blockCRC; if (s->blockNo > 1) - s->numZ = 0; + s->posZ = s->zbits; // was: s->numZ = 0; BZ2_blockSort(s); } s->zbits = &((uint8_t*)s->arr2)[s->nblock]; + s->posZ = s->zbits; + s->state_out_pos = s->zbits; /*-- If this is the first block, create the stream header. --*/ if (s->blockNo == 1) { -- cgit v1.2.3-55-g6feb From 359230da8ea92d980ec2a852754e8e63aa893f73 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 02:03:42 +0100 Subject: bzip2: code shrink function old new delta sendMTFValues 2111 2100 -11 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 534cf665a..992fd5884 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -289,11 +289,16 @@ void sendMTFValues(EState* s) /*--- Decide how many coding tables to use ---*/ AssertH(s->nMTF > 0, 3001); - if (s->nMTF < 200) nGroups = 2; else - if (s->nMTF < 600) nGroups = 3; else - if (s->nMTF < 1200) nGroups = 4; else - if (s->nMTF < 2400) nGroups = 5; else - nGroups = 6; + // 1..199 = 2 + // 200..599 = 3 + // 600..1199 = 4 + // 1200..2399 = 5 + // else 6 + nGroups = 2; + nGroups += (s->nMTF >= 200); + nGroups += (s->nMTF >= 600); + nGroups += (s->nMTF >= 1200); + nGroups += (s->nMTF >= 2400); /*--- Generate an initial set of coding tables ---*/ { -- cgit v1.2.3-55-g6feb From 3a2c97bd123477aba8ea5c2d88f374d53f84b3de Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 03:12:14 +0100 Subject: bgip2: fewer specifically-sized [u]int32_t's locals in sendMTFValues Generic ints/unsigneds are usually fine. Yes, really. function old new delta sendMTFValues 2100 2093 -7 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 44 ++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 992fd5884..ab0c5d9ec 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -260,8 +260,11 @@ void generateMTFValues(EState* s) static NOINLINE void sendMTFValues(EState* s) { - int32_t v, t, i, j, gs, ge, bt, bc, iter; - int32_t nSelectors, alphaSize, minLen, maxLen, selCtr; + int32_t t, i; + unsigned iter; + unsigned gs; + int32_t alphaSize; + unsigned nSelectors, selCtr; int32_t nGroups; /* @@ -277,15 +280,17 @@ void sendMTFValues(EState* s) #define rfreq sendMTFValues__rfreq #define len_pack sendMTFValues__len_pack - uint16_t cost[BZ_N_GROUPS]; + unsigned /*uint16_t*/ cost[BZ_N_GROUPS]; int32_t fave[BZ_N_GROUPS]; uint16_t* mtfv = s->mtfv; alphaSize = s->nInUse + 2; - for (t = 0; t < BZ_N_GROUPS; t++) + for (t = 0; t < BZ_N_GROUPS; t++) { + unsigned v; for (v = 0; v < alphaSize; v++) s->len[t][v] = BZ_GREATER_ICOST; + } /*--- Decide how many coding tables to use ---*/ AssertH(s->nMTF > 0, 3001); @@ -302,16 +307,20 @@ void sendMTFValues(EState* s) /*--- Generate an initial set of coding tables ---*/ { - int32_t nPart, remF, tFreq, aFreq; + unsigned nPart, remF; nPart = nGroups; remF = s->nMTF; gs = 0; while (nPart > 0) { + unsigned v; + unsigned ge; + unsigned tFreq, aFreq; + tFreq = remF / nPart; - ge = gs - 1; + ge = gs - 1; //underflows on 1st iteration aFreq = 0; - while (aFreq < tFreq && ge < alphaSize-1) { + while (aFreq < tFreq && (int)ge < (int)alphaSize-1) { ge++; aFreq += s->mtfFreq[ge]; } @@ -343,9 +352,11 @@ void sendMTFValues(EState* s) for (t = 0; t < nGroups; t++) fave[t] = 0; - for (t = 0; t < nGroups; t++) + for (t = 0; t < nGroups; t++) { + unsigned v; for (v = 0; v < alphaSize; v++) s->rfreq[t][v] = 0; + } #if CONFIG_BZIP2_FAST >= 5 /* @@ -353,6 +364,7 @@ void sendMTFValues(EState* s) * the common case (nGroups == 6). */ if (nGroups == 6) { + unsigned v; for (v = 0; v < alphaSize; v++) { s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v]; s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v]; @@ -363,6 +375,9 @@ void sendMTFValues(EState* s) nSelectors = 0; gs = 0; while (1) { + unsigned ge; + unsigned bt, bc; + /*--- Set group start & end marks. --*/ if (gs >= s->nMTF) break; @@ -406,7 +421,7 @@ void sendMTFValues(EState* s) { /*--- slow version which correctly handles all situations ---*/ for (i = gs; i <= ge; i++) { - uint16_t icv = mtfv[i]; + unsigned /*uint16_t*/ icv = mtfv[i]; for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv]; } @@ -480,6 +495,7 @@ void sendMTFValues(EState* s) for (i = 0; i < nGroups; i++) pos[i] = i; for (i = 0; i < nSelectors; i++) { + unsigned j; ll_i = s->selector[i]; j = 0; tmp = pos[j]; @@ -496,8 +512,8 @@ void sendMTFValues(EState* s) /*--- Assign actual codes for the tables. --*/ for (t = 0; t < nGroups; t++) { - minLen = 32; - maxLen = 0; + unsigned minLen = 32; //todo: s->len[t][0]; + unsigned maxLen = 0; //todo: s->len[t][0]; for (i = 0; i < alphaSize; i++) { if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; if (s->len[t][i] < minLen) minLen = s->len[t][i]; @@ -531,6 +547,7 @@ void sendMTFValues(EState* s) for (i = 0; i < 16; i++) { if (inUse16 < 0) { unsigned v16 = 0; + unsigned j; for (j = 0; j < 16; j++) v16 = v16*2 + s->inUse[i * 16 + j]; bsW16(s, v16); @@ -543,6 +560,7 @@ void sendMTFValues(EState* s) bsW(s, 3, nGroups); bsW(s, 15, nSelectors); for (i = 0; i < nSelectors; i++) { + unsigned j; for (j = 0; j < s->selectorMtf[i]; j++) bsW(s, 1, 1); bsW(s, 1, 0); @@ -550,7 +568,7 @@ void sendMTFValues(EState* s) /*--- Now the coding tables. ---*/ for (t = 0; t < nGroups; t++) { - int32_t curr = s->len[t][0]; + unsigned curr = s->len[t][0]; bsW(s, 5, curr); for (i = 0; i < alphaSize; i++) { while (curr < s->len[t][i]) { bsW(s, 2, 2); curr++; /* 10 */ }; @@ -563,6 +581,8 @@ void sendMTFValues(EState* s) selCtr = 0; gs = 0; while (1) { + unsigned ge; + if (gs >= s->nMTF) break; ge = gs + BZ_G_SIZE - 1; -- cgit v1.2.3-55-g6feb From 83dd4ff69631f8def367920b3353e112b93fcc87 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 03:17:48 +0100 Subject: bzip2: delete write-only fave[] array Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index ab0c5d9ec..377f2f166 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -281,7 +281,6 @@ void sendMTFValues(EState* s) #define len_pack sendMTFValues__len_pack unsigned /*uint16_t*/ cost[BZ_N_GROUPS]; - int32_t fave[BZ_N_GROUPS]; uint16_t* mtfv = s->mtfv; @@ -349,9 +348,6 @@ void sendMTFValues(EState* s) * Iterate up to BZ_N_ITERS times to improve the tables. */ for (iter = 0; iter < BZ_N_ITERS; iter++) { - for (t = 0; t < nGroups; t++) - fave[t] = 0; - for (t = 0; t < nGroups; t++) { unsigned v; for (v = 0; v < alphaSize; v++) @@ -440,7 +436,6 @@ void sendMTFValues(EState* s) bt = t; } } - fave[bt]++; s->selector[nSelectors] = bt; nSelectors++; -- cgit v1.2.3-55-g6feb From 982c44d030dbb9eec3ae6522b12838c5f0754070 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 03:34:40 +0100 Subject: bzip2: rewrite bit of code which depends on integer overflow function old new delta sendMTFValues 2093 2070 -23 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 377f2f166..271982cf2 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -297,7 +297,7 @@ void sendMTFValues(EState* s) // 200..599 = 3 // 600..1199 = 4 // 1200..2399 = 5 - // else 6 + // 2400..99999 = 6 nGroups = 2; nGroups += (s->nMTF >= 200); nGroups += (s->nMTF >= 600); @@ -317,12 +317,12 @@ void sendMTFValues(EState* s) unsigned tFreq, aFreq; tFreq = remF / nPart; - ge = gs - 1; //underflows on 1st iteration + ge = gs; aFreq = 0; - while (aFreq < tFreq && (int)ge < (int)alphaSize-1) { - ge++; - aFreq += s->mtfFreq[ge]; + while (aFreq < tFreq && ge < alphaSize) { + aFreq += s->mtfFreq[ge++]; } + ge--; if (ge > gs && nPart != nGroups && nPart != 1 -- cgit v1.2.3-55-g6feb From feafb3423e76d3c02a1f4fc740fb3f91a211ce1c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 04:43:46 +0100 Subject: bzip2: ~1% speedup by special-casing "store 1 bit" function function old new delta bsW1 - 52 +52 BZ2_compressBlock 230 225 -5 BZ2_blockSort 125 118 -7 sendMTFValues 2070 2051 -19 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/3 up/down: 52/-31) Total: 21 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 2 ++ archival/libarchive/bz/bzlib.c | 2 +- archival/libarchive/bz/compress.c | 24 ++++++++++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index e600cb7a7..a3b099f4b 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -1056,7 +1056,9 @@ void BZ2_blockSort(EState* s) } } +#if BZ_LIGHT_DEBUG s->origPtr = -1; +#endif for (i = 0; i < s->nblock; i++) if (ptr[i] == 0) { s->origPtr = i; diff --git a/archival/libarchive/bz/bzlib.c b/archival/libarchive/bz/bzlib.c index 3572474f4..ef98bb213 100644 --- a/archival/libarchive/bz/bzlib.c +++ b/archival/libarchive/bz/bzlib.c @@ -55,7 +55,7 @@ void prepare_new_block(EState* s) { int i; s->nblock = 0; - //indexes inot s->zbits[], initialzation moved to init of s->zbits + //indexes into s->zbits[], initialzation moved to init of s->zbits //s->posZ = s->zbits; // was: s->numZ = 0; //s->state_out_pos = s->zbits; BZ_INITIALISE_CRC(s->blockCRC); diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 271982cf2..4d0f77592 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -88,6 +88,22 @@ void bsW16(EState* s, uint32_t v) s->bsBuff |= (v << (16 - s->bsLive)); s->bsLive += 16; } +/* Same with n == 1: */ +static +#if CONFIG_BZIP2_FAST >= 5 +ALWAYS_INLINE +#endif +void bsW1(EState* s, uint32_t v) +{ + /* need space for only 1 bit, no need for loop freeing > 8 bits */ + if (s->bsLive >= 8) { + *s->posZ++ = (uint8_t)(s->bsBuff >> 24); + s->bsBuff <<= 8; + s->bsLive -= 8; + } + s->bsBuff |= (v << (31 - s->bsLive)); + s->bsLive += 1; +} /*---------------------------------------------------*/ @@ -557,8 +573,8 @@ void sendMTFValues(EState* s) for (i = 0; i < nSelectors; i++) { unsigned j; for (j = 0; j < s->selectorMtf[i]; j++) - bsW(s, 1, 1); - bsW(s, 1, 0); + bsW1(s, 1); + bsW1(s, 0); } /*--- Now the coding tables. ---*/ @@ -568,7 +584,7 @@ void sendMTFValues(EState* s) for (i = 0; i < alphaSize; i++) { while (curr < s->len[t][i]) { bsW(s, 2, 2); curr++; /* 10 */ }; while (curr > s->len[t][i]) { bsW(s, 2, 3); curr--; /* 11 */ }; - bsW(s, 1, 0); + bsW1(s, 0); } } @@ -682,7 +698,7 @@ void BZ2_compressBlock(EState* s, int is_last_block) * so as to maintain backwards compatibility with * older versions of bzip2. */ - bsW(s, 1, 0); + bsW1(s, 0); bsW(s, 24, s->origPtr); generateMTFValues(s); -- cgit v1.2.3-55-g6feb From fc228b48c9fe2c5770d2f0059bb5027ff7dd159e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 14:56:43 +0100 Subject: bzip2: have two separate "store bit 0" and "store bit 1" functions function old new delta sendMTFValues 2051 2085 +34 bsW1_0 - 33 +33 BZ2_compressBlock 225 223 -2 bsW1 52 - -52 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/1 up/down: 67/-54) Total: 13 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 4d0f77592..fc6af6595 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -90,10 +90,23 @@ void bsW16(EState* s, uint32_t v) } /* Same with n == 1: */ static +ALWAYS_INLINE /* one callsite */ +void bsW1_1(EState* s) +{ + /* need space for only 1 bit, no need for loop freeing > 8 bits */ + if (s->bsLive >= 8) { + *s->posZ++ = (uint8_t)(s->bsBuff >> 24); + s->bsBuff <<= 8; + s->bsLive -= 8; + } + s->bsBuff |= (1 << (31 - s->bsLive)); + s->bsLive += 1; +} +static #if CONFIG_BZIP2_FAST >= 5 ALWAYS_INLINE #endif -void bsW1(EState* s, uint32_t v) +void bsW1_0(EState* s) { /* need space for only 1 bit, no need for loop freeing > 8 bits */ if (s->bsLive >= 8) { @@ -101,7 +114,7 @@ void bsW1(EState* s, uint32_t v) s->bsBuff <<= 8; s->bsLive -= 8; } - s->bsBuff |= (v << (31 - s->bsLive)); + //s->bsBuff |= (0 << (31 - s->bsLive)); s->bsLive += 1; } @@ -573,8 +586,8 @@ void sendMTFValues(EState* s) for (i = 0; i < nSelectors; i++) { unsigned j; for (j = 0; j < s->selectorMtf[i]; j++) - bsW1(s, 1); - bsW1(s, 0); + bsW1_1(s); + bsW1_0(s); } /*--- Now the coding tables. ---*/ @@ -584,7 +597,7 @@ void sendMTFValues(EState* s) for (i = 0; i < alphaSize; i++) { while (curr < s->len[t][i]) { bsW(s, 2, 2); curr++; /* 10 */ }; while (curr > s->len[t][i]) { bsW(s, 2, 3); curr--; /* 11 */ }; - bsW1(s, 0); + bsW1_0(s); } } @@ -698,7 +711,7 @@ void BZ2_compressBlock(EState* s, int is_last_block) * so as to maintain backwards compatibility with * older versions of bzip2. */ - bsW1(s, 0); + bsW1_0(s); bsW(s, 24, s->origPtr); generateMTFValues(s); -- cgit v1.2.3-55-g6feb From 1cbcb023169abdb7ca278ae7c589c6f9fb60ca03 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 15:26:00 +0100 Subject: bzip2: optimize zPend variable code function old new delta generateMTFValues 433 378 -55 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 18 ++++++++-------- archival/libarchive/bz/compress.c | 42 ++++++++++++++++++++++++++------------ archival/libarchive/bz/huffman.c | 2 +- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index a3b099f4b..0b614ce08 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -161,7 +161,7 @@ void fallbackQSort3(uint32_t* fmap, ltLo++; unLo++; continue; - }; + } if (n > 0) break; unLo++; } @@ -172,7 +172,7 @@ void fallbackQSort3(uint32_t* fmap, mswap(fmap[unHi], fmap[gtHi]); gtHi--; unHi--; continue; - }; + } if (n < 0) break; unHi--; } @@ -326,7 +326,7 @@ void fallbackSort(uint32_t* fmap, if (cc != cc1) { SET_BH(i); cc = cc1; - }; + } } } } @@ -545,7 +545,7 @@ uint8_t mmed3(uint8_t a, uint8_t b, uint8_t c) t = a; a = b; b = t; - }; + } /* here b >= a */ if (b > c) { b = c; @@ -638,8 +638,8 @@ void mainQSort3(uint32_t* ptr, ltLo++; unLo++; continue; - }; - if (n > 0) break; + } + if (n > 0) break; unLo++; } while (1) { @@ -651,8 +651,8 @@ void mainQSort3(uint32_t* ptr, gtHi--; unHi--; continue; - }; - if (n < 0) break; + } + if (n < 0) break; unHi--; } if (unLo > unHi) @@ -1063,7 +1063,7 @@ void BZ2_blockSort(EState* s) if (ptr[i] == 0) { s->origPtr = i; break; - }; + } AssertH(s->origPtr != -1, 1003); } diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index fc6af6595..7efa533b0 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -162,7 +162,7 @@ void generateMTFValues(EState* s) { uint8_t yy[256]; int32_t i, j; - int32_t zPend; + int zPend; int32_t wr; int32_t EOB; @@ -217,6 +217,7 @@ void generateMTFValues(EState* s) if (zPend > 0) { zPend--; while (1) { +#if 0 if (zPend & 1) { mtfv[wr] = BZ_RUNB; wr++; s->mtfFreq[BZ_RUNB]++; @@ -224,10 +225,18 @@ void generateMTFValues(EState* s) mtfv[wr] = BZ_RUNA; wr++; s->mtfFreq[BZ_RUNA]++; } - if (zPend < 2) break; - zPend = (uint32_t)(zPend - 2) / 2; +#else /* same as above, since BZ_RUNA is 0 and BZ_RUNB is 1 */ + unsigned run = zPend & 1; + mtfv[wr] = run; + wr++; + s->mtfFreq[run]++; +#endif + zPend -= 2; + if (zPend < 0) + break; + zPend = (unsigned)zPend / 2; /* bbox: unsigned div is easier */ - }; + } zPend = 0; } { @@ -244,7 +253,7 @@ void generateMTFValues(EState* s) rtmp2 = rtmp; rtmp = *ryy_j; *ryy_j = rtmp2; - }; + } yy[0] = rtmp; j = ryy_j - &(yy[0]); mtfv[wr] = j+1; @@ -257,6 +266,7 @@ void generateMTFValues(EState* s) if (zPend > 0) { zPend--; while (1) { +#if 0 if (zPend & 1) { mtfv[wr] = BZ_RUNB; wr++; @@ -266,12 +276,18 @@ void generateMTFValues(EState* s) wr++; s->mtfFreq[BZ_RUNA]++; } - if (zPend < 2) +#else /* same as above, since BZ_RUNA is 0 and BZ_RUNB is 1 */ + unsigned run = zPend & 1; + mtfv[wr] = run; + wr++; + s->mtfFreq[run]++; +#endif + zPend -= 2; + if (zPend < 0) break; - zPend = (uint32_t)(zPend - 2) / 2; + zPend = (unsigned)zPend / 2; /* bbox: unsigned div is easier */ - }; - zPend = 0; + } } mtfv[wr] = EOB; @@ -528,11 +544,11 @@ void sendMTFValues(EState* s) tmp2 = tmp; tmp = pos[j]; pos[j] = tmp2; - }; + } pos[0] = tmp; s->selectorMtf[i] = j; } - }; + } /*--- Assign actual codes for the tables. --*/ for (t = 0; t < nGroups; t++) { @@ -595,8 +611,8 @@ void sendMTFValues(EState* s) unsigned curr = s->len[t][0]; bsW(s, 5, curr); for (i = 0; i < alphaSize; i++) { - while (curr < s->len[t][i]) { bsW(s, 2, 2); curr++; /* 10 */ }; - while (curr > s->len[t][i]) { bsW(s, 2, 3); curr--; /* 11 */ }; + while (curr < s->len[t][i]) { bsW(s, 2, 2); curr++; /* 10 */ } + while (curr > s->len[t][i]) { bsW(s, 2, 3); curr--; /* 11 */ } bsW1_0(s); } } diff --git a/archival/libarchive/bz/huffman.c b/archival/libarchive/bz/huffman.c index bbec11adb..be5930e00 100644 --- a/archival/libarchive/bz/huffman.c +++ b/archival/libarchive/bz/huffman.c @@ -217,7 +217,7 @@ void BZ2_hbAssignCodes(int32_t *code, if (length[i] == n) { code[i] = vec; vec++; - }; + } } vec <<= 1; } -- cgit v1.2.3-55-g6feb From 2cfe10a5586abe4f50994f4a0d6a01cc867b8d43 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 15:31:54 +0100 Subject: bzip2: shrink makeMaps_e() function old new delta generateMTFValues 378 368 -10 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 7efa533b0..0d083486b 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -146,13 +146,14 @@ static void makeMaps_e(EState* s) { int i; - s->nInUse = 0; + unsigned cnt = 0; for (i = 0; i < 256; i++) { if (s->inUse[i]) { - s->unseqToSeq[i] = s->nInUse; - s->nInUse++; + s->unseqToSeq[i] = cnt; + cnt++; } } + s->nInUse = cnt; } -- cgit v1.2.3-55-g6feb From 9e5662ea74ce314104904729a092a0130db6c85b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 15:53:17 +0100 Subject: bzip2: reuse zPend processing code function old new delta generateMTFValues 378 357 -21 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 44 ++++++++++++--------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 0d083486b..6260fd94c 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -162,7 +162,7 @@ static NOINLINE void generateMTFValues(EState* s) { uint8_t yy[256]; - int32_t i, j; + int i; int zPend; int32_t wr; int32_t EOB; @@ -195,16 +195,18 @@ void generateMTFValues(EState* s) makeMaps_e(s); EOB = s->nInUse+1; + wr = 0; + zPend = 0; for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0; - wr = 0; - zPend = 0; for (i = 0; i < s->nInUse; i++) yy[i] = (uint8_t) i; for (i = 0; i < s->nblock; i++) { - uint8_t ll_i; + uint8_t ll_i = ll_i; /* gcc 4.3.1 thinks it may be used w/o init */ + int32_t j; + AssertD(wr <= i, "generateMTFValues(1)"); j = ptr[i] - 1; if (j < 0) @@ -216,6 +218,7 @@ void generateMTFValues(EState* s) zPend++; } else { if (zPend > 0) { + process_zPend: zPend--; while (1) { #if 0 @@ -238,6 +241,8 @@ void generateMTFValues(EState* s) zPend = (unsigned)zPend / 2; /* bbox: unsigned div is easier */ } + if (i < 0) /* came via "goto process_zPend"? exit */ + goto end; zPend = 0; } { @@ -264,33 +269,10 @@ void generateMTFValues(EState* s) } } - if (zPend > 0) { - zPend--; - while (1) { -#if 0 - if (zPend & 1) { - mtfv[wr] = BZ_RUNB; - wr++; - s->mtfFreq[BZ_RUNB]++; - } else { - mtfv[wr] = BZ_RUNA; - wr++; - s->mtfFreq[BZ_RUNA]++; - } -#else /* same as above, since BZ_RUNA is 0 and BZ_RUNB is 1 */ - unsigned run = zPend & 1; - mtfv[wr] = run; - wr++; - s->mtfFreq[run]++; -#endif - zPend -= 2; - if (zPend < 0) - break; - zPend = (unsigned)zPend / 2; - /* bbox: unsigned div is easier */ - } - } - + i = -1; + if (zPend > 0) + goto process_zPend; /* "process it and come back here" */ + end: mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++; -- cgit v1.2.3-55-g6feb From e59e5ff96e9461dc658748509ec41408c140f6fb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 15:59:46 +0100 Subject: bzip2: reduce indentation, no code changes Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 89 ++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 6260fd94c..f1393242d 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -216,56 +216,57 @@ void generateMTFValues(EState* s) if (yy[0] == ll_i) { zPend++; - } else { - if (zPend > 0) { + continue; + } + + if (zPend > 0) { process_zPend: - zPend--; - while (1) { + zPend--; + while (1) { #if 0 - if (zPend & 1) { - mtfv[wr] = BZ_RUNB; wr++; - s->mtfFreq[BZ_RUNB]++; - } else { - mtfv[wr] = BZ_RUNA; wr++; - s->mtfFreq[BZ_RUNA]++; - } + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } #else /* same as above, since BZ_RUNA is 0 and BZ_RUNB is 1 */ - unsigned run = zPend & 1; - mtfv[wr] = run; - wr++; - s->mtfFreq[run]++; + unsigned run = zPend & 1; + mtfv[wr] = run; + wr++; + s->mtfFreq[run]++; #endif - zPend -= 2; - if (zPend < 0) - break; - zPend = (unsigned)zPend / 2; - /* bbox: unsigned div is easier */ - } - if (i < 0) /* came via "goto process_zPend"? exit */ - goto end; - zPend = 0; + zPend -= 2; + if (zPend < 0) + break; + zPend = (unsigned)zPend / 2; + /* bbox: unsigned div is easier */ } - { - register uint8_t rtmp; - register uint8_t* ryy_j; - register uint8_t rll_i; - rtmp = yy[1]; - yy[1] = yy[0]; - ryy_j = &(yy[1]); - rll_i = ll_i; - while (rll_i != rtmp) { - register uint8_t rtmp2; - ryy_j++; - rtmp2 = rtmp; - rtmp = *ryy_j; - *ryy_j = rtmp2; - } - yy[0] = rtmp; - j = ryy_j - &(yy[0]); - mtfv[wr] = j+1; - wr++; - s->mtfFreq[j+1]++; + if (i < 0) /* came via "goto process_zPend"? exit */ + goto end; + zPend = 0; + } + { + register uint8_t rtmp; + register uint8_t* ryy_j; + register uint8_t rll_i; + rtmp = yy[1]; + yy[1] = yy[0]; + ryy_j = &(yy[1]); + rll_i = ll_i; + while (rll_i != rtmp) { + register uint8_t rtmp2; + ryy_j++; + rtmp2 = rtmp; + rtmp = *ryy_j; + *ryy_j = rtmp2; } + yy[0] = rtmp; + j = ryy_j - &(yy[0]); + mtfv[wr] = j+1; + wr++; + s->mtfFreq[j+1]++; } } -- cgit v1.2.3-55-g6feb From aaa3818a75bb64bb96a1cda9412162aa7a8a44de Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 16:43:33 +0100 Subject: bzip2: remove redundant loop termination check in mainSort() function old new delta mainSort 1202 1192 -10 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 0b614ce08..19341369c 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -825,7 +825,6 @@ void mainSort(EState* state, } { - int32_t vv; /* bbox: was: int32_t h = 1; */ /* do h = 3 * h + 1; while (h <= 256); */ uint32_t h = 364; @@ -834,6 +833,7 @@ void mainSort(EState* state, /*h = h / 3;*/ h = (h * 171) >> 9; /* bbox: fast h/3 */ for (i = h; i <= 255; i++) { + int32_t vv; vv = runningOrder[i]; j = i; while (BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv)) { @@ -854,7 +854,7 @@ void mainSort(EState* state, numQSorted = 0; - for (i = 0; i <= 255; i++) { + for (i = 0; /*i <= 255*/; i++) { /* * Process big buckets, starting with the least full. @@ -974,7 +974,10 @@ void mainSort(EState* state, */ bigDone[ss] = True; - if (i < 255) { + if (i == 255) + break; + + { int32_t bbStart = ftab[ss << 8] & CLEARMASK; int32_t bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; int32_t shifts = 0; -- cgit v1.2.3-55-g6feb From 2109fce41093ad38c94fafcf610957b5c38b0b4c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 17:22:06 +0100 Subject: bzip2: make locals in mainSort() saner, convert one of them from uint16 to unsigned function old new delta mainSort 1192 1178 -14 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 65 +++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 19341369c..a95d1f54d 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -729,10 +729,8 @@ void mainSort(EState* state, int32_t nblock, int32_t* budget) { - int32_t i, j, k, ss, sb; - uint8_t c1; + int32_t i, j; int32_t numQSorted; - uint16_t s; Bool bigDone[256]; /* bbox: moved to EState to save stack int32_t runningOrder[256]; @@ -785,33 +783,36 @@ void mainSort(EState* state, ftab[i] = j; } - s = block[0] << 8; - i = nblock - 1; + { + unsigned s; + s = block[0] << 8; + i = nblock - 1; #if CONFIG_BZIP2_FAST >= 2 - for (; i >= 3; i -= 4) { - s = (s >> 8) | (block[i] << 8); - j = ftab[s] - 1; - ftab[s] = j; - ptr[j] = i; - s = (s >> 8) | (block[i-1] << 8); - j = ftab[s] - 1; - ftab[s] = j; - ptr[j] = i-1; - s = (s >> 8) | (block[i-2] << 8); - j = ftab[s] - 1; - ftab[s] = j; - ptr[j] = i-2; - s = (s >> 8) | (block[i-3] << 8); - j = ftab[s] - 1; - ftab[s] = j; - ptr[j] = i-3; - } + for (; i >= 3; i -= 4) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] - 1; + ftab[s] = j; + ptr[j] = i; + s = (s >> 8) | (block[i-1] << 8); + j = ftab[s] - 1; + ftab[s] = j; + ptr[j] = i-1; + s = (s >> 8) | (block[i-2] << 8); + j = ftab[s] - 1; + ftab[s] = j; + ptr[j] = i-2; + s = (s >> 8) | (block[i-3] << 8); + j = ftab[s] - 1; + ftab[s] = j; + ptr[j] = i-3; + } #endif - for (; i >= 0; i--) { - s = (s >> 8) | (block[i] << 8); - j = ftab[s] - 1; - ftab[s] = j; - ptr[j] = i; + for (; i >= 0; i--) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] - 1; + ftab[s] = j; + ptr[j] = i; + } } /* @@ -827,7 +828,7 @@ void mainSort(EState* state, { /* bbox: was: int32_t h = 1; */ /* do h = 3 * h + 1; while (h <= 256); */ - uint32_t h = 364; + unsigned h = 364; do { /*h = h / 3;*/ @@ -855,6 +856,7 @@ void mainSort(EState* state, numQSorted = 0; for (i = 0; /*i <= 255*/; i++) { + int32_t ss; /* * Process big buckets, starting with the least full. @@ -874,6 +876,7 @@ void mainSort(EState* state, */ for (j = 0; j <= 255; j++) { if (j != ss) { + int32_t sb; sb = (ss << 8) + j; if (!(ftab[sb] & SETMASK)) { int32_t lo = ftab[sb] & CLEARMASK; @@ -906,6 +909,8 @@ void mainSort(EState* state, copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; } for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { + unsigned c1; + int32_t k; k = ptr[j] - 1; if (k < 0) k += nblock; @@ -914,6 +919,8 @@ void mainSort(EState* state, ptr[copyStart[c1]++] = k; } for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { + unsigned c1; + int32_t k; k = ptr[j]-1; if (k < 0) k += nblock; -- cgit v1.2.3-55-g6feb From 524fa29a934e4974736e36d6a40225b5ed8e2b17 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 17:30:16 +0100 Subject: bzip2: eliminate write-only local numQSorted Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index a95d1f54d..3fe74f71c 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -730,7 +730,6 @@ void mainSort(EState* state, int32_t* budget) { int32_t i, j; - int32_t numQSorted; Bool bigDone[256]; /* bbox: moved to EState to save stack int32_t runningOrder[256]; @@ -853,8 +852,6 @@ void mainSort(EState* state, * The main sorting loop. */ - numQSorted = 0; - for (i = 0; /*i <= 255*/; i++) { int32_t ss; @@ -887,7 +884,6 @@ void mainSort(EState* state, lo, hi, BZ_N_RADIX, budget ); if (*budget < 0) return; - numQSorted += (hi - lo + 1); } } ftab[sb] |= SETMASK; @@ -940,6 +936,9 @@ void mainSort(EState* state, for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; + if (i == 255) + break; + /* * Step 3: * The [ss] big bucket is now done. Record this fact, @@ -981,9 +980,6 @@ void mainSort(EState* state, */ bigDone[ss] = True; - if (i == 255) - break; - { int32_t bbStart = ftab[ss << 8] & CLEARMASK; int32_t bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; -- cgit v1.2.3-55-g6feb From df23f55e395d78d9cfc0fc5054651f5da58dcf25 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 17:38:23 +0100 Subject: bzip2: remove redundant clearing of an alredy unset bit function old new delta mainSort 1178 1171 -7 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 3fe74f71c..473244db0 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -873,10 +873,10 @@ void mainSort(EState* state, */ for (j = 0; j <= 255; j++) { if (j != ss) { - int32_t sb; + unsigned sb; sb = (ss << 8) + j; if (!(ftab[sb] & SETMASK)) { - int32_t lo = ftab[sb] & CLEARMASK; + int32_t lo = ftab[sb] /*& CLEARMASK (redundant)*/; int32_t hi = (ftab[sb+1] & CLEARMASK) - 1; if (hi > lo) { mainQSort3( -- cgit v1.2.3-55-g6feb From c364d32ccc030c04b5289f0ffea0197f4ff7e666 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 17:44:00 +0100 Subject: bzip2: runningOrder[] values are always 0..255, make it uint8 function old new delta mainSort 1171 1124 -47 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 9 ++++----- archival/libarchive/bz/bzlib_private.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 473244db0..c2d5f15c6 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -732,7 +732,7 @@ void mainSort(EState* state, int32_t i, j; Bool bigDone[256]; /* bbox: moved to EState to save stack - int32_t runningOrder[256]; + uint8_t runningOrder[256]; int32_t copyStart[256]; int32_t copyEnd [256]; */ @@ -833,16 +833,15 @@ void mainSort(EState* state, /*h = h / 3;*/ h = (h * 171) >> 9; /* bbox: fast h/3 */ for (i = h; i <= 255; i++) { - int32_t vv; - vv = runningOrder[i]; + unsigned vv; + vv = runningOrder[i]; /* uint8[] */ j = i; while (BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv)) { runningOrder[j] = runningOrder[j-h]; j = j - h; if (j <= (h - 1)) - goto zero; + break; } - zero: runningOrder[j] = vv; } } while (h != 1); diff --git a/archival/libarchive/bz/bzlib_private.h b/archival/libarchive/bz/bzlib_private.h index 8e44a8e64..4acaef8b8 100644 --- a/archival/libarchive/bz/bzlib_private.h +++ b/archival/libarchive/bz/bzlib_private.h @@ -192,7 +192,7 @@ typedef struct EState { int32_t BZ2_hbMakeCodeLengths__weight[BZ_MAX_ALPHA_SIZE * 2]; int32_t BZ2_hbMakeCodeLengths__parent[BZ_MAX_ALPHA_SIZE * 2]; - int32_t mainSort__runningOrder[256]; + uint8_t mainSort__runningOrder[256]; int32_t mainSort__copyStart[256]; int32_t mainSort__copyEnd[256]; } EState; -- cgit v1.2.3-55-g6feb From fe1bab4d35e6e3ab8ea8742556474ddedfdfeccb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 18:03:33 +0100 Subject: bzip2: convert some locals to unsigned's Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index c2d5f15c6..fe2b2c2f2 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -852,7 +852,7 @@ void mainSort(EState* state, */ for (i = 0; /*i <= 255*/; i++) { - int32_t ss; + unsigned ss; /* * Process big buckets, starting with the least full. @@ -980,14 +980,14 @@ void mainSort(EState* state, bigDone[ss] = True; { - int32_t bbStart = ftab[ss << 8] & CLEARMASK; - int32_t bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; - int32_t shifts = 0; + unsigned bbStart = ftab[ss << 8] & CLEARMASK; + unsigned bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + unsigned shifts = 0; while ((bbSize >> shifts) > 65534) shifts++; for (j = bbSize-1; j >= 0; j--) { - int32_t a2update = ptr[bbStart + j]; + unsigned a2update = ptr[bbStart + j]; /* uint32[] */ uint16_t qVal = (uint16_t)(j >> shifts); quadrant[a2update] = qVal; if (a2update < BZ_N_OVERSHOOT) -- cgit v1.2.3-55-g6feb From 9431bdd189859e3053bcb268116d6459964ebe60 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 18:11:08 +0100 Subject: bzip2: small simplification in mainSort() function old new delta mainSort 1127 1118 -9 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index fe2b2c2f2..2e08f2f9d 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -833,13 +833,13 @@ void mainSort(EState* state, /*h = h / 3;*/ h = (h * 171) >> 9; /* bbox: fast h/3 */ for (i = h; i <= 255; i++) { - unsigned vv; + unsigned vv, jh; vv = runningOrder[i]; /* uint8[] */ j = i; - while (BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv)) { - runningOrder[j] = runningOrder[j-h]; - j = j - h; - if (j <= (h - 1)) + while (jh = j - h, BIGFREQ(runningOrder[jh]) > BIGFREQ(vv)) { + runningOrder[j] = runningOrder[jh]; + j = jh; + if (j < h) break; } runningOrder[j] = vv; -- cgit v1.2.3-55-g6feb From 8e31412231cc56e36bd4eb8410bffc78d0b252d9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 18:28:10 +0100 Subject: bzip2: eliminate one parameter to mainQSort3() Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 2e08f2f9d..9de9cc3cc 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -468,8 +468,7 @@ void mainSimpleSort(uint32_t* ptr, int32_t d, int32_t* budget) { - int32_t i, j, h, bigN, hp; - uint32_t v; + int32_t bigN, hp; bigN = hi - lo + 1; if (bigN < 2) return; @@ -479,10 +478,14 @@ void mainSimpleSort(uint32_t* ptr, hp--; for (; hp >= 0; hp--) { - h = incs[hp]; + int32_t i, h; + h = incs[hp]; i = lo + h; while (1) { + int32_t j; + uint32_t v; + /*-- copy 1 --*/ if (i > hi) break; v = ptr[i]; @@ -592,9 +595,10 @@ void mainQSort3(uint32_t* ptr, int32_t nblock, int32_t loSt, int32_t hiSt, - int32_t dSt, + /*int32_t dSt,*/ int32_t* budget) { + enum { dSt = BZ_N_RADIX }; int32_t unLo, unHi, ltLo, gtHi, n, m, med; int32_t sp, lo, hi, d; @@ -880,7 +884,7 @@ void mainSort(EState* state, if (hi > lo) { mainQSort3( ptr, block, quadrant, nblock, - lo, hi, BZ_N_RADIX, budget + lo, hi, /*BZ_N_RADIX,*/ budget ); if (*budget < 0) return; } -- cgit v1.2.3-55-g6feb From 0599a137ba5a6043ce6195a2c12deeaf3886f002 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 18:47:34 +0100 Subject: bzip2: a few more locals converted to generic types Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 9de9cc3cc..a1ee59224 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -452,7 +452,7 @@ int mainGtU( * usually small, typically <= 20. */ static -const int32_t incs[14] = { +const uint32_t incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484 @@ -468,7 +468,8 @@ void mainSimpleSort(uint32_t* ptr, int32_t d, int32_t* budget) { - int32_t bigN, hp; + int32_t bigN; + int hp; bigN = hi - lo + 1; if (bigN < 2) return; @@ -478,15 +479,15 @@ void mainSimpleSort(uint32_t* ptr, hp--; for (; hp >= 0; hp--) { - int32_t i, h; + int32_t i; + unsigned h; h = incs[hp]; i = lo + h; while (1) { - int32_t j; - uint32_t v; + unsigned j; + unsigned v; - /*-- copy 1 --*/ if (i > hi) break; v = ptr[i]; j = i; @@ -511,7 +512,6 @@ void mainSimpleSort(uint32_t* ptr, } ptr[j] = v; i++; - /*-- copy 3 --*/ if (i > hi) break; v = ptr[i]; -- cgit v1.2.3-55-g6feb From 10f516500ec8bbf2a9fb2ac53f88ba89f7472c17 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 19:11:00 +0100 Subject: gzip2: small simplification in mainSimpleSort() function old new delta mainQSort3 1165 1163 -2 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index a1ee59224..578f6d41f 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -468,15 +468,16 @@ void mainSimpleSort(uint32_t* ptr, int32_t d, int32_t* budget) { - int32_t bigN; - int hp; - - bigN = hi - lo + 1; - if (bigN < 2) return; - - hp = 0; - while (incs[hp] < bigN) hp++; - hp--; + /* At which increment to start? */ + int hp = 0; + { + int bigN = hi - lo; + if (bigN <= 0) + return; + while (incs[hp] <= bigN) + hp++; + hp--; + } for (; hp >= 0; hp--) { int32_t i; @@ -754,22 +755,22 @@ void mainSort(EState* state, #if CONFIG_BZIP2_FAST >= 2 for (; i >= 3; i -= 4) { quadrant[i] = 0; - j = (j >> 8) | (((uint16_t)block[i]) << 8); + j = (j >> 8) | (((unsigned)block[i]) << 8); ftab[j]++; quadrant[i-1] = 0; - j = (j >> 8) | (((uint16_t)block[i-1]) << 8); + j = (j >> 8) | (((unsigned)block[i-1]) << 8); ftab[j]++; quadrant[i-2] = 0; - j = (j >> 8) | (((uint16_t)block[i-2]) << 8); + j = (j >> 8) | (((unsigned)block[i-2]) << 8); ftab[j]++; quadrant[i-3] = 0; - j = (j >> 8) | (((uint16_t)block[i-3]) << 8); + j = (j >> 8) | (((unsigned)block[i-3]) << 8); ftab[j]++; } #endif for (; i >= 0; i--) { quadrant[i] = 0; - j = (j >> 8) | (((uint16_t)block[i]) << 8); + j = (j >> 8) | (((unsigned)block[i]) << 8); ftab[j]++; } -- cgit v1.2.3-55-g6feb From c9ae8d770bf8a21fec962f67b759569b263c68fc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 20:19:51 +0100 Subject: bzip2: pass sorting params through EState* pointer function old new delta mainGtU 499 515 +16 sendMTFValues 2085 2094 +9 mainSort 1116 1119 +3 generateMTFValues 357 356 -1 fallbackSort 1719 1705 -14 mainQSort3 1163 1141 -22 BZ2_blockSort 118 85 -33 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/4 up/down: 28/-70) Total: -42 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 124 +++++++++++++++------------------ archival/libarchive/bz/bzlib.c | 2 +- archival/libarchive/bz/bzlib_private.h | 6 ++ 3 files changed, 65 insertions(+), 67 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 578f6d41f..effaa152a 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -227,17 +227,19 @@ void fallbackQSort3(uint32_t* fmap, #define UNALIGNED_BH(zz) ((zz) & 0x01f) static -void fallbackSort(uint32_t* fmap, - uint32_t* eclass, - uint32_t* bhtab, - int32_t nblock) +void fallbackSort(EState* state) { int32_t ftab[257]; int32_t ftabCopy[256]; int32_t H, i, j, k, l, r, cc, cc1; int32_t nNotDone; int32_t nBhtab; - uint8_t* eclass8 = (uint8_t*)eclass; + /* params */ + uint32_t *const fmap = state->arr1; + uint32_t *const eclass = state->arr2; +#define eclass8 ((uint8_t*)eclass) + uint32_t *const bhtab = state->ftab; + const int32_t nblock = state->nblock; /* * Initial 1-char radix sort to generate @@ -349,6 +351,7 @@ void fallbackSort(uint32_t* fmap, eclass8[fmap[i]] = (uint8_t)j; } AssertH(j < 256, 1005); +#undef eclass8 } #undef SET_BH @@ -367,18 +370,18 @@ void fallbackSort(uint32_t* fmap, /*---------------------------------------------*/ static NOINLINE -int mainGtU( +int mainGtU(EState* state, uint32_t i1, - uint32_t i2, - uint8_t* block, - uint16_t* quadrant, - uint32_t nblock, - int32_t* budget) + uint32_t i2) { int32_t k; uint8_t c1, c2; uint16_t s1, s2; + uint8_t *const block = state->block; + uint16_t *const quadrant = state->quadrant; + const int32_t nblock = state->nblock; + /* Loop unrolling here is actually very useful * (generated code is much simpler), * code size increase is only 270 bytes (i386) @@ -435,7 +438,7 @@ int mainGtU( if (i1 >= nblock) i1 -= nblock; if (i2 >= nblock) i2 -= nblock; - (*budget)--; + state->budget--; k -= 8; } while (k >= 0); @@ -459,15 +462,13 @@ const uint32_t incs[14] = { }; static -void mainSimpleSort(uint32_t* ptr, - uint8_t* block, - uint16_t* quadrant, - int32_t nblock, +void mainSimpleSort(EState* state, int32_t lo, int32_t hi, - int32_t d, - int32_t* budget) + int32_t d) { + uint32_t *const ptr = state->ptr; + /* At which increment to start? */ int hp = 0; { @@ -492,7 +493,7 @@ void mainSimpleSort(uint32_t* ptr, if (i > hi) break; v = ptr[i]; j = i; - while (mainGtU(ptr[j-h]+d, v+d, block, quadrant, nblock, budget)) { + while (mainGtU(state, ptr[j-h]+d, v+d)) { ptr[j] = ptr[j-h]; j = j - h; if (j <= (lo + h - 1)) break; @@ -506,7 +507,7 @@ void mainSimpleSort(uint32_t* ptr, if (i > hi) break; v = ptr[i]; j = i; - while (mainGtU(ptr[j-h]+d, v+d, block, quadrant, nblock, budget)) { + while (mainGtU(state, ptr[j-h]+d, v+d)) { ptr[j] = ptr[j-h]; j = j - h; if (j <= (lo + h - 1)) break; @@ -517,7 +518,7 @@ void mainSimpleSort(uint32_t* ptr, if (i > hi) break; v = ptr[i]; j = i; - while (mainGtU(ptr[j-h]+d, v+d, block, quadrant, nblock, budget)) { + while (mainGtU(state, ptr[j-h]+d, v+d)) { ptr[j] = ptr[j-h]; j = j - h; if (j <= (lo + h - 1)) break; @@ -525,7 +526,7 @@ void mainSimpleSort(uint32_t* ptr, ptr[j] = v; i++; #endif - if (*budget < 0) return; + if (state->budget < 0) return; } } } @@ -590,14 +591,10 @@ uint8_t mmed3(uint8_t a, uint8_t b, uint8_t c) #define MAIN_QSORT_STACK_SIZE 100 static NOINLINE -void mainQSort3(uint32_t* ptr, - uint8_t* block, - uint16_t* quadrant, - int32_t nblock, +void mainQSort3(EState* state, int32_t loSt, - int32_t hiSt, - /*int32_t dSt,*/ - int32_t* budget) + int32_t hiSt + /*int32_t dSt*/) { enum { dSt = BZ_N_RADIX }; int32_t unLo, unHi, ltLo, gtHi, n, m, med; @@ -611,6 +608,9 @@ void mainQSort3(uint32_t* ptr, int32_t nextHi[3]; int32_t nextD [3]; + uint32_t *const ptr = state->ptr; + uint8_t *const block = state->block; + sp = 0; mpush(loSt, hiSt, dSt); @@ -621,8 +621,8 @@ void mainQSort3(uint32_t* ptr, if (hi - lo < MAIN_QSORT_SMALL_THRESH || d > MAIN_QSORT_DEPTH_THRESH ) { - mainSimpleSort(ptr, block, quadrant, nblock, lo, hi, d, budget); - if (*budget < 0) + mainSimpleSort(state, lo, hi, d); + if (state->budget < 0) return; continue; } @@ -726,13 +726,7 @@ void mainQSort3(uint32_t* ptr, #define CLEARMASK (~(SETMASK)) static NOINLINE -void mainSort(EState* state, - uint32_t* ptr, - uint8_t* block, - uint16_t* quadrant, - uint32_t* ftab, - int32_t nblock, - int32_t* budget) +void mainSort(EState* state) { int32_t i, j; Bool bigDone[256]; @@ -745,6 +739,12 @@ void mainSort(EState* state, #define copyStart (state->mainSort__copyStart) #define copyEnd (state->mainSort__copyEnd) + uint32_t *const ptr = state->ptr; + uint8_t *const block = state->block; + uint32_t *const ftab = state->ftab; + const int32_t nblock = state->nblock; + uint16_t *const quadrant = state->quadrant; + /*-- set up the 2-byte frequency table --*/ /* was: for (i = 65536; i >= 0; i--) ftab[i] = 0; */ memset(ftab, 0, 65537 * sizeof(ftab[0])); @@ -883,11 +883,8 @@ void mainSort(EState* state, int32_t lo = ftab[sb] /*& CLEARMASK (redundant)*/; int32_t hi = (ftab[sb+1] & CLEARMASK) - 1; if (hi > lo) { - mainQSort3( - ptr, block, quadrant, nblock, - lo, hi, /*BZ_N_RADIX,*/ budget - ); - if (*budget < 0) return; + mainQSort3(state, lo, hi /*,BZ_N_RADIX*/); + if (state->budget < 0) return; } } ftab[sb] |= SETMASK; @@ -1025,31 +1022,25 @@ void mainSort(EState* state, * arr1[0 .. nblock-1] holds sorted order */ static NOINLINE -void BZ2_blockSort(EState* s) +void BZ2_blockSort(EState* state) { /* In original bzip2 1.0.4, it's a parameter, but 30 * (which was the default) should work ok. */ enum { wfact = 30 }; + unsigned i; - uint32_t* ptr = s->ptr; - uint8_t* block = s->block; - uint32_t* ftab = s->ftab; - int32_t nblock = s->nblock; - uint16_t* quadrant; - int32_t budget; - int32_t i; - - if (nblock < 10000) { - fallbackSort(s->arr1, s->arr2, ftab, nblock); + if (state->nblock < 10000) { + fallbackSort(state); } else { /* Calculate the location for quadrant, remembering to get * the alignment right. Assumes that &(block[0]) is at least * 2-byte aligned -- this should be ok since block is really * the first section of arr2. */ - i = nblock + BZ_N_OVERSHOOT; - if (i & 1) i++; - quadrant = (uint16_t*)(&(block[i])); + i = state->nblock + BZ_N_OVERSHOOT; + if (i & 1) + i++; + state->quadrant = (uint16_t*) &(state->block[i]); /* (wfact-1) / 3 puts the default-factor-30 * transition point at very roughly the same place as @@ -1058,24 +1049,25 @@ void BZ2_blockSort(EState* s) * resulting compressed stream is now the same regardless * of whether or not we use the main sort or fallback sort. */ - budget = nblock * ((wfact-1) / 3); + state->budget = state->nblock * ((wfact-1) / 3); - mainSort(s, ptr, block, quadrant, ftab, nblock, &budget); - if (budget < 0) { - fallbackSort(s->arr1, s->arr2, ftab, nblock); + mainSort(state); + if (state->budget < 0) { + fallbackSort(state); } } #if BZ_LIGHT_DEBUG - s->origPtr = -1; + state->origPtr = -1; #endif - for (i = 0; i < s->nblock; i++) - if (ptr[i] == 0) { - s->origPtr = i; + for (i = 0; i < state->nblock; i++) { + if (state->ptr[i] == 0) { + state->origPtr = i; break; } + } - AssertH(s->origPtr != -1, 1003); + AssertH(state->origPtr != -1, 1003); } diff --git a/archival/libarchive/bz/bzlib.c b/archival/libarchive/bz/bzlib.c index ef98bb213..9af2f026d 100644 --- a/archival/libarchive/bz/bzlib.c +++ b/archival/libarchive/bz/bzlib.c @@ -87,7 +87,7 @@ int isempty_RL(EState* s) static void BZ2_bzCompressInit(bz_stream *strm, int blockSize100k) { - int32_t n; + unsigned n; EState* s; s = xzalloc(sizeof(EState)); diff --git a/archival/libarchive/bz/bzlib_private.h b/archival/libarchive/bz/bzlib_private.h index 4acaef8b8..fc05d0ebe 100644 --- a/archival/libarchive/bz/bzlib_private.h +++ b/archival/libarchive/bz/bzlib_private.h @@ -121,6 +121,7 @@ typedef struct EState { /* mode this stream is in, and whether inputting */ /* or outputting data */ int32_t mode; +//both smallint? int32_t state; /* remembers avail_in when flush/finish requested */ @@ -134,6 +135,9 @@ typedef struct EState { uint32_t *arr2; uint32_t *ftab; + uint16_t* quadrant; + int32_t budget; + /* aliases for arr1 and arr2 */ uint32_t *ptr; uint8_t *block; @@ -142,6 +146,7 @@ typedef struct EState { /* guess what */ uint32_t *crc32table; +//move down /* run-length-encoding of the input */ uint32_t state_in_ch; @@ -165,6 +170,7 @@ typedef struct EState { /* misc administratium */ int32_t blockNo; int32_t blockSize100k; +//smallint? /* stuff for coding the MTF values */ int32_t nMTF; -- cgit v1.2.3-55-g6feb From 86be6d5ba9df8b8237a8c3edc2a844aaa63bd559 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 20:50:20 +0100 Subject: bzip2: move ->origPtr out of struct EState, make a few members smaller function old new delta BZ2_compressBlock 223 228 +5 BZ2_blockSort 85 88 +3 generateMTFValues 356 357 +1 handle_compress 355 349 -6 compressStream 538 531 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/2 up/down: 9/-13) Total: -4 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 22 +++++++++++----------- archival/libarchive/bz/bzlib_private.h | 26 ++++++++++++-------------- archival/libarchive/bz/compress.c | 6 ++++-- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index effaa152a..7c5b6c552 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -1022,16 +1022,15 @@ void mainSort(EState* state) * arr1[0 .. nblock-1] holds sorted order */ static NOINLINE -void BZ2_blockSort(EState* state) +int32_t BZ2_blockSort(EState* state) { /* In original bzip2 1.0.4, it's a parameter, but 30 * (which was the default) should work ok. */ enum { wfact = 30 }; unsigned i; + int32_t origPtr = origPtr; - if (state->nblock < 10000) { - fallbackSort(state); - } else { + if (state->nblock >= 10000) { /* Calculate the location for quadrant, remembering to get * the alignment right. Assumes that &(block[0]) is at least * 2-byte aligned -- this should be ok since block is really @@ -1050,24 +1049,25 @@ void BZ2_blockSort(EState* state) * of whether or not we use the main sort or fallback sort. */ state->budget = state->nblock * ((wfact-1) / 3); - mainSort(state); - if (state->budget < 0) { - fallbackSort(state); - } + if (state->budget >= 0) + goto good; } + fallbackSort(state); + good: #if BZ_LIGHT_DEBUG - state->origPtr = -1; + origPtr = -1; #endif for (i = 0; i < state->nblock; i++) { if (state->ptr[i] == 0) { - state->origPtr = i; + origPtr = i; break; } } - AssertH(state->origPtr != -1, 1003); + AssertH(origPtr != -1, 1003); + return origPtr; } diff --git a/archival/libarchive/bz/bzlib_private.h b/archival/libarchive/bz/bzlib_private.h index fc05d0ebe..8b8bbe3eb 100644 --- a/archival/libarchive/bz/bzlib_private.h +++ b/archival/libarchive/bz/bzlib_private.h @@ -120,9 +120,11 @@ typedef struct EState { /* mode this stream is in, and whether inputting */ /* or outputting data */ - int32_t mode; -//both smallint? - int32_t state; + uint8_t mode; + uint8_t state; + + /* misc administratium */ + uint8_t blockSize100k; /* remembers avail_in when flush/finish requested */ /* bbox: not needed, strm->avail_in always has the same value */ @@ -130,12 +132,11 @@ typedef struct EState { /* uint32_t avail_in_expect; */ /* for doing the block sorting */ - int32_t origPtr; uint32_t *arr1; uint32_t *arr2; uint32_t *ftab; - uint16_t* quadrant; + uint16_t *quadrant; int32_t budget; /* aliases for arr1 and arr2 */ @@ -144,10 +145,6 @@ typedef struct EState { uint16_t *mtfv; uint8_t *zbits; - /* guess what */ - uint32_t *crc32table; -//move down - /* run-length-encoding of the input */ uint32_t state_in_ch; int32_t state_in_len; @@ -156,21 +153,22 @@ typedef struct EState { int32_t nblock; int32_t nblockMAX; //int32_t numZ; // index into s->zbits[], replaced by pointer: - uint8_t *posZ; - uint8_t *state_out_pos; + uint8_t *posZ; + uint8_t *state_out_pos; /* the buffer for bit stream creation */ uint32_t bsBuff; int32_t bsLive; + /* guess what */ + uint32_t *crc32table; + /* block and combined CRCs */ uint32_t blockCRC; uint32_t combinedCRC; /* misc administratium */ int32_t blockNo; - int32_t blockSize100k; -//smallint? /* stuff for coding the MTF values */ int32_t nMTF; @@ -206,7 +204,7 @@ typedef struct EState { /*-- compression. --*/ -static void +static int32_t BZ2_blockSort(EState*); static void diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index f1393242d..f65076758 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -665,6 +665,8 @@ void sendMTFValues(EState* s) static void BZ2_compressBlock(EState* s, int is_last_block) { + int32_t origPtr = origPtr; + if (s->nblock > 0) { BZ_FINALISE_CRC(s->blockCRC); s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31); @@ -672,7 +674,7 @@ void BZ2_compressBlock(EState* s, int is_last_block) if (s->blockNo > 1) s->posZ = s->zbits; // was: s->numZ = 0; - BZ2_blockSort(s); + origPtr = BZ2_blockSort(s); } s->zbits = &((uint8_t*)s->arr2)[s->nblock]; @@ -713,7 +715,7 @@ void BZ2_compressBlock(EState* s, int is_last_block) */ bsW1_0(s); - bsW(s, 24, s->origPtr); + bsW(s, 24, origPtr); generateMTFValues(s); sendMTFValues(s); } -- cgit v1.2.3-55-g6feb From 0e60a36c929e57e47d5de8e1ac0e53d4ec185a70 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Feb 2018 22:52:11 +0100 Subject: bzip2: move runningOrder[] back to stack - 256 bytes is not much function old new delta mainSort 1119 1108 -11 Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/blocksort.c | 13 ++++++++----- archival/libarchive/bz/bzlib_private.h | 1 - 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 7c5b6c552..0a9a597d0 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -113,9 +113,8 @@ void fallbackQSort3(uint32_t* fmap, int32_t loSt, int32_t hiSt) { - int32_t unLo, unHi, ltLo, gtHi, n, m; - int32_t sp, lo, hi; - uint32_t med, r, r3; + int32_t sp; + uint32_t r; int32_t stackLo[FALLBACK_QSORT_STACK_SIZE]; int32_t stackHi[FALLBACK_QSORT_STACK_SIZE]; @@ -125,6 +124,11 @@ void fallbackQSort3(uint32_t* fmap, fpush(loSt, hiSt); while (sp > 0) { + int32_t unLo, unHi, ltLo, gtHi, n, m; + int32_t lo, hi; + uint32_t med; + uint32_t r3; + AssertH(sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004); fpop(lo, hi); @@ -730,12 +734,11 @@ void mainSort(EState* state) { int32_t i, j; Bool bigDone[256]; - /* bbox: moved to EState to save stack uint8_t runningOrder[256]; + /* bbox: moved to EState to save stack int32_t copyStart[256]; int32_t copyEnd [256]; */ -#define runningOrder (state->mainSort__runningOrder) #define copyStart (state->mainSort__copyStart) #define copyEnd (state->mainSort__copyEnd) diff --git a/archival/libarchive/bz/bzlib_private.h b/archival/libarchive/bz/bzlib_private.h index 8b8bbe3eb..ef75ef08a 100644 --- a/archival/libarchive/bz/bzlib_private.h +++ b/archival/libarchive/bz/bzlib_private.h @@ -196,7 +196,6 @@ typedef struct EState { int32_t BZ2_hbMakeCodeLengths__weight[BZ_MAX_ALPHA_SIZE * 2]; int32_t BZ2_hbMakeCodeLengths__parent[BZ_MAX_ALPHA_SIZE * 2]; - uint8_t mainSort__runningOrder[256]; int32_t mainSort__copyStart[256]; int32_t mainSort__copyEnd[256]; } EState; -- cgit v1.2.3-55-g6feb From 2598915d43d7403e72d312ac426e585499e94173 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Feb 2018 00:15:29 +0100 Subject: gunzip: fix from gzip-1.3.12 for gzip file with all zero length codes Corresponding changelog from gzip-1.3.12 reads: """ 2006-12-20 Paul Eggert * inflate.c (huft_build): Fix regression that caused gzip to refuse to uncompress null input (all zero length codes). Problem reported by Yiorgos Adamopoulos. This regression was caused by the security patch installed 2006-11-20, which in turn came from Debian, which in turn apparently came from Thomas Biege of SuSe. """ function old new delta huft_build 1176 1216 +40 Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_gunzip.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index edff7e0e5..9a58d10d4 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c @@ -280,8 +280,8 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current /* Given a list of code lengths and a maximum table size, make a set of * tables to decode that set of codes. Return zero on success, one if * the given code set is incomplete (the tables are still built in this - * case), two if the input is invalid (all zero length codes or an - * oversubscribed set of lengths) - in this case stores NULL in *t. + * case), two if the input is invalid (an oversubscribed set of lengths) + * - in this case stores NULL in *t. * * b: code lengths in bits (all assumed <= BMAX) * n: number of codes (assumed <= N_MAX) @@ -330,8 +330,15 @@ static int huft_build(const unsigned *b, const unsigned n, p++; /* can't combine with above line (Solaris bug) */ } while (--i); if (c[0] == n) { /* null input - all zero length codes */ - *m = 0; - return 2; + q = xzalloc(3 * sizeof(*q)); + //q[0].v.t = NULL; + q[1].e = 99; /* invalid code marker */ + q[1].b = 1; + q[2].e = 99; /* invalid code marker */ + q[2].b = 1; + *t = q + 1; + *m = 1; + return 0; } /* Find minimum and maximum length, bound *m by those */ -- cgit v1.2.3-55-g6feb From 565af2322271984edf6eb533f90789e52e311848 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Feb 2018 18:32:21 +0100 Subject: ftpd: switch to mallced "globals" function old new delta cmdio_write_ok 45 49 +4 cmdio_write_error 45 49 +4 handle_dir_common 360 363 +3 handle_cwd 40 43 +3 port_or_pasv_was_seen 37 39 +2 pasv_active 13 15 +2 cmdio_write_raw 34 36 +2 cmdio_write 78 80 +2 get_remote_transfer_fd 94 93 -1 port_pasv_cleanup 50 45 -5 bind_for_passive_mode 124 119 -5 cmdio_get_cmd_and_arg 237 230 -7 timeout_handler 104 93 -11 ftpd_main 2222 2152 -70 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 8/6 up/down: 22/-99) Total: -77 bytes Signed-off-by: Denys Vlasenko --- networking/ftpd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/networking/ftpd.c b/networking/ftpd.c index 8af5acac2..833507ba1 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -171,9 +171,13 @@ struct globals { char msg_ok [(sizeof("NNN " MSG_OK ) + 3) & 0xfffc]; char msg_err[(sizeof("NNN " MSG_ERR) + 3) & 0xfffc]; } FIX_ALIASING; -#define G (*(struct globals*)bb_common_bufsiz1) +#define G (*ptr_to_globals) +/* ^^^ about 75 bytes smaller code than this: */ +//#define G (*(struct globals*)bb_common_bufsiz1) #define INIT_G() do { \ - setup_common_bufsiz(); \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ + /*setup_common_bufsiz();*/ \ + \ /* Moved to main */ \ /*strcpy(G.msg_ok + 4, MSG_OK );*/ \ /*strcpy(G.msg_err + 4, MSG_ERR);*/ \ -- cgit v1.2.3-55-g6feb From daa643205f76da5cb3e899aba2a047fc2c6f1994 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Feb 2018 18:49:31 +0100 Subject: ftpgetput: preparations for ESPV support, no code changes Signed-off-by: Denys Vlasenko --- networking/ftpgetput.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index e866a7754..3f98e07f3 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c @@ -174,24 +174,25 @@ For example, vsftp happily answers TODO2: need to stop ignoring IP address in PASV response. */ + //if (ftpcmd("EPSV", NULL) != 229) { + if (ftpcmd("PASV", NULL) != 227) { + ftp_die("PASV"); + } - if (ftpcmd("PASV", NULL) != 227) { - ftp_die("PASV"); - } - - /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage] - * Server's IP is N1.N2.N3.N4 (we ignore it) - * Server's port for data connection is P1*256+P2 */ - buf_ptr = strrchr(buf, ')'); - if (buf_ptr) *buf_ptr = '\0'; + /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage] + * Server's IP is N1.N2.N3.N4 (we ignore it) + * Server's port for data connection is P1*256+P2 */ + buf_ptr = strrchr(buf, ')'); + if (buf_ptr) *buf_ptr = '\0'; - buf_ptr = strrchr(buf, ','); - *buf_ptr = '\0'; - port_num = xatoul_range(buf_ptr + 1, 0, 255); + buf_ptr = strrchr(buf, ','); + *buf_ptr = '\0'; + port_num = xatoul_range(buf_ptr + 1, 0, 255); - buf_ptr = strrchr(buf, ','); - *buf_ptr = '\0'; - port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256; + buf_ptr = strrchr(buf, ','); + *buf_ptr = '\0'; + port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256; + //} set_nport(&lsa->u.sa, htons(port_num)); return xconnect_stream(lsa); -- cgit v1.2.3-55-g6feb From 05b84d4e92b79fa47259907a78d8375bb5490135 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Feb 2018 19:08:34 +0100 Subject: ftpgetput: add EPSV support (PASV-like thing for IPv6) Based on a patch by Kev Kitchens. function old new delta xconnect_ftpdata 149 223 +74 Signed-off-by: Denys Vlasenko --- networking/ftpgetput.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 3f98e07f3..697955e82 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c @@ -156,7 +156,7 @@ static int xconnect_ftpdata(void) unsigned port_num; /* -TODO: PASV command will not work for IPv6. RFC2428 describes +PASV command will not work for IPv6. RFC2428 describes IPv6-capable "extended PASV" - EPSV. "EPSV [protocol]" asks server to bind to and listen on a data port @@ -171,15 +171,16 @@ but we don't need that. NB: PASV may still work for some servers even over IPv6. For example, vsftp happily answers "227 Entering Passive Mode (0,0,0,0,n,n)" and proceeds as usual. - -TODO2: need to stop ignoring IP address in PASV response. */ - //if (ftpcmd("EPSV", NULL) != 229) { + if (!ENABLE_FEATURE_IPV6 + || ftpcmd("EPSV", NULL) != 229 + ) { +/* maybe also go straight to PAST if lsa->u.sa.sa_family == AF_INET? */ if (ftpcmd("PASV", NULL) != 227) { ftp_die("PASV"); } - /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage] + /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]" * Server's IP is N1.N2.N3.N4 (we ignore it) * Server's port for data connection is P1*256+P2 */ buf_ptr = strrchr(buf, ')'); @@ -192,7 +193,16 @@ TODO2: need to stop ignoring IP address in PASV response. buf_ptr = strrchr(buf, ','); *buf_ptr = '\0'; port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256; - //} + } else { + /* Response is "NNN garbage(|||P1|)" + * Server's port for data connection is P1 */ + buf_ptr = strrchr(buf, '|'); + if (buf_ptr) *buf_ptr = '\0'; + + buf_ptr = strrchr(buf, '|'); + *buf_ptr = '\0'; + port_num = xatoul_range(buf_ptr + 1, 0, 65535); + } set_nport(&lsa->u.sa, htons(port_num)); return xconnect_stream(lsa); -- cgit v1.2.3-55-g6feb From f75a7c04397b8b3409b5c4f5a4438654b6b830ce Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Feb 2018 23:55:14 +0100 Subject: ftpd: fix aliasing warning from gcc-6.1.1 Signed-off-by: Denys Vlasenko --- networking/ftpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/ftpd.c b/networking/ftpd.c index 833507ba1..dd0fc4e92 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -262,7 +262,7 @@ cmdio_write(uint32_t status_str, const char *str) static void cmdio_write_ok(unsigned status) { - *(uint32_t *) G.msg_ok = status; + *(bb__aliased_uint32_t *) G.msg_ok = status; xwrite(STDOUT_FILENO, G.msg_ok, sizeof("NNN " MSG_OK) - 1); if (G.verbose > 1) verbose_log(G.msg_ok); @@ -273,7 +273,7 @@ cmdio_write_ok(unsigned status) static void cmdio_write_error(unsigned status) { - *(uint32_t *) G.msg_err = status; + *(bb__aliased_uint32_t *) G.msg_err = status; xwrite(STDOUT_FILENO, G.msg_err, sizeof("NNN " MSG_ERR) - 1); if (G.verbose > 0) verbose_log(G.msg_err); -- cgit v1.2.3-55-g6feb From c2a51b0cf16918482c993c4998a2a920e499a43f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Feb 2018 00:34:08 +0100 Subject: bzip2: work around bad compiler optimization gc-6.1.1 x86_64: function old new delta generateMTFValues 380 367 -13 gcc-4.3.1 386: function old new delta inner_loop - 41 +41 generateMTFValues 357 294 -63 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 41/-63) Total: -22 bytes gcc-6.3.0 386: function old new delta inner_loop - 36 +36 generateMTFValues 363 250 -113 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 36/-113) Total: -77 bytes The last case, gcc-6.3.0, runs almost 3 times faster after this change. Signed-off-by: Denys Vlasenko --- archival/libarchive/bz/compress.c | 75 ++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index f65076758..462740b6c 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -158,6 +158,38 @@ void makeMaps_e(EState* s) /*---------------------------------------------------*/ +/* + * This bit of code is performance-critical. + * On 32bit x86, gcc-6.3.0 was observed to spill ryy_j to stack, + * resulting in abysmal performance (x3 slowdown). + * Forcing it into a separate function alleviates register pressure, + * and spillage no longer happens. + * Other versions of gcc do not exhibit this problem, but out-of-line code + * seems to be helping them too (code is both smaller and faster). + * Therefore NOINLINE is enabled for the entire 32bit x86 arch for now, + * without a check for gcc version. + */ +static +#if defined __i386__ +NOINLINE +#endif +int inner_loop(uint8_t *yy, uint8_t ll_i) +{ + register uint8_t rtmp; + register uint8_t* ryy_j; + rtmp = yy[1]; + yy[1] = yy[0]; + ryy_j = &(yy[1]); + while (ll_i != rtmp) { + register uint8_t rtmp2; + ryy_j++; + rtmp2 = rtmp; + rtmp = *ryy_j; + *ryy_j = rtmp2; + } + yy[0] = rtmp; + return ryy_j - &(yy[0]); +} static NOINLINE void generateMTFValues(EState* s) { @@ -165,7 +197,6 @@ void generateMTFValues(EState* s) int i; int zPend; int32_t wr; - int32_t EOB; /* * After sorting (eg, here), @@ -189,15 +220,12 @@ void generateMTFValues(EState* s) * compressBlock(). */ uint32_t* ptr = s->ptr; - uint8_t* block = s->block; - uint16_t* mtfv = s->mtfv; makeMaps_e(s); - EOB = s->nInUse+1; wr = 0; zPend = 0; - for (i = 0; i <= EOB; i++) + for (i = 0; i <= s->nInUse+1; i++) s->mtfFreq[i] = 0; for (i = 0; i < s->nInUse; i++) @@ -211,7 +239,7 @@ void generateMTFValues(EState* s) j = ptr[i] - 1; if (j < 0) j += s->nblock; - ll_i = s->unseqToSeq[block[j]]; + ll_i = s->unseqToSeq[s->block[j]]; AssertD(ll_i < s->nInUse, "generateMTFValues(2a)"); if (yy[0] == ll_i) { @@ -225,15 +253,15 @@ void generateMTFValues(EState* s) while (1) { #if 0 if (zPend & 1) { - mtfv[wr] = BZ_RUNB; wr++; + s->mtfv[wr] = BZ_RUNB; wr++; s->mtfFreq[BZ_RUNB]++; } else { - mtfv[wr] = BZ_RUNA; wr++; + s->mtfv[wr] = BZ_RUNA; wr++; s->mtfFreq[BZ_RUNA]++; } #else /* same as above, since BZ_RUNA is 0 and BZ_RUNB is 1 */ unsigned run = zPend & 1; - mtfv[wr] = run; + s->mtfv[wr] = run; wr++; s->mtfFreq[run]++; #endif @@ -247,36 +275,19 @@ void generateMTFValues(EState* s) goto end; zPend = 0; } - { - register uint8_t rtmp; - register uint8_t* ryy_j; - register uint8_t rll_i; - rtmp = yy[1]; - yy[1] = yy[0]; - ryy_j = &(yy[1]); - rll_i = ll_i; - while (rll_i != rtmp) { - register uint8_t rtmp2; - ryy_j++; - rtmp2 = rtmp; - rtmp = *ryy_j; - *ryy_j = rtmp2; - } - yy[0] = rtmp; - j = ryy_j - &(yy[0]); - mtfv[wr] = j+1; - wr++; - s->mtfFreq[j+1]++; - } + j = inner_loop(yy, ll_i); + s->mtfv[wr] = j+1; + wr++; + s->mtfFreq[j+1]++; } i = -1; if (zPend > 0) goto process_zPend; /* "process it and come back here" */ end: - mtfv[wr] = EOB; + s->mtfv[wr] = s->nInUse+1; wr++; - s->mtfFreq[EOB]++; + s->mtfFreq[s->nInUse+1]++; s->nMTF = wr; } -- cgit v1.2.3-55-g6feb From 5740e15de55baa343955196c641baeaec8a73b5c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Feb 2018 19:06:40 +0100 Subject: ftpd: handle restarts past 2147483647 bytes. closes 10741 Signed-off-by: Denys Vlasenko --- networking/ftpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/ftpd.c b/networking/ftpd.c index dd0fc4e92..8abbf7f57 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -603,7 +603,7 @@ static void handle_rest(void) { /* When ftp_arg == NULL simply restart from beginning */ - G.restart_pos = G.ftp_arg ? xatoi_positive(G.ftp_arg) : 0; + G.restart_pos = G.ftp_arg ? XATOOFF(G.ftp_arg) : 0; WRITE_OK(FTP_RESTOK); } -- cgit v1.2.3-55-g6feb From 98066662aa15a21627ef8a3fb7318b6ee301df22 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 13:33:00 +0100 Subject: tls: fix hash calculations if client cert is requested and sent Symptoms: connecting to openssl s_server -cert vsftpd.pem -port 990 -debug -cipher AES128-SHA works, but with "-verify 1" option added it does not. function old new delta tls_xread_record 474 499 +25 tls_handshake 1582 1607 +25 bad_record_die 98 110 +12 tls_run_copy_loop 282 293 +11 tls_xread_handshake_block 58 51 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 73/-7) Total: 66 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 94 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index fd3cb0dba..7936afca2 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -84,23 +84,23 @@ # define dbg_der(...) ((void)0) #endif -#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 -#define RECORD_TYPE_ALERT 21 -#define RECORD_TYPE_HANDSHAKE 22 -#define RECORD_TYPE_APPLICATION_DATA 23 - -#define HANDSHAKE_HELLO_REQUEST 0 -#define HANDSHAKE_CLIENT_HELLO 1 -#define HANDSHAKE_SERVER_HELLO 2 -#define HANDSHAKE_HELLO_VERIFY_REQUEST 3 -#define HANDSHAKE_NEW_SESSION_TICKET 4 -#define HANDSHAKE_CERTIFICATE 11 -#define HANDSHAKE_SERVER_KEY_EXCHANGE 12 -#define HANDSHAKE_CERTIFICATE_REQUEST 13 -#define HANDSHAKE_SERVER_HELLO_DONE 14 -#define HANDSHAKE_CERTIFICATE_VERIFY 15 -#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 -#define HANDSHAKE_FINISHED 20 +#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 /* 0x14 */ +#define RECORD_TYPE_ALERT 21 /* 0x15 */ +#define RECORD_TYPE_HANDSHAKE 22 /* 0x16 */ +#define RECORD_TYPE_APPLICATION_DATA 23 /* 0x17 */ + +#define HANDSHAKE_HELLO_REQUEST 0 /* 0x00 */ +#define HANDSHAKE_CLIENT_HELLO 1 /* 0x01 */ +#define HANDSHAKE_SERVER_HELLO 2 /* 0x02 */ +#define HANDSHAKE_HELLO_VERIFY_REQUEST 3 /* 0x03 */ +#define HANDSHAKE_NEW_SESSION_TICKET 4 /* 0x04 */ +#define HANDSHAKE_CERTIFICATE 11 /* 0x0b */ +#define HANDSHAKE_SERVER_KEY_EXCHANGE 12 /* 0x0c */ +#define HANDSHAKE_CERTIFICATE_REQUEST 13 /* 0x0d */ +#define HANDSHAKE_SERVER_HELLO_DONE 14 /* 0x0e */ +#define HANDSHAKE_CERTIFICATE_VERIFY 15 /* 0x0f */ +#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 /* 0x10 */ +#define HANDSHAKE_FINISHED 20 /* 0x14 */ #define SSL_NULL_WITH_NULL_NULL 0x0000 #define SSL_RSA_WITH_NULL_MD5 0x0001 @@ -512,10 +512,12 @@ static void bad_record_die(tls_state_t *tls, const char *expected, int len) bb_error_msg("got bad TLS record (len:%d) while expecting %s", len, expected); if (len > 0) { uint8_t *p = tls->inbuf; - while (len > 0) { + if (len > 99) + len = 99; /* don't flood, a few lines should be enough */ + do { fprintf(stderr, " %02x", *p++); len--; - } + } while (len != 0); fputc('\n', stderr); } xfunc_die(); @@ -671,9 +673,11 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) // AES_128_CBC Block 16 16 16 // AES_256_CBC Block 32 16 16 - /* Fill IV and padding in outbuf */ tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ - dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, tls->MAC_size); + dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", + size - tls->MAC_size, tls->MAC_size); + + /* Fill IV and padding in outbuf */ // RFC is talking nonsense: // "Padding that is added to force the length of the plaintext to be // an integral multiple of the block cipher's block length." @@ -773,7 +777,7 @@ static const char *alert_text(int code) return itoa(code); } -static int tls_xread_record(tls_state_t *tls) +static int tls_xread_record(tls_state_t *tls, const char *expected) { struct record_hdr *xhdr; int sz; @@ -796,13 +800,16 @@ static int tls_xread_record(tls_state_t *tls) if (total >= RECHDR_LEN && target == MAX_INBUF) { xhdr = (void*)tls->inbuf; target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); - if (target > MAX_INBUF) { - /* malformed input (too long): yell and die */ - tls->buffered_size = 0; - tls->ofs_to_buffered = total; - tls_error_die(tls); + + if (target > MAX_INBUF /* malformed input (too long) */ + || xhdr->proto_maj != TLS_MAJ + || xhdr->proto_min != TLS_MIN + ) { + sz = total < target ? total : target; + if (sz > 24) + sz = 24; /* don't flood */ + bad_record_die(tls, expected, sz); } - /* can also check type/proto_maj/proto_min here */ dbg("xhdr type:%d ver:%d.%d len:%d\n", xhdr->type, xhdr->proto_maj, xhdr->proto_min, 0x100 * xhdr->len16_hi + xhdr->len16_lo @@ -1137,13 +1144,11 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) static int tls_xread_handshake_block(tls_state_t *tls, int min_len) { struct record_hdr *xhdr; - int len = tls_xread_record(tls); + int len = tls_xread_record(tls, "handshake record"); xhdr = (void*)tls->inbuf; if (len < min_len || xhdr->type != RECORD_TYPE_HANDSHAKE - || xhdr->proto_maj != TLS_MAJ - || xhdr->proto_min != TLS_MIN ) { bad_record_die(tls, "handshake record", len); } @@ -1195,7 +1200,9 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) // 0023 0000 - session_ticket // 000a 0008 0006001700180019 - supported_groups // 000b 0002 0100 - ec_point_formats -// 000d 0016 00140401040305010503060106030301030302010203 - signature_algorithms +// 000d 0016 0014 0401 0403 0501 0503 0601 0603 0301 0303 0201 0203 - signature_algorithms +// wolfssl library sends this option, RFC 7627 (closes a security weakness, some servers may require it. TODO?): +// 0017 0000 - extended master secret }; struct client_hello *record; int len; @@ -1354,7 +1361,7 @@ static void get_server_cert(tls_state_t *tls) xhdr = (void*)tls->inbuf; certbuf = (void*)(xhdr + 1); if (certbuf[0] != HANDSHAKE_CERTIFICATE) - tls_error_die(tls); + bad_record_die(tls, "certificate", len); dbg("<< CERTIFICATE\n"); // 4392 bytes: // 0b 00|11|24 00|11|21 00|05|b0 30|82|05|ac|30|82|04|94|a0|03|02|01|02|02|11|00|9f|85|bf|66|4b|0c|dd|af|ca|50|86|79|50|1b|2b|e4|30|0d... @@ -1611,6 +1618,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) // <------- Finished // Application Data <------> Application Data int len; + int got_cert_req; send_client_hello_and_alloc_hsd(tls, sni); get_server_hello(tls); @@ -1638,7 +1646,8 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) len = tls_xread_handshake_block(tls, 4); } - if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { + got_cert_req = (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST); + if (got_cert_req) { dbg("<< CERTIFICATE_REQUEST\n"); // RFC 5246: "If no suitable certificate is available, // the client MUST send a certificate message containing no @@ -1647,7 +1656,9 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) // Client certificates are sent using the Certificate structure // defined in Section 7.4.2." // (i.e. the same format as server certs) - send_empty_client_cert(tls); + + /*send_empty_client_cert(tls); - WRONG (breaks handshake hash calc) */ + /* need to hash _all_ server replies first, up to ServerHelloDone */ len = tls_xread_handshake_block(tls, 4); } @@ -1657,6 +1668,9 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) // 0e 000000 (len:0) dbg("<< SERVER_HELLO_DONE\n"); + if (got_cert_req) + send_empty_client_cert(tls); + send_client_key_exchange(tls); send_change_cipher_spec(tls); @@ -1667,7 +1681,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) send_client_finished(tls); /* Get CHANGE_CIPHER_SPEC */ - len = tls_xread_record(tls); + len = tls_xread_record(tls, "switch to encrypted traffic"); if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) bad_record_die(tls, "switch to encrypted traffic", len); dbg("<< CHANGE_CIPHER_SPEC\n"); @@ -1685,9 +1699,9 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) } /* Get (encrypted) FINISHED from the server */ - len = tls_xread_record(tls); + len = tls_xread_record(tls, "'server finished'"); if (len < 4 || tls->inbuf[RECHDR_LEN] != HANDSHAKE_FINISHED) - tls_error_die(tls); + bad_record_die(tls, "'server finished'", len); dbg("<< FINISHED\n"); /* application data can be sent/received */ @@ -1763,7 +1777,7 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) if (pfds[1].revents) { dbg("NETWORK HAS DATA\n"); read_record: - nread = tls_xread_record(tls); + nread = tls_xread_record(tls, "encrypted data"); if (nread < 1) { /* TLS protocol has no real concept of one-sided shutdowns: * if we get "TLS EOF" from the peer, writes will fail too @@ -1775,7 +1789,7 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) break; } if (tls->inbuf[0] != RECORD_TYPE_APPLICATION_DATA) - bb_error_msg_and_die("unexpected record type %d", tls->inbuf[0]); + bad_record_die(tls, "encrypted data", nread); xwrite(STDOUT_FILENO, tls->inbuf + RECHDR_LEN, nread); /* We may already have a complete next record buffered, * can process it without network reads (and possible blocking) -- cgit v1.2.3-55-g6feb From e999657f6da95b8a40e51978461d964b56189e92 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 15:02:16 +0100 Subject: wget: preparations for ftps:// support (block move, no code changes) Signed-off-by: Denys Vlasenko --- networking/wget.c | 162 +++++++++++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index d1d85230c..9300fa30b 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -602,87 +602,6 @@ static void reset_beg_range_to_zero(void) /* ftruncate(G.output_fd, 0); */ } -static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) -{ - FILE *sfp; - char *str; - int port; - - if (!target->user) - target->user = xstrdup("anonymous:busybox@"); - - sfp = open_socket(lsa); - if (ftpcmd(NULL, NULL, sfp) != 220) - bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4)); - - /* - * Splitting username:password pair, - * trying to log in - */ - str = strchr(target->user, ':'); - if (str) - *str++ = '\0'; - switch (ftpcmd("USER ", target->user, sfp)) { - case 230: - break; - case 331: - if (ftpcmd("PASS ", str, sfp) == 230) - break; - /* fall through (failed login) */ - default: - bb_error_msg_and_die("ftp login: %s", sanitize_string(G.wget_buf + 4)); - } - - ftpcmd("TYPE I", NULL, sfp); - - /* - * Querying file size - */ - if (ftpcmd("SIZE ", target->path, sfp) == 213) { - G.content_len = BB_STRTOOFF(G.wget_buf + 4, NULL, 10); - if (G.content_len < 0 || errno) { - bb_error_msg_and_die("SIZE value is garbage"); - } - G.got_clen = 1; - } - - /* - * Entering passive mode - */ - if (ftpcmd("PASV", NULL, sfp) != 227) { - pasv_error: - bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf)); - } - // Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage] - // Server's IP is N1.N2.N3.N4 (we ignore it) - // Server's port for data connection is P1*256+P2 - str = strrchr(G.wget_buf, ')'); - if (str) str[0] = '\0'; - str = strrchr(G.wget_buf, ','); - if (!str) goto pasv_error; - port = xatou_range(str+1, 0, 255); - *str = '\0'; - str = strrchr(G.wget_buf, ','); - if (!str) goto pasv_error; - port += xatou_range(str+1, 0, 255) * 256; - set_nport(&lsa->u.sa, htons(port)); - - *dfpp = open_socket(lsa); - - if (G.beg_range != 0) { - sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); - if (ftpcmd(G.wget_buf, NULL, sfp) == 350) - G.content_len -= G.beg_range; - else - reset_beg_range_to_zero(); - } - - if (ftpcmd("RETR ", target->path, sfp) > 150) - bb_error_msg_and_die("bad response to %s: %s", "RETR", sanitize_string(G.wget_buf)); - - return sfp; -} - #if ENABLE_FEATURE_WGET_OPENSSL static int spawn_https_helper_openssl(const char *host, unsigned port) { @@ -808,6 +727,87 @@ static void spawn_ssl_client(const char *host, int network_fd) } #endif +static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) +{ + FILE *sfp; + char *str; + int port; + + if (!target->user) + target->user = xstrdup("anonymous:busybox@"); + + sfp = open_socket(lsa); + if (ftpcmd(NULL, NULL, sfp) != 220) + bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4)); + + /* + * Splitting username:password pair, + * trying to log in + */ + str = strchr(target->user, ':'); + if (str) + *str++ = '\0'; + switch (ftpcmd("USER ", target->user, sfp)) { + case 230: + break; + case 331: + if (ftpcmd("PASS ", str, sfp) == 230) + break; + /* fall through (failed login) */ + default: + bb_error_msg_and_die("ftp login: %s", sanitize_string(G.wget_buf + 4)); + } + + ftpcmd("TYPE I", NULL, sfp); + + /* + * Querying file size + */ + if (ftpcmd("SIZE ", target->path, sfp) == 213) { + G.content_len = BB_STRTOOFF(G.wget_buf + 4, NULL, 10); + if (G.content_len < 0 || errno) { + bb_error_msg_and_die("SIZE value is garbage"); + } + G.got_clen = 1; + } + + /* + * Entering passive mode + */ + if (ftpcmd("PASV", NULL, sfp) != 227) { + pasv_error: + bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf)); + } + // Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage] + // Server's IP is N1.N2.N3.N4 (we ignore it) + // Server's port for data connection is P1*256+P2 + str = strrchr(G.wget_buf, ')'); + if (str) str[0] = '\0'; + str = strrchr(G.wget_buf, ','); + if (!str) goto pasv_error; + port = xatou_range(str+1, 0, 255); + *str = '\0'; + str = strrchr(G.wget_buf, ','); + if (!str) goto pasv_error; + port += xatou_range(str+1, 0, 255) * 256; + set_nport(&lsa->u.sa, htons(port)); + + *dfpp = open_socket(lsa); + + if (G.beg_range != 0) { + sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); + if (ftpcmd(G.wget_buf, NULL, sfp) == 350) + G.content_len -= G.beg_range; + else + reset_beg_range_to_zero(); + } + + if (ftpcmd("RETR ", target->path, sfp) > 150) + bb_error_msg_and_die("bad response to %s: %s", "RETR", sanitize_string(G.wget_buf)); + + return sfp; +} + static void NOINLINE retrieve_file_data(FILE *dfp) { #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT -- cgit v1.2.3-55-g6feb From 403f2999f94937ba3f37db6d093832f636815bb9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 15:15:08 +0100 Subject: wget: initial support for ftps:// function old new delta spawn_ssl_client - 185 +185 parse_url 409 461 +52 packed_usage 32259 32278 +19 tls_run_copy_loop 293 306 +13 ssl_client_main 128 138 +10 showmode 330 338 +8 P_FTPS - 5 +5 filter_datapoints 177 179 +2 deflate 907 905 -2 decode_one_format 723 716 -7 wget_main 2591 2440 -151 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 6/3 up/down: 294/-160) Total: 134 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 3 ++- networking/ssl_client.c | 14 ++++++++------ networking/tls.c | 4 +++- networking/wget.c | 37 +++++++++++++++++++++++++++++-------- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 2bb364366..a4eb6ee67 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -772,7 +772,8 @@ static inline tls_state_t *new_tls_state(void) return tls; } void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC; -void tls_run_copy_loop(tls_state_t *tls) FAST_FUNC; +#define TLSLOOP_EXIT_ON_LOCAL_EOF (1 << 0) +void tls_run_copy_loop(tls_state_t *tls, unsigned flags) FAST_FUNC; void socket_want_pktinfo(int fd) FAST_FUNC; diff --git a/networking/ssl_client.c b/networking/ssl_client.c index d479846d7..eb84e7726 100644 --- a/networking/ssl_client.c +++ b/networking/ssl_client.c @@ -15,7 +15,7 @@ //kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o //usage:#define ssl_client_trivial_usage -//usage: "-s FD [-r FD] [-n SNI]" +//usage: "[-e] -s FD [-r FD] [-n SNI]" //usage:#define ssl_client_full_usage "" #include "libbb.h" @@ -30,26 +30,28 @@ int ssl_client_main(int argc UNUSED_PARAM, char **argv) // INIT_G(); tls = new_tls_state(); - opt = getopt32(argv, "s:#r:#n:", &tls->ofd, &tls->ifd, &sni); - if (!(opt & 2)) { + opt = getopt32(argv, "es:#r:#n:", &tls->ofd, &tls->ifd, &sni); + if (!(opt & (1<<2))) { /* -r N defaults to -s N */ tls->ifd = tls->ofd; } - if (!(opt & 3)) { + if (!(opt & (3<<1))) { if (!argv[1]) bb_show_usage(); /* Undocumented debug feature: without -s and -r, takes HOST arg and connects to it */ // // Talk to kernel.org: - // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox ssl_client kernel.org + // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | busybox ssl_client kernel.org if (!sni) sni = argv[1]; tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443); } tls_handshake(tls, sni); - tls_run_copy_loop(tls); + + BUILD_BUG_ON(TLSLOOP_EXIT_ON_LOCAL_EOF != 1); + tls_run_copy_loop(tls, /*flags*/ opt & 1); return EXIT_SUCCESS; } diff --git a/networking/tls.c b/networking/tls.c index 7936afca2..da7b6058f 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1727,7 +1727,7 @@ static void tls_xwrite(tls_state_t *tls, int len) // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 -void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) +void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) { int inbuf_size; const int INBUF_STEP = 4 * 1024; @@ -1762,6 +1762,8 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) */ pfds[0].fd = -1; tls_free_outbuf(tls); /* mem usage optimization */ + if (flags & TLSLOOP_EXIT_ON_LOCAL_EOF) + break; } else { if (nread == inbuf_size) { /* TLS has per record overhead, if input comes fast, diff --git a/networking/wget.c b/networking/wget.c index 9300fa30b..daa728a9d 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -48,6 +48,7 @@ //config: //config:config FEATURE_WGET_HTTPS //config: bool "Support HTTPS using internal TLS code" +//it also enables FTPS support, but it's not well tested yet //config: default y //config: depends on WGET //config: select TLS @@ -176,6 +177,9 @@ struct host_info { static const char P_FTP[] ALIGN1 = "ftp"; static const char P_HTTP[] ALIGN1 = "http"; #if SSL_SUPPORTED +# if ENABLE_FEATURE_WGET_HTTPS +static const char P_FTPS[] ALIGN1 = "ftps"; +# endif static const char P_HTTPS[] ALIGN1 = "https"; #endif @@ -484,6 +488,12 @@ static void parse_url(const char *src_url, struct host_info *h) h->port = bb_lookup_port(P_FTP, "tcp", 21); } else #if SSL_SUPPORTED +# if ENABLE_FEATURE_WGET_HTTPS + if (strcmp(url, P_FTPS) == 0) { + h->port = bb_lookup_port(P_FTPS, "tcp", 990); + h->protocol = P_FTPS; + } else +# endif if (strcmp(url, P_HTTPS) == 0) { h->port = bb_lookup_port(P_HTTPS, "tcp", 443); h->protocol = P_HTTPS; @@ -678,7 +688,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) #endif #if ENABLE_FEATURE_WGET_HTTPS -static void spawn_ssl_client(const char *host, int network_fd) +static void spawn_ssl_client(const char *host, int network_fd, int flags) { int sp[2]; int pid; @@ -703,17 +713,19 @@ static void spawn_ssl_client(const char *host, int network_fd) tls_state_t *tls = new_tls_state(); tls->ifd = tls->ofd = network_fd; tls_handshake(tls, servername); - tls_run_copy_loop(tls); + tls_run_copy_loop(tls, flags); exit(0); } else { - char *argv[5]; + char *argv[6]; + xmove_fd(network_fd, 3); argv[0] = (char*)"ssl_client"; argv[1] = (char*)"-s3"; //TODO: if (!is_ip_address(servername))... argv[2] = (char*)"-n"; argv[3] = servername; - argv[4] = NULL; + argv[4] = (flags & TLSLOOP_EXIT_ON_LOCAL_EOF ? (char*)"-e" : NULL); + argv[5] = NULL; BB_EXECVP(argv[0], argv); bb_perror_msg_and_die("can't execute '%s'", argv[0]); } @@ -737,6 +749,11 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ target->user = xstrdup("anonymous:busybox@"); sfp = open_socket(lsa); +#if ENABLE_FEATURE_WGET_HTTPS + if (target->protocol == P_FTPS) + spawn_ssl_client(target->host, fileno(sfp), TLSLOOP_EXIT_ON_LOCAL_EOF); +#endif + if (ftpcmd(NULL, NULL, sfp) != 220) bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4)); @@ -794,6 +811,10 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ *dfpp = open_socket(lsa); + //For encrypted data, need to send "PROT P" and get "200 PROT now Private" response first + //Without it (or with "PROT C"), data is sent unencrypted + //spawn_ssl_client(target->host, fileno(*dfpp), /*flags*/ 0); + if (G.beg_range != 0) { sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); if (ftpcmd(G.wget_buf, NULL, sfp) == 350) @@ -981,7 +1002,7 @@ static void download_one_url(const char *url) /* Use the proxy if necessary */ use_proxy = (strcmp(G.proxy_flag, "off") != 0); if (use_proxy) { - proxy = getenv(target.protocol == P_FTP ? "ftp_proxy" : "http_proxy"); + proxy = getenv(target.protocol[0] == 'f' ? "ftp_proxy" : "http_proxy"); //FIXME: what if protocol is https? Ok to use http_proxy? use_proxy = (proxy && proxy[0]); if (use_proxy) @@ -1042,7 +1063,7 @@ static void download_one_url(const char *url) /*G.content_len = 0; - redundant, got_clen = 0 is enough */ G.got_clen = 0; G.chunked = 0; - if (use_proxy || target.protocol != P_FTP) { + if (use_proxy || target.protocol[0] != 'f' /*not ftp[s]*/) { /* * HTTP session */ @@ -1060,7 +1081,7 @@ static void download_one_url(const char *url) # if ENABLE_FEATURE_WGET_HTTPS if (fd < 0) { /* no openssl? try internal */ sfp = open_socket(lsa); - spawn_ssl_client(server.host, fileno(sfp)); + spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); goto socket_opened; } # else @@ -1077,7 +1098,7 @@ static void download_one_url(const char *url) /* Only internal TLS support is configured */ sfp = open_socket(lsa); if (target.protocol == P_HTTPS) - spawn_ssl_client(server.host, fileno(sfp)); + spawn_ssl_client(server.host, fileno(sfp), /*flags*/ 0); #else /* ssl (https) support is not configured */ sfp = open_socket(lsa); -- cgit v1.2.3-55-g6feb From 1783ffa990814e2aac14e7ff5a4bbf2d5bebe3cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 15:48:12 +0100 Subject: wget: add EPSV support function old new delta parse_pasv_epsv - 151 +151 wget_main 2440 2382 -58 xconnect_ftpdata 223 94 -129 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/2 up/down: 151/-187) Total: -36 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + networking/ftpgetput.c | 57 ++++++-------------------------------- networking/parse_pasv_epsv.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ networking/wget.c | 19 +++++-------- 4 files changed, 82 insertions(+), 61 deletions(-) create mode 100644 networking/parse_pasv_epsv.c diff --git a/include/libbb.h b/include/libbb.h index a4eb6ee67..e2bedaf41 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -787,6 +787,7 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags, socklen_t sa_size) FAST_FUNC; uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; +int parse_pasv_epsv(char *buf) FAST_FUNC; /* 0 if argv[0] is NULL: */ unsigned string_array_len(char **argv) FAST_FUNC; diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 697955e82..cdad629da 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c @@ -152,57 +152,16 @@ static void ftp_login(void) static int xconnect_ftpdata(void) { - char *buf_ptr; - unsigned port_num; + int port_num; -/* -PASV command will not work for IPv6. RFC2428 describes -IPv6-capable "extended PASV" - EPSV. - -"EPSV [protocol]" asks server to bind to and listen on a data port -in specified protocol. Protocol is 1 for IPv4, 2 for IPv6. -If not specified, defaults to "same as used for control connection". -If server understood you, it should answer "229 (|||port|)" -where "|" are literal pipe chars and "port" is ASCII decimal port#. - -There is also an IPv6-capable replacement for PORT (EPRT), -but we don't need that. - -NB: PASV may still work for some servers even over IPv6. -For example, vsftp happily answers -"227 Entering Passive Mode (0,0,0,0,n,n)" and proceeds as usual. -*/ - if (!ENABLE_FEATURE_IPV6 - || ftpcmd("EPSV", NULL) != 229 - ) { -/* maybe also go straight to PAST if lsa->u.sa.sa_family == AF_INET? */ - if (ftpcmd("PASV", NULL) != 227) { - ftp_die("PASV"); - } - - /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]" - * Server's IP is N1.N2.N3.N4 (we ignore it) - * Server's port for data connection is P1*256+P2 */ - buf_ptr = strrchr(buf, ')'); - if (buf_ptr) *buf_ptr = '\0'; - - buf_ptr = strrchr(buf, ','); - *buf_ptr = '\0'; - port_num = xatoul_range(buf_ptr + 1, 0, 255); - - buf_ptr = strrchr(buf, ','); - *buf_ptr = '\0'; - port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256; - } else { - /* Response is "NNN garbage(|||P1|)" - * Server's port for data connection is P1 */ - buf_ptr = strrchr(buf, '|'); - if (buf_ptr) *buf_ptr = '\0'; - - buf_ptr = strrchr(buf, '|'); - *buf_ptr = '\0'; - port_num = xatoul_range(buf_ptr + 1, 0, 65535); + if (ENABLE_FEATURE_IPV6 && ftpcmd("EPSV", NULL) == 229) { + /* good */ + } else if (ftpcmd("PASV", NULL) != 227) { + ftp_die("PASV"); } + port_num = parse_pasv_epsv(buf); + if (port_num < 0) + ftp_die("PASV"); set_nport(&lsa->u.sa, htons(port_num)); return xconnect_stream(lsa); diff --git a/networking/parse_pasv_epsv.c b/networking/parse_pasv_epsv.c new file mode 100644 index 000000000..f32087152 --- /dev/null +++ b/networking/parse_pasv_epsv.c @@ -0,0 +1,66 @@ +/* + * Utility routines. + * + * Copyright (C) 2018 Denys Vlasenko + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ +//kbuild:lib-$(CONFIG_FTPGET) += ftpgetput.o +//kbuild:lib-$(CONFIG_FTPPUT) += ftpgetput.o +//kbuild:lib-$(CONFIG_WGET) += parse_pasv_epsv.o + +#include "libbb.h" + +int FAST_FUNC parse_pasv_epsv(char *buf) +{ +/* + * PASV command will not work for IPv6. RFC2428 describes + * IPv6-capable "extended PASV" - EPSV. + * + * "EPSV [protocol]" asks server to bind to and listen on a data port + * in specified protocol. Protocol is 1 for IPv4, 2 for IPv6. + * If not specified, defaults to "same as used for control connection". + * If server understood you, it should answer "229 (|||port|)" + * where "|" are literal pipe chars and "port" is ASCII decimal port#. + * + * There is also an IPv6-capable replacement for PORT (EPRT), + * but we don't need that. + * + * NB: PASV may still work for some servers even over IPv6. + * For example, vsftp happily answers + * "227 Entering Passive Mode (0,0,0,0,n,n)" and proceeds as usual. + */ + char *ptr; + int port; + + if (!ENABLE_FEATURE_IPV6 || buf[2] == '7' /* "227" */) { + /* Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage]" + * Server's IP is N1.N2.N3.N4 (we ignore it) + * Server's port for data connection is P1*256+P2 */ + ptr = strrchr(buf, ')'); + if (ptr) *ptr = '\0'; + + ptr = strrchr(buf, ','); + if (!ptr) return -1; + *ptr = '\0'; + port = xatou_range(ptr + 1, 0, 255); + + ptr = strrchr(buf, ','); + if (!ptr) return -1; + *ptr = '\0'; + port += xatou_range(ptr + 1, 0, 255) * 256; + } else { + /* Response is "229 garbage(|||P1|)" + * Server's port for data connection is P1 */ + ptr = strrchr(buf, '|'); + if (!ptr) return -1; + *ptr = '\0'; + + ptr = strrchr(buf, '|'); + if (!ptr) return -1; + *ptr = '\0'; + port = xatou_range(ptr + 1, 0, 65535); + } + + return port; +} diff --git a/networking/wget.c b/networking/wget.c index daa728a9d..7ca4bfb33 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -791,22 +791,17 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ /* * Entering passive mode */ + if (ENABLE_FEATURE_IPV6 && ftpcmd("EPSV", NULL, sfp) == 229) { + /* good */ + } else if (ftpcmd("PASV", NULL, sfp) != 227) { pasv_error: bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf)); } - // Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage] - // Server's IP is N1.N2.N3.N4 (we ignore it) - // Server's port for data connection is P1*256+P2 - str = strrchr(G.wget_buf, ')'); - if (str) str[0] = '\0'; - str = strrchr(G.wget_buf, ','); - if (!str) goto pasv_error; - port = xatou_range(str+1, 0, 255); - *str = '\0'; - str = strrchr(G.wget_buf, ','); - if (!str) goto pasv_error; - port += xatou_range(str+1, 0, 255) * 256; + port = parse_pasv_epsv(G.wget_buf); + if (port < 0) + goto pasv_error; + set_nport(&lsa->u.sa, htons(port)); *dfpp = open_socket(lsa); -- cgit v1.2.3-55-g6feb From 8d943175ceda0b5195a5956dadf7bd2c174df99f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 17:11:15 +0100 Subject: fix a thinko in parse_pasv_epsv.c Signed-off-by: Denys Vlasenko --- networking/parse_pasv_epsv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/parse_pasv_epsv.c b/networking/parse_pasv_epsv.c index f32087152..14f4d4258 100644 --- a/networking/parse_pasv_epsv.c +++ b/networking/parse_pasv_epsv.c @@ -5,8 +5,8 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -//kbuild:lib-$(CONFIG_FTPGET) += ftpgetput.o -//kbuild:lib-$(CONFIG_FTPPUT) += ftpgetput.o +//kbuild:lib-$(CONFIG_FTPGET) += parse_pasv_epsv.o +//kbuild:lib-$(CONFIG_FTPPUT) += parse_pasv_epsv.o //kbuild:lib-$(CONFIG_WGET) += parse_pasv_epsv.o #include "libbb.h" -- cgit v1.2.3-55-g6feb From 0a90960f446ebaf062244afbc626546b14689e0a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 17:39:45 +0100 Subject: ar: hopefully fix out-of-bounds read in get_header_ar() https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=882175 Signed-off-by: Denys Vlasenko --- archival/libarchive/get_header_ar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archival/libarchive/get_header_ar.c b/archival/libarchive/get_header_ar.c index 1809ec396..93e071c9f 100644 --- a/archival/libarchive/get_header_ar.c +++ b/archival/libarchive/get_header_ar.c @@ -83,7 +83,7 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle) */ ar_long_name_size = size; free(ar_long_names); - ar_long_names = xmalloc(size); + ar_long_names = xzalloc(size + 1); xread(archive_handle->src_fd, ar_long_names, size); archive_handle->offset += size; /* Return next header */ @@ -107,7 +107,7 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle) unsigned long_offset; /* The number after the '/' indicates the offset in the ar data section - * (saved in ar_long_names) that conatains the real filename */ + * (saved in ar_long_names) that contains the real filename */ long_offset = read_num(&ar.formatted.name[1], 10, sizeof(ar.formatted.name) - 1); if (long_offset >= ar_long_name_size) { -- cgit v1.2.3-55-g6feb From 5cdd120f0c6423a42fa2eec2311126142a9a49f0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 17:59:32 +0100 Subject: unzip: do not set directory mode to 0777 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=882177 Signed-off-by: Denys Vlasenko --- archival/unzip.c | 4 +++- libbb/make_directory.c | 16 ++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/archival/unzip.c b/archival/unzip.c index 653fdd10f..da4b2a544 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -336,7 +336,9 @@ static void unzip_create_leading_dirs(const char *fn) { /* Create all leading directories */ char *name = xstrdup(fn); - if (bb_make_directory(dirname(name), 0777, FILEUTILS_RECUR)) { + + /* mode of -1: set mode according to umask */ + if (bb_make_directory(dirname(name), -1, FILEUTILS_RECUR)) { xfunc_die(); /* bb_make_directory is noisy */ } free(name); diff --git a/libbb/make_directory.c b/libbb/make_directory.c index b9916d165..64736efbe 100644 --- a/libbb/make_directory.c +++ b/libbb/make_directory.c @@ -92,6 +92,7 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags) } } + //bb_error_msg("mkdir '%s'", path); if (mkdir(path, 0777) < 0) { /* If we failed for any other reason than the directory * already exists, output a diagnostic and return -1 */ @@ -118,13 +119,16 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags) /* Done. If necessary, update perms on the newly * created directory. Failure to update here _is_ * an error. */ - if ((mode != -1) && (chmod(path, mode) < 0)) { - fail_msg = "set permissions of"; - if (flags & FILEUTILS_IGNORE_CHMOD_ERR) { - flags = 0; - goto print_err; + if (mode != -1) { + //bb_error_msg("chmod 0%03lo mkdir '%s'", mode, path); + if (chmod(path, mode) < 0)) { + fail_msg = "set permissions of"; + if (flags & FILEUTILS_IGNORE_CHMOD_ERR) { + flags = 0; + goto print_err; + } + break; } - break; } goto ret0; } -- cgit v1.2.3-55-g6feb From 1267770a9db90b2a29553e682e3b63aa86b0b34d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 18:01:39 +0100 Subject: fix compile failure in previous commit Signed-off-by: Denys Vlasenko --- libbb/make_directory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/make_directory.c b/libbb/make_directory.c index 64736efbe..9b03bb8d0 100644 --- a/libbb/make_directory.c +++ b/libbb/make_directory.c @@ -121,7 +121,7 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags) * an error. */ if (mode != -1) { //bb_error_msg("chmod 0%03lo mkdir '%s'", mode, path); - if (chmod(path, mode) < 0)) { + if (chmod(path, mode) < 0) { fail_msg = "set permissions of"; if (flags & FILEUTILS_IGNORE_CHMOD_ERR) { flags = 0; -- cgit v1.2.3-55-g6feb From 2b7515722b929794f2f8563b80d9cea48f6b3304 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 6 Feb 2018 20:49:27 +0100 Subject: wget: attempt to negotiate encrypted data ftps stream ("PROT P") function old new delta wget_main 2382 2422 +40 Signed-off-by: Denys Vlasenko --- networking/wget.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 7ca4bfb33..633dabb57 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -806,9 +806,13 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ *dfpp = open_socket(lsa); - //For encrypted data, need to send "PROT P" and get "200 PROT now Private" response first - //Without it (or with "PROT C"), data is sent unencrypted - //spawn_ssl_client(target->host, fileno(*dfpp), /*flags*/ 0); +#if ENABLE_FEATURE_WGET_HTTPS + /* "PROT P" enables encryption of data stream. + * Without it (or with "PROT C"), data is sent unencrypted. + */ + if (ftpcmd("PROT P", NULL, sfp) == 200) + spawn_ssl_client(target->host, fileno(*dfpp), /*flags*/ 0); +#endif if (G.beg_range != 0) { sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); -- cgit v1.2.3-55-g6feb From 4cae044b436a842e0575c3b6787729fb436fd04c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Feb 2018 01:33:25 +0100 Subject: bzip2: expose tuning knob for faster/smaller code Signed-off-by: Denys Vlasenko --- archival/bzip2.c | 25 +++++++++++++++++++++++-- archival/libarchive/bz/blocksort.c | 8 ++++---- archival/libarchive/bz/bzlib_private.h | 2 +- archival/libarchive/bz/compress.c | 24 ++++++++++++------------ archival/libarchive/bz/huffman.c | 2 +- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/archival/bzip2.c b/archival/bzip2.c index fa906150f..357891ca3 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c @@ -19,6 +19,23 @@ //config: Unless you have a specific application which requires bzip2, you //config: should probably say N here. //config: +//config:config BZIP2_SMALL +//config: int "Trade bytes for speed (0:fast, 9:small)" +//config: default 8 # all "fast or small" options default to small +//config: range 0 9 +//config: depends on BZIP2 +//config: help +//config: Trade code size versus speed. +//config: Approximate values with gcc-6.3.0 "bzip -9" compressing +//config: linux-4.15.tar were: +//config: value time (sec) code size (386) +//config: 9 (smallest) 70.11 7687 +//config: 8 67.93 8091 +//config: 7 67.88 8405 +//config: 6 67.78 8624 +//config: 5 67.05 9427 +//config: 4-0 (fastest) 64.14 12083 +//config: //config:config FEATURE_BZIP2_DECOMPRESS //config: bool "Enable decompression" //config: default y @@ -48,7 +65,11 @@ #include "libbb.h" #include "bb_archive.h" -#define CONFIG_BZIP2_FAST 1 +#if CONFIG_BZIP2_SMALL >= 4 +#define BZIP2_SPEED (9 - CONFIG_BZIP2_SMALL) +#else +#define BZIP2_SPEED 5 +#endif /* Speed test: * Compiled with gcc 4.2.1, run on Athlon 64 1800 MHz (512K L2 cache). @@ -56,7 +77,7 @@ * (time to compress gcc-4.2.1.tar is 126.4% compared to bbox). * At SPEED 5 difference is 32.7%. * - * Test run of all CONFIG_BZIP2_FAST values on a 11Mb text file: + * Test run of all BZIP2_SPEED values on a 11Mb text file: * Size Time (3 runs) * 0: 10828 4.145 4.146 4.148 * 1: 11097 3.845 3.860 3.861 diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c index 0a9a597d0..92d6d8251 100644 --- a/archival/libarchive/bz/blocksort.c +++ b/archival/libarchive/bz/blocksort.c @@ -392,7 +392,7 @@ int mainGtU(EState* state, * but speeds up compression 10% overall */ -#if CONFIG_BZIP2_FAST >= 1 +#if BZIP2_SPEED >= 1 #define TIMES_8(code) \ code; code; code; code; \ @@ -506,7 +506,7 @@ void mainSimpleSort(EState* state, i++; /* 1.5% overall speedup, +290 bytes */ -#if CONFIG_BZIP2_FAST >= 3 +#if BZIP2_SPEED >= 3 /*-- copy 2 --*/ if (i > hi) break; v = ptr[i]; @@ -755,7 +755,7 @@ void mainSort(EState* state) j = block[0] << 8; i = nblock - 1; /* 3%, +300 bytes */ -#if CONFIG_BZIP2_FAST >= 2 +#if BZIP2_SPEED >= 2 for (; i >= 3; i -= 4) { quadrant[i] = 0; j = (j >> 8) | (((unsigned)block[i]) << 8); @@ -794,7 +794,7 @@ void mainSort(EState* state) unsigned s; s = block[0] << 8; i = nblock - 1; -#if CONFIG_BZIP2_FAST >= 2 +#if BZIP2_SPEED >= 2 for (; i >= 3; i -= 4) { s = (s >> 8) | (block[i] << 8); j = ftab[s] - 1; diff --git a/archival/libarchive/bz/bzlib_private.h b/archival/libarchive/bz/bzlib_private.h index ef75ef08a..ea0f29b7c 100644 --- a/archival/libarchive/bz/bzlib_private.h +++ b/archival/libarchive/bz/bzlib_private.h @@ -188,7 +188,7 @@ typedef struct EState { /* stack-saving measures: these can be local, but they are too big */ int32_t sendMTFValues__code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; int32_t sendMTFValues__rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; -#if CONFIG_BZIP2_FAST >= 5 +#if BZIP2_SPEED >= 5 /* second dimension: only 3 needed; 4 makes index calculations faster */ uint32_t sendMTFValues__len_pack[BZ_MAX_ALPHA_SIZE][4]; #endif diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 462740b6c..539ab927e 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -32,6 +32,12 @@ in the file LICENSE. /* #include "bzlib_private.h" */ +#if BZIP2_SPEED >= 5 +# define ALWAYS_INLINE_5 ALWAYS_INLINE +#else +# define ALWAYS_INLINE_5 /*nothing*/ +#endif + /*---------------------------------------------------*/ /*--- Bit stream I/O ---*/ /*---------------------------------------------------*/ @@ -60,9 +66,7 @@ void bsFinishWrite(EState* s) /*---------------------------------------------------*/ static /* Helps only on level 5, on other levels hurts. ? */ -#if CONFIG_BZIP2_FAST >= 5 -ALWAYS_INLINE -#endif +ALWAYS_INLINE_5 void bsW(EState* s, int32_t n, uint32_t v) { while (s->bsLive >= 8) { @@ -75,9 +79,7 @@ void bsW(EState* s, int32_t n, uint32_t v) } /* Same with n == 16: */ static -#if CONFIG_BZIP2_FAST >= 5 -ALWAYS_INLINE -#endif +ALWAYS_INLINE_5 void bsW16(EState* s, uint32_t v) { while (s->bsLive >= 8) { @@ -103,9 +105,7 @@ void bsW1_1(EState* s) s->bsLive += 1; } static -#if CONFIG_BZIP2_FAST >= 5 -ALWAYS_INLINE -#endif +ALWAYS_INLINE_5 void bsW1_0(EState* s) { /* need space for only 1 bit, no need for loop freeing > 8 bits */ @@ -394,7 +394,7 @@ void sendMTFValues(EState* s) s->rfreq[t][v] = 0; } -#if CONFIG_BZIP2_FAST >= 5 +#if BZIP2_SPEED >= 5 /* * Set up an auxiliary length table which is used to fast-track * the common case (nGroups == 6). @@ -427,7 +427,7 @@ void sendMTFValues(EState* s) */ for (t = 0; t < nGroups; t++) cost[t] = 0; -#if CONFIG_BZIP2_FAST >= 5 +#if BZIP2_SPEED >= 5 if (nGroups == 6 && 50 == ge-gs+1) { /*--- fast track the common case ---*/ register uint32_t cost01, cost23, cost45; @@ -483,7 +483,7 @@ void sendMTFValues(EState* s) * Increment the symbol frequencies for the selected table. */ /* 1% faster compress. +800 bytes */ -#if CONFIG_BZIP2_FAST >= 4 +#if BZIP2_SPEED >= 4 if (nGroups == 6 && 50 == ge-gs+1) { /*--- fast track the common case ---*/ #define BZ_ITUR(nn) s->rfreq[bt][mtfv[gs + (nn)]]++ diff --git a/archival/libarchive/bz/huffman.c b/archival/libarchive/bz/huffman.c index be5930e00..dc851cd3f 100644 --- a/archival/libarchive/bz/huffman.c +++ b/archival/libarchive/bz/huffman.c @@ -48,7 +48,7 @@ in the file LICENSE. /* 90 bytes, 0.3% of overall compress speed */ -#if CONFIG_BZIP2_FAST >= 1 +#if BZIP2_SPEED >= 1 /* macro works better than inline (gcc 4.2.1) */ #define DOWNHEAP1(heap, weight, Heap) \ -- cgit v1.2.3-55-g6feb From 2bd5b4e9a0442102ab937ed771b2c11142afb744 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Feb 2018 16:32:30 +0100 Subject: udhcp: do not setlinebuf(stdout), we don't print to stdout anymore Since bb_info_msg() was eliminated type of buffering on stdout is not important function old new delta udhcpd_main 1463 1451 -12 udhcpc_main 2735 2723 -12 setlinebuf 19 - -19 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 0/2 up/down: 0/-43) Total: -43 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 2 -- networking/udhcp/dhcpc.c | 2 -- networking/udhcp/dhcpd.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 07a8b11c1..35c99e89c 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1201,8 +1201,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) /* Make sure fd 0,1,2 are open */ bb_sanitize_stdio(); - /* Equivalent of doing a fflush after every \n */ - setlinebuf(stdout); /* Create pidfile */ write_pidfile(client_config.pidfile); /* Goes to stdout (unless NOMMU) and possibly syslog */ diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 385fc4998..35694fbe3 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1386,8 +1386,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* Make sure fd 0,1,2 are open */ bb_sanitize_stdio(); - /* Equivalent of doing a fflush after every \n */ - setlinebuf(stdout); /* Create pidfile */ write_pidfile(client_config.pidfile); /* Goes to stdout (unless NOMMU) and possibly syslog */ diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index ff7450739..093239536 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -856,8 +856,6 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) /* Make sure fd 0,1,2 are open */ bb_sanitize_stdio(); - /* Equivalent of doing a fflush after every \n */ - setlinebuf(stdout); /* Create pidfile */ write_pidfile(server_config.pidfile); -- cgit v1.2.3-55-g6feb From ab843e3244e98f92e16b9c9c1f06dbab87e97175 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Feb 2018 17:47:39 +0100 Subject: libbb: shrink wget/tftp progress indicator code for 32-bit function old new delta bb_progress_update 756 654 -102 Signed-off-by: Denys Vlasenko --- libbb/progress.c | 78 +++++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/libbb/progress.c b/libbb/progress.c index 64e6529ac..17272fd17 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -71,7 +71,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, uoff_t transferred, uoff_t totalsize) { - uoff_t beg_and_transferred; + unsigned beg_and_transferred; /* does not need uoff_t, see scaling code below */ unsigned since_last_update, elapsed; int notty; int kiloscale; @@ -102,33 +102,24 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, * without risking overflow: we guarantee 10 highest bits to be 0. * Introduced error is less than 1 / 2^12 ~= 0.025% */ - if (ULONG_MAX > 0xffffffff || sizeof(off_t) == 4 || sizeof(off_t) != 8) { - /* - * 64-bit CPU || small off_t: in either case, - * >> is cheap, single-word operation. - * ... || strange off_t: also use this code - * (it is safe, just suboptimal wrt code size), - * because 32/64 optimized one works only for 64-bit off_t. - */ - if (totalsize >= (1 << 22)) { - totalsize >>= 10; - beg_size >>= 10; - transferred >>= 10; - kiloscale = 1; - } - } else { - /* 32-bit CPU and 64-bit off_t. - * Use a 40-bit shift, it is easier to do on 32-bit CPU. - */ -/* ONE suppresses "warning: shift count >= width of type" */ -#define ONE (sizeof(off_t) > 4) - if (totalsize >= (uoff_t)(1ULL << 54*ONE)) { - totalsize = (uint32_t)(totalsize >> 32*ONE) >> 8; - beg_size = (uint32_t)(beg_size >> 32*ONE) >> 8; - transferred = (uint32_t)(transferred >> 32*ONE) >> 8; - kiloscale = 4; - } + while (totalsize >= (1 << 22)) { + totalsize >>= 10; + beg_size >>= 10; + transferred >>= 10; + kiloscale++; } + /* If they were huge, now they are scaled down to [4194303,4096] range. + * (N * totalsize) won't overflow 32 bits for N up to 1024. + * The downside is that files larger than 4194303 kbytes (>4GB) + * never show kbytes download size, they show "0M","1M"... right away + * since kiloscale is already >1. + */ +#if ULONG_MAX == 0xffffffff +/* 32-bit CPU, uoff_t arithmetic is complex on it, cast variables to narrower types */ +# define totalsize ((unsigned)totalsize) +# define beg_size ((unsigned)beg_size) +# define transferred ((unsigned)transferred) +#endif notty = !isatty(STDERR_FILENO); @@ -146,13 +137,18 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, barlength = get_terminal_width(2) - 49; if (barlength > 0) { - /* god bless gcc for variable arrays :) */ - char buf[barlength + 1]; - unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize; - memset(buf, ' ', barlength); - buf[barlength] = '\0'; - memset(buf, '*', stars); - fprintf(stderr, " |%s|", buf); + if (barlength > 999) + barlength = 999; + { + /* god bless gcc for variable arrays :) */ + char buf[barlength + 1]; + unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize; + /* can't overflow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ + memset(buf, ' ', barlength); + buf[barlength] = '\0'; + memset(buf, '*', stars); + fprintf(stderr, " |%s|", buf); + } } } @@ -184,16 +180,18 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, fprintf(stderr, " --:--:-- ETA"); } else { unsigned eta, secs, hours; + unsigned bytes; - totalsize -= beg_size; /* now it's "total to upload" */ + bytes = totalsize - beg_size; /* Estimated remaining time = - * estimated_sec_to_dl_totalsize_bytes - elapsed_sec = - * totalsize / average_bytes_sec_so_far - elapsed = - * totalsize / (transferred/elapsed) - elapsed = - * totalsize * elapsed / transferred - elapsed + * estimated_sec_to_dl_bytes - elapsed_sec = + * bytes / average_bytes_sec_so_far - elapsed = + * bytes / (transferred/elapsed) - elapsed = + * bytes * elapsed / transferred - elapsed */ - eta = totalsize * elapsed / transferred - elapsed; + eta = (unsigned long)bytes * elapsed / transferred - elapsed; + /* if 32bit, can overflow ^^^^^^^^^^, but this would only show bad ETA */ if (eta >= 1000*60*60) eta = 1000*60*60 - 1; secs = eta % 3600; -- cgit v1.2.3-55-g6feb From 47529d3f165c06bd0c3be751fdd4b743b4bddedb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Feb 2018 23:48:34 +0100 Subject: libbb: shrink wget/tftp progress indicator code a bit more This makes size display 5-char wide instead of 6-char, but now it's smarter (can show sizes in "12.3M" format). function old new delta bb_progress_update 654 622 -32 Signed-off-by: Denys Vlasenko --- libbb/progress.c | 56 +++++++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/libbb/progress.c b/libbb/progress.c index 17272fd17..f1d980d68 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -71,10 +71,9 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, uoff_t transferred, uoff_t totalsize) { - unsigned beg_and_transferred; /* does not need uoff_t, see scaling code below */ + char numbuf5[6]; /* 5 + 1 for NUL */ unsigned since_last_update, elapsed; int notty; - int kiloscale; //transferred = 1234; /* use for stall detection testing */ //totalsize = 0; /* use for unknown size download testing */ @@ -95,24 +94,22 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, return; } - kiloscale = 0; + /* Before we lose real, unscaled sizes, produce human-readable size string */ + smart_ulltoa5(beg_size + transferred, numbuf5, " kMGTPEZY")[0] = '\0'; + /* * Scale sizes down if they are close to overflowing. * This allows calculations like (100 * transferred / totalsize) * without risking overflow: we guarantee 10 highest bits to be 0. * Introduced error is less than 1 / 2^12 ~= 0.025% */ - while (totalsize >= (1 << 22)) { - totalsize >>= 10; - beg_size >>= 10; - transferred >>= 10; - kiloscale++; + while (totalsize >= (1 << 20)) { + totalsize >>= 8; + beg_size >>= 8; + transferred >>= 8; } - /* If they were huge, now they are scaled down to [4194303,4096] range. - * (N * totalsize) won't overflow 32 bits for N up to 1024. - * The downside is that files larger than 4194303 kbytes (>4GB) - * never show kbytes download size, they show "0M","1M"... right away - * since kiloscale is already >1. + /* If they were huge, now they are scaled down to [1048575,4096] range. + * (N * totalsize) won't overflow 32 bits for N up to 4096. */ #if ULONG_MAX == 0xffffffff /* 32-bit CPU, uoff_t arithmetic is complex on it, cast variables to narrower types */ @@ -124,19 +121,26 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, notty = !isatty(STDERR_FILENO); if (ENABLE_UNICODE_SUPPORT) - fprintf(stderr, "\r%s" + notty, p->curfile); + fprintf(stderr, "\r%s " + notty, p->curfile); else - fprintf(stderr, "\r%-20.20s" + notty, p->curfile); - - beg_and_transferred = beg_size + transferred; + fprintf(stderr, "\r%-20.20s " + notty, p->curfile); if (totalsize != 0) { int barlength; - unsigned ratio = 100 * beg_and_transferred / totalsize; - fprintf(stderr, "%4u%%", ratio); + unsigned beg_and_transferred; /* does not need uoff_t, see scaling code */ + unsigned ratio; + + beg_and_transferred = beg_size + transferred; + ratio = 100 * beg_and_transferred / totalsize; + /* can't overflow ^^^^^^^^^^^^^^^ */ + fprintf(stderr, "%3u%% ", ratio); - barlength = get_terminal_width(2) - 49; - if (barlength > 0) { + barlength = get_terminal_width(2) - 48; + /* + * Must reject barlength <= 0 (terminal too narrow). While at it, + * also reject: 1-char bar (useless), 2-char bar (ridiculous). + */ + if (barlength > 2) { if (barlength > 999) barlength = 999; { @@ -147,18 +151,12 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, memset(buf, ' ', barlength); buf[barlength] = '\0'; memset(buf, '*', stars); - fprintf(stderr, " |%s|", buf); + fprintf(stderr, "|%s| ", buf); } } } - while (beg_and_transferred >= 100000) { - beg_and_transferred >>= 10; - kiloscale++; - } - /* see http://en.wikipedia.org/wiki/Tera */ - fprintf(stderr, "%6u%c", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); -#define beg_and_transferred dont_use_beg_and_transferred_below() + fputs(numbuf5, stderr); /* "NNNNk" */ since_last_update = elapsed - p->last_change_sec; if ((unsigned)transferred != p->last_size) { -- cgit v1.2.3-55-g6feb From 237a900bc5654c865298b33a70dee60e2cd05dbc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Feb 2018 00:28:30 +0100 Subject: wget: do not ask for TLS-encrypted downloads on plain ftp:// URLs function old new delta wget_main 2422 2431 +9 Signed-off-by: Denys Vlasenko --- networking/wget.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 633dabb57..95b88ad37 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -807,11 +807,13 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ *dfpp = open_socket(lsa); #if ENABLE_FEATURE_WGET_HTTPS - /* "PROT P" enables encryption of data stream. - * Without it (or with "PROT C"), data is sent unencrypted. - */ - if (ftpcmd("PROT P", NULL, sfp) == 200) - spawn_ssl_client(target->host, fileno(*dfpp), /*flags*/ 0); + if (target->protocol == P_FTPS) { + /* "PROT P" enables encryption of data stream. + * Without it (or with "PROT C"), data is sent unencrypted. + */ + if (ftpcmd("PROT P", NULL, sfp) == 200) + spawn_ssl_client(target->host, fileno(*dfpp), /*flags*/ 0); + } #endif if (G.beg_range != 0) { -- cgit v1.2.3-55-g6feb From 68ae54243cacee6beeb69842c7d562435acd5ad1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Feb 2018 08:42:37 +0100 Subject: ip: fix crash in "ip neigh show" parse_rtattr() was using tb[] array without initializing it. Based on patch by Balaji Punnuru function old new delta parse_rtattr 85 107 +22 print_route 1630 1617 -13 print_linkinfo 807 794 -13 iproute_get 835 822 -13 print_rule 680 665 -15 ll_remember_index 263 248 -15 print_addrinfo 1223 1197 -26 ipaddr_list_or_flush 1253 1223 -30 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/7 up/down: 22/-125) Total: -103 bytes Signed-off-by: Denys Vlasenko --- networking/libiproute/ipaddress.c | 6 +++--- networking/libiproute/ipneigh.c | 10 ++++++---- networking/libiproute/iproute.c | 4 ++-- networking/libiproute/iprule.c | 2 +- networking/libiproute/libnetlink.c | 2 ++ networking/libiproute/ll_map.c | 2 +- networking/tc.c | 22 +++++++++++++--------- 7 files changed, 28 insertions(+), 20 deletions(-) diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 921ecf0d9..d7f888176 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c @@ -113,7 +113,7 @@ static NOINLINE int print_linkinfo(const struct nlmsghdr *n) if (G_filter.up && !(ifi->ifi_flags & IFF_UP)) return 0; - memset(tb, 0, sizeof(tb)); + //memset(tb, 0, sizeof(tb)); - parse_rtattr does this parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); if (tb[IFLA_IFNAME] == NULL) { bb_error_msg("nil ifname"); @@ -227,7 +227,7 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM, if (G_filter.flushb && n->nlmsg_type != RTM_NEWADDR) return 0; - memset(rta_tb, 0, sizeof(rta_tb)); + //memset(rta_tb, 0, sizeof(rta_tb)); - parse_rtattr does this parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); if (!rta_tb[IFA_LOCAL]) @@ -535,7 +535,7 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush) continue; if (G_filter.pfx.family || G_filter.label) { struct rtattr *tb[IFA_MAX+1]; - memset(tb, 0, sizeof(tb)); + //memset(tb, 0, sizeof(tb)); - parse_rtattr does this parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); if (!tb[IFA_LOCAL]) tb[IFA_LOCAL] = tb[IFA_ADDRESS]; diff --git a/networking/libiproute/ipneigh.c b/networking/libiproute/ipneigh.c index 1cd90d707..f572414e9 100644 --- a/networking/libiproute/ipneigh.c +++ b/networking/libiproute/ipneigh.c @@ -110,11 +110,13 @@ static int FAST_FUNC print_neigh(const struct sockaddr_nl *who UNUSED_PARAM, return 0; if (G_filter.index && G_filter.index != r->ndm_ifindex) return 0; - if (!(G_filter.state&r->ndm_state) && - !(r->ndm_flags & NTF_PROXY) && - (r->ndm_state || !(G_filter.state & 0x100)) && - (r->ndm_family != AF_DECnet)) + if (!(G_filter.state&r->ndm_state) + && !(r->ndm_flags & NTF_PROXY) + && (r->ndm_state || !(G_filter.state & 0x100)) + && (r->ndm_family != AF_DECnet) + ) { return 0; + } parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index 95dafe183..2a8610ea6 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c @@ -83,7 +83,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, if (len < 0) bb_error_msg_and_die("wrong nlmsg len %d", len); - memset(tb, 0, sizeof(tb)); + //memset(tb, 0, sizeof(tb)); - parse_rtattr does this parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); #if HAVE_RTA_TABLE @@ -1081,7 +1081,7 @@ static int iproute_get(char **argv) bb_error_msg_and_die("wrong len %d", len); } - memset(tb, 0, sizeof(tb)); + //memset(tb, 0, sizeof(tb)); - parse_rtattr does this parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); if (tb[RTA_PREFSRC]) { diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c index 53b11e16c..0ce0dfeef 100644 --- a/networking/libiproute/iprule.c +++ b/networking/libiproute/iprule.c @@ -63,7 +63,7 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM, if (len < 0) return -1; - memset(tb, 0, sizeof(tb)); + //memset(tb, 0, sizeof(tb)); - parse_rtattr does this parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); if (r->rtm_family == AF_INET) diff --git a/networking/libiproute/libnetlink.c b/networking/libiproute/libnetlink.c index 3f0f70326..f08d862d0 100644 --- a/networking/libiproute/libnetlink.c +++ b/networking/libiproute/libnetlink.c @@ -401,6 +401,8 @@ int FAST_FUNC rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data void FAST_FUNC parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) { + memset(tb, 0, (max + 1) * sizeof(tb[0])); + while (RTA_OK(rta, len)) { if (rta->rta_type <= max) { tb[rta->rta_type] = rta; diff --git a/networking/libiproute/ll_map.c b/networking/libiproute/ll_map.c index be88a04e8..66401da77 100644 --- a/networking/libiproute/ll_map.c +++ b/networking/libiproute/ll_map.c @@ -51,7 +51,7 @@ int FAST_FUNC ll_remember_index(const struct sockaddr_nl *who UNUSED_PARAM, if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi))) return -1; - memset(tb, 0, sizeof(tb)); + //memset(tb, 0, sizeof(tb)); - parse_rtattr does this parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); if (tb[IFLA_IFNAME] == NULL) return 0; diff --git a/networking/tc.c b/networking/tc.c index 4e375a066..4fa3e47bf 100644 --- a/networking/tc.c +++ b/networking/tc.c @@ -66,17 +66,21 @@ enum /* nullifies tb on error */ #define __parse_rtattr_nested_compat(tb, max, rta, len) \ - ({if ((RTA_PAYLOAD(rta) >= len) && \ - (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr))) { \ - rta = RTA_DATA(rta) + RTA_ALIGN(len); \ - parse_rtattr_nested(tb, max, rta); \ - } else \ - memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); \ - }) +({ \ + if ((RTA_PAYLOAD(rta) >= len) \ + && (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) \ + ) { \ + rta = RTA_DATA(rta) + RTA_ALIGN(len); \ + parse_rtattr_nested(tb, max, rta); \ + } else \ + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); \ +}) #define parse_rtattr_nested_compat(tb, max, rta, data, len) \ - ({data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \ - __parse_rtattr_nested_compat(tb, max, rta, len); }) +({ \ + data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \ + __parse_rtattr_nested_compat(tb, max, rta, len); \ +}) #define show_details (0) /* not implemented. Does anyone need it? */ #define use_iec (0) /* not currently documented in the upstream manpage */ -- cgit v1.2.3-55-g6feb From 5807e18f0c4f6fc247103830affcab73ca1ffa37 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Feb 2018 19:19:04 +0100 Subject: hush: LINENO fix Script triggering the bug: t=0 echo "at line ${LINENO}" while [ ${t} -lt 10 ]; do echo "at line ${LINENO}" # LINENO was 3 instead of 4 here t=$((t+1)) done function old new delta parse_stream 2754 2788 +34 done_word 711 738 +27 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 61/0) Total: 61 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 101 +++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 585c51bd5..f2ffcf54d 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -120,6 +120,11 @@ //config: help //config: Enable {abc,def} extension. //config: +//config:config HUSH_LINENO_VAR +//config: bool "$LINENO variable" +//config: default y +//config: depends on HUSH_BASH_COMPAT +//config: //config:config HUSH_BASH_SOURCE_CURDIR //config: bool "'source' and '.' builtins search current directory after $PATH" //config: default n # do not encourage non-standard behavior @@ -368,7 +373,6 @@ #define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT #define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT #define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT -#define BASH_LINENO_VAR ENABLE_HUSH_BASH_COMPAT #define BASH_TEST2 (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST) #define BASH_READ_D ENABLE_HUSH_BASH_COMPAT @@ -620,7 +624,7 @@ typedef enum redir_type { struct command { pid_t pid; /* 0 if exited */ int assignment_cnt; /* how many argv[i] are assignments? */ -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR unsigned lineno; #endif smallint cmd_type; /* CMD_xxx */ @@ -942,7 +946,7 @@ struct globals { unsigned handled_SIGCHLD; smallint we_have_children; #endif -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR unsigned lineno; char *lineno_var; #endif @@ -2152,7 +2156,7 @@ static int set_local_var(char *str, unsigned flags) } name_len = eq_sign - str + 1; /* including '=' */ -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR if (G.lineno_var) { if (name_len == 7 && strncmp("LINENO", str, 6) == 0) G.lineno_var = NULL; @@ -2285,7 +2289,7 @@ static int unset_local_var_len(const char *name, int name_len) if (name_len == 6 && strncmp(name, "OPTIND", 6) == 0) G.getopt_count = 0; #endif -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR if (name_len == 6 && G.lineno_var && strncmp(name, "LINENO", 6) == 0) G.lineno_var = NULL; #endif @@ -2608,9 +2612,11 @@ static int i_getch(struct in_str *i) out: debug_printf("file_get: got '%c' %d\n", ch, ch); i->last_char = ch; -#if BASH_LINENO_VAR - if (ch == '\n') +#if ENABLE_HUSH_LINENO_VAR + if (ch == '\n') { G.lineno++; + debug_printf_parse("G.lineno++ = %u\n", G.lineno); + } #endif return ch; } @@ -3412,8 +3418,13 @@ static void debug_print_tree(struct pipe *pi, int lvl) pin = 0; while (pi) { - fdprintf(2, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", - pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); + fdprintf(2, "%*spipe %d %sres_word=%s followup=%d %s\n", + lvl*2, "", + pin, + (IF_HAS_KEYWORDS(pi->pi_inverted ? "! " :) ""), + RES[pi->res_word], + pi->followup, PIPE[pi->followup] + ); prn = 0; while (prn < pi->num_cmds) { struct command *command = &pi->cmds[prn]; @@ -3422,6 +3433,9 @@ static void debug_print_tree(struct pipe *pi, int lvl) fdprintf(2, "%*s cmd %d assignment_cnt:%d", lvl*2, "", prn, command->assignment_cnt); +#if ENABLE_HUSH_LINENO_VAR + fdprintf(2, " LINENO:%u", command->lineno); +#endif if (command->group) { fdprintf(2, " group %s: (argv=%p)%s%s\n", CMDTYPE[command->cmd_type], @@ -3494,8 +3508,9 @@ static int done_command(struct parse_context *ctx) ctx->command = command = &pi->cmds[pi->num_cmds]; clear_and_ret: memset(command, 0, sizeof(*command)); -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR command->lineno = G.lineno; + debug_printf_parse("command->lineno = G.lineno (%u)\n", G.lineno); #endif return pi->num_cmds; /* used only for 0/nonzero check */ } @@ -3684,9 +3699,9 @@ static const struct reserved_combo* match_reserved_word(o_string *word) } return NULL; } -/* Return 0: not a keyword, 1: keyword +/* Return NULL: not a keyword, else: keyword */ -static int reserved_word(o_string *word, struct parse_context *ctx) +static const struct reserved_combo* reserved_word(o_string *word, struct parse_context *ctx) { # if ENABLE_HUSH_CASE static const struct reserved_combo reserved_match = { @@ -3699,7 +3714,7 @@ static int reserved_word(o_string *word, struct parse_context *ctx) return 0; r = match_reserved_word(word); if (!r) - return 0; + return r; /* NULL */ debug_printf("found reserved word %s, res %d\n", r->literal, r->res); # if ENABLE_HUSH_CASE @@ -3714,7 +3729,7 @@ static int reserved_word(o_string *word, struct parse_context *ctx) ctx->ctx_res_w = RES_SNTX; } ctx->ctx_inverted = 1; - return 1; + return r; } if (r->flag & FLAG_START) { struct parse_context *old; @@ -3726,7 +3741,7 @@ static int reserved_word(o_string *word, struct parse_context *ctx) } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) { syntax_error_at(word->data); ctx->ctx_res_w = RES_SNTX; - return 1; + return r; } else { /* "{...} fi" is ok. "{...} if" is not * Example: @@ -3776,7 +3791,7 @@ static int reserved_word(o_string *word, struct parse_context *ctx) *ctx = *old; /* physical copy */ free(old); } - return 1; + return r; } #endif /* HAS_KEYWORDS */ @@ -3842,9 +3857,26 @@ static int done_word(o_string *word, struct parse_context *ctx) && ctx->ctx_res_w != RES_CASE # endif ) { - int reserved = reserved_word(word, ctx); - debug_printf_parse("checking for reserved-ness: %d\n", reserved); + const struct reserved_combo *reserved; + reserved = reserved_word(word, ctx); + debug_printf_parse("checking for reserved-ness: %d\n", !!reserved); if (reserved) { +# if ENABLE_HUSH_LINENO_VAR +/* Case: + * "while ...; do + * cmd ..." + * If we don't close the pipe _now_, immediately after "do", lineno logic + * sees "cmd" as starting at "do" - i.e., at the previous line. + */ + if (0 + IF_HUSH_IF(|| reserved->res == RES_THEN) + IF_HUSH_IF(|| reserved->res == RES_ELIF) + IF_HUSH_IF(|| reserved->res == RES_ELSE) + IF_HUSH_LOOPS(|| reserved->res == RES_DO) + ) { + done_pipe(ctx, PIPE_SEQ); + } +# endif o_reset_to_empty_unquoted(word); debug_printf_parse("done_word return %d\n", (ctx->ctx_res_w == RES_SNTX)); @@ -4979,6 +5011,27 @@ static struct pipe *parse_stream(char **pstring, } if (is_blank) { +#if ENABLE_HUSH_LINENO_VAR +/* Case: + * "while ...; do + * cmd ..." + * would think that "cmd" starts in - + * i.e., at the previous line. + * We need to skip all whitespace before newlines. + */ + if (ch != '\n') { + /* It was whitespace, but not a newline. + * Eat all whitespace. + */ + for (;;) { + next = i_peek(input); + if (next != ' ' && next != '\t' && next != '\n') + break; /* next char is not ws */ + ch = i_getch(input); + } + /* ch == last eaten whitespace char */ + } +#endif if (done_word(&dest, &ctx)) { goto parse_error; } @@ -6573,7 +6626,7 @@ static void parse_and_run_string(const char *s) static void parse_and_run_file(FILE *f) { struct in_str input; -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR unsigned sv; sv = G.lineno; @@ -6581,7 +6634,7 @@ static void parse_and_run_file(FILE *f) #endif setup_file_in_str(&input, f); parse_and_run_stream(&input, ';'); -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR G.lineno = sv; #endif } @@ -8130,7 +8183,7 @@ static NOINLINE int run_pipe(struct pipe *pi) char **new_env = NULL; struct variable *old_vars = NULL; -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR if (G.lineno_var) strcpy(G.lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); #endif @@ -8339,7 +8392,7 @@ static NOINLINE int run_pipe(struct pipe *pi) if (cmd_no < pi->num_cmds) xpiped_pair(pipefds); -#if BASH_LINENO_VAR +#if ENABLE_HUSH_LINENO_VAR if (G.lineno_var) strcpy(G.lineno_var + sizeof("LINENO=")-1, utoa(command->lineno)); #endif @@ -9057,8 +9110,8 @@ int hush_main(int argc, char **argv) */ #endif -#if BASH_LINENO_VAR - if (BASH_LINENO_VAR) { +#if ENABLE_HUSH_LINENO_VAR + if (ENABLE_HUSH_LINENO_VAR) { char *p = xasprintf("LINENO=%*s", (int)(sizeof(int)*3), ""); set_local_var(p, /*flags*/ 0); G.lineno_var = p; /* can't assign before set_local_var("LINENO=...") */ -- cgit v1.2.3-55-g6feb From f786901c4bc2e724221e5c07208c3cd7913cb98c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 8 Feb 2018 19:39:42 +0100 Subject: hush: probably fixing a bug in last LINENO fix I don't have an example of mishandled script, but the logic looked wrong: it could sometimes treat newlines as if they are spaces. function old new delta parse_stream 2788 2787 -1 Signed-off-by: Denys Vlasenko --- shell/hush.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index f2ffcf54d..8f1017e3c 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5019,18 +5019,13 @@ static struct pipe *parse_stream(char **pstring, * i.e., at the previous line. * We need to skip all whitespace before newlines. */ - if (ch != '\n') { - /* It was whitespace, but not a newline. - * Eat all whitespace. - */ - for (;;) { - next = i_peek(input); - if (next != ' ' && next != '\t' && next != '\n') - break; /* next char is not ws */ - ch = i_getch(input); - } - /* ch == last eaten whitespace char */ + while (ch != '\n') { + next = i_peek(input); + if (next != ' ' && next != '\t' && next != '\n') + break; /* next char is not ws */ + ch = i_getch(input); } + /* ch == last eaten whitespace char */ #endif if (done_word(&dest, &ctx)) { goto parse_error; -- cgit v1.2.3-55-g6feb From 3f52d13647f0660aeb9eb191ddb221f62c9df069 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 9 Feb 2018 20:21:01 +0100 Subject: svlogd: improve --help text function old new delta packed_usage 32278 32367 +89 Signed-off-by: Denys Vlasenko --- runit/svlogd.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/runit/svlogd.c b/runit/svlogd.c index dfd7e38a0..412290ca9 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c @@ -140,15 +140,22 @@ log message, you can use a pattern like this instead //usage:#define svlogd_full_usage "\n\n" //usage: "Read log data from stdin and write to rotated log files in DIRs" //usage: "\n" +//usage: "\n""-r C Replace non-printable characters with C" +//usage: "\n""-R CHARS Also replace CHARS with C (default _)" +//usage: "\n""-t Timestamp with @tai64n" +//usage: "\n""-tt Timestamp with yyyy-mm-dd_hh:mm:ss.sssss" +//usage: "\n""-ttt Timestamp with yyyy-mm-ddThh:mm:ss.sssss" +//usage: "\n""-v Verbose" +//usage: "\n" //usage: "\n""DIR/config file modifies behavior:" -//usage: "\n""sSIZE - when to rotate logs" +//usage: "\n""sSIZE - when to rotate logs (default 1000000, 0 disables)" //usage: "\n""nNUM - number of files to retain" -/*usage: "\n""NNUM - min number files to retain" - confusing */ -/*usage: "\n""tSEC - rotate file if it get SEC seconds old" - confusing */ +///////: "\n""NNUM - min number files to retain" - confusing +///////: "\n""tSEC - rotate file if it get SEC seconds old" - confusing //usage: "\n""!PROG - process rotated log with PROG" -/*usage: "\n""uIPADDR - send log over UDP" - unsupported */ -/*usage: "\n""UIPADDR - send log over UDP and DONT log" - unsupported */ -/*usage: "\n""pPFX - prefix each line with PFX" - unsupported */ +///////: "\n""uIPADDR - send log over UDP" - unsupported +///////: "\n""UIPADDR - send log over UDP and DONT log" - unsupported +///////: "\n""pPFX - prefix each line with PFX" - unsupported //usage: "\n""+,-PATTERN - (de)select line for logging" //usage: "\n""E,ePATTERN - (de)select line for stderr" -- cgit v1.2.3-55-g6feb From f5d50fbd2f1814b9f4dbaeec6818d66989a43a5c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Feb 2018 13:27:54 +0100 Subject: arping: code shrink Do not clear extra bits on option_mask32, it's not necessary. Move DAD bit to 2, this makes exit logic simpler. function old new delta arping_main 1655 1629 -26 Signed-off-by: Denys Vlasenko --- networking/arping.c | 56 ++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/networking/arping.c b/networking/arping.c index f9967d81e..fd2f52cdb 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -11,7 +11,6 @@ //config: select PLATFORM_LINUX //config: help //config: Ping hosts by ARP packets. -//config: //applet:IF_ARPING(APPLET(arping, BB_DIR_USR_SBIN, BB_SUID_DROP)) @@ -45,14 +44,23 @@ #define MONOTONIC_US() ((unsigned)monotonic_us()) enum { - DAD = 1, - UNSOLICITED = 2, - ADVERT = 4, - QUIET = 8, - QUIT_ON_REPLY = 16, - BCAST_ONLY = 32, - UNICASTING = 64 + UNSOLICITED = 1 << 0, + DAD = 1 << 1, + ADVERT = 1 << 2, + QUIET = 1 << 3, + QUIT_ON_REPLY = 1 << 4, + BCAST_ONLY = 1 << 5, + UNICASTING = 1 << 6, + TIMEOUT = 1 << 7, }; +#define GETOPT32(str_timeout, device, source) \ + getopt32(argv, "^" \ + "UDAqfbc:+w:I:s:" \ + /* Dad also sets quit_on_reply, */ \ + /* Advert also sets unsolicited: */ \ + "\0" "=1:Df:AU", \ + &count, &str_timeout, &device, &source \ + ); struct globals { struct in_addr src; @@ -92,21 +100,15 @@ struct globals { count = -1; \ } while (0) -// If GNUisms are not available... -//static void *mempcpy(void *_dst, const void *_src, int n) -//{ -// memcpy(_dst, _src, n); -// return (char*)_dst + n; -//} - static int send_pack(struct in_addr *src_addr, - struct in_addr *dst_addr, struct sockaddr_ll *ME, + struct in_addr *dst_addr, + struct sockaddr_ll *ME, struct sockaddr_ll *HE) { int err; unsigned char buf[256]; struct arphdr *ah = (struct arphdr *) buf; - unsigned char *p = (unsigned char *) (ah + 1); + unsigned char *p; ah->ar_hrd = htons(ARPHRD_ETHER); ah->ar_pro = htons(ETH_P_IP); @@ -114,6 +116,7 @@ static int send_pack(struct in_addr *src_addr, ah->ar_pln = 4; ah->ar_op = option_mask32 & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); + p = (unsigned char *) (ah + 1); p = mempcpy(p, &ME->sll_addr, ah->ar_hln); p = mempcpy(p, src_addr, 4); @@ -303,16 +306,9 @@ int arping_main(int argc UNUSED_PARAM, char **argv) unsigned opt; char *str_timeout; - /* Dad also sets quit_on_reply. - * Advert also sets unsolicited. - */ - opt = getopt32(argv, "^" "DUAqfbc:+w:I:s:" "\0" "=1:Df:AU", - &count, &str_timeout, &device, &source - ); - if (opt & 0x80) /* -w: timeout */ + opt = GETOPT32(str_timeout, device, source); + if (opt & TIMEOUT) timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000; - //if (opt & 0x200) /* -s: source */ - option_mask32 &= 0x3f; /* set respective flags */ } target = argv[optind]; @@ -336,7 +332,9 @@ int arping_main(int argc UNUSED_PARAM, char **argv) } if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { bb_error_msg(err_str, "is not ARPable"); - return (option_mask32 & DAD ? 0 : 2); + BUILD_BUG_ON(DAD != 2); + /* exit 0 if DAD, else exit 2 */ + return (~option_mask32 & DAD); } } @@ -401,7 +399,9 @@ int arping_main(int argc UNUSED_PARAM, char **argv) } if (me.sll_halen == 0) { bb_error_msg(err_str, "is not ARPable (no ll address)"); - return (option_mask32 & DAD ? 0 : 2); + BUILD_BUG_ON(DAD != 2); + /* exit 0 if DAD, else exit 2 */ + return (~option_mask32 & DAD); } he = me; memset(he.sll_addr, -1, he.sll_halen); -- cgit v1.2.3-55-g6feb From a3ec3bd0f85befdc95657a249b4cc789667440d7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Feb 2018 13:37:07 +0100 Subject: arping: change a few message strings to be closer to iputils arping ARPING 192.168.1.1 from 192.168.1.172 wlan0 Unicast reply from 192.168.1.1 [F4:F2:6D:52:A8:DE] 1.672ms Sent 1 probes (1 broadcast(s)) Received 1 response(s) ARPING 192.168.1.1 from 192.168.1.172 wlan0 Unicast reply from 192.168.1.1 [f4:f2:6d:52:a8:de] 1.152ms Sent 1 probe(s) (1 broadcast(s)) Received 1 response(s) (0 request(s), 0 broadcast(s)) function old new delta finish 120 100 -20 Signed-off-by: Denys Vlasenko --- networking/arping.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/networking/arping.c b/networking/arping.c index fd2f52cdb..898c3054e 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -142,10 +142,10 @@ static void finish(void) { if (!(option_mask32 & QUIET)) { printf("Sent %u probe(s) (%u broadcast(s))\n" - "Received %u repl%s" + "Received %u response(s)" " (%u request(s), %u broadcast(s))\n", sent, brd_sent, - received, (received == 1) ? "ies" : "y", + received, req_recv, brd_recv); } if (option_mask32 & DAD) @@ -245,6 +245,7 @@ static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) if (!(option_mask32 & QUIET)) { int s_printed = 0; +//TODO: arping from iputils-s20160308 print upprcase hex in MAC, follow them? printf("%scast re%s from %s [%02x:%02x:%02x:%02x:%02x:%02x]", FROM->sll_pkttype == PACKET_HOST ? "Uni" : "Broad", ah->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest", @@ -252,14 +253,14 @@ static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) p[0], p[1], p[2], p[3], p[4], p[5] ); if (dst_ip.s_addr != src.s_addr) { - printf("for %s ", inet_ntoa(dst_ip)); + printf("for %s", inet_ntoa(dst_ip)); s_printed = 1; } if (memcmp(p + ah->ar_hln + 4, me.sll_addr, ah->ar_hln)) { unsigned char *pp = p + ah->ar_hln + 4; if (!s_printed) - printf("for "); - printf("[%02x:%02x:%02x:%02x:%02x:%02x]", + printf(" for"); + printf(" [%02x:%02x:%02x:%02x:%02x:%02x]", pp[0], pp[1], pp[2], pp[3], pp[4], pp[5] ); } @@ -408,8 +409,8 @@ int arping_main(int argc UNUSED_PARAM, char **argv) if (!(option_mask32 & QUIET)) { /* inet_ntoa uses static storage, can't use in same printf */ - printf("ARPING to %s", inet_ntoa(dst)); - printf(" from %s via %s\n", inet_ntoa(src), device); + printf("ARPING %s", inet_ntoa(dst)); + printf(" from %s %s\n", inet_ntoa(src), device); } signal_SA_RESTART_empty_mask(SIGINT, (void (*)(int))finish); -- cgit v1.2.3-55-g6feb From e015d0659fd3039c321b179190834c7e5909522a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Feb 2018 13:48:52 +0100 Subject: arping: fix the case when inherited signal mask masks out ALRM function old new delta arping_main 1629 1635 +6 Signed-off-by: Denys Vlasenko --- networking/arping.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/networking/arping.c b/networking/arping.c index 898c3054e..97e9e680a 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -413,28 +413,37 @@ int arping_main(int argc UNUSED_PARAM, char **argv) printf(" from %s %s\n", inet_ntoa(src), device); } + packet = xmalloc(4096); + signal_SA_RESTART_empty_mask(SIGINT, (void (*)(int))finish); signal_SA_RESTART_empty_mask(SIGALRM, (void (*)(int))catcher); + /* Send the first packet, arm ALRM */ catcher(); - packet = xmalloc(4096); while (1) { - sigset_t sset, osset; + sigset_t sset; struct sockaddr_ll from; socklen_t alen = sizeof(from); int cc; + sigemptyset(&sset); + sigaddset(&sset, SIGALRM); + sigaddset(&sset, SIGINT); + /* Unblock SIGALRM so that the previously called alarm() + * can prevent recvfrom from blocking forever in case the + * inherited procmask is blocking SIGALRM. + */ + sigprocmask(SIG_UNBLOCK, &sset, NULL); + cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen); + + /* Don't allow SIGALRMs while we process the reply */ + sigprocmask(SIG_BLOCK, &sset, NULL); if (cc < 0) { bb_perror_msg("recvfrom"); continue; } - sigemptyset(&sset); - sigaddset(&sset, SIGALRM); - sigaddset(&sset, SIGINT); - sigprocmask(SIG_BLOCK, &sset, &osset); recv_pack(packet, cc, &from); - sigprocmask(SIG_SETMASK, &osset, NULL); } } -- cgit v1.2.3-55-g6feb From d3162773d5c722cc1f5c5b1ea5171c8d3c208135 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Feb 2018 14:35:05 +0100 Subject: arping: move packet buffer, sigset and struct ifreq to malloced "globals" This way, we can zero them all in one go. We do malloc() anyway, thus nothing is lost by mallocing "globals" function old new delta arping_main 1683 1686 +3 finish 100 86 -14 catcher 350 310 -40 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 3/-54) Total: -51 bytes Signed-off-by: Denys Vlasenko --- networking/arping.c | 75 ++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/networking/arping.c b/networking/arping.c index 97e9e680a..a16f04b9f 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -79,8 +79,11 @@ struct globals { unsigned received; unsigned brd_recv; unsigned req_recv; + + struct ifreq ifr; + sigset_t sset; + unsigned char packet[4096]; } FIX_ALIASING; -#define G (*(struct globals*)bb_common_bufsiz1) #define src (G.src ) #define dst (G.dst ) #define me (G.me ) @@ -95,8 +98,11 @@ struct globals { #define received (G.received ) #define brd_recv (G.brd_recv ) #define req_recv (G.req_recv ) +//#define G (*(struct globals*)bb_common_bufsiz1) +#define G (*ptr_to_globals) #define INIT_G() do { \ - setup_common_bufsiz(); \ + /*setup_common_bufsiz();*/ \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ count = -1; \ } while (0) @@ -183,15 +189,10 @@ static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) struct arphdr *ah = (struct arphdr *) buf; unsigned char *p = (unsigned char *) (ah + 1); struct in_addr src_ip, dst_ip; + /* moves below assume in_addr is 4 bytes big, ensure that */ - struct BUG_in_addr_must_be_4 { - char BUG_in_addr_must_be_4[ - sizeof(struct in_addr) == 4 ? 1 : -1 - ]; - char BUG_s_addr_must_be_4[ - sizeof(src_ip.s_addr) == 4 ? 1 : -1 - ]; - }; + BUILD_BUG_ON(sizeof(struct in_addr) != 4); + BUILD_BUG_ON(sizeof(src_ip.s_addr) != 4); /* Filter out wild packets */ if (FROM->sll_pkttype != PACKET_HOST @@ -212,8 +213,10 @@ static void recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) if (ah->ar_pro != htons(ETH_P_IP) || (ah->ar_pln != 4) || (ah->ar_hln != me.sll_halen) - || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln)))) + || (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln))) + ) { return; + } move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln); move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln); @@ -292,7 +295,6 @@ int arping_main(int argc UNUSED_PARAM, char **argv) const char *device = "eth0"; char *source = NULL; char *target; - unsigned char *packet; char *err_str; INIT_G(); @@ -316,27 +318,21 @@ int arping_main(int argc UNUSED_PARAM, char **argv) err_str = xasprintf("interface %s %%s", device); xfunc_error_retval = 2; - { - struct ifreq ifr; - - memset(&ifr, 0, sizeof(ifr)); - strncpy_IFNAMSIZ(ifr.ifr_name, device); - /* We use ifr.ifr_name in error msg so that problem - * with truncated name will be visible */ - ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found"); - me.sll_ifindex = ifr.ifr_ifindex; + /*memset(&G.ifr, 0, sizeof(G.ifr)); - zeroed by INIT_G */ + strncpy_IFNAMSIZ(G.ifr.ifr_name, device); + ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &G.ifr, err_str, "not found"); + me.sll_ifindex = G.ifr.ifr_ifindex; - xioctl(sock_fd, SIOCGIFFLAGS, (char *) &ifr); + xioctl(sock_fd, SIOCGIFFLAGS, (char *) &G.ifr); - if (!(ifr.ifr_flags & IFF_UP)) { - bb_error_msg_and_die(err_str, "is down"); - } - if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { - bb_error_msg(err_str, "is not ARPable"); - BUILD_BUG_ON(DAD != 2); - /* exit 0 if DAD, else exit 2 */ - return (~option_mask32 & DAD); - } + if (!(G.ifr.ifr_flags & IFF_UP)) { + bb_error_msg_and_die(err_str, "is down"); + } + if (G.ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { + bb_error_msg(err_str, "is not ARPable"); + BUILD_BUG_ON(DAD != 2); + /* exit 0 if DAD, else exit 2 */ + return (~option_mask32 & DAD); } /* if (!inet_aton(target, &dst)) - not needed */ { @@ -413,8 +409,9 @@ int arping_main(int argc UNUSED_PARAM, char **argv) printf(" from %s %s\n", inet_ntoa(src), device); } - packet = xmalloc(4096); - + /*sigemptyset(&G.sset); - zeroed by INIT_G */ + sigaddset(&G.sset, SIGALRM); + sigaddset(&G.sset, SIGINT); signal_SA_RESTART_empty_mask(SIGINT, (void (*)(int))finish); signal_SA_RESTART_empty_mask(SIGALRM, (void (*)(int))catcher); @@ -422,28 +419,24 @@ int arping_main(int argc UNUSED_PARAM, char **argv) catcher(); while (1) { - sigset_t sset; struct sockaddr_ll from; socklen_t alen = sizeof(from); int cc; - sigemptyset(&sset); - sigaddset(&sset, SIGALRM); - sigaddset(&sset, SIGINT); /* Unblock SIGALRM so that the previously called alarm() * can prevent recvfrom from blocking forever in case the * inherited procmask is blocking SIGALRM. */ - sigprocmask(SIG_UNBLOCK, &sset, NULL); + sigprocmask(SIG_UNBLOCK, &G.sset, NULL); - cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen); + cc = recvfrom(sock_fd, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &alen); /* Don't allow SIGALRMs while we process the reply */ - sigprocmask(SIG_BLOCK, &sset, NULL); + sigprocmask(SIG_BLOCK, &G.sset, NULL); if (cc < 0) { bb_perror_msg("recvfrom"); continue; } - recv_pack(packet, cc, &from); + recv_pack(G.packet, cc, &from); } } -- cgit v1.2.3-55-g6feb From ba3b9dbf065438402d89655d7baefb0ccc6f0663 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Feb 2018 14:55:46 +0100 Subject: libbb: introduce and use bb_getsockname() function old new delta bb_getsockname - 18 +18 xrtnl_open 88 83 -5 do_iplink 1216 1209 -7 arping_main 1686 1668 -18 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/3 up/down: 18/-30) Total: -12 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/bb_getsockname.c | 19 +++++++++++++++++++ networking/arping.c | 15 +++++---------- networking/inetd.c | 5 ++--- networking/libiproute/iplink.c | 4 +--- networking/libiproute/libnetlink.c | 5 +---- 6 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 libbb/bb_getsockname.c diff --git a/include/libbb.h b/include/libbb.h index e2bedaf41..2c34859a2 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -636,6 +636,7 @@ void setsockopt_reuseaddr(int fd) FAST_FUNC; /* On Linux this never fails. */ int setsockopt_keepalive(int fd) FAST_FUNC; int setsockopt_broadcast(int fd) FAST_FUNC; int setsockopt_bindtodevice(int fd, const char *iface) FAST_FUNC; +int bb_getsockname(int sockfd, void *addr, socklen_t addrlen) FAST_FUNC; /* NB: returns port in host byte order */ unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default_port) FAST_FUNC; typedef struct len_and_sockaddr { diff --git a/libbb/bb_getsockname.c b/libbb/bb_getsockname.c new file mode 100644 index 000000000..1af9b39b9 --- /dev/null +++ b/libbb/bb_getsockname.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//kbuild:lib-y += bb_getsockname.o + +#include "libbb.h" + +int FAST_FUNC bb_getsockname(int sockfd, void *addr, socklen_t addrlen) +{ + /* The usefullness of this function is that for getsockname(), + * addrlen must go on stack (to _have_ an address to be passed), + * but many callers do not need its modified value. + * By using this shim, they can avoid unnecessary stack spillage. + */ + return getsockname(sockfd, (struct sockaddr *)addr, &addrlen); +} diff --git a/networking/arping.c b/networking/arping.c index a16f04b9f..59092a7d7 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -363,15 +363,13 @@ int arping_main(int argc UNUSED_PARAM, char **argv) xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); } else { /* !(option_mask32 & DAD) case */ /* Find IP address on this iface */ - socklen_t alen = sizeof(saddr); - saddr.sin_port = htons(1025); saddr.sin_addr = dst; if (setsockopt_SOL_SOCKET_1(probe_fd, SO_DONTROUTE) != 0) bb_perror_msg("setsockopt(%s)", "SO_DONTROUTE"); xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); - getsockname(probe_fd, (struct sockaddr *) &saddr, &alen); + bb_getsockname(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); //never happens: //if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) // bb_perror_msg_and_die("getsockname"); @@ -387,13 +385,10 @@ int arping_main(int argc UNUSED_PARAM, char **argv) me.sll_protocol = htons(ETH_P_ARP); xbind(sock_fd, (struct sockaddr *) &me, sizeof(me)); - { - socklen_t alen = sizeof(me); - getsockname(sock_fd, (struct sockaddr *) &me, &alen); - //never happens: - //if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) - // bb_perror_msg_and_die("getsockname"); - } + bb_getsockname(sock_fd, (struct sockaddr *) &me, sizeof(me)); + //never happens: + //if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) + // bb_perror_msg_and_die("getsockname"); if (me.sll_halen == 0) { bb_error_msg(err_str, "is not ARPable (no ll address)"); BUILD_BUG_ON(DAD != 2); diff --git a/networking/inetd.c b/networking/inetd.c index 4dfa0089a..6843845fb 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -497,10 +497,9 @@ static void register_rpc(servtab_t *sep) { int n; struct sockaddr_in ir_sin; - socklen_t size; - size = sizeof(ir_sin); - if (getsockname(sep->se_fd, (struct sockaddr *) &ir_sin, &size) < 0) { + if (bb_getsockname(sep->se_fd, (struct sockaddr *) &ir_sin, sizeof(ir_sin)) < 0) { +//TODO: verify that such failure is even possible in Linux kernel bb_perror_msg("getsockname"); return; } diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index aef5f6490..f38fba055 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c @@ -132,7 +132,6 @@ static int get_address(char *dev, int *htype) { struct ifreq ifr; struct sockaddr_ll me; - socklen_t alen; int s; s = xsocket(PF_PACKET, SOCK_DGRAM, 0); @@ -146,8 +145,7 @@ static int get_address(char *dev, int *htype) me.sll_ifindex = ifr.ifr_ifindex; me.sll_protocol = htons(ETH_P_LOOP); xbind(s, (struct sockaddr*)&me, sizeof(me)); - alen = sizeof(me); - getsockname(s, (struct sockaddr*)&me, &alen); + bb_getsockname(s, (struct sockaddr*)&me, sizeof(me)); //never happens: //if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) // bb_perror_msg_and_die("getsockname"); diff --git a/networking/libiproute/libnetlink.c b/networking/libiproute/libnetlink.c index f08d862d0..40955fcae 100644 --- a/networking/libiproute/libnetlink.c +++ b/networking/libiproute/libnetlink.c @@ -15,16 +15,13 @@ void FAST_FUNC xrtnl_open(struct rtnl_handle *rth/*, unsigned subscriptions*/) { - socklen_t addr_len; - memset(rth, 0, sizeof(*rth)); rth->fd = xsocket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); rth->local.nl_family = AF_NETLINK; /*rth->local.nl_groups = subscriptions;*/ xbind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)); - addr_len = sizeof(rth->local); - getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len); + bb_getsockname(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)); /* too much paranoia if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) -- cgit v1.2.3-55-g6feb From b5257a670196d3fee6b1307adce62c68bb3eb4fc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Feb 2018 21:16:24 +0100 Subject: arping: code shrink function old new delta catcher 310 309 -1 arping_main 1668 1641 -27 Signed-off-by: Denys Vlasenko --- networking/arping.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/networking/arping.c b/networking/arping.c index 59092a7d7..788fded3c 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -28,6 +28,7 @@ //usage: "\n -A ARP answer mode, update your neighbors" //usage: "\n -c N Stop after sending N ARP requests" //usage: "\n -w TIMEOUT Seconds to wait for ARP reply" +//NB: in iputils-s20160308, iface is mandatory, no default //usage: "\n -I IFACE Interface to use (default eth0)" //usage: "\n -s SRC_IP Sender IP address" //usage: "\n DST_IP Target IP address" @@ -56,8 +57,8 @@ enum { #define GETOPT32(str_timeout, device, source) \ getopt32(argv, "^" \ "UDAqfbc:+w:I:s:" \ - /* Dad also sets quit_on_reply, */ \ - /* Advert also sets unsolicited: */ \ + /* DAD also sets quit_on_reply, */ \ + /* advert also sets unsolicited: */ \ "\0" "=1:Df:AU", \ &count, &str_timeout, &device, &source \ ); @@ -67,7 +68,6 @@ struct globals { struct in_addr dst; struct sockaddr_ll me; struct sockaddr_ll he; - int sock_fd; int count; // = -1; unsigned last; @@ -80,7 +80,9 @@ struct globals { unsigned brd_recv; unsigned req_recv; + /* should be in main(), but are here to reduce stack use: */ struct ifreq ifr; + struct sockaddr_in probe_saddr; sigset_t sset; unsigned char packet[4096]; } FIX_ALIASING; @@ -88,7 +90,6 @@ struct globals { #define dst (G.dst ) #define me (G.me ) #define he (G.he ) -#define sock_fd (G.sock_fd ) #define count (G.count ) #define last (G.last ) #define timeout_us (G.timeout_us) @@ -106,6 +107,8 @@ struct globals { count = -1; \ } while (0) +#define sock_fd 3 + static int send_pack(struct in_addr *src_addr, struct in_addr *dst_addr, struct sockaddr_ll *ME, @@ -299,7 +302,7 @@ int arping_main(int argc UNUSED_PARAM, char **argv) INIT_G(); - sock_fd = xsocket(AF_PACKET, SOCK_DGRAM, 0); + xmove_fd(xsocket(AF_PACKET, SOCK_DGRAM, 0), sock_fd); // If you ever change BB_SUID_DROP to BB_SUID_REQUIRE, // drop suid root privileges here: @@ -351,31 +354,29 @@ int arping_main(int argc UNUSED_PARAM, char **argv) src = dst; if (!(option_mask32 & DAD) || src.s_addr) { - struct sockaddr_in saddr; + /*struct sockaddr_in probe_saddr;*/ int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); setsockopt_bindtodevice(probe_fd, device); - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; + + /*memset(&G.probe_saddr, 0, sizeof(G.probe_saddr)); - zeroed by INIT_G */ + G.probe_saddr.sin_family = AF_INET; if (src.s_addr) { /* Check that this is indeed our IP */ - saddr.sin_addr = src; - xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); + G.probe_saddr.sin_addr = src; + xbind(probe_fd, (struct sockaddr *) &G.probe_saddr, sizeof(G.probe_saddr)); } else { /* !(option_mask32 & DAD) case */ /* Find IP address on this iface */ - saddr.sin_port = htons(1025); - saddr.sin_addr = dst; + G.probe_saddr.sin_port = htons(1025); + G.probe_saddr.sin_addr = dst; if (setsockopt_SOL_SOCKET_1(probe_fd, SO_DONTROUTE) != 0) bb_perror_msg("setsockopt(%s)", "SO_DONTROUTE"); - xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); - bb_getsockname(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); - //never happens: - //if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) - // bb_perror_msg_and_die("getsockname"); - if (saddr.sin_family != AF_INET) + xconnect(probe_fd, (struct sockaddr *) &G.probe_saddr, sizeof(G.probe_saddr)); + bb_getsockname(probe_fd, (struct sockaddr *) &G.probe_saddr, sizeof(G.probe_saddr)); + if (G.probe_saddr.sin_family != AF_INET) bb_error_msg_and_die("no IP address configured"); - src = saddr.sin_addr; + src = G.probe_saddr.sin_addr; } close(probe_fd); } -- cgit v1.2.3-55-g6feb From 7f441403cbcb6cce864bae66e1fc7bb626954e04 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Feb 2018 21:25:23 +0100 Subject: cp: fix option handling in non-longopt config the patch getopt32: remove opt_complementary 22542eca18e5807b72ddc78999f5101e33f17a53 introduced a regressed in the cp command since it removed all aliases of arguments if long_opts is not configured. Patch by Sebastian Gottschall Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/coreutils/cp.c b/coreutils/cp.c index 8d93c6fe4..455bffbba 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -101,7 +101,11 @@ int cp_main(int argc, char **argv) "parents\0" No_argument "\xfe" ); #else - flags = getopt32(argv, FILEUTILS_CP_OPTSTR); + flags = getopt32(argv, "^" + FILEUTILS_CP_OPTSTR + "\0" + "-2:l--s:s--l:Pd:rRd:Rd:apdR" + ); #endif /* Options of cp from GNU coreutils 6.10: * -a, --archive -- cgit v1.2.3-55-g6feb From ecaec1dbecda67e5b740694878c0780eb4347d26 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 9 Feb 2018 09:01:19 +0000 Subject: testsuite: update busybox and bzcat tests Test scripts that use CONFIG_* variables need to source .config. Since this wasn't being done for busybox many tests were skipped. As a result new failures due to changes in help output were missed. Also remove some unnecessary echos in the bzcat script. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- testsuite/busybox.tests | 16 ++++++---------- testsuite/bzcat.tests | 10 ++++++---- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/testsuite/busybox.tests b/testsuite/busybox.tests index 545cad5c0..beb17440c 100755 --- a/testsuite/busybox.tests +++ b/testsuite/busybox.tests @@ -5,6 +5,7 @@ # Licensed under GPLv2, see file LICENSE in this source tree. . ./testing.sh +test -f "$bindir/.config" && . "$bindir/.config" ln -s `which busybox` unknown @@ -18,29 +19,24 @@ test x"$CONFIG_BUSYBOX" = x"y" \ HELPDUMP=`true | busybox 2>&1 | cat` -# We need to test under calling the binary under other names. - optional FEATURE_VERBOSE_USAGE -testing "busybox --help busybox" "true | busybox --help busybox 2>&1 | cat" "$HELPDUMP\n\n" "" "" +testing "busybox --help busybox" "true | busybox --help busybox 2>&1 | cat" "$HELPDUMP\n" "" "" SKIP= ln -s `which busybox` busybox-suffix for i in busybox ./busybox-suffix do - # The gratuitous "\n"s are due to a shell idiosyncrasy: - # environment variables seem to strip trailing whitespace. - - testing "" "$i" "$HELPDUMP\n\n" "" "" + testing "$i" "$i 2>&1 | cat" "$HELPDUMP\n" "" "" testing "$i unknown" "$i unknown 2>&1" \ "unknown: applet not found\n" "" "" - testing "$i --help" "$i --help 2>&1" "$HELPDUMP\n\n" "" "" + testing "$i --help" "$i --help 2>&1" "$HELPDUMP\n" "" "" optional FEATURE_VERBOSE_USAGE CAT testing "" "$i cat" "moo" "" "moo" - testing "$i --help cat" "$i --help cat 2>&1 | grep print" \ - "Concatenate FILEs and print them to stdout\n" "" "" + testing "$i --help cat" "$i --help cat 2>&1 | grep Print" \ + "Print FILEs to stdout\n" "" "" SKIP= testing "$i --help unknown" "$i --help unknown 2>&1" \ diff --git a/testsuite/bzcat.tests b/testsuite/bzcat.tests index 0ae530dc7..32c1c5d7f 100755 --- a/testsuite/bzcat.tests +++ b/testsuite/bzcat.tests @@ -1,5 +1,7 @@ #!/bin/sh +test -f "$bindir/.config" && . "$bindir/.config" + FAILCOUNT=0 bb="busybox " @@ -73,7 +75,7 @@ done # "input" file is bzipped file with "a\n" data testing "bzcat can print many files" \ -"$ECHO -ne '$hexdump' | bzcat input input; echo \$?" \ +"bzcat input input; echo \$?" \ "\ a a @@ -86,7 +88,7 @@ a # "input" file is bzipped zero byte file testing "bzcat can handle compressed zero-length bzip2 files" \ -"$ECHO -ne '$hexdump' | bzcat input input; echo \$?" \ +"bzcat input input; echo \$?" \ "0\n" \ "\x42\x5a\x68\x39\x17\x72\x45\x38\x50\x90\x00\x00\x00\x00" "" @@ -95,7 +97,7 @@ testing "bzcat can handle compressed zero-length bzip2 files" \ # "input" file is compressed (.Z) file with "a\n" data test x"$CONFIG_UNCOMPRESS" = x"y" && \ testing "zcat can print many files" \ -"$ECHO -ne '$hexdump' | zcat input input; echo \$?" \ +"zcat input input; echo \$?" \ "\ a a @@ -107,7 +109,7 @@ a # "input" file is compressed (.Z) zero byte file test x"$CONFIG_UNCOMPRESS" = x"y" && \ testing "zcat can handle compressed zero-length (.Z) files" \ -"$ECHO -ne '$hexdump' | zcat input input; echo \$?" \ +"zcat input input; echo \$?" \ "0\n" \ "\x1f\x9d\x90\x00" "" -- cgit v1.2.3-55-g6feb From 3459024bf404af814cacfe90a0deb719e282ae62 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 12 Feb 2018 16:46:13 +0100 Subject: wget: more thorough sanitization of other side's data function old new delta get_sanitized_hdr - 156 +156 fgets_trim_sanitize - 128 +128 ftpcmd 129 133 +4 parse_url 461 454 -7 sanitize_string 14 - -14 wget_main 2431 2381 -50 fgets_and_trim 119 - -119 gethdr 163 - -163 ------------------------------------------------------------------------------ (add/remove: 2/3 grow/shrink: 1/2 up/down: 288/-353) Total: -65 bytes Signed-off-by: Denys Vlasenko --- networking/wget.c | 86 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 95b88ad37..3a5d68173 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -352,15 +352,6 @@ static char *base64enc(const char *str) } #endif -static char* sanitize_string(char *s) -{ - unsigned char *p = (void *) s; - while (*p >= ' ') - p++; - *p = '\0'; - return s; -} - #if ENABLE_FEATURE_WGET_TIMEOUT static void alarm_handler(int sig UNUSED_PARAM) { @@ -423,22 +414,49 @@ static FILE *open_socket(len_and_sockaddr *lsa) return fp; } +/* We balk at any control chars in other side's messages. + * This prevents nasty surprises (e.g. ESC sequences) in "Location:" URLs + * and error messages. + * + * The only exception is tabs, which are converted to (one) space: + * HTTP's "headers: values" may have those. + */ +static char* sanitize_string(char *s) +{ + unsigned char *p = (void *) s; + while (*p) { + if (*p < ' ') { + if (*p != '\t') + break; + *p = ' '; + } + p++; + } + *p = '\0'; + return s; +} + /* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ -static char fgets_and_trim(FILE *fp, const char *fmt) +static char fgets_trim_sanitize(FILE *fp, const char *fmt) { char c; char *buf_ptr; set_alarm(); - if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL) + if (fgets(G.wget_buf, sizeof(G.wget_buf), fp) == NULL) bb_perror_msg_and_die("error getting response"); clear_alarm(); buf_ptr = strchrnul(G.wget_buf, '\n'); c = *buf_ptr; +#if 1 + /* Disallow any control chars: trim at first char < 0x20 */ + sanitize_string(G.wget_buf); +#else *buf_ptr = '\0'; buf_ptr = strchrnul(G.wget_buf, '\r'); *buf_ptr = '\0'; +#endif log_io("< %s", G.wget_buf); @@ -462,8 +480,10 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp) log_io("> %s%s", s1, s2); } + /* Read until "Nxx something" is received */ + G.wget_buf[3] = 0; do { - fgets_and_trim(fp, "%s\n"); + fgets_trim_sanitize(fp, "%s\n"); } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); G.wget_buf[3] = '\0'; @@ -505,7 +525,7 @@ static void parse_url(const char *src_url, struct host_info *h) h->protocol = P_HTTP; } else { *p = ':'; - bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url)); + bb_error_msg_and_die("not an http or ftp url: %s", url); } } else { // GNU wget is user-friendly and falls back to http:// @@ -560,13 +580,13 @@ static void parse_url(const char *src_url, struct host_info *h) */ } -static char *gethdr(FILE *fp) +static char *get_sanitized_hdr(FILE *fp) { char *s, *hdrval; int c; /* retrieve header line */ - c = fgets_and_trim(fp, " %s\n"); + c = fgets_trim_sanitize(fp, " %s\n"); /* end of the headers? */ if (G.wget_buf[0] == '\0') @@ -588,7 +608,7 @@ static char *gethdr(FILE *fp) /* verify we are at the end of the header name */ if (*s != ':') - bb_error_msg_and_die("bad header line: %s", sanitize_string(G.wget_buf)); + bb_error_msg_and_die("bad header line: %s", G.wget_buf); /* locate the start of the header value */ *s++ = '\0'; @@ -755,7 +775,8 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ #endif if (ftpcmd(NULL, NULL, sfp) != 220) - bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4)); + bb_error_msg_and_die("%s", G.wget_buf); + /* note: ftpcmd() sanitizes G.wget_buf, ok to print */ /* * Splitting username:password pair, @@ -772,7 +793,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ break; /* fall through (failed login) */ default: - bb_error_msg_and_die("ftp login: %s", sanitize_string(G.wget_buf + 4)); + bb_error_msg_and_die("ftp login: %s", G.wget_buf); } ftpcmd("TYPE I", NULL, sfp); @@ -796,7 +817,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ } else if (ftpcmd("PASV", NULL, sfp) != 227) { pasv_error: - bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf)); + bb_error_msg_and_die("bad response to %s: %s", "PASV", G.wget_buf); } port = parse_pasv_epsv(G.wget_buf); if (port < 0) @@ -824,8 +845,11 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ reset_beg_range_to_zero(); } +//TODO: needs ftp-escaping 0xff and '\n' bytes here. +//Or disallow '\n' altogether via sanitize_string() in parse_url(). +//But 0xff's are possible in valid utf8 filenames. if (ftpcmd("RETR ", target->path, sfp) > 150) - bb_error_msg_and_die("bad response to %s: %s", "RETR", sanitize_string(G.wget_buf)); + bb_error_msg_and_die("bad response to %s: %s", "RETR", G.wget_buf); return sfp; } @@ -946,9 +970,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp) if (!G.chunked) break; - fgets_and_trim(dfp, NULL); /* Eat empty line */ + fgets_trim_sanitize(dfp, NULL); /* Eat empty line */ get_clen: - fgets_and_trim(dfp, NULL); + fgets_trim_sanitize(dfp, NULL); G.content_len = STRTOOFF(G.wget_buf, NULL, 16); /* FIXME: error check? */ if (G.content_len == 0) @@ -1178,7 +1202,7 @@ static void download_one_url(const char *url) * Retrieve HTTP response line and check for "200" status code. */ read_response: - fgets_and_trim(sfp, " %s\n"); + fgets_trim_sanitize(sfp, " %s\n"); str = G.wget_buf; str = skip_non_whitespace(str); @@ -1189,7 +1213,7 @@ static void download_one_url(const char *url) switch (status) { case 0: case 100: - while (gethdr(sfp) != NULL) + while (get_sanitized_hdr(sfp) != NULL) /* eat all remaining headers */; goto read_response; @@ -1253,13 +1277,13 @@ However, in real world it was observed that some web servers /* Partial Content even though we did not ask for it??? */ /* fall through */ default: - bb_error_msg_and_die("server returned error: %s", sanitize_string(G.wget_buf)); + bb_error_msg_and_die("server returned error: %s", G.wget_buf); } /* * Retrieve HTTP headers. */ - while ((str = gethdr(sfp)) != NULL) { + while ((str = get_sanitized_hdr(sfp)) != NULL) { static const char keywords[] ALIGN1 = "content-length\0""transfer-encoding\0""location\0"; enum { @@ -1267,7 +1291,7 @@ However, in real world it was observed that some web servers }; smalluint key; - /* gethdr converted "FOO:" string to lowercase */ + /* get_sanitized_hdr converted "FOO:" string to lowercase */ /* strip trailing whitespace */ char *s = strchrnul(str, '\0') - 1; @@ -1279,14 +1303,14 @@ However, in real world it was observed that some web servers if (key == KEY_content_length) { G.content_len = BB_STRTOOFF(str, NULL, 10); if (G.content_len < 0 || errno) { - bb_error_msg_and_die("content-length %s is garbage", sanitize_string(str)); + bb_error_msg_and_die("content-length %s is garbage", str); } G.got_clen = 1; continue; } if (key == KEY_transfer_encoding) { if (strcmp(str_tolower(str), "chunked") != 0) - bb_error_msg_and_die("transfer encoding '%s' is not supported", sanitize_string(str)); + bb_error_msg_and_die("transfer encoding '%s' is not supported", str); G.chunked = 1; } if (key == KEY_location && status >= 300) { @@ -1295,7 +1319,7 @@ However, in real world it was observed that some web servers fclose(sfp); if (str[0] == '/') { free(redirected_path); - target.path = redirected_path = xstrdup(str+1); + target.path = redirected_path = xstrdup(str + 1); /* lsa stays the same: it's on the same server */ } else { parse_url(str, &target); @@ -1342,7 +1366,7 @@ However, in real world it was observed that some web servers /* It's ftp. Close data connection properly */ fclose(dfp); if (ftpcmd(NULL, NULL, sfp) != 226) - bb_error_msg_and_die("ftp error: %s", sanitize_string(G.wget_buf + 4)); + bb_error_msg_and_die("ftp error: %s", G.wget_buf); /* ftpcmd("QUIT", NULL, sfp); - why bother? */ } fclose(sfp); -- cgit v1.2.3-55-g6feb