diff options
-rw-r--r-- | src/ustar.c | 147 | ||||
-rw-r--r-- | src/ustar.h | 20 |
2 files changed, 127 insertions, 40 deletions
diff --git a/src/ustar.c b/src/ustar.c index 7f9666a..69071c7 100644 --- a/src/ustar.c +++ b/src/ustar.c @@ -45,18 +45,35 @@ struct _opkg_opk_ustar_header { unsigned char padding [12]; } __attribute__((__packed__)); +struct opkg_opk_ustar { + struct opkg_opk_gzip *gzip; + int32_t data_size_remaining; +}; + +struct opkg_opk_ustar * +opkg_opk_ustar_init(struct opkg_opk_gzip *gzip) +{ + struct opkg_opk_ustar *ustar; + + ustar = malloc(sizeof(*ustar)); + if (ustar == NULL) { + return NULL; + } + + ustar->gzip = gzip; + ustar->data_size_remaining = 0; + + return ustar; +} + static int -_opkg_opk_ustar_next(struct opkg_opk_gzip_state *gzip_state, const char *member, - struct _opkg_opk_ustar_header *header, unsigned char **contents) +_opkg_opk_ustar_next(struct opkg_opk_ustar *ustar, + struct _opkg_opk_ustar_header *header) { static unsigned char record[512]; - int ret; char *size_end; - uint32_t size; - unsigned char *contents_cursor; - uint32_t i; - switch ((ret = opkg_opk_gzip_next_record(gzip_state, header))) { + switch (opkg_opk_gzip_read(ustar->gzip, header)) { case OPKG_OPK_OK: break; case OPKG_OPK_END: @@ -64,56 +81,114 @@ _opkg_opk_ustar_next(struct opkg_opk_gzip_state *gzip_state, const char *member, return OPKG_OPK_ERROR; } memset(record, 0, 512); - if (strncmp(header, record, 512) == 0) { + if (memcmp(header, record, 512) == 0) { /* TODO: End gzip stream */ return OPKG_OPK_END; } - if (strncmp(header->magic, "ustar", strlen("ustar")) != 0) { + if (memcmp(header->magic, "ustar", strlen("ustar")) != 0) { return OPKG_OPK_ERROR; } - size = strtol(header->size, &size_end, 8); + ustar->data_size_remaining = strtol((char *) header->size, &size_end, + 8); if (*size_end != '\0') { return OPKG_OPK_ERROR; } - for (i = 0; i < (size + 511) / 512; ++i) { - switch ((ret = opkg_opk_gzip_next_record(gzip_state, record))) { - case OPKG_OPK_OK: - break; - case OPKG_OPK_END: - case OPKG_OPK_ERROR: - return OPKG_OPK_ERROR; + + return OPKG_OPK_OK; +} + +int +opkg_opk_ustar_list(struct opkg_opk_ustar *ustar, + struct opkg_opk_ustar_member *member) +{ + static struct _opkg_opk_ustar_header record; + int ret; + + if ((ret =_opkg_opk_ustar_next(ustar, &record)) != OPKG_OPK_OK) { + return ret; /* Error or end of archive */ + } + + if (record.prefix[0] != '\0') { + sprintf(member->name, "%s/%s", record.prefix, record.name); + } else { + memcpy(member->name, record.name, 100); + member->name[100] = '\0'; + } + + while (ustar->data_size_remaining > 0) { + if (opkg_opk_ustar_read(ustar, (char *) &record, NULL) == + OPKG_OPK_ERROR) { + return OPKG_OPK_ERROR; } } - return ret; + return OPKG_OPK_OK; /* Possibly more members in archive */ } -unsigned char * -opkg_opk_ustar_read(struct opkg_opk_gzip_state *gzip_state, const char *member) +int +opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, const char *member) { - struct _opkg_opk_ustar_header header; - int ret; - unsigned char *contents; + static struct _opkg_opk_ustar_header record; + static unsigned char name[257]; + int ret; - while ((ret = _opkg_opk_ustar_next(gzip_state, member, - &header, &contents)) == OPKG_OPK_OK) { - /* TODO: End gzip stream */ - return contents; + for (;;) { + if ((ret =_opkg_opk_ustar_next(ustar, &record)) != OPKG_OPK_OK) + { + return OPKG_OPK_ERROR; /* Error or end (not found) */ + } + + if (record.prefix[0] != '\0') { + sprintf((char *) name, "%s/%s", record.prefix, + record.name); + } else { + memcpy(name, record.name, 100); + name[100] = '\0'; + } + + if (strcmp((char *) name, member) == 0) { + ret = OPKG_OPK_OK; /* Member found */ + } else { + ret = OPKG_OPK_ERROR; /* Member not found (yet) */ + } + + while (ustar->data_size_remaining > 0) { + if (opkg_opk_ustar_read(ustar, (char *) &record, NULL) + == OPKG_OPK_ERROR) { + return OPKG_OPK_ERROR; + } + } } - return NULL; + + return ret; } int -opkg_opk_ustar_list(struct opkg_opk_gzip_state *gzip_state, - void (*member)(const char *name)) +opkg_opk_ustar_read(struct opkg_opk_ustar *ustar, char *buffer, size_t *size) { - struct _opkg_opk_ustar_header header; - int ret; + if (ustar->data_size_remaining == 0) { + return OPKG_OPK_END; + } - while ((ret = _opkg_opk_ustar_next(gzip_state, NULL, &header, NULL)) == - OPKG_OPK_OK) { - printf("%s\n", header.name); + switch (opkg_opk_gzip_read(ustar->gzip, buffer)) { + case OPKG_OPK_OK: + break; + case OPKG_OPK_END: + case OPKG_OPK_ERROR: + return OPKG_OPK_ERROR; } - return ret; + + if (ustar->data_size_remaining >= 512) { + if (size != NULL) { + *size = 512; + } + ustar->data_size_remaining -= 512; + } else { + if (size != NULL) { + *size = ustar->data_size_remaining; + } + ustar->data_size_remaining = 0; + } + return OPKG_OPK_OK; } diff --git a/src/ustar.h b/src/ustar.h index a6959c7..a1c5e75 100644 --- a/src/ustar.h +++ b/src/ustar.h @@ -20,11 +20,23 @@ #ifndef OPKG_OPK_USTAR_H_ #define OPKG_OPK_USTAR_H_ -unsigned char * -opkg_opk_ustar_read(struct opkg_opk_gzip_state *gzip_state, const char *member); +struct opkg_opk_ustar; + +struct opkg_opk_ustar_member { + char name[257]; /* prefix[155] + '/' + name[100] + '\0' */ +}; + +struct opkg_opk_ustar * +opkg_opk_ustar_init(struct opkg_opk_gzip *gzip); + +int +opkg_opk_ustar_list(struct opkg_opk_ustar *ustar, + struct opkg_opk_ustar_member *member); + +int +opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, const char *member); int -opkg_opk_ustar_list(struct opkg_opk_gzip_state *gzip_state, - void (*member)(const char *name)); +opkg_opk_ustar_read(struct opkg_opk_ustar *ustar, char *buffer, size_t *size); #endif /* OPKG_OPK_USTAR_H_ */ |