parent
a23f6f4afb
commit
9567337fd2
|
@ -27,6 +27,7 @@ apk_OBJS = \
|
|||
index.o \
|
||||
info.o \
|
||||
search.o \
|
||||
fetch.o \
|
||||
audit.o \
|
||||
apk.o
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@ typedef int (*apk_archive_entry_parser)(void *ctx,
|
|||
const struct apk_file_info *ae,
|
||||
struct apk_istream *istream);
|
||||
|
||||
int apk_file_get_info(const char *filename, struct apk_file_info *fi);
|
||||
|
||||
int apk_parse_tar(struct apk_istream *, apk_archive_entry_parser parser, void *ctx);
|
||||
int apk_parse_tar_gz(struct apk_bstream *, apk_archive_entry_parser parser, void *ctx);
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db,
|
|||
#define APK_OPENF_READ 0x0000
|
||||
#define APK_OPENF_WRITE 0x0001
|
||||
#define APK_OPENF_CREATE 0x0002
|
||||
#define APK_OPENF_EMPTY_STATE 0x0004
|
||||
|
||||
int apk_db_open(struct apk_database *db, const char *root, unsigned int flags);
|
||||
int apk_db_write_config(struct apk_database *db);
|
||||
|
|
|
@ -58,6 +58,7 @@ extern unsigned int apk_flags;
|
|||
#define APK_CLEAN_PROTECTED 0x0004
|
||||
#define APK_PROGRESS 0x0008
|
||||
#define APK_UPGRADE 0x0010
|
||||
#define APK_RECURSIVE 0x0020
|
||||
|
||||
#define apk_error(args...) apk_log("ERROR: ", args);
|
||||
#define apk_warning(args...) if (apk_verbosity > 0) { apk_log("WARNING: ", args); }
|
||||
|
|
|
@ -67,4 +67,6 @@ struct apk_ostream *apk_ostream_to_file_gz(const char *file, mode_t mode);
|
|||
apk_blob_t apk_blob_from_istream(struct apk_istream *istream, size_t size);
|
||||
apk_blob_t apk_blob_from_file(const char *file);
|
||||
|
||||
int apk_file_get_info(const char *filename, struct apk_file_info *fi);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,19 @@
|
|||
|
||||
#include "apk_database.h"
|
||||
|
||||
struct apk_state;
|
||||
typedef void *apk_name_state_t;
|
||||
|
||||
struct apk_change {
|
||||
struct list_head change_list;
|
||||
struct apk_package *oldpkg;
|
||||
struct apk_package *newpkg;
|
||||
};
|
||||
|
||||
struct apk_state {
|
||||
int refs;
|
||||
struct list_head change_list_head;
|
||||
apk_name_state_t name[];
|
||||
};
|
||||
|
||||
struct apk_state *apk_state_new(struct apk_database *db);
|
||||
struct apk_state *apk_state_dup(struct apk_state *state);
|
||||
|
|
|
@ -693,18 +693,20 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags)
|
|||
apk_blob_for_each_segment(blob, ":", add_protected_path, db);
|
||||
|
||||
if (root != NULL) {
|
||||
r = apk_db_read_state(db);
|
||||
if (r == -ENOENT && (flags & APK_OPENF_CREATE)) {
|
||||
r = apk_db_create(db);
|
||||
if (!(flags & APK_OPENF_EMPTY_STATE)) {
|
||||
r = apk_db_read_state(db);
|
||||
if (r == -ENOENT && (flags & APK_OPENF_CREATE)) {
|
||||
r = apk_db_create(db);
|
||||
if (r != 0) {
|
||||
msg = "Unable to create database";
|
||||
goto ret_r;
|
||||
}
|
||||
r = apk_db_read_state(db);
|
||||
}
|
||||
if (r != 0) {
|
||||
msg = "Unable to create database";
|
||||
msg = "Unable to read database state";
|
||||
goto ret_r;
|
||||
}
|
||||
r = apk_db_read_state(db);
|
||||
}
|
||||
if (r != 0) {
|
||||
msg = "Unable to read database state";
|
||||
goto ret_r;
|
||||
}
|
||||
|
||||
if (apk_repos == NULL)
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
/* fetch.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 <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "apk_applet.h"
|
||||
#include "apk_database.h"
|
||||
#include "apk_state.h"
|
||||
#include "apk_io.h"
|
||||
|
||||
#define FETCH_RECURSIVE 1
|
||||
#define FETCH_STDOUT 2
|
||||
|
||||
struct fetch_ctx {
|
||||
unsigned int flags;
|
||||
const char *outdir;
|
||||
};
|
||||
|
||||
static int fetch_parse(void *ctx, int optch, int optindex, const char *optarg)
|
||||
{
|
||||
struct fetch_ctx *fctx = (struct fetch_ctx *) ctx;
|
||||
|
||||
switch (optch) {
|
||||
case 'R':
|
||||
fctx->flags |= FETCH_RECURSIVE;
|
||||
break;
|
||||
case 's':
|
||||
fctx->flags |= FETCH_STDOUT;
|
||||
break;
|
||||
case 'o':
|
||||
fctx->outdir = optarg;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fetch_package(struct fetch_ctx *fctx,
|
||||
struct apk_database *db,
|
||||
struct apk_package *pkg)
|
||||
{
|
||||
struct apk_istream *is;
|
||||
char file[256];
|
||||
int i, r, fd;
|
||||
|
||||
if (fctx->flags & FETCH_STDOUT) {
|
||||
fd = STDOUT_FILENO;
|
||||
} else {
|
||||
struct apk_file_info fi;
|
||||
|
||||
snprintf(file, sizeof(file), "%s/%s-%s.apk",
|
||||
fctx->outdir ? fctx->outdir : ".",
|
||||
pkg->name->name, pkg->version);
|
||||
|
||||
if (apk_file_get_info(file, &fi) == 0 &&
|
||||
fi.size == pkg->size)
|
||||
return 0;
|
||||
|
||||
fd = creat(file, 0644);
|
||||
if (fd < 0) {
|
||||
apk_error("Unable to create '%s'", file);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
apk_message("Downloading %s-%s", pkg->name->name, pkg->version);
|
||||
|
||||
for (i = 0; i < APK_MAX_REPOS; i++)
|
||||
if (pkg->repos & BIT(i))
|
||||
break;
|
||||
|
||||
if (i >= APK_MAX_REPOS) {
|
||||
apk_error("%s-%s: not present in any repository",
|
||||
pkg->name->name, pkg->version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(file, sizeof(file), "%s/%s-%s.apk",
|
||||
db->repos[i].url, pkg->name->name, pkg->version);
|
||||
is = apk_istream_from_url(file);
|
||||
if (is == NULL) {
|
||||
apk_error("Unable to download '%s'", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = apk_istream_splice(is, fd, pkg->size, NULL, NULL);
|
||||
if (r != pkg->size) {
|
||||
is->close(is);
|
||||
apk_error("Unable to download '%s'", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fetch_main(void *ctx, int argc, char **argv)
|
||||
{
|
||||
struct fetch_ctx *fctx = (struct fetch_ctx *) ctx;
|
||||
struct apk_database db;
|
||||
int i, j, r;
|
||||
|
||||
r = apk_db_open(&db, apk_root, APK_OPENF_EMPTY_STATE);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
struct apk_dependency dep = (struct apk_dependency) {
|
||||
.name = apk_db_get_name(&db, APK_BLOB_STR(argv[i])),
|
||||
.result_mask = APK_DEPMASK_REQUIRE,
|
||||
};
|
||||
|
||||
if (fctx->flags & FETCH_RECURSIVE) {
|
||||
struct apk_state *state;
|
||||
struct apk_change *change;
|
||||
|
||||
state = apk_state_new(&db);
|
||||
r = apk_state_lock_dependency(state, &dep);
|
||||
if (r != 0) {
|
||||
apk_state_unref(state);
|
||||
apk_error("Unable to install '%s'",
|
||||
dep.name->name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
list_for_each_entry(change, &state->change_list_head, change_list) {
|
||||
r = fetch_package(fctx, &db, change->newpkg);
|
||||
if (r != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
apk_state_unref(state);
|
||||
} else if (dep.name->pkgs != NULL) {
|
||||
struct apk_package *pkg = NULL;
|
||||
|
||||
for (j = 0; j < dep.name->pkgs->num; j++)
|
||||
if (pkg == NULL ||
|
||||
apk_version_compare(APK_BLOB_STR(dep.name->pkgs->item[j]->version),
|
||||
APK_BLOB_STR(pkg->version))
|
||||
== APK_VERSION_GREATER)
|
||||
pkg = dep.name->pkgs->item[j];
|
||||
|
||||
r = fetch_package(fctx, &db, pkg);
|
||||
if (r != 0)
|
||||
goto err;
|
||||
} else {
|
||||
apk_message("Unable to get '%s'", dep.name->name);
|
||||
r = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
apk_db_close(&db);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct option fetch_options[] = {
|
||||
{ "recursive", no_argument, NULL, 'R' },
|
||||
{ "stdout", no_argument, NULL, 's' },
|
||||
{ "output", required_argument, NULL, 'o' },
|
||||
};
|
||||
|
||||
static struct apk_applet apk_fetch = {
|
||||
.name = "fetch",
|
||||
.usage = "[-R|--recursive|--stdout] [-o dir] apkname...",
|
||||
.context_size = sizeof(struct fetch_ctx),
|
||||
.num_options = ARRAY_SIZE(fetch_options),
|
||||
.options = fetch_options,
|
||||
.parse = fetch_parse,
|
||||
.main = fetch_main,
|
||||
};
|
||||
|
||||
APK_DEFINE_APPLET(apk_fetch);
|
||||
|
14
src/state.c
14
src/state.c
|
@ -16,25 +16,11 @@
|
|||
#include "apk_state.h"
|
||||
#include "apk_database.h"
|
||||
|
||||
typedef void *apk_name_state_t;
|
||||
|
||||
struct apk_change {
|
||||
struct list_head change_list;
|
||||
struct apk_package *oldpkg;
|
||||
struct apk_package *newpkg;
|
||||
};
|
||||
|
||||
struct apk_name_choices {
|
||||
unsigned short refs, num;
|
||||
struct apk_package *pkgs[];
|
||||
};
|
||||
|
||||
struct apk_state {
|
||||
int refs;
|
||||
struct list_head change_list_head;
|
||||
apk_name_state_t name[];
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct apk_deferred_state {
|
||||
unsigned int preference;
|
||||
|
|
Loading…
Reference in New Issue