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