ea9a62
From d8a169164cf40fc1cf6448792c1fa991f19bb375 Mon Sep 17 00:00:00 2001
ea9a62
From: Florian Festi <ffesti@redhat.com>
ea9a62
Date: Thu, 22 Apr 2021 14:50:34 +0200
ea9a62
Subject: [PATCH] Add --nocompression option to rpm2archive
ea9a62
ea9a62
Also use popt for the command line handling. As we are using librpm
ea9a62
anyway there is no reason to keep the dependencies low (as with
ea9a62
rpm2cpio).
ea9a62
ea9a62
Resolves: #1530
ea9a62
---
ea9a62
 doc/rpm2archive.8 | 16 ++++++++++---
ea9a62
 rpm2archive.c     | 60 ++++++++++++++++++++++++++++++++++-------------
ea9a62
 2 files changed, 57 insertions(+), 19 deletions(-)
ea9a62
ea9a62
diff --git a/doc/rpm2archive.8 b/doc/rpm2archive.8
ea9a62
index 8bd6d4ed9d..3895d01981 100644
ea9a62
--- a/doc/rpm2archive.8
ea9a62
+++ b/doc/rpm2archive.8
ea9a62
@@ -3,10 +3,10 @@
ea9a62
 .SH NAME
ea9a62
 rpm2archive \- Create tar archive from RPM Package Manager (RPM) package.
ea9a62
 .SH SYNOPSIS
ea9a62
-\fBrpm2archive\fP [filename] 
ea9a62
+\fBrpm2archive\fP \fB{-n|--nocompression}\fR \fB\fIFILES\fB\fR
ea9a62
 .SH DESCRIPTION
ea9a62
-\fBrpm2archive\fP converts the .rpm files specified as arguments to gz
ea9a62
-compressed tar files with suffix ".tgz".
ea9a62
+\fBrpm2archive\fP converts the .rpm files specified as arguments to
ea9a62
+tar files. By default they are gzip compressed and saved with postfix ".tgz".
ea9a62
 
ea9a62
 If '-' is given as argument, an rpm stream is read from standard in and
ea9a62
 written to standard out.
ea9a62
@@ -16,6 +16,16 @@ containing files greater than 4GB which are not supported by cpio. Unless
ea9a62
 \fBrpm2cpio\fP \fBrpm2archive\fP needs a working rpm installation which limits
ea9a62
 its usefulness for some disaster recovery scenarios.
ea9a62
 
ea9a62
+.SH "OPTIONS"
ea9a62
+.TP
ea9a62
+\fB\-n, --nocompression\fR
ea9a62
+Generate uncompressed tar archive and use ".tar" as postfix of the
ea9a62
+file name.
ea9a62
+.PP
ea9a62
+
ea9a62
+.SH EXAMPLES
ea9a62
+.PP
ea9a62
+
ea9a62
 .br
ea9a62
 .I "\fBrpm2archive glint-1.0-1.i386.rpm ; tar -xvz glint-1.0-1.i386.rpm.tgz\fP"
ea9a62
 .br
ea9a62
diff --git a/rpm2archive.c b/rpm2archive.c
ea9a62
index d96db006ea..cb39c7a712 100644
ea9a62
--- a/rpm2archive.c
ea9a62
+++ b/rpm2archive.c
ea9a62
@@ -10,6 +10,8 @@
ea9a62
 
ea9a62
 #include <rpm/rpmts.h>
ea9a62
 
ea9a62
+#include <popt.h>
ea9a62
+
ea9a62
 #include <archive.h>
ea9a62
 #include <archive_entry.h>
ea9a62
 #include <unistd.h>
ea9a62
@@ -18,6 +20,16 @@
ea9a62
 
ea9a62
 #define BUFSIZE (128*1024)
ea9a62
 
ea9a62
+int compress = 1;
ea9a62
+
ea9a62
+static struct poptOption optionsTable[] = {
ea9a62
+    { "nocompression", 'n', POPT_ARG_VAL, &compress, 0,
ea9a62
+        N_("create uncompressed tar file"),
ea9a62
+        NULL },
ea9a62
+    POPT_AUTOHELP
ea9a62
+    POPT_TABLEEND
ea9a62
+};
ea9a62
+
ea9a62
 static void fill_archive_entry(struct archive * a, struct archive_entry * entry, rpmfi fi)
ea9a62
 {
ea9a62
     archive_entry_clear(entry);
ea9a62
@@ -60,7 +72,7 @@ static void write_file_content(struct archive * a, char * buf, rpmfi fi)
ea9a62
     }
ea9a62
 }
ea9a62
 
