cache: new applet (ref #49)
Administrative tool to download or delete files to/from the cache.cute-signatures
parent
233918e518
commit
9858ffff69
|
@ -3,7 +3,7 @@ apk-objs := state.o database.o package.o archive.o \
|
|||
version.o io.o url.o gunzip.o blob.o \
|
||||
hash.o md5.o apk.o \
|
||||
add.o del.o update.o info.o search.o upgrade.o \
|
||||
ver.o index.o fetch.o audit.o
|
||||
cache.o ver.o index.o fetch.o audit.o
|
||||
CFLAGS_apk.o := -DAPK_VERSION=\"$(FULL_VERSION)\"
|
||||
|
||||
progs-$(STATIC) += apk.static
|
||||
|
|
|
@ -328,5 +328,8 @@ int main(int argc, char **argv)
|
|||
argv++;
|
||||
}
|
||||
|
||||
return applet->main(ctx, argc, argv);
|
||||
r = applet->main(ctx, argc, argv);
|
||||
if (r == -100)
|
||||
return usage(applet);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#define APK_MAX_REPOS 32
|
||||
|
||||
extern const char * const apk_index_gz;
|
||||
|
||||
struct apk_name;
|
||||
APK_ARRAY(apk_name_array, struct apk_name *);
|
||||
|
||||
|
@ -120,6 +122,7 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db,
|
|||
int apk_db_open(struct apk_database *db, const char *root, unsigned int flags);
|
||||
int apk_db_write_config(struct apk_database *db);
|
||||
void apk_db_close(struct apk_database *db);
|
||||
int apk_db_cache_active(struct apk_database *db);
|
||||
|
||||
struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *file);
|
||||
struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg);
|
||||
|
@ -133,6 +136,10 @@ int apk_db_add_repository(apk_database_t db, apk_blob_t repository);
|
|||
int apk_repository_update(struct apk_database *db, struct apk_repository *repo);
|
||||
int apk_repository_update_all(struct apk_database *db);
|
||||
|
||||
int apk_cache_download(struct apk_database *db, csum_t csum,
|
||||
const char *url, const char *item);
|
||||
int apk_cache_exists(struct apk_database *db, csum_t csum, const char *item);
|
||||
|
||||
int apk_db_install_pkg(struct apk_database *db,
|
||||
struct apk_package *oldpkg,
|
||||
struct apk_package *newpkg,
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/* cache.c - Alpine Package Keeper (APK)
|
||||
*
|
||||
* Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
|
||||
* Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation. See http://www.gnu.org/ for details.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "apk_defines.h"
|
||||
#include "apk_applet.h"
|
||||
#include "apk_database.h"
|
||||
|
||||
#define CACHE_CLEAN BIT(0)
|
||||
#define CACHE_DOWNLOAD BIT(1)
|
||||
|
||||
static int cache_download(struct apk_database *db)
|
||||
{
|
||||
struct apk_package *pkg;
|
||||
char pkgfile[256];
|
||||
int i, r;
|
||||
|
||||
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
|
||||
snprintf(pkgfile, sizeof(pkgfile), "%s-%s.apk",
|
||||
pkg->name->name, pkg->version);
|
||||
if (apk_cache_exists(db, pkg->csum, pkgfile))
|
||||
continue;
|
||||
for (i = 0; i < db->num_repos; i++) {
|
||||
if (!(pkg->repos & BIT(i)))
|
||||
continue;
|
||||
|
||||
r = apk_cache_download(db, pkg->csum, db->repos[i].url,
|
||||
pkgfile);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cache_clean(struct apk_database *db)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
char path[256];
|
||||
int delete, i;
|
||||
csum_t csum;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", db->root, db->cache_dir);
|
||||
if (chdir(path) != 0)
|
||||
return -1;
|
||||
|
||||
dir = opendir(path);
|
||||
if (dir == NULL)
|
||||
return -1;
|
||||
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
delete = TRUE;
|
||||
do {
|
||||
if (strlen(de->d_name) <= sizeof(csum_t)*2+2)
|
||||
break;
|
||||
if (apk_hexdump_parse(APK_BLOB_BUF(csum),
|
||||
APK_BLOB_PTR_LEN(de->d_name,
|
||||
sizeof(csum_t) * 2)) != 0)
|
||||
break;
|
||||
if (de->d_name[sizeof(csum_t)*2] != '.')
|
||||
break;
|
||||
if (strcmp(&de->d_name[sizeof(csum_t)*2+1],
|
||||
apk_index_gz) == 0) {
|
||||
/* Index - check for matching repository */
|
||||
for (i = 0; i < db->num_repos; i++)
|
||||
if (memcmp(db->repos[i].url_csum,
|
||||
csum, sizeof(csum_t)) == 0)
|
||||
break;
|
||||
delete = (i >= db->num_repos);
|
||||
} else {
|
||||
/* Package - search for it */
|
||||
delete = (apk_db_get_pkg(db, csum) == NULL);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (delete) {
|
||||
if (apk_verbosity >= 2)
|
||||
apk_message("Deleting %s", de->d_name);
|
||||
if (!(apk_flags & APK_SIMULATE))
|
||||
unlink(de->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cache_main(void *ctx, int argc, char **argv)
|
||||
{
|
||||
struct apk_database db;
|
||||
int actions = 0;
|
||||
int r;
|
||||
|
||||
if (argc != 1)
|
||||
return -100;
|
||||
|
||||
if (strcmp(argv[0], "sync") == 0)
|
||||
actions = CACHE_CLEAN | CACHE_DOWNLOAD;
|
||||
else if (strcmp(argv[0], "clean") == 0)
|
||||
actions = CACHE_CLEAN;
|
||||
else if (strcmp(argv[0], "download") == 0)
|
||||
actions = CACHE_DOWNLOAD;
|
||||
else
|
||||
return -100;
|
||||
|
||||
r = apk_db_open(&db, apk_root,
|
||||
(actions & CACHE_DOWNLOAD) ? 0 : APK_OPENF_EMPTY_STATE);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (!apk_db_cache_active(&db)) {
|
||||
apk_error("Package cache is not enabled.\n");
|
||||
r = 2;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (r == 0 && (actions & CACHE_CLEAN))
|
||||
r = cache_clean(&db);
|
||||
if (r == 0 && (actions & CACHE_DOWNLOAD))
|
||||
r = cache_download(&db);
|
||||
|
||||
err:
|
||||
apk_db_close(&db);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct apk_applet apk_cache = {
|
||||
.name = "cache",
|
||||
.help = "Download missing PACKAGEs to cache directory, or delete "
|
||||
"files no longer required. Package caching is enabled by "
|
||||
"making /etc/apk/cache a symlink to the directory (on boot "
|
||||
"media) that will be used as package cache.",
|
||||
.arguments = "sync | clean | download",
|
||||
.main = cache_main,
|
||||
};
|
||||
|
||||
APK_DEFINE_APPLET(apk_cache);
|
|
@ -25,7 +25,7 @@
|
|||
#include "apk_state.h"
|
||||
#include "apk_applet.h"
|
||||
|
||||
static const char * const apk_index_gz = "APK_INDEX.gz";
|
||||
const char * const apk_index_gz = "APK_INDEX.gz";
|
||||
static const char * const apk_static_cache_dir = "var/lib/apk";
|
||||
static const char * const apk_linked_cache_dir = "etc/apk/cache";
|
||||
|
||||
|
@ -832,6 +832,11 @@ void apk_db_close(struct apk_database *db)
|
|||
free(db->root);
|
||||
}
|
||||
|
||||
int apk_db_cache_active(struct apk_database *db)
|
||||
{
|
||||
return db->cache_dir != apk_static_cache_dir;
|
||||
}
|
||||
|
||||
struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum)
|
||||
{
|
||||
return apk_hash_get(&db->available.packages,
|
||||
|
@ -908,7 +913,8 @@ static void apk_db_cache_get_name(char *buf, size_t bufsz,
|
|||
{
|
||||
char csumstr[sizeof(csum_t)*2+1];
|
||||
|
||||
apk_hexdump_format(sizeof(csumstr), csumstr, APK_BLOB_BUF(csum));
|
||||
apk_hexdump_format(sizeof(csumstr), csumstr,
|
||||
APK_BLOB_PTR_LEN((void *)csum, sizeof(csum_t)));
|
||||
snprintf(buf, bufsz, "%s/%s/%s.%s%s",
|
||||
db->root, db->cache_dir, csumstr, file, temp ? ".new" : "");
|
||||
}
|
||||
|
@ -935,32 +941,49 @@ static struct apk_bstream *apk_repository_file_open(struct apk_repository *repo,
|
|||
return apk_bstream_from_url(tmp);
|
||||
}
|
||||
|
||||
int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
|
||||
int apk_cache_download(struct apk_database *db, csum_t csum,
|
||||
const char *url, const char *item)
|
||||
{
|
||||
char tmp[256], tmp2[256];
|
||||
int r;
|
||||
|
||||
if (!csum_valid(repo->url_csum))
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", url, item);
|
||||
apk_message("fetch %s", tmp);
|
||||
|
||||
if (apk_flags & APK_SIMULATE)
|
||||
return 0;
|
||||
|
||||
apk_message("fetch index %s", repo->url);
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", repo->url, apk_index_gz);
|
||||
apk_db_cache_get_name(tmp2, sizeof(tmp2), db, repo->url_csum,
|
||||
apk_index_gz, TRUE);
|
||||
|
||||
apk_db_cache_get_name(tmp2, sizeof(tmp2), db, csum, item, TRUE);
|
||||
r = apk_url_download(tmp, tmp2);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
apk_db_cache_get_name(tmp, sizeof(tmp), db, repo->url_csum,
|
||||
apk_index_gz, FALSE);
|
||||
apk_db_cache_get_name(tmp, sizeof(tmp), db, csum, item, FALSE);
|
||||
if (rename(tmp2, tmp) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apk_cache_exists(struct apk_database *db, csum_t csum, const char *item)
|
||||
{
|
||||
char tmp[256];
|
||||
|
||||
if (db->root == NULL)
|
||||
return 0;
|
||||
|
||||
apk_db_cache_get_name(tmp, sizeof(tmp), db, csum, item, FALSE);
|
||||
return access(tmp, R_OK | W_OK) == 0;
|
||||
}
|
||||
|
||||
int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
|
||||
{
|
||||
if (!csum_valid(repo->url_csum))
|
||||
return 0;
|
||||
|
||||
return apk_cache_download(db, repo->url_csum, repo->url, apk_index_gz);
|
||||
}
|
||||
|
||||
int apk_repository_update_all(struct apk_database *db)
|
||||
{
|
||||
int i, ret;
|
||||
|
@ -1238,7 +1261,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
|||
struct install_ctx ctx;
|
||||
struct apk_bstream *bs = NULL;
|
||||
char pkgname[256], file[256];
|
||||
int i, need_copy = TRUE;
|
||||
int i, need_copy = FALSE;
|
||||
size_t length;
|
||||
|
||||
snprintf(pkgname, sizeof(pkgname), "%s-%s.apk",
|
||||
|
@ -1258,8 +1281,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
|||
}
|
||||
|
||||
repo = &db->repos[i];
|
||||
if (db->cache_dir != apk_static_cache_dir &&
|
||||
csum_valid(repo->url_csum))
|
||||
if (apk_db_cache_active(db) && csum_valid(repo->url_csum))
|
||||
bs = apk_db_cache_open(db, newpkg->csum, pkgname);
|
||||
|
||||
if (bs == NULL) {
|
||||
|
@ -1273,6 +1295,8 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
|||
bs = apk_bstream_from_file(newpkg->filename);
|
||||
need_copy = TRUE;
|
||||
}
|
||||
if (!apk_db_cache_active(db))
|
||||
need_copy = FALSE;
|
||||
if (need_copy) {
|
||||
apk_db_cache_get_name(file, sizeof(file), db, newpkg->csum,
|
||||
pkgname, TRUE);
|
||||
|
|
3
src/io.c
3
src/io.c
|
@ -331,7 +331,7 @@ static size_t tee_read(void *stream, void **ptr)
|
|||
{
|
||||
struct apk_tee_bstream *tbs =
|
||||
container_of(stream, struct apk_tee_bstream, bs);
|
||||
size_t size;
|
||||
ssize_t size;
|
||||
|
||||
size = tbs->inner_bs->read(tbs->inner_bs, ptr);
|
||||
if (size >= 0)
|
||||
|
@ -373,6 +373,7 @@ struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, const char *to)
|
|||
};
|
||||
tbs->inner_bs = from;
|
||||
tbs->fd = fd;
|
||||
tbs->size = 0;
|
||||
|
||||
return &tbs->bs;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue