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* 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 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 49 while (true) { 50 static struct option sLongOptions[] = { 51 { "help", no_argument, 0, 'h' }, 52 { "quiet", no_argument, 0, 'q' }, 53 { "verbose", no_argument, 0, 'v' }, 54 { 0, 0, 0, 0 } 55 }; 56 57 opterr = 0; // don't print errors 58 int c = getopt_long(argc, (char**)argv, "+0123456789:hqv", 59 sLongOptions, NULL); 60 if (c == -1) 61 break; 62 63 switch (c) { 64 case '0': 65 case '1': 66 case '2': 67 case '3': 68 case '4': 69 case '5': 70 case '6': 71 case '7': 72 case '8': 73 case '9': 74 compressionLevel = c - '0'; 75 break; 76 77 case 'h': 78 print_usage_and_exit(false); 79 break; 80 81 case 'q': 82 quiet = true; 83 break; 84 85 case 'v': 86 verbose = true; 87 break; 88 89 default: 90 print_usage_and_exit(true); 91 break; 92 } 93 } 94 95 // The remaining arguments are the input package file and the output 96 // package file, i.e. two more arguments. 97 if (argc - optind != 2) 98 print_usage_and_exit(true); 99 100 const char* inputPackageFileName = argv[optind++]; 101 const char* outputPackageFileName = argv[optind++]; 102 103 // open the input package 104 status_t error = B_OK; 105 BPositionIO* inputFile; 106 if (strcmp(inputPackageFileName, "-") == 0) { 107 inputFile = create_stdio(true); 108 } else { 109 BFile* inputFileFile = new BFile; 110 error = inputFileFile->SetTo(inputPackageFileName, O_RDONLY); 111 if (error != B_OK) { 112 fprintf(stderr, "Error: Failed to open input file \"%s\": %s\n", 113 inputPackageFileName, strerror(error)); 114 return 1; 115 } 116 inputFile = inputFileFile; 117 } 118 119 // write the output package 120 BPackageWriterParameters writerParameters; 121 writerParameters.SetCompressionLevel(compressionLevel); 122 if (compressionLevel == 0) { 123 writerParameters.SetCompression( 124 BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE); 125 } 126 127 PackageWriterListener listener(verbose, quiet); 128 BPackageWriter packageWriter(&listener); 129 if (strcmp(outputPackageFileName, "-") == 0) { 130 if (compressionLevel != 0) { 131 fprintf(stderr, "Error: Writing to stdout is supported only with " 132 "compression level 0.\n"); 133 return 1; 134 } 135 136 error = packageWriter.Init(create_stdio(false), true, 137 &writerParameters); 138 } else 139 error = packageWriter.Init(outputPackageFileName, &writerParameters); 140 if (error != B_OK) 141 return 1; 142 143 error = packageWriter.Recompress(inputFile); 144 if (error != B_OK) 145 return 1; 146 147 if (verbose) 148 printf("\nsuccessfully wrote package '%s'\n", outputPackageFileName); 149 150 return 0; 151 } 152