From df50f9698332f3a225aa67704969c72c88ca941c Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Thu, 19 Jan 2023 21:22:08 +0100 Subject: [PATCH 01/74] feat: begin binary tree implementation --- include/vieter_tree.h | 15 +++++++++++++++ src/tree/node.h | 13 +++++++++++++ src/tree/tree.c | 6 ++++++ 3 files changed, 34 insertions(+) create mode 100644 include/vieter_tree.h create mode 100644 src/tree/node.h create mode 100644 src/tree/tree.c diff --git a/include/vieter_tree.h b/include/vieter_tree.h new file mode 100644 index 0000000..7dda9e1 --- /dev/null +++ b/include/vieter_tree.h @@ -0,0 +1,15 @@ +#ifndef VIETER_TREE +#define VIETER_TREE + +#include + +typedef struct vieter_tree vieter_tree; + +typedef enum vieter_tree_error { + vieter_tree_ok = 0, + vieter_tree_already_present = 1 +} vieter_tree_error; + +vieter_tree_error vieter_tree_insert(uint64_t key, void *data); + +#endif diff --git a/src/tree/node.h b/src/tree/node.h new file mode 100644 index 0000000..10143ca --- /dev/null +++ b/src/tree/node.h @@ -0,0 +1,13 @@ +#ifndef VIETER_BALANCED_TREE_NODE +#define VIETER_BALANCED_TREE_NODE + +#include + +typedef struct vieter_tree_node { + uint64_t key; + void *data; + struct vieter_tree_node *left; + struct vieter_tree_node *right; +} vieter_tree_node; + +#endif diff --git a/src/tree/tree.c b/src/tree/tree.c new file mode 100644 index 0000000..4a10d5a --- /dev/null +++ b/src/tree/tree.c @@ -0,0 +1,6 @@ +#include "vieter_tree.h" +#include "node.h" + +struct vieter_tree { + uint64_t size; +}; From 98f158e1f5df2a4842eeb2aea51bf9169db7e2b3 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 19 Jan 2023 22:23:19 +0100 Subject: [PATCH 02/74] feat(tree): started standard binary tree --- Makefile | 4 +++ include/vieter_tree.h | 21 +++++++++++-- src/tree/node.c | 61 ++++++++++++++++++++++++++++++++++++ src/tree/node.h | 14 +++++++-- src/tree/tree.c | 57 +++++++++++++++++++++++++++++++-- test/tree/test_binary_tree.c | 32 +++++++++++++++++++ 6 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 src/tree/node.c create mode 100644 test/tree/test_binary_tree.c diff --git a/Makefile b/Makefile index 04c6dd3..411a033 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,10 @@ $(TARGETS_TEST): test-%: % $(TARGETS_MEM_TEST): test-mem-%: % valgrind --tool=memcheck --error-exitcode=1 --track-origins=yes --leak-check=full ./$^ +test-mem: build-test + @ $(foreach bin,$(BINS_TEST),valgrind --tool=memcheck --error-exitcode=1 \ + --track-origins=yes --leak-check=full ./$(bin);) + .PHONY: build-test build-test: $(BINS_TEST) diff --git a/include/vieter_tree.h b/include/vieter_tree.h index 7dda9e1..be381e5 100644 --- a/include/vieter_tree.h +++ b/include/vieter_tree.h @@ -2,14 +2,29 @@ #define VIETER_TREE #include +#include typedef struct vieter_tree vieter_tree; typedef enum vieter_tree_error { - vieter_tree_ok = 0, - vieter_tree_already_present = 1 + vieter_tree_ok = 0, + vieter_tree_already_present = 1, + vieter_tree_not_present = 2 } vieter_tree_error; -vieter_tree_error vieter_tree_insert(uint64_t key, void *data); +vieter_tree *vieter_tree_init(); + +void vieter_tree_free(vieter_tree *tree); + +vieter_tree_error vieter_tree_insert(vieter_tree *tree, uint64_t key, + void *data); + +vieter_tree_error vieter_tree_search(void **out, vieter_tree *tree, + uint64_t key); + +vieter_tree_error vieter_tree_remove(void **out, vieter_tree *tree, + uint64_t key); + +uint64_t vieter_tree_size(vieter_tree *tree); #endif diff --git a/src/tree/node.c b/src/tree/node.c new file mode 100644 index 0000000..935a56d --- /dev/null +++ b/src/tree/node.c @@ -0,0 +1,61 @@ +#include "node.h" + +vieter_tree_node *vieter_tree_node_init() { + return calloc(1, sizeof(vieter_tree_node)); +} + +vieter_tree_error vieter_tree_node_insert(vieter_tree_node *node, uint64_t key, + void *data) { + vieter_tree_node *parent = node; + + while (node != NULL) { + if (node->key == key) { + return vieter_tree_already_present; + } + + parent = node; + + if (key < node->key) { + node = parent->left; + } else { + node = parent->right; + } + } + + vieter_tree_node *new_node = vieter_tree_node_init(); + new_node->key = key; + new_node->data = data; + new_node->parent = parent; + + if (key < node->key) { + parent->left = new_node; + } else { + parent->right = new_node; + } + + return vieter_tree_ok; +} + +vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *node, + uint64_t key) { + while (node != NULL) { + if (node->key == key) { + *out = node->data; + + return vieter_tree_ok; + } + + if (key < node->key) { + node = node->left; + } else { + node = node->right; + } + } + + return vieter_tree_not_present; +} + +vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *node, + uint64_t key) { + return vieter_tree_not_present; +} diff --git a/src/tree/node.h b/src/tree/node.h index 10143ca..f22a965 100644 --- a/src/tree/node.h +++ b/src/tree/node.h @@ -1,13 +1,23 @@ -#ifndef VIETER_BALANCED_TREE_NODE -#define VIETER_BALANCED_TREE_NODE +#ifndef VIETER_TREE_NODE +#define VIETER_TREE_NODE +#include "vieter_tree.h" #include typedef struct vieter_tree_node { uint64_t key; void *data; + struct vieter_tree_node *parent; struct vieter_tree_node *left; struct vieter_tree_node *right; } vieter_tree_node; +vieter_tree_node *vieter_tree_node_init(); + +vieter_tree_error vieter_tree_node_insert(vieter_tree_node *node, uint64_t key, void *data); + +vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *node, uint64_t key); + +vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *node, uint64_t key); + #endif diff --git a/src/tree/tree.c b/src/tree/tree.c index 4a10d5a..725fcda 100644 --- a/src/tree/tree.c +++ b/src/tree/tree.c @@ -1,6 +1,59 @@ -#include "vieter_tree.h" #include "node.h" +#include "vieter_tree.h" struct vieter_tree { - uint64_t size; + uint64_t size; + vieter_tree_node *root; }; + +vieter_tree *vieter_tree_init() { return calloc(1, sizeof(vieter_tree)); } + +uint64_t vieter_tree_size(vieter_tree *tree) { return tree->size; } + +vieter_tree_error vieter_tree_insert(vieter_tree *tree, uint64_t key, + void *data) { + if (tree->size == 0) { + tree->root = vieter_tree_node_init(); + tree->root->key = key; + tree->root->data = data; + tree->size = 1; + + return vieter_tree_ok; + } + + vieter_tree_error res = vieter_tree_node_insert(tree->root, key, data); + + if (res != vieter_tree_ok) { + return res; + } + + tree->size++; + + return vieter_tree_ok; +} + +vieter_tree_error vieter_tree_search(void **out, vieter_tree *tree, + uint64_t key) { + if (tree->size == 0) { + return vieter_tree_not_present; + } + + return vieter_tree_node_search(out, tree->root, key); +} + +vieter_tree_error vieter_tree_remove(void **out, vieter_tree *tree, + uint64_t key) { + if (tree->size == 0) { + return vieter_tree_not_present; + } + + vieter_tree_error res = vieter_tree_node_remove(out, tree->root, key); + + if (res != vieter_tree_ok) { + return res; + } + + tree->size--; + + return vieter_tree_ok; +} diff --git a/test/tree/test_binary_tree.c b/test/tree/test_binary_tree.c new file mode 100644 index 0000000..fd6bb1b --- /dev/null +++ b/test/tree/test_binary_tree.c @@ -0,0 +1,32 @@ +#include "acutest.h" +#include "vieter_tree.h" + +#define TEST_SIZE(tree, size) \ + TEST_CHECK(vieter_tree_size(tree) == size); \ + TEST_MSG("Size: %zu", vieter_tree_size(tree)) + +void test_init() { + vieter_tree *tree = vieter_tree_init(); + TEST_CHECK(tree != NULL); + TEST_SIZE(tree, 0); + /* vieter_tree_free(tree); */ +} + +void test_insert() { + vieter_tree *tree = vieter_tree_init(); + + for (uint64_t i = 0; i < 25; i++) { + TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); + } + + void *out; + + for (uint64_t i = 0; i < 25; i++) { + TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_already_present); + TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); + } +} + +TEST_LIST = { + {NULL, NULL} +}; From 935a610b7ecf803d24affe357696042b6b3e970f Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 19 Jan 2023 22:45:22 +0100 Subject: [PATCH 03/74] feat(tree): initially working binary tree --- Makefile | 2 +- src/tree/node.c | 125 +++++++++++++++++++++++++++++++---- src/tree/node.h | 11 ++- test/tree/test_binary_tree.c | 21 ++++++ 4 files changed, 141 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 411a033..665c411 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ objs: $(OBJS) .PHONY: vieter vieter: $(LIB) -$(BUILD_DIR)/$(LIB_FILENAME): $(OBJS) +$(LIB): $(OBJS) ar -rcs $@ $(OBJS) $(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c diff --git a/src/tree/node.c b/src/tree/node.c index 935a56d..131e932 100644 --- a/src/tree/node.c +++ b/src/tree/node.c @@ -4,9 +4,35 @@ vieter_tree_node *vieter_tree_node_init() { return calloc(1, sizeof(vieter_tree_node)); } -vieter_tree_error vieter_tree_node_insert(vieter_tree_node *node, uint64_t key, +void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, + vieter_tree_node *child) { + if (parent == NULL) { + return; + } + + if (key < parent->key) { + parent->left = child; + } else { + parent->right = child; + } + + if (child != NULL) { + child->parent = parent; + } +} + +void vieter_tree_node_replace(vieter_tree_node *to_replace, + vieter_tree_node *replacement) { + to_replace->key = replacement->key; + to_replace->data = replacement->data; + to_replace->left = replacement->left; + to_replace->right = replacement->right; +} + +vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, void *data) { - vieter_tree_node *parent = node; + vieter_tree_node *node = root; + vieter_tree_node *parent = root; while (node != NULL) { if (node->key == key) { @@ -15,7 +41,7 @@ vieter_tree_error vieter_tree_node_insert(vieter_tree_node *node, uint64_t key, parent = node; - if (key < node->key) { + if (key < parent->key) { node = parent->left; } else { node = parent->right; @@ -25,22 +51,20 @@ vieter_tree_error vieter_tree_node_insert(vieter_tree_node *node, uint64_t key, vieter_tree_node *new_node = vieter_tree_node_init(); new_node->key = key; new_node->data = data; - new_node->parent = parent; - if (key < node->key) { - parent->left = new_node; - } else { - parent->right = new_node; - } + vieter_tree_node_add_child(parent, key, new_node); return vieter_tree_ok; } -vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *node, - uint64_t key) { +vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, + vieter_tree_node *root, + uint64_t key) { + vieter_tree_node *node = root; + while (node != NULL) { if (node->key == key) { - *out = node->data; + *out = node; return vieter_tree_ok; } @@ -55,7 +79,80 @@ vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *node, return vieter_tree_not_present; } -vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *node, +vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, uint64_t key) { - return vieter_tree_not_present; + vieter_tree_node *target; + vieter_tree_error res = vieter_tree_node_search_node(&target, root, key); + + if (res != vieter_tree_ok) { + return res; + } + + *out = target->data; + + return vieter_tree_ok; +} + +vieter_tree_node *vieter_tree_node_successor(vieter_tree_node *node) { + if ((node->left != NULL) ^ (node->right != NULL)) { + return node->left != NULL ? node->left : node->right; + } + + node = node->right; + + while (node->left != NULL) { + node = node->left; + } + + return node; +} + +vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, + uint64_t key) { + vieter_tree_node *target; + vieter_tree_error res = vieter_tree_node_search_node(&target, root, key); + + if (res != vieter_tree_ok) { + return res; + } + + *out = target->data; + + if (target->left == NULL && target->right == NULL) { + vieter_tree_node_add_child(target->parent, target->key, NULL); + + free(target); + } else if ((target->left == NULL) ^ (target->right == NULL)) { + vieter_tree_node *child = + target->left != NULL ? target->left : target->right; + + if (target->parent != NULL) { + vieter_tree_node_add_child(target->parent, child->key, child); + free(target); + } else { + vieter_tree_node_replace(target, child); + free(child); + } + + } else { + vieter_tree_node *replacement = target->right; + + while (replacement->left != NULL) { + replacement = replacement->left; + } + + // We use replacement->key here because the right child can be NULL, so + // reading its key isn't safe. Using replacement->key however, the child + // will still get placed into the right location because of how binary + // trees work. + vieter_tree_node_add_child(replacement->parent, replacement->key, + replacement->right); + + target->key = replacement->key; + target->data = replacement->data; + + free(replacement); + } + + return vieter_tree_ok; } diff --git a/src/tree/node.h b/src/tree/node.h index f22a965..68da70e 100644 --- a/src/tree/node.h +++ b/src/tree/node.h @@ -14,10 +14,15 @@ typedef struct vieter_tree_node { vieter_tree_node *vieter_tree_node_init(); -vieter_tree_error vieter_tree_node_insert(vieter_tree_node *node, uint64_t key, void *data); +vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, void *data); -vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *node, uint64_t key); +vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, vieter_tree_node *root, uint64_t key); +vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, uint64_t key); -vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *node, uint64_t key); +vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, uint64_t key); + +vieter_tree_node *vieter_tree_node_successor(vieter_tree_node *node); + +void vieter_tree_node_replace(vieter_tree_node *to_replace, vieter_tree_node *replacement); #endif diff --git a/test/tree/test_binary_tree.c b/test/tree/test_binary_tree.c index fd6bb1b..4b1ceba 100644 --- a/test/tree/test_binary_tree.c +++ b/test/tree/test_binary_tree.c @@ -17,16 +17,37 @@ void test_insert() { for (uint64_t i = 0; i < 25; i++) { TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); + TEST_SIZE(tree, i + 1); } void *out; for (uint64_t i = 0; i < 25; i++) { + TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_already_present); TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); } } +void test_remove() { + vieter_tree *tree = vieter_tree_init(); + + for (uint64_t i = 0; i < 25; i++) { + TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); + } + + void *out; + + for (uint64_t i = 0; i < 25; i++) { + TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); + TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok); + TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_not_present); + } +} + TEST_LIST = { + {"test_init", test_init}, + {"test_insert", test_insert}, + {"test_remove", test_remove}, {NULL, NULL} }; From 910d7bc3bbceb6b820c2e5d5413604c9a999f869 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Fri, 20 Jan 2023 11:07:33 +0100 Subject: [PATCH 04/74] feat(tree): implement free function --- src/tree/node.c | 10 +++++---- src/tree/node.h | 4 ++-- src/tree/tree.c | 40 ++++++++++++++++++++++++++++++++++++ test/tree/test_binary_tree.c | 7 ++++++- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/tree/node.c b/src/tree/node.c index 131e932..568103e 100644 --- a/src/tree/node.c +++ b/src/tree/node.c @@ -4,6 +4,8 @@ vieter_tree_node *vieter_tree_node_init() { return calloc(1, sizeof(vieter_tree_node)); } +void vieter_tree_node_free(vieter_tree_node *node) { free(node); } + void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, vieter_tree_node *child) { if (parent == NULL) { @@ -121,17 +123,17 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, if (target->left == NULL && target->right == NULL) { vieter_tree_node_add_child(target->parent, target->key, NULL); - free(target); + vieter_tree_node_free(target); } else if ((target->left == NULL) ^ (target->right == NULL)) { vieter_tree_node *child = target->left != NULL ? target->left : target->right; if (target->parent != NULL) { vieter_tree_node_add_child(target->parent, child->key, child); - free(target); + vieter_tree_node_free(target); } else { vieter_tree_node_replace(target, child); - free(child); + vieter_tree_node_free(child); } } else { @@ -151,7 +153,7 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, target->key = replacement->key; target->data = replacement->data; - free(replacement); + vieter_tree_node_free(replacement); } return vieter_tree_ok; diff --git a/src/tree/node.h b/src/tree/node.h index 68da70e..dc8cce0 100644 --- a/src/tree/node.h +++ b/src/tree/node.h @@ -14,6 +14,8 @@ typedef struct vieter_tree_node { vieter_tree_node *vieter_tree_node_init(); +void vieter_tree_node_free(vieter_tree_node *node); + vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, void *data); vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, vieter_tree_node *root, uint64_t key); @@ -21,8 +23,6 @@ vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, ui vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, uint64_t key); -vieter_tree_node *vieter_tree_node_successor(vieter_tree_node *node); - void vieter_tree_node_replace(vieter_tree_node *to_replace, vieter_tree_node *replacement); #endif diff --git a/src/tree/tree.c b/src/tree/tree.c index 725fcda..c2c7aa7 100644 --- a/src/tree/tree.c +++ b/src/tree/tree.c @@ -57,3 +57,43 @@ vieter_tree_error vieter_tree_remove(void **out, vieter_tree *tree, return vieter_tree_ok; } + +void vieter_tree_free(vieter_tree *tree) { + if (tree->size == 0) { + goto end; + } + + uint64_t capacity = 4; + uint64_t size = 1; + vieter_tree_node **stack = malloc(capacity * sizeof(vieter_tree_node *)); + stack[0] = tree->root; + + vieter_tree_node *node; + + while (size > 0) { + node = stack[size - 1]; + size--; + + if (size + 2 > capacity) { + capacity *= 2; + stack = realloc(stack, capacity * sizeof(vieter_tree_node *)); + } + + if (node->left != NULL) { + stack[size] = node->left; + size++; + } + + if (node->right != NULL) { + stack[size] = node->right; + size++; + } + + vieter_tree_node_free(node); + } + + free(stack); + +end: + free(tree); +} diff --git a/test/tree/test_binary_tree.c b/test/tree/test_binary_tree.c index 4b1ceba..7e85ebe 100644 --- a/test/tree/test_binary_tree.c +++ b/test/tree/test_binary_tree.c @@ -9,7 +9,7 @@ void test_init() { vieter_tree *tree = vieter_tree_init(); TEST_CHECK(tree != NULL); TEST_SIZE(tree, 0); - /* vieter_tree_free(tree); */ + vieter_tree_free(tree); } void test_insert() { @@ -27,6 +27,8 @@ void test_insert() { TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_already_present); TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); } + + vieter_tree_free(tree); } void test_remove() { @@ -42,7 +44,10 @@ void test_remove() { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_not_present); + TEST_SIZE(tree, 25 - i - 1); } + + vieter_tree_free(tree); } TEST_LIST = { From 41bc6516fa799fd91d7d2fba6a6d01bfb6950e3e Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Fri, 20 Jan 2023 12:08:05 +0100 Subject: [PATCH 05/74] feat(tree): add node bit flags support --- src/tree/balancing.c | 3 +++ src/tree/balancing.h | 8 ++++++++ src/tree/node.c | 12 ++++++++++++ src/tree/node.h | 12 ++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 src/tree/balancing.c create mode 100644 src/tree/balancing.h diff --git a/src/tree/balancing.c b/src/tree/balancing.c new file mode 100644 index 0000000..85ae1a3 --- /dev/null +++ b/src/tree/balancing.c @@ -0,0 +1,3 @@ +#include "balancing.h" + +void vieter_tree_node_balance_after_insert(vieter_tree_node *node) {} diff --git a/src/tree/balancing.h b/src/tree/balancing.h new file mode 100644 index 0000000..3e4c6bc --- /dev/null +++ b/src/tree/balancing.h @@ -0,0 +1,8 @@ +#ifndef VIETER_TREE_BALANCING +#define VIETER_TREE_BALANCING + +#include "node.h" + +void vieter_tree_node_balance_after_insert(vieter_tree_node *node); + +#endif diff --git a/src/tree/node.c b/src/tree/node.c index 568103e..b36feed 100644 --- a/src/tree/node.c +++ b/src/tree/node.c @@ -158,3 +158,15 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, return vieter_tree_ok; } + +void vieter_tree_node_set(vieter_tree_node *node, vieter_node_flag flag) { + node->flags |= flag; +} + +void vieter_tree_node_unset(vieter_tree_node *node, vieter_node_flag flag) { + node->flags &= ~flag; +} + +bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag) { + return (node->flags & flag) != 0; +} diff --git a/src/tree/node.h b/src/tree/node.h index dc8cce0..2db2145 100644 --- a/src/tree/node.h +++ b/src/tree/node.h @@ -3,6 +3,13 @@ #include "vieter_tree.h" #include +#include + +#define VIETER_NODE_BLACK ((uint8_t)1) + +typedef enum vieter_node_flag { + vieter_node_black = ((uint8_t)1) << 0 +} vieter_node_flag; typedef struct vieter_tree_node { uint64_t key; @@ -10,6 +17,7 @@ typedef struct vieter_tree_node { struct vieter_tree_node *parent; struct vieter_tree_node *left; struct vieter_tree_node *right; + uint8_t flags; } vieter_tree_node; vieter_tree_node *vieter_tree_node_init(); @@ -25,4 +33,8 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, ui void vieter_tree_node_replace(vieter_tree_node *to_replace, vieter_tree_node *replacement); +void vieter_tree_node_set(vieter_tree_node *node, vieter_node_flag flag); +void vieter_tree_node_unset(vieter_tree_node *node, vieter_node_flag flag); +bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag); + #endif From 1c591ac42348322d5309cb51c5f4d309bea8997f Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Fri, 20 Jan 2023 13:23:53 +0100 Subject: [PATCH 06/74] feat(tree): first attempt at balanced inserts --- src/tree/balancing.c | 94 +++++++++++++++++++++++++++++++++++++++++++- src/tree/node.c | 16 +------- src/tree/node.h | 3 ++ src/tree/tree.c | 1 + 4 files changed, 99 insertions(+), 15 deletions(-) diff --git a/src/tree/balancing.c b/src/tree/balancing.c index 85ae1a3..b7466ea 100644 --- a/src/tree/balancing.c +++ b/src/tree/balancing.c @@ -1,3 +1,95 @@ #include "balancing.h" -void vieter_tree_node_balance_after_insert(vieter_tree_node *node) {} +vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { + vieter_tree_node *parent = node->parent; + vieter_tree_node *grand_parent = parent->parent; + vieter_tree_node *grand_grand_parent = grand_parent->parent; + vieter_tree_node *root, *left, *right; + vieter_tree_node *children[4]; + + if (node->key < parent->key && parent->key < grand_parent->key) { + root = parent; + left = node; + right = grand_parent; + + children[0] = node->left; + children[1] = node->right; + children[2] = parent->right; + children[3] = grand_parent->right; + } else if (node->key < parent->key && parent->key > grand_parent->key) { + root = node; + left = grand_parent; + right = parent; + + children[0] = grand_parent->left; + children[1] = node->left; + children[2] = node->right; + children[3] = parent->right; + } else if (node->key > parent->key && parent->key < grand_parent->key) { + root = node; + left = parent; + right = grand_parent; + + children[0] = parent->left; + children[1] = node->left; + children[2] = node->right; + children[3] = grand_parent->right; + } else { + root = parent; + left = grand_parent; + right = node; + + children[0] = grand_parent->left; + children[1] = parent->left; + children[2] = node->left; + children[3] = node->right; + } + + vieter_tree_node_set(left, vieter_node_black); + vieter_tree_node_set(right, vieter_node_black); + vieter_tree_node_unset(root, vieter_node_black); + + left->left = children[0]; + left->right = children[1]; + + if (children[0] != NULL) + children[0]->parent = left; + + if (children[1] != NULL) + children[1]->parent = left; + + right->left = children[2]; + right->right = children[3]; + + if (children[2] != NULL) + children[2]->parent = right; + + if (children[3] != NULL) + children[3]->parent = right; + + root->left = left; + root->right = right; + left->parent = root; + right->parent = root; + + if (grand_grand_parent != NULL) { + vieter_tree_node_add_child(grand_grand_parent, root->key, root); + } else { + root->parent = NULL; + } + + return root; +} + +void vieter_tree_node_balance_after_insert(vieter_tree_node *node) { + while (!vieter_tree_node_get(node, vieter_node_black) && + node->parent != NULL && + !vieter_tree_node_get(node->parent, vieter_node_black)) { + node = vieter_tree_node_balance(node); + } + + // The root must always be black + if (node->parent == NULL) { + vieter_tree_node_set(node, vieter_node_black); + } +} diff --git a/src/tree/node.c b/src/tree/node.c index b36feed..d6c2b6d 100644 --- a/src/tree/node.c +++ b/src/tree/node.c @@ -1,4 +1,5 @@ #include "node.h" +#include "balancing.h" vieter_tree_node *vieter_tree_node_init() { return calloc(1, sizeof(vieter_tree_node)); @@ -55,6 +56,7 @@ vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, new_node->data = data; vieter_tree_node_add_child(parent, key, new_node); + vieter_tree_node_balance_after_insert(new_node); return vieter_tree_ok; } @@ -95,20 +97,6 @@ vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, return vieter_tree_ok; } -vieter_tree_node *vieter_tree_node_successor(vieter_tree_node *node) { - if ((node->left != NULL) ^ (node->right != NULL)) { - return node->left != NULL ? node->left : node->right; - } - - node = node->right; - - while (node->left != NULL) { - node = node->left; - } - - return node; -} - vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, uint64_t key) { vieter_tree_node *target; diff --git a/src/tree/node.h b/src/tree/node.h index 2db2145..522ee59 100644 --- a/src/tree/node.h +++ b/src/tree/node.h @@ -37,4 +37,7 @@ void vieter_tree_node_set(vieter_tree_node *node, vieter_node_flag flag); void vieter_tree_node_unset(vieter_tree_node *node, vieter_node_flag flag); bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag); +void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, + vieter_tree_node *child); + #endif diff --git a/src/tree/tree.c b/src/tree/tree.c index c2c7aa7..d2579e6 100644 --- a/src/tree/tree.c +++ b/src/tree/tree.c @@ -16,6 +16,7 @@ vieter_tree_error vieter_tree_insert(vieter_tree *tree, uint64_t key, tree->root = vieter_tree_node_init(); tree->root->key = key; tree->root->data = data; + vieter_tree_node_set(tree->root, vieter_node_black); tree->size = 1; return vieter_tree_ok; From 1ce3b47edf0bdc4789f09848544c9103dd1922cd Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Fri, 20 Jan 2023 15:44:32 +0100 Subject: [PATCH 07/74] feat(tree): remove works --- src/tree/balancing.c | 49 ++++++++++++++++++++++++------------ src/tree/node.c | 12 ++++++--- test/tree/test_binary_tree.c | 10 ++++---- 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/tree/balancing.c b/src/tree/balancing.c index b7466ea..9f9d896 100644 --- a/src/tree/balancing.c +++ b/src/tree/balancing.c @@ -3,22 +3,35 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { vieter_tree_node *parent = node->parent; vieter_tree_node *grand_parent = parent->parent; - vieter_tree_node *grand_grand_parent = grand_parent->parent; - vieter_tree_node *root, *left, *right; + vieter_tree_node *root = grand_parent; + vieter_tree_node *left, *right; vieter_tree_node *children[4]; + uint64_t key_root = root->key; + void *data_root = root->data; + if (node->key < parent->key && parent->key < grand_parent->key) { - root = parent; + root->key = parent->key; + root->data = parent->data; + + parent->key = key_root; + parent->data = data_root; + left = node; - right = grand_parent; + right = parent; children[0] = node->left; children[1] = node->right; children[2] = parent->right; children[3] = grand_parent->right; } else if (node->key < parent->key && parent->key > grand_parent->key) { - root = node; - left = grand_parent; + root->key = node->key; + root->data = node->data; + + node->key = key_root; + node->data = data_root; + + left = node; right = parent; children[0] = grand_parent->left; @@ -26,17 +39,27 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { children[2] = node->right; children[3] = parent->right; } else if (node->key > parent->key && parent->key < grand_parent->key) { - root = node; + root->key = node->key; + root->data = node->data; + + node->key = key_root; + node->data = data_root; + left = parent; - right = grand_parent; + right = node; children[0] = parent->left; children[1] = node->left; children[2] = node->right; children[3] = grand_parent->right; } else { - root = parent; - left = grand_parent; + root->key = parent->key; + root->data = parent->data; + + parent->key = key_root; + parent->data = data_root; + + left = parent; right = node; children[0] = grand_parent->left; @@ -72,12 +95,6 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { left->parent = root; right->parent = root; - if (grand_grand_parent != NULL) { - vieter_tree_node_add_child(grand_grand_parent, root->key, root); - } else { - root->parent = NULL; - } - return root; } diff --git a/src/tree/node.c b/src/tree/node.c index d6c2b6d..0d74773 100644 --- a/src/tree/node.c +++ b/src/tree/node.c @@ -24,12 +24,18 @@ void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, } } -void vieter_tree_node_replace(vieter_tree_node *to_replace, - vieter_tree_node *replacement) { +void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, + vieter_tree_node *replacement) { to_replace->key = replacement->key; to_replace->data = replacement->data; to_replace->left = replacement->left; to_replace->right = replacement->right; + + if (to_replace->left != NULL) + to_replace->left->parent = to_replace; + + if (to_replace->right != NULL) + to_replace->right->parent = to_replace; } vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, @@ -120,7 +126,7 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, vieter_tree_node_add_child(target->parent, child->key, child); vieter_tree_node_free(target); } else { - vieter_tree_node_replace(target, child); + vieter_tree_node_replace_with_child(target, child); vieter_tree_node_free(child); } diff --git a/test/tree/test_binary_tree.c b/test/tree/test_binary_tree.c index 7e85ebe..aa7fc0f 100644 --- a/test/tree/test_binary_tree.c +++ b/test/tree/test_binary_tree.c @@ -15,14 +15,14 @@ void test_init() { void test_insert() { vieter_tree *tree = vieter_tree_init(); - for (uint64_t i = 0; i < 25; i++) { + for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); TEST_SIZE(tree, i + 1); } void *out; - for (uint64_t i = 0; i < 25; i++) { + for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_already_present); TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); @@ -34,17 +34,17 @@ void test_insert() { void test_remove() { vieter_tree *tree = vieter_tree_init(); - for (uint64_t i = 0; i < 25; i++) { + for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); } void *out; - for (uint64_t i = 0; i < 25; i++) { + for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_not_present); - TEST_SIZE(tree, 25 - i - 1); + TEST_SIZE(tree, 250 - i - 1); } vieter_tree_free(tree); From e4e92b3e57dcad6564c1109c4b6c3b70f981f43b Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sun, 22 Jan 2023 09:42:08 +0100 Subject: [PATCH 08/74] refactor(tree): proper filenames --- src/tree/{tree.c => vieter_tree.c} | 2 +- src/tree/{balancing.c => vieter_tree_balancing.c} | 2 +- src/tree/{balancing.h => vieter_tree_balancing.h} | 2 +- src/tree/{node.c => vieter_tree_node.c} | 4 ++-- src/tree/{node.h => vieter_tree_node.h} | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename src/tree/{tree.c => vieter_tree.c} (98%) rename src/tree/{balancing.c => vieter_tree_balancing.c} (98%) rename src/tree/{balancing.h => vieter_tree_balancing.h} (82%) rename src/tree/{node.c => vieter_tree_node.c} (98%) rename src/tree/{node.h => vieter_tree_node.h} (100%) diff --git a/src/tree/tree.c b/src/tree/vieter_tree.c similarity index 98% rename from src/tree/tree.c rename to src/tree/vieter_tree.c index d2579e6..72360b0 100644 --- a/src/tree/tree.c +++ b/src/tree/vieter_tree.c @@ -1,5 +1,5 @@ -#include "node.h" #include "vieter_tree.h" +#include "vieter_tree_node.h" struct vieter_tree { uint64_t size; diff --git a/src/tree/balancing.c b/src/tree/vieter_tree_balancing.c similarity index 98% rename from src/tree/balancing.c rename to src/tree/vieter_tree_balancing.c index 9f9d896..56047a0 100644 --- a/src/tree/balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -1,4 +1,4 @@ -#include "balancing.h" +#include "vieter_tree_balancing.h" vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { vieter_tree_node *parent = node->parent; diff --git a/src/tree/balancing.h b/src/tree/vieter_tree_balancing.h similarity index 82% rename from src/tree/balancing.h rename to src/tree/vieter_tree_balancing.h index 3e4c6bc..4492588 100644 --- a/src/tree/balancing.h +++ b/src/tree/vieter_tree_balancing.h @@ -1,7 +1,7 @@ #ifndef VIETER_TREE_BALANCING #define VIETER_TREE_BALANCING -#include "node.h" +#include "vieter_tree_node.h" void vieter_tree_node_balance_after_insert(vieter_tree_node *node); diff --git a/src/tree/node.c b/src/tree/vieter_tree_node.c similarity index 98% rename from src/tree/node.c rename to src/tree/vieter_tree_node.c index 0d74773..40407a3 100644 --- a/src/tree/node.c +++ b/src/tree/vieter_tree_node.c @@ -1,5 +1,5 @@ -#include "node.h" -#include "balancing.h" +#include "vieter_tree_node.h" +#include "vieter_tree_balancing.h" vieter_tree_node *vieter_tree_node_init() { return calloc(1, sizeof(vieter_tree_node)); diff --git a/src/tree/node.h b/src/tree/vieter_tree_node.h similarity index 100% rename from src/tree/node.h rename to src/tree/vieter_tree_node.h From 276fa99e4b7b703379fe50cf1c906b20188aa1da Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 13:00:33 +0100 Subject: [PATCH 09/74] refactor: Add original .c package files by Jef. --- include/dynarray.h | 19 +++++ include/package.h | 26 +++++++ include/package_info.h | 39 +++++++++++ src/package/dynarray.c | 55 +++++++++++++++ src/package/package.c | 98 ++++++++++++++++++++++++++ src/package/package_info.c | 139 +++++++++++++++++++++++++++++++++++++ 6 files changed, 376 insertions(+) create mode 100644 include/dynarray.h create mode 100644 include/package.h create mode 100644 include/package_info.h create mode 100644 src/package/dynarray.c create mode 100644 src/package/package.c create mode 100644 src/package/package_info.c diff --git a/include/dynarray.h b/include/dynarray.h new file mode 100644 index 0000000..e552ec4 --- /dev/null +++ b/include/dynarray.h @@ -0,0 +1,19 @@ +#ifndef VIETER_DYNARRAY +#define VIETER_DYNARRAY + +#include +#include + +typedef struct dyn_array DynArray; + +DynArray *dynarray_init(size_t initial_capacity); +void dynarray_add(DynArray *da, const char * s); +void dynarray_free(DynArray *da); + +/** + * Convert a DynArray into an array by freeing all its surrounding components + * and returning the underlying array pointer. + */ +char **dynarray_convert(DynArray *da); + +#endif diff --git a/include/package.h b/include/package.h new file mode 100644 index 0000000..09e91bd --- /dev/null +++ b/include/package.h @@ -0,0 +1,26 @@ +#ifndef VIETER_PACKAGE +#define VIETER_PACKAGE + +#include +#include +#include +#include + +#include "archive.h" +#include "archive_entry.h" + +#include "package_info.h" +#include "dynarray.h" + +typedef struct pkg { + char *path; + PkgInfo *info; + DynArray *files; + int compression; +} Pkg; + +Pkg *package_read_archive(const char *pkg_path); +void package_free(Pkg ** ptp); +char *package_to_description(Pkg *pkg); + +#endif diff --git a/include/package_info.h b/include/package_info.h new file mode 100644 index 0000000..d71386e --- /dev/null +++ b/include/package_info.h @@ -0,0 +1,39 @@ +#ifndef VIETER_PACKAGE_INFO +#define VIETER_PACKAGE_INFO + +#define FREE_STRING(sp) if (sp != NULL) free(sp) + +#include + +#include "dynarray.h" + +typedef struct pkg_info { + char *name; + char *base; + char *version; + char *description; + int64_t size; + int64_t csize; + char *url; + char *arch; + int64_t build_date; + char *packager; + char *pgpsig; + int64_t pgpsigsize; + + DynArray *groups; + DynArray *licenses; + DynArray *replaces; + DynArray *depends; + DynArray *conflicts; + DynArray *provides; + DynArray *optdepends; + DynArray *makedepends; + DynArray *checkdepends; +} PkgInfo; + +PkgInfo *package_info_init(); +int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); +void package_info_free(PkgInfo *pkg_info); + +#endif diff --git a/src/package/dynarray.c b/src/package/dynarray.c new file mode 100644 index 0000000..480c08f --- /dev/null +++ b/src/package/dynarray.c @@ -0,0 +1,55 @@ +#include "dynarray.h" + +struct dyn_array { + char **array; + size_t size; + size_t capacity; +}; + +DynArray *dynarray_init(size_t initial_capacity) { + DynArray *da = malloc(sizeof(DynArray)); + da->size = 0; + da->capacity = initial_capacity; + + return da; +} + +void dynarray_add(DynArray *da, const char *s) { + // An empty dynarray does not have an allocated internal array yet + if (da->size == 0) { + da->array = malloc(sizeof(char*) * da->capacity); + } + // Double array size if it's full + else if (da->size == da->capacity) { + da->array = realloc(da->array, da->capacity * 2); + da->capacity *= 2; + } + + da->array[da->size] = strdup(s); + da->size++; +} + +void dynarray_free(DynArray *da) { + if (da == NULL) { + return; + } + + if (da->array != NULL) { + for (size_t i = 0; i < da->size; i++) { + free(da->array[i]); + } + + free(da->array); + } + + free(da); +} + +char **dynarray_convert(DynArray *da) { + char **array = da->array; + + da->array = NULL; + dynarray_free(da); + + return array; +} diff --git a/src/package/package.c b/src/package/package.c new file mode 100644 index 0000000..a098abb --- /dev/null +++ b/src/package/package.c @@ -0,0 +1,98 @@ +#include "package.h" + +static char *ignored_names[5] = { + ".BUILDINFO", + ".INSTALL", + ".MTREE", + ".PKGINFO", + ".CHANGELOG" +}; +static int ignored_words_len = sizeof(ignored_names) / sizeof(char *); + +Pkg *package_init() { + return calloc(sizeof(PkgInfo), 1); +} + +Pkg *package_read_archive(const char *pkg_path) { + struct archive *a = archive_read_new(); + struct archive_entry *entry = archive_entry_new(); + + // These three are the most commonly used compression methods + archive_read_support_filter_zstd(a); + archive_read_support_filter_gzip(a); + archive_read_support_filter_xz(a); + + // Contents should always be a tarball + archive_read_support_format_tar(a); + + // TODO where does this 10240 come from? + int r = archive_read_open_filename(a, pkg_path, 10240); + + // Exit early if we weren't able to successfully open the archive for reading + if (r != ARCHIVE_OK) { + return NULL; + } + + int compression_code = archive_filter_code(a, 0); + const char *path_name; + + PkgInfo *pkg_info; + DynArray *files = dynarray_init(16); + + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + path_name = archive_entry_pathname(entry); + + bool ignore = false; + + for (size_t i = 0; i < ignored_words_len; i++) { + if (strcmp(path_name, ignored_names[i]) == 0) { + ignore = true; + break; + } + } + + if (!ignore) { + dynarray_add(files, path_name); + } + + if (strcmp(path_name, ".PKGINFO") == 0) { + // Read data of file into memory buffer + int size = archive_entry_size(entry); + char *buf = malloc(size); + archive_read_data(a, buf, size); + + // Parse package info string into a struct + pkg_info = package_info_init(); + package_info_parse(pkg_info, buf); + + free(buf); + } else { + archive_read_data_skip(a); + } + } + + // Get size of file + struct stat stats; + + if (stat(pkg_path, &stats) != 0) { + return NULL; + } + + pkg_info->csize = stats.st_size; + + archive_read_free(a); + archive_entry_free(entry); + + // Create final return value + Pkg *pkg = package_init(); + pkg->path = strdup(pkg_path); + pkg->info = pkg_info; + pkg->files = files; + pkg->compression = compression_code; + + return pkg; +} + +char *package_to_description(Pkg *pkg) { + +} diff --git a/src/package/package_info.c b/src/package/package_info.c new file mode 100644 index 0000000..1202485 --- /dev/null +++ b/src/package/package_info.c @@ -0,0 +1,139 @@ +#include + +#include "package_info.h" + +PkgInfo *package_info_init() { + return calloc(1, sizeof(PkgInfo)); +} + +void package_info_free(PkgInfo *pkg_info) { + FREE_STRING(pkg_info->name); + FREE_STRING(pkg_info->base); + FREE_STRING(pkg_info->version); + FREE_STRING(pkg_info->description); + FREE_STRING(pkg_info->url); + FREE_STRING(pkg_info->arch); + FREE_STRING(pkg_info->packager); + FREE_STRING(pkg_info->pgpsig); + + dynarray_free(pkg_info->groups); + dynarray_free(pkg_info->licenses); + dynarray_free(pkg_info->replaces); + dynarray_free(pkg_info->depends); + dynarray_free(pkg_info->conflicts); + dynarray_free(pkg_info->provides); + dynarray_free(pkg_info->optdepends); + dynarray_free(pkg_info->makedepends); + dynarray_free(pkg_info->checkdepends); + + free(pkg_info); +} + +/** + * Advance the pointer until all spaces are skipped. + */ +static inline char *trim_spaces_front(char *ptr) { + while (ptr[0] == ' ') { + ptr++; + } + + return ptr; +} + +/** + * Given a string pointer in the middle of a string, move over all spaces in the + * given direction. The final space is replaced with a NULL-byte. + */ +static inline void trim_spaces_back(char *ptr) { + if (ptr[0] != ' ') { + return; + } + + while (ptr[-1] == ' ') { + ptr--; + } + + ptr[0] = '\0'; +} + +#define PKG_INFO_STRING(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = strdup(value_ptr); goto advance; } +#define PKG_INFO_INT(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = atoi(value_ptr); goto advance; } +#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { \ + if (pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ + dynarray_add(pkg_info->field, value_ptr); goto advance; \ +} + +int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { + char *offset_ptr, *equals_ptr, *key_ptr, *value_ptr; + + bool end = false; + + // Iterate over all lines in file + while (!end) { + // This pointer will always point to the final character of the + // current line, be it the position of a newline or the NULL byte at + // the end of the entire string + offset_ptr = strchr(pkg_info_str, '\n'); + + // We replace the newline with a NULL byte. Now we know the line runs + // until the next NULL byte. + if (offset_ptr != NULL) { + offset_ptr[0] = '\0'; + } else { + // Advance pointer to the NULL byte of the string + offset_ptr = pkg_info_str + 1; + + while (*offset_ptr != '\0') { + offset_ptr++; + } + + end = true; + } + + // Skip comment lines + if (pkg_info_str[0] == '#') { + goto advance; + } + + equals_ptr = strchr(pkg_info_str, '='); + + // If a line doesn't contain an equals sign, the file is invalid + if (equals_ptr == NULL) { + return 1; + } + + // Trim whitespace from key + key_ptr = trim_spaces_front(pkg_info_str); + trim_spaces_back(equals_ptr - 1); + + // Trim spaces from value + value_ptr = trim_spaces_front(equals_ptr + 1); + trim_spaces_back(offset_ptr - 1); + + // Match key + PKG_INFO_STRING("pkgname", name); + PKG_INFO_STRING("pkgbase", base); + PKG_INFO_STRING("pkgver", version); + PKG_INFO_STRING("pkgdesc", description); + PKG_INFO_INT("size", size); + PKG_INFO_STRING("url", url); + PKG_INFO_STRING("arch", arch); + PKG_INFO_INT("builddate", build_date); + PKG_INFO_STRING("packager", packager); + PKG_INFO_STRING("pgpsig", pgpsig); + PKG_INFO_INT("pgpsigsize", pgpsigsize); + PKG_INFO_ARRAY("group", groups); + PKG_INFO_ARRAY("license", licenses); + PKG_INFO_ARRAY("replaces", replaces); + PKG_INFO_ARRAY("depend", depends); + PKG_INFO_ARRAY("optdepend", optdepends); + PKG_INFO_ARRAY("makedepend", makedepends); + PKG_INFO_ARRAY("checkdepend", checkdepends); + +advance: + pkg_info_str = offset_ptr + 1; + continue; + } + + return 0; +} From a60c9235479daa66faa99f6cfed05c9a188ac665 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 16:22:22 +0100 Subject: [PATCH 10/74] refactor: Modified .PKGINFO parser not to rely on gotos and continues. Parser is now optimistic and assumes .PKGINFO file is valid. After my changes to the macros, they still feel a bit hacky, but I'm content with them. I also changed the parser to assume the .PKGINFO files are always valid because they are automatically generated. The parser also assumes the same fields will always appear in the same fixed order. I made this change after checking how makepkg generated this file. --- include/package_info.h | 2 +- src/package/package_info.c | 152 +++++++++++-------------------------- 2 files changed, 47 insertions(+), 107 deletions(-) diff --git a/include/package_info.h b/include/package_info.h index d71386e..b1388a2 100644 --- a/include/package_info.h +++ b/include/package_info.h @@ -33,7 +33,7 @@ typedef struct pkg_info { } PkgInfo; PkgInfo *package_info_init(); -int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); +void package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); void package_info_free(PkgInfo *pkg_info); #endif diff --git a/src/package/package_info.c b/src/package/package_info.c index 1202485..5e1986d 100644 --- a/src/package/package_info.c +++ b/src/package/package_info.c @@ -2,6 +2,31 @@ #include "package_info.h" +#define PKG_INFO_STRING(key_ptr, field) if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ + value_ptr += strlen(key_ptr);\ + tail_ptr = strchr(value_ptr, '\n');\ + tail_ptr[0] = '\0'; \ + pkg_info->field = strdup(value_ptr); \ + tail_ptr[0] = '\n'; \ +} value_ptr = tail_ptr; + +#define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr);\ + tail_ptr = strchr(value_ptr, '\n');\ + tail_ptr[0] = '\0'; \ + pkg_info->field = atoi(value_ptr); \ + tail_ptr[0] = '\n'; \ + value_ptr = tail_ptr; + +#define PKG_INFO_ARRAY(key_ptr, field) while((value_ptr = strstr(value_ptr, key_ptr)) != NULL){ \ + value_ptr = value_ptr + strlen(key_ptr);\ + tail_ptr = strchr(value_ptr, '\n'); \ + tail_ptr[0] = '\0'; \ + if(pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ + dynarray_add(pkg_info->field, value_ptr); \ + tail_ptr[0] = '\n'; \ + value_ptr = tail_ptr;\ +} value_ptr = tail_ptr; + PkgInfo *package_info_init() { return calloc(1, sizeof(PkgInfo)); } @@ -29,111 +54,26 @@ void package_info_free(PkgInfo *pkg_info) { free(pkg_info); } -/** - * Advance the pointer until all spaces are skipped. - */ -static inline char *trim_spaces_front(char *ptr) { - while (ptr[0] == ' ') { - ptr++; - } +void package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { + char *value_ptr = pkg_info_str, *tail_ptr; + + PKG_INFO_STRING("\npkgname = ", name); + PKG_INFO_STRING("\npkgbase = ", base); + PKG_INFO_STRING("\npkgver = ", version); + PKG_INFO_STRING("\npkgdesc = ", description); + PKG_INFO_STRING("\nurl = ", url); + PKG_INFO_INT("\nbuilddate = ", build_date); + PKG_INFO_STRING("\npackager = ", packager); + PKG_INFO_INT("\nsize = ", size); + PKG_INFO_STRING("\narch = ", arch); + PKG_INFO_ARRAY("\nlicense = ", licenses); + PKG_INFO_ARRAY("\nreplaces = ", replaces); + PKG_INFO_ARRAY("\ngroup = ", groups); + PKG_INFO_ARRAY("\nconflict = ", conflicts); + PKG_INFO_ARRAY("\nprovides = ", provides); + PKG_INFO_ARRAY("\ndepend = ", depends); + PKG_INFO_ARRAY("\noptdepend = ", optdepends); + PKG_INFO_ARRAY("\nmakedepend = ", makedepends); + PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends); - return ptr; -} - -/** - * Given a string pointer in the middle of a string, move over all spaces in the - * given direction. The final space is replaced with a NULL-byte. - */ -static inline void trim_spaces_back(char *ptr) { - if (ptr[0] != ' ') { - return; - } - - while (ptr[-1] == ' ') { - ptr--; - } - - ptr[0] = '\0'; -} - -#define PKG_INFO_STRING(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = strdup(value_ptr); goto advance; } -#define PKG_INFO_INT(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = atoi(value_ptr); goto advance; } -#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { \ - if (pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ - dynarray_add(pkg_info->field, value_ptr); goto advance; \ -} - -int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { - char *offset_ptr, *equals_ptr, *key_ptr, *value_ptr; - - bool end = false; - - // Iterate over all lines in file - while (!end) { - // This pointer will always point to the final character of the - // current line, be it the position of a newline or the NULL byte at - // the end of the entire string - offset_ptr = strchr(pkg_info_str, '\n'); - - // We replace the newline with a NULL byte. Now we know the line runs - // until the next NULL byte. - if (offset_ptr != NULL) { - offset_ptr[0] = '\0'; - } else { - // Advance pointer to the NULL byte of the string - offset_ptr = pkg_info_str + 1; - - while (*offset_ptr != '\0') { - offset_ptr++; - } - - end = true; - } - - // Skip comment lines - if (pkg_info_str[0] == '#') { - goto advance; - } - - equals_ptr = strchr(pkg_info_str, '='); - - // If a line doesn't contain an equals sign, the file is invalid - if (equals_ptr == NULL) { - return 1; - } - - // Trim whitespace from key - key_ptr = trim_spaces_front(pkg_info_str); - trim_spaces_back(equals_ptr - 1); - - // Trim spaces from value - value_ptr = trim_spaces_front(equals_ptr + 1); - trim_spaces_back(offset_ptr - 1); - - // Match key - PKG_INFO_STRING("pkgname", name); - PKG_INFO_STRING("pkgbase", base); - PKG_INFO_STRING("pkgver", version); - PKG_INFO_STRING("pkgdesc", description); - PKG_INFO_INT("size", size); - PKG_INFO_STRING("url", url); - PKG_INFO_STRING("arch", arch); - PKG_INFO_INT("builddate", build_date); - PKG_INFO_STRING("packager", packager); - PKG_INFO_STRING("pgpsig", pgpsig); - PKG_INFO_INT("pgpsigsize", pgpsigsize); - PKG_INFO_ARRAY("group", groups); - PKG_INFO_ARRAY("license", licenses); - PKG_INFO_ARRAY("replaces", replaces); - PKG_INFO_ARRAY("depend", depends); - PKG_INFO_ARRAY("optdepend", optdepends); - PKG_INFO_ARRAY("makedepend", makedepends); - PKG_INFO_ARRAY("checkdepend", checkdepends); - -advance: - pkg_info_str = offset_ptr + 1; - continue; - } - - return 0; } From 6d731d788c3a5067c37abaa8d103b8907c0d6662 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 17:17:18 +0100 Subject: [PATCH 11/74] refactor: Created function that will return the char ** (originally char *) that will be used to make the description file. Also removed free that was resulting in a crash. --- include/package.h | 2 +- src/package/package.c | 49 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/include/package.h b/include/package.h index 09e91bd..dfb3a34 100644 --- a/include/package.h +++ b/include/package.h @@ -21,6 +21,6 @@ typedef struct pkg { Pkg *package_read_archive(const char *pkg_path); void package_free(Pkg ** ptp); -char *package_to_description(Pkg *pkg); +char **package_to_description(Pkg *pkg); #endif diff --git a/src/package/package.c b/src/package/package.c index a098abb..3b9c6f9 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -1,5 +1,20 @@ #include "package.h" +#define BUFF_SIZE 128 + +#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ + snprintf(aux, BUFF_SIZE, section, pkg_info->field); \ + dynarray_add(description, aux); \ +} +#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ + snprintf(aux, BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ + dynarray_add(description, aux); \ + while (pkg_info->field->array[i] != NULL) { \ + snprintf(aux, BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ + dynarray_add(description, aux); \ + } \ +} + static char *ignored_names[5] = { ".BUILDINFO", ".INSTALL", @@ -7,7 +22,7 @@ static char *ignored_names[5] = { ".PKGINFO", ".CHANGELOG" }; -static int ignored_words_len = sizeof(ignored_names) / sizeof(char *); +static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *); Pkg *package_init() { return calloc(sizeof(PkgInfo), 1); @@ -38,6 +53,7 @@ Pkg *package_read_archive(const char *pkg_path) { PkgInfo *pkg_info; DynArray *files = dynarray_init(16); + dynarray_add(files, "%FILES%"); while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { path_name = archive_entry_pathname(entry); @@ -81,7 +97,6 @@ Pkg *package_read_archive(const char *pkg_path) { pkg_info->csize = stats.st_size; archive_read_free(a); - archive_entry_free(entry); // Create final return value Pkg *pkg = package_init(); @@ -93,6 +108,34 @@ Pkg *package_read_archive(const char *pkg_path) { return pkg; } -char *package_to_description(Pkg *pkg) { +char **package_to_description(Pkg *pkg) { + PkgInfo *pkg_info = pkg->info; + + DynArray *description = dynarray_init(16); + + char aux[BUFF_SIZE]; + int i; + ADD_STRING("\n\n%%NAME%%\n%s", name); + ADD_STRING("-%s", version); + ADD_STRING("\n\n%%PKGBASE%%\n%s", base); + ADD_STRING("\n\n%%DESCRIPTION%%\n%s", description); + ADD_STRING("\n\n%%SIZE%%\n%ld", size); + ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); + ADD_STRING("\n\n%%URL%%\n%s", url); + ADD_STRING("\n\n%%ARCH%%\n%s", arch); + ADD_STRING("\n\n%%BUILD_DATE%%\n%ld", build_date); + ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); + + ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); + ADD_ARRAY("\n\n%%LICENSES%%\n%s", licenses); + ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces); + ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); + ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts); + ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides); + ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends); + ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); + ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); + + return description; } From 2d6ac2ac1978c7339abfab34383cf09ba8350d2d Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 17:24:03 +0100 Subject: [PATCH 12/74] fix: Took a very long time finding a very annyoing bug because realloc is the devil. --- include/dynarray.h | 5 +++++ src/package/dynarray.c | 11 +++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/dynarray.h b/include/dynarray.h index e552ec4..2ab4022 100644 --- a/include/dynarray.h +++ b/include/dynarray.h @@ -5,6 +5,11 @@ #include typedef struct dyn_array DynArray; +struct dyn_array { + char **array; + size_t capacity; + size_t size; +}; DynArray *dynarray_init(size_t initial_capacity); void dynarray_add(DynArray *da, const char * s); diff --git a/src/package/dynarray.c b/src/package/dynarray.c index 480c08f..a78e7ff 100644 --- a/src/package/dynarray.c +++ b/src/package/dynarray.c @@ -1,11 +1,5 @@ #include "dynarray.h" -struct dyn_array { - char **array; - size_t size; - size_t capacity; -}; - DynArray *dynarray_init(size_t initial_capacity) { DynArray *da = malloc(sizeof(DynArray)); da->size = 0; @@ -21,10 +15,11 @@ void dynarray_add(DynArray *da, const char *s) { } // Double array size if it's full else if (da->size == da->capacity) { - da->array = realloc(da->array, da->capacity * 2); + // if the realloc fails, access to memory in da->array is lost + da->array = realloc(da->array, sizeof(char*) * da->capacity * 2); da->capacity *= 2; } - + da->array[da->size] = strdup(s); da->size++; } From 2ce7a819a9aba909f0f4e78eb3a38baca7061275 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 22:15:07 +0100 Subject: [PATCH 13/74] refactor: Decided to not return char** in function that creates the package description after all, now returns char*. The method I was trying started to irk me when I thought of creating a test unit for it. Also fixed some other issues I found in the package_to_description function (SHA256SUM section still missing). --- include/package.h | 2 +- src/package/package.c | 74 ++++++++++++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/include/package.h b/include/package.h index dfb3a34..09e91bd 100644 --- a/include/package.h +++ b/include/package.h @@ -21,6 +21,6 @@ typedef struct pkg { Pkg *package_read_archive(const char *pkg_path); void package_free(Pkg ** ptp); -char **package_to_description(Pkg *pkg); +char *package_to_description(Pkg *pkg); #endif diff --git a/src/package/package.c b/src/package/package.c index 3b9c6f9..bd77f3e 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -1,18 +1,30 @@ #include "package.h" -#define BUFF_SIZE 128 +#define SMALL_BUFF_SIZE 128 #define ADD_STRING(section, field) if (pkg_info->field != 0) { \ - snprintf(aux, BUFF_SIZE, section, pkg_info->field); \ - dynarray_add(description, aux); \ + snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ + if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ + description = realloc(description, buff_size * 2);\ + buff_size *= 2; \ + } \ + strcat(description, aux); \ } #define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ - snprintf(aux, BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ - dynarray_add(description, aux); \ - while (pkg_info->field->array[i] != NULL) { \ - snprintf(aux, BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ - dynarray_add(description, aux); \ - } \ + snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ + if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ + description = realloc(description, buff_size * 2);\ + buff_size *= 2; \ + } \ + strcat(description, aux); \ + while (pkg_info->field->array[i] != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ + if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ + description = realloc(description, buff_size * 2);\ + buff_size *= 2; \ + } \ + strcat(description, aux); \ + } \ } static char *ignored_names[5] = { @@ -109,33 +121,43 @@ Pkg *package_read_archive(const char *pkg_path) { } -char **package_to_description(Pkg *pkg) { +char *package_to_description(Pkg *pkg) { PkgInfo *pkg_info = pkg->info; - DynArray *description = dynarray_init(16); - - char aux[BUFF_SIZE]; + size_t buff_size = 1024; + char aux[SMALL_BUFF_SIZE]; + char *description = malloc(sizeof(char) * buff_size); int i; - ADD_STRING("\n\n%%NAME%%\n%s", name); - ADD_STRING("-%s", version); - ADD_STRING("\n\n%%PKGBASE%%\n%s", base); - ADD_STRING("\n\n%%DESCRIPTION%%\n%s", description); - ADD_STRING("\n\n%%SIZE%%\n%ld", size); - ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); - ADD_STRING("\n\n%%URL%%\n%s", url); - ADD_STRING("\n\n%%ARCH%%\n%s", arch); - ADD_STRING("\n\n%%BUILD_DATE%%\n%ld", build_date); - ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); + // special case for FILENAME + // assuming .pkg.tar.zst; other formats are valid, this should account for that + snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version, + pkg_info->arch); + strcat(description, aux); + + ADD_STRING("\n\n%%NAME%%\n%s", name); + ADD_STRING("\n\n%%BASE%%\n%s", base); + ADD_STRING("\n\n%%VERSION%%\n%s", version); + ADD_STRING("\n\n%%DESC%%\n%s", description); ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); - ADD_ARRAY("\n\n%%LICENSES%%\n%s", licenses); + ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); + ADD_STRING("\n\n%%ISIZE%%\n%ld", size); + //SHA256SUM + ADD_STRING("\n\n%%URL%%\n%s", url); + ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses); + ADD_STRING("\n\n%%ARCH%%\n%s", arch); + ADD_STRING("\n\n%%BUILDDATE%%\n%ld", build_date); + ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces); - ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts); ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides); + ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends); ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); - return description; + snprintf(aux, SMALL_BUFF_SIZE, "\n\n"); + strcat(description, aux); + + return description; } From d1a8ba7737b8ee12d5078da657a245858195695b Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 23:10:53 +0100 Subject: [PATCH 14/74] refactor: Added SHA256 to package description file. --- src/package/package.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/package/package.c b/src/package/package.c index bd77f3e..932ac32 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -5,7 +5,7 @@ #define ADD_STRING(section, field) if (pkg_info->field != 0) { \ snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2);\ + description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ @@ -13,14 +13,14 @@ #define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2);\ + description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ while (pkg_info->field->array[i] != NULL) { \ snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2);\ + description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ @@ -120,6 +120,14 @@ Pkg *package_read_archive(const char *pkg_path) { return pkg; } +void sha256sum(Pkg *pkg, char *res) { + char command[SMALL_BUFF_SIZE]; + snprintf(command, SMALL_BUFF_SIZE, "sha256sum %s", pkg->path); + FILE *p = popen(command, "r"); + + fgets(res, 65, p); + pclose(p); +} char *package_to_description(Pkg *pkg) { PkgInfo *pkg_info = pkg->info; @@ -142,7 +150,16 @@ char *package_to_description(Pkg *pkg) { ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); ADD_STRING("\n\n%%ISIZE%%\n%ld", size); - //SHA256SUM + + char res[65]; + sha256sum(pkg, res); + snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", res); + if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { + description = realloc(description, buff_size * 2); + buff_size *= 2; + } + strcat(description, aux); + ADD_STRING("\n\n%%URL%%\n%s", url); ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses); ADD_STRING("\n\n%%ARCH%%\n%s", arch); From 10eb08b8e437e6295f422f13d08897ad685c5bd6 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Fri, 27 Jan 2023 22:23:23 +0000 Subject: [PATCH 15/74] chore: Rebase to dev branch with binomial heap PR. --- Makefile | 5 + src/package/package.c | 6 +- test/package/.PKGINFO | 22 ++ test/package/desc | 45 ++++ test/package/files | 243 ++++++++++++++++++ test/package/test_package.c | 86 +++++++ .../xcursor-dmz-0.4.5-2-any.pkg.tar.zst | Bin 0 -> 328282 bytes 7 files changed, 404 insertions(+), 3 deletions(-) create mode 100644 test/package/.PKGINFO create mode 100644 test/package/desc create mode 100644 test/package/files create mode 100644 test/package/test_package.c create mode 100644 test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst diff --git a/Makefile b/Makefile index 04c6dd3..ac56c97 100644 --- a/Makefile +++ b/Makefile @@ -71,9 +71,14 @@ build-test: $(BINS_TEST) # For simplicity, we link every object file to each of the test files. This # might be changed later if this starts to become too slow. +<<<<<<< HEAD $(BINS_TEST): %: %.c.o $(LIB) $(CC) \ $^ -o $@ +======= +$(BINS_TEST): %: %.c.o $(OBJS) + $(CC) $^ -larchive -o $@ +>>>>>>> c94ab92 (refactor: Add libarchive link to test compilation area of the Makefile. Created test units with xcursor-dmz as test package.) # Along with the include directory, each test includes $(TEST_DIR) (which # contains the acutest.h header file), and the src directory of the module it's diff --git a/src/package/package.c b/src/package/package.c index 932ac32..8d1565d 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -151,9 +151,9 @@ char *package_to_description(Pkg *pkg) { ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); ADD_STRING("\n\n%%ISIZE%%\n%ld", size); - char res[65]; - sha256sum(pkg, res); - snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", res); + char checksum[65]; + sha256sum(pkg, checksum); + snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum); if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { description = realloc(description, buff_size * 2); buff_size *= 2; diff --git a/test/package/.PKGINFO b/test/package/.PKGINFO new file mode 100644 index 0000000..7113061 --- /dev/null +++ b/test/package/.PKGINFO @@ -0,0 +1,22 @@ +# Generated by makepkg 6.0.2 +# using fakeroot version 1.30.1 +pkgname = xcursor-dmz +pkgbase = xcursor-dmz +pkgver = 0.4.5-2 +pkgdesc = Style neutral, scalable cursor theme +url = https://packages.debian.org/sid/dmz-cursor-theme +builddate = 1673751613 +packager = Unknown Packager +size = 3469584 +arch = any +license = MIT +replaces = test1 +group = x11 +conflict = test2 +conflict = test3 +provides = test4 +depend = test5 +depend = test6 +optdepend = test7 +makedepend = xorg-xcursorgen +checkdepend = test8 diff --git a/test/package/desc b/test/package/desc new file mode 100644 index 0000000..d583af1 --- /dev/null +++ b/test/package/desc @@ -0,0 +1,45 @@ +%FILENAME% +xcursor-dmz-0.4.5-2-any.pkg.tar.zst + +%NAME% +xcursor-dmz + +%BASE% +xcursor-dmz + +%VERSION% +0.4.5-2 + +%DESC% +Style neutral, scalable cursor theme + +%GROUPS% +x11 + +%CSIZE% +328282 + +%ISIZE% +3469584 + +%SHA256SUM% +4f4bce9e975334ed7775ff4ddf4d2e82e411d599802f6179a122f89149f53bfb + +%URL% +https://packages.debian.org/sid/dmz-cursor-theme + +%LICENSE% +MIT + +%ARCH% +any + +%BUILDDATE% +1673751613 + +%PACKAGER% +Unknown Packager + +%MAKEDEPENDS% +xorg-xcursorgen + diff --git a/test/package/files b/test/package/files new file mode 100644 index 0000000..aab44b1 --- /dev/null +++ b/test/package/files @@ -0,0 +1,243 @@ +%FILES% +usr/ +usr/share/ +usr/share/icons/ +usr/share/icons/DMZ-Black/ +usr/share/icons/DMZ-Black/cursor.theme +usr/share/icons/DMZ-Black/cursors/ +usr/share/icons/DMZ-Black/cursors/00008160000006810000408080010102 +usr/share/icons/DMZ-Black/cursors/028006030e0e7ebffc7f7070c0600140 +usr/share/icons/DMZ-Black/cursors/03b6e0fcb3499374a867c041f52298f0 +usr/share/icons/DMZ-Black/cursors/08e8e1c95fe2fc01f976f1e063a24ccd +usr/share/icons/DMZ-Black/cursors/1081e37283d90000800003c07f3ef6bf +usr/share/icons/DMZ-Black/cursors/14fef782d02440884392942c11205230 +usr/share/icons/DMZ-Black/cursors/2870a09082c103050810ffdffffe0204 +usr/share/icons/DMZ-Black/cursors/3085a0e285430894940527032f8b26df +usr/share/icons/DMZ-Black/cursors/3ecb610c1bf2410f44200f48c40d3599 +usr/share/icons/DMZ-Black/cursors/4498f0e0c1937ffe01fd06f973665830 +usr/share/icons/DMZ-Black/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408 +usr/share/icons/DMZ-Black/cursors/6407b0e94181790501fd1e167b474872 +usr/share/icons/DMZ-Black/cursors/640fb0e74195791501fd1ed57b41487f +usr/share/icons/DMZ-Black/cursors/9081237383d90e509aa00f00170e968f +usr/share/icons/DMZ-Black/cursors/9d800788f1b08800ae810202380a0822 +usr/share/icons/DMZ-Black/cursors/X_cursor +usr/share/icons/DMZ-Black/cursors/alias +usr/share/icons/DMZ-Black/cursors/arrow +usr/share/icons/DMZ-Black/cursors/bd_double_arrow +usr/share/icons/DMZ-Black/cursors/bottom_left_corner +usr/share/icons/DMZ-Black/cursors/bottom_right_corner +usr/share/icons/DMZ-Black/cursors/bottom_side +usr/share/icons/DMZ-Black/cursors/bottom_tee +usr/share/icons/DMZ-Black/cursors/c7088f0f3e6c8088236ef8e1e3e70000 +usr/share/icons/DMZ-Black/cursors/circle +usr/share/icons/DMZ-Black/cursors/col-resize +usr/share/icons/DMZ-Black/cursors/color-picker +usr/share/icons/DMZ-Black/cursors/copy +usr/share/icons/DMZ-Black/cursors/cross +usr/share/icons/DMZ-Black/cursors/cross_reverse +usr/share/icons/DMZ-Black/cursors/crossed_circle +usr/share/icons/DMZ-Black/cursors/crosshair +usr/share/icons/DMZ-Black/cursors/d9ce0ab605698f320427677b458ad60b +usr/share/icons/DMZ-Black/cursors/default +usr/share/icons/DMZ-Black/cursors/diamond_cross +usr/share/icons/DMZ-Black/cursors/dnd-ask +usr/share/icons/DMZ-Black/cursors/dnd-copy +usr/share/icons/DMZ-Black/cursors/dnd-link +usr/share/icons/DMZ-Black/cursors/dnd-move +usr/share/icons/DMZ-Black/cursors/dnd-none +usr/share/icons/DMZ-Black/cursors/dot_box_mask +usr/share/icons/DMZ-Black/cursors/dotbox +usr/share/icons/DMZ-Black/cursors/double_arrow +usr/share/icons/DMZ-Black/cursors/draft_large +usr/share/icons/DMZ-Black/cursors/draft_small +usr/share/icons/DMZ-Black/cursors/draped_box +usr/share/icons/DMZ-Black/cursors/e-resize +usr/share/icons/DMZ-Black/cursors/e29285e634086352946a0e7090d73106 +usr/share/icons/DMZ-Black/cursors/ew-resize +usr/share/icons/DMZ-Black/cursors/fcf1c3c7cd4491d801f1e1c78f100000 +usr/share/icons/DMZ-Black/cursors/fd_double_arrow +usr/share/icons/DMZ-Black/cursors/fleur +usr/share/icons/DMZ-Black/cursors/grab +usr/share/icons/DMZ-Black/cursors/grabbing +usr/share/icons/DMZ-Black/cursors/h_double_arrow +usr/share/icons/DMZ-Black/cursors/hand +usr/share/icons/DMZ-Black/cursors/hand1 +usr/share/icons/DMZ-Black/cursors/hand2 +usr/share/icons/DMZ-Black/cursors/help +usr/share/icons/DMZ-Black/cursors/icon +usr/share/icons/DMZ-Black/cursors/left_ptr +usr/share/icons/DMZ-Black/cursors/left_ptr_help +usr/share/icons/DMZ-Black/cursors/left_ptr_watch +usr/share/icons/DMZ-Black/cursors/left_side +usr/share/icons/DMZ-Black/cursors/left_tee +usr/share/icons/DMZ-Black/cursors/link +usr/share/icons/DMZ-Black/cursors/ll_angle +usr/share/icons/DMZ-Black/cursors/lr_angle +usr/share/icons/DMZ-Black/cursors/move +usr/share/icons/DMZ-Black/cursors/n-resize +usr/share/icons/DMZ-Black/cursors/ne-resize +usr/share/icons/DMZ-Black/cursors/nesw-resize +usr/share/icons/DMZ-Black/cursors/not-allowed +usr/share/icons/DMZ-Black/cursors/ns-resize +usr/share/icons/DMZ-Black/cursors/nw-resize +usr/share/icons/DMZ-Black/cursors/nwse-resize +usr/share/icons/DMZ-Black/cursors/openhand +usr/share/icons/DMZ-Black/cursors/pencil +usr/share/icons/DMZ-Black/cursors/pirate +usr/share/icons/DMZ-Black/cursors/plus +usr/share/icons/DMZ-Black/cursors/pointer +usr/share/icons/DMZ-Black/cursors/progress +usr/share/icons/DMZ-Black/cursors/question_arrow +usr/share/icons/DMZ-Black/cursors/right_ptr +usr/share/icons/DMZ-Black/cursors/right_side +usr/share/icons/DMZ-Black/cursors/right_tee +usr/share/icons/DMZ-Black/cursors/row-resize +usr/share/icons/DMZ-Black/cursors/s-resize +usr/share/icons/DMZ-Black/cursors/sb_down_arrow +usr/share/icons/DMZ-Black/cursors/sb_h_double_arrow +usr/share/icons/DMZ-Black/cursors/sb_left_arrow +usr/share/icons/DMZ-Black/cursors/sb_right_arrow +usr/share/icons/DMZ-Black/cursors/sb_up_arrow +usr/share/icons/DMZ-Black/cursors/sb_v_double_arrow +usr/share/icons/DMZ-Black/cursors/se-resize +usr/share/icons/DMZ-Black/cursors/size_bdiag +usr/share/icons/DMZ-Black/cursors/size_fdiag +usr/share/icons/DMZ-Black/cursors/size_hor +usr/share/icons/DMZ-Black/cursors/size_ver +usr/share/icons/DMZ-Black/cursors/sw-resize +usr/share/icons/DMZ-Black/cursors/target +usr/share/icons/DMZ-Black/cursors/tcross +usr/share/icons/DMZ-Black/cursors/text +usr/share/icons/DMZ-Black/cursors/top_left_arrow +usr/share/icons/DMZ-Black/cursors/top_left_corner +usr/share/icons/DMZ-Black/cursors/top_right_corner +usr/share/icons/DMZ-Black/cursors/top_side +usr/share/icons/DMZ-Black/cursors/top_tee +usr/share/icons/DMZ-Black/cursors/ul_angle +usr/share/icons/DMZ-Black/cursors/ur_angle +usr/share/icons/DMZ-Black/cursors/v_double_arrow +usr/share/icons/DMZ-Black/cursors/w-resize +usr/share/icons/DMZ-Black/cursors/wait +usr/share/icons/DMZ-Black/cursors/watch +usr/share/icons/DMZ-Black/cursors/xterm +usr/share/icons/DMZ-White/ +usr/share/icons/DMZ-White/cursor.theme +usr/share/icons/DMZ-White/cursors/ +usr/share/icons/DMZ-White/cursors/00008160000006810000408080010102 +usr/share/icons/DMZ-White/cursors/028006030e0e7ebffc7f7070c0600140 +usr/share/icons/DMZ-White/cursors/03b6e0fcb3499374a867c041f52298f0 +usr/share/icons/DMZ-White/cursors/08e8e1c95fe2fc01f976f1e063a24ccd +usr/share/icons/DMZ-White/cursors/1081e37283d90000800003c07f3ef6bf +usr/share/icons/DMZ-White/cursors/14fef782d02440884392942c11205230 +usr/share/icons/DMZ-White/cursors/2870a09082c103050810ffdffffe0204 +usr/share/icons/DMZ-White/cursors/3085a0e285430894940527032f8b26df +usr/share/icons/DMZ-White/cursors/3ecb610c1bf2410f44200f48c40d3599 +usr/share/icons/DMZ-White/cursors/4498f0e0c1937ffe01fd06f973665830 +usr/share/icons/DMZ-White/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408 +usr/share/icons/DMZ-White/cursors/6407b0e94181790501fd1e167b474872 +usr/share/icons/DMZ-White/cursors/640fb0e74195791501fd1ed57b41487f +usr/share/icons/DMZ-White/cursors/9081237383d90e509aa00f00170e968f +usr/share/icons/DMZ-White/cursors/9d800788f1b08800ae810202380a0822 +usr/share/icons/DMZ-White/cursors/X_cursor +usr/share/icons/DMZ-White/cursors/alias +usr/share/icons/DMZ-White/cursors/arrow +usr/share/icons/DMZ-White/cursors/bd_double_arrow +usr/share/icons/DMZ-White/cursors/bottom_left_corner +usr/share/icons/DMZ-White/cursors/bottom_right_corner +usr/share/icons/DMZ-White/cursors/bottom_side +usr/share/icons/DMZ-White/cursors/bottom_tee +usr/share/icons/DMZ-White/cursors/c7088f0f3e6c8088236ef8e1e3e70000 +usr/share/icons/DMZ-White/cursors/circle +usr/share/icons/DMZ-White/cursors/col-resize +usr/share/icons/DMZ-White/cursors/color-picker +usr/share/icons/DMZ-White/cursors/copy +usr/share/icons/DMZ-White/cursors/cross +usr/share/icons/DMZ-White/cursors/cross_reverse +usr/share/icons/DMZ-White/cursors/crossed_circle +usr/share/icons/DMZ-White/cursors/crosshair +usr/share/icons/DMZ-White/cursors/d9ce0ab605698f320427677b458ad60b +usr/share/icons/DMZ-White/cursors/default +usr/share/icons/DMZ-White/cursors/diamond_cross +usr/share/icons/DMZ-White/cursors/dnd-ask +usr/share/icons/DMZ-White/cursors/dnd-copy +usr/share/icons/DMZ-White/cursors/dnd-link +usr/share/icons/DMZ-White/cursors/dnd-move +usr/share/icons/DMZ-White/cursors/dnd-none +usr/share/icons/DMZ-White/cursors/dot_box_mask +usr/share/icons/DMZ-White/cursors/dotbox +usr/share/icons/DMZ-White/cursors/double_arrow +usr/share/icons/DMZ-White/cursors/draft_large +usr/share/icons/DMZ-White/cursors/draft_small +usr/share/icons/DMZ-White/cursors/draped_box +usr/share/icons/DMZ-White/cursors/e-resize +usr/share/icons/DMZ-White/cursors/e29285e634086352946a0e7090d73106 +usr/share/icons/DMZ-White/cursors/ew-resize +usr/share/icons/DMZ-White/cursors/fcf1c3c7cd4491d801f1e1c78f100000 +usr/share/icons/DMZ-White/cursors/fd_double_arrow +usr/share/icons/DMZ-White/cursors/fleur +usr/share/icons/DMZ-White/cursors/grab +usr/share/icons/DMZ-White/cursors/grabbing +usr/share/icons/DMZ-White/cursors/h_double_arrow +usr/share/icons/DMZ-White/cursors/hand +usr/share/icons/DMZ-White/cursors/hand1 +usr/share/icons/DMZ-White/cursors/hand2 +usr/share/icons/DMZ-White/cursors/help +usr/share/icons/DMZ-White/cursors/icon +usr/share/icons/DMZ-White/cursors/left_ptr +usr/share/icons/DMZ-White/cursors/left_ptr_help +usr/share/icons/DMZ-White/cursors/left_ptr_watch +usr/share/icons/DMZ-White/cursors/left_side +usr/share/icons/DMZ-White/cursors/left_tee +usr/share/icons/DMZ-White/cursors/link +usr/share/icons/DMZ-White/cursors/ll_angle +usr/share/icons/DMZ-White/cursors/lr_angle +usr/share/icons/DMZ-White/cursors/move +usr/share/icons/DMZ-White/cursors/n-resize +usr/share/icons/DMZ-White/cursors/ne-resize +usr/share/icons/DMZ-White/cursors/nesw-resize +usr/share/icons/DMZ-White/cursors/not-allowed +usr/share/icons/DMZ-White/cursors/ns-resize +usr/share/icons/DMZ-White/cursors/nw-resize +usr/share/icons/DMZ-White/cursors/nwse-resize +usr/share/icons/DMZ-White/cursors/openhand +usr/share/icons/DMZ-White/cursors/pencil +usr/share/icons/DMZ-White/cursors/pirate +usr/share/icons/DMZ-White/cursors/plus +usr/share/icons/DMZ-White/cursors/pointer +usr/share/icons/DMZ-White/cursors/progress +usr/share/icons/DMZ-White/cursors/question_arrow +usr/share/icons/DMZ-White/cursors/right_ptr +usr/share/icons/DMZ-White/cursors/right_side +usr/share/icons/DMZ-White/cursors/right_tee +usr/share/icons/DMZ-White/cursors/row-resize +usr/share/icons/DMZ-White/cursors/s-resize +usr/share/icons/DMZ-White/cursors/sb_down_arrow +usr/share/icons/DMZ-White/cursors/sb_h_double_arrow +usr/share/icons/DMZ-White/cursors/sb_left_arrow +usr/share/icons/DMZ-White/cursors/sb_right_arrow +usr/share/icons/DMZ-White/cursors/sb_up_arrow +usr/share/icons/DMZ-White/cursors/sb_v_double_arrow +usr/share/icons/DMZ-White/cursors/se-resize +usr/share/icons/DMZ-White/cursors/size_bdiag +usr/share/icons/DMZ-White/cursors/size_fdiag +usr/share/icons/DMZ-White/cursors/size_hor +usr/share/icons/DMZ-White/cursors/size_ver +usr/share/icons/DMZ-White/cursors/sw-resize +usr/share/icons/DMZ-White/cursors/target +usr/share/icons/DMZ-White/cursors/tcross +usr/share/icons/DMZ-White/cursors/text +usr/share/icons/DMZ-White/cursors/top_left_arrow +usr/share/icons/DMZ-White/cursors/top_left_corner +usr/share/icons/DMZ-White/cursors/top_right_corner +usr/share/icons/DMZ-White/cursors/top_side +usr/share/icons/DMZ-White/cursors/top_tee +usr/share/icons/DMZ-White/cursors/ul_angle +usr/share/icons/DMZ-White/cursors/ur_angle +usr/share/icons/DMZ-White/cursors/v_double_arrow +usr/share/icons/DMZ-White/cursors/w-resize +usr/share/icons/DMZ-White/cursors/wait +usr/share/icons/DMZ-White/cursors/watch +usr/share/icons/DMZ-White/cursors/xterm +usr/share/licenses/ +usr/share/licenses/xcursor-dmz/ +usr/share/licenses/xcursor-dmz/LICENSE diff --git a/test/package/test_package.c b/test/package/test_package.c new file mode 100644 index 0000000..43911a8 --- /dev/null +++ b/test/package/test_package.c @@ -0,0 +1,86 @@ +#include "acutest.h" +#include "package.h" + +void test_pkg_info_parse() { + FILE *f = fopen("./test/package/.PKGINFO", "r"); + TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package "); + fseek(f, 0L, SEEK_END); + size_t size = ftell(f); + fflush(stdout); + rewind(f); + char *pkg_info_str = malloc(size); + fread(pkg_info_str, 1, size, f); + fclose(f); + PkgInfo *pkg_info = package_info_init(); + package_info_parse(pkg_info, pkg_info_str); + + TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); + TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); + TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); + TEST_CHECK(pkg_info->build_date == 1673751613); + TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); + TEST_CHECK(pkg_info->size == 3469584); + TEST_CHECK(!strcmp(pkg_info->arch, "any")); + + TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); + TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); + TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); + TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); + TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); + TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); + TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); + TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); + TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); + +} + +void test_pkg_read_archive_files() { + Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + + FILE *f = fopen("./test/package/files", "r"); + TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); + char *buff = malloc(sizeof(char) * 128); + size_t i = 0; + + while ((fgets(buff, 128, f)) != NULL || i < pkg->files->size) { + if (buff[strlen(buff) - 1] == '\n') { + buff[strlen(buff) - 1] = '\0'; + } + + TEST_CHECK_(!strcmp(pkg->files->array[i], buff), "%s != %s", pkg->files->array[i], buff); + i++; + } + TEST_CHECK(pkg->compression = 14); + +} + +void test_pkg_read_archive_desc() { + Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + + char *description = package_to_description(pkg); + + FILE *f = fopen("./test/package/desc", "r"); + TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package"); + fseek(f, 0, SEEK_END); + size_t size = ftell(f); + rewind(f); + char *desc = malloc(size); + fread(desc, 1, size, f); + fclose(f); + + TEST_CHECK(!strcmp(description, desc)); + +} + +TEST_LIST = { + {"pkg_info_valid_parse", test_pkg_info_parse}, + {"pkg_read_archive_files", test_pkg_read_archive_files}, + {"pkg_read_archive_desc", test_pkg_read_archive_desc}, + {NULL, NULL} +}; diff --git a/test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst b/test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst new file mode 100644 index 0000000000000000000000000000000000000000..a878047ad426e5e3f5d211967ed9fdf950051de5 GIT binary patch literal 328282 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

rfEN4S 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%0AX3PJ)XAv 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

g2c$|h8?TE+9iC)Tdxl*KPH+Aw&jWHyv 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

D7nMvY$U) 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�rz|2hY>Qy8PRwmF(ef|7^EDWIX1ClJ38_bdL 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 NV8C6xC literal 0 HcmV?d00001 From 9452fea2abb3b0a2db0eee76dd4f075fff85d579 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 23:55:04 +0100 Subject: [PATCH 16/74] fix: Somehow, test file changed line endings to CRLF. Changed it back to LF. --- test/package/test_package.c | 170 ++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 86 deletions(-) diff --git a/test/package/test_package.c b/test/package/test_package.c index 43911a8..c0c7085 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -1,86 +1,84 @@ -#include "acutest.h" -#include "package.h" - -void test_pkg_info_parse() { - FILE *f = fopen("./test/package/.PKGINFO", "r"); - TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package "); - fseek(f, 0L, SEEK_END); - size_t size = ftell(f); - fflush(stdout); - rewind(f); - char *pkg_info_str = malloc(size); - fread(pkg_info_str, 1, size, f); - fclose(f); - PkgInfo *pkg_info = package_info_init(); - package_info_parse(pkg_info, pkg_info_str); - - TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); - TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); - TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); - TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); - TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); - TEST_CHECK(pkg_info->build_date == 1673751613); - TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); - TEST_CHECK(pkg_info->size == 3469584); - TEST_CHECK(!strcmp(pkg_info->arch, "any")); - - TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); - TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); - TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); - TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); - TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); - TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); - TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); - TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); - TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); - TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); - TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); - -} - -void test_pkg_read_archive_files() { - Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); - TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); - - FILE *f = fopen("./test/package/files", "r"); - TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); - char *buff = malloc(sizeof(char) * 128); - size_t i = 0; - - while ((fgets(buff, 128, f)) != NULL || i < pkg->files->size) { - if (buff[strlen(buff) - 1] == '\n') { - buff[strlen(buff) - 1] = '\0'; - } - - TEST_CHECK_(!strcmp(pkg->files->array[i], buff), "%s != %s", pkg->files->array[i], buff); - i++; - } - TEST_CHECK(pkg->compression = 14); - -} - -void test_pkg_read_archive_desc() { - Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); - TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); - - char *description = package_to_description(pkg); - - FILE *f = fopen("./test/package/desc", "r"); - TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package"); - fseek(f, 0, SEEK_END); - size_t size = ftell(f); - rewind(f); - char *desc = malloc(size); - fread(desc, 1, size, f); - fclose(f); - - TEST_CHECK(!strcmp(description, desc)); - -} - -TEST_LIST = { - {"pkg_info_valid_parse", test_pkg_info_parse}, - {"pkg_read_archive_files", test_pkg_read_archive_files}, - {"pkg_read_archive_desc", test_pkg_read_archive_desc}, - {NULL, NULL} -}; +#include "acutest.h" +#include "package.h" + +void test_pkg_info_parse() { + FILE *f = fopen("./test/package/.PKGINFO", "r"); + TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package "); + fseek(f, 0L, SEEK_END); + size_t size = ftell(f); + fflush(stdout); + rewind(f); + char *pkg_info_str = malloc(size); + fread(pkg_info_str, 1, size, f); + fclose(f); + PkgInfo *pkg_info = package_info_init(); + package_info_parse(pkg_info, pkg_info_str); + + TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); + TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); + TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); + TEST_CHECK(pkg_info->build_date == 1673751613); + TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); + TEST_CHECK(pkg_info->size == 3469584); + TEST_CHECK(!strcmp(pkg_info->arch, "any")); + + TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); + TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); + TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); + TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); + TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); + TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); + TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); + TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); + TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); +} + +void test_pkg_read_archive_files() { + Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + + FILE *f = fopen("./test/package/files", "r"); + TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); + char buff[128]; + size_t i = 0; + + while ((fgets(buff, 128, f)) != NULL || i < pkg->files->size) { + if (buff[strlen(buff) - 1] == '\n') { + buff[strlen(buff) - 1] = '\0'; + } + + TEST_CHECK_(!strcmp(pkg->files->array[i], buff), "%s != %s", pkg->files->array[i], buff); + i++; + } + TEST_CHECK(pkg->compression = 14); + +} + +void test_pkg_read_archive_desc() { + Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + + char *description = package_to_description(pkg); + + FILE *f = fopen("./test/package/desc", "r"); + TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package"); + fseek(f, 0, SEEK_END); + size_t size = ftell(f); + rewind(f); + char *desc = malloc(size); + fread(desc, 1, size, f); + fclose(f); + + TEST_CHECK(!strcmp(description, desc)); +} + +TEST_LIST = { + {"pkg_info_valid_parse", test_pkg_info_parse}, + {"pkg_read_archive_files", test_pkg_read_archive_files}, + {"pkg_read_archive_desc", test_pkg_read_archive_desc}, + {NULL, NULL} +}; From adfdca18da1a521a0cd5d1cbbef38d6275e992ce Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 28 Jan 2023 09:09:17 +0100 Subject: [PATCH 17/74] docs(tree): add function docstrings --- include/vieter_tree.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/vieter_tree.h b/include/vieter_tree.h index be381e5..d3abd2f 100644 --- a/include/vieter_tree.h +++ b/include/vieter_tree.h @@ -12,19 +12,37 @@ typedef enum vieter_tree_error { vieter_tree_not_present = 2 } vieter_tree_error; +/* + * Allocate and initialize a new red-black binary tree. + */ vieter_tree *vieter_tree_init(); +/* + * Deallocate a red-black binary tree. + */ void vieter_tree_free(vieter_tree *tree); +/* + * Insert a new entry into the tree. + */ vieter_tree_error vieter_tree_insert(vieter_tree *tree, uint64_t key, void *data); +/* + * Look for an entry in the tree. + */ vieter_tree_error vieter_tree_search(void **out, vieter_tree *tree, uint64_t key); +/* + * Remove a given entry from the tree. + */ vieter_tree_error vieter_tree_remove(void **out, vieter_tree *tree, uint64_t key); +/* + * Return how many entries are currently in the tree. + */ uint64_t vieter_tree_size(vieter_tree *tree); #endif From 3bf3150b4ad5a838d3f1effdd37e91698554d4d1 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 28 Jan 2023 09:30:35 +0100 Subject: [PATCH 18/74] test: rename some stuff; separate cron part tests --- README.md | 11 +++++ src/cron/vieter_cron_parse.c | 2 +- src/cron/vieter_cron_parse.h | 11 +++++ test/cron/test_parse.c | 4 +- test/cron/test_parse_part.c | 43 +++++++++++++++++++ test/heap/test_heap.c | 10 ++--- test/heap/test_merge.c | 2 +- test/tree/{test_binary_tree.c => test_tree.c} | 6 +-- 8 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 src/cron/vieter_cron_parse.h create mode 100644 test/cron/test_parse_part.c rename test/tree/{test_binary_tree.c => test_tree.c} (93%) diff --git a/README.md b/README.md index d1fef1a..abc250a 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,17 @@ files defined in its respective module. This allows testing internal functions. To run the tests, simply run `make test`. If you wish to only run a specific test binary, you can find them in `build/test`. +The name of tests in the `TEST_LIST` variable should be prefixed with the +module they're testing. This makes it much easier to distinguish the output of +tests in the CLI. For example: + +```c +TEST_LIST = { + {"cron illegal parts", test_illegal_parts}, + {NULL, NULL} +}; +``` + ### `compile_commands.json` Clangd requires a `compile_commands.json` to function properly. You can diff --git a/src/cron/vieter_cron_parse.c b/src/cron/vieter_cron_parse.c index a82d1c3..b42e1a9 100644 --- a/src/cron/vieter_cron_parse.c +++ b/src/cron/vieter_cron_parse.c @@ -1,4 +1,4 @@ -#include "vieter_cron.h" +#include "vieter_cron_parse.h" #include #include #include diff --git a/src/cron/vieter_cron_parse.h b/src/cron/vieter_cron_parse.h new file mode 100644 index 0000000..21ccf81 --- /dev/null +++ b/src/cron/vieter_cron_parse.h @@ -0,0 +1,11 @@ +#ifndef VIETER_CRON_PARSE +#define VIETER_CRON_PARSE + +#include "vieter_cron.h" + +vieter_cron_parse_error vieter_cron_expr_parse_range(uint64_t *out, char *s, + uint8_t min, uint8_t max); + +vieter_cron_parse_error vieter_cron_expr_parse_part(uint64_t *out, char *s, + uint8_t min, uint8_t max); +#endif diff --git a/test/cron/test_parse.c b/test/cron/test_parse.c index 030c720..6417c40 100644 --- a/test/cron/test_parse.c +++ b/test/cron/test_parse.c @@ -1,7 +1,7 @@ #include "acutest.h" #include "vieter_cron.h" -void test_not_allowed() { +void test_illegal_expressions() { char *expressions[] = { "4 *-7", "4 *-7/4", @@ -33,6 +33,6 @@ void test_not_allowed() { } TEST_LIST = { - {"not_allowed", test_not_allowed}, + {"cron illegal expressions", test_illegal_expressions}, {NULL, NULL} }; diff --git a/test/cron/test_parse_part.c b/test/cron/test_parse_part.c new file mode 100644 index 0000000..5c9c10e --- /dev/null +++ b/test/cron/test_parse_part.c @@ -0,0 +1,43 @@ +#include "acutest.h" +#include "vieter_cron_parse.h" + +struct parse_test { + char *part; + uint8_t min; + uint8_t max; +}; + +void test_illegal_parts() { + struct parse_test parts[] = { + { "*-7", 0, 23 }, + { "*-7/4", 0, 23 }, + { "7/*", 0, 23 }, + { "/5", 0, 23 }, + { "4~6", 0, 23 }, + { "5/2-5", 0, 23 }, + { "1/2/3", 0, 23 }, + { "*5", 0, 59 }, + { "x", 0, 59 }, + { NULL, 0, 0 } + }; + + int i = 0; + uint64_t out; + char *s; + + while (parts[i].part != NULL) { + // Function modifies string in-place + s = strdup(parts[i].part); + + TEST_CHECK_(vieter_cron_expr_parse_part(&out, s, parts[i].min, parts[i].max) != vieter_cron_parse_ok, "%s (%i - %i)", parts[i].part, parts[i].min, parts[i].max); + + free(s); + + i++; + } +} + +TEST_LIST = { + {"cron illegal parts", test_illegal_parts}, + {NULL, NULL} +}; diff --git a/test/heap/test_heap.c b/test/heap/test_heap.c index f77b0dc..31ea354 100644 --- a/test/heap/test_heap.c +++ b/test/heap/test_heap.c @@ -178,10 +178,10 @@ void test_pop_random() { } TEST_LIST = { - {"init", test_init}, - {"insert", test_insert}, - {"insert random", test_insert_random}, - {"pop", test_pop}, - {"pop random", test_pop_random}, + {"heap init", test_init}, + {"heap insert", test_insert}, + {"heap insert random", test_insert_random}, + {"heap pop", test_pop}, + {"heap pop random", test_pop_random}, {NULL, NULL} }; diff --git a/test/heap/test_merge.c b/test/heap/test_merge.c index 10053f2..f0861fe 100644 --- a/test/heap/test_merge.c +++ b/test/heap/test_merge.c @@ -23,6 +23,6 @@ void test_merge_same_order() { } TEST_LIST = { - {"merge same order", test_merge_same_order}, + {"heap merge same order", test_merge_same_order}, {NULL, NULL} }; diff --git a/test/tree/test_binary_tree.c b/test/tree/test_tree.c similarity index 93% rename from test/tree/test_binary_tree.c rename to test/tree/test_tree.c index aa7fc0f..d0ea661 100644 --- a/test/tree/test_binary_tree.c +++ b/test/tree/test_tree.c @@ -51,8 +51,8 @@ void test_remove() { } TEST_LIST = { - {"test_init", test_init}, - {"test_insert", test_insert}, - {"test_remove", test_remove}, + {"tree init", test_init}, + {"tree insert", test_insert}, + {"tree remove", test_remove}, {NULL, NULL} }; From b25da21fd12a4038d63f3f3b9a602c318f684cc7 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 28 Jan 2023 09:58:32 +0100 Subject: [PATCH 19/74] chore: fix merge marker in makefile --- Makefile | 8 ++------ README.md | 4 ++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index ac56c97..f3059a7 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ BINS_TEST := $(OBJS_TEST:%.c.o=%) TARGETS_TEST := $(BINS_TEST:%=test-%) TARGETS_MEM_TEST := $(BINS_TEST:%=test-mem-%) +LIBFLAGS := -larchive INC_FLAGS := $(addprefix -I,$(INC_DIRS)) # -MMD: generate a .d file for every source file. This file can be imported by @@ -71,14 +72,9 @@ build-test: $(BINS_TEST) # For simplicity, we link every object file to each of the test files. This # might be changed later if this starts to become too slow. -<<<<<<< HEAD $(BINS_TEST): %: %.c.o $(LIB) $(CC) \ - $^ -o $@ -======= -$(BINS_TEST): %: %.c.o $(OBJS) - $(CC) $^ -larchive -o $@ ->>>>>>> c94ab92 (refactor: Add libarchive link to test compilation area of the Makefile. Created test units with xcursor-dmz as test package.) + $^ $(LIBFLAGS) -o $@ # Along with the include directory, each test includes $(TEST_DIR) (which # contains the acutest.h header file), and the src directory of the module it's diff --git a/README.md b/README.md index d1fef1a..448b87b 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,10 @@ See the [source code](src) for the list of modules. Everything is handled by the provided Makefile. To compile the static library, simply run `make`. +### Required libraries + +Libvieter requires libarchive. + ### Project structure Each module has its own subdirectory inside `src`, e.g. `src/cron`. This From 72fea90e135b7d601e2de20f8ae2e353d80a50c7 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sat, 28 Jan 2023 09:57:38 +0000 Subject: [PATCH 20/74] fix: strcat can not be used on uninitialised strings in non-musl environments. --- src/package/package.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package/package.c b/src/package/package.c index 8d1565d..f5f4ee5 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -141,7 +141,7 @@ char *package_to_description(Pkg *pkg) { // assuming .pkg.tar.zst; other formats are valid, this should account for that snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version, pkg_info->arch); - strcat(description, aux); + strcpy(description, aux); ADD_STRING("\n\n%%NAME%%\n%s", name); ADD_STRING("\n\n%%BASE%%\n%s", base); From 89d1c9cdca04b976ead2d7168b5dde99524cfc4f Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 28 Jan 2023 12:02:52 +0100 Subject: [PATCH 21/74] chore: add license --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. From 3fb027715c51de7d0030d46453b2afd6721c608e Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 28 Jan 2023 19:27:40 +0100 Subject: [PATCH 22/74] test(tree): validation function to use in testing --- src/tree/vieter_tree.c | 22 +++++++++++++++++- src/tree/vieter_tree_balancing.c | 38 ++++++++++++++++++++++++++++++++ src/tree/vieter_tree_internal.h | 8 +++++++ src/tree/vieter_tree_node.h | 2 ++ test/tree/test_tree.c | 7 ++++-- 5 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/tree/vieter_tree_internal.h diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index 72360b0..792ad30 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -1,4 +1,4 @@ -#include "vieter_tree.h" +#include "vieter_tree_internal.h" #include "vieter_tree_node.h" struct vieter_tree { @@ -98,3 +98,23 @@ void vieter_tree_free(vieter_tree *tree) { end: free(tree); } + +int vieter_tree_validate(vieter_tree *tree) { + if (tree->size == 0) { + return 0; + } + + // DFS to get expected black nodes + uint64_t expected_black_nodes = 0; + vieter_tree_node *node = tree->root; + + while (node != NULL) { + if (vieter_tree_node_get(node, vieter_node_black)) { + expected_black_nodes++; + } + + node = node->left; + } + + return vieter_tree_node_validate(tree->root, 0, expected_black_nodes); +} diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index 56047a0..70c52e0 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -1,5 +1,43 @@ #include "vieter_tree_balancing.h" +int vieter_tree_node_validate(vieter_tree_node *node, + uint64_t passed_black_nodes, + uint64_t expected_black_nodes) { + if (vieter_tree_node_get(node, vieter_node_black)) { + passed_black_nodes++; + } else { + // A red node should have black child nodes + if ((node->left != NULL && + !vieter_tree_node_get(node->left, vieter_node_black)) || + (node->right != NULL && + !vieter_tree_node_get(node->right, vieter_node_black))) { + return 1; + } + } + + // All paths to a NULL child should have the same amount of black nodes + if ((node->left == NULL || node->right == NULL) && + passed_black_nodes != expected_black_nodes) { + return 1; + } + + if (node->left != NULL) { + if (vieter_tree_node_validate(node->left, passed_black_nodes, + expected_black_nodes) != 0) { + return 1; + } + } + + if (node->right != NULL) { + if (vieter_tree_node_validate(node->right, passed_black_nodes, + expected_black_nodes) != 0) { + return 1; + } + } + + return 0; +} + vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { vieter_tree_node *parent = node->parent; vieter_tree_node *grand_parent = parent->parent; diff --git a/src/tree/vieter_tree_internal.h b/src/tree/vieter_tree_internal.h new file mode 100644 index 0000000..dc4ee81 --- /dev/null +++ b/src/tree/vieter_tree_internal.h @@ -0,0 +1,8 @@ +#include "vieter_tree.h" + +/* + * Inspect whether the tree is still a valid red-black-tree. + * + * @return 0 if correct, 1 if not. + */ +int vieter_tree_validate(vieter_tree *tree); diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 522ee59..1c88159 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -40,4 +40,6 @@ bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag); void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, vieter_tree_node *child); +int vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, uint64_t expected_black_nodes); + #endif diff --git a/test/tree/test_tree.c b/test/tree/test_tree.c index d0ea661..c875137 100644 --- a/test/tree/test_tree.c +++ b/test/tree/test_tree.c @@ -1,5 +1,5 @@ #include "acutest.h" -#include "vieter_tree.h" +#include "vieter_tree_internal.h" #define TEST_SIZE(tree, size) \ TEST_CHECK(vieter_tree_size(tree) == size); \ @@ -18,6 +18,7 @@ void test_insert() { for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); TEST_SIZE(tree, i + 1); + TEST_CHECK(vieter_tree_validate(tree) == 0); } void *out; @@ -36,13 +37,15 @@ void test_remove() { for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); + TEST_CHECK(vieter_tree_validate(tree) == 0); } void *out; - for (uint64_t i = 0; i < 250; i++) { + for (uint64_t i = 0; i < 25; i++) { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok); + TEST_CHECK(vieter_tree_validate(tree) == 0); TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_not_present); TEST_SIZE(tree, 250 - i - 1); } From b87d6b1542f026553b9af1ceef0fe88db1bcce17 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sat, 28 Jan 2023 22:01:00 +0000 Subject: [PATCH 23/74] refactor: Subsituted old hash generation with a proper implementation. --- include/package.h | 4 +- include/sha256.h | 34 +++++++++ src/package/package.c | 52 ++++++++++++-- src/package/sha256.c | 158 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 241 insertions(+), 7 deletions(-) create mode 100644 include/sha256.h create mode 100644 src/package/sha256.c diff --git a/include/package.h b/include/package.h index 09e91bd..0360a6a 100644 --- a/include/package.h +++ b/include/package.h @@ -6,8 +6,8 @@ #include #include -#include "archive.h" -#include "archive_entry.h" +#include +#include #include "package_info.h" #include "dynarray.h" diff --git a/include/sha256.h b/include/sha256.h new file mode 100644 index 0000000..7123a30 --- /dev/null +++ b/include/sha256.h @@ -0,0 +1,34 @@ +/********************************************************************* +* Filename: sha256.h +* Author: Brad Conte (brad AT bradconte.com) +* Copyright: +* Disclaimer: This code is presented "as is" without any guarantees. +* Details: Defines the API for the corresponding SHA1 implementation. +*********************************************************************/ + +#ifndef SHA256_H +#define SHA256_H + +/*************************** HEADER FILES ***************************/ +#include + +/****************************** MACROS ******************************/ +#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest + +/**************************** DATA TYPES ****************************/ +typedef unsigned char BYTE; // 8-bit byte +typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines + +typedef struct { + BYTE data[64]; + WORD datalen; + unsigned long long bitlen; + WORD state[8]; +} SHA256_CTX; + +/*********************** FUNCTION DECLARATIONS **********************/ +void sha256_init(SHA256_CTX *ctx); +void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len); +void sha256_final(SHA256_CTX *ctx, BYTE hash[]); + +#endif // SHA256_H diff --git a/src/package/package.c b/src/package/package.c index f5f4ee5..577e3c9 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -1,4 +1,5 @@ #include "package.h" +#include "sha256.h" #define SMALL_BUFF_SIZE 128 @@ -121,12 +122,52 @@ Pkg *package_read_archive(const char *pkg_path) { } void sha256sum(Pkg *pkg, char *res) { - char command[SMALL_BUFF_SIZE]; - snprintf(command, SMALL_BUFF_SIZE, "sha256sum %s", pkg->path); - FILE *p = popen(command, "r"); + FILE *f = fopen(pkg->path, "r"); + fseek(f, 0, SEEK_END); + size_t size = ftell(f); + rewind(f); + unsigned char *in = malloc(size); + fread(in, 1, size, f); + fclose(f); - fgets(res, 65, p); - pclose(p); + unsigned char hash[32]; + SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); + + sha256_init(ctx); + sha256_update(ctx, in, size); + sha256_final(ctx, hash); + + free(in); + free(ctx); + + // We need to convert the bytes in the hash to get a string representation of its hex values + // i.e. turn 1001 1111 into the string "9f" + // Each byte of the hash is going to turn into two bytes in the final string + // so we are going to convert each half byte into a char + unsigned int half_byte = 0; + int j = 0; + + // We advance in the string 2 bytes for every one byte of the hash + for (int i = 0; i < 32; i++) { + // We transform the first half byte into the second character to keep + // each byte from becoming reversed in the final string + half_byte = hash[i] & 0b1111; + if (half_byte < 10) { + res[j+1] = half_byte + 48; + } else { + res[j+1] = half_byte + 87; + } + hash[i] = hash[i] >> 4; + half_byte = hash[i] & 0b1111; + if (half_byte < 10) { + res[j] = half_byte + 48; + } else { + res[j] = half_byte + 87; + } + + j += 2; + } + res[j] = '\0'; } char *package_to_description(Pkg *pkg) { @@ -153,6 +194,7 @@ char *package_to_description(Pkg *pkg) { char checksum[65]; sha256sum(pkg, checksum); + snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum); if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { description = realloc(description, buff_size * 2); diff --git a/src/package/sha256.c b/src/package/sha256.c new file mode 100644 index 0000000..eb9c5c0 --- /dev/null +++ b/src/package/sha256.c @@ -0,0 +1,158 @@ +/********************************************************************* +* Filename: sha256.c +* Author: Brad Conte (brad AT bradconte.com) +* Copyright: +* Disclaimer: This code is presented "as is" without any guarantees. +* Details: Implementation of the SHA-256 hashing algorithm. + SHA-256 is one of the three algorithms in the SHA2 + specification. The others, SHA-384 and SHA-512, are not + offered in this implementation. + Algorithm specification can be found here: + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf + This implementation uses little endian byte order. +*********************************************************************/ + +/*************************** HEADER FILES ***************************/ +#include +#include +#include "sha256.h" + +/****************************** MACROS ******************************/ +#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) +#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) + +#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) +#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) +#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) +#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) + +/**************************** VARIABLES *****************************/ +static const WORD k[64] = { + 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, + 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, + 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, + 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +}; + +/*********************** FUNCTION DEFINITIONS ***********************/ +void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) +{ + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for ( ; i < 64; ++i) + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; + t2 = EP0(a) + MAJ(a,b,c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + ctx->state[3] += d; + ctx->state[4] += e; + ctx->state[5] += f; + ctx->state[6] += g; + ctx->state[7] += h; +} + +void sha256_init(SHA256_CTX *ctx) +{ + ctx->datalen = 0; + ctx->bitlen = 0; + ctx->state[0] = 0x6a09e667; + ctx->state[1] = 0xbb67ae85; + ctx->state[2] = 0x3c6ef372; + ctx->state[3] = 0xa54ff53a; + ctx->state[4] = 0x510e527f; + ctx->state[5] = 0x9b05688c; + ctx->state[6] = 0x1f83d9ab; + ctx->state[7] = 0x5be0cd19; +} + +void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) +{ + WORD i; + + for (i = 0; i < len; ++i) { + ctx->data[ctx->datalen] = data[i]; + ctx->datalen++; + if (ctx->datalen == 64) { + sha256_transform(ctx, ctx->data); + ctx->bitlen += 512; + ctx->datalen = 0; + } + } +} + +void sha256_final(SHA256_CTX *ctx, BYTE hash[]) +{ + WORD i; + + i = ctx->datalen; + + // Pad whatever data is left in the buffer. + if (ctx->datalen < 56) { + ctx->data[i++] = 0x80; + while (i < 56) + ctx->data[i++] = 0x00; + } + else { + ctx->data[i++] = 0x80; + while (i < 64) + ctx->data[i++] = 0x00; + sha256_transform(ctx, ctx->data); + memset(ctx->data, 0, 56); + } + + // Append to the padding the total message's length in bits and transform. + ctx->bitlen += ctx->datalen * 8; + ctx->data[63] = ctx->bitlen; + ctx->data[62] = ctx->bitlen >> 8; + ctx->data[61] = ctx->bitlen >> 16; + ctx->data[60] = ctx->bitlen >> 24; + ctx->data[59] = ctx->bitlen >> 32; + ctx->data[58] = ctx->bitlen >> 40; + ctx->data[57] = ctx->bitlen >> 48; + ctx->data[56] = ctx->bitlen >> 56; + sha256_transform(ctx, ctx->data); + + // Since this implementation uses little endian byte ordering and SHA uses big endian, + // reverse all the bytes when copying the final state to the output hash. + for (i = 0; i < 4; ++i) { + hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; + hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; + hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; + hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; + hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; + hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; + hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; + hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; + } +} From 4812cde90582c61922035905a9b8b6aab51ebbdf Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sun, 29 Jan 2023 11:48:59 +0000 Subject: [PATCH 24/74] chore: Package module now follows the naming and structure conventions of libvieter. --- include/dynarray.h | 24 -------- include/package.h | 26 -------- include/package_info.h | 39 ------------ include/vieter_package.h | 30 +++++++++ src/package/README.md | 5 ++ {include => src/package}/sha256.h | 0 src/package/{package.c => vieter_package.c} | 51 ++++++++-------- .../{dynarray.c => vieter_package_dynarray.c} | 14 ++--- src/package/vieter_package_dynarray.h | 36 +++++++++++ .../{package_info.c => vieter_package_info.c} | 54 ++++++++-------- src/package/vieter_package_info.h | 52 ++++++++++++++++ src/package/vieter_package_internal.h | 10 +++ test/package/test_package.c | 61 ++++++++++--------- 13 files changed, 224 insertions(+), 178 deletions(-) delete mode 100644 include/dynarray.h delete mode 100644 include/package.h delete mode 100644 include/package_info.h create mode 100644 include/vieter_package.h create mode 100644 src/package/README.md rename {include => src/package}/sha256.h (100%) rename src/package/{package.c => vieter_package.c} (81%) rename src/package/{dynarray.c => vieter_package_dynarray.c} (67%) create mode 100644 src/package/vieter_package_dynarray.h rename src/package/{package_info.c => vieter_package_info.c} (59%) create mode 100644 src/package/vieter_package_info.h create mode 100644 src/package/vieter_package_internal.h diff --git a/include/dynarray.h b/include/dynarray.h deleted file mode 100644 index 2ab4022..0000000 --- a/include/dynarray.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef VIETER_DYNARRAY -#define VIETER_DYNARRAY - -#include -#include - -typedef struct dyn_array DynArray; -struct dyn_array { - char **array; - size_t capacity; - size_t size; -}; - -DynArray *dynarray_init(size_t initial_capacity); -void dynarray_add(DynArray *da, const char * s); -void dynarray_free(DynArray *da); - -/** - * Convert a DynArray into an array by freeing all its surrounding components - * and returning the underlying array pointer. - */ -char **dynarray_convert(DynArray *da); - -#endif diff --git a/include/package.h b/include/package.h deleted file mode 100644 index 0360a6a..0000000 --- a/include/package.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef VIETER_PACKAGE -#define VIETER_PACKAGE - -#include -#include -#include -#include - -#include -#include - -#include "package_info.h" -#include "dynarray.h" - -typedef struct pkg { - char *path; - PkgInfo *info; - DynArray *files; - int compression; -} Pkg; - -Pkg *package_read_archive(const char *pkg_path); -void package_free(Pkg ** ptp); -char *package_to_description(Pkg *pkg); - -#endif diff --git a/include/package_info.h b/include/package_info.h deleted file mode 100644 index b1388a2..0000000 --- a/include/package_info.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef VIETER_PACKAGE_INFO -#define VIETER_PACKAGE_INFO - -#define FREE_STRING(sp) if (sp != NULL) free(sp) - -#include - -#include "dynarray.h" - -typedef struct pkg_info { - char *name; - char *base; - char *version; - char *description; - int64_t size; - int64_t csize; - char *url; - char *arch; - int64_t build_date; - char *packager; - char *pgpsig; - int64_t pgpsigsize; - - DynArray *groups; - DynArray *licenses; - DynArray *replaces; - DynArray *depends; - DynArray *conflicts; - DynArray *provides; - DynArray *optdepends; - DynArray *makedepends; - DynArray *checkdepends; -} PkgInfo; - -PkgInfo *package_info_init(); -void package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); -void package_info_free(PkgInfo *pkg_info); - -#endif diff --git a/include/vieter_package.h b/include/vieter_package.h new file mode 100644 index 0000000..ebe6487 --- /dev/null +++ b/include/vieter_package.h @@ -0,0 +1,30 @@ +#ifndef VIETER_PACKAGE +#define VIETER_PACKAGE + +#include +#include +#include +#include + +#include +#include + +typedef struct pkg Pkg; + +/* + * Parse package file into something usable by libvieter. + * The pointer returned by this function will need to freed at a later point. + */ +Pkg *vieter_package_read_archive(const char *pkg_path); + +/* + * Deallocate a package. + */ +void vieter_package_free(Pkg ** ptp); + +/* + * Create string that will become the package's desc file. + */ +char *vieter_package_to_description(Pkg *pkg); + +#endif diff --git a/src/package/README.md b/src/package/README.md new file mode 100644 index 0000000..b2bcbd7 --- /dev/null +++ b/src/package/README.md @@ -0,0 +1,5 @@ +# package + +This module handles both parsing the published Arch tarballs & the contents of +their `.PKGINFO` files, as well as generating the contents of the database +archives' `desc` & `files` files. diff --git a/include/sha256.h b/src/package/sha256.h similarity index 100% rename from include/sha256.h rename to src/package/sha256.h diff --git a/src/package/package.c b/src/package/vieter_package.c similarity index 81% rename from src/package/package.c rename to src/package/vieter_package.c index 577e3c9..a3d2cd6 100644 --- a/src/package/package.c +++ b/src/package/vieter_package.c @@ -1,25 +1,25 @@ -#include "package.h" +#include "vieter_package_internal.h" #include "sha256.h" #define SMALL_BUFF_SIZE 128 -#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ +#define ADD_STRING(section, field) if (info->field != 0) { \ + snprintf(aux, SMALL_BUFF_SIZE, section, info->field); \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ } -#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ +#define ADD_ARRAY(section, field) i = 0; if (info->field != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, section, info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ - while (pkg_info->field->array[i] != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ + while (info->field->array[i] != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, "\n%s", info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ @@ -37,11 +37,11 @@ static char *ignored_names[5] = { }; static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *); -Pkg *package_init() { - return calloc(sizeof(PkgInfo), 1); +Pkg *vieter_package_init() { + return calloc(sizeof(pkg_info), 1); } -Pkg *package_read_archive(const char *pkg_path) { +Pkg *vieter_package_read_archive(const char *pkg_path) { struct archive *a = archive_read_new(); struct archive_entry *entry = archive_entry_new(); @@ -64,9 +64,9 @@ Pkg *package_read_archive(const char *pkg_path) { int compression_code = archive_filter_code(a, 0); const char *path_name; - PkgInfo *pkg_info; - DynArray *files = dynarray_init(16); - dynarray_add(files, "%FILES%"); + pkg_info *info; + dynarray *files = vieter_package_dynarray_init(16); + vieter_package_dynarray_add(files, "%FILES%"); while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { path_name = archive_entry_pathname(entry); @@ -81,7 +81,7 @@ Pkg *package_read_archive(const char *pkg_path) { } if (!ignore) { - dynarray_add(files, path_name); + vieter_package_dynarray_add(files, path_name); } if (strcmp(path_name, ".PKGINFO") == 0) { @@ -91,8 +91,8 @@ Pkg *package_read_archive(const char *pkg_path) { archive_read_data(a, buf, size); // Parse package info string into a struct - pkg_info = package_info_init(); - package_info_parse(pkg_info, buf); + info = vieter_package_info_init(); + vieter_package_info_parse(info, buf); free(buf); } else { @@ -107,21 +107,21 @@ Pkg *package_read_archive(const char *pkg_path) { return NULL; } - pkg_info->csize = stats.st_size; + info->csize = stats.st_size; archive_read_free(a); // Create final return value - Pkg *pkg = package_init(); + Pkg *pkg = vieter_package_init(); pkg->path = strdup(pkg_path); - pkg->info = pkg_info; + pkg->info = info; pkg->files = files; pkg->compression = compression_code; return pkg; } -void sha256sum(Pkg *pkg, char *res) { +void vieter_package_sha256sum(Pkg *pkg, char *res) { FILE *f = fopen(pkg->path, "r"); fseek(f, 0, SEEK_END); size_t size = ftell(f); @@ -170,18 +170,19 @@ void sha256sum(Pkg *pkg, char *res) { res[j] = '\0'; } -char *package_to_description(Pkg *pkg) { - PkgInfo *pkg_info = pkg->info; +char *vieter_package_to_description(Pkg *pkg) { + pkg_info *info = pkg->info; size_t buff_size = 1024; char aux[SMALL_BUFF_SIZE]; char *description = malloc(sizeof(char) * buff_size); + // Helper variable for ADD_ARRAY macro int i; // special case for FILENAME // assuming .pkg.tar.zst; other formats are valid, this should account for that - snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version, - pkg_info->arch); + snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", info->name, info->version, + info->arch); strcpy(description, aux); ADD_STRING("\n\n%%NAME%%\n%s", name); @@ -193,7 +194,7 @@ char *package_to_description(Pkg *pkg) { ADD_STRING("\n\n%%ISIZE%%\n%ld", size); char checksum[65]; - sha256sum(pkg, checksum); + vieter_package_sha256sum(pkg, checksum); snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum); if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { diff --git a/src/package/dynarray.c b/src/package/vieter_package_dynarray.c similarity index 67% rename from src/package/dynarray.c rename to src/package/vieter_package_dynarray.c index a78e7ff..4f23cbb 100644 --- a/src/package/dynarray.c +++ b/src/package/vieter_package_dynarray.c @@ -1,14 +1,14 @@ -#include "dynarray.h" +#include "vieter_package_dynarray.h" -DynArray *dynarray_init(size_t initial_capacity) { - DynArray *da = malloc(sizeof(DynArray)); +dynarray *vieter_package_dynarray_init(size_t initial_capacity) { + dynarray *da = malloc(sizeof(dynarray)); da->size = 0; da->capacity = initial_capacity; return da; } -void dynarray_add(DynArray *da, const char *s) { +void vieter_package_dynarray_add(dynarray *da, const char *s) { // An empty dynarray does not have an allocated internal array yet if (da->size == 0) { da->array = malloc(sizeof(char*) * da->capacity); @@ -24,7 +24,7 @@ void dynarray_add(DynArray *da, const char *s) { da->size++; } -void dynarray_free(DynArray *da) { +void vieter_package_dynarray_free(dynarray *da) { if (da == NULL) { return; } @@ -40,11 +40,11 @@ void dynarray_free(DynArray *da) { free(da); } -char **dynarray_convert(DynArray *da) { +char **vieter_package_dynarray_convert(dynarray *da) { char **array = da->array; da->array = NULL; - dynarray_free(da); + vieter_package_dynarray_free(da); return array; } diff --git a/src/package/vieter_package_dynarray.h b/src/package/vieter_package_dynarray.h new file mode 100644 index 0000000..0a96de0 --- /dev/null +++ b/src/package/vieter_package_dynarray.h @@ -0,0 +1,36 @@ +#ifndef VIETER_DYNARRAY +#define VIETER_DYNARRAY + +#include +#include +#include "vieter_package.h" + +typedef struct dynarray dynarray; +struct dynarray { + char **array; + size_t capacity; + size_t size; +}; + +/* + * Allocate a dynamic array. + */ +dynarray *vieter_package_dynarray_init(size_t initial_capacity); + +/* + * Initialise array (if it's not already initialised) and insert a string. + */ +void vieter_package_dynarray_add(dynarray *da, const char * s); + +/* + * Deallocate dynamic array. + */ +void vieter_package_dynarray_free(dynarray *da); + +/* + * Convert a dynarray into an array by freeing all its surrounding components + * and returning the underlying array pointer. + */ +char **vieter_package_dynarray_convert(dynarray *da); + +#endif diff --git a/src/package/package_info.c b/src/package/vieter_package_info.c similarity index 59% rename from src/package/package_info.c rename to src/package/vieter_package_info.c index 5e1986d..b897685 100644 --- a/src/package/package_info.c +++ b/src/package/vieter_package_info.c @@ -1,19 +1,19 @@ #include -#include "package_info.h" +#include "vieter_package_info.h" #define PKG_INFO_STRING(key_ptr, field) if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ value_ptr += strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n');\ tail_ptr[0] = '\0'; \ - pkg_info->field = strdup(value_ptr); \ + info->field = strdup(value_ptr); \ tail_ptr[0] = '\n'; \ } value_ptr = tail_ptr; #define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n');\ tail_ptr[0] = '\0'; \ - pkg_info->field = atoi(value_ptr); \ + info->field = atoi(value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr; @@ -21,40 +21,40 @@ value_ptr = value_ptr + strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n'); \ tail_ptr[0] = '\0'; \ - if(pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ - dynarray_add(pkg_info->field, value_ptr); \ + if(info->field == NULL) { info->field = vieter_package_dynarray_init(4); } \ + vieter_package_dynarray_add(info->field, value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr;\ } value_ptr = tail_ptr; -PkgInfo *package_info_init() { - return calloc(1, sizeof(PkgInfo)); +pkg_info *vieter_package_info_init() { + return calloc(1, sizeof(pkg_info)); } -void package_info_free(PkgInfo *pkg_info) { - FREE_STRING(pkg_info->name); - FREE_STRING(pkg_info->base); - FREE_STRING(pkg_info->version); - FREE_STRING(pkg_info->description); - FREE_STRING(pkg_info->url); - FREE_STRING(pkg_info->arch); - FREE_STRING(pkg_info->packager); - FREE_STRING(pkg_info->pgpsig); +void vieter_package_info_free(pkg_info *info) { + FREE_STRING(info->name); + FREE_STRING(info->base); + FREE_STRING(info->version); + FREE_STRING(info->description); + FREE_STRING(info->url); + FREE_STRING(info->arch); + FREE_STRING(info->packager); + FREE_STRING(info->pgpsig); - dynarray_free(pkg_info->groups); - dynarray_free(pkg_info->licenses); - dynarray_free(pkg_info->replaces); - dynarray_free(pkg_info->depends); - dynarray_free(pkg_info->conflicts); - dynarray_free(pkg_info->provides); - dynarray_free(pkg_info->optdepends); - dynarray_free(pkg_info->makedepends); - dynarray_free(pkg_info->checkdepends); + vieter_package_dynarray_free(info->groups); + vieter_package_dynarray_free(info->licenses); + vieter_package_dynarray_free(info->replaces); + vieter_package_dynarray_free(info->depends); + vieter_package_dynarray_free(info->conflicts); + vieter_package_dynarray_free(info->provides); + vieter_package_dynarray_free(info->optdepends); + vieter_package_dynarray_free(info->makedepends); + vieter_package_dynarray_free(info->checkdepends); - free(pkg_info); + free(info); } -void package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { +void vieter_package_info_parse(pkg_info *info, char *pkg_info_str) { char *value_ptr = pkg_info_str, *tail_ptr; PKG_INFO_STRING("\npkgname = ", name); diff --git a/src/package/vieter_package_info.h b/src/package/vieter_package_info.h new file mode 100644 index 0000000..fc9f411 --- /dev/null +++ b/src/package/vieter_package_info.h @@ -0,0 +1,52 @@ +#ifndef VIETER_PACKAGE_INFO +#define VIETER_PACKAGE_INFO + +#define FREE_STRING(sp) if (sp != NULL) free(sp) + +#include + +#include "vieter_package.h" +#include "vieter_package_dynarray.h" + + +typedef struct pkg_info { + char *name; + char *base; + char *version; + char *description; + int64_t size; + int64_t csize; + char *url; + char *arch; + int64_t build_date; + char *packager; + char *pgpsig; + int64_t pgpsigsize; + + dynarray *groups; + dynarray *licenses; + dynarray *replaces; + dynarray *depends; + dynarray *conflicts; + dynarray *provides; + dynarray *optdepends; + dynarray *makedepends; + dynarray *checkdepends; +} pkg_info; + +/* + * Allocate and initialise a pkg_info pointer to hold .PKGINFO. + */ +pkg_info *vieter_package_info_init(); + +/* + * Parse .PKGINFO file into something usable by libvieter. + */ +void vieter_package_info_parse(pkg_info *info, char *pkg_info_str); + +/* + * Deallocate a pkg_info pointer. + */ +void vieter_package_info_free(pkg_info *info); + +#endif diff --git a/src/package/vieter_package_internal.h b/src/package/vieter_package_internal.h new file mode 100644 index 0000000..c13278e --- /dev/null +++ b/src/package/vieter_package_internal.h @@ -0,0 +1,10 @@ +#include "vieter_package.h" +#include "vieter_package_info.h" +#include "vieter_package_dynarray.h" + +struct pkg { + char *path; + pkg_info *info; + dynarray *files; + int compression; +}; diff --git a/test/package/test_package.c b/test/package/test_package.c index c0c7085..a79d5df 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -1,7 +1,7 @@ #include "acutest.h" -#include "package.h" +#include "vieter_package_internal.h" -void test_pkg_info_parse() { +void test_info_parse() { FILE *f = fopen("./test/package/.PKGINFO", "r"); TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package "); fseek(f, 0L, SEEK_END); @@ -11,34 +11,35 @@ void test_pkg_info_parse() { char *pkg_info_str = malloc(size); fread(pkg_info_str, 1, size, f); fclose(f); - PkgInfo *pkg_info = package_info_init(); - package_info_parse(pkg_info, pkg_info_str); - TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); - TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); - TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); - TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); - TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); - TEST_CHECK(pkg_info->build_date == 1673751613); - TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); - TEST_CHECK(pkg_info->size == 3469584); - TEST_CHECK(!strcmp(pkg_info->arch, "any")); + pkg_info *info = vieter_package_info_init(); + vieter_package_info_parse(info, pkg_info_str); - TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); - TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); - TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); - TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); - TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); - TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); - TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); - TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); - TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); - TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); - TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); + TEST_CHECK(!strcmp(info->name, "xcursor-dmz")); + TEST_CHECK(!strcmp(info->base, "xcursor-dmz")); + TEST_CHECK(!strcmp(info->version, "0.4.5-2")); + TEST_CHECK(!strcmp(info->description, "Style neutral, scalable cursor theme")); + TEST_CHECK(!strcmp(info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); + TEST_CHECK(info->build_date == 1673751613); + TEST_CHECK(!strcmp(info->packager, "Unknown Packager")); + TEST_CHECK(info->size == 3469584); + TEST_CHECK(!strcmp(info->arch, "any")); + + TEST_CHECK(!strcmp(info->licenses->array[0], "MIT")); + TEST_CHECK(!strcmp(info->replaces->array[0], "test1")); + TEST_CHECK(!strcmp(info->groups->array[0], "x11")); + TEST_CHECK(!strcmp(info->conflicts->array[0], "test2")); + TEST_CHECK(!strcmp(info->conflicts->array[1], "test3")); + TEST_CHECK(!strcmp(info->provides->array[0], "test4")); + TEST_CHECK(!strcmp(info->depends->array[0], "test5")); + TEST_CHECK(!strcmp(info->depends->array[1], "test6")); + TEST_CHECK(!strcmp(info->optdepends->array[0], "test7")); + TEST_CHECK(!strcmp(info->makedepends->array[0], "xorg-xcursorgen")); + TEST_CHECK(!strcmp(info->checkdepends->array[0], "test8")); } void test_pkg_read_archive_files() { - Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + Pkg *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); FILE *f = fopen("./test/package/files", "r"); @@ -59,10 +60,10 @@ void test_pkg_read_archive_files() { } void test_pkg_read_archive_desc() { - Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + Pkg *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); - char *description = package_to_description(pkg); + char *description = vieter_package_to_description(pkg); FILE *f = fopen("./test/package/desc", "r"); TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package"); @@ -77,8 +78,8 @@ void test_pkg_read_archive_desc() { } TEST_LIST = { - {"pkg_info_valid_parse", test_pkg_info_parse}, - {"pkg_read_archive_files", test_pkg_read_archive_files}, - {"pkg_read_archive_desc", test_pkg_read_archive_desc}, + {".PKGINFO parse", test_info_parse}, + {"files array creation", test_pkg_read_archive_files}, + {"desc file creation", test_pkg_read_archive_desc}, {NULL, NULL} }; From de1227b97beeebcbd1fd45b81d0ab7253b463dbd Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sun, 29 Jan 2023 11:55:22 +0000 Subject: [PATCH 25/74] refactor: Added free function for package struct. While going through with the renaming, I saw that I actually forgot to implement that part. --- src/package/vieter_package.c | 9 +++++++++ test/package/test_package.c | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index a3d2cd6..4a6515c 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -221,3 +221,12 @@ char *vieter_package_to_description(Pkg *pkg) { return description; } + +void vieter_package_free(Pkg **ptp) { + FREE_STRING((*ptp)->path); + vieter_package_info_free((*ptp)->info); + vieter_package_dynarray_free((*ptp)->files); + free(*ptp); + *ptp = NULL; + +} diff --git a/test/package/test_package.c b/test/package/test_package.c index a79d5df..f6597c8 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -57,6 +57,8 @@ void test_pkg_read_archive_files() { } TEST_CHECK(pkg->compression = 14); + vieter_package_free(&pkg); + } void test_pkg_read_archive_desc() { From 4cacb1534fa6a7fa3d7603182fa6eb96635700ae Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sun, 29 Jan 2023 12:45:48 +0000 Subject: [PATCH 26/74] chore: Also renamed structs to follow naming conventions. --- include/vieter_package.h | 8 ++--- src/package/vieter_package.c | 46 ++++++++++++------------ src/package/vieter_package_dynarray.c | 12 +++---- src/package/vieter_package_dynarray.h | 14 ++++---- src/package/vieter_package_info.c | 52 +++++++++++++-------------- src/package/vieter_package_info.h | 28 +++++++-------- src/package/vieter_package_internal.h | 6 ++-- test/package/test_package.c | 48 ++++++++++++------------- 8 files changed, 107 insertions(+), 107 deletions(-) diff --git a/include/vieter_package.h b/include/vieter_package.h index ebe6487..179ff57 100644 --- a/include/vieter_package.h +++ b/include/vieter_package.h @@ -9,22 +9,22 @@ #include #include -typedef struct pkg Pkg; +typedef struct vieter_package vieter_package; /* * Parse package file into something usable by libvieter. * The pointer returned by this function will need to freed at a later point. */ -Pkg *vieter_package_read_archive(const char *pkg_path); +vieter_package *vieter_package_read_archive(const char *pkg_path); /* * Deallocate a package. */ -void vieter_package_free(Pkg ** ptp); +void vieter_package_free(vieter_package ** ptp); /* * Create string that will become the package's desc file. */ -char *vieter_package_to_description(Pkg *pkg); +char *vieter_package_to_description(vieter_package *pkg); #endif diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 4a6515c..3bb19ba 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -3,23 +3,23 @@ #define SMALL_BUFF_SIZE 128 -#define ADD_STRING(section, field) if (info->field != 0) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, info->field); \ +#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ + snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ } -#define ADD_ARRAY(section, field) i = 0; if (info->field != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, info->field->array[i]); i++; \ +#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ - while (info->field->array[i] != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, "\n%s", info->field->array[i]); i++; \ + while (pkg_info->field->array[i] != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ @@ -37,11 +37,11 @@ static char *ignored_names[5] = { }; static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *); -Pkg *vieter_package_init() { - return calloc(sizeof(pkg_info), 1); +vieter_package *vieter_package_init() { + return calloc(sizeof(vieter_package_info), 1); } -Pkg *vieter_package_read_archive(const char *pkg_path) { +vieter_package *vieter_package_read_archive(const char *pkg_path) { struct archive *a = archive_read_new(); struct archive_entry *entry = archive_entry_new(); @@ -64,8 +64,8 @@ Pkg *vieter_package_read_archive(const char *pkg_path) { int compression_code = archive_filter_code(a, 0); const char *path_name; - pkg_info *info; - dynarray *files = vieter_package_dynarray_init(16); + vieter_package_info *pkg_info; + vieter_package_dynarray *files = vieter_package_dynarray_init(16); vieter_package_dynarray_add(files, "%FILES%"); while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { @@ -90,9 +90,9 @@ Pkg *vieter_package_read_archive(const char *pkg_path) { char *buf = malloc(size); archive_read_data(a, buf, size); - // Parse package info string into a struct - info = vieter_package_info_init(); - vieter_package_info_parse(info, buf); + // Parse package vieter_package_info string into a struct + pkg_info = vieter_package_info_init(); + vieter_package_info_parse(pkg_info, buf); free(buf); } else { @@ -107,21 +107,21 @@ Pkg *vieter_package_read_archive(const char *pkg_path) { return NULL; } - info->csize = stats.st_size; + pkg_info->csize = stats.st_size; archive_read_free(a); // Create final return value - Pkg *pkg = vieter_package_init(); + vieter_package *pkg = vieter_package_init(); pkg->path = strdup(pkg_path); - pkg->info = info; + pkg->info = pkg_info; pkg->files = files; pkg->compression = compression_code; return pkg; } -void vieter_package_sha256sum(Pkg *pkg, char *res) { +void vieter_package_sha256sum(vieter_package *pkg, char *res) { FILE *f = fopen(pkg->path, "r"); fseek(f, 0, SEEK_END); size_t size = ftell(f); @@ -170,8 +170,8 @@ void vieter_package_sha256sum(Pkg *pkg, char *res) { res[j] = '\0'; } -char *vieter_package_to_description(Pkg *pkg) { - pkg_info *info = pkg->info; +char *vieter_package_to_description(vieter_package *pkg) { + vieter_package_info *pkg_info = pkg->info; size_t buff_size = 1024; char aux[SMALL_BUFF_SIZE]; @@ -181,8 +181,8 @@ char *vieter_package_to_description(Pkg *pkg) { // special case for FILENAME // assuming .pkg.tar.zst; other formats are valid, this should account for that - snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", info->name, info->version, - info->arch); + snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, + pkg_info->version, pkg_info->arch); strcpy(description, aux); ADD_STRING("\n\n%%NAME%%\n%s", name); @@ -222,7 +222,7 @@ char *vieter_package_to_description(Pkg *pkg) { return description; } -void vieter_package_free(Pkg **ptp) { +void vieter_package_free(vieter_package **ptp) { FREE_STRING((*ptp)->path); vieter_package_info_free((*ptp)->info); vieter_package_dynarray_free((*ptp)->files); diff --git a/src/package/vieter_package_dynarray.c b/src/package/vieter_package_dynarray.c index 4f23cbb..2cc20b6 100644 --- a/src/package/vieter_package_dynarray.c +++ b/src/package/vieter_package_dynarray.c @@ -1,15 +1,15 @@ #include "vieter_package_dynarray.h" -dynarray *vieter_package_dynarray_init(size_t initial_capacity) { - dynarray *da = malloc(sizeof(dynarray)); +vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity) { + vieter_package_dynarray *da = malloc(sizeof(vieter_package_dynarray)); da->size = 0; da->capacity = initial_capacity; return da; } -void vieter_package_dynarray_add(dynarray *da, const char *s) { - // An empty dynarray does not have an allocated internal array yet +void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { + // An empty vieter_package_dynarray does not have an allocated internal array yet if (da->size == 0) { da->array = malloc(sizeof(char*) * da->capacity); } @@ -24,7 +24,7 @@ void vieter_package_dynarray_add(dynarray *da, const char *s) { da->size++; } -void vieter_package_dynarray_free(dynarray *da) { +void vieter_package_dynarray_free(vieter_package_dynarray *da) { if (da == NULL) { return; } @@ -40,7 +40,7 @@ void vieter_package_dynarray_free(dynarray *da) { free(da); } -char **vieter_package_dynarray_convert(dynarray *da) { +char **vieter_package_dynarray_convert(vieter_package_dynarray *da) { char **array = da->array; da->array = NULL; diff --git a/src/package/vieter_package_dynarray.h b/src/package/vieter_package_dynarray.h index 0a96de0..c198ea1 100644 --- a/src/package/vieter_package_dynarray.h +++ b/src/package/vieter_package_dynarray.h @@ -5,8 +5,8 @@ #include #include "vieter_package.h" -typedef struct dynarray dynarray; -struct dynarray { +typedef struct vieter_package_dynarray vieter_package_dynarray; +struct vieter_package_dynarray { char **array; size_t capacity; size_t size; @@ -15,22 +15,22 @@ struct dynarray { /* * Allocate a dynamic array. */ -dynarray *vieter_package_dynarray_init(size_t initial_capacity); +vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity); /* * Initialise array (if it's not already initialised) and insert a string. */ -void vieter_package_dynarray_add(dynarray *da, const char * s); +void vieter_package_dynarray_add(vieter_package_dynarray *da, const char * s); /* * Deallocate dynamic array. */ -void vieter_package_dynarray_free(dynarray *da); +void vieter_package_dynarray_free(vieter_package_dynarray *da); /* - * Convert a dynarray into an array by freeing all its surrounding components + * Convert a vieter_package_dynarray into an array by freeing all its surrounding components * and returning the underlying array pointer. */ -char **vieter_package_dynarray_convert(dynarray *da); +char **vieter_package_dynarray_convert(vieter_package_dynarray *da); #endif diff --git a/src/package/vieter_package_info.c b/src/package/vieter_package_info.c index b897685..5ed040e 100644 --- a/src/package/vieter_package_info.c +++ b/src/package/vieter_package_info.c @@ -6,14 +6,14 @@ value_ptr += strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n');\ tail_ptr[0] = '\0'; \ - info->field = strdup(value_ptr); \ + pkg_info->field = strdup(value_ptr); \ tail_ptr[0] = '\n'; \ } value_ptr = tail_ptr; #define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n');\ tail_ptr[0] = '\0'; \ - info->field = atoi(value_ptr); \ + pkg_info->field = atoi(value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr; @@ -21,40 +21,40 @@ value_ptr = value_ptr + strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n'); \ tail_ptr[0] = '\0'; \ - if(info->field == NULL) { info->field = vieter_package_dynarray_init(4); } \ - vieter_package_dynarray_add(info->field, value_ptr); \ + if(pkg_info->field == NULL) { pkg_info->field = vieter_package_dynarray_init(4); } \ + vieter_package_dynarray_add(pkg_info->field, value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr;\ } value_ptr = tail_ptr; -pkg_info *vieter_package_info_init() { - return calloc(1, sizeof(pkg_info)); +vieter_package_info *vieter_package_info_init() { + return calloc(1, sizeof(vieter_package_info)); } -void vieter_package_info_free(pkg_info *info) { - FREE_STRING(info->name); - FREE_STRING(info->base); - FREE_STRING(info->version); - FREE_STRING(info->description); - FREE_STRING(info->url); - FREE_STRING(info->arch); - FREE_STRING(info->packager); - FREE_STRING(info->pgpsig); +void vieter_package_info_free(vieter_package_info *pkg_info) { + FREE_STRING(pkg_info->name); + FREE_STRING(pkg_info->base); + FREE_STRING(pkg_info->version); + FREE_STRING(pkg_info->description); + FREE_STRING(pkg_info->url); + FREE_STRING(pkg_info->arch); + FREE_STRING(pkg_info->packager); + FREE_STRING(pkg_info->pgpsig); - vieter_package_dynarray_free(info->groups); - vieter_package_dynarray_free(info->licenses); - vieter_package_dynarray_free(info->replaces); - vieter_package_dynarray_free(info->depends); - vieter_package_dynarray_free(info->conflicts); - vieter_package_dynarray_free(info->provides); - vieter_package_dynarray_free(info->optdepends); - vieter_package_dynarray_free(info->makedepends); - vieter_package_dynarray_free(info->checkdepends); + vieter_package_dynarray_free(pkg_info->groups); + vieter_package_dynarray_free(pkg_info->licenses); + vieter_package_dynarray_free(pkg_info->replaces); + vieter_package_dynarray_free(pkg_info->depends); + vieter_package_dynarray_free(pkg_info->conflicts); + vieter_package_dynarray_free(pkg_info->provides); + vieter_package_dynarray_free(pkg_info->optdepends); + vieter_package_dynarray_free(pkg_info->makedepends); + vieter_package_dynarray_free(pkg_info->checkdepends); - free(info); + free(pkg_info); } -void vieter_package_info_parse(pkg_info *info, char *pkg_info_str) { +void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str) { char *value_ptr = pkg_info_str, *tail_ptr; PKG_INFO_STRING("\npkgname = ", name); diff --git a/src/package/vieter_package_info.h b/src/package/vieter_package_info.h index fc9f411..b931928 100644 --- a/src/package/vieter_package_info.h +++ b/src/package/vieter_package_info.h @@ -9,7 +9,7 @@ #include "vieter_package_dynarray.h" -typedef struct pkg_info { +typedef struct vieter_package_info { char *name; char *base; char *version; @@ -23,30 +23,30 @@ typedef struct pkg_info { char *pgpsig; int64_t pgpsigsize; - dynarray *groups; - dynarray *licenses; - dynarray *replaces; - dynarray *depends; - dynarray *conflicts; - dynarray *provides; - dynarray *optdepends; - dynarray *makedepends; - dynarray *checkdepends; -} pkg_info; + vieter_package_dynarray *groups; + vieter_package_dynarray *licenses; + vieter_package_dynarray *replaces; + vieter_package_dynarray *depends; + vieter_package_dynarray *conflicts; + vieter_package_dynarray *provides; + vieter_package_dynarray *optdepends; + vieter_package_dynarray *makedepends; + vieter_package_dynarray *checkdepends; +} vieter_package_info; /* * Allocate and initialise a pkg_info pointer to hold .PKGINFO. */ -pkg_info *vieter_package_info_init(); +vieter_package_info *vieter_package_info_init(); /* * Parse .PKGINFO file into something usable by libvieter. */ -void vieter_package_info_parse(pkg_info *info, char *pkg_info_str); +void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str); /* * Deallocate a pkg_info pointer. */ -void vieter_package_info_free(pkg_info *info); +void vieter_package_info_free(vieter_package_info *pkg_info); #endif diff --git a/src/package/vieter_package_internal.h b/src/package/vieter_package_internal.h index c13278e..fe84f17 100644 --- a/src/package/vieter_package_internal.h +++ b/src/package/vieter_package_internal.h @@ -2,9 +2,9 @@ #include "vieter_package_info.h" #include "vieter_package_dynarray.h" -struct pkg { +struct vieter_package { char *path; - pkg_info *info; - dynarray *files; + vieter_package_info *info; + vieter_package_dynarray *files; int compression; }; diff --git a/test/package/test_package.c b/test/package/test_package.c index f6597c8..5bbda26 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -12,34 +12,34 @@ void test_info_parse() { fread(pkg_info_str, 1, size, f); fclose(f); - pkg_info *info = vieter_package_info_init(); - vieter_package_info_parse(info, pkg_info_str); + vieter_package_info *pkg_info = vieter_package_info_init(); + vieter_package_info_parse(pkg_info, pkg_info_str); - TEST_CHECK(!strcmp(info->name, "xcursor-dmz")); - TEST_CHECK(!strcmp(info->base, "xcursor-dmz")); - TEST_CHECK(!strcmp(info->version, "0.4.5-2")); - TEST_CHECK(!strcmp(info->description, "Style neutral, scalable cursor theme")); - TEST_CHECK(!strcmp(info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); - TEST_CHECK(info->build_date == 1673751613); - TEST_CHECK(!strcmp(info->packager, "Unknown Packager")); - TEST_CHECK(info->size == 3469584); - TEST_CHECK(!strcmp(info->arch, "any")); + TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); + TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); + TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); + TEST_CHECK(pkg_info->build_date == 1673751613); + TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); + TEST_CHECK(pkg_info->size == 3469584); + TEST_CHECK(!strcmp(pkg_info->arch, "any")); - TEST_CHECK(!strcmp(info->licenses->array[0], "MIT")); - TEST_CHECK(!strcmp(info->replaces->array[0], "test1")); - TEST_CHECK(!strcmp(info->groups->array[0], "x11")); - TEST_CHECK(!strcmp(info->conflicts->array[0], "test2")); - TEST_CHECK(!strcmp(info->conflicts->array[1], "test3")); - TEST_CHECK(!strcmp(info->provides->array[0], "test4")); - TEST_CHECK(!strcmp(info->depends->array[0], "test5")); - TEST_CHECK(!strcmp(info->depends->array[1], "test6")); - TEST_CHECK(!strcmp(info->optdepends->array[0], "test7")); - TEST_CHECK(!strcmp(info->makedepends->array[0], "xorg-xcursorgen")); - TEST_CHECK(!strcmp(info->checkdepends->array[0], "test8")); + TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); + TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); + TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); + TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); + TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); + TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); + TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); + TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); + TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); } void test_pkg_read_archive_files() { - Pkg *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); FILE *f = fopen("./test/package/files", "r"); @@ -62,7 +62,7 @@ void test_pkg_read_archive_files() { } void test_pkg_read_archive_desc() { - Pkg *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); char *description = vieter_package_to_description(pkg); From 06fca6f5ae68b8fc9e3f5f9790fedec54e70d172 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 29 Jan 2023 17:32:27 +0100 Subject: [PATCH 27/74] refactor(tree): better testing code --- src/tree/vieter_tree.c | 11 +++--- src/tree/vieter_tree_balancing.c | 68 ++++++++++++++------------------ src/tree/vieter_tree_balancing.h | 11 ++++++ src/tree/vieter_tree_internal.h | 6 ++- src/tree/vieter_tree_node.c | 7 ++-- src/tree/vieter_tree_node.h | 22 ++++++----- test/tree/test_tree.c | 6 +-- 7 files changed, 70 insertions(+), 61 deletions(-) diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index 792ad30..bd0200e 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -16,7 +16,7 @@ vieter_tree_error vieter_tree_insert(vieter_tree *tree, uint64_t key, tree->root = vieter_tree_node_init(); tree->root->key = key; tree->root->data = data; - vieter_tree_node_set(tree->root, vieter_node_black); + vieter_tree_node_set(tree->root, vieter_tree_node_black); tree->size = 1; return vieter_tree_ok; @@ -99,9 +99,9 @@ end: free(tree); } -int vieter_tree_validate(vieter_tree *tree) { +bool vieter_tree_validate(vieter_tree *tree) { if (tree->size == 0) { - return 0; + return true; } // DFS to get expected black nodes @@ -109,12 +109,13 @@ int vieter_tree_validate(vieter_tree *tree) { vieter_tree_node *node = tree->root; while (node != NULL) { - if (vieter_tree_node_get(node, vieter_node_black)) { + if (vieter_tree_node_get(node, vieter_tree_node_black)) { expected_black_nodes++; } node = node->left; } - return vieter_tree_node_validate(tree->root, 0, expected_black_nodes); + return vieter_tree_node_get(tree->root, vieter_tree_node_black) && + vieter_tree_node_validate(tree->root, 0, expected_black_nodes); } diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index 70c52e0..d9fc66e 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -1,41 +1,31 @@ #include "vieter_tree_balancing.h" -int vieter_tree_node_validate(vieter_tree_node *node, - uint64_t passed_black_nodes, - uint64_t expected_black_nodes) { - if (vieter_tree_node_get(node, vieter_node_black)) { +bool vieter_tree_node_validate(vieter_tree_node *node, + uint64_t passed_black_nodes, + uint64_t expected_black_nodes) { + // Path to NULL children should contain the same amount of black nodes + if (node == NULL) { + return passed_black_nodes == expected_black_nodes; + } + + if (vieter_tree_node_get(node, vieter_tree_node_black)) { passed_black_nodes++; - } else { - // A red node should have black child nodes - if ((node->left != NULL && - !vieter_tree_node_get(node->left, vieter_node_black)) || - (node->right != NULL && - !vieter_tree_node_get(node->right, vieter_node_black))) { - return 1; - } } - // All paths to a NULL child should have the same amount of black nodes - if ((node->left == NULL || node->right == NULL) && - passed_black_nodes != expected_black_nodes) { - return 1; - } + // Either the node itself is black, or its children are both either NULL or + // black. + bool correctly_colored_children = + vieter_tree_node_get(node, vieter_tree_node_black) || + ((node->left == NULL || + vieter_tree_node_get(node->left, vieter_tree_node_black)) && + (node->right == NULL || + vieter_tree_node_get(node->right, vieter_tree_node_black))); - if (node->left != NULL) { - if (vieter_tree_node_validate(node->left, passed_black_nodes, - expected_black_nodes) != 0) { - return 1; - } - } - - if (node->right != NULL) { - if (vieter_tree_node_validate(node->right, passed_black_nodes, - expected_black_nodes) != 0) { - return 1; - } - } - - return 0; + return correctly_colored_children && + vieter_tree_node_validate(node->left, passed_black_nodes, + expected_black_nodes) && + vieter_tree_node_validate(node->right, passed_black_nodes, + expected_black_nodes); } vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { @@ -106,9 +96,9 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { children[3] = node->right; } - vieter_tree_node_set(left, vieter_node_black); - vieter_tree_node_set(right, vieter_node_black); - vieter_tree_node_unset(root, vieter_node_black); + vieter_tree_node_set(left, vieter_tree_node_black); + vieter_tree_node_set(right, vieter_tree_node_black); + vieter_tree_node_unset(root, vieter_tree_node_black); left->left = children[0]; left->right = children[1]; @@ -137,14 +127,16 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { } void vieter_tree_node_balance_after_insert(vieter_tree_node *node) { - while (!vieter_tree_node_get(node, vieter_node_black) && + while (!vieter_tree_node_get(node, vieter_tree_node_black) && node->parent != NULL && - !vieter_tree_node_get(node->parent, vieter_node_black)) { + !vieter_tree_node_get(node->parent, vieter_tree_node_black)) { node = vieter_tree_node_balance(node); } // The root must always be black if (node->parent == NULL) { - vieter_tree_node_set(node, vieter_node_black); + vieter_tree_node_set(node, vieter_tree_node_black); } } + +void vieter_tree_node_remove_balanced(vieter_tree_node *node) {} diff --git a/src/tree/vieter_tree_balancing.h b/src/tree/vieter_tree_balancing.h index 4492588..007af34 100644 --- a/src/tree/vieter_tree_balancing.h +++ b/src/tree/vieter_tree_balancing.h @@ -3,6 +3,17 @@ #include "vieter_tree_node.h" +/* + * Ensure the tree remains a valid red-black tree after having inserting the + * node. + */ void vieter_tree_node_balance_after_insert(vieter_tree_node *node); +/* + * Remove the given node, ensuring the tree remains a valid red-black tree. + * + * @param node node to remove. This node should have at least one NULL child. + */ +void vieter_tree_node_remove_balanced(vieter_tree_node *node); + #endif diff --git a/src/tree/vieter_tree_internal.h b/src/tree/vieter_tree_internal.h index dc4ee81..670d45b 100644 --- a/src/tree/vieter_tree_internal.h +++ b/src/tree/vieter_tree_internal.h @@ -1,8 +1,10 @@ #include "vieter_tree.h" +#include + /* * Inspect whether the tree is still a valid red-black-tree. * - * @return 0 if correct, 1 if not. + * @return true if valid, false otherwise. */ -int vieter_tree_validate(vieter_tree *tree); +bool vieter_tree_validate(vieter_tree *tree); diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index 40407a3..b7e82a8 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -153,14 +153,15 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, return vieter_tree_ok; } -void vieter_tree_node_set(vieter_tree_node *node, vieter_node_flag flag) { +void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag) { node->flags |= flag; } -void vieter_tree_node_unset(vieter_tree_node *node, vieter_node_flag flag) { +void vieter_tree_node_unset(vieter_tree_node *node, + vieter_tree_node_flag flag) { node->flags &= ~flag; } -bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag) { +bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag) { return (node->flags & flag) != 0; } diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 1c88159..5e74280 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -5,11 +5,9 @@ #include #include -#define VIETER_NODE_BLACK ((uint8_t)1) - -typedef enum vieter_node_flag { - vieter_node_black = ((uint8_t)1) << 0 -} vieter_node_flag; +typedef enum vieter_tree_node_flag { + vieter_tree_node_black = ((uint8_t)1) << 0 +} vieter_tree_node_flag; typedef struct vieter_tree_node { uint64_t key; @@ -26,20 +24,24 @@ void vieter_tree_node_free(vieter_tree_node *node); vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, void *data); +/* + * Return the node representing the requested value. + */ vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, vieter_tree_node *root, uint64_t key); + vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, uint64_t key); vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, uint64_t key); -void vieter_tree_node_replace(vieter_tree_node *to_replace, vieter_tree_node *replacement); +void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement); -void vieter_tree_node_set(vieter_tree_node *node, vieter_node_flag flag); -void vieter_tree_node_unset(vieter_tree_node *node, vieter_node_flag flag); -bool vieter_tree_node_get(vieter_tree_node *node, vieter_node_flag flag); +void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag); +void vieter_tree_node_unset(vieter_tree_node *node, vieter_tree_node_flag flag); +bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag); void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, vieter_tree_node *child); -int vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, uint64_t expected_black_nodes); +bool vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, uint64_t expected_black_nodes); #endif diff --git a/test/tree/test_tree.c b/test/tree/test_tree.c index c875137..257ec66 100644 --- a/test/tree/test_tree.c +++ b/test/tree/test_tree.c @@ -18,7 +18,7 @@ void test_insert() { for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); TEST_SIZE(tree, i + 1); - TEST_CHECK(vieter_tree_validate(tree) == 0); + TEST_CHECK(vieter_tree_validate(tree)); } void *out; @@ -37,7 +37,7 @@ void test_remove() { for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); - TEST_CHECK(vieter_tree_validate(tree) == 0); + TEST_CHECK(vieter_tree_validate(tree)); } void *out; @@ -45,7 +45,7 @@ void test_remove() { for (uint64_t i = 0; i < 25; i++) { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok); - TEST_CHECK(vieter_tree_validate(tree) == 0); + TEST_CHECK(vieter_tree_validate(tree)); TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_not_present); TEST_SIZE(tree, 250 - i - 1); } From 193fc4b454135d67d331afcebc7f956a62ab08fb Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 29 Jan 2023 20:33:11 +0100 Subject: [PATCH 28/74] refactor(tree): store children as static array instead --- src/tree/vieter_tree.c | 10 +++--- src/tree/vieter_tree_balancing.c | 56 ++++++++++++++++---------------- src/tree/vieter_tree_node.c | 45 +++++++++---------------- src/tree/vieter_tree_node.h | 8 +++-- 4 files changed, 54 insertions(+), 65 deletions(-) diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index bd0200e..92f8831 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -80,13 +80,13 @@ void vieter_tree_free(vieter_tree *tree) { stack = realloc(stack, capacity * sizeof(vieter_tree_node *)); } - if (node->left != NULL) { - stack[size] = node->left; + if (node->children[0] != NULL) { + stack[size] = node->children[0]; size++; } - if (node->right != NULL) { - stack[size] = node->right; + if (node->children[1] != NULL) { + stack[size] = node->children[1]; size++; } @@ -113,7 +113,7 @@ bool vieter_tree_validate(vieter_tree *tree) { expected_black_nodes++; } - node = node->left; + node = node->children[0]; } return vieter_tree_node_get(tree->root, vieter_tree_node_black) && diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index d9fc66e..c04825d 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -16,15 +16,15 @@ bool vieter_tree_node_validate(vieter_tree_node *node, // black. bool correctly_colored_children = vieter_tree_node_get(node, vieter_tree_node_black) || - ((node->left == NULL || - vieter_tree_node_get(node->left, vieter_tree_node_black)) && - (node->right == NULL || - vieter_tree_node_get(node->right, vieter_tree_node_black))); + ((node->children[0] == NULL || + vieter_tree_node_get(node->children[0], vieter_tree_node_black)) && + (node->children[1] == NULL || + vieter_tree_node_get(node->children[1], vieter_tree_node_black))); return correctly_colored_children && - vieter_tree_node_validate(node->left, passed_black_nodes, + vieter_tree_node_validate(node->children[0], passed_black_nodes, expected_black_nodes) && - vieter_tree_node_validate(node->right, passed_black_nodes, + vieter_tree_node_validate(node->children[1], passed_black_nodes, expected_black_nodes); } @@ -48,10 +48,10 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { left = node; right = parent; - children[0] = node->left; - children[1] = node->right; - children[2] = parent->right; - children[3] = grand_parent->right; + children[0] = node->children[0]; + children[1] = node->children[1]; + children[2] = parent->children[1]; + children[3] = grand_parent->children[1]; } else if (node->key < parent->key && parent->key > grand_parent->key) { root->key = node->key; root->data = node->data; @@ -62,10 +62,10 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { left = node; right = parent; - children[0] = grand_parent->left; - children[1] = node->left; - children[2] = node->right; - children[3] = parent->right; + children[0] = grand_parent->children[0]; + children[1] = node->children[0]; + children[2] = node->children[1]; + children[3] = parent->children[1]; } else if (node->key > parent->key && parent->key < grand_parent->key) { root->key = node->key; root->data = node->data; @@ -76,10 +76,10 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { left = parent; right = node; - children[0] = parent->left; - children[1] = node->left; - children[2] = node->right; - children[3] = grand_parent->right; + children[0] = parent->children[0]; + children[1] = node->children[0]; + children[2] = node->children[1]; + children[3] = grand_parent->children[1]; } else { root->key = parent->key; root->data = parent->data; @@ -90,18 +90,18 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { left = parent; right = node; - children[0] = grand_parent->left; - children[1] = parent->left; - children[2] = node->left; - children[3] = node->right; + children[0] = grand_parent->children[0]; + children[1] = parent->children[0]; + children[2] = node->children[0]; + children[3] = node->children[1]; } vieter_tree_node_set(left, vieter_tree_node_black); vieter_tree_node_set(right, vieter_tree_node_black); vieter_tree_node_unset(root, vieter_tree_node_black); - left->left = children[0]; - left->right = children[1]; + left->children[0] = children[0]; + left->children[1] = children[1]; if (children[0] != NULL) children[0]->parent = left; @@ -109,8 +109,8 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { if (children[1] != NULL) children[1]->parent = left; - right->left = children[2]; - right->right = children[3]; + right->children[0] = children[2]; + right->children[1] = children[3]; if (children[2] != NULL) children[2]->parent = right; @@ -118,8 +118,8 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { if (children[3] != NULL) children[3]->parent = right; - root->left = left; - root->right = right; + root->children[0] = left; + root->children[1] = right; left->parent = root; right->parent = root; diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index b7e82a8..ca506b9 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -13,11 +13,7 @@ void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, return; } - if (key < parent->key) { - parent->left = child; - } else { - parent->right = child; - } + parent->children[key > parent->key] = child; if (child != NULL) { child->parent = parent; @@ -28,14 +24,14 @@ void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement) { to_replace->key = replacement->key; to_replace->data = replacement->data; - to_replace->left = replacement->left; - to_replace->right = replacement->right; + to_replace->children[0] = replacement->children[0]; + to_replace->children[1] = replacement->children[1]; - if (to_replace->left != NULL) - to_replace->left->parent = to_replace; + if (to_replace->children[0] != NULL) + to_replace->children[0]->parent = to_replace; - if (to_replace->right != NULL) - to_replace->right->parent = to_replace; + if (to_replace->children[1] != NULL) + to_replace->children[1]->parent = to_replace; } vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, @@ -49,12 +45,7 @@ vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, } parent = node; - - if (key < parent->key) { - node = parent->left; - } else { - node = parent->right; - } + node = node->children[key > parent->key]; } vieter_tree_node *new_node = vieter_tree_node_init(); @@ -79,11 +70,7 @@ vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, return vieter_tree_ok; } - if (key < node->key) { - node = node->left; - } else { - node = node->right; - } + node = node->children[key > node->key]; } return vieter_tree_not_present; @@ -114,13 +101,13 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, *out = target->data; - if (target->left == NULL && target->right == NULL) { + if (target->children[0] == NULL && target->children[1] == NULL) { vieter_tree_node_add_child(target->parent, target->key, NULL); vieter_tree_node_free(target); - } else if ((target->left == NULL) ^ (target->right == NULL)) { + } else if ((target->children[0] == NULL) ^ (target->children[1] == NULL)) { vieter_tree_node *child = - target->left != NULL ? target->left : target->right; + target->children[0] != NULL ? target->children[0] : target->children[1]; if (target->parent != NULL) { vieter_tree_node_add_child(target->parent, child->key, child); @@ -131,10 +118,10 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, } } else { - vieter_tree_node *replacement = target->right; + vieter_tree_node *replacement = target->children[1]; - while (replacement->left != NULL) { - replacement = replacement->left; + while (replacement->children[0] != NULL) { + replacement = replacement->children[0]; } // We use replacement->key here because the right child can be NULL, so @@ -142,7 +129,7 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, // will still get placed into the right location because of how binary // trees work. vieter_tree_node_add_child(replacement->parent, replacement->key, - replacement->right); + replacement->children[1]); target->key = replacement->key; target->data = replacement->data; diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 5e74280..21bbb81 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -6,15 +6,17 @@ #include typedef enum vieter_tree_node_flag { - vieter_tree_node_black = ((uint8_t)1) << 0 + vieter_tree_node_black = ((uint8_t)1) << 0, + // This flag is used to index the children array. If this flag isn't set, + // it'll evaluate to false, or index 0 in the children array. + vieter_tree_node_right = ((uint8_t)1) << 1 } vieter_tree_node_flag; typedef struct vieter_tree_node { uint64_t key; void *data; struct vieter_tree_node *parent; - struct vieter_tree_node *left; - struct vieter_tree_node *right; + struct vieter_tree_node *children[2]; uint8_t flags; } vieter_tree_node; From e5130a638377751197c5f574533efe2325e23591 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 29 Jan 2023 20:57:08 +0100 Subject: [PATCH 29/74] feat(tree): bit flag so children know which child they are --- src/tree/vieter_tree.c | 2 +- src/tree/vieter_tree_balancing.c | 134 +++++++++++++++++-------------- src/tree/vieter_tree_node.c | 24 +++--- src/tree/vieter_tree_node.h | 3 +- 4 files changed, 89 insertions(+), 74 deletions(-) diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index 92f8831..b066af1 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -16,7 +16,7 @@ vieter_tree_error vieter_tree_insert(vieter_tree *tree, uint64_t key, tree->root = vieter_tree_node_init(); tree->root->key = key; tree->root->data = data; - vieter_tree_node_set(tree->root, vieter_tree_node_black); + vieter_tree_node_set(tree->root, vieter_tree_node_black, true); tree->size = 1; return vieter_tree_ok; diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index c04825d..6a58179 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -1,4 +1,5 @@ #include "vieter_tree_balancing.h" +#include bool vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, @@ -38,85 +39,96 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { uint64_t key_root = root->key; void *data_root = root->data; - if (node->key < parent->key && parent->key < grand_parent->key) { - root->key = parent->key; - root->data = parent->data; - - parent->key = key_root; - parent->data = data_root; - - left = node; - right = parent; - - children[0] = node->children[0]; - children[1] = node->children[1]; - children[2] = parent->children[1]; - children[3] = grand_parent->children[1]; - } else if (node->key < parent->key && parent->key > grand_parent->key) { - root->key = node->key; - root->data = node->data; - - node->key = key_root; - node->data = data_root; - - left = node; - right = parent; - - children[0] = grand_parent->children[0]; - children[1] = node->children[0]; - children[2] = node->children[1]; - children[3] = parent->children[1]; - } else if (node->key > parent->key && parent->key < grand_parent->key) { - root->key = node->key; - root->data = node->data; - - node->key = key_root; - node->data = data_root; - + if (vieter_tree_node_get(node, vieter_tree_node_right)) { left = parent; right = node; - children[0] = parent->children[0]; - children[1] = node->children[0]; - children[2] = node->children[1]; - children[3] = grand_parent->children[1]; + if (vieter_tree_node_get(parent, vieter_tree_node_right)) { + root->key = parent->key; + root->data = parent->data; + + parent->key = key_root; + parent->data = data_root; + + children[0] = grand_parent->children[0]; + children[1] = parent->children[0]; + children[2] = node->children[0]; + children[3] = node->children[1]; + } else { + root->key = node->key; + root->data = node->data; + + node->key = key_root; + node->data = data_root; + + children[0] = parent->children[0]; + children[1] = node->children[0]; + children[2] = node->children[1]; + children[3] = grand_parent->children[1]; + } } else { - root->key = parent->key; - root->data = parent->data; + left = node; + right = parent; - parent->key = key_root; - parent->data = data_root; + if (vieter_tree_node_get(parent, vieter_tree_node_right)) { + root->key = node->key; + root->data = node->data; - left = parent; - right = node; + node->key = key_root; + node->data = data_root; - children[0] = grand_parent->children[0]; - children[1] = parent->children[0]; - children[2] = node->children[0]; - children[3] = node->children[1]; + children[0] = grand_parent->children[0]; + children[1] = node->children[0]; + children[2] = node->children[1]; + children[3] = parent->children[1]; + } else { + root->key = parent->key; + root->data = parent->data; + + parent->key = key_root; + parent->data = data_root; + + children[0] = node->children[0]; + children[1] = node->children[1]; + children[2] = parent->children[1]; + children[3] = grand_parent->children[1]; + } } - vieter_tree_node_set(left, vieter_tree_node_black); - vieter_tree_node_set(right, vieter_tree_node_black); - vieter_tree_node_unset(root, vieter_tree_node_black); + vieter_tree_node_set( + root, vieter_tree_node_right, + vieter_tree_node_get(grand_parent, vieter_tree_node_right)); - left->children[0] = children[0]; - left->children[1] = children[1]; + vieter_tree_node_set(left, vieter_tree_node_black, true); + vieter_tree_node_set(left, vieter_tree_node_right, false); + vieter_tree_node_set(right, vieter_tree_node_black, true); + vieter_tree_node_set(left, vieter_tree_node_right, true); - if (children[0] != NULL) + vieter_tree_node_set(root, vieter_tree_node_black, false); + + memcpy(&left->children, children, 2 * sizeof(vieter_tree_node *)); + + if (children[0] != NULL) { children[0]->parent = left; + vieter_tree_node_set(children[0], vieter_tree_node_right, false); + } - if (children[1] != NULL) + if (children[1] != NULL) { children[1]->parent = left; + vieter_tree_node_set(children[0], vieter_tree_node_right, true); + } - right->children[0] = children[2]; - right->children[1] = children[3]; + memcpy(&right->children, children + 2, 2 * sizeof(vieter_tree_node *)); - if (children[2] != NULL) + if (children[2] != NULL) { children[2]->parent = right; + vieter_tree_node_set(children[2], vieter_tree_node_right, false); + } - if (children[3] != NULL) + if (children[3] != NULL) { children[3]->parent = right; + vieter_tree_node_set(children[2], vieter_tree_node_right, true); + } root->children[0] = left; root->children[1] = right; @@ -135,7 +147,7 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node) { // The root must always be black if (node->parent == NULL) { - vieter_tree_node_set(node, vieter_tree_node_black); + vieter_tree_node_set(node, vieter_tree_node_black, true); } } diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index ca506b9..853281a 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -1,6 +1,8 @@ #include "vieter_tree_node.h" #include "vieter_tree_balancing.h" +#include + vieter_tree_node *vieter_tree_node_init() { return calloc(1, sizeof(vieter_tree_node)); } @@ -13,10 +15,12 @@ void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, return; } - parent->children[key > parent->key] = child; + bool side = key > parent->key; + parent->children[side] = child; if (child != NULL) { child->parent = parent; + vieter_tree_node_set(child, vieter_tree_node_right, side); } } @@ -24,8 +28,8 @@ void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement) { to_replace->key = replacement->key; to_replace->data = replacement->data; - to_replace->children[0] = replacement->children[0]; - to_replace->children[1] = replacement->children[1]; + memcpy(to_replace->children, replacement->children, + 2 * sizeof(vieter_tree_node *)); if (to_replace->children[0] != NULL) to_replace->children[0]->parent = to_replace; @@ -140,13 +144,13 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, return vieter_tree_ok; } -void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag) { - node->flags |= flag; -} - -void vieter_tree_node_unset(vieter_tree_node *node, - vieter_tree_node_flag flag) { - node->flags &= ~flag; +void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag, + bool set) { + if (set) { + node->flags |= flag; + } else { + node->flags &= ~flag; + } } bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag) { diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 21bbb81..4012d1d 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -37,8 +37,7 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, ui void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement); -void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag); -void vieter_tree_node_unset(vieter_tree_node *node, vieter_tree_node_flag flag); +void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag, bool value); bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag); void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, From b74a4e932651466259ba02d34b114d2037864aca Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 29 Jan 2023 21:08:17 +0100 Subject: [PATCH 30/74] refactor(tree): bit more cleanup --- src/tree/vieter_tree_balancing.c | 81 +++++++++++--------------------- src/tree/vieter_tree_node.c | 21 +++++---- src/tree/vieter_tree_node.h | 1 + 3 files changed, 41 insertions(+), 62 deletions(-) diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index 6a58179..b160563 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -33,15 +33,15 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { vieter_tree_node *parent = node->parent; vieter_tree_node *grand_parent = parent->parent; vieter_tree_node *root = grand_parent; - vieter_tree_node *left, *right; - vieter_tree_node *children[4]; + vieter_tree_node *children[2]; + vieter_tree_node *grand_children[4]; uint64_t key_root = root->key; void *data_root = root->data; if (vieter_tree_node_get(node, vieter_tree_node_right)) { - left = parent; - right = node; + children[0] = parent; + children[1] = node; if (vieter_tree_node_get(parent, vieter_tree_node_right)) { root->key = parent->key; @@ -50,10 +50,10 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { parent->key = key_root; parent->data = data_root; - children[0] = grand_parent->children[0]; - children[1] = parent->children[0]; - children[2] = node->children[0]; - children[3] = node->children[1]; + grand_children[0] = grand_parent->children[0]; + grand_children[1] = parent->children[0]; + grand_children[2] = node->children[0]; + grand_children[3] = node->children[1]; } else { root->key = node->key; root->data = node->data; @@ -61,14 +61,14 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { node->key = key_root; node->data = data_root; - children[0] = parent->children[0]; - children[1] = node->children[0]; - children[2] = node->children[1]; - children[3] = grand_parent->children[1]; + grand_children[0] = parent->children[0]; + grand_children[1] = node->children[0]; + grand_children[2] = node->children[1]; + grand_children[3] = grand_parent->children[1]; } } else { - left = node; - right = parent; + children[0] = node; + children[1] = parent; if (vieter_tree_node_get(parent, vieter_tree_node_right)) { root->key = node->key; @@ -77,10 +77,10 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { node->key = key_root; node->data = data_root; - children[0] = grand_parent->children[0]; - children[1] = node->children[0]; - children[2] = node->children[1]; - children[3] = parent->children[1]; + grand_children[0] = grand_parent->children[0]; + grand_children[1] = node->children[0]; + grand_children[2] = node->children[1]; + grand_children[3] = parent->children[1]; } else { root->key = parent->key; root->data = parent->data; @@ -88,10 +88,10 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { parent->key = key_root; parent->data = data_root; - children[0] = node->children[0]; - children[1] = node->children[1]; - children[2] = parent->children[1]; - children[3] = grand_parent->children[1]; + grand_children[0] = node->children[0]; + grand_children[1] = node->children[1]; + grand_children[2] = parent->children[1]; + grand_children[3] = grand_parent->children[1]; } } @@ -99,41 +99,14 @@ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { root, vieter_tree_node_right, vieter_tree_node_get(grand_parent, vieter_tree_node_right)); - vieter_tree_node_set(left, vieter_tree_node_black, true); - vieter_tree_node_set(left, vieter_tree_node_right, false); - vieter_tree_node_set(right, vieter_tree_node_black, true); - vieter_tree_node_set(left, vieter_tree_node_right, true); + vieter_tree_node_set(children[0], vieter_tree_node_black, true); + vieter_tree_node_set(children[1], vieter_tree_node_black, true); vieter_tree_node_set(root, vieter_tree_node_black, false); - memcpy(&left->children, children, 2 * sizeof(vieter_tree_node *)); - - if (children[0] != NULL) { - children[0]->parent = left; - vieter_tree_node_set(children[0], vieter_tree_node_right, false); - } - - if (children[1] != NULL) { - children[1]->parent = left; - vieter_tree_node_set(children[0], vieter_tree_node_right, true); - } - - memcpy(&right->children, children + 2, 2 * sizeof(vieter_tree_node *)); - - if (children[2] != NULL) { - children[2]->parent = right; - vieter_tree_node_set(children[2], vieter_tree_node_right, false); - } - - if (children[3] != NULL) { - children[3]->parent = right; - vieter_tree_node_set(children[2], vieter_tree_node_right, true); - } - - root->children[0] = left; - root->children[1] = right; - left->parent = root; - right->parent = root; + vieter_tree_node_set_children(children[0], grand_children); + vieter_tree_node_set_children(children[1], grand_children + 2); + vieter_tree_node_set_children(root, children); return root; } diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index 853281a..2f45b82 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -24,18 +24,23 @@ void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, } } +void vieter_tree_node_set_children(vieter_tree_node *parent, + vieter_tree_node **children) { + memcpy(parent->children, children, 2 * sizeof(vieter_tree_node *)); + + for (uint8_t i = 0; i < 2; i++) { + if (parent->children[i] != NULL) { + parent->children[i]->parent = parent; + vieter_tree_node_set(parent->children[i], vieter_tree_node_right, i); + } + } +} + void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement) { to_replace->key = replacement->key; to_replace->data = replacement->data; - memcpy(to_replace->children, replacement->children, - 2 * sizeof(vieter_tree_node *)); - - if (to_replace->children[0] != NULL) - to_replace->children[0]->parent = to_replace; - - if (to_replace->children[1] != NULL) - to_replace->children[1]->parent = to_replace; + vieter_tree_node_set_children(to_replace, replacement->children); } vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 4012d1d..1ebb15a 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -42,6 +42,7 @@ bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag); void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, vieter_tree_node *child); +void vieter_tree_node_set_children(vieter_tree_node *parent, vieter_tree_node **children); bool vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, uint64_t expected_black_nodes); From 1d458c68a47afb979ca7741e845529a5d38d9617 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 29 Jan 2023 21:34:44 +0100 Subject: [PATCH 31/74] feat(tree): start of balanced removal --- src/tree/vieter_tree_balancing.c | 23 ++++++++++++++++++- src/tree/vieter_tree_balancing.h | 3 ++- src/tree/vieter_tree_node.c | 39 ++++++++++++-------------------- src/tree/vieter_tree_node.h | 1 + 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index b160563..e2a9d18 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -124,4 +124,25 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node) { } } -void vieter_tree_node_remove_balanced(vieter_tree_node *node) {} +void vieter_tree_node_remove_balanced(vieter_tree_node *node) { + // A red node can only have 0 or 2 children. The node we receive only has + // one child at most, so we know if it's red that it doesn't have any + // children. A black node that has a single (right) child can be replaced by + // this child, granted it becomes black as well. Either way, the node can be + // replaced by its right child (even if it's NULL). + if (!vieter_tree_node_get(node, vieter_tree_node_black) || + node->children[1] != NULL) { + vieter_tree_node_set_child( + node->parent, node->children[1], + vieter_tree_node_get(node, vieter_tree_node_right)); + + if (node->children[1] != NULL) + vieter_tree_node_set(node->children[1], vieter_tree_node_black, true); + + vieter_tree_node_free(node); + + return; + } + + // The complicated case is when we want to remove a black leaf +} diff --git a/src/tree/vieter_tree_balancing.h b/src/tree/vieter_tree_balancing.h index 007af34..befc035 100644 --- a/src/tree/vieter_tree_balancing.h +++ b/src/tree/vieter_tree_balancing.h @@ -12,7 +12,8 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node); /* * Remove the given node, ensuring the tree remains a valid red-black tree. * - * @param node node to remove. This node should have at least one NULL child. + * @param node node to remove. This should have at most a single child, namely + * the right one. */ void vieter_tree_node_remove_balanced(vieter_tree_node *node); diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index 2f45b82..3f09f3e 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -36,6 +36,16 @@ void vieter_tree_node_set_children(vieter_tree_node *parent, } } +void vieter_tree_node_set_child(vieter_tree_node *parent, + vieter_tree_node *child, bool right) { + parent->children[right] = child; + + if (child != NULL) { + child->parent = parent; + vieter_tree_node_set(child, vieter_tree_node_right, right); + } +} + void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement) { to_replace->key = replacement->key; @@ -110,40 +120,19 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, *out = target->data; - if (target->children[0] == NULL && target->children[1] == NULL) { - vieter_tree_node_add_child(target->parent, target->key, NULL); - - vieter_tree_node_free(target); - } else if ((target->children[0] == NULL) ^ (target->children[1] == NULL)) { - vieter_tree_node *child = - target->children[0] != NULL ? target->children[0] : target->children[1]; - - if (target->parent != NULL) { - vieter_tree_node_add_child(target->parent, child->key, child); - vieter_tree_node_free(target); - } else { - vieter_tree_node_replace_with_child(target, child); - vieter_tree_node_free(child); - } - - } else { + if (target->children[0] != NULL && target->children[1] != NULL) { vieter_tree_node *replacement = target->children[1]; while (replacement->children[0] != NULL) { replacement = replacement->children[0]; } - // We use replacement->key here because the right child can be NULL, so - // reading its key isn't safe. Using replacement->key however, the child - // will still get placed into the right location because of how binary - // trees work. - vieter_tree_node_add_child(replacement->parent, replacement->key, - replacement->children[1]); - target->key = replacement->key; target->data = replacement->data; - vieter_tree_node_free(replacement); + vieter_tree_node_remove_balanced(replacement); + } else { + vieter_tree_node_remove_balanced(target); } return vieter_tree_ok; diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 1ebb15a..f164704 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -43,6 +43,7 @@ bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag); void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, vieter_tree_node *child); void vieter_tree_node_set_children(vieter_tree_node *parent, vieter_tree_node **children); +void vieter_tree_node_set_child(vieter_tree_node *parent, vieter_tree_node *child, bool right); bool vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, uint64_t expected_black_nodes); From 17c2e153851697ce9e2f9969d15a20ffcaad6ff5 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Mon, 30 Jan 2023 12:28:08 +0100 Subject: [PATCH 32/74] feat(tree): first attempt at wikipedia pseudo code --- src/tree/vieter_tree_balancing.c | 92 ++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index e2a9d18..710203b 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -124,6 +124,22 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node) { } } +vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, + bool dir) { + vieter_tree_node *new_root = old_root->children[1 - dir]; + + // Right rotation + if (dir) { + vieter_tree_node_set_child(old_root, new_root->children[1], false); + vieter_tree_node_set_child(new_root, old_root, true); + } else { + vieter_tree_node_set_child(old_root, new_root->children[0], true); + vieter_tree_node_set_child(new_root, old_root, false); + } + + return new_root; +} + void vieter_tree_node_remove_balanced(vieter_tree_node *node) { // A red node can only have 0 or 2 children. The node we receive only has // one child at most, so we know if it's red that it doesn't have any @@ -145,4 +161,80 @@ void vieter_tree_node_remove_balanced(vieter_tree_node *node) { } // The complicated case is when we want to remove a black leaf + // https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#Removal_of_a_black_non-root_leaf + + vieter_tree_node *parent = node->parent; + vieter_tree_node *sibling, *close_nephew, *distant_nephew; + bool dir = vieter_tree_node_get(node, vieter_tree_node_right); + parent->children[dir] = NULL; + + vieter_tree_node_free(node); + + goto start; + + do { + dir = vieter_tree_node_get(node, vieter_tree_node_right); + + start: + sibling = parent->children[1 - dir]; + distant_nephew = sibling->children[1 - dir]; + close_nephew = sibling->children[dir]; + + if (!vieter_tree_node_get(sibling, vieter_tree_node_black)) + goto case3; + + if (distant_nephew != NULL && + !vieter_tree_node_get(distant_nephew, vieter_tree_node_black)) + goto case6; + + if (close_nephew != NULL && + !vieter_tree_node_get(close_nephew, vieter_tree_node_black)) + goto case5; + + if (!vieter_tree_node_get(parent, vieter_tree_node_black)) + goto case4; + + // Case 2 + vieter_tree_node_set(sibling, vieter_tree_node_black, false); + node = parent; + } while ((parent = node->parent) != NULL); + + // Case 1 + return; + +case3: + vieter_tree_node_rotate(parent, dir); + vieter_tree_node_set(parent, vieter_tree_node_black, false); + vieter_tree_node_set(sibling, vieter_tree_node_black, true); + sibling = close_nephew; + distant_nephew = sibling->children[1 - dir]; + + if (distant_nephew != NULL && + !vieter_tree_node_get(distant_nephew, vieter_tree_node_black)) + goto case6; + + close_nephew = sibling->children[dir]; + + if (close_nephew != NULL && + !vieter_tree_node_get(close_nephew, vieter_tree_node_black)) + goto case5; + +case4: + vieter_tree_node_set(sibling, vieter_tree_node_black, false); + vieter_tree_node_set(parent, vieter_tree_node_black, true); + return; + +case5: + vieter_tree_node_rotate(sibling, 1 - dir); + vieter_tree_node_set(sibling, vieter_tree_node_black, false); + vieter_tree_node_set(close_nephew, vieter_tree_node_black, true); + distant_nephew = sibling; + sibling = close_nephew; + +case6: + vieter_tree_node_rotate(parent, dir); + vieter_tree_node_set(sibling, vieter_tree_node_black, + vieter_tree_node_get(parent, vieter_tree_node_black)); + vieter_tree_node_set(parent, vieter_tree_node_black, true); + vieter_tree_node_set(distant_nephew, vieter_tree_node_black, true); } From 307e7ba6e92b1ac97342be471c7a731cef7b4352 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Tue, 31 Jan 2023 20:41:05 +0000 Subject: [PATCH 33/74] fix: Initialise array pointers to 0 before performing check on them. --- src/package/vieter_package_dynarray.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/package/vieter_package_dynarray.c b/src/package/vieter_package_dynarray.c index 2cc20b6..6da07ee 100644 --- a/src/package/vieter_package_dynarray.c +++ b/src/package/vieter_package_dynarray.c @@ -12,12 +12,18 @@ void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { // An empty vieter_package_dynarray does not have an allocated internal array yet if (da->size == 0) { da->array = malloc(sizeof(char*) * da->capacity); + + // Initialise all char*'s to 0 so array[i] == NULL can be used to see if field is empty + memset(da->array, 0, sizeof(char*) * da->capacity); } // Double array size if it's full else if (da->size == da->capacity) { // if the realloc fails, access to memory in da->array is lost da->array = realloc(da->array, sizeof(char*) * da->capacity * 2); da->capacity *= 2; + + // Same as the previous memset, but only for newly allocated pointers + memset(da->array + da->size, 0, sizeof(char*) * da->capacity / 2); } da->array[da->size] = strdup(s); From e4d6ffc40395b2e49b110aafd5c816a56bf277e5 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Tue, 31 Jan 2023 21:00:08 +0000 Subject: [PATCH 34/74] fix: Using snprintf while ignoring its return value could lead to valid inputs getting truncated. --- include/vieter_package.h | 10 ++----- src/package/vieter_package.c | 51 ++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/include/vieter_package.h b/include/vieter_package.h index 179ff57..32fb0eb 100644 --- a/include/vieter_package.h +++ b/include/vieter_package.h @@ -1,16 +1,10 @@ #ifndef VIETER_PACKAGE #define VIETER_PACKAGE -#include -#include -#include -#include - -#include -#include - typedef struct vieter_package vieter_package; + + /* * Parse package file into something usable by libvieter. * The pointer returned by this function will need to freed at a later point. diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 3bb19ba..031fe15 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -1,30 +1,29 @@ +#include +#include +#include +#include + #include "vieter_package_internal.h" #include "sha256.h" -#define SMALL_BUFF_SIZE 128 - #define ADD_STRING(section, field) if (pkg_info->field != 0) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ - if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ + size_to_be_written = snprintf(aux, small_buff_size, section, pkg_info->field); \ + if (size_to_be_written > small_buff_size) { \ + aux = realloc(aux, size_to_be_written + 1); \ + small_buff_size = size_to_be_written + 1; \ + snprintf(aux, small_buff_size, section, pkg_info->field); \ + } \ + if (buff_size < strlen(description) + small_buff_size + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ } + #define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ - if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2); \ - buff_size *= 2; \ - } \ - strcat(description, aux); \ + ADD_STRING(section, field->array[i]); i++; \ while (pkg_info->field->array[i] != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ - if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2); \ - buff_size *= 2; \ - } \ - strcat(description, aux); \ + ADD_STRING("\n%s", field->array[i]); i++; \ } \ } @@ -170,19 +169,32 @@ void vieter_package_sha256sum(vieter_package *pkg, char *res) { res[j] = '\0'; } + + char *vieter_package_to_description(vieter_package *pkg) { vieter_package_info *pkg_info = pkg->info; size_t buff_size = 1024; - char aux[SMALL_BUFF_SIZE]; + int small_buff_size = 128; + int size_to_be_written; + char *aux = malloc(sizeof(char) * small_buff_size); char *description = malloc(sizeof(char) * buff_size); // Helper variable for ADD_ARRAY macro int i; // special case for FILENAME // assuming .pkg.tar.zst; other formats are valid, this should account for that - snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, + size_to_be_written = snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version, pkg_info->arch); + + // We neither want to let an arbritrarily long input to overflow the buffer + // nor to truncate perfectly valid inputs + if (size_to_be_written > small_buff_size) { + aux = realloc(aux, size_to_be_written + 1); + small_buff_size = size_to_be_written + 1; + snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, + pkg_info->version, pkg_info->arch); + } strcpy(description, aux); ADD_STRING("\n\n%%NAME%%\n%s", name); @@ -216,8 +228,7 @@ char *vieter_package_to_description(vieter_package *pkg) { ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); - snprintf(aux, SMALL_BUFF_SIZE, "\n\n"); - strcat(description, aux); + strcat(description, "\n\n"); return description; } From 41fabe21a282c4406fde234b8092134d5632cc25 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Tue, 31 Jan 2023 21:08:09 +0000 Subject: [PATCH 35/74] refactor: Package archive parser now returns meaningful error enums in case of failure. --- include/vieter_package.h | 12 ++++++++++-- src/package/vieter_package.c | 11 ++++++----- test/package/test_package.c | 11 ++++++----- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/vieter_package.h b/include/vieter_package.h index 32fb0eb..c9a941e 100644 --- a/include/vieter_package.h +++ b/include/vieter_package.h @@ -3,13 +3,21 @@ typedef struct vieter_package vieter_package; +typedef enum vieter_package_error { + vieter_package_ok = 0, + vieter_package_unarchive_error = 1, + vieter_package_stat_error = 2 +} vieter_package_error; +/* + * Allocate an empty package + */ +vieter_package *vieter_package_init(); /* * Parse package file into something usable by libvieter. - * The pointer returned by this function will need to freed at a later point. */ -vieter_package *vieter_package_read_archive(const char *pkg_path); +vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path); /* * Deallocate a package. diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 031fe15..cf273d8 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -40,7 +40,7 @@ vieter_package *vieter_package_init() { return calloc(sizeof(vieter_package_info), 1); } -vieter_package *vieter_package_read_archive(const char *pkg_path) { +vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path) { struct archive *a = archive_read_new(); struct archive_entry *entry = archive_entry_new(); @@ -57,7 +57,7 @@ vieter_package *vieter_package_read_archive(const char *pkg_path) { // Exit early if we weren't able to successfully open the archive for reading if (r != ARCHIVE_OK) { - return NULL; + return vieter_package_unarchive_error; } int compression_code = archive_filter_code(a, 0); @@ -103,7 +103,9 @@ vieter_package *vieter_package_read_archive(const char *pkg_path) { struct stat stats; if (stat(pkg_path, &stats) != 0) { - return NULL; + // errno is set if stat() fails; the calling function should check + // the value of errno in case vieter_package_stat_error is returned + return vieter_package_stat_error; } pkg_info->csize = stats.st_size; @@ -111,13 +113,12 @@ vieter_package *vieter_package_read_archive(const char *pkg_path) { archive_read_free(a); // Create final return value - vieter_package *pkg = vieter_package_init(); pkg->path = strdup(pkg_path); pkg->info = pkg_info; pkg->files = files; pkg->compression = compression_code; - return pkg; + return vieter_package_ok; } void vieter_package_sha256sum(vieter_package *pkg, char *res) { diff --git a/test/package/test_package.c b/test/package/test_package.c index 5bbda26..3c8b249 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -39,8 +39,9 @@ void test_info_parse() { } void test_pkg_read_archive_files() { - vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); - TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + vieter_package *pkg = vieter_package_init(); + vieter_package_error e = vieter_package_read_archive(pkg, "./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(e == vieter_package_ok, "failure parsing pkg archive"); FILE *f = fopen("./test/package/files", "r"); TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); @@ -58,12 +59,12 @@ void test_pkg_read_archive_files() { TEST_CHECK(pkg->compression = 14); vieter_package_free(&pkg); - } void test_pkg_read_archive_desc() { - vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); - TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + vieter_package *pkg = vieter_package_init(); + vieter_package_error e = vieter_package_read_archive(pkg, "./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(e == vieter_package_ok, "failure parsing pkg archive"); char *description = vieter_package_to_description(pkg); From 031e28ed33e63c695ac1bfb5d65df57120469026 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Tue, 31 Jan 2023 21:09:47 +0000 Subject: [PATCH 36/74] refactor: Hashing function now streams data into hasher instead of doing it in one go. --- src/package/vieter_package.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index cf273d8..d1ef6c4 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -123,20 +123,21 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char void vieter_package_sha256sum(vieter_package *pkg, char *res) { FILE *f = fopen(pkg->path, "r"); - fseek(f, 0, SEEK_END); - size_t size = ftell(f); - rewind(f); - unsigned char *in = malloc(size); - fread(in, 1, size, f); - fclose(f); + // Try to read 100KiB at a time + unsigned char *in = malloc(102400); + // Actual number of bytes read + size_t read_size; - unsigned char hash[32]; SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); - sha256_init(ctx); - sha256_update(ctx, in, size); + while ((read_size = fread(in, 1, 102400, f)) != 0) { + sha256_update(ctx, in, read_size); + } + unsigned char hash[SHA256_BLOCK_SIZE]; + sha256_final(ctx, hash); + fclose(f); free(in); free(ctx); @@ -147,8 +148,8 @@ void vieter_package_sha256sum(vieter_package *pkg, char *res) { unsigned int half_byte = 0; int j = 0; - // We advance in the string 2 bytes for every one byte of the hash - for (int i = 0; i < 32; i++) { + // We advance 2 bytes in the string for every one byte of the hash + for (int i = 0; i < SHA256_BLOCK_SIZE; i++) { // We transform the first half byte into the second character to keep // each byte from becoming reversed in the final string half_byte = hash[i] & 0b1111; @@ -206,11 +207,11 @@ char *vieter_package_to_description(vieter_package *pkg) { ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); ADD_STRING("\n\n%%ISIZE%%\n%ld", size); - char checksum[65]; + char checksum[SHA256_BLOCK_SIZE * 2 + 1]; vieter_package_sha256sum(pkg, checksum); - snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum); - if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { + snprintf(aux, small_buff_size, "\n\n%%SHA256SUM%%\n%s", checksum); + if (buff_size < strlen(description) + small_buff_size + 1) { description = realloc(description, buff_size * 2); buff_size *= 2; } From 70217bee21f59afab50212545cc892a0caab6843 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 1 Feb 2023 22:12:34 +0100 Subject: [PATCH 37/74] fix(tree): fix wrong rotation function --- src/tree/vieter_tree_balancing.c | 14 +++++++- src/tree/vieter_tree_balancing.h | 1 + test/tree/test_balancing.c | 56 ++++++++++++++++++++++++++++++++ test/tree/test_tree.c | 2 +- 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 test/tree/test_balancing.c diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index 710203b..96b0c10 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -21,8 +21,12 @@ bool vieter_tree_node_validate(vieter_tree_node *node, vieter_tree_node_get(node->children[0], vieter_tree_node_black)) && (node->children[1] == NULL || vieter_tree_node_get(node->children[1], vieter_tree_node_black))); + bool right_child_flag_set = + node->parent == NULL || + (vieter_tree_node_get(node, vieter_tree_node_right) == + (node->parent->children[1] == node)); - return correctly_colored_children && + return correctly_colored_children && right_child_flag_set && vieter_tree_node_validate(node->children[0], passed_black_nodes, expected_black_nodes) && vieter_tree_node_validate(node->children[1], passed_black_nodes, @@ -128,6 +132,14 @@ vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, bool dir) { vieter_tree_node *new_root = old_root->children[1 - dir]; + if (old_root->parent != NULL) { + vieter_tree_node_set_child( + old_root->parent, new_root, + vieter_tree_node_get(old_root, vieter_tree_node_right)); + } else { + new_root->parent = NULL; + } + // Right rotation if (dir) { vieter_tree_node_set_child(old_root, new_root->children[1], false); diff --git a/src/tree/vieter_tree_balancing.h b/src/tree/vieter_tree_balancing.h index befc035..0d1acc5 100644 --- a/src/tree/vieter_tree_balancing.h +++ b/src/tree/vieter_tree_balancing.h @@ -17,4 +17,5 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node); */ void vieter_tree_node_remove_balanced(vieter_tree_node *node); +vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, bool dir); #endif diff --git a/test/tree/test_balancing.c b/test/tree/test_balancing.c new file mode 100644 index 0000000..5794ab9 --- /dev/null +++ b/test/tree/test_balancing.c @@ -0,0 +1,56 @@ +#include "acutest.h" +#include "vieter_tree_internal.h" +#include "vieter_tree_node.h" +#include "vieter_tree_balancing.h" + +void test_rotate_right() { + vieter_tree_node *a = vieter_tree_node_init(); + vieter_tree_node *b = vieter_tree_node_init(); + vieter_tree_node *p = vieter_tree_node_init(); + + vieter_tree_node_set_child(p, a, false); + vieter_tree_node_set_child(p, b, true); + + vieter_tree_node *c = vieter_tree_node_init(); + vieter_tree_node *q = vieter_tree_node_init(); + + vieter_tree_node_set_child(q, p, false); + vieter_tree_node_set_child(q, c, true); + + vieter_tree_node *new_root = vieter_tree_node_rotate(q, true); + + TEST_CHECK(new_root == p); + TEST_CHECK(new_root->children[0] == a); + TEST_CHECK(new_root->children[1] == q); + TEST_CHECK(new_root->children[1]->children[0] == b); + TEST_CHECK(new_root->children[1]->children[1] == c); +} + +void test_rotate_left() { + vieter_tree_node *b = vieter_tree_node_init(); + vieter_tree_node *c = vieter_tree_node_init(); + vieter_tree_node *q = vieter_tree_node_init(); + + vieter_tree_node_set_child(q, b, false); + vieter_tree_node_set_child(q, c, true); + + vieter_tree_node *a = vieter_tree_node_init(); + vieter_tree_node *p = vieter_tree_node_init(); + + vieter_tree_node_set_child(p, a, false); + vieter_tree_node_set_child(p, q, true); + + vieter_tree_node *new_root = vieter_tree_node_rotate(p, false); + + TEST_CHECK(new_root == q); + TEST_CHECK(new_root->children[0] == p); + TEST_CHECK(new_root->children[1] == c); + TEST_CHECK(new_root->children[0]->children[0] == a); + TEST_CHECK(new_root->children[0]->children[1] == b); +} + +TEST_LIST = { + {"tree tree rotate right", test_rotate_right}, + {"tree tree rotate left", test_rotate_left}, + {NULL, NULL} +}; diff --git a/test/tree/test_tree.c b/test/tree/test_tree.c index 257ec66..6fdd430 100644 --- a/test/tree/test_tree.c +++ b/test/tree/test_tree.c @@ -42,7 +42,7 @@ void test_remove() { void *out; - for (uint64_t i = 0; i < 25; i++) { + for (uint64_t i = 0; i < 100; i++) { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_validate(tree)); From bee520a781e74a5c7bee1a55ca6f4539b85a232b Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 1 Feb 2023 23:04:35 +0100 Subject: [PATCH 38/74] fix(tree): working balanced remove --- src/tree/vieter_tree.c | 2 +- src/tree/vieter_tree_balancing.c | 51 +++++++++++++++++++++++++++----- src/tree/vieter_tree_balancing.h | 31 +++++++++++++++++-- src/tree/vieter_tree_node.c | 17 +++++++---- src/tree/vieter_tree_node.h | 2 +- test/tree/test_balancing.c | 15 ++++++++++ test/tree/test_tree.c | 2 +- 7 files changed, 102 insertions(+), 18 deletions(-) diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index b066af1..8a00088 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -48,7 +48,7 @@ vieter_tree_error vieter_tree_remove(void **out, vieter_tree *tree, return vieter_tree_not_present; } - vieter_tree_error res = vieter_tree_node_remove(out, tree->root, key); + vieter_tree_error res = vieter_tree_node_remove(out, &tree->root, key); if (res != vieter_tree_ok) { return res; diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index 96b0c10..6e7dcd9 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -33,6 +33,9 @@ bool vieter_tree_node_validate(vieter_tree_node *node, expected_black_nodes); } +/* + * This function should be rewritten to use tree rotations instead. + */ vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node) { vieter_tree_node *parent = node->parent; vieter_tree_node *grand_parent = parent->parent; @@ -144,7 +147,9 @@ vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, if (dir) { vieter_tree_node_set_child(old_root, new_root->children[1], false); vieter_tree_node_set_child(new_root, old_root, true); - } else { + } + // Left rotation + else { vieter_tree_node_set_child(old_root, new_root->children[0], true); vieter_tree_node_set_child(new_root, old_root, false); } @@ -152,7 +157,32 @@ vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, return new_root; } -void vieter_tree_node_remove_balanced(vieter_tree_node *node) { +/* + * This function is currently implemented by very literally following the + * Wikipedia pseudocode. It's honestly not too bad, and I couldn't be bothered + * to properly research how to implement red-black removal (how is this so hard + * to find?) + * + * https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#Removal_of_a_black_non-root_leaf + */ +vieter_tree_node *vieter_tree_node_remove_balanced(vieter_tree_node *node) { + vieter_tree_node *out; + + if (node->parent == NULL) { + out = node->children[0] != NULL ? node->children[0] : node->children[1]; + + vieter_tree_node_free(node); + + // This only happens when the root was the only element in the tree + if (out == NULL) + return out; + + vieter_tree_node_set(out, vieter_tree_node_black, true); + out->parent = NULL; + + return out; + } + // A red node can only have 0 or 2 children. The node we receive only has // one child at most, so we know if it's red that it doesn't have any // children. A black node that has a single (right) child can be replaced by @@ -160,6 +190,8 @@ void vieter_tree_node_remove_balanced(vieter_tree_node *node) { // replaced by its right child (even if it's NULL). if (!vieter_tree_node_get(node, vieter_tree_node_black) || node->children[1] != NULL) { + out = node->children[1]; + vieter_tree_node_set_child( node->parent, node->children[1], vieter_tree_node_get(node, vieter_tree_node_right)); @@ -169,12 +201,13 @@ void vieter_tree_node_remove_balanced(vieter_tree_node *node) { vieter_tree_node_free(node); - return; + return out; } // The complicated case is when we want to remove a black leaf // https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#Removal_of_a_black_non-root_leaf + out = node; vieter_tree_node *parent = node->parent; vieter_tree_node *sibling, *close_nephew, *distant_nephew; bool dir = vieter_tree_node_get(node, vieter_tree_node_right); @@ -209,13 +242,14 @@ void vieter_tree_node_remove_balanced(vieter_tree_node *node) { // Case 2 vieter_tree_node_set(sibling, vieter_tree_node_black, false); node = parent; + out = node; } while ((parent = node->parent) != NULL); // Case 1 - return; + return out; case3: - vieter_tree_node_rotate(parent, dir); + out = vieter_tree_node_rotate(parent, dir); vieter_tree_node_set(parent, vieter_tree_node_black, false); vieter_tree_node_set(sibling, vieter_tree_node_black, true); sibling = close_nephew; @@ -234,7 +268,8 @@ case3: case4: vieter_tree_node_set(sibling, vieter_tree_node_black, false); vieter_tree_node_set(parent, vieter_tree_node_black, true); - return; + + return out; case5: vieter_tree_node_rotate(sibling, 1 - dir); @@ -244,9 +279,11 @@ case5: sibling = close_nephew; case6: - vieter_tree_node_rotate(parent, dir); + out = vieter_tree_node_rotate(parent, dir); vieter_tree_node_set(sibling, vieter_tree_node_black, vieter_tree_node_get(parent, vieter_tree_node_black)); vieter_tree_node_set(parent, vieter_tree_node_black, true); vieter_tree_node_set(distant_nephew, vieter_tree_node_black, true); + + return out; } diff --git a/src/tree/vieter_tree_balancing.h b/src/tree/vieter_tree_balancing.h index 0d1acc5..e5dced0 100644 --- a/src/tree/vieter_tree_balancing.h +++ b/src/tree/vieter_tree_balancing.h @@ -3,6 +3,26 @@ #include "vieter_tree_node.h" +/* + * Check whether the given tree is a valid red-black tree. + * + * @param node root of the (sub)tree + * @param passed_black_nodes how many black nodes the recursion has already seen + * at this point. This should be initialized as 0 for the topmost call. + * @param expected_black_nodes the correct amount of black nodes to expect when + * a NULL child is encountered. + * @return true if the tree is valid, false otherwise + */ +bool vieter_tree_node_validate(vieter_tree_node *node, + uint64_t passed_black_nodes, + uint64_t expected_black_nodes); + +/* + * Balance a path of 3 nodes into a complete binary tree, with a red root and + * black children. + */ +vieter_tree_node *vieter_tree_node_balance(vieter_tree_node *node); + /* * Ensure the tree remains a valid red-black tree after having inserting the * node. @@ -12,10 +32,15 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node); /* * Remove the given node, ensuring the tree remains a valid red-black tree. * - * @param node node to remove. This should have at most a single child, namely - * the right one. + * @param node node to remove. This should have at most a single child. If node + * isn't the root, this should be the right child, otherwise it can be either. + * @return root of the subtree that this function operated on. This can + * sometimes be the new root of the entire tree. */ -void vieter_tree_node_remove_balanced(vieter_tree_node *node); +vieter_tree_node *vieter_tree_node_remove_balanced(vieter_tree_node *node); +/* + * Perform a tree rotation of the subtree with the given root. + */ vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, bool dir); #endif diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index 3f09f3e..57aea05 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -109,16 +109,17 @@ vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, return vieter_tree_ok; } -vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, - uint64_t key) { +vieter_tree_error +vieter_tree_node_remove(void **out, vieter_tree_node **root_ptr, uint64_t key) { vieter_tree_node *target; - vieter_tree_error res = vieter_tree_node_search_node(&target, root, key); + vieter_tree_error res = vieter_tree_node_search_node(&target, *root_ptr, key); if (res != vieter_tree_ok) { return res; } *out = target->data; + vieter_tree_node *possible_new_root; if (target->children[0] != NULL && target->children[1] != NULL) { vieter_tree_node *replacement = target->children[1]; @@ -130,9 +131,15 @@ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, target->key = replacement->key; target->data = replacement->data; - vieter_tree_node_remove_balanced(replacement); + possible_new_root = vieter_tree_node_remove_balanced(replacement); } else { - vieter_tree_node_remove_balanced(target); + possible_new_root = vieter_tree_node_remove_balanced(target); + } + + if (possible_new_root == NULL) { + *root_ptr = NULL; + } else if (possible_new_root->parent == NULL) { + *root_ptr = possible_new_root; } return vieter_tree_ok; diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index f164704..fabee6b 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -33,7 +33,7 @@ vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, vieter_tr vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, uint64_t key); -vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node *root, uint64_t key); +vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node **root_ptr, uint64_t key); void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement); diff --git a/test/tree/test_balancing.c b/test/tree/test_balancing.c index 5794ab9..cfda9d3 100644 --- a/test/tree/test_balancing.c +++ b/test/tree/test_balancing.c @@ -3,6 +3,9 @@ #include "vieter_tree_node.h" #include "vieter_tree_balancing.h" +// This uses the examples from wikipedia +// https://en.wikipedia.org/wiki/Tree_rotation + void test_rotate_right() { vieter_tree_node *a = vieter_tree_node_init(); vieter_tree_node *b = vieter_tree_node_init(); @@ -24,6 +27,12 @@ void test_rotate_right() { TEST_CHECK(new_root->children[1] == q); TEST_CHECK(new_root->children[1]->children[0] == b); TEST_CHECK(new_root->children[1]->children[1] == c); + + vieter_tree_node_free(a); + vieter_tree_node_free(b); + vieter_tree_node_free(p); + vieter_tree_node_free(c); + vieter_tree_node_free(q); } void test_rotate_left() { @@ -47,6 +56,12 @@ void test_rotate_left() { TEST_CHECK(new_root->children[1] == c); TEST_CHECK(new_root->children[0]->children[0] == a); TEST_CHECK(new_root->children[0]->children[1] == b); + + vieter_tree_node_free(a); + vieter_tree_node_free(b); + vieter_tree_node_free(p); + vieter_tree_node_free(c); + vieter_tree_node_free(q); } TEST_LIST = { diff --git a/test/tree/test_tree.c b/test/tree/test_tree.c index 6fdd430..2ab6870 100644 --- a/test/tree/test_tree.c +++ b/test/tree/test_tree.c @@ -42,7 +42,7 @@ void test_remove() { void *out; - for (uint64_t i = 0; i < 100; i++) { + for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_validate(tree)); From ef5037f9415bc442eebb332e285b63065d8712f2 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Wed, 1 Feb 2023 23:24:22 +0100 Subject: [PATCH 39/74] chore(tree): some small cleanups --- src/tree/vieter_tree.c | 1 + src/tree/vieter_tree_node.c | 7 ------- src/tree/vieter_tree_node.h | 38 +++++++++++++++++++++++++++++++++---- test/tree/test_balancing.c | 4 ++-- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index 8a00088..eef2aef 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -1,5 +1,6 @@ #include "vieter_tree_internal.h" #include "vieter_tree_node.h" +#include "vieter_tree_balancing.h" struct vieter_tree { uint64_t size; diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index 57aea05..e58092e 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -46,13 +46,6 @@ void vieter_tree_node_set_child(vieter_tree_node *parent, } } -void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, - vieter_tree_node *replacement) { - to_replace->key = replacement->key; - to_replace->data = replacement->data; - vieter_tree_node_set_children(to_replace, replacement->children); -} - vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, void *data) { vieter_tree_node *node = root; diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index fabee6b..3b1c169 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -20,10 +20,19 @@ typedef struct vieter_tree_node { uint8_t flags; } vieter_tree_node; +/* + * Allocate a new node. + */ vieter_tree_node *vieter_tree_node_init(); +/* + * Free an allocated node. + */ void vieter_tree_node_free(vieter_tree_node *node); +/* + * Insert a new key into the given tree. + */ vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, void *data); /* @@ -31,20 +40,41 @@ vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, */ vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, vieter_tree_node *root, uint64_t key); +/* + * Search for the data represented by the given key. + */ vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, uint64_t key); +/* + * Remove the data associated with the given key. + */ vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node **root_ptr, uint64_t key); -void vieter_tree_node_replace_with_child(vieter_tree_node *to_replace, vieter_tree_node *replacement); - +/* + * Set a node's bit flag to the given value. + */ void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag, bool value); + +/* + * Get whether a node's bit flag is set. + */ bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag); +/* + * Add a new child to the parent, replacing either its left or right child, + * depending on the key values. + */ void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, vieter_tree_node *child); + +/* + * Replace a node's children array. + */ void vieter_tree_node_set_children(vieter_tree_node *parent, vieter_tree_node **children); + +/* + * Set a node's left or right child to the given node. + */ void vieter_tree_node_set_child(vieter_tree_node *parent, vieter_tree_node *child, bool right); -bool vieter_tree_node_validate(vieter_tree_node *node, uint64_t passed_black_nodes, uint64_t expected_black_nodes); - #endif diff --git a/test/tree/test_balancing.c b/test/tree/test_balancing.c index cfda9d3..bdcd846 100644 --- a/test/tree/test_balancing.c +++ b/test/tree/test_balancing.c @@ -65,7 +65,7 @@ void test_rotate_left() { } TEST_LIST = { - {"tree tree rotate right", test_rotate_right}, - {"tree tree rotate left", test_rotate_left}, + {"tree rotate right", test_rotate_right}, + {"tree rotate left", test_rotate_left}, {NULL, NULL} }; From bfa1130478dcdd1e453120251c13d02b8cd20b28 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 2 Feb 2023 11:16:47 +0100 Subject: [PATCH 40/74] refactor: separate directory for thirdparty code --- Makefile | 14 +++++++++++--- {src/package => thirdparty/include}/sha256.h | 0 {src/package => thirdparty/src}/sha256.c | 0 3 files changed, 11 insertions(+), 3 deletions(-) rename {src/package => thirdparty/include}/sha256.h (100%) rename {src/package => thirdparty/src}/sha256.c (100%) diff --git a/Makefile b/Makefile index f3059a7..7a817a6 100644 --- a/Makefile +++ b/Makefile @@ -6,15 +6,20 @@ LIB_FILENAME ?= libvieter.a BUILD_DIR ?= build SRC_DIR ?= src TEST_DIR ?= test -INC_DIRS ?= include +3RDPARTY_DIR ?= thirdparty +INCLUDE_DIR ?= include +INC_DIRS ?= $(INCLUDE_DIR) $(3RDPARTY_DIR)/include LIB := $(BUILD_DIR)/$(LIB_FILENAME) SRCS != find '$(SRC_DIR)' -iname '*.c' -SRCS_H != find $(INC_DIRS) -iname '*.h' +SRCS_H != find $(INCLUDE_DIR) -iname '*.h' SRCS_TEST != find '$(TEST_DIR)' -iname '*.c' +SRCS_3RDPARTY != find '$(3RDPARTY_DIR)/src' -iname '*.c' -OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) +$(info ${SRCS}) + +OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) $(SRCS_3RDPARTY:%=$(BUILD_DIR)/%.o) OBJS_TEST := $(SRCS_TEST:%=$(BUILD_DIR)/%.o) DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) $(SRCS_TEST:%=$(BUILD_DIR)/%.d) @@ -51,6 +56,9 @@ $(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c mkdir -p $(dir $@) $(CC) $(VIETERCFLAGS) -c $< -o $@ +$(BUILD_DIR)/$(3RDPARTY_DIR)/src/%.c.o: $(3RDPARTY_DIR)/src/%.c + mkdir -p $(dir $@) + $(CC) $(VIETERCFLAGS) -c $< -o $@ # =====TESTING===== .PHONY: test diff --git a/src/package/sha256.h b/thirdparty/include/sha256.h similarity index 100% rename from src/package/sha256.h rename to thirdparty/include/sha256.h diff --git a/src/package/sha256.c b/thirdparty/src/sha256.c similarity index 100% rename from src/package/sha256.c rename to thirdparty/src/sha256.c From 655daff4851acd04c1d1d9e48b0bb8f3b1e21d95 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 2 Feb 2023 11:17:16 +0100 Subject: [PATCH 41/74] chore(package): ran fmt --- include/vieter_package.h | 11 +- src/package/vieter_package.c | 379 +++++++++++++------------- src/package/vieter_package_dynarray.c | 72 ++--- src/package/vieter_package_info.c | 131 ++++----- 4 files changed, 302 insertions(+), 291 deletions(-) diff --git a/include/vieter_package.h b/include/vieter_package.h index c9a941e..fb220c8 100644 --- a/include/vieter_package.h +++ b/include/vieter_package.h @@ -4,9 +4,9 @@ typedef struct vieter_package vieter_package; typedef enum vieter_package_error { - vieter_package_ok = 0, - vieter_package_unarchive_error = 1, - vieter_package_stat_error = 2 + vieter_package_ok = 0, + vieter_package_unarchive_error = 1, + vieter_package_stat_error = 2 } vieter_package_error; /* @@ -17,12 +17,13 @@ vieter_package *vieter_package_init(); /* * Parse package file into something usable by libvieter. */ -vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path); +vieter_package_error vieter_package_read_archive(vieter_package *pkg, + const char *pkg_path); /* * Deallocate a package. */ -void vieter_package_free(vieter_package ** ptp); +void vieter_package_free(vieter_package **ptp); /* * Create string that will become the package's desc file. diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index d1ef6c4..4bb7622 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -1,245 +1,246 @@ -#include -#include #include #include +#include +#include -#include "vieter_package_internal.h" #include "sha256.h" +#include "vieter_package_internal.h" -#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ - size_to_be_written = snprintf(aux, small_buff_size, section, pkg_info->field); \ - if (size_to_be_written > small_buff_size) { \ - aux = realloc(aux, size_to_be_written + 1); \ - small_buff_size = size_to_be_written + 1; \ - snprintf(aux, small_buff_size, section, pkg_info->field); \ - } \ - if (buff_size < strlen(description) + small_buff_size + 1) { \ - description = realloc(description, buff_size * 2); \ - buff_size *= 2; \ - } \ - strcat(description, aux); \ -} +#define ADD_STRING(section, field) \ + if (pkg_info->field != 0) { \ + size_to_be_written = \ + snprintf(aux, small_buff_size, section, pkg_info->field); \ + if (size_to_be_written > small_buff_size) { \ + aux = realloc(aux, size_to_be_written + 1); \ + small_buff_size = size_to_be_written + 1; \ + snprintf(aux, small_buff_size, section, pkg_info->field); \ + } \ + if (buff_size < strlen(description) + small_buff_size + 1) { \ + description = realloc(description, buff_size * 2); \ + buff_size *= 2; \ + } \ + strcat(description, aux); \ + } -#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ - ADD_STRING(section, field->array[i]); i++; \ - while (pkg_info->field->array[i] != NULL) { \ - ADD_STRING("\n%s", field->array[i]); i++; \ - } \ -} +#define ADD_ARRAY(section, field) \ + i = 0; \ + if (pkg_info->field != NULL) { \ + ADD_STRING(section, field->array[i]); \ + i++; \ + while (pkg_info->field->array[i] != NULL) { \ + ADD_STRING("\n%s", field->array[i]); \ + i++; \ + } \ + } -static char *ignored_names[5] = { - ".BUILDINFO", - ".INSTALL", - ".MTREE", - ".PKGINFO", - ".CHANGELOG" -}; +static char *ignored_names[5] = {".BUILDINFO", ".INSTALL", ".MTREE", ".PKGINFO", + ".CHANGELOG"}; static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *); vieter_package *vieter_package_init() { - return calloc(sizeof(vieter_package_info), 1); + return calloc(sizeof(vieter_package_info), 1); } -vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path) { - struct archive *a = archive_read_new(); - struct archive_entry *entry = archive_entry_new(); +vieter_package_error vieter_package_read_archive(vieter_package *pkg, + const char *pkg_path) { + struct archive *a = archive_read_new(); + struct archive_entry *entry = archive_entry_new(); - // These three are the most commonly used compression methods - archive_read_support_filter_zstd(a); - archive_read_support_filter_gzip(a); - archive_read_support_filter_xz(a); + // These three are the most commonly used compression methods + archive_read_support_filter_zstd(a); + archive_read_support_filter_gzip(a); + archive_read_support_filter_xz(a); - // Contents should always be a tarball - archive_read_support_format_tar(a); + // Contents should always be a tarball + archive_read_support_format_tar(a); - // TODO where does this 10240 come from? - int r = archive_read_open_filename(a, pkg_path, 10240); + // TODO where does this 10240 come from? + int r = archive_read_open_filename(a, pkg_path, 10240); - // Exit early if we weren't able to successfully open the archive for reading - if (r != ARCHIVE_OK) { - return vieter_package_unarchive_error; - } + // Exit early if we weren't able to successfully open the archive for reading + if (r != ARCHIVE_OK) { + return vieter_package_unarchive_error; + } - int compression_code = archive_filter_code(a, 0); - const char *path_name; + int compression_code = archive_filter_code(a, 0); + const char *path_name; - vieter_package_info *pkg_info; - vieter_package_dynarray *files = vieter_package_dynarray_init(16); - vieter_package_dynarray_add(files, "%FILES%"); + vieter_package_info *pkg_info; + vieter_package_dynarray *files = vieter_package_dynarray_init(16); + vieter_package_dynarray_add(files, "%FILES%"); - while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { - path_name = archive_entry_pathname(entry); + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + path_name = archive_entry_pathname(entry); - bool ignore = false; + bool ignore = false; - for (size_t i = 0; i < ignored_words_len; i++) { - if (strcmp(path_name, ignored_names[i]) == 0) { - ignore = true; - break; - } - } + for (size_t i = 0; i < ignored_words_len; i++) { + if (strcmp(path_name, ignored_names[i]) == 0) { + ignore = true; + break; + } + } - if (!ignore) { - vieter_package_dynarray_add(files, path_name); - } + if (!ignore) { + vieter_package_dynarray_add(files, path_name); + } - if (strcmp(path_name, ".PKGINFO") == 0) { - // Read data of file into memory buffer - int size = archive_entry_size(entry); - char *buf = malloc(size); - archive_read_data(a, buf, size); + if (strcmp(path_name, ".PKGINFO") == 0) { + // Read data of file into memory buffer + int size = archive_entry_size(entry); + char *buf = malloc(size); + archive_read_data(a, buf, size); - // Parse package vieter_package_info string into a struct - pkg_info = vieter_package_info_init(); - vieter_package_info_parse(pkg_info, buf); + // Parse package vieter_package_info string into a struct + pkg_info = vieter_package_info_init(); + vieter_package_info_parse(pkg_info, buf); - free(buf); - } else { - archive_read_data_skip(a); - } - } + free(buf); + } else { + archive_read_data_skip(a); + } + } - // Get size of file - struct stat stats; + // Get size of file + struct stat stats; - if (stat(pkg_path, &stats) != 0) { - // errno is set if stat() fails; the calling function should check - // the value of errno in case vieter_package_stat_error is returned - return vieter_package_stat_error; - } + if (stat(pkg_path, &stats) != 0) { + // errno is set if stat() fails; the calling function should check + // the value of errno in case vieter_package_stat_error is returned + return vieter_package_stat_error; + } - pkg_info->csize = stats.st_size; + pkg_info->csize = stats.st_size; - archive_read_free(a); + archive_read_free(a); - // Create final return value - pkg->path = strdup(pkg_path); - pkg->info = pkg_info; - pkg->files = files; - pkg->compression = compression_code; + // Create final return value + pkg->path = strdup(pkg_path); + pkg->info = pkg_info; + pkg->files = files; + pkg->compression = compression_code; - return vieter_package_ok; + return vieter_package_ok; } void vieter_package_sha256sum(vieter_package *pkg, char *res) { - FILE *f = fopen(pkg->path, "r"); - // Try to read 100KiB at a time - unsigned char *in = malloc(102400); - // Actual number of bytes read - size_t read_size; + FILE *f = fopen(pkg->path, "r"); + // Try to read 100KiB at a time + unsigned char *in = malloc(102400); + // Actual number of bytes read + size_t read_size; - SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); - sha256_init(ctx); - while ((read_size = fread(in, 1, 102400, f)) != 0) { - sha256_update(ctx, in, read_size); - } - unsigned char hash[SHA256_BLOCK_SIZE]; + SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); + sha256_init(ctx); + while ((read_size = fread(in, 1, 102400, f)) != 0) { + sha256_update(ctx, in, read_size); + } + unsigned char hash[SHA256_BLOCK_SIZE]; - sha256_final(ctx, hash); + sha256_final(ctx, hash); - fclose(f); - free(in); - free(ctx); + fclose(f); + free(in); + free(ctx); - // We need to convert the bytes in the hash to get a string representation of its hex values - // i.e. turn 1001 1111 into the string "9f" - // Each byte of the hash is going to turn into two bytes in the final string - // so we are going to convert each half byte into a char - unsigned int half_byte = 0; - int j = 0; + // We need to convert the bytes in the hash to get a string representation of + // its hex values i.e. turn 1001 1111 into the string "9f" Each byte of the + // hash is going to turn into two bytes in the final string so we are going to + // convert each half byte into a char + unsigned int half_byte = 0; + int j = 0; - // We advance 2 bytes in the string for every one byte of the hash - for (int i = 0; i < SHA256_BLOCK_SIZE; i++) { - // We transform the first half byte into the second character to keep - // each byte from becoming reversed in the final string - half_byte = hash[i] & 0b1111; - if (half_byte < 10) { - res[j+1] = half_byte + 48; - } else { - res[j+1] = half_byte + 87; - } - hash[i] = hash[i] >> 4; - half_byte = hash[i] & 0b1111; - if (half_byte < 10) { - res[j] = half_byte + 48; - } else { - res[j] = half_byte + 87; - } + // We advance 2 bytes in the string for every one byte of the hash + for (int i = 0; i < SHA256_BLOCK_SIZE; i++) { + // We transform the first half byte into the second character to keep + // each byte from becoming reversed in the final string + half_byte = hash[i] & 0b1111; + if (half_byte < 10) { + res[j + 1] = half_byte + 48; + } else { + res[j + 1] = half_byte + 87; + } + hash[i] = hash[i] >> 4; + half_byte = hash[i] & 0b1111; + if (half_byte < 10) { + res[j] = half_byte + 48; + } else { + res[j] = half_byte + 87; + } - j += 2; - } - res[j] = '\0'; + j += 2; + } + res[j] = '\0'; } - - char *vieter_package_to_description(vieter_package *pkg) { - vieter_package_info *pkg_info = pkg->info; + vieter_package_info *pkg_info = pkg->info; - size_t buff_size = 1024; - int small_buff_size = 128; - int size_to_be_written; - char *aux = malloc(sizeof(char) * small_buff_size); - char *description = malloc(sizeof(char) * buff_size); - // Helper variable for ADD_ARRAY macro - int i; + size_t buff_size = 1024; + int small_buff_size = 128; + int size_to_be_written; + char *aux = malloc(sizeof(char) * small_buff_size); + char *description = malloc(sizeof(char) * buff_size); + // Helper variable for ADD_ARRAY macro + int i; - // special case for FILENAME - // assuming .pkg.tar.zst; other formats are valid, this should account for that - size_to_be_written = snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, - pkg_info->version, pkg_info->arch); + // special case for FILENAME + // assuming .pkg.tar.zst; other formats are valid, this should account for + // that + size_to_be_written = + snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", + pkg_info->name, pkg_info->version, pkg_info->arch); - // We neither want to let an arbritrarily long input to overflow the buffer - // nor to truncate perfectly valid inputs - if (size_to_be_written > small_buff_size) { - aux = realloc(aux, size_to_be_written + 1); - small_buff_size = size_to_be_written + 1; - snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, - pkg_info->version, pkg_info->arch); - } - strcpy(description, aux); + // We neither want to let an arbritrarily long input to overflow the buffer + // nor to truncate perfectly valid inputs + if (size_to_be_written > small_buff_size) { + aux = realloc(aux, size_to_be_written + 1); + small_buff_size = size_to_be_written + 1; + snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", + pkg_info->name, pkg_info->version, pkg_info->arch); + } + strcpy(description, aux); - ADD_STRING("\n\n%%NAME%%\n%s", name); - ADD_STRING("\n\n%%BASE%%\n%s", base); - ADD_STRING("\n\n%%VERSION%%\n%s", version); - ADD_STRING("\n\n%%DESC%%\n%s", description); - ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); - ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); - ADD_STRING("\n\n%%ISIZE%%\n%ld", size); + ADD_STRING("\n\n%%NAME%%\n%s", name); + ADD_STRING("\n\n%%BASE%%\n%s", base); + ADD_STRING("\n\n%%VERSION%%\n%s", version); + ADD_STRING("\n\n%%DESC%%\n%s", description); + ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); + ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); + ADD_STRING("\n\n%%ISIZE%%\n%ld", size); - char checksum[SHA256_BLOCK_SIZE * 2 + 1]; - vieter_package_sha256sum(pkg, checksum); + char checksum[SHA256_BLOCK_SIZE * 2 + 1]; + vieter_package_sha256sum(pkg, checksum); - snprintf(aux, small_buff_size, "\n\n%%SHA256SUM%%\n%s", checksum); - if (buff_size < strlen(description) + small_buff_size + 1) { - description = realloc(description, buff_size * 2); - buff_size *= 2; - } - strcat(description, aux); + snprintf(aux, small_buff_size, "\n\n%%SHA256SUM%%\n%s", checksum); + if (buff_size < strlen(description) + small_buff_size + 1) { + description = realloc(description, buff_size * 2); + buff_size *= 2; + } + strcat(description, aux); - ADD_STRING("\n\n%%URL%%\n%s", url); - ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses); - ADD_STRING("\n\n%%ARCH%%\n%s", arch); - ADD_STRING("\n\n%%BUILDDATE%%\n%ld", build_date); - ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); - ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces); - ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts); - ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides); - ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); - ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends); - ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); - ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); + ADD_STRING("\n\n%%URL%%\n%s", url); + ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses); + ADD_STRING("\n\n%%ARCH%%\n%s", arch); + ADD_STRING("\n\n%%BUILDDATE%%\n%ld", build_date); + ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); + ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces); + ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts); + ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides); + ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); + ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends); + ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); + ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); - strcat(description, "\n\n"); + strcat(description, "\n\n"); - return description; + return description; } void vieter_package_free(vieter_package **ptp) { - FREE_STRING((*ptp)->path); - vieter_package_info_free((*ptp)->info); - vieter_package_dynarray_free((*ptp)->files); - free(*ptp); - *ptp = NULL; - + FREE_STRING((*ptp)->path); + vieter_package_info_free((*ptp)->info); + vieter_package_dynarray_free((*ptp)->files); + free(*ptp); + *ptp = NULL; } diff --git a/src/package/vieter_package_dynarray.c b/src/package/vieter_package_dynarray.c index 6da07ee..a29c843 100644 --- a/src/package/vieter_package_dynarray.c +++ b/src/package/vieter_package_dynarray.c @@ -1,56 +1,58 @@ #include "vieter_package_dynarray.h" vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity) { - vieter_package_dynarray *da = malloc(sizeof(vieter_package_dynarray)); - da->size = 0; - da->capacity = initial_capacity; + vieter_package_dynarray *da = malloc(sizeof(vieter_package_dynarray)); + da->size = 0; + da->capacity = initial_capacity; - return da; + return da; } void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { - // An empty vieter_package_dynarray does not have an allocated internal array yet - if (da->size == 0) { - da->array = malloc(sizeof(char*) * da->capacity); + // An empty vieter_package_dynarray does not have an allocated internal array + // yet + if (da->size == 0) { + da->array = malloc(sizeof(char *) * da->capacity); - // Initialise all char*'s to 0 so array[i] == NULL can be used to see if field is empty - memset(da->array, 0, sizeof(char*) * da->capacity); - } - // Double array size if it's full - else if (da->size == da->capacity) { - // if the realloc fails, access to memory in da->array is lost - da->array = realloc(da->array, sizeof(char*) * da->capacity * 2); - da->capacity *= 2; + // Initialise all char*'s to 0 so array[i] == NULL can be used to see if + // field is empty + memset(da->array, 0, sizeof(char *) * da->capacity); + } + // Double array size if it's full + else if (da->size == da->capacity) { + // if the realloc fails, access to memory in da->array is lost + da->array = realloc(da->array, sizeof(char *) * da->capacity * 2); + da->capacity *= 2; - // Same as the previous memset, but only for newly allocated pointers - memset(da->array + da->size, 0, sizeof(char*) * da->capacity / 2); - } - - da->array[da->size] = strdup(s); - da->size++; + // Same as the previous memset, but only for newly allocated pointers + memset(da->array + da->size, 0, sizeof(char *) * da->capacity / 2); + } + + da->array[da->size] = strdup(s); + da->size++; } void vieter_package_dynarray_free(vieter_package_dynarray *da) { - if (da == NULL) { - return; - } + if (da == NULL) { + return; + } - if (da->array != NULL) { - for (size_t i = 0; i < da->size; i++) { - free(da->array[i]); - } + if (da->array != NULL) { + for (size_t i = 0; i < da->size; i++) { + free(da->array[i]); + } - free(da->array); - } + free(da->array); + } - free(da); + free(da); } char **vieter_package_dynarray_convert(vieter_package_dynarray *da) { - char **array = da->array; + char **array = da->array; - da->array = NULL; - vieter_package_dynarray_free(da); + da->array = NULL; + vieter_package_dynarray_free(da); - return array; + return array; } diff --git a/src/package/vieter_package_info.c b/src/package/vieter_package_info.c index 5ed040e..1dfd0b7 100644 --- a/src/package/vieter_package_info.c +++ b/src/package/vieter_package_info.c @@ -2,78 +2,85 @@ #include "vieter_package_info.h" -#define PKG_INFO_STRING(key_ptr, field) if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ - value_ptr += strlen(key_ptr);\ - tail_ptr = strchr(value_ptr, '\n');\ - tail_ptr[0] = '\0'; \ - pkg_info->field = strdup(value_ptr); \ - tail_ptr[0] = '\n'; \ -} value_ptr = tail_ptr; +#define PKG_INFO_STRING(key_ptr, field) \ + if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ + value_ptr += strlen(key_ptr); \ + tail_ptr = strchr(value_ptr, '\n'); \ + tail_ptr[0] = '\0'; \ + pkg_info->field = strdup(value_ptr); \ + tail_ptr[0] = '\n'; \ + } \ + value_ptr = tail_ptr; -#define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr);\ - tail_ptr = strchr(value_ptr, '\n');\ - tail_ptr[0] = '\0'; \ - pkg_info->field = atoi(value_ptr); \ - tail_ptr[0] = '\n'; \ - value_ptr = tail_ptr; +#define PKG_INFO_INT(key_ptr, field) \ + value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr); \ + tail_ptr = strchr(value_ptr, '\n'); \ + tail_ptr[0] = '\0'; \ + pkg_info->field = atoi(value_ptr); \ + tail_ptr[0] = '\n'; \ + value_ptr = tail_ptr; -#define PKG_INFO_ARRAY(key_ptr, field) while((value_ptr = strstr(value_ptr, key_ptr)) != NULL){ \ - value_ptr = value_ptr + strlen(key_ptr);\ - tail_ptr = strchr(value_ptr, '\n'); \ - tail_ptr[0] = '\0'; \ - if(pkg_info->field == NULL) { pkg_info->field = vieter_package_dynarray_init(4); } \ - vieter_package_dynarray_add(pkg_info->field, value_ptr); \ - tail_ptr[0] = '\n'; \ - value_ptr = tail_ptr;\ -} value_ptr = tail_ptr; +#define PKG_INFO_ARRAY(key_ptr, field) \ + while ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ + value_ptr = value_ptr + strlen(key_ptr); \ + tail_ptr = strchr(value_ptr, '\n'); \ + tail_ptr[0] = '\0'; \ + if (pkg_info->field == NULL) { \ + pkg_info->field = vieter_package_dynarray_init(4); \ + } \ + vieter_package_dynarray_add(pkg_info->field, value_ptr); \ + tail_ptr[0] = '\n'; \ + value_ptr = tail_ptr; \ + } \ + value_ptr = tail_ptr; vieter_package_info *vieter_package_info_init() { - return calloc(1, sizeof(vieter_package_info)); + return calloc(1, sizeof(vieter_package_info)); } void vieter_package_info_free(vieter_package_info *pkg_info) { - FREE_STRING(pkg_info->name); - FREE_STRING(pkg_info->base); - FREE_STRING(pkg_info->version); - FREE_STRING(pkg_info->description); - FREE_STRING(pkg_info->url); - FREE_STRING(pkg_info->arch); - FREE_STRING(pkg_info->packager); - FREE_STRING(pkg_info->pgpsig); + FREE_STRING(pkg_info->name); + FREE_STRING(pkg_info->base); + FREE_STRING(pkg_info->version); + FREE_STRING(pkg_info->description); + FREE_STRING(pkg_info->url); + FREE_STRING(pkg_info->arch); + FREE_STRING(pkg_info->packager); + FREE_STRING(pkg_info->pgpsig); - vieter_package_dynarray_free(pkg_info->groups); - vieter_package_dynarray_free(pkg_info->licenses); - vieter_package_dynarray_free(pkg_info->replaces); - vieter_package_dynarray_free(pkg_info->depends); - vieter_package_dynarray_free(pkg_info->conflicts); - vieter_package_dynarray_free(pkg_info->provides); - vieter_package_dynarray_free(pkg_info->optdepends); - vieter_package_dynarray_free(pkg_info->makedepends); - vieter_package_dynarray_free(pkg_info->checkdepends); + vieter_package_dynarray_free(pkg_info->groups); + vieter_package_dynarray_free(pkg_info->licenses); + vieter_package_dynarray_free(pkg_info->replaces); + vieter_package_dynarray_free(pkg_info->depends); + vieter_package_dynarray_free(pkg_info->conflicts); + vieter_package_dynarray_free(pkg_info->provides); + vieter_package_dynarray_free(pkg_info->optdepends); + vieter_package_dynarray_free(pkg_info->makedepends); + vieter_package_dynarray_free(pkg_info->checkdepends); - free(pkg_info); + free(pkg_info); } -void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str) { - char *value_ptr = pkg_info_str, *tail_ptr; - - PKG_INFO_STRING("\npkgname = ", name); - PKG_INFO_STRING("\npkgbase = ", base); - PKG_INFO_STRING("\npkgver = ", version); - PKG_INFO_STRING("\npkgdesc = ", description); - PKG_INFO_STRING("\nurl = ", url); - PKG_INFO_INT("\nbuilddate = ", build_date); - PKG_INFO_STRING("\npackager = ", packager); - PKG_INFO_INT("\nsize = ", size); - PKG_INFO_STRING("\narch = ", arch); - PKG_INFO_ARRAY("\nlicense = ", licenses); - PKG_INFO_ARRAY("\nreplaces = ", replaces); - PKG_INFO_ARRAY("\ngroup = ", groups); - PKG_INFO_ARRAY("\nconflict = ", conflicts); - PKG_INFO_ARRAY("\nprovides = ", provides); - PKG_INFO_ARRAY("\ndepend = ", depends); - PKG_INFO_ARRAY("\noptdepend = ", optdepends); - PKG_INFO_ARRAY("\nmakedepend = ", makedepends); - PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends); +void vieter_package_info_parse(vieter_package_info *pkg_info, + char *pkg_info_str) { + char *value_ptr = pkg_info_str, *tail_ptr; + PKG_INFO_STRING("\npkgname = ", name); + PKG_INFO_STRING("\npkgbase = ", base); + PKG_INFO_STRING("\npkgver = ", version); + PKG_INFO_STRING("\npkgdesc = ", description); + PKG_INFO_STRING("\nurl = ", url); + PKG_INFO_INT("\nbuilddate = ", build_date); + PKG_INFO_STRING("\npackager = ", packager); + PKG_INFO_INT("\nsize = ", size); + PKG_INFO_STRING("\narch = ", arch); + PKG_INFO_ARRAY("\nlicense = ", licenses); + PKG_INFO_ARRAY("\nreplaces = ", replaces); + PKG_INFO_ARRAY("\ngroup = ", groups); + PKG_INFO_ARRAY("\nconflict = ", conflicts); + PKG_INFO_ARRAY("\nprovides = ", provides); + PKG_INFO_ARRAY("\ndepend = ", depends); + PKG_INFO_ARRAY("\noptdepend = ", optdepends); + PKG_INFO_ARRAY("\nmakedepend = ", makedepends); + PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends); } From c0925fec14a79312c7339b0d4984d347516cbd96 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Thu, 2 Feb 2023 11:02:31 +0000 Subject: [PATCH 42/74] fix: Initialise variables to keep CI from breaking. --- src/package/vieter_package.c | 2 +- src/package/vieter_package_info.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 4bb7622..e5530e4 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -65,7 +65,7 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, int compression_code = archive_filter_code(a, 0); const char *path_name; - vieter_package_info *pkg_info; + vieter_package_info *pkg_info = NULL; vieter_package_dynarray *files = vieter_package_dynarray_init(16); vieter_package_dynarray_add(files, "%FILES%"); diff --git a/src/package/vieter_package_info.c b/src/package/vieter_package_info.c index 1dfd0b7..ff5f1fe 100644 --- a/src/package/vieter_package_info.c +++ b/src/package/vieter_package_info.c @@ -63,7 +63,7 @@ void vieter_package_info_free(vieter_package_info *pkg_info) { void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str) { - char *value_ptr = pkg_info_str, *tail_ptr; + char *value_ptr = pkg_info_str, *tail_ptr = NULL; PKG_INFO_STRING("\npkgname = ", name); PKG_INFO_STRING("\npkgbase = ", base); From da7e41e8cada9d61cd14b00bb9f7ffb7e520388e Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Thu, 2 Feb 2023 11:42:00 +0000 Subject: [PATCH 43/74] refactor: Package extension now depends on what compression method was detected. --- src/package/vieter_package.c | 22 ++++++++++++++++++---- test/package/test_package.c | 2 ++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index e5530e4..5c61d45 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -185,11 +185,25 @@ char *vieter_package_to_description(vieter_package *pkg) { int i; // special case for FILENAME - // assuming .pkg.tar.zst; other formats are valid, this should account for - // that + char *ext; + switch (pkg->compression) { + case 0: + ext = ".tar"; + break; + case 1: + ext = ".tar.gz"; + break; + case 6: + ext = ".tar.xz"; + break; + case 14: + ext = ".tar.zst"; + break; + } + size_to_be_written = - snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", - pkg_info->name, pkg_info->version, pkg_info->arch); + snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg%s", + pkg_info->name, pkg_info->version, pkg_info->arch, ext); // We neither want to let an arbritrarily long input to overflow the buffer // nor to truncate perfectly valid inputs diff --git a/test/package/test_package.c b/test/package/test_package.c index 3c8b249..d4dd981 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -78,6 +78,8 @@ void test_pkg_read_archive_desc() { fclose(f); TEST_CHECK(!strcmp(description, desc)); + + vieter_package_free(&pkg); } TEST_LIST = { From b9dbb8af5ce7336b1c9390d50b530759f0588400 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Thu, 2 Feb 2023 12:45:32 +0000 Subject: [PATCH 44/74] fix: Initialised variable to keep CI from breaking (again). --- src/package/vieter_package.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 5c61d45..bec0bf5 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -185,7 +185,7 @@ char *vieter_package_to_description(vieter_package *pkg) { int i; // special case for FILENAME - char *ext; + char *ext = NULL; switch (pkg->compression) { case 0: ext = ".tar"; From a6ed89d8cd9a99174a7d4cc28264c30f55aa2538 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 2 Feb 2023 14:10:35 +0100 Subject: [PATCH 45/74] feat(tree): add tree iterator --- include/vieter_tree.h | 24 +++++++++++++++- src/tree/vieter_tree.c | 8 +----- src/tree/vieter_tree_internal.h | 12 ++++++++ src/tree/vieter_tree_iterator.c | 49 +++++++++++++++++++++++++++++++++ src/tree/vieter_tree_node.c | 19 +++++++++++++ src/tree/vieter_tree_node.h | 6 ++++ test/tree/test_tree.c | 15 ++++++++-- 7 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 src/tree/vieter_tree_iterator.c diff --git a/include/vieter_tree.h b/include/vieter_tree.h index d3abd2f..2079eb9 100644 --- a/include/vieter_tree.h +++ b/include/vieter_tree.h @@ -9,7 +9,8 @@ typedef struct vieter_tree vieter_tree; typedef enum vieter_tree_error { vieter_tree_ok = 0, vieter_tree_already_present = 1, - vieter_tree_not_present = 2 + vieter_tree_not_present = 2, + vieter_tree_iterator_done = 3 } vieter_tree_error; /* @@ -45,4 +46,25 @@ vieter_tree_error vieter_tree_remove(void **out, vieter_tree *tree, */ uint64_t vieter_tree_size(vieter_tree *tree); +/* + * An iterator that can be used to traverse a tree in-order. + */ +typedef struct vieter_tree_iterator vieter_tree_iterator; + +/* + * Allocate and initialize a new iterator from the given tree. + */ +vieter_tree_iterator *vieter_tree_iterator_from(vieter_tree *tree); + +/* + * Free an iterator. + */ +void vieter_tree_iterator_free(vieter_tree_iterator **ptp); + +/* + * Return the iterator's next element. + */ +vieter_tree_error vieter_tree_iterator_next(void **out, + vieter_tree_iterator *iter); + #endif diff --git a/src/tree/vieter_tree.c b/src/tree/vieter_tree.c index eef2aef..84a1a26 100644 --- a/src/tree/vieter_tree.c +++ b/src/tree/vieter_tree.c @@ -1,11 +1,5 @@ -#include "vieter_tree_internal.h" -#include "vieter_tree_node.h" #include "vieter_tree_balancing.h" - -struct vieter_tree { - uint64_t size; - vieter_tree_node *root; -}; +#include "vieter_tree_internal.h" vieter_tree *vieter_tree_init() { return calloc(1, sizeof(vieter_tree)); } diff --git a/src/tree/vieter_tree_internal.h b/src/tree/vieter_tree_internal.h index 670d45b..855139f 100644 --- a/src/tree/vieter_tree_internal.h +++ b/src/tree/vieter_tree_internal.h @@ -1,10 +1,22 @@ #include "vieter_tree.h" +#include "vieter_tree_node.h" #include +struct vieter_tree { + uint64_t size; + vieter_tree_node *root; +}; + /* * Inspect whether the tree is still a valid red-black-tree. * * @return true if valid, false otherwise. */ bool vieter_tree_validate(vieter_tree *tree); + +struct vieter_tree_iterator { + vieter_tree_node *current_node; + bool started; + bool done; +}; diff --git a/src/tree/vieter_tree_iterator.c b/src/tree/vieter_tree_iterator.c new file mode 100644 index 0000000..4eefe02 --- /dev/null +++ b/src/tree/vieter_tree_iterator.c @@ -0,0 +1,49 @@ +#include "vieter_tree.h" +#include "vieter_tree_internal.h" + +vieter_tree_iterator *vieter_tree_iterator_from(vieter_tree *tree) { + vieter_tree_iterator *iter = calloc(1, sizeof(vieter_tree_iterator)); + + // An empty tree's iterator will be done immediately + if (tree->size == 0) { + iter->started = true; + iter->done = true; + + return iter; + } + + iter->current_node = tree->root; + + return iter; +} + +vieter_tree_error vieter_tree_iterator_next(void **out, + vieter_tree_iterator *iter) { + if (iter->done) { + return vieter_tree_iterator_done; + } + + if (!iter->started) { + while (iter->current_node->children[0] != NULL) { + iter->current_node = iter->current_node->children[0]; + } + + iter->started = true; + } + + *out = iter->current_node->data; + + iter->current_node = vieter_tree_node_next(iter->current_node); + + if (iter->current_node == NULL) { + iter->done = true; + } + + return vieter_tree_ok; +} + +void vieter_tree_iterator_free(vieter_tree_iterator **ptp) { + free(*ptp); + + *ptp = NULL; +} diff --git a/src/tree/vieter_tree_node.c b/src/tree/vieter_tree_node.c index e58092e..0a8e658 100644 --- a/src/tree/vieter_tree_node.c +++ b/src/tree/vieter_tree_node.c @@ -150,3 +150,22 @@ void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag, bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag) { return (node->flags & flag) != 0; } + +vieter_tree_node *vieter_tree_node_next(vieter_tree_node *node) { + if (node->children[1] != NULL) { + node = node->children[1]; + + while (node->children[0] != NULL) { + node = node->children[0]; + } + + return node; + } + + while (node->parent != NULL && + vieter_tree_node_get(node, vieter_tree_node_right)) { + node = node->parent; + } + + return node->parent; +} diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 3b1c169..3cf8e56 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -77,4 +77,10 @@ void vieter_tree_node_set_children(vieter_tree_node *parent, vieter_tree_node ** */ void vieter_tree_node_set_child(vieter_tree_node *parent, vieter_tree_node *child, bool right); +/* + * Return the in-order successor of the given node, or NULL if it's the last + * node in the tree. + */ +vieter_tree_node *vieter_tree_node_next(vieter_tree_node *node); + #endif diff --git a/test/tree/test_tree.c b/test/tree/test_tree.c index 2ab6870..10235cb 100644 --- a/test/tree/test_tree.c +++ b/test/tree/test_tree.c @@ -16,19 +16,30 @@ void test_insert() { vieter_tree *tree = vieter_tree_init(); for (uint64_t i = 0; i < 250; i++) { - TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_ok); + TEST_CHECK(vieter_tree_insert(tree, i, (void *)i) == vieter_tree_ok); TEST_SIZE(tree, i + 1); TEST_CHECK(vieter_tree_validate(tree)); } - void *out; + vieter_tree_iterator *iter = vieter_tree_iterator_from(tree); + + void *out = NULL; for (uint64_t i = 0; i < 250; i++) { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); + TEST_CHECK(out == (void *)i); TEST_CHECK(vieter_tree_insert(tree, i, NULL) == vieter_tree_already_present); TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); + + out = NULL; + + TEST_CHECK(vieter_tree_iterator_next(&out, iter) == vieter_tree_ok); + TEST_CHECK(out == (void *)i); } + TEST_CHECK(vieter_tree_iterator_next(&out, iter) == vieter_tree_iterator_done); + + vieter_tree_iterator_free(&iter); vieter_tree_free(tree); } From d9402ced54c44961b70e6559321e6d42fb9b14f3 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Thu, 2 Feb 2023 15:30:57 +0100 Subject: [PATCH 46/74] test(tree): add random insert test --- test/tree/test_tree_random.c | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 test/tree/test_tree_random.c diff --git a/test/tree/test_tree_random.c b/test/tree/test_tree_random.c new file mode 100644 index 0000000..d1b9ab0 --- /dev/null +++ b/test/tree/test_tree_random.c @@ -0,0 +1,59 @@ +#include "acutest.h" +#include "vieter_tree_internal.h" + +#define TEST_SIZE(tree, size) \ + TEST_CHECK(vieter_tree_size(tree) == size); \ + TEST_MSG("Size: %zu", vieter_tree_size(tree)) + +int uint64_t_compare(const void *a, const void *b) { + if ((*(uint64_t *)a) < (*(uint64_t *)b)) { + return -1; + } else if ((*(uint64_t *)a) > (*(uint64_t *)b)) { + return 1; + } else { + return 0; + } +} + +void test_insert_random() { + const uint64_t n = 1000; + srand(0); + + vieter_tree *tree = vieter_tree_init(); + + uint64_t *numbers = malloc(n * sizeof(uint64_t)); + uint64_t num; + void *out = NULL; + + for (uint64_t i = 0; i < n; i++) { + num = rand(); + vieter_tree_insert(tree, num, (void *)num); + TEST_SIZE(tree, i + 1); + TEST_CHECK(vieter_tree_validate(tree)); + TEST_CHECK(vieter_tree_search(&out, tree, num) == vieter_tree_ok); + TEST_CHECK(out == (void *)num); + + out = NULL; + + numbers[i] = num; + } + + qsort(numbers, n, sizeof(uint64_t), uint64_t_compare); + + vieter_tree_iterator *iter = vieter_tree_iterator_from(tree); + out = NULL; + + for (uint64_t i = 0; i < n; i++) { + TEST_CHECK(vieter_tree_iterator_next(&out, iter) == vieter_tree_ok); + TEST_CHECK(out == (void *)numbers[i]); + } + + free(numbers); + vieter_tree_iterator_free(&iter); + vieter_tree_free(tree); +} + +TEST_LIST = { + {"tree insert random", test_insert_random}, + {NULL, NULL} +}; From e5f0ac8decc8fce795550160da3bb531d53e3ced Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Thu, 2 Feb 2023 19:29:34 +0000 Subject: [PATCH 47/74] fix: Plug memory leaks and fix strings that were not null terminated. --- src/package/vieter_package.c | 7 +++++-- test/package/test_package.c | 11 +++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index bec0bf5..4bce4f5 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -44,7 +44,7 @@ vieter_package *vieter_package_init() { vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path) { struct archive *a = archive_read_new(); - struct archive_entry *entry = archive_entry_new(); + struct archive_entry *entry; // These three are the most commonly used compression methods archive_read_support_filter_zstd(a); @@ -88,8 +88,9 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, if (strcmp(path_name, ".PKGINFO") == 0) { // Read data of file into memory buffer int size = archive_entry_size(entry); - char *buf = malloc(size); + char *buf = malloc(size + 1); archive_read_data(a, buf, size); + buf[size] = '\0'; // Parse package vieter_package_info string into a struct pkg_info = vieter_package_info_init(); @@ -248,6 +249,8 @@ char *vieter_package_to_description(vieter_package *pkg) { strcat(description, "\n\n"); + free(aux); + return description; } diff --git a/test/package/test_package.c b/test/package/test_package.c index d4dd981..bcefdf6 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -8,8 +8,9 @@ void test_info_parse() { size_t size = ftell(f); fflush(stdout); rewind(f); - char *pkg_info_str = malloc(size); + char *pkg_info_str = malloc(size + 1); fread(pkg_info_str, 1, size, f); + pkg_info_str[size] = '\0'; fclose(f); vieter_package_info *pkg_info = vieter_package_info_init(); @@ -36,6 +37,9 @@ void test_info_parse() { TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); + + free(pkg_info_str); + vieter_package_info_free(pkg_info); } void test_pkg_read_archive_files() { @@ -73,13 +77,16 @@ void test_pkg_read_archive_desc() { fseek(f, 0, SEEK_END); size_t size = ftell(f); rewind(f); - char *desc = malloc(size); + char *desc = malloc(size + 1); fread(desc, 1, size, f); + desc[size] = '\0'; fclose(f); TEST_CHECK(!strcmp(description, desc)); vieter_package_free(&pkg); + free(description); + free(desc); } TEST_LIST = { From caee502382f534d066c9d1e0c29db877a8dcf4e9 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 23 Feb 2023 09:54:50 +0100 Subject: [PATCH 48/74] refactor: move dynarray into own module --- include/vieter_dynarray.h | 34 ++++++++++++++++++ .../vieter_dynarray.c} | 16 ++++----- src/package/vieter_package.c | 8 ++--- src/package/vieter_package_dynarray.h | 36 ------------------- src/package/vieter_package_info.c | 22 ++++++------ src/package/vieter_package_info.h | 20 +++++------ src/package/vieter_package_internal.h | 4 +-- 7 files changed, 69 insertions(+), 71 deletions(-) create mode 100644 include/vieter_dynarray.h rename src/{package/vieter_package_dynarray.c => dynarray/vieter_dynarray.c} (65%) delete mode 100644 src/package/vieter_package_dynarray.h diff --git a/include/vieter_dynarray.h b/include/vieter_dynarray.h new file mode 100644 index 0000000..2a6305e --- /dev/null +++ b/include/vieter_dynarray.h @@ -0,0 +1,34 @@ +#ifndef VIETER_DYNARRAY +#define VIETER_DYNARRAY + +#include +#include + +typedef struct vieter_dynarray { + char **array; + size_t capacity; + size_t size; +} vieter_dynarray; + +/* + * Allocate a dynamic array. + */ +vieter_dynarray *vieter_dynarray_init(size_t initial_capacity); + +/* + * Initialise array (if it's not already initialised) and insert a string. + */ +void vieter_dynarray_add(vieter_dynarray *da, const char *s); + +/* + * Deallocate dynamic array. + */ +void vieter_dynarray_free(vieter_dynarray *da); + +/* + * Convert a vieter_dynarray into an array by freeing all its surrounding + * components and returning the underlying array pointer. + */ +char **vieter_dynarray_convert(vieter_dynarray *da); + +#endif diff --git a/src/package/vieter_package_dynarray.c b/src/dynarray/vieter_dynarray.c similarity index 65% rename from src/package/vieter_package_dynarray.c rename to src/dynarray/vieter_dynarray.c index a29c843..5c4026b 100644 --- a/src/package/vieter_package_dynarray.c +++ b/src/dynarray/vieter_dynarray.c @@ -1,15 +1,15 @@ -#include "vieter_package_dynarray.h" +#include "vieter_dynarray.h" -vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity) { - vieter_package_dynarray *da = malloc(sizeof(vieter_package_dynarray)); +vieter_dynarray *vieter_dynarray_init(size_t initial_capacity) { + vieter_dynarray *da = malloc(sizeof(vieter_dynarray)); da->size = 0; da->capacity = initial_capacity; return da; } -void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { - // An empty vieter_package_dynarray does not have an allocated internal array +void vieter_dynarray_add(vieter_dynarray *da, const char *s) { + // An empty vieter_dynarray does not have an allocated internal array // yet if (da->size == 0) { da->array = malloc(sizeof(char *) * da->capacity); @@ -32,7 +32,7 @@ void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { da->size++; } -void vieter_package_dynarray_free(vieter_package_dynarray *da) { +void vieter_dynarray_free(vieter_dynarray *da) { if (da == NULL) { return; } @@ -48,11 +48,11 @@ void vieter_package_dynarray_free(vieter_package_dynarray *da) { free(da); } -char **vieter_package_dynarray_convert(vieter_package_dynarray *da) { +char **vieter_dynarray_convert(vieter_dynarray *da) { char **array = da->array; da->array = NULL; - vieter_package_dynarray_free(da); + vieter_dynarray_free(da); return array; } diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 4bce4f5..6aca847 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -66,8 +66,8 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *path_name; vieter_package_info *pkg_info = NULL; - vieter_package_dynarray *files = vieter_package_dynarray_init(16); - vieter_package_dynarray_add(files, "%FILES%"); + vieter_dynarray *files = vieter_dynarray_init(16); + vieter_dynarray_add(files, "%FILES%"); while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { path_name = archive_entry_pathname(entry); @@ -82,7 +82,7 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, } if (!ignore) { - vieter_package_dynarray_add(files, path_name); + vieter_dynarray_add(files, path_name); } if (strcmp(path_name, ".PKGINFO") == 0) { @@ -257,7 +257,7 @@ char *vieter_package_to_description(vieter_package *pkg) { void vieter_package_free(vieter_package **ptp) { FREE_STRING((*ptp)->path); vieter_package_info_free((*ptp)->info); - vieter_package_dynarray_free((*ptp)->files); + vieter_dynarray_free((*ptp)->files); free(*ptp); *ptp = NULL; } diff --git a/src/package/vieter_package_dynarray.h b/src/package/vieter_package_dynarray.h deleted file mode 100644 index c198ea1..0000000 --- a/src/package/vieter_package_dynarray.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef VIETER_DYNARRAY -#define VIETER_DYNARRAY - -#include -#include -#include "vieter_package.h" - -typedef struct vieter_package_dynarray vieter_package_dynarray; -struct vieter_package_dynarray { - char **array; - size_t capacity; - size_t size; -}; - -/* - * Allocate a dynamic array. - */ -vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity); - -/* - * Initialise array (if it's not already initialised) and insert a string. - */ -void vieter_package_dynarray_add(vieter_package_dynarray *da, const char * s); - -/* - * Deallocate dynamic array. - */ -void vieter_package_dynarray_free(vieter_package_dynarray *da); - -/* - * Convert a vieter_package_dynarray into an array by freeing all its surrounding components - * and returning the underlying array pointer. - */ -char **vieter_package_dynarray_convert(vieter_package_dynarray *da); - -#endif diff --git a/src/package/vieter_package_info.c b/src/package/vieter_package_info.c index ff5f1fe..4805206 100644 --- a/src/package/vieter_package_info.c +++ b/src/package/vieter_package_info.c @@ -26,9 +26,9 @@ tail_ptr = strchr(value_ptr, '\n'); \ tail_ptr[0] = '\0'; \ if (pkg_info->field == NULL) { \ - pkg_info->field = vieter_package_dynarray_init(4); \ + pkg_info->field = vieter_dynarray_init(4); \ } \ - vieter_package_dynarray_add(pkg_info->field, value_ptr); \ + vieter_dynarray_add(pkg_info->field, value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr; \ } \ @@ -48,15 +48,15 @@ void vieter_package_info_free(vieter_package_info *pkg_info) { FREE_STRING(pkg_info->packager); FREE_STRING(pkg_info->pgpsig); - vieter_package_dynarray_free(pkg_info->groups); - vieter_package_dynarray_free(pkg_info->licenses); - vieter_package_dynarray_free(pkg_info->replaces); - vieter_package_dynarray_free(pkg_info->depends); - vieter_package_dynarray_free(pkg_info->conflicts); - vieter_package_dynarray_free(pkg_info->provides); - vieter_package_dynarray_free(pkg_info->optdepends); - vieter_package_dynarray_free(pkg_info->makedepends); - vieter_package_dynarray_free(pkg_info->checkdepends); + vieter_dynarray_free(pkg_info->groups); + vieter_dynarray_free(pkg_info->licenses); + vieter_dynarray_free(pkg_info->replaces); + vieter_dynarray_free(pkg_info->depends); + vieter_dynarray_free(pkg_info->conflicts); + vieter_dynarray_free(pkg_info->provides); + vieter_dynarray_free(pkg_info->optdepends); + vieter_dynarray_free(pkg_info->makedepends); + vieter_dynarray_free(pkg_info->checkdepends); free(pkg_info); } diff --git a/src/package/vieter_package_info.h b/src/package/vieter_package_info.h index b931928..2c69d92 100644 --- a/src/package/vieter_package_info.h +++ b/src/package/vieter_package_info.h @@ -6,7 +6,7 @@ #include #include "vieter_package.h" -#include "vieter_package_dynarray.h" +#include "vieter_dynarray.h" typedef struct vieter_package_info { @@ -23,15 +23,15 @@ typedef struct vieter_package_info { char *pgpsig; int64_t pgpsigsize; - vieter_package_dynarray *groups; - vieter_package_dynarray *licenses; - vieter_package_dynarray *replaces; - vieter_package_dynarray *depends; - vieter_package_dynarray *conflicts; - vieter_package_dynarray *provides; - vieter_package_dynarray *optdepends; - vieter_package_dynarray *makedepends; - vieter_package_dynarray *checkdepends; + vieter_dynarray *groups; + vieter_dynarray *licenses; + vieter_dynarray *replaces; + vieter_dynarray *depends; + vieter_dynarray *conflicts; + vieter_dynarray *provides; + vieter_dynarray *optdepends; + vieter_dynarray *makedepends; + vieter_dynarray *checkdepends; } vieter_package_info; /* diff --git a/src/package/vieter_package_internal.h b/src/package/vieter_package_internal.h index fe84f17..4c4eef6 100644 --- a/src/package/vieter_package_internal.h +++ b/src/package/vieter_package_internal.h @@ -1,10 +1,10 @@ #include "vieter_package.h" #include "vieter_package_info.h" -#include "vieter_package_dynarray.h" +#include "vieter_dynarray.h" struct vieter_package { char *path; vieter_package_info *info; - vieter_package_dynarray *files; + vieter_dynarray *files; int compression; }; From 38e84afd1d10606aec18711f66464140ae2e5aba Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 23 Feb 2023 10:13:58 +0100 Subject: [PATCH 49/74] fix: also lint internal header files --- Makefile | 8 +------- src/heap/vieter_heap_tree.h | 23 +++++++++++----------- src/tree/vieter_tree_internal.h | 6 +++--- src/tree/vieter_tree_node.h | 34 ++++++++++++++++++++------------- 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/Makefile b/Makefile index 665c411..fadf89d 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ INC_DIRS ?= include LIB := $(BUILD_DIR)/$(LIB_FILENAME) SRCS != find '$(SRC_DIR)' -iname '*.c' -SRCS_H != find $(INC_DIRS) -iname '*.h' +SRCS_H != find $(INC_DIRS) '$(SRC_DIR)' -iname '*.h' SRCS_TEST != find '$(TEST_DIR)' -iname '*.c' OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) @@ -66,15 +66,9 @@ $(TARGETS_TEST): test-%: % $(TARGETS_MEM_TEST): test-mem-%: % valgrind --tool=memcheck --error-exitcode=1 --track-origins=yes --leak-check=full ./$^ -test-mem: build-test - @ $(foreach bin,$(BINS_TEST),valgrind --tool=memcheck --error-exitcode=1 \ - --track-origins=yes --leak-check=full ./$(bin);) - .PHONY: build-test build-test: $(BINS_TEST) -# For simplicity, we link every object file to each of the test files. This -# might be changed later if this starts to become too slow. $(BINS_TEST): %: %.c.o $(LIB) $(CC) \ $^ -o $@ diff --git a/src/heap/vieter_heap_tree.h b/src/heap/vieter_heap_tree.h index 0a299db..615491a 100644 --- a/src/heap/vieter_heap_tree.h +++ b/src/heap/vieter_heap_tree.h @@ -5,16 +5,16 @@ #include typedef struct vieter_heap_node { - uint64_t key; - void *data; - struct vieter_heap_node *largest_order; - union { - // Roots point to next tree in the heap, other nodes point to their first - // neighbour. - struct vieter_heap_node *next_tree; - struct vieter_heap_node *next_largest_order; - } ptr; - uint8_t order; + uint64_t key; + void *data; + struct vieter_heap_node *largest_order; + union { + // Roots point to next tree in the heap, other nodes point to their first + // neighbour. + struct vieter_heap_node *next_tree; + struct vieter_heap_node *next_largest_order; + } ptr; + uint8_t order; } vieter_heap_node; /* @@ -36,7 +36,8 @@ void vieter_heap_tree_free(vieter_heap_node *root); * Given the roots of the smallest trees in two heaps, merge them into a single * large heap. */ -vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, vieter_heap_node *root_b); +vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, + vieter_heap_node *root_b); /* * Given the roots of two trees of the same order, merge them into a heap of one diff --git a/src/tree/vieter_tree_internal.h b/src/tree/vieter_tree_internal.h index 855139f..1214572 100644 --- a/src/tree/vieter_tree_internal.h +++ b/src/tree/vieter_tree_internal.h @@ -16,7 +16,7 @@ struct vieter_tree { bool vieter_tree_validate(vieter_tree *tree); struct vieter_tree_iterator { - vieter_tree_node *current_node; - bool started; - bool done; + vieter_tree_node *current_node; + bool started; + bool done; }; diff --git a/src/tree/vieter_tree_node.h b/src/tree/vieter_tree_node.h index 3cf8e56..4db3cfe 100644 --- a/src/tree/vieter_tree_node.h +++ b/src/tree/vieter_tree_node.h @@ -2,8 +2,8 @@ #define VIETER_TREE_NODE #include "vieter_tree.h" -#include #include +#include typedef enum vieter_tree_node_flag { vieter_tree_node_black = ((uint8_t)1) << 0, @@ -13,11 +13,11 @@ typedef enum vieter_tree_node_flag { } vieter_tree_node_flag; typedef struct vieter_tree_node { - uint64_t key; - void *data; - struct vieter_tree_node *parent; - struct vieter_tree_node *children[2]; - uint8_t flags; + uint64_t key; + void *data; + struct vieter_tree_node *parent; + struct vieter_tree_node *children[2]; + uint8_t flags; } vieter_tree_node; /* @@ -33,27 +33,33 @@ void vieter_tree_node_free(vieter_tree_node *node); /* * Insert a new key into the given tree. */ -vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, void *data); +vieter_tree_error vieter_tree_node_insert(vieter_tree_node *root, uint64_t key, + void *data); /* * Return the node representing the requested value. */ -vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, vieter_tree_node *root, uint64_t key); +vieter_tree_error vieter_tree_node_search_node(vieter_tree_node **out, + vieter_tree_node *root, + uint64_t key); /* * Search for the data represented by the given key. */ -vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, uint64_t key); +vieter_tree_error vieter_tree_node_search(void **out, vieter_tree_node *root, + uint64_t key); /* * Remove the data associated with the given key. */ -vieter_tree_error vieter_tree_node_remove(void **out, vieter_tree_node **root_ptr, uint64_t key); +vieter_tree_error +vieter_tree_node_remove(void **out, vieter_tree_node **root_ptr, uint64_t key); /* * Set a node's bit flag to the given value. */ -void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag, bool value); +void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag, + bool value); /* * Get whether a node's bit flag is set. @@ -70,12 +76,14 @@ void vieter_tree_node_add_child(vieter_tree_node *parent, uint64_t key, /* * Replace a node's children array. */ -void vieter_tree_node_set_children(vieter_tree_node *parent, vieter_tree_node **children); +void vieter_tree_node_set_children(vieter_tree_node *parent, + vieter_tree_node **children); /* * Set a node's left or right child to the given node. */ -void vieter_tree_node_set_child(vieter_tree_node *parent, vieter_tree_node *child, bool right); +void vieter_tree_node_set_child(vieter_tree_node *parent, + vieter_tree_node *child, bool right); /* * Return the in-order successor of the given node, or NULL if it's the last From c2313fe0be75287cbb9e3338b7118ede3d7f520c Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 13:00:33 +0100 Subject: [PATCH 50/74] refactor: Add original .c package files by Jef. --- include/dynarray.h | 19 +++++ include/package.h | 26 +++++++ include/package_info.h | 39 +++++++++++ src/package/dynarray.c | 55 +++++++++++++++ src/package/package.c | 98 ++++++++++++++++++++++++++ src/package/package_info.c | 139 +++++++++++++++++++++++++++++++++++++ 6 files changed, 376 insertions(+) create mode 100644 include/dynarray.h create mode 100644 include/package.h create mode 100644 include/package_info.h create mode 100644 src/package/dynarray.c create mode 100644 src/package/package.c create mode 100644 src/package/package_info.c diff --git a/include/dynarray.h b/include/dynarray.h new file mode 100644 index 0000000..e552ec4 --- /dev/null +++ b/include/dynarray.h @@ -0,0 +1,19 @@ +#ifndef VIETER_DYNARRAY +#define VIETER_DYNARRAY + +#include +#include + +typedef struct dyn_array DynArray; + +DynArray *dynarray_init(size_t initial_capacity); +void dynarray_add(DynArray *da, const char * s); +void dynarray_free(DynArray *da); + +/** + * Convert a DynArray into an array by freeing all its surrounding components + * and returning the underlying array pointer. + */ +char **dynarray_convert(DynArray *da); + +#endif diff --git a/include/package.h b/include/package.h new file mode 100644 index 0000000..09e91bd --- /dev/null +++ b/include/package.h @@ -0,0 +1,26 @@ +#ifndef VIETER_PACKAGE +#define VIETER_PACKAGE + +#include +#include +#include +#include + +#include "archive.h" +#include "archive_entry.h" + +#include "package_info.h" +#include "dynarray.h" + +typedef struct pkg { + char *path; + PkgInfo *info; + DynArray *files; + int compression; +} Pkg; + +Pkg *package_read_archive(const char *pkg_path); +void package_free(Pkg ** ptp); +char *package_to_description(Pkg *pkg); + +#endif diff --git a/include/package_info.h b/include/package_info.h new file mode 100644 index 0000000..d71386e --- /dev/null +++ b/include/package_info.h @@ -0,0 +1,39 @@ +#ifndef VIETER_PACKAGE_INFO +#define VIETER_PACKAGE_INFO + +#define FREE_STRING(sp) if (sp != NULL) free(sp) + +#include + +#include "dynarray.h" + +typedef struct pkg_info { + char *name; + char *base; + char *version; + char *description; + int64_t size; + int64_t csize; + char *url; + char *arch; + int64_t build_date; + char *packager; + char *pgpsig; + int64_t pgpsigsize; + + DynArray *groups; + DynArray *licenses; + DynArray *replaces; + DynArray *depends; + DynArray *conflicts; + DynArray *provides; + DynArray *optdepends; + DynArray *makedepends; + DynArray *checkdepends; +} PkgInfo; + +PkgInfo *package_info_init(); +int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); +void package_info_free(PkgInfo *pkg_info); + +#endif diff --git a/src/package/dynarray.c b/src/package/dynarray.c new file mode 100644 index 0000000..480c08f --- /dev/null +++ b/src/package/dynarray.c @@ -0,0 +1,55 @@ +#include "dynarray.h" + +struct dyn_array { + char **array; + size_t size; + size_t capacity; +}; + +DynArray *dynarray_init(size_t initial_capacity) { + DynArray *da = malloc(sizeof(DynArray)); + da->size = 0; + da->capacity = initial_capacity; + + return da; +} + +void dynarray_add(DynArray *da, const char *s) { + // An empty dynarray does not have an allocated internal array yet + if (da->size == 0) { + da->array = malloc(sizeof(char*) * da->capacity); + } + // Double array size if it's full + else if (da->size == da->capacity) { + da->array = realloc(da->array, da->capacity * 2); + da->capacity *= 2; + } + + da->array[da->size] = strdup(s); + da->size++; +} + +void dynarray_free(DynArray *da) { + if (da == NULL) { + return; + } + + if (da->array != NULL) { + for (size_t i = 0; i < da->size; i++) { + free(da->array[i]); + } + + free(da->array); + } + + free(da); +} + +char **dynarray_convert(DynArray *da) { + char **array = da->array; + + da->array = NULL; + dynarray_free(da); + + return array; +} diff --git a/src/package/package.c b/src/package/package.c new file mode 100644 index 0000000..a098abb --- /dev/null +++ b/src/package/package.c @@ -0,0 +1,98 @@ +#include "package.h" + +static char *ignored_names[5] = { + ".BUILDINFO", + ".INSTALL", + ".MTREE", + ".PKGINFO", + ".CHANGELOG" +}; +static int ignored_words_len = sizeof(ignored_names) / sizeof(char *); + +Pkg *package_init() { + return calloc(sizeof(PkgInfo), 1); +} + +Pkg *package_read_archive(const char *pkg_path) { + struct archive *a = archive_read_new(); + struct archive_entry *entry = archive_entry_new(); + + // These three are the most commonly used compression methods + archive_read_support_filter_zstd(a); + archive_read_support_filter_gzip(a); + archive_read_support_filter_xz(a); + + // Contents should always be a tarball + archive_read_support_format_tar(a); + + // TODO where does this 10240 come from? + int r = archive_read_open_filename(a, pkg_path, 10240); + + // Exit early if we weren't able to successfully open the archive for reading + if (r != ARCHIVE_OK) { + return NULL; + } + + int compression_code = archive_filter_code(a, 0); + const char *path_name; + + PkgInfo *pkg_info; + DynArray *files = dynarray_init(16); + + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + path_name = archive_entry_pathname(entry); + + bool ignore = false; + + for (size_t i = 0; i < ignored_words_len; i++) { + if (strcmp(path_name, ignored_names[i]) == 0) { + ignore = true; + break; + } + } + + if (!ignore) { + dynarray_add(files, path_name); + } + + if (strcmp(path_name, ".PKGINFO") == 0) { + // Read data of file into memory buffer + int size = archive_entry_size(entry); + char *buf = malloc(size); + archive_read_data(a, buf, size); + + // Parse package info string into a struct + pkg_info = package_info_init(); + package_info_parse(pkg_info, buf); + + free(buf); + } else { + archive_read_data_skip(a); + } + } + + // Get size of file + struct stat stats; + + if (stat(pkg_path, &stats) != 0) { + return NULL; + } + + pkg_info->csize = stats.st_size; + + archive_read_free(a); + archive_entry_free(entry); + + // Create final return value + Pkg *pkg = package_init(); + pkg->path = strdup(pkg_path); + pkg->info = pkg_info; + pkg->files = files; + pkg->compression = compression_code; + + return pkg; +} + +char *package_to_description(Pkg *pkg) { + +} diff --git a/src/package/package_info.c b/src/package/package_info.c new file mode 100644 index 0000000..1202485 --- /dev/null +++ b/src/package/package_info.c @@ -0,0 +1,139 @@ +#include + +#include "package_info.h" + +PkgInfo *package_info_init() { + return calloc(1, sizeof(PkgInfo)); +} + +void package_info_free(PkgInfo *pkg_info) { + FREE_STRING(pkg_info->name); + FREE_STRING(pkg_info->base); + FREE_STRING(pkg_info->version); + FREE_STRING(pkg_info->description); + FREE_STRING(pkg_info->url); + FREE_STRING(pkg_info->arch); + FREE_STRING(pkg_info->packager); + FREE_STRING(pkg_info->pgpsig); + + dynarray_free(pkg_info->groups); + dynarray_free(pkg_info->licenses); + dynarray_free(pkg_info->replaces); + dynarray_free(pkg_info->depends); + dynarray_free(pkg_info->conflicts); + dynarray_free(pkg_info->provides); + dynarray_free(pkg_info->optdepends); + dynarray_free(pkg_info->makedepends); + dynarray_free(pkg_info->checkdepends); + + free(pkg_info); +} + +/** + * Advance the pointer until all spaces are skipped. + */ +static inline char *trim_spaces_front(char *ptr) { + while (ptr[0] == ' ') { + ptr++; + } + + return ptr; +} + +/** + * Given a string pointer in the middle of a string, move over all spaces in the + * given direction. The final space is replaced with a NULL-byte. + */ +static inline void trim_spaces_back(char *ptr) { + if (ptr[0] != ' ') { + return; + } + + while (ptr[-1] == ' ') { + ptr--; + } + + ptr[0] = '\0'; +} + +#define PKG_INFO_STRING(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = strdup(value_ptr); goto advance; } +#define PKG_INFO_INT(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = atoi(value_ptr); goto advance; } +#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { \ + if (pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ + dynarray_add(pkg_info->field, value_ptr); goto advance; \ +} + +int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { + char *offset_ptr, *equals_ptr, *key_ptr, *value_ptr; + + bool end = false; + + // Iterate over all lines in file + while (!end) { + // This pointer will always point to the final character of the + // current line, be it the position of a newline or the NULL byte at + // the end of the entire string + offset_ptr = strchr(pkg_info_str, '\n'); + + // We replace the newline with a NULL byte. Now we know the line runs + // until the next NULL byte. + if (offset_ptr != NULL) { + offset_ptr[0] = '\0'; + } else { + // Advance pointer to the NULL byte of the string + offset_ptr = pkg_info_str + 1; + + while (*offset_ptr != '\0') { + offset_ptr++; + } + + end = true; + } + + // Skip comment lines + if (pkg_info_str[0] == '#') { + goto advance; + } + + equals_ptr = strchr(pkg_info_str, '='); + + // If a line doesn't contain an equals sign, the file is invalid + if (equals_ptr == NULL) { + return 1; + } + + // Trim whitespace from key + key_ptr = trim_spaces_front(pkg_info_str); + trim_spaces_back(equals_ptr - 1); + + // Trim spaces from value + value_ptr = trim_spaces_front(equals_ptr + 1); + trim_spaces_back(offset_ptr - 1); + + // Match key + PKG_INFO_STRING("pkgname", name); + PKG_INFO_STRING("pkgbase", base); + PKG_INFO_STRING("pkgver", version); + PKG_INFO_STRING("pkgdesc", description); + PKG_INFO_INT("size", size); + PKG_INFO_STRING("url", url); + PKG_INFO_STRING("arch", arch); + PKG_INFO_INT("builddate", build_date); + PKG_INFO_STRING("packager", packager); + PKG_INFO_STRING("pgpsig", pgpsig); + PKG_INFO_INT("pgpsigsize", pgpsigsize); + PKG_INFO_ARRAY("group", groups); + PKG_INFO_ARRAY("license", licenses); + PKG_INFO_ARRAY("replaces", replaces); + PKG_INFO_ARRAY("depend", depends); + PKG_INFO_ARRAY("optdepend", optdepends); + PKG_INFO_ARRAY("makedepend", makedepends); + PKG_INFO_ARRAY("checkdepend", checkdepends); + +advance: + pkg_info_str = offset_ptr + 1; + continue; + } + + return 0; +} From 4309ad8cc5151dca6a259519bfe68cfc8a5ac6aa Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 16:22:22 +0100 Subject: [PATCH 51/74] refactor: Modified .PKGINFO parser not to rely on gotos and continues. Parser is now optimistic and assumes .PKGINFO file is valid. After my changes to the macros, they still feel a bit hacky, but I'm content with them. I also changed the parser to assume the .PKGINFO files are always valid because they are automatically generated. The parser also assumes the same fields will always appear in the same fixed order. I made this change after checking how makepkg generated this file. --- include/package_info.h | 2 +- src/package/package_info.c | 152 +++++++++++-------------------------- 2 files changed, 47 insertions(+), 107 deletions(-) diff --git a/include/package_info.h b/include/package_info.h index d71386e..b1388a2 100644 --- a/include/package_info.h +++ b/include/package_info.h @@ -33,7 +33,7 @@ typedef struct pkg_info { } PkgInfo; PkgInfo *package_info_init(); -int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); +void package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); void package_info_free(PkgInfo *pkg_info); #endif diff --git a/src/package/package_info.c b/src/package/package_info.c index 1202485..5e1986d 100644 --- a/src/package/package_info.c +++ b/src/package/package_info.c @@ -2,6 +2,31 @@ #include "package_info.h" +#define PKG_INFO_STRING(key_ptr, field) if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ + value_ptr += strlen(key_ptr);\ + tail_ptr = strchr(value_ptr, '\n');\ + tail_ptr[0] = '\0'; \ + pkg_info->field = strdup(value_ptr); \ + tail_ptr[0] = '\n'; \ +} value_ptr = tail_ptr; + +#define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr);\ + tail_ptr = strchr(value_ptr, '\n');\ + tail_ptr[0] = '\0'; \ + pkg_info->field = atoi(value_ptr); \ + tail_ptr[0] = '\n'; \ + value_ptr = tail_ptr; + +#define PKG_INFO_ARRAY(key_ptr, field) while((value_ptr = strstr(value_ptr, key_ptr)) != NULL){ \ + value_ptr = value_ptr + strlen(key_ptr);\ + tail_ptr = strchr(value_ptr, '\n'); \ + tail_ptr[0] = '\0'; \ + if(pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ + dynarray_add(pkg_info->field, value_ptr); \ + tail_ptr[0] = '\n'; \ + value_ptr = tail_ptr;\ +} value_ptr = tail_ptr; + PkgInfo *package_info_init() { return calloc(1, sizeof(PkgInfo)); } @@ -29,111 +54,26 @@ void package_info_free(PkgInfo *pkg_info) { free(pkg_info); } -/** - * Advance the pointer until all spaces are skipped. - */ -static inline char *trim_spaces_front(char *ptr) { - while (ptr[0] == ' ') { - ptr++; - } +void package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { + char *value_ptr = pkg_info_str, *tail_ptr; + + PKG_INFO_STRING("\npkgname = ", name); + PKG_INFO_STRING("\npkgbase = ", base); + PKG_INFO_STRING("\npkgver = ", version); + PKG_INFO_STRING("\npkgdesc = ", description); + PKG_INFO_STRING("\nurl = ", url); + PKG_INFO_INT("\nbuilddate = ", build_date); + PKG_INFO_STRING("\npackager = ", packager); + PKG_INFO_INT("\nsize = ", size); + PKG_INFO_STRING("\narch = ", arch); + PKG_INFO_ARRAY("\nlicense = ", licenses); + PKG_INFO_ARRAY("\nreplaces = ", replaces); + PKG_INFO_ARRAY("\ngroup = ", groups); + PKG_INFO_ARRAY("\nconflict = ", conflicts); + PKG_INFO_ARRAY("\nprovides = ", provides); + PKG_INFO_ARRAY("\ndepend = ", depends); + PKG_INFO_ARRAY("\noptdepend = ", optdepends); + PKG_INFO_ARRAY("\nmakedepend = ", makedepends); + PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends); - return ptr; -} - -/** - * Given a string pointer in the middle of a string, move over all spaces in the - * given direction. The final space is replaced with a NULL-byte. - */ -static inline void trim_spaces_back(char *ptr) { - if (ptr[0] != ' ') { - return; - } - - while (ptr[-1] == ' ') { - ptr--; - } - - ptr[0] = '\0'; -} - -#define PKG_INFO_STRING(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = strdup(value_ptr); goto advance; } -#define PKG_INFO_INT(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = atoi(value_ptr); goto advance; } -#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { \ - if (pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ - dynarray_add(pkg_info->field, value_ptr); goto advance; \ -} - -int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { - char *offset_ptr, *equals_ptr, *key_ptr, *value_ptr; - - bool end = false; - - // Iterate over all lines in file - while (!end) { - // This pointer will always point to the final character of the - // current line, be it the position of a newline or the NULL byte at - // the end of the entire string - offset_ptr = strchr(pkg_info_str, '\n'); - - // We replace the newline with a NULL byte. Now we know the line runs - // until the next NULL byte. - if (offset_ptr != NULL) { - offset_ptr[0] = '\0'; - } else { - // Advance pointer to the NULL byte of the string - offset_ptr = pkg_info_str + 1; - - while (*offset_ptr != '\0') { - offset_ptr++; - } - - end = true; - } - - // Skip comment lines - if (pkg_info_str[0] == '#') { - goto advance; - } - - equals_ptr = strchr(pkg_info_str, '='); - - // If a line doesn't contain an equals sign, the file is invalid - if (equals_ptr == NULL) { - return 1; - } - - // Trim whitespace from key - key_ptr = trim_spaces_front(pkg_info_str); - trim_spaces_back(equals_ptr - 1); - - // Trim spaces from value - value_ptr = trim_spaces_front(equals_ptr + 1); - trim_spaces_back(offset_ptr - 1); - - // Match key - PKG_INFO_STRING("pkgname", name); - PKG_INFO_STRING("pkgbase", base); - PKG_INFO_STRING("pkgver", version); - PKG_INFO_STRING("pkgdesc", description); - PKG_INFO_INT("size", size); - PKG_INFO_STRING("url", url); - PKG_INFO_STRING("arch", arch); - PKG_INFO_INT("builddate", build_date); - PKG_INFO_STRING("packager", packager); - PKG_INFO_STRING("pgpsig", pgpsig); - PKG_INFO_INT("pgpsigsize", pgpsigsize); - PKG_INFO_ARRAY("group", groups); - PKG_INFO_ARRAY("license", licenses); - PKG_INFO_ARRAY("replaces", replaces); - PKG_INFO_ARRAY("depend", depends); - PKG_INFO_ARRAY("optdepend", optdepends); - PKG_INFO_ARRAY("makedepend", makedepends); - PKG_INFO_ARRAY("checkdepend", checkdepends); - -advance: - pkg_info_str = offset_ptr + 1; - continue; - } - - return 0; } From edca243331d4a11f870edc904a20dd4579b39d87 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 17:17:18 +0100 Subject: [PATCH 52/74] refactor: Created function that will return the char ** (originally char *) that will be used to make the description file. Also removed free that was resulting in a crash. --- include/package.h | 2 +- src/package/package.c | 49 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/include/package.h b/include/package.h index 09e91bd..dfb3a34 100644 --- a/include/package.h +++ b/include/package.h @@ -21,6 +21,6 @@ typedef struct pkg { Pkg *package_read_archive(const char *pkg_path); void package_free(Pkg ** ptp); -char *package_to_description(Pkg *pkg); +char **package_to_description(Pkg *pkg); #endif diff --git a/src/package/package.c b/src/package/package.c index a098abb..3b9c6f9 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -1,5 +1,20 @@ #include "package.h" +#define BUFF_SIZE 128 + +#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ + snprintf(aux, BUFF_SIZE, section, pkg_info->field); \ + dynarray_add(description, aux); \ +} +#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ + snprintf(aux, BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ + dynarray_add(description, aux); \ + while (pkg_info->field->array[i] != NULL) { \ + snprintf(aux, BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ + dynarray_add(description, aux); \ + } \ +} + static char *ignored_names[5] = { ".BUILDINFO", ".INSTALL", @@ -7,7 +22,7 @@ static char *ignored_names[5] = { ".PKGINFO", ".CHANGELOG" }; -static int ignored_words_len = sizeof(ignored_names) / sizeof(char *); +static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *); Pkg *package_init() { return calloc(sizeof(PkgInfo), 1); @@ -38,6 +53,7 @@ Pkg *package_read_archive(const char *pkg_path) { PkgInfo *pkg_info; DynArray *files = dynarray_init(16); + dynarray_add(files, "%FILES%"); while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { path_name = archive_entry_pathname(entry); @@ -81,7 +97,6 @@ Pkg *package_read_archive(const char *pkg_path) { pkg_info->csize = stats.st_size; archive_read_free(a); - archive_entry_free(entry); // Create final return value Pkg *pkg = package_init(); @@ -93,6 +108,34 @@ Pkg *package_read_archive(const char *pkg_path) { return pkg; } -char *package_to_description(Pkg *pkg) { +char **package_to_description(Pkg *pkg) { + PkgInfo *pkg_info = pkg->info; + + DynArray *description = dynarray_init(16); + + char aux[BUFF_SIZE]; + int i; + ADD_STRING("\n\n%%NAME%%\n%s", name); + ADD_STRING("-%s", version); + ADD_STRING("\n\n%%PKGBASE%%\n%s", base); + ADD_STRING("\n\n%%DESCRIPTION%%\n%s", description); + ADD_STRING("\n\n%%SIZE%%\n%ld", size); + ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); + ADD_STRING("\n\n%%URL%%\n%s", url); + ADD_STRING("\n\n%%ARCH%%\n%s", arch); + ADD_STRING("\n\n%%BUILD_DATE%%\n%ld", build_date); + ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); + + ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); + ADD_ARRAY("\n\n%%LICENSES%%\n%s", licenses); + ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces); + ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); + ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts); + ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides); + ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends); + ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); + ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); + + return description; } From 01688fd5463e98ccae121e649e6851b2adea6180 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 17:24:03 +0100 Subject: [PATCH 53/74] fix: Took a very long time finding a very annyoing bug because realloc is the devil. --- include/dynarray.h | 5 +++++ src/package/dynarray.c | 11 +++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/dynarray.h b/include/dynarray.h index e552ec4..2ab4022 100644 --- a/include/dynarray.h +++ b/include/dynarray.h @@ -5,6 +5,11 @@ #include typedef struct dyn_array DynArray; +struct dyn_array { + char **array; + size_t capacity; + size_t size; +}; DynArray *dynarray_init(size_t initial_capacity); void dynarray_add(DynArray *da, const char * s); diff --git a/src/package/dynarray.c b/src/package/dynarray.c index 480c08f..a78e7ff 100644 --- a/src/package/dynarray.c +++ b/src/package/dynarray.c @@ -1,11 +1,5 @@ #include "dynarray.h" -struct dyn_array { - char **array; - size_t size; - size_t capacity; -}; - DynArray *dynarray_init(size_t initial_capacity) { DynArray *da = malloc(sizeof(DynArray)); da->size = 0; @@ -21,10 +15,11 @@ void dynarray_add(DynArray *da, const char *s) { } // Double array size if it's full else if (da->size == da->capacity) { - da->array = realloc(da->array, da->capacity * 2); + // if the realloc fails, access to memory in da->array is lost + da->array = realloc(da->array, sizeof(char*) * da->capacity * 2); da->capacity *= 2; } - + da->array[da->size] = strdup(s); da->size++; } From 7561a7479373993eb9606ba76afb30eb9e18756b Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 22:15:07 +0100 Subject: [PATCH 54/74] refactor: Decided to not return char** in function that creates the package description after all, now returns char*. The method I was trying started to irk me when I thought of creating a test unit for it. Also fixed some other issues I found in the package_to_description function (SHA256SUM section still missing). --- include/package.h | 2 +- src/package/package.c | 74 ++++++++++++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/include/package.h b/include/package.h index dfb3a34..09e91bd 100644 --- a/include/package.h +++ b/include/package.h @@ -21,6 +21,6 @@ typedef struct pkg { Pkg *package_read_archive(const char *pkg_path); void package_free(Pkg ** ptp); -char **package_to_description(Pkg *pkg); +char *package_to_description(Pkg *pkg); #endif diff --git a/src/package/package.c b/src/package/package.c index 3b9c6f9..bd77f3e 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -1,18 +1,30 @@ #include "package.h" -#define BUFF_SIZE 128 +#define SMALL_BUFF_SIZE 128 #define ADD_STRING(section, field) if (pkg_info->field != 0) { \ - snprintf(aux, BUFF_SIZE, section, pkg_info->field); \ - dynarray_add(description, aux); \ + snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ + if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ + description = realloc(description, buff_size * 2);\ + buff_size *= 2; \ + } \ + strcat(description, aux); \ } #define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ - snprintf(aux, BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ - dynarray_add(description, aux); \ - while (pkg_info->field->array[i] != NULL) { \ - snprintf(aux, BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ - dynarray_add(description, aux); \ - } \ + snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ + if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ + description = realloc(description, buff_size * 2);\ + buff_size *= 2; \ + } \ + strcat(description, aux); \ + while (pkg_info->field->array[i] != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ + if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ + description = realloc(description, buff_size * 2);\ + buff_size *= 2; \ + } \ + strcat(description, aux); \ + } \ } static char *ignored_names[5] = { @@ -109,33 +121,43 @@ Pkg *package_read_archive(const char *pkg_path) { } -char **package_to_description(Pkg *pkg) { +char *package_to_description(Pkg *pkg) { PkgInfo *pkg_info = pkg->info; - DynArray *description = dynarray_init(16); - - char aux[BUFF_SIZE]; + size_t buff_size = 1024; + char aux[SMALL_BUFF_SIZE]; + char *description = malloc(sizeof(char) * buff_size); int i; - ADD_STRING("\n\n%%NAME%%\n%s", name); - ADD_STRING("-%s", version); - ADD_STRING("\n\n%%PKGBASE%%\n%s", base); - ADD_STRING("\n\n%%DESCRIPTION%%\n%s", description); - ADD_STRING("\n\n%%SIZE%%\n%ld", size); - ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); - ADD_STRING("\n\n%%URL%%\n%s", url); - ADD_STRING("\n\n%%ARCH%%\n%s", arch); - ADD_STRING("\n\n%%BUILD_DATE%%\n%ld", build_date); - ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); + // special case for FILENAME + // assuming .pkg.tar.zst; other formats are valid, this should account for that + snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version, + pkg_info->arch); + strcat(description, aux); + + ADD_STRING("\n\n%%NAME%%\n%s", name); + ADD_STRING("\n\n%%BASE%%\n%s", base); + ADD_STRING("\n\n%%VERSION%%\n%s", version); + ADD_STRING("\n\n%%DESC%%\n%s", description); ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); - ADD_ARRAY("\n\n%%LICENSES%%\n%s", licenses); + ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); + ADD_STRING("\n\n%%ISIZE%%\n%ld", size); + //SHA256SUM + ADD_STRING("\n\n%%URL%%\n%s", url); + ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses); + ADD_STRING("\n\n%%ARCH%%\n%s", arch); + ADD_STRING("\n\n%%BUILDDATE%%\n%ld", build_date); + ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces); - ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts); ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides); + ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends); ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); - return description; + snprintf(aux, SMALL_BUFF_SIZE, "\n\n"); + strcat(description, aux); + + return description; } From 660e711b176f6053b6edf089c7d8c79af392b59e Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 23:10:53 +0100 Subject: [PATCH 55/74] refactor: Added SHA256 to package description file. --- src/package/package.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/package/package.c b/src/package/package.c index bd77f3e..932ac32 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -5,7 +5,7 @@ #define ADD_STRING(section, field) if (pkg_info->field != 0) { \ snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2);\ + description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ @@ -13,14 +13,14 @@ #define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2);\ + description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ while (pkg_info->field->array[i] != NULL) { \ snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2);\ + description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ @@ -120,6 +120,14 @@ Pkg *package_read_archive(const char *pkg_path) { return pkg; } +void sha256sum(Pkg *pkg, char *res) { + char command[SMALL_BUFF_SIZE]; + snprintf(command, SMALL_BUFF_SIZE, "sha256sum %s", pkg->path); + FILE *p = popen(command, "r"); + + fgets(res, 65, p); + pclose(p); +} char *package_to_description(Pkg *pkg) { PkgInfo *pkg_info = pkg->info; @@ -142,7 +150,16 @@ char *package_to_description(Pkg *pkg) { ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); ADD_STRING("\n\n%%ISIZE%%\n%ld", size); - //SHA256SUM + + char res[65]; + sha256sum(pkg, res); + snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", res); + if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { + description = realloc(description, buff_size * 2); + buff_size *= 2; + } + strcat(description, aux); + ADD_STRING("\n\n%%URL%%\n%s", url); ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses); ADD_STRING("\n\n%%ARCH%%\n%s", arch); From fbbc15cf731ddfdc90a8c63af98e40bc1a293d4e Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Fri, 27 Jan 2023 22:23:23 +0000 Subject: [PATCH 56/74] chore: Rebase to dev branch with binomial heap PR. --- Makefile | 4 + src/package/package.c | 6 +- test/package/.PKGINFO | 22 ++ test/package/desc | 45 ++++ test/package/files | 243 ++++++++++++++++++ test/package/test_package.c | 86 +++++++ .../xcursor-dmz-0.4.5-2-any.pkg.tar.zst | Bin 0 -> 328282 bytes 7 files changed, 403 insertions(+), 3 deletions(-) create mode 100644 test/package/.PKGINFO create mode 100644 test/package/desc create mode 100644 test/package/files create mode 100644 test/package/test_package.c create mode 100644 test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst diff --git a/Makefile b/Makefile index fadf89d..d7d4ca4 100644 --- a/Makefile +++ b/Makefile @@ -72,6 +72,10 @@ build-test: $(BINS_TEST) $(BINS_TEST): %: %.c.o $(LIB) $(CC) \ $^ -o $@ +======= +$(BINS_TEST): %: %.c.o $(OBJS) + $(CC) $^ -larchive -o $@ +>>>>>>> c94ab92 (refactor: Add libarchive link to test compilation area of the Makefile. Created test units with xcursor-dmz as test package.) # Along with the include directory, each test includes $(TEST_DIR) (which # contains the acutest.h header file), and the src directory of the module it's diff --git a/src/package/package.c b/src/package/package.c index 932ac32..8d1565d 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -151,9 +151,9 @@ char *package_to_description(Pkg *pkg) { ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); ADD_STRING("\n\n%%ISIZE%%\n%ld", size); - char res[65]; - sha256sum(pkg, res); - snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", res); + char checksum[65]; + sha256sum(pkg, checksum); + snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum); if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { description = realloc(description, buff_size * 2); buff_size *= 2; diff --git a/test/package/.PKGINFO b/test/package/.PKGINFO new file mode 100644 index 0000000..7113061 --- /dev/null +++ b/test/package/.PKGINFO @@ -0,0 +1,22 @@ +# Generated by makepkg 6.0.2 +# using fakeroot version 1.30.1 +pkgname = xcursor-dmz +pkgbase = xcursor-dmz +pkgver = 0.4.5-2 +pkgdesc = Style neutral, scalable cursor theme +url = https://packages.debian.org/sid/dmz-cursor-theme +builddate = 1673751613 +packager = Unknown Packager +size = 3469584 +arch = any +license = MIT +replaces = test1 +group = x11 +conflict = test2 +conflict = test3 +provides = test4 +depend = test5 +depend = test6 +optdepend = test7 +makedepend = xorg-xcursorgen +checkdepend = test8 diff --git a/test/package/desc b/test/package/desc new file mode 100644 index 0000000..d583af1 --- /dev/null +++ b/test/package/desc @@ -0,0 +1,45 @@ +%FILENAME% +xcursor-dmz-0.4.5-2-any.pkg.tar.zst + +%NAME% +xcursor-dmz + +%BASE% +xcursor-dmz + +%VERSION% +0.4.5-2 + +%DESC% +Style neutral, scalable cursor theme + +%GROUPS% +x11 + +%CSIZE% +328282 + +%ISIZE% +3469584 + +%SHA256SUM% +4f4bce9e975334ed7775ff4ddf4d2e82e411d599802f6179a122f89149f53bfb + +%URL% +https://packages.debian.org/sid/dmz-cursor-theme + +%LICENSE% +MIT + +%ARCH% +any + +%BUILDDATE% +1673751613 + +%PACKAGER% +Unknown Packager + +%MAKEDEPENDS% +xorg-xcursorgen + diff --git a/test/package/files b/test/package/files new file mode 100644 index 0000000..aab44b1 --- /dev/null +++ b/test/package/files @@ -0,0 +1,243 @@ +%FILES% +usr/ +usr/share/ +usr/share/icons/ +usr/share/icons/DMZ-Black/ +usr/share/icons/DMZ-Black/cursor.theme +usr/share/icons/DMZ-Black/cursors/ +usr/share/icons/DMZ-Black/cursors/00008160000006810000408080010102 +usr/share/icons/DMZ-Black/cursors/028006030e0e7ebffc7f7070c0600140 +usr/share/icons/DMZ-Black/cursors/03b6e0fcb3499374a867c041f52298f0 +usr/share/icons/DMZ-Black/cursors/08e8e1c95fe2fc01f976f1e063a24ccd +usr/share/icons/DMZ-Black/cursors/1081e37283d90000800003c07f3ef6bf +usr/share/icons/DMZ-Black/cursors/14fef782d02440884392942c11205230 +usr/share/icons/DMZ-Black/cursors/2870a09082c103050810ffdffffe0204 +usr/share/icons/DMZ-Black/cursors/3085a0e285430894940527032f8b26df +usr/share/icons/DMZ-Black/cursors/3ecb610c1bf2410f44200f48c40d3599 +usr/share/icons/DMZ-Black/cursors/4498f0e0c1937ffe01fd06f973665830 +usr/share/icons/DMZ-Black/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408 +usr/share/icons/DMZ-Black/cursors/6407b0e94181790501fd1e167b474872 +usr/share/icons/DMZ-Black/cursors/640fb0e74195791501fd1ed57b41487f +usr/share/icons/DMZ-Black/cursors/9081237383d90e509aa00f00170e968f +usr/share/icons/DMZ-Black/cursors/9d800788f1b08800ae810202380a0822 +usr/share/icons/DMZ-Black/cursors/X_cursor +usr/share/icons/DMZ-Black/cursors/alias +usr/share/icons/DMZ-Black/cursors/arrow +usr/share/icons/DMZ-Black/cursors/bd_double_arrow +usr/share/icons/DMZ-Black/cursors/bottom_left_corner +usr/share/icons/DMZ-Black/cursors/bottom_right_corner +usr/share/icons/DMZ-Black/cursors/bottom_side +usr/share/icons/DMZ-Black/cursors/bottom_tee +usr/share/icons/DMZ-Black/cursors/c7088f0f3e6c8088236ef8e1e3e70000 +usr/share/icons/DMZ-Black/cursors/circle +usr/share/icons/DMZ-Black/cursors/col-resize +usr/share/icons/DMZ-Black/cursors/color-picker +usr/share/icons/DMZ-Black/cursors/copy +usr/share/icons/DMZ-Black/cursors/cross +usr/share/icons/DMZ-Black/cursors/cross_reverse +usr/share/icons/DMZ-Black/cursors/crossed_circle +usr/share/icons/DMZ-Black/cursors/crosshair +usr/share/icons/DMZ-Black/cursors/d9ce0ab605698f320427677b458ad60b +usr/share/icons/DMZ-Black/cursors/default +usr/share/icons/DMZ-Black/cursors/diamond_cross +usr/share/icons/DMZ-Black/cursors/dnd-ask +usr/share/icons/DMZ-Black/cursors/dnd-copy +usr/share/icons/DMZ-Black/cursors/dnd-link +usr/share/icons/DMZ-Black/cursors/dnd-move +usr/share/icons/DMZ-Black/cursors/dnd-none +usr/share/icons/DMZ-Black/cursors/dot_box_mask +usr/share/icons/DMZ-Black/cursors/dotbox +usr/share/icons/DMZ-Black/cursors/double_arrow +usr/share/icons/DMZ-Black/cursors/draft_large +usr/share/icons/DMZ-Black/cursors/draft_small +usr/share/icons/DMZ-Black/cursors/draped_box +usr/share/icons/DMZ-Black/cursors/e-resize +usr/share/icons/DMZ-Black/cursors/e29285e634086352946a0e7090d73106 +usr/share/icons/DMZ-Black/cursors/ew-resize +usr/share/icons/DMZ-Black/cursors/fcf1c3c7cd4491d801f1e1c78f100000 +usr/share/icons/DMZ-Black/cursors/fd_double_arrow +usr/share/icons/DMZ-Black/cursors/fleur +usr/share/icons/DMZ-Black/cursors/grab +usr/share/icons/DMZ-Black/cursors/grabbing +usr/share/icons/DMZ-Black/cursors/h_double_arrow +usr/share/icons/DMZ-Black/cursors/hand +usr/share/icons/DMZ-Black/cursors/hand1 +usr/share/icons/DMZ-Black/cursors/hand2 +usr/share/icons/DMZ-Black/cursors/help +usr/share/icons/DMZ-Black/cursors/icon +usr/share/icons/DMZ-Black/cursors/left_ptr +usr/share/icons/DMZ-Black/cursors/left_ptr_help +usr/share/icons/DMZ-Black/cursors/left_ptr_watch +usr/share/icons/DMZ-Black/cursors/left_side +usr/share/icons/DMZ-Black/cursors/left_tee +usr/share/icons/DMZ-Black/cursors/link +usr/share/icons/DMZ-Black/cursors/ll_angle +usr/share/icons/DMZ-Black/cursors/lr_angle +usr/share/icons/DMZ-Black/cursors/move +usr/share/icons/DMZ-Black/cursors/n-resize +usr/share/icons/DMZ-Black/cursors/ne-resize +usr/share/icons/DMZ-Black/cursors/nesw-resize +usr/share/icons/DMZ-Black/cursors/not-allowed +usr/share/icons/DMZ-Black/cursors/ns-resize +usr/share/icons/DMZ-Black/cursors/nw-resize +usr/share/icons/DMZ-Black/cursors/nwse-resize +usr/share/icons/DMZ-Black/cursors/openhand +usr/share/icons/DMZ-Black/cursors/pencil +usr/share/icons/DMZ-Black/cursors/pirate +usr/share/icons/DMZ-Black/cursors/plus +usr/share/icons/DMZ-Black/cursors/pointer +usr/share/icons/DMZ-Black/cursors/progress +usr/share/icons/DMZ-Black/cursors/question_arrow +usr/share/icons/DMZ-Black/cursors/right_ptr +usr/share/icons/DMZ-Black/cursors/right_side +usr/share/icons/DMZ-Black/cursors/right_tee +usr/share/icons/DMZ-Black/cursors/row-resize +usr/share/icons/DMZ-Black/cursors/s-resize +usr/share/icons/DMZ-Black/cursors/sb_down_arrow +usr/share/icons/DMZ-Black/cursors/sb_h_double_arrow +usr/share/icons/DMZ-Black/cursors/sb_left_arrow +usr/share/icons/DMZ-Black/cursors/sb_right_arrow +usr/share/icons/DMZ-Black/cursors/sb_up_arrow +usr/share/icons/DMZ-Black/cursors/sb_v_double_arrow +usr/share/icons/DMZ-Black/cursors/se-resize +usr/share/icons/DMZ-Black/cursors/size_bdiag +usr/share/icons/DMZ-Black/cursors/size_fdiag +usr/share/icons/DMZ-Black/cursors/size_hor +usr/share/icons/DMZ-Black/cursors/size_ver +usr/share/icons/DMZ-Black/cursors/sw-resize +usr/share/icons/DMZ-Black/cursors/target +usr/share/icons/DMZ-Black/cursors/tcross +usr/share/icons/DMZ-Black/cursors/text +usr/share/icons/DMZ-Black/cursors/top_left_arrow +usr/share/icons/DMZ-Black/cursors/top_left_corner +usr/share/icons/DMZ-Black/cursors/top_right_corner +usr/share/icons/DMZ-Black/cursors/top_side +usr/share/icons/DMZ-Black/cursors/top_tee +usr/share/icons/DMZ-Black/cursors/ul_angle +usr/share/icons/DMZ-Black/cursors/ur_angle +usr/share/icons/DMZ-Black/cursors/v_double_arrow +usr/share/icons/DMZ-Black/cursors/w-resize +usr/share/icons/DMZ-Black/cursors/wait +usr/share/icons/DMZ-Black/cursors/watch +usr/share/icons/DMZ-Black/cursors/xterm +usr/share/icons/DMZ-White/ +usr/share/icons/DMZ-White/cursor.theme +usr/share/icons/DMZ-White/cursors/ +usr/share/icons/DMZ-White/cursors/00008160000006810000408080010102 +usr/share/icons/DMZ-White/cursors/028006030e0e7ebffc7f7070c0600140 +usr/share/icons/DMZ-White/cursors/03b6e0fcb3499374a867c041f52298f0 +usr/share/icons/DMZ-White/cursors/08e8e1c95fe2fc01f976f1e063a24ccd +usr/share/icons/DMZ-White/cursors/1081e37283d90000800003c07f3ef6bf +usr/share/icons/DMZ-White/cursors/14fef782d02440884392942c11205230 +usr/share/icons/DMZ-White/cursors/2870a09082c103050810ffdffffe0204 +usr/share/icons/DMZ-White/cursors/3085a0e285430894940527032f8b26df +usr/share/icons/DMZ-White/cursors/3ecb610c1bf2410f44200f48c40d3599 +usr/share/icons/DMZ-White/cursors/4498f0e0c1937ffe01fd06f973665830 +usr/share/icons/DMZ-White/cursors/5c6cd98b3f3ebcb1f9c7f1c204630408 +usr/share/icons/DMZ-White/cursors/6407b0e94181790501fd1e167b474872 +usr/share/icons/DMZ-White/cursors/640fb0e74195791501fd1ed57b41487f +usr/share/icons/DMZ-White/cursors/9081237383d90e509aa00f00170e968f +usr/share/icons/DMZ-White/cursors/9d800788f1b08800ae810202380a0822 +usr/share/icons/DMZ-White/cursors/X_cursor +usr/share/icons/DMZ-White/cursors/alias +usr/share/icons/DMZ-White/cursors/arrow +usr/share/icons/DMZ-White/cursors/bd_double_arrow +usr/share/icons/DMZ-White/cursors/bottom_left_corner +usr/share/icons/DMZ-White/cursors/bottom_right_corner +usr/share/icons/DMZ-White/cursors/bottom_side +usr/share/icons/DMZ-White/cursors/bottom_tee +usr/share/icons/DMZ-White/cursors/c7088f0f3e6c8088236ef8e1e3e70000 +usr/share/icons/DMZ-White/cursors/circle +usr/share/icons/DMZ-White/cursors/col-resize +usr/share/icons/DMZ-White/cursors/color-picker +usr/share/icons/DMZ-White/cursors/copy +usr/share/icons/DMZ-White/cursors/cross +usr/share/icons/DMZ-White/cursors/cross_reverse +usr/share/icons/DMZ-White/cursors/crossed_circle +usr/share/icons/DMZ-White/cursors/crosshair +usr/share/icons/DMZ-White/cursors/d9ce0ab605698f320427677b458ad60b +usr/share/icons/DMZ-White/cursors/default +usr/share/icons/DMZ-White/cursors/diamond_cross +usr/share/icons/DMZ-White/cursors/dnd-ask +usr/share/icons/DMZ-White/cursors/dnd-copy +usr/share/icons/DMZ-White/cursors/dnd-link +usr/share/icons/DMZ-White/cursors/dnd-move +usr/share/icons/DMZ-White/cursors/dnd-none +usr/share/icons/DMZ-White/cursors/dot_box_mask +usr/share/icons/DMZ-White/cursors/dotbox +usr/share/icons/DMZ-White/cursors/double_arrow +usr/share/icons/DMZ-White/cursors/draft_large +usr/share/icons/DMZ-White/cursors/draft_small +usr/share/icons/DMZ-White/cursors/draped_box +usr/share/icons/DMZ-White/cursors/e-resize +usr/share/icons/DMZ-White/cursors/e29285e634086352946a0e7090d73106 +usr/share/icons/DMZ-White/cursors/ew-resize +usr/share/icons/DMZ-White/cursors/fcf1c3c7cd4491d801f1e1c78f100000 +usr/share/icons/DMZ-White/cursors/fd_double_arrow +usr/share/icons/DMZ-White/cursors/fleur +usr/share/icons/DMZ-White/cursors/grab +usr/share/icons/DMZ-White/cursors/grabbing +usr/share/icons/DMZ-White/cursors/h_double_arrow +usr/share/icons/DMZ-White/cursors/hand +usr/share/icons/DMZ-White/cursors/hand1 +usr/share/icons/DMZ-White/cursors/hand2 +usr/share/icons/DMZ-White/cursors/help +usr/share/icons/DMZ-White/cursors/icon +usr/share/icons/DMZ-White/cursors/left_ptr +usr/share/icons/DMZ-White/cursors/left_ptr_help +usr/share/icons/DMZ-White/cursors/left_ptr_watch +usr/share/icons/DMZ-White/cursors/left_side +usr/share/icons/DMZ-White/cursors/left_tee +usr/share/icons/DMZ-White/cursors/link +usr/share/icons/DMZ-White/cursors/ll_angle +usr/share/icons/DMZ-White/cursors/lr_angle +usr/share/icons/DMZ-White/cursors/move +usr/share/icons/DMZ-White/cursors/n-resize +usr/share/icons/DMZ-White/cursors/ne-resize +usr/share/icons/DMZ-White/cursors/nesw-resize +usr/share/icons/DMZ-White/cursors/not-allowed +usr/share/icons/DMZ-White/cursors/ns-resize +usr/share/icons/DMZ-White/cursors/nw-resize +usr/share/icons/DMZ-White/cursors/nwse-resize +usr/share/icons/DMZ-White/cursors/openhand +usr/share/icons/DMZ-White/cursors/pencil +usr/share/icons/DMZ-White/cursors/pirate +usr/share/icons/DMZ-White/cursors/plus +usr/share/icons/DMZ-White/cursors/pointer +usr/share/icons/DMZ-White/cursors/progress +usr/share/icons/DMZ-White/cursors/question_arrow +usr/share/icons/DMZ-White/cursors/right_ptr +usr/share/icons/DMZ-White/cursors/right_side +usr/share/icons/DMZ-White/cursors/right_tee +usr/share/icons/DMZ-White/cursors/row-resize +usr/share/icons/DMZ-White/cursors/s-resize +usr/share/icons/DMZ-White/cursors/sb_down_arrow +usr/share/icons/DMZ-White/cursors/sb_h_double_arrow +usr/share/icons/DMZ-White/cursors/sb_left_arrow +usr/share/icons/DMZ-White/cursors/sb_right_arrow +usr/share/icons/DMZ-White/cursors/sb_up_arrow +usr/share/icons/DMZ-White/cursors/sb_v_double_arrow +usr/share/icons/DMZ-White/cursors/se-resize +usr/share/icons/DMZ-White/cursors/size_bdiag +usr/share/icons/DMZ-White/cursors/size_fdiag +usr/share/icons/DMZ-White/cursors/size_hor +usr/share/icons/DMZ-White/cursors/size_ver +usr/share/icons/DMZ-White/cursors/sw-resize +usr/share/icons/DMZ-White/cursors/target +usr/share/icons/DMZ-White/cursors/tcross +usr/share/icons/DMZ-White/cursors/text +usr/share/icons/DMZ-White/cursors/top_left_arrow +usr/share/icons/DMZ-White/cursors/top_left_corner +usr/share/icons/DMZ-White/cursors/top_right_corner +usr/share/icons/DMZ-White/cursors/top_side +usr/share/icons/DMZ-White/cursors/top_tee +usr/share/icons/DMZ-White/cursors/ul_angle +usr/share/icons/DMZ-White/cursors/ur_angle +usr/share/icons/DMZ-White/cursors/v_double_arrow +usr/share/icons/DMZ-White/cursors/w-resize +usr/share/icons/DMZ-White/cursors/wait +usr/share/icons/DMZ-White/cursors/watch +usr/share/icons/DMZ-White/cursors/xterm +usr/share/licenses/ +usr/share/licenses/xcursor-dmz/ +usr/share/licenses/xcursor-dmz/LICENSE diff --git a/test/package/test_package.c b/test/package/test_package.c new file mode 100644 index 0000000..43911a8 --- /dev/null +++ b/test/package/test_package.c @@ -0,0 +1,86 @@ +#include "acutest.h" +#include "package.h" + +void test_pkg_info_parse() { + FILE *f = fopen("./test/package/.PKGINFO", "r"); + TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package "); + fseek(f, 0L, SEEK_END); + size_t size = ftell(f); + fflush(stdout); + rewind(f); + char *pkg_info_str = malloc(size); + fread(pkg_info_str, 1, size, f); + fclose(f); + PkgInfo *pkg_info = package_info_init(); + package_info_parse(pkg_info, pkg_info_str); + + TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); + TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); + TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); + TEST_CHECK(pkg_info->build_date == 1673751613); + TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); + TEST_CHECK(pkg_info->size == 3469584); + TEST_CHECK(!strcmp(pkg_info->arch, "any")); + + TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); + TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); + TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); + TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); + TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); + TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); + TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); + TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); + TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); + +} + +void test_pkg_read_archive_files() { + Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + + FILE *f = fopen("./test/package/files", "r"); + TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); + char *buff = malloc(sizeof(char) * 128); + size_t i = 0; + + while ((fgets(buff, 128, f)) != NULL || i < pkg->files->size) { + if (buff[strlen(buff) - 1] == '\n') { + buff[strlen(buff) - 1] = '\0'; + } + + TEST_CHECK_(!strcmp(pkg->files->array[i], buff), "%s != %s", pkg->files->array[i], buff); + i++; + } + TEST_CHECK(pkg->compression = 14); + +} + +void test_pkg_read_archive_desc() { + Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + + char *description = package_to_description(pkg); + + FILE *f = fopen("./test/package/desc", "r"); + TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package"); + fseek(f, 0, SEEK_END); + size_t size = ftell(f); + rewind(f); + char *desc = malloc(size); + fread(desc, 1, size, f); + fclose(f); + + TEST_CHECK(!strcmp(description, desc)); + +} + +TEST_LIST = { + {"pkg_info_valid_parse", test_pkg_info_parse}, + {"pkg_read_archive_files", test_pkg_read_archive_files}, + {"pkg_read_archive_desc", test_pkg_read_archive_desc}, + {NULL, NULL} +}; diff --git a/test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst b/test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst new file mode 100644 index 0000000000000000000000000000000000000000..a878047ad426e5e3f5d211967ed9fdf950051de5 GIT binary patch literal 328282 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

rfEN4S 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%0AX3PJ)XAv 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

g2c$|h8?TE+9iC)Tdxl*KPH+Aw&jWHyv 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

D7nMvY$U) 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�rz|2hY>Qy8PRwmF(ef|7^EDWIX1ClJ38_bdL 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 NV8C6xC literal 0 HcmV?d00001 From d0914adbb545652ef24e54023af3c3c3247b8dcb Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Wed, 25 Jan 2023 23:55:04 +0100 Subject: [PATCH 57/74] fix: Somehow, test file changed line endings to CRLF. Changed it back to LF. --- test/package/test_package.c | 170 ++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 86 deletions(-) diff --git a/test/package/test_package.c b/test/package/test_package.c index 43911a8..c0c7085 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -1,86 +1,84 @@ -#include "acutest.h" -#include "package.h" - -void test_pkg_info_parse() { - FILE *f = fopen("./test/package/.PKGINFO", "r"); - TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package "); - fseek(f, 0L, SEEK_END); - size_t size = ftell(f); - fflush(stdout); - rewind(f); - char *pkg_info_str = malloc(size); - fread(pkg_info_str, 1, size, f); - fclose(f); - PkgInfo *pkg_info = package_info_init(); - package_info_parse(pkg_info, pkg_info_str); - - TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); - TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); - TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); - TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); - TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); - TEST_CHECK(pkg_info->build_date == 1673751613); - TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); - TEST_CHECK(pkg_info->size == 3469584); - TEST_CHECK(!strcmp(pkg_info->arch, "any")); - - TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); - TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); - TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); - TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); - TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); - TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); - TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); - TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); - TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); - TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); - TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); - -} - -void test_pkg_read_archive_files() { - Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); - TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); - - FILE *f = fopen("./test/package/files", "r"); - TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); - char *buff = malloc(sizeof(char) * 128); - size_t i = 0; - - while ((fgets(buff, 128, f)) != NULL || i < pkg->files->size) { - if (buff[strlen(buff) - 1] == '\n') { - buff[strlen(buff) - 1] = '\0'; - } - - TEST_CHECK_(!strcmp(pkg->files->array[i], buff), "%s != %s", pkg->files->array[i], buff); - i++; - } - TEST_CHECK(pkg->compression = 14); - -} - -void test_pkg_read_archive_desc() { - Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); - TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); - - char *description = package_to_description(pkg); - - FILE *f = fopen("./test/package/desc", "r"); - TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package"); - fseek(f, 0, SEEK_END); - size_t size = ftell(f); - rewind(f); - char *desc = malloc(size); - fread(desc, 1, size, f); - fclose(f); - - TEST_CHECK(!strcmp(description, desc)); - -} - -TEST_LIST = { - {"pkg_info_valid_parse", test_pkg_info_parse}, - {"pkg_read_archive_files", test_pkg_read_archive_files}, - {"pkg_read_archive_desc", test_pkg_read_archive_desc}, - {NULL, NULL} -}; +#include "acutest.h" +#include "package.h" + +void test_pkg_info_parse() { + FILE *f = fopen("./test/package/.PKGINFO", "r"); + TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package "); + fseek(f, 0L, SEEK_END); + size_t size = ftell(f); + fflush(stdout); + rewind(f); + char *pkg_info_str = malloc(size); + fread(pkg_info_str, 1, size, f); + fclose(f); + PkgInfo *pkg_info = package_info_init(); + package_info_parse(pkg_info, pkg_info_str); + + TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); + TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); + TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); + TEST_CHECK(pkg_info->build_date == 1673751613); + TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); + TEST_CHECK(pkg_info->size == 3469584); + TEST_CHECK(!strcmp(pkg_info->arch, "any")); + + TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); + TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); + TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); + TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); + TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); + TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); + TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); + TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); + TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); +} + +void test_pkg_read_archive_files() { + Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + + FILE *f = fopen("./test/package/files", "r"); + TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); + char buff[128]; + size_t i = 0; + + while ((fgets(buff, 128, f)) != NULL || i < pkg->files->size) { + if (buff[strlen(buff) - 1] == '\n') { + buff[strlen(buff) - 1] = '\0'; + } + + TEST_CHECK_(!strcmp(pkg->files->array[i], buff), "%s != %s", pkg->files->array[i], buff); + i++; + } + TEST_CHECK(pkg->compression = 14); + +} + +void test_pkg_read_archive_desc() { + Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + + char *description = package_to_description(pkg); + + FILE *f = fopen("./test/package/desc", "r"); + TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package"); + fseek(f, 0, SEEK_END); + size_t size = ftell(f); + rewind(f); + char *desc = malloc(size); + fread(desc, 1, size, f); + fclose(f); + + TEST_CHECK(!strcmp(description, desc)); +} + +TEST_LIST = { + {"pkg_info_valid_parse", test_pkg_info_parse}, + {"pkg_read_archive_files", test_pkg_read_archive_files}, + {"pkg_read_archive_desc", test_pkg_read_archive_desc}, + {NULL, NULL} +}; From d11a9d3638a2641cfeda04e45892a09718c66cfb Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 28 Jan 2023 09:58:32 +0100 Subject: [PATCH 58/74] chore: fix merge marker in makefile --- Makefile | 7 ++----- README.md | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d7d4ca4..84c9b52 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ BINS_TEST := $(OBJS_TEST:%.c.o=%) TARGETS_TEST := $(BINS_TEST:%=test-%) TARGETS_MEM_TEST := $(BINS_TEST:%=test-mem-%) +LIBFLAGS := -larchive INC_FLAGS := $(addprefix -I,$(INC_DIRS)) # -MMD: generate a .d file for every source file. This file can be imported by @@ -71,11 +72,7 @@ build-test: $(BINS_TEST) $(BINS_TEST): %: %.c.o $(LIB) $(CC) \ - $^ -o $@ -======= -$(BINS_TEST): %: %.c.o $(OBJS) - $(CC) $^ -larchive -o $@ ->>>>>>> c94ab92 (refactor: Add libarchive link to test compilation area of the Makefile. Created test units with xcursor-dmz as test package.) + $^ $(LIBFLAGS) -o $@ # Along with the include directory, each test includes $(TEST_DIR) (which # contains the acutest.h header file), and the src directory of the module it's diff --git a/README.md b/README.md index abc250a..408f760 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,10 @@ See the [source code](src) for the list of modules. Everything is handled by the provided Makefile. To compile the static library, simply run `make`. +### Required libraries + +Libvieter requires libarchive. + ### Project structure Each module has its own subdirectory inside `src`, e.g. `src/cron`. This From bbdc2fbd6e82b7de6ada5dff2b1f80e1832a367d Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sat, 28 Jan 2023 09:57:38 +0000 Subject: [PATCH 59/74] fix: strcat can not be used on uninitialised strings in non-musl environments. --- src/package/package.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package/package.c b/src/package/package.c index 8d1565d..f5f4ee5 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -141,7 +141,7 @@ char *package_to_description(Pkg *pkg) { // assuming .pkg.tar.zst; other formats are valid, this should account for that snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version, pkg_info->arch); - strcat(description, aux); + strcpy(description, aux); ADD_STRING("\n\n%%NAME%%\n%s", name); ADD_STRING("\n\n%%BASE%%\n%s", base); From 1ccd4101af6c60648d493fff592a7d50f703ef6b Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sat, 28 Jan 2023 22:01:00 +0000 Subject: [PATCH 60/74] refactor: Subsituted old hash generation with a proper implementation. --- include/package.h | 4 +- include/sha256.h | 34 +++++++++ src/package/package.c | 52 ++++++++++++-- src/package/sha256.c | 158 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 241 insertions(+), 7 deletions(-) create mode 100644 include/sha256.h create mode 100644 src/package/sha256.c diff --git a/include/package.h b/include/package.h index 09e91bd..0360a6a 100644 --- a/include/package.h +++ b/include/package.h @@ -6,8 +6,8 @@ #include #include -#include "archive.h" -#include "archive_entry.h" +#include +#include #include "package_info.h" #include "dynarray.h" diff --git a/include/sha256.h b/include/sha256.h new file mode 100644 index 0000000..7123a30 --- /dev/null +++ b/include/sha256.h @@ -0,0 +1,34 @@ +/********************************************************************* +* Filename: sha256.h +* Author: Brad Conte (brad AT bradconte.com) +* Copyright: +* Disclaimer: This code is presented "as is" without any guarantees. +* Details: Defines the API for the corresponding SHA1 implementation. +*********************************************************************/ + +#ifndef SHA256_H +#define SHA256_H + +/*************************** HEADER FILES ***************************/ +#include + +/****************************** MACROS ******************************/ +#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest + +/**************************** DATA TYPES ****************************/ +typedef unsigned char BYTE; // 8-bit byte +typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines + +typedef struct { + BYTE data[64]; + WORD datalen; + unsigned long long bitlen; + WORD state[8]; +} SHA256_CTX; + +/*********************** FUNCTION DECLARATIONS **********************/ +void sha256_init(SHA256_CTX *ctx); +void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len); +void sha256_final(SHA256_CTX *ctx, BYTE hash[]); + +#endif // SHA256_H diff --git a/src/package/package.c b/src/package/package.c index f5f4ee5..577e3c9 100644 --- a/src/package/package.c +++ b/src/package/package.c @@ -1,4 +1,5 @@ #include "package.h" +#include "sha256.h" #define SMALL_BUFF_SIZE 128 @@ -121,12 +122,52 @@ Pkg *package_read_archive(const char *pkg_path) { } void sha256sum(Pkg *pkg, char *res) { - char command[SMALL_BUFF_SIZE]; - snprintf(command, SMALL_BUFF_SIZE, "sha256sum %s", pkg->path); - FILE *p = popen(command, "r"); + FILE *f = fopen(pkg->path, "r"); + fseek(f, 0, SEEK_END); + size_t size = ftell(f); + rewind(f); + unsigned char *in = malloc(size); + fread(in, 1, size, f); + fclose(f); - fgets(res, 65, p); - pclose(p); + unsigned char hash[32]; + SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); + + sha256_init(ctx); + sha256_update(ctx, in, size); + sha256_final(ctx, hash); + + free(in); + free(ctx); + + // We need to convert the bytes in the hash to get a string representation of its hex values + // i.e. turn 1001 1111 into the string "9f" + // Each byte of the hash is going to turn into two bytes in the final string + // so we are going to convert each half byte into a char + unsigned int half_byte = 0; + int j = 0; + + // We advance in the string 2 bytes for every one byte of the hash + for (int i = 0; i < 32; i++) { + // We transform the first half byte into the second character to keep + // each byte from becoming reversed in the final string + half_byte = hash[i] & 0b1111; + if (half_byte < 10) { + res[j+1] = half_byte + 48; + } else { + res[j+1] = half_byte + 87; + } + hash[i] = hash[i] >> 4; + half_byte = hash[i] & 0b1111; + if (half_byte < 10) { + res[j] = half_byte + 48; + } else { + res[j] = half_byte + 87; + } + + j += 2; + } + res[j] = '\0'; } char *package_to_description(Pkg *pkg) { @@ -153,6 +194,7 @@ char *package_to_description(Pkg *pkg) { char checksum[65]; sha256sum(pkg, checksum); + snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum); if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { description = realloc(description, buff_size * 2); diff --git a/src/package/sha256.c b/src/package/sha256.c new file mode 100644 index 0000000..eb9c5c0 --- /dev/null +++ b/src/package/sha256.c @@ -0,0 +1,158 @@ +/********************************************************************* +* Filename: sha256.c +* Author: Brad Conte (brad AT bradconte.com) +* Copyright: +* Disclaimer: This code is presented "as is" without any guarantees. +* Details: Implementation of the SHA-256 hashing algorithm. + SHA-256 is one of the three algorithms in the SHA2 + specification. The others, SHA-384 and SHA-512, are not + offered in this implementation. + Algorithm specification can be found here: + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf + This implementation uses little endian byte order. +*********************************************************************/ + +/*************************** HEADER FILES ***************************/ +#include +#include +#include "sha256.h" + +/****************************** MACROS ******************************/ +#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) +#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) + +#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) +#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) +#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) +#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) + +/**************************** VARIABLES *****************************/ +static const WORD k[64] = { + 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, + 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, + 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, + 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +}; + +/*********************** FUNCTION DEFINITIONS ***********************/ +void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) +{ + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for ( ; i < 64; ++i) + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; + t2 = EP0(a) + MAJ(a,b,c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + ctx->state[3] += d; + ctx->state[4] += e; + ctx->state[5] += f; + ctx->state[6] += g; + ctx->state[7] += h; +} + +void sha256_init(SHA256_CTX *ctx) +{ + ctx->datalen = 0; + ctx->bitlen = 0; + ctx->state[0] = 0x6a09e667; + ctx->state[1] = 0xbb67ae85; + ctx->state[2] = 0x3c6ef372; + ctx->state[3] = 0xa54ff53a; + ctx->state[4] = 0x510e527f; + ctx->state[5] = 0x9b05688c; + ctx->state[6] = 0x1f83d9ab; + ctx->state[7] = 0x5be0cd19; +} + +void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) +{ + WORD i; + + for (i = 0; i < len; ++i) { + ctx->data[ctx->datalen] = data[i]; + ctx->datalen++; + if (ctx->datalen == 64) { + sha256_transform(ctx, ctx->data); + ctx->bitlen += 512; + ctx->datalen = 0; + } + } +} + +void sha256_final(SHA256_CTX *ctx, BYTE hash[]) +{ + WORD i; + + i = ctx->datalen; + + // Pad whatever data is left in the buffer. + if (ctx->datalen < 56) { + ctx->data[i++] = 0x80; + while (i < 56) + ctx->data[i++] = 0x00; + } + else { + ctx->data[i++] = 0x80; + while (i < 64) + ctx->data[i++] = 0x00; + sha256_transform(ctx, ctx->data); + memset(ctx->data, 0, 56); + } + + // Append to the padding the total message's length in bits and transform. + ctx->bitlen += ctx->datalen * 8; + ctx->data[63] = ctx->bitlen; + ctx->data[62] = ctx->bitlen >> 8; + ctx->data[61] = ctx->bitlen >> 16; + ctx->data[60] = ctx->bitlen >> 24; + ctx->data[59] = ctx->bitlen >> 32; + ctx->data[58] = ctx->bitlen >> 40; + ctx->data[57] = ctx->bitlen >> 48; + ctx->data[56] = ctx->bitlen >> 56; + sha256_transform(ctx, ctx->data); + + // Since this implementation uses little endian byte ordering and SHA uses big endian, + // reverse all the bytes when copying the final state to the output hash. + for (i = 0; i < 4; ++i) { + hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; + hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; + hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; + hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; + hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; + hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; + hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; + hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; + } +} From 76e4adae92d53836fe5c85a6fbbeb2f1ea95386e Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sun, 29 Jan 2023 11:48:59 +0000 Subject: [PATCH 61/74] chore: Package module now follows the naming and structure conventions of libvieter. --- include/dynarray.h | 24 -------- include/package.h | 26 -------- include/package_info.h | 39 ------------ include/vieter_package.h | 30 +++++++++ src/package/README.md | 5 ++ {include => src/package}/sha256.h | 0 src/package/{package.c => vieter_package.c} | 51 ++++++++-------- .../{dynarray.c => vieter_package_dynarray.c} | 14 ++--- src/package/vieter_package_dynarray.h | 36 +++++++++++ .../{package_info.c => vieter_package_info.c} | 54 ++++++++-------- src/package/vieter_package_info.h | 52 ++++++++++++++++ src/package/vieter_package_internal.h | 10 +++ test/package/test_package.c | 61 ++++++++++--------- 13 files changed, 224 insertions(+), 178 deletions(-) delete mode 100644 include/dynarray.h delete mode 100644 include/package.h delete mode 100644 include/package_info.h create mode 100644 include/vieter_package.h create mode 100644 src/package/README.md rename {include => src/package}/sha256.h (100%) rename src/package/{package.c => vieter_package.c} (81%) rename src/package/{dynarray.c => vieter_package_dynarray.c} (67%) create mode 100644 src/package/vieter_package_dynarray.h rename src/package/{package_info.c => vieter_package_info.c} (59%) create mode 100644 src/package/vieter_package_info.h create mode 100644 src/package/vieter_package_internal.h diff --git a/include/dynarray.h b/include/dynarray.h deleted file mode 100644 index 2ab4022..0000000 --- a/include/dynarray.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef VIETER_DYNARRAY -#define VIETER_DYNARRAY - -#include -#include - -typedef struct dyn_array DynArray; -struct dyn_array { - char **array; - size_t capacity; - size_t size; -}; - -DynArray *dynarray_init(size_t initial_capacity); -void dynarray_add(DynArray *da, const char * s); -void dynarray_free(DynArray *da); - -/** - * Convert a DynArray into an array by freeing all its surrounding components - * and returning the underlying array pointer. - */ -char **dynarray_convert(DynArray *da); - -#endif diff --git a/include/package.h b/include/package.h deleted file mode 100644 index 0360a6a..0000000 --- a/include/package.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef VIETER_PACKAGE -#define VIETER_PACKAGE - -#include -#include -#include -#include - -#include -#include - -#include "package_info.h" -#include "dynarray.h" - -typedef struct pkg { - char *path; - PkgInfo *info; - DynArray *files; - int compression; -} Pkg; - -Pkg *package_read_archive(const char *pkg_path); -void package_free(Pkg ** ptp); -char *package_to_description(Pkg *pkg); - -#endif diff --git a/include/package_info.h b/include/package_info.h deleted file mode 100644 index b1388a2..0000000 --- a/include/package_info.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef VIETER_PACKAGE_INFO -#define VIETER_PACKAGE_INFO - -#define FREE_STRING(sp) if (sp != NULL) free(sp) - -#include - -#include "dynarray.h" - -typedef struct pkg_info { - char *name; - char *base; - char *version; - char *description; - int64_t size; - int64_t csize; - char *url; - char *arch; - int64_t build_date; - char *packager; - char *pgpsig; - int64_t pgpsigsize; - - DynArray *groups; - DynArray *licenses; - DynArray *replaces; - DynArray *depends; - DynArray *conflicts; - DynArray *provides; - DynArray *optdepends; - DynArray *makedepends; - DynArray *checkdepends; -} PkgInfo; - -PkgInfo *package_info_init(); -void package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); -void package_info_free(PkgInfo *pkg_info); - -#endif diff --git a/include/vieter_package.h b/include/vieter_package.h new file mode 100644 index 0000000..ebe6487 --- /dev/null +++ b/include/vieter_package.h @@ -0,0 +1,30 @@ +#ifndef VIETER_PACKAGE +#define VIETER_PACKAGE + +#include +#include +#include +#include + +#include +#include + +typedef struct pkg Pkg; + +/* + * Parse package file into something usable by libvieter. + * The pointer returned by this function will need to freed at a later point. + */ +Pkg *vieter_package_read_archive(const char *pkg_path); + +/* + * Deallocate a package. + */ +void vieter_package_free(Pkg ** ptp); + +/* + * Create string that will become the package's desc file. + */ +char *vieter_package_to_description(Pkg *pkg); + +#endif diff --git a/src/package/README.md b/src/package/README.md new file mode 100644 index 0000000..b2bcbd7 --- /dev/null +++ b/src/package/README.md @@ -0,0 +1,5 @@ +# package + +This module handles both parsing the published Arch tarballs & the contents of +their `.PKGINFO` files, as well as generating the contents of the database +archives' `desc` & `files` files. diff --git a/include/sha256.h b/src/package/sha256.h similarity index 100% rename from include/sha256.h rename to src/package/sha256.h diff --git a/src/package/package.c b/src/package/vieter_package.c similarity index 81% rename from src/package/package.c rename to src/package/vieter_package.c index 577e3c9..a3d2cd6 100644 --- a/src/package/package.c +++ b/src/package/vieter_package.c @@ -1,25 +1,25 @@ -#include "package.h" +#include "vieter_package_internal.h" #include "sha256.h" #define SMALL_BUFF_SIZE 128 -#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ +#define ADD_STRING(section, field) if (info->field != 0) { \ + snprintf(aux, SMALL_BUFF_SIZE, section, info->field); \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ } -#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ +#define ADD_ARRAY(section, field) i = 0; if (info->field != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, section, info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ - while (pkg_info->field->array[i] != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ + while (info->field->array[i] != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, "\n%s", info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ @@ -37,11 +37,11 @@ static char *ignored_names[5] = { }; static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *); -Pkg *package_init() { - return calloc(sizeof(PkgInfo), 1); +Pkg *vieter_package_init() { + return calloc(sizeof(pkg_info), 1); } -Pkg *package_read_archive(const char *pkg_path) { +Pkg *vieter_package_read_archive(const char *pkg_path) { struct archive *a = archive_read_new(); struct archive_entry *entry = archive_entry_new(); @@ -64,9 +64,9 @@ Pkg *package_read_archive(const char *pkg_path) { int compression_code = archive_filter_code(a, 0); const char *path_name; - PkgInfo *pkg_info; - DynArray *files = dynarray_init(16); - dynarray_add(files, "%FILES%"); + pkg_info *info; + dynarray *files = vieter_package_dynarray_init(16); + vieter_package_dynarray_add(files, "%FILES%"); while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { path_name = archive_entry_pathname(entry); @@ -81,7 +81,7 @@ Pkg *package_read_archive(const char *pkg_path) { } if (!ignore) { - dynarray_add(files, path_name); + vieter_package_dynarray_add(files, path_name); } if (strcmp(path_name, ".PKGINFO") == 0) { @@ -91,8 +91,8 @@ Pkg *package_read_archive(const char *pkg_path) { archive_read_data(a, buf, size); // Parse package info string into a struct - pkg_info = package_info_init(); - package_info_parse(pkg_info, buf); + info = vieter_package_info_init(); + vieter_package_info_parse(info, buf); free(buf); } else { @@ -107,21 +107,21 @@ Pkg *package_read_archive(const char *pkg_path) { return NULL; } - pkg_info->csize = stats.st_size; + info->csize = stats.st_size; archive_read_free(a); // Create final return value - Pkg *pkg = package_init(); + Pkg *pkg = vieter_package_init(); pkg->path = strdup(pkg_path); - pkg->info = pkg_info; + pkg->info = info; pkg->files = files; pkg->compression = compression_code; return pkg; } -void sha256sum(Pkg *pkg, char *res) { +void vieter_package_sha256sum(Pkg *pkg, char *res) { FILE *f = fopen(pkg->path, "r"); fseek(f, 0, SEEK_END); size_t size = ftell(f); @@ -170,18 +170,19 @@ void sha256sum(Pkg *pkg, char *res) { res[j] = '\0'; } -char *package_to_description(Pkg *pkg) { - PkgInfo *pkg_info = pkg->info; +char *vieter_package_to_description(Pkg *pkg) { + pkg_info *info = pkg->info; size_t buff_size = 1024; char aux[SMALL_BUFF_SIZE]; char *description = malloc(sizeof(char) * buff_size); + // Helper variable for ADD_ARRAY macro int i; // special case for FILENAME // assuming .pkg.tar.zst; other formats are valid, this should account for that - snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version, - pkg_info->arch); + snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", info->name, info->version, + info->arch); strcpy(description, aux); ADD_STRING("\n\n%%NAME%%\n%s", name); @@ -193,7 +194,7 @@ char *package_to_description(Pkg *pkg) { ADD_STRING("\n\n%%ISIZE%%\n%ld", size); char checksum[65]; - sha256sum(pkg, checksum); + vieter_package_sha256sum(pkg, checksum); snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum); if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { diff --git a/src/package/dynarray.c b/src/package/vieter_package_dynarray.c similarity index 67% rename from src/package/dynarray.c rename to src/package/vieter_package_dynarray.c index a78e7ff..4f23cbb 100644 --- a/src/package/dynarray.c +++ b/src/package/vieter_package_dynarray.c @@ -1,14 +1,14 @@ -#include "dynarray.h" +#include "vieter_package_dynarray.h" -DynArray *dynarray_init(size_t initial_capacity) { - DynArray *da = malloc(sizeof(DynArray)); +dynarray *vieter_package_dynarray_init(size_t initial_capacity) { + dynarray *da = malloc(sizeof(dynarray)); da->size = 0; da->capacity = initial_capacity; return da; } -void dynarray_add(DynArray *da, const char *s) { +void vieter_package_dynarray_add(dynarray *da, const char *s) { // An empty dynarray does not have an allocated internal array yet if (da->size == 0) { da->array = malloc(sizeof(char*) * da->capacity); @@ -24,7 +24,7 @@ void dynarray_add(DynArray *da, const char *s) { da->size++; } -void dynarray_free(DynArray *da) { +void vieter_package_dynarray_free(dynarray *da) { if (da == NULL) { return; } @@ -40,11 +40,11 @@ void dynarray_free(DynArray *da) { free(da); } -char **dynarray_convert(DynArray *da) { +char **vieter_package_dynarray_convert(dynarray *da) { char **array = da->array; da->array = NULL; - dynarray_free(da); + vieter_package_dynarray_free(da); return array; } diff --git a/src/package/vieter_package_dynarray.h b/src/package/vieter_package_dynarray.h new file mode 100644 index 0000000..0a96de0 --- /dev/null +++ b/src/package/vieter_package_dynarray.h @@ -0,0 +1,36 @@ +#ifndef VIETER_DYNARRAY +#define VIETER_DYNARRAY + +#include +#include +#include "vieter_package.h" + +typedef struct dynarray dynarray; +struct dynarray { + char **array; + size_t capacity; + size_t size; +}; + +/* + * Allocate a dynamic array. + */ +dynarray *vieter_package_dynarray_init(size_t initial_capacity); + +/* + * Initialise array (if it's not already initialised) and insert a string. + */ +void vieter_package_dynarray_add(dynarray *da, const char * s); + +/* + * Deallocate dynamic array. + */ +void vieter_package_dynarray_free(dynarray *da); + +/* + * Convert a dynarray into an array by freeing all its surrounding components + * and returning the underlying array pointer. + */ +char **vieter_package_dynarray_convert(dynarray *da); + +#endif diff --git a/src/package/package_info.c b/src/package/vieter_package_info.c similarity index 59% rename from src/package/package_info.c rename to src/package/vieter_package_info.c index 5e1986d..b897685 100644 --- a/src/package/package_info.c +++ b/src/package/vieter_package_info.c @@ -1,19 +1,19 @@ #include -#include "package_info.h" +#include "vieter_package_info.h" #define PKG_INFO_STRING(key_ptr, field) if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ value_ptr += strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n');\ tail_ptr[0] = '\0'; \ - pkg_info->field = strdup(value_ptr); \ + info->field = strdup(value_ptr); \ tail_ptr[0] = '\n'; \ } value_ptr = tail_ptr; #define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n');\ tail_ptr[0] = '\0'; \ - pkg_info->field = atoi(value_ptr); \ + info->field = atoi(value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr; @@ -21,40 +21,40 @@ value_ptr = value_ptr + strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n'); \ tail_ptr[0] = '\0'; \ - if(pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ - dynarray_add(pkg_info->field, value_ptr); \ + if(info->field == NULL) { info->field = vieter_package_dynarray_init(4); } \ + vieter_package_dynarray_add(info->field, value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr;\ } value_ptr = tail_ptr; -PkgInfo *package_info_init() { - return calloc(1, sizeof(PkgInfo)); +pkg_info *vieter_package_info_init() { + return calloc(1, sizeof(pkg_info)); } -void package_info_free(PkgInfo *pkg_info) { - FREE_STRING(pkg_info->name); - FREE_STRING(pkg_info->base); - FREE_STRING(pkg_info->version); - FREE_STRING(pkg_info->description); - FREE_STRING(pkg_info->url); - FREE_STRING(pkg_info->arch); - FREE_STRING(pkg_info->packager); - FREE_STRING(pkg_info->pgpsig); +void vieter_package_info_free(pkg_info *info) { + FREE_STRING(info->name); + FREE_STRING(info->base); + FREE_STRING(info->version); + FREE_STRING(info->description); + FREE_STRING(info->url); + FREE_STRING(info->arch); + FREE_STRING(info->packager); + FREE_STRING(info->pgpsig); - dynarray_free(pkg_info->groups); - dynarray_free(pkg_info->licenses); - dynarray_free(pkg_info->replaces); - dynarray_free(pkg_info->depends); - dynarray_free(pkg_info->conflicts); - dynarray_free(pkg_info->provides); - dynarray_free(pkg_info->optdepends); - dynarray_free(pkg_info->makedepends); - dynarray_free(pkg_info->checkdepends); + vieter_package_dynarray_free(info->groups); + vieter_package_dynarray_free(info->licenses); + vieter_package_dynarray_free(info->replaces); + vieter_package_dynarray_free(info->depends); + vieter_package_dynarray_free(info->conflicts); + vieter_package_dynarray_free(info->provides); + vieter_package_dynarray_free(info->optdepends); + vieter_package_dynarray_free(info->makedepends); + vieter_package_dynarray_free(info->checkdepends); - free(pkg_info); + free(info); } -void package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { +void vieter_package_info_parse(pkg_info *info, char *pkg_info_str) { char *value_ptr = pkg_info_str, *tail_ptr; PKG_INFO_STRING("\npkgname = ", name); diff --git a/src/package/vieter_package_info.h b/src/package/vieter_package_info.h new file mode 100644 index 0000000..fc9f411 --- /dev/null +++ b/src/package/vieter_package_info.h @@ -0,0 +1,52 @@ +#ifndef VIETER_PACKAGE_INFO +#define VIETER_PACKAGE_INFO + +#define FREE_STRING(sp) if (sp != NULL) free(sp) + +#include + +#include "vieter_package.h" +#include "vieter_package_dynarray.h" + + +typedef struct pkg_info { + char *name; + char *base; + char *version; + char *description; + int64_t size; + int64_t csize; + char *url; + char *arch; + int64_t build_date; + char *packager; + char *pgpsig; + int64_t pgpsigsize; + + dynarray *groups; + dynarray *licenses; + dynarray *replaces; + dynarray *depends; + dynarray *conflicts; + dynarray *provides; + dynarray *optdepends; + dynarray *makedepends; + dynarray *checkdepends; +} pkg_info; + +/* + * Allocate and initialise a pkg_info pointer to hold .PKGINFO. + */ +pkg_info *vieter_package_info_init(); + +/* + * Parse .PKGINFO file into something usable by libvieter. + */ +void vieter_package_info_parse(pkg_info *info, char *pkg_info_str); + +/* + * Deallocate a pkg_info pointer. + */ +void vieter_package_info_free(pkg_info *info); + +#endif diff --git a/src/package/vieter_package_internal.h b/src/package/vieter_package_internal.h new file mode 100644 index 0000000..c13278e --- /dev/null +++ b/src/package/vieter_package_internal.h @@ -0,0 +1,10 @@ +#include "vieter_package.h" +#include "vieter_package_info.h" +#include "vieter_package_dynarray.h" + +struct pkg { + char *path; + pkg_info *info; + dynarray *files; + int compression; +}; diff --git a/test/package/test_package.c b/test/package/test_package.c index c0c7085..a79d5df 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -1,7 +1,7 @@ #include "acutest.h" -#include "package.h" +#include "vieter_package_internal.h" -void test_pkg_info_parse() { +void test_info_parse() { FILE *f = fopen("./test/package/.PKGINFO", "r"); TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package "); fseek(f, 0L, SEEK_END); @@ -11,34 +11,35 @@ void test_pkg_info_parse() { char *pkg_info_str = malloc(size); fread(pkg_info_str, 1, size, f); fclose(f); - PkgInfo *pkg_info = package_info_init(); - package_info_parse(pkg_info, pkg_info_str); - TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); - TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); - TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); - TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); - TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); - TEST_CHECK(pkg_info->build_date == 1673751613); - TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); - TEST_CHECK(pkg_info->size == 3469584); - TEST_CHECK(!strcmp(pkg_info->arch, "any")); + pkg_info *info = vieter_package_info_init(); + vieter_package_info_parse(info, pkg_info_str); - TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); - TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); - TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); - TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); - TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); - TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); - TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); - TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); - TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); - TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); - TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); + TEST_CHECK(!strcmp(info->name, "xcursor-dmz")); + TEST_CHECK(!strcmp(info->base, "xcursor-dmz")); + TEST_CHECK(!strcmp(info->version, "0.4.5-2")); + TEST_CHECK(!strcmp(info->description, "Style neutral, scalable cursor theme")); + TEST_CHECK(!strcmp(info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); + TEST_CHECK(info->build_date == 1673751613); + TEST_CHECK(!strcmp(info->packager, "Unknown Packager")); + TEST_CHECK(info->size == 3469584); + TEST_CHECK(!strcmp(info->arch, "any")); + + TEST_CHECK(!strcmp(info->licenses->array[0], "MIT")); + TEST_CHECK(!strcmp(info->replaces->array[0], "test1")); + TEST_CHECK(!strcmp(info->groups->array[0], "x11")); + TEST_CHECK(!strcmp(info->conflicts->array[0], "test2")); + TEST_CHECK(!strcmp(info->conflicts->array[1], "test3")); + TEST_CHECK(!strcmp(info->provides->array[0], "test4")); + TEST_CHECK(!strcmp(info->depends->array[0], "test5")); + TEST_CHECK(!strcmp(info->depends->array[1], "test6")); + TEST_CHECK(!strcmp(info->optdepends->array[0], "test7")); + TEST_CHECK(!strcmp(info->makedepends->array[0], "xorg-xcursorgen")); + TEST_CHECK(!strcmp(info->checkdepends->array[0], "test8")); } void test_pkg_read_archive_files() { - Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + Pkg *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); FILE *f = fopen("./test/package/files", "r"); @@ -59,10 +60,10 @@ void test_pkg_read_archive_files() { } void test_pkg_read_archive_desc() { - Pkg *pkg = package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + Pkg *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); - char *description = package_to_description(pkg); + char *description = vieter_package_to_description(pkg); FILE *f = fopen("./test/package/desc", "r"); TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package"); @@ -77,8 +78,8 @@ void test_pkg_read_archive_desc() { } TEST_LIST = { - {"pkg_info_valid_parse", test_pkg_info_parse}, - {"pkg_read_archive_files", test_pkg_read_archive_files}, - {"pkg_read_archive_desc", test_pkg_read_archive_desc}, + {".PKGINFO parse", test_info_parse}, + {"files array creation", test_pkg_read_archive_files}, + {"desc file creation", test_pkg_read_archive_desc}, {NULL, NULL} }; From 03bae825694499a601e623d565bfd0b3e2ddfa5b Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sun, 29 Jan 2023 11:55:22 +0000 Subject: [PATCH 62/74] refactor: Added free function for package struct. While going through with the renaming, I saw that I actually forgot to implement that part. --- src/package/vieter_package.c | 9 +++++++++ test/package/test_package.c | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index a3d2cd6..4a6515c 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -221,3 +221,12 @@ char *vieter_package_to_description(Pkg *pkg) { return description; } + +void vieter_package_free(Pkg **ptp) { + FREE_STRING((*ptp)->path); + vieter_package_info_free((*ptp)->info); + vieter_package_dynarray_free((*ptp)->files); + free(*ptp); + *ptp = NULL; + +} diff --git a/test/package/test_package.c b/test/package/test_package.c index a79d5df..f6597c8 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -57,6 +57,8 @@ void test_pkg_read_archive_files() { } TEST_CHECK(pkg->compression = 14); + vieter_package_free(&pkg); + } void test_pkg_read_archive_desc() { From bcae64e02351d6178b11d9e7d3ddec5750ad62da Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Sun, 29 Jan 2023 12:45:48 +0000 Subject: [PATCH 63/74] chore: Also renamed structs to follow naming conventions. --- include/vieter_package.h | 8 ++--- src/package/vieter_package.c | 46 ++++++++++++------------ src/package/vieter_package_dynarray.c | 12 +++---- src/package/vieter_package_dynarray.h | 14 ++++---- src/package/vieter_package_info.c | 52 +++++++++++++-------------- src/package/vieter_package_info.h | 28 +++++++-------- src/package/vieter_package_internal.h | 6 ++-- test/package/test_package.c | 48 ++++++++++++------------- 8 files changed, 107 insertions(+), 107 deletions(-) diff --git a/include/vieter_package.h b/include/vieter_package.h index ebe6487..179ff57 100644 --- a/include/vieter_package.h +++ b/include/vieter_package.h @@ -9,22 +9,22 @@ #include #include -typedef struct pkg Pkg; +typedef struct vieter_package vieter_package; /* * Parse package file into something usable by libvieter. * The pointer returned by this function will need to freed at a later point. */ -Pkg *vieter_package_read_archive(const char *pkg_path); +vieter_package *vieter_package_read_archive(const char *pkg_path); /* * Deallocate a package. */ -void vieter_package_free(Pkg ** ptp); +void vieter_package_free(vieter_package ** ptp); /* * Create string that will become the package's desc file. */ -char *vieter_package_to_description(Pkg *pkg); +char *vieter_package_to_description(vieter_package *pkg); #endif diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 4a6515c..3bb19ba 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -3,23 +3,23 @@ #define SMALL_BUFF_SIZE 128 -#define ADD_STRING(section, field) if (info->field != 0) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, info->field); \ +#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ + snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ } -#define ADD_ARRAY(section, field) i = 0; if (info->field != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, info->field->array[i]); i++; \ +#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ - while (info->field->array[i] != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, "\n%s", info->field->array[i]); i++; \ + while (pkg_info->field->array[i] != NULL) { \ + snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ @@ -37,11 +37,11 @@ static char *ignored_names[5] = { }; static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *); -Pkg *vieter_package_init() { - return calloc(sizeof(pkg_info), 1); +vieter_package *vieter_package_init() { + return calloc(sizeof(vieter_package_info), 1); } -Pkg *vieter_package_read_archive(const char *pkg_path) { +vieter_package *vieter_package_read_archive(const char *pkg_path) { struct archive *a = archive_read_new(); struct archive_entry *entry = archive_entry_new(); @@ -64,8 +64,8 @@ Pkg *vieter_package_read_archive(const char *pkg_path) { int compression_code = archive_filter_code(a, 0); const char *path_name; - pkg_info *info; - dynarray *files = vieter_package_dynarray_init(16); + vieter_package_info *pkg_info; + vieter_package_dynarray *files = vieter_package_dynarray_init(16); vieter_package_dynarray_add(files, "%FILES%"); while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { @@ -90,9 +90,9 @@ Pkg *vieter_package_read_archive(const char *pkg_path) { char *buf = malloc(size); archive_read_data(a, buf, size); - // Parse package info string into a struct - info = vieter_package_info_init(); - vieter_package_info_parse(info, buf); + // Parse package vieter_package_info string into a struct + pkg_info = vieter_package_info_init(); + vieter_package_info_parse(pkg_info, buf); free(buf); } else { @@ -107,21 +107,21 @@ Pkg *vieter_package_read_archive(const char *pkg_path) { return NULL; } - info->csize = stats.st_size; + pkg_info->csize = stats.st_size; archive_read_free(a); // Create final return value - Pkg *pkg = vieter_package_init(); + vieter_package *pkg = vieter_package_init(); pkg->path = strdup(pkg_path); - pkg->info = info; + pkg->info = pkg_info; pkg->files = files; pkg->compression = compression_code; return pkg; } -void vieter_package_sha256sum(Pkg *pkg, char *res) { +void vieter_package_sha256sum(vieter_package *pkg, char *res) { FILE *f = fopen(pkg->path, "r"); fseek(f, 0, SEEK_END); size_t size = ftell(f); @@ -170,8 +170,8 @@ void vieter_package_sha256sum(Pkg *pkg, char *res) { res[j] = '\0'; } -char *vieter_package_to_description(Pkg *pkg) { - pkg_info *info = pkg->info; +char *vieter_package_to_description(vieter_package *pkg) { + vieter_package_info *pkg_info = pkg->info; size_t buff_size = 1024; char aux[SMALL_BUFF_SIZE]; @@ -181,8 +181,8 @@ char *vieter_package_to_description(Pkg *pkg) { // special case for FILENAME // assuming .pkg.tar.zst; other formats are valid, this should account for that - snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", info->name, info->version, - info->arch); + snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, + pkg_info->version, pkg_info->arch); strcpy(description, aux); ADD_STRING("\n\n%%NAME%%\n%s", name); @@ -222,7 +222,7 @@ char *vieter_package_to_description(Pkg *pkg) { return description; } -void vieter_package_free(Pkg **ptp) { +void vieter_package_free(vieter_package **ptp) { FREE_STRING((*ptp)->path); vieter_package_info_free((*ptp)->info); vieter_package_dynarray_free((*ptp)->files); diff --git a/src/package/vieter_package_dynarray.c b/src/package/vieter_package_dynarray.c index 4f23cbb..2cc20b6 100644 --- a/src/package/vieter_package_dynarray.c +++ b/src/package/vieter_package_dynarray.c @@ -1,15 +1,15 @@ #include "vieter_package_dynarray.h" -dynarray *vieter_package_dynarray_init(size_t initial_capacity) { - dynarray *da = malloc(sizeof(dynarray)); +vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity) { + vieter_package_dynarray *da = malloc(sizeof(vieter_package_dynarray)); da->size = 0; da->capacity = initial_capacity; return da; } -void vieter_package_dynarray_add(dynarray *da, const char *s) { - // An empty dynarray does not have an allocated internal array yet +void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { + // An empty vieter_package_dynarray does not have an allocated internal array yet if (da->size == 0) { da->array = malloc(sizeof(char*) * da->capacity); } @@ -24,7 +24,7 @@ void vieter_package_dynarray_add(dynarray *da, const char *s) { da->size++; } -void vieter_package_dynarray_free(dynarray *da) { +void vieter_package_dynarray_free(vieter_package_dynarray *da) { if (da == NULL) { return; } @@ -40,7 +40,7 @@ void vieter_package_dynarray_free(dynarray *da) { free(da); } -char **vieter_package_dynarray_convert(dynarray *da) { +char **vieter_package_dynarray_convert(vieter_package_dynarray *da) { char **array = da->array; da->array = NULL; diff --git a/src/package/vieter_package_dynarray.h b/src/package/vieter_package_dynarray.h index 0a96de0..c198ea1 100644 --- a/src/package/vieter_package_dynarray.h +++ b/src/package/vieter_package_dynarray.h @@ -5,8 +5,8 @@ #include #include "vieter_package.h" -typedef struct dynarray dynarray; -struct dynarray { +typedef struct vieter_package_dynarray vieter_package_dynarray; +struct vieter_package_dynarray { char **array; size_t capacity; size_t size; @@ -15,22 +15,22 @@ struct dynarray { /* * Allocate a dynamic array. */ -dynarray *vieter_package_dynarray_init(size_t initial_capacity); +vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity); /* * Initialise array (if it's not already initialised) and insert a string. */ -void vieter_package_dynarray_add(dynarray *da, const char * s); +void vieter_package_dynarray_add(vieter_package_dynarray *da, const char * s); /* * Deallocate dynamic array. */ -void vieter_package_dynarray_free(dynarray *da); +void vieter_package_dynarray_free(vieter_package_dynarray *da); /* - * Convert a dynarray into an array by freeing all its surrounding components + * Convert a vieter_package_dynarray into an array by freeing all its surrounding components * and returning the underlying array pointer. */ -char **vieter_package_dynarray_convert(dynarray *da); +char **vieter_package_dynarray_convert(vieter_package_dynarray *da); #endif diff --git a/src/package/vieter_package_info.c b/src/package/vieter_package_info.c index b897685..5ed040e 100644 --- a/src/package/vieter_package_info.c +++ b/src/package/vieter_package_info.c @@ -6,14 +6,14 @@ value_ptr += strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n');\ tail_ptr[0] = '\0'; \ - info->field = strdup(value_ptr); \ + pkg_info->field = strdup(value_ptr); \ tail_ptr[0] = '\n'; \ } value_ptr = tail_ptr; #define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n');\ tail_ptr[0] = '\0'; \ - info->field = atoi(value_ptr); \ + pkg_info->field = atoi(value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr; @@ -21,40 +21,40 @@ value_ptr = value_ptr + strlen(key_ptr);\ tail_ptr = strchr(value_ptr, '\n'); \ tail_ptr[0] = '\0'; \ - if(info->field == NULL) { info->field = vieter_package_dynarray_init(4); } \ - vieter_package_dynarray_add(info->field, value_ptr); \ + if(pkg_info->field == NULL) { pkg_info->field = vieter_package_dynarray_init(4); } \ + vieter_package_dynarray_add(pkg_info->field, value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr;\ } value_ptr = tail_ptr; -pkg_info *vieter_package_info_init() { - return calloc(1, sizeof(pkg_info)); +vieter_package_info *vieter_package_info_init() { + return calloc(1, sizeof(vieter_package_info)); } -void vieter_package_info_free(pkg_info *info) { - FREE_STRING(info->name); - FREE_STRING(info->base); - FREE_STRING(info->version); - FREE_STRING(info->description); - FREE_STRING(info->url); - FREE_STRING(info->arch); - FREE_STRING(info->packager); - FREE_STRING(info->pgpsig); +void vieter_package_info_free(vieter_package_info *pkg_info) { + FREE_STRING(pkg_info->name); + FREE_STRING(pkg_info->base); + FREE_STRING(pkg_info->version); + FREE_STRING(pkg_info->description); + FREE_STRING(pkg_info->url); + FREE_STRING(pkg_info->arch); + FREE_STRING(pkg_info->packager); + FREE_STRING(pkg_info->pgpsig); - vieter_package_dynarray_free(info->groups); - vieter_package_dynarray_free(info->licenses); - vieter_package_dynarray_free(info->replaces); - vieter_package_dynarray_free(info->depends); - vieter_package_dynarray_free(info->conflicts); - vieter_package_dynarray_free(info->provides); - vieter_package_dynarray_free(info->optdepends); - vieter_package_dynarray_free(info->makedepends); - vieter_package_dynarray_free(info->checkdepends); + vieter_package_dynarray_free(pkg_info->groups); + vieter_package_dynarray_free(pkg_info->licenses); + vieter_package_dynarray_free(pkg_info->replaces); + vieter_package_dynarray_free(pkg_info->depends); + vieter_package_dynarray_free(pkg_info->conflicts); + vieter_package_dynarray_free(pkg_info->provides); + vieter_package_dynarray_free(pkg_info->optdepends); + vieter_package_dynarray_free(pkg_info->makedepends); + vieter_package_dynarray_free(pkg_info->checkdepends); - free(info); + free(pkg_info); } -void vieter_package_info_parse(pkg_info *info, char *pkg_info_str) { +void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str) { char *value_ptr = pkg_info_str, *tail_ptr; PKG_INFO_STRING("\npkgname = ", name); diff --git a/src/package/vieter_package_info.h b/src/package/vieter_package_info.h index fc9f411..b931928 100644 --- a/src/package/vieter_package_info.h +++ b/src/package/vieter_package_info.h @@ -9,7 +9,7 @@ #include "vieter_package_dynarray.h" -typedef struct pkg_info { +typedef struct vieter_package_info { char *name; char *base; char *version; @@ -23,30 +23,30 @@ typedef struct pkg_info { char *pgpsig; int64_t pgpsigsize; - dynarray *groups; - dynarray *licenses; - dynarray *replaces; - dynarray *depends; - dynarray *conflicts; - dynarray *provides; - dynarray *optdepends; - dynarray *makedepends; - dynarray *checkdepends; -} pkg_info; + vieter_package_dynarray *groups; + vieter_package_dynarray *licenses; + vieter_package_dynarray *replaces; + vieter_package_dynarray *depends; + vieter_package_dynarray *conflicts; + vieter_package_dynarray *provides; + vieter_package_dynarray *optdepends; + vieter_package_dynarray *makedepends; + vieter_package_dynarray *checkdepends; +} vieter_package_info; /* * Allocate and initialise a pkg_info pointer to hold .PKGINFO. */ -pkg_info *vieter_package_info_init(); +vieter_package_info *vieter_package_info_init(); /* * Parse .PKGINFO file into something usable by libvieter. */ -void vieter_package_info_parse(pkg_info *info, char *pkg_info_str); +void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str); /* * Deallocate a pkg_info pointer. */ -void vieter_package_info_free(pkg_info *info); +void vieter_package_info_free(vieter_package_info *pkg_info); #endif diff --git a/src/package/vieter_package_internal.h b/src/package/vieter_package_internal.h index c13278e..fe84f17 100644 --- a/src/package/vieter_package_internal.h +++ b/src/package/vieter_package_internal.h @@ -2,9 +2,9 @@ #include "vieter_package_info.h" #include "vieter_package_dynarray.h" -struct pkg { +struct vieter_package { char *path; - pkg_info *info; - dynarray *files; + vieter_package_info *info; + vieter_package_dynarray *files; int compression; }; diff --git a/test/package/test_package.c b/test/package/test_package.c index f6597c8..5bbda26 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -12,34 +12,34 @@ void test_info_parse() { fread(pkg_info_str, 1, size, f); fclose(f); - pkg_info *info = vieter_package_info_init(); - vieter_package_info_parse(info, pkg_info_str); + vieter_package_info *pkg_info = vieter_package_info_init(); + vieter_package_info_parse(pkg_info, pkg_info_str); - TEST_CHECK(!strcmp(info->name, "xcursor-dmz")); - TEST_CHECK(!strcmp(info->base, "xcursor-dmz")); - TEST_CHECK(!strcmp(info->version, "0.4.5-2")); - TEST_CHECK(!strcmp(info->description, "Style neutral, scalable cursor theme")); - TEST_CHECK(!strcmp(info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); - TEST_CHECK(info->build_date == 1673751613); - TEST_CHECK(!strcmp(info->packager, "Unknown Packager")); - TEST_CHECK(info->size == 3469584); - TEST_CHECK(!strcmp(info->arch, "any")); + TEST_CHECK(!strcmp(pkg_info->name, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz")); + TEST_CHECK(!strcmp(pkg_info->version, "0.4.5-2")); + TEST_CHECK(!strcmp(pkg_info->description, "Style neutral, scalable cursor theme")); + TEST_CHECK(!strcmp(pkg_info->url, "https://packages.debian.org/sid/dmz-cursor-theme")); + TEST_CHECK(pkg_info->build_date == 1673751613); + TEST_CHECK(!strcmp(pkg_info->packager, "Unknown Packager")); + TEST_CHECK(pkg_info->size == 3469584); + TEST_CHECK(!strcmp(pkg_info->arch, "any")); - TEST_CHECK(!strcmp(info->licenses->array[0], "MIT")); - TEST_CHECK(!strcmp(info->replaces->array[0], "test1")); - TEST_CHECK(!strcmp(info->groups->array[0], "x11")); - TEST_CHECK(!strcmp(info->conflicts->array[0], "test2")); - TEST_CHECK(!strcmp(info->conflicts->array[1], "test3")); - TEST_CHECK(!strcmp(info->provides->array[0], "test4")); - TEST_CHECK(!strcmp(info->depends->array[0], "test5")); - TEST_CHECK(!strcmp(info->depends->array[1], "test6")); - TEST_CHECK(!strcmp(info->optdepends->array[0], "test7")); - TEST_CHECK(!strcmp(info->makedepends->array[0], "xorg-xcursorgen")); - TEST_CHECK(!strcmp(info->checkdepends->array[0], "test8")); + TEST_CHECK(!strcmp(pkg_info->licenses->array[0], "MIT")); + TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1")); + TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2")); + TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3")); + TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4")); + TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5")); + TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6")); + TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); + TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); + TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); } void test_pkg_read_archive_files() { - Pkg *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); FILE *f = fopen("./test/package/files", "r"); @@ -62,7 +62,7 @@ void test_pkg_read_archive_files() { } void test_pkg_read_archive_desc() { - Pkg *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); char *description = vieter_package_to_description(pkg); From 9211bc33519f674bce50dc7d11c07874807d5116 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Tue, 31 Jan 2023 20:41:05 +0000 Subject: [PATCH 64/74] fix: Initialise array pointers to 0 before performing check on them. --- src/package/vieter_package_dynarray.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/package/vieter_package_dynarray.c b/src/package/vieter_package_dynarray.c index 2cc20b6..6da07ee 100644 --- a/src/package/vieter_package_dynarray.c +++ b/src/package/vieter_package_dynarray.c @@ -12,12 +12,18 @@ void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { // An empty vieter_package_dynarray does not have an allocated internal array yet if (da->size == 0) { da->array = malloc(sizeof(char*) * da->capacity); + + // Initialise all char*'s to 0 so array[i] == NULL can be used to see if field is empty + memset(da->array, 0, sizeof(char*) * da->capacity); } // Double array size if it's full else if (da->size == da->capacity) { // if the realloc fails, access to memory in da->array is lost da->array = realloc(da->array, sizeof(char*) * da->capacity * 2); da->capacity *= 2; + + // Same as the previous memset, but only for newly allocated pointers + memset(da->array + da->size, 0, sizeof(char*) * da->capacity / 2); } da->array[da->size] = strdup(s); From c7c4043108707c194ab242080db7b51478618c98 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Tue, 31 Jan 2023 21:00:08 +0000 Subject: [PATCH 65/74] fix: Using snprintf while ignoring its return value could lead to valid inputs getting truncated. --- include/vieter_package.h | 10 ++----- src/package/vieter_package.c | 51 ++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/include/vieter_package.h b/include/vieter_package.h index 179ff57..32fb0eb 100644 --- a/include/vieter_package.h +++ b/include/vieter_package.h @@ -1,16 +1,10 @@ #ifndef VIETER_PACKAGE #define VIETER_PACKAGE -#include -#include -#include -#include - -#include -#include - typedef struct vieter_package vieter_package; + + /* * Parse package file into something usable by libvieter. * The pointer returned by this function will need to freed at a later point. diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 3bb19ba..031fe15 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -1,30 +1,29 @@ +#include +#include +#include +#include + #include "vieter_package_internal.h" #include "sha256.h" -#define SMALL_BUFF_SIZE 128 - #define ADD_STRING(section, field) if (pkg_info->field != 0) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \ - if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ + size_to_be_written = snprintf(aux, small_buff_size, section, pkg_info->field); \ + if (size_to_be_written > small_buff_size) { \ + aux = realloc(aux, size_to_be_written + 1); \ + small_buff_size = size_to_be_written + 1; \ + snprintf(aux, small_buff_size, section, pkg_info->field); \ + } \ + if (buff_size < strlen(description) + small_buff_size + 1) { \ description = realloc(description, buff_size * 2); \ buff_size *= 2; \ } \ strcat(description, aux); \ } + #define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \ - if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2); \ - buff_size *= 2; \ - } \ - strcat(description, aux); \ + ADD_STRING(section, field->array[i]); i++; \ while (pkg_info->field->array[i] != NULL) { \ - snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \ - if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \ - description = realloc(description, buff_size * 2); \ - buff_size *= 2; \ - } \ - strcat(description, aux); \ + ADD_STRING("\n%s", field->array[i]); i++; \ } \ } @@ -170,19 +169,32 @@ void vieter_package_sha256sum(vieter_package *pkg, char *res) { res[j] = '\0'; } + + char *vieter_package_to_description(vieter_package *pkg) { vieter_package_info *pkg_info = pkg->info; size_t buff_size = 1024; - char aux[SMALL_BUFF_SIZE]; + int small_buff_size = 128; + int size_to_be_written; + char *aux = malloc(sizeof(char) * small_buff_size); char *description = malloc(sizeof(char) * buff_size); // Helper variable for ADD_ARRAY macro int i; // special case for FILENAME // assuming .pkg.tar.zst; other formats are valid, this should account for that - snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, + size_to_be_written = snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version, pkg_info->arch); + + // We neither want to let an arbritrarily long input to overflow the buffer + // nor to truncate perfectly valid inputs + if (size_to_be_written > small_buff_size) { + aux = realloc(aux, size_to_be_written + 1); + small_buff_size = size_to_be_written + 1; + snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, + pkg_info->version, pkg_info->arch); + } strcpy(description, aux); ADD_STRING("\n\n%%NAME%%\n%s", name); @@ -216,8 +228,7 @@ char *vieter_package_to_description(vieter_package *pkg) { ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); - snprintf(aux, SMALL_BUFF_SIZE, "\n\n"); - strcat(description, aux); + strcat(description, "\n\n"); return description; } From 4c9b429eaa5b3224103fdac171a0624f16f072e9 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Tue, 31 Jan 2023 21:08:09 +0000 Subject: [PATCH 66/74] refactor: Package archive parser now returns meaningful error enums in case of failure. --- include/vieter_package.h | 12 ++++++++++-- src/package/vieter_package.c | 11 ++++++----- test/package/test_package.c | 11 ++++++----- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/vieter_package.h b/include/vieter_package.h index 32fb0eb..c9a941e 100644 --- a/include/vieter_package.h +++ b/include/vieter_package.h @@ -3,13 +3,21 @@ typedef struct vieter_package vieter_package; +typedef enum vieter_package_error { + vieter_package_ok = 0, + vieter_package_unarchive_error = 1, + vieter_package_stat_error = 2 +} vieter_package_error; +/* + * Allocate an empty package + */ +vieter_package *vieter_package_init(); /* * Parse package file into something usable by libvieter. - * The pointer returned by this function will need to freed at a later point. */ -vieter_package *vieter_package_read_archive(const char *pkg_path); +vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path); /* * Deallocate a package. diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 031fe15..cf273d8 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -40,7 +40,7 @@ vieter_package *vieter_package_init() { return calloc(sizeof(vieter_package_info), 1); } -vieter_package *vieter_package_read_archive(const char *pkg_path) { +vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path) { struct archive *a = archive_read_new(); struct archive_entry *entry = archive_entry_new(); @@ -57,7 +57,7 @@ vieter_package *vieter_package_read_archive(const char *pkg_path) { // Exit early if we weren't able to successfully open the archive for reading if (r != ARCHIVE_OK) { - return NULL; + return vieter_package_unarchive_error; } int compression_code = archive_filter_code(a, 0); @@ -103,7 +103,9 @@ vieter_package *vieter_package_read_archive(const char *pkg_path) { struct stat stats; if (stat(pkg_path, &stats) != 0) { - return NULL; + // errno is set if stat() fails; the calling function should check + // the value of errno in case vieter_package_stat_error is returned + return vieter_package_stat_error; } pkg_info->csize = stats.st_size; @@ -111,13 +113,12 @@ vieter_package *vieter_package_read_archive(const char *pkg_path) { archive_read_free(a); // Create final return value - vieter_package *pkg = vieter_package_init(); pkg->path = strdup(pkg_path); pkg->info = pkg_info; pkg->files = files; pkg->compression = compression_code; - return pkg; + return vieter_package_ok; } void vieter_package_sha256sum(vieter_package *pkg, char *res) { diff --git a/test/package/test_package.c b/test/package/test_package.c index 5bbda26..3c8b249 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -39,8 +39,9 @@ void test_info_parse() { } void test_pkg_read_archive_files() { - vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); - TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + vieter_package *pkg = vieter_package_init(); + vieter_package_error e = vieter_package_read_archive(pkg, "./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(e == vieter_package_ok, "failure parsing pkg archive"); FILE *f = fopen("./test/package/files", "r"); TEST_ASSERT_(f != NULL, "could not find test files file in ./test/package"); @@ -58,12 +59,12 @@ void test_pkg_read_archive_files() { TEST_CHECK(pkg->compression = 14); vieter_package_free(&pkg); - } void test_pkg_read_archive_desc() { - vieter_package *pkg = vieter_package_read_archive("./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); - TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive"); + vieter_package *pkg = vieter_package_init(); + vieter_package_error e = vieter_package_read_archive(pkg, "./test/package/xcursor-dmz-0.4.5-2-any.pkg.tar.zst"); + TEST_ASSERT_(e == vieter_package_ok, "failure parsing pkg archive"); char *description = vieter_package_to_description(pkg); From b6d97df1bc7ebc3f79326cc8b967ce834fc6ad83 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Tue, 31 Jan 2023 21:09:47 +0000 Subject: [PATCH 67/74] refactor: Hashing function now streams data into hasher instead of doing it in one go. --- src/package/vieter_package.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index cf273d8..d1ef6c4 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -123,20 +123,21 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char void vieter_package_sha256sum(vieter_package *pkg, char *res) { FILE *f = fopen(pkg->path, "r"); - fseek(f, 0, SEEK_END); - size_t size = ftell(f); - rewind(f); - unsigned char *in = malloc(size); - fread(in, 1, size, f); - fclose(f); + // Try to read 100KiB at a time + unsigned char *in = malloc(102400); + // Actual number of bytes read + size_t read_size; - unsigned char hash[32]; SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); - sha256_init(ctx); - sha256_update(ctx, in, size); + while ((read_size = fread(in, 1, 102400, f)) != 0) { + sha256_update(ctx, in, read_size); + } + unsigned char hash[SHA256_BLOCK_SIZE]; + sha256_final(ctx, hash); + fclose(f); free(in); free(ctx); @@ -147,8 +148,8 @@ void vieter_package_sha256sum(vieter_package *pkg, char *res) { unsigned int half_byte = 0; int j = 0; - // We advance in the string 2 bytes for every one byte of the hash - for (int i = 0; i < 32; i++) { + // We advance 2 bytes in the string for every one byte of the hash + for (int i = 0; i < SHA256_BLOCK_SIZE; i++) { // We transform the first half byte into the second character to keep // each byte from becoming reversed in the final string half_byte = hash[i] & 0b1111; @@ -206,11 +207,11 @@ char *vieter_package_to_description(vieter_package *pkg) { ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); ADD_STRING("\n\n%%ISIZE%%\n%ld", size); - char checksum[65]; + char checksum[SHA256_BLOCK_SIZE * 2 + 1]; vieter_package_sha256sum(pkg, checksum); - snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum); - if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { + snprintf(aux, small_buff_size, "\n\n%%SHA256SUM%%\n%s", checksum); + if (buff_size < strlen(description) + small_buff_size + 1) { description = realloc(description, buff_size * 2); buff_size *= 2; } From 46e7e093d9098100829000dd932d5b77c5539655 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 2 Feb 2023 11:16:47 +0100 Subject: [PATCH 68/74] refactor: separate directory for thirdparty code --- Makefile | 12 ++++++++++-- {src/package => thirdparty/include}/sha256.h | 0 {src/package => thirdparty/src}/sha256.c | 0 3 files changed, 10 insertions(+), 2 deletions(-) rename {src/package => thirdparty/include}/sha256.h (100%) rename {src/package => thirdparty/src}/sha256.c (100%) diff --git a/Makefile b/Makefile index 84c9b52..f2dd960 100644 --- a/Makefile +++ b/Makefile @@ -6,15 +6,20 @@ LIB_FILENAME ?= libvieter.a BUILD_DIR ?= build SRC_DIR ?= src TEST_DIR ?= test -INC_DIRS ?= include +3RDPARTY_DIR ?= thirdparty +INCLUDE_DIR ?= include +INC_DIRS ?= $(INCLUDE_DIR) $(3RDPARTY_DIR)/include LIB := $(BUILD_DIR)/$(LIB_FILENAME) SRCS != find '$(SRC_DIR)' -iname '*.c' SRCS_H != find $(INC_DIRS) '$(SRC_DIR)' -iname '*.h' SRCS_TEST != find '$(TEST_DIR)' -iname '*.c' +SRCS_3RDPARTY != find '$(3RDPARTY_DIR)/src' -iname '*.c' -OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) +$(info ${SRCS}) + +OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) $(SRCS_3RDPARTY:%=$(BUILD_DIR)/%.o) OBJS_TEST := $(SRCS_TEST:%=$(BUILD_DIR)/%.o) DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) $(SRCS_TEST:%=$(BUILD_DIR)/%.d) @@ -51,6 +56,9 @@ $(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c mkdir -p $(dir $@) $(CC) $(VIETERCFLAGS) -c $< -o $@ +$(BUILD_DIR)/$(3RDPARTY_DIR)/src/%.c.o: $(3RDPARTY_DIR)/src/%.c + mkdir -p $(dir $@) + $(CC) $(VIETERCFLAGS) -c $< -o $@ # =====TESTING===== .PHONY: test diff --git a/src/package/sha256.h b/thirdparty/include/sha256.h similarity index 100% rename from src/package/sha256.h rename to thirdparty/include/sha256.h diff --git a/src/package/sha256.c b/thirdparty/src/sha256.c similarity index 100% rename from src/package/sha256.c rename to thirdparty/src/sha256.c From e253e039c33d3abf192b8873b85a1b7a5266a6fc Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 2 Feb 2023 11:17:16 +0100 Subject: [PATCH 69/74] chore(package): ran fmt --- include/vieter_package.h | 11 +- src/package/vieter_package.c | 379 +++++++++++++------------- src/package/vieter_package_dynarray.c | 72 ++--- src/package/vieter_package_info.c | 131 ++++----- 4 files changed, 302 insertions(+), 291 deletions(-) diff --git a/include/vieter_package.h b/include/vieter_package.h index c9a941e..fb220c8 100644 --- a/include/vieter_package.h +++ b/include/vieter_package.h @@ -4,9 +4,9 @@ typedef struct vieter_package vieter_package; typedef enum vieter_package_error { - vieter_package_ok = 0, - vieter_package_unarchive_error = 1, - vieter_package_stat_error = 2 + vieter_package_ok = 0, + vieter_package_unarchive_error = 1, + vieter_package_stat_error = 2 } vieter_package_error; /* @@ -17,12 +17,13 @@ vieter_package *vieter_package_init(); /* * Parse package file into something usable by libvieter. */ -vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path); +vieter_package_error vieter_package_read_archive(vieter_package *pkg, + const char *pkg_path); /* * Deallocate a package. */ -void vieter_package_free(vieter_package ** ptp); +void vieter_package_free(vieter_package **ptp); /* * Create string that will become the package's desc file. diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index d1ef6c4..4bb7622 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -1,245 +1,246 @@ -#include -#include #include #include +#include +#include -#include "vieter_package_internal.h" #include "sha256.h" +#include "vieter_package_internal.h" -#define ADD_STRING(section, field) if (pkg_info->field != 0) { \ - size_to_be_written = snprintf(aux, small_buff_size, section, pkg_info->field); \ - if (size_to_be_written > small_buff_size) { \ - aux = realloc(aux, size_to_be_written + 1); \ - small_buff_size = size_to_be_written + 1; \ - snprintf(aux, small_buff_size, section, pkg_info->field); \ - } \ - if (buff_size < strlen(description) + small_buff_size + 1) { \ - description = realloc(description, buff_size * 2); \ - buff_size *= 2; \ - } \ - strcat(description, aux); \ -} +#define ADD_STRING(section, field) \ + if (pkg_info->field != 0) { \ + size_to_be_written = \ + snprintf(aux, small_buff_size, section, pkg_info->field); \ + if (size_to_be_written > small_buff_size) { \ + aux = realloc(aux, size_to_be_written + 1); \ + small_buff_size = size_to_be_written + 1; \ + snprintf(aux, small_buff_size, section, pkg_info->field); \ + } \ + if (buff_size < strlen(description) + small_buff_size + 1) { \ + description = realloc(description, buff_size * 2); \ + buff_size *= 2; \ + } \ + strcat(description, aux); \ + } -#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \ - ADD_STRING(section, field->array[i]); i++; \ - while (pkg_info->field->array[i] != NULL) { \ - ADD_STRING("\n%s", field->array[i]); i++; \ - } \ -} +#define ADD_ARRAY(section, field) \ + i = 0; \ + if (pkg_info->field != NULL) { \ + ADD_STRING(section, field->array[i]); \ + i++; \ + while (pkg_info->field->array[i] != NULL) { \ + ADD_STRING("\n%s", field->array[i]); \ + i++; \ + } \ + } -static char *ignored_names[5] = { - ".BUILDINFO", - ".INSTALL", - ".MTREE", - ".PKGINFO", - ".CHANGELOG" -}; +static char *ignored_names[5] = {".BUILDINFO", ".INSTALL", ".MTREE", ".PKGINFO", + ".CHANGELOG"}; static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *); vieter_package *vieter_package_init() { - return calloc(sizeof(vieter_package_info), 1); + return calloc(sizeof(vieter_package_info), 1); } -vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path) { - struct archive *a = archive_read_new(); - struct archive_entry *entry = archive_entry_new(); +vieter_package_error vieter_package_read_archive(vieter_package *pkg, + const char *pkg_path) { + struct archive *a = archive_read_new(); + struct archive_entry *entry = archive_entry_new(); - // These three are the most commonly used compression methods - archive_read_support_filter_zstd(a); - archive_read_support_filter_gzip(a); - archive_read_support_filter_xz(a); + // These three are the most commonly used compression methods + archive_read_support_filter_zstd(a); + archive_read_support_filter_gzip(a); + archive_read_support_filter_xz(a); - // Contents should always be a tarball - archive_read_support_format_tar(a); + // Contents should always be a tarball + archive_read_support_format_tar(a); - // TODO where does this 10240 come from? - int r = archive_read_open_filename(a, pkg_path, 10240); + // TODO where does this 10240 come from? + int r = archive_read_open_filename(a, pkg_path, 10240); - // Exit early if we weren't able to successfully open the archive for reading - if (r != ARCHIVE_OK) { - return vieter_package_unarchive_error; - } + // Exit early if we weren't able to successfully open the archive for reading + if (r != ARCHIVE_OK) { + return vieter_package_unarchive_error; + } - int compression_code = archive_filter_code(a, 0); - const char *path_name; + int compression_code = archive_filter_code(a, 0); + const char *path_name; - vieter_package_info *pkg_info; - vieter_package_dynarray *files = vieter_package_dynarray_init(16); - vieter_package_dynarray_add(files, "%FILES%"); + vieter_package_info *pkg_info; + vieter_package_dynarray *files = vieter_package_dynarray_init(16); + vieter_package_dynarray_add(files, "%FILES%"); - while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { - path_name = archive_entry_pathname(entry); + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + path_name = archive_entry_pathname(entry); - bool ignore = false; + bool ignore = false; - for (size_t i = 0; i < ignored_words_len; i++) { - if (strcmp(path_name, ignored_names[i]) == 0) { - ignore = true; - break; - } - } + for (size_t i = 0; i < ignored_words_len; i++) { + if (strcmp(path_name, ignored_names[i]) == 0) { + ignore = true; + break; + } + } - if (!ignore) { - vieter_package_dynarray_add(files, path_name); - } + if (!ignore) { + vieter_package_dynarray_add(files, path_name); + } - if (strcmp(path_name, ".PKGINFO") == 0) { - // Read data of file into memory buffer - int size = archive_entry_size(entry); - char *buf = malloc(size); - archive_read_data(a, buf, size); + if (strcmp(path_name, ".PKGINFO") == 0) { + // Read data of file into memory buffer + int size = archive_entry_size(entry); + char *buf = malloc(size); + archive_read_data(a, buf, size); - // Parse package vieter_package_info string into a struct - pkg_info = vieter_package_info_init(); - vieter_package_info_parse(pkg_info, buf); + // Parse package vieter_package_info string into a struct + pkg_info = vieter_package_info_init(); + vieter_package_info_parse(pkg_info, buf); - free(buf); - } else { - archive_read_data_skip(a); - } - } + free(buf); + } else { + archive_read_data_skip(a); + } + } - // Get size of file - struct stat stats; + // Get size of file + struct stat stats; - if (stat(pkg_path, &stats) != 0) { - // errno is set if stat() fails; the calling function should check - // the value of errno in case vieter_package_stat_error is returned - return vieter_package_stat_error; - } + if (stat(pkg_path, &stats) != 0) { + // errno is set if stat() fails; the calling function should check + // the value of errno in case vieter_package_stat_error is returned + return vieter_package_stat_error; + } - pkg_info->csize = stats.st_size; + pkg_info->csize = stats.st_size; - archive_read_free(a); + archive_read_free(a); - // Create final return value - pkg->path = strdup(pkg_path); - pkg->info = pkg_info; - pkg->files = files; - pkg->compression = compression_code; + // Create final return value + pkg->path = strdup(pkg_path); + pkg->info = pkg_info; + pkg->files = files; + pkg->compression = compression_code; - return vieter_package_ok; + return vieter_package_ok; } void vieter_package_sha256sum(vieter_package *pkg, char *res) { - FILE *f = fopen(pkg->path, "r"); - // Try to read 100KiB at a time - unsigned char *in = malloc(102400); - // Actual number of bytes read - size_t read_size; + FILE *f = fopen(pkg->path, "r"); + // Try to read 100KiB at a time + unsigned char *in = malloc(102400); + // Actual number of bytes read + size_t read_size; - SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); - sha256_init(ctx); - while ((read_size = fread(in, 1, 102400, f)) != 0) { - sha256_update(ctx, in, read_size); - } - unsigned char hash[SHA256_BLOCK_SIZE]; + SHA256_CTX *ctx = malloc(sizeof(SHA256_CTX)); + sha256_init(ctx); + while ((read_size = fread(in, 1, 102400, f)) != 0) { + sha256_update(ctx, in, read_size); + } + unsigned char hash[SHA256_BLOCK_SIZE]; - sha256_final(ctx, hash); + sha256_final(ctx, hash); - fclose(f); - free(in); - free(ctx); + fclose(f); + free(in); + free(ctx); - // We need to convert the bytes in the hash to get a string representation of its hex values - // i.e. turn 1001 1111 into the string "9f" - // Each byte of the hash is going to turn into two bytes in the final string - // so we are going to convert each half byte into a char - unsigned int half_byte = 0; - int j = 0; + // We need to convert the bytes in the hash to get a string representation of + // its hex values i.e. turn 1001 1111 into the string "9f" Each byte of the + // hash is going to turn into two bytes in the final string so we are going to + // convert each half byte into a char + unsigned int half_byte = 0; + int j = 0; - // We advance 2 bytes in the string for every one byte of the hash - for (int i = 0; i < SHA256_BLOCK_SIZE; i++) { - // We transform the first half byte into the second character to keep - // each byte from becoming reversed in the final string - half_byte = hash[i] & 0b1111; - if (half_byte < 10) { - res[j+1] = half_byte + 48; - } else { - res[j+1] = half_byte + 87; - } - hash[i] = hash[i] >> 4; - half_byte = hash[i] & 0b1111; - if (half_byte < 10) { - res[j] = half_byte + 48; - } else { - res[j] = half_byte + 87; - } + // We advance 2 bytes in the string for every one byte of the hash + for (int i = 0; i < SHA256_BLOCK_SIZE; i++) { + // We transform the first half byte into the second character to keep + // each byte from becoming reversed in the final string + half_byte = hash[i] & 0b1111; + if (half_byte < 10) { + res[j + 1] = half_byte + 48; + } else { + res[j + 1] = half_byte + 87; + } + hash[i] = hash[i] >> 4; + half_byte = hash[i] & 0b1111; + if (half_byte < 10) { + res[j] = half_byte + 48; + } else { + res[j] = half_byte + 87; + } - j += 2; - } - res[j] = '\0'; + j += 2; + } + res[j] = '\0'; } - - char *vieter_package_to_description(vieter_package *pkg) { - vieter_package_info *pkg_info = pkg->info; + vieter_package_info *pkg_info = pkg->info; - size_t buff_size = 1024; - int small_buff_size = 128; - int size_to_be_written; - char *aux = malloc(sizeof(char) * small_buff_size); - char *description = malloc(sizeof(char) * buff_size); - // Helper variable for ADD_ARRAY macro - int i; + size_t buff_size = 1024; + int small_buff_size = 128; + int size_to_be_written; + char *aux = malloc(sizeof(char) * small_buff_size); + char *description = malloc(sizeof(char) * buff_size); + // Helper variable for ADD_ARRAY macro + int i; - // special case for FILENAME - // assuming .pkg.tar.zst; other formats are valid, this should account for that - size_to_be_written = snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, - pkg_info->version, pkg_info->arch); + // special case for FILENAME + // assuming .pkg.tar.zst; other formats are valid, this should account for + // that + size_to_be_written = + snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", + pkg_info->name, pkg_info->version, pkg_info->arch); - // We neither want to let an arbritrarily long input to overflow the buffer - // nor to truncate perfectly valid inputs - if (size_to_be_written > small_buff_size) { - aux = realloc(aux, size_to_be_written + 1); - small_buff_size = size_to_be_written + 1; - snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, - pkg_info->version, pkg_info->arch); - } - strcpy(description, aux); + // We neither want to let an arbritrarily long input to overflow the buffer + // nor to truncate perfectly valid inputs + if (size_to_be_written > small_buff_size) { + aux = realloc(aux, size_to_be_written + 1); + small_buff_size = size_to_be_written + 1; + snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", + pkg_info->name, pkg_info->version, pkg_info->arch); + } + strcpy(description, aux); - ADD_STRING("\n\n%%NAME%%\n%s", name); - ADD_STRING("\n\n%%BASE%%\n%s", base); - ADD_STRING("\n\n%%VERSION%%\n%s", version); - ADD_STRING("\n\n%%DESC%%\n%s", description); - ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); - ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); - ADD_STRING("\n\n%%ISIZE%%\n%ld", size); + ADD_STRING("\n\n%%NAME%%\n%s", name); + ADD_STRING("\n\n%%BASE%%\n%s", base); + ADD_STRING("\n\n%%VERSION%%\n%s", version); + ADD_STRING("\n\n%%DESC%%\n%s", description); + ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups); + ADD_STRING("\n\n%%CSIZE%%\n%ld", csize); + ADD_STRING("\n\n%%ISIZE%%\n%ld", size); - char checksum[SHA256_BLOCK_SIZE * 2 + 1]; - vieter_package_sha256sum(pkg, checksum); + char checksum[SHA256_BLOCK_SIZE * 2 + 1]; + vieter_package_sha256sum(pkg, checksum); - snprintf(aux, small_buff_size, "\n\n%%SHA256SUM%%\n%s", checksum); - if (buff_size < strlen(description) + small_buff_size + 1) { - description = realloc(description, buff_size * 2); - buff_size *= 2; - } - strcat(description, aux); + snprintf(aux, small_buff_size, "\n\n%%SHA256SUM%%\n%s", checksum); + if (buff_size < strlen(description) + small_buff_size + 1) { + description = realloc(description, buff_size * 2); + buff_size *= 2; + } + strcat(description, aux); - ADD_STRING("\n\n%%URL%%\n%s", url); - ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses); - ADD_STRING("\n\n%%ARCH%%\n%s", arch); - ADD_STRING("\n\n%%BUILDDATE%%\n%ld", build_date); - ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); - ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces); - ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts); - ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides); - ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); - ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends); - ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); - ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); + ADD_STRING("\n\n%%URL%%\n%s", url); + ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses); + ADD_STRING("\n\n%%ARCH%%\n%s", arch); + ADD_STRING("\n\n%%BUILDDATE%%\n%ld", build_date); + ADD_STRING("\n\n%%PACKAGER%%\n%s", packager); + ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces); + ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts); + ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides); + ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends); + ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends); + ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends); + ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends); - strcat(description, "\n\n"); + strcat(description, "\n\n"); - return description; + return description; } void vieter_package_free(vieter_package **ptp) { - FREE_STRING((*ptp)->path); - vieter_package_info_free((*ptp)->info); - vieter_package_dynarray_free((*ptp)->files); - free(*ptp); - *ptp = NULL; - + FREE_STRING((*ptp)->path); + vieter_package_info_free((*ptp)->info); + vieter_package_dynarray_free((*ptp)->files); + free(*ptp); + *ptp = NULL; } diff --git a/src/package/vieter_package_dynarray.c b/src/package/vieter_package_dynarray.c index 6da07ee..a29c843 100644 --- a/src/package/vieter_package_dynarray.c +++ b/src/package/vieter_package_dynarray.c @@ -1,56 +1,58 @@ #include "vieter_package_dynarray.h" vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity) { - vieter_package_dynarray *da = malloc(sizeof(vieter_package_dynarray)); - da->size = 0; - da->capacity = initial_capacity; + vieter_package_dynarray *da = malloc(sizeof(vieter_package_dynarray)); + da->size = 0; + da->capacity = initial_capacity; - return da; + return da; } void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { - // An empty vieter_package_dynarray does not have an allocated internal array yet - if (da->size == 0) { - da->array = malloc(sizeof(char*) * da->capacity); + // An empty vieter_package_dynarray does not have an allocated internal array + // yet + if (da->size == 0) { + da->array = malloc(sizeof(char *) * da->capacity); - // Initialise all char*'s to 0 so array[i] == NULL can be used to see if field is empty - memset(da->array, 0, sizeof(char*) * da->capacity); - } - // Double array size if it's full - else if (da->size == da->capacity) { - // if the realloc fails, access to memory in da->array is lost - da->array = realloc(da->array, sizeof(char*) * da->capacity * 2); - da->capacity *= 2; + // Initialise all char*'s to 0 so array[i] == NULL can be used to see if + // field is empty + memset(da->array, 0, sizeof(char *) * da->capacity); + } + // Double array size if it's full + else if (da->size == da->capacity) { + // if the realloc fails, access to memory in da->array is lost + da->array = realloc(da->array, sizeof(char *) * da->capacity * 2); + da->capacity *= 2; - // Same as the previous memset, but only for newly allocated pointers - memset(da->array + da->size, 0, sizeof(char*) * da->capacity / 2); - } - - da->array[da->size] = strdup(s); - da->size++; + // Same as the previous memset, but only for newly allocated pointers + memset(da->array + da->size, 0, sizeof(char *) * da->capacity / 2); + } + + da->array[da->size] = strdup(s); + da->size++; } void vieter_package_dynarray_free(vieter_package_dynarray *da) { - if (da == NULL) { - return; - } + if (da == NULL) { + return; + } - if (da->array != NULL) { - for (size_t i = 0; i < da->size; i++) { - free(da->array[i]); - } + if (da->array != NULL) { + for (size_t i = 0; i < da->size; i++) { + free(da->array[i]); + } - free(da->array); - } + free(da->array); + } - free(da); + free(da); } char **vieter_package_dynarray_convert(vieter_package_dynarray *da) { - char **array = da->array; + char **array = da->array; - da->array = NULL; - vieter_package_dynarray_free(da); + da->array = NULL; + vieter_package_dynarray_free(da); - return array; + return array; } diff --git a/src/package/vieter_package_info.c b/src/package/vieter_package_info.c index 5ed040e..1dfd0b7 100644 --- a/src/package/vieter_package_info.c +++ b/src/package/vieter_package_info.c @@ -2,78 +2,85 @@ #include "vieter_package_info.h" -#define PKG_INFO_STRING(key_ptr, field) if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ - value_ptr += strlen(key_ptr);\ - tail_ptr = strchr(value_ptr, '\n');\ - tail_ptr[0] = '\0'; \ - pkg_info->field = strdup(value_ptr); \ - tail_ptr[0] = '\n'; \ -} value_ptr = tail_ptr; +#define PKG_INFO_STRING(key_ptr, field) \ + if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ + value_ptr += strlen(key_ptr); \ + tail_ptr = strchr(value_ptr, '\n'); \ + tail_ptr[0] = '\0'; \ + pkg_info->field = strdup(value_ptr); \ + tail_ptr[0] = '\n'; \ + } \ + value_ptr = tail_ptr; -#define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr);\ - tail_ptr = strchr(value_ptr, '\n');\ - tail_ptr[0] = '\0'; \ - pkg_info->field = atoi(value_ptr); \ - tail_ptr[0] = '\n'; \ - value_ptr = tail_ptr; +#define PKG_INFO_INT(key_ptr, field) \ + value_ptr = strstr(value_ptr, key_ptr) + strlen(key_ptr); \ + tail_ptr = strchr(value_ptr, '\n'); \ + tail_ptr[0] = '\0'; \ + pkg_info->field = atoi(value_ptr); \ + tail_ptr[0] = '\n'; \ + value_ptr = tail_ptr; -#define PKG_INFO_ARRAY(key_ptr, field) while((value_ptr = strstr(value_ptr, key_ptr)) != NULL){ \ - value_ptr = value_ptr + strlen(key_ptr);\ - tail_ptr = strchr(value_ptr, '\n'); \ - tail_ptr[0] = '\0'; \ - if(pkg_info->field == NULL) { pkg_info->field = vieter_package_dynarray_init(4); } \ - vieter_package_dynarray_add(pkg_info->field, value_ptr); \ - tail_ptr[0] = '\n'; \ - value_ptr = tail_ptr;\ -} value_ptr = tail_ptr; +#define PKG_INFO_ARRAY(key_ptr, field) \ + while ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \ + value_ptr = value_ptr + strlen(key_ptr); \ + tail_ptr = strchr(value_ptr, '\n'); \ + tail_ptr[0] = '\0'; \ + if (pkg_info->field == NULL) { \ + pkg_info->field = vieter_package_dynarray_init(4); \ + } \ + vieter_package_dynarray_add(pkg_info->field, value_ptr); \ + tail_ptr[0] = '\n'; \ + value_ptr = tail_ptr; \ + } \ + value_ptr = tail_ptr; vieter_package_info *vieter_package_info_init() { - return calloc(1, sizeof(vieter_package_info)); + return calloc(1, sizeof(vieter_package_info)); } void vieter_package_info_free(vieter_package_info *pkg_info) { - FREE_STRING(pkg_info->name); - FREE_STRING(pkg_info->base); - FREE_STRING(pkg_info->version); - FREE_STRING(pkg_info->description); - FREE_STRING(pkg_info->url); - FREE_STRING(pkg_info->arch); - FREE_STRING(pkg_info->packager); - FREE_STRING(pkg_info->pgpsig); + FREE_STRING(pkg_info->name); + FREE_STRING(pkg_info->base); + FREE_STRING(pkg_info->version); + FREE_STRING(pkg_info->description); + FREE_STRING(pkg_info->url); + FREE_STRING(pkg_info->arch); + FREE_STRING(pkg_info->packager); + FREE_STRING(pkg_info->pgpsig); - vieter_package_dynarray_free(pkg_info->groups); - vieter_package_dynarray_free(pkg_info->licenses); - vieter_package_dynarray_free(pkg_info->replaces); - vieter_package_dynarray_free(pkg_info->depends); - vieter_package_dynarray_free(pkg_info->conflicts); - vieter_package_dynarray_free(pkg_info->provides); - vieter_package_dynarray_free(pkg_info->optdepends); - vieter_package_dynarray_free(pkg_info->makedepends); - vieter_package_dynarray_free(pkg_info->checkdepends); + vieter_package_dynarray_free(pkg_info->groups); + vieter_package_dynarray_free(pkg_info->licenses); + vieter_package_dynarray_free(pkg_info->replaces); + vieter_package_dynarray_free(pkg_info->depends); + vieter_package_dynarray_free(pkg_info->conflicts); + vieter_package_dynarray_free(pkg_info->provides); + vieter_package_dynarray_free(pkg_info->optdepends); + vieter_package_dynarray_free(pkg_info->makedepends); + vieter_package_dynarray_free(pkg_info->checkdepends); - free(pkg_info); + free(pkg_info); } -void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str) { - char *value_ptr = pkg_info_str, *tail_ptr; - - PKG_INFO_STRING("\npkgname = ", name); - PKG_INFO_STRING("\npkgbase = ", base); - PKG_INFO_STRING("\npkgver = ", version); - PKG_INFO_STRING("\npkgdesc = ", description); - PKG_INFO_STRING("\nurl = ", url); - PKG_INFO_INT("\nbuilddate = ", build_date); - PKG_INFO_STRING("\npackager = ", packager); - PKG_INFO_INT("\nsize = ", size); - PKG_INFO_STRING("\narch = ", arch); - PKG_INFO_ARRAY("\nlicense = ", licenses); - PKG_INFO_ARRAY("\nreplaces = ", replaces); - PKG_INFO_ARRAY("\ngroup = ", groups); - PKG_INFO_ARRAY("\nconflict = ", conflicts); - PKG_INFO_ARRAY("\nprovides = ", provides); - PKG_INFO_ARRAY("\ndepend = ", depends); - PKG_INFO_ARRAY("\noptdepend = ", optdepends); - PKG_INFO_ARRAY("\nmakedepend = ", makedepends); - PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends); +void vieter_package_info_parse(vieter_package_info *pkg_info, + char *pkg_info_str) { + char *value_ptr = pkg_info_str, *tail_ptr; + PKG_INFO_STRING("\npkgname = ", name); + PKG_INFO_STRING("\npkgbase = ", base); + PKG_INFO_STRING("\npkgver = ", version); + PKG_INFO_STRING("\npkgdesc = ", description); + PKG_INFO_STRING("\nurl = ", url); + PKG_INFO_INT("\nbuilddate = ", build_date); + PKG_INFO_STRING("\npackager = ", packager); + PKG_INFO_INT("\nsize = ", size); + PKG_INFO_STRING("\narch = ", arch); + PKG_INFO_ARRAY("\nlicense = ", licenses); + PKG_INFO_ARRAY("\nreplaces = ", replaces); + PKG_INFO_ARRAY("\ngroup = ", groups); + PKG_INFO_ARRAY("\nconflict = ", conflicts); + PKG_INFO_ARRAY("\nprovides = ", provides); + PKG_INFO_ARRAY("\ndepend = ", depends); + PKG_INFO_ARRAY("\noptdepend = ", optdepends); + PKG_INFO_ARRAY("\nmakedepend = ", makedepends); + PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends); } From df83bf9fb32f4090ac977a262faa5262a8110298 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Thu, 2 Feb 2023 11:02:31 +0000 Subject: [PATCH 70/74] fix: Initialise variables to keep CI from breaking. --- src/package/vieter_package.c | 2 +- src/package/vieter_package_info.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 4bb7622..e5530e4 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -65,7 +65,7 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, int compression_code = archive_filter_code(a, 0); const char *path_name; - vieter_package_info *pkg_info; + vieter_package_info *pkg_info = NULL; vieter_package_dynarray *files = vieter_package_dynarray_init(16); vieter_package_dynarray_add(files, "%FILES%"); diff --git a/src/package/vieter_package_info.c b/src/package/vieter_package_info.c index 1dfd0b7..ff5f1fe 100644 --- a/src/package/vieter_package_info.c +++ b/src/package/vieter_package_info.c @@ -63,7 +63,7 @@ void vieter_package_info_free(vieter_package_info *pkg_info) { void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str) { - char *value_ptr = pkg_info_str, *tail_ptr; + char *value_ptr = pkg_info_str, *tail_ptr = NULL; PKG_INFO_STRING("\npkgname = ", name); PKG_INFO_STRING("\npkgbase = ", base); From ea852f9102545552cb79ba67938f7845721c2db6 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Thu, 2 Feb 2023 11:42:00 +0000 Subject: [PATCH 71/74] refactor: Package extension now depends on what compression method was detected. --- src/package/vieter_package.c | 22 ++++++++++++++++++---- test/package/test_package.c | 2 ++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index e5530e4..5c61d45 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -185,11 +185,25 @@ char *vieter_package_to_description(vieter_package *pkg) { int i; // special case for FILENAME - // assuming .pkg.tar.zst; other formats are valid, this should account for - // that + char *ext; + switch (pkg->compression) { + case 0: + ext = ".tar"; + break; + case 1: + ext = ".tar.gz"; + break; + case 6: + ext = ".tar.xz"; + break; + case 14: + ext = ".tar.zst"; + break; + } + size_to_be_written = - snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", - pkg_info->name, pkg_info->version, pkg_info->arch); + snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg%s", + pkg_info->name, pkg_info->version, pkg_info->arch, ext); // We neither want to let an arbritrarily long input to overflow the buffer // nor to truncate perfectly valid inputs diff --git a/test/package/test_package.c b/test/package/test_package.c index 3c8b249..d4dd981 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -78,6 +78,8 @@ void test_pkg_read_archive_desc() { fclose(f); TEST_CHECK(!strcmp(description, desc)); + + vieter_package_free(&pkg); } TEST_LIST = { From 96d07dfb54bb2191a27095e5192406b75dad8835 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Thu, 2 Feb 2023 12:45:32 +0000 Subject: [PATCH 72/74] fix: Initialised variable to keep CI from breaking (again). --- src/package/vieter_package.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 5c61d45..bec0bf5 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -185,7 +185,7 @@ char *vieter_package_to_description(vieter_package *pkg) { int i; // special case for FILENAME - char *ext; + char *ext = NULL; switch (pkg->compression) { case 0: ext = ".tar"; From 19c5515c5e4045e7cbc7a6ddf8a04b3a40325875 Mon Sep 17 00:00:00 2001 From: GreekStapler Date: Thu, 2 Feb 2023 19:29:34 +0000 Subject: [PATCH 73/74] fix: Plug memory leaks and fix strings that were not null terminated. --- src/package/vieter_package.c | 7 +++++-- test/package/test_package.c | 11 +++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index bec0bf5..4bce4f5 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -44,7 +44,7 @@ vieter_package *vieter_package_init() { vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *pkg_path) { struct archive *a = archive_read_new(); - struct archive_entry *entry = archive_entry_new(); + struct archive_entry *entry; // These three are the most commonly used compression methods archive_read_support_filter_zstd(a); @@ -88,8 +88,9 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, if (strcmp(path_name, ".PKGINFO") == 0) { // Read data of file into memory buffer int size = archive_entry_size(entry); - char *buf = malloc(size); + char *buf = malloc(size + 1); archive_read_data(a, buf, size); + buf[size] = '\0'; // Parse package vieter_package_info string into a struct pkg_info = vieter_package_info_init(); @@ -248,6 +249,8 @@ char *vieter_package_to_description(vieter_package *pkg) { strcat(description, "\n\n"); + free(aux); + return description; } diff --git a/test/package/test_package.c b/test/package/test_package.c index d4dd981..bcefdf6 100644 --- a/test/package/test_package.c +++ b/test/package/test_package.c @@ -8,8 +8,9 @@ void test_info_parse() { size_t size = ftell(f); fflush(stdout); rewind(f); - char *pkg_info_str = malloc(size); + char *pkg_info_str = malloc(size + 1); fread(pkg_info_str, 1, size, f); + pkg_info_str[size] = '\0'; fclose(f); vieter_package_info *pkg_info = vieter_package_info_init(); @@ -36,6 +37,9 @@ void test_info_parse() { TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7")); TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen")); TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8")); + + free(pkg_info_str); + vieter_package_info_free(pkg_info); } void test_pkg_read_archive_files() { @@ -73,13 +77,16 @@ void test_pkg_read_archive_desc() { fseek(f, 0, SEEK_END); size_t size = ftell(f); rewind(f); - char *desc = malloc(size); + char *desc = malloc(size + 1); fread(desc, 1, size, f); + desc[size] = '\0'; fclose(f); TEST_CHECK(!strcmp(description, desc)); vieter_package_free(&pkg); + free(description); + free(desc); } TEST_LIST = { From 1f9bd26ae5b4b141cc8d1e7e117646efecf1bf04 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 23 Feb 2023 09:54:50 +0100 Subject: [PATCH 74/74] refactor: move dynarray into own module --- include/vieter_dynarray.h | 34 ++++++++++++++++++ .../vieter_dynarray.c} | 16 ++++----- src/package/vieter_package.c | 8 ++--- src/package/vieter_package_dynarray.h | 36 ------------------- src/package/vieter_package_info.c | 22 ++++++------ src/package/vieter_package_info.h | 20 +++++------ src/package/vieter_package_internal.h | 4 +-- 7 files changed, 69 insertions(+), 71 deletions(-) create mode 100644 include/vieter_dynarray.h rename src/{package/vieter_package_dynarray.c => dynarray/vieter_dynarray.c} (65%) delete mode 100644 src/package/vieter_package_dynarray.h diff --git a/include/vieter_dynarray.h b/include/vieter_dynarray.h new file mode 100644 index 0000000..2a6305e --- /dev/null +++ b/include/vieter_dynarray.h @@ -0,0 +1,34 @@ +#ifndef VIETER_DYNARRAY +#define VIETER_DYNARRAY + +#include +#include + +typedef struct vieter_dynarray { + char **array; + size_t capacity; + size_t size; +} vieter_dynarray; + +/* + * Allocate a dynamic array. + */ +vieter_dynarray *vieter_dynarray_init(size_t initial_capacity); + +/* + * Initialise array (if it's not already initialised) and insert a string. + */ +void vieter_dynarray_add(vieter_dynarray *da, const char *s); + +/* + * Deallocate dynamic array. + */ +void vieter_dynarray_free(vieter_dynarray *da); + +/* + * Convert a vieter_dynarray into an array by freeing all its surrounding + * components and returning the underlying array pointer. + */ +char **vieter_dynarray_convert(vieter_dynarray *da); + +#endif diff --git a/src/package/vieter_package_dynarray.c b/src/dynarray/vieter_dynarray.c similarity index 65% rename from src/package/vieter_package_dynarray.c rename to src/dynarray/vieter_dynarray.c index a29c843..5c4026b 100644 --- a/src/package/vieter_package_dynarray.c +++ b/src/dynarray/vieter_dynarray.c @@ -1,15 +1,15 @@ -#include "vieter_package_dynarray.h" +#include "vieter_dynarray.h" -vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity) { - vieter_package_dynarray *da = malloc(sizeof(vieter_package_dynarray)); +vieter_dynarray *vieter_dynarray_init(size_t initial_capacity) { + vieter_dynarray *da = malloc(sizeof(vieter_dynarray)); da->size = 0; da->capacity = initial_capacity; return da; } -void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { - // An empty vieter_package_dynarray does not have an allocated internal array +void vieter_dynarray_add(vieter_dynarray *da, const char *s) { + // An empty vieter_dynarray does not have an allocated internal array // yet if (da->size == 0) { da->array = malloc(sizeof(char *) * da->capacity); @@ -32,7 +32,7 @@ void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) { da->size++; } -void vieter_package_dynarray_free(vieter_package_dynarray *da) { +void vieter_dynarray_free(vieter_dynarray *da) { if (da == NULL) { return; } @@ -48,11 +48,11 @@ void vieter_package_dynarray_free(vieter_package_dynarray *da) { free(da); } -char **vieter_package_dynarray_convert(vieter_package_dynarray *da) { +char **vieter_dynarray_convert(vieter_dynarray *da) { char **array = da->array; da->array = NULL; - vieter_package_dynarray_free(da); + vieter_dynarray_free(da); return array; } diff --git a/src/package/vieter_package.c b/src/package/vieter_package.c index 4bce4f5..6aca847 100644 --- a/src/package/vieter_package.c +++ b/src/package/vieter_package.c @@ -66,8 +66,8 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, const char *path_name; vieter_package_info *pkg_info = NULL; - vieter_package_dynarray *files = vieter_package_dynarray_init(16); - vieter_package_dynarray_add(files, "%FILES%"); + vieter_dynarray *files = vieter_dynarray_init(16); + vieter_dynarray_add(files, "%FILES%"); while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { path_name = archive_entry_pathname(entry); @@ -82,7 +82,7 @@ vieter_package_error vieter_package_read_archive(vieter_package *pkg, } if (!ignore) { - vieter_package_dynarray_add(files, path_name); + vieter_dynarray_add(files, path_name); } if (strcmp(path_name, ".PKGINFO") == 0) { @@ -257,7 +257,7 @@ char *vieter_package_to_description(vieter_package *pkg) { void vieter_package_free(vieter_package **ptp) { FREE_STRING((*ptp)->path); vieter_package_info_free((*ptp)->info); - vieter_package_dynarray_free((*ptp)->files); + vieter_dynarray_free((*ptp)->files); free(*ptp); *ptp = NULL; } diff --git a/src/package/vieter_package_dynarray.h b/src/package/vieter_package_dynarray.h deleted file mode 100644 index c198ea1..0000000 --- a/src/package/vieter_package_dynarray.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef VIETER_DYNARRAY -#define VIETER_DYNARRAY - -#include -#include -#include "vieter_package.h" - -typedef struct vieter_package_dynarray vieter_package_dynarray; -struct vieter_package_dynarray { - char **array; - size_t capacity; - size_t size; -}; - -/* - * Allocate a dynamic array. - */ -vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity); - -/* - * Initialise array (if it's not already initialised) and insert a string. - */ -void vieter_package_dynarray_add(vieter_package_dynarray *da, const char * s); - -/* - * Deallocate dynamic array. - */ -void vieter_package_dynarray_free(vieter_package_dynarray *da); - -/* - * Convert a vieter_package_dynarray into an array by freeing all its surrounding components - * and returning the underlying array pointer. - */ -char **vieter_package_dynarray_convert(vieter_package_dynarray *da); - -#endif diff --git a/src/package/vieter_package_info.c b/src/package/vieter_package_info.c index ff5f1fe..4805206 100644 --- a/src/package/vieter_package_info.c +++ b/src/package/vieter_package_info.c @@ -26,9 +26,9 @@ tail_ptr = strchr(value_ptr, '\n'); \ tail_ptr[0] = '\0'; \ if (pkg_info->field == NULL) { \ - pkg_info->field = vieter_package_dynarray_init(4); \ + pkg_info->field = vieter_dynarray_init(4); \ } \ - vieter_package_dynarray_add(pkg_info->field, value_ptr); \ + vieter_dynarray_add(pkg_info->field, value_ptr); \ tail_ptr[0] = '\n'; \ value_ptr = tail_ptr; \ } \ @@ -48,15 +48,15 @@ void vieter_package_info_free(vieter_package_info *pkg_info) { FREE_STRING(pkg_info->packager); FREE_STRING(pkg_info->pgpsig); - vieter_package_dynarray_free(pkg_info->groups); - vieter_package_dynarray_free(pkg_info->licenses); - vieter_package_dynarray_free(pkg_info->replaces); - vieter_package_dynarray_free(pkg_info->depends); - vieter_package_dynarray_free(pkg_info->conflicts); - vieter_package_dynarray_free(pkg_info->provides); - vieter_package_dynarray_free(pkg_info->optdepends); - vieter_package_dynarray_free(pkg_info->makedepends); - vieter_package_dynarray_free(pkg_info->checkdepends); + vieter_dynarray_free(pkg_info->groups); + vieter_dynarray_free(pkg_info->licenses); + vieter_dynarray_free(pkg_info->replaces); + vieter_dynarray_free(pkg_info->depends); + vieter_dynarray_free(pkg_info->conflicts); + vieter_dynarray_free(pkg_info->provides); + vieter_dynarray_free(pkg_info->optdepends); + vieter_dynarray_free(pkg_info->makedepends); + vieter_dynarray_free(pkg_info->checkdepends); free(pkg_info); } diff --git a/src/package/vieter_package_info.h b/src/package/vieter_package_info.h index b931928..2c69d92 100644 --- a/src/package/vieter_package_info.h +++ b/src/package/vieter_package_info.h @@ -6,7 +6,7 @@ #include #include "vieter_package.h" -#include "vieter_package_dynarray.h" +#include "vieter_dynarray.h" typedef struct vieter_package_info { @@ -23,15 +23,15 @@ typedef struct vieter_package_info { char *pgpsig; int64_t pgpsigsize; - vieter_package_dynarray *groups; - vieter_package_dynarray *licenses; - vieter_package_dynarray *replaces; - vieter_package_dynarray *depends; - vieter_package_dynarray *conflicts; - vieter_package_dynarray *provides; - vieter_package_dynarray *optdepends; - vieter_package_dynarray *makedepends; - vieter_package_dynarray *checkdepends; + vieter_dynarray *groups; + vieter_dynarray *licenses; + vieter_dynarray *replaces; + vieter_dynarray *depends; + vieter_dynarray *conflicts; + vieter_dynarray *provides; + vieter_dynarray *optdepends; + vieter_dynarray *makedepends; + vieter_dynarray *checkdepends; } vieter_package_info; /* diff --git a/src/package/vieter_package_internal.h b/src/package/vieter_package_internal.h index fe84f17..4c4eef6 100644 --- a/src/package/vieter_package_internal.h +++ b/src/package/vieter_package_internal.h @@ -1,10 +1,10 @@ #include "vieter_package.h" #include "vieter_package_info.h" -#include "vieter_package_dynarray.h" +#include "vieter_dynarray.h" struct vieter_package { char *path; vieter_package_info *info; - vieter_package_dynarray *files; + vieter_dynarray *files; int compression; };