#include <pakfire/logging.h>
#include <pakfire/package.h>
#include <pakfire/pakfire.h>
-#include <pakfire/parser.h>
#include <pakfire/private.h>
#include <pakfire/repo.h>
#include <pakfire/scriptlet.h>
// metadata
unsigned int format;
struct json_object* metadata;
- struct pakfire_parser* parser;
struct pakfire_filelist* filelist;
// Archives must be uncompressed tarballs
archive_read_support_format_tar(a);
- // Archives are either compressed using XZ or Zstandard
- archive_read_support_filter_xz(a);
+ // Archives are compressed using Zstandard
archive_read_support_filter_zstd(a);
// Start reading from the beginning
return r;
}
-static int find_archive_entry(struct pakfire_archive* archive, struct archive_entry** entry,
- struct archive* a, const char* filename) {
- while (1) {
- int r = archive_read_next_header(a, entry);
-
- // Nothing found
- if (r == ARCHIVE_EOF) {
- break;
-
- // Some error has occured
- } else if (r)
- return r;
-
- // Compare the name
- const char* entry_name = archive_entry_pathname(*entry);
-
- // Match?
- if (strcmp(entry_name, filename) == 0)
- return 0;
- }
-
- DEBUG(archive->pakfire, "Could not find an entry named '%s'\n", filename);
- errno = ENOENT;
-
- // Nothing found
- *entry = NULL;
- return 1;
-}
-
-static la_ssize_t pakfire_archive_read_callback(struct archive* a,
- void* client_data, const void** buffer) {
- struct archive* archive = (struct archive*)client_data;
-
- size_t len = 0;
- off_t offset = 0;
-
- // Try reading the next block (without copying it)
- int r = archive_read_data_block(archive, buffer, &len, &offset);
-
- switch (r) {
- case ARCHIVE_OK:
- return len;
-
- // Return zero to signal that everything was read
- case ARCHIVE_EOF:
- return 0;
-
- // Return -1 on any other errors
- default:
- return -1;
- }
-}
-
-static struct archive* pakfire_archive_open_payload(struct pakfire_archive* archive,
- struct archive* a, size_t* size) {
- struct archive_entry* entry = NULL;
- struct archive* payload = NULL;
-
- // Find the payload
- int r = find_archive_entry(archive, &entry, a, "data.img");
- if (r)
- goto ERROR;
-
- // Store size
- if (size)
- *size = archive_entry_size(entry);
-
- // Allocate a new archive object
- payload = archive_read_new();
- if (!payload)
- goto ERROR;
-
- // All of our packages are tar balls
- archive_read_support_format_tar(payload);
-
- // They are compressed using XZ
- archive_read_support_filter_xz(payload);
-
- // Try opening the payload archive
- r = archive_read_open2(payload, a, NULL, pakfire_archive_read_callback, NULL, NULL);
- if (r) {
- ERROR(archive->pakfire, "Could not open payload archive: %s\n",
- archive_error_string(payload));
- goto ERROR;
- }
-
- return payload;
-
-ERROR:
- if (payload)
- archive_read_free(payload);
-
- return NULL;
-}
-
static void pakfire_archive_free(struct pakfire_archive* archive) {
// Close the file
if (archive->f)
pakfire_package_unref(archive->package);
if (archive->metadata)
json_object_put(archive->metadata);
- if (archive->parser)
- pakfire_parser_unref(archive->parser);
pakfire_unref(archive->pakfire);
free(archive);
}
return r;
}
-static int pakfire_archive_parse_legacy_metadata(struct pakfire_archive* archive,
- const char* data, const size_t length) {
- int r = 1;
-
- // Allocate a new parser
- archive->parser = pakfire_parser_create(archive->pakfire, NULL, NULL, 0);
- if (!archive->parser)
- goto ERROR;
-
- // Parse the metadata
- r = pakfire_parser_parse_data(archive->parser, data, length, NULL);
- if (r) {
- ERROR(archive->pakfire, "Error parsing metadata\n");
- goto ERROR;
- }
-
- // Success
- return 0;
-
-ERROR:
- if (archive->parser) {
- pakfire_parser_unref(archive->parser);
- archive->parser = NULL;
- }
-
- return r;
-}
-
static int pakfire_archive_parse_format(struct pakfire_archive* archive,
const char* data, const size_t length) {
// Check if format has already been set
switch (archive->format) {
// Handle all supported formats
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
case 6:
break;
}
// Determine type
- if (archive->format >= 6)
- type = pakfire_path_relpath(".scriptlets/", path);
- else if (archive->format >= 1)
- type = pakfire_path_relpath("scriptlet/", path);
-
+ type = pakfire_path_relpath(".scriptlets/", path);
if (!type) {
ERROR(archive->pakfire, "Could not determine the scriptlet type from '%s'\n", path);
errno = EINVAL;
goto ERROR;
}
- // Format >= 1
- } else if (archive->format >= 1) {
- // Parse info
- if (strcmp(path, "info") == 0) {
- r = pakfire_archive_parse_legacy_metadata(archive, data, length);
- if (r)
- goto ERROR;
-
- // Parse scriptlets
- } else if (pakfire_string_startswith(path, "scriptlet/")) {
- r = pakfire_archive_parse_scriptlet(archive, path, data, length);
- if (r)
- goto ERROR;
- }
-
// pakfire-format
} else if (strcmp(path, "pakfire-format") == 0) {
r = pakfire_archive_parse_format(archive, data, length);
// Otherwise, the payload begins
return PAKFIRE_WALK_DONE;
- // Format >= 1
- } else if (archive->format >= 1) {
- // info
- if (strcmp(path, "info") == 0)
- return PAKFIRE_WALK_OK;
-
- // scriptlets
- else if (pakfire_string_startswith(path, "scriptlets/"))
- return PAKFIRE_WALK_OK;
-
- // Ignore anything else
- return PAKFIRE_WALK_SKIP;
-
// The pakfire-format file is part of the metadata
} else if (strcmp(path, "pakfire-format") == 0) {
return PAKFIRE_WALK_OK;
}
// Check if we have read some metadata
- if (!archive->metadata && !archive->parser) {
+ if (!archive->metadata) {
ERROR(archive->pakfire, "Archive has no metadata\n");
errno = EINVAL;
return 1;
return json_object_get_int64(object);
}
-PAKFIRE_EXPORT char* pakfire_archive_get(struct pakfire_archive* archive,
- const char* namespace, const char* key) {
- return pakfire_parser_get(archive->parser, namespace, key);
-}
-
-static int __pakfire_archive_read_legacy(struct pakfire_archive* archive,
- const char* path, char** data, size_t* length) {
- int r = 1;
-
- struct archive* a = NULL;
- struct archive_entry* entry = NULL;
- struct archive* payload = NULL;
-
- // Open the archive
- a = open_archive(archive);
- if (!a) {
- r = 1;
- goto ERROR;
- }
-
- payload = pakfire_archive_open_payload(archive, a, NULL);
- if (!payload)
- goto ERROR;
-
- r = find_archive_entry(archive, &entry, payload, path);
- if (r)
- goto ERROR;
-
- r = pakfire_archive_copy_data_to_buffer(archive->pakfire, payload, entry,
- data, length);
-
-ERROR:
- if (payload)
- archive_read_free(payload);
- close_archive(archive, a);
-
- return r;
-}
-
struct pakfire_archive_read {
struct pakfire_archive* archive;
const char* path;
static int __pakfire_archive_read(struct pakfire_archive* archive,
const char* path, char** data, size_t* length) {
struct pakfire_archive_read _read = {
- .path = path,
- .data = data,
- .length = length,
+ .archive = archive,
+ .path = path,
+ .data = data,
+ .length = length,
};
// Walk through the archive
return 1;
}
- if (archive->format >= 6)
- return __pakfire_archive_read(archive, path, data, length);
- else
- return __pakfire_archive_read_legacy(archive, path, data, length);
+ return __pakfire_archive_read(archive, path, data, length);
}
int pakfire_archive_copy(struct pakfire_archive* archive, const char* path) {
struct pakfire_filelist* filelist = NULL;
struct pakfire_package* pkg = NULL;
struct archive* a = NULL;
- struct archive* payload = NULL;
char prefix[PATH_MAX] = "";
- size_t size = archive->stat.st_size;
int r = 1;
// Fetch package
goto ERROR;
}
- // Open the internal tarball with the payload for older formats
- if (archive->format < 6) {
- payload = pakfire_archive_open_payload(archive, a, &size);
- if (!payload)
- goto ERROR;
- }
-
// Extract
- r = pakfire_extract(archive->pakfire, (payload) ? payload : a, size,
+ r = pakfire_extract(archive->pakfire, a, archive->stat.st_size,
filelist, prefix, nevra, flags);
if (r)
goto ERROR;
pakfire_filelist_unref(filelist);
if (pkg)
pakfire_package_unref(pkg);
- if (payload)
- archive_read_free(payload);
if (a)
close_archive(archive, a);
return r;
}
-static int pakfire_archive_package_set_string(struct pakfire_archive* archive,
- struct pakfire_package* pkg, const enum pakfire_package_key key,
- const char* key1, const char* key2) {
- char* value = NULL;
- int r;
-
- // Fetch the value
- value = pakfire_archive_get(archive, key1, key2);
-
- // Set the value
- r = pakfire_package_set_string(pkg, key, value);
-
- if (value)
- free(value);
-
- return r;
-}
-
-static int pakfire_archive_make_legacy_package(struct pakfire_archive* archive,
- struct pakfire_repo* repo, struct pakfire_package** package) {
- int r;
-
- // Calculate digest
- r = pakfire_archive_compute_digests(archive);
- if (r)
- return r;
-
- char* name = pakfire_archive_get(archive, "package", "name");
- char* arch = pakfire_archive_get(archive, "package", "arch");
-
- char* evr = pakfire_archive_get(archive, "package", "evr");
- if (!evr) {
- char* epoch = pakfire_archive_get(archive, "package", "epoch");
- char* version = pakfire_archive_get(archive, "package", "version");
- char* release = pakfire_archive_get(archive, "package", "release");
-
- evr = pakfire_package_join_evr(epoch, version, release);
-
- if (epoch)
- free(epoch);
- if (version)
- free(version);
- if (release)
- free(release);
- }
-
- /*
- Check architecture
- Legacy package formats use "arch = all" for source packages.
- We need to check for "type = source" and then reset arch
- */
- if (arch && strcmp(arch, "all") == 0) {
- char* type = pakfire_archive_get(archive, "package", "type");
- if (type) {
- if (strcmp(type, "source") == 0) {
- free(arch);
- arch = NULL;
- }
- }
- free(type);
- }
-
- struct pakfire_package* pkg = NULL;
-
- r = pakfire_package_create(&pkg, archive->pakfire, repo, name, evr,
- (arch) ? arch : "src");
-
- if (name)
- free(name);
- if (evr)
- free(evr);
- if (arch)
- free(arch);
-
- if (r)
- goto ERROR;
-
- // Set package pointer right here to avoid an endless loop when loading the filelist
- *package = pkg;
-
-#ifdef ENABLE_DEBUG
- const char* nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA);
-
- DEBUG(archive->pakfire, "Created package %s (%p) from archive %p\n",
- nevra, pkg, archive);
-#endif
-
- // Set path
- pakfire_package_set_string(pkg, PAKFIRE_PKG_PATH, archive->path);
-
- // Set UUID
- r = pakfire_archive_package_set_string(archive, pkg,
- PAKFIRE_PKG_UUID, "package", "uuid");
- if (r)
- goto ERROR;
-
- // Set groups
- r = pakfire_archive_package_set_string(archive, pkg,
- PAKFIRE_PKG_GROUPS, "package", "groups");
- if (r)
- goto ERROR;
-
- // Set packager
- r = pakfire_archive_package_set_string(archive, pkg,
- PAKFIRE_PKG_PACKAGER, "package", "packager");
- if (r)
- goto ERROR;
-
- // Set URL
- r = pakfire_archive_package_set_string(archive, pkg,
- PAKFIRE_PKG_URL, "package", "url");
- if (r)
- goto ERROR;
-
- // Set license
- r = pakfire_archive_package_set_string(archive, pkg,
- PAKFIRE_PKG_LICENSE, "package", "license");
- if (r)
- goto ERROR;
-
- // Set summary
- r = pakfire_archive_package_set_string(archive, pkg,
- PAKFIRE_PKG_SUMMARY, "package", "summary");
- if (r)
- goto ERROR;
-
- // Set description
- r = pakfire_archive_package_set_string(archive, pkg,
- PAKFIRE_PKG_DESCRIPTION, "package", "description");
- if (r)
- goto ERROR;
-
- // Get package size
- pakfire_package_set_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE,
- pakfire_archive_get_size(archive));
-
- // Get install size
- char* size = pakfire_archive_get(archive, "package", "size");
- if (size) {
- size_t s = strtoul(size, NULL, 10);
- free(size);
-
- pakfire_package_set_num(pkg, PAKFIRE_PKG_INSTALLSIZE, s);
- }
-
- // Set vendor
- r = pakfire_archive_package_set_string(archive, pkg,
- PAKFIRE_PKG_VENDOR, "distribution", "vendor");
- if (r)
- goto ERROR;
-
- // Set build host
- char* build_host = pakfire_archive_get(archive, "build", "host");
- if (build_host) {
- pakfire_package_set_string(pkg, PAKFIRE_PKG_BUILD_HOST, build_host);
- free(build_host);
- }
-
- // Set build ID
- char* build_id = pakfire_archive_get(archive, "build", "id");
- if (build_id) {
- pakfire_package_set_string(pkg, PAKFIRE_PKG_BUILD_ID, build_id);
- free(build_id);
- }
-
- // Set build time
- char* build_time = pakfire_archive_get(archive, "build", "time");
- if (build_time) {
- time_t t = strtoull(build_time, NULL, 10);
- free(build_time);
-
- pakfire_package_set_num(pkg, PAKFIRE_PKG_BUILD_TIME, t);
- }
-
- // Dependencies
- for (const struct pakfire_dep* dep = pakfire_deps; dep->key; dep++) {
- char* rels = pakfire_archive_get(archive, "dependencies", dep->name);
- if (rels) {
- r = pakfire_str2deps(archive->pakfire, pkg, dep->key, rels);
- free(rels);
-
- if (r)
- goto ERROR;
- }
- }
-
- // Import filelist
- struct pakfire_filelist* filelist = pakfire_archive_get_filelist(archive);
- if (filelist) {
- pakfire_package_set_filelist(pkg, filelist);
- pakfire_filelist_unref(filelist);
- }
-
- // Set digest
- switch (PAKFIRE_ARCHIVE_CHECKSUM) {
- case PAKFIRE_DIGEST_SHA2_512:
- pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM,
- archive->digests.sha2_512, sizeof(archive->digests.sha2_512));
- break;
-
- case PAKFIRE_DIGEST_SHA2_256:
- pakfire_package_set_digest(pkg, PAKFIRE_ARCHIVE_CHECKSUM,
- archive->digests.sha2_256, sizeof(archive->digests.sha2_256));
- break;
-
- case PAKFIRE_DIGEST_UNDEFINED:
- break;
- }
-
-ERROR:
- return r;
-}
-
/*
Copy all metadata from this archive to the package object
*/
}
// Make package from JSON metadata
- if (archive->format >= 6)
- r = pakfire_archive_make_package_from_json(archive, repo, package);
-
- // Use legacy stuff
- else
- r = pakfire_archive_make_legacy_package(archive, repo, package);
+ r = pakfire_archive_make_package_from_json(archive, repo, package);
// Free dummy repository
if (dummy)