From f56fe8254274cea34d2550870c2dfc010bdfa7e8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Aug 2010 17:21:52 +0200 Subject: update var_bash4 test. one more bug revealed by it now... Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-vars/var_bash4.right | 25 ++++++++++++++-- shell/ash_test/ash-vars/var_bash4.tests | 51 +++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/shell/ash_test/ash-vars/var_bash4.right b/shell/ash_test/ash-vars/var_bash4.right index fc3a9e41c..2d4e45be8 100644 --- a/shell/ash_test/ash-vars/var_bash4.right +++ b/shell/ash_test/ash-vars/var_bash4.right @@ -1,4 +1,23 @@ -In assignment: a*b-backslashstar- -Unquoted: a*b-backslashstar- -Quoted: a*b-backslashstar- +Source: a*b\*c +Replace str: _\\_\z_ +Pattern: single backslash and star: "replace literal star" +In assignment: a_\_z_b\*c +Unquoted: a_\_z_b\*c +Quoted: a_\_\z_b\*c +Pattern: double backslash and star: "replace backslash and everything after it" +In assignment: a*b_\_z_ +Unquoted: a*b_\_z_ +Quoted: a*b_\_\z_ + +Source: a\bc +Replace str: _\\_\z_ +Pattern: single backslash and b: "replace literal b" +In assignment: a\_\_z_c +Unquoted: a\_\_z_c +Quoted: a\_\_\z_c +Pattern: double backslash and b: "replace backslash and b" +In assignment: a_\_z_c +Unquoted: a_\_z_c +Quoted: a_\_\z_c + Done: 0 diff --git a/shell/ash_test/ash-vars/var_bash4.tests b/shell/ash_test/ash-vars/var_bash4.tests index 3b323c576..01a0def51 100755 --- a/shell/ash_test/ash-vars/var_bash4.tests +++ b/shell/ash_test/ash-vars/var_bash4.tests @@ -1,6 +1,47 @@ -FOO='a*b\*c' -BAR=${FOO//\\*/-backslashstar-} -echo In assignment: "$BAR" -echo Unquoted: ${FOO//\\*/-backslashstar-} -echo Quoted: "${FOO//\\*/-backslashstar-}" +# This testcase demonstrates that backslashes are treated differently +# in 1st and 2nd parts of ${var/search/repl}: +# if quoted: "${var/search/repl}", and repl contains \a (a non-special char), +# the backslash in repl stays; if unquoted, backslash: removed +# But search part does not act like that: \a is always converted to just a, +# even in quotes. +# +# bash4 (and probably bash3 too) result: "Quoted:" results are different - +# they have extra backslash before z. + +v='a*b\*c' +echo 'Source: ' "$v" +echo 'Replace str: ' '_\\_\z_' + +echo 'Pattern: ' 'single backslash and star: "replace literal star"' +r=${v/\*/_\\_\z_} +echo 'In assignment:' "$r" +echo 'Unquoted: ' ${v/\*/_\\_\z_} +echo 'Quoted: ' "${v/\*/_\\_\z_}" + +echo 'Pattern: ' 'double backslash and star: "replace backslash and everything after it"' +r=${v/\\*/_\\_\z_} +echo 'In assignment:' "$r" +echo 'Unquoted: ' ${v/\\*/_\\_\z_} +echo 'Quoted: ' "${v/\\*/_\\_\z_}" + +echo + +v='a\bc' +echo 'Source: ' "$v" +echo 'Replace str: ' '_\\_\z_' + +echo 'Pattern: ' 'single backslash and b: "replace literal b"' +r=${v/\b/_\\_\z_} +echo 'In assignment:' "$r" +echo 'Unquoted: ' ${v/\b/_\\_\z_} +echo 'Quoted: ' "${v/\b/_\\_\z_}" + +echo 'Pattern: ' 'double backslash and b: "replace backslash and b"' +r=${v/\\b/_\\_\z_} +echo 'In assignment:' "$r" +echo 'Unquoted: ' ${v/\\b/_\\_\z_} +echo 'Quoted: ' "${v/\\b/_\\_\z_}" + +echo + echo Done: $? -- cgit v1.2.3-55-g6feb From f02c82f38c749f20a917aeb7ff4d929c5292a63d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Aug 2010 19:14:47 +0200 Subject: ash: fix dequoting error detected by var_bash4 test But the test still fails (one more bug to fix) function old new delta changepath 195 192 -3 readtoken1 3247 3240 -7 subevalvar 1204 1184 -20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-30) Total: -30 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 16783f2e8..74b1c3aad 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6267,7 +6267,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags) #if ENABLE_ASH_BASH_COMPAT static char * -parse_sub_pattern(char *arg, int inquotes) +parse_sub_pattern(char *arg, int varflags) { char *idx, *repl = NULL; unsigned char c; @@ -6285,7 +6285,7 @@ parse_sub_pattern(char *arg, int inquotes) } } *idx++ = c; - if (!inquotes && c == '\\' && arg[1] == '\\') + if (!(varflags & VSQUOTE) && c == '\\' && arg[1] == '\\') arg++; /* skip both \\, not just first one */ arg++; } @@ -6427,7 +6427,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, char *idx, *end; if (!repl) { - repl = parse_sub_pattern(str, varflags & VSQUOTE); + repl = parse_sub_pattern(str, varflags); //bb_error_msg("repl:'%s'", repl); if (!repl) repl = nullstr; @@ -6496,12 +6496,11 @@ subevalvar(char *p, char *varname, int strloc, int subtype, } if (subtype == VSREPLACE) { + //bb_error_msg("tail:'%s', quotes:%x", idx, quotes); while (*idx) { char *restart_detect = stackblock(); - if (quotes && *idx == '\\') { - STPUTC(CTLESC, expdest); - len++; - } + if (quotes && (unsigned char)*idx == CTLESC) + idx++; STPUTC(*idx, expdest); if (stackblock() != restart_detect) goto restart; -- cgit v1.2.3-55-g6feb From c8d305d89f06e0d6612b7acdc91cb8775f5667b1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Aug 2010 19:28:04 +0200 Subject: var_bash4.tests: better wording in comment Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-vars/var_bash4.tests | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shell/ash_test/ash-vars/var_bash4.tests b/shell/ash_test/ash-vars/var_bash4.tests index 01a0def51..a6e98fd86 100755 --- a/shell/ash_test/ash-vars/var_bash4.tests +++ b/shell/ash_test/ash-vars/var_bash4.tests @@ -1,12 +1,12 @@ # This testcase demonstrates that backslashes are treated differently # in 1st and 2nd parts of ${var/search/repl}: -# if quoted: "${var/search/repl}", and repl contains \a (a non-special char), -# the backslash in repl stays; if unquoted, backslash: removed +# if quoted ("${var/search/repl}"), and repl contains \a (a non-special char), +# the backslash in repl stays; if unquoted, backslash is removed. # But search part does not act like that: \a is always converted to just a, # even in quotes. # -# bash4 (and probably bash3 too) result: "Quoted:" results are different - -# they have extra backslash before z. +# bash4 (and probably bash3 too): "Quoted:" results are different from +# unquoted and assignment expansions - they have a backslash before z. v='a*b\*c' echo 'Source: ' "$v" -- cgit v1.2.3-55-g6feb From 1614900522a5d603909a2679acbdd4744c235c1b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Aug 2010 22:06:21 +0200 Subject: ash: fix another bug detected by var_bash4.tests ... but var_bash4.tests still does not pass! function old new delta expandarg 959 962 +3 localcmd 259 257 -2 readtoken1 3275 3260 -15 subevalvar 1178 1141 -37 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 3/-54) Total: -51 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 74b1c3aad..dcac4fe04 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6272,6 +6272,8 @@ parse_sub_pattern(char *arg, int varflags) char *idx, *repl = NULL; unsigned char c; + //char *org_arg = arg; + //bb_error_msg("arg:'%s'", arg); idx = arg; while (1) { c = *arg; @@ -6290,6 +6292,7 @@ parse_sub_pattern(char *arg, int varflags) arg++; } *idx = c; /* NUL */ + //bb_error_msg("pattern:'%s' repl:'%s'", org_arg, repl); return repl; } @@ -6499,8 +6502,6 @@ subevalvar(char *p, char *varname, int strloc, int subtype, //bb_error_msg("tail:'%s', quotes:%x", idx, quotes); while (*idx) { char *restart_detect = stackblock(); - if (quotes && (unsigned char)*idx == CTLESC) - idx++; STPUTC(*idx, expdest); if (stackblock() != restart_detect) goto restart; -- cgit v1.2.3-55-g6feb From 09dd6ec7326c91352dc32187dcc215f18c28d3f0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Aug 2010 02:44:33 +0200 Subject: ash: cosmetic fixes, no code changes Signed-off-by: Denys Vlasenko --- shell/ash.c | 81 ++++++++++++++++--------------------------------------------- 1 file changed, 21 insertions(+), 60 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index dcac4fe04..6befe0fd3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5687,7 +5687,7 @@ removerecordregions(int endoff) return; if (ifsfirst.endoff > endoff) { - while (ifsfirst.next != NULL) { + while (ifsfirst.next) { struct ifsregion *ifsp; INT_OFF; ifsp = ifsfirst.next->next; @@ -5695,9 +5695,9 @@ removerecordregions(int endoff) ifsfirst.next = ifsp; INT_ON; } - if (ifsfirst.begoff > endoff) + if (ifsfirst.begoff > endoff) { ifslastp = NULL; - else { + } else { ifslastp = &ifsfirst; ifsfirst.endoff = endoff; } @@ -5706,8 +5706,8 @@ removerecordregions(int endoff) ifslastp = &ifsfirst; while (ifslastp->next && ifslastp->next->begoff < endoff) - ifslastp=ifslastp->next; - while (ifslastp->next != NULL) { + ifslastp = ifslastp->next; + while (ifslastp->next) { struct ifsregion *ifsp; INT_OFF; ifsp = ifslastp->next->next; @@ -5884,9 +5884,9 @@ expbackq(union node *cmd, int quoted, int quotes) if (quoted == 0) recordregion(startloc, dest - (char *)stackblock(), 0); - TRACE(("evalbackq: size=%d: \"%.*s\"\n", - (dest - (char *)stackblock()) - startloc, - (dest - (char *)stackblock()) - startloc, + TRACE(("evalbackq: size:%d:'%.*s'\n", + (int)((dest - (char *)stackblock()) - startloc), + (int)((dest - (char *)stackblock()) - startloc), stackblock() + startloc)); } @@ -6105,42 +6105,16 @@ argstr(char *p, int flags, struct strlist *var_str_list) } static char * -scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes, - int zero) -{ -// This commented out code was added by James Simmons -// as part of a larger change when he added support for ${var/a/b}. -// However, it broke # and % operators: -// -//var=ababcdcd -// ok bad -//echo ${var#ab} abcdcd abcdcd -//echo ${var##ab} abcdcd abcdcd -//echo ${var#a*b} abcdcd ababcdcd (!) -//echo ${var##a*b} cdcd cdcd -//echo ${var#?} babcdcd ababcdcd (!) -//echo ${var##?} babcdcd babcdcd -//echo ${var#*} ababcdcd babcdcd (!) -//echo ${var##*} -//echo ${var%cd} ababcd ababcd -//echo ${var%%cd} ababcd abab (!) -//echo ${var%c*d} ababcd ababcd -//echo ${var%%c*d} abab ababcdcd (!) -//echo ${var%?} ababcdc ababcdc -//echo ${var%%?} ababcdc ababcdcd (!) -//echo ${var%*} ababcdcd ababcdcd -//echo ${var%%*} -// -// Commenting it back out helped. Remove it completely if it really -// is not needed. - - char *loc, *loc2; //, *full; +scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, + char *pattern, int quotes, int zero) +{ + char *loc, *loc2; char c; loc = startp; loc2 = rmesc; do { - int match; // = strlen(str); + int match; const char *s = loc2; c = *loc2; @@ -6148,35 +6122,22 @@ scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int *loc2 = '\0'; s = rmesc; } - match = pmatch(str, s); // this line was deleted - -// // chop off end if its '*' -// full = strrchr(str, '*'); -// if (full && full != str) -// match--; -// -// // If str starts with '*' replace with s. -// if ((*str == '*') && strlen(s) >= match) { -// full = xstrdup(s); -// strncpy(full+strlen(s)-match+1, str+1, match-1); -// } else -// full = xstrndup(str, match); -// match = strncmp(s, full, strlen(full)); -// free(full); -// + match = pmatch(pattern, s); + *loc2 = c; - if (match) // if (!match) + if (match) return loc; if (quotes && (unsigned char)*loc == CTLESC) loc++; loc++; loc2++; } while (c); - return 0; + return NULL; } static char * -scanright(char *startp, char *rmesc, char *rmescend, char *pattern, int quotes, int match_at_start) +scanright(char *startp, char *rmesc, char *rmescend, + char *pattern, int quotes, int match_at_start) { #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE int try2optimize = match_at_start; @@ -6242,7 +6203,7 @@ scanright(char *startp, char *rmesc, char *rmescend, char *pattern, int quotes, } } } - return 0; + return NULL; } static void varunset(const char *, const char *, const char *, int) NORETURN; @@ -6262,7 +6223,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags) msg = umsg; } } - ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail); + ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail); } #if ENABLE_ASH_BASH_COMPAT -- cgit v1.2.3-55-g6feb From 0d98b4409bef0f0c7b57965da0e8d93344445529 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Aug 2010 02:56:43 +0200 Subject: udhcpc: add -v to help text Signed-off-by: Denys Vlasenko --- include/usage.src.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/include/usage.src.h b/include/usage.src.h index 0053a7c4b..57c25a0f8 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -4467,8 +4467,13 @@ INSERT #define tune2fs_full_usage "\n\n" \ "Adjust filesystem options on ext[23] filesystems" +#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 +# define IF_UDHCP_VERBOSE(...) __VA_ARGS__ +#else +# define IF_UDHCP_VERBOSE(...) +#endif #define udhcpc_trivial_usage \ - "[-fbnqvoCR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" \ + "[-fbnq"IF_UDHCP_VERBOSE("v")"oCR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" \ " [-H HOSTNAME] [-c CID] [-V VENDOR] [-O DHCP_OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") #define udhcpc_full_usage "\n" \ IF_LONG_OPTS( \ @@ -4501,6 +4506,9 @@ INSERT "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')" \ "\n -c,--clientid CLIENTID Client identifier (default own MAC)" \ "\n -C,--clientid-none Don't send client identifier" \ + IF_UDHCP_VERBOSE( \ + "\n -v Verbose" \ + ) \ ) \ IF_NOT_LONG_OPTS( \ "\n -i IFACE Interface to use (default eth0)" \ @@ -4532,7 +4540,10 @@ INSERT "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')" \ "\n -c CLIENTID Client identifier (default own MAC)" \ "\n -C Don't send client identifier" \ - ) + IF_UDHCP_VERBOSE( \ + "\n -v Verbose" \ + ) \ + ) \ #define udhcpd_trivial_usage \ "[-fS]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [configfile]" \ -- cgit v1.2.3-55-g6feb From 58a15cd9d2765e9b9bca6b71ad9713bcc3784821 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Aug 2010 14:02:26 +0200 Subject: Fix a typo in config text Signed-off-by: Denys Vlasenko --- networking/udhcp/Config.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 331dffc2e..dcd493f13 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -85,7 +85,7 @@ config UDHCP_DEBUG depends on UDHCPD || UDHCPC || DHCPRELAY help Verbosity can be increased with multiple -v options. - This options controls how high it can be cranked up. + This option controls how high it can be cranked up. Bigger values result in bigger code. Levels above 1 are very verbose and useful for debugging only. -- cgit v1.2.3-55-g6feb From 33bbb27e45c7c6a0fecb40b3a5aa36aef69825f9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Aug 2010 22:24:36 +0200 Subject: ash: fix another bit of var_bash4 bug But it _still_ doesn't pass! quoted case is a tough nut to crack function old new delta redirect 1281 1286 +5 subevalvar 1141 1142 +1 Signed-off-by: Denys Vlasenko --- shell/ash.c | 17 ++++++++++++++--- shell/ash_test/ash-vars/var_bash4.right | 2 +- shell/ash_test/ash-vars/var_bash4.tests | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 6befe0fd3..4fbae2498 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6234,7 +6234,7 @@ parse_sub_pattern(char *arg, int varflags) unsigned char c; //char *org_arg = arg; - //bb_error_msg("arg:'%s'", arg); + //bb_error_msg("arg:'%s' varflags:%x", arg, varflags); idx = arg; while (1) { c = *arg; @@ -6248,9 +6248,20 @@ parse_sub_pattern(char *arg, int varflags) } } *idx++ = c; - if (!(varflags & VSQUOTE) && c == '\\' && arg[1] == '\\') - arg++; /* skip both \\, not just first one */ arg++; + /* + * Example: v='ab\c'; echo ${v/\\b/_\\_\z_} + * The result is a_\_z_c (not a\_\_z_c)! + * + * Enable debug prints in this function and you'll see: + * ash: arg:'\\b/_\\_z_' varflags:d + * ash: pattern:'\\b' repl:'_\_z_' + * That is, \\b is interpreted as \\b, but \\_ as \_! + * IOW: search pattern and replace string treat backslashes + * differently! That is the reason why we check repl below: + */ + if (c == '\\' && *arg == '\\' && repl && !(varflags & VSQUOTE)) + arg++; /* skip both '\', not just first one */ } *idx = c; /* NUL */ //bb_error_msg("pattern:'%s' repl:'%s'", org_arg, repl); diff --git a/shell/ash_test/ash-vars/var_bash4.right b/shell/ash_test/ash-vars/var_bash4.right index 2d4e45be8..600e8532f 100644 --- a/shell/ash_test/ash-vars/var_bash4.right +++ b/shell/ash_test/ash-vars/var_bash4.right @@ -11,7 +11,7 @@ Quoted: a*b_\_\z_ Source: a\bc Replace str: _\\_\z_ -Pattern: single backslash and b: "replace literal b" +Pattern: single backslash and b: "replace b" In assignment: a\_\_z_c Unquoted: a\_\_z_c Quoted: a\_\_\z_c diff --git a/shell/ash_test/ash-vars/var_bash4.tests b/shell/ash_test/ash-vars/var_bash4.tests index a6e98fd86..d5470614b 100755 --- a/shell/ash_test/ash-vars/var_bash4.tests +++ b/shell/ash_test/ash-vars/var_bash4.tests @@ -30,7 +30,7 @@ v='a\bc' echo 'Source: ' "$v" echo 'Replace str: ' '_\\_\z_' -echo 'Pattern: ' 'single backslash and b: "replace literal b"' +echo 'Pattern: ' 'single backslash and b: "replace b"' r=${v/\b/_\\_\z_} echo 'In assignment:' "$r" echo 'Unquoted: ' ${v/\b/_\\_\z_} -- cgit v1.2.3-55-g6feb From c97131c2af832f03e769a12b2a95e4de86c5858f Mon Sep 17 00:00:00 2001 From: "Bradley M. Kuhn" Date: Sun, 8 Aug 2010 02:51:20 +0200 Subject: wget: implement -T SEC; rework progress meter to not use signals (it was unsafe) function old new delta retrieve_file_data 364 450 +86 bb_progress_update 615 682 +67 packed_usage 27406 27422 +16 wget_main 2440 2453 +13 static.wget_longopts 145 155 +10 progress_meter 199 159 -40 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/1 up/down: 192/-40) Total: 152 bytes Signed-off-by: Bradley M. Kuhn Signed-off-by: Denys Vlasenko --- TEST_config_rh9 | 1 + include/usage.src.h | 11 +++-- libbb/progress.c | 35 ++++++++++----- networking/Config.src | 12 +++++ networking/wget.c | 121 ++++++++++++++++++++++++++++++-------------------- 5 files changed, 117 insertions(+), 63 deletions(-) diff --git a/TEST_config_rh9 b/TEST_config_rh9 index f376cd439..3ffb1c6f3 100644 --- a/TEST_config_rh9 +++ b/TEST_config_rh9 @@ -803,6 +803,7 @@ CONFIG_WGET=y CONFIG_FEATURE_WGET_STATUSBAR=y CONFIG_FEATURE_WGET_AUTHENTICATION=y CONFIG_FEATURE_WGET_LONG_OPTIONS=y +CONFIG_FEATURE_WGET_TIMEOUT=y CONFIG_ZCIP=y # diff --git a/include/usage.src.h b/include/usage.src.h index 57c25a0f8..ebd8c2e6a 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -4779,10 +4779,12 @@ INSERT IF_FEATURE_WGET_LONG_OPTIONS( \ "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" \ " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" \ - " [--no-check-certificate] [-U|--user-agent AGENT] URL" \ + " [--no-check-certificate] [-U|--user-agent AGENT]" \ + IF_FEATURE_WGET_TIMEOUT("[-T SEC] ") " URL" \ ) \ IF_NOT_FEATURE_WGET_LONG_OPTIONS( \ - "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT] URL" \ + "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" \ + IF_FEATURE_WGET_TIMEOUT("[-T SEC] ") " URL" \ ) #define wget_full_usage "\n\n" \ "Retrieve files via HTTP or FTP\n" \ @@ -4790,7 +4792,10 @@ INSERT "\n -s Spider mode - only check file existence" \ "\n -c Continue retrieval of aborted transfer" \ "\n -q Quiet" \ - "\n -P Set directory prefix to DIR" \ + "\n -P DIR Save to DIR (default .)" \ + IF_FEATURE_WGET_TIMEOUT( \ + "\n -T SEC Network read timeout is SEC seconds" \ + ) \ "\n -O FILE Save to FILE ('-' for stdout)" \ "\n -U STR Use STR for User-Agent header" \ "\n -Y Use proxy ('on' or 'off')" \ diff --git a/libbb/progress.c b/libbb/progress.c index e96039042..7fb8536d2 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -66,16 +66,29 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, off_t transferred, off_t totalsize) { - off_t abbrevsize; + uoff_t beg_and_transferred; unsigned since_last_update, elapsed; unsigned ratio; int barlength, i; + /* totalsize == 0 if it is unknown */ + + elapsed = monotonic_sec(); + since_last_update = elapsed - p->lastupdate_sec; + /* Do not update on every call + * (might be: on every network read!) */ + if (since_last_update == 0 && !totalsize) + return; + + beg_and_transferred = beg_range + transferred; ratio = 100; - if (totalsize) { + if (beg_and_transferred < totalsize) { + /* Do not update on every call + * (might be: on every network read!) */ + if (since_last_update == 0) + return; /* long long helps to have it working even if !LFS */ - ratio = (unsigned) (100ULL * (transferred+beg_range) / totalsize); - if (ratio > 100) ratio = 100; + ratio = 100ULL * beg_and_transferred / (uoff_t)totalsize; } #if ENABLE_UNICODE_SUPPORT @@ -95,11 +108,11 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, /* back to multibyte; cant overflow */ wcstombs(buf, wbuf21, INT_MAX); len = (len > 20) ? 0 : 20 - len; - fprintf(stderr, "\r%s%*s%4d%% ", buf, len, "", ratio); + fprintf(stderr, "\r%s%*s%4u%% ", buf, len, "", ratio); free(buf); } #else - fprintf(stderr, "\r%-20.20s%4d%% ", curfile, ratio); + fprintf(stderr, "\r%-20.20s%4u%% ", curfile, ratio); #endif barlength = get_tty2_width() - 49; @@ -114,16 +127,14 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, } } i = 0; - abbrevsize = transferred + beg_range; - while (abbrevsize >= 100000) { + while (beg_and_transferred >= 100000) { i++; - abbrevsize >>= 10; + beg_and_transferred >>= 10; } /* see http://en.wikipedia.org/wiki/Tera */ - fprintf(stderr, "%6d%c ", (int)abbrevsize, " kMGTPEZY"[i]); + fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[i]); +#define beg_and_transferred dont_use_beg_and_transferred_below - elapsed = monotonic_sec(); - since_last_update = elapsed - p->lastupdate_sec; if (transferred > p->lastsize) { p->lastupdate_sec = elapsed; p->lastsize = transferred; diff --git a/networking/Config.src b/networking/Config.src index 8604c53e9..1d9a33f2b 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -1012,6 +1012,18 @@ config FEATURE_WGET_LONG_OPTIONS help Support long options for the wget applet. +config FEATURE_WGET_TIMEOUT + bool "Enable timeout options" + default n + depends on WGET + help + Supports network read timeout for wget, so that wget will give + up and timeout when reading network data, through the -T command + line option. Currently only network data read timeout is + supported (i.e., timeout is not applied to the DNS nor TCP + connection initialization). When FEATURE_WGET_LONG_OPTIONS is + also enabled, the --timeout option will work in addition to -T. + config ZCIP bool "zcip" default y diff --git a/networking/wget.c b/networking/wget.c index 1f35f8b03..f62339071 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -3,8 +3,10 @@ * wget - retrieve a file using HTTP or FTP * * Chip Rosenthal Covad Communications - * * Licensed under GPLv2, see file LICENSE in this tarball for details. + * + * Copyright (C) 2010 Bradley M. Kuhn + * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. */ #include "libbb.h" @@ -19,7 +21,7 @@ struct host_info { }; -/* Globals (can be accessed from signal handlers) */ +/* Globals */ struct globals { off_t content_len; /* Content-length of the file */ off_t beg_range; /* Range at which continue begins */ @@ -27,6 +29,9 @@ struct globals { off_t transferred; /* Number of bytes transferred so far */ const char *curfile; /* Name of current file being transferred */ bb_progress_t pmt; +#endif +#if ENABLE_FEATURE_WGET_TIMEOUT + unsigned timeout_seconds; #endif smallint chunked; /* chunked transfer encoding */ smallint got_clen; /* got content-length: from server */ @@ -35,42 +40,51 @@ struct globals { struct BUG_G_too_big { char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; }; -#define INIT_G() do { } while (0) +#define INIT_G() do { \ + IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \ +} while (0) -#if ENABLE_FEATURE_WGET_STATUSBAR +/* Must match option string! */ +enum { + WGET_OPT_CONTINUE = (1 << 0), + WGET_OPT_SPIDER = (1 << 1), + WGET_OPT_QUIET = (1 << 2), + WGET_OPT_OUTNAME = (1 << 3), + WGET_OPT_PREFIX = (1 << 4), + WGET_OPT_PROXY = (1 << 5), + WGET_OPT_USER_AGENT = (1 << 6), + WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 7), + WGET_OPT_RETRIES = (1 << 8), + WGET_OPT_PASSIVE = (1 << 9), + WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, +}; +enum { + PROGRESS_START = -1, + PROGRESS_END = 0, + PROGRESS_BUMP = 1, +}; +#if ENABLE_FEATURE_WGET_STATUSBAR static void progress_meter(int flag) { - /* We can be called from signal handler */ - int save_errno = errno; + if (option_mask32 & WGET_OPT_QUIET) + return; - if (flag == -1) { /* first call to progress_meter */ + if (flag == PROGRESS_START) bb_progress_init(&G.pmt); - } bb_progress_update(&G.pmt, G.curfile, G.beg_range, G.transferred, G.chunked ? 0 : G.beg_range + G.transferred + G.content_len); - if (flag == 0) { - /* last call to progress_meter */ - alarm(0); + if (flag == PROGRESS_END) { bb_putchar_stderr('\n'); G.transferred = 0; - } else { - if (flag == -1) { /* first call to progress_meter */ - signal_SA_RESTART_empty_mask(SIGALRM, progress_meter); - } - alarm(1); } - - errno = save_errno; } - -#else /* FEATURE_WGET_STATUSBAR */ - +#else static ALWAYS_INLINE void progress_meter(int flag UNUSED_PARAM) { } - #endif @@ -430,28 +444,20 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ return sfp; } -/* Must match option string! */ -enum { - WGET_OPT_CONTINUE = (1 << 0), - WGET_OPT_SPIDER = (1 << 1), - WGET_OPT_QUIET = (1 << 2), - WGET_OPT_OUTNAME = (1 << 3), - WGET_OPT_PREFIX = (1 << 4), - WGET_OPT_PROXY = (1 << 5), - WGET_OPT_USER_AGENT = (1 << 6), - WGET_OPT_RETRIES = (1 << 7), - WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 8), - WGET_OPT_PASSIVE = (1 << 9), - WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, -}; - static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) { char buf[512]; - - if (!(option_mask32 & WGET_OPT_QUIET)) - progress_meter(-1); +#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT +# if ENABLE_FEATURE_WGET_TIMEOUT + unsigned second_cnt; +# endif + struct pollfd polldata; + + polldata.fd = fileno(dfp); + polldata.events = POLLIN | POLLPRI; + ndelay(polldata.fd); +#endif + progress_meter(PROGRESS_START); if (G.chunked) goto get_clen; @@ -470,6 +476,23 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) rdsz = (unsigned)G.content_len; } } +#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT +# if ENABLE_FEATURE_WGET_TIMEOUT + second_cnt = G.timeout_seconds; +# endif + while (1) { + if (safe_poll(&polldata, 1, 1000) != 0) + break; /* error, EOF, or data is available */ +# if ENABLE_FEATURE_WGET_TIMEOUT + if (second_cnt != 0 && --second_cnt == 0) { + progress_meter(PROGRESS_END); + bb_perror_msg_and_die("download timed out"); + } +# endif + /* Needed for "stalled" indicator */ + progress_meter(PROGRESS_BUMP); + } +#endif n = safe_fread(buf, rdsz, dfp); if (n <= 0) { if (ferror(dfp)) { @@ -481,6 +504,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) xwrite(output_fd, buf, n); #if ENABLE_FEATURE_WGET_STATUSBAR G.transferred += n; + progress_meter(PROGRESS_BUMP); #endif if (G.got_clen) G.content_len -= n; @@ -499,8 +523,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) G.got_clen = 1; } - if (!(option_mask32 & WGET_OPT_QUIET)) - progress_meter(0); + progress_meter(PROGRESS_END); } int wget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -541,9 +564,11 @@ int wget_main(int argc UNUSED_PARAM, char **argv) "directory-prefix\0" Required_argument "P" "proxy\0" Required_argument "Y" "user-agent\0" Required_argument "U" +#if ENABLE_FEATURE_WGET_TIMEOUT + "timeout\0" Required_argument "T" +#endif /* Ignored: */ // "tries\0" Required_argument "t" - // "timeout\0" Required_argument "T" /* Ignored (we always use PASV): */ "passive-ftp\0" No_argument "\xff" "header\0" Required_argument "\xfe" @@ -559,12 +584,12 @@ int wget_main(int argc UNUSED_PARAM, char **argv) applet_long_options = wget_longopts; #endif /* server.allocated = target.allocated = NULL; */ - opt_complementary = "-1" IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::"); - opt = getopt32(argv, "csqO:P:Y:U:" /*ignored:*/ "t:T:", + opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::"); + opt = getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:", &fname_out, &dir_prefix, &proxy_flag, &user_agent, - NULL, /* -t RETRIES */ - NULL /* -T NETWORK_READ_TIMEOUT */ + IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL), + NULL /* -t RETRIES */ IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist) IF_FEATURE_WGET_LONG_OPTIONS(, &post_data) ); -- cgit v1.2.3-55-g6feb From 64f2ba276cb98f43dbc4e420d48330830aec29a8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Aug 2010 02:59:06 +0200 Subject: wget: make -T support enabled by default Signed-off-by: Denys Vlasenko --- networking/Config.src | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/Config.src b/networking/Config.src index 1d9a33f2b..9fc122bf3 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -1013,8 +1013,8 @@ config FEATURE_WGET_LONG_OPTIONS Support long options for the wget applet. config FEATURE_WGET_TIMEOUT - bool "Enable timeout options" - default n + bool "Enable read timeout option -T SEC" + default y depends on WGET help Supports network read timeout for wget, so that wget will give -- cgit v1.2.3-55-g6feb From da0df47f244be581f48fd50909d6a68ceae327a9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Aug 2010 04:21:50 +0200 Subject: wget: fix ndelay_on call; progress bar: small shrink function old new delta bb_progress_update 682 670 -12 Signed-off-by: Denys Vlasenko --- libbb/progress.c | 24 ++++++++++++------------ networking/wget.c | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libbb/progress.c b/libbb/progress.c index 7fb8536d2..f53271398 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -76,7 +76,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, elapsed = monotonic_sec(); since_last_update = elapsed - p->lastupdate_sec; /* Do not update on every call - * (might be: on every network read!) */ + * (we can be called on every network read!) */ if (since_last_update == 0 && !totalsize) return; @@ -84,7 +84,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, ratio = 100; if (beg_and_transferred < totalsize) { /* Do not update on every call - * (might be: on every network read!) */ + * (we can be called on every network read!) */ if (since_last_update == 0) return; /* long long helps to have it working even if !LFS */ @@ -118,14 +118,14 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, barlength = get_tty2_width() - 49; if (barlength > 0) { /* god bless gcc for variable arrays :) */ - i = barlength * ratio / 100; - { - char buf[i+1]; - memset(buf, '*', i); - buf[i] = '\0'; - fprintf(stderr, "|%s%*s|", buf, barlength - i, ""); - } + char buf[barlength + 1]; + unsigned stars = (unsigned)barlength * ratio / (unsigned)100; + memset(buf, ' ', barlength); + buf[barlength] = '\0'; + memset(buf, '*', stars); + fprintf(stderr, "|%s|", buf); } + i = 0; while (beg_and_transferred >= 100000) { i++; @@ -155,10 +155,10 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, fprintf(stderr, "--:--:-- ETA"); } else { /* to_download / (transferred/elapsed) - elapsed: */ - int eta = (int) ((unsigned long long)to_download*elapsed/transferred - elapsed); /* (long long helps to have working ETA even if !LFS) */ - i = eta % 3600; - fprintf(stderr, "%02d:%02d:%02d ETA", eta / 3600, i / 60, i % 60); + unsigned eta = (unsigned long long)to_download*elapsed/(uoff_t)transferred - elapsed; + unsigned secs = eta % 3600; + fprintf(stderr, "%02u:%02u:%02u ETA", eta / 3600, secs / 60, secs % 60); } } } diff --git a/networking/wget.c b/networking/wget.c index f62339071..fb8e51317 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -455,7 +455,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) polldata.fd = fileno(dfp); polldata.events = POLLIN | POLLPRI; - ndelay(polldata.fd); + ndelay_on(polldata.fd); #endif progress_meter(PROGRESS_START); -- cgit v1.2.3-55-g6feb From d07b20ff14a934c113a53210abb8a91ac587d9a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Aug 2010 13:06:06 +0200 Subject: rtc: remove useless code in "RTC is in UTC" detection Signed-off-by: Denys Vlasenko --- libbb/rtc.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libbb/rtc.c b/libbb/rtc.c index fcd6c64d7..97d18ed53 100644 --- a/libbb/rtc.c +++ b/libbb/rtc.c @@ -22,13 +22,6 @@ int FAST_FUNC rtc_adjtime_is_utc(void) char buffer[128]; while (fgets(buffer, sizeof(buffer), f)) { - int len = strlen(buffer); - - while (len && isspace(buffer[len - 1])) - len--; - - buffer[len] = 0; - if (strncmp(buffer, "UTC", 3) == 0) { utc = 1; break; -- cgit v1.2.3-55-g6feb From 81d9e60a88c471c585168659e41cf50aa3653a1c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Aug 2010 15:14:36 +0200 Subject: Set HWCLOCK_ADJTIME_FHS to off by default Signed-off-by: Denys Vlasenko --- util-linux/Config.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/Config.src b/util-linux/Config.src index 98953c17b..afa30923b 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src @@ -333,7 +333,7 @@ config FEATURE_HWCLOCK_LONG_OPTIONS config FEATURE_HWCLOCK_ADJTIME_FHS bool "Use FHS /var/lib/hwclock/adjtime" - default y + default n # util-linux-ng in Fedora 13 still uses /etc/adjtime depends on HWCLOCK help Starting with FHS 2.3, the adjtime state file is supposed to exist -- cgit v1.2.3-55-g6feb From f03fc7d77a5df53aae5eb2d02a49860dc2878da7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Aug 2010 05:15:52 +0200 Subject: ntpd: mention -N in help text Signed-off-by: Denys Vlasenko --- include/usage.src.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/usage.src.h b/include/usage.src.h index ebd8c2e6a..0eff1b129 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -2989,9 +2989,7 @@ INSERT "\n -d Verbose" \ "\n -n Do not daemonize" \ "\n -q Quit after clock is set" \ -/* -N exists for mostly compat reasons, thus not essential to inform */ \ -/* the user that it exists: user may use nice as well */ \ -/* "\n -N Run at high priority" */ \ + "\n -N Run at high priority" \ "\n -w Do not set time (only query peers), implies -n" \ "\n -l Run as server on port 123" \ "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" \ -- cgit v1.2.3-55-g6feb From 775965de859c6df5d5652f3f58edfd68803f0813 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 10 Aug 2010 23:33:57 -0700 Subject: Improved portability of tests Removed assumptions about umask and locale. Fixed hostname tests to work even when the host has no DNS domain set. Signed-off-by: Dan Fandrich Signed-off-by: Denys Vlasenko --- testsuite/cpio.tests | 2 ++ testsuite/date/date-works-1 | 3 +++ testsuite/du/du-k-works | 4 +++- testsuite/du/du-l-works | 3 +++ testsuite/hostname/hostname-d-works | 4 ++-- testsuite/makedevs.tests | 4 ++++ testsuite/tar.tests | 6 ++++++ testsuite/uuencode.tests | 3 +-- 8 files changed, 24 insertions(+), 5 deletions(-) diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index 7aee774a1..44c17e693 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests @@ -4,6 +4,8 @@ . ./testing.sh +umask 022 + # ls -ln shows date. Need to remove that, it's variable. # sed: coalesce spaces # cut: remove date diff --git a/testsuite/date/date-works-1 b/testsuite/date/date-works-1 index e745d3841..cb5cea2c5 100644 --- a/testsuite/date/date-works-1 +++ b/testsuite/date/date-works-1 @@ -1,4 +1,7 @@ unset LANG +unset LANGUAGE +unset LC_TIME +unset LC_ALL dt=`busybox date -d 1:2 +%T` test x"$dt" = x"01:02:00" diff --git a/testsuite/du/du-k-works b/testsuite/du/du-k-works index a52264945..229a948ee 100644 --- a/testsuite/du/du-k-works +++ b/testsuite/du/du-k-works @@ -1,4 +1,6 @@ +mkdir du.testdir +cd du.testdir dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null test x"`busybox du -k .`" = x"80 ." \ - -o x"`busybox du -k .`" = x"88 ." \ + -o x"`busybox du -k .`" = x"88 ." diff --git a/testsuite/du/du-l-works b/testsuite/du/du-l-works index 6b150e0dd..426ee891b 100644 --- a/testsuite/du/du-l-works +++ b/testsuite/du/du-l-works @@ -1,8 +1,11 @@ # FEATURE: CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K +mkdir du.testdir +cd du.testdir dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null ln file1 file1.1 dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null test x"`busybox du -l .`" = x"144 ." \ -o x"`busybox du -l .`" = x"148 ." \ -o x"`busybox du -l .`" = x"152 ." \ + -o x"`busybox du -l .`" = x"156 ." diff --git a/testsuite/hostname/hostname-d-works b/testsuite/hostname/hostname-d-works index e062242bb..54c0aac0c 100644 --- a/testsuite/hostname/hostname-d-works +++ b/testsuite/hostname/hostname-d-works @@ -1,3 +1,3 @@ -f=$(busybox hostname -f) +f=$(busybox hostname -f). d=$(busybox hostname -d) -test x"${f#*.}" = x"$d" +test x"${f#*.}" = x"$d${d:+.}" diff --git a/testsuite/makedevs.tests b/testsuite/makedevs.tests index f69b4a6b1..f19af8a52 100755 --- a/testsuite/makedevs.tests +++ b/testsuite/makedevs.tests @@ -4,6 +4,10 @@ . ./testing.sh +unset LANG +unset LC_COLLATE +unset LC_ALL + # ls -ln is showing date. Need to remove that, it's variable # sed: (1) "maj, min" -> "maj,min" (2) coalesce spaces # cut: remove date diff --git a/testsuite/tar.tests b/testsuite/tar.tests index f40079037..6604b4d22 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -4,6 +4,12 @@ . ./testing.sh +unset LANG +unset LANGUAGE +unset LC_COLLATE +unset LC_ALL +umask 022 + rm -rf tar.tempdir 2>/dev/null mkdir tar.tempdir && cd tar.tempdir || exit 1 diff --git a/testsuite/uuencode.tests b/testsuite/uuencode.tests index 6556e60d1..adb2d3390 100755 --- a/testsuite/uuencode.tests +++ b/testsuite/uuencode.tests @@ -13,11 +13,10 @@ # test can create a file "actual" instead of writing to stdout # Test setup of standard input -saved_umask=$(umask) umask 0 testing "uuencode sets standard input mode correctly" \ "uuencode foo 2!F;W@@:G5M<&5D(&]V97(@=&AE(&QA>GD@8G)O=VX@\n%9&]G+@H\`\n\`\nend\n" \ -- cgit v1.2.3-55-g6feb From 96693637403f59cd23af57f123f3543ba06dee0a Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 10 Aug 2010 23:45:27 -0700 Subject: Remove some more mentions of Subversion Signed-off-by: Dan Fandrich Signed-off-by: Denys Vlasenko --- README | 2 +- docs/new-applet-HOWTO.txt | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README b/README index 3a9d849a6..a3a725a5d 100644 --- a/README +++ b/README @@ -80,7 +80,7 @@ Downloading the current source code: The developers also have a bug and patch tracking system (https://bugs.busybox.net) although posting a bug/patch to the mailing list is generally a faster way of getting it fixed, and the complete archive of - what happened is the subversion changelog. + what happened is the git changelog. Note: if you want to compile busybox in a busybox environment you must select CONFIG_DESKTOP. diff --git a/docs/new-applet-HOWTO.txt b/docs/new-applet-HOWTO.txt index 0646e728e..7fbd62ed1 100644 --- a/docs/new-applet-HOWTO.txt +++ b/docs/new-applet-HOWTO.txt @@ -8,7 +8,7 @@ Matt Kraai - initial writeup Mark Whitley - the remix Thomas Lundquist - Trying to keep it updated. -When doing this you should consider using the latest svn trunk. +When doing this you should consider using the latest git HEAD. This is a good thing if you plan to getting it committed into mainline. Initial Write @@ -169,12 +169,13 @@ Be sure to read the top of applets.h before adding your applet. The Grand Announcement ---------------------- -Then create a diff by adding the new files with svn (remember your libbb files) - svn add /mu.c +Then create a diff by adding the new files to git (remember your libbb files) + git add /mu.c eventually also: - svn add libbb/function.c + git add libbb/function.c then - svn diff + git commit + git format-patch HEAD^ and send it to the mailing list: busybox@busybox.net http://busybox.net/mailman/listinfo/busybox -- cgit v1.2.3-55-g6feb From 1fbaf3a2d1f9abe1ee64acfc0927fdfedfdae998 Mon Sep 17 00:00:00 2001 From: Macpaul Lin Date: Thu, 5 Aug 2010 13:14:04 +0800 Subject: fdisk: Add support for NDS32 architecture. NDS32 is a new architecture invented by Andestech.com. This patch add the support to fdisk utility. Signed-off-by: Macpaul Lin Signed-off-by: Denys Vlasenko --- util-linux/fdisk_osf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c index b89a2b2af..79be0cd0f 100644 --- a/util-linux/fdisk_osf.c +++ b/util-linux/fdisk_osf.c @@ -46,7 +46,8 @@ #if defined(i386) || defined(__sparc__) || defined(__arm__) \ || defined(__m68k__) || defined(__mips__) || defined(__s390__) \ || defined(__s390__) || defined(__s390x__) \ - || defined(__sh__) || defined(__x86_64__) || defined(__avr32__) + || defined(__sh__) || defined(__x86_64__) || defined(__avr32__) \ + || defined(__nds32__) # define BSD_LABELSECTOR 1 # define BSD_LABELOFFSET 0 #elif defined(__alpha__) || defined(__powerpc__) || defined(__ia64__) \ -- cgit v1.2.3-55-g6feb From 58662f2c9376b526029935492b84d5b5829dfb1e Mon Sep 17 00:00:00 2001 From: Macpaul Lin Date: Thu, 5 Aug 2010 13:14:05 +0800 Subject: modutils: Add support for NDS32 architecture. Add support of NDS32 architecture to modutils. Signed-off-by: Macpaul Lin Signed-off-by: Denys Vlasenko --- modutils/modutils-24.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/modutils/modutils-24.c b/modutils/modutils-24.c index 7f39e253d..c42d3c0bb 100644 --- a/modutils/modutils-24.c +++ b/modutils/modutils-24.c @@ -90,6 +90,27 @@ #define USE_SINGLE #endif +/* NDS32 support */ +#if defined(__nds32__) || defined(__NDS32__) +#define CONFIG_USE_GOT_ENTRIES +#define CONFIG_GOT_ENTRY_SIZE 4 +#define CONFIG_USE_SINGLE + +#if defined(__NDS32_EB__) +#define MATCH_MACHINE(x) (x == EM_NDS32) +#define SHT_RELM SHT_RELA +#define Elf32_RelM Elf32_Rela +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__NDS32_EL__) +#define MATCH_MACHINE(x) (x == EM_NDS32) +#define SHT_RELM SHT_RELA +#define Elf32_RelM Elf32_Rela +#define ELFCLASSM ELFCLASS32 +#endif +#endif + /* blackfin */ #if defined(BFIN) #define MATCH_MACHINE(x) (x == EM_BLACKFIN) -- cgit v1.2.3-55-g6feb From 733f26f40708e0a4a2eb2475c446ae6a8e31f477 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 11 Aug 2010 17:00:59 +0200 Subject: iostat: new applet. 2800 bytes Signed-off-by: Marek Polacek Signed-off-by: Denys Vlasenko --- procps/iostat.c | 615 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 615 insertions(+) create mode 100644 procps/iostat.c diff --git a/procps/iostat.c b/procps/iostat.c new file mode 100644 index 000000000..573419e1c --- /dev/null +++ b/procps/iostat.c @@ -0,0 +1,615 @@ +/* vi: set sw=4 ts=4: */ +/* + * Report CPU and I/O stats, based on sysstat version 9.1.2 by Sebastien Godard + * + * Copyright (C) 2010 Marek Polacek + * + * Licensed under GPLv2, see file License in this tarball for details. + */ + +//applet:IF_IOSTAT(APPLET(iostat, _BB_DIR_BIN, _BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_IOSTAT) += iostat.o + +//config:config IOSTAT +//config: bool "iostat" +//config: default y +//config: help +//config: Report CPU and I/O statistics + +#include "libbb.h" +#include /* Need struct utsname */ + +#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) +//#define debug(fmt, ...) ((void)0) + +#define MAX_DEVICE_NAME 12 +#define CURRENT 0 +#define LAST 1 + +#if 1 +typedef unsigned long long cputime_t; +typedef long long icputime_t; +# define FMT_DATA "ll" +# define CPUTIME_MAX (~0ULL) +#else +typedef unsigned long cputime_t; +typedef long icputime_t; +# define FMT_DATA "l" +# define CPUTIME_MAX (~0UL) +#endif + +struct stats_cpu { + cputime_t cpu_user; + cputime_t cpu_nice; + cputime_t cpu_system; + cputime_t cpu_idle; + cputime_t cpu_iowait; + cputime_t cpu_steal; + cputime_t cpu_irq; + cputime_t cpu_softirq; + cputime_t cpu_guest; +}; + +struct stats_dev { + char dname[MAX_DEVICE_NAME]; + unsigned long long rd_sectors; + unsigned long long wr_sectors; + unsigned long rd_ops; + unsigned long wr_ops; +}; + +/* List of devices entered on the command line */ +struct device_list { + char dname[MAX_DEVICE_NAME]; +}; + +/* Globals. Sort by size and access frequency. */ +struct globals { + smallint show_all; + unsigned devlist_i; /* Index to the list of devices */ + unsigned total_cpus; /* Number of CPUs */ + unsigned clk_tck; /* Number of clock ticks per second */ + struct device_list *dlist; + struct stats_dev *saved_stats_dev; + struct tm tmtime; +}; +#define G (*ptr_to_globals) +#define INIT_G() do { \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ +} while (0) + +/* Must match option string! */ +enum { + OPT_c = 1 << 0, + OPT_d = 1 << 1, + OPT_t = 1 << 2, + OPT_z = 1 << 3, + OPT_k = 1 << 4, + OPT_m = 1 << 5, +}; + +static ALWAYS_INLINE unsigned get_user_hz(void) +{ + return sysconf(_SC_CLK_TCK); +} + +static ALWAYS_INLINE int this_is_smp(void) +{ + return (G.total_cpus > 1); +} + +static void print_header(void) +{ + char buf[16]; + struct utsname uts; + + if (uname(&uts) < 0) + bb_perror_msg_and_die("uname"); + + strftime(buf, sizeof(buf), "%x", &G.tmtime); + + printf("%s %s (%s) \t%s \t_%s_\t(%d CPU)\n\n", + uts.sysname, uts.release, uts.nodename, + buf, uts.machine, G.total_cpus); +} + +static int get_number_of_cpus(void) +{ +#ifdef _SC_NPROCESSORS_CONF + return sysconf(_SC_NPROCESSORS_CONF); +#else + char buf[128]; + int n = 0; + FILE *fp; + + fp = xfopen_for_read("/proc/cpuinfo"); + + while (fgets(buf, sizeof(buf), fp)) + if (strncmp(buf, "processor\t:", 11) == 0) + n++; + + fclose(fp); + return n; +#endif +} + +static void get_localtime(struct tm *ptm) +{ + time_t timer; + time(&timer); + localtime_r(&timer, ptm); +} + +static void print_timestamp(void) +{ + char buf[20]; + strftime(buf, sizeof(buf), "%x %X", &G.tmtime); + printf("%s\n", buf); +} + +/* Does str start with "cpu"? */ +static int starts_with_cpu(const char *str) +{ + return ((str[0] - 'c') | (str[1] - 'p') | (str[2] - 'u')) == 0; +} + +/* Fetch CPU statistics from /proc/stat */ +static void get_cpu_statistics(struct stats_cpu *sc) +{ + FILE *fp; + char buf[1024]; + + fp = xfopen_for_read("/proc/stat"); + + memset(sc, 0, sizeof(*sc)); + + while (fgets(buf, sizeof(buf), fp)) { + /* Does the line starts with "cpu "? */ + if (starts_with_cpu(buf) && buf[3] == ' ') { + sscanf(buf + 4 + 1, + "%"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %" + FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u", + &sc->cpu_user, &sc->cpu_nice, &sc->cpu_system, + &sc->cpu_idle, &sc->cpu_iowait, &sc->cpu_irq, + &sc->cpu_softirq, &sc->cpu_steal, &sc->cpu_guest); + } + } + + fclose(fp); +} + +static cputime_t get_smp_uptime(void) +{ + FILE *fp; + char buf[sizeof(long)*3 * 2 + 4]; + unsigned long sec, dec; + + fp = xfopen_for_read("/proc/uptime"); + + if (fgets(buf, sizeof(buf), fp)) + if (sscanf(buf, "%lu.%lu", &sec, &dec) != 2) + bb_error_msg_and_die("can't read /proc/uptime"); + + fclose(fp); + + return (cputime_t)sec * G.clk_tck + dec * G.clk_tck / 100; +} + +/* + * Obtain current uptime in jiffies. + * Uptime is sum of individual CPUs' uptimes. + */ +static cputime_t get_uptime(const struct stats_cpu *sc) +{ + /* NB: Don't include cpu_guest, it is already in cpu_user */ + return sc->cpu_user + sc->cpu_nice + sc->cpu_system + sc->cpu_idle + + + sc->cpu_iowait + sc->cpu_irq + sc->cpu_steal + sc->cpu_softirq; +} + +static ALWAYS_INLINE cputime_t get_interval(cputime_t old, cputime_t new) +{ + cputime_t itv = new - old; + + return (itv == 0) ? 1 : itv; +} + +#if CPUTIME_MAX > 0xffffffff +/* + * Handle overflow conditions properly for counters which can have + * less bits than cputime_t, depending on the kernel version. + */ +/* Surprisingly, on 32bit inlining is a size win */ +static ALWAYS_INLINE cputime_t overflow_safe_sub(cputime_t prev, cputime_t curr) +{ + cputime_t v = curr - prev; + + if ((icputime_t)v < 0 /* curr < prev - counter overflow? */ + && prev <= 0xffffffff /* kernel uses 32bit value for the counter? */ + ) { + /* Add 33th bit set to 1 to curr, compensating for the overflow */ + /* double shift defeats "warning: left shift count >= width of type" */ + v += ((cputime_t)1 << 16) << 16; + } + return v; +} +#else +static ALWAYS_INLINE cputime_t overflow_safe_sub(cputime_t prev, cputime_t curr) +{ + return curr - prev; +} +#endif + +static double percent_value(cputime_t prev, cputime_t curr, cputime_t itv) +{ + return ((double)overflow_safe_sub(prev, curr)) / itv * 100; +} + +static void print_stats_cpu_struct(const struct stats_cpu *p, + const struct stats_cpu *c, cputime_t itv) +{ + printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", + percent_value(p->cpu_user , c->cpu_user , itv), + percent_value(p->cpu_nice , c->cpu_nice , itv), + percent_value(p->cpu_system + p->cpu_softirq + p->cpu_irq, + c->cpu_system + c->cpu_softirq + c->cpu_irq, itv), + percent_value(p->cpu_iowait , c->cpu_iowait , itv), + percent_value(p->cpu_steal , c->cpu_steal , itv), + percent_value(p->cpu_idle , c->cpu_idle , itv) + ); +} + +static void print_stats_dev_struct(const struct stats_dev *p, + const struct stats_dev *c, cputime_t itv) +{ + int unit = 1; + + if (option_mask32 & OPT_k) + unit = 2; + else if (option_mask32 & OPT_m) + unit = 2048; + + if (option_mask32 & OPT_z) + if (p->rd_ops == c->rd_ops && p->wr_ops == c->wr_ops) + return; + + printf("%-13s", c->dname); + printf(" %8.2f %12.2f %12.2f %10llu %10llu \n", + percent_value(p->rd_ops + p->wr_ops , + /**/ c->rd_ops + c->wr_ops , itv), + percent_value(p->rd_sectors, c->rd_sectors, itv) / unit, + percent_value(p->wr_sectors, c->wr_sectors, itv) / unit, + (c->rd_sectors - p->rd_sectors) / unit, + (c->wr_sectors - p->wr_sectors) / unit); +} + +static void cpu_report(const struct stats_cpu *last, + const struct stats_cpu *cur, + cputime_t itv) +{ + /* Always print a header */ + puts("avg-cpu: %user %nice %system %iowait %steal %idle"); + + /* Print current statistics */ + print_stats_cpu_struct(last, cur, itv); +} + +static void print_devstat_header(void) +{ + printf("Device: tps"); + + if (option_mask32 & OPT_m) + puts(" MB_read/s MB_wrtn/s MB_read MB_wrtn"); + else if (option_mask32 & OPT_k) + puts(" kB_read/s kB_wrtn/s kB_read kB_wrtn"); + else + puts(" Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn"); +} + +/* + * Is input partition of format [sdaN]? + */ +static int is_partition(const char *dev) +{ + /* Ok, this is naive... */ + return ((dev[0] - 's') | (dev[1] - 'd') | (dev[2] - 'a')) == 0 && isdigit(dev[3]); +} + +/* + * Return number of numbers on cmdline. + * Reasonable values are only 0 (no interval/count specified), + * 1 (interval specified) and 2 (both interval and count specified) + */ +static int numbers_on_cmdline(int argc, char *argv[]) +{ + int sum = 0; + + if (isdigit(argv[argc-1][0])) + sum++; + if (argc > 2 && isdigit(argv[argc-2][0])) + sum++; + + return sum; +} + +static int is_dev_in_dlist(const char *dev) +{ + int i; + + /* Go through the device list */ + for (i = 0; i < G.devlist_i; i++) + if (strcmp(G.dlist[i].dname, dev) == 0) + /* Found a match */ + return 1; + + /* No match found */ + return 0; +} + +static void do_disk_statistics(cputime_t itv) +{ + FILE *fp; + int rc; + int i = 0; + char buf[128]; + unsigned major, minor; + unsigned long wr_ops, dummy; /* %*lu for suppres the conversion wouldn't work */ + unsigned long long rd_sec_or_wr_ops; + unsigned long long rd_sec_or_dummy, wr_sec_or_dummy, wr_sec; + struct stats_dev sd; + + fp = xfopen_for_read("/proc/diskstats"); + + /* Read and possibly print stats from /proc/diskstats */ + while (fgets(buf, sizeof(buf), fp)) { + rc = sscanf(buf, "%u %u %s %lu %llu %llu %llu %lu %lu %llu %lu %lu %lu %lu", + &major, &minor, sd.dname, &sd.rd_ops, + &rd_sec_or_dummy, &rd_sec_or_wr_ops, &wr_sec_or_dummy, + &wr_ops, &dummy, &wr_sec, &dummy, &dummy, &dummy, &dummy); + + switch (rc) { + case 14: + sd.wr_ops = wr_ops; + sd.rd_sectors = rd_sec_or_wr_ops; + sd.wr_sectors = wr_sec; + break; + case 7: + sd.rd_sectors = rd_sec_or_dummy; + sd.wr_ops = (unsigned long)rd_sec_or_wr_ops; + sd.wr_sectors = wr_sec_or_dummy; + break; + default: + break; + } + + if (!G.devlist_i && !is_partition(sd.dname)) { + /* User didn't specify device */ + if (!G.show_all && !sd.rd_ops && !sd.wr_ops) { + /* Don't print unused device */ + continue; + } + print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv); + G.saved_stats_dev[i] = sd; + i++; + } else { + /* Is device in device list? */ + if (is_dev_in_dlist(sd.dname)) { + /* Print current statistics */ + print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv); + G.saved_stats_dev[i] = sd; + i++; + } else + continue; + } + } +} + +static void dev_report(cputime_t itv) +{ + /* Always print a header */ + print_devstat_header(); + + /* Fetch current disk statistics */ + do_disk_statistics(itv); +} + +static void save_to_devlist(const char *dname) +{ + int i; + struct device_list *tmp = G.dlist; + + if (strncmp(dname, "/dev/", 5) == 0) + /* We'll ignore prefix '/dev/' */ + dname += 5; + + /* Go through the list */ + for (i = 0; i < G.devlist_i; i++, tmp++) + if (strcmp(tmp->dname, dname) == 0) + /* Already in the list */ + return; + + /* Add device name to the list */ + strncpy(tmp->dname, dname, MAX_DEVICE_NAME - 1); + + /* Update device list index */ + G.devlist_i++; +} + +static unsigned get_number_of_devices(void) +{ + FILE *fp; + char buf[128]; + int rv; + unsigned n = 0; + unsigned long rd_ops, wr_ops; + char dname[MAX_DEVICE_NAME]; + + fp = xfopen_for_read("/proc/diskstats"); + + while (fgets(buf, sizeof(buf), fp)) { + rv = sscanf(buf, "%*d %*d %s %lu %*u %*u %*u %lu", + dname, &rd_ops, &wr_ops); + if (rv == 2 || is_partition(dname)) + /* A partition */ + continue; + if (!rd_ops && !wr_ops) { + /* Unused device */ + if (!G.show_all) + continue; + } + n++; + } + + fclose(fp); + return n; +} + +static int number_of_ALL_on_cmdline(char **argv) +{ + int alls = 0; + + /* Iterate over cmd line arguments, count "ALL" */ + while (*argv) + if (strcmp(*argv++, "ALL") == 0) + alls++; + + return alls; +} + +//usage:#define iostat_trivial_usage +//usage: "[-c] [-d] [-t] [-z] [-k|-m] [ALL|BLOCKDEV...] [INTERVAL [COUNT]]" +//usage:#define iostat_full_usage "\n\n" +//usage: "Report CPU and I/O statistics\n" +//usage: "\nOptions:" +//usage: "\n -c Show CPU utilization" +//usage: "\n -d Show device utilization" +//usage: "\n -t Print current time" +//usage: "\n -z Omit devices with no activity" +//usage: "\n -k Use kb/s" +//usage: "\n -m Use Mb/s" + +int iostat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int iostat_main(int argc, char **argv) +{ + int opt, dev_num; + unsigned interval = 0; + int count = 0; + cputime_t global_uptime[2] = { 0 }; + cputime_t smp_uptime[2] = { 0 }; + cputime_t itv; + struct stats_cpu stats_cur, stats_last; + + INIT_G(); + + memset(&stats_last, 0, sizeof(stats_last)); + + /* Get number of clock ticks per sec */ + G.clk_tck = get_user_hz(); + + /* Determine number of CPUs */ + G.total_cpus = get_number_of_cpus(); + + /* Parse and process arguments */ + /* -k and -m are mutually exclusive */ + opt_complementary = "k--m:m--k"; + opt = getopt32(argv, "cdtzkm"); + if (!(opt & (OPT_c + OPT_d))) + /* Default is -cd */ + opt |= OPT_c + OPT_d; + + argv += optind; + argc -= optind; + + dev_num = argc - numbers_on_cmdline(argc, argv); + /* We don't want to allocate space for 'ALL' */ + dev_num -= number_of_ALL_on_cmdline(argv); + if (dev_num > 0) + /* Make space for device list */ + G.dlist = xzalloc(sizeof(G.dlist[0]) * dev_num); + + /* Store device names into device list */ + while (*argv && !isdigit(*argv[0])) { + if (strcmp(*argv, "ALL") != 0) + /* If not ALL, save device name */ + save_to_devlist(*argv); + else + G.show_all = 1; + argv++; + } + + if (*argv) { + /* Get interval */ + interval = xatoi_u(*argv); + count = interval ? -1 : 1; + argv++; + if (*argv) + /* Get count value */ + count = xatoi_u(*argv); + } + + /* Allocate space for device stats */ + if (opt & OPT_d) { + G.saved_stats_dev = xzalloc(sizeof(G.saved_stats_dev[0]) * + (dev_num ? dev_num : get_number_of_devices()) + ); + } + + /* Display header */ + print_header(); + + /* Main loop */ + for (;;) { + /* Fill the time structure */ + get_localtime(&G.tmtime); + + /* Fetch current CPU statistics */ + get_cpu_statistics(&stats_cur); + + /* Fetch current uptime */ + global_uptime[CURRENT] = get_uptime(&stats_cur); + + /* Get interval */ + itv = get_interval(global_uptime[LAST], global_uptime[CURRENT]); + + if (opt & OPT_t) + print_timestamp(); + + if (opt & OPT_c) { + cpu_report(&stats_last, &stats_cur, itv); + if (opt & OPT_d) + /* Separate outputs by a newline */ + bb_putchar('\n'); + } + + if (opt & OPT_d) { + if (this_is_smp()) { + smp_uptime[CURRENT] = get_smp_uptime(); + itv = get_interval(smp_uptime[LAST], smp_uptime[CURRENT]); + smp_uptime[LAST] = smp_uptime[CURRENT]; + } + dev_report(itv); + } + + if (count > 0) { + if (--count == 0) + break; + } + + /* Backup current stats */ + global_uptime[LAST] = global_uptime[CURRENT]; + stats_last = stats_cur; + + bb_putchar('\n'); + sleep(interval); + } + + bb_putchar('\n'); + + if (ENABLE_FEATURE_CLEAN_UP) { + free(&G); + free(G.dlist); + free(G.saved_stats_dev); + } + + return EXIT_SUCCESS; +} -- cgit v1.2.3-55-g6feb From 7bfbbd434a6f435b0287cd25406927c630b03f68 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 12 Aug 2010 01:56:44 +0200 Subject: free: more compatible output. +16 bytes. Closes bug 2383. Signed-off-by: Denys Vlasenko --- procps/free.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/procps/free.c b/procps/free.c index 473d70be8..db70712cf 100644 --- a/procps/free.c +++ b/procps/free.c @@ -53,29 +53,41 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) info.bufferram *= mem_unit; } - printf(" %13s%13s%13s%13s%13s\n", + printf(" %13s%13s%13s%13s%13s\n", "total", "used", "free", "shared", "buffers" /* swap and total don't have these columns */ + /* procps version 3.2.8 also shows "cached" column, but + * sysinfo() does not provide this value, need to parse + * /proc/meminfo instead and get "Cached: NNN kB" from there. + */ ); - printf("%6s%13lu%13lu%13lu%13lu%13lu\n", "Mem:", +#define FIELDS_5 "%13lu%13lu%13lu%13lu%13lu\n" +#define FIELDS_3 (FIELDS_5 + 2*5) +#define FIELDS_2 (FIELDS_5 + 3*5) + printf("Mem: "); + printf(FIELDS_5, info.totalram, info.totalram - info.freeram, info.freeram, info.sharedram, info.bufferram ); + /* Show alternate, more meaningful busy/free numbers by counting + * buffer cache as free memory (make it "-/+ buffers/cache" + * if/when we add support for "cached" column): */ + printf("-/+ buffers: "); + printf(FIELDS_2, + info.totalram - info.freeram - info.bufferram, + info.freeram + info.bufferram + ); #if BB_MMU - printf("%6s%13lu%13lu%13lu\n", "Swap:", + printf("Swap:"); + printf(FIELDS_3, info.totalswap, info.totalswap - info.freeswap, info.freeswap ); - printf("%6s%13lu%13lu%13lu\n", "Total:", - info.totalram + info.totalswap, - (info.totalram - info.freeram) + (info.totalswap - info.freeswap), - info.freeram + info.freeswap - ); #endif return EXIT_SUCCESS; } -- cgit v1.2.3-55-g6feb From 7783248eaac715b813f0635b06cc140ea99bb4d9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 12 Aug 2010 14:14:45 +0200 Subject: *: s/xatoi_u/xatoi_positive/g - I got bored of mistyping xatoi_u as xatou_i Signed-off-by: Denys Vlasenko --- coreutils/cut.c | 4 ++-- coreutils/date.c | 2 +- debianutils/start_stop_daemon.c | 2 +- e2fsprogs/fsck.c | 4 ++-- e2fsprogs/old_e2fsprogs/mke2fs.c | 6 +++--- findutils/find.c | 2 +- include/libbb.h | 11 ++++++++--- libbb/getopt32.c | 6 +++--- libbb/xatonum.c | 2 +- miscutils/fbsplash.c | 2 +- miscutils/hdparm.c | 4 ++-- miscutils/ionice.c | 2 +- miscutils/makedevs.c | 8 ++++---- miscutils/mt.c | 2 +- miscutils/rfkill.c | 2 +- networking/brctl.c | 2 +- networking/ftpd.c | 2 +- networking/wget.c | 2 +- printutils/lpd.c | 2 +- procps/iostat.c | 4 ++-- procps/mpstat.c | 6 +++--- procps/nmeter.c | 2 +- runit/svlogd.c | 6 +++--- shell/hush.c | 2 +- util-linux/flock.c | 2 +- util-linux/hexdump.c | 2 +- util-linux/mount.c | 2 +- 27 files changed, 49 insertions(+), 44 deletions(-) diff --git a/coreutils/cut.c b/coreutils/cut.c index 696478bb2..b7a3cfabb 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c @@ -224,7 +224,7 @@ int cut_main(int argc UNUSED_PARAM, char **argv) if (!ntok[0]) { s = BOL; } else { - s = xatoi_u(ntok); + s = xatoi_positive(ntok); /* account for the fact that arrays are zero based, while * the user expects the first char on the line to be char #1 */ if (s != 0) @@ -237,7 +237,7 @@ int cut_main(int argc UNUSED_PARAM, char **argv) } else if (!ltok[0]) { e = EOL; } else { - e = xatoi_u(ltok); + e = xatoi_positive(ltok); /* if the user specified and end position of 0, * that means "til the end of the line" */ if (e == 0) diff --git a/coreutils/date.c b/coreutils/date.c index cb41724af..3ce352c8d 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -300,7 +300,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) scale = 1; pres = 9; if (n) { - pres = xatoi_u(p); + pres = xatoi_positive(p); if (pres == 0) pres = 9; m = 9 - pres; diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 665f38fbd..568f32eec 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -373,7 +373,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) // IF_FEATURE_START_STOP_DAEMON_FANCY( // if (retry_arg) -// retries = xatoi_u(retry_arg); +// retries = xatoi_positive(retry_arg); // ) //argc -= optind; argv += optind; diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index 7c449e3e7..d694bb110 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c @@ -972,13 +972,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) case 'C': progress = 1; if (arg[++j]) { /* -Cn */ - progress_fd = xatoi_u(&arg[j]); + progress_fd = xatoi_positive(&arg[j]); goto next_arg; } /* -C n */ if (!*++argv) bb_show_usage(); - progress_fd = xatoi_u(*argv); + progress_fd = xatoi_positive(*argv); goto next_arg; #endif case 'V': diff --git a/e2fsprogs/old_e2fsprogs/mke2fs.c b/e2fsprogs/old_e2fsprogs/mke2fs.c index 520364550..f1e97b96a 100644 --- a/e2fsprogs/old_e2fsprogs/mke2fs.c +++ b/e2fsprogs/old_e2fsprogs/mke2fs.c @@ -895,7 +895,7 @@ static int PRS(int argc, char **argv) creator_os = optarg; break; case 'r': - param.s_rev_level = xatoi_u(optarg); + param.s_rev_level = xatoi_positive(optarg); if (param.s_rev_level == EXT2_GOOD_OLD_REV) { param.s_feature_incompat = 0; param.s_feature_compat = 0; @@ -912,11 +912,11 @@ static int PRS(int argc, char **argv) break; #ifdef EXT2_DYNAMIC_REV case 'I': - inode_size = xatoi_u(optarg); + inode_size = xatoi_positive(optarg); break; #endif case 'N': - num_inodes = xatoi_u(optarg); + num_inodes = xatoi_positive(optarg); break; case 'v': quiet = 0; diff --git a/findutils/find.c b/findutils/find.c index 297081489..d4bcd6545 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -1210,7 +1210,7 @@ IF_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,) if (opt == OPT_MINDEPTH || opt == OPT_MINDEPTH + 1) { if (!argp[1]) bb_show_usage(); - minmaxdepth[opt - OPT_MINDEPTH] = xatoi_u(argp[1]); + minmaxdepth[opt - OPT_MINDEPTH] = xatoi_positive(argp[1]); argp[0] = (char*)"-a"; argp[1] = (char*)"-a"; argp++; diff --git a/include/libbb.h b/include/libbb.h index 118d777bc..03fc5d44b 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -190,7 +190,7 @@ typedef unsigned long long uoff_t; /* While sizeof(off_t) == sizeof(int), off_t is typedef'ed to long anyway. * gcc will throw warnings on printf("%d", off_t). Crap... */ typedef unsigned long uoff_t; -# define XATOOFF(a) xatoi_u(a) +# define XATOOFF(a) xatoi_positive(a) # define BB_STRTOOFF bb_strtou # define STRTOOFF strtol # define OFF_FMT "l" @@ -765,11 +765,16 @@ struct suffix_mult { }; #include "xatonum.h" /* Specialized: */ + /* Using xatoi() instead of naive atoi() is not always convenient - * in many places people want *non-negative* values, but store them * in signed int. Therefore we need this one: - * dies if input is not in [0, INT_MAX] range. Also will reject '-0' etc */ -int xatoi_u(const char *numstr) FAST_FUNC; + * dies if input is not in [0, INT_MAX] range. Also will reject '-0' etc. + * It should really be named xatoi_nonnegative (since it allows 0), + * but that would be too long. + */ +int xatoi_positive(const char *numstr) FAST_FUNC; + /* Useful for reading port numbers */ uint16_t xatou16(const char *numstr) FAST_FUNC; diff --git a/libbb/getopt32.c b/libbb/getopt32.c index b5f83c127..8c87fe3f0 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c @@ -233,7 +233,7 @@ Special characters: "a+" A plus after a char in opt_complementary means that the parameter for this option is a nonnegative integer. It will be processed - with xatoi_u() - allowed range is 0..INT_MAX. + with xatoi_positive() - allowed range is 0..INT_MAX. int param; // "unsigned param;" will also work opt_complementary = "p+"; @@ -579,8 +579,8 @@ getopt32(char **argv, const char *applet_opts, ...) llist_add_to_end((llist_t **)(on_off->optarg), optarg); } else if (on_off->param_type == PARAM_INT) { if (optarg) -//TODO: xatoi_u indirectly pulls in printf machinery - *(unsigned*)(on_off->optarg) = xatoi_u(optarg); +//TODO: xatoi_positive indirectly pulls in printf machinery + *(unsigned*)(on_off->optarg) = xatoi_positive(optarg); } else if (on_off->optarg) { if (optarg) *(char **)(on_off->optarg) = optarg; diff --git a/libbb/xatonum.c b/libbb/xatonum.c index 3cdf63425..60b65f525 100644 --- a/libbb/xatonum.c +++ b/libbb/xatonum.c @@ -59,7 +59,7 @@ unsigned bb_strtoui(const char *str, char **end, int b) /* A few special cases */ -int FAST_FUNC xatoi_u(const char *numstr) +int FAST_FUNC xatoi_positive(const char *numstr) { return xatou_range(numstr, 0, INT_MAX); } diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c index e370d207b..a031cbd3a 100644 --- a/miscutils/fbsplash.c +++ b/miscutils/fbsplash.c @@ -311,7 +311,7 @@ static void init(const char *cfg_filename) parser_t *parser = config_open2(cfg_filename, xfopen_stdin); while (config_read(parser, token, 2, 2, "#=", (PARSE_NORMAL | PARSE_MIN_DIE) & ~(PARSE_TRIM | PARSE_COLLAPSE))) { - unsigned val = xatoi_u(token[1]); + unsigned val = xatoi_positive(token[1]); int i = index_in_strings(param_names, token[0]); if (i < 0) bb_error_msg_and_die("syntax error: %s", token[0]); diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index 236b1749c..c6ca3af80 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c @@ -2055,8 +2055,8 @@ int hdparm_main(int argc, char **argv) #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF if (c == 'R') { scan_hwif = parse_opts_0_INTMAX(&hwif_data); - hwif_ctrl = xatoi_u((argv[optind]) ? argv[optind] : ""); - hwif_irq = xatoi_u((argv[optind+1]) ? argv[optind+1] : ""); + hwif_ctrl = xatoi_positive((argv[optind]) ? argv[optind] : ""); + hwif_irq = xatoi_positive((argv[optind+1]) ? argv[optind+1] : ""); /* Move past the 2 additional arguments */ argv += 2; argc -= 2; diff --git a/miscutils/ionice.c b/miscutils/ionice.c index 52e51b908..6b791c491 100644 --- a/miscutils/ionice.c +++ b/miscutils/ionice.c @@ -73,7 +73,7 @@ int ionice_main(int argc UNUSED_PARAM, char **argv) if (!(opt & (OPT_n|OPT_c))) { if (!(opt & OPT_p) && *argv) - pid = xatoi_u(*argv); + pid = xatoi_positive(*argv); pri = ioprio_get(IOPRIO_WHO_PROCESS, pid); if (pri == -1) diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c index abf505770..0578d9251 100644 --- a/miscutils/makedevs.c +++ b/miscutils/makedevs.c @@ -36,10 +36,10 @@ int makedevs_main(int argc, char **argv) basedev = argv[1]; buf = xasprintf("%s%u", argv[1], (unsigned)-1); type = argv[2]; - Smajor = xatoi_u(argv[3]); - Sminor = xatoi_u(argv[4]); - S = xatoi_u(argv[5]); - E = xatoi_u(argv[6]); + Smajor = xatoi_positive(argv[3]); + Sminor = xatoi_positive(argv[4]); + S = xatoi_positive(argv[5]); + E = xatoi_positive(argv[6]); nodname = argv[7] ? basedev : buf; mode = 0660; diff --git a/miscutils/mt.c b/miscutils/mt.c index 586373d13..8df2b75f7 100644 --- a/miscutils/mt.c +++ b/miscutils/mt.c @@ -106,7 +106,7 @@ int mt_main(int argc UNUSED_PARAM, char **argv) op.mt_op = opcode_value[idx]; if (argv[2]) - op.mt_count = xatoi_u(argv[2]); + op.mt_count = xatoi_positive(argv[2]); else op.mt_count = 1; /* One, not zero, right? */ diff --git a/miscutils/rfkill.c b/miscutils/rfkill.c index 0f5817b76..7d8ad1cfc 100644 --- a/miscutils/rfkill.c +++ b/miscutils/rfkill.c @@ -53,7 +53,7 @@ int rfkill_main(int argc UNUSED_PARAM, char **argv) rf_name = "uwb"; rf_type = index_in_strings(rfkill_types, rf_name); if (rf_type < 0) { - rf_idx = xatoi_u(rf_name); + rf_idx = xatoi_positive(rf_name); } } diff --git a/networking/brctl.c b/networking/brctl.c index a36ab45c3..0f56412ce 100644 --- a/networking/brctl.c +++ b/networking/brctl.c @@ -271,7 +271,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) } } arg1 = port; - arg2 = xatoi_u(*argv); + arg2 = xatoi_positive(*argv); if (key == ARG_setbridgeprio) { arg1 = arg2; arg2 = 0; diff --git a/networking/ftpd.c b/networking/ftpd.c index e8cae0a36..0daf9f7a3 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -534,7 +534,7 @@ static void handle_rest(void) { /* When ftp_arg == NULL simply restart from beginning */ - G.restart_pos = G.ftp_arg ? xatoi_u(G.ftp_arg) : 0; + G.restart_pos = G.ftp_arg ? xatoi_positive(G.ftp_arg) : 0; WRITE_OK(FTP_RESTOK); } diff --git a/networking/wget.c b/networking/wget.c index fb8e51317..784e405da 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -213,7 +213,7 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp, char *buf) } while (!isdigit(buf[0]) || buf[3] != ' '); buf[3] = '\0'; - result = xatoi_u(buf); + result = xatoi_positive(buf); buf[3] = ' '; return result; } diff --git a/printutils/lpd.c b/printutils/lpd.c index d91491f1b..54ff2227e 100644 --- a/printutils/lpd.c +++ b/printutils/lpd.c @@ -135,7 +135,7 @@ int lpd_main(int argc UNUSED_PARAM, char *argv[]) while (1) { char *fname; int fd; - // int is easier than ssize_t: can use xatoi_u, + // int is easier than ssize_t: can use xatoi_positive, // and can correctly display error returns (-1) int expected_len, real_len; diff --git a/procps/iostat.c b/procps/iostat.c index 573419e1c..8641c2391 100644 --- a/procps/iostat.c +++ b/procps/iostat.c @@ -539,12 +539,12 @@ int iostat_main(int argc, char **argv) if (*argv) { /* Get interval */ - interval = xatoi_u(*argv); + interval = xatoi_positive(*argv); count = interval ? -1 : 1; argv++; if (*argv) /* Get count value */ - count = xatoi_u(*argv); + count = xatoi_positive(*argv); } /* Allocate space for device stats */ diff --git a/procps/mpstat.c b/procps/mpstat.c index 7610a68fb..85cbb45db 100644 --- a/procps/mpstat.c +++ b/procps/mpstat.c @@ -930,14 +930,14 @@ int mpstat_main(int UNUSED_PARAM argc, char **argv) if (*argv) { /* Get interval */ - G.interval = xatoi_u(*argv); + G.interval = xatoi_positive(*argv); G.count = -1; argv++; if (*argv) { /* Get count value */ if (G.interval == 0) bb_show_usage(); - G.count = xatoi_u(*argv); + G.count = xatoi_positive(*argv); //if (*++argv) // bb_show_usage(); } @@ -979,7 +979,7 @@ int mpstat_main(int UNUSED_PARAM argc, char **argv) memset(G.cpu_bitmap, 0xff, G.cpu_bitmap_len); } else { /* Get CPU number */ - unsigned n = xatoi_u(t); + unsigned n = xatoi_positive(t); if (n >= G.cpu_nr) bb_error_msg_and_die("not that many processors"); n++; diff --git a/procps/nmeter.c b/procps/nmeter.c index bb1e819a6..930585695 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -422,7 +422,7 @@ static s_stat* init_int(const char *param) if (param[0] == '\0') { s->no = 1; } else { - int n = xatoi_u(param); + int n = xatoi_positive(param); s->no = n + 2; } return (s_stat*)s; diff --git a/runit/svlogd.c b/runit/svlogd.c index 9fe81b900..1f0a77cc2 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c @@ -688,10 +688,10 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn) break; } case 'n': - ld->nmax = xatoi_u(&s[1]); + ld->nmax = xatoi_positive(&s[1]); break; case 'N': - ld->nmin = xatoi_u(&s[1]); + ld->nmin = xatoi_positive(&s[1]); break; case 't': { static const struct suffix_mult mh_suffixes[] = { @@ -981,7 +981,7 @@ int svlogd_main(int argc, char **argv) linemax = 256; } ////if (opt & 8) { // -b - //// buflen = xatoi_u(b); + //// buflen = xatoi_positive(b); //// if (buflen == 0) buflen = 1024; ////} //if (opt & 0x10) timestamp++; // -t diff --git a/shell/hush.c b/shell/hush.c index 0a420f685..df4058998 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2788,7 +2788,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char /* lookup the variable in question */ if (isdigit(var[0])) { /* parse_dollar() should have vetted var for us */ - i = xatoi_u(var); + i = xatoi_positive(var); if (i < G.global_argc) val = G.global_argv[i]; /* else val remains NULL: $N with too big N */ diff --git a/util-linux/flock.c b/util-linux/flock.c index 78b1e4ba3..be3d552fa 100644 --- a/util-linux/flock.c +++ b/util-linux/flock.c @@ -40,7 +40,7 @@ int flock_main(int argc UNUSED_PARAM, char **argv) bb_perror_msg_and_die("can't open '%s'", argv[0]); //TODO? close_on_exec_on(fd); } else { - fd = xatoi_u(argv[0]); + fd = xatoi_positive(argv[0]); } argv++; diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 2eb5e57ae..7b89e6fdc 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c @@ -90,7 +90,7 @@ int hexdump_main(int argc, char **argv) bb_dump_addfile(dumper, optarg); } /* else */ if (ch == 'n') { - dumper->dump_length = xatoi_u(optarg); + dumper->dump_length = xatoi_positive(optarg); } /* else */ if (ch == 's') { /* compat: -s accepts hex numbers too */ dumper->dump_skip = xstrtoul_range_sfx(optarg, /*base:*/ 0, /*lo:*/ 0, /*hi:*/ LONG_MAX, suffixes); diff --git a/util-linux/mount.c b/util-linux/mount.c index 9107e4308..aa17872da 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -1147,7 +1147,7 @@ static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts) continue; } - val = xatoi_u(opteq); + val = xatoi_positive(opteq); switch (idx) { case 0: // "rsize" data.rsize = val; -- cgit v1.2.3-55-g6feb From dcaed97e0f44d0cd285fb590ec6ec80d0d73e738 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 12 Aug 2010 15:36:34 +0200 Subject: iostat: add forgotted fclose(); fix default count. Signed-off-by: Denys Vlasenko --- procps/iostat.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/procps/iostat.c b/procps/iostat.c index 8641c2391..76c5353cc 100644 --- a/procps/iostat.c +++ b/procps/iostat.c @@ -20,8 +20,8 @@ #include "libbb.h" #include /* Need struct utsname */ -#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) -//#define debug(fmt, ...) ((void)0) +//#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) +#define debug(fmt, ...) ((void)0) #define MAX_DEVICE_NAME 12 #define CURRENT 0 @@ -402,6 +402,8 @@ static void do_disk_statistics(cputime_t itv) continue; } } + + fclose(fp); } static void dev_report(cputime_t itv) @@ -493,7 +495,7 @@ int iostat_main(int argc, char **argv) { int opt, dev_num; unsigned interval = 0; - int count = 0; + int count; cputime_t global_uptime[2] = { 0 }; cputime_t smp_uptime[2] = { 0 }; cputime_t itv; @@ -537,10 +539,11 @@ int iostat_main(int argc, char **argv) argv++; } + count = 1; if (*argv) { /* Get interval */ interval = xatoi_positive(*argv); - count = interval ? -1 : 1; + count = (interval != 0 ? -1 : 1); argv++; if (*argv) /* Get count value */ -- cgit v1.2.3-55-g6feb