summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/local.mk4
-rw-r--r--src/ustar.c109
-rw-r--r--src/ustar.h30
3 files changed, 142 insertions, 1 deletions
diff --git a/src/local.mk b/src/local.mk
index a3ebaf1..ec4b347 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -2,4 +2,6 @@ opkg_opk_SOURCES += \
%reldir%/defs.h \
%reldir%/gzip.c \
%reldir%/gzip.h \
- %reldir%/main.c
+ %reldir%/main.c \
+ %reldir%/ustar.c \
+ %reldir%/ustar.h
diff --git a/src/ustar.c b/src/ustar.c
new file mode 100644
index 0000000..6388d76
--- /dev/null
+++ b/src/ustar.c
@@ -0,0 +1,109 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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;
+ }
+ 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;
+}
diff --git a/src/ustar.h b/src/ustar.h
new file mode 100644
index 0000000..a6959c7
--- /dev/null
+++ b/src/ustar.h
@@ -0,0 +1,30 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#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);
+
+int
+opkg_opk_ustar_list(struct opkg_opk_gzip_state *gzip_state,
+ void (*member)(const char *name));
+
+#endif /* OPKG_OPK_USTAR_H_ */