forked from vieter-v/libvieter
181 lines
4.8 KiB
C
181 lines
4.8 KiB
C
#include "package.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); \
|
|
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++; \
|
|
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++; \
|
|
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) { \
|
|
description = realloc(description, buff_size * 2); \
|
|
buff_size *= 2; \
|
|
} \
|
|
strcat(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;
|
|
}
|
|
|
|
void sha256sum(Pkg *pkg, char *res) {
|
|
char command[SMALL_BUFF_SIZE];
|
|
snprintf(command, SMALL_BUFF_SIZE, "sha256sum %s", pkg->path);
|
|
FILE *p = popen(command, "r");
|
|
|
|
fgets(res, 65, p);
|
|
pclose(p);
|
|
}
|
|
|
|
char *package_to_description(Pkg *pkg) {
|
|
PkgInfo *pkg_info = pkg->info;
|
|
|
|
size_t buff_size = 1024;
|
|
char aux[SMALL_BUFF_SIZE];
|
|
char *description = malloc(sizeof(char) * buff_size);
|
|
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);
|
|
strcat(description, aux);
|
|
|
|
ADD_STRING("\n\n%%NAME%%\n%s", name);
|
|
ADD_STRING("\n\n%%BASE%%\n%s", base);
|
|
ADD_STRING("\n\n%%VERSION%%\n%s", version);
|
|
ADD_STRING("\n\n%%DESC%%\n%s", description);
|
|
ADD_ARRAY("\n\n%%GROUPS%%\n%s", groups);
|
|
ADD_STRING("\n\n%%CSIZE%%\n%ld", csize);
|
|
ADD_STRING("\n\n%%ISIZE%%\n%ld", size);
|
|
|
|
char res[65];
|
|
sha256sum(pkg, res);
|
|
snprintf(aux, SMALL_BUFF_SIZE, "\n\n%%SHA256SUM%%\n%s", res);
|
|
if (buff_size < strlen(description) + SMALL_BUFF_SIZE + 1) {
|
|
description = realloc(description, buff_size * 2);
|
|
buff_size *= 2;
|
|
}
|
|
strcat(description, aux);
|
|
|
|
ADD_STRING("\n\n%%URL%%\n%s", url);
|
|
ADD_ARRAY("\n\n%%LICENSE%%\n%s", licenses);
|
|
ADD_STRING("\n\n%%ARCH%%\n%s", arch);
|
|
ADD_STRING("\n\n%%BUILDDATE%%\n%ld", build_date);
|
|
ADD_STRING("\n\n%%PACKAGER%%\n%s", packager);
|
|
ADD_ARRAY("\n\n%%REPLACES%%\n%s", replaces);
|
|
ADD_ARRAY("\n\n%%CONFLICTS%%\n%s", conflicts);
|
|
ADD_ARRAY("\n\n%%PROVIDES%%\n%s", provides);
|
|
ADD_ARRAY("\n\n%%DEPENDS%%\n%s", depends);
|
|
ADD_ARRAY("\n\n%%OPTDEPENDS%%\n%s", optdepends);
|
|
ADD_ARRAY("\n\n%%MAKEDEPENDS%%\n%s", makedepends);
|
|
ADD_ARRAY("\n\n%%CHECKDEPENDS%%\n%s", checkdepends);
|
|
|
|
snprintf(aux, SMALL_BUFF_SIZE, "\n\n");
|
|
strcat(description, aux);
|
|
|
|
return description;
|
|
}
|