xref: /haiku/src/bin/package/command_recompress.cpp (revision a629567a9001547736cfe892cdf992be16868fed)
1 /*
2  * Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <getopt.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 
15 #include <package/hpkg/HPKGDefs.h>
16 #include <package/hpkg/PackageReader.h>
17 #include <package/hpkg/PackageWriter.h>
18 
19 #include "package.h"
20 #include "PackageWriterListener.h"
21 
22 
23 using BPackageKit::BHPKG::BPackageReader;
24 using BPackageKit::BHPKG::BPackageWriter;
25 using BPackageKit::BHPKG::BPackageWriterListener;
26 using BPackageKit::BHPKG::BPackageWriterParameters;
27 
28 
29 int
30 command_recompress(int argc, const char* const* argv)
31 {
32 	bool quiet = false;
33 	bool verbose = false;
34 	int32 compressionLevel = BPackageKit::BHPKG::B_HPKG_COMPRESSION_LEVEL_BEST;
35 
36 	while (true) {
37 		static struct option sLongOptions[] = {
38 			{ "help", no_argument, 0, 'h' },
39 			{ "quiet", no_argument, 0, 'q' },
40 			{ "verbose", no_argument, 0, 'v' },
41 			{ 0, 0, 0, 0 }
42 		};
43 
44 		opterr = 0; // don't print errors
45 		int c = getopt_long(argc, (char**)argv, "+0123456789:hqv",
46 			sLongOptions, NULL);
47 		if (c == -1)
48 			break;
49 
50 		switch (c) {
51 			case '0':
52 			case '1':
53 			case '2':
54 			case '3':
55 			case '4':
56 			case '5':
57 			case '6':
58 			case '7':
59 			case '8':
60 			case '9':
61 				compressionLevel = c - '0';
62 				break;
63 
64 			case 'h':
65 				print_usage_and_exit(false);
66 				break;
67 
68 			case 'q':
69 				quiet = true;
70 				break;
71 
72 			case 'v':
73 				verbose = true;
74 				break;
75 
76 			default:
77 				print_usage_and_exit(true);
78 				break;
79 		}
80 	}
81 
82 	// The remaining arguments are the input package file and optionally the
83 	// output package file, i.e. one or two more arguments.
84 	if (argc - optind < 1 || argc - optind > 2)
85 		print_usage_and_exit(true);
86 
87 	const char* inputPackageFileName = argv[optind++];
88 	const char* outputPackageFileName = optind < argc ? argv[optind++] : NULL;
89 
90 	// If compression is used, an output file is required.
91 	if (compressionLevel != 0 && outputPackageFileName == NULL) {
92 		fprintf(stderr, "Error: Writing to stdout is supported only with "
93 			"compression level 0.\n");
94 		return 1;
95 	}
96 
97 	// TODO: Implement streaming support!
98 	if (outputPackageFileName == NULL) {
99 		fprintf(stderr, "Error: Writing to stdout is not supported yet.\n");
100 		return 1;
101 	}
102 
103 	// open the input package
104 	PackageWriterListener listener(verbose, quiet);
105 
106 	BPackageReader packageReader(&listener);
107 	status_t error = packageReader.Init(inputPackageFileName);
108 	if (error != B_OK)
109 		return 1;
110 
111 	// write the output package
112 	BPackageWriterParameters writerParameters;
113 	writerParameters.SetCompressionLevel(compressionLevel);
114 
115 	BPackageWriter packageWriter(&listener);
116 	error = packageWriter.Init(outputPackageFileName, &writerParameters);
117 	if (error != B_OK)
118 		return 1;
119 
120 	error = packageWriter.Recompress(&packageReader);
121 	if (error != B_OK)
122 		return 1;
123 
124 	if (verbose)
125 		printf("\nsuccessfully wrote package '%s'\n", outputPackageFileName);
126 
127 	return 0;
128 }
129