Refactor package module into C #6
|
|
@ -17,7 +17,8 @@ vieter_package *vieter_package_init();
|
||||||
/*
|
/*
|
||||||
* Parse package file into something usable by libvieter.
|
* 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.
|
* Deallocate a package.
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <archive.h>
|
#include <archive.h>
|
||||||
#include <archive_entry.h>
|
#include <archive_entry.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "vieter_package_internal.h"
|
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
|
#include "vieter_package_internal.h"
|
||||||
|
Jef Roosens
commented
General note for General note for `snprintf` usage: what happens if the value is larger than the buffer? Is it simply cut off? Cuz if so, we shouldn't be making assumptions about the length of the input.
GreekStapler
commented
I used I used `snprintf` because I didn't want to risk any buffer overflows, but it can truncate perfectly valid inputs if they are long enough (e.g. very long url). I'll turn `aux` into a malloc'd string and use the return value of `snprintf` to reallocate memory as is necessary without any overflows.
|
|||||||
|
|
||||||
#define ADD_STRING(section, field) if (pkg_info->field != 0) { \
|
#define ADD_STRING(section, field) \
|
||||||
size_to_be_written = snprintf(aux, small_buff_size, section, pkg_info->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) { \
|
if (size_to_be_written > small_buff_size) { \
|
||||||
aux = realloc(aux, size_to_be_written + 1); \
|
aux = realloc(aux, size_to_be_written + 1); \
|
||||||
small_buff_size = size_to_be_written + 1; \
|
small_buff_size = size_to_be_written + 1; \
|
||||||
|
|
@ -20,27 +22,27 @@
|
||||||
strcat(description, aux); \
|
strcat(description, aux); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \
|
#define ADD_ARRAY(section, field) \
|
||||||
ADD_STRING(section, field->array[i]); i++; \
|
i = 0; \
|
||||||
|
if (pkg_info->field != NULL) { \
|
||||||
|
ADD_STRING(section, field->array[i]); \
|
||||||
|
i++; \
|
||||||
while (pkg_info->field->array[i] != NULL) { \
|
while (pkg_info->field->array[i] != NULL) { \
|
||||||
ADD_STRING("\n%s", field->array[i]); i++; \
|
ADD_STRING("\n%s", field->array[i]); \
|
||||||
|
i++; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ignored_names[5] = {
|
static char *ignored_names[5] = {".BUILDINFO", ".INSTALL", ".MTREE", ".PKGINFO",
|
||||||
".BUILDINFO",
|
".CHANGELOG"};
|
||||||
".INSTALL",
|
|
||||||
".MTREE",
|
|
||||||
".PKGINFO",
|
|
||||||
".CHANGELOG"
|
|
||||||
};
|
|
||||||
static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *);
|
static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *);
|
||||||
|
|
||||||
vieter_package *vieter_package_init() {
|
vieter_package *vieter_package_init() {
|
||||||
return calloc(sizeof(vieter_package_info), 1);
|
return calloc(sizeof(vieter_package_info), 1);
|
||||||
|
GreekStapler marked this conversation as resolved
Outdated
Jef Roosens
commented
Shouldn't this be Shouldn't this be `sizeof(a package)`?
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
struct archive *a = archive_read_new();
|
struct archive *a = archive_read_new();
|
||||||
struct archive_entry *entry = archive_entry_new();
|
struct archive_entry *entry = archive_entry_new();
|
||||||
|
|
||||||
|
|
@ -141,10 +143,10 @@ void vieter_package_sha256sum(vieter_package *pkg, char *res) {
|
||||||
free(in);
|
free(in);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
|
|
||||||
// We need to convert the bytes in the hash to get a string representation of its hex values
|
// We need to convert the bytes in the hash to get a string representation of
|
||||||
// i.e. turn 1001 1111 into the string "9f"
|
// its hex values i.e. turn 1001 1111 into the string "9f" Each byte of the
|
||||||
// Each byte of the hash is going to turn into two bytes in the final string
|
// hash is going to turn into two bytes in the final string so we are going to
|
||||||
// so we are going to convert each half byte into a char
|
// convert each half byte into a char
|
||||||
unsigned int half_byte = 0;
|
unsigned int half_byte = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
|
|
@ -171,8 +173,6 @@ void vieter_package_sha256sum(vieter_package *pkg, char *res) {
|
||||||
res[j] = '\0';
|
res[j] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *vieter_package_to_description(vieter_package *pkg) {
|
char *vieter_package_to_description(vieter_package *pkg) {
|
||||||
|
Jef Roosens
commented
This should also use This should also use `SMALL_BUFF_SIZE` I think, just for consistency.
|
|||||||
vieter_package_info *pkg_info = pkg->info;
|
vieter_package_info *pkg_info = pkg->info;
|
||||||
|
|
||||||
|
|
@ -185,17 +185,19 @@ char *vieter_package_to_description(vieter_package *pkg) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// special case for FILENAME
|
// special case for FILENAME
|
||||||
// assuming .pkg.tar.zst; other formats are valid, this should account for that
|
// assuming .pkg.tar.zst; other formats are valid, this should account for
|
||||||
size_to_be_written = snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name,
|
// that
|
||||||
pkg_info->version, pkg_info->arch);
|
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
|
// We neither want to let an arbritrarily long input to overflow the buffer
|
||||||
// nor to truncate perfectly valid inputs
|
// nor to truncate perfectly valid inputs
|
||||||
if (size_to_be_written > small_buff_size) {
|
if (size_to_be_written > small_buff_size) {
|
||||||
aux = realloc(aux, size_to_be_written + 1);
|
aux = realloc(aux, size_to_be_written + 1);
|
||||||
small_buff_size = 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,
|
snprintf(aux, small_buff_size, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst",
|
||||||
pkg_info->version, pkg_info->arch);
|
pkg_info->name, pkg_info->version, pkg_info->arch);
|
||||||
}
|
}
|
||||||
strcpy(description, aux);
|
strcpy(description, aux);
|
||||||
|
|
||||||
|
|
@ -241,5 +243,4 @@ void vieter_package_free(vieter_package **ptp) {
|
||||||
vieter_package_dynarray_free((*ptp)->files);
|
vieter_package_dynarray_free((*ptp)->files);
|
||||||
free(*ptp);
|
free(*ptp);
|
||||||
*ptp = NULL;
|
*ptp = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ vieter_package_dynarray *vieter_package_dynarray_init(size_t initial_capacity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vieter_package_dynarray_add(vieter_package_dynarray *da, const char *s) {
|
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
|
// An empty vieter_package_dynarray does not have an allocated internal array
|
||||||
|
// yet
|
||||||
if (da->size == 0) {
|
if (da->size == 0) {
|
||||||
da->array = malloc(sizeof(char *) * da->capacity);
|
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
|
// 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);
|
memset(da->array, 0, sizeof(char *) * da->capacity);
|
||||||
}
|
}
|
||||||
// Double array size if it's full
|
// Double array size if it's full
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,37 @@
|
||||||
|
|
||||||
#include "vieter_package_info.h"
|
#include "vieter_package_info.h"
|
||||||
|
|
||||||
#define PKG_INFO_STRING(key_ptr, field) if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \
|
#define PKG_INFO_STRING(key_ptr, field) \
|
||||||
|
if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \
|
||||||
|
Jef Roosens
commented
How does this work? How does this work? `strstr` doens't write any terminating NULL bytes for the substring or anything, so won't this `strlen` call return the entire remaining size of the pkginfo string?
GreekStapler
commented
The The pkginfo string in here is The `strlen` is called on `key_ptr` which is just a small self contained string (e.g. "\ngroup = ") that is null terminated.
The pkginfo string in here is `value_ptr`.
|
|||||||
value_ptr += strlen(key_ptr); \
|
value_ptr += strlen(key_ptr); \
|
||||||
tail_ptr = strchr(value_ptr, '\n'); \
|
tail_ptr = strchr(value_ptr, '\n'); \
|
||||||
tail_ptr[0] = '\0'; \
|
tail_ptr[0] = '\0'; \
|
||||||
pkg_info->field = strdup(value_ptr); \
|
pkg_info->field = strdup(value_ptr); \
|
||||||
tail_ptr[0] = '\n'; \
|
tail_ptr[0] = '\n'; \
|
||||||
} value_ptr = tail_ptr;
|
} \
|
||||||
|
value_ptr = tail_ptr;
|
||||||
|
|
||||||
#define PKG_INFO_INT(key_ptr, field) value_ptr = strstr(value_ptr, key_ptr) + strlen(key_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 = strchr(value_ptr, '\n'); \
|
||||||
tail_ptr[0] = '\0'; \
|
tail_ptr[0] = '\0'; \
|
||||||
pkg_info->field = atoi(value_ptr); \
|
pkg_info->field = atoi(value_ptr); \
|
||||||
tail_ptr[0] = '\n'; \
|
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){ \
|
#define PKG_INFO_ARRAY(key_ptr, field) \
|
||||||
|
while ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \
|
||||||
value_ptr = value_ptr + strlen(key_ptr); \
|
value_ptr = value_ptr + strlen(key_ptr); \
|
||||||
tail_ptr = strchr(value_ptr, '\n'); \
|
tail_ptr = strchr(value_ptr, '\n'); \
|
||||||
tail_ptr[0] = '\0'; \
|
tail_ptr[0] = '\0'; \
|
||||||
if(pkg_info->field == NULL) { pkg_info->field = vieter_package_dynarray_init(4); } \
|
if (pkg_info->field == NULL) { \
|
||||||
|
pkg_info->field = vieter_package_dynarray_init(4); \
|
||||||
|
} \
|
||||||
vieter_package_dynarray_add(pkg_info->field, value_ptr); \
|
vieter_package_dynarray_add(pkg_info->field, value_ptr); \
|
||||||
tail_ptr[0] = '\n'; \
|
tail_ptr[0] = '\n'; \
|
||||||
value_ptr = tail_ptr; \
|
value_ptr = tail_ptr; \
|
||||||
} value_ptr = tail_ptr;
|
} \
|
||||||
|
value_ptr = tail_ptr;
|
||||||
|
|
||||||
vieter_package_info *vieter_package_info_init() {
|
vieter_package_info *vieter_package_info_init() {
|
||||||
return calloc(1, sizeof(vieter_package_info));
|
return calloc(1, sizeof(vieter_package_info));
|
||||||
|
|
@ -54,7 +61,8 @@ void vieter_package_info_free(vieter_package_info *pkg_info) {
|
||||||
free(pkg_info);
|
free(pkg_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vieter_package_info_parse(vieter_package_info *pkg_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;
|
char *value_ptr = pkg_info_str, *tail_ptr;
|
||||||
|
|
||||||
PKG_INFO_STRING("\npkgname = ", name);
|
PKG_INFO_STRING("\npkgname = ", name);
|
||||||
|
|
@ -75,5 +83,4 @@ void vieter_package_info_parse(vieter_package_info *pkg_info, char *pkg_info_str
|
||||||
PKG_INFO_ARRAY("\noptdepend = ", optdepends);
|
PKG_INFO_ARRAY("\noptdepend = ", optdepends);
|
||||||
PKG_INFO_ARRAY("\nmakedepend = ", makedepends);
|
PKG_INFO_ARRAY("\nmakedepend = ", makedepends);
|
||||||
PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends);
|
PKG_INFO_ARRAY("\ncheckdepend = ", checkdepends);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
I don't personally use this style of free function right now, but it might be interesting to migrate all free functions to this style indeed. I'm assuming the pointer-to-pointer is so you can set the variable containing the pointer to NULL as well?
Yeah, dangling pointers can cause some real headaches, so I prefer to have free functions set the pointer to NULL themselves to make it less error prone.