xref: /haiku/src/bin/package/command_create.cpp (revision 1bd38c43184fef526026c8c9d93ded7d1c9ff635)
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 <dirent.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <getopt.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 
17 #include <Entry.h>
18 
19 #include <package/PackageInfo.h>
20 #include <package/hpkg/HPKGDefs.h>
21 #include <package/hpkg/PackageWriter.h>
22 
23 #include "package.h"
24 #include "PackageWriterListener.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 	bool quiet = false;
38 	bool verbose = false;
39 
40 	while (true) {
41 		static struct option sLongOptions[] = {
42 			{ "help", no_argument, 0, 'h' },
43 			{ "quiet", no_argument, 0, 'q' },
44 			{ "verbose", no_argument, 0, 'v' },
45 			{ 0, 0, 0, 0 }
46 		};
47 
48 		opterr = 0; // don't print errors
49 		int c = getopt_long(argc, (char**)argv, "+C:hi:qv", sLongOptions, NULL);
50 		if (c == -1)
51 			break;
52 
53 		switch (c) {
54 			case 'C':
55 				changeToDirectory = optarg;
56 				break;
57 
58 			case 'h':
59 				print_usage_and_exit(false);
60 				break;
61 
62 			case 'i':
63 				packageInfoFileName = optarg;
64 				break;
65 
66 			case 'q':
67 				quiet = true;
68 				break;
69 
70 			case 'v':
71 				verbose = true;
72 				break;
73 
74 			default:
75 				print_usage_and_exit(true);
76 				break;
77 		}
78 	}
79 
80 	// The remaining arguments is the package file, i.e. one more argument.
81 	if (optind + 1 != argc)
82 		print_usage_and_exit(true);
83 
84 	const char* packageFileName = argv[optind++];
85 
86 	// create package
87 	PackageWriterListener listener(verbose, quiet);
88 	BPackageWriter packageWriter(&listener);
89 	status_t result = packageWriter.Init(packageFileName);
90 	if (result != B_OK)
91 		return 1;
92 
93 	// If a package info file has been specified explicitly, open it.
94 	int packageInfoFD = -1;
95 	if (packageInfoFileName != NULL) {
96 		packageInfoFD = open(packageInfoFileName, O_RDONLY);
97 		if (packageInfoFD < 0) {
98 			fprintf(stderr, "Error: Failed to open package info file \"%s\": "
99 				"%s\n", packageInfoFileName, strerror(errno));
100 		}
101 	}
102 
103 	// change directory, if requested
104 	if (changeToDirectory != NULL) {
105 		if (chdir(changeToDirectory) != 0) {
106 			listener.PrintError(
107 				"Error: Failed to change the current working directory to "
108 				"\"%s\": %s\n", changeToDirectory, strerror(errno));
109 		}
110 	}
111 
112 	// add all files of current directory
113 	DIR* dir = opendir(".");
114 	if (dir == NULL) {
115 		listener.PrintError("Error: Failed to opendir '.': %s\n",
116 			strerror(errno));
117 		return 1;
118 	}
119 
120 	while (dirent* entry = readdir(dir)) {
121 		// skip "." and ".."
122 		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
123 			continue;
124 
125 		// also skip the .PackageInfo -- we'll add it later
126 		if (strcmp(entry->d_name, B_HPKG_PACKAGE_INFO_FILE_NAME) == 0)
127 			continue;
128 
129 		result = packageWriter.AddEntry(entry->d_name);
130 		if (result != B_OK)
131 			return 1;
132 	}
133 
134 	closedir(dir);
135 
136 	// add the .PackageInfo
137 	result = packageWriter.AddEntry(B_HPKG_PACKAGE_INFO_FILE_NAME,
138 		packageInfoFD);
139 	if (result != B_OK)
140 		return 1;
141 
142 	// write the package
143 	result = packageWriter.Finish();
144 	if (result != B_OK)
145 		return 1;
146 
147 	if (verbose)
148 		printf("\nsuccessfully created package '%s'\n", packageFileName);
149 
150 	return 0;
151 }
152