1 /* 2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <getopt.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 16 #include <Entry.h> 17 18 #include <package/PackageInfo.h> 19 #include <package/hpkg/HPKGDefs.h> 20 #include <package/hpkg/PackageWriter.h> 21 22 #include "package.h" 23 #include "PackageWriterListener.h" 24 #include "PackageWritingUtils.h" 25 26 27 using BPackageKit::BHPKG::BPackageWriter; 28 using BPackageKit::BHPKG::BPackageWriterListener; 29 using BPackageKit::BHPKG::BPackageWriterParameters; 30 31 32 int 33 command_create(int argc, const char* const* argv) 34 { 35 const char* changeToDirectory = NULL; 36 const char* packageInfoFileName = NULL; 37 const char* installPath = NULL; 38 bool isBuildPackage = false; 39 bool quiet = false; 40 bool verbose = false; 41 int32 compressionLevel = BPackageKit::BHPKG::B_HPKG_COMPRESSION_LEVEL_BEST; 42 43 while (true) { 44 static struct option sLongOptions[] = { 45 { "help", no_argument, 0, 'h' }, 46 { "quiet", no_argument, 0, 'q' }, 47 { "verbose", no_argument, 0, 'v' }, 48 { 0, 0, 0, 0 } 49 }; 50 51 opterr = 0; // don't print errors 52 int c = getopt_long(argc, (char**)argv, "+b0123456789C:hi:I:qv", 53 sLongOptions, NULL); 54 if (c == -1) 55 break; 56 57 switch (c) { 58 case '0': 59 case '1': 60 case '2': 61 case '3': 62 case '4': 63 case '5': 64 case '6': 65 case '7': 66 case '8': 67 case '9': 68 compressionLevel = c - '0'; 69 break; 70 71 case 'b': 72 isBuildPackage = true; 73 break; 74 75 case 'C': 76 changeToDirectory = optarg; 77 break; 78 79 case 'h': 80 print_usage_and_exit(false); 81 break; 82 83 case 'i': 84 packageInfoFileName = optarg; 85 break; 86 87 case 'I': 88 installPath = optarg; 89 break; 90 91 case 'q': 92 quiet = true; 93 break; 94 95 case 'v': 96 verbose = true; 97 break; 98 99 default: 100 print_usage_and_exit(true); 101 break; 102 } 103 } 104 105 // The remaining arguments is the package file, i.e. one more argument. 106 if (optind + 1 != argc) 107 print_usage_and_exit(true); 108 109 const char* packageFileName = argv[optind++]; 110 111 // -I is only allowed when -b is given 112 if (installPath != NULL && !isBuildPackage) { 113 fprintf(stderr, "Error: \"-I\" is only allowed when \"-b\" is " 114 "given.\n"); 115 return 1; 116 } 117 118 // create package 119 BPackageWriterParameters writerParameters; 120 writerParameters.SetCompressionLevel(compressionLevel); 121 122 PackageWriterListener listener(verbose, quiet); 123 BPackageWriter packageWriter(&listener); 124 status_t result = packageWriter.Init(packageFileName, &writerParameters); 125 if (result != B_OK) 126 return 1; 127 128 // If a package info file has been specified explicitly, open it. 129 int packageInfoFD = -1; 130 if (packageInfoFileName != NULL) { 131 packageInfoFD = open(packageInfoFileName, O_RDONLY); 132 if (packageInfoFD < 0) { 133 fprintf(stderr, "Error: Failed to open package info file \"%s\": " 134 "%s\n", packageInfoFileName, strerror(errno)); 135 return 1; 136 } 137 } 138 139 // change directory, if requested 140 if (changeToDirectory != NULL) { 141 if (chdir(changeToDirectory) != 0) { 142 listener.PrintError( 143 "Error: Failed to change the current working directory to " 144 "\"%s\": %s\n", changeToDirectory, strerror(errno)); 145 return 1; 146 } 147 } 148 149 if (isBuildPackage) 150 packageWriter.SetCheckLicenses(false); 151 152 // set install path, if specified 153 if (installPath != NULL) { 154 result = packageWriter.SetInstallPath(installPath); 155 if (result != B_OK) { 156 fprintf(stderr, "Error: Failed to set the package install path: " 157 "%s\n", strerror(result)); 158 return 1; 159 } 160 } 161 162 // add all files of the current directory, save for the .PackageInfo 163 if (!isBuildPackage) { 164 if (add_current_directory_entries(packageWriter, listener, true) 165 != B_OK) { 166 return 1; 167 } 168 } 169 170 // add the .PackageInfo 171 result = packageWriter.AddEntry( 172 BPackageKit::BHPKG::B_HPKG_PACKAGE_INFO_FILE_NAME, packageInfoFD); 173 if (result != B_OK) 174 return 1; 175 176 // write the package 177 result = packageWriter.Finish(); 178 if (result != B_OK) 179 return 1; 180 181 if (verbose) 182 printf("\nsuccessfully created package '%s'\n", packageFileName); 183 184 return 0; 185 } 186