From effcd79eb38e3ab125a0eaf64850f52df914e965 Mon Sep 17 00:00:00 2001 From: Patrick McDermott Date: Fri, 28 Apr 2023 19:03:41 -0400 Subject: opk: Absorb seek list management from ustar --- (limited to 'src/opk.c') diff --git a/src/opk.c b/src/opk.c index a6cafce..7bf5870 100644 --- a/src/opk.c +++ b/src/opk.c @@ -28,18 +28,24 @@ #include "opk.h" #include "ustar.h" +struct _opkg_opk_opk_seek_name { + const char *name; + int found; + struct _opkg_opk_opk_seek_name *next; +}; + struct opkg_opk_opk { - struct opkg_opk_ustar_seek_name *print_control; - int list_data; - FILE *file; - char file_buffer[8192]; - struct opkg_opk_gzip *outer_gzip; - struct opkg_opk_ustar *outer_ustar; - char *version_buffer; - size_t version_size; - struct opkg_opk_gzip *inner_gzip; - struct opkg_opk_ustar *inner_ustar; - int previously_printed; + struct _opkg_opk_opk_seek_name *print_control; + int list_data; + FILE *file; + char file_buffer[8192]; + struct opkg_opk_gzip *outer_gzip; + struct opkg_opk_ustar *outer_ustar; + char *version_buffer; + size_t version_size; + struct opkg_opk_gzip *inner_gzip; + struct opkg_opk_ustar *inner_ustar; + int previously_printed; }; struct opkg_opk_opk * @@ -59,10 +65,28 @@ opkg_opk_opk_init(void) return opk; } +static int +_opkg_opk_opk_add_seek_name(struct _opkg_opk_opk_seek_name **names, + const char *name) +{ + struct _opkg_opk_opk_seek_name *seek_name; + + seek_name = malloc(sizeof(*seek_name)); + if (seek_name == NULL) { + return OPKG_OPK_ERROR; + } + seek_name->name = name; + seek_name->found = 0; + seek_name->next = *names; + + *names = seek_name; + return OPKG_OPK_OK; +} + int opkg_opk_opk_print_control(struct opkg_opk_opk *opk, const char *name) { - return opkg_opk_ustar_add_seek_name(&opk->print_control, name); + return _opkg_opk_opk_add_seek_name(&opk->print_control, name); } int @@ -90,25 +114,8 @@ _opkg_opk_opk_file_read(void *user_data, char **buffer, size_t *size) } static int -_opkg_opk_opk_init_inner(struct opkg_opk_opk *opk, const char *member) +_opkg_opk_opk_init_inner(struct opkg_opk_opk *opk) { - int ret; - - /* Finish reading previous inner archive, if any. */ - while ((ret = opkg_opk_ustar_read(opk->outer_ustar, NULL, NULL)) == - OPKG_OPK_OK); - if (ret == OPKG_OPK_ERROR) { - fputs(_("Error: Failed to read archive\n"), stderr); - return OPKG_OPK_ERROR; - } - - /* Find requested inner archive. */ - if (opkg_opk_ustar_seek_one(opk->outer_ustar, member) != OPKG_OPK_OK) { - fprintf(stderr, _("Error: Failed to find \"%s\" in archive\n"), - member); - return OPKG_OPK_ERROR; - } - /* Initialize inner gzip decompressor. */ opk->inner_gzip = opkg_opk_gzip_init_read( (opkg_opk_gzip_read_func *) &opkg_opk_ustar_read, @@ -137,6 +144,61 @@ _opkg_opk_opk_free_inner(struct opkg_opk_opk *opk) } static int +_opkg_opk_opk_seek(struct opkg_opk_ustar *ustar, + struct _opkg_opk_opk_seek_name *names) +{ + struct opkg_opk_ustar_member *member; + int found; + int found_all; + struct _opkg_opk_opk_seek_name *seek_name; + + for (;;) { + /* Get next header record. */ + if (opkg_opk_ustar_list(ustar, &member) != OPKG_OPK_OK) { + return OPKG_OPK_ERROR; /* Error or end (not found) */ + } + + /* Check each requested name. */ + found = 0; + found_all = 1; + for (seek_name = names; seek_name != NULL; + seek_name = seek_name->next) { + if (seek_name->found == 1) { + continue; /* Previously found this member */ + } + if (strcmp(member->name, seek_name->name) == 0) { + if (found == 0) { + seek_name->found = 1; + found = 1; + continue; + } + } + if (member->name[0] == '.' && member->name[1] == '/' && + strcmp(member->name + 2, + seek_name->name) == 0) + { + if (found == 0) { + seek_name->found = 1; + found = 1; + continue; + } + } + found_all = 0; + } + free(member); + if (found == 1) { + if (found_all == 1) { + /* All requested members found */ + return OPKG_OPK_END; + } + return OPKG_OPK_OK; /* Member found, but more remain */ + } + } + + return OPKG_OPK_ERROR; /* Member not found */ +} + +static int _opkg_opk_opk_read_control(struct opkg_opk_opk *opk) { char *buffer; @@ -149,11 +211,11 @@ _opkg_opk_opk_read_control(struct opkg_opk_opk *opk) return OPKG_OPK_OK; } - if (_opkg_opk_opk_init_inner(opk, "control.tar.gz") != OPKG_OPK_OK) { + if (_opkg_opk_opk_init_inner(opk) != OPKG_OPK_OK) { return OPKG_OPK_ERROR; } - while ((ret_seek = opkg_opk_ustar_seek(opk->inner_ustar, + while ((ret_seek = _opkg_opk_opk_seek(opk->inner_ustar, opk->print_control)) != OPKG_OPK_ERROR) { if (opk->previously_printed == 1) { @@ -219,7 +281,7 @@ _opkg_opk_opk_list_members(struct opkg_opk_opk *opk) puts(""); } - if (_opkg_opk_opk_init_inner(opk, "data.tar.gz") != OPKG_OPK_OK) { + if (_opkg_opk_opk_init_inner(opk) != OPKG_OPK_OK) { return OPKG_OPK_ERROR; } @@ -311,7 +373,8 @@ _opkg_opk_opk_list_members(struct opkg_opk_opk *opk) int opkg_opk_opk_read(struct opkg_opk_opk *opk, const char *file_name) { - int ret; + int ret; + struct opkg_opk_ustar_member *member; ret = OPKG_OPK_OK; @@ -342,13 +405,15 @@ opkg_opk_opk_read(struct opkg_opk_opk *opk, const char *file_name) } /* Check package version. */ - if (opkg_opk_ustar_seek_one(opk->outer_ustar, "debian-binary") != - OPKG_OPK_OK) { + if (opkg_opk_ustar_list(opk->outer_ustar, &member) != OPKG_OPK_OK || + strcmp(member->name, "debian-binary") != 0) { + free(member); fputs(_("Error: Failed to find \"debian-binary\" in archive\n"), stderr); ret = OPKG_OPK_ERROR; goto out3; } + free(member); if (opkg_opk_ustar_read(opk->outer_ustar, &opk->version_buffer, &opk->version_size) != OPKG_OPK_OK) { @@ -364,11 +429,29 @@ opkg_opk_opk_read(struct opkg_opk_opk *opk, const char *file_name) goto out3; } - /* Perform the configured read actions. */ + /* Read control archive. */ + if (opkg_opk_ustar_list(opk->outer_ustar, &member) != OPKG_OPK_OK || + strcmp(member->name, "control.tar.gz") != 0) { + free(member); + fputs(_("Error: Failed to find \"control.tar.gz\" in archive\n") + , stderr); + return OPKG_OPK_ERROR; + } + free(member); if (_opkg_opk_opk_read_control(opk) != OPKG_OPK_OK) { ret = OPKG_OPK_ERROR; goto out3; } + + /* Read data archive. */ + if (opkg_opk_ustar_list(opk->outer_ustar, &member) != OPKG_OPK_OK || + strcmp(member->name, "data.tar.gz") != 0) { + free(member); + fputs(_("Error: Failed to find \"data.tar.gz\" in archive\n"), + stderr); + return OPKG_OPK_ERROR; + } + free(member); if (_opkg_opk_opk_list_members(opk) != OPKG_OPK_OK) { ret = OPKG_OPK_ERROR; goto out3; @@ -387,8 +470,12 @@ opkg_opk_opk_read(struct opkg_opk_opk *opk, const char *file_name) void opkg_opk_opk_free(struct opkg_opk_opk *opk) { - if (opk->print_control != NULL) { - opkg_opk_ustar_free_seek_names(opk->print_control); + struct _opkg_opk_opk_seek_name *name; + + while (opk->print_control != NULL) { + name = opk->print_control; + opk->print_control = opk->print_control->next; + free(name); } free(opk); } -- cgit v0.9.1