ea9a62
-static int process_package(rpmts ts, char * filename)
ea9a62
+static int process_package(rpmts ts, const char * filename)
ea9a62
 {
ea9a62
     FD_t fdi;
ea9a62
     FD_t gzdi;
ea9a62
@@ -119,9 +131,11 @@ static int process_package(rpmts ts, char * filename)
ea9a62
 
ea9a62
     /* create archive */
ea9a62
     a = archive_write_new();
ea9a62
-    if (archive_write_add_filter_gzip(a) != ARCHIVE_OK) {
ea9a62
-	fprintf(stderr, "Error: Could not create gzip output filter\n");
ea9a62
-	exit(EXIT_FAILURE);
ea9a62
+    if (compress) {
ea9a62
+	if (archive_write_add_filter_gzip(a) != ARCHIVE_OK) {
ea9a62
+	    fprintf(stderr, "%s\n", archive_error_string(a));
ea9a62
+	    exit(EXIT_FAILURE);
ea9a62
+	}
ea9a62
     }
ea9a62
     if (archive_write_set_format_pax_restricted(a) != ARCHIVE_OK) {
ea9a62
 	fprintf(stderr, "Error: Format pax restricted is not supported\n");
ea9a62
@@ -142,7 +156,12 @@ static int process_package(rpmts ts, char * filename)
ea9a62
 	}
ea9a62
 	archive_write_open_fd(a, STDOUT_FILENO);
ea9a62
     } else {
ea9a62
-	char * outname = rstrscat(NULL, filename, ".tgz", NULL);
ea9a62
+	char * outname = rstrscat(NULL, filename, NULL);
ea9a62
+	if (compress) {
ea9a62
+	    outname = rstrscat(&outname, ".tgz", NULL);
ea9a62
+	} else {
ea9a62
+	    outname = rstrscat(&outname, ".tar", NULL);
ea9a62
+	}
ea9a62
 	if (archive_write_open_filename(a, outname) != ARCHIVE_OK) {
ea9a62
 	    fprintf(stderr, "Error: Can't open output file: %s\n", outname);
ea9a62
 	    exit(EXIT_FAILURE);
ea9a62
@@ -203,21 +222,22 @@ static int process_package(rpmts ts, char * filename)
ea9a62
     return rc;
ea9a62
 }
ea9a62
 
ea9a62
-int main(int argc, char *argv[])
ea9a62
+int main(int argc, const char *argv[])
ea9a62
 {
ea9a62
-    int rc = 0, i;
ea9a62
+    int rc = 0;
ea9a62
+    poptContext optCon;
ea9a62
+    const char *fn;
ea9a62
 
ea9a62
     xsetprogname(argv[0]);	/* Portability call -- see system.h */
ea9a62
     rpmReadConfigFiles(NULL, NULL);
ea9a62
 
ea9a62
-    if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help"))) {
ea9a62
-	fprintf(stderr, "Usage: %s [file.rpm ...]\n", argv[0]);
ea9a62
+    optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
ea9a62
+    poptSetOtherOptionHelp(optCon, "[OPTIONS]* <FILES>");
ea9a62
+    if (argc < 2 || poptGetNextOpt(optCon) == 0) {
ea9a62
+	poptPrintUsage(optCon, stderr, 0);
ea9a62
 	exit(EXIT_FAILURE);
ea9a62
     }
ea9a62
 
ea9a62
-    if (argc == 1)
ea9a62
-	argv[argc++] = "-";	/* abuse NULL pointer at the end of argv */
ea9a62
-
ea9a62
     rpmts ts = rpmtsCreate();
ea9a62
     rpmVSFlags vsflags = 0;
ea9a62
 
ea9a62
@@ -227,13 +247,21 @@ int main(int argc, char *argv[])
ea9a62
     vsflags |= RPMVSF_NOHDRCHK;
ea9a62
     (void) rpmtsSetVSFlags(ts, vsflags);
ea9a62
 
ea9a62
-    for (i = 1; i < argc; i++) {
ea9a62
+    /* if no file name is given use stdin/stdout */
ea9a62
+    if (!poptPeekArg(optCon)) {
ea9a62
+	rc = process_package(ts, "-");
ea9a62
+	if (rc != 0)
ea9a62
+	    goto exit;
ea9a62
+    }
ea9a62
 
ea9a62
-	rc = process_package(ts, argv[i]);
ea9a62
+    while ((fn = poptGetArg(optCon)) != NULL) {
ea9a62
+	rc = process_package(ts, fn);
ea9a62
 	if (rc != 0)
ea9a62
-	    return rc;
ea9a62
+	    goto exit;
ea9a62
     }
ea9a62
 
ea9a62
+ exit:
ea9a62
+    poptFreeContext(optCon);
ea9a62
     (void) rpmtsFree(ts);
ea9a62
     return rc;
ea9a62
 }