Refactor package module into C #6
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef VIETER_DYNARRAY
|
|
||||||
#define VIETER_DYNARRAY
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef VIETER_PACKAGE
|
|
||||||
#define VIETER_PACKAGE
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
#ifndef VIETER_PACKAGE_INFO
|
|
||||||
#define VIETER_PACKAGE_INFO
|
|
||||||
|
|
||||||
#define FREE_STRING(sp) if (sp != NULL) free(sp)
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#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
|
|
||||||
30
include/vieter_package.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef VIETER_PACKAGE
|
||||||
|
#define VIETER_PACKAGE
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <archive.h>
|
||||||
|
#include <archive_entry.h>
|
||||||
|
|
||||||
|
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
|
||||||
5
src/package/README.md
Normal file
|
|
@ -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.
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
#include "package.h"
|
#include "vieter_package_internal.h"
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
|
|
||||||
#define SMALL_BUFF_SIZE 128
|
#define SMALL_BUFF_SIZE 128
|
||||||
|
|
||||||
#define ADD_STRING(section, field) if (pkg_info->field != 0) { \
|
#define ADD_STRING(section, field) if (info->field != 0) { \
|
||||||
snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field); \
|
snprintf(aux, SMALL_BUFF_SIZE, section, info->field); \
|
||||||
|
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.
|
|||||||
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
|
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
|
||||||
description = realloc(description, buff_size * 2); \
|
description = realloc(description, buff_size * 2); \
|
||||||
buff_size *= 2; \
|
buff_size *= 2; \
|
||||||
} \
|
} \
|
||||||
strcat(description, aux); \
|
strcat(description, aux); \
|
||||||
}
|
}
|
||||||
#define ADD_ARRAY(section, field) i = 0; if (pkg_info->field != NULL) { \
|
#define ADD_ARRAY(section, field) i = 0; if (info->field != NULL) { \
|
||||||
snprintf(aux, SMALL_BUFF_SIZE, section, pkg_info->field->array[i]); i++; \
|
snprintf(aux, SMALL_BUFF_SIZE, section, info->field->array[i]); i++; \
|
||||||
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
|
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
|
||||||
description = realloc(description, buff_size * 2); \
|
description = realloc(description, buff_size * 2); \
|
||||||
buff_size *= 2; \
|
buff_size *= 2; \
|
||||||
} \
|
} \
|
||||||
strcat(description, aux); \
|
strcat(description, aux); \
|
||||||
while (pkg_info->field->array[i] != NULL) { \
|
while (info->field->array[i] != NULL) { \
|
||||||
|
Jef Roosens
commented
This check is not safe, the dynarray code doesn't make any guarantees about empty fields being NULL, they're simply malloc'ed and not initialised. This check is not safe, the dynarray code doesn't make any guarantees about empty fields being NULL, they're simply malloc'ed and not initialised.
|
|||||||
snprintf(aux, SMALL_BUFF_SIZE, "\n%s", pkg_info->field->array[i]); i++; \
|
snprintf(aux, SMALL_BUFF_SIZE, "\n%s", info->field->array[i]); i++; \
|
||||||
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
|
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
|
||||||
description = realloc(description, buff_size * 2); \
|
description = realloc(description, buff_size * 2); \
|
||||||
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 *);
|
static size_t ignored_words_len = sizeof(ignored_names) / sizeof(char *);
|
||||||
|
|
||||||
Pkg *package_init() {
|
Pkg *vieter_package_init() {
|
||||||
return calloc(sizeof(PkgInfo), 1);
|
return calloc(sizeof(pkg_info), 1);
|
||||||
|
GreekStapler marked this conversation as resolved
Outdated
Jef Roosens
commented
Shouldn't this be Shouldn't this be `sizeof(a package)`?
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 *a = archive_read_new();
|
||||||
struct archive_entry *entry = archive_entry_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);
|
int compression_code = archive_filter_code(a, 0);
|
||||||
const char *path_name;
|
const char *path_name;
|
||||||
|
|
||||||
PkgInfo *pkg_info;
|
pkg_info *info;
|
||||||
DynArray *files = dynarray_init(16);
|
dynarray *files = vieter_package_dynarray_init(16);
|
||||||
dynarray_add(files, "%FILES%");
|
vieter_package_dynarray_add(files, "%FILES%");
|
||||||
|
|
||||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||||
path_name = archive_entry_pathname(entry);
|
path_name = archive_entry_pathname(entry);
|
||||||
|
|
@ -81,7 +81,7 @@ Pkg *package_read_archive(const char *pkg_path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ignore) {
|
if (!ignore) {
|
||||||
dynarray_add(files, path_name);
|
vieter_package_dynarray_add(files, path_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(path_name, ".PKGINFO") == 0) {
|
if (strcmp(path_name, ".PKGINFO") == 0) {
|
||||||
|
|
@ -91,8 +91,8 @@ Pkg *package_read_archive(const char *pkg_path) {
|
||||||
archive_read_data(a, buf, size);
|
archive_read_data(a, buf, size);
|
||||||
|
|
||||||
// Parse package info string into a struct
|
// Parse package info string into a struct
|
||||||
pkg_info = package_info_init();
|
info = vieter_package_info_init();
|
||||||
package_info_parse(pkg_info, buf);
|
vieter_package_info_parse(info, buf);
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -107,21 +107,21 @@ Pkg *package_read_archive(const char *pkg_path) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg_info->csize = stats.st_size;
|
info->csize = stats.st_size;
|
||||||
|
|
||||||
archive_read_free(a);
|
archive_read_free(a);
|
||||||
|
|
||||||
// Create final return value
|
// Create final return value
|
||||||
Pkg *pkg = package_init();
|
Pkg *pkg = vieter_package_init();
|
||||||
pkg->path = strdup(pkg_path);
|
pkg->path = strdup(pkg_path);
|
||||||
pkg->info = pkg_info;
|
pkg->info = info;
|
||||||
pkg->files = files;
|
pkg->files = files;
|
||||||
pkg->compression = compression_code;
|
pkg->compression = compression_code;
|
||||||
|
|
||||||
return pkg;
|
return pkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha256sum(Pkg *pkg, char *res) {
|
void vieter_package_sha256sum(Pkg *pkg, char *res) {
|
||||||
|
Jef Roosens
commented
As mentioned on matrix, this function should become a streaming one. As mentioned on matrix, this function should become a streaming one.
|
|||||||
FILE *f = fopen(pkg->path, "r");
|
FILE *f = fopen(pkg->path, "r");
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
size_t size = ftell(f);
|
size_t size = ftell(f);
|
||||||
|
|
@ -170,18 +170,19 @@ void sha256sum(Pkg *pkg, char *res) {
|
||||||
res[j] = '\0';
|
res[j] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
char *package_to_description(Pkg *pkg) {
|
char *vieter_package_to_description(Pkg *pkg) {
|
||||||
PkgInfo *pkg_info = pkg->info;
|
pkg_info *info = pkg->info;
|
||||||
|
|
||||||
size_t buff_size = 1024;
|
size_t buff_size = 1024;
|
||||||
|
Jef Roosens
commented
This should also use This should also use `SMALL_BUFF_SIZE` I think, just for consistency.
|
|||||||
char aux[SMALL_BUFF_SIZE];
|
char aux[SMALL_BUFF_SIZE];
|
||||||
char *description = malloc(sizeof(char) * buff_size);
|
char *description = malloc(sizeof(char) * buff_size);
|
||||||
|
// Helper variable for ADD_ARRAY macro
|
||||||
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 that
|
||||||
snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", pkg_info->name, pkg_info->version,
|
snprintf(aux, SMALL_BUFF_SIZE, "%%FILENAME%%\n%s-%s-%s.pkg.tar.zst", info->name, info->version,
|
||||||
|
Jef Roosens
commented
Vieter doesn't only supports zstd-compressed archives. Currently it also accepts xz- or gzip-compressed archives, so this should be accounted for. This choice was made noteably because Archlinux ARM uses xz-compressed archives instead of zstd. Vieter doesn't only supports zstd-compressed archives. Currently it also accepts xz- or gzip-compressed archives, so this should be accounted for.
This choice was made noteably because Archlinux ARM uses xz-compressed archives instead of zstd.
|
|||||||
pkg_info->arch);
|
info->arch);
|
||||||
strcpy(description, aux);
|
strcpy(description, aux);
|
||||||
|
|
||||||
ADD_STRING("\n\n%%NAME%%\n%s", name);
|
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);
|
ADD_STRING("\n\n%%ISIZE%%\n%ld", size);
|
||||||
|
|
||||||
char checksum[65];
|
char checksum[65];
|
||||||
sha256sum(pkg, checksum);
|
vieter_package_sha256sum(pkg, checksum);
|
||||||
|
|
||||||
snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum);
|
snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", checksum);
|
||||||
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) {
|
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) {
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
#include "dynarray.h"
|
#include "vieter_package_dynarray.h"
|
||||||
|
|
||||||
DynArray *dynarray_init(size_t initial_capacity) {
|
dynarray *vieter_package_dynarray_init(size_t initial_capacity) {
|
||||||
DynArray *da = malloc(sizeof(DynArray));
|
dynarray *da = malloc(sizeof(dynarray));
|
||||||
da->size = 0;
|
da->size = 0;
|
||||||
da->capacity = initial_capacity;
|
da->capacity = initial_capacity;
|
||||||
|
|
||||||
return da;
|
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
|
// An empty 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);
|
||||||
|
|
@ -24,7 +24,7 @@ void dynarray_add(DynArray *da, const char *s) {
|
||||||
da->size++;
|
da->size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dynarray_free(DynArray *da) {
|
void vieter_package_dynarray_free(dynarray *da) {
|
||||||
if (da == NULL) {
|
if (da == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -40,11 +40,11 @@ void dynarray_free(DynArray *da) {
|
||||||
free(da);
|
free(da);
|
||||||
}
|
}
|
||||||
|
|
||||||
char **dynarray_convert(DynArray *da) {
|
char **vieter_package_dynarray_convert(dynarray *da) {
|
||||||
char **array = da->array;
|
char **array = da->array;
|
||||||
|
|
||||||
da->array = NULL;
|
da->array = NULL;
|
||||||
dynarray_free(da);
|
vieter_package_dynarray_free(da);
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
36
src/package/vieter_package_dynarray.h
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef VIETER_DYNARRAY
|
||||||
|
#define VIETER_DYNARRAY
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#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) { \
|
#define PKG_INFO_STRING(key_ptr, field) if ((value_ptr = strstr(value_ptr, key_ptr)) != NULL) { \
|
||||||
value_ptr += strlen(key_ptr);\
|
value_ptr += strlen(key_ptr);\
|
||||||
|
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`.
|
|||||||
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); \
|
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); \
|
info->field = atoi(value_ptr); \
|
||||||
tail_ptr[0] = '\n'; \
|
tail_ptr[0] = '\n'; \
|
||||||
value_ptr = tail_ptr;
|
value_ptr = tail_ptr;
|
||||||
|
|
||||||
|
|
@ -21,40 +21,40 @@
|
||||||
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 = dynarray_init(4); } \
|
if(info->field == NULL) { info->field = vieter_package_dynarray_init(4); } \
|
||||||
dynarray_add(pkg_info->field, value_ptr); \
|
vieter_package_dynarray_add(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;
|
||||||
|
|
||||||
PkgInfo *package_info_init() {
|
pkg_info *vieter_package_info_init() {
|
||||||
return calloc(1, sizeof(PkgInfo));
|
return calloc(1, sizeof(pkg_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
void package_info_free(PkgInfo *pkg_info) {
|
void vieter_package_info_free(pkg_info *info) {
|
||||||
FREE_STRING(pkg_info->name);
|
FREE_STRING(info->name);
|
||||||
FREE_STRING(pkg_info->base);
|
FREE_STRING(info->base);
|
||||||
FREE_STRING(pkg_info->version);
|
FREE_STRING(info->version);
|
||||||
FREE_STRING(pkg_info->description);
|
FREE_STRING(info->description);
|
||||||
FREE_STRING(pkg_info->url);
|
FREE_STRING(info->url);
|
||||||
FREE_STRING(pkg_info->arch);
|
FREE_STRING(info->arch);
|
||||||
FREE_STRING(pkg_info->packager);
|
FREE_STRING(info->packager);
|
||||||
FREE_STRING(pkg_info->pgpsig);
|
FREE_STRING(info->pgpsig);
|
||||||
|
|
||||||
dynarray_free(pkg_info->groups);
|
vieter_package_dynarray_free(info->groups);
|
||||||
dynarray_free(pkg_info->licenses);
|
vieter_package_dynarray_free(info->licenses);
|
||||||
dynarray_free(pkg_info->replaces);
|
vieter_package_dynarray_free(info->replaces);
|
||||||
dynarray_free(pkg_info->depends);
|
vieter_package_dynarray_free(info->depends);
|
||||||
dynarray_free(pkg_info->conflicts);
|
vieter_package_dynarray_free(info->conflicts);
|
||||||
dynarray_free(pkg_info->provides);
|
vieter_package_dynarray_free(info->provides);
|
||||||
dynarray_free(pkg_info->optdepends);
|
vieter_package_dynarray_free(info->optdepends);
|
||||||
dynarray_free(pkg_info->makedepends);
|
vieter_package_dynarray_free(info->makedepends);
|
||||||
dynarray_free(pkg_info->checkdepends);
|
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;
|
char *value_ptr = pkg_info_str, *tail_ptr;
|
||||||
|
|
||||||
PKG_INFO_STRING("\npkgname = ", name);
|
PKG_INFO_STRING("\npkgname = ", name);
|
||||||
52
src/package/vieter_package_info.h
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef VIETER_PACKAGE_INFO
|
||||||
|
#define VIETER_PACKAGE_INFO
|
||||||
|
|
||||||
|
#define FREE_STRING(sp) if (sp != NULL) free(sp)
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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
|
||||||
10
src/package/vieter_package_internal.h
Normal file
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "acutest.h"
|
#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");
|
FILE *f = fopen("./test/package/.PKGINFO", "r");
|
||||||
TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package ");
|
TEST_ASSERT_(f != NULL, "could not find test .PKGINFO file in ./test/package ");
|
||||||
fseek(f, 0L, SEEK_END);
|
fseek(f, 0L, SEEK_END);
|
||||||
|
|
@ -11,34 +11,35 @@ void test_pkg_info_parse() {
|
||||||
char *pkg_info_str = malloc(size);
|
char *pkg_info_str = malloc(size);
|
||||||
fread(pkg_info_str, 1, size, f);
|
fread(pkg_info_str, 1, size, f);
|
||||||
fclose(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"));
|
pkg_info *info = vieter_package_info_init();
|
||||||
TEST_CHECK(!strcmp(pkg_info->base, "xcursor-dmz"));
|
vieter_package_info_parse(info, pkg_info_str);
|
||||||
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(info->name, "xcursor-dmz"));
|
||||||
TEST_CHECK(!strcmp(pkg_info->replaces->array[0], "test1"));
|
TEST_CHECK(!strcmp(info->base, "xcursor-dmz"));
|
||||||
TEST_CHECK(!strcmp(pkg_info->groups->array[0], "x11"));
|
TEST_CHECK(!strcmp(info->version, "0.4.5-2"));
|
||||||
TEST_CHECK(!strcmp(pkg_info->conflicts->array[0], "test2"));
|
TEST_CHECK(!strcmp(info->description, "Style neutral, scalable cursor theme"));
|
||||||
TEST_CHECK(!strcmp(pkg_info->conflicts->array[1], "test3"));
|
TEST_CHECK(!strcmp(info->url, "https://packages.debian.org/sid/dmz-cursor-theme"));
|
||||||
TEST_CHECK(!strcmp(pkg_info->provides->array[0], "test4"));
|
TEST_CHECK(info->build_date == 1673751613);
|
||||||
TEST_CHECK(!strcmp(pkg_info->depends->array[0], "test5"));
|
TEST_CHECK(!strcmp(info->packager, "Unknown Packager"));
|
||||||
TEST_CHECK(!strcmp(pkg_info->depends->array[1], "test6"));
|
TEST_CHECK(info->size == 3469584);
|
||||||
TEST_CHECK(!strcmp(pkg_info->optdepends->array[0], "test7"));
|
TEST_CHECK(!strcmp(info->arch, "any"));
|
||||||
TEST_CHECK(!strcmp(pkg_info->makedepends->array[0], "xorg-xcursorgen"));
|
|
||||||
TEST_CHECK(!strcmp(pkg_info->checkdepends->array[0], "test8"));
|
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() {
|
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");
|
TEST_ASSERT_(pkg != NULL, "failure parsing pkg archive");
|
||||||
|
|
||||||
FILE *f = fopen("./test/package/files", "r");
|
FILE *f = fopen("./test/package/files", "r");
|
||||||
|
|
@ -59,10 +60,10 @@ void test_pkg_read_archive_files() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_pkg_read_archive_desc() {
|
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");
|
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");
|
FILE *f = fopen("./test/package/desc", "r");
|
||||||
TEST_ASSERT_(f != NULL, "could not find test desc file in ./test/package");
|
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 = {
|
TEST_LIST = {
|
||||||
{"pkg_info_valid_parse", test_pkg_info_parse},
|
{".PKGINFO parse", test_info_parse},
|
||||||
{"pkg_read_archive_files", test_pkg_read_archive_files},
|
{"files array creation", test_pkg_read_archive_files},
|
||||||
{"pkg_read_archive_desc", test_pkg_read_archive_desc},
|
{"desc file creation", test_pkg_read_archive_desc},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
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.