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 if (compressionLevel == 0) { 122 writerParameters.SetCompression( 123 BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE); 124 } 125 126 PackageWriterListener listener(verbose, quiet); 127 BPackageWriter packageWriter(&listener); 128 status_t result = packageWriter.Init(packageFileName, &writerParameters); 129 if (result != B_OK) 130 return 1; 131 132 // If a package info file has been specified explicitly, open it. 133 int packageInfoFD = -1; 134 if (packageInfoFileName != NULL) { 135 packageInfoFD = open(packageInfoFileName, O_RDONLY); 136 if (packageInfoFD < 0) { 137 fprintf(stderr, "Error: Failed to open package info file \"%s\": " 138 "%s\n", packageInfoFileName, strerror(errno)); 139 return 1; 140 } 141 } 142 143 // change directory, if requested 144 if (changeToDirectory != NULL) { 145 if (chdir(changeToDirectory) != 0) { 146 listener.PrintError( 147 "Error: Failed to change the current working directory to " 148 "\"%s\": %s\n", changeToDirectory, strerror(errno)); 149 return 1; 150 } 151 } 152 153 if (isBuildPackage) 154 packageWriter.SetCheckLicenses(false); 155 156 // set install path, if specified 157 if (installPath != NULL) { 158 result = packageWriter.SetInstallPath(installPath); 159 if (result != B_OK) { 160 fprintf(stderr, "Error: Failed to set the package install path: " 161 "%s\n", strerror(result)); 162 return 1; 163 } 164 } 165 166 // add all files of the current directory, save for the .PackageInfo 167 if (!isBuildPackage) { 168 if (add_current_directory_entries(packageWriter, listener, true) 169 != B_OK) { 170 return 1; 171 } 172 } 173 174 // add the .PackageInfo 175 result = packageWriter.AddEntry( 176 BPackageKit::BHPKG::B_HPKG_PACKAGE_INFO_FILE_NAME, packageInfoFD); 177 if (result != B_OK) 178 return 1; 179 180 // write the package 181 result = packageWriter.Finish(); 182 if (result != B_OK) 183 return 1; 184 185 if (verbose) 186 printf("\nsuccessfully created package '%s'\n", packageFileName); 187 188 return 0; 189 } 190