summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c280
1 files changed, 222 insertions, 58 deletions
diff --git a/src/main.c b/src/main.c
index f5a484a..5a20236 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}