summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick 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)
commit507c5f7001a1da8a22ade991c885b89cafd76696 (patch)
treea94e5f6f3a1559cd935be02d26591b23e57e9cfd
parent62e056a12300a276ec99a99f9061bef5fa35fe9e (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.c170
1 files changed, 103 insertions, 67 deletions
diff --git a/src/main.c b/src/main.c
index e2496aa..3b80e8e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}