summaryrefslogtreecommitdiff
path: root/src/database.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2013-06-17 14:24:34 +0300
committerTimo Teräs <timo.teras@iki.fi>2013-06-17 14:38:27 +0300
commit9d100378074d21f99dc26bae8417932dc110664e (patch)
treee66829190a5648b146698e372b2a9403d535f866 /src/database.c
parentdbb642206d2ef73c5428a04cb10bb27e7cdd3b29 (diff)
downloadapk-tools-9d100378074d21f99dc26bae8417932dc110664e.tar.gz
apk-tools-9d100378074d21f99dc26bae8417932dc110664e.tar.bz2
apk-tools-9d100378074d21f99dc26bae8417932dc110664e.tar.xz
apk-tools-9d100378074d21f99dc26bae8417932dc110664e.zip
db: refactor repository file construction
Fixes also 'fetch' applet to prefer copying/linking to files from cache if possible.
Diffstat (limited to 'src/database.c')
-rw-r--r--src/database.c236
1 files changed, 129 insertions, 107 deletions
diff --git a/src/database.c b/src/database.c
index c4f8433..199829f 100644
--- a/src/database.c
+++ b/src/database.c
@@ -46,7 +46,8 @@ enum {
int apk_verbosity = 1;
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_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;
}
-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 */
apk_blob_push_blob(&to, APK_BLOB_STR("APKINDEX."));
- apk_blob_push_hexdump(&to, APK_BLOB_PTR_LEN((char *) repo->csum.data,
- APK_CACHE_CSUM_BYTES));
+ apk_blob_push_hexdump(&to, APK_BLOB_PTR_LEN((char *) repo->csum.data, APK_CACHE_CSUM_BYTES));
apk_blob_push_blob(&to, APK_BLOB_STR(".tar.gz"));
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,
- const char *item, const char *cacheitem, int verify)
+int apk_repo_format_real_url(struct apk_database *db, struct apk_repository *repo,
+ struct apk_package *pkg, char *buf, size_t len)
{
- char fullurl[PATH_MAX];
int r;
- apk_repo_format_filename(fullurl, sizeof(fullurl), url, arch, item);
- apk_message("fetch %s", fullurl);
+ if (pkg != NULL)
+ 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;
+}
- if (apk_flags & APK_SIMULATE)
- 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);
+ }
+}
- r = apk_url_download(fullurl, db->cachetmp_fd, cacheitem);
+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;
- if (verify != APK_SIGN_NONE) {
- struct apk_istream *is;
- struct apk_sign_ctx sctx;
+ r = apk_repo_format_real_url(db, repo, pkg, url, sizeof(url));
+ if (r < 0)
+ return r;
- apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd);
- is = apk_bstream_gunzip_mpart(
- apk_bstream_from_file(db->cachetmp_fd, cacheitem),
- apk_sign_ctx_mpart_cb, &sctx);
+ apk_message("fetch %s", url);
+
+ if (apk_flags & APK_SIMULATE)
+ return 0;
+ if (verify != APK_SIGN_NONE) {
+ apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd);
+ bs = apk_bstream_from_url(url);
+ bs = apk_bstream_tee(bs, db->cachetmp_fd, cacheitem);
+ 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);
- is->close(is);
apk_sign_ctx_free(&sctx);
- if (r != 0) {
- unlinkat(db->cachetmp_fd, cacheitem, 0);
- return r;
+ } else {
+ is = apk_istream_from_url(url);
+ 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 (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)
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) {
pkg = pkg0;
break;
@@ -1878,24 +1941,6 @@ struct apk_package *apk_db_get_file_owner(struct apk_database *db,
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 repository_mask = 0;
@@ -1910,22 +1955,6 @@ unsigned int apk_db_get_pinning_mask_repos(struct apk_database *db, unsigned sho
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_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)
{
- char cacheitem[PATH_MAX];
- int r;
+ int r, verify = (apk_flags & APK_ALLOW_UNTRUSTED) ? APK_SIGN_NONE : APK_SIGN_VERIFY;
- apk_cache_format_index(APK_BLOB_BUF(cacheitem), repo);
- r = apk_cache_download(db, repo->url, db->arch, apkindex_tar_gz, cacheitem,
- (apk_flags & APK_ALLOW_UNTRUSTED) ?
- APK_SIGN_NONE : APK_SIGN_VERIFY);
+ r = apk_cache_download(db, repo, NULL, verify);
if (r != 0)
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)
apk_repository_update(db, repo);
}
- apk_cache_format_index(APK_BLOB_BUF(buf), repo);
- bs = apk_bstream_from_file(db->cache_fd, buf);
+ r = apk_repo_format_cache_index(APK_BLOB_BUF(buf), repo);
} else {
db->local_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) {
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) {
snprintf(name, sizeof(name),
- PKG_FILE_FMT "%s",
- PKG_FILE_PRINTF(diri->dir, file),
+ DIR_FILE_FMT "%s",
+ DIR_FILE_PRINTF(diri->dir, file),
exten ?: "");
key = (struct apk_db_file_hash_key) {
@@ -2433,10 +2460,10 @@ static void apk_db_migrate_files(struct apk_database *db,
dir->modified = 1;
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
- snprintf(name, sizeof(name), PKG_FILE_FMT,
- PKG_FILE_PRINTF(diri->dir, file));
- snprintf(tmpname, sizeof(tmpname), PKG_FILE_FMT ".apk-new",
- PKG_FILE_PRINTF(diri->dir, file));
+ snprintf(name, sizeof(name), DIR_FILE_FMT,
+ DIR_FILE_PRINTF(diri->dir, file));
+ snprintf(tmpname, sizeof(tmpname), DIR_FILE_FMT ".apk-new",
+ DIR_FILE_PRINTF(diri->dir, file));
key = (struct apk_db_file_hash_key) {
.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 apk_bstream *bs = NULL;
struct apk_istream *tar;
+ struct apk_repository *repo;
struct apk_package *pkg = ipkg->pkg;
+ const char *action = "";
char file[PATH_MAX], item[128];
- int r, need_copy = FALSE;
+ int r, filefd = AT_FDCWD, need_copy = FALSE;
if (pkg->filename == NULL) {
- struct apk_repository *repo;
-
repo = apk_db_select_repo(db, pkg);
if (repo == NULL) {
- apk_error("%s-%s: package is not currently available",
- pkg->name->name, pkg->version);
- return -1;
- }
-
- 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;
+ action = "unable to select package: ";
+ r = -ENOPKG;
+ goto err_msg;
}
+ 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 {
- bs = apk_bstream_from_file(AT_FDCWD, pkg->filename);
strncpy(file, pkg->filename, sizeof(file));
need_copy = TRUE;
}
if (!apk_db_cache_active(db))
need_copy = FALSE;
+ bs = apk_bstream_from_fd_url(filefd, file);
if (bs == NULL) {
- apk_error("%s: %s", file, strerror(errno));
- return errno;
+ r = -errno;
+ goto err_msg;
}
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);
if (bs == NULL) {
- apk_error("Unable to cache %s: %s",
- file, strerror(errno));
- return errno;
+ action = "unable cache package: ";
+ r = -errno;
+ goto err_msg;
}
}
@@ -2580,19 +2601,20 @@ static int apk_db_unpack_pkg(struct apk_database *db,
unlinkat(db->cachetmp_fd, item, 0);
}
}
+ if (r != 0)
+ goto err_msg;
+ r = apk_db_run_pending_script(&ctx);
if (r != 0) {
- apk_error("%s: %s", file, apk_error_str(r));
- goto err;
+ action = "unable to run script: ";
+ goto err_msg;
}
- r = apk_db_run_pending_script(&ctx);
- if (r != 0)
- goto err;
apk_db_migrate_files(db, ipkg);
return 0;
-err:
+err_msg:
+ apk_error("%s: %s%s", file, action, apk_error_str(r));
if (!reinstall)
apk_db_purge_pkg(db, ipkg, ".apk-new");
return r;