rpm2cpio: handle LZMA compressed rpms. closes 10166
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 10 Aug 2017 08:35:08 +0000 (10:35 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 10 Aug 2017 08:36:37 +0000 (10:36 +0200)
function                                             old     new   delta
rpm2cpio_main                                         78     120     +42
setup_lzma_on_fd                                       -      29     +29
fork_transformer_and_free                              -      28     +28
...
setup_unzip_on_fd                                     56      32     -24
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 3/5 up/down: 104/-67)            Total: 37 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
archival/libarchive/open_transformer.c
archival/rpm.c
include/libbb.h

index ac7e5db95f5aa7db9184b6400d50477141be8aa1..290dd130f9f896ac3dff73efdbd4201996dd33df 100644 (file)
@@ -225,18 +225,8 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
        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)
+static void fork_transformer_and_free(transformer_state_t *xstate)
 {
-       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
@@ -249,8 +239,34 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed)
        fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
 # endif
        free(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->xformer) {
+               free(xstate);
+               return 1;
+       }
+
+       fork_transformer_and_free(xstate);
        return 0;
 }
+#if ENABLE_FEATURE_SEAMLESS_LZMA
+/* ...and custom version for LZMA */
+void FAST_FUNC setup_lzma_on_fd(int fd)
+{
+       transformer_state_t *xstate = xzalloc(sizeof(*xstate));
+       xstate->src_fd = fd;
+       xstate->xformer = unpack_lzma_stream;
+       USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";)
+       fork_transformer_and_free(xstate);
+}
+#endif
 
 static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed)
 {
index f46d88b9220b548a6649751708ffe1d5ba4917c9..cca17da33a17f97c32e9ef5b04fbbf3a3903bbc7 100644 (file)
@@ -56,6 +56,8 @@
 #define TAG_DIRINDEXES          1116
 #define TAG_BASENAMES           1117
 #define TAG_DIRNAMES            1118
+#define TAG_PAYLOADCOMPRESSOR   1125
+
 
 #define RPMFILE_CONFIG          (1 << 0)
 #define RPMFILE_DOC             (1 << 1)
@@ -510,6 +512,7 @@ int rpm_main(int argc, char **argv)
 int rpm2cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
 {
+       const char *str;
        int rpm_fd;
 
        G.pagesize = getpagesize();
@@ -520,11 +523,17 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
        //      /* We need to know whether child (gzip/bzip/etc) exits abnormally */
        //      signal(SIGCHLD, check_errors_in_children);
 
-//TODO: look for rpm tag RPMTAG_PAYLOADCOMPRESSOR (dec 1125, hex 0x465),
-// if the value is "lzma", set up decompressor without detection
-// (lzma can't be detected).
+       if (ENABLE_FEATURE_SEAMLESS_LZMA
+        && (str = rpm_getstr0(TAG_PAYLOADCOMPRESSOR)) != NULL
+        && strcmp(str, "lzma") == 0
+       ) {
+               // lzma compression can't be detected
+               // set up decompressor without detection
+               setup_lzma_on_fd(rpm_fd);
+       } else {
+               setup_unzip_on_fd(rpm_fd, /*fail_if_not_compressed:*/ 1);
+       }
 
-       setup_unzip_on_fd(rpm_fd, /*fail_if_not_compressed:*/ 1);
        if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0)
                bb_error_msg_and_die("error unpacking");
 
index 2eb1fef33a4975d10850f1306d90e8b42eb6fb28..86ad0a057ce35716ff6bab412a3d485a513d7874 100644 (file)
@@ -863,7 +863,7 @@ unsigned bb_clk_tck(void) FAST_FUNC;
 
 #if SEAMLESS_COMPRESSION
 /* Autodetects gzip/bzip2 formats. fd may be in the middle of the file! */
-extern int setup_unzip_on_fd(int fd, int fail_if_not_compressed) FAST_FUNC;
+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;
@@ -872,6 +872,8 @@ extern void *xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
 # 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
+/* lzma has no signature, need a little helper. NB: exist only for ENABLE_FEATURE_SEAMLESS_LZMA=y */
+void setup_lzma_on_fd(int fd) FAST_FUNC;
 
 extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC;
 // NB: will return short write on error, not -1,