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