forked from vieter-v/vieter
feat(package): started rewrite in C
parent
9e11237ff9
commit
3e40eeff2d
|
@ -5,6 +5,6 @@ root = true
|
|||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.v]
|
||||
[*.{v,c,h}]
|
||||
# vfmt wants it :(
|
||||
indent_style = tab
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
*.c
|
||||
vieter.c
|
||||
/data/
|
||||
|
||||
# Build artifacts
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#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 **ptp) {
|
||||
DynArray *da = *ptp;
|
||||
|
||||
for (size_t i = 0; i < da->size; i++) {
|
||||
free(da->array[i]);
|
||||
}
|
||||
|
||||
free(da->array);
|
||||
free(da);
|
||||
|
||||
*ptp = NULL;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef VIETER_DYNARRAY
|
||||
#define VIETER_DYNARRAY
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct dyn_array DynArray;
|
||||
|
||||
DynArray *dynarray_init(size_t initial_capacity);
|
||||
void dynarray_add(DynArray *da, const char * s);
|
||||
char ** dynarray_get_array(DynArray *da);
|
||||
void dynarray_free(DynArray **ptp);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,94 @@
|
|||
#include "package.h"
|
||||
|
||||
static char *ignored_names[5] = {
|
||||
".BUILDINFO",
|
||||
".INSTALL",
|
||||
".MTREE",
|
||||
".PKGINFO",
|
||||
".CHANGELOG"
|
||||
};
|
||||
static int ignored_words_len = sizeof(ignored_names) / sizeof(char *);
|
||||
|
||||
inline 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;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#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);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,46 @@
|
|||
#include "package_info.h"
|
||||
|
||||
PkgInfo *package_info_init() {
|
||||
PkgInfo *pkg_info = calloc(1, sizeof(PkgInfo));
|
||||
|
||||
pkg_info->groups = dynarray_init(4);
|
||||
pkg_info->licenses = dynarray_init(4);
|
||||
pkg_info->replaces = dynarray_init(4);
|
||||
pkg_info->depends = dynarray_init(4);
|
||||
pkg_info->conflicts = dynarray_init(4);
|
||||
pkg_info->provides = dynarray_init(4);
|
||||
pkg_info->optdepends = dynarray_init(4);
|
||||
pkg_info->makedepends = dynarray_init(4);
|
||||
pkg_info->checkdepends = dynarray_init(4);
|
||||
|
||||
return pkg_info;
|
||||
}
|
||||
|
||||
void package_info_free(PkgInfo **ptp) {
|
||||
PkgInfo *pkg_info = *ptp;
|
||||
|
||||
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);
|
||||
|
||||
*ptp = NULL;
|
||||
}
|
||||
|
||||
void package_info_parse(PkgInfo *pkg_info, const char *pkg_info_str) {
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#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, const char *pkg_info_str);
|
||||
void package_info_free(PkgInfo **ptp);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue