From 050896fd00110c5a8744b540041c4c81c68530da Mon Sep 17 00:00:00 2001
From: Patrick McDermott <patrick.mcdermott@libiquity.com>
Date: Thu, 13 Apr 2023 01:30:00 -0400
Subject: ustar: Implement

---
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_ */
--
cgit v0.9.1