xref: /haiku/src/bin/package/command_recompress.cpp (revision 3cc6297e22bc7d945612e50906c78326119b2e62)
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 <FdIO.h>
20 #include <DataPositionIOWrapper.h>
21 
22 #include "package.h"
23 #include "PackageWriterListener.h"
24 
25 
26 using BPackageKit::BHPKG::BPackageReader;
27 using BPackageKit::BHPKG::BPackageWriter;
28 using BPackageKit::BHPKG::BPackageWriterListener;
29 using BPackageKit::BHPKG::BPackageWriterParameters;
30 
31 
32 static BPositionIO*
33 create_stdio(bool isInput)
34 {
35 	BFdIO* dataIO = new BFdIO(isInput ? 0 : 1, false);
36 	return new BDataPositionIOWrapper(dataIO);
37 }
38 
39 
40 int
41 command_recompress(int argc, const char* const* argv)
42 {
43 	bool quiet = false;
44 	bool verbose = false;
45 	int32 compressionLevel = BPackageKit::BHPKG::B_HPKG_COMPRESSION_LEVEL_BEST;
46 
47 	while (true) {
48 		static struct option sLongOptions[] = {
49 			{ "help", no_argument, 0, 'h' },
50 			{ "quiet", no_argument, 0, 'q' },
51 			{ "verbose", no_argument, 0, 'v' },
52 			{ 0, 0, 0, 0 }
53 		};
54 
55 		opterr = 0; // don't print errors
56 		int c = getopt_long(argc, (char**)argv, "+0123456789:hqv",
57 			sLongOptions, NULL);
58 		if (c == -1)
59 			break;
60 
61 		switch (c) {
62 			case '0':
63 			case '1':
64 			case '2':
65 			case '3':
66 			case '4':
67 			case '5':
68 			case '6':
69 			case '7':
70 			case '8':
71 			case '9':
72 				compressionLevel = c - '0';
73 				break;
74 
75 			case 'h':
76 				print_usage_and_exit(false);
77 				break;
78 
79 			case 'q':
80 				quiet = true;
81 				break;
82 
83 			case 'v':
84 				verbose = true;
85 				break;
86 
87 			default:
88 				print_usage_and_exit(true);
89 				break;
90 		}
91 	}
92 
93 	// The remaining arguments are the input package file and the output
94 	// package file, i.e. two more arguments.
95 	if (argc - optind != 2)
96 		print_usage_and_exit(true);
97 
98 	const char* inputPackageFileName = argv[optind++];
99 	const char* outputPackageFileName = argv[optind++];
100 
101 	// open the input package
102 	PackageWriterListener listener(verbose, quiet);
103 
104 	BPackageReader packageReader(&listener);
105 	status_t error;
106 	if (strcmp(inputPackageFileName, "-") == 0)
107 		error = packageReader.Init(create_stdio(true), true);
108 	else
109 		error = packageReader.Init(inputPackageFileName);
110 	if (error != B_OK)
111 		return 1;
112 
113 	// write the output package
114 	BPackageWriterParameters writerParameters;
115 	writerParameters.SetCompressionLevel(compressionLevel);
116 	if (compressionLevel == 0) {
117 		writerParameters.SetCompression(
118 			BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE);
119 	}
120 
121 	BPackageWriter packageWriter(&listener);
122 	if (strcmp(outputPackageFileName, "-") == 0) {
123 		if (compressionLevel != 0) {
124 			fprintf(stderr, "Error: Writing to stdout is supported only with "
125 				"compression level 0.\n");
126 			return 1;
127 		}
128 
129 		error = packageWriter.Init(create_stdio(false), true,
130 			&writerParameters);
131 	} else
132 		error = packageWriter.Init(outputPackageFileName, &writerParameters);
133 	if (error != B_OK)
134 		return 1;
135 
136 	error = packageWriter.Recompress(&packageReader);
137 	if (error != B_OK)
138 		return 1;
139 
140 	if (verbose)
141 		printf("\nsuccessfully wrote package '%s'\n", outputPackageFileName);
142 
143 	return 0;
144 }
145