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 #include "StandardErrorOutput.h" 26 27 28 using BPackageKit::BHPKG::BPackageWriterListener; 29 using BPackageKit::BHPKG::BPackageWriter; 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 42 while (true) { 43 static struct option sLongOptions[] = { 44 { "help", no_argument, 0, 'h' }, 45 { "quiet", no_argument, 0, 'q' }, 46 { "verbose", no_argument, 0, 'v' }, 47 { 0, 0, 0, 0 } 48 }; 49 50 opterr = 0; // don't print errors 51 int c = getopt_long(argc, (char**)argv, "+bC:hi:I:qv", sLongOptions, 52 NULL); 53 if (c == -1) 54 break; 55 56 switch (c) { 57 case 'b': 58 isBuildPackage = true; 59 break; 60 61 case 'C': 62 changeToDirectory = optarg; 63 break; 64 65 case 'h': 66 print_usage_and_exit(false); 67 break; 68 69 case 'i': 70 packageInfoFileName = optarg; 71 break; 72 73 case 'I': 74 installPath = optarg; 75 break; 76 77 case 'q': 78 quiet = true; 79 break; 80 81 case 'v': 82 verbose = true; 83 break; 84 85 default: 86 print_usage_and_exit(true); 87 break; 88 } 89 } 90 91 // The remaining arguments is the package file, i.e. one more argument. 92 if (optind + 1 != argc) 93 print_usage_and_exit(true); 94 95 const char* packageFileName = argv[optind++]; 96 97 // -I is only allowed when -b is given 98 if (installPath != NULL && !isBuildPackage) { 99 fprintf(stderr, "Error: \"-I\" is only allowed when \"-b\" is " 100 "given.\n"); 101 return 1; 102 } 103 104 // create package 105 PackageWriterListener listener(verbose, quiet); 106 BPackageWriter packageWriter(&listener); 107 status_t result = packageWriter.Init(packageFileName); 108 if (result != B_OK) 109 return 1; 110 111 // If a package info file has been specified explicitly, open it. 112 int packageInfoFD = -1; 113 if (packageInfoFileName != NULL) { 114 packageInfoFD = open(packageInfoFileName, O_RDONLY); 115 if (packageInfoFD < 0) { 116 fprintf(stderr, "Error: Failed to open package info file \"%s\": " 117 "%s\n", packageInfoFileName, strerror(errno)); 118 return 1; 119 } 120 } 121 122 // change directory, if requested 123 if (changeToDirectory != NULL) { 124 if (chdir(changeToDirectory) != 0) { 125 listener.PrintError( 126 "Error: Failed to change the current working directory to " 127 "\"%s\": %s\n", changeToDirectory, strerror(errno)); 128 return 1; 129 } 130 } 131 132 if (isBuildPackage) 133 packageWriter.SetCheckLicenses(false); 134 135 // set install path, if specified 136 if (installPath != NULL) { 137 result = packageWriter.SetInstallPath(installPath); 138 if (result != B_OK) { 139 fprintf(stderr, "Error: Failed to set the package install path: " 140 "%s\n", strerror(result)); 141 return 1; 142 } 143 } 144 145 // add all files of the current directory, save for the .PackageInfo 146 if (!isBuildPackage) { 147 if (add_current_directory_entries(packageWriter, listener, true) 148 != B_OK) { 149 return 1; 150 } 151 } 152 153 // add the .PackageInfo 154 result = packageWriter.AddEntry(B_HPKG_PACKAGE_INFO_FILE_NAME, 155 packageInfoFD); 156 if (result != B_OK) 157 return 1; 158 159 // write the package 160 result = packageWriter.Finish(); 161 if (result != B_OK) 162 return 1; 163 164 if (verbose) 165 printf("\nsuccessfully created package '%s'\n", packageFileName); 166 167 return 0; 168 } 169