diff options
author | Ron Yorston <rmy@pobox.com> | 2014-12-14 14:20:56 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2014-12-14 14:20:56 +0000 |
commit | 6d6d18d45c145899fce3a39553771cf0af671f30 (patch) | |
tree | 1936d18cbf61b9e0989464aad0a11c52cbeff7b7 | |
parent | 0c204dc07b718244c360e0b84df66ce0a012e14f (diff) | |
parent | acb8be721768b54075a51d1859d390904a0f1f6c (diff) | |
download | busybox-w32-6d6d18d45c145899fce3a39553771cf0af671f30.tar.gz busybox-w32-6d6d18d45c145899fce3a39553771cf0af671f30.tar.bz2 busybox-w32-6d6d18d45c145899fce3a39553771cf0af671f30.zip |
Merge branch 'busybox' into merge
Conflicts:
archival/libarchive/open_transformer.c
libbb/lineedit.c
miscutils/man.c
44 files changed, 645 insertions, 345 deletions
diff --git a/.gitignore b/.gitignore index cae1d53dd..01400a678 100644 --- a/.gitignore +++ b/.gitignore | |||
@@ -42,3 +42,4 @@ core | |||
42 | # | 42 | # |
43 | /busybox.links | 43 | /busybox.links |
44 | /runtest-tempdir-links | 44 | /runtest-tempdir-links |
45 | /testsuite/echo-ne | ||
@@ -278,6 +278,19 @@ config PAM | |||
278 | Use PAM in some busybox applets (currently login and httpd) instead | 278 | Use PAM in some busybox applets (currently login and httpd) instead |
279 | of direct access to password database. | 279 | of direct access to password database. |
280 | 280 | ||
281 | config FEATURE_USE_SENDFILE | ||
282 | bool "Use sendfile system call" | ||
283 | default y | ||
284 | select PLATFORM_LINUX | ||
285 | help | ||
286 | When enabled, busybox will use the kernel sendfile() function | ||
287 | instead of read/write loops to copy data between file descriptors | ||
288 | (for example, cp command does this a lot). | ||
289 | If sendfile() doesn't work, copying code falls back to read/write | ||
290 | loop. sendfile() was originally implemented for faster I/O | ||
291 | from files to sockets, but since Linux 2.6.33 it was extended | ||
292 | to work for many more file types. | ||
293 | |||
281 | config LONG_OPTS | 294 | config LONG_OPTS |
282 | bool "Support for --long-options" | 295 | bool "Support for --long-options" |
283 | default y | 296 | default y |
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 4d417f3f1..a859ef201 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -39,7 +39,7 @@ char* FAST_FUNC append_ext(char *filename, const char *expected_ext) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | int FAST_FUNC bbunpack(char **argv, | 41 | int FAST_FUNC bbunpack(char **argv, |
42 | IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_aux_data_t *aux), | 42 | IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_state_t *xstate), |
43 | char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), | 43 | char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), |
44 | const char *expected_ext | 44 | const char *expected_ext |
45 | ) | 45 | ) |
@@ -48,7 +48,7 @@ int FAST_FUNC bbunpack(char **argv, | |||
48 | IF_DESKTOP(long long) int status = 0; | 48 | IF_DESKTOP(long long) int status = 0; |
49 | char *filename, *new_name; | 49 | char *filename, *new_name; |
50 | smallint exitcode = 0; | 50 | smallint exitcode = 0; |
51 | transformer_aux_data_t aux; | 51 | transformer_state_t xstate; |
52 | 52 | ||
53 | do { | 53 | do { |
54 | /* NB: new_name is *maybe* malloc'ed! */ | 54 | /* NB: new_name is *maybe* malloc'ed! */ |
@@ -120,9 +120,11 @@ int FAST_FUNC bbunpack(char **argv, | |||
120 | } | 120 | } |
121 | 121 | ||
122 | if (!(option_mask32 & SEAMLESS_MAGIC)) { | 122 | if (!(option_mask32 & SEAMLESS_MAGIC)) { |
123 | init_transformer_aux_data(&aux); | 123 | init_transformer_state(&xstate); |
124 | aux.check_signature = 1; | 124 | xstate.check_signature = 1; |
125 | status = unpacker(&aux); | 125 | /*xstate.src_fd = STDIN_FILENO; - already is */ |
126 | xstate.dst_fd = STDOUT_FILENO; | ||
127 | status = unpacker(&xstate); | ||
126 | if (status < 0) | 128 | if (status < 0) |
127 | exitcode = 1; | 129 | exitcode = 1; |
128 | } else { | 130 | } else { |
@@ -141,10 +143,10 @@ int FAST_FUNC bbunpack(char **argv, | |||
141 | unsigned new_name_len; | 143 | unsigned new_name_len; |
142 | 144 | ||
143 | /* TODO: restore other things? */ | 145 | /* TODO: restore other things? */ |
144 | if (aux.mtime != 0) { | 146 | if (xstate.mtime != 0) { |
145 | struct timeval times[2]; | 147 | struct timeval times[2]; |
146 | 148 | ||
147 | times[1].tv_sec = times[0].tv_sec = aux.mtime; | 149 | times[1].tv_sec = times[0].tv_sec = xstate.mtime; |
148 | times[1].tv_usec = times[0].tv_usec = 0; | 150 | times[1].tv_usec = times[0].tv_usec = 0; |
149 | /* Note: we closed it first. | 151 | /* Note: we closed it first. |
150 | * On some systems calling utimes | 152 | * On some systems calling utimes |
@@ -228,18 +230,13 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) | |||
228 | //applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP)) | 230 | //applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP)) |
229 | //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o | 231 | //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o |
230 | #if ENABLE_UNCOMPRESS | 232 | #if ENABLE_UNCOMPRESS |
231 | static | ||
232 | IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(transformer_aux_data_t *aux) | ||
233 | { | ||
234 | return unpack_Z_stream(aux, STDIN_FILENO, STDOUT_FILENO); | ||
235 | } | ||
236 | int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 233 | int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
237 | int uncompress_main(int argc UNUSED_PARAM, char **argv) | 234 | int uncompress_main(int argc UNUSED_PARAM, char **argv) |
238 | { | 235 | { |
239 | getopt32(argv, "cf"); | 236 | getopt32(argv, "cf"); |
240 | argv += optind; | 237 | argv += optind; |
241 | 238 | ||
242 | return bbunpack(argv, unpack_uncompress, make_new_name_generic, "Z"); | 239 | return bbunpack(argv, unpack_Z_stream, make_new_name_generic, "Z"); |
243 | } | 240 | } |
244 | #endif | 241 | #endif |
245 | 242 | ||
@@ -326,11 +323,6 @@ char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UN | |||
326 | } | 323 | } |
327 | return filename; | 324 | return filename; |
328 | } | 325 | } |
329 | static | ||
330 | IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_aux_data_t *aux) | ||
331 | { | ||
332 | return unpack_gz_stream(aux, STDIN_FILENO, STDOUT_FILENO); | ||
333 | } | ||
334 | /* | 326 | /* |
335 | * Linux kernel build uses gzip -d -n. We accept and ignore it. | 327 | * Linux kernel build uses gzip -d -n. We accept and ignore it. |
336 | * Man page says: | 328 | * Man page says: |
@@ -357,7 +349,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
357 | if (applet_name[1] == 'c') | 349 | if (applet_name[1] == 'c') |
358 | option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; | 350 | option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; |
359 | 351 | ||
360 | return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL); | 352 | return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); |
361 | } | 353 | } |
362 | #endif | 354 | #endif |
363 | 355 | ||
@@ -397,11 +389,6 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
397 | //kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o | 389 | //kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o |
398 | //kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o | 390 | //kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o |
399 | #if ENABLE_BUNZIP2 | 391 | #if ENABLE_BUNZIP2 |
400 | static | ||
401 | IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_aux_data_t *aux) | ||
402 | { | ||
403 | return unpack_bz2_stream(aux, STDIN_FILENO, STDOUT_FILENO); | ||
404 | } | ||
405 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 392 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
406 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) | 393 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) |
407 | { | 394 | { |
@@ -410,7 +397,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
410 | if (applet_name[2] == 'c') /* bzcat */ | 397 | if (applet_name[2] == 'c') /* bzcat */ |
411 | option_mask32 |= OPT_STDOUT; | 398 | option_mask32 |= OPT_STDOUT; |
412 | 399 | ||
413 | return bbunpack(argv, unpack_bunzip2, make_new_name_generic, "bz2"); | 400 | return bbunpack(argv, unpack_bz2_stream, make_new_name_generic, "bz2"); |
414 | } | 401 | } |
415 | #endif | 402 | #endif |
416 | 403 | ||
@@ -496,11 +483,6 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
496 | //applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) | 483 | //applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) |
497 | //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o | 484 | //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o |
498 | #if ENABLE_UNLZMA | 485 | #if ENABLE_UNLZMA |
499 | static | ||
500 | IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_aux_data_t *aux) | ||
501 | { | ||
502 | return unpack_lzma_stream(aux, STDIN_FILENO, STDOUT_FILENO); | ||
503 | } | ||
504 | int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 486 | int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
505 | int unlzma_main(int argc UNUSED_PARAM, char **argv) | 487 | int unlzma_main(int argc UNUSED_PARAM, char **argv) |
506 | { | 488 | { |
@@ -515,7 +497,7 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
515 | option_mask32 |= OPT_STDOUT; | 497 | option_mask32 |= OPT_STDOUT; |
516 | 498 | ||
517 | argv += optind; | 499 | argv += optind; |
518 | return bbunpack(argv, unpack_unlzma, make_new_name_generic, "lzma"); | 500 | return bbunpack(argv, unpack_lzma_stream, make_new_name_generic, "lzma"); |
519 | } | 501 | } |
520 | #endif | 502 | #endif |
521 | 503 | ||
@@ -539,11 +521,6 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) | |||
539 | //applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) | 521 | //applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) |
540 | //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o | 522 | //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o |
541 | #if ENABLE_UNXZ | 523 | #if ENABLE_UNXZ |
542 | static | ||
543 | IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_aux_data_t *aux) | ||
544 | { | ||
545 | return unpack_xz_stream(aux, STDIN_FILENO, STDOUT_FILENO); | ||
546 | } | ||
547 | int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 524 | int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
548 | int unxz_main(int argc UNUSED_PARAM, char **argv) | 525 | int unxz_main(int argc UNUSED_PARAM, char **argv) |
549 | { | 526 | { |
@@ -558,6 +535,6 @@ int unxz_main(int argc UNUSED_PARAM, char **argv) | |||
558 | option_mask32 |= OPT_STDOUT; | 535 | option_mask32 |= OPT_STDOUT; |
559 | 536 | ||
560 | argv += optind; | 537 | argv += optind; |
561 | return bbunpack(argv, unpack_unxz, make_new_name_generic, "xz"); | 538 | return bbunpack(argv, unpack_xz_stream, make_new_name_generic, "xz"); |
562 | } | 539 | } |
563 | #endif | 540 | #endif |
diff --git a/archival/bzip2.c b/archival/bzip2.c index f7718b411..47fa29af3 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c | |||
@@ -127,7 +127,7 @@ IF_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, vo | |||
127 | } | 127 | } |
128 | 128 | ||
129 | static | 129 | static |
130 | IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_aux_data_t *aux UNUSED_PARAM) | 130 | IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_state_t *xstate UNUSED_PARAM) |
131 | { | 131 | { |
132 | IF_DESKTOP(long long) int total; | 132 | IF_DESKTOP(long long) int total; |
133 | ssize_t count; | 133 | ssize_t count; |
diff --git a/archival/gzip.c b/archival/gzip.c index 1e779c9c3..a93d2175a 100644 --- a/archival/gzip.c +++ b/archival/gzip.c | |||
@@ -2042,7 +2042,7 @@ static void zip(ulg time_stamp) | |||
2042 | 2042 | ||
2043 | /* ======================================================================== */ | 2043 | /* ======================================================================== */ |
2044 | static | 2044 | static |
2045 | IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_aux_data_t *aux UNUSED_PARAM) | 2045 | IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED_PARAM) |
2046 | { | 2046 | { |
2047 | struct stat s; | 2047 | struct stat s; |
2048 | 2048 | ||
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 6396fe40d..fe5953da2 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c | |||
@@ -731,7 +731,7 @@ void FAST_FUNC dealloc_bunzip(bunzip_data *bd) | |||
731 | 731 | ||
732 | /* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ | 732 | /* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ |
733 | IF_DESKTOP(long long) int FAST_FUNC | 733 | IF_DESKTOP(long long) int FAST_FUNC |
734 | unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | 734 | unpack_bz2_stream(transformer_state_t *xstate) |
735 | { | 735 | { |
736 | IF_DESKTOP(long long total_written = 0;) | 736 | IF_DESKTOP(long long total_written = 0;) |
737 | bunzip_data *bd; | 737 | bunzip_data *bd; |
@@ -739,14 +739,14 @@ unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
739 | int i; | 739 | int i; |
740 | unsigned len; | 740 | unsigned len; |
741 | 741 | ||
742 | if (check_signature16(aux, src_fd, BZIP2_MAGIC)) | 742 | if (check_signature16(xstate, BZIP2_MAGIC)) |
743 | return -1; | 743 | return -1; |
744 | 744 | ||
745 | outbuf = xmalloc(IOBUF_SIZE); | 745 | outbuf = xmalloc(IOBUF_SIZE); |
746 | len = 0; | 746 | len = 0; |
747 | while (1) { /* "Process one BZ... stream" loop */ | 747 | while (1) { /* "Process one BZ... stream" loop */ |
748 | 748 | ||
749 | i = start_bunzip(&bd, src_fd, outbuf + 2, len); | 749 | i = start_bunzip(&bd, xstate->src_fd, outbuf + 2, len); |
750 | 750 | ||
751 | if (i == 0) { | 751 | if (i == 0) { |
752 | while (1) { /* "Produce some output bytes" loop */ | 752 | while (1) { /* "Produce some output bytes" loop */ |
@@ -756,8 +756,7 @@ unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
756 | i = IOBUF_SIZE - i; /* number of bytes produced */ | 756 | i = IOBUF_SIZE - i; /* number of bytes produced */ |
757 | if (i == 0) /* EOF? */ | 757 | if (i == 0) /* EOF? */ |
758 | break; | 758 | break; |
759 | if (i != full_write(dst_fd, outbuf, i)) { | 759 | if (i != transformer_write(xstate, outbuf, i)) { |
760 | bb_error_msg("short write"); | ||
761 | i = RETVAL_SHORT_WRITE; | 760 | i = RETVAL_SHORT_WRITE; |
762 | goto release_mem; | 761 | goto release_mem; |
763 | } | 762 | } |
@@ -790,7 +789,7 @@ unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
790 | len = bd->inbufCount - bd->inbufPos; | 789 | len = bd->inbufCount - bd->inbufPos; |
791 | memcpy(outbuf, &bd->inbuf[bd->inbufPos], len); | 790 | memcpy(outbuf, &bd->inbuf[bd->inbufPos], len); |
792 | if (len < 2) { | 791 | if (len < 2) { |
793 | if (safe_read(src_fd, outbuf + len, 2 - len) != 2 - len) | 792 | if (safe_read(xstate->src_fd, outbuf + len, 2 - len) != 2 - len) |
794 | break; | 793 | break; |
795 | len = 2; | 794 | len = 2; |
796 | } | 795 | } |
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 7c6f38ec3..1360abef7 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c | |||
@@ -971,7 +971,7 @@ static int inflate_get_next_window(STATE_PARAM_ONLY) | |||
971 | 971 | ||
972 | /* Called from unpack_gz_stream() and inflate_unzip() */ | 972 | /* Called from unpack_gz_stream() and inflate_unzip() */ |
973 | static IF_DESKTOP(long long) int | 973 | static IF_DESKTOP(long long) int |
974 | inflate_unzip_internal(STATE_PARAM int in, int out) | 974 | inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate) |
975 | { | 975 | { |
976 | IF_DESKTOP(long long) int n = 0; | 976 | IF_DESKTOP(long long) int n = 0; |
977 | ssize_t nwrote; | 977 | ssize_t nwrote; |
@@ -980,7 +980,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out) | |||
980 | gunzip_window = xmalloc(GUNZIP_WSIZE); | 980 | gunzip_window = xmalloc(GUNZIP_WSIZE); |
981 | gunzip_outbuf_count = 0; | 981 | gunzip_outbuf_count = 0; |
982 | gunzip_bytes_out = 0; | 982 | gunzip_bytes_out = 0; |
983 | gunzip_src_fd = in; | 983 | gunzip_src_fd = xstate->src_fd; |
984 | 984 | ||
985 | /* (re) initialize state */ | 985 | /* (re) initialize state */ |
986 | method = -1; | 986 | method = -1; |
@@ -1002,9 +1002,8 @@ inflate_unzip_internal(STATE_PARAM int in, int out) | |||
1002 | 1002 | ||
1003 | while (1) { | 1003 | while (1) { |
1004 | int r = inflate_get_next_window(PASS_STATE_ONLY); | 1004 | int r = inflate_get_next_window(PASS_STATE_ONLY); |
1005 | nwrote = full_write(out, gunzip_window, gunzip_outbuf_count); | 1005 | nwrote = transformer_write(xstate, gunzip_window, gunzip_outbuf_count); |
1006 | if (nwrote != (ssize_t)gunzip_outbuf_count) { | 1006 | if (nwrote == (ssize_t)-1) { |
1007 | bb_perror_msg("write"); | ||
1008 | n = -1; | 1007 | n = -1; |
1009 | goto ret; | 1008 | goto ret; |
1010 | } | 1009 | } |
@@ -1034,22 +1033,22 @@ inflate_unzip_internal(STATE_PARAM int in, int out) | |||
1034 | /* For unzip */ | 1033 | /* For unzip */ |
1035 | 1034 | ||
1036 | IF_DESKTOP(long long) int FAST_FUNC | 1035 | IF_DESKTOP(long long) int FAST_FUNC |
1037 | inflate_unzip(transformer_aux_data_t *aux, int in, int out) | 1036 | inflate_unzip(transformer_state_t *xstate) |
1038 | { | 1037 | { |
1039 | IF_DESKTOP(long long) int n; | 1038 | IF_DESKTOP(long long) int n; |
1040 | DECLARE_STATE; | 1039 | DECLARE_STATE; |
1041 | 1040 | ||
1042 | ALLOC_STATE; | 1041 | ALLOC_STATE; |
1043 | 1042 | ||
1044 | to_read = aux->bytes_in; | 1043 | to_read = xstate->bytes_in; |
1045 | // bytebuffer_max = 0x8000; | 1044 | // bytebuffer_max = 0x8000; |
1046 | bytebuffer_offset = 4; | 1045 | bytebuffer_offset = 4; |
1047 | bytebuffer = xmalloc(bytebuffer_max); | 1046 | bytebuffer = xmalloc(bytebuffer_max); |
1048 | n = inflate_unzip_internal(PASS_STATE in, out); | 1047 | n = inflate_unzip_internal(PASS_STATE xstate); |
1049 | free(bytebuffer); | 1048 | free(bytebuffer); |
1050 | 1049 | ||
1051 | aux->crc32 = gunzip_crc; | 1050 | xstate->crc32 = gunzip_crc; |
1052 | aux->bytes_out = gunzip_bytes_out; | 1051 | xstate->bytes_out = gunzip_bytes_out; |
1053 | DEALLOC_STATE; | 1052 | DEALLOC_STATE; |
1054 | return n; | 1053 | return n; |
1055 | } | 1054 | } |
@@ -1107,7 +1106,7 @@ static uint32_t buffer_read_le_u32(STATE_PARAM_ONLY) | |||
1107 | return res; | 1106 | return res; |
1108 | } | 1107 | } |
1109 | 1108 | ||
1110 | static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux) | 1109 | static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) |
1111 | { | 1110 | { |
1112 | union { | 1111 | union { |
1113 | unsigned char raw[8]; | 1112 | unsigned char raw[8]; |
@@ -1169,8 +1168,7 @@ static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux) | |||
1169 | } | 1168 | } |
1170 | } | 1169 | } |
1171 | 1170 | ||
1172 | if (aux) | 1171 | xstate->mtime = SWAP_LE32(header.formatted.mtime); |
1173 | aux->mtime = SWAP_LE32(header.formatted.mtime); | ||
1174 | 1172 | ||
1175 | /* Read the header checksum */ | 1173 | /* Read the header checksum */ |
1176 | if (header.formatted.flags & 0x02) { | 1174 | if (header.formatted.flags & 0x02) { |
@@ -1182,27 +1180,27 @@ static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux) | |||
1182 | } | 1180 | } |
1183 | 1181 | ||
1184 | IF_DESKTOP(long long) int FAST_FUNC | 1182 | IF_DESKTOP(long long) int FAST_FUNC |
1185 | unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | 1183 | unpack_gz_stream(transformer_state_t *xstate) |
1186 | { | 1184 | { |
1187 | uint32_t v32; | 1185 | uint32_t v32; |
1188 | IF_DESKTOP(long long) int total, n; | 1186 | IF_DESKTOP(long long) int total, n; |
1189 | DECLARE_STATE; | 1187 | DECLARE_STATE; |
1190 | 1188 | ||
1191 | #if !ENABLE_FEATURE_SEAMLESS_Z | 1189 | #if !ENABLE_FEATURE_SEAMLESS_Z |
1192 | if (check_signature16(aux, src_fd, GZIP_MAGIC)) | 1190 | if (check_signature16(xstate, GZIP_MAGIC)) |
1193 | return -1; | 1191 | return -1; |
1194 | #else | 1192 | #else |
1195 | if (aux && aux->check_signature) { | 1193 | if (xstate->check_signature) { |
1196 | uint16_t magic2; | 1194 | uint16_t magic2; |
1197 | 1195 | ||
1198 | if (full_read(src_fd, &magic2, 2) != 2) { | 1196 | if (full_read(xstate->src_fd, &magic2, 2) != 2) { |
1199 | bad_magic: | 1197 | bad_magic: |
1200 | bb_error_msg("invalid magic"); | 1198 | bb_error_msg("invalid magic"); |
1201 | return -1; | 1199 | return -1; |
1202 | } | 1200 | } |
1203 | if (magic2 == COMPRESS_MAGIC) { | 1201 | if (magic2 == COMPRESS_MAGIC) { |
1204 | aux->check_signature = 0; | 1202 | xstate->check_signature = 0; |
1205 | return unpack_Z_stream(aux, src_fd, dst_fd); | 1203 | return unpack_Z_stream(xstate); |
1206 | } | 1204 | } |
1207 | if (magic2 != GZIP_MAGIC) | 1205 | if (magic2 != GZIP_MAGIC) |
1208 | goto bad_magic; | 1206 | goto bad_magic; |
@@ -1215,16 +1213,16 @@ unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
1215 | to_read = -1; | 1213 | to_read = -1; |
1216 | // bytebuffer_max = 0x8000; | 1214 | // bytebuffer_max = 0x8000; |
1217 | bytebuffer = xmalloc(bytebuffer_max); | 1215 | bytebuffer = xmalloc(bytebuffer_max); |
1218 | gunzip_src_fd = src_fd; | 1216 | gunzip_src_fd = xstate->src_fd; |
1219 | 1217 | ||
1220 | again: | 1218 | again: |
1221 | if (!check_header_gzip(PASS_STATE aux)) { | 1219 | if (!check_header_gzip(PASS_STATE xstate)) { |
1222 | bb_error_msg("corrupted data"); | 1220 | bb_error_msg("corrupted data"); |
1223 | total = -1; | 1221 | total = -1; |
1224 | goto ret; | 1222 | goto ret; |
1225 | } | 1223 | } |
1226 | 1224 | ||
1227 | n = inflate_unzip_internal(PASS_STATE src_fd, dst_fd); | 1225 | n = inflate_unzip_internal(PASS_STATE xstate); |
1228 | if (n < 0) { | 1226 | if (n < 0) { |
1229 | total = -1; | 1227 | total = -1; |
1230 | goto ret; | 1228 | goto ret; |
diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c index 53c27080f..496d864a7 100644 --- a/archival/libarchive/decompress_uncompress.c +++ b/archival/libarchive/decompress_uncompress.c | |||
@@ -73,7 +73,7 @@ | |||
73 | */ | 73 | */ |
74 | 74 | ||
75 | IF_DESKTOP(long long) int FAST_FUNC | 75 | IF_DESKTOP(long long) int FAST_FUNC |
76 | unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | 76 | unpack_Z_stream(transformer_state_t *xstate) |
77 | { | 77 | { |
78 | IF_DESKTOP(long long total_written = 0;) | 78 | IF_DESKTOP(long long total_written = 0;) |
79 | IF_DESKTOP(long long) int retval = -1; | 79 | IF_DESKTOP(long long) int retval = -1; |
@@ -102,7 +102,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
102 | /* block compress mode -C compatible with 2.0 */ | 102 | /* block compress mode -C compatible with 2.0 */ |
103 | int block_mode; /* = BLOCK_MODE; */ | 103 | int block_mode; /* = BLOCK_MODE; */ |
104 | 104 | ||
105 | if (check_signature16(aux, src_fd, COMPRESS_MAGIC)) | 105 | if (check_signature16(xstate, COMPRESS_MAGIC)) |
106 | return -1; | 106 | return -1; |
107 | 107 | ||
108 | inbuf = xzalloc(IBUFSIZ + 64); | 108 | inbuf = xzalloc(IBUFSIZ + 64); |
@@ -114,7 +114,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
114 | 114 | ||
115 | /* xread isn't good here, we have to return - caller may want | 115 | /* xread isn't good here, we have to return - caller may want |
116 | * to do some cleanup (e.g. delete incomplete unpacked file etc) */ | 116 | * to do some cleanup (e.g. delete incomplete unpacked file etc) */ |
117 | if (full_read(src_fd, inbuf, 1) != 1) { | 117 | if (full_read(xstate->src_fd, inbuf, 1) != 1) { |
118 | bb_error_msg("short read"); | 118 | bb_error_msg("short read"); |
119 | goto err; | 119 | goto err; |
120 | } | 120 | } |
@@ -166,7 +166,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
166 | } | 166 | } |
167 | 167 | ||
168 | if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { | 168 | if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { |
169 | rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ); | 169 | rsize = safe_read(xstate->src_fd, inbuf + insize, IBUFSIZ); |
170 | if (rsize < 0) | 170 | if (rsize < 0) |
171 | bb_error_msg_and_die(bb_msg_read_error); | 171 | bb_error_msg_and_die(bb_msg_read_error); |
172 | insize += rsize; | 172 | insize += rsize; |
@@ -274,7 +274,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
274 | } | 274 | } |
275 | 275 | ||
276 | if (outpos >= OBUFSIZ) { | 276 | if (outpos >= OBUFSIZ) { |
277 | xwrite(dst_fd, outbuf, outpos); | 277 | xtransformer_write(xstate, outbuf, outpos); |
278 | IF_DESKTOP(total_written += outpos;) | 278 | IF_DESKTOP(total_written += outpos;) |
279 | outpos = 0; | 279 | outpos = 0; |
280 | } | 280 | } |
@@ -301,7 +301,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
301 | } while (rsize > 0); | 301 | } while (rsize > 0); |
302 | 302 | ||
303 | if (outpos > 0) { | 303 | if (outpos > 0) { |
304 | xwrite(dst_fd, outbuf, outpos); | 304 | xtransformer_write(xstate, outbuf, outpos); |
305 | IF_DESKTOP(total_written += outpos;) | 305 | IF_DESKTOP(total_written += outpos;) |
306 | } | 306 | } |
307 | 307 | ||
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index 3d99e1388..c8622f97b 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c | |||
@@ -206,7 +206,7 @@ enum { | |||
206 | 206 | ||
207 | 207 | ||
208 | IF_DESKTOP(long long) int FAST_FUNC | 208 | IF_DESKTOP(long long) int FAST_FUNC |
209 | unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst_fd) | 209 | unpack_lzma_stream(transformer_state_t *xstate) |
210 | { | 210 | { |
211 | IF_DESKTOP(long long total_written = 0;) | 211 | IF_DESKTOP(long long total_written = 0;) |
212 | lzma_header_t header; | 212 | lzma_header_t header; |
@@ -223,7 +223,7 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst | |||
223 | int state = 0; | 223 | int state = 0; |
224 | uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; | 224 | uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; |
225 | 225 | ||
226 | if (full_read(src_fd, &header, sizeof(header)) != sizeof(header) | 226 | if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header) |
227 | || header.pos >= (9 * 5 * 5) | 227 | || header.pos >= (9 * 5 * 5) |
228 | ) { | 228 | ) { |
229 | bb_error_msg("bad lzma header"); | 229 | bb_error_msg("bad lzma header"); |
@@ -258,7 +258,7 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst | |||
258 | p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; | 258 | p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; |
259 | } | 259 | } |
260 | 260 | ||
261 | rc = rc_init(src_fd); /*, RC_BUFFER_SIZE); */ | 261 | rc = rc_init(xstate->src_fd); /*, RC_BUFFER_SIZE); */ |
262 | 262 | ||
263 | while (global_pos + buffer_pos < header.dst_size) { | 263 | while (global_pos + buffer_pos < header.dst_size) { |
264 | int pos_state = (buffer_pos + global_pos) & pos_state_mask; | 264 | int pos_state = (buffer_pos + global_pos) & pos_state_mask; |
@@ -306,7 +306,7 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst | |||
306 | if (buffer_pos == header.dict_size) { | 306 | if (buffer_pos == header.dict_size) { |
307 | buffer_pos = 0; | 307 | buffer_pos = 0; |
308 | global_pos += header.dict_size; | 308 | global_pos += header.dict_size; |
309 | if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size) | 309 | if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size) |
310 | goto bad; | 310 | goto bad; |
311 | IF_DESKTOP(total_written += header.dict_size;) | 311 | IF_DESKTOP(total_written += header.dict_size;) |
312 | } | 312 | } |
@@ -440,7 +440,7 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst | |||
440 | if (buffer_pos == header.dict_size) { | 440 | if (buffer_pos == header.dict_size) { |
441 | buffer_pos = 0; | 441 | buffer_pos = 0; |
442 | global_pos += header.dict_size; | 442 | global_pos += header.dict_size; |
443 | if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size) | 443 | if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size) |
444 | goto bad; | 444 | goto bad; |
445 | IF_DESKTOP(total_written += header.dict_size;) | 445 | IF_DESKTOP(total_written += header.dict_size;) |
446 | } | 446 | } |
@@ -455,7 +455,7 @@ unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst | |||
455 | { | 455 | { |
456 | IF_NOT_DESKTOP(int total_written = 0; /* success */) | 456 | IF_NOT_DESKTOP(int total_written = 0; /* success */) |
457 | IF_DESKTOP(total_written += buffer_pos;) | 457 | IF_DESKTOP(total_written += buffer_pos;) |
458 | if (full_write(dst_fd, buffer, buffer_pos) != (ssize_t)buffer_pos) { | 458 | if (transformer_write(xstate, buffer, buffer_pos) != (ssize_t)buffer_pos) { |
459 | bad: | 459 | bad: |
460 | total_written = -1; /* failure */ | 460 | total_written = -1; /* failure */ |
461 | } | 461 | } |
diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 986b7b191..1f408abfd 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c | |||
@@ -38,7 +38,7 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) | |||
38 | #include "unxz/xz_dec_stream.c" | 38 | #include "unxz/xz_dec_stream.c" |
39 | 39 | ||
40 | IF_DESKTOP(long long) int FAST_FUNC | 40 | IF_DESKTOP(long long) int FAST_FUNC |
41 | unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | 41 | unpack_xz_stream(transformer_state_t *xstate) |
42 | { | 42 | { |
43 | enum xz_ret xz_result; | 43 | enum xz_ret xz_result; |
44 | struct xz_buf iobuf; | 44 | struct xz_buf iobuf; |
@@ -55,7 +55,7 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
55 | iobuf.out = membuf + BUFSIZ; | 55 | iobuf.out = membuf + BUFSIZ; |
56 | iobuf.out_size = BUFSIZ; | 56 | iobuf.out_size = BUFSIZ; |
57 | 57 | ||
58 | if (!aux || aux->check_signature == 0) { | 58 | if (!xstate || xstate->check_signature == 0) { |
59 | /* Preload XZ file signature */ | 59 | /* Preload XZ file signature */ |
60 | strcpy((char*)membuf, HEADER_MAGIC); | 60 | strcpy((char*)membuf, HEADER_MAGIC); |
61 | iobuf.in_size = HEADER_MAGIC_SIZE; | 61 | iobuf.in_size = HEADER_MAGIC_SIZE; |
@@ -67,7 +67,7 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
67 | xz_result = X_OK; | 67 | xz_result = X_OK; |
68 | while (1) { | 68 | while (1) { |
69 | if (iobuf.in_pos == iobuf.in_size) { | 69 | if (iobuf.in_pos == iobuf.in_size) { |
70 | int rd = safe_read(src_fd, membuf, BUFSIZ); | 70 | int rd = safe_read(xstate->src_fd, membuf, BUFSIZ); |
71 | if (rd < 0) { | 71 | if (rd < 0) { |
72 | bb_error_msg(bb_msg_read_error); | 72 | bb_error_msg(bb_msg_read_error); |
73 | total = -1; | 73 | total = -1; |
@@ -104,7 +104,7 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
104 | // bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d", | 104 | // bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d", |
105 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, xz_result); | 105 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, xz_result); |
106 | if (iobuf.out_pos) { | 106 | if (iobuf.out_pos) { |
107 | xwrite(dst_fd, iobuf.out, iobuf.out_pos); | 107 | xtransformer_write(xstate, iobuf.out, iobuf.out_pos); |
108 | IF_DESKTOP(total += iobuf.out_pos;) | 108 | IF_DESKTOP(total += iobuf.out_pos;) |
109 | iobuf.out_pos = 0; | 109 | iobuf.out_pos = 0; |
110 | } | 110 | } |
diff --git a/archival/libarchive/get_header_tar_bz2.c b/archival/libarchive/get_header_tar_bz2.c index 0ee00df53..78f78a858 100644 --- a/archival/libarchive/get_header_tar_bz2.c +++ b/archival/libarchive/get_header_tar_bz2.c | |||
@@ -11,7 +11,7 @@ char FAST_FUNC get_header_tar_bz2(archive_handle_t *archive_handle) | |||
11 | /* Can't lseek over pipes */ | 11 | /* Can't lseek over pipes */ |
12 | archive_handle->seek = seek_by_read; | 12 | archive_handle->seek = seek_by_read; |
13 | 13 | ||
14 | open_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2"); | 14 | fork_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2"); |
15 | archive_handle->offset = 0; | 15 | archive_handle->offset = 0; |
16 | while (get_header_tar(archive_handle) == EXIT_SUCCESS) | 16 | while (get_header_tar(archive_handle) == EXIT_SUCCESS) |
17 | continue; | 17 | continue; |
diff --git a/archival/libarchive/get_header_tar_gz.c b/archival/libarchive/get_header_tar_gz.c index 03284342b..b11f503dc 100644 --- a/archival/libarchive/get_header_tar_gz.c +++ b/archival/libarchive/get_header_tar_gz.c | |||
@@ -11,7 +11,7 @@ char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle) | |||
11 | /* Can't lseek over pipes */ | 11 | /* Can't lseek over pipes */ |
12 | archive_handle->seek = seek_by_read; | 12 | archive_handle->seek = seek_by_read; |
13 | 13 | ||
14 | open_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip"); | 14 | fork_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip"); |
15 | archive_handle->offset = 0; | 15 | archive_handle->offset = 0; |
16 | while (get_header_tar(archive_handle) == EXIT_SUCCESS) | 16 | while (get_header_tar(archive_handle) == EXIT_SUCCESS) |
17 | continue; | 17 | continue; |
diff --git a/archival/libarchive/get_header_tar_lzma.c b/archival/libarchive/get_header_tar_lzma.c index d565a217d..d228cbc13 100644 --- a/archival/libarchive/get_header_tar_lzma.c +++ b/archival/libarchive/get_header_tar_lzma.c | |||
@@ -14,7 +14,7 @@ char FAST_FUNC get_header_tar_lzma(archive_handle_t *archive_handle) | |||
14 | /* Can't lseek over pipes */ | 14 | /* Can't lseek over pipes */ |
15 | archive_handle->seek = seek_by_read; | 15 | archive_handle->seek = seek_by_read; |
16 | 16 | ||
17 | open_transformer_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma"); | 17 | fork_transformer_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma"); |
18 | archive_handle->offset = 0; | 18 | archive_handle->offset = 0; |
19 | while (get_header_tar(archive_handle) == EXIT_SUCCESS) | 19 | while (get_header_tar(archive_handle) == EXIT_SUCCESS) |
20 | continue; | 20 | continue; |
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 7e0d1dd02..0a8c657b7 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -6,19 +6,19 @@ | |||
6 | #include "libbb.h" | 6 | #include "libbb.h" |
7 | #include "bb_archive.h" | 7 | #include "bb_archive.h" |
8 | 8 | ||
9 | void FAST_FUNC init_transformer_aux_data(transformer_aux_data_t *aux) | 9 | void FAST_FUNC init_transformer_state(transformer_state_t *xstate) |
10 | { | 10 | { |
11 | memset(aux, 0, sizeof(*aux)); | 11 | memset(xstate, 0, sizeof(*xstate)); |
12 | } | 12 | } |
13 | 13 | ||
14 | int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16) | 14 | int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16) |
15 | { | 15 | { |
16 | if (aux && aux->check_signature) { | 16 | if (xstate->check_signature) { |
17 | uint16_t magic2; | 17 | uint16_t magic2; |
18 | if (full_read(src_fd, &magic2, 2) != 2 || magic2 != magic16) { | 18 | if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { |
19 | bb_error_msg("invalid magic"); | 19 | bb_error_msg("invalid magic"); |
20 | #if 0 /* possible future extension */ | 20 | #if 0 /* possible future extension */ |
21 | if (aux->check_signature > 1) | 21 | if (xstate->check_signature > 1) |
22 | xfunc_die(); | 22 | xfunc_die(); |
23 | #endif | 23 | #endif |
24 | return -1; | 24 | return -1; |
@@ -27,9 +27,48 @@ int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigne | |||
27 | return 0; | 27 | return 0; |
28 | } | 28 | } |
29 | 29 | ||
30 | ssize_t FAST_FUNC transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) | ||
31 | { | ||
32 | ssize_t nwrote; | ||
30 | 33 | ||
31 | #if SEAMLESS_COMPRESSION | 34 | if (xstate->mem_output_size_max != 0) { |
35 | size_t pos = xstate->mem_output_size; | ||
36 | size_t size; | ||
37 | |||
38 | size = (xstate->mem_output_size += bufsize); | ||
39 | if (size > xstate->mem_output_size_max) { | ||
40 | free(xstate->mem_output_buf); | ||
41 | xstate->mem_output_buf = NULL; | ||
42 | bb_perror_msg("buffer %u too small", (unsigned)xstate->mem_output_size_max); | ||
43 | nwrote = -1; | ||
44 | goto ret; | ||
45 | } | ||
46 | xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size + 1); | ||
47 | memcpy(xstate->mem_output_buf + pos, buf, bufsize); | ||
48 | xstate->mem_output_buf[size] = '\0'; | ||
49 | nwrote = bufsize; | ||
50 | } else { | ||
51 | nwrote = full_write(xstate->dst_fd, buf, bufsize); | ||
52 | if (nwrote != (ssize_t)bufsize) { | ||
53 | bb_perror_msg("write"); | ||
54 | nwrote = -1; | ||
55 | goto ret; | ||
56 | } | ||
57 | } | ||
58 | ret: | ||
59 | return nwrote; | ||
60 | } | ||
61 | |||
62 | ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) | ||
63 | { | ||
64 | ssize_t nwrote = transformer_write(xstate, buf, bufsize); | ||
65 | if (nwrote != (ssize_t)bufsize) { | ||
66 | xfunc_die(); | ||
67 | } | ||
68 | return nwrote; | ||
69 | } | ||
32 | 70 | ||
71 | #if SEAMLESS_COMPRESSION | ||
33 | void check_errors_in_children(int signo) | 72 | void check_errors_in_children(int signo) |
34 | { | 73 | { |
35 | int status; | 74 | int status; |
@@ -63,12 +102,12 @@ void check_errors_in_children(int signo) | |||
63 | 102 | ||
64 | /* transformer(), more than meets the eye */ | 103 | /* transformer(), more than meets the eye */ |
65 | #if BB_MMU | 104 | #if BB_MMU |
66 | void FAST_FUNC open_transformer(int fd, | 105 | void FAST_FUNC fork_transformer(int fd, |
67 | int check_signature, | 106 | int check_signature, |
68 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd) | 107 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) |
69 | ) | 108 | ) |
70 | #else | 109 | #else |
71 | void FAST_FUNC open_transformer(int fd, const char *transform_prog) | 110 | void FAST_FUNC fork_transformer(int fd, const char *transform_prog) |
72 | #endif | 111 | #endif |
73 | { | 112 | { |
74 | struct fd_pair fd_pipe; | 113 | struct fd_pair fd_pipe; |
@@ -83,10 +122,12 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog) | |||
83 | #if BB_MMU | 122 | #if BB_MMU |
84 | { | 123 | { |
85 | IF_DESKTOP(long long) int r; | 124 | IF_DESKTOP(long long) int r; |
86 | transformer_aux_data_t aux; | 125 | transformer_state_t xstate; |
87 | init_transformer_aux_data(&aux); | 126 | init_transformer_state(&xstate); |
88 | aux.check_signature = check_signature; | 127 | xstate.check_signature = check_signature; |
89 | r = transformer(&aux, fd, fd_pipe.wr); | 128 | xstate.src_fd = fd; |
129 | xstate.dst_fd = fd_pipe.wr; | ||
130 | r = transformer(&xstate); | ||
90 | if (ENABLE_FEATURE_CLEAN_UP) { | 131 | if (ENABLE_FEATURE_CLEAN_UP) { |
91 | close(fd_pipe.wr); /* send EOF */ | 132 | close(fd_pipe.wr); /* send EOF */ |
92 | close(fd); | 133 | close(fd); |
@@ -118,16 +159,19 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog) | |||
118 | /* Used by e.g. rpm which gives us a fd without filename, | 159 | /* Used by e.g. rpm which gives us a fd without filename, |
119 | * thus we can't guess the format from filename's extension. | 160 | * thus we can't guess the format from filename's extension. |
120 | */ | 161 | */ |
121 | int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | 162 | static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) |
122 | { | 163 | { |
123 | union { | 164 | union { |
124 | uint8_t b[4]; | 165 | uint8_t b[4]; |
125 | uint16_t b16[2]; | 166 | uint16_t b16[2]; |
126 | uint32_t b32[1]; | 167 | uint32_t b32[1]; |
127 | } magic; | 168 | } magic; |
128 | int offset = -2; | 169 | int offset; |
129 | USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);) | 170 | transformer_state_t *xstate; |
130 | USE_FOR_NOMMU(const char *xformer_prog;) | 171 | |
172 | offset = -2; | ||
173 | xstate = xzalloc(sizeof(*xstate)); | ||
174 | xstate->src_fd = fd; | ||
131 | 175 | ||
132 | /* .gz and .bz2 both have 2-byte signature, and their | 176 | /* .gz and .bz2 both have 2-byte signature, and their |
133 | * unpack_XXX_stream wants this header skipped. */ | 177 | * unpack_XXX_stream wants this header skipped. */ |
@@ -135,15 +179,15 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | |||
135 | if (ENABLE_FEATURE_SEAMLESS_GZ | 179 | if (ENABLE_FEATURE_SEAMLESS_GZ |
136 | && magic.b16[0] == GZIP_MAGIC | 180 | && magic.b16[0] == GZIP_MAGIC |
137 | ) { | 181 | ) { |
138 | USE_FOR_MMU(xformer = unpack_gz_stream;) | 182 | xstate->xformer = unpack_gz_stream; |
139 | USE_FOR_NOMMU(xformer_prog = "gunzip";) | 183 | USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) |
140 | goto found_magic; | 184 | goto found_magic; |
141 | } | 185 | } |
142 | if (ENABLE_FEATURE_SEAMLESS_BZ2 | 186 | if (ENABLE_FEATURE_SEAMLESS_BZ2 |
143 | && magic.b16[0] == BZIP2_MAGIC | 187 | && magic.b16[0] == BZIP2_MAGIC |
144 | ) { | 188 | ) { |
145 | USE_FOR_MMU(xformer = unpack_bz2_stream;) | 189 | xstate->xformer = unpack_bz2_stream; |
146 | USE_FOR_NOMMU(xformer_prog = "bunzip2";) | 190 | USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) |
147 | goto found_magic; | 191 | goto found_magic; |
148 | } | 192 | } |
149 | if (ENABLE_FEATURE_SEAMLESS_XZ | 193 | if (ENABLE_FEATURE_SEAMLESS_XZ |
@@ -152,8 +196,8 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | |||
152 | offset = -6; | 196 | offset = -6; |
153 | xread(fd, magic.b32, sizeof(magic.b32[0])); | 197 | xread(fd, magic.b32, sizeof(magic.b32[0])); |
154 | if (magic.b32[0] == XZ_MAGIC2) { | 198 | if (magic.b32[0] == XZ_MAGIC2) { |
155 | USE_FOR_MMU(xformer = unpack_xz_stream;) | 199 | xstate->xformer = unpack_xz_stream; |
156 | USE_FOR_NOMMU(xformer_prog = "unxz";) | 200 | USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) |
157 | goto found_magic; | 201 | goto found_magic; |
158 | } | 202 | } |
159 | } | 203 | } |
@@ -164,52 +208,130 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | |||
164 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") | 208 | IF_FEATURE_SEAMLESS_BZ2("/bzip2") |
165 | IF_FEATURE_SEAMLESS_XZ("/xz") | 209 | IF_FEATURE_SEAMLESS_XZ("/xz") |
166 | " magic"); | 210 | " magic"); |
211 | |||
212 | /* Some callers expect this function to "consume" fd | ||
213 | * even if data is not compressed. In this case, | ||
214 | * we return a state with trivial transformer. | ||
215 | */ | ||
216 | // USE_FOR_MMU(xstate->xformer = copy_stream;) | ||
217 | // USE_FOR_NOMMU(xstate->xformer_prog = "cat";) | ||
218 | /* fall through to seeking bck over bytes we read earlier */ | ||
219 | |||
220 | USE_FOR_NOMMU(found_magic:) | ||
221 | /* NOMMU version of fork_transformer execs | ||
222 | * an external unzipper that wants | ||
223 | * file position at the start of the file. | ||
224 | */ | ||
167 | xlseek(fd, offset, SEEK_CUR); | 225 | xlseek(fd, offset, SEEK_CUR); |
168 | return 1; | ||
169 | 226 | ||
170 | found_magic: | 227 | USE_FOR_MMU(found_magic:) |
228 | /* In MMU case, if magic was found, seeking back is not necessary */ | ||
229 | |||
230 | return xstate; | ||
231 | } | ||
232 | |||
233 | /* Used by e.g. rpm which gives us a fd without filename, | ||
234 | * thus we can't guess the format from filename's extension. | ||
235 | */ | ||
236 | int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | ||
237 | { | ||
238 | transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); | ||
239 | |||
240 | if (!xstate || !xstate->xformer) { | ||
241 | free(xstate); | ||
242 | return 1; | ||
243 | } | ||
244 | |||
171 | # if BB_MMU | 245 | # if BB_MMU |
172 | open_transformer_with_no_sig(fd, xformer); | 246 | fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); |
173 | # else | 247 | # else |
174 | /* NOMMU version of open_transformer execs | 248 | fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); |
175 | * an external unzipper that wants | ||
176 | * file position at the start of the file */ | ||
177 | xlseek(fd, offset, SEEK_CUR); | ||
178 | open_transformer_with_sig(fd, xformer, xformer_prog); | ||
179 | # endif | 249 | # endif |
250 | free(xstate); | ||
180 | return 0; | 251 | return 0; |
181 | } | 252 | } |
182 | 253 | ||
183 | int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) | 254 | static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed) |
184 | { | 255 | { |
256 | transformer_state_t *xstate; | ||
185 | int fd; | 257 | int fd; |
186 | 258 | ||
187 | fd = open(fname, O_RDONLY); | 259 | fd = open(fname, O_RDONLY); |
188 | if (fd < 0) | 260 | if (fd < 0) |
189 | return fd; | 261 | return NULL; |
190 | 262 | ||
191 | if (ENABLE_FEATURE_SEAMLESS_LZMA) { | 263 | if (ENABLE_FEATURE_SEAMLESS_LZMA) { |
192 | /* .lzma has no header/signature, can only detect it by extension */ | 264 | /* .lzma has no header/signature, can only detect it by extension */ |
193 | char *sfx = strrchr(fname, '.'); | 265 | char *sfx = strrchr(fname, '.'); |
194 | if (sfx && strcmp(sfx+1, "lzma") == 0) { | 266 | if (sfx && strcmp(sfx+1, "lzma") == 0) { |
195 | open_transformer_with_sig(fd, unpack_lzma_stream, "unlzma"); | 267 | xstate = xzalloc(sizeof(*xstate)); |
196 | return fd; | 268 | xstate->src_fd = fd; |
269 | xstate->xformer = unpack_lzma_stream; | ||
270 | USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";) | ||
271 | return xstate; | ||
197 | } | 272 | } |
198 | } | 273 | } |
199 | if ((ENABLE_FEATURE_SEAMLESS_GZ) | 274 | |
200 | || (ENABLE_FEATURE_SEAMLESS_BZ2) | 275 | xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); |
201 | || (ENABLE_FEATURE_SEAMLESS_XZ) | 276 | |
202 | ) { | 277 | return xstate; |
203 | setup_unzip_on_fd(fd, fail_if_not_compressed); | 278 | } |
279 | |||
280 | int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) | ||
281 | { | ||
282 | int fd; | ||
283 | transformer_state_t *xstate; | ||
284 | |||
285 | xstate = open_transformer(fname, fail_if_not_compressed); | ||
286 | if (!xstate) | ||
287 | return -1; | ||
288 | |||
289 | fd = xstate->src_fd; | ||
290 | if (xstate->xformer) { | ||
291 | # if BB_MMU | ||
292 | fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); | ||
293 | # else | ||
294 | fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); | ||
295 | # endif | ||
204 | } | 296 | } |
297 | /* else: the file is not compressed */ | ||
205 | 298 | ||
299 | free(xstate); | ||
206 | return fd; | 300 | return fd; |
207 | } | 301 | } |
208 | 302 | ||
209 | #endif /* SEAMLESS_COMPRESSION */ | ||
210 | |||
211 | void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) | 303 | void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) |
212 | { | 304 | { |
305 | # if 1 | ||
306 | transformer_state_t *xstate; | ||
307 | char *image; | ||
308 | |||
309 | xstate = open_transformer(fname, /*fail_if_not_compressed:*/ 0); | ||
310 | if (!xstate) /* file open error */ | ||
311 | return NULL; | ||
312 | |||
313 | image = NULL; | ||
314 | if (xstate->xformer) { | ||
315 | /* In-memory decompression */ | ||
316 | xstate->mem_output_size_max = maxsz_p ? *maxsz_p : (size_t)(INT_MAX - 4095); | ||
317 | xstate->xformer(xstate); | ||
318 | if (xstate->mem_output_buf) { | ||
319 | image = xstate->mem_output_buf; | ||
320 | if (maxsz_p) | ||
321 | *maxsz_p = xstate->mem_output_size; | ||
322 | } | ||
323 | } else { | ||
324 | /* File is not compressed */ | ||
325 | image = xmalloc_read(xstate->src_fd, maxsz_p); | ||
326 | } | ||
327 | |||
328 | if (!image) | ||
329 | bb_perror_msg("read error from '%s'", fname); | ||
330 | close(xstate->src_fd); | ||
331 | free(xstate); | ||
332 | return image; | ||
333 | # else | ||
334 | /* This version forks a subprocess - much more expensive */ | ||
213 | int fd; | 335 | int fd; |
214 | char *image; | 336 | char *image; |
215 | 337 | ||
@@ -221,6 +343,8 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_ | |||
221 | if (!image) | 343 | if (!image) |
222 | bb_perror_msg("read error from '%s'", fname); | 344 | bb_perror_msg("read error from '%s'", fname); |
223 | close(fd); | 345 | close(fd); |
224 | |||
225 | return image; | 346 | return image; |
347 | # endif | ||
226 | } | 348 | } |
349 | |||
350 | #endif /* SEAMLESS_COMPRESSION */ | ||
diff --git a/archival/lzop.c b/archival/lzop.c index 5062d9300..73d11a705 100644 --- a/archival/lzop.c +++ b/archival/lzop.c | |||
@@ -1099,7 +1099,7 @@ static char* FAST_FUNC make_new_name_lzop(char *filename, const char *expected_e | |||
1099 | return xasprintf("%s.lzo", filename); | 1099 | return xasprintf("%s.lzo", filename); |
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_aux_data_t *aux UNUSED_PARAM) | 1102 | static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_state_t *xstate UNUSED_PARAM) |
1103 | { | 1103 | { |
1104 | if (option_mask32 & OPT_DECOMPRESS) | 1104 | if (option_mask32 & OPT_DECOMPRESS) |
1105 | return do_lzo_decompress(); | 1105 | return do_lzo_decompress(); |
diff --git a/archival/tar.c b/archival/tar.c index 63d844a3a..e00ed26a8 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -160,13 +160,6 @@ | |||
160 | #define block_buf bb_common_bufsiz1 | 160 | #define block_buf bb_common_bufsiz1 |
161 | 161 | ||
162 | 162 | ||
163 | #if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2 | ||
164 | /* Do not pass gzip flag to writeTarFile() */ | ||
165 | #define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \ | ||
166 | writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude) | ||
167 | #endif | ||
168 | |||
169 | |||
170 | #if ENABLE_FEATURE_TAR_CREATE | 163 | #if ENABLE_FEATURE_TAR_CREATE |
171 | 164 | ||
172 | /* | 165 | /* |
@@ -623,21 +616,12 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb | |||
623 | return TRUE; | 616 | return TRUE; |
624 | } | 617 | } |
625 | 618 | ||
626 | #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 | 619 | #if SEAMLESS_COMPRESSION |
627 | # if !(ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2) | ||
628 | # define vfork_compressor(tar_fd, gzip) vfork_compressor(tar_fd) | ||
629 | # endif | ||
630 | /* Don't inline: vfork scares gcc and pessimizes code */ | 620 | /* Don't inline: vfork scares gcc and pessimizes code */ |
631 | static void NOINLINE vfork_compressor(int tar_fd, int gzip) | 621 | static void NOINLINE vfork_compressor(int tar_fd, const char *gzip) |
632 | { | 622 | { |
633 | pid_t gzipPid; | 623 | pid_t gzipPid; |
634 | # if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2 | 624 | |
635 | const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; | ||
636 | # elif ENABLE_FEATURE_SEAMLESS_GZ | ||
637 | const char *zip_exec = "gzip"; | ||
638 | # else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */ | ||
639 | const char *zip_exec = "bzip2"; | ||
640 | # endif | ||
641 | // On Linux, vfork never unpauses parent early, although standard | 625 | // On Linux, vfork never unpauses parent early, although standard |
642 | // allows for that. Do we want to waste bytes checking for it? | 626 | // allows for that. Do we want to waste bytes checking for it? |
643 | # define WAIT_FOR_CHILD 0 | 627 | # define WAIT_FOR_CHILD 0 |
@@ -651,11 +635,6 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) | |||
651 | 635 | ||
652 | signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ | 636 | signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ |
653 | 637 | ||
654 | # if defined(__GNUC__) && __GNUC__ | ||
655 | /* Avoid vfork clobbering */ | ||
656 | (void) &zip_exec; | ||
657 | # endif | ||
658 | |||
659 | gzipPid = xvfork(); | 638 | gzipPid = xvfork(); |
660 | 639 | ||
661 | if (gzipPid == 0) { | 640 | if (gzipPid == 0) { |
@@ -671,7 +650,7 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) | |||
671 | xmove_fd(gzipDataPipe.rd, 0); | 650 | xmove_fd(gzipDataPipe.rd, 0); |
672 | xmove_fd(tar_fd, 1); | 651 | xmove_fd(tar_fd, 1); |
673 | /* exec gzip/bzip2 program/applet */ | 652 | /* exec gzip/bzip2 program/applet */ |
674 | BB_EXECLP(zip_exec, zip_exec, "-f", (char *)0); | 653 | BB_EXECLP(gzip, gzip, "-f", (char *)0); |
675 | vfork_exec_errno = errno; | 654 | vfork_exec_errno = errno; |
676 | _exit(EXIT_FAILURE); | 655 | _exit(EXIT_FAILURE); |
677 | } | 656 | } |
@@ -694,16 +673,21 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) | |||
694 | # endif | 673 | # endif |
695 | if (vfork_exec_errno) { | 674 | if (vfork_exec_errno) { |
696 | errno = vfork_exec_errno; | 675 | errno = vfork_exec_errno; |
697 | bb_perror_msg_and_die("can't execute '%s'", zip_exec); | 676 | bb_perror_msg_and_die("can't execute '%s'", gzip); |
698 | } | 677 | } |
699 | } | 678 | } |
700 | #endif /* ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 */ | 679 | #endif /* SEAMLESS_COMPRESSION */ |
701 | 680 | ||
702 | 681 | ||
682 | #if !SEAMLESS_COMPRESSION | ||
683 | /* Do not pass gzip flag to writeTarFile() */ | ||
684 | #define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \ | ||
685 | writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude) | ||
686 | #endif | ||
703 | /* gcc 4.2.1 inlines it, making code bigger */ | 687 | /* gcc 4.2.1 inlines it, making code bigger */ |
704 | static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, | 688 | static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, |
705 | int recurseFlags, const llist_t *include, | 689 | int recurseFlags, const llist_t *include, |
706 | const llist_t *exclude, int gzip) | 690 | const llist_t *exclude, const char *gzip) |
707 | { | 691 | { |
708 | int errorFlag = FALSE; | 692 | int errorFlag = FALSE; |
709 | struct TarBallInfo tbInfo; | 693 | struct TarBallInfo tbInfo; |
@@ -716,7 +700,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, | |||
716 | * can avoid including the tarball into itself.... */ | 700 | * can avoid including the tarball into itself.... */ |
717 | xfstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf, "can't stat tar file"); | 701 | xfstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf, "can't stat tar file"); |
718 | 702 | ||
719 | #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 | 703 | #if SEAMLESS_COMPRESSION |
720 | if (gzip) | 704 | if (gzip) |
721 | vfork_compressor(tbInfo.tarFd, gzip); | 705 | vfork_compressor(tbInfo.tarFd, gzip); |
722 | #endif | 706 | #endif |
@@ -751,7 +735,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, | |||
751 | if (errorFlag) | 735 | if (errorFlag) |
752 | bb_error_msg("error exit delayed from previous errors"); | 736 | bb_error_msg("error exit delayed from previous errors"); |
753 | 737 | ||
754 | #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 | 738 | #if SEAMLESS_COMPRESSION |
755 | if (gzip) { | 739 | if (gzip) { |
756 | int status; | 740 | int status; |
757 | if (safe_waitpid(-1, &status, 0) == -1) | 741 | if (safe_waitpid(-1, &status, 0) == -1) |
@@ -766,7 +750,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, | |||
766 | #else | 750 | #else |
767 | int writeTarFile(int tar_fd, int verboseFlag, | 751 | int writeTarFile(int tar_fd, int verboseFlag, |
768 | int recurseFlags, const llist_t *include, | 752 | int recurseFlags, const llist_t *include, |
769 | const llist_t *exclude, int gzip); | 753 | const llist_t *exclude, const char *gzip); |
770 | #endif /* FEATURE_TAR_CREATE */ | 754 | #endif /* FEATURE_TAR_CREATE */ |
771 | 755 | ||
772 | #if ENABLE_FEATURE_TAR_FROM | 756 | #if ENABLE_FEATURE_TAR_FROM |
@@ -1151,18 +1135,24 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1151 | if (base_dir) | 1135 | if (base_dir) |
1152 | xchdir(base_dir); | 1136 | xchdir(base_dir); |
1153 | 1137 | ||
1154 | //if (SEAMLESS_COMPRESSION || OPT_COMPRESS) | 1138 | //if (SEAMLESS_COMPRESSION) |
1155 | // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ | 1139 | // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ |
1156 | // signal(SIGCHLD, check_errors_in_children); | 1140 | // signal(SIGCHLD, check_errors_in_children); |
1157 | 1141 | ||
1158 | /* Create an archive */ | 1142 | /* Create an archive */ |
1159 | if (opt & OPT_CREATE) { | 1143 | if (opt & OPT_CREATE) { |
1160 | #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 | 1144 | #if SEAMLESS_COMPRESSION |
1161 | int zipMode = 0; | 1145 | const char *zipMode = NULL; |
1162 | if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP)) | 1146 | if (opt & OPT_COMPRESS) |
1163 | zipMode = 1; | 1147 | zipMode = "compress"; |
1164 | if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2)) | 1148 | if (opt & OPT_GZIP) |
1165 | zipMode = 2; | 1149 | zipMode = "gzip"; |
1150 | if (opt & OPT_BZIP2) | ||
1151 | zipMode = "bzip2"; | ||
1152 | if (opt & OPT_LZMA) | ||
1153 | zipMode = "lzma"; | ||
1154 | if (opt & OPT_XZ) | ||
1155 | zipMode = "xz"; | ||
1166 | #endif | 1156 | #endif |
1167 | /* NB: writeTarFile() closes tar_handle->src_fd */ | 1157 | /* NB: writeTarFile() closes tar_handle->src_fd */ |
1168 | return writeTarFile(tar_handle->src_fd, verboseFlag, | 1158 | return writeTarFile(tar_handle->src_fd, verboseFlag, |
@@ -1173,7 +1163,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1173 | } | 1163 | } |
1174 | 1164 | ||
1175 | if (opt & OPT_ANY_COMPRESS) { | 1165 | if (opt & OPT_ANY_COMPRESS) { |
1176 | USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);) | 1166 | USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);) |
1177 | USE_FOR_NOMMU(const char *xformer_prog;) | 1167 | USE_FOR_NOMMU(const char *xformer_prog;) |
1178 | 1168 | ||
1179 | if (opt & OPT_COMPRESS) | 1169 | if (opt & OPT_COMPRESS) |
@@ -1192,7 +1182,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1192 | USE_FOR_MMU(xformer = unpack_xz_stream;) | 1182 | USE_FOR_MMU(xformer = unpack_xz_stream;) |
1193 | USE_FOR_NOMMU(xformer_prog = "unxz";) | 1183 | USE_FOR_NOMMU(xformer_prog = "unxz";) |
1194 | 1184 | ||
1195 | open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); | 1185 | fork_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); |
1196 | /* Can't lseek over pipes */ | 1186 | /* Can't lseek over pipes */ |
1197 | tar_handle->seek = seek_by_read; | 1187 | tar_handle->seek = seek_by_read; |
1198 | /*tar_handle->offset = 0; - already is */ | 1188 | /*tar_handle->offset = 0; - already is */ |
diff --git a/archival/unzip.c b/archival/unzip.c index fcfc9a448..38a07e212 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -280,17 +280,19 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd) | |||
280 | bb_copyfd_exact_size(zip_fd, dst_fd, size); | 280 | bb_copyfd_exact_size(zip_fd, dst_fd, size); |
281 | } else { | 281 | } else { |
282 | /* Method 8 - inflate */ | 282 | /* Method 8 - inflate */ |
283 | transformer_aux_data_t aux; | 283 | transformer_state_t xstate; |
284 | init_transformer_aux_data(&aux); | 284 | init_transformer_state(&xstate); |
285 | aux.bytes_in = zip_header->formatted.cmpsize; | 285 | xstate.bytes_in = zip_header->formatted.cmpsize; |
286 | if (inflate_unzip(&aux, zip_fd, dst_fd) < 0) | 286 | xstate.src_fd = zip_fd; |
287 | xstate.dst_fd = dst_fd; | ||
288 | if (inflate_unzip(&xstate) < 0) | ||
287 | bb_error_msg_and_die("inflate error"); | 289 | bb_error_msg_and_die("inflate error"); |
288 | /* Validate decompression - crc */ | 290 | /* Validate decompression - crc */ |
289 | if (zip_header->formatted.crc32 != (aux.crc32 ^ 0xffffffffL)) { | 291 | if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) { |
290 | bb_error_msg_and_die("crc error"); | 292 | bb_error_msg_and_die("crc error"); |
291 | } | 293 | } |
292 | /* Validate decompression - size */ | 294 | /* Validate decompression - size */ |
293 | if (zip_header->formatted.ucmpsize != aux.bytes_out) { | 295 | if (zip_header->formatted.ucmpsize != xstate.bytes_out) { |
294 | /* Don't die. Who knows, maybe len calculation | 296 | /* Don't die. Who knows, maybe len calculation |
295 | * was botched somewhere. After all, crc matched! */ | 297 | * was botched somewhere. After all, crc matched! */ |
296 | bb_error_msg("bad length"); | 298 | bb_error_msg("bad length"); |
diff --git a/docs/logging_and_backgrounding.txt b/docs/logging_and_backgrounding.txt index 7e6885560..c76cd3653 100644 --- a/docs/logging_and_backgrounding.txt +++ b/docs/logging_and_backgrounding.txt | |||
@@ -45,6 +45,8 @@ udhcpc - auto-backgrounds unless -f after lease is obtained, | |||
45 | udhcpd - auto-backgrounds and do not log to stderr unless -f, | 45 | udhcpd - auto-backgrounds and do not log to stderr unless -f, |
46 | otherwise logs to stderr, but option -S makes it log *also* to syslog | 46 | otherwise logs to stderr, but option -S makes it log *also* to syslog |
47 | zcip - auto-backgrounds and logs *also* to syslog unless -f | 47 | zcip - auto-backgrounds and logs *also* to syslog unless -f |
48 | behaviour can be overridden with experimental LOGGING env.var | ||
49 | (can be set to either "none" or "syslog") | ||
48 | 50 | ||
49 | Total: 13 applets (+1 obsolete), | 51 | Total: 13 applets (+1 obsolete), |
50 | 4 log to syslog by default (crond fakeidentd inetd zcip), | 52 | 4 log to syslog by default (crond fakeidentd inetd zcip), |
diff --git a/include/bb_archive.h b/include/bb_archive.h index b82cfd83c..a6b166fe3 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h | |||
@@ -203,43 +203,57 @@ int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; | |||
203 | void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; | 203 | void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; |
204 | 204 | ||
205 | /* Meaning and direction (input/output) of the fields are transformer-specific */ | 205 | /* Meaning and direction (input/output) of the fields are transformer-specific */ |
206 | typedef struct transformer_aux_data_t { | 206 | typedef struct transformer_state_t { |
207 | smallint check_signature; /* most often referenced member */ | 207 | smallint check_signature; /* most often referenced member */ |
208 | |||
209 | IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate); | ||
210 | USE_FOR_NOMMU(const char *xformer_prog;) | ||
211 | |||
212 | /* Source */ | ||
213 | int src_fd; | ||
214 | /* Output */ | ||
215 | int dst_fd; | ||
216 | size_t mem_output_size_max; /* if non-zero, decompress to RAM instead of fd */ | ||
217 | size_t mem_output_size; | ||
218 | char *mem_output_buf; | ||
219 | |||
208 | off_t bytes_out; | 220 | off_t bytes_out; |
209 | off_t bytes_in; /* used in unzip code only: needs to know packed size */ | 221 | off_t bytes_in; /* used in unzip code only: needs to know packed size */ |
210 | uint32_t crc32; | 222 | uint32_t crc32; |
211 | time_t mtime; /* gunzip code may set this on exit */ | 223 | time_t mtime; /* gunzip code may set this on exit */ |
212 | } transformer_aux_data_t; | 224 | } transformer_state_t; |
213 | 225 | ||
214 | void init_transformer_aux_data(transformer_aux_data_t *aux) FAST_FUNC; | 226 | void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; |
215 | int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16) FAST_FUNC; | 227 | ssize_t transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC; |
228 | ssize_t xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC; | ||
229 | int check_signature16(transformer_state_t *xstate, unsigned magic16) FAST_FUNC; | ||
216 | 230 | ||
217 | IF_DESKTOP(long long) int inflate_unzip(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; | 231 | IF_DESKTOP(long long) int inflate_unzip(transformer_state_t *xstate) FAST_FUNC; |
218 | IF_DESKTOP(long long) int unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; | 232 | IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate) FAST_FUNC; |
219 | IF_DESKTOP(long long) int unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; | 233 | IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate) FAST_FUNC; |
220 | IF_DESKTOP(long long) int unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; | 234 | IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate) FAST_FUNC; |
221 | IF_DESKTOP(long long) int unpack_lzma_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; | 235 | IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate) FAST_FUNC; |
222 | IF_DESKTOP(long long) int unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; | 236 | IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate) FAST_FUNC; |
223 | 237 | ||
224 | char* append_ext(char *filename, const char *expected_ext) FAST_FUNC; | 238 | char* append_ext(char *filename, const char *expected_ext) FAST_FUNC; |
225 | int bbunpack(char **argv, | 239 | int bbunpack(char **argv, |
226 | IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_aux_data_t *aux), | 240 | IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_state_t *xstate), |
227 | char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), | 241 | char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), |
228 | const char *expected_ext | 242 | const char *expected_ext |
229 | ) FAST_FUNC; | 243 | ) FAST_FUNC; |
230 | 244 | ||
231 | void check_errors_in_children(int signo); | 245 | void check_errors_in_children(int signo); |
232 | #if BB_MMU | 246 | #if BB_MMU |
233 | void open_transformer(int fd, | 247 | void fork_transformer(int fd, |
234 | int check_signature, | 248 | int check_signature, |
235 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd) | 249 | IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) |
236 | ) FAST_FUNC; | 250 | ) FAST_FUNC; |
237 | #define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), 1, (transformer)) | 251 | #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer)) |
238 | #define open_transformer_with_no_sig(fd, transformer) open_transformer((fd), 0, (transformer)) | 252 | #define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 0, (transformer)) |
239 | #else | 253 | #else |
240 | void open_transformer(int fd, const char *transform_prog) FAST_FUNC; | 254 | void fork_transformer(int fd, const char *transform_prog) FAST_FUNC; |
241 | #define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), (transform_prog)) | 255 | #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog)) |
242 | /* open_transformer_with_no_sig() does not exist on NOMMU */ | 256 | /* fork_transformer_with_no_sig() does not exist on NOMMU */ |
243 | #endif | 257 | #endif |
244 | 258 | ||
245 | 259 | ||
diff --git a/include/libbb.h b/include/libbb.h index 21a56d78f..802779932 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -744,11 +744,14 @@ extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST | |||
744 | /* Never returns NULL */ | 744 | /* Never returns NULL */ |
745 | extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | 745 | extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; |
746 | 746 | ||
747 | #if defined ARG_MAX | 747 | #if defined(ARG_MAX) && (ARG_MAX >= 60*1024 || !defined(_SC_ARG_MAX)) |
748 | /* Use _constant_ maximum if: defined && (big enough || no variable one exists) */ | ||
748 | # define bb_arg_max() ((unsigned)ARG_MAX) | 749 | # define bb_arg_max() ((unsigned)ARG_MAX) |
749 | #elif defined _SC_ARG_MAX | 750 | #elif defined(_SC_ARG_MAX) |
751 | /* Else use variable one (a bit more expensive) */ | ||
750 | unsigned bb_arg_max(void) FAST_FUNC; | 752 | unsigned bb_arg_max(void) FAST_FUNC; |
751 | #else | 753 | #else |
754 | /* If all else fails */ | ||
752 | # define bb_arg_max() ((unsigned)(32 * 1024)) | 755 | # define bb_arg_max() ((unsigned)(32 * 1024)) |
753 | #endif | 756 | #endif |
754 | unsigned bb_clk_tck(void) FAST_FUNC; | 757 | unsigned bb_clk_tck(void) FAST_FUNC; |
@@ -765,11 +768,12 @@ unsigned bb_clk_tck(void) FAST_FUNC; | |||
765 | extern int setup_unzip_on_fd(int fd, int fail_if_not_compressed) FAST_FUNC; | 768 | extern int setup_unzip_on_fd(int fd, int fail_if_not_compressed) FAST_FUNC; |
766 | /* Autodetects .gz etc */ | 769 | /* Autodetects .gz etc */ |
767 | extern int open_zipped(const char *fname, int fail_if_not_compressed) FAST_FUNC; | 770 | extern int open_zipped(const char *fname, int fail_if_not_compressed) FAST_FUNC; |
771 | extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | ||
768 | #else | 772 | #else |
769 | # define setup_unzip_on_fd(...) (0) | 773 | # define setup_unzip_on_fd(...) (0) |
770 | # define open_zipped(fname, fail_if_not_compressed) open((fname), O_RDONLY); | 774 | # define open_zipped(fname, fail_if_not_compressed) open((fname), O_RDONLY); |
775 | # define xmalloc_open_zipped_read_close(fname, maxsz_p) xmalloc_open_read_close((fname), (maxsz_p)) | ||
771 | #endif | 776 | #endif |
772 | extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; | ||
773 | 777 | ||
774 | extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC; | 778 | extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC; |
775 | // NB: will return short write on error, not -1, | 779 | // NB: will return short write on error, not -1, |
@@ -1120,6 +1124,7 @@ extern void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC; | |||
1120 | extern void bb_perror_nomsg(void) FAST_FUNC; | 1124 | extern void bb_perror_nomsg(void) FAST_FUNC; |
1121 | extern void bb_info_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; | 1125 | extern void bb_info_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; |
1122 | extern void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC; | 1126 | extern void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC; |
1127 | extern void bb_logenv_override(void) FAST_FUNC; | ||
1123 | 1128 | ||
1124 | /* We need to export XXX_main from libbusybox | 1129 | /* We need to export XXX_main from libbusybox |
1125 | * only if we build "individual" binaries | 1130 | * only if we build "individual" binaries |
diff --git a/init/init.c b/init/init.c index de438be20..d99d68ce4 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -822,7 +822,7 @@ static void halt_reboot_pwoff(int sig) | |||
822 | 822 | ||
823 | /* Handler for QUIT - exec "restart" action, | 823 | /* Handler for QUIT - exec "restart" action, |
824 | * else (no such action defined) do nothing */ | 824 | * else (no such action defined) do nothing */ |
825 | static void restart_handler(int sig UNUSED_PARAM) | 825 | static void exec_restart_action(void) |
826 | { | 826 | { |
827 | struct init_action *a; | 827 | struct init_action *a; |
828 | 828 | ||
@@ -975,6 +975,20 @@ static int check_delayed_sigs(void) | |||
975 | #endif | 975 | #endif |
976 | if (sig == SIGINT) | 976 | if (sig == SIGINT) |
977 | run_actions(CTRLALTDEL); | 977 | run_actions(CTRLALTDEL); |
978 | if (sig == SIGQUIT) { | ||
979 | exec_restart_action(); | ||
980 | /* returns only if no restart action defined */ | ||
981 | } | ||
982 | if ((1 << sig) & (0 | ||
983 | #ifdef SIGPWR | ||
984 | + (1 << SIGPWR) | ||
985 | #endif | ||
986 | + (1 << SIGUSR1) | ||
987 | + (1 << SIGUSR2) | ||
988 | + (1 << SIGTERM) | ||
989 | )) { | ||
990 | halt_reboot_pwoff(sig); | ||
991 | } | ||
978 | } | 992 | } |
979 | } | 993 | } |
980 | 994 | ||
@@ -1070,7 +1084,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1070 | 1084 | ||
1071 | #if 0 | 1085 | #if 0 |
1072 | /* It's 2013, does anyone really still depend on this? */ | 1086 | /* It's 2013, does anyone really still depend on this? */ |
1073 | /* If you do, consider adding swapon to sysinot actions then! */ | 1087 | /* If you do, consider adding swapon to sysinit actions then! */ |
1074 | /* struct sysinfo is linux-specific */ | 1088 | /* struct sysinfo is linux-specific */ |
1075 | # ifdef __linux__ | 1089 | # ifdef __linux__ |
1076 | /* Make sure there is enough memory to do something useful. */ | 1090 | /* Make sure there is enough memory to do something useful. */ |
@@ -1134,16 +1148,6 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1134 | if (!DEBUG_INIT) { | 1148 | if (!DEBUG_INIT) { |
1135 | struct sigaction sa; | 1149 | struct sigaction sa; |
1136 | 1150 | ||
1137 | bb_signals(0 | ||
1138 | #ifdef SIGPWR | ||
1139 | + (1 << SIGPWR) /* halt */ | ||
1140 | #endif | ||
1141 | + (1 << SIGUSR1) /* halt */ | ||
1142 | + (1 << SIGTERM) /* reboot */ | ||
1143 | + (1 << SIGUSR2) /* poweroff */ | ||
1144 | , halt_reboot_pwoff); | ||
1145 | signal(SIGQUIT, restart_handler); /* re-exec another init */ | ||
1146 | |||
1147 | /* Stop handler must allow only SIGCONT inside itself */ | 1151 | /* Stop handler must allow only SIGCONT inside itself */ |
1148 | memset(&sa, 0, sizeof(sa)); | 1152 | memset(&sa, 0, sizeof(sa)); |
1149 | sigfillset(&sa.sa_mask); | 1153 | sigfillset(&sa.sa_mask); |
@@ -1158,18 +1162,24 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
1158 | */ | 1162 | */ |
1159 | sigaction_set(SIGSTOP, &sa); /* pause */ | 1163 | sigaction_set(SIGSTOP, &sa); /* pause */ |
1160 | 1164 | ||
1161 | /* SIGINT (Ctrl-Alt-Del) must interrupt wait(), | 1165 | /* These signals must interrupt wait(), |
1162 | * setting handler without SA_RESTART flag. | 1166 | * setting handler without SA_RESTART flag. |
1163 | */ | 1167 | */ |
1164 | bb_signals_recursive_norestart((1 << SIGINT), record_signo); | 1168 | bb_signals_recursive_norestart(0 |
1169 | + (1 << SIGINT) /* Ctrl-Alt-Del */ | ||
1170 | + (1 << SIGQUIT) /* re-exec another init */ | ||
1171 | #ifdef SIGPWR | ||
1172 | + (1 << SIGPWR) /* halt */ | ||
1173 | #endif | ||
1174 | + (1 << SIGUSR1) /* halt */ | ||
1175 | + (1 << SIGTERM) /* reboot */ | ||
1176 | + (1 << SIGUSR2) /* poweroff */ | ||
1177 | #if ENABLE_FEATURE_USE_INITTAB | ||
1178 | + (1 << SIGHUP) /* reread /etc/inittab */ | ||
1179 | #endif | ||
1180 | , record_signo); | ||
1165 | } | 1181 | } |
1166 | 1182 | ||
1167 | /* Set up "reread /etc/inittab" handler. | ||
1168 | * Handler is set up without SA_RESTART, it will interrupt syscalls. | ||
1169 | */ | ||
1170 | if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB) | ||
1171 | bb_signals_recursive_norestart((1 << SIGHUP), record_signo); | ||
1172 | |||
1173 | /* Now run everything that needs to be run */ | 1183 | /* Now run everything that needs to be run */ |
1174 | /* First run the sysinit command */ | 1184 | /* First run the sysinit command */ |
1175 | run_actions(SYSINIT); | 1185 | run_actions(SYSINIT); |
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 1f2ed36d9..1be87b337 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -189,3 +189,6 @@ lib-$(CONFIG_PGREP) += xregcomp.o | |||
189 | lib-$(CONFIG_PKILL) += xregcomp.o | 189 | lib-$(CONFIG_PKILL) += xregcomp.o |
190 | lib-$(CONFIG_DEVFSD) += xregcomp.o | 190 | lib-$(CONFIG_DEVFSD) += xregcomp.o |
191 | lib-$(CONFIG_FEATURE_FIND_REGEX) += xregcomp.o | 191 | lib-$(CONFIG_FEATURE_FIND_REGEX) += xregcomp.o |
192 | |||
193 | # Add the experimental logging functionality, only used by zcip | ||
194 | lib-$(CONFIG_ZCIP) += logenv.o | ||
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 2c85062b4..b74b6e724 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -746,7 +746,8 @@ static int busybox_main(char **argv) | |||
746 | /*bb_error_msg_and_die("applet not found"); - sucks in printf */ | 746 | /*bb_error_msg_and_die("applet not found"); - sucks in printf */ |
747 | full_write2_str(applet_name); | 747 | full_write2_str(applet_name); |
748 | full_write2_str(": applet not found\n"); | 748 | full_write2_str(": applet not found\n"); |
749 | xfunc_die(); | 749 | /* POSIX: "If a command is not found, the exit status shall be 127" */ |
750 | exit(127); | ||
750 | } | 751 | } |
751 | 752 | ||
752 | void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) | 753 | void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) |
@@ -870,6 +871,7 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
870 | /*bb_error_msg_and_die("applet not found"); - sucks in printf */ | 871 | /*bb_error_msg_and_die("applet not found"); - sucks in printf */ |
871 | full_write2_str(applet_name); | 872 | full_write2_str(applet_name); |
872 | full_write2_str(": applet not found\n"); | 873 | full_write2_str(": applet not found\n"); |
873 | xfunc_die(); | 874 | /* POSIX: "If a command is not found, the exit status shall be 127" */ |
875 | exit(127); | ||
874 | #endif | 876 | #endif |
875 | } | 877 | } |
diff --git a/libbb/bbunit.c b/libbb/bbunit.c index 256014441..4c692d59f 100644 --- a/libbb/bbunit.c +++ b/libbb/bbunit.c | |||
@@ -77,7 +77,7 @@ int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
77 | #if WANT_TIMING | 77 | #if WANT_TIMING |
78 | gettimeofday(&end, NULL); | 78 | gettimeofday(&end, NULL); |
79 | timeval_diff(&time_spent, &end, &begin); | 79 | timeval_diff(&time_spent, &end, &begin); |
80 | bb_error_msg("Elapsed time %u.%06u seconds" | 80 | bb_error_msg("Elapsed time %u.%06u seconds", |
81 | (int)time_spent.tv_sec, | 81 | (int)time_spent.tv_sec, |
82 | (int)time_spent.tv_usec); | 82 | (int)time_spent.tv_usec); |
83 | #endif | 83 | #endif |
diff --git a/libbb/copyfd.c b/libbb/copyfd.c index eda2747f9..7e3531903 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c | |||
@@ -8,6 +8,20 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | #if ENABLE_FEATURE_USE_SENDFILE | ||
12 | # include <sys/sendfile.h> | ||
13 | #else | ||
14 | # define sendfile(a,b,c,d) (-1) | ||
15 | #endif | ||
16 | |||
17 | /* | ||
18 | * We were using 0x7fff0000 as sendfile chunk size, but it | ||
19 | * was seen to cause largish delays when user tries to ^C a file copy. | ||
20 | * Let's use a saner size. | ||
21 | * Note: needs to be >= max(CONFIG_FEATURE_COPYBUF_KB), | ||
22 | * or else "copy to eof" code will use neddlesly short reads. | ||
23 | */ | ||
24 | #define SENDFILE_BIGBUF (16*1024*1024) | ||
11 | 25 | ||
12 | /* Used by NOFORK applets (e.g. cat) - must not use xmalloc. | 26 | /* Used by NOFORK applets (e.g. cat) - must not use xmalloc. |
13 | * size < 0 means "ignore write errors", used by tar --to-command | 27 | * size < 0 means "ignore write errors", used by tar --to-command |
@@ -18,12 +32,13 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) | |||
18 | int status = -1; | 32 | int status = -1; |
19 | off_t total = 0; | 33 | off_t total = 0; |
20 | bool continue_on_write_error = 0; | 34 | bool continue_on_write_error = 0; |
21 | #if CONFIG_FEATURE_COPYBUF_KB <= 4 | 35 | ssize_t sendfile_sz; |
36 | #if CONFIG_FEATURE_COPYBUF_KB > 4 | ||
37 | char *buffer = buffer; /* for compiler */ | ||
38 | int buffer_size = 0; | ||
39 | #else | ||
22 | char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; | 40 | char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; |
23 | enum { buffer_size = sizeof(buffer) }; | 41 | enum { buffer_size = sizeof(buffer) }; |
24 | #else | ||
25 | char *buffer; | ||
26 | int buffer_size; | ||
27 | #endif | 42 | #endif |
28 | 43 | ||
29 | if (size < 0) { | 44 | if (size < 0) { |
@@ -31,46 +46,58 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) | |||
31 | continue_on_write_error = 1; | 46 | continue_on_write_error = 1; |
32 | } | 47 | } |
33 | 48 | ||
34 | #if CONFIG_FEATURE_COPYBUF_KB > 4 | ||
35 | if (size > 0 && size <= 4 * 1024) | ||
36 | goto use_small_buf; | ||
37 | /* We want page-aligned buffer, just in case kernel is clever | ||
38 | * and can do page-aligned io more efficiently */ | ||
39 | buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, | ||
40 | PROT_READ | PROT_WRITE, | ||
41 | MAP_PRIVATE | MAP_ANON, | ||
42 | /* ignored: */ -1, 0); | ||
43 | buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; | ||
44 | if (buffer == MAP_FAILED) { | ||
45 | use_small_buf: | ||
46 | buffer = alloca(4 * 1024); | ||
47 | buffer_size = 4 * 1024; | ||
48 | } | ||
49 | #endif | ||
50 | |||
51 | if (src_fd < 0) | 49 | if (src_fd < 0) |
52 | goto out; | 50 | goto out; |
53 | 51 | ||
52 | sendfile_sz = !ENABLE_FEATURE_USE_SENDFILE | ||
53 | ? 0 | ||
54 | : SENDFILE_BIGBUF; | ||
54 | if (!size) { | 55 | if (!size) { |
55 | size = buffer_size; | 56 | size = SENDFILE_BIGBUF; |
56 | status = 1; /* copy until eof */ | 57 | status = 1; /* copy until eof */ |
57 | } | 58 | } |
58 | 59 | ||
59 | while (1) { | 60 | while (1) { |
60 | ssize_t rd; | 61 | ssize_t rd; |
61 | 62 | ||
62 | rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); | 63 | if (sendfile_sz) { |
63 | 64 | rd = sendfile(dst_fd, src_fd, NULL, | |
64 | if (!rd) { /* eof - all done */ | 65 | size > sendfile_sz ? sendfile_sz : size); |
65 | status = 0; | 66 | if (rd >= 0) |
66 | break; | 67 | goto read_ok; |
68 | sendfile_sz = 0; /* do not try sendfile anymore */ | ||
69 | } | ||
70 | #if CONFIG_FEATURE_COPYBUF_KB > 4 | ||
71 | if (buffer_size == 0) { | ||
72 | if (size > 0 && size <= 4 * 1024) | ||
73 | goto use_small_buf; | ||
74 | /* We want page-aligned buffer, just in case kernel is clever | ||
75 | * and can do page-aligned io more efficiently */ | ||
76 | buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, | ||
77 | PROT_READ | PROT_WRITE, | ||
78 | MAP_PRIVATE | MAP_ANON, | ||
79 | /* ignored: */ -1, 0); | ||
80 | buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; | ||
81 | if (buffer == MAP_FAILED) { | ||
82 | use_small_buf: | ||
83 | buffer = alloca(4 * 1024); | ||
84 | buffer_size = 4 * 1024; | ||
85 | } | ||
67 | } | 86 | } |
87 | #endif | ||
88 | rd = safe_read(src_fd, buffer, | ||
89 | size > buffer_size ? buffer_size : size); | ||
68 | if (rd < 0) { | 90 | if (rd < 0) { |
69 | bb_perror_msg(bb_msg_read_error); | 91 | bb_perror_msg(bb_msg_read_error); |
70 | break; | 92 | break; |
71 | } | 93 | } |
94 | read_ok: | ||
95 | if (!rd) { /* eof - all done */ | ||
96 | status = 0; | ||
97 | break; | ||
98 | } | ||
72 | /* dst_fd == -1 is a fake, else... */ | 99 | /* dst_fd == -1 is a fake, else... */ |
73 | if (dst_fd >= 0) { | 100 | if (dst_fd >= 0 && !sendfile_sz) { |
74 | ssize_t wr = full_write(dst_fd, buffer, rd); | 101 | ssize_t wr = full_write(dst_fd, buffer, rd); |
75 | if (wr < rd) { | 102 | if (wr < rd) { |
76 | if (!continue_on_write_error) { | 103 | if (!continue_on_write_error) { |
@@ -92,10 +119,8 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) | |||
92 | } | 119 | } |
93 | out: | 120 | out: |
94 | 121 | ||
95 | #if CONFIG_FEATURE_COPYBUF_KB > 4 | 122 | if (buffer_size > 4 * 1024) |
96 | if (buffer_size != 4 * 1024) | ||
97 | munmap(buffer, buffer_size); | 123 | munmap(buffer, buffer_size); |
98 | #endif | ||
99 | return status ? -1 : total; | 124 | return status ? -1 : total; |
100 | } | 125 | } |
101 | 126 | ||
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 1f5653cb5..3d96a8e9f 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -2316,10 +2316,14 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2316 | if (!isatty(0) || !isatty(1)) { | 2316 | if (!isatty(0) || !isatty(1)) { |
2317 | #else | 2317 | #else |
2318 | if (tcgetattr(STDIN_FILENO, &initial_settings) < 0 | 2318 | if (tcgetattr(STDIN_FILENO, &initial_settings) < 0 |
2319 | || !(initial_settings.c_lflag & ECHO) | 2319 | || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON |
2320 | ) { | 2320 | ) { |
2321 | #endif | 2321 | #endif |
2322 | /* Happens when e.g. stty -echo was run before */ | 2322 | /* Happens when e.g. stty -echo was run before. |
2323 | * But if ICANON is not set, we don't come here. | ||
2324 | * (example: interactive python ^Z-backgrounded, | ||
2325 | * tty is still in "raw mode"). | ||
2326 | */ | ||
2323 | parse_and_put_prompt(prompt); | 2327 | parse_and_put_prompt(prompt); |
2324 | /* fflush_all(); - done by parse_and_put_prompt */ | 2328 | /* fflush_all(); - done by parse_and_put_prompt */ |
2325 | if (fgets(command, maxsize, stdin) == NULL) | 2329 | if (fgets(command, maxsize, stdin) == NULL) |
diff --git a/libbb/logenv.c b/libbb/logenv.c new file mode 100644 index 000000000..66c60bd4e --- /dev/null +++ b/libbb/logenv.c | |||
@@ -0,0 +1,24 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Copyright (C) 2014 by Fugro Intersite B.V. <m.stam@fugro.nl> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
8 | */ | ||
9 | #include "libbb.h" | ||
10 | |||
11 | void FAST_FUNC bb_logenv_override(void) | ||
12 | { | ||
13 | const char* mode = getenv("LOGGING"); | ||
14 | |||
15 | if (!mode) | ||
16 | return; | ||
17 | |||
18 | if (strcmp(mode, "none") == 0) | ||
19 | logmode = LOGMODE_NONE; | ||
20 | #if ENABLE_FEATURE_SYSLOG | ||
21 | else if (strcmp(mode, "syslog") == 0) | ||
22 | logmode = LOGMODE_SYSLOG; | ||
23 | #endif | ||
24 | } | ||
diff --git a/libbb/sysconf.c b/libbb/sysconf.c index 031901980..cfad9cdc0 100644 --- a/libbb/sysconf.c +++ b/libbb/sysconf.c | |||
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | #if !defined(ARG_MAX) && defined(_SC_ARG_MAX) | 11 | #if !defined(bb_arg_max) |
12 | unsigned FAST_FUNC bb_arg_max(void) | 12 | unsigned FAST_FUNC bb_arg_max(void) |
13 | { | 13 | { |
14 | return sysconf(_SC_ARG_MAX); | 14 | return sysconf(_SC_ARG_MAX); |
diff --git a/miscutils/flashcp.c b/miscutils/flashcp.c index b526566a4..9bc588d14 100644 --- a/miscutils/flashcp.c +++ b/miscutils/flashcp.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #define OPT_v (1 << 0) | 22 | #define OPT_v (1 << 0) |
23 | 23 | ||
24 | #define BUFSIZE (8 * 1024) | 24 | #define BUFSIZE (4 * 1024) |
25 | 25 | ||
26 | static void progress(int mode, uoff_t count, uoff_t total) | 26 | static void progress(int mode, uoff_t count, uoff_t total) |
27 | { | 27 | { |
diff --git a/miscutils/man.c b/miscutils/man.c index 0e0b1cba6..3f389b435 100644 --- a/miscutils/man.c +++ b/miscutils/man.c | |||
@@ -147,15 +147,55 @@ static int show_manpage(const char *pager, char *man_filename, int man, int leve | |||
147 | return run_pipe(pager, man_filename, man, level); | 147 | return run_pipe(pager, man_filename, man, level); |
148 | } | 148 | } |
149 | 149 | ||
150 | static char **add_MANPATH(char **man_path_list, int *count_mp, char *path) | ||
151 | { | ||
152 | if (path) while (*path) { | ||
153 | char *next_path; | ||
154 | char **path_element; | ||
155 | |||
156 | #if ENABLE_PLATFORM_MINGW32 | ||
157 | next_path = next_path_sep(path); | ||
158 | #else | ||
159 | next_path = strchr(path, ':'); | ||
160 | #endif | ||
161 | if (next_path) { | ||
162 | if (next_path == path) /* "::"? */ | ||
163 | goto next; | ||
164 | *next_path = '\0'; | ||
165 | } | ||
166 | /* Do we already have path? */ | ||
167 | path_element = man_path_list; | ||
168 | if (path_element) while (*path_element) { | ||
169 | if (strcmp(*path_element, path) == 0) | ||
170 | goto skip; | ||
171 | path_element++; | ||
172 | } | ||
173 | man_path_list = xrealloc_vector(man_path_list, 4, *count_mp); | ||
174 | man_path_list[*count_mp] = xstrdup(path); | ||
175 | (*count_mp)++; | ||
176 | /* man_path_list is NULL terminated */ | ||
177 | /* man_path_list[*count_mp] = NULL; - xrealloc_vector did it */ | ||
178 | skip: | ||
179 | if (!next_path) | ||
180 | break; | ||
181 | /* "path" may be a result of getenv(), be nice and don't mangle it */ | ||
182 | *next_path = ':'; | ||
183 | next: | ||
184 | path = next_path + 1; | ||
185 | } | ||
186 | return man_path_list; | ||
187 | } | ||
188 | |||
150 | int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 189 | int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
151 | int man_main(int argc UNUSED_PARAM, char **argv) | 190 | int man_main(int argc UNUSED_PARAM, char **argv) |
152 | { | 191 | { |
153 | parser_t *parser; | 192 | parser_t *parser; |
154 | const char *pager = ENABLE_LESS ? "less" : "more"; | 193 | const char *pager = ENABLE_LESS ? "less" : "more"; |
155 | char **man_path_list; | ||
156 | char *sec_list; | 194 | char *sec_list; |
157 | char *cur_path, *cur_sect; | 195 | char *cur_path, *cur_sect; |
158 | int count_mp, cur_mp; | 196 | char **man_path_list; |
197 | int count_mp; | ||
198 | int cur_mp; | ||
159 | int opt, not_found; | 199 | int opt, not_found; |
160 | char *token[2]; | 200 | char *token[2]; |
161 | 201 | ||
@@ -164,14 +204,20 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
164 | argv += optind; | 204 | argv += optind; |
165 | 205 | ||
166 | sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9"); | 206 | sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9"); |
167 | /* Last valid man_path_list[] is [0x10] */ | 207 | |
168 | count_mp = 0; | 208 | count_mp = 0; |
169 | man_path_list = xzalloc(0x11 * sizeof(man_path_list[0])); | 209 | man_path_list = add_MANPATH(NULL, &count_mp, |
170 | man_path_list[0] = getenv("MANPATH"); | 210 | getenv("MANDATORY_MANPATH"+10) /* "MANPATH" */ |
171 | if (!man_path_list[0]) /* default, may be overridden by /etc/man.conf */ | 211 | ); |
212 | if (!man_path_list) { | ||
213 | /* default, may be overridden by /etc/man.conf */ | ||
214 | man_path_list = xzalloc(2 * sizeof(man_path_list[0])); | ||
172 | man_path_list[0] = (char*)"/usr/man"; | 215 | man_path_list[0] = (char*)"/usr/man"; |
173 | else | 216 | /* count_mp stays 0. |
174 | count_mp++; | 217 | * Thus, man.conf will overwrite man_path_list[0] |
218 | * if a path is defined there. | ||
219 | */ | ||
220 | } | ||
175 | 221 | ||
176 | /* Parse man.conf[ig] or man_db.conf */ | 222 | /* Parse man.conf[ig] or man_db.conf */ |
177 | /* man version 1.6f uses man.config */ | 223 | /* man version 1.6f uses man.config */ |
@@ -193,39 +239,7 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
193 | if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */ | 239 | if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */ |
194 | || strcmp("MANDATORY_MANPATH", token[0]) == 0 | 240 | || strcmp("MANDATORY_MANPATH", token[0]) == 0 |
195 | ) { | 241 | ) { |
196 | char *path = token[1]; | 242 | man_path_list = add_MANPATH(man_path_list, &count_mp, token[1]); |
197 | while (*path) { | ||
198 | char *next_path; | ||
199 | char **path_element; | ||
200 | |||
201 | #if ENABLE_PLATFORM_MINGW32 | ||
202 | next_path = next_path_sep(path); | ||
203 | #else | ||
204 | next_path = strchr(path, ':'); | ||
205 | #endif | ||
206 | if (next_path) { | ||
207 | *next_path = '\0'; | ||
208 | if (next_path++ == path) /* "::"? */ | ||
209 | goto next; | ||
210 | } | ||
211 | /* Do we already have path? */ | ||
212 | path_element = man_path_list; | ||
213 | while (*path_element) { | ||
214 | if (strcmp(*path_element, path) == 0) | ||
215 | goto skip; | ||
216 | path_element++; | ||
217 | } | ||
218 | man_path_list = xrealloc_vector(man_path_list, 4, count_mp); | ||
219 | man_path_list[count_mp] = xstrdup(path); | ||
220 | count_mp++; | ||
221 | /* man_path_list is NULL terminated */ | ||
222 | /*man_path_list[count_mp] = NULL; - xrealloc_vector did it */ | ||
223 | skip: | ||
224 | if (!next_path) | ||
225 | break; | ||
226 | next: | ||
227 | path = next_path; | ||
228 | } | ||
229 | } | 243 | } |
230 | if (strcmp("MANSECT", token[0]) == 0) { | 244 | if (strcmp("MANSECT", token[0]) == 0) { |
231 | free(sec_list); | 245 | free(sec_list); |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index f08f0850d..f0904285b 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -238,6 +238,17 @@ static void add_probe(const char *name) | |||
238 | { | 238 | { |
239 | struct module_entry *m; | 239 | struct module_entry *m; |
240 | 240 | ||
241 | /* | ||
242 | * get_or_add_modentry() strips path from name and works | ||
243 | * on remaining basename. | ||
244 | * This would make "rmmod dir/name" and "modprobe dir/name" | ||
245 | * to work like "rmmod name" and "modprobe name", | ||
246 | * which is wrong, and can be abused via implicit modprobing: | ||
247 | * "ifconfig /usbserial up" tries to modprobe netdev-/usbserial. | ||
248 | */ | ||
249 | if (strchr(name, '/')) | ||
250 | bb_error_msg_and_die("malformed module name '%s'", name); | ||
251 | |||
241 | m = get_or_add_modentry(name); | 252 | m = get_or_add_modentry(name); |
242 | if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) | 253 | if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) |
243 | && (m->flags & MODULE_FLAG_LOADED) | 254 | && (m->flags & MODULE_FLAG_LOADED) |
diff --git a/networking/Config.src b/networking/Config.src index e56646917..15a696876 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -181,14 +181,6 @@ config FEATURE_HTTPD_RANGES | |||
181 | "Range: bytes=NNN-[MMM]" header. Allows for resuming interrupted | 181 | "Range: bytes=NNN-[MMM]" header. Allows for resuming interrupted |
182 | downloads, seeking in multimedia players etc. | 182 | downloads, seeking in multimedia players etc. |
183 | 183 | ||
184 | config FEATURE_HTTPD_USE_SENDFILE | ||
185 | bool "Use sendfile system call" | ||
186 | default y | ||
187 | depends on HTTPD | ||
188 | help | ||
189 | When enabled, httpd will use the kernel sendfile() function | ||
190 | instead of read/write loop. | ||
191 | |||
192 | config FEATURE_HTTPD_SETUID | 184 | config FEATURE_HTTPD_SETUID |
193 | bool "Enable -u <user> option" | 185 | bool "Enable -u <user> option" |
194 | default y | 186 | default y |
diff --git a/networking/httpd.c b/networking/httpd.c index 621d9cddc..9cf080401 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -133,7 +133,7 @@ | |||
133 | # include <security/pam_appl.h> | 133 | # include <security/pam_appl.h> |
134 | # include <security/pam_misc.h> | 134 | # include <security/pam_misc.h> |
135 | #endif | 135 | #endif |
136 | #if ENABLE_FEATURE_HTTPD_USE_SENDFILE | 136 | #if ENABLE_FEATURE_USE_SENDFILE |
137 | # include <sys/sendfile.h> | 137 | # include <sys/sendfile.h> |
138 | #endif | 138 | #endif |
139 | /* amount of buffering in a pipe */ | 139 | /* amount of buffering in a pipe */ |
@@ -1624,7 +1624,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what) | |||
1624 | #endif | 1624 | #endif |
1625 | if (what & SEND_HEADERS) | 1625 | if (what & SEND_HEADERS) |
1626 | send_headers(HTTP_OK); | 1626 | send_headers(HTTP_OK); |
1627 | #if ENABLE_FEATURE_HTTPD_USE_SENDFILE | 1627 | #if ENABLE_FEATURE_USE_SENDFILE |
1628 | { | 1628 | { |
1629 | off_t offset = range_start; | 1629 | off_t offset = range_start; |
1630 | while (1) { | 1630 | while (1) { |
@@ -1654,7 +1654,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what) | |||
1654 | break; | 1654 | break; |
1655 | } | 1655 | } |
1656 | if (count < 0) { | 1656 | if (count < 0) { |
1657 | IF_FEATURE_HTTPD_USE_SENDFILE(fin:) | 1657 | IF_FEATURE_USE_SENDFILE(fin:) |
1658 | if (verbose > 1) | 1658 | if (verbose > 1) |
1659 | bb_perror_msg("error"); | 1659 | bb_perror_msg("error"); |
1660 | } | 1660 | } |
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index ec4d8ba03..170c67b30 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c | |||
@@ -298,6 +298,19 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, | |||
298 | if (tb[RTA_PRIORITY]) { | 298 | if (tb[RTA_PRIORITY]) { |
299 | printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY])); | 299 | printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY])); |
300 | } | 300 | } |
301 | if (r->rtm_flags & RTNH_F_DEAD) { | ||
302 | printf("dead "); | ||
303 | } | ||
304 | if (r->rtm_flags & RTNH_F_ONLINK) { | ||
305 | printf("onlink "); | ||
306 | } | ||
307 | if (r->rtm_flags & RTNH_F_PERVASIVE) { | ||
308 | printf("pervasive "); | ||
309 | } | ||
310 | if (r->rtm_flags & RTM_F_NOTIFY) { | ||
311 | printf("notify "); | ||
312 | } | ||
313 | |||
301 | if (r->rtm_family == AF_INET6) { | 314 | if (r->rtm_family == AF_INET6) { |
302 | struct rta_cacheinfo *ci = NULL; | 315 | struct rta_cacheinfo *ci = NULL; |
303 | if (tb[RTA_CACHEINFO]) { | 316 | if (tb[RTA_CACHEINFO]) { |
@@ -330,7 +343,7 @@ static int iproute_modify(int cmd, unsigned flags, char **argv) | |||
330 | { | 343 | { |
331 | static const char keywords[] ALIGN1 = | 344 | static const char keywords[] ALIGN1 = |
332 | "src\0""via\0""mtu\0""lock\0""protocol\0"IF_FEATURE_IP_RULE("table\0") | 345 | "src\0""via\0""mtu\0""lock\0""protocol\0"IF_FEATURE_IP_RULE("table\0") |
333 | "dev\0""oif\0""to\0""metric\0"; | 346 | "dev\0""oif\0""to\0""metric\0""onlink\0"; |
334 | enum { | 347 | enum { |
335 | ARG_src, | 348 | ARG_src, |
336 | ARG_via, | 349 | ARG_via, |
@@ -341,6 +354,7 @@ IF_FEATURE_IP_RULE(ARG_table,) | |||
341 | ARG_oif, | 354 | ARG_oif, |
342 | ARG_to, | 355 | ARG_to, |
343 | ARG_metric, | 356 | ARG_metric, |
357 | ARG_onlink, | ||
344 | }; | 358 | }; |
345 | enum { | 359 | enum { |
346 | gw_ok = 1 << 0, | 360 | gw_ok = 1 << 0, |
@@ -431,6 +445,8 @@ IF_FEATURE_IP_RULE(ARG_table,) | |||
431 | NEXT_ARG(); | 445 | NEXT_ARG(); |
432 | metric = get_u32(*argv, "metric"); | 446 | metric = get_u32(*argv, "metric"); |
433 | addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric); | 447 | addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric); |
448 | } else if (arg == ARG_onlink) { | ||
449 | req.r.rtm_flags |= RTNH_F_ONLINK; | ||
434 | } else { | 450 | } else { |
435 | int type; | 451 | int type; |
436 | inet_prefix dst; | 452 | inet_prefix dst; |
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c index b43e52e96..fad2283c3 100644 --- a/networking/udhcp/arpping.c +++ b/networking/udhcp/arpping.c | |||
@@ -39,7 +39,8 @@ int FAST_FUNC arpping(uint32_t test_nip, | |||
39 | const uint8_t *safe_mac, | 39 | const uint8_t *safe_mac, |
40 | uint32_t from_ip, | 40 | uint32_t from_ip, |
41 | uint8_t *from_mac, | 41 | uint8_t *from_mac, |
42 | const char *interface) | 42 | const char *interface, |
43 | unsigned timeo) | ||
43 | { | 44 | { |
44 | int timeout_ms; | 45 | int timeout_ms; |
45 | struct pollfd pfd[1]; | 46 | struct pollfd pfd[1]; |
@@ -48,6 +49,9 @@ int FAST_FUNC arpping(uint32_t test_nip, | |||
48 | struct sockaddr addr; /* for interface name */ | 49 | struct sockaddr addr; /* for interface name */ |
49 | struct arpMsg arp; | 50 | struct arpMsg arp; |
50 | 51 | ||
52 | if (!timeo) | ||
53 | return 1; | ||
54 | |||
51 | s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); | 55 | s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); |
52 | if (s == -1) { | 56 | if (s == -1) { |
53 | bb_perror_msg(bb_msg_can_not_create_raw_socket); | 57 | bb_perror_msg(bb_msg_can_not_create_raw_socket); |
@@ -83,7 +87,7 @@ int FAST_FUNC arpping(uint32_t test_nip, | |||
83 | } | 87 | } |
84 | 88 | ||
85 | /* wait for arp reply, and check it */ | 89 | /* wait for arp reply, and check it */ |
86 | timeout_ms = 2000; | 90 | timeout_ms = (int)timeo; |
87 | do { | 91 | do { |
88 | typedef uint32_t aliased_uint32_t FIX_ALIASING; | 92 | typedef uint32_t aliased_uint32_t FIX_ALIASING; |
89 | int r; | 93 | int r; |
@@ -124,7 +128,7 @@ int FAST_FUNC arpping(uint32_t test_nip, | |||
124 | * this is more under/overflow-resistant | 128 | * this is more under/overflow-resistant |
125 | * (people did see overflows here when system time jumps): | 129 | * (people did see overflows here when system time jumps): |
126 | */ | 130 | */ |
127 | } while ((unsigned)timeout_ms <= 2000); | 131 | } while ((unsigned)timeout_ms <= timeo); |
128 | 132 | ||
129 | ret: | 133 | ret: |
130 | close(s); | 134 | close(s); |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index e5e0f2599..d20659e2f 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -311,7 +311,8 @@ int arpping(uint32_t test_nip, | |||
311 | const uint8_t *safe_mac, | 311 | const uint8_t *safe_mac, |
312 | uint32_t from_ip, | 312 | uint32_t from_ip, |
313 | uint8_t *from_mac, | 313 | uint8_t *from_mac, |
314 | const char *interface) FAST_FUNC; | 314 | const char *interface, |
315 | unsigned timeo) FAST_FUNC; | ||
315 | 316 | ||
316 | /* note: ip is a pointer to an IPv6 in network order, possibly misaliged */ | 317 | /* note: ip is a pointer to an IPv6 in network order, possibly misaliged */ |
317 | int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) FAST_FUNC; | 318 | int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) FAST_FUNC; |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index e468b7bbb..35e7c2070 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -54,7 +54,7 @@ static const char udhcpc_longopts[] ALIGN1 = | |||
54 | "foreground\0" No_argument "f" | 54 | "foreground\0" No_argument "f" |
55 | "background\0" No_argument "b" | 55 | "background\0" No_argument "b" |
56 | "broadcast\0" No_argument "B" | 56 | "broadcast\0" No_argument "B" |
57 | IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") | 57 | IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a") |
58 | IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") | 58 | IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") |
59 | ; | 59 | ; |
60 | #endif | 60 | #endif |
@@ -1150,7 +1150,7 @@ static void client_background(void) | |||
1150 | //usage:# define IF_UDHCP_VERBOSE(...) | 1150 | //usage:# define IF_UDHCP_VERBOSE(...) |
1151 | //usage:#endif | 1151 | //usage:#endif |
1152 | //usage:#define udhcpc_trivial_usage | 1152 | //usage:#define udhcpc_trivial_usage |
1153 | //usage: "[-fbq"IF_UDHCP_VERBOSE("v")IF_FEATURE_UDHCPC_ARPING("a")"RB] [-t N] [-T SEC] [-A SEC/-n]\n" | 1153 | //usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC/-n]\n" |
1154 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" | 1154 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" |
1155 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." | 1155 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." |
1156 | //usage:#define udhcpc_full_usage "\n" | 1156 | //usage:#define udhcpc_full_usage "\n" |
@@ -1174,7 +1174,7 @@ static void client_background(void) | |||
1174 | //usage: ) | 1174 | //usage: ) |
1175 | //usage: "\n -S,--syslog Log to syslog too" | 1175 | //usage: "\n -S,--syslog Log to syslog too" |
1176 | //usage: IF_FEATURE_UDHCPC_ARPING( | 1176 | //usage: IF_FEATURE_UDHCPC_ARPING( |
1177 | //usage: "\n -a,--arping Use arping to validate offered address" | 1177 | //usage: "\n -a[MSEC],--arping[=MSEC] Validate offered address with ARP ping" |
1178 | //usage: ) | 1178 | //usage: ) |
1179 | //usage: "\n -r,--request IP Request this IP address" | 1179 | //usage: "\n -r,--request IP Request this IP address" |
1180 | //usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" | 1180 | //usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" |
@@ -1211,7 +1211,7 @@ static void client_background(void) | |||
1211 | //usage: ) | 1211 | //usage: ) |
1212 | //usage: "\n -S Log to syslog too" | 1212 | //usage: "\n -S Log to syslog too" |
1213 | //usage: IF_FEATURE_UDHCPC_ARPING( | 1213 | //usage: IF_FEATURE_UDHCPC_ARPING( |
1214 | //usage: "\n -a Use arping to validate offered address" | 1214 | //usage: "\n -a[MSEC] Validate offered address with ARP ping" |
1215 | //usage: ) | 1215 | //usage: ) |
1216 | //usage: "\n -r IP Request this IP address" | 1216 | //usage: "\n -r IP Request this IP address" |
1217 | //usage: "\n -o Don't request any options (unless -O is given)" | 1217 | //usage: "\n -o Don't request any options (unless -O is given)" |
@@ -1238,6 +1238,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1238 | { | 1238 | { |
1239 | uint8_t *message; | 1239 | uint8_t *message; |
1240 | const char *str_V, *str_h, *str_F, *str_r; | 1240 | const char *str_V, *str_h, *str_F, *str_r; |
1241 | IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";) | ||
1241 | IF_FEATURE_UDHCP_PORT(char *str_P;) | 1242 | IF_FEATURE_UDHCP_PORT(char *str_P;) |
1242 | void *clientid_mac_ptr; | 1243 | void *clientid_mac_ptr; |
1243 | llist_t *list_O = NULL; | 1244 | llist_t *list_O = NULL; |
@@ -1252,6 +1253,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1252 | int timeout; /* must be signed */ | 1253 | int timeout; /* must be signed */ |
1253 | unsigned already_waited_sec; | 1254 | unsigned already_waited_sec; |
1254 | unsigned opt; | 1255 | unsigned opt; |
1256 | IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;) | ||
1255 | int max_fd; | 1257 | int max_fd; |
1256 | int retval; | 1258 | int retval; |
1257 | fd_set rfds; | 1259 | fd_set rfds; |
@@ -1269,7 +1271,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1269 | IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) | 1271 | IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) |
1270 | opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB" | 1272 | opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB" |
1271 | USE_FOR_MMU("b") | 1273 | USE_FOR_MMU("b") |
1272 | IF_FEATURE_UDHCPC_ARPING("a") | 1274 | IF_FEATURE_UDHCPC_ARPING("a::") |
1273 | IF_FEATURE_UDHCP_PORT("P:") | 1275 | IF_FEATURE_UDHCP_PORT("P:") |
1274 | "v" | 1276 | "v" |
1275 | , &str_V, &str_h, &str_h, &str_F | 1277 | , &str_V, &str_h, &str_h, &str_F |
@@ -1278,6 +1280,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1278 | , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ | 1280 | , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ |
1279 | , &list_O | 1281 | , &list_O |
1280 | , &list_x | 1282 | , &list_x |
1283 | IF_FEATURE_UDHCPC_ARPING(, &str_a) | ||
1281 | IF_FEATURE_UDHCP_PORT(, &str_P) | 1284 | IF_FEATURE_UDHCP_PORT(, &str_P) |
1282 | IF_UDHCP_VERBOSE(, &dhcp_verbose) | 1285 | IF_UDHCP_VERBOSE(, &dhcp_verbose) |
1283 | ); | 1286 | ); |
@@ -1309,6 +1312,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1309 | SERVER_PORT = CLIENT_PORT - 1; | 1312 | SERVER_PORT = CLIENT_PORT - 1; |
1310 | } | 1313 | } |
1311 | #endif | 1314 | #endif |
1315 | IF_FEATURE_UDHCPC_ARPING(arpping_ms = xatou(str_a);) | ||
1312 | while (list_O) { | 1316 | while (list_O) { |
1313 | char *optstr = llist_pop(&list_O); | 1317 | char *optstr = llist_pop(&list_O); |
1314 | unsigned n = bb_strtou(optstr, NULL, 0); | 1318 | unsigned n = bb_strtou(optstr, NULL, 0); |
@@ -1726,7 +1730,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1726 | NULL, | 1730 | NULL, |
1727 | (uint32_t) 0, | 1731 | (uint32_t) 0, |
1728 | client_config.client_mac, | 1732 | client_config.client_mac, |
1729 | client_config.interface) | 1733 | client_config.interface, |
1734 | arpping_ms) | ||
1730 | ) { | 1735 | ) { |
1731 | bb_info_msg("Offered address is in use " | 1736 | bb_info_msg("Offered address is in use " |
1732 | "(got ARP reply), declining"); | 1737 | "(got ARP reply), declining"); |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index a1a7f6b57..4b3ed240c 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -28,6 +28,7 @@ | |||
28 | //usage: "\n -f Run in foreground" | 28 | //usage: "\n -f Run in foreground" |
29 | //usage: "\n -S Log to syslog too" | 29 | //usage: "\n -S Log to syslog too" |
30 | //usage: "\n -I ADDR Local address" | 30 | //usage: "\n -I ADDR Local address" |
31 | //usage: "\n -a MSEC Timeout for ARP ping (default 2000)" | ||
31 | //usage: IF_FEATURE_UDHCP_PORT( | 32 | //usage: IF_FEATURE_UDHCP_PORT( |
32 | //usage: "\n -P N Use port N (default 67)" | 33 | //usage: "\n -P N Use port N (default 67)" |
33 | //usage: ) | 34 | //usage: ) |
@@ -148,7 +149,8 @@ static uint32_t select_lease_time(struct dhcp_packet *packet) | |||
148 | static NOINLINE void send_offer(struct dhcp_packet *oldpacket, | 149 | static NOINLINE void send_offer(struct dhcp_packet *oldpacket, |
149 | uint32_t static_lease_nip, | 150 | uint32_t static_lease_nip, |
150 | struct dyn_lease *lease, | 151 | struct dyn_lease *lease, |
151 | uint8_t *requested_ip_opt) | 152 | uint8_t *requested_ip_opt, |
153 | unsigned arpping_ms) | ||
152 | { | 154 | { |
153 | struct dhcp_packet packet; | 155 | struct dhcp_packet packet; |
154 | uint32_t lease_time_sec; | 156 | uint32_t lease_time_sec; |
@@ -187,7 +189,7 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, | |||
187 | } | 189 | } |
188 | else { | 190 | else { |
189 | /* Otherwise, find a free IP */ | 191 | /* Otherwise, find a free IP */ |
190 | packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr); | 192 | packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr, arpping_ms); |
191 | } | 193 | } |
192 | 194 | ||
193 | if (!packet.yiaddr) { | 195 | if (!packet.yiaddr) { |
@@ -304,6 +306,8 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
304 | unsigned opt; | 306 | unsigned opt; |
305 | struct option_set *option; | 307 | struct option_set *option; |
306 | char *str_I = str_I; | 308 | char *str_I = str_I; |
309 | const char *str_a = "2000"; | ||
310 | unsigned arpping_ms; | ||
307 | IF_FEATURE_UDHCP_PORT(char *str_P;) | 311 | IF_FEATURE_UDHCP_PORT(char *str_P;) |
308 | 312 | ||
309 | #if ENABLE_FEATURE_UDHCP_PORT | 313 | #if ENABLE_FEATURE_UDHCP_PORT |
@@ -314,9 +318,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
314 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 | 318 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 |
315 | opt_complementary = "vv"; | 319 | opt_complementary = "vv"; |
316 | #endif | 320 | #endif |
317 | opt = getopt32(argv, "fSI:v" | 321 | opt = getopt32(argv, "fSI:va:" |
318 | IF_FEATURE_UDHCP_PORT("P:") | 322 | IF_FEATURE_UDHCP_PORT("P:") |
319 | , &str_I | 323 | , &str_I |
324 | , &str_a | ||
320 | IF_FEATURE_UDHCP_PORT(, &str_P) | 325 | IF_FEATURE_UDHCP_PORT(, &str_P) |
321 | IF_UDHCP_VERBOSE(, &dhcp_verbose) | 326 | IF_UDHCP_VERBOSE(, &dhcp_verbose) |
322 | ); | 327 | ); |
@@ -336,11 +341,13 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
336 | free(lsa); | 341 | free(lsa); |
337 | } | 342 | } |
338 | #if ENABLE_FEATURE_UDHCP_PORT | 343 | #if ENABLE_FEATURE_UDHCP_PORT |
339 | if (opt & 16) { /* -P */ | 344 | if (opt & 32) { /* -P */ |
340 | SERVER_PORT = xatou16(str_P); | 345 | SERVER_PORT = xatou16(str_P); |
341 | CLIENT_PORT = SERVER_PORT + 1; | 346 | CLIENT_PORT = SERVER_PORT + 1; |
342 | } | 347 | } |
343 | #endif | 348 | #endif |
349 | arpping_ms = xatou(str_a); | ||
350 | |||
344 | /* Would rather not do read_config before daemonization - | 351 | /* Would rather not do read_config before daemonization - |
345 | * otherwise NOMMU machines will parse config twice */ | 352 | * otherwise NOMMU machines will parse config twice */ |
346 | read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); | 353 | read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); |
@@ -498,7 +505,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
498 | case DHCPDISCOVER: | 505 | case DHCPDISCOVER: |
499 | log1("Received DISCOVER"); | 506 | log1("Received DISCOVER"); |
500 | 507 | ||
501 | send_offer(&packet, static_lease_nip, lease, requested_ip_opt); | 508 | send_offer(&packet, static_lease_nip, lease, requested_ip_opt, arpping_ms); |
502 | break; | 509 | break; |
503 | 510 | ||
504 | case DHCPREQUEST: | 511 | case DHCPREQUEST: |
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h index a77724f20..183e7e24c 100644 --- a/networking/udhcp/dhcpd.h +++ b/networking/udhcp/dhcpd.h | |||
@@ -100,7 +100,7 @@ struct dyn_lease *add_lease( | |||
100 | int is_expired_lease(struct dyn_lease *lease) FAST_FUNC; | 100 | int is_expired_lease(struct dyn_lease *lease) FAST_FUNC; |
101 | struct dyn_lease *find_lease_by_mac(const uint8_t *mac) FAST_FUNC; | 101 | struct dyn_lease *find_lease_by_mac(const uint8_t *mac) FAST_FUNC; |
102 | struct dyn_lease *find_lease_by_nip(uint32_t nip) FAST_FUNC; | 102 | struct dyn_lease *find_lease_by_nip(uint32_t nip) FAST_FUNC; |
103 | uint32_t find_free_or_expired_nip(const uint8_t *safe_mac) FAST_FUNC; | 103 | uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) FAST_FUNC; |
104 | 104 | ||
105 | 105 | ||
106 | /* Config file parser will pass static lease info to this function | 106 | /* Config file parser will pass static lease info to this function |
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c index 6840f3c25..1c8808c0f 100644 --- a/networking/udhcp/files.c +++ b/networking/udhcp/files.c | |||
@@ -189,12 +189,24 @@ void FAST_FUNC read_leases(const char *file) | |||
189 | goto ret; | 189 | goto ret; |
190 | 190 | ||
191 | while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) { | 191 | while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) { |
192 | //FIXME: what if it matches some static lease? | ||
193 | uint32_t y = ntohl(lease.lease_nip); | 192 | uint32_t y = ntohl(lease.lease_nip); |
194 | if (y >= server_config.start_ip && y <= server_config.end_ip) { | 193 | if (y >= server_config.start_ip && y <= server_config.end_ip) { |
195 | signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed; | 194 | signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed; |
195 | uint32_t static_nip; | ||
196 | |||
196 | if (expires <= 0) | 197 | if (expires <= 0) |
197 | continue; | 198 | continue; |
199 | |||
200 | /* Check if there is a different static lease for this IP or MAC */ | ||
201 | static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac); | ||
202 | if (static_nip) { | ||
203 | /* NB: we do not add lease even if static_nip == lease.lease_nip. | ||
204 | */ | ||
205 | continue; | ||
206 | } | ||
207 | if (is_nip_reserved(server_config.static_leases, lease.lease_nip)) | ||
208 | continue; | ||
209 | |||
198 | /* NB: add_lease takes "relative time", IOW, | 210 | /* NB: add_lease takes "relative time", IOW, |
199 | * lease duration, not lease deadline. */ | 211 | * lease duration, not lease deadline. */ |
200 | if (add_lease(lease.lease_mac, lease.lease_nip, | 212 | if (add_lease(lease.lease_mac, lease.lease_nip, |
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c index c5b60b108..745340ad3 100644 --- a/networking/udhcp/leases.c +++ b/networking/udhcp/leases.c | |||
@@ -112,7 +112,7 @@ struct dyn_lease* FAST_FUNC find_lease_by_nip(uint32_t nip) | |||
112 | } | 112 | } |
113 | 113 | ||
114 | /* Check if the IP is taken; if it is, add it to the lease table */ | 114 | /* Check if the IP is taken; if it is, add it to the lease table */ |
115 | static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac) | 115 | static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms) |
116 | { | 116 | { |
117 | struct in_addr temp; | 117 | struct in_addr temp; |
118 | int r; | 118 | int r; |
@@ -120,7 +120,8 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac) | |||
120 | r = arpping(nip, safe_mac, | 120 | r = arpping(nip, safe_mac, |
121 | server_config.server_nip, | 121 | server_config.server_nip, |
122 | server_config.server_mac, | 122 | server_config.server_mac, |
123 | server_config.interface); | 123 | server_config.interface, |
124 | arpping_ms); | ||
124 | if (r) | 125 | if (r) |
125 | return r; | 126 | return r; |
126 | 127 | ||
@@ -132,7 +133,7 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac) | |||
132 | } | 133 | } |
133 | 134 | ||
134 | /* Find a new usable (we think) address */ | 135 | /* Find a new usable (we think) address */ |
135 | uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac) | 136 | uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) |
136 | { | 137 | { |
137 | uint32_t addr; | 138 | uint32_t addr; |
138 | struct dyn_lease *oldest_lease = NULL; | 139 | struct dyn_lease *oldest_lease = NULL; |
@@ -177,7 +178,7 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac) | |||
177 | lease = find_lease_by_nip(nip); | 178 | lease = find_lease_by_nip(nip); |
178 | if (!lease) { | 179 | if (!lease) { |
179 | //TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping! | 180 | //TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping! |
180 | if (nobody_responds_to_arp(nip, safe_mac)) | 181 | if (nobody_responds_to_arp(nip, safe_mac, arpping_ms)) |
181 | return nip; | 182 | return nip; |
182 | } else { | 183 | } else { |
183 | if (!oldest_lease || lease->expires < oldest_lease->expires) | 184 | if (!oldest_lease || lease->expires < oldest_lease->expires) |
@@ -194,7 +195,7 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac) | |||
194 | 195 | ||
195 | if (oldest_lease | 196 | if (oldest_lease |
196 | && is_expired_lease(oldest_lease) | 197 | && is_expired_lease(oldest_lease) |
197 | && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac) | 198 | && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms) |
198 | ) { | 199 | ) { |
199 | return oldest_lease->lease_nip; | 200 | return oldest_lease->lease_nip; |
200 | } | 201 | } |
diff --git a/networking/zcip.c b/networking/zcip.c index 45d1f7c1c..a3307c5c9 100644 --- a/networking/zcip.c +++ b/networking/zcip.c | |||
@@ -30,8 +30,12 @@ | |||
30 | //usage: "\n -f Run in foreground" | 30 | //usage: "\n -f Run in foreground" |
31 | //usage: "\n -q Quit after obtaining address" | 31 | //usage: "\n -q Quit after obtaining address" |
32 | //usage: "\n -r 169.254.x.x Request this address first" | 32 | //usage: "\n -r 169.254.x.x Request this address first" |
33 | //usage: "\n -l x.x.0.0 Use this range instead of 169.254" | ||
33 | //usage: "\n -v Verbose" | 34 | //usage: "\n -v Verbose" |
34 | //usage: "\n" | 35 | //usage: "\n" |
36 | //usage: "\n$LOGGING=none Suppress logging" | ||
37 | //usage: "\n$LOGGING=syslog Log to syslog" | ||
38 | //usage: "\n" | ||
35 | //usage: "\nWith no -q, runs continuously monitoring for ARP conflicts," | 39 | //usage: "\nWith no -q, runs continuously monitoring for ARP conflicts," |
36 | //usage: "\nexits only on I/O errors (link down etc)" | 40 | //usage: "\nexits only on I/O errors (link down etc)" |
37 | 41 | ||
@@ -87,6 +91,7 @@ enum { | |||
87 | struct globals { | 91 | struct globals { |
88 | struct sockaddr saddr; | 92 | struct sockaddr saddr; |
89 | struct ether_addr eth_addr; | 93 | struct ether_addr eth_addr; |
94 | uint32_t localnet_ip; | ||
90 | } FIX_ALIASING; | 95 | } FIX_ALIASING; |
91 | #define G (*(struct globals*)&bb_common_bufsiz1) | 96 | #define G (*(struct globals*)&bb_common_bufsiz1) |
92 | #define saddr (G.saddr ) | 97 | #define saddr (G.saddr ) |
@@ -98,14 +103,14 @@ struct globals { | |||
98 | * Pick a random link local IP address on 169.254/16, except that | 103 | * Pick a random link local IP address on 169.254/16, except that |
99 | * the first and last 256 addresses are reserved. | 104 | * the first and last 256 addresses are reserved. |
100 | */ | 105 | */ |
101 | static uint32_t pick(void) | 106 | static uint32_t pick_nip(void) |
102 | { | 107 | { |
103 | unsigned tmp; | 108 | unsigned tmp; |
104 | 109 | ||
105 | do { | 110 | do { |
106 | tmp = rand() & IN_CLASSB_HOST; | 111 | tmp = rand() & IN_CLASSB_HOST; |
107 | } while (tmp > (IN_CLASSB_HOST - 0x0200)); | 112 | } while (tmp > (IN_CLASSB_HOST - 0x0200)); |
108 | return htonl((LINKLOCAL_ADDR + 0x0100) + tmp); | 113 | return htonl((G.localnet_ip + 0x0100) + tmp); |
109 | } | 114 | } |
110 | 115 | ||
111 | /** | 116 | /** |
@@ -197,6 +202,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
197 | { | 202 | { |
198 | int state; | 203 | int state; |
199 | char *r_opt; | 204 | char *r_opt; |
205 | const char *l_opt = "169.254.0.0"; | ||
200 | unsigned opts; | 206 | unsigned opts; |
201 | 207 | ||
202 | // ugly trick, but I want these zeroed in one go | 208 | // ugly trick, but I want these zeroed in one go |
@@ -231,7 +237,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
231 | // parse commandline: prog [options] ifname script | 237 | // parse commandline: prog [options] ifname script |
232 | // exactly 2 args; -v accumulates and implies -f | 238 | // exactly 2 args; -v accumulates and implies -f |
233 | opt_complementary = "=2:vv:vf"; | 239 | opt_complementary = "=2:vv:vf"; |
234 | opts = getopt32(argv, "fqr:v", &r_opt, &verbose); | 240 | opts = getopt32(argv, "fqr:l:v", &r_opt, &l_opt, &verbose); |
235 | #if !BB_MMU | 241 | #if !BB_MMU |
236 | // on NOMMU reexec early (or else we will rerun things twice) | 242 | // on NOMMU reexec early (or else we will rerun things twice) |
237 | if (!FOREGROUND) | 243 | if (!FOREGROUND) |
@@ -246,9 +252,20 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
246 | openlog(applet_name, 0, LOG_DAEMON); | 252 | openlog(applet_name, 0, LOG_DAEMON); |
247 | logmode |= LOGMODE_SYSLOG; | 253 | logmode |= LOGMODE_SYSLOG; |
248 | } | 254 | } |
255 | bb_logenv_override(); | ||
256 | |||
257 | { // -l n.n.n.n | ||
258 | struct in_addr net; | ||
259 | if (inet_aton(l_opt, &net) == 0 | ||
260 | || (net.s_addr & htonl(IN_CLASSB_NET)) != net.s_addr | ||
261 | ) { | ||
262 | bb_error_msg_and_die("invalid network address"); | ||
263 | } | ||
264 | G.localnet_ip = ntohl(net.s_addr); | ||
265 | } | ||
249 | if (opts & 4) { // -r n.n.n.n | 266 | if (opts & 4) { // -r n.n.n.n |
250 | if (inet_aton(r_opt, &ip) == 0 | 267 | if (inet_aton(r_opt, &ip) == 0 |
251 | || (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR | 268 | || (ntohl(ip.s_addr) & IN_CLASSB_NET) != G.localnet_ip |
252 | ) { | 269 | ) { |
253 | bb_error_msg_and_die("invalid link address"); | 270 | bb_error_msg_and_die("invalid link address"); |
254 | } | 271 | } |
@@ -295,7 +312,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
295 | srand(t); | 312 | srand(t); |
296 | } | 313 | } |
297 | if (ip.s_addr == 0) | 314 | if (ip.s_addr == 0) |
298 | ip.s_addr = pick(); | 315 | ip.s_addr = pick_nip(); |
299 | 316 | ||
300 | // FIXME cases to handle: | 317 | // FIXME cases to handle: |
301 | // - zcip already running! | 318 | // - zcip already running! |
@@ -433,7 +450,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
433 | default: | 450 | default: |
434 | // Invalid, should never happen. Restart the whole protocol. | 451 | // Invalid, should never happen. Restart the whole protocol. |
435 | state = PROBE; | 452 | state = PROBE; |
436 | ip.s_addr = pick(); | 453 | ip.s_addr = pick_nip(); |
437 | timeout_ms = 0; | 454 | timeout_ms = 0; |
438 | nprobes = 0; | 455 | nprobes = 0; |
439 | nclaims = 0; | 456 | nclaims = 0; |
@@ -535,7 +552,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
535 | } | 552 | } |
536 | 553 | ||
537 | // restart the whole protocol | 554 | // restart the whole protocol |
538 | ip.s_addr = pick(); | 555 | ip.s_addr = pick_nip(); |
539 | timeout_ms = 0; | 556 | timeout_ms = 0; |
540 | nprobes = 0; | 557 | nprobes = 0; |
541 | nclaims = 0; | 558 | nclaims = 0; |
@@ -561,7 +578,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
561 | run(argv, "deconfig", &ip); | 578 | run(argv, "deconfig", &ip); |
562 | 579 | ||
563 | // restart the whole protocol | 580 | // restart the whole protocol |
564 | ip.s_addr = pick(); | 581 | ip.s_addr = pick_nip(); |
565 | timeout_ms = 0; | 582 | timeout_ms = 0; |
566 | nprobes = 0; | 583 | nprobes = 0; |
567 | nclaims = 0; | 584 | nclaims = 0; |
@@ -571,7 +588,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) | |||
571 | // Invalid, should never happen. Restart the whole protocol. | 588 | // Invalid, should never happen. Restart the whole protocol. |
572 | VDBG("invalid state -- starting over\n"); | 589 | VDBG("invalid state -- starting over\n"); |
573 | state = PROBE; | 590 | state = PROBE; |
574 | ip.s_addr = pick(); | 591 | ip.s_addr = pick_nip(); |
575 | timeout_ms = 0; | 592 | timeout_ms = 0; |
576 | nprobes = 0; | 593 | nprobes = 0; |
577 | nclaims = 0; | 594 | nclaims = 0; |
diff --git a/shell/ash.c b/shell/ash.c index 3f3e2f4bc..b95356034 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -6740,7 +6740,15 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6740 | len = number(loc); | 6740 | len = number(loc); |
6741 | } | 6741 | } |
6742 | } | 6742 | } |
6743 | if (pos >= orig_len) { | 6743 | if (pos < 0) { |
6744 | /* ${VAR:$((-n)):l} starts n chars from the end */ | ||
6745 | pos = orig_len + pos; | ||
6746 | } | ||
6747 | if ((unsigned)pos >= orig_len) { | ||
6748 | /* apart from obvious ${VAR:999999:l}, | ||
6749 | * covers ${VAR:$((-9999999)):l} - result is "" | ||
6750 | * (bash-compat) | ||
6751 | */ | ||
6744 | pos = 0; | 6752 | pos = 0; |
6745 | len = 0; | 6753 | len = 0; |
6746 | } | 6754 | } |
diff --git a/shell/math.c b/shell/math.c index 3da151137..006221b6a 100644 --- a/shell/math.c +++ b/shell/math.c | |||
@@ -415,10 +415,29 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |||
415 | } | 415 | } |
416 | else if (right_side_val == 0) | 416 | else if (right_side_val == 0) |
417 | return "divide by zero"; | 417 | return "divide by zero"; |
418 | else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) | 418 | else if (op == TOK_DIV || op == TOK_DIV_ASSIGN |
419 | rez /= right_side_val; | 419 | || op == TOK_REM || op == TOK_REM_ASSIGN) { |
420 | else if (op == TOK_REM || op == TOK_REM_ASSIGN) | 420 | /* |
421 | rez %= right_side_val; | 421 | * bash 4.2.45 x86 64bit: SEGV on 'echo $((2**63 / -1))' |
422 | * | ||
423 | * MAX_NEGATIVE_INT / -1 = MAX_POSITIVE_INT+1 | ||
424 | * and thus is not representable. | ||
425 | * Some CPUs segfault trying such op. | ||
426 | * Others overflow MAX_POSITIVE_INT+1 to | ||
427 | * MAX_NEGATIVE_INT (0x7fff+1 = 0x8000). | ||
428 | * Make sure to at least not SEGV here: | ||
429 | */ | ||
430 | if (right_side_val == -1 | ||
431 | && rez << 1 == 0 /* MAX_NEGATIVE_INT or 0 */ | ||
432 | ) { | ||
433 | right_side_val = 1; | ||
434 | } | ||
435 | if (op == TOK_DIV || op == TOK_DIV_ASSIGN) | ||
436 | rez /= right_side_val; | ||
437 | else { | ||
438 | rez %= right_side_val; | ||
439 | } | ||
440 | } | ||
422 | } | 441 | } |
423 | 442 | ||
424 | if (is_assign_op(op)) { | 443 | if (is_assign_op(op)) { |