summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPatrick McDermott <patrick.mcdermott@libiquity.com>2023-04-18 16:41:42 (EDT)
committer Patrick McDermott <patrick.mcdermott@libiquity.com>2023-04-18 19:47:12 (EDT)
commitb65c075d13990383f30b27aeafacdd4575fafdee (patch)
treec338c3db137405b98bf74091d9c9965d5c92d7cf /src
parent25ce512c39f578def257f81e10e22b06123a069d (diff)
ustar: Use linked list instead of varargs in seek
Also indicate when all sought member files are found.
Diffstat (limited to 'src')
-rw-r--r--src/main.c19
-rw-r--r--src/opk.c25
-rw-r--r--src/opk.h5
-rw-r--r--src/ustar.c74
-rw-r--r--src/ustar.h39
5 files changed, 131 insertions, 31 deletions
diff --git a/src/main.c b/src/main.c
index d9ccb64..b24a2fd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,11 +20,21 @@
#include <stdlib.h>
#include "defs.h"
#include "opk.h"
+#include "ustar.h"
int
main(int argc, char *argv[])
{
- struct opkg_opk_opk *opk;
+ struct opkg_opk_ustar_seek_name *control_files_head;
+ struct opkg_opk_ustar_seek_name *control_files_tail;
+ struct opkg_opk_opk *opk;
+
+ control_files_head = control_files_tail = NULL;
+ if (opkg_opk_ustar_add_seek_name(
+ &control_files_head, &control_files_tail,
+ "control") != OPKG_OPK_OK) {
+ goto error0;
+ }
/* Initialize outer archive. */
opk = opkg_opk_opk_init_outer(argv[1]);
@@ -36,7 +46,7 @@ main(int argc, char *argv[])
if (opkg_opk_opk_init_inner(opk, "control.tar.gz") != OPKG_OPK_OK) {
goto error1;
}
- if (opkg_opk_opk_read_control(opk) != OPKG_OPK_OK) {
+ if (opkg_opk_opk_read_control(opk, control_files_head) != OPKG_OPK_OK) {
goto error2;
}
opkg_opk_opk_free_inner(opk);
@@ -58,5 +68,10 @@ main(int argc, char *argv[])
error1:
opkg_opk_opk_free_outer(opk);
error0:
+ for (control_files_tail = control_files_head;
+ control_files_tail != NULL; ) {
+ control_files_tail = control_files_head->next;
+ free(control_files_head);
+ }
return EXIT_FAILURE;
}
diff --git a/src/opk.c b/src/opk.c
index ce24e55..82aaca3 100644
--- a/src/opk.c
+++ b/src/opk.c
@@ -59,7 +59,8 @@ _opkg_opk_opk_file_read(void *user_data, char **buffer, size_t *size)
struct opkg_opk_opk *
opkg_opk_opk_init_outer(const char *file_name)
{
- struct opkg_opk_opk *opk;
+ struct opkg_opk_opk *opk;
+ struct opkg_opk_ustar_seek_name seek_name;
opk = malloc(sizeof(*opk));
if (opk == NULL) {
@@ -89,8 +90,10 @@ opkg_opk_opk_init_outer(const char *file_name)
}
/* Check package version. */
- if (opkg_opk_ustar_seek(opk->outer_ustar, 1, "debian-binary") !=
- OPKG_OPK_OK) {
+ seek_name.name = "debian-binary";
+ seek_name.next = NULL;
+ if (opkg_opk_ustar_seek(opk->outer_ustar, &seek_name) == OPKG_OPK_ERROR)
+ {
fputs("Error: Failed to find \"debian-binary\" in archive\n",
stderr);
goto error3;
@@ -125,7 +128,8 @@ opkg_opk_opk_init_outer(const char *file_name)
int
opkg_opk_opk_init_inner(struct opkg_opk_opk *opk, const char *member)
{
- int ret;
+ int ret;
+ struct opkg_opk_ustar_seek_name seek_name;
/* Finish reading previous inner archive, if any. */
while ((ret = opkg_opk_ustar_read(opk->outer_ustar, NULL, NULL)) ==
@@ -136,8 +140,11 @@ opkg_opk_opk_init_inner(struct opkg_opk_opk *opk, const char *member)
}
/* Find requested inner archive. */
- if (opkg_opk_ustar_seek(opk->outer_ustar, 1, member) !=
- OPKG_OPK_OK) {
+ seek_name.name = member;
+ seek_name.found = 0;
+ seek_name.next = NULL;
+ if (opkg_opk_ustar_seek(opk->outer_ustar, &seek_name) == OPKG_OPK_ERROR)
+ {
fprintf(stderr, "Error: Failed to find \"%s\" in archive\n",
member);
return OPKG_OPK_ERROR;
@@ -164,7 +171,8 @@ opkg_opk_opk_init_inner(struct opkg_opk_opk *opk, const char *member)
}
int
-opkg_opk_opk_read_control(struct opkg_opk_opk *opk)
+opkg_opk_opk_read_control(struct opkg_opk_opk *opk,
+ struct opkg_opk_ustar_seek_name *names)
{
char *buffer;
size_t size;
@@ -174,8 +182,7 @@ opkg_opk_opk_read_control(struct opkg_opk_opk *opk)
puts("");
}
- if (opkg_opk_ustar_seek(opk->inner_ustar, 2, "control", "./control") !=
- OPKG_OPK_OK) {
+ if (opkg_opk_ustar_seek(opk->inner_ustar, names) == OPKG_OPK_ERROR) {
fputs("Error: Failed to find control file\n", stderr);
return OPKG_OPK_ERROR;
}
diff --git a/src/opk.h b/src/opk.h
index 02ee090..1b7e681 100644
--- a/src/opk.h
+++ b/src/opk.h
@@ -20,6 +20,8 @@
#ifndef OPKG_OPK_OPK_H_
#define OPKG_OPK_OPK_H_
+#include "ustar.h"
+
struct opkg_opk_opk;
struct opkg_opk_opk *
@@ -29,7 +31,8 @@ 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);
+opkg_opk_opk_read_control(struct opkg_opk_opk *opk,
+ struct opkg_opk_ustar_seek_name *names);
int
opkg_opk_opk_list_members(struct opkg_opk_opk *opk);
diff --git a/src/ustar.c b/src/ustar.c
index cf1134a..2a386f0 100644
--- a/src/ustar.c
+++ b/src/ustar.c
@@ -17,7 +17,6 @@
* along with opkg-opk. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -227,13 +226,38 @@ opkg_opk_ustar_list(struct opkg_opk_ustar *ustar,
}
int
-opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, int num_keys, ...)
+opkg_opk_ustar_add_seek_name(struct opkg_opk_ustar_seek_name **head,
+ struct opkg_opk_ustar_seek_name **tail, const char *name)
{
- static struct _opkg_opk_ustar_header header;
- static char name[OPKG_OPK_USTAR_NAME_MAX_LEN];
- va_list ap;
- int key;
- const char *member;
+ struct opkg_opk_ustar_seek_name *seek_name;
+
+ seek_name = malloc(sizeof(*seek_name));
+ if (seek_name == NULL) {
+ return OPKG_OPK_ERROR;
+ }
+ seek_name->name = name;
+ seek_name->found = 0;
+ seek_name->next = NULL;
+
+ if (*head == NULL) {
+ *head = seek_name;
+ } else {
+ (*tail)->next = seek_name;
+ }
+ *tail = seek_name;
+
+ return OPKG_OPK_OK;
+}
+
+int
+opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar,
+ struct opkg_opk_ustar_seek_name *names)
+{
+ static struct _opkg_opk_ustar_header header;
+ static char name[OPKG_OPK_USTAR_NAME_MAX_LEN];
+ int found;
+ int found_all;
+ struct opkg_opk_ustar_seek_name *seek_name;
for (;;) {
/* Get next header record. */
@@ -251,14 +275,38 @@ opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, int num_keys, ...)
}
/* Check each requested name. */
- va_start(ap, num_keys);
- for (key = 0; key < num_keys; ++key) {
- member = va_arg(ap, const char *);
- if (strcmp(name, member) == 0) {
- return OPKG_OPK_OK; /* Member found */
+ found = 0;
+ found_all = 1;
+ for (seek_name = names; seek_name != NULL;
+ seek_name = seek_name->next) {
+ if (seek_name->found == 1) {
+ continue; /* Previously found this member */
+ }
+ if (strcmp(name, seek_name->name) == 0) {
+ if (found == 0) {
+ seek_name->found = 1;
+ found = 1;
+ continue;
+ }
+ }
+ if (name[0] == '.' && name[1] == '/' &&
+ strcmp(name + 2, seek_name->name) == 0)
+ {
+ if (found == 0) {
+ seek_name->found = 1;
+ found = 1;
+ continue;
+ }
+ }
+ found_all = 0;
+ }
+ if (found == 1) {
+ if (found_all == 1) {
+ /* All requested members found */
+ return OPKG_OPK_END;
}
+ return OPKG_OPK_OK; /* Member found, but more remain */
}
- va_end(ap);
/* Seek through data records until next header record. */
while (ustar->data_size_remaining > 0) {
diff --git a/src/ustar.h b/src/ustar.h
index 47f3efa..d2317b6 100644
--- a/src/ustar.h
+++ b/src/ustar.h
@@ -21,6 +21,7 @@
#define OPKG_OPK_USTAR_H_
#include <stdint.h>
+#include "gzip.h"
#define OPKG_OPK_USTAR_RECORD_SIZE 512
#define OPKG_OPK_USTAR_NAME_MAX_LEN 257 /* prefix[155] + '/' + name[100] + '\0'
@@ -40,6 +41,12 @@ struct opkg_opk_ustar_member {
struct opkg_opk_ustar_member *next;
};
+struct opkg_opk_ustar_seek_name {
+ const char *name;
+ int found;
+ struct opkg_opk_ustar_seek_name *next;
+};
+
/*
* Allocates and initializes an archive structure.
* Parameters:
@@ -68,18 +75,38 @@ opkg_opk_ustar_list(struct opkg_opk_ustar *ustar,
struct opkg_opk_ustar_member **member);
/*
- * Advances to a named member file.
+ * Adds a name to a list of names to find with opkg_opk_ustar_seek(). List is
+ * dynamically allocated; free with free().
* Parameters:
- * - ustar: Archive structure.
- * - num_keys: Number of search keys to follow.
- * - ...: Search keys of type (const char *).
+ * - head: Address in which to store address of list head.
+ * - tail: Address in which to store address of list tail.
+ * - name: Name of member file to find.
+ * Returns:
+ * - OPKG_OPK_OK if the name was added to the list.
+ * - OPKG_OPK_ERROR on memory exhaustion.
+ */
+int
+opkg_opk_ustar_add_seek_name(struct opkg_opk_ustar_seek_name **head,
+ struct opkg_opk_ustar_seek_name **tail, const char *name);
+
+/*
+ * Advances to a named member file. May be called multiple times until all
+ * requested members are found.
+ * Parameters:
+ * - ustar: Archive structure.
+ * - names: Name(s) to find. Member "found" will be set to "1" on the first
+ * name found.
* Returns:
- * - OPKG_OPK_OK if a member matching one of the search keys is found.
+ * - OPKG_OPK_OK if a member matching one of the requested names is found but
+ * more names remain to be found.
+ * - OPKG_OPK_END if a member matching one of the requested names is found and
+ * no more names remain to be found.
* - OPKG_OPK_ERROR if no matching member is found or on decompression error, an
* invalid header, or unsupported file type.
*/
int
-opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar, int num_keys, ...);
+opkg_opk_ustar_seek(struct opkg_opk_ustar *ustar,
+ struct opkg_opk_ustar_seek_name *names);
/*
* Reads up to a record (512 octets) of member file data at a time.