michal-grzedzicki / rpms / rpm

Forked from rpms/rpm 5 months ago
Clone
Blob Blame History Raw
From d8a169164cf40fc1cf6448792c1fa991f19bb375 Mon Sep 17 00:00:00 2001
From: Florian Festi <ffesti@redhat.com>
Date: Thu, 22 Apr 2021 14:50:34 +0200
Subject: [PATCH] Add --nocompression option to rpm2archive

Also use popt for the command line handling. As we are using librpm
anyway there is no reason to keep the dependencies low (as with
rpm2cpio).

Resolves: #1530
---
 doc/rpm2archive.8 | 16 ++++++++++---
 rpm2archive.c     | 60 ++++++++++++++++++++++++++++++++++-------------
 2 files changed, 57 insertions(+), 19 deletions(-)

diff --git a/rpm2archive.c b/rpm2archive.c
index d96db006ea..cb39c7a712 100644
--- a/rpm2archive.c
+++ b/rpm2archive.c
@@ -10,6 +10,8 @@
 
 #include <rpm/rpmts.h>
 
+#include <popt.h>
+
 #include <archive.h>
 #include <archive_entry.h>
 #include <unistd.h>
@@ -18,6 +20,16 @@
 
 #define BUFSIZE (128*1024)
 
+int compress = 1;
+
+static struct poptOption optionsTable[] = {
+    { "nocompression", 'n', POPT_ARG_VAL, &compress, 0,
+        N_("create uncompressed tar file"),
+        NULL },
+    POPT_AUTOHELP
+    POPT_TABLEEND
+};
+
 static void fill_archive_entry(struct archive * a, struct archive_entry * entry, rpmfi fi)
 {
     archive_entry_clear(entry);
@@ -60,7 +72,7 @@ static void write_file_content(struct archive * a, char * buf, rpmfi fi)
     }
 }
 
-static int process_package(rpmts ts, char * filename)
+static int process_package(rpmts ts, const char * filename)
 {
     FD_t fdi;
     FD_t gzdi;
@@ -119,9 +131,11 @@ static int process_package(rpmts ts, char * filename)
 
     /* create archive */
     a = archive_write_new();
-    if (archive_write_add_filter_gzip(a) != ARCHIVE_OK) {
-	fprintf(stderr, "Error: Could not create gzip output filter\n");
-	exit(EXIT_FAILURE);
+    if (compress) {
+	if (archive_write_add_filter_gzip(a) != ARCHIVE_OK) {
+	    fprintf(stderr, "%s\n", archive_error_string(a));
+	    exit(EXIT_FAILURE);
+	}
     }
     if (archive_write_set_format_pax_restricted(a) != ARCHIVE_OK) {
 	fprintf(stderr, "Error: Format pax restricted is not supported\n");
@@ -142,7 +156,12 @@ static int process_package(rpmts ts, char * filename)
 	}
 	archive_write_open_fd(a, STDOUT_FILENO);
     } else {
-	char * outname = rstrscat(NULL, filename, ".tgz", NULL);
+	char * outname = rstrscat(NULL, filename, NULL);
+	if (compress) {
+	    outname = rstrscat(&outname, ".tgz", NULL);
+	} else {
+	    outname = rstrscat(&outname, ".tar", NULL);
+	}
 	if (archive_write_open_filename(a, outname) != ARCHIVE_OK) {
 	    fprintf(stderr, "Error: Can't open output file: %s\n", outname);
 	    exit(EXIT_FAILURE);
@@ -203,21 +222,22 @@ static int process_package(rpmts ts, char * filename)
     return rc;
 }
 
-int main(int argc, char *argv[])
+int main(int argc, const char *argv[])
 {
-    int rc = 0, i;
+    int rc = 0;
+    poptContext optCon;
+    const char *fn;
 
     xsetprogname(argv[0]);	/* Portability call -- see system.h */
     rpmReadConfigFiles(NULL, NULL);
 
-    if (argc > 1 && (rstreq(argv[1], "-h") || rstreq(argv[1], "--help"))) {
-	fprintf(stderr, "Usage: %s [file.rpm ...]\n", argv[0]);
+    optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
+    poptSetOtherOptionHelp(optCon, "[OPTIONS]* <FILES>");
+    if (argc < 2 || poptGetNextOpt(optCon) == 0) {
+	poptPrintUsage(optCon, stderr, 0);
 	exit(EXIT_FAILURE);
     }
 
-    if (argc == 1)
-	argv[argc++] = "-";	/* abuse NULL pointer at the end of argv */
-
     rpmts ts = rpmtsCreate();
     rpmVSFlags vsflags = 0;
 
@@ -227,13 +247,21 @@ int main(int argc, char *argv[])
     vsflags |= RPMVSF_NOHDRCHK;
     (void) rpmtsSetVSFlags(ts, vsflags);
 
-    for (i = 1; i < argc; i++) {
+    /* if no file name is given use stdin/stdout */
+    if (!poptPeekArg(optCon)) {
+	rc = process_package(ts, "-");
+	if (rc != 0)
+	    goto exit;
+    }
 
-	rc = process_package(ts, argv[i]);
+    while ((fn = poptGetArg(optCon)) != NULL) {
+	rc = process_package(ts, fn);
 	if (rc != 0)
-	    return rc;
+	    goto exit;
     }
 
+ exit:
+    poptFreeContext(optCon);
     (void) rpmtsFree(ts);
     return rc;
 }