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') 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); } diff --git a/src/ustar.c b/src/ustar.c index 1bc8261..1a2858b 100644 --- a/src/ustar.c +++ b/src/ustar.c @@ -54,12 +54,6 @@ struct opkg_opk_ustar { char read_record[OPKG_OPK_USTAR_RECORD_SIZE]; }; -struct opkg_opk_ustar_seek_name { - const char *name; - int found; - struct opkg_opk_ustar_seek_name *next; -}; - struct opkg_opk_ustar * opkg_opk_ustar_init(struct opkg_opk_gzip *gzip) { @@ -236,117 +230,6 @@ opkg_opk_ustar_list(struct opkg_opk_ustar *ustar, } int -opkg_opk_ustar_add_seek_name(struct opkg_opk_ustar_seek_name **names, - const char *name) -{ - struct opkg_opk_ustar_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; -} - -void -opkg_opk_ustar_free_seek_names(struct opkg_opk_ustar_seek_name *names) -{ - struct opkg_opk_ustar_seek_name *name; - - while (names != NULL) { - name = names; - names = names->next; - free(name); - } -} - -int -opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, - struct opkg_opk_ustar_seek_name *names) -{ - char name[OPKG_OPK_USTAR_NAME_SIZE]; - int found; - int found_all; - struct opkg_opk_ustar_seek_name *seek_name; - - for (;;) { - /* Get next header record. */ - if (_opkg_opk_ustar_next(ustar) != OPKG_OPK_OK) { - return OPKG_OPK_ERROR; /* Error or end (not found) */ - } - - /* Prepare name (with prefix if any) for check. */ - if (ustar->header.prefix[0] != '\0') { - sprintf(name, "%s/%s", ustar->header.prefix, - ustar->header.name); - } else { - /* Use memcpy() because ustar->header.name may not be - * NUL-terminated. */ - memcpy(name, ustar->header.name, - sizeof(ustar->header.name)); - name[sizeof(ustar->header.name)] = '\0'; - } - - /* 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(name, seek_name->name) == 0) { - if (found == 0) { - seek_name->found = 1; - found = 1; - continue; - } - } - if (name[0] == '.' && name[1] == '/' && - strcmp(name + 2, seek_name->name) == 0) - { - if (found == 0) { - seek_name->found = 1; - found = 1; - continue; - } - } - found_all = 0; - } - 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 */ -} - -int -opkg_opk_ustar_seek_one(struct opkg_opk_ustar *ustar, const char *name) -{ - struct opkg_opk_ustar_seek_name seek_name; - - seek_name.name = name; - seek_name.found = 0; - seek_name.next = NULL; - - if (opkg_opk_ustar_seek(ustar, &seek_name) == OPKG_OPK_END) { - return OPKG_OPK_OK; - } else { - return OPKG_OPK_ERROR; - } -} - -int opkg_opk_ustar_read(struct opkg_opk_ustar *ustar, char **buffer, size_t *size) { if (ustar->data_size_remaining == 0) { diff --git a/src/ustar.h b/src/ustar.h index 220603a..802412a 100644 --- a/src/ustar.h +++ b/src/ustar.h @@ -71,59 +71,6 @@ opkg_opk_ustar_list(struct opkg_opk_ustar *ustar, struct opkg_opk_ustar_member **member); /* - * Adds a name to a list of names to find with opkg_opk_ustar_seek(). List is - * dynamically allocated; free with opkg_opk_ustar_free_seek_names(). - * Parameters: - * - names: Address in which to store address of list. - * - name: Name of member file to find. - * Returns: - * - OPKG_OPK_OK if the name was added to the list. - * - OPKG_OPK_ERROR on memory exhaustion. - */ -int -opkg_opk_ustar_add_seek_name(struct opkg_opk_ustar_seek_name **names, - const char *name); - -/* - * Frees a list of names to find with opkg_opk_ustar_seek(). - * Parameters: - * - names: List of names. - */ -void -opkg_opk_ustar_free_seek_names(struct opkg_opk_ustar_seek_name *names); - -/* - * Advances to a named member file. May be called multiple times until all - * requested members are found. - * Parameters: - * - ustar: Archive structure. - * - names: Name(s) to find. - * Returns: - * - OPKG_OPK_OK if a member matching one of the requested names is found but - * more names remain to be found. - * - OPKG_OPK_END if a member matching one of the requested names is found and - * no more names remain to be found. - * - OPKG_OPK_ERROR if no matching member is found or on decompression error, an - * invalid header, or unsupported file type. - */ -int -opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, - struct opkg_opk_ustar_seek_name *names); - -/* - * Advances to a named member file. - * Parameters: - * - ustar: Archive structure. - * - name: Name to find. - * Returns: - * - OPKG_OPK_OK if a member matching the requested name is found. - * - OPKG_OPK_ERROR if no matching member is found or on decompression error, an - * invalid header, or unsupported file type. - */ -int -opkg_opk_ustar_seek_one(struct opkg_opk_ustar *ustar, const char *name); - -/* * Reads up to a record (512 octets) of member file data at a time. * Parameters: * - ustar: Archive structure. -- cgit v0.9.1