diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 280 |
1 files changed, 222 insertions, 58 deletions
@@ -19,79 +19,243 @@ #include "config.h" +#ifdef ENABLE_NLS +#include <locale.h> +#endif #include <stdio.h> #include <stdlib.h> #include "defs.h" -#include "gzip.h" +#include "i18n.h" +#include "opk.h" +#include "ustar.h" -FILE *_out_fp; -char _out_buffer[8192]; +#ifdef HAVE_GETOPT_LONG +#include <getopt.h> +#else +#include <unistd.h> +#endif -static int -_write(void *user_data, size_t size) +extern const char *PACKAGE_VERSION_GIT; + +const char *_optstring = "I:fchV"; +#ifdef HAVE_GETOPT_LONG +struct option _longopts[] = { + { + .name = "info", + .has_arg = 1, + .flag = NULL, + .val = 'I', + }, + { + .name = "control", + .has_arg = 0, + .flag = NULL, + .val = 'f', + }, + { + .name = "contents", + .has_arg = 0, + .flag = NULL, + .val = 'c', + }, + { + .name = "help", + .has_arg = 0, + .flag = NULL, + .val = 'h', + }, + { + .name = "version", + .has_arg = 0, + .flag = NULL, + .val = 'V', + }, +}; +#endif + +static void +_help(const char *program_name) { - if (fwrite(_out_buffer, 1, size, _out_fp) == size) { - return OPKG_OPK_OK; - } else { - return OPKG_OPK_ERROR; - } + printf(_("Usage: %s OPTION... PACKAGE\n"), program_name); +#ifdef HAVE_GETOPT_LONG + puts(_("Options:\n" +" -I, --info=CONTROL-FILE Print the named control file. If this option is\n" +" given multiple times, the named control files will " + "be\n" +" printed in the order they appear in the package.\n" +" -f, --control Print the control file.\n" +" -c, --contents List the contents of the filesystem tree archive\n" +" portion of the package. It is currently produced " + "in\n" +" a format similar to that generated by GNU and " + "BusyBox\n" +" tar's verbose listing. User and group IDs and " + "names\n" +" are not checked against those on the host system,\n" +" since they may differ.\n" +" -h, --help Show this help information and exit.\n" +" -V, --version Show version information and exit.")); +#else + puts(_("Options:\n" +" -I Print the named control file. If this option is given multiple times, " + "the\n" +" named control files will be printed in the order they appear in the\n" +" package.\n" +" -f Print the control file.\n" +" -c List the contents of the filesystem tree archive portion of the " + "package.\n" +" It is currently produced in a format similar to that generated by GNU " + "and\n" +" BusyBox tar's verbose listing. User and group IDs and names are not\n" +" checked against those on the host system, since they may differ.\n" +" -h Show this help information and exit.\n" +" -V Show version information and exit.")); +#endif +} + +static void +_version(void) +{ + printf("%s %s%s\n", PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_VERSION_GIT); + /* TRANSLATORS: The "%s" conversion specifications are the copyright + * year(s) and copyright holder(s), respectively. */ + printf(_("Copyright (C) %s %s\n"), "2023", "Patrick McDermott"); + puts(_("License GPLv3+: GNU GPL version 3 or later " + "<http://gnu.org/licenses/gpl.html>.\n" + "This is free software: you are free to change and " + "redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by " + "law.\n")); + printf(_("Please report bugs to <%s>.\n"), PACKAGE_BUGREPORT); +} + +static void +_help_tip(const char *program_name) +{ + /* TRANSLATORS: The "%s" conversion specifications are the program name + * and help option, respectively. */ + fprintf(stderr, _("Try \"%s %s\" for more information\n"), program_name, +#ifdef HAVE_GETOPT_LONG + "--help" +#else + "-h" +#endif + ); } int main(int argc, char *argv[]) { - int ret; - FILE *in_fp; - char in_buffer[512]; - struct opkg_opk_gzip *gzip; - size_t in_size; - - ret = EXIT_SUCCESS; - in_fp = fopen(argv[1], "rb"); - if (in_fp == NULL) { - puts("Error opening input"); - ret = EXIT_FAILURE; - goto out0; + const char *program_name; + struct opkg_opk_ustar_seek_name *control_files; + int list_members; + int opt; + struct opkg_opk_opk *opk; + +#ifdef ENABLE_NLS + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); +#ifdef HAVE_BIND_TEXTDOMAIN_CODESET + bind_textdomain_codeset(PACKAGE, "UTF-8"); +#endif + textdomain(PACKAGE); + setlocale(LC_ALL, ""); +#endif + + program_name = argv[0]; + control_files = NULL; + list_members = 0; + opterr = 0; +#ifdef HAVE_GETOPT_LONG + while ((opt = getopt_long(argc, argv, _optstring, _longopts, NULL)) + != -1) { +#else + while ((opt = getopt(argc, argv, _optstring)) != -1) { +#endif + switch(opt) { + case 'I': + if (opkg_opk_ustar_add_seek_name(&control_files, + optarg) != + OPKG_OPK_OK) { + goto error0; + } + break; + case 'f': + if (opkg_opk_ustar_add_seek_name(&control_files, + "control") != + OPKG_OPK_OK) { + goto error0; + } + break; + case 'c': + list_members = 1; + break; + case 'h': + _help(program_name); + return EXIT_SUCCESS; + case 'V': + _version(); + return EXIT_SUCCESS; + default: + fprintf(stderr, _("%s: Invalid option: " + "\"%c\"\n"), + program_name, optopt); + _help_tip(program_name); + return EXIT_FAILURE; + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { + fprintf(stderr, _("%s: Missing package file operand\n"), + program_name); + _help_tip(program_name); + return EXIT_FAILURE; + } else if (argc > 1) { + fprintf(stderr, _("%s: Too many package file operands\n"), + program_name); + _help_tip(program_name); + return EXIT_FAILURE; } - _out_fp = fopen("out.gz", "wb"); - if (_out_fp == NULL) { - puts("Error opening output"); - ret = EXIT_FAILURE; - goto out1; + if (control_files == NULL && list_members == 0) { + fprintf(stderr, _("%s: At least one of -I, -f, or -c must be " + "given\n"), program_name); + _help_tip(program_name); + return EXIT_FAILURE; } - gzip = opkg_opk_gzip_init_write(_out_buffer, sizeof(_out_buffer), - _write, NULL); - if (gzip == NULL) { - puts("Error initializing compressor"); - ret = EXIT_FAILURE; - goto out2; + + /* Initialize outer archive. */ + opk = opkg_opk_opk_init(argv[0]); + if (opk == NULL) { + goto error0; } - while ((in_size = fread(in_buffer, 1, sizeof(in_buffer), in_fp)) > 0) { - if (feof(in_fp)) { - if (opkg_opk_gzip_write(gzip, in_buffer, in_size, 1) != - OPKG_OPK_END) { - puts("Error finishing compression"); - ret = EXIT_FAILURE; - goto out3; - } - } else { - if (opkg_opk_gzip_write(gzip, in_buffer, in_size, 0) != - OPKG_OPK_OK) { - puts("Error compressing"); - ret = EXIT_FAILURE; - goto out3; - } + + /* Read control file. */ + if (control_files != NULL) { + if (opkg_opk_opk_read_control(opk, control_files) != + OPKG_OPK_OK) { + goto error1; } } - out3: - if (opkg_opk_gzip_free(gzip) != OPKG_OPK_OK) { - puts("Error freeing compressor"); - ret = EXIT_FAILURE; + + /* List data files. */ + if (list_members == 1) { + if (opkg_opk_opk_list_members(opk) != OPKG_OPK_OK) { + goto error1; + } + } + + opkg_opk_opk_free(opk); + if (control_files != NULL) { + opkg_opk_ustar_free_seek_names(control_files); + } + return EXIT_SUCCESS; + + error1: + opkg_opk_opk_free(opk); + error0: + if (control_files != NULL) { + opkg_opk_ustar_free_seek_names(control_files); } - out2: - fclose(_out_fp); - out1: - fclose(in_fp); - out0: - return ret; + return EXIT_FAILURE; } |