diff options
-rw-r--r-- | src/main.c | 10 | ||||
-rw-r--r-- | src/ustar.c | 18 |
2 files changed, 28 insertions, 0 deletions
@@ -62,6 +62,7 @@ _opkg_opk_main_extract(const char *file_name, const char *outer_member, 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) { fprintf(stderr, "Error: Failed to open file \"%s\"\n", @@ -69,18 +70,21 @@ _opkg_opk_main_extract(const char *file_name, const char *outer_member, goto error0; } + /* Initialize outer gzip decompressor. */ outer_gzip = opkg_opk_gzip_init(&_opkg_opk_main_file_read, &file); if (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) { fputs("Error: Failed to initialize\n", stderr); goto error2; } + /* Check package version. */ if (opkg_opk_ustar_seek(outer_ustar, 1, "debian-binary") != OPKG_OPK_OK) { fputs("Error: Failed to find \"debian-binary\" in archive\n", @@ -97,12 +101,14 @@ _opkg_opk_main_extract(const char *file_name, const char *outer_member, goto error3; } + /* Find requested inner archive. */ if (opkg_opk_ustar_seek(outer_ustar, 1, outer_member) != OPKG_OPK_OK) { fprintf(stderr, "Error: Failed to find \"%s\" in archive\n", outer_member); goto error3; } + /* Initialize inner gzip decompressor. */ inner_gzip = opkg_opk_gzip_init( (opkg_opk_gzip_read_func *) &opkg_opk_ustar_read, outer_ustar); @@ -111,12 +117,14 @@ _opkg_opk_main_extract(const char *file_name, const char *outer_member, goto error3; } + /* Initialize inner ustar unarchiver. */ inner_ustar = opkg_opk_ustar_init(inner_gzip); if (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; } @@ -183,6 +191,7 @@ _opkg_opk_main_list_members(struct opkg_opk_ustar *ustar) char mode[10]; char mtime[20]; + /* Build singly-linked list and find maximum column widths. */ head = NULL; uname_len_max = 0; gname_len_max = 0; @@ -212,6 +221,7 @@ _opkg_opk_main_list_members(struct opkg_opk_ustar *ustar) } tail->next = NULL; + /* Print and free members. */ snprintf(fmt, sizeof(fmt), "%%c%%s %%-%zus/%%-%zus %%%lid %%s %%s\n", uname_len, gname_len, lrint(ceil(log10(size_max)))); for (member = head; member != NULL;) { diff --git a/src/ustar.c b/src/ustar.c index 43292e9..cf1134a 100644 --- a/src/ustar.c +++ b/src/ustar.c @@ -81,22 +81,28 @@ _opkg_opk_ustar_next(struct opkg_opk_ustar *ustar, size_t i; char *header_uc; + /* Decompress next (hopefully valid header) record. */ switch (opkg_opk_gzip_read(ustar->gzip, header)) { case OPKG_OPK_OK: break; case OPKG_OPK_END: + /* End of gzip stream before end of ustar archive */ case OPKG_OPK_ERROR: return OPKG_OPK_ERROR; } + + /* Check for end of archive. */ memset(record, 0, OPKG_OPK_USTAR_RECORD_SIZE); if (memcmp(header, record, OPKG_OPK_USTAR_RECORD_SIZE) == 0) { return OPKG_OPK_END; } + /* Verify magic. */ if (memcmp(header->magic, "ustar", strlen("ustar")) != 0) { return OPKG_OPK_ERROR; } + /* Verify checksum. */ chksum_got = strtol(header->chksum, &end, OPKG_OPK_USTAR_NUM_BASE_); chksum_exp = 0; @@ -114,6 +120,7 @@ _opkg_opk_ustar_next(struct opkg_opk_ustar *ustar, return OPKG_OPK_ERROR; } + /* Depending on type, get size. */ switch (*header->typeflag) { case '0': /* Regular file */ case '7': /* High-performance or regular file */ @@ -147,15 +154,18 @@ opkg_opk_ustar_list(struct opkg_opk_ustar *ustar, int ret; char *end; + /* Get next header record, if any. */ if ((ret =_opkg_opk_ustar_next(ustar, &header)) != OPKG_OPK_OK) { return ret; /* Error or end of archive */ } + /* Allocate outward-facing member information structure. */ *member = malloc(sizeof(**member)); if (*member == NULL) { return OPKG_OPK_ERROR; } + /* Set name, mode, size, mtime, type, linkname, uname, and gname. */ if (header.prefix[0] != '\0') { sprintf((*member)->name, "%s/%s", header.prefix, header.name); } else { @@ -205,6 +215,7 @@ opkg_opk_ustar_list(struct opkg_opk_ustar *ustar, strncpy((*member)->uname, header.uname, sizeof((*member)->uname)); strncpy((*member)->gname, header.gname, sizeof((*member)->gname)); + /* Seek through data records until next header record. */ while (ustar->data_size_remaining > 0) { if (opkg_opk_ustar_read(ustar, NULL, NULL) == OPKG_OPK_ERROR) { free(*member); @@ -225,10 +236,12 @@ opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, int num_keys, ...) const char *member; for (;;) { + /* Get next header record. */ if (_opkg_opk_ustar_next(ustar, &header) != OPKG_OPK_OK) { return OPKG_OPK_ERROR; /* Error or end (not found) */ } + /* Prepare name (with prefix if any) for check. */ if (header.prefix[0] != '\0') { sprintf(name, "%s/%s", header.prefix, header.name); @@ -237,6 +250,7 @@ opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, int num_keys, ...) name[sizeof(header.name)] = '\0'; } + /* Check each requested name. */ va_start(ap, num_keys); for (key = 0; key < num_keys; ++key) { member = va_arg(ap, const char *); @@ -246,6 +260,7 @@ opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, int num_keys, ...) } va_end(ap); + /* Seek through data records until next header record. */ while (ustar->data_size_remaining > 0) { if (opkg_opk_ustar_read(ustar, NULL, NULL) == OPKG_OPK_ERROR) { @@ -264,6 +279,7 @@ opkg_opk_ustar_read(struct opkg_opk_ustar *ustar, char **buffer, size_t *size) return OPKG_OPK_END; } + /* Decompress next data record. */ switch (opkg_opk_gzip_read(ustar->gzip, ustar->read_record)) { case OPKG_OPK_OK: break; @@ -272,6 +288,8 @@ opkg_opk_ustar_read(struct opkg_opk_ustar *ustar, char **buffer, size_t *size) return OPKG_OPK_ERROR; } + /* Store buffer and size in caller's memory and update remaining size. + */ if (buffer != NULL) { *buffer = ustar->read_record; } |