/*
* Copyright (C) 2023 Patrick McDermott
*
* This file is part of opkg-opk.
*
* opkg-opk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* opkg-opk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with opkg-opk. If not, see .
*/
#include "config.h"
#ifdef ENABLE_NLS
#include
#endif
#include
#include
#include "defs.h"
#include "i18n.h"
#include "opk.h"
#include "ustar.h"
#ifdef HAVE_GETOPT_LONG
#include
#else
#include
#endif
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)
{
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 "
".\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[])
{
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;
}
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;
}
/* Initialize outer archive. */
opk = opkg_opk_opk_init(argv[0]);
if (opk == NULL) {
goto error0;
}
/* Read control file. */
if (control_files != NULL) {
if (opkg_opk_opk_read_control(opk, control_files) !=
OPKG_OPK_OK) {
goto error1;
}
}
/* 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);
}
return EXIT_FAILURE;
}