Compare commits

...

2 Commits

Author SHA1 Message Date
GreekStapler de1227b97b refactor: Added free function for package struct.
While going through with the renaming, I saw that I actually forgot to implement that part.
2023-01-29 11:55:22 +00:00
GreekStapler 4812cde905 chore: Package module now follows the naming and structure conventions of libvieter. 2023-01-29 11:48:59 +00:00
13 changed files with 235 additions and 178 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View 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.

View File

@ -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) {
@ -220,3 +221,12 @@ char *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;
}

View File

@ -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;
}

View 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

View File

@ -1,19 +1,19 @@
#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) { \
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);

View 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

View 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;
};

View File

@ -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");
@ -56,13 +57,15 @@ void test_pkg_read_archive_files() {
}
TEST_CHECK(pkg->compression = 14);
vieter_package_free(&pkg);
}
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 +80,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}
};