xref: /haiku/src/bin/package/command_create.cpp (revision 1c09002cbee8e797a0f8bbfc5678dfadd39ee1a7)
1 /*
2  * Copyright 2009, 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 <getopt.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <Entry.h>
16 
17 #include <package/PackageInfo.h>
18 #include <package/hpkg/HPKGDefs.h>
19 #include <package/hpkg/PackageWriter.h>
20 
21 #include "package.h"
22 #include "StandardErrorOutput.h"
23 
24 
25 using BPackageKit::BHPKG::BPackageWriterListener;
26 using BPackageKit::BHPKG::BPackageWriter;
27 
28 
29 class PackageWriterListener	: public BPackageWriterListener {
30 public:
31 	PackageWriterListener(bool verbose, bool quiet)
32 		: fVerbose(verbose), fQuiet(quiet)
33 	{
34 	}
35 
36 	virtual void PrintErrorVarArgs(const char* format, va_list args)
37 	{
38 		vfprintf(stderr, format, args);
39 	}
40 
41 	virtual void OnEntryAdded(const char* path)
42 	{
43 		if (fQuiet || !fVerbose)
44 			return;
45 
46 		printf("\t%s\n", path);
47 	}
48 
49 	virtual void OnTOCSizeInfo(uint64 uncompressedStringsSize,
50 		uint64 uncompressedMainSize, uint64 uncompressedTOCSize)
51 	{
52 		if (fQuiet || !fVerbose)
53 			return;
54 
55 		printf("----- TOC Info -----------------------------------\n");
56 		printf("cached strings size:     %10llu (uncompressed)\n",
57 			uncompressedStringsSize);
58 		printf("TOC main size:           %10llu (uncompressed)\n",
59 			uncompressedMainSize);
60 		printf("total TOC size:          %10llu (uncompressed)\n",
61 			uncompressedTOCSize);
62 	}
63 
64 	virtual void OnPackageAttributesSizeInfo(uint32 stringCount,
65 		uint32 uncompressedSize)
66 	{
67 		if (fQuiet || !fVerbose)
68 			return;
69 
70 		printf("----- Package Attribute Info ---------------------\n");
71 		printf("string count:            %10lu\n", stringCount);
72 		printf("package attributes size: %10lu (uncompressed)\n",
73 			uncompressedSize);
74 	}
75 
76 	virtual void OnPackageSizeInfo(uint32 headerSize, uint64 heapSize,
77 		uint64 tocSize, uint32 packageAttributesSize, uint64 totalSize)
78 	{
79 		if (fQuiet)
80 			return;
81 
82 		printf("----- Package Info ----------------\n");
83 		printf("header size:             %10lu\n", headerSize);
84 		printf("heap size:               %10llu\n", heapSize);
85 		printf("TOC size:                %10llu\n", tocSize);
86 		printf("package attributes size: %10lu\n", packageAttributesSize);
87 		printf("total size:              %10llu\n", totalSize);
88 		printf("-----------------------------------\n");
89 	}
90 
91 private:
92 	bool fVerbose;
93 	bool fQuiet;
94 };
95 
96 
97 int
98 command_create(int argc, const char* const* argv)
99 {
100 	const char* changeToDirectory = NULL;
101 	bool quiet = false;
102 	bool verbose = false;
103 
104 	while (true) {
105 		static struct option sLongOptions[] = {
106 			{ "help", no_argument, 0, 'h' },
107 			{ "quiet", no_argument, 0, 'q' },
108 			{ "verbose", no_argument, 0, 'v' },
109 			{ 0, 0, 0, 0 }
110 		};
111 
112 		opterr = 0; // don't print errors
113 		int c = getopt_long(argc, (char**)argv, "+C:hqv", sLongOptions, NULL);
114 		if (c == -1)
115 			break;
116 
117 		switch (c) {
118 			case 'C':
119 				changeToDirectory = optarg;
120 				break;
121 
122 			case 'h':
123 				print_usage_and_exit(false);
124 				break;
125 
126 			case 'q':
127 				quiet = true;
128 				break;
129 
130 			case 'v':
131 				verbose = true;
132 				break;
133 
134 			default:
135 				print_usage_and_exit(true);
136 				break;
137 		}
138 	}
139 
140 	// The remaining arguments is the package file, i.e. one more argument.
141 	if (optind + 1 != argc)
142 		print_usage_and_exit(true);
143 
144 	const char* packageFileName = argv[optind++];
145 
146 	// create package
147 	PackageWriterListener listener(verbose, quiet);
148 	BPackageWriter packageWriter(&listener);
149 	status_t result = packageWriter.Init(packageFileName);
150 	if (result != B_OK)
151 		return 1;
152 
153 	// change directory, if requested
154 	if (changeToDirectory != NULL) {
155 		if (chdir(changeToDirectory) != 0) {
156 			listener.PrintError(
157 				"Error: Failed to change the current working directory to "
158 				"\"%s\": %s\n", changeToDirectory, strerror(errno));
159 		}
160 	}
161 
162 	// add all files of current directory
163 	DIR* dir = opendir(".");
164 	if (dir == NULL) {
165 		listener.PrintError("Error: Failed to opendir '.': %s\n",
166 			strerror(errno));
167 		return 1;
168 	}
169 	while (dirent* entry = readdir(dir)) {
170 		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
171 			continue;
172 
173 		result = packageWriter.AddEntry(entry->d_name);
174 		if (result != B_OK)
175 			return 1;
176 	}
177 	closedir(dir);
178 
179 	// write the package
180 	result = packageWriter.Finish();
181 	if (result != B_OK)
182 		return 1;
183 
184 	if (verbose)
185 		printf("\nsuccessfully created package '%s'\n", packageFileName);
186 
187 	return 0;
188 }
189