From 4e314faa0aecb66717418e9a47a4451aec59262b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 20 Nov 2014 18:24:33 +0100 Subject: [PATCH 01/24] modprobe,rmmod: reject module names with slashes function old new delta add_probe 86 113 +27 Signed-off-by: Denys Vlasenko --- modutils/modprobe.c | 11 +++++++++++ 1 file changed, 11 insertions(+) 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) { struct module_entry *m; + /* + * get_or_add_modentry() strips path from name and works + * on remaining basename. + * This would make "rmmod dir/name" and "modprobe dir/name" + * to work like "rmmod name" and "modprobe name", + * which is wrong, and can be abused via implicit modprobing: + * "ifconfig /usbserial up" tries to modprobe netdev-/usbserial. + */ + if (strchr(name, '/')) + bb_error_msg_and_die("malformed module name '%s'", name); + m = get_or_add_modentry(name); if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) && (m->flags & MODULE_FLAG_LOADED) From 2bba9ad67a917de2624d427c8c107ce3e2d3d085 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Nov 2014 20:10:57 +0100 Subject: [PATCH 02/24] init: do not run shutdown/reexec actions from signal handler this is racy wrt various libc functions such as syslog() function old new delta check_delayed_sigs 182 352 +170 init_main 772 728 -44 restart_handler 74 - -74 halt_reboot_pwoff 79 - -79 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 1/1 up/down: 170/-197) Total: -27 bytes Signed-off-by: Denys Vlasenko --- init/init.c | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) 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) /* Handler for QUIT - exec "restart" action, * else (no such action defined) do nothing */ -static void restart_handler(int sig UNUSED_PARAM) +static void exec_restart_action(void) { struct init_action *a; @@ -975,6 +975,20 @@ static int check_delayed_sigs(void) #endif if (sig == SIGINT) run_actions(CTRLALTDEL); + if (sig == SIGQUIT) { + exec_restart_action(); + /* returns only if no restart action defined */ + } + if ((1 << sig) & (0 +#ifdef SIGPWR + + (1 << SIGPWR) +#endif + + (1 << SIGUSR1) + + (1 << SIGUSR2) + + (1 << SIGTERM) + )) { + halt_reboot_pwoff(sig); + } } } @@ -1070,7 +1084,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) #if 0 /* It's 2013, does anyone really still depend on this? */ -/* If you do, consider adding swapon to sysinot actions then! */ +/* If you do, consider adding swapon to sysinit actions then! */ /* struct sysinfo is linux-specific */ # ifdef __linux__ /* Make sure there is enough memory to do something useful. */ @@ -1134,16 +1148,6 @@ int init_main(int argc UNUSED_PARAM, char **argv) if (!DEBUG_INIT) { struct sigaction sa; - bb_signals(0 -#ifdef SIGPWR - + (1 << SIGPWR) /* halt */ -#endif - + (1 << SIGUSR1) /* halt */ - + (1 << SIGTERM) /* reboot */ - + (1 << SIGUSR2) /* poweroff */ - , halt_reboot_pwoff); - signal(SIGQUIT, restart_handler); /* re-exec another init */ - /* Stop handler must allow only SIGCONT inside itself */ memset(&sa, 0, sizeof(sa)); sigfillset(&sa.sa_mask); @@ -1158,18 +1162,24 @@ int init_main(int argc UNUSED_PARAM, char **argv) */ sigaction_set(SIGSTOP, &sa); /* pause */ - /* SIGINT (Ctrl-Alt-Del) must interrupt wait(), + /* These signals must interrupt wait(), * setting handler without SA_RESTART flag. */ - bb_signals_recursive_norestart((1 << SIGINT), record_signo); + bb_signals_recursive_norestart(0 + + (1 << SIGINT) /* Ctrl-Alt-Del */ + + (1 << SIGQUIT) /* re-exec another init */ +#ifdef SIGPWR + + (1 << SIGPWR) /* halt */ +#endif + + (1 << SIGUSR1) /* halt */ + + (1 << SIGTERM) /* reboot */ + + (1 << SIGUSR2) /* poweroff */ +#if ENABLE_FEATURE_USE_INITTAB + + (1 << SIGHUP) /* reread /etc/inittab */ +#endif + , record_signo); } - /* Set up "reread /etc/inittab" handler. - * Handler is set up without SA_RESTART, it will interrupt syscalls. - */ - if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB) - bb_signals_recursive_norestart((1 << SIGHUP), record_signo); - /* Now run everything that needs to be run */ /* First run the sysinit command */ run_actions(SYSINIT); From 298fabaefcdb79037d0dd33ba331369586690202 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Nov 2014 18:49:14 +0100 Subject: [PATCH 03/24] udhcpd: if a lease from lease file coincides with a static one, ignore it function old new delta read_leases 269 328 +59 Signed-off-by: Denys Vlasenko --- networking/udhcp/files.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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) goto ret; while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) { -//FIXME: what if it matches some static lease? uint32_t y = ntohl(lease.lease_nip); if (y >= server_config.start_ip && y <= server_config.end_ip) { signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed; + uint32_t static_nip; + if (expires <= 0) continue; + + /* Check if there is a different static lease for this IP or MAC */ + static_nip = get_static_nip_by_mac(server_config.static_leases, lease.lease_mac); + if (static_nip) { + /* NB: we do not add lease even if static_nip == lease.lease_nip. + */ + continue; + } + if (is_nip_reserved(server_config.static_leases, lease.lease_nip)) + continue; + /* NB: add_lease takes "relative time", IOW, * lease duration, not lease deadline. */ if (add_lease(lease.lease_mac, lease.lease_nip, From eff58f15b05733eb10b8a579fd495cf4ca3b1493 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 26 Nov 2014 13:28:54 +0100 Subject: [PATCH 04/24] gitignore: add testsuite/echo-ne Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8d6d17601..73e88fb5b 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ core # /busybox.links /runtest-tempdir-links +/testsuite/echo-ne From 2835a224cd603489ac08625265d383d4690cb58a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Nov 2014 14:04:51 +0100 Subject: [PATCH 05/24] bbunit: fix WANT_TIMING compilation Signed-off-by: Denys Vlasenko --- libbb/bbunit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) #if WANT_TIMING gettimeofday(&end, NULL); timeval_diff(&time_spent, &end, &begin); - bb_error_msg("Elapsed time %u.%06u seconds" + bb_error_msg("Elapsed time %u.%06u seconds", (int)time_spent.tv_sec, (int)time_spent.tv_usec); #endif From 04c14176023c65550fd46c2e44a1aa04d426d69a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Nov 2014 15:17:59 +0100 Subject: [PATCH 06/24] libbb: use ARG_MAX for bb_arg_max() only if it's 60k+ Sometimes ARG_MAX is small (like 32k) yet sysconf(_SC_ARG_MAX) is big, and people prefer using the bigger value. OTOH, with sufficiently large ARG_MAX, further wins from sysconf(_SC_ARG_MAX) being bigger are exponentially smaller: you can see 4 times fewer fork+execs when you run find, but when each execed process already takes a thousand parameters it's likely execution time is dominated by what that process does with each parameter. Thus, with this change ARG_MAX is used if it's sufficiently big, otherwise sysconf(_SC_ARG_MAX) is used. Signed-off-by: Denys Vlasenko --- include/libbb.h | 7 +++++-- libbb/sysconf.c | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index cc2bea32d..17a0089d8 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -731,11 +731,14 @@ extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST /* Never returns NULL */ extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; -#if defined ARG_MAX +#if defined(ARG_MAX) && (ARG_MAX >= 60*1024 || !defined(_SC_ARG_MAX)) +/* Use _constant_ maximum if: defined && (big enough || no variable one exists) */ # define bb_arg_max() ((unsigned)ARG_MAX) -#elif defined _SC_ARG_MAX +#elif defined(_SC_ARG_MAX) +/* Else use variable one (a bit more expensive) */ unsigned bb_arg_max(void) FAST_FUNC; #else +/* If all else fails */ # define bb_arg_max() ((unsigned)(32 * 1024)) #endif unsigned bb_clk_tck(void) FAST_FUNC; 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 @@ */ #include "libbb.h" -#if !defined(ARG_MAX) && defined(_SC_ARG_MAX) +#if !defined(bb_arg_max) unsigned FAST_FUNC bb_arg_max(void) { return sysconf(_SC_ARG_MAX); From ee41094b809452fdd23d25c1879a96acfcddde08 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Nov 2014 00:40:08 +0100 Subject: [PATCH 07/24] man: accept a list of dirs in $MANPATH function old new delta add_MANPATH - 143 +143 man_main 852 731 -121 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 143/-121) Total: 22 bytes Signed-off-by: Denys Vlasenko --- miscutils/man.c | 86 ++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/miscutils/man.c b/miscutils/man.c index 5c1fa2c9d..ccb57a93f 100644 --- a/miscutils/man.c +++ b/miscutils/man.c @@ -147,15 +147,49 @@ static int show_manpage(const char *pager, char *man_filename, int man, int leve return run_pipe(pager, man_filename, man, level); } +static char **add_MANPATH(char **man_path_list, int *count_mp, char *path) +{ + if (path) while (*path) { + char *next_path; + char **path_element; + + next_path = strchr(path, ':'); + if (next_path) { + *next_path = '\0'; + if (next_path++ == path) /* "::"? */ + goto next; + } + /* Do we already have path? */ + path_element = man_path_list; + if (path_element) while (*path_element) { + if (strcmp(*path_element, path) == 0) + goto skip; + path_element++; + } + man_path_list = xrealloc_vector(man_path_list, 4, *count_mp); + man_path_list[*count_mp] = xstrdup(path); + (*count_mp)++; + /* man_path_list is NULL terminated */ + /* man_path_list[*count_mp] = NULL; - xrealloc_vector did it */ + skip: + if (!next_path) + break; + next: + path = next_path; + } + return man_path_list; +} + int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int man_main(int argc UNUSED_PARAM, char **argv) { parser_t *parser; const char *pager = ENABLE_LESS ? "less" : "more"; - char **man_path_list; char *sec_list; char *cur_path, *cur_sect; - int count_mp, cur_mp; + char **man_path_list; + int count_mp; + int cur_mp; int opt, not_found; char *token[2]; @@ -164,14 +198,20 @@ int man_main(int argc UNUSED_PARAM, char **argv) argv += optind; sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9"); - /* Last valid man_path_list[] is [0x10] */ + count_mp = 0; - man_path_list = xzalloc(0x11 * sizeof(man_path_list[0])); - man_path_list[0] = getenv("MANPATH"); - if (!man_path_list[0]) /* default, may be overridden by /etc/man.conf */ + man_path_list = add_MANPATH(NULL, &count_mp, + getenv("MANDATORY_MANPATH"+10) /* "MANPATH" */ + ); + if (!man_path_list) { + /* default, may be overridden by /etc/man.conf */ + man_path_list = xzalloc(2 * sizeof(man_path_list[0])); man_path_list[0] = (char*)"/usr/man"; - else - count_mp++; + /* count_mp stays 0. + * Thus, man.conf will overwrite man_path_list[0] + * if a path is defined there. + */ + } /* Parse man.conf[ig] or man_db.conf */ /* man version 1.6f uses man.config */ @@ -193,35 +233,7 @@ int man_main(int argc UNUSED_PARAM, char **argv) if (strcmp("MANDATORY_MANPATH"+10, token[0]) == 0 /* "MANPATH"? */ || strcmp("MANDATORY_MANPATH", token[0]) == 0 ) { - char *path = token[1]; - while (*path) { - char *next_path; - char **path_element; - - next_path = strchr(path, ':'); - if (next_path) { - *next_path = '\0'; - if (next_path++ == path) /* "::"? */ - goto next; - } - /* Do we already have path? */ - path_element = man_path_list; - while (*path_element) { - if (strcmp(*path_element, path) == 0) - goto skip; - path_element++; - } - man_path_list = xrealloc_vector(man_path_list, 4, count_mp); - man_path_list[count_mp] = xstrdup(path); - count_mp++; - /* man_path_list is NULL terminated */ - /*man_path_list[count_mp] = NULL; - xrealloc_vector did it */ - skip: - if (!next_path) - break; - next: - path = next_path; - } + man_path_list = add_MANPATH(man_path_list, &count_mp, token[1]); } if (strcmp("MANSECT", token[0]) == 0) { free(sec_list); From 8d75d794ea505003fddea8e757d43976db8d6861 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 27 Nov 2014 13:20:24 +0100 Subject: [PATCH 08/24] libbb: use sendfile() to copy data between file descriptors Busybox already uses sendfile in httpd. This patch proposes to use it globally to copy data between file descriptors. It speeds up the copying on slow systems a lot - below are the times needed to copy a 450Mb file with and without this option enabled on a BeagleBone Black: sendfile: user 0m0.000s sys 0m8.170s read/write 4k: user 0m0.470s sys 0m16.300s function old new delta bb_full_fd_action 394 474 +80 Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- Config.in | 12 ++++++ libbb/copyfd.c | 87 ++++++++++++++++++++++++++++--------------- networking/Config.src | 8 ---- networking/httpd.c | 6 +-- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/Config.in b/Config.in index b83beb52d..285fe0a19 100644 --- a/Config.in +++ b/Config.in @@ -264,6 +264,18 @@ config PAM Use PAM in some busybox applets (currently login and httpd) instead of direct access to password database. +config FEATURE_USE_SENDFILE + bool "Use sendfile system call" + default y + help + When enabled, busybox will use the kernel sendfile() function + instead of read/write loops to copy data between file descriptors + (for example, cp command does this a lot). + If sendfile() doesn't work, copying code falls back to read/write + loop. sendfile() was originally implemented for faster I/O + from files to sockets, but since Linux 2.6.33 it was extended + to work for many more file types. + config LONG_OPTS bool "Support for --long-options" default y 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 @@ */ #include "libbb.h" +#if ENABLE_FEATURE_USE_SENDFILE +# include +#else +# define sendfile(a,b,c,d) (-1) +#endif + +/* + * We were using 0x7fff0000 as sendfile chunk size, but it + * was seen to cause largish delays when user tries to ^C a file copy. + * Let's use a saner size. + * Note: needs to be >= max(CONFIG_FEATURE_COPYBUF_KB), + * or else "copy to eof" code will use neddlesly short reads. + */ +#define SENDFILE_BIGBUF (16*1024*1024) /* Used by NOFORK applets (e.g. cat) - must not use xmalloc. * 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) int status = -1; off_t total = 0; bool continue_on_write_error = 0; -#if CONFIG_FEATURE_COPYBUF_KB <= 4 + ssize_t sendfile_sz; +#if CONFIG_FEATURE_COPYBUF_KB > 4 + char *buffer = buffer; /* for compiler */ + int buffer_size = 0; +#else char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; enum { buffer_size = sizeof(buffer) }; -#else - char *buffer; - int buffer_size; #endif if (size < 0) { @@ -31,46 +46,58 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) continue_on_write_error = 1; } -#if CONFIG_FEATURE_COPYBUF_KB > 4 - if (size > 0 && size <= 4 * 1024) - goto use_small_buf; - /* We want page-aligned buffer, just in case kernel is clever - * and can do page-aligned io more efficiently */ - buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - /* ignored: */ -1, 0); - buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; - if (buffer == MAP_FAILED) { - use_small_buf: - buffer = alloca(4 * 1024); - buffer_size = 4 * 1024; - } -#endif - if (src_fd < 0) goto out; + sendfile_sz = !ENABLE_FEATURE_USE_SENDFILE + ? 0 + : SENDFILE_BIGBUF; if (!size) { - size = buffer_size; + size = SENDFILE_BIGBUF; status = 1; /* copy until eof */ } while (1) { ssize_t rd; - rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); - - if (!rd) { /* eof - all done */ - status = 0; - break; + if (sendfile_sz) { + rd = sendfile(dst_fd, src_fd, NULL, + size > sendfile_sz ? sendfile_sz : size); + if (rd >= 0) + goto read_ok; + sendfile_sz = 0; /* do not try sendfile anymore */ } +#if CONFIG_FEATURE_COPYBUF_KB > 4 + if (buffer_size == 0) { + if (size > 0 && size <= 4 * 1024) + goto use_small_buf; + /* We want page-aligned buffer, just in case kernel is clever + * and can do page-aligned io more efficiently */ + buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, + /* ignored: */ -1, 0); + buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; + if (buffer == MAP_FAILED) { + use_small_buf: + buffer = alloca(4 * 1024); + buffer_size = 4 * 1024; + } + } +#endif + rd = safe_read(src_fd, buffer, + size > buffer_size ? buffer_size : size); if (rd < 0) { bb_perror_msg(bb_msg_read_error); break; } + read_ok: + if (!rd) { /* eof - all done */ + status = 0; + break; + } /* dst_fd == -1 is a fake, else... */ - if (dst_fd >= 0) { + if (dst_fd >= 0 && !sendfile_sz) { ssize_t wr = full_write(dst_fd, buffer, rd); if (wr < rd) { 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) } out: -#if CONFIG_FEATURE_COPYBUF_KB > 4 - if (buffer_size != 4 * 1024) + if (buffer_size > 4 * 1024) munmap(buffer, buffer_size); -#endif return status ? -1 : total; } 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 "Range: bytes=NNN-[MMM]" header. Allows for resuming interrupted downloads, seeking in multimedia players etc. -config FEATURE_HTTPD_USE_SENDFILE - bool "Use sendfile system call" - default y - depends on HTTPD - help - When enabled, httpd will use the kernel sendfile() function - instead of read/write loop. - config FEATURE_HTTPD_SETUID bool "Enable -u option" 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 @@ # include # include #endif -#if ENABLE_FEATURE_HTTPD_USE_SENDFILE +#if ENABLE_FEATURE_USE_SENDFILE # include #endif /* amount of buffering in a pipe */ @@ -1624,7 +1624,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what) #endif if (what & SEND_HEADERS) send_headers(HTTP_OK); -#if ENABLE_FEATURE_HTTPD_USE_SENDFILE +#if ENABLE_FEATURE_USE_SENDFILE { off_t offset = range_start; while (1) { @@ -1654,7 +1654,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what) break; } if (count < 0) { - IF_FEATURE_HTTPD_USE_SENDFILE(fin:) + IF_FEATURE_USE_SENDFILE(fin:) if (verbose > 1) bb_perror_msg("error"); } From 476654cdbeb2923fc5d2485701587b42579e1635 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 30 Nov 2014 19:39:58 +0100 Subject: [PATCH 09/24] man: do not mangle $MANPATH in memory Signed-off-by: Denys Vlasenko --- miscutils/man.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/miscutils/man.c b/miscutils/man.c index ccb57a93f..c39870e67 100644 --- a/miscutils/man.c +++ b/miscutils/man.c @@ -155,9 +155,9 @@ static char **add_MANPATH(char **man_path_list, int *count_mp, char *path) next_path = strchr(path, ':'); if (next_path) { - *next_path = '\0'; - if (next_path++ == path) /* "::"? */ + if (next_path == path) /* "::"? */ goto next; + *next_path = '\0'; } /* Do we already have path? */ path_element = man_path_list; @@ -174,8 +174,10 @@ static char **add_MANPATH(char **man_path_list, int *count_mp, char *path) skip: if (!next_path) break; + /* "path" may be a result of getenv(), be nice and don't mangle it */ + *next_path = ':'; next: - path = next_path; + path = next_path + 1; } return man_path_list; } From e7800f351ad9eca012fe27a1c9234692a04419e7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 7 Dec 2014 00:42:49 +0100 Subject: [PATCH 10/24] Rename transformer_aux_data_t -> transformer_state_t No code changes Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 34 ++++++++++----------- archival/bzip2.c | 2 +- archival/gzip.c | 2 +- archival/libarchive/decompress_bunzip2.c | 4 +-- archival/libarchive/decompress_gunzip.c | 26 ++++++++-------- archival/libarchive/decompress_uncompress.c | 4 +-- archival/libarchive/decompress_unlzma.c | 2 +- archival/libarchive/decompress_unxz.c | 4 +-- archival/libarchive/open_transformer.c | 22 ++++++------- archival/lzop.c | 2 +- archival/tar.c | 2 +- archival/unzip.c | 12 ++++---- include/bb_archive.h | 24 +++++++-------- 13 files changed, 70 insertions(+), 70 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index fce5ab9e1..84f58f138 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -39,7 +39,7 @@ char* FAST_FUNC append_ext(char *filename, const char *expected_ext) } int FAST_FUNC bbunpack(char **argv, - IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_aux_data_t *aux), + IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_state_t *xstate), char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), const char *expected_ext ) @@ -48,7 +48,7 @@ int FAST_FUNC bbunpack(char **argv, IF_DESKTOP(long long) int status = 0; char *filename, *new_name; smallint exitcode = 0; - transformer_aux_data_t aux; + transformer_state_t xstate; do { /* NB: new_name is *maybe* malloc'ed! */ @@ -120,9 +120,9 @@ int FAST_FUNC bbunpack(char **argv, } if (!(option_mask32 & SEAMLESS_MAGIC)) { - init_transformer_aux_data(&aux); - aux.check_signature = 1; - status = unpacker(&aux); + init_transformer_state(&xstate); + xstate.check_signature = 1; + status = unpacker(&xstate); if (status < 0) exitcode = 1; } else { @@ -141,10 +141,10 @@ int FAST_FUNC bbunpack(char **argv, unsigned new_name_len; /* TODO: restore other things? */ - if (aux.mtime != 0) { + if (xstate.mtime != 0) { struct timeval times[2]; - times[1].tv_sec = times[0].tv_sec = aux.mtime; + times[1].tv_sec = times[0].tv_sec = xstate.mtime; times[1].tv_usec = times[0].tv_usec = 0; /* Note: we closed it first. * On some systems calling utimes @@ -227,9 +227,9 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o #if ENABLE_UNCOMPRESS static -IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(transformer_aux_data_t *aux) +IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(transformer_state_t *xstate) { - return unpack_Z_stream(aux, STDIN_FILENO, STDOUT_FILENO); + return unpack_Z_stream(xstate, STDIN_FILENO, STDOUT_FILENO); } int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int uncompress_main(int argc UNUSED_PARAM, char **argv) @@ -325,9 +325,9 @@ char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UN return filename; } static -IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_aux_data_t *aux) +IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_state_t *xstate) { - return unpack_gz_stream(aux, STDIN_FILENO, STDOUT_FILENO); + return unpack_gz_stream(xstate, STDIN_FILENO, STDOUT_FILENO); } /* * Linux kernel build uses gzip -d -n. We accept and ignore it. @@ -396,9 +396,9 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o #if ENABLE_BUNZIP2 static -IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_aux_data_t *aux) +IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_state_t *xstate) { - return unpack_bz2_stream(aux, STDIN_FILENO, STDOUT_FILENO); + return unpack_bz2_stream(xstate, STDIN_FILENO, STDOUT_FILENO); } int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bunzip2_main(int argc UNUSED_PARAM, char **argv) @@ -495,9 +495,9 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o #if ENABLE_UNLZMA static -IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_aux_data_t *aux) +IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_state_t *xstate) { - return unpack_lzma_stream(aux, STDIN_FILENO, STDOUT_FILENO); + return unpack_lzma_stream(xstate, STDIN_FILENO, STDOUT_FILENO); } int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int unlzma_main(int argc UNUSED_PARAM, char **argv) @@ -538,9 +538,9 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o #if ENABLE_UNXZ static -IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_aux_data_t *aux) +IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_state_t *xstate) { - return unpack_xz_stream(aux, STDIN_FILENO, STDOUT_FILENO); + return unpack_xz_stream(xstate, STDIN_FILENO, STDOUT_FILENO); } int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int unxz_main(int argc UNUSED_PARAM, char **argv) 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 } static -IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_aux_data_t *aux UNUSED_PARAM) +IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_state_t *xstate UNUSED_PARAM) { IF_DESKTOP(long long) int total; 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) /* ======================================================================== */ static -IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_aux_data_t *aux UNUSED_PARAM) +IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED_PARAM) { struct stat s; diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 6396fe40d..36237e221 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) /* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ IF_DESKTOP(long long) int FAST_FUNC -unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) +unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) { IF_DESKTOP(long long total_written = 0;) bunzip_data *bd; @@ -739,7 +739,7 @@ unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) int i; unsigned len; - if (check_signature16(aux, src_fd, BZIP2_MAGIC)) + if (check_signature16(xstate, src_fd, BZIP2_MAGIC)) return -1; outbuf = xmalloc(IOBUF_SIZE); diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 7c6f38ec3..62a3d78b6 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c @@ -1034,22 +1034,22 @@ inflate_unzip_internal(STATE_PARAM int in, int out) /* For unzip */ IF_DESKTOP(long long) int FAST_FUNC -inflate_unzip(transformer_aux_data_t *aux, int in, int out) +inflate_unzip(transformer_state_t *xstate, int in, int out) { IF_DESKTOP(long long) int n; DECLARE_STATE; ALLOC_STATE; - to_read = aux->bytes_in; + to_read = xstate->bytes_in; // bytebuffer_max = 0x8000; bytebuffer_offset = 4; bytebuffer = xmalloc(bytebuffer_max); n = inflate_unzip_internal(PASS_STATE in, out); free(bytebuffer); - aux->crc32 = gunzip_crc; - aux->bytes_out = gunzip_bytes_out; + xstate->crc32 = gunzip_crc; + xstate->bytes_out = gunzip_bytes_out; DEALLOC_STATE; return n; } @@ -1107,7 +1107,7 @@ static uint32_t buffer_read_le_u32(STATE_PARAM_ONLY) return res; } -static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux) +static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) { union { unsigned char raw[8]; @@ -1169,8 +1169,8 @@ static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux) } } - if (aux) - aux->mtime = SWAP_LE32(header.formatted.mtime); + if (xstate) + xstate->mtime = SWAP_LE32(header.formatted.mtime); /* Read the header checksum */ if (header.formatted.flags & 0x02) { @@ -1182,17 +1182,17 @@ static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux) } IF_DESKTOP(long long) int FAST_FUNC -unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) +unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) { uint32_t v32; IF_DESKTOP(long long) int total, n; DECLARE_STATE; #if !ENABLE_FEATURE_SEAMLESS_Z - if (check_signature16(aux, src_fd, GZIP_MAGIC)) + if (check_signature16(xstate, src_fd, GZIP_MAGIC)) return -1; #else - if (aux && aux->check_signature) { + if (xstate && xstate->check_signature) { uint16_t magic2; if (full_read(src_fd, &magic2, 2) != 2) { @@ -1201,8 +1201,8 @@ unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) return -1; } if (magic2 == COMPRESS_MAGIC) { - aux->check_signature = 0; - return unpack_Z_stream(aux, src_fd, dst_fd); + xstate->check_signature = 0; + return unpack_Z_stream(xstate, src_fd, dst_fd); } if (magic2 != GZIP_MAGIC) goto bad_magic; @@ -1218,7 +1218,7 @@ unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) gunzip_src_fd = src_fd; again: - if (!check_header_gzip(PASS_STATE aux)) { + if (!check_header_gzip(PASS_STATE xstate)) { bb_error_msg("corrupted data"); total = -1; goto ret; diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c index 53c27080f..cb3d55a88 100644 --- a/archival/libarchive/decompress_uncompress.c +++ b/archival/libarchive/decompress_uncompress.c @@ -73,7 +73,7 @@ */ IF_DESKTOP(long long) int FAST_FUNC -unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) +unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) { IF_DESKTOP(long long total_written = 0;) 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) /* block compress mode -C compatible with 2.0 */ int block_mode; /* = BLOCK_MODE; */ - if (check_signature16(aux, src_fd, COMPRESS_MAGIC)) + if (check_signature16(xstate, src_fd, COMPRESS_MAGIC)) return -1; inbuf = xzalloc(IBUFSIZ + 64); diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index 3d99e1388..ccedac49d 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c @@ -206,7 +206,7 @@ enum { IF_DESKTOP(long long) int FAST_FUNC -unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst_fd) +unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst_fd) { IF_DESKTOP(long long total_written = 0;) lzma_header_t header; diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 986b7b191..6df54e131 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) #include "unxz/xz_dec_stream.c" IF_DESKTOP(long long) int FAST_FUNC -unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) +unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) { enum xz_ret xz_result; struct xz_buf iobuf; @@ -55,7 +55,7 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) iobuf.out = membuf + BUFSIZ; iobuf.out_size = BUFSIZ; - if (!aux || aux->check_signature == 0) { + if (!xstate || xstate->check_signature == 0) { /* Preload XZ file signature */ strcpy((char*)membuf, HEADER_MAGIC); iobuf.in_size = HEADER_MAGIC_SIZE; diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 198663041..584b15de4 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -6,19 +6,19 @@ #include "libbb.h" #include "bb_archive.h" -void FAST_FUNC init_transformer_aux_data(transformer_aux_data_t *aux) +void FAST_FUNC init_transformer_state(transformer_state_t *xstate) { - memset(aux, 0, sizeof(*aux)); + memset(xstate, 0, sizeof(*xstate)); } -int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16) +int FAST_FUNC check_signature16(transformer_state_t *xstate, int src_fd, unsigned magic16) { - if (aux && aux->check_signature) { + if (xstate && xstate->check_signature) { uint16_t magic2; if (full_read(src_fd, &magic2, 2) != 2 || magic2 != magic16) { bb_error_msg("invalid magic"); #if 0 /* possible future extension */ - if (aux->check_signature > 1) + if (xstate->check_signature > 1) xfunc_die(); #endif return -1; @@ -62,7 +62,7 @@ void check_errors_in_children(int signo) #if BB_MMU void FAST_FUNC open_transformer(int fd, int check_signature, - IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd) + IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate, int src_fd, int dst_fd) ) #else void FAST_FUNC open_transformer(int fd, const char *transform_prog) @@ -80,10 +80,10 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog) #if BB_MMU { IF_DESKTOP(long long) int r; - transformer_aux_data_t aux; - init_transformer_aux_data(&aux); - aux.check_signature = check_signature; - r = transformer(&aux, fd, fd_pipe.wr); + transformer_state_t xstate; + init_transformer_state(&xstate); + xstate.check_signature = check_signature; + r = transformer(&xstate, fd, fd_pipe.wr); if (ENABLE_FEATURE_CLEAN_UP) { close(fd_pipe.wr); /* send EOF */ close(fd); @@ -126,7 +126,7 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) uint32_t b32[1]; } magic; int offset = -2; - USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);) + USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate, int src_fd, int dst_fd);) USE_FOR_NOMMU(const char *xformer_prog;) /* .gz and .bz2 both have 2-byte signature, and their 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 return xasprintf("%s.lzo", filename); } -static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_aux_data_t *aux UNUSED_PARAM) +static IF_DESKTOP(long long) int FAST_FUNC pack_lzop(transformer_state_t *xstate UNUSED_PARAM) { if (option_mask32 & OPT_DECOMPRESS) return do_lzo_decompress(); diff --git a/archival/tar.c b/archival/tar.c index aa02d3512..7897a4af6 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -1171,7 +1171,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) } if (opt & OPT_ANY_COMPRESS) { - USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);) + USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate, int src_fd, int dst_fd);) USE_FOR_NOMMU(const char *xformer_prog;) if (opt & OPT_COMPRESS) diff --git a/archival/unzip.c b/archival/unzip.c index fcfc9a448..c622bde57 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -280,17 +280,17 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd) bb_copyfd_exact_size(zip_fd, dst_fd, size); } else { /* Method 8 - inflate */ - transformer_aux_data_t aux; - init_transformer_aux_data(&aux); - aux.bytes_in = zip_header->formatted.cmpsize; - if (inflate_unzip(&aux, zip_fd, dst_fd) < 0) + transformer_state_t xstate; + init_transformer_state(&xstate); + xstate.bytes_in = zip_header->formatted.cmpsize; + if (inflate_unzip(&xstate, zip_fd, dst_fd) < 0) bb_error_msg_and_die("inflate error"); /* Validate decompression - crc */ - if (zip_header->formatted.crc32 != (aux.crc32 ^ 0xffffffffL)) { + if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) { bb_error_msg_and_die("crc error"); } /* Validate decompression - size */ - if (zip_header->formatted.ucmpsize != aux.bytes_out) { + if (zip_header->formatted.ucmpsize != xstate.bytes_out) { /* Don't die. Who knows, maybe len calculation * was botched somewhere. After all, crc matched! */ bb_error_msg("bad length"); diff --git a/include/bb_archive.h b/include/bb_archive.h index b82cfd83c..8a2dd2735 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -203,27 +203,27 @@ int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; /* Meaning and direction (input/output) of the fields are transformer-specific */ -typedef struct transformer_aux_data_t { +typedef struct transformer_state_t { smallint check_signature; /* most often referenced member */ off_t bytes_out; off_t bytes_in; /* used in unzip code only: needs to know packed size */ uint32_t crc32; time_t mtime; /* gunzip code may set this on exit */ -} transformer_aux_data_t; +} transformer_state_t; -void init_transformer_aux_data(transformer_aux_data_t *aux) FAST_FUNC; -int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16) FAST_FUNC; +void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; +int FAST_FUNC check_signature16(transformer_state_t *xstate, int src_fd, unsigned magic16) FAST_FUNC; -IF_DESKTOP(long long) int inflate_unzip(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_gz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_lzma_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) FAST_FUNC; +IF_DESKTOP(long long) int inflate_unzip(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; +IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; +IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; +IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; +IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; +IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; char* append_ext(char *filename, const char *expected_ext) FAST_FUNC; int bbunpack(char **argv, - IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_aux_data_t *aux), + IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_state_t *xstate), char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), const char *expected_ext ) FAST_FUNC; @@ -232,7 +232,7 @@ void check_errors_in_children(int signo); #if BB_MMU void open_transformer(int fd, int check_signature, - IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd) + IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate, int src_fd, int dst_fd) ) FAST_FUNC; #define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), 1, (transformer)) #define open_transformer_with_no_sig(fd, transformer) open_transformer((fd), 0, (transformer)) From b4c11c139717729b8257ee9382d4e5ed713d4dde Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 7 Dec 2014 00:44:00 +0100 Subject: [PATCH 11/24] libarchive: add capability to unpack to mem.buffer The performance and number of processes for a "depmod -a" with gzipped modules was abysmal. This patch adds a code path without fork, benefiting all users of xmalloc_open_zipped_read_close. "modinfo radeon.ko.gz", a single-file reader, got 30% faster. "depmod -a", which used to fork over 800 times, got 20% faster. Heavily based on a patch by Lauri Kasanen function old new delta setup_transformer_on_fd - 159 +159 transformer_write - 122 +122 fork_transformer - 112 +112 xmalloc_open_zipped_read_close 63 118 +55 read_bunzip 1866 1896 +30 xtransformer_write - 19 +19 unzip_main 2449 2462 +13 bbunpack 755 766 +11 unpack_lzma_stream 2717 2723 +6 unpack_xz_stream 2393 2397 +4 unpack_Z_stream 1173 1175 +2 inflate_unzip 111 105 -6 check_signature16 70 63 -7 unpack_bz2_stream 359 349 -10 unpack_unxz 12 - -12 unpack_unlzma 12 - -12 unpack_uncompress 12 - -12 unpack_gunzip 12 - -12 unpack_bunzip2 12 - -12 open_transformer 106 92 -14 inflate_unzip_internal 1945 1916 -29 unpack_gz_stream 693 655 -38 open_zipped 89 47 -42 setup_unzip_on_fd 142 53 -89 ------------------------------------------------------------------------------ (add/remove: 4/5 grow/shrink: 7/8 up/down: 533/-295) Total: 238 bytes Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 37 +--- archival/libarchive/decompress_bunzip2.c | 11 +- archival/libarchive/decompress_gunzip.c | 30 ++- archival/libarchive/decompress_uncompress.c | 12 +- archival/libarchive/decompress_unlzma.c | 12 +- archival/libarchive/decompress_unxz.c | 6 +- archival/libarchive/get_header_tar_bz2.c | 2 +- archival/libarchive/get_header_tar_gz.c | 2 +- archival/libarchive/get_header_tar_lzma.c | 2 +- archival/libarchive/open_transformer.c | 203 ++++++++++++++++---- archival/tar.c | 4 +- archival/unzip.c | 4 +- include/bb_archive.h | 42 ++-- include/libbb.h | 3 +- 14 files changed, 243 insertions(+), 127 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 84f58f138..90aac1427 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -122,6 +122,8 @@ int FAST_FUNC bbunpack(char **argv, if (!(option_mask32 & SEAMLESS_MAGIC)) { init_transformer_state(&xstate); xstate.check_signature = 1; + /*xstate.src_fd = STDIN_FILENO; - already is */ + xstate.dst_fd = STDOUT_FILENO; status = unpacker(&xstate); if (status < 0) exitcode = 1; @@ -226,18 +228,13 @@ char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) //applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o #if ENABLE_UNCOMPRESS -static -IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(transformer_state_t *xstate) -{ - return unpack_Z_stream(xstate, STDIN_FILENO, STDOUT_FILENO); -} int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int uncompress_main(int argc UNUSED_PARAM, char **argv) { getopt32(argv, "cf"); argv += optind; - return bbunpack(argv, unpack_uncompress, make_new_name_generic, "Z"); + return bbunpack(argv, unpack_Z_stream, make_new_name_generic, "Z"); } #endif @@ -324,11 +321,6 @@ char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UN } return filename; } -static -IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_state_t *xstate) -{ - return unpack_gz_stream(xstate, STDIN_FILENO, STDOUT_FILENO); -} /* * Linux kernel build uses gzip -d -n. We accept and ignore it. * Man page says: @@ -355,7 +347,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) if (applet_name[1] == 'c') option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; - return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL); + return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); } #endif @@ -395,11 +387,6 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o //kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o #if ENABLE_BUNZIP2 -static -IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_state_t *xstate) -{ - return unpack_bz2_stream(xstate, STDIN_FILENO, STDOUT_FILENO); -} int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bunzip2_main(int argc UNUSED_PARAM, char **argv) { @@ -408,7 +395,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) if (applet_name[2] == 'c') /* bzcat */ option_mask32 |= OPT_STDOUT; - return bbunpack(argv, unpack_bunzip2, make_new_name_generic, "bz2"); + return bbunpack(argv, unpack_bz2_stream, make_new_name_generic, "bz2"); } #endif @@ -494,11 +481,6 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o #if ENABLE_UNLZMA -static -IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_state_t *xstate) -{ - return unpack_lzma_stream(xstate, STDIN_FILENO, STDOUT_FILENO); -} int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int unlzma_main(int argc UNUSED_PARAM, char **argv) { @@ -513,7 +495,7 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) option_mask32 |= OPT_STDOUT; argv += optind; - return bbunpack(argv, unpack_unlzma, make_new_name_generic, "lzma"); + return bbunpack(argv, unpack_lzma_stream, make_new_name_generic, "lzma"); } #endif @@ -537,11 +519,6 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) //applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o #if ENABLE_UNXZ -static -IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_state_t *xstate) -{ - return unpack_xz_stream(xstate, STDIN_FILENO, STDOUT_FILENO); -} int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int unxz_main(int argc UNUSED_PARAM, char **argv) { @@ -556,6 +533,6 @@ int unxz_main(int argc UNUSED_PARAM, char **argv) option_mask32 |= OPT_STDOUT; argv += optind; - return bbunpack(argv, unpack_unxz, make_new_name_generic, "xz"); + return bbunpack(argv, unpack_xz_stream, make_new_name_generic, "xz"); } #endif diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 36237e221..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) /* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ IF_DESKTOP(long long) int FAST_FUNC -unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) +unpack_bz2_stream(transformer_state_t *xstate) { IF_DESKTOP(long long total_written = 0;) bunzip_data *bd; @@ -739,14 +739,14 @@ unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) int i; unsigned len; - if (check_signature16(xstate, src_fd, BZIP2_MAGIC)) + if (check_signature16(xstate, BZIP2_MAGIC)) return -1; outbuf = xmalloc(IOBUF_SIZE); len = 0; while (1) { /* "Process one BZ... stream" loop */ - i = start_bunzip(&bd, src_fd, outbuf + 2, len); + i = start_bunzip(&bd, xstate->src_fd, outbuf + 2, len); if (i == 0) { while (1) { /* "Produce some output bytes" loop */ @@ -756,8 +756,7 @@ unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) i = IOBUF_SIZE - i; /* number of bytes produced */ if (i == 0) /* EOF? */ break; - if (i != full_write(dst_fd, outbuf, i)) { - bb_error_msg("short write"); + if (i != transformer_write(xstate, outbuf, i)) { i = RETVAL_SHORT_WRITE; goto release_mem; } @@ -790,7 +789,7 @@ unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) len = bd->inbufCount - bd->inbufPos; memcpy(outbuf, &bd->inbuf[bd->inbufPos], len); if (len < 2) { - if (safe_read(src_fd, outbuf + len, 2 - len) != 2 - len) + if (safe_read(xstate->src_fd, outbuf + len, 2 - len) != 2 - len) break; len = 2; } diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 62a3d78b6..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) /* Called from unpack_gz_stream() and inflate_unzip() */ static IF_DESKTOP(long long) int -inflate_unzip_internal(STATE_PARAM int in, int out) +inflate_unzip_internal(STATE_PARAM transformer_state_t *xstate) { IF_DESKTOP(long long) int n = 0; ssize_t nwrote; @@ -980,7 +980,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out) gunzip_window = xmalloc(GUNZIP_WSIZE); gunzip_outbuf_count = 0; gunzip_bytes_out = 0; - gunzip_src_fd = in; + gunzip_src_fd = xstate->src_fd; /* (re) initialize state */ method = -1; @@ -1002,9 +1002,8 @@ inflate_unzip_internal(STATE_PARAM int in, int out) while (1) { int r = inflate_get_next_window(PASS_STATE_ONLY); - nwrote = full_write(out, gunzip_window, gunzip_outbuf_count); - if (nwrote != (ssize_t)gunzip_outbuf_count) { - bb_perror_msg("write"); + nwrote = transformer_write(xstate, gunzip_window, gunzip_outbuf_count); + if (nwrote == (ssize_t)-1) { n = -1; goto ret; } @@ -1034,7 +1033,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out) /* For unzip */ IF_DESKTOP(long long) int FAST_FUNC -inflate_unzip(transformer_state_t *xstate, int in, int out) +inflate_unzip(transformer_state_t *xstate) { IF_DESKTOP(long long) int n; DECLARE_STATE; @@ -1045,7 +1044,7 @@ inflate_unzip(transformer_state_t *xstate, int in, int out) // bytebuffer_max = 0x8000; bytebuffer_offset = 4; bytebuffer = xmalloc(bytebuffer_max); - n = inflate_unzip_internal(PASS_STATE in, out); + n = inflate_unzip_internal(PASS_STATE xstate); free(bytebuffer); xstate->crc32 = gunzip_crc; @@ -1169,8 +1168,7 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) } } - if (xstate) - xstate->mtime = SWAP_LE32(header.formatted.mtime); + xstate->mtime = SWAP_LE32(header.formatted.mtime); /* Read the header checksum */ if (header.formatted.flags & 0x02) { @@ -1182,27 +1180,27 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) } IF_DESKTOP(long long) int FAST_FUNC -unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) +unpack_gz_stream(transformer_state_t *xstate) { uint32_t v32; IF_DESKTOP(long long) int total, n; DECLARE_STATE; #if !ENABLE_FEATURE_SEAMLESS_Z - if (check_signature16(xstate, src_fd, GZIP_MAGIC)) + if (check_signature16(xstate, GZIP_MAGIC)) return -1; #else - if (xstate && xstate->check_signature) { + if (xstate->check_signature) { uint16_t magic2; - if (full_read(src_fd, &magic2, 2) != 2) { + if (full_read(xstate->src_fd, &magic2, 2) != 2) { bad_magic: bb_error_msg("invalid magic"); return -1; } if (magic2 == COMPRESS_MAGIC) { xstate->check_signature = 0; - return unpack_Z_stream(xstate, src_fd, dst_fd); + return unpack_Z_stream(xstate); } if (magic2 != GZIP_MAGIC) goto bad_magic; @@ -1215,7 +1213,7 @@ unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) to_read = -1; // bytebuffer_max = 0x8000; bytebuffer = xmalloc(bytebuffer_max); - gunzip_src_fd = src_fd; + gunzip_src_fd = xstate->src_fd; again: if (!check_header_gzip(PASS_STATE xstate)) { @@ -1224,7 +1222,7 @@ unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) goto ret; } - n = inflate_unzip_internal(PASS_STATE src_fd, dst_fd); + n = inflate_unzip_internal(PASS_STATE xstate); if (n < 0) { total = -1; goto ret; diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c index cb3d55a88..496d864a7 100644 --- a/archival/libarchive/decompress_uncompress.c +++ b/archival/libarchive/decompress_uncompress.c @@ -73,7 +73,7 @@ */ IF_DESKTOP(long long) int FAST_FUNC -unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) +unpack_Z_stream(transformer_state_t *xstate) { IF_DESKTOP(long long total_written = 0;) IF_DESKTOP(long long) int retval = -1; @@ -102,7 +102,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) /* block compress mode -C compatible with 2.0 */ int block_mode; /* = BLOCK_MODE; */ - if (check_signature16(xstate, src_fd, COMPRESS_MAGIC)) + if (check_signature16(xstate, COMPRESS_MAGIC)) return -1; inbuf = xzalloc(IBUFSIZ + 64); @@ -114,7 +114,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) /* xread isn't good here, we have to return - caller may want * to do some cleanup (e.g. delete incomplete unpacked file etc) */ - if (full_read(src_fd, inbuf, 1) != 1) { + if (full_read(xstate->src_fd, inbuf, 1) != 1) { bb_error_msg("short read"); goto err; } @@ -166,7 +166,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) } if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { - rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ); + rsize = safe_read(xstate->src_fd, inbuf + insize, IBUFSIZ); if (rsize < 0) bb_error_msg_and_die(bb_msg_read_error); insize += rsize; @@ -274,7 +274,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) } if (outpos >= OBUFSIZ) { - xwrite(dst_fd, outbuf, outpos); + xtransformer_write(xstate, outbuf, outpos); IF_DESKTOP(total_written += outpos;) outpos = 0; } @@ -301,7 +301,7 @@ unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) } while (rsize > 0); if (outpos > 0) { - xwrite(dst_fd, outbuf, outpos); + xtransformer_write(xstate, outbuf, outpos); IF_DESKTOP(total_written += outpos;) } diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index ccedac49d..c8622f97b 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c @@ -206,7 +206,7 @@ enum { IF_DESKTOP(long long) int FAST_FUNC -unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst_fd) +unpack_lzma_stream(transformer_state_t *xstate) { IF_DESKTOP(long long total_written = 0;) lzma_header_t header; @@ -223,7 +223,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst int state = 0; uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; - if (full_read(src_fd, &header, sizeof(header)) != sizeof(header) + if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header) || header.pos >= (9 * 5 * 5) ) { bb_error_msg("bad lzma header"); @@ -258,7 +258,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; } - rc = rc_init(src_fd); /*, RC_BUFFER_SIZE); */ + rc = rc_init(xstate->src_fd); /*, RC_BUFFER_SIZE); */ while (global_pos + buffer_pos < header.dst_size) { int pos_state = (buffer_pos + global_pos) & pos_state_mask; @@ -306,7 +306,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst if (buffer_pos == header.dict_size) { buffer_pos = 0; global_pos += header.dict_size; - if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size) + if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size) goto bad; IF_DESKTOP(total_written += header.dict_size;) } @@ -440,7 +440,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst if (buffer_pos == header.dict_size) { buffer_pos = 0; global_pos += header.dict_size; - if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size) + if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size) goto bad; IF_DESKTOP(total_written += header.dict_size;) } @@ -455,7 +455,7 @@ unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst { IF_NOT_DESKTOP(int total_written = 0; /* success */) IF_DESKTOP(total_written += buffer_pos;) - if (full_write(dst_fd, buffer, buffer_pos) != (ssize_t)buffer_pos) { + if (transformer_write(xstate, buffer, buffer_pos) != (ssize_t)buffer_pos) { bad: total_written = -1; /* failure */ } diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 6df54e131..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) #include "unxz/xz_dec_stream.c" IF_DESKTOP(long long) int FAST_FUNC -unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) +unpack_xz_stream(transformer_state_t *xstate) { enum xz_ret xz_result; struct xz_buf iobuf; @@ -67,7 +67,7 @@ unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) xz_result = X_OK; while (1) { if (iobuf.in_pos == iobuf.in_size) { - int rd = safe_read(src_fd, membuf, BUFSIZ); + int rd = safe_read(xstate->src_fd, membuf, BUFSIZ); if (rd < 0) { bb_error_msg(bb_msg_read_error); total = -1; @@ -104,7 +104,7 @@ unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) // bb_error_msg("seek = seek_by_read; - open_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2"); + fork_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2"); archive_handle->offset = 0; while (get_header_tar(archive_handle) == EXIT_SUCCESS) 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) /* Can't lseek over pipes */ archive_handle->seek = seek_by_read; - open_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip"); + fork_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip"); archive_handle->offset = 0; while (get_header_tar(archive_handle) == EXIT_SUCCESS) 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) /* Can't lseek over pipes */ archive_handle->seek = seek_by_read; - open_transformer_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma"); + fork_transformer_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma"); archive_handle->offset = 0; while (get_header_tar(archive_handle) == EXIT_SUCCESS) continue; diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 584b15de4..9d762a859 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -11,11 +11,11 @@ void FAST_FUNC init_transformer_state(transformer_state_t *xstate) memset(xstate, 0, sizeof(*xstate)); } -int FAST_FUNC check_signature16(transformer_state_t *xstate, int src_fd, unsigned magic16) +int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16) { - if (xstate && xstate->check_signature) { + if (xstate->check_signature) { uint16_t magic2; - if (full_read(src_fd, &magic2, 2) != 2 || magic2 != magic16) { + if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { bb_error_msg("invalid magic"); #if 0 /* possible future extension */ if (xstate->check_signature > 1) @@ -27,6 +27,46 @@ int FAST_FUNC check_signature16(transformer_state_t *xstate, int src_fd, unsigne return 0; } +ssize_t FAST_FUNC transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) +{ + ssize_t nwrote; + + if (xstate->mem_output_size_max != 0) { + size_t pos = xstate->mem_output_size; + size_t size; + + size = (xstate->mem_output_size += bufsize); + if (size > xstate->mem_output_size_max) { + free(xstate->mem_output_buf); + xstate->mem_output_buf = NULL; + bb_perror_msg("buffer %u too small", (unsigned)xstate->mem_output_size_max); + nwrote = -1; + goto ret; + } + xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size); + memcpy(xstate->mem_output_buf + pos, buf, bufsize); + nwrote = bufsize; + } else { + nwrote = full_write(xstate->dst_fd, buf, bufsize); + if (nwrote != (ssize_t)bufsize) { + bb_perror_msg("write"); + nwrote = -1; + goto ret; + } + } + ret: + return nwrote; +} + +ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) +{ + ssize_t nwrote = transformer_write(xstate, buf, bufsize); + if (nwrote != (ssize_t)bufsize) { + xfunc_die(); + } + return nwrote; +} + void check_errors_in_children(int signo) { int status; @@ -60,12 +100,12 @@ void check_errors_in_children(int signo) /* transformer(), more than meets the eye */ #if BB_MMU -void FAST_FUNC open_transformer(int fd, +void FAST_FUNC fork_transformer(int fd, int check_signature, - IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate, int src_fd, int dst_fd) + IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) ) #else -void FAST_FUNC open_transformer(int fd, const char *transform_prog) +void FAST_FUNC fork_transformer(int fd, const char *transform_prog) #endif { struct fd_pair fd_pipe; @@ -83,7 +123,9 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog) transformer_state_t xstate; init_transformer_state(&xstate); xstate.check_signature = check_signature; - r = transformer(&xstate, fd, fd_pipe.wr); + xstate.src_fd = fd; + xstate.dst_fd = fd_pipe.wr; + r = transformer(&xstate); if (ENABLE_FEATURE_CLEAN_UP) { close(fd_pipe.wr); /* send EOF */ close(fd); @@ -118,16 +160,19 @@ void FAST_FUNC open_transformer(int fd, const char *transform_prog) /* Used by e.g. rpm which gives us a fd without filename, * thus we can't guess the format from filename's extension. */ -int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) +static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) { union { uint8_t b[4]; uint16_t b16[2]; uint32_t b32[1]; } magic; - int offset = -2; - USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate, int src_fd, int dst_fd);) - USE_FOR_NOMMU(const char *xformer_prog;) + int offset; + transformer_state_t *xstate; + + offset = -2; + xstate = xzalloc(sizeof(*xstate)); + xstate->src_fd = fd; /* .gz and .bz2 both have 2-byte signature, and their * unpack_XXX_stream wants this header skipped. */ @@ -135,15 +180,15 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) if (ENABLE_FEATURE_SEAMLESS_GZ && magic.b16[0] == GZIP_MAGIC ) { - USE_FOR_MMU(xformer = unpack_gz_stream;) - USE_FOR_NOMMU(xformer_prog = "gunzip";) + xstate->xformer = unpack_gz_stream; + USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) goto found_magic; } if (ENABLE_FEATURE_SEAMLESS_BZ2 && magic.b16[0] == BZIP2_MAGIC ) { - USE_FOR_MMU(xformer = unpack_bz2_stream;) - USE_FOR_NOMMU(xformer_prog = "bunzip2";) + xstate->xformer = unpack_bz2_stream; + USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";) goto found_magic; } if (ENABLE_FEATURE_SEAMLESS_XZ @@ -152,8 +197,8 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) offset = -6; xread(fd, magic.b32, sizeof(magic.b32[0])); if (magic.b32[0] == XZ_MAGIC2) { - USE_FOR_MMU(xformer = unpack_xz_stream;) - USE_FOR_NOMMU(xformer_prog = "unxz";) + xstate->xformer = unpack_xz_stream; + USE_FOR_NOMMU(xstate->xformer_prog = "unxz";) goto found_magic; } } @@ -164,52 +209,130 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) IF_FEATURE_SEAMLESS_BZ2("/bzip2") IF_FEATURE_SEAMLESS_XZ("/xz") " magic"); - xlseek(fd, offset, SEEK_CUR); - return 1; - found_magic: -# if BB_MMU - open_transformer_with_no_sig(fd, xformer); -# else - /* NOMMU version of open_transformer execs + /* Some callers expect this function to "consume" fd + * even if data is not compressed. In this case, + * we return a state with trivial transformer. + */ +// USE_FOR_MMU(xstate->xformer = copy_stream;) +// USE_FOR_NOMMU(xstate->xformer_prog = "cat";) + /* fall through to seeking bck over bytes we read earlier */ + + USE_FOR_NOMMU(found_magic:) + /* NOMMU version of fork_transformer execs * an external unzipper that wants - * file position at the start of the file */ + * file position at the start of the file. + */ xlseek(fd, offset, SEEK_CUR); - open_transformer_with_sig(fd, xformer, xformer_prog); + + USE_FOR_MMU(found_magic:) + /* In MMU case, if magic was found, seeking back is not necessary */ + + return xstate; +} + +/* Used by e.g. rpm which gives us a fd without filename, + * thus we can't guess the format from filename's extension. + */ +int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) +{ + transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); + + if (!xstate || !xstate->xformer) { + free(xstate); + return 1; + } + +# if BB_MMU + fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); +# else + fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); # endif + free(xstate); return 0; } -int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) +static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed) { + transformer_state_t *xstate; int fd; fd = open(fname, O_RDONLY); if (fd < 0) - return fd; + return NULL; if (ENABLE_FEATURE_SEAMLESS_LZMA) { /* .lzma has no header/signature, can only detect it by extension */ char *sfx = strrchr(fname, '.'); if (sfx && strcmp(sfx+1, "lzma") == 0) { - open_transformer_with_sig(fd, unpack_lzma_stream, "unlzma"); - return fd; + xstate = xzalloc(sizeof(*xstate)); + xstate->src_fd = fd; + xstate->xformer = unpack_lzma_stream; + USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";) + return xstate; } } - if ((ENABLE_FEATURE_SEAMLESS_GZ) - || (ENABLE_FEATURE_SEAMLESS_BZ2) - || (ENABLE_FEATURE_SEAMLESS_XZ) - ) { - setup_unzip_on_fd(fd, fail_if_not_compressed); - } + xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); + + return xstate; +} + +int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) +{ + int fd; + transformer_state_t *xstate; + + xstate = open_transformer(fname, fail_if_not_compressed); + if (!xstate) + return -1; + + fd = xstate->src_fd; + if (xstate->xformer) { +# if BB_MMU + fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); +# else + fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); +# endif + } + /* else: the file is not compressed */ + + free(xstate); return fd; } -#endif /* SEAMLESS_COMPRESSION */ - void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) { +# if 1 + transformer_state_t *xstate; + char *image; + + xstate = open_transformer(fname, /*fail_if_not_compressed:*/ 0); + if (!xstate) /* file open error */ + return NULL; + + image = NULL; + if (xstate->xformer) { + /* In-memory decompression */ + xstate->mem_output_size_max = maxsz_p ? *maxsz_p : (size_t)(INT_MAX - 4095); + xstate->xformer(xstate); + if (xstate->mem_output_buf) { + image = xstate->mem_output_buf; + if (maxsz_p) + *maxsz_p = xstate->mem_output_size; + } + } else { + /* File is not compressed */ + image = xmalloc_read(xstate->src_fd, maxsz_p); + } + + if (!image) + bb_perror_msg("read error from '%s'", fname); + close(xstate->src_fd); + free(xstate); + return image; +# else + /* This version forks a subprocess - much more expensive */ int fd; char *image; @@ -221,6 +344,8 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_ if (!image) bb_perror_msg("read error from '%s'", fname); close(fd); - return image; +# endif } + +#endif /* SEAMLESS_COMPRESSION */ diff --git a/archival/tar.c b/archival/tar.c index 7897a4af6..5bd473aac 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -1171,7 +1171,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) } if (opt & OPT_ANY_COMPRESS) { - USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate, int src_fd, int dst_fd);) + USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);) USE_FOR_NOMMU(const char *xformer_prog;) if (opt & OPT_COMPRESS) @@ -1190,7 +1190,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) USE_FOR_MMU(xformer = unpack_xz_stream;) USE_FOR_NOMMU(xformer_prog = "unxz";) - open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); + fork_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); /* Can't lseek over pipes */ tar_handle->seek = seek_by_read; /*tar_handle->offset = 0; - already is */ diff --git a/archival/unzip.c b/archival/unzip.c index c622bde57..38a07e212 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -283,7 +283,9 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd) transformer_state_t xstate; init_transformer_state(&xstate); xstate.bytes_in = zip_header->formatted.cmpsize; - if (inflate_unzip(&xstate, zip_fd, dst_fd) < 0) + xstate.src_fd = zip_fd; + xstate.dst_fd = dst_fd; + if (inflate_unzip(&xstate) < 0) bb_error_msg_and_die("inflate error"); /* Validate decompression - crc */ if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) { diff --git a/include/bb_archive.h b/include/bb_archive.h index 8a2dd2735..a6b166fe3 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -205,6 +205,18 @@ void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; /* Meaning and direction (input/output) of the fields are transformer-specific */ typedef struct transformer_state_t { smallint check_signature; /* most often referenced member */ + + IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate); + USE_FOR_NOMMU(const char *xformer_prog;) + + /* Source */ + int src_fd; + /* Output */ + int dst_fd; + size_t mem_output_size_max; /* if non-zero, decompress to RAM instead of fd */ + size_t mem_output_size; + char *mem_output_buf; + off_t bytes_out; off_t bytes_in; /* used in unzip code only: needs to know packed size */ uint32_t crc32; @@ -212,14 +224,16 @@ typedef struct transformer_state_t { } transformer_state_t; void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; -int FAST_FUNC check_signature16(transformer_state_t *xstate, int src_fd, unsigned magic16) FAST_FUNC; +ssize_t transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC; +ssize_t xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC; +int check_signature16(transformer_state_t *xstate, unsigned magic16) FAST_FUNC; -IF_DESKTOP(long long) int inflate_unzip(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; -IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate, int src_fd, int dst_fd) FAST_FUNC; +IF_DESKTOP(long long) int inflate_unzip(transformer_state_t *xstate) FAST_FUNC; +IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate) FAST_FUNC; +IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate) FAST_FUNC; +IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate) FAST_FUNC; +IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate) FAST_FUNC; +IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate) FAST_FUNC; char* append_ext(char *filename, const char *expected_ext) FAST_FUNC; int bbunpack(char **argv, @@ -230,16 +244,16 @@ int bbunpack(char **argv, void check_errors_in_children(int signo); #if BB_MMU -void open_transformer(int fd, +void fork_transformer(int fd, int check_signature, - IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate, int src_fd, int dst_fd) + IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) ) FAST_FUNC; -#define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), 1, (transformer)) -#define open_transformer_with_no_sig(fd, transformer) open_transformer((fd), 0, (transformer)) +#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer)) +#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 0, (transformer)) #else -void open_transformer(int fd, const char *transform_prog) FAST_FUNC; -#define open_transformer_with_sig(fd, transformer, transform_prog) open_transformer((fd), (transform_prog)) -/* open_transformer_with_no_sig() does not exist on NOMMU */ +void fork_transformer(int fd, const char *transform_prog) FAST_FUNC; +#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog)) +/* fork_transformer_with_no_sig() does not exist on NOMMU */ #endif diff --git a/include/libbb.h b/include/libbb.h index 17a0089d8..8e8b9ca0e 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -755,11 +755,12 @@ unsigned bb_clk_tck(void) FAST_FUNC; extern int setup_unzip_on_fd(int fd, int fail_if_not_compressed) FAST_FUNC; /* Autodetects .gz etc */ extern int open_zipped(const char *fname, int fail_if_not_compressed) FAST_FUNC; +extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; #else # define setup_unzip_on_fd(...) (0) # define open_zipped(fname, fail_if_not_compressed) open((fname), O_RDONLY); +# define xmalloc_open_zipped_read_close(fname, maxsz_p) xmalloc_open_read_close((fname), (maxsz_p)) #endif -extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC; // NB: will return short write on error, not -1, From cfcd2399b20998a374ad52a5fac353f77e6ec0f6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 7 Dec 2014 00:49:55 +0100 Subject: [PATCH 12/24] make xmalloc_open_zipped_read_close result NUL terminated Compat with xmalloc_open_read_close Signed-off-by: Denys Vlasenko --- archival/libarchive/open_transformer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 9d762a859..ab6aa3afc 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -43,8 +43,9 @@ ssize_t FAST_FUNC transformer_write(transformer_state_t *xstate, const void *buf nwrote = -1; goto ret; } - xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size); + xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size + 1); memcpy(xstate->mem_output_buf + pos, buf, bufsize); + xstate->mem_output_buf[size] = '\0'; nwrote = bufsize; } else { nwrote = full_write(xstate->dst_fd, buf, bufsize); From bd7c1f2d13cd1f7927ec081e4f23ee0f0b079e9a Mon Sep 17 00:00:00 2001 From: Jacob Kjaergaard Date: Wed, 10 Dec 2014 13:44:27 +0100 Subject: [PATCH 13/24] flashcp: change BUFSIZE to 4k some flash partitions can be smaller than the existing BUFSIZE thus write BUFSIZE will fail with "no space left on device" Signed-off-by: Jacob Kjaergaard Signed-off-by: Denys Vlasenko --- miscutils/flashcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@ #define OPT_v (1 << 0) -#define BUFSIZE (8 * 1024) +#define BUFSIZE (4 * 1024) static void progress(int mode, uoff_t count, uoff_t total) { From 202d9a646489ed3f15c0460d76776b3dfb1d4e72 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 10 Dec 2014 13:34:42 +0100 Subject: [PATCH 14/24] Config: select PLATFORM_LINUX if using sendfile() Man entry for sendfile: Not specified in POSIX.1-2001, or other standards. Other UNIX systems implement sendfile() with different semantics and prototypes. It should not be used in portable programs. Select PLATFORM_LINUX if enabling FEATURE_USE_SENDFILE. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- Config.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Config.in b/Config.in index 285fe0a19..07b4bf36b 100644 --- a/Config.in +++ b/Config.in @@ -267,6 +267,7 @@ config PAM config FEATURE_USE_SENDFILE bool "Use sendfile system call" default y + select PLATFORM_LINUX help When enabled, busybox will use the kernel sendfile() function instead of read/write loops to copy data between file descriptors From d598a8d4e655b095c741f0cf73e139b3c9524da1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 10 Dec 2014 17:22:13 +0100 Subject: [PATCH 15/24] lineedit: don't fall back to simple line input if tty is in raw mode Testcase: shell command input after python ^Z should still work Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 85643079b..3961b1de3 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2256,9 +2256,13 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman INIT_S(); if (tcgetattr(STDIN_FILENO, &initial_settings) < 0 - || !(initial_settings.c_lflag & ECHO) + || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON ) { - /* Happens when e.g. stty -echo was run before */ + /* Happens when e.g. stty -echo was run before. + * But if ICANON is not set, we don't come here. + * (example: interactive python ^Z-backgrounded, + * tty is still in "raw mode"). + */ parse_and_put_prompt(prompt); /* fflush_all(); - done by parse_and_put_prompt */ if (fgets(command, maxsize, stdin) == NULL) From acb8be721768b54075a51d1859d390904a0f1f6c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 11 Dec 2014 15:33:07 +0100 Subject: [PATCH 16/24] tar: fix "tar -cJ" ignoring -J option. closes 7706 function old new delta tar_main 895 938 +43 vfork_compressor 206 191 -15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 43/-15) Total: 28 bytes Signed-off-by: Denys Vlasenko --- archival/tar.c | 66 +++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/archival/tar.c b/archival/tar.c index 5bd473aac..e116bd287 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -160,13 +160,6 @@ #define block_buf bb_common_bufsiz1 -#if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2 -/* Do not pass gzip flag to writeTarFile() */ -#define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \ - writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude) -#endif - - #if ENABLE_FEATURE_TAR_CREATE /* @@ -621,21 +614,12 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb return TRUE; } -#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 -# if !(ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2) -# define vfork_compressor(tar_fd, gzip) vfork_compressor(tar_fd) -# endif +#if SEAMLESS_COMPRESSION /* Don't inline: vfork scares gcc and pessimizes code */ -static void NOINLINE vfork_compressor(int tar_fd, int gzip) +static void NOINLINE vfork_compressor(int tar_fd, const char *gzip) { pid_t gzipPid; -# if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2 - const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; -# elif ENABLE_FEATURE_SEAMLESS_GZ - const char *zip_exec = "gzip"; -# else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */ - const char *zip_exec = "bzip2"; -# endif + // On Linux, vfork never unpauses parent early, although standard // allows for that. Do we want to waste bytes checking for it? # define WAIT_FOR_CHILD 0 @@ -649,11 +633,6 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ -# if defined(__GNUC__) && __GNUC__ - /* Avoid vfork clobbering */ - (void) &zip_exec; -# endif - gzipPid = xvfork(); if (gzipPid == 0) { @@ -669,7 +648,7 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) xmove_fd(gzipDataPipe.rd, 0); xmove_fd(tar_fd, 1); /* exec gzip/bzip2 program/applet */ - BB_EXECLP(zip_exec, zip_exec, "-f", (char *)0); + BB_EXECLP(gzip, gzip, "-f", (char *)0); vfork_exec_errno = errno; _exit(EXIT_FAILURE); } @@ -692,16 +671,21 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) # endif if (vfork_exec_errno) { errno = vfork_exec_errno; - bb_perror_msg_and_die("can't execute '%s'", zip_exec); + bb_perror_msg_and_die("can't execute '%s'", gzip); } } -#endif /* ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 */ +#endif /* SEAMLESS_COMPRESSION */ +#if !SEAMLESS_COMPRESSION +/* Do not pass gzip flag to writeTarFile() */ +#define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \ + writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude) +#endif /* gcc 4.2.1 inlines it, making code bigger */ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, int recurseFlags, const llist_t *include, - const llist_t *exclude, int gzip) + const llist_t *exclude, const char *gzip) { int errorFlag = FALSE; struct TarBallInfo tbInfo; @@ -714,7 +698,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, * can avoid including the tarball into itself.... */ xfstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf, "can't stat tar file"); -#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 +#if SEAMLESS_COMPRESSION if (gzip) vfork_compressor(tbInfo.tarFd, gzip); #endif @@ -749,7 +733,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, if (errorFlag) bb_error_msg("error exit delayed from previous errors"); -#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 +#if SEAMLESS_COMPRESSION if (gzip) { int status; if (safe_waitpid(-1, &status, 0) == -1) @@ -764,7 +748,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, #else int writeTarFile(int tar_fd, int verboseFlag, int recurseFlags, const llist_t *include, - const llist_t *exclude, int gzip); + const llist_t *exclude, const char *gzip); #endif /* FEATURE_TAR_CREATE */ #if ENABLE_FEATURE_TAR_FROM @@ -1149,18 +1133,24 @@ int tar_main(int argc UNUSED_PARAM, char **argv) if (base_dir) xchdir(base_dir); - //if (SEAMLESS_COMPRESSION || OPT_COMPRESS) + //if (SEAMLESS_COMPRESSION) // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ // signal(SIGCHLD, check_errors_in_children); /* Create an archive */ if (opt & OPT_CREATE) { -#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 - int zipMode = 0; - if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP)) - zipMode = 1; - if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2)) - zipMode = 2; +#if SEAMLESS_COMPRESSION + const char *zipMode = NULL; + if (opt & OPT_COMPRESS) + zipMode = "compress"; + if (opt & OPT_GZIP) + zipMode = "gzip"; + if (opt & OPT_BZIP2) + zipMode = "bzip2"; + if (opt & OPT_LZMA) + zipMode = "lzma"; + if (opt & OPT_XZ) + zipMode = "xz"; #endif /* NB: writeTarFile() closes tar_handle->src_fd */ return writeTarFile(tar_handle->src_fd, verboseFlag, From 20cd31a2d7cc1b633b725280eb7546ca14eef7eb Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 12 Dec 2014 08:29:41 +0000 Subject: [PATCH 17/24] lineedit: don't block when looking for escape sequence in vi-mode In vi-mode lineedit tries to detect some escape sequences. After the ESC it reads the next character to check for certain values. This read should have a timeout or a user-entered ESC to switch to command mode doesn't properly handle the next character. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 3961b1de3..720a4951e 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2611,7 +2611,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman * standard readline bindings (IOW: bash) do. * Often, Alt- generates ESC-. */ - ic = lineedit_read_key(read_key_buffer, timeout); + ic = lineedit_read_key(read_key_buffer, 50); switch (ic) { //case KEYCODE_LEFT: - bash doesn't do this case 'b': From e835afadfe84a820b698f715a01e777f8b7bf833 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Wed, 17 Dec 2014 17:02:37 +0100 Subject: [PATCH 18/24] nandwrite: fix build when long options are disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Required_argument macro is only defined when long options are enabled. Fixes the following build error: miscutils/nandwrite.c: In function 'nandwrite_main': miscutils/nandwrite.c:120:10: error: expected ',' or ';' before 'Required_argument' Reported-by: Christian Kästner Signed-off-by: Baruch Siach Signed-off-by: Denys Vlasenko --- miscutils/nandwrite.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index 29ff351a3..c825fc315 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c @@ -116,12 +116,13 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv) struct mtd_oob_buf oob; unsigned char *filebuf; const char *opt_s = "0", *opt_f = "-", *opt_l, *opt_bb; - static const char nanddump_longopts[] ALIGN1 = - "bb\0" Required_argument "\xff"; /* no short equivalent */ if (IS_NANDDUMP) { opt_complementary = "=1"; - applet_long_options = nanddump_longopts; +#if ENABLE_LONG_OPTS + applet_long_options = + "bb\0" Required_argument "\xff"; /* no short equivalent */ +#endif opts = getopt32(argv, "os:f:l:", &opt_s, &opt_f, &opt_l, &opt_bb); } else { /* nandwrite */ opt_complementary = "-1:?2"; From ad0d009e0c1968a14f17189264d3aa8008ea2e3b Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 18 Dec 2014 00:27:26 +0200 Subject: [PATCH 19/24] nanddump: don't show --bb in usage when disabled The --bb options now depends on LONG_OPTS. Omit mentions of --bb from usage text when LONG_OPTS is disabled. Signed-off-by: Baruch Siach Signed-off-by: Denys Vlasenko --- miscutils/nandwrite.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index c825fc315..247fc72f4 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c @@ -36,16 +36,18 @@ //usage: "\n -s ADDR Start address" //usage:#define nanddump_trivial_usage -//usage: "[-o] [--bb=padbad|skipbad] [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE" +//usage: "[-o]" IF_LONG_OPTS(" [--bb=padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE" //usage:#define nanddump_full_usage "\n\n" //usage: "Dump MTD_DEVICE\n" //usage: "\n -o Dump oob data" //usage: "\n -s ADDR Start address" //usage: "\n -l LEN Length" //usage: "\n -f FILE Dump to file ('-' for stdout)" +//usage: IF_LONG_OPTS( //usage: "\n --bb=METHOD:" //usage: "\n skipbad: skip bad blocks" //usage: "\n padbad: substitute bad blocks by 0xff (default)" +//usage: ) #include "libbb.h" #include From 28634924f0950f1938ea74a7808d412dc1063fd0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 21 Dec 2014 16:10:22 +0100 Subject: [PATCH 20/24] udhcpc: account for script run time Based on the following user report: I ran into an issue where I was seeing a long delay in the scripts called in udhcp_run_script. I was using an old version of OpenWrt (kamikaze) and a satellite modem. An NTP script was being called and the modem would sometimes take a long time to respond to the DNS lookup when it was offline. This delay started affecting my lease time. The lease that I would get from my satellite modem before it was online would be short: only 60 seconds. The delay with NTP and the modem would typically be about 18 seconds. This would cause the first DHCP renew request from dhcpc to be a little late. Under certain circumstances, I could even see the first DHCP renew to occur after the lease had expired! function old new delta udhcpc_main 2816 2837 +21 Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 35e7c2070..a34829c3a 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1697,6 +1697,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) case RENEW_REQUESTED: case REBINDING: if (*message == DHCPACK) { + unsigned start; uint32_t lease_seconds; struct in_addr temp_addr; uint8_t *temp; @@ -1756,7 +1757,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) bb_info_msg("Lease of %s obtained, lease time %u", inet_ntoa(temp_addr), (unsigned)lease_seconds); requested_ip = packet.yiaddr; + + start = monotonic_sec(); udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); + already_waited_sec = (unsigned)monotonic_sec() - start; state = BOUND; change_listen_mode(LISTEN_NONE); @@ -1774,7 +1778,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) #endif /* make future renew packets use different xid */ /* xid = random_xid(); ...but why bother? */ - already_waited_sec = 0; + continue; /* back to main loop */ } if (*message == DHCPNAK) { From a6588fa10230e7b87990482773a445701abbaae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20K=C3=BCmmel?= Date: Mon, 22 Dec 2014 01:55:54 +0100 Subject: [PATCH 21/24] Make it possible to override LOGIN_FAIL_DELAY in CONFIG_EXTRA_CFLAGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Kümmel Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/libbb.h b/include/libbb.h index 8e8b9ca0e..68a7cf002 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1271,7 +1271,9 @@ char *bb_simplify_path(const char *path) FAST_FUNC; /* Returns ptr to NUL */ char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC; +#ifndef LOGIN_FAIL_DELAY #define LOGIN_FAIL_DELAY 3 +#endif extern void bb_do_delay(int seconds) FAST_FUNC; extern void change_identity(const struct passwd *pw) FAST_FUNC; extern void run_shell(const char *shell, int loginshell, const char *command, const char **additional_args) NORETURN FAST_FUNC; From 11775edbfc27d2ad1cd0dff3f7af385f67719866 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Dec 2014 19:37:05 +0100 Subject: [PATCH 22/24] randomconfig fixes Signed-off-by: Denys Vlasenko --- archival/tar.c | 8 +++----- libbb/Kbuild.src | 1 + testsuite/find.tests | 3 ++- testsuite/mdev.tests | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/archival/tar.c b/archival/tar.c index e116bd287..aa03ba990 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -745,11 +745,9 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, #endif return errorFlag; } -#else -int writeTarFile(int tar_fd, int verboseFlag, - int recurseFlags, const llist_t *include, - const llist_t *exclude, const char *gzip); -#endif /* FEATURE_TAR_CREATE */ +#else /* !FEATURE_TAR_CREATE */ +# define writeTarFile(...) 0 +#endif #if ENABLE_FEATURE_TAR_FROM static llist_t *append_file_list_to_list(llist_t *list) diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index f204816c5..7fb687227 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -142,6 +142,7 @@ lib-$(CONFIG_ADDUSER) += update_passwd.o lib-$(CONFIG_DELGROUP) += update_passwd.o lib-$(CONFIG_DELUSER) += update_passwd.o +lib-$(CONFIG_FTPD) += correct_password.o lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o lib-$(CONFIG_CRYPTPW) += pw_encrypt.o diff --git a/testsuite/find.tests b/testsuite/find.tests index f041106c3..78dfa1230 100755 --- a/testsuite/find.tests +++ b/testsuite/find.tests @@ -10,11 +10,12 @@ mkdir -p find.tempdir touch find.tempdir/testfile +optional FEATURE_FIND_TYPE testing "find -type f" \ "cd find.tempdir && find -type f 2>&1" \ "./testfile\n" \ "" "" - +SKIP= optional FEATURE_FIND_EXEC testing "find -exec exitcode 1" \ "cd find.tempdir && find testfile -exec true {} \; 2>&1; echo \$?" \ diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 48d3dcc2c..59873011a 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests @@ -168,7 +168,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH ASH_BUILTIN_ECHO testing "mdev command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ From ca9c4653a95907e32674c2eb5dc3921dc8e6f1a0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Dec 2014 01:46:29 +0100 Subject: [PATCH 23/24] libbb: add sanity check in bb_arg_max() Signed-off-by: Denys Vlasenko --- libbb/sysconf.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libbb/sysconf.c b/libbb/sysconf.c index cfad9cdc0..8c1caef5c 100644 --- a/libbb/sysconf.c +++ b/libbb/sysconf.c @@ -11,7 +11,15 @@ #if !defined(bb_arg_max) unsigned FAST_FUNC bb_arg_max(void) { - return sysconf(_SC_ARG_MAX); + long r = sysconf(_SC_ARG_MAX); + + /* I've seen a version of uclibc which returned -1. + * Guard about it, and also avoid insanely large values + */ + if ((unsigned long)r > 64*1024*1024) + r = 64*1024*1024; + + return r; } #endif From 6968e081230fb6434a2a6f0eed39d538ea982f3f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Dec 2014 01:23:34 +0100 Subject: [PATCH 24/24] Bump version to 1.23.0 Signed-off-by: Denys Vlasenko --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 778a02ff8..b487f0457 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 PATCHLEVEL = 23 SUBLEVEL = 0 -EXTRAVERSION = .git +EXTRAVERSION = NAME = Unnamed # *DOCUMENTATION*