libvieter/src/package/package.c

142 lines
3.6 KiB
C

#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",
".MTREE",
".PKGINFO",
".CHANGELOG"
};
static size_t 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);
dynarray_add(files, "%FILES%");
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);
// 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) {
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;
}