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