summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main.c10
-rw-r--r--src/ustar.c18
2 files changed, 28 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
index 332ac0d..e2496aa 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}