diff options
author | Ron Yorston <rmy@pobox.com> | 2021-08-17 08:26:36 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-08-17 08:26:36 +0100 |
commit | f13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03 (patch) | |
tree | 15c9c174532e433e5632637c541d09e591c01d60 | |
parent | 41f31584037be6b9d74a89245dff9ad8f0db146f (diff) | |
parent | 540aa116615713ad53e5ac98850993162e27c32d (diff) | |
download | busybox-w32-f13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03.tar.gz busybox-w32-f13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03.tar.bz2 busybox-w32-f13defb1c8f892ecf3e8dd5dbe486cc2b53e6f03.zip |
Merge branch 'busybox' into merge
40 files changed, 301 insertions, 59 deletions
diff --git a/archival/tar.c b/archival/tar.c index 8cd371173..67c90e6fd 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -509,6 +509,9 @@ static int FAST_FUNC writeFileToTarball(struct recursive_state *state, | |||
509 | if (header_name[0] == '\0') | 509 | if (header_name[0] == '\0') |
510 | return TRUE; | 510 | return TRUE; |
511 | 511 | ||
512 | if (exclude_file(tbInfo->excludeList, header_name)) | ||
513 | return SKIP; /* "do not recurse on this directory", no error message printed */ | ||
514 | |||
512 | /* It is against the rules to archive a socket */ | 515 | /* It is against the rules to archive a socket */ |
513 | if (S_ISSOCK(statbuf->st_mode)) { | 516 | if (S_ISSOCK(statbuf->st_mode)) { |
514 | bb_error_msg("%s: socket ignored", fileName); | 517 | bb_error_msg("%s: socket ignored", fileName); |
@@ -548,9 +551,6 @@ static int FAST_FUNC writeFileToTarball(struct recursive_state *state, | |||
548 | } | 551 | } |
549 | #endif | 552 | #endif |
550 | 553 | ||
551 | if (exclude_file(tbInfo->excludeList, header_name)) | ||
552 | return SKIP; | ||
553 | |||
554 | # if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS | 554 | # if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS |
555 | if (strlen(header_name) >= NAME_SIZE) { | 555 | if (strlen(header_name) >= NAME_SIZE) { |
556 | bb_simple_error_msg("names longer than "NAME_SIZE_STR" chars not supported"); | 556 | bb_simple_error_msg("names longer than "NAME_SIZE_STR" chars not supported"); |
@@ -563,13 +563,13 @@ static int FAST_FUNC writeFileToTarball(struct recursive_state *state, | |||
563 | /* open the file we want to archive, and make sure all is well */ | 563 | /* open the file we want to archive, and make sure all is well */ |
564 | inputFileFd = open_or_warn(fileName, O_RDONLY); | 564 | inputFileFd = open_or_warn(fileName, O_RDONLY); |
565 | if (inputFileFd < 0) { | 565 | if (inputFileFd < 0) { |
566 | return FALSE; | 566 | return FALSE; /* make recursive_action() return FALSE */ |
567 | } | 567 | } |
568 | } | 568 | } |
569 | 569 | ||
570 | /* Add an entry to the tarball */ | 570 | /* Add an entry to the tarball */ |
571 | if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) { | 571 | if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) { |
572 | return FALSE; | 572 | return FALSE; /* make recursive_action() return FALSE */ |
573 | } | 573 | } |
574 | 574 | ||
575 | /* If it was a regular file, write out the body */ | 575 | /* If it was a regular file, write out the body */ |
@@ -1153,14 +1153,15 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1153 | tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE; | 1153 | tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE; |
1154 | 1154 | ||
1155 | #if ENABLE_FEATURE_TAR_FROM | 1155 | #if ENABLE_FEATURE_TAR_FROM |
1156 | /* Convert each -X EXCLFILE to list of to-be-rejected glob patterns */ | ||
1156 | tar_handle->reject = append_file_list_to_list(tar_handle->reject); | 1157 | tar_handle->reject = append_file_list_to_list(tar_handle->reject); |
1157 | # if ENABLE_FEATURE_TAR_LONG_OPTIONS | 1158 | # if ENABLE_FEATURE_TAR_LONG_OPTIONS |
1158 | /* Append excludes to reject */ | 1159 | /* Append --exclude=GLOBPATTERNs to reject */ |
1159 | while (excludes) { | 1160 | if (excludes) { |
1160 | llist_t *next = excludes->link; | 1161 | llist_t **p2next = &tar_handle->reject; |
1161 | excludes->link = tar_handle->reject; | 1162 | while (*p2next) |
1162 | tar_handle->reject = excludes; | 1163 | p2next = &((*p2next)->link); |
1163 | excludes = next; | 1164 | *p2next = excludes; |
1164 | } | 1165 | } |
1165 | # endif | 1166 | # endif |
1166 | tar_handle->accept = append_file_list_to_list(tar_handle->accept); | 1167 | tar_handle->accept = append_file_list_to_list(tar_handle->accept); |
diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig index 503157c12..104e70f23 100644 --- a/configs/android_502_defconfig +++ b/configs/android_502_defconfig | |||
@@ -33,7 +33,6 @@ | |||
33 | ## Assorted header problems: | 33 | ## Assorted header problems: |
34 | ## # CONFIG_HOSTID is not set | 34 | ## # CONFIG_HOSTID is not set |
35 | ## # CONFIG_FEATURE_SYNC_FANCY is not set - syncfs() | 35 | ## # CONFIG_FEATURE_SYNC_FANCY is not set - syncfs() |
36 | ## # CONFIG_FEATURE_TOUCH_NODEREF is not set - lutimes() | ||
37 | ## # CONFIG_LOGNAME is not set - getlogin_r() | 36 | ## # CONFIG_LOGNAME is not set - getlogin_r() |
38 | ## # CONFIG_LOADFONT is not set | 37 | ## # CONFIG_LOADFONT is not set |
39 | ## # CONFIG_SETFONT is not set | 38 | ## # CONFIG_SETFONT is not set |
@@ -269,7 +268,6 @@ CONFIG_SYNC=y | |||
269 | CONFIG_TEST=y | 268 | CONFIG_TEST=y |
270 | CONFIG_FEATURE_TEST_64=y | 269 | CONFIG_FEATURE_TEST_64=y |
271 | CONFIG_TOUCH=y | 270 | CONFIG_TOUCH=y |
272 | # CONFIG_FEATURE_TOUCH_NODEREF is not set | ||
273 | CONFIG_FEATURE_TOUCH_SUSV3=y | 271 | CONFIG_FEATURE_TOUCH_SUSV3=y |
274 | CONFIG_TR=y | 272 | CONFIG_TR=y |
275 | CONFIG_FEATURE_TR_CLASSES=y | 273 | CONFIG_FEATURE_TR_CLASSES=y |
diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig index 03d497d2e..425593454 100644 --- a/configs/android_ndk_defconfig +++ b/configs/android_ndk_defconfig | |||
@@ -193,7 +193,6 @@ CONFIG_SYNC=y | |||
193 | CONFIG_TEST=y | 193 | CONFIG_TEST=y |
194 | CONFIG_FEATURE_TEST_64=y | 194 | CONFIG_FEATURE_TEST_64=y |
195 | CONFIG_TOUCH=y | 195 | CONFIG_TOUCH=y |
196 | # CONFIG_FEATURE_TOUCH_NODEREF is not set | ||
197 | CONFIG_FEATURE_TOUCH_SUSV3=y | 196 | CONFIG_FEATURE_TOUCH_SUSV3=y |
198 | CONFIG_TR=y | 197 | CONFIG_TR=y |
199 | CONFIG_FEATURE_TR_CLASSES=y | 198 | CONFIG_FEATURE_TR_CLASSES=y |
diff --git a/coreutils/cp.c b/coreutils/cp.c index 50ca1ccea..ee40af50b 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c | |||
@@ -121,14 +121,12 @@ int cp_main(int argc, char **argv) | |||
121 | int d_flags; | 121 | int d_flags; |
122 | int flags; | 122 | int flags; |
123 | int status; | 123 | int status; |
124 | enum { | ||
125 | #if ENABLE_FEATURE_CP_LONG_OPTIONS | 124 | #if ENABLE_FEATURE_CP_LONG_OPTIONS |
125 | enum { | ||
126 | /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTBITS */ | 126 | /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTBITS */ |
127 | OPT_parents = 1 << (FILEUTILS_CP_OPTBITS+1), | 127 | OPT_parents = 1 << (FILEUTILS_CP_OPTBITS+1), |
128 | OPT_reflink = 1 << (FILEUTILS_CP_OPTBITS+2), | 128 | OPT_reflink = 1 << (FILEUTILS_CP_OPTBITS+2), |
129 | #endif | ||
130 | }; | 129 | }; |
131 | #if ENABLE_FEATURE_CP_LONG_OPTIONS | ||
132 | # if ENABLE_FEATURE_CP_REFLINK | 130 | # if ENABLE_FEATURE_CP_REFLINK |
133 | char *reflink = NULL; | 131 | char *reflink = NULL; |
134 | # endif | 132 | # endif |
diff --git a/coreutils/dd.c b/coreutils/dd.c index b476ed24f..a3c9ababf 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
@@ -56,8 +56,8 @@ | |||
56 | //kbuild:lib-$(CONFIG_DD) += dd.o | 56 | //kbuild:lib-$(CONFIG_DD) += dd.o |
57 | 57 | ||
58 | //usage:#define dd_trivial_usage | 58 | //usage:#define dd_trivial_usage |
59 | //usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n" | 59 | //usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]" |
60 | //usage: IF_FEATURE_DD_IBS_OBS( | 60 | //usage: IF_FEATURE_DD_IBS_OBS("\n" |
61 | //usage: " [conv=notrunc|noerror|sync|fsync]\n" | 61 | //usage: " [conv=notrunc|noerror|sync|fsync]\n" |
62 | //usage: " [iflag=skip_bytes|count_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]" | 62 | //usage: " [iflag=skip_bytes|count_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]" |
63 | //usage: ) | 63 | //usage: ) |
diff --git a/coreutils/touch.c b/coreutils/touch.c index ec12eb7cf..78100ba1d 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c | |||
@@ -127,6 +127,7 @@ int touch_main(int argc UNUSED_PARAM, char **argv) | |||
127 | #endif | 127 | #endif |
128 | ); | 128 | ); |
129 | 129 | ||
130 | #if ENABLE_FEATURE_TOUCH_SUSV3 | ||
130 | timebuf[0].tv_nsec = timebuf[1].tv_nsec = UTIME_NOW; | 131 | timebuf[0].tv_nsec = timebuf[1].tv_nsec = UTIME_NOW; |
131 | if (opts & OPT_r) { | 132 | if (opts & OPT_r) { |
132 | struct stat stbuf; | 133 | struct stat stbuf; |
@@ -160,6 +161,7 @@ int touch_main(int argc UNUSED_PARAM, char **argv) | |||
160 | timebuf[1].tv_nsec = UTIME_OMIT; | 161 | timebuf[1].tv_nsec = UTIME_OMIT; |
161 | if ((opts & (OPT_a|OPT_m)) == OPT_m) | 162 | if ((opts & (OPT_a|OPT_m)) == OPT_m) |
162 | timebuf[0].tv_nsec = UTIME_OMIT; | 163 | timebuf[0].tv_nsec = UTIME_OMIT; |
164 | #endif | ||
163 | 165 | ||
164 | argv += optind; | 166 | argv += optind; |
165 | do { | 167 | do { |
diff --git a/editors/vi.c b/editors/vi.c index a079be3fe..c5dff3fee 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -320,6 +320,7 @@ struct globals { | |||
320 | #define autoindent (0) | 320 | #define autoindent (0) |
321 | #define expandtab (0) | 321 | #define expandtab (0) |
322 | #define err_method (0) | 322 | #define err_method (0) |
323 | #define ignorecase (0) | ||
323 | #endif | 324 | #endif |
324 | 325 | ||
325 | #if ENABLE_FEATURE_VI_READONLY | 326 | #if ENABLE_FEATURE_VI_READONLY |
diff --git a/networking/traceroute.c b/networking/traceroute.c index 057f8591a..4bbe1ab8e 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c | |||
@@ -713,11 +713,16 @@ packet4_ok(int read_len, int seq) | |||
713 | up = (struct udphdr *)((char *)hip + hlen); | 713 | up = (struct udphdr *)((char *)hip + hlen); |
714 | if (hlen + 12 <= read_len | 714 | if (hlen + 12 <= read_len |
715 | && hip->ip_p == IPPROTO_UDP | 715 | && hip->ip_p == IPPROTO_UDP |
716 | // Off: since we do not form the entire IP packet, | 716 | #if !defined(__FreeBSD__) |
717 | // Disabled source check: since we do not form the entire IP packet, | ||
717 | // but defer it to kernel, we can't set source port, | 718 | // but defer it to kernel, we can't set source port, |
718 | // and thus can't check it here in the reply | 719 | // and thus can't check it here in the reply |
720 | /* && up->source == ident */ | ||
721 | && up->dest == htons(port + seq) | ||
722 | #else | ||
719 | /* && up->uh_sport == ident */ | 723 | /* && up->uh_sport == ident */ |
720 | && up->uh_dport == htons(port + seq) | 724 | && up->uh_dport == htons(port + seq) |
725 | #endif | ||
721 | ) { | 726 | ) { |
722 | return (type == ICMP_TIMXCEED ? -1 : code + 1); | 727 | return (type == ICMP_TIMXCEED ? -1 : code + 1); |
723 | } | 728 | } |
diff --git a/scripts/randomtest b/scripts/randomtest index 76550d267..f6e0c9d8c 100755 --- a/scripts/randomtest +++ b/scripts/randomtest | |||
@@ -83,7 +83,6 @@ if test x"$LIBC" = x"uclibc"; then | |||
83 | \ | 83 | \ |
84 | | grep -v CONFIG_FEATURE_2_4_MODULES \ | 84 | | grep -v CONFIG_FEATURE_2_4_MODULES \ |
85 | | grep -v CONFIG_FEATURE_SYNC_FANCY \ | 85 | | grep -v CONFIG_FEATURE_SYNC_FANCY \ |
86 | | grep -v CONFIG_FEATURE_TOUCH_NODEREF \ | ||
87 | | grep -v CONFIG_NANDWRITE \ | 86 | | grep -v CONFIG_NANDWRITE \ |
88 | | grep -v CONFIG_NANDDUMP \ | 87 | | grep -v CONFIG_NANDDUMP \ |
89 | | grep -v CONFIG_BLKDISCARD \ | 88 | | grep -v CONFIG_BLKDISCARD \ |
@@ -100,7 +99,6 @@ if test x"$LIBC" = x"uclibc"; then | |||
100 | echo '# CONFIG_PIE is not set' >>.config | 99 | echo '# CONFIG_PIE is not set' >>.config |
101 | echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config | 100 | echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config |
102 | echo '# CONFIG_FEATURE_SYNC_FANCY is not set' >>.config | 101 | echo '# CONFIG_FEATURE_SYNC_FANCY is not set' >>.config |
103 | echo '# CONFIG_FEATURE_TOUCH_NODEREF is not set' >>.config | ||
104 | # My uclibc installation does not support some needed APIs... | 102 | # My uclibc installation does not support some needed APIs... |
105 | echo '# CONFIG_NANDWRITE is not set' >>.config | 103 | echo '# CONFIG_NANDWRITE is not set' >>.config |
106 | echo '# CONFIG_NANDDUMP is not set' >>.config | 104 | echo '# CONFIG_NANDDUMP is not set' >>.config |
diff --git a/scripts/randomtest.loop b/scripts/randomtest.loop index edfbc5c58..c6d2cdcda 100755 --- a/scripts/randomtest.loop +++ b/scripts/randomtest.loop | |||
@@ -6,13 +6,18 @@ run_testsuite=true | |||
6 | run_single_test=false | 6 | run_single_test=false |
7 | run_single_test=true | 7 | run_single_test=true |
8 | 8 | ||
9 | test -d "$1" || { echo "'$1' is not a directory"; exit 1; } | ||
10 | test -x "$1/scripts/randomtest" || { echo "No scripts/randomtest in '$1'"; exit 1; } | ||
11 | |||
12 | export LIBC="uclibc" | 9 | export LIBC="uclibc" |
13 | export CROSS_COMPILER_PREFIX="i686-" | 10 | export CROSS_COMPILER_PREFIX="i686-" |
14 | export MAKEOPTS="-j9" | 11 | export MAKEOPTS="-j9" |
15 | 12 | ||
13 | test -d "$1" || { echo "'$1' is not a directory"; exit 1; } | ||
14 | test -x "$1/scripts/randomtest" || { echo "No scripts/randomtest in '$1'"; exit 1; } | ||
15 | |||
16 | test "$SKIP_MOUNT_MAND_TESTS" = "1" || { | ||
17 | echo "SKIP_MOUNT_MAND_TESTS not set, some mount tests will fail" | ||
18 | echo "if current kernel has CONFIG_MANDATORY_FILE_LOCKING off." | ||
19 | } | ||
20 | |||
16 | cnt=0 | 21 | cnt=0 |
17 | fail=0 | 22 | fail=0 |
18 | while sleep 1; do | 23 | while sleep 1; do |
diff --git a/shell/ash.c b/shell/ash.c index 28f74e8a8..c9eaaf52a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -7855,7 +7855,7 @@ subevalvar(char *start, char *str, int strloc, | |||
7855 | while (idx <= end) { | 7855 | while (idx <= end) { |
7856 | try_to_match: | 7856 | try_to_match: |
7857 | if (no_meta_len == 0) { | 7857 | if (no_meta_len == 0) { |
7858 | /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ | 7858 | /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ |
7859 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); | 7859 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); |
7860 | } else { | 7860 | } else { |
7861 | /* Testcase for very slow replace (performs about 22k replaces): | 7861 | /* Testcase for very slow replace (performs about 22k replaces): |
@@ -7863,16 +7863,19 @@ subevalvar(char *start, char *str, int strloc, | |||
7863 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 7863 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
7864 | * echo "${x//:/|}" | 7864 | * echo "${x//:/|}" |
7865 | */ | 7865 | */ |
7866 | size_t n; | ||
7867 | if (strncmp(rmesc, str, no_meta_len) != 0) | 7866 | if (strncmp(rmesc, str, no_meta_len) != 0) |
7868 | goto no_match; | 7867 | goto no_match; |
7869 | n = no_meta_len; | ||
7870 | loc = idx; | 7868 | loc = idx; |
7871 | do { | 7869 | if (!quotes) { |
7872 | if (quotes && (unsigned char)*loc == CTLESC) | 7870 | loc += no_meta_len; |
7871 | } else { | ||
7872 | size_t n = no_meta_len; | ||
7873 | do { | ||
7874 | if ((unsigned char)*loc == CTLESC) | ||
7875 | loc++; | ||
7873 | loc++; | 7876 | loc++; |
7874 | loc++; | 7877 | } while (--n != 0); |
7875 | } while (--n != 0); | 7878 | } |
7876 | } | 7879 | } |
7877 | //bb_error_msg("scanright('%s'):'%s'", str, loc); | 7880 | //bb_error_msg("scanright('%s'):'%s'", str, loc); |
7878 | if (!loc) { | 7881 | if (!loc) { |
diff --git a/shell/ash_test/ash-psubst/falsetick.right b/shell/ash_test/ash-psubst/falsetick.right new file mode 100644 index 000000000..0335254a8 --- /dev/null +++ b/shell/ash_test/ash-psubst/falsetick.right | |||
@@ -0,0 +1,24 @@ | |||
1 | 0 | ||
2 | 0 | ||
3 | 0 | ||
4 | 0 | ||
5 | 2 | ||
6 | 2 | ||
7 | 2 | ||
8 | 2 | ||
9 | ./falsetick.tests: line 12: can't create /does/not/exist: nonexistent directory | ||
10 | 1 | ||
11 | ./falsetick.tests: line 13: can't create /does/not/exist: nonexistent directory | ||
12 | 1 | ||
13 | ./falsetick.tests: line 14: can't create /does/not/exist: nonexistent directory | ||
14 | 1 | ||
15 | ./falsetick.tests: line 15: can't create /does/not/exist: nonexistent directory | ||
16 | 1 | ||
17 | ./falsetick.tests: line 16: can't create /does/not/exist: nonexistent directory | ||
18 | 1 | ||
19 | ./falsetick.tests: line 17: can't create /does/not/exist: nonexistent directory | ||
20 | 1 | ||
21 | ./falsetick.tests: line 18: can't create /does/not/exist: nonexistent directory | ||
22 | 1 | ||
23 | ./falsetick.tests: line 19: can't create /does/not/exist: nonexistent directory | ||
24 | 1 | ||
diff --git a/shell/ash_test/ash-psubst/falsetick.tests b/shell/ash_test/ash-psubst/falsetick.tests new file mode 100755 index 000000000..d2b93695e --- /dev/null +++ b/shell/ash_test/ash-psubst/falsetick.tests | |||
@@ -0,0 +1,19 @@ | |||
1 | # Exitcode 0 (`` has no exitcode, but assignment has): | ||
2 | true; a=``; echo $? | ||
3 | false; a=``; echo $? | ||
4 | true; a=$(); echo $? | ||
5 | false; a=$(); echo $? | ||
6 | # Exitcode 2 (`cmd` expansion sets exitcode after assignment set it to 0): | ||
7 | true; a=`exit 2`; echo $? | ||
8 | false; a=`exit 2`; echo $? | ||
9 | true; a=$(exit 2); echo $? | ||
10 | false; a=$(exit 2); echo $? | ||
11 | # Exitcode 1 (redirect sets exitcode to 1 on error after them): | ||
12 | true; a=`` >/does/not/exist; echo $? | ||
13 | false; a=`` >/does/not/exist; echo $? | ||
14 | true; a=$() >/does/not/exist; echo $? | ||
15 | false; a=$() >/does/not/exist; echo $? | ||
16 | true; a=`exit 2` >/does/not/exist; echo $? | ||
17 | false; a=`exit 2` >/does/not/exist; echo $? | ||
18 | true; a=$(exit 2) >/does/not/exist; echo $? | ||
19 | false; a=$(exit 2) >/does/not/exist; echo $? | ||
diff --git a/shell/ash_test/ash-psubst/falsetick2.right b/shell/ash_test/ash-psubst/falsetick2.right new file mode 100644 index 000000000..670f560f1 --- /dev/null +++ b/shell/ash_test/ash-psubst/falsetick2.right | |||
@@ -0,0 +1 @@ | |||
Two:2 v:[] | |||
diff --git a/shell/ash_test/ash-psubst/falsetick2.tests b/shell/ash_test/ash-psubst/falsetick2.tests new file mode 100755 index 000000000..cfbd1a5de --- /dev/null +++ b/shell/ash_test/ash-psubst/falsetick2.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | v=v | ||
2 | v=`exit 2` `false` | ||
3 | echo Two:$? v:"[$v]" | ||
diff --git a/shell/ash_test/ash-vars/var6.right b/shell/ash_test/ash-vars/var6.right new file mode 100644 index 000000000..b37417fa1 --- /dev/null +++ b/shell/ash_test/ash-vars/var6.right | |||
@@ -0,0 +1,2 @@ | |||
1 | SHELL: line 1: syntax error: bad substitution | ||
2 | SHELL: line 1: syntax error: bad substitution | ||
diff --git a/shell/ash_test/ash-vars/var6.tests b/shell/ash_test/ash-vars/var6.tests new file mode 100755 index 000000000..626e60ee1 --- /dev/null +++ b/shell/ash_test/ash-vars/var6.tests | |||
@@ -0,0 +1,5 @@ | |||
1 | # reject invalid vars | ||
2 | # (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages) | ||
3 | "$THIS_SH" -c 'echo ${1q}' SHELL | ||
4 | "$THIS_SH" -c 'echo ${&}' SHELL | ||
5 | #"$THIS_SH" -c 'echo ${$}' SHELL -- this is valid as it's the same as $$ | ||
diff --git a/shell/ash_test/ash-vars/var_nested1.right b/shell/ash_test/ash-vars/var_nested1.right new file mode 100644 index 000000000..f4bc5f4b6 --- /dev/null +++ b/shell/ash_test/ash-vars/var_nested1.right | |||
@@ -0,0 +1,3 @@ | |||
1 | Expected:AB Actual:AB | ||
2 | Expected:Ab Actual:Ab | ||
3 | Expected:ab Actual:ab | ||
diff --git a/shell/ash_test/ash-vars/var_nested1.tests b/shell/ash_test/ash-vars/var_nested1.tests new file mode 100755 index 000000000..59e4a14fa --- /dev/null +++ b/shell/ash_test/ash-vars/var_nested1.tests | |||
@@ -0,0 +1,16 @@ | |||
1 | f() { a=A; b=B; } | ||
2 | |||
3 | a=a | ||
4 | b=b | ||
5 | f | ||
6 | echo Expected:AB Actual:$a$b | ||
7 | |||
8 | a=a | ||
9 | b=b | ||
10 | b= f | ||
11 | echo Expected:Ab Actual:$a$b | ||
12 | |||
13 | a=a | ||
14 | b=b | ||
15 | a= b= f | ||
16 | echo Expected:ab Actual:$a$b | ||
diff --git a/shell/ash_test/ash-vars/var_nested2.right b/shell/ash_test/ash-vars/var_nested2.right new file mode 100644 index 000000000..c930d971c --- /dev/null +++ b/shell/ash_test/ash-vars/var_nested2.right | |||
@@ -0,0 +1 @@ | |||
aB | |||
diff --git a/shell/ash_test/ash-vars/var_nested2.tests b/shell/ash_test/ash-vars/var_nested2.tests new file mode 100755 index 000000000..e8865861e --- /dev/null +++ b/shell/ash_test/ash-vars/var_nested2.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | # the bug was easier to trigger in one-liner form | ||
2 | a=a; b=b; f() { a=A; b=B; }; a= f; echo $a$b | ||
diff --git a/shell/hush.c b/shell/hush.c index 1aa0a400d..27092c12f 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -384,6 +384,7 @@ | |||
384 | #define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT | 384 | #define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT |
385 | #define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT | 385 | #define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT |
386 | #define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT | 386 | #define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT |
387 | #define BASH_DOLLAR_SQUOTE ENABLE_HUSH_BASH_COMPAT | ||
387 | #define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT | 388 | #define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT |
388 | #define BASH_EPOCH_VARS ENABLE_HUSH_BASH_COMPAT | 389 | #define BASH_EPOCH_VARS ENABLE_HUSH_BASH_COMPAT |
389 | #define BASH_TEST2 (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST) | 390 | #define BASH_TEST2 (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST) |
@@ -4919,6 +4920,101 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign | |||
4919 | } | 4920 | } |
4920 | #endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */ | 4921 | #endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */ |
4921 | 4922 | ||
4923 | #if BASH_DOLLAR_SQUOTE | ||
4924 | /* Return code: 1 for "found and parsed", 0 for "seen something else" */ | ||
4925 | # if BB_MMU | ||
4926 | #define parse_dollar_squote(as_string, dest, input) \ | ||
4927 | parse_dollar_squote(dest, input) | ||
4928 | #define as_string NULL | ||
4929 | # endif | ||
4930 | static int parse_dollar_squote(o_string *as_string, o_string *dest, struct in_str *input) | ||
4931 | { | ||
4932 | int start; | ||
4933 | int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */ | ||
4934 | debug_printf_parse("parse_dollar_squote entered: ch='%c'\n", ch); | ||
4935 | if (ch != '\'') | ||
4936 | return 0; | ||
4937 | |||
4938 | dest->has_quoted_part = 1; | ||
4939 | start = dest->length; | ||
4940 | |||
4941 | ch = i_getch(input); /* eat ' */ | ||
4942 | nommu_addchr(as_string, ch); | ||
4943 | while (1) { | ||
4944 | ch = i_getch(input); | ||
4945 | nommu_addchr(as_string, ch); | ||
4946 | if (ch == EOF) { | ||
4947 | syntax_error_unterm_ch('\''); | ||
4948 | return 0; | ||
4949 | } | ||
4950 | if (ch == '\'') | ||
4951 | break; | ||
4952 | if (ch == SPECIAL_VAR_SYMBOL) { | ||
4953 | /* Convert raw ^C to corresponding special variable reference */ | ||
4954 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
4955 | o_addchr(dest, SPECIAL_VAR_QUOTED_SVS); | ||
4956 | /* will addchr() another SPECIAL_VAR_SYMBOL (see after the if() block) */ | ||
4957 | } else if (ch == '\\') { | ||
4958 | static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567"; | ||
4959 | |||
4960 | ch = i_getch(input); | ||
4961 | nommu_addchr(as_string, ch); | ||
4962 | if (strchr(C_escapes, ch)) { | ||
4963 | char buf[4]; | ||
4964 | char *p = buf; | ||
4965 | int cnt = 2; | ||
4966 | |||
4967 | buf[0] = ch; | ||
4968 | if ((unsigned char)(ch - '0') <= 7) { /* \ooo */ | ||
4969 | do { | ||
4970 | ch = i_peek(input); | ||
4971 | if ((unsigned char)(ch - '0') > 7) | ||
4972 | break; | ||
4973 | *++p = ch = i_getch(input); | ||
4974 | nommu_addchr(as_string, ch); | ||
4975 | } while (--cnt != 0); | ||
4976 | } else if (ch == 'x') { /* \xHH */ | ||
4977 | do { | ||
4978 | ch = i_peek(input); | ||
4979 | if (!isxdigit(ch)) | ||
4980 | break; | ||
4981 | *++p = ch = i_getch(input); | ||
4982 | nommu_addchr(as_string, ch); | ||
4983 | } while (--cnt != 0); | ||
4984 | if (cnt == 2) { /* \x but next char is "bad" */ | ||
4985 | ch = 'x'; | ||
4986 | goto unrecognized; | ||
4987 | } | ||
4988 | } /* else simple seq like \\ or \t */ | ||
4989 | *++p = '\0'; | ||
4990 | p = buf; | ||
4991 | ch = bb_process_escape_sequence((void*)&p); | ||
4992 | //bb_error_msg("buf:'%s' ch:%x", buf, ch); | ||
4993 | if (ch == '\0') | ||
4994 | continue; /* bash compat: $'...\0...' emits nothing */ | ||
4995 | } else { /* unrecognized "\z": encode both chars unless ' or " */ | ||
4996 | if (ch != '\'' && ch != '"') { | ||
4997 | unrecognized: | ||
4998 | o_addqchr(dest, '\\'); | ||
4999 | } | ||
5000 | } | ||
5001 | } /* if (\...) */ | ||
5002 | o_addqchr(dest, ch); | ||
5003 | } | ||
5004 | |||
5005 | if (dest->length == start) { | ||
5006 | /* $'', $'\0', $'\000\x00' and the like */ | ||
5007 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
5008 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
5009 | } | ||
5010 | |||
5011 | return 1; | ||
5012 | # undef as_string | ||
5013 | } | ||
5014 | #else | ||
5015 | # define parse_dollar_squote(as_string, dest, input) 0 | ||
5016 | #endif /* BASH_DOLLAR_SQUOTE */ | ||
5017 | |||
4922 | /* Return code: 0 for OK, 1 for syntax error */ | 5018 | /* Return code: 0 for OK, 1 for syntax error */ |
4923 | #if BB_MMU | 5019 | #if BB_MMU |
4924 | #define parse_dollar(as_string, dest, input, quote_mask) \ | 5020 | #define parse_dollar(as_string, dest, input, quote_mask) \ |
@@ -4931,7 +5027,7 @@ static int parse_dollar(o_string *as_string, | |||
4931 | { | 5027 | { |
4932 | int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */ | 5028 | int ch = i_peek_and_eat_bkslash_nl(input); /* first character after the $ */ |
4933 | 5029 | ||
4934 | debug_printf_parse("parse_dollar entered: ch='%c'\n", ch); | 5030 | debug_printf_parse("parse_dollar entered: ch='%c' quote_mask:0x%x\n", ch, quote_mask); |
4935 | if (isalpha(ch)) { | 5031 | if (isalpha(ch)) { |
4936 | make_var: | 5032 | make_var: |
4937 | ch = i_getch(input); | 5033 | ch = i_getch(input); |
@@ -5247,6 +5343,8 @@ static int encode_string(o_string *as_string, | |||
5247 | goto again; | 5343 | goto again; |
5248 | } | 5344 | } |
5249 | if (ch == '$') { | 5345 | if (ch == '$') { |
5346 | //if (parse_dollar_squote(as_string, dest, input)) | ||
5347 | // goto again; | ||
5250 | if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) { | 5348 | if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) { |
5251 | debug_printf_parse("encode_string return 0: " | 5349 | debug_printf_parse("encode_string return 0: " |
5252 | "parse_dollar returned 0 (error)\n"); | 5350 | "parse_dollar returned 0 (error)\n"); |
@@ -5723,6 +5821,8 @@ static struct pipe *parse_stream(char **pstring, | |||
5723 | o_addchr(&ctx.word, ch); | 5821 | o_addchr(&ctx.word, ch); |
5724 | continue; /* get next char */ | 5822 | continue; /* get next char */ |
5725 | case '$': | 5823 | case '$': |
5824 | if (parse_dollar_squote(&ctx.as_string, &ctx.word, input)) | ||
5825 | continue; /* get next char */ | ||
5726 | if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { | 5826 | if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { |
5727 | debug_printf_parse("parse_stream parse error: " | 5827 | debug_printf_parse("parse_stream parse error: " |
5728 | "parse_dollar returned 0 (error)\n"); | 5828 | "parse_dollar returned 0 (error)\n"); |
@@ -5850,7 +5950,6 @@ static struct pipe *parse_stream(char **pstring, | |||
5850 | if (ctx.ctx_res_w == RES_MATCH) | 5950 | if (ctx.ctx_res_w == RES_MATCH) |
5851 | goto case_semi; | 5951 | goto case_semi; |
5852 | #endif | 5952 | #endif |
5853 | |||
5854 | case '}': | 5953 | case '}': |
5855 | /* proper use of this character is caught by end_trigger: | 5954 | /* proper use of this character is caught by end_trigger: |
5856 | * if we see {, we call parse_group(..., end_trigger='}') | 5955 | * if we see {, we call parse_group(..., end_trigger='}') |
@@ -6166,6 +6265,8 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int | |||
6166 | continue; | 6265 | continue; |
6167 | } | 6266 | } |
6168 | if (ch == '$') { | 6267 | if (ch == '$') { |
6268 | if (parse_dollar_squote(NULL, &dest, &input)) | ||
6269 | continue; | ||
6169 | if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) { | 6270 | if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) { |
6170 | debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); | 6271 | debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); |
6171 | goto ret; | 6272 | goto ret; |
@@ -6365,6 +6466,18 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) | |||
6365 | /* ${var/[/]pattern[/repl]} helpers */ | 6466 | /* ${var/[/]pattern[/repl]} helpers */ |
6366 | static char *strstr_pattern(char *val, const char *pattern, int *size) | 6467 | static char *strstr_pattern(char *val, const char *pattern, int *size) |
6367 | { | 6468 | { |
6469 | int sz = strcspn(pattern, "*?[\\"); | ||
6470 | if (pattern[sz] == '\0') { | ||
6471 | /* Optimization for trivial patterns. | ||
6472 | * Testcase for very slow replace (performs about 22k replaces): | ||
6473 | * x=:::::::::::::::::::::: | ||
6474 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | ||
6475 | * echo "${x//:/|}" | ||
6476 | */ | ||
6477 | *size = sz; | ||
6478 | return strstr(val, pattern); | ||
6479 | } | ||
6480 | |||
6368 | while (1) { | 6481 | while (1) { |
6369 | char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF); | 6482 | char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF); |
6370 | debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end); | 6483 | debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end); |
diff --git a/shell/hush_test/hush-psubst/falsetick.right b/shell/hush_test/hush-psubst/falsetick.right index 0b98fb778..d2d1a2880 100644 --- a/shell/hush_test/hush-psubst/falsetick.right +++ b/shell/hush_test/hush-psubst/falsetick.right | |||
@@ -22,6 +22,3 @@ hush: can't open '/does/not/exist': No such file or directory | |||
22 | 1 | 22 | 1 |
23 | hush: can't open '/does/not/exist': No such file or directory | 23 | hush: can't open '/does/not/exist': No such file or directory |
24 | 1 | 24 | 1 |
25 | hush: can't open '/does/not/exist': No such file or directory | ||
26 | 1 | ||
27 | Done: a=b | ||
diff --git a/shell/hush_test/hush-psubst/falsetick.tests b/shell/hush_test/hush-psubst/falsetick.tests index 44d2eae8b..d2b93695e 100755 --- a/shell/hush_test/hush-psubst/falsetick.tests +++ b/shell/hush_test/hush-psubst/falsetick.tests | |||
@@ -17,6 +17,3 @@ true; a=`exit 2` >/does/not/exist; echo $? | |||
17 | false; a=`exit 2` >/does/not/exist; echo $? | 17 | false; a=`exit 2` >/does/not/exist; echo $? |
18 | true; a=$(exit 2) >/does/not/exist; echo $? | 18 | true; a=$(exit 2) >/does/not/exist; echo $? |
19 | false; a=$(exit 2) >/does/not/exist; echo $? | 19 | false; a=$(exit 2) >/does/not/exist; echo $? |
20 | # ...and assignment still happens despite redirect error: | ||
21 | true; a=$(echo b) >/does/not/exist; echo $? | ||
22 | echo "Done: a=$a" | ||
diff --git a/shell/hush_test/hush-psubst/falsetick3.right b/shell/hush_test/hush-psubst/falsetick3.right new file mode 100644 index 000000000..327849a31 --- /dev/null +++ b/shell/hush_test/hush-psubst/falsetick3.right | |||
@@ -0,0 +1,3 @@ | |||
1 | hush: can't open '/does/not/exist': No such file or directory | ||
2 | 1 | ||
3 | Done: a=b | ||
diff --git a/shell/hush_test/hush-psubst/falsetick3.tests b/shell/hush_test/hush-psubst/falsetick3.tests new file mode 100755 index 000000000..cd185335e --- /dev/null +++ b/shell/hush_test/hush-psubst/falsetick3.tests | |||
@@ -0,0 +1,3 @@ | |||
1 | # assignment still happens despite redirect error | ||
2 | true; a=$(echo b) >/does/not/exist; echo $? | ||
3 | echo "Done: a=$a" | ||
diff --git a/shell/hush_test/hush-quoting/dollar_squote_bash1.right b/shell/hush_test/hush-quoting/dollar_squote_bash1.right new file mode 100644 index 000000000..9f4e25efa --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_squote_bash1.right | |||
@@ -0,0 +1,10 @@ | |||
1 | a b | ||
2 | $'a\tb' | ||
3 | a | ||
4 | b c | ||
5 | def | ||
6 | a'b c"d e\f | ||
7 | a3b c3b e33f | ||
8 | a\80b c08b | ||
9 | a3b c30b | ||
10 | x y | ||
diff --git a/shell/hush_test/hush-quoting/dollar_squote_bash1.tests b/shell/hush_test/hush-quoting/dollar_squote_bash1.tests new file mode 100755 index 000000000..6fc411b93 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_squote_bash1.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | echo $'a\tb' | ||
2 | echo "$'a\tb'" | ||
3 | echo $'a\nb' $'c\nd''ef' | ||
4 | echo $'a\'b' $'c\"d' $'e\\f' | ||
5 | echo $'a\63b' $'c\063b' $'e\0633f' | ||
6 | echo $'a\80b' $'c\608b' | ||
7 | echo $'a\x33b' $'c\x330b' | ||
8 | echo $'x\x9y' | ||
diff --git a/shell/hush_test/hush-quoting/dollar_squote_bash2.right b/shell/hush_test/hush-quoting/dollar_squote_bash2.right new file mode 100644 index 000000000..f7a1731dd --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_squote_bash2.right | |||
@@ -0,0 +1,6 @@ | |||
1 | strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr | ||
2 | strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr | ||
3 | 80:\ | ||
4 | 81:\ | ||
5 | 82:\ | ||
6 | Done:0 | ||
diff --git a/shell/hush_test/hush-quoting/dollar_squote_bash2.tests b/shell/hush_test/hush-quoting/dollar_squote_bash2.tests new file mode 100755 index 000000000..449772813 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_squote_bash2.tests | |||
@@ -0,0 +1,10 @@ | |||
1 | # Embedded NULs | ||
2 | echo $'str\x00'strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr | ||
3 | echo $'str\000'strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr | ||
4 | |||
5 | # The chars after '\' are hex 0x80,81,82... | ||
6 | echo 80:$'\' | ||
7 | echo 81:$'\' | ||
8 | echo 82:$'\' | ||
9 | |||
10 | echo Done:$? | ||
diff --git a/shell/hush_test/hush-vars/var6.tests b/shell/hush_test/hush-vars/var6.tests index aea36d62d..626e60ee1 100755 --- a/shell/hush_test/hush-vars/var6.tests +++ b/shell/hush_test/hush-vars/var6.tests | |||
@@ -1,4 +1,5 @@ | |||
1 | # reject invalid vars | 1 | # reject invalid vars |
2 | "$THIS_SH" -c 'echo ${1q}' | 2 | # (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages) |
3 | "$THIS_SH" -c 'echo ${&}' | 3 | "$THIS_SH" -c 'echo ${1q}' SHELL |
4 | #"$THIS_SH" -c 'echo ${$}' -- this is valid as it's the same as $$ | 4 | "$THIS_SH" -c 'echo ${&}' SHELL |
5 | #"$THIS_SH" -c 'echo ${$}' SHELL -- this is valid as it's the same as $$ | ||
diff --git a/shell/hush_test/hush-vars/var_bash7.right b/shell/hush_test/hush-vars/var_bash7.right new file mode 100644 index 000000000..223b7836f --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash7.right | |||
@@ -0,0 +1 @@ | |||
B | |||
diff --git a/shell/hush_test/hush-vars/var_bash7.tests b/shell/hush_test/hush-vars/var_bash7.tests new file mode 100755 index 000000000..c4ce03f7f --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash7.tests | |||
@@ -0,0 +1 @@ | |||
x=AB; echo "${x#$'\x41'}" | |||
diff --git a/shell/match.c b/shell/match.c index ee8abb2db..90f77546d 100644 --- a/shell/match.c +++ b/shell/match.c | |||
@@ -64,11 +64,10 @@ char* FAST_FUNC scan_and_match(char *string, const char *pattern, unsigned flags | |||
64 | } | 64 | } |
65 | 65 | ||
66 | while (loc != end) { | 66 | while (loc != end) { |
67 | char c; | ||
68 | int r; | 67 | int r; |
69 | 68 | ||
70 | c = *loc; | ||
71 | if (flags & SCAN_MATCH_LEFT_HALF) { | 69 | if (flags & SCAN_MATCH_LEFT_HALF) { |
70 | char c = *loc; | ||
72 | *loc = '\0'; | 71 | *loc = '\0'; |
73 | r = fnmatch(pattern, string, 0); | 72 | r = fnmatch(pattern, string, 0); |
74 | //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r); | 73 | //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r); |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index f53b1efe2..dc2ae2e11 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -410,7 +410,7 @@ testing "awk printf('%c') can output NUL" \ | |||
410 | "awk '{printf(\"hello%c null\n\", 0)}'" "hello\0 null\n" "" "\n" | 410 | "awk '{printf(\"hello%c null\n\", 0)}'" "hello\0 null\n" "" "\n" |
411 | SKIP= | 411 | SKIP= |
412 | 412 | ||
413 | optional FEATURE_AWK_GNU_EXTENSIONS | 413 | optional FEATURE_AWK_GNU_EXTENSIONS DESKTOP |
414 | testing "awk printf('%-10c') can output NUL" \ | 414 | testing "awk printf('%-10c') can output NUL" \ |
415 | "awk 'BEGIN { printf \"[%-10c]\n\", 0 }' | od -tx1" "\ | 415 | "awk 'BEGIN { printf \"[%-10c]\n\", 0 }' | od -tx1" "\ |
416 | 0000000 5b 00 20 20 20 20 20 20 20 20 20 5d 0a | 416 | 0000000 5b 00 20 20 20 20 20 20 20 20 20 5d 0a |
diff --git a/testsuite/cut.tests b/testsuite/cut.tests index d705b91c3..2458c019c 100755 --- a/testsuite/cut.tests +++ b/testsuite/cut.tests | |||
@@ -66,6 +66,7 @@ testing "cut with -d -f(a) -s" "cut -da -f3 -s input" "n\nsium:Jim\n\ncion:Ed\n" | |||
66 | testing "cut with -d -f(a) -s -n" "cut -da -f3 -s -n input" "n\nsium:Jim\n\ncion:Ed\n" "$input" "" | 66 | testing "cut with -d -f(a) -s -n" "cut -da -f3 -s -n input" "n\nsium:Jim\n\ncion:Ed\n" "$input" "" |
67 | 67 | ||
68 | # substitute for awk | 68 | # substitute for awk |
69 | optional FEATURE_CUT_REGEX | ||
69 | testing "cut -DF" "cut -DF 2,7,5" \ | 70 | testing "cut -DF" "cut -DF 2,7,5" \ |
70 | "said and your\nare\nis demand. supply\nforecast :\nyou you better,\n\nEm: Took hate\n" "" \ | 71 | "said and your\nare\nis demand. supply\nforecast :\nyou you better,\n\nEm: Took hate\n" "" \ |
71 | "Bother, said Pooh. It's your husband, and he has a gun. | 72 | "Bother, said Pooh. It's your husband, and he has a gun. |
@@ -75,6 +76,7 @@ Weather forecast for tonight : dark. | |||
75 | Apple: you can buy better, but you can't pay more. | 76 | Apple: you can buy better, but you can't pay more. |
76 | Subcalifragilisticexpialidocious. | 77 | Subcalifragilisticexpialidocious. |
77 | Auntie Em: Hate you, hate Kansas. Took the dog. Dorothy." | 78 | Auntie Em: Hate you, hate Kansas. Took the dog. Dorothy." |
79 | SKIP= | ||
78 | 80 | ||
79 | testing "cut empty field" "cut -d ':' -f 1-3" "a::b\n" "" "a::b\n" | 81 | testing "cut empty field" "cut -d ':' -f 1-3" "a::b\n" "" "a::b\n" |
80 | testing "cut empty field 2" "cut -d ':' -f 3-5" "b::c\n" "" "a::b::c:d\n" | 82 | testing "cut empty field 2" "cut -d ':' -f 3-5" "b::c\n" "" "a::b::c:d\n" |
diff --git a/testsuite/dd/dd-count-bytes b/testsuite/dd/dd-count-bytes index 0730cba5e..ae1b6c50a 100644 --- a/testsuite/dd/dd-count-bytes +++ b/testsuite/dd/dd-count-bytes | |||
@@ -1 +1,3 @@ | |||
1 | # FEATURE: CONFIG_FEATURE_DD_IBS_OBS | ||
2 | |||
1 | test "$(echo I WANT | busybox dd count=3 iflag=count_bytes 2>/dev/null)" = "I W" | 3 | test "$(echo I WANT | busybox dd count=3 iflag=count_bytes 2>/dev/null)" = "I W" |
diff --git a/testsuite/tar.tests b/testsuite/tar.tests index d71a34910..0f2e89112 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests | |||
@@ -3,6 +3,7 @@ | |||
3 | # Licensed under GPLv2, see file LICENSE in this source tree. | 3 | # Licensed under GPLv2, see file LICENSE in this source tree. |
4 | 4 | ||
5 | . ./testing.sh | 5 | . ./testing.sh |
6 | test -f "$bindir/.config" && . "$bindir/.config" | ||
6 | 7 | ||
7 | unset LANG | 8 | unset LANG |
8 | unset LANGUAGE | 9 | unset LANGUAGE |
@@ -12,7 +13,7 @@ umask 022 | |||
12 | 13 | ||
13 | # testing "test name" "script" "expected result" "file input" "stdin" | 14 | # testing "test name" "script" "expected result" "file input" "stdin" |
14 | 15 | ||
15 | testing "Empty file is not a tarball" '\ | 16 | testing "tar Empty file is not a tarball" '\ |
16 | tar xvf - 2>&1; echo $? | 17 | tar xvf - 2>&1; echo $? |
17 | ' "\ | 18 | ' "\ |
18 | tar: short read | 19 | tar: short read |
@@ -25,7 +26,7 @@ optional FEATURE_SEAMLESS_GZ GUNZIP | |||
25 | # In NOMMU case, "invalid magic" message comes from gunzip child process. | 26 | # In NOMMU case, "invalid magic" message comes from gunzip child process. |
26 | # Otherwise, it comes from tar. | 27 | # Otherwise, it comes from tar. |
27 | # Need to fix output up to avoid false positive. | 28 | # Need to fix output up to avoid false positive. |
28 | testing "Empty file is not a tarball.tar.gz" '\ | 29 | testing "tar Empty file is not a tarball.tar.gz" '\ |
29 | { tar xvzf - 2>&1; echo $?; } | grep -Fv "invalid magic" | 30 | { tar xvzf - 2>&1; echo $?; } | grep -Fv "invalid magic" |
30 | ' "\ | 31 | ' "\ |
31 | tar: short read | 32 | tar: short read |
@@ -34,7 +35,7 @@ tar: short read | |||
34 | "" "" | 35 | "" "" |
35 | SKIP= | 36 | SKIP= |
36 | 37 | ||
37 | testing "Two zeroed blocks is a ('truncated') empty tarball" '\ | 38 | testing "tar Two zeroed blocks is a ('truncated') empty tarball" '\ |
38 | dd if=/dev/zero bs=512 count=2 2>/dev/null | tar xvf - 2>&1; echo $? | 39 | dd if=/dev/zero bs=512 count=2 2>/dev/null | tar xvf - 2>&1; echo $? |
39 | ' "\ | 40 | ' "\ |
40 | 0 | 41 | 0 |
@@ -42,7 +43,7 @@ dd if=/dev/zero bs=512 count=2 2>/dev/null | tar xvf - 2>&1; echo $? | |||
42 | "" "" | 43 | "" "" |
43 | SKIP= | 44 | SKIP= |
44 | 45 | ||
45 | testing "Twenty zeroed blocks is an empty tarball" '\ | 46 | testing "tar Twenty zeroed blocks is an empty tarball" '\ |
46 | dd if=/dev/zero bs=512 count=20 2>/dev/null | tar xvf - 2>&1; echo $? | 47 | dd if=/dev/zero bs=512 count=20 2>/dev/null | tar xvf - 2>&1; echo $? |
47 | ' "\ | 48 | ' "\ |
48 | 0 | 49 | 0 |
@@ -313,9 +314,10 @@ l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI= | |||
313 | SKIP= | 314 | SKIP= |
314 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null | 315 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null |
315 | 316 | ||
317 | if test x"$CONFIG_UNICODE_USING_LOCALE" != x"y"; then | ||
316 | mkdir tar.tempdir && cd tar.tempdir || exit 1 | 318 | mkdir tar.tempdir && cd tar.tempdir || exit 1 |
317 | optional UNICODE_SUPPORT FEATURE_TAR_GNU_EXTENSIONS FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT | 319 | optional UNICODE_SUPPORT FEATURE_TAR_GNU_EXTENSIONS FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT |
318 | testing "Pax-encoded UTF8 names and symlinks" '\ | 320 | testing "tar Pax-encoded UTF8 names and symlinks" '\ |
319 | tar xvf ../tar.utf8.tar.bz2 2>&1; echo $? | 321 | tar xvf ../tar.utf8.tar.bz2 2>&1; echo $? |
320 | export LANG=en_US.UTF-8 | 322 | export LANG=en_US.UTF-8 |
321 | ls -l etc/ssl/certs/* | sed "s:.*etc/:etc/:" | sort | 323 | ls -l etc/ssl/certs/* | sed "s:.*etc/:etc/:" | sort |
@@ -334,10 +336,11 @@ etc/ssl/certs/f80cc7f6.0 -> EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem | |||
334 | "" "" | 336 | "" "" |
335 | SKIP= | 337 | SKIP= |
336 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null | 338 | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null |
339 | fi | ||
337 | 340 | ||
338 | mkdir tar.tempdir && cd tar.tempdir || exit 1 | 341 | mkdir tar.tempdir && cd tar.tempdir || exit 1 |
339 | optional FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT LS | 342 | optional FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT LS |
340 | testing "Symlink attack: create symlink and then write through it" '\ | 343 | testing "tar Symlink attack: create symlink and then write through it" '\ |
341 | exec 2>&1 | 344 | exec 2>&1 |
342 | uudecode -o input && tar xvf input; echo $? | 345 | uudecode -o input && tar xvf input; echo $? |
343 | ls /tmp/bb_test_evilfile | 346 | ls /tmp/bb_test_evilfile |
@@ -367,7 +370,7 @@ cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null | |||
367 | 370 | ||
368 | mkdir tar.tempdir && cd tar.tempdir || exit 1 | 371 | mkdir tar.tempdir && cd tar.tempdir || exit 1 |
369 | optional FEATURE_TAR_CREATE | 372 | optional FEATURE_TAR_CREATE |
370 | testing "Symlinks and hardlinks coexist" '\ | 373 | testing "tar Symlinks and hardlinks coexist" '\ |
371 | mkdir dir | 374 | mkdir dir |
372 | >dir/a | 375 | >dir/a |
373 | ln -s ../dir/a dir/b | 376 | ln -s ../dir/a dir/b |
diff --git a/util-linux/fdisk_sun.c b/util-linux/fdisk_sun.c index 427b9487b..66e434833 100644 --- a/util-linux/fdisk_sun.c +++ b/util-linux/fdisk_sun.c | |||
@@ -292,10 +292,10 @@ create_sunlabel(void) | |||
292 | } else { | 292 | } else { |
293 | g_heads = read_int(1, g_heads, 1024, 0, "Heads"); | 293 | g_heads = read_int(1, g_heads, 1024, 0, "Heads"); |
294 | g_sectors = read_int(1, g_sectors, 1024, 0, "Sectors/track"); | 294 | g_sectors = read_int(1, g_sectors, 1024, 0, "Sectors/track"); |
295 | if (g_cylinders) | 295 | if (g_cylinders) |
296 | g_cylinders = read_int(1, g_cylinders - 2, 65535, 0, "Cylinders"); | 296 | g_cylinders = read_int(1, g_cylinders - 2, 65535, 0, "Cylinders"); |
297 | else | 297 | else |
298 | g_cylinders = read_int(1, 0, 65535, 0, "Cylinders"); | 298 | g_cylinders = read_int(1, 0, 65535, 0, "Cylinders"); |
299 | sunlabel->nacyl = SUN_SSWAP16(read_int(0, 2, 65535, 0, "Alternate cylinders")); | 299 | sunlabel->nacyl = SUN_SSWAP16(read_int(0, 2, 65535, 0, "Alternate cylinders")); |
300 | sunlabel->pcylcount = SUN_SSWAP16(read_int(0, g_cylinders + SUN_SSWAP16(sunlabel->nacyl), 65535, 0, "Physical cylinders")); | 300 | sunlabel->pcylcount = SUN_SSWAP16(read_int(0, g_cylinders + SUN_SSWAP16(sunlabel->nacyl), 65535, 0, "Physical cylinders")); |
301 | sunlabel->rspeed = SUN_SSWAP16(read_int(1, 5400, 100000, 0, "Rotation speed (rpm)")); | 301 | sunlabel->rspeed = SUN_SSWAP16(read_int(1, 5400, 100000, 0, "Rotation speed (rpm)")); |
diff --git a/util-linux/taskset.c b/util-linux/taskset.c index afe2f04d2..d2ef9b98f 100644 --- a/util-linux/taskset.c +++ b/util-linux/taskset.c | |||
@@ -218,7 +218,7 @@ static int process_pid_str(const char *pid_str, unsigned opts, char *aff) | |||
218 | ul *mask; | 218 | ul *mask; |
219 | unsigned mask_size_in_bytes; | 219 | unsigned mask_size_in_bytes; |
220 | const char *current_new; | 220 | const char *current_new; |
221 | pid_t pid = xatoi_positive(pid_str); | 221 | pid_t pid = !pid_str ? 0 : xatou_range(pid_str, 1, INT_MAX); /* disallow "0": "taskset -p 0" should fail */ |
222 | 222 | ||
223 | mask_size_in_bytes = SZOF_UL; | 223 | mask_size_in_bytes = SZOF_UL; |
224 | current_new = "current"; | 224 | current_new = "current"; |
@@ -343,7 +343,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) | |||
343 | /* <aff> <cmd...> */ | 343 | /* <aff> <cmd...> */ |
344 | if (!*argv) | 344 | if (!*argv) |
345 | bb_show_usage(); | 345 | bb_show_usage(); |
346 | process_pid_str("0", opts, aff); | 346 | process_pid_str(NULL, opts, aff); |
347 | BB_EXECVP_or_die(argv); | 347 | BB_EXECVP_or_die(argv); |
348 | } | 348 | } |
349 | 349 | ||