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