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