summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McDermott <patrick.mcdermott@libiquity.com>2023-04-18 13:53:52 (EDT)
committer Patrick McDermott <patrick.mcdermott@libiquity.com>2023-04-18 13:53:52 (EDT)
commit49a767d3b62d948882179fcca2f9194da626f056 (patch)
treee3c972c4e2067629eabdf9b928354b66800d5a33
parent60f11fdb2ba2df49ed2fca1511828f96d3bbd9ce (diff)
opk: Split from main
-rw-r--r--src/local.mk2
-rw-r--r--src/main.c264
-rw-r--r--src/opk.c280
-rw-r--r--src/opk.h43
4 files changed, 338 insertions, 251 deletions
diff --git a/src/local.mk b/src/local.mk
index ec4b347..808322f 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -3,5 +3,7 @@ opkg_opk_SOURCES += \
%reldir%/gzip.c \
%reldir%/gzip.h \
%reldir%/main.c \
+ %reldir%/opk.c \
+ %reldir%/opk.h \
%reldir%/ustar.c \
%reldir%/ustar.h
diff --git a/src/main.c b/src/main.c
index 8b80a1f..1fecdfe 100644
--- a/src/main.c
+++ b/src/main.c
@@ -17,287 +17,49 @@
* along with opkg-opk. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <time.h>
#include "defs.h"
-#include "gzip.h"
-#include "ustar.h"
-
-struct _opkg_opk_main_opk {
- FILE *file;
- char file_buffer[8192];
- struct opkg_opk_gzip *outer_gzip;
- struct opkg_opk_ustar *outer_ustar;
- char *version_buffer;
- size_t version_size;
- struct opkg_opk_gzip *inner_gzip;
- struct opkg_opk_ustar *inner_ustar;
-};
-
-static int
-_opkg_opk_main_file_read(void *user_data, char **buffer, size_t *size)
-{
- struct _opkg_opk_main_opk *opk = user_data;
-
- *buffer = opk->file_buffer;
- *size = fread(opk->file_buffer, 1, sizeof(opk->file_buffer),
- opk->file);
- if (feof(opk->file)) {
- return OPKG_OPK_END;
- } else if (ferror(opk->file) || *size == 0) {
- return OPKG_OPK_ERROR;
- } else {
- return OPKG_OPK_OK;
- }
-}
-
-static int
-_opkg_opk_main_init_outer(struct _opkg_opk_main_opk *opk, const char *file_name)
-{
- /* Open outer archive. */
- opk->file = fopen(file_name, "rb");
- if (opk->file == NULL) {
- fprintf(stderr, "Error: Failed to open file \"%s\"\n",
- file_name);
- goto error0;
- }
-
- /* Initialize outer gzip decompressor. */
- opk->outer_gzip = opkg_opk_gzip_init(&_opkg_opk_main_file_read, opk);
- if (opk->outer_gzip == NULL) {
- fputs("Error: Failed to initialize\n", stderr);
- goto error1;
- }
-
- /* Initialize outer ustar unarchiver. */
- opk->outer_ustar = opkg_opk_ustar_init(opk->outer_gzip);
- if (opk->outer_ustar == NULL) {
- fputs("Error: Failed to initialize\n", stderr);
- goto error2;
- }
-
- /* Check package version. */
- if (opkg_opk_ustar_seek(opk->outer_ustar, 1, "debian-binary") !=
- OPKG_OPK_OK) {
- fputs("Error: Failed to find \"debian-binary\" in archive\n",
- stderr);
- goto error3;
- }
- if (opkg_opk_ustar_read(opk->outer_ustar,
- &opk->version_buffer, &opk->version_size) !=
- OPKG_OPK_OK) {
- fputs("Error: Failed to read \"debian-binary\" in archive\n",
- stderr);
- goto error3;
- }
- if (opk->version_size < 4 || strncmp(opk->version_buffer, "2.", 2) != 0)
- {
- fputs("Error: Unsupported package version\n", stderr);
- goto error3;
- }
-
- return OPKG_OPK_OK;
-
- error3:
- opkg_opk_ustar_free(opk->outer_ustar);
- error2:
- opkg_opk_gzip_free(opk->outer_gzip);
- error1:
- fclose(opk->file);
- error0:
- return OPKG_OPK_ERROR;
-}
-
-static int
-_opkg_opk_main_init_inner(struct _opkg_opk_main_opk *opk, const char *member)
-{
- int ret;
-
- /* Finish reading previous inner archive, if any. */
- while ((ret = opkg_opk_ustar_read(opk->outer_ustar, NULL, NULL)) ==
- OPKG_OPK_OK);
- if (ret == OPKG_OPK_ERROR) {
- fputs("Error: Failed to read archive\n", stderr);
- return OPKG_OPK_ERROR;
- }
-
- /* Find requested inner archive. */
- if (opkg_opk_ustar_seek(opk->outer_ustar, 1, member) !=
- OPKG_OPK_OK) {
- fprintf(stderr, "Error: Failed to find \"%s\" in archive\n",
- member);
- return OPKG_OPK_ERROR;
- }
-
- /* Initialize inner gzip decompressor. */
- opk->inner_gzip = opkg_opk_gzip_init(
- (opkg_opk_gzip_read_func *) &opkg_opk_ustar_read,
- opk->outer_ustar);
- if (opk->inner_gzip == NULL) {
- fputs("Error: Failed to initialize\n", stderr);
- return OPKG_OPK_ERROR;
- }
-
- /* Initialize inner ustar unarchiver. */
- opk->inner_ustar = opkg_opk_ustar_init(opk->inner_gzip);
- if (opk->inner_ustar == NULL) {
- fputs("Error: Failed to initialize\n", stderr);
- opkg_opk_gzip_free(opk->inner_gzip);
- return OPKG_OPK_ERROR;
- }
-
- return OPKG_OPK_OK;
-}
-
-static int
-_opkg_opk_main_read_control(struct opkg_opk_ustar *ustar)
-{
- char *buffer;
- size_t size;
- int ret;
-
- if (opkg_opk_ustar_seek(ustar, 2, "control", "./control") !=
- OPKG_OPK_OK) {
- fputs("Error: Failed to find control file\n", stderr);
- return OPKG_OPK_ERROR;
- }
- while ((ret = opkg_opk_ustar_read(ustar, &buffer, &size)) ==
- OPKG_OPK_OK) {
- fwrite(buffer, 1, size, stdout);
- }
- if (ret == OPKG_OPK_ERROR) {
- fputs("Error: Failed to read control file\n", stderr);
- return OPKG_OPK_ERROR;
- }
-
- return OPKG_OPK_OK;
-}
-
-static int
-_opkg_opk_main_list_members(struct opkg_opk_ustar *ustar)
-{
- struct opkg_opk_ustar_member *head;
- struct opkg_opk_ustar_member *tail;
- struct opkg_opk_ustar_member *member;
- int ret;
- size_t uname_len;
- size_t uname_len_max;
- size_t gname_len;
- size_t gname_len_max;
- uint64_t size_max;
- char fmt[29];
- /* "%c%s %-32s/%-32s %11d %s %s\n" */
- 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;
- size_max = 0;
- while ((ret = opkg_opk_ustar_list(ustar, &member)) == OPKG_OPK_OK) {
- if (head == NULL) {
- head = member;
- } else {
- tail->next = member;
- }
- tail = member;
- uname_len = strlen(member->uname);
- if (uname_len > uname_len_max) {
- uname_len_max = uname_len;
- }
- gname_len = strlen(member->gname);
- if (gname_len > gname_len_max) {
- gname_len_max = gname_len;
- }
- if (member->size > size_max) {
- size_max = member->size;
- }
- }
- if (ret == OPKG_OPK_ERROR) {
- fputs("Error: Failed to list data files\n", stderr);
- return OPKG_OPK_ERROR;
- }
- 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;) {
- if (member->mode & 00400) mode[0] = 'r'; else mode[0] = '-';
- if (member->mode & 00200) mode[1] = 'w'; else mode[1] = '-';
- if (member->mode & 00100) mode[2] = 'x'; else mode[2] = '-';
- if (member->mode & 04000) mode[2] = 's';
- if (member->mode & 00040) mode[3] = 'r'; else mode[3] = '-';
- if (member->mode & 00020) mode[4] = 'w'; else mode[4] = '-';
- if (member->mode & 00010) mode[5] = 'x'; else mode[5] = '-';
- if (member->mode & 02000) mode[5] = 's';
- if (member->mode & 00004) mode[6] = 'r'; else mode[6] = '-';
- if (member->mode & 00002) mode[7] = 'w'; else mode[7] = '-';
- if (member->mode & 00001) mode[8] = 'x'; else mode[8] = '-';
- if (member->mode & 01000) mode[8] = 't';
- mode[9] = '\0';
- strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S",
- localtime(&member->mtime));
- printf(fmt,
- member->type, mode,
- member->uname, member->gname,
- member->size, mtime, member->name);
- head = member;
- member = member->next;
- free(head);
- }
-
- return OPKG_OPK_OK;
-}
+#include "opk.h"
int
main(int argc, char *argv[])
{
- struct _opkg_opk_main_opk opk;
+ struct opkg_opk_opk *opk;
/* Initialize outer archive. */
- if (_opkg_opk_main_init_outer(&opk, argv[1]) != OPKG_OPK_OK) {
+ opk = opkg_opk_opk_init_outer(argv[1]);
+ if (opk == NULL) {
goto error0;
}
/* Read control file. */
- if (_opkg_opk_main_init_inner(&opk, "control.tar.gz") != OPKG_OPK_OK) {
+ if (opkg_opk_opk_init_inner(opk, "control.tar.gz") != OPKG_OPK_OK) {
goto error1;
}
- if (_opkg_opk_main_read_control(opk.inner_ustar) != OPKG_OPK_OK) {
+ if (opkg_opk_opk_read_control(opk) != OPKG_OPK_OK) {
goto error2;
}
- opkg_opk_ustar_free(opk.inner_ustar);
- opkg_opk_gzip_free(opk.inner_gzip);
+ opkg_opk_opk_free_inner(opk);
puts("");
/* List data files. */
- if (_opkg_opk_main_init_inner(&opk, "data.tar.gz") != OPKG_OPK_OK) {
+ if (opkg_opk_opk_init_inner(opk, "data.tar.gz") != OPKG_OPK_OK) {
goto error1;
}
- if (_opkg_opk_main_list_members(opk.inner_ustar) != OPKG_OPK_OK) {
+ if (opkg_opk_opk_list_members(opk) != OPKG_OPK_OK) {
goto error2;
}
- opkg_opk_ustar_free(opk.inner_ustar);
- opkg_opk_gzip_free(opk.inner_gzip);
+ opkg_opk_opk_free_inner(opk);
- opkg_opk_ustar_free(opk.outer_ustar);
- opkg_opk_gzip_free(opk.outer_gzip);
- fclose(opk.file);
+ opkg_opk_opk_free_outer(opk);
return EXIT_SUCCESS;
error2:
- opkg_opk_ustar_free(opk.inner_ustar);
- opkg_opk_gzip_free(opk.inner_gzip);
+ opkg_opk_opk_free_inner(opk);
error1:
- opkg_opk_ustar_free(opk.outer_ustar);
- opkg_opk_gzip_free(opk.outer_gzip);
- fclose(opk.file);
+ opkg_opk_opk_free_outer(opk);
error0:
return EXIT_FAILURE;
}
diff --git a/src/opk.c b/src/opk.c
new file mode 100644
index 0000000..14efe10
--- /dev/null
+++ b/src/opk.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2023 Patrick McDermott
+ *
+ * This file is part of opkg-opkg.
+ *
+ * opkg-opkg 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-opkg 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-opkg. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "defs.h"
+#include "gzip.h"
+#include "opk.h"
+#include "ustar.h"
+
+struct opkg_opk_opk {
+ FILE *file;
+ char file_buffer[8192];
+ struct opkg_opk_gzip *outer_gzip;
+ struct opkg_opk_ustar *outer_ustar;
+ char *version_buffer;
+ size_t version_size;
+ struct opkg_opk_gzip *inner_gzip;
+ struct opkg_opk_ustar *inner_ustar;
+};
+
+static int
+_opkg_opk_opk_file_read(void *user_data, char **buffer, size_t *size)
+{
+ struct opkg_opk_opk *opk = user_data;
+
+ *buffer = opk->file_buffer;
+ *size = fread(opk->file_buffer, 1, sizeof(opk->file_buffer),
+ opk->file);
+ if (feof(opk->file)) {
+ return OPKG_OPK_END;
+ } else if (ferror(opk->file) || *size == 0) {
+ return OPKG_OPK_ERROR;
+ } else {
+ return OPKG_OPK_OK;
+ }
+}
+
+struct opkg_opk_opk *
+opkg_opk_opk_init_outer(const char *file_name)
+{
+ struct opkg_opk_opk *opk;
+
+ opk = malloc(sizeof(*opk));
+ if (opk == NULL) {
+ goto error0;
+ }
+
+ /* Open outer archive. */
+ opk->file = fopen(file_name, "rb");
+ if (opk->file == NULL) {
+ fprintf(stderr, "Error: Failed to open file \"%s\"\n",
+ file_name);
+ goto error0;
+ }
+
+ /* Initialize outer gzip decompressor. */
+ opk->outer_gzip = opkg_opk_gzip_init(&_opkg_opk_opk_file_read, opk);
+ if (opk->outer_gzip == NULL) {
+ fputs("Error: Failed to initialize\n", stderr);
+ goto error1;
+ }
+
+ /* Initialize outer ustar unarchiver. */
+ opk->outer_ustar = opkg_opk_ustar_init(opk->outer_gzip);
+ if (opk->outer_ustar == NULL) {
+ fputs("Error: Failed to initialize\n", stderr);
+ goto error2;
+ }
+
+ /* Check package version. */
+ if (opkg_opk_ustar_seek(opk->outer_ustar, 1, "debian-binary") !=
+ OPKG_OPK_OK) {
+ fputs("Error: Failed to find \"debian-binary\" in archive\n",
+ stderr);
+ goto error3;
+ }
+ if (opkg_opk_ustar_read(opk->outer_ustar,
+ &opk->version_buffer, &opk->version_size) !=
+ OPKG_OPK_OK) {
+ fputs("Error: Failed to read \"debian-binary\" in archive\n",
+ stderr);
+ goto error3;
+ }
+ if (opk->version_size < 4 || strncmp(opk->version_buffer, "2.", 2) != 0)
+ {
+ fputs("Error: Unsupported package version\n", stderr);
+ goto error3;
+ }
+
+ return opk;
+
+ error3:
+ opkg_opk_ustar_free(opk->outer_ustar);
+ error2:
+ opkg_opk_gzip_free(opk->outer_gzip);
+ error1:
+ fclose(opk->file);
+ error0:
+ return NULL;
+}
+
+int
+opkg_opk_opk_init_inner(struct opkg_opk_opk *opk, const char *member)
+{
+ int ret;
+
+ /* Finish reading previous inner archive, if any. */
+ while ((ret = opkg_opk_ustar_read(opk->outer_ustar, NULL, NULL)) ==
+ OPKG_OPK_OK);
+ if (ret == OPKG_OPK_ERROR) {
+ fputs("Error: Failed to read archive\n", stderr);
+ return OPKG_OPK_ERROR;
+ }
+
+ /* Find requested inner archive. */
+ if (opkg_opk_ustar_seek(opk->outer_ustar, 1, member) !=
+ OPKG_OPK_OK) {
+ fprintf(stderr, "Error: Failed to find \"%s\" in archive\n",
+ member);
+ return OPKG_OPK_ERROR;
+ }
+
+ /* Initialize inner gzip decompressor. */
+ opk->inner_gzip = opkg_opk_gzip_init(
+ (opkg_opk_gzip_read_func *) &opkg_opk_ustar_read,
+ opk->outer_ustar);
+ if (opk->inner_gzip == NULL) {
+ fputs("Error: Failed to initialize\n", stderr);
+ return OPKG_OPK_ERROR;
+ }
+
+ /* Initialize inner ustar unarchiver. */
+ opk->inner_ustar = opkg_opk_ustar_init(opk->inner_gzip);
+ if (opk->inner_ustar == NULL) {
+ fputs("Error: Failed to initialize\n", stderr);
+ opkg_opk_gzip_free(opk->inner_gzip);
+ return OPKG_OPK_ERROR;
+ }
+
+ return OPKG_OPK_OK;
+}
+
+int
+opkg_opk_opk_read_control(struct opkg_opk_opk *opk)
+{
+ char *buffer;
+ size_t size;
+ int ret;
+
+ if (opkg_opk_ustar_seek(opk->inner_ustar, 2, "control", "./control") !=
+ OPKG_OPK_OK) {
+ fputs("Error: Failed to find control file\n", stderr);
+ return OPKG_OPK_ERROR;
+ }
+ while ((ret = opkg_opk_ustar_read(opk->inner_ustar, &buffer, &size)) ==
+ OPKG_OPK_OK) {
+ fwrite(buffer, 1, size, stdout);
+ }
+ if (ret == OPKG_OPK_ERROR) {
+ fputs("Error: Failed to read control file\n", stderr);
+ return OPKG_OPK_ERROR;
+ }
+
+ return OPKG_OPK_OK;
+}
+
+int
+opkg_opk_opk_list_members(struct opkg_opk_opk *opk)
+{
+ struct opkg_opk_ustar_member *head;
+ struct opkg_opk_ustar_member *tail;
+ struct opkg_opk_ustar_member *member;
+ int ret;
+ size_t uname_len;
+ size_t uname_len_max;
+ size_t gname_len;
+ size_t gname_len_max;
+ uint64_t size_max;
+ char fmt[29];
+ /* "%c%s %-32s/%-32s %11d %s %s\n" */
+ 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;
+ size_max = 0;
+ while ((ret = opkg_opk_ustar_list(opk->inner_ustar, &member)) ==
+ OPKG_OPK_OK) {
+ if (head == NULL) {
+ head = member;
+ } else {
+ tail->next = member;
+ }
+ tail = member;
+ uname_len = strlen(member->uname);
+ if (uname_len > uname_len_max) {
+ uname_len_max = uname_len;
+ }
+ gname_len = strlen(member->gname);
+ if (gname_len > gname_len_max) {
+ gname_len_max = gname_len;
+ }
+ if (member->size > size_max) {
+ size_max = member->size;
+ }
+ }
+ if (ret == OPKG_OPK_ERROR) {
+ fputs("Error: Failed to list data files\n", stderr);
+ return OPKG_OPK_ERROR;
+ }
+ 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;) {
+ if (member->mode & 00400) mode[0] = 'r'; else mode[0] = '-';
+ if (member->mode & 00200) mode[1] = 'w'; else mode[1] = '-';
+ if (member->mode & 00100) mode[2] = 'x'; else mode[2] = '-';
+ if (member->mode & 04000) mode[2] = 's';
+ if (member->mode & 00040) mode[3] = 'r'; else mode[3] = '-';
+ if (member->mode & 00020) mode[4] = 'w'; else mode[4] = '-';
+ if (member->mode & 00010) mode[5] = 'x'; else mode[5] = '-';
+ if (member->mode & 02000) mode[5] = 's';
+ if (member->mode & 00004) mode[6] = 'r'; else mode[6] = '-';
+ if (member->mode & 00002) mode[7] = 'w'; else mode[7] = '-';
+ if (member->mode & 00001) mode[8] = 'x'; else mode[8] = '-';
+ if (member->mode & 01000) mode[8] = 't';
+ mode[9] = '\0';
+ strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S",
+ localtime(&member->mtime));
+ printf(fmt,
+ member->type, mode,
+ member->uname, member->gname,
+ member->size, mtime, member->name);
+ head = member;
+ member = member->next;
+ free(head);
+ }
+
+ return OPKG_OPK_OK;
+}
+
+void
+opkg_opk_opk_free_inner(struct opkg_opk_opk *opk)
+{
+ opkg_opk_ustar_free(opk->inner_ustar);
+ opkg_opk_gzip_free(opk->inner_gzip);
+}
+
+void
+opkg_opk_opk_free_outer(struct opkg_opk_opk *opk)
+{
+ opkg_opk_ustar_free(opk->outer_ustar);
+ opkg_opk_gzip_free(opk->outer_gzip);
+ fclose(opk->file);
+ free(opk);
+}
diff --git a/src/opk.h b/src/opk.h
new file mode 100644
index 0000000..02ee090
--- /dev/null
+++ b/src/opk.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 Patrick McDermott
+ *
+ * This file is part of opkg-opkg.
+ *
+ * opkg-opkg 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-opkg 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-opkg. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef OPKG_OPK_OPK_H_
+#define OPKG_OPK_OPK_H_
+
+struct opkg_opk_opk;
+
+struct opkg_opk_opk *
+opkg_opk_opk_init_outer(const char *file_name);
+
+int
+opkg_opk_opk_init_inner(struct opkg_opk_opk *opk, const char *member);
+
+int
+opkg_opk_opk_read_control(struct opkg_opk_opk *opk);
+
+int
+opkg_opk_opk_list_members(struct opkg_opk_opk *opk);
+
+void
+opkg_opk_opk_free_inner(struct opkg_opk_opk *opk);
+
+void
+opkg_opk_opk_free_outer(struct opkg_opk_opk *opk);
+
+#endif /* OPKG_OPK_OPK_H_ */