diff options
author | Patrick McDermott <patrick.mcdermott@libiquity.com> | 2023-04-18 13:16:29 (EDT) |
---|---|---|
committer | Patrick McDermott <patrick.mcdermott@libiquity.com> | 2023-04-18 13:16:29 (EDT) |
commit | 507c5f7001a1da8a22ade991c885b89cafd76696 (patch) | |
tree | a94e5f6f3a1559cd935be02d26591b23e57e9cfd | |
parent | 62e056a12300a276ec99a99f9061bef5fa35fe9e (diff) |
main: Split outer and inner archive initialization
Thus, we can both read the control file and list data files in one pass
through the outer archive. Unlike dpkg-deb, opkg-opk will allow both -I
and -c options (commands in dpkg-deb syntax) to be used together.
-rw-r--r-- | src/main.c | 170 |
1 files changed, 103 insertions, 67 deletions
@@ -28,22 +28,28 @@ #define OPKG_OPK_MAIN_FILE_BUFFER_SIZE_ 8192 -struct _opkg_opk_main_file { - FILE *file; - char buffer[OPKG_OPK_MAIN_FILE_BUFFER_SIZE_]; +struct _opkg_opk_main_opk { + FILE *file; + char file_buffer[OPKG_OPK_MAIN_FILE_BUFFER_SIZE_]; + 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; }; static int _opkg_opk_main_file_read(void *user_data, char **buffer, size_t *size) { - struct _opkg_opk_main_file *file = user_data; + struct _opkg_opk_main_opk *opk = user_data; - *buffer = file->buffer; - *size = fread(file->buffer, 1, OPKG_OPK_MAIN_FILE_BUFFER_SIZE_, - file->file); - if (feof(file->file)) { + *buffer = opk->file_buffer; + *size = fread(opk->file_buffer, 1, OPKG_OPK_MAIN_FILE_BUFFER_SIZE_, + opk->file); + if (feof(opk->file)) { return OPKG_OPK_END; - } else if (ferror(file->file) || *size == 0) { + } else if (ferror(opk->file) || *size == 0) { return OPKG_OPK_ERROR; } else { return OPKG_OPK_OK; @@ -51,103 +57,101 @@ _opkg_opk_main_file_read(void *user_data, char **buffer, size_t *size) } static int -_opkg_opk_main_extract(const char *file_name, const char *outer_member, - int (*inner_action)(struct opkg_opk_ustar *)) +_opkg_opk_main_init_outer(struct _opkg_opk_main_opk *opk, const char *file_name) { - struct _opkg_opk_main_file file; - struct opkg_opk_gzip *outer_gzip; - struct opkg_opk_ustar *outer_ustar; - char *buffer; - size_t size; - struct opkg_opk_gzip *inner_gzip; - struct opkg_opk_ustar *inner_ustar; - /* Open outer archive. */ - file.file = fopen(file_name, "rb"); - if (file.file == NULL) { + opk->file = fopen(file_name, "rb"); + if (opk->file == NULL) { fprintf(stderr, "Error: Failed to open file \"%s\"\n", file_name); goto error0; } /* Initialize outer gzip decompressor. */ - outer_gzip = opkg_opk_gzip_init(&_opkg_opk_main_file_read, &file); - if (outer_gzip == NULL) { + opk->outer_gzip = opkg_opk_gzip_init(&_opkg_opk_main_file_read, opk); + if (opk->outer_gzip == NULL) { fputs("Error: Failed to initialize\n", stderr); goto error1; } /* Initialize outer ustar unarchiver. */ - outer_ustar = opkg_opk_ustar_init(outer_gzip); - if (outer_ustar == NULL) { + opk->outer_ustar = opkg_opk_ustar_init(opk->outer_gzip); + if (opk->outer_ustar == NULL) { fputs("Error: Failed to initialize\n", stderr); goto error2; } /* Check package version. */ - if (opkg_opk_ustar_seek(outer_ustar, 1, "debian-binary") != + if (opkg_opk_ustar_seek(opk->outer_ustar, 1, "debian-binary") != OPKG_OPK_OK) { fputs("Error: Failed to find \"debian-binary\" in archive\n", stderr); goto error3; } - if (opkg_opk_ustar_read(outer_ustar, &buffer, &size) != OPKG_OPK_OK) { + if (opkg_opk_ustar_read(opk->outer_ustar, + &opk->version_buffer, &opk->version_size) != + OPKG_OPK_OK) { fputs("Error: Failed to read \"debian-binary\" in archive\n", stderr); goto error3; } - if (size < 4 || strncmp(buffer, "2.", 2) != 0) { + if (opk->version_size < 4 || strncmp(opk->version_buffer, "2.", 2) != 0) + { fputs("Error: Unsupported package version\n", stderr); goto error3; } + return OPKG_OPK_OK; + + error3: + opkg_opk_ustar_free(opk->outer_ustar); + error2: + opkg_opk_gzip_free(opk->outer_gzip); + error1: + fclose(opk->file); + error0: + return OPKG_OPK_ERROR; +} + +static int +_opkg_opk_main_init_inner(struct _opkg_opk_main_opk *opk, const char *member) +{ + 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(outer_ustar, 1, outer_member) != OPKG_OPK_OK) { + if (opkg_opk_ustar_seek(opk->outer_ustar, 1, member) != + OPKG_OPK_OK) { fprintf(stderr, "Error: Failed to find \"%s\" in archive\n", - outer_member); - goto error3; + member); + return OPKG_OPK_ERROR; } /* Initialize inner gzip decompressor. */ - inner_gzip = opkg_opk_gzip_init( + opk->inner_gzip = opkg_opk_gzip_init( (opkg_opk_gzip_read_func *) &opkg_opk_ustar_read, - outer_ustar); - if (inner_gzip == NULL) { + opk->outer_ustar); + if (opk->inner_gzip == NULL) { fputs("Error: Failed to initialize\n", stderr); - goto error3; + return OPKG_OPK_ERROR; } /* Initialize inner ustar unarchiver. */ - inner_ustar = opkg_opk_ustar_init(inner_gzip); - if (inner_ustar == NULL) { + opk->inner_ustar = opkg_opk_ustar_init(opk->inner_gzip); + if (opk->inner_ustar == NULL) { fputs("Error: Failed to initialize\n", stderr); - goto error4; - } - - /* Read control file or list data files. */ - if (inner_action(inner_ustar) != OPKG_OPK_OK) { - goto error5; + opkg_opk_gzip_free(opk->inner_gzip); + return OPKG_OPK_ERROR; } - opkg_opk_ustar_free(inner_ustar); - opkg_opk_gzip_free(inner_gzip); - opkg_opk_ustar_free(outer_ustar); - opkg_opk_gzip_free(outer_gzip); - fclose(file.file); return OPKG_OPK_OK; - - error5: - opkg_opk_ustar_free(inner_ustar); - error4: - opkg_opk_gzip_free(inner_gzip); - error3: - opkg_opk_ustar_free(outer_ustar); - error2: - opkg_opk_gzip_free(outer_gzip); - error1: - fclose(file.file); - error0: - return OPKG_OPK_ERROR; } static int @@ -255,15 +259,47 @@ _opkg_opk_main_list_members(struct opkg_opk_ustar *ustar) int main(int argc, char *argv[]) { - if (_opkg_opk_main_extract(argv[1], "control.tar.gz", - &_opkg_opk_main_read_control) != OPKG_OPK_OK) { - return EXIT_FAILURE; + struct _opkg_opk_main_opk opk; + + /* Initialize outer archive. */ + if (_opkg_opk_main_init_outer(&opk, argv[1]) != OPKG_OPK_OK) { + goto error0; + } + + /* Read control file. */ + if (_opkg_opk_main_init_inner(&opk, "control.tar.gz") != OPKG_OPK_OK) { + goto error1; + } + if (_opkg_opk_main_read_control(opk.inner_ustar) != OPKG_OPK_OK) { + goto error2; } + opkg_opk_ustar_free(opk.inner_ustar); + opkg_opk_gzip_free(opk.inner_gzip); + puts(""); - if (_opkg_opk_main_extract(argv[1], "data.tar.gz", - &_opkg_opk_main_list_members) != OPKG_OPK_OK) { - return EXIT_FAILURE; + + /* List data files. */ + if (_opkg_opk_main_init_inner(&opk, "data.tar.gz") != OPKG_OPK_OK) { + goto error1; } + if (_opkg_opk_main_list_members(opk.inner_ustar) != OPKG_OPK_OK) { + goto error2; + } + opkg_opk_ustar_free(opk.inner_ustar); + opkg_opk_gzip_free(opk.inner_gzip); + opkg_opk_ustar_free(opk.outer_ustar); + opkg_opk_gzip_free(opk.outer_gzip); + fclose(opk.file); return EXIT_SUCCESS; + + error2: + opkg_opk_ustar_free(opk.inner_ustar); + opkg_opk_gzip_free(opk.inner_gzip); + error1: + opkg_opk_ustar_free(opk.outer_ustar); + opkg_opk_gzip_free(opk.outer_gzip); + fclose(opk.file); + error0: + return EXIT_FAILURE; } |