⛏️ index : haiku.git

/*
 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
 * Distributed under the terms of the MIT License.
 */


#include "package.h"

#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <package/hpkg/HPKGDefs.h>


extern const char* __progname;
const char* kCommandName = __progname;


static const char* kUsage =
	"Usage: %s <command> <command args>\n"
	"Creates, inspects, or extracts a Haiku package.\n"
	"\n"
	"Commands:\n"
	"    add [ <options> ] <package> <entries>...\n"
	"        Adds the specified entries <entries> to package file <package>.\n"
	"\n"
	"        -0 ... -9  - Use compression level 0 ... 9. 0 means no, 9 best\n"
	"                     compression. Defaults to 9.\n"
	"        -C <dir>   - Change to directory <dir> before adding entries.\n"
	"        -f         - Force adding, replacing already existing entries. Without\n"
	"                     this option adding will fail when encountering a\n"
	"                     pre-existing entry (directories will be merged, though).\n"
	"        -i <info>  - Use the package info file <info>. It will be added as\n"
	"                     \".PackageInfo\", overriding a \".PackageInfo\" file,\n"
	"                     existing.\n"
	"        -q         - Be quiet (don't show any output except for errors).\n"
	"        -v         - Be verbose (show more info about created package).\n"
	"\n"
	"    checksum [ <options> ] [ <package> ]\n"
	"        Computes the checksum of package file <package>. If <package> is omitted\n"
	"        or \"-\", the file is read from stdin. This is only supported, if the\n"
	"        package is uncompressed.\n"
	"\n"
	"        -q         - Be quiet (don't show any output except for errors).\n"
	"        -v         - Be verbose (show more info about created package).\n"
	"\n"
	"    create [ <options> ] <package>\n"
	"        Creates package file <package> from contents of current directory.\n"
	"\n"
	"        -0 ... -9  - Use compression level 0 ... 9. 0 means no, 9 best\n"
	"                     compression. Defaults to 9.\n"
	"        -b         - Create an empty build package. Only the .PackageInfo will\n"
	"                     be added.\n"
	"        -C <dir>   - Change to directory <dir> before adding entries.\n"
	"        -i <info>  - Use the package info file <info>. It will be added as\n"
	"                     \".PackageInfo\", overriding a \".PackageInfo\" file,\n"
	"                     existing.\n"
	"        -I <path>  - Set the package's installation path to <path>. This is\n"
	"                     an option only for use in package building. It will cause\n"
	"                     the package .self link to point to <path>, which is useful\n"
	"                     to redirect a \"make install\". Only allowed with -b.\n"
	"        -z <type>  - Specify compression method to use.\n"
	"        -q         - Be quiet (don't show any output except for errors).\n"
	"        -v         - Be verbose (show more info about created package).\n"
	"\n"
	"    dump [ <options> ] <package>\n"
	"        Dumps the TOC section of package file <package>. For debugging only.\n"
	"\n"
	"    extract [ <options> ] <package> [ <entries>... ]\n"
	"        Extracts the contents of package file <package>. If <entries> are\n"
	"        specified, only those entries are extracted (directories recursively).\n"
	"\n"
	"        -C <dir>   - Change to directory <dir> before extracting the contents\n"
	"                     of the archive.\n"
	"        -i <info>  - Extract the .PackageInfo file to <info> instead.\n"
	"\n"
	"    info [ <options> ] <package>\n"
	"        Prints individual meta information of package file <package>.\n"
	"\n"
	"        -f <format>, --format <format>\n"
	"                   - Print the given format string, performing the following\n"
	"                     replacements:\n"
	"                        %%fileName%%     - the package's canonical file name\n"
	"                        %%name%%         - the package name\n"
	"                        %%version%%      - the package version\n"
	"                        %%%%             - %%\n"
	"                        \\n             - new line\n"
	"                        \\t             - tab\n"
	"\n"
	"    list [ <options> ] <package>\n"
	"        Lists the contents of package file <package>.\n"
	"\n"
	"        -a         - Also list the file attributes.\n"
	"        -i         - Only print the meta information, not the files.\n"
	"        -p         - Only print a list of file paths.\n"
	"\n"
	"    recompress [ <options> ] <input package> <output package>\n"
	"        Reads the package file <input package> and writes it to new package\n"
	"        <output package> using the specified compression options. If the\n"
	"        compression level 0 is specified (i.e. no compression), "
		     "<output package>\n"
	"        can be \"-\", in which case the data are written to stdout.\n"
	"        If the input files doesn't use compression <input package>\n"
	"        can be \"-\", in which case the data are read from stdin.\n"
	"\n"
	"        -0 ... -9  - Use compression level 0 ... 9. 0 means no, 9 best\n"
	"                     compression. Defaults to 9.\n"
	"        -z <type>  - Specify compression method to use.\n"
	"        -q         - Be quiet (don't show any output except for errors).\n"
	"        -v         - Be verbose (show more info about created package).\n"
	"\n"
	"Common Options:\n"
	"    -h, --help   - Print this usage info.\n"
;


void
print_usage_and_exit(bool error)
{
    fprintf(error ? stderr : stdout, kUsage, kCommandName);
    exit(error ? 1 : 0);
}


int32
parse_compression_argument(const char* arg)
{
	if (arg == NULL) {
		// Default compression method.
#ifdef ZSTD_DEFAULT
		return BPackageKit::BHPKG::B_HPKG_COMPRESSION_ZSTD;
#else
		return BPackageKit::BHPKG::B_HPKG_COMPRESSION_ZLIB;
#endif
	}

	if (strcmp(arg, "zstd") == 0) {
		return BPackageKit::BHPKG::B_HPKG_COMPRESSION_ZSTD;
	} else if (strcmp(arg, "zlib") == 0) {
		return BPackageKit::BHPKG::B_HPKG_COMPRESSION_ZLIB;
	} else {
		fprintf(stderr, "error: unknown compression method '%s'\n", arg);
		exit(1);
	}
}


int
main(int argc, const char* const* argv)
{
	if (argc < 2)
		print_usage_and_exit(true);

	const char* command = argv[1];
	if (strcmp(command, "add") == 0)
		return command_add(argc - 1, argv + 1);

	if (strcmp(command, "checksum") == 0)
		return command_checksum(argc - 1, argv + 1);

	if (strcmp(command, "create") == 0)
		return command_create(argc - 1, argv + 1);

	if (strcmp(command, "dump") == 0)
		return command_dump(argc - 1, argv + 1);

	if (strcmp(command, "extract") == 0)
		return command_extract(argc - 1, argv + 1);

	if (strcmp(command, "list") == 0)
		return command_list(argc - 1, argv + 1);

	if (strcmp(command, "info") == 0)
		return command_info(argc - 1, argv + 1);

	if (strcmp(command, "recompress") == 0)
		return command_recompress(argc - 1, argv + 1);

	if (strcmp(command, "help") == 0)
		print_usage_and_exit(false);
	else
		print_usage_and_exit(true);

	// never gets here
	return 0;
}