diff --git a/src/apk_database.h b/src/apk_database.h
index 43d879f..48bd5f9 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -21,9 +21,6 @@
 #include "apk_provider_data.h"
 #include "apk_solver_data.h"
 
-extern const char * const apk_index_gz;
-extern const char * const apkindex_tar_gz;
-
 struct apk_name;
 APK_ARRAY(apk_name_array, struct apk_name *);
 
@@ -71,8 +68,8 @@ struct apk_db_dir {
 	char name[];
 };
 
-#define PKG_FILE_FMT			"%s%s%s"
-#define PKG_FILE_PRINTF(dir,file)	(dir)->name, (dir)->namelen ? "/" : "", (file)->name
+#define DIR_FILE_FMT			"%s%s%s"
+#define DIR_FILE_PRINTF(dir,file)	(dir)->name, (dir)->namelen ? "/" : "", (file)->name
 
 struct apk_db_dir_instance {
 	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);
 struct apk_repository *apk_db_select_repo(struct apk_database *db,
 					  struct apk_package *pkg);
-int apk_repo_format_filename(char *buf, size_t len,
-			     const char *repourl, apk_blob_t *arch,
-			     const char *pkgfile);
+
+int apk_repo_format_cache_index(apk_blob_t to, struct apk_repository *repo);
+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);
 
 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, const char *url, apk_blob_t *arch,
-		       const char *item, const char *cache_item, int verify);
+int apk_cache_download(struct apk_database *db, struct apk_repository *repo,
+		       struct apk_package *pkg, int verify);
 
 typedef void (*apk_cache_item_cb)(struct apk_database *db,
 				  int dirfd, const char *name,
diff --git a/src/apk_package.h b/src/apk_package.h
index 979de5e..7f7a37c 100644
--- a/src/apk_package.h
+++ b/src/apk_package.h
@@ -123,6 +123,8 @@ APK_ARRAY(apk_package_array, struct apk_package *);
 
 #define PKG_VER_FMT		"%s-" BLOB_FMT
 #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[];
 
@@ -160,8 +162,6 @@ int apk_script_type(const char *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);
 int apk_pkg_read(struct apk_database *db, const char *name,
 		 struct apk_sign_ctx *ctx, struct apk_package **pkg);
diff --git a/src/cache.c b/src/cache.c
index fc58f7e..d1ce06e 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -31,7 +31,6 @@ static int cache_download(struct apk_database *db)
 	struct apk_change *change;
 	struct apk_package *pkg;
 	struct apk_repository *repo;
-	char item[PATH_MAX], cacheitem[PATH_MAX];
 	int i, r, ret = 0;
 
 	r = apk_solver_solve(db, 0, db->world, &changeset);
@@ -50,13 +49,9 @@ static int cache_download(struct apk_database *db)
 		if (repo == NULL)
 			continue;
 
-		apk_pkg_format_cache(pkg, APK_BLOB_BUF(cacheitem));
-		apk_pkg_format_plain(pkg, APK_BLOB_BUF(item));
-		r = apk_cache_download(db, repo->url, pkg->arch,
-					item, cacheitem,
-					APK_SIGN_VERIFY_IDENTITY);
+		r = apk_cache_download(db, repo, pkg, APK_SIGN_VERIFY_IDENTITY);
 		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++;
 		}
 	}
@@ -76,7 +71,7 @@ static void cache_clean_item(struct apk_database *db, int dirfd, const char *nam
 	b = APK_BLOB_STR(name);
 	for (i = 0; i < db->num_repos; i++) {
 		/* 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)
 			return;
 	}
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;
+}
+
+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)
 		return 0;
 
-	r = apk_url_download(fullurl, db->cachetmp_fd, cacheitem);
-	if (r < 0)
-		return r;
-
 	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);
-		is = apk_bstream_gunzip_mpart(
-			apk_bstream_from_file(db->cachetmp_fd, cacheitem),
-			apk_sign_ctx_mpart_cb, &sctx);
-
+		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) {
-		apk_error("%s: %s", file, apk_error_str(r));
-		goto err;
-	}
-	r = apk_db_run_pending_script(&ctx);
 	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);
 
 	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;
diff --git a/src/fetch.c b/src/fetch.c
index f3debd0..028a999 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -95,67 +95,74 @@ static int fetch_package(struct fetch_ctx *fctx,
 {
 	struct apk_istream *is;
 	struct apk_repository *repo;
-	char pkgfile[PATH_MAX], url[PATH_MAX];
-	int r, fd;
+	struct apk_file_info fi;
+	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)) {
-		struct apk_file_info fi;
-
-		if (apk_file_get_info(fctx->outdir_fd, pkgfile,
-				      APK_CHECKSUM_NONE, &fi) == 0 &&
+		if (apk_file_get_info(fctx->outdir_fd, filename, APK_CHECKSUM_NONE, &fi) == 0 &&
 		    fi.size == pkg->size)
 			return 0;
 	}
 
 	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)
 		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) {
 		fd = STDOUT_FILENO;
 	} else {
-		if ((fctx->flags & FETCH_LINK) && apk_url_local_file(url)) {
-			if (linkat(AT_FDCWD, url,
-				   fctx->outdir_fd, pkgfile,
+		if ((fctx->flags & FETCH_LINK) && urlfd >= 0) {
+			if (linkat(urlfd, url,
+				   fctx->outdir_fd, filename,
 				   AT_SYMLINK_FOLLOW) == 0)
 				return 0;
 		}
-		fd = openat(fctx->outdir_fd, pkgfile,
+		fd = openat(fctx->outdir_fd, filename,
 			    O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644);
 		if (fd < 0) {
-			apk_error("%s: %s", pkgfile, strerror(errno));
-			return -1;
+			r = -errno;
+			goto err;
 		}
 	}
 
-	is = apk_istream_from_url(url);
+	is = apk_istream_from_fd_url(urlfd, url);
 	if (is == NULL) {
-		apk_error("Unable to download '%s'", url);
-		return -1;
+		r = -EIO;
+		goto err;
 	}
 
 	r = apk_istream_splice(is, fd, pkg->size, NULL, NULL);
 	is->close(is);
 	if (fd != STDOUT_FILENO)
 		close(fd);
+
 	if (r != pkg->size) {
-		apk_error("Unable to download '%s'", url);
-		unlinkat(fctx->outdir_fd, pkgfile, 0);
-		return -1;
+		unlinkat(fctx->outdir_fd, filename, 0);
+		if (r >= 0) r = -EIO;
+		goto err;
 	}
 
 	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)
diff --git a/src/info.c b/src/info.c
index f643df2..0abff22 100644
--- a/src/info.c
+++ b/src/info.c
@@ -314,7 +314,7 @@ static void info_print_contents(struct apk_database *db, struct apk_package *pkg
 					  diri_files_list) {
 			if (apk_verbosity > 1)
 				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));
 		}
 	}
 }
diff --git a/src/package.c b/src/package.c
index 0fca1db..61927e7 100644
--- a/src/package.c
+++ b/src/package.c
@@ -53,29 +53,6 @@ struct apk_package *apk_pkg_get_installed(struct apk_name *name)
 	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 *pkg;
diff --git a/src/print.c b/src/print.c
index 93ef931..aceef38 100644
--- a/src/print.c
+++ b/src/print.c
@@ -84,6 +84,8 @@ const char *apk_error_str(int error)
 		return "BAD archive";
 	case ENOMSG:
 		return "archive does not contain expected data";
+	case ENOPKG:
+		return "package not available";
 	default:
 		return strerror(error);
 	}
diff --git a/src/solver.c b/src/solver.c
index 1b55496..279d1f6 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -427,7 +427,7 @@ static int compare_providers(struct apk_solver_state *ss,
 		return r;
 
 	/* Prefer available */
-	if (solver_flags & APK_SOLVERF_AVAILABLE) {
+	if (solver_flags & (APK_SOLVERF_AVAILABLE | APK_SOLVERF_REINSTALL)) {
 		r = !!(pkgA->repos & db->available_repos) -
 		    !!(pkgB->repos & db->available_repos);
 		if (r)