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