xref: /haiku/src/bin/package/command_create.cpp (revision 7a74a5df454197933bc6e80a542102362ee98703)
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