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