db: refactor repository file construction
Fixes also 'fetch' applet to prefer copying/linking to files from cache if possible.cute-signatures
parent
dbb642206d
commit
9d10037807
|
@ -21,9 +21,6 @@
|
||||||
#include "apk_provider_data.h"
|
#include "apk_provider_data.h"
|
||||||
#include "apk_solver_data.h"
|
#include "apk_solver_data.h"
|
||||||
|
|
||||||
extern const char * const apk_index_gz;
|
|
||||||
extern const char * const apkindex_tar_gz;
|
|
||||||
|
|
||||||
struct apk_name;
|
struct apk_name;
|
||||||
APK_ARRAY(apk_name_array, struct apk_name *);
|
APK_ARRAY(apk_name_array, struct apk_name *);
|
||||||
|
|
||||||
|
@ -71,8 +68,8 @@ struct apk_db_dir {
|
||||||
char name[];
|
char name[];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PKG_FILE_FMT "%s%s%s"
|
#define DIR_FILE_FMT "%s%s%s"
|
||||||
#define PKG_FILE_PRINTF(dir,file) (dir)->name, (dir)->namelen ? "/" : "", (file)->name
|
#define DIR_FILE_PRINTF(dir,file) (dir)->name, (dir)->namelen ? "/" : "", (file)->name
|
||||||
|
|
||||||
struct apk_db_dir_instance {
|
struct apk_db_dir_instance {
|
||||||
struct hlist_node pkg_dirs_list;
|
struct hlist_node pkg_dirs_list;
|
||||||
|
@ -220,15 +217,16 @@ int apk_db_index_write(struct apk_database *db, struct apk_ostream *os);
|
||||||
int apk_db_add_repository(apk_database_t db, apk_blob_t repository);
|
int apk_db_add_repository(apk_database_t db, apk_blob_t repository);
|
||||||
struct apk_repository *apk_db_select_repo(struct apk_database *db,
|
struct apk_repository *apk_db_select_repo(struct apk_database *db,
|
||||||
struct apk_package *pkg);
|
struct apk_package *pkg);
|
||||||
int apk_repo_format_filename(char *buf, size_t len,
|
|
||||||
const char *repourl, apk_blob_t *arch,
|
int apk_repo_format_cache_index(apk_blob_t to, struct apk_repository *repo);
|
||||||
const char *pkgfile);
|
int apk_repo_format_item(struct apk_database *db, struct apk_repository *repo, struct apk_package *pkg,
|
||||||
|
int *fd, char *buf, size_t len);
|
||||||
|
|
||||||
unsigned int apk_db_get_pinning_mask_repos(struct apk_database *db, unsigned short pinning_mask);
|
unsigned int apk_db_get_pinning_mask_repos(struct apk_database *db, unsigned short pinning_mask);
|
||||||
|
|
||||||
int apk_db_cache_active(struct apk_database *db);
|
int apk_db_cache_active(struct apk_database *db);
|
||||||
void apk_cache_format_index(apk_blob_t to, struct apk_repository *repo);
|
int apk_cache_download(struct apk_database *db, struct apk_repository *repo,
|
||||||
int apk_cache_download(struct apk_database *db, const char *url, apk_blob_t *arch,
|
struct apk_package *pkg, int verify);
|
||||||
const char *item, const char *cache_item, int verify);
|
|
||||||
|
|
||||||
typedef void (*apk_cache_item_cb)(struct apk_database *db,
|
typedef void (*apk_cache_item_cb)(struct apk_database *db,
|
||||||
int dirfd, const char *name,
|
int dirfd, const char *name,
|
||||||
|
|
|
@ -123,6 +123,8 @@ APK_ARRAY(apk_package_array, struct apk_package *);
|
||||||
|
|
||||||
#define PKG_VER_FMT "%s-" BLOB_FMT
|
#define PKG_VER_FMT "%s-" BLOB_FMT
|
||||||
#define PKG_VER_PRINTF(pkg) pkg->name->name, BLOB_PRINTF(*pkg->version)
|
#define PKG_VER_PRINTF(pkg) pkg->name->name, BLOB_PRINTF(*pkg->version)
|
||||||
|
#define PKG_FILE_FMT PKG_VER_FMT ".apk"
|
||||||
|
#define PKG_FILE_PRINTF(pkg) PKG_VER_PRINTF(pkg)
|
||||||
|
|
||||||
extern const char *apk_script_types[];
|
extern const char *apk_script_types[];
|
||||||
|
|
||||||
|
@ -160,8 +162,6 @@ int apk_script_type(const char *name);
|
||||||
|
|
||||||
struct apk_package *apk_pkg_get_installed(struct apk_name *name);
|
struct apk_package *apk_pkg_get_installed(struct apk_name *name);
|
||||||
|
|
||||||
void apk_pkg_format_plain(struct apk_package *pkg, apk_blob_t to);
|
|
||||||
void apk_pkg_format_cache(struct apk_package *pkg, apk_blob_t to);
|
|
||||||
struct apk_package *apk_pkg_new(void);
|
struct apk_package *apk_pkg_new(void);
|
||||||
int apk_pkg_read(struct apk_database *db, const char *name,
|
int apk_pkg_read(struct apk_database *db, const char *name,
|
||||||
struct apk_sign_ctx *ctx, struct apk_package **pkg);
|
struct apk_sign_ctx *ctx, struct apk_package **pkg);
|
||||||
|
|
11
src/cache.c
11
src/cache.c
|
@ -31,7 +31,6 @@ static int cache_download(struct apk_database *db)
|
||||||
struct apk_change *change;
|
struct apk_change *change;
|
||||||
struct apk_package *pkg;
|
struct apk_package *pkg;
|
||||||
struct apk_repository *repo;
|
struct apk_repository *repo;
|
||||||
char item[PATH_MAX], cacheitem[PATH_MAX];
|
|
||||||
int i, r, ret = 0;
|
int i, r, ret = 0;
|
||||||
|
|
||||||
r = apk_solver_solve(db, 0, db->world, &changeset);
|
r = apk_solver_solve(db, 0, db->world, &changeset);
|
||||||
|
@ -50,13 +49,9 @@ static int cache_download(struct apk_database *db)
|
||||||
if (repo == NULL)
|
if (repo == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
apk_pkg_format_cache(pkg, APK_BLOB_BUF(cacheitem));
|
r = apk_cache_download(db, repo, pkg, APK_SIGN_VERIFY_IDENTITY);
|
||||||
apk_pkg_format_plain(pkg, APK_BLOB_BUF(item));
|
|
||||||
r = apk_cache_download(db, repo->url, pkg->arch,
|
|
||||||
item, cacheitem,
|
|
||||||
APK_SIGN_VERIFY_IDENTITY);
|
|
||||||
if (r) {
|
if (r) {
|
||||||
apk_error("%s: %s", item, apk_error_str(r));
|
apk_error(PKG_VER_FMT ": %s", PKG_VER_PRINTF(pkg), apk_error_str(r));
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +71,7 @@ static void cache_clean_item(struct apk_database *db, int dirfd, const char *nam
|
||||||
b = APK_BLOB_STR(name);
|
b = APK_BLOB_STR(name);
|
||||||
for (i = 0; i < db->num_repos; i++) {
|
for (i = 0; i < db->num_repos; i++) {
|
||||||
/* Check if this is a valid index */
|
/* Check if this is a valid index */
|
||||||
apk_cache_format_index(APK_BLOB_BUF(tmp), &db->repos[i]);
|
apk_repo_format_cache_index(APK_BLOB_BUF(tmp), &db->repos[i]);
|
||||||
if (apk_blob_compare(b, APK_BLOB_STR(tmp)) == 0)
|
if (apk_blob_compare(b, APK_BLOB_STR(tmp)) == 0)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
242
src/database.c
242
src/database.c
|
@ -46,7 +46,8 @@ enum {
|
||||||
int apk_verbosity = 1;
|
int apk_verbosity = 1;
|
||||||
unsigned int apk_flags = 0;
|
unsigned int apk_flags = 0;
|
||||||
|
|
||||||
const char * const apkindex_tar_gz = "APKINDEX.tar.gz";
|
static const char * const apkindex_tar_gz = "APKINDEX.tar.gz";
|
||||||
|
|
||||||
static const char * const apk_static_cache_dir = "var/cache/apk";
|
static const char * const apk_static_cache_dir = "var/cache/apk";
|
||||||
static const char * const apk_linked_cache_dir = "etc/apk/cache";
|
static const char * const apk_linked_cache_dir = "etc/apk/cache";
|
||||||
|
|
||||||
|
@ -562,49 +563,111 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *
|
||||||
return idb;
|
return idb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apk_cache_format_index(apk_blob_t to, struct apk_repository *repo)
|
static int apk_pkg_format_cache_pkg(apk_blob_t to, struct apk_package *pkg)
|
||||||
|
{
|
||||||
|
/* pkgname-1.0_alpha1.12345678.apk */
|
||||||
|
apk_blob_push_blob(&to, APK_BLOB_STR(pkg->name->name));
|
||||||
|
apk_blob_push_blob(&to, APK_BLOB_STR("-"));
|
||||||
|
apk_blob_push_blob(&to, *pkg->version);
|
||||||
|
apk_blob_push_blob(&to, APK_BLOB_STR("."));
|
||||||
|
apk_blob_push_hexdump(&to, APK_BLOB_PTR_LEN((char *) pkg->csum.data,
|
||||||
|
APK_CACHE_CSUM_BYTES));
|
||||||
|
apk_blob_push_blob(&to, APK_BLOB_STR(".apk"));
|
||||||
|
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
|
||||||
|
if (APK_BLOB_IS_NULL(to))
|
||||||
|
return -ENOBUFS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int apk_repo_format_cache_index(apk_blob_t to, struct apk_repository *repo)
|
||||||
{
|
{
|
||||||
/* APKINDEX.12345678.tar.gz */
|
/* APKINDEX.12345678.tar.gz */
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR("APKINDEX."));
|
apk_blob_push_blob(&to, APK_BLOB_STR("APKINDEX."));
|
||||||
apk_blob_push_hexdump(&to, APK_BLOB_PTR_LEN((char *) repo->csum.data,
|
apk_blob_push_hexdump(&to, APK_BLOB_PTR_LEN((char *) repo->csum.data, APK_CACHE_CSUM_BYTES));
|
||||||
APK_CACHE_CSUM_BYTES));
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR(".tar.gz"));
|
apk_blob_push_blob(&to, APK_BLOB_STR(".tar.gz"));
|
||||||
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
|
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
|
||||||
|
if (APK_BLOB_IS_NULL(to))
|
||||||
|
return -ENOBUFS;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int apk_cache_download(struct apk_database *db, const char *url, apk_blob_t *arch,
|
int apk_repo_format_real_url(struct apk_database *db, struct apk_repository *repo,
|
||||||
const char *item, const char *cacheitem, int verify)
|
struct apk_package *pkg, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
char fullurl[PATH_MAX];
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
apk_repo_format_filename(fullurl, sizeof(fullurl), url, arch, item);
|
if (pkg != NULL)
|
||||||
apk_message("fetch %s", fullurl);
|
r = snprintf(buf, len, "%s%s" BLOB_FMT "/" PKG_FILE_FMT,
|
||||||
|
repo->url, repo->url[strlen(repo->url)-1] == '/' ? "" : "/",
|
||||||
|
BLOB_PRINTF(*db->arch), PKG_FILE_PRINTF(pkg));
|
||||||
|
else
|
||||||
|
r = snprintf(buf, len, "%s%s" BLOB_FMT "/%s",
|
||||||
|
repo->url, repo->url[strlen(repo->url)-1] == '/' ? "" : "/",
|
||||||
|
BLOB_PRINTF(*db->arch), apkindex_tar_gz);
|
||||||
|
if (r >= len)
|
||||||
|
return -ENOBUFS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int apk_repo_format_item(struct apk_database *db, struct apk_repository *repo, struct apk_package *pkg,
|
||||||
|
int *fd, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
if (strcmp(repo->url, "cache") == 0) {
|
||||||
|
*fd = db->cache_fd;
|
||||||
|
return apk_pkg_format_cache_pkg(APK_BLOB_PTR_LEN(buf, len), pkg);
|
||||||
|
} else {
|
||||||
|
*fd = AT_FDCWD;
|
||||||
|
return apk_repo_format_real_url(db, repo, pkg, buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int apk_cache_download(struct apk_database *db, struct apk_repository *repo,
|
||||||
|
struct apk_package *pkg, int verify)
|
||||||
|
{
|
||||||
|
char cacheitem[128], url[PATH_MAX];
|
||||||
|
struct apk_istream *is;
|
||||||
|
struct apk_bstream *bs;
|
||||||
|
struct apk_sign_ctx sctx;
|
||||||
|
int r, fd;
|
||||||
|
|
||||||
|
if (pkg != NULL)
|
||||||
|
r = apk_pkg_format_cache_pkg(APK_BLOB_BUF(cacheitem), pkg);
|
||||||
|
else
|
||||||
|
r = apk_repo_format_cache_index(APK_BLOB_BUF(cacheitem), repo);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = apk_repo_format_real_url(db, repo, pkg, url, sizeof(url));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
apk_message("fetch %s", url);
|
||||||
|
|
||||||
if (apk_flags & APK_SIMULATE)
|
if (apk_flags & APK_SIMULATE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = apk_url_download(fullurl, db->cachetmp_fd, cacheitem);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (verify != APK_SIGN_NONE) {
|
if (verify != APK_SIGN_NONE) {
|
||||||
struct apk_istream *is;
|
|
||||||
struct apk_sign_ctx sctx;
|
|
||||||
|
|
||||||
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd);
|
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd);
|
||||||
is = apk_bstream_gunzip_mpart(
|
bs = apk_bstream_from_url(url);
|
||||||
apk_bstream_from_file(db->cachetmp_fd, cacheitem),
|
bs = apk_bstream_tee(bs, db->cachetmp_fd, cacheitem);
|
||||||
apk_sign_ctx_mpart_cb, &sctx);
|
is = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &sctx);
|
||||||
|
|
||||||
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE, &db->id_cache);
|
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE, &db->id_cache);
|
||||||
is->close(is);
|
|
||||||
apk_sign_ctx_free(&sctx);
|
apk_sign_ctx_free(&sctx);
|
||||||
if (r != 0) {
|
} else {
|
||||||
unlinkat(db->cachetmp_fd, cacheitem, 0);
|
is = apk_istream_from_url(url);
|
||||||
return r;
|
fd = openat(db->cachetmp_fd, cacheitem, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
|
||||||
|
if (fd >= 0) {
|
||||||
|
r = apk_istream_splice(is, fd, APK_SPLICE_ALL, NULL, NULL);
|
||||||
|
close(fd);
|
||||||
|
} else {
|
||||||
|
r = -errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is->close(is);
|
||||||
|
if (r < 0) {
|
||||||
|
unlinkat(db->cachetmp_fd, cacheitem, 0);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if (db->cachetmp_fd != db->cache_fd) {
|
if (db->cachetmp_fd != db->cache_fd) {
|
||||||
if (renameat(db->cachetmp_fd, cacheitem, db->cache_fd, cacheitem) < 0)
|
if (renameat(db->cachetmp_fd, cacheitem, db->cache_fd, cacheitem) < 0)
|
||||||
|
@ -1802,7 +1865,7 @@ static int foreach_cache_file(void *pctx, int dirfd, const char *name)
|
||||||
if (pkg0->name != name)
|
if (pkg0->name != name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
apk_pkg_format_cache(pkg0, APK_BLOB_BUF(tmp));
|
apk_pkg_format_cache_pkg(APK_BLOB_BUF(tmp), pkg0);
|
||||||
if (apk_blob_compare(b, APK_BLOB_STR(tmp)) == 0) {
|
if (apk_blob_compare(b, APK_BLOB_STR(tmp)) == 0) {
|
||||||
pkg = pkg0;
|
pkg = pkg0;
|
||||||
break;
|
break;
|
||||||
|
@ -1878,24 +1941,6 @@ struct apk_package *apk_db_get_file_owner(struct apk_database *db,
|
||||||
return dbf->diri->pkg;
|
return dbf->diri->pkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
int apk_repo_format_filename(char *buf, size_t len,
|
|
||||||
const char *repourl, apk_blob_t *arch,
|
|
||||||
const char *item)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (arch != NULL)
|
|
||||||
n = snprintf(buf, len, "%s%s" BLOB_FMT "/%s",
|
|
||||||
repourl, repourl[strlen(repourl)-1] == '/' ? "" : "/",
|
|
||||||
BLOB_PRINTF(*arch), item);
|
|
||||||
else
|
|
||||||
n = snprintf(buf, len, "%s%s%s",
|
|
||||||
repourl, repourl[strlen(repourl)-1] == '/' ? "" : "/",
|
|
||||||
item);
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int apk_db_get_pinning_mask_repos(struct apk_database *db, unsigned short pinning_mask)
|
unsigned int apk_db_get_pinning_mask_repos(struct apk_database *db, unsigned short pinning_mask)
|
||||||
{
|
{
|
||||||
unsigned int repository_mask = 0;
|
unsigned int repository_mask = 0;
|
||||||
|
@ -1910,22 +1955,6 @@ unsigned int apk_db_get_pinning_mask_repos(struct apk_database *db, unsigned sho
|
||||||
return repository_mask;
|
return repository_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct apk_bstream *apk_repo_file_open(struct apk_repository *repo,
|
|
||||||
apk_blob_t *arch,
|
|
||||||
const char *file,
|
|
||||||
char *buf, int buflen)
|
|
||||||
{
|
|
||||||
const char *url = repo->url;
|
|
||||||
|
|
||||||
apk_repo_format_filename(buf, buflen, url, arch, file);
|
|
||||||
|
|
||||||
/* We should not get called for non-repository files */
|
|
||||||
if (strcmp(repo->url, "cache") == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return apk_bstream_from_url(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct apk_repository *apk_db_select_repo(struct apk_database *db,
|
struct apk_repository *apk_db_select_repo(struct apk_database *db,
|
||||||
struct apk_package *pkg)
|
struct apk_package *pkg)
|
||||||
{
|
{
|
||||||
|
@ -1950,13 +1979,9 @@ struct apk_repository *apk_db_select_repo(struct apk_database *db,
|
||||||
|
|
||||||
static int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
|
static int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
|
||||||
{
|
{
|
||||||
char cacheitem[PATH_MAX];
|
int r, verify = (apk_flags & APK_ALLOW_UNTRUSTED) ? APK_SIGN_NONE : APK_SIGN_VERIFY;
|
||||||
int r;
|
|
||||||
|
|
||||||
apk_cache_format_index(APK_BLOB_BUF(cacheitem), repo);
|
r = apk_cache_download(db, repo, NULL, verify);
|
||||||
r = apk_cache_download(db, repo->url, db->arch, apkindex_tar_gz, cacheitem,
|
|
||||||
(apk_flags & APK_ALLOW_UNTRUSTED) ?
|
|
||||||
APK_SIGN_NONE : APK_SIGN_VERIFY);
|
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
apk_error("%s: %s", repo->url, apk_error_str(r));
|
apk_error("%s: %s", repo->url, apk_error_str(r));
|
||||||
|
|
||||||
|
@ -2083,17 +2108,19 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository)
|
||||||
if (apk_flags & APK_UPDATE_CACHE)
|
if (apk_flags & APK_UPDATE_CACHE)
|
||||||
apk_repository_update(db, repo);
|
apk_repository_update(db, repo);
|
||||||
}
|
}
|
||||||
apk_cache_format_index(APK_BLOB_BUF(buf), repo);
|
r = apk_repo_format_cache_index(APK_BLOB_BUF(buf), repo);
|
||||||
bs = apk_bstream_from_file(db->cache_fd, buf);
|
|
||||||
} else {
|
} else {
|
||||||
db->local_repos |= BIT(repo_num);
|
db->local_repos |= BIT(repo_num);
|
||||||
db->available_repos |= BIT(repo_num);
|
db->available_repos |= BIT(repo_num);
|
||||||
bs = apk_repo_file_open(repo, db->arch, apkindex_tar_gz, buf, sizeof(buf));
|
r = apk_repo_format_real_url(db, repo, NULL, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (r == 0) {
|
||||||
|
bs = apk_bstream_from_fd_url(db->cache_fd, buf);
|
||||||
|
if (bs != NULL)
|
||||||
|
r = load_index(db, bs, targz, repo_num);
|
||||||
|
else
|
||||||
|
r = -ENOENT;
|
||||||
}
|
}
|
||||||
if (bs != NULL)
|
|
||||||
r = load_index(db, bs, targz, repo_num);
|
|
||||||
else
|
|
||||||
r = -ENOENT;
|
|
||||||
|
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
apk_warning("Ignoring %s: %s", buf, apk_error_str(r));
|
apk_warning("Ignoring %s: %s", buf, apk_error_str(r));
|
||||||
|
@ -2386,8 +2413,8 @@ static void apk_db_purge_pkg(struct apk_database *db,
|
||||||
|
|
||||||
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
|
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
|
||||||
snprintf(name, sizeof(name),
|
snprintf(name, sizeof(name),
|
||||||
PKG_FILE_FMT "%s",
|
DIR_FILE_FMT "%s",
|
||||||
PKG_FILE_PRINTF(diri->dir, file),
|
DIR_FILE_PRINTF(diri->dir, file),
|
||||||
exten ?: "");
|
exten ?: "");
|
||||||
|
|
||||||
key = (struct apk_db_file_hash_key) {
|
key = (struct apk_db_file_hash_key) {
|
||||||
|
@ -2433,10 +2460,10 @@ static void apk_db_migrate_files(struct apk_database *db,
|
||||||
dir->modified = 1;
|
dir->modified = 1;
|
||||||
|
|
||||||
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
|
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
|
||||||
snprintf(name, sizeof(name), PKG_FILE_FMT,
|
snprintf(name, sizeof(name), DIR_FILE_FMT,
|
||||||
PKG_FILE_PRINTF(diri->dir, file));
|
DIR_FILE_PRINTF(diri->dir, file));
|
||||||
snprintf(tmpname, sizeof(tmpname), PKG_FILE_FMT ".apk-new",
|
snprintf(tmpname, sizeof(tmpname), DIR_FILE_FMT ".apk-new",
|
||||||
PKG_FILE_PRINTF(diri->dir, file));
|
DIR_FILE_PRINTF(diri->dir, file));
|
||||||
|
|
||||||
key = (struct apk_db_file_hash_key) {
|
key = (struct apk_db_file_hash_key) {
|
||||||
.dirname = APK_BLOB_PTR_LEN(dir->name, dir->namelen),
|
.dirname = APK_BLOB_PTR_LEN(dir->name, dir->namelen),
|
||||||
|
@ -2510,49 +2537,43 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
||||||
struct install_ctx ctx;
|
struct install_ctx ctx;
|
||||||
struct apk_bstream *bs = NULL;
|
struct apk_bstream *bs = NULL;
|
||||||
struct apk_istream *tar;
|
struct apk_istream *tar;
|
||||||
|
struct apk_repository *repo;
|
||||||
struct apk_package *pkg = ipkg->pkg;
|
struct apk_package *pkg = ipkg->pkg;
|
||||||
|
const char *action = "";
|
||||||
char file[PATH_MAX], item[128];
|
char file[PATH_MAX], item[128];
|
||||||
int r, need_copy = FALSE;
|
int r, filefd = AT_FDCWD, need_copy = FALSE;
|
||||||
|
|
||||||
if (pkg->filename == NULL) {
|
if (pkg->filename == NULL) {
|
||||||
struct apk_repository *repo;
|
|
||||||
|
|
||||||
repo = apk_db_select_repo(db, pkg);
|
repo = apk_db_select_repo(db, pkg);
|
||||||
if (repo == NULL) {
|
if (repo == NULL) {
|
||||||
apk_error("%s-%s: package is not currently available",
|
action = "unable to select package: ";
|
||||||
pkg->name->name, pkg->version);
|
r = -ENOPKG;
|
||||||
return -1;
|
goto err_msg;
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(repo->url, "cache") == 0) {
|
|
||||||
apk_pkg_format_cache(pkg, APK_BLOB_BUF(file));
|
|
||||||
bs = apk_bstream_from_file(db->cache_fd, file);
|
|
||||||
} else {
|
|
||||||
apk_pkg_format_plain(pkg, APK_BLOB_BUF(item));
|
|
||||||
bs = apk_repo_file_open(repo, pkg->arch,
|
|
||||||
item, file, sizeof(file));
|
|
||||||
if (!(pkg->repos & db->local_repos))
|
|
||||||
need_copy = TRUE;
|
|
||||||
}
|
}
|
||||||
|
r = apk_repo_format_item(db, repo, pkg, &filefd, file, sizeof(file));
|
||||||
|
if (r < 0)
|
||||||
|
goto err_msg;
|
||||||
|
if (!(pkg->repos & db->local_repos))
|
||||||
|
need_copy = TRUE;
|
||||||
} else {
|
} else {
|
||||||
bs = apk_bstream_from_file(AT_FDCWD, pkg->filename);
|
|
||||||
strncpy(file, pkg->filename, sizeof(file));
|
strncpy(file, pkg->filename, sizeof(file));
|
||||||
need_copy = TRUE;
|
need_copy = TRUE;
|
||||||
}
|
}
|
||||||
if (!apk_db_cache_active(db))
|
if (!apk_db_cache_active(db))
|
||||||
need_copy = FALSE;
|
need_copy = FALSE;
|
||||||
|
|
||||||
|
bs = apk_bstream_from_fd_url(filefd, file);
|
||||||
if (bs == NULL) {
|
if (bs == NULL) {
|
||||||
apk_error("%s: %s", file, strerror(errno));
|
r = -errno;
|
||||||
return errno;
|
goto err_msg;
|
||||||
}
|
}
|
||||||
if (need_copy) {
|
if (need_copy) {
|
||||||
apk_pkg_format_cache(pkg, APK_BLOB_BUF(item));
|
apk_pkg_format_cache_pkg(APK_BLOB_BUF(item), pkg);
|
||||||
bs = apk_bstream_tee(bs, db->cachetmp_fd, item);
|
bs = apk_bstream_tee(bs, db->cachetmp_fd, item);
|
||||||
if (bs == NULL) {
|
if (bs == NULL) {
|
||||||
apk_error("Unable to cache %s: %s",
|
action = "unable cache package: ";
|
||||||
file, strerror(errno));
|
r = -errno;
|
||||||
return errno;
|
goto err_msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2580,19 +2601,20 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
||||||
unlinkat(db->cachetmp_fd, item, 0);
|
unlinkat(db->cachetmp_fd, item, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r != 0) {
|
|
||||||
apk_error("%s: %s", file, apk_error_str(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
r = apk_db_run_pending_script(&ctx);
|
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
goto err;
|
goto err_msg;
|
||||||
|
|
||||||
|
r = apk_db_run_pending_script(&ctx);
|
||||||
|
if (r != 0) {
|
||||||
|
action = "unable to run script: ";
|
||||||
|
goto err_msg;
|
||||||
|
}
|
||||||
|
|
||||||
apk_db_migrate_files(db, ipkg);
|
apk_db_migrate_files(db, ipkg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err_msg:
|
||||||
|
apk_error("%s: %s%s", file, action, apk_error_str(r));
|
||||||
if (!reinstall)
|
if (!reinstall)
|
||||||
apk_db_purge_pkg(db, ipkg, ".apk-new");
|
apk_db_purge_pkg(db, ipkg, ".apk-new");
|
||||||
return r;
|
return r;
|
||||||
|
|
61
src/fetch.c
61
src/fetch.c
|
@ -95,67 +95,74 @@ static int fetch_package(struct fetch_ctx *fctx,
|
||||||
{
|
{
|
||||||
struct apk_istream *is;
|
struct apk_istream *is;
|
||||||
struct apk_repository *repo;
|
struct apk_repository *repo;
|
||||||
char pkgfile[PATH_MAX], url[PATH_MAX];
|
struct apk_file_info fi;
|
||||||
int r, fd;
|
char url[PATH_MAX], filename[256];
|
||||||
|
int r, fd, urlfd;
|
||||||
|
|
||||||
apk_pkg_format_plain(pkg, APK_BLOB_BUF(pkgfile));
|
repo = apk_db_select_repo(db, pkg);
|
||||||
|
if (repo == NULL) {
|
||||||
|
r = -ENOPKG;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snprintf(filename, sizeof(filename), PKG_FILE_FMT, PKG_FILE_PRINTF(pkg)) >= sizeof(filename)) {
|
||||||
|
r = -ENOBUFS;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(fctx->flags & FETCH_STDOUT)) {
|
if (!(fctx->flags & FETCH_STDOUT)) {
|
||||||
struct apk_file_info fi;
|
if (apk_file_get_info(fctx->outdir_fd, filename, APK_CHECKSUM_NONE, &fi) == 0 &&
|
||||||
|
|
||||||
if (apk_file_get_info(fctx->outdir_fd, pkgfile,
|
|
||||||
APK_CHECKSUM_NONE, &fi) == 0 &&
|
|
||||||
fi.size == pkg->size)
|
fi.size == pkg->size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
apk_message("Downloading " PKG_VER_FMT, PKG_VER_PRINTF(pkg));
|
apk_message("Downloading " PKG_VER_FMT, PKG_VER_PRINTF(pkg));
|
||||||
repo = apk_db_select_repo(db, pkg);
|
|
||||||
if (repo == NULL) {
|
|
||||||
apk_error(PKG_VER_FMT ": package is not currently available",
|
|
||||||
PKG_VER_PRINTF(pkg));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apk_flags & APK_SIMULATE)
|
if (apk_flags & APK_SIMULATE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
apk_repo_format_filename(url, sizeof(url), repo->url, pkg->arch, pkgfile);
|
r = apk_repo_format_item(db, repo, pkg, &urlfd, url, sizeof(url));
|
||||||
|
if (r < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (fctx->flags & FETCH_STDOUT) {
|
if (fctx->flags & FETCH_STDOUT) {
|
||||||
fd = STDOUT_FILENO;
|
fd = STDOUT_FILENO;
|
||||||
} else {
|
} else {
|
||||||
if ((fctx->flags & FETCH_LINK) && apk_url_local_file(url)) {
|
if ((fctx->flags & FETCH_LINK) && urlfd >= 0) {
|
||||||
if (linkat(AT_FDCWD, url,
|
if (linkat(urlfd, url,
|
||||||
fctx->outdir_fd, pkgfile,
|
fctx->outdir_fd, filename,
|
||||||
AT_SYMLINK_FOLLOW) == 0)
|
AT_SYMLINK_FOLLOW) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fd = openat(fctx->outdir_fd, pkgfile,
|
fd = openat(fctx->outdir_fd, filename,
|
||||||
O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644);
|
O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
apk_error("%s: %s", pkgfile, strerror(errno));
|
r = -errno;
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is = apk_istream_from_url(url);
|
is = apk_istream_from_fd_url(urlfd, url);
|
||||||
if (is == NULL) {
|
if (is == NULL) {
|
||||||
apk_error("Unable to download '%s'", url);
|
r = -EIO;
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = apk_istream_splice(is, fd, pkg->size, NULL, NULL);
|
r = apk_istream_splice(is, fd, pkg->size, NULL, NULL);
|
||||||
is->close(is);
|
is->close(is);
|
||||||
if (fd != STDOUT_FILENO)
|
if (fd != STDOUT_FILENO)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (r != pkg->size) {
|
if (r != pkg->size) {
|
||||||
apk_error("Unable to download '%s'", url);
|
unlinkat(fctx->outdir_fd, filename, 0);
|
||||||
unlinkat(fctx->outdir_fd, pkgfile, 0);
|
if (r >= 0) r = -EIO;
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
apk_error(PKG_VER_FMT ": %s", PKG_VER_PRINTF(pkg), apk_error_str(r));
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fetch_main(void *ctx, struct apk_database *db, int argc, char **argv)
|
static int fetch_main(void *ctx, struct apk_database *db, int argc, char **argv)
|
||||||
|
|
|
@ -314,7 +314,7 @@ static void info_print_contents(struct apk_database *db, struct apk_package *pkg
|
||||||
diri_files_list) {
|
diri_files_list) {
|
||||||
if (apk_verbosity > 1)
|
if (apk_verbosity > 1)
|
||||||
printf("%s: ", pkg->name->name);
|
printf("%s: ", pkg->name->name);
|
||||||
printf(PKG_FILE_FMT "\n", PKG_FILE_PRINTF(diri->dir, file));
|
printf(DIR_FILE_FMT "\n", DIR_FILE_PRINTF(diri->dir, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,29 +53,6 @@ struct apk_package *apk_pkg_get_installed(struct apk_name *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apk_pkg_format_plain(struct apk_package *pkg, apk_blob_t to)
|
|
||||||
{
|
|
||||||
/* pkgname-1.0.apk */
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR(pkg->name->name));
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR("-"));
|
|
||||||
apk_blob_push_blob(&to, *pkg->version);
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR(".apk"));
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void apk_pkg_format_cache(struct apk_package *pkg, apk_blob_t to)
|
|
||||||
{
|
|
||||||
/* pkgname-1.0_alpha1.12345678.apk */
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR(pkg->name->name));
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR("-"));
|
|
||||||
apk_blob_push_blob(&to, *pkg->version);
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR("."));
|
|
||||||
apk_blob_push_hexdump(&to, APK_BLOB_PTR_LEN((char *) pkg->csum.data,
|
|
||||||
APK_CACHE_CSUM_BYTES));
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_STR(".apk"));
|
|
||||||
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct apk_package *apk_pkg_new(void)
|
struct apk_package *apk_pkg_new(void)
|
||||||
{
|
{
|
||||||
struct apk_package *pkg;
|
struct apk_package *pkg;
|
||||||
|
|
|
@ -84,6 +84,8 @@ const char *apk_error_str(int error)
|
||||||
return "BAD archive";
|
return "BAD archive";
|
||||||
case ENOMSG:
|
case ENOMSG:
|
||||||
return "archive does not contain expected data";
|
return "archive does not contain expected data";
|
||||||
|
case ENOPKG:
|
||||||
|
return "package not available";
|
||||||
default:
|
default:
|
||||||
return strerror(error);
|
return strerror(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -427,7 +427,7 @@ static int compare_providers(struct apk_solver_state *ss,
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Prefer available */
|
/* Prefer available */
|
||||||
if (solver_flags & APK_SOLVERF_AVAILABLE) {
|
if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
|
||||||
r = !!(pkgA->repos & db->available_repos) -
|
r = !!(pkgA->repos & db->available_repos) -
|
||||||
!!(pkgB->repos & db->available_repos);
|
!!(pkgB->repos & db->available_repos);
|
||||||
if (r)
|
if (r)
|
||||||
|
|
Loading…
Reference in New Issue