/* * Copyright (C) 2023 Patrick McDermott * * This file is part of opkg-opk. * * opkg-opk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * opkg-opk is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with opkg-opk. If not, see . */ #include #include #include #include #include "defs.h" #include "gzip.h" #include "ustar.h" struct _opkg_opk_ustar_header { unsigned char name [100]; unsigned char mode [8]; unsigned char uid [8]; unsigned char gid [8]; unsigned char size [12]; unsigned char mtime [12]; unsigned char chksum [8]; unsigned char typeflag [1]; unsigned char linkname [100]; unsigned char magic [6]; unsigned char version [2]; unsigned char uname [32]; unsigned char gname [32]; unsigned char devmajor [8]; unsigned char devminor [8]; unsigned char prefix [155]; unsigned char padding [12]; } __attribute__((__packed__)); 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) { 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))) { case OPKG_OPK_OK: case OPKG_OPK_END: break; case OPKG_OPK_ERROR: return OPKG_OPK_ERROR; } if (strncmp(header->magic, "ustar", strlen("ustar")) != 0) { return OPKG_OPK_ERROR; } size = strtol(header->size, &size_end, 10); 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: case OPKG_OPK_END: break; case OPKG_OPK_ERROR: return OPKG_OPK_ERROR; } } return ret; } unsigned char * opkg_opk_ustar_read(struct opkg_opk_gzip_state *gzip_state, const char *member) { struct _opkg_opk_ustar_header header; int ret; unsigned char *contents; while ((ret = _opkg_opk_ustar_next(gzip_state, member, &header, &contents)) == OPKG_OPK_OK) { /* TODO: End gzip stream */ return contents; } return NULL; } int opkg_opk_ustar_list(struct opkg_opk_gzip_state *gzip_state, void (*member)(const char *name)) { struct _opkg_opk_ustar_header header; int ret; while ((ret = _opkg_opk_ustar_next(gzip_state, NULL, &header, NULL)) == OPKG_OPK_OK) { printf("%s\n", header.name); } return ret; }