From 316ecf214a051121516730f794721f5e7b3036ac Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 27 May 2015 15:23:31 +0100 Subject: Enable seamless compression for WIN32 In the archival code we pretend that WIN32 is a no-MMU platform and use the new mingw_popen_fd routine to pipe data to/from commands to compress/decompress. The pretence is maintained by redefining MMU macros in bb_archive.h. This is mostly used in the archival code but there are a handful of places where it's used to access public interfaces. The symbol BB_ARCHIVE_PUBLIC is defined in these places. With these changes: tar supports seamless compression/decompression rpm2cpio and dpkg-deb can be enabled --- README.md | 1 - archival/cpio.c | 4 ++++ archival/libarchive/init_handle.c | 5 +++++ archival/libarchive/open_transformer.c | 20 ++++++++++++++++++++ archival/rpm2cpio.c | 2 +- archival/tar.c | 31 ++++++++++++++++++++++++++++++- configs/mingw32_defconfig | 18 +++++++++--------- include/bb_archive.h | 10 ++++++++++ libbb/appletlib.c | 1 + miscutils/bbconfig.c | 1 + procps/smemcap.c | 1 + 11 files changed, 82 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d4140487c..90a89521a 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,5 @@ Then just `make`. - Use forward slashes in paths: Windows doesn't mind and the shell will be happier. - Don't do wild things with Windows drive or UNC notation. - - tar doesn't support seamless compression/decompression: use a pipeline to a compressor/decompressor. - Wildcard expansion is disabled by default, though it can be turned on at compile time. This only affects command line arguments to the binary: the BusyBox shell has full support for wildcards. - Handling of users, groups and permissions is totally bogus. The system only admits to knowing about the current user and always returns the same hardcoded uid, gid and permission values. diff --git a/archival/cpio.c b/archival/cpio.c index 454648d68..3cb7fdb35 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -374,6 +374,10 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) argv += optind; if (opt & OPT_FILE) { /* -F */ xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); +#if ENABLE_PLATFORM_MINGW32 + /* default is seek_by_read but seek_by_jump is OK for file */ + archive_handle->seek = seek_by_jump; +#endif } #else opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt); diff --git a/archival/libarchive/init_handle.c b/archival/libarchive/init_handle.c index cbae06ac3..b1166d577 100644 --- a/archival/libarchive/init_handle.c +++ b/archival/libarchive/init_handle.c @@ -16,7 +16,12 @@ archive_handle_t* FAST_FUNC init_handle(void) archive_handle->action_header = header_skip; archive_handle->action_data = data_skip; archive_handle->filter = filter_accept_all; +#if !ENABLE_PLATFORM_MINGW32 archive_handle->seek = seek_by_jump; +#else + /* can't reliably detect pipes on WIN32: default to seek_by_read */ + archive_handle->seek = seek_by_read; +#endif return archive_handle; } diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 1c5c185d0..24524f6ee 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -69,6 +69,7 @@ ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *bu } #if SEAMLESS_COMPRESSION +#if !ENABLE_PLATFORM_MINGW32 void check_errors_in_children(int signo) { int status; @@ -155,6 +156,25 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog) close(fd_pipe.wr); /* don't want to write to the child */ xmove_fd(fd_pipe.rd, fd); } +#else +void FAST_FUNC fork_transformer(int fd, const char *transform_prog) +{ + char *cmd; + int fd1; + + if (find_applet_by_name(transform_prog) >= 0) { + cmd = xasprintf("%s %s -cf -", bb_busybox_exec_path, transform_prog); + } + else { + cmd = xasprintf("%s -cf -", transform_prog); + } + if ( (fd1=mingw_popen_fd(cmd, "r", fd, NULL)) == -1 ) { + bb_perror_msg_and_die("can't execute '%s'", transform_prog); + } + free(cmd); + xmove_fd(fd1, fd); +} +#endif /* Used by e.g. rpm which gives us a fd without filename, * thus we can't guess the format from filename's extension. diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c index 7057570f5..7703629cb 100644 --- a/archival/rpm2cpio.c +++ b/archival/rpm2cpio.c @@ -88,7 +88,7 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) close(rpm_fd); } - if (SEAMLESS_COMPRESSION) { + if (SEAMLESS_COMPRESSION && !ENABLE_PLATFORM_MINGW32) { check_errors_in_children(0); return bb_got_signal; } diff --git a/archival/tar.c b/archival/tar.c index 85551684b..1f9dd23d2 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -617,6 +617,7 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb } #if SEAMLESS_COMPRESSION +#if !ENABLE_PLATFORM_MINGW32 /* Don't inline: vfork scares gcc and pessimizes code */ static void NOINLINE vfork_compressor(int tar_fd, const char *gzip) { @@ -676,6 +677,27 @@ static void NOINLINE vfork_compressor(int tar_fd, const char *gzip) bb_perror_msg_and_die("can't execute '%s'", gzip); } } +#else +static pid_t vfork_compressor(int tar_fd, const char *gzip) +{ + char *cmd; + int fd1; + pid_t pid; + + if (find_applet_by_name(gzip) >= 0) { + cmd = xasprintf("%s %s -cf -", bb_busybox_exec_path, gzip); + } + else { + cmd = xasprintf("%s -cf -", gzip); + } + if ( (fd1=mingw_popen_fd(cmd, "w", tar_fd, &pid)) == -1 ) { + bb_perror_msg_and_die("can't execute '%s'", gzip); + } + free(cmd); + xmove_fd(fd1, tar_fd); + return pid; +} +#endif /* ENABLE_PLATFORM_MINGW32 */ #endif /* SEAMLESS_COMPRESSION */ @@ -691,6 +713,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, { int errorFlag = FALSE; struct TarBallInfo tbInfo; + IF_PLATFORM_MINGW32(pid_t pid = 0;) tbInfo.hlInfoHead = NULL; tbInfo.tarFd = tar_fd; @@ -702,7 +725,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, #if SEAMLESS_COMPRESSION if (gzip) - vfork_compressor(tbInfo.tarFd, gzip); + IF_PLATFORM_MINGW32(pid = )vfork_compressor(tbInfo.tarFd, gzip); #endif tbInfo.excludeList = exclude; @@ -738,7 +761,11 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, #if SEAMLESS_COMPRESSION if (gzip) { int status; +#if !ENABLE_PLATFORM_MINGW32 if (safe_waitpid(-1, &status, 0) == -1) +#else + if (safe_waitpid(pid, &status, 0) == -1) +#endif bb_perror_msg("waitpid"); else if (!WIFEXITED(status) || WEXITSTATUS(status)) /* gzip was killed or has exited with nonzero! */ @@ -1208,10 +1235,12 @@ int tar_main(int argc UNUSED_PARAM, char **argv) if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */) close(tar_handle->src_fd); +#if !ENABLE_PLATFORM_MINGW32 if (SEAMLESS_COMPRESSION || OPT_COMPRESS) { /* Set bb_got_signal to 1 if a child died with !0 exitcode */ check_errors_in_children(0); } +#endif return bb_got_signal; } diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index 6804752f2..71ed1c11c 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Busybox version: 1.24.0.git -# Mon May 18 14:31:53 2015 +# Wed May 27 14:28:56 2015 # CONFIG_HAVE_DOT_CONFIG=y # CONFIG_PLATFORM_POSIX is not set @@ -133,11 +133,11 @@ CONFIG_IOCTL_HEX2STR_ERROR=y # # Archival Utilities # -# CONFIG_FEATURE_SEAMLESS_XZ is not set -# CONFIG_FEATURE_SEAMLESS_LZMA is not set -# CONFIG_FEATURE_SEAMLESS_BZ2 is not set -# CONFIG_FEATURE_SEAMLESS_GZ is not set -# CONFIG_FEATURE_SEAMLESS_Z is not set +CONFIG_FEATURE_SEAMLESS_XZ=y +CONFIG_FEATURE_SEAMLESS_LZMA=y +CONFIG_FEATURE_SEAMLESS_BZ2=y +CONFIG_FEATURE_SEAMLESS_GZ=y +CONFIG_FEATURE_SEAMLESS_Z=y CONFIG_AR=y CONFIG_FEATURE_AR_LONG_FILENAMES=y CONFIG_FEATURE_AR_CREATE=y @@ -154,7 +154,7 @@ CONFIG_CPIO=y CONFIG_FEATURE_CPIO_O=y CONFIG_FEATURE_CPIO_P=y # CONFIG_DPKG is not set -# CONFIG_DPKG_DEB is not set +CONFIG_DPKG_DEB=y # CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set CONFIG_GZIP=y CONFIG_FEATURE_GZIP_LONG_OPTIONS=y @@ -162,11 +162,11 @@ CONFIG_GZIP_FAST=2 CONFIG_FEATURE_GZIP_LEVELS=y CONFIG_LZOP=y # CONFIG_LZOP_COMPR_HIGH is not set -# CONFIG_RPM2CPIO is not set +CONFIG_RPM2CPIO=y # CONFIG_RPM is not set CONFIG_TAR=y CONFIG_FEATURE_TAR_CREATE=y -# CONFIG_FEATURE_TAR_AUTODETECT is not set +CONFIG_FEATURE_TAR_AUTODETECT=y CONFIG_FEATURE_TAR_FROM=y CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y # CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set diff --git a/include/bb_archive.h b/include/bb_archive.h index 5d9e24c17..d94169627 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -2,6 +2,16 @@ #ifndef UNARCHIVE_H #define UNARCHIVE_H 1 +#if !defined(BB_ARCHIVE_PUBLIC) && ENABLE_PLATFORM_MINGW32 +/* treat mingw as a non-MMU platform */ +#undef BB_MMU +#undef USE_FOR_NOMMU +#undef USE_FOR_MMU +#define BB_MMU 0 +#define USE_FOR_NOMMU(...) __VA_ARGS__ +#define USE_FOR_MMU(...) +#endif + PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN enum { diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 683d10b20..841494a70 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -62,6 +62,7 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; #if ENABLE_FEATURE_COMPRESS_USAGE static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; +#define BB_ARCHIVE_PUBLIC # include "bb_archive.h" static const char *unpack_usage_messages(void) { diff --git a/miscutils/bbconfig.c b/miscutils/bbconfig.c index e5f4eb379..b252779f5 100644 --- a/miscutils/bbconfig.c +++ b/miscutils/bbconfig.c @@ -10,6 +10,7 @@ #include "libbb.h" #include "bbconfigopts.h" #if ENABLE_FEATURE_COMPRESS_BBCONFIG +#define BB_ARCHIVE_PUBLIC # include "bb_archive.h" # include "bbconfigopts_bz2.h" #endif diff --git a/procps/smemcap.c b/procps/smemcap.c index 9d1126a49..b2b32198f 100644 --- a/procps/smemcap.c +++ b/procps/smemcap.c @@ -20,6 +20,7 @@ //config: a memory usage statistic tool. #include "libbb.h" +#define BB_ARCHIVE_PUBLIC #include "bb_archive.h" struct fileblock { -- cgit v1.2.3-55-g6feb