summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2011-04-20 17:51:44 +0200
committerNatanael Copa <ncopa@alpinelinux.org>2011-04-20 17:51:44 +0200
commitf372bfd978be3874c3361cc022e8fc5842657ad2 (patch)
treec058b1de64347d4e65e862a1f5f9124434240a24
parentfde9ad1782dd4ddb28c428b488e0278471a91c90 (diff)
parent35bba3de1f4d6464dc03ffc60b6a6b6ec25ef6b0 (diff)
downloadapk-tools-lua.tar.bz2
apk-tools-lua.tar.xz
Merge branch 'lua-apk' into luaHEADlua
Conflicts: src/lua-apk.c
-rw-r--r--Makefile2
-rw-r--r--src/add.c2
-rw-r--r--src/apk.c27
-rw-r--r--src/apk_database.h9
-rw-r--r--src/apk_defines.h1
-rw-r--r--src/apk_io.h1
-rw-r--r--src/apk_package.h4
-rw-r--r--src/apk_state.h2
-rw-r--r--src/cache.c5
-rw-r--r--src/database.c281
-rw-r--r--src/del.c2
-rw-r--r--src/fetch.c10
-rw-r--r--src/fix.c2
-rw-r--r--src/index.c15
-rw-r--r--src/info.c80
-rw-r--r--src/io.c31
-rw-r--r--src/lua-apk.c82
-rw-r--r--src/package.c34
-rw-r--r--src/state.c235
-rw-r--r--src/upgrade.c28
-rw-r--r--src/url.c4
21 files changed, 645 insertions, 212 deletions
diff --git a/Makefile b/Makefile
index 1f0b2e2..023b21c 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
-include config.mk
PACKAGE := apk-tools
-VERSION := 2.0.7
+VERSION := 2.1.0_rc1
##
# Default directories
diff --git a/src/add.c b/src/add.c
index 977c772..d63f61d 100644
--- a/src/add.c
+++ b/src/add.c
@@ -142,7 +142,7 @@ static int add_main(void *ctx, struct apk_database *db, int argc, char **argv)
apk_state_print_errors(state);
r = -1;
} else {
- r = apk_state_commit(state, db);
+ r = apk_state_commit(state);
}
if (state != NULL)
apk_state_unref(state);
diff --git a/src/apk.c b/src/apk.c
index 4b97be5..c40cc20 100644
--- a/src/apk.c
+++ b/src/apk.c
@@ -17,7 +17,9 @@
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
+#include <unistd.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <openssl/crypto.h>
#ifndef OPENSSL_NO_ENGINE
@@ -31,6 +33,7 @@
#include "apk_print.h"
char **apk_argv;
+int apk_screen_width;
static struct apk_option generic_options[] = {
{ 'h', "help", "Show generic help or applet specific help" },
@@ -45,6 +48,7 @@ static struct apk_option generic_options[] = {
{ 'f', "force", "Do what was asked even if it looks dangerous" },
{ 'U', "update-cache", "Update the repository cache" },
{ 0x101, "progress", "Show a progress bar" },
+ { 0x110, "no-progress", "Disable progress bar even for TTYs" },
{ 0x102, "clean-protected", "Do not create .apk-new files to "
"configuration dirs" },
{ 0x106, "purge", "Delete also modified configuration files on "
@@ -62,6 +66,8 @@ static struct apk_option generic_options[] = {
required_argument, "REPOFILE" },
{ 0x109, "no-network", "Do not use network (cache is still used)" },
{ 0x111, "overlay-from-stdin", "Read list of overlay files from stdin" },
+ { 0x112, "arch", "Use architecture with --root",
+ required_argument, "ARCH" },
};
static int version(void)
@@ -236,6 +242,20 @@ static void init_openssl(void)
#endif
}
+static void setup_terminal(void)
+{
+ struct winsize w;
+
+ setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
+ if (ioctl(STDERR_FILENO,TIOCGWINSZ, &w) == 0)
+ apk_screen_width = w.ws_col;
+ else
+ apk_screen_width = 70;
+ if (isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) && isatty(STDIN_FILENO))
+ apk_flags |= APK_PROGRESS;
+
+}
+
int main(int argc, char **argv)
{
struct apk_applet *applet;
@@ -255,6 +275,7 @@ int main(int argc, char **argv)
list_init(&dbopts.repository_list);
apk_atom_init();
umask(0);
+ setup_terminal();
applet = deduce_applet(argc, argv);
num_options = ARRAY_SIZE(generic_options) + 1;
@@ -326,6 +347,9 @@ int main(int argc, char **argv)
case 0x101:
apk_flags |= APK_PROGRESS;
break;
+ case 0x110:
+ apk_flags &= ~APK_PROGRESS;
+ break;
case 0x102:
apk_flags |= APK_CLEAN_PROTECTED;
break;
@@ -347,6 +371,9 @@ int main(int argc, char **argv)
case 0x111:
apk_flags |= APK_OVERLAY_FROM_STDIN;
break;
+ case 0x112:
+ dbopts.arch = optarg;
+ break;
default:
if (applet == NULL || applet->parse == NULL ||
applet->parse(ctx, &dbopts, r,
diff --git a/src/apk_database.h b/src/apk_database.h
index b79253d..9b032e7 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -95,6 +95,7 @@ struct apk_db_options {
int lock_wait;
unsigned long open_flags;
char *root;
+ char *arch;
char *keys_dir;
char *repositories_file;
struct list_head repository_list;
@@ -105,9 +106,11 @@ struct apk_database {
int root_fd, lock_fd, cache_fd, cachetmp_fd, keys_fd;
unsigned name_id, num_repos;
const char *cache_dir;
+ char *cache_remount_dir;
apk_blob_t *arch;
unsigned int local_repos;
int permanent : 1;
+ int ro_cache : 1;
int compat_newfeatures : 1;
int compat_notinstallable : 1;
@@ -155,6 +158,7 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db,
#define APK_OPENF_NO_WORLD 0x0040
#define APK_OPENF_NO_SYS_REPOS 0x0100
#define APK_OPENF_NO_INSTALLED_REPO 0x0200
+#define APK_OPENF_CACHE_WRITE 0x0400
#define APK_OPENF_NO_REPOS (APK_OPENF_NO_SYS_REPOS | \
APK_OPENF_NO_INSTALLED_REPO)
@@ -180,10 +184,13 @@ 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_repository_update(struct apk_database *db, struct apk_repository *repo);
+int apk_repo_format_filename(char *buf, size_t len,
+ const char *repourl, apk_blob_t *arch,
+ const char *pkgfile);
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,
+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_db_install_pkg(struct apk_database *db,
diff --git a/src/apk_defines.h b/src/apk_defines.h
index b11d181..b5ad12e 100644
--- a/src/apk_defines.h
+++ b/src/apk_defines.h
@@ -51,6 +51,7 @@ extern int apk_verbosity;
extern unsigned int apk_flags;
extern const char *apk_arch;
extern char **apk_argv;
+extern int apk_screen_width;
#define APK_FORCE 0x0001
#define APK_SIMULATE 0x0002
diff --git a/src/apk_io.h b/src/apk_io.h
index 3845554..8cf24d8 100644
--- a/src/apk_io.h
+++ b/src/apk_io.h
@@ -110,6 +110,7 @@ apk_blob_t apk_blob_from_file(int atfd, const char *file);
int apk_file_get_info(int atfd, const char *filename, unsigned int flags,
struct apk_file_info *fi);
+int apk_move_file(int atfd, const char *from, const char *to);
int apk_url_download(const char *url, int atfd, const char *file);
const char *apk_url_local_file(const char *url);
diff --git a/src/apk_package.h b/src/apk_package.h
index ed25bd4..9802dfa 100644
--- a/src/apk_package.h
+++ b/src/apk_package.h
@@ -83,10 +83,12 @@ struct apk_package {
struct apk_name *name;
struct apk_installed_package *ipkg;
apk_blob_t *version, *arch, *license;
- char *url, *description;
+ apk_blob_t *origin, *maintainer;
+ char *url, *description, *commit;
char *filename;
struct apk_dependency_array *depends, *install_if;
size_t installed_size, size;
+ time_t build_time;
unsigned repos;
struct apk_checksum csum;
};
diff --git a/src/apk_state.h b/src/apk_state.h
index 1ac049a..e0df54e 100644
--- a/src/apk_state.h
+++ b/src/apk_state.h
@@ -37,7 +37,7 @@ struct apk_state *apk_state_dup(struct apk_state *state);
void apk_state_unref(struct apk_state *state);
void apk_state_print_errors(struct apk_state *state);
-int apk_state_commit(struct apk_state *state, struct apk_database *db);
+int apk_state_commit(struct apk_state *state);
int apk_state_lock_dependency(struct apk_state *state,
struct apk_dependency *dep);
int apk_state_lock_name(struct apk_state *state,
diff --git a/src/cache.c b/src/cache.c
index 60c7aeb..8cee1e4 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -58,7 +58,8 @@ static int cache_download(struct apk_database *db)
continue;
apk_pkg_format_plain(pkg, APK_BLOB_BUF(item));
- apk_cache_download(db, repo->url, item, cacheitem,
+ apk_cache_download(db, repo->url, pkg->arch,
+ item, cacheitem,
APK_SIGN_VERIFY_IDENTITY);
}
@@ -171,7 +172,7 @@ static struct apk_applet apk_cache = {
"making /etc/apk/cache a symlink to the directory (on boot "
"media) that will be used as package cache.",
.arguments = "sync | clean | download",
- .open_flags = APK_OPENF_READ|APK_OPENF_NO_SCRIPTS|APK_OPENF_NO_INSTALLED,
+ .open_flags = APK_OPENF_READ|APK_OPENF_NO_SCRIPTS|APK_OPENF_NO_INSTALLED|APK_OPENF_CACHE_WRITE,
.main = cache_main,
};
diff --git a/src/database.c b/src/database.c
index 53a18c7..45960d2 100644
--- a/src/database.c
+++ b/src/database.c
@@ -12,6 +12,7 @@
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
+#include <mntent.h>
#include <limits.h>
#include <unistd.h>
#include <malloc.h>
@@ -19,8 +20,11 @@
#include <stdlib.h>
#include <signal.h>
#include <fnmatch.h>
+#include <sys/vfs.h>
#include <sys/file.h>
+#include <sys/wait.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include "apk_defines.h"
#include "apk_package.h"
@@ -45,12 +49,29 @@ enum {
int apk_verbosity = 1;
unsigned int apk_flags = 0;
-const char *apk_arch = APK_DEFAULT_ARCH;
const char * const apkindex_tar_gz = "APKINDEX.tar.gz";
-static const char * const apk_static_cache_dir = "var/lib/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_lock_file = "var/lock/apkdb";
+
+static const char * const apk_world_file = "etc/apk/world";
+static const char * const apk_world_file_tmp = "etc/apk/world.new";
+static const char * const apk_world_file_old = "var/lib/apk/world";
+
+static const char * const apk_scripts_file = "lib/apk/db/scripts.tar";
+static const char * const apk_scripts_file_tmp = "lib/apk/db/scripts.tar.new";
+static const char * const apk_scripts_file_old = "var/lib/apk/scripts.tar";
+
+static const char * const apk_triggers_file = "lib/apk/db/triggers";
+static const char * const apk_triggers_file_tmp = "lib/apk/db/triggers.new";
+static const char * const apk_triggers_file_old = "var/lib/apk/triggers";
+
+static const char * const apk_installed_file = "lib/apk/db/installed";
+static const char * const apk_installed_file_tmp = "lib/apk/db/installed.new";
+static const char * const apk_installed_file_old = "var/lib/apk/installed";
+
struct install_ctx {
struct apk_database *db;
struct apk_package *pkg;
@@ -427,9 +448,7 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *
struct apk_package *idb;
if (pkg->license == NULL)
- pkg->license = apk_blob_atomize(APK_BLOB_NULL);
- if (pkg->arch == NULL)
- pkg->arch = apk_blob_atomize(APK_BLOB_STR(APK_DEFAULT_ARCH));
+ pkg->license = apk_blob_atomize(APK_BLOB_NULL);
idb = apk_hash_get(&db->available.packages, APK_BLOB_CSUM(pkg->csum));
if (idb == NULL) {
@@ -463,15 +482,13 @@ void apk_cache_format_index(apk_blob_t to, struct apk_repository *repo)
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
}
-int apk_cache_download(struct apk_database *db, const char *url,
+int apk_cache_download(struct apk_database *db, const char *url, apk_blob_t *arch,
const char *item, const char *cacheitem, int verify)
{
char fullurl[PATH_MAX];
int r;
- snprintf(fullurl, sizeof(fullurl), "%s%s" BLOB_FMT "/%s",
- url, url[strlen(url)-1] == '/' ? "" : "/",
- BLOB_PRINTF(*db->arch), item);
+ apk_repo_format_filename(fullurl, sizeof(fullurl), url, arch, item);
apk_message("fetch %s", fullurl);
if (apk_flags & APK_SIMULATE)
@@ -499,8 +516,10 @@ int apk_cache_download(struct apk_database *db, const char *url,
}
}
- if (renameat(db->cachetmp_fd, cacheitem, db->cache_fd, cacheitem) < 0)
- return -errno;
+ if (db->cachetmp_fd != db->cache_fd) {
+ if (renameat(db->cachetmp_fd, cacheitem, db->cache_fd, cacheitem) < 0)
+ return -errno;
+ }
return 0;
}
@@ -536,7 +555,6 @@ int apk_db_read_overlay(struct apk_database *db, struct apk_bstream *bs)
struct hlist_node **diri_node = NULL, **file_diri_node = NULL;
struct apk_package *pkg;
struct apk_installed_package *ipkg;
- struct apk_db_file *file;
apk_blob_t token = APK_BLOB_STR("\n"), line, bdir, bfile;
pkg = apk_pkg_new();
@@ -562,7 +580,7 @@ int apk_db_read_overlay(struct apk_database *db, struct apk_bstream *bs)
diri = apk_db_diri_new(db, pkg, bdir, &diri_node);
file_diri_node = &diri->owned_files.first;
}
- file = apk_db_file_get(db, diri, bfile, &file_diri_node);
+ (void) apk_db_file_get(db, diri, bfile, &file_diri_node);
}
}
@@ -774,30 +792,6 @@ static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os
return apk_tar_write_entry(os, NULL, NULL);
}
-static int apk_db_scriptdb_read_v1(struct apk_database *db, struct apk_istream *is)
-{
- struct apk_package *pkg;
- struct {
- unsigned char md5sum[16];
- unsigned int type;
- unsigned int size;
- } hdr;
- struct apk_checksum csum;
-
- while (is->read(is, &hdr, sizeof(hdr)) == sizeof(hdr)) {
- memcpy(csum.data, hdr.md5sum, sizeof(hdr.md5sum));
- csum.type = APK_CHECKSUM_MD5;
-
- pkg = apk_db_get_pkg(db, &csum);
- if (pkg != NULL && pkg->ipkg != NULL)
- apk_ipkg_add_script(pkg->ipkg, is, hdr.type, hdr.size);
- else
- apk_istream_skip(is, hdr.size);
- }
-
- return 0;
-}
-
static int apk_read_script_archive_entry(void *ctx,
const struct apk_file_info *ae,
struct apk_istream *is)
@@ -910,7 +904,7 @@ static int apk_db_read_state(struct apk_database *db, int flags)
* 6. script db
*/
if (!(flags & APK_OPENF_NO_WORLD)) {
- blob = apk_blob_from_file(db->root_fd, "var/lib/apk/world");
+ blob = apk_blob_from_file(db->root_fd, apk_world_file);
if (APK_BLOB_IS_NULL(blob))
return -ENOENT;
apk_deps_parse(db, &db->world, blob);
@@ -921,7 +915,7 @@ static int apk_db_read_state(struct apk_database *db, int flags)
}
if (!(flags & APK_OPENF_NO_INSTALLED)) {
- bs = apk_bstream_from_file(db->root_fd, "var/lib/apk/installed");
+ bs = apk_bstream_from_file(db->root_fd, apk_installed_file);
if (bs != NULL) {
r = apk_db_index_read(db, bs, -1);
bs->close(bs, NULL);
@@ -929,7 +923,7 @@ static int apk_db_read_state(struct apk_database *db, int flags)
return -1;
}
- bs = apk_bstream_from_file(db->root_fd, "var/lib/apk/triggers");
+ bs = apk_bstream_from_file(db->root_fd, apk_triggers_file);
if (bs != NULL) {
apk_db_triggers_read(db, bs);
bs->close(bs, NULL);
@@ -937,17 +931,12 @@ static int apk_db_read_state(struct apk_database *db, int flags)
}
if (!(flags & APK_OPENF_NO_SCRIPTS)) {
- is = apk_istream_from_file(db->root_fd, "var/lib/apk/scripts.tar");
+ is = apk_istream_from_file(db->root_fd, apk_scripts_file);
if (is != NULL) {
apk_tar_parse(is, apk_read_script_archive_entry, db,
FALSE, &db->id_cache);
- } else {
- is = apk_istream_from_file(db->root_fd, "var/lib/apk/scripts");
- if (is != NULL)
- apk_db_scriptdb_read_v1(db, is);
- }
- if (is != NULL)
is->close(is);
+ }
}
return 0;
@@ -1037,13 +1026,18 @@ static int apk_db_create(struct apk_database *db)
mkdirat(db->root_fd, "tmp", 01777);
mkdirat(db->root_fd, "dev", 0755);
mknodat(db->root_fd, "dev/null", 0666, makedev(1, 3));
+ mkdirat(db->root_fd, "etc", 0755);
+ mkdirat(db->root_fd, "etc/apk", 0755);
+ mkdirat(db->root_fd, "lib", 0755);
+ mkdirat(db->root_fd, "lib/apk", 0755);
+ mkdirat(db->root_fd, "lib/apk/db", 0755);
mkdirat(db->root_fd, "var", 0755);
- mkdirat(db->root_fd, "var/lib", 0755);
- mkdirat(db->root_fd, "var/lib/apk", 0755);
mkdirat(db->root_fd, "var/cache", 0755);
+ mkdirat(db->root_fd, "var/cache/apk", 0755);
mkdirat(db->root_fd, "var/cache/misc", 0755);
+ mkdirat(db->root_fd, "var/lock", 0755);
- fd = openat(db->root_fd, "var/lib/apk/world", O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644);
+ fd = openat(db->root_fd, apk_world_file, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644);
if (fd < 0)
return -errno;
close(fd);
@@ -1055,14 +1049,83 @@ static void handle_alarm(int sig)
{
}
+static char *find_mountpoint(int atfd, const char *rel_path)
+{
+ struct mntent *me;
+ struct stat64 st;
+ FILE *f;
+ char *ret = NULL;
+ dev_t dev;
+
+ if (fstatat64(atfd, rel_path, &st, 0) != 0)
+ return NULL;
+ dev = st.st_dev;
+
+ f = setmntent("/proc/mounts", "r");
+ if (f == NULL)
+ return NULL;
+ while ((me = getmntent(f)) != NULL) {
+ if (strcmp(me->mnt_fsname, "rootfs") == 0)
+ continue;
+ if (fstatat64(atfd, me->mnt_dir, &st, 0) == 0 &&
+ st.st_dev == dev) {
+ ret = strdup(me->mnt_dir);
+ break;
+ }
+ }
+ endmntent(f);
+
+ return ret;
+}
+
+static int do_remount(const char *path, const char *option)
+{
+ pid_t pid;
+ int status;
+
+ pid = fork();
+ if (pid < 0)
+ return -errno;
+
+ if (pid == 0) {
+ execl("/bin/mount", "mount", "-o", "remount", "-o",
+ option, path, NULL);
+ return 1;
+ }
+
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status))
+ return -1;
+
+ return WEXITSTATUS(status);
+}
+
+static void relocate_database(struct apk_database *db)
+{
+ mkdirat(db->root_fd, "etc", 0755);
+ mkdirat(db->root_fd, "etc/apk", 0755);
+ mkdirat(db->root_fd, "lib", 0755);
+ mkdirat(db->root_fd, "lib/apk", 0755);
+ mkdirat(db->root_fd, "lib/apk/db", 0755);
+ mkdirat(db->root_fd, "var", 0755);
+ mkdirat(db->root_fd, "var/cache", 0755);
+ mkdirat(db->root_fd, "var/cache/apk", 0755);
+ mkdirat(db->root_fd, "var/cache/misc", 0755);
+ mkdirat(db->root_fd, "var/lock", 0755);
+ apk_move_file(db->root_fd, apk_world_file_old, apk_world_file);
+ apk_move_file(db->root_fd, apk_scripts_file_old, apk_scripts_file);
+ apk_move_file(db->root_fd, apk_triggers_file_old, apk_triggers_file);
+ apk_move_file(db->root_fd, apk_installed_file_old, apk_installed_file);
+}
+
int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
{
const char *msg = NULL;
struct apk_repository_list *repo = NULL;
struct apk_bstream *bs;
- struct stat64 st;
+ struct statfs stfs;
apk_blob_t blob;
- int r, rr = 0;
+ int r, fd, rr = 0;
memset(db, 0, sizeof(*db));
if (apk_flags & APK_SIMULATE) {
@@ -1083,9 +1146,13 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
list_init(&db->installed.triggers);
apk_dependency_array_init(&db->world);
apk_string_array_init(&db->protected_paths);
- db->cache_dir = apk_static_cache_dir;
db->permanent = 1;
+ if (dbopts->root && dbopts->arch) {
+ db->arch = apk_blob_atomize(APK_BLOB_STR(dbopts->arch));
+ } else {
+ db->arch = apk_blob_atomize(APK_BLOB_STR(APK_DEFAULT_ARCH));
+ }
db->root = strdup(dbopts->root ?: "/");
db->root_fd = openat(AT_FDCWD, db->root, O_RDONLY | O_CLOEXEC);
if (db->root_fd < 0 && (dbopts->open_flags & APK_OPENF_CREATE)) {
@@ -1096,17 +1163,17 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
msg = "Unable to open root";
goto ret_errno;
}
- if (fstat64(db->root_fd, &st) != 0 || major(st.st_dev) == 0)
+ if (fstatfs(db->root_fd, &stfs) == 0 &&
+ stfs.f_type == 0x01021994 /* TMPFS_MAGIC */)
db->permanent = 0;
- if (fstatat64(db->root_fd, apk_linked_cache_dir, &st, 0) == 0 &&
- S_ISDIR(st.st_mode) && major(st.st_dev) != 0)
- db->cache_dir = apk_linked_cache_dir;
-
apk_id_cache_init(&db->id_cache, db->root_fd);
if (dbopts->open_flags & APK_OPENF_WRITE) {
- db->lock_fd = openat(db->root_fd, "var/lib/apk/lock",
+ if (faccessat(db->root_fd, apk_installed_file_old, F_OK, 0) == 0)
+ relocate_database(db);
+
+ db->lock_fd = openat(db->root_fd, apk_lock_file,
O_CREAT | O_RDWR | O_CLOEXEC, 0400);
if (db->lock_fd < 0 && errno == ENOENT &&
(dbopts->open_flags & APK_OPENF_CREATE)) {
@@ -1115,7 +1182,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
msg = "Unable to create database";
goto ret_r;
}
- db->lock_fd = openat(db->root_fd, "var/lib/apk/lock",
+ db->lock_fd = openat(db->root_fd, apk_lock_file,
O_CREAT | O_RDWR | O_CLOEXEC, 0400);
}
if (db->lock_fd < 0 ||
@@ -1144,10 +1211,25 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
blob = APK_BLOB_STR("etc:*etc/init.d");
apk_blob_for_each_segment(blob, ":", add_protected_path, db);
- db->arch = apk_blob_atomize(APK_BLOB_STR(apk_arch));
- db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC);
- mkdirat(db->cache_fd, "tmp", 0644);
- db->cachetmp_fd = openat(db->cache_fd, "tmp", O_RDONLY | O_CLOEXEC);
+ /* figure out where to have the cache */
+ fd = openat(db->root_fd, apk_linked_cache_dir, O_RDONLY | O_CLOEXEC);
+ if (fd >= 0 && fstatfs(fd, &stfs) == 0 && stfs.f_type != 0x01021994 /* TMPFS_MAGIC */) {
+ struct statvfs stvfs;
+
+ db->cache_dir = apk_linked_cache_dir;
+ db->cache_fd = fd;
+ mkdirat(db->cache_fd, "tmp", 0644);
+ db->cachetmp_fd = openat(db->cache_fd, "tmp", O_RDONLY | O_CLOEXEC);
+ if (fstatvfs(fd, &stvfs) == 0 && (stvfs.f_flag & ST_RDONLY) != 0)
+ db->ro_cache = 1;
+ } else {
+ if (fd >= 0)
+ close(fd);
+ db->cache_dir = apk_static_cache_dir;
+ db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC);
+ db->cachetmp_fd = db->cache_fd;
+ }
+
db->keys_fd = openat(db->root_fd,
dbopts->keys_dir ?: "etc/apk/keys",
O_RDONLY | O_CLOEXEC);
@@ -1211,6 +1293,21 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
"might not function properly");
}
+ if ((dbopts->open_flags & (APK_OPENF_WRITE | APK_OPENF_CACHE_WRITE)) &&
+ db->ro_cache) {
+ /* remount cache read-write */
+ db->cache_remount_dir = find_mountpoint(db->root_fd, db->cache_dir);
+ if (db->cache_remount_dir == NULL) {
+ apk_warning("Unable to find cache directory mount point");
+ } else if (do_remount(db->cache_remount_dir, "rw") != 0) {
+ free(db->cache_remount_dir);
+ db->cache_remount_dir = NULL;
+ apk_error("Unable to remount cache read-write");
+ r = EROFS;
+ goto ret_r;
+ }
+ }
+
return rr;
ret_errno:
@@ -1242,8 +1339,8 @@ int apk_db_write_config(struct apk_database *db)
}
os = apk_ostream_to_file(db->root_fd,
- "var/lib/apk/world",
- "var/lib/apk/world.new",
+ apk_world_file,
+ apk_world_file_tmp,
0644);
if (os == NULL)
return -1;
@@ -1255,8 +1352,8 @@ int apk_db_write_config(struct apk_database *db)
return r;
os = apk_ostream_to_file(db->root_fd,
- "var/lib/apk/installed",
- "var/lib/apk/installed.new",
+ apk_installed_file,
+ apk_installed_file_tmp,
0644);
if (os == NULL)
return -1;
@@ -1266,8 +1363,8 @@ int apk_db_write_config(struct apk_database *db)
return r;
os = apk_ostream_to_file(db->root_fd,
- "var/lib/apk/scripts.tar",
- "var/lib/apk/scripts.tar.new",
+ apk_scripts_file,
+ apk_scripts_file_tmp,
0644);
if (os == NULL)
return -1;
@@ -1276,12 +1373,11 @@ int apk_db_write_config(struct apk_database *db)
if (r < 0)
return r;
- unlinkat(db->root_fd, "var/lib/apk/scripts", 0);
apk_db_index_write_nr_cache(db);
os = apk_ostream_to_file(db->root_fd,
- "var/lib/apk/triggers",
- "var/lib/apk/triggers.new",
+ apk_triggers_file,
+ apk_triggers_file_tmp,
0644);
if (os == NULL)
return -1;
@@ -1300,6 +1396,12 @@ void apk_db_close(struct apk_database *db)
struct hlist_node *dc, *dn;
int i;
+ if (db->cache_remount_dir) {
+ do_remount(db->cache_remount_dir, "ro");
+ free(db->cache_remount_dir);
+ db->cache_remount_dir = NULL;
+ }
+
apk_id_cache_free(&db->id_cache);
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
@@ -1323,7 +1425,7 @@ void apk_db_close(struct apk_database *db)
if (db->keys_fd)
close(db->keys_fd);
- if (db->cachetmp_fd)
+ if (db->cachetmp_fd && db->cachetmp_fd != db->cache_fd)
close(db->cachetmp_fd);
if (db->cache_fd)
close(db->cache_fd);
@@ -1423,21 +1525,37 @@ 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;
+}
+
static int apk_repo_is_remote(struct apk_repository *repo)
{
return repo->csum.type != APK_CHECKSUM_NONE;
}
static struct apk_bstream *apk_repo_file_open(struct apk_repository *repo,
- apk_blob_t arch,
+ apk_blob_t *arch,
const char *file,
char *buf, int buflen)
{
const char *url = repo->url;
- snprintf(buf, buflen, "%s%s" BLOB_FMT "/%s",
- url, url[strlen(url)-1] == '/' ? "" : "/",
- BLOB_PRINTF(arch), file);
+ apk_repo_format_filename(buf, buflen, url, arch, file);
if ((apk_flags & APK_NO_NETWORK) && apk_repo_is_remote(repo))
return NULL;
@@ -1497,7 +1615,7 @@ int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
return 0;
apk_cache_format_index(APK_BLOB_BUF(cacheitem), repo);
- r = apk_cache_download(db, repo->url, apkindex_tar_gz, cacheitem,
+ 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)
@@ -1605,7 +1723,7 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
bs = apk_bstream_from_file(db->cache_fd, buf);
} else {
db->local_repos |= BIT(r);
- bs = apk_repo_file_open(repo, *db->arch, apkindex_tar_gz, buf, sizeof(buf));
+ bs = apk_repo_file_open(repo, db->arch, apkindex_tar_gz, buf, sizeof(buf));
}
if (bs == NULL) {
apk_warning("%s: index failed to open", buf);
@@ -2015,7 +2133,8 @@ static int apk_db_unpack_pkg(struct apk_database *db,
if (bs == NULL) {
apk_pkg_format_plain(pkg, APK_BLOB_BUF(item));
- bs = apk_repo_file_open(repo, *(pkg->arch ?: db->arch), item, file, sizeof(file));
+ bs = apk_repo_file_open(repo, pkg->arch,
+ item, file, sizeof(file));
if (apk_repo_is_remote(repo))
need_copy = TRUE;
}
diff --git a/src/del.c b/src/del.c
index 695785f..4c00ade 100644
--- a/src/del.c
+++ b/src/del.c
@@ -58,7 +58,7 @@ static int del_main(void *ctx, struct apk_database *db, int argc, char **argv)
r |= apk_state_lock_dependency(state, &dep);
}
if (r == 0)
- r = apk_state_commit(state, db);
+ r = apk_state_commit(state);
else
apk_state_print_errors(state);
err:
diff --git a/src/fetch.c b/src/fetch.c
index b67a189..72b481d 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -109,20 +109,18 @@ static int fetch_package(struct fetch_ctx *fctx,
return 0;
}
- apk_message("Downloading %s-%s", pkg->name->name, pkg->version);
+ apk_message("Downloading " PKG_VER_FMT, PKG_VER_PRINTF(pkg));
repo = apk_db_select_repo(db, pkg);
if (repo == NULL) {
- apk_error("%s-%s: package is not currently available",
- pkg->name->name, pkg->version);
+ apk_error(PKG_VER_FMT ": package is not currently available",
+ PKG_VER_PRINTF(pkg));
return -1;
}
if (apk_flags & APK_SIMULATE)
return 0;
- snprintf(url, sizeof(url), "%s%s%s", repo->url,
- repo->url[strlen(repo->url)-1] == '/' ? "" : "/",
- pkgfile);
+ apk_repo_format_filename(url, sizeof(url), repo->url, pkg->arch, pkgfile);
if (fctx->flags & FETCH_STDOUT) {
fd = STDOUT_FILENO;
diff --git a/src/fix.c b/src/fix.c
index 1bacce2..48cab9c 100644
--- a/src/fix.c
+++ b/src/fix.c
@@ -89,7 +89,7 @@ static int fix_main(void *pctx, struct apk_database *db, int argc, char **argv)
r |= apk_state_lock_dependency(state, &deps[i]);
if (r == 0 || (apk_flags & APK_FORCE))
- r = apk_state_commit(state, db);
+ r = apk_state_commit(state);
else
apk_state_print_errors(state);
err:
diff --git a/src/index.c b/src/index.c
index d2b4b01..442e98a 100644
--- a/src/index.c
+++ b/src/index.c
@@ -25,6 +25,7 @@ struct index_ctx {
const char *index;
const char *output;
const char *description;
+ apk_blob_t *rewrite_arch;
time_t index_mtime;
int method;
};
@@ -44,6 +45,9 @@ static int index_parse(void *ctx, struct apk_db_options *dbopts,
case 'd':
ictx->description = optarg;
break;
+ case 0x10000:
+ ictx->rewrite_arch = apk_blob_atomize(APK_BLOB_STR(optarg));
+ break;
default:
return -1;
}
@@ -88,6 +92,7 @@ static int index_main(void *ctx, struct apk_database *db, int argc, char **argv)
struct apk_file_info fi;
int total, r, i, j, found, newpkgs = 0;
struct index_ctx *ictx = (struct index_ctx *) ctx;
+ struct apk_package *pkg;
if (isatty(STDOUT_FILENO) && ictx->output == NULL &&
!(apk_flags & APK_FORCE)) {
@@ -139,12 +144,14 @@ static int index_main(void *ctx, struct apk_database *db, int argc, char **argv)
break;
for (j = 0; j < name->pkgs->num; j++) {
- struct apk_package *pkg = name->pkgs->item[j];
+ pkg = name->pkgs->item[j];
if (apk_blob_compare(bver, *pkg->version) != 0)
continue;
if (pkg->size != fi.size)
continue;
pkg->filename = strdup(argv[i]);
+ if (ictx->rewrite_arch != NULL)
+ pkg->arch = ictx->rewrite_arch;
found = TRUE;
break;
}
@@ -153,8 +160,10 @@ static int index_main(void *ctx, struct apk_database *db, int argc, char **argv)
if (!found) {
struct apk_sign_ctx sctx;
apk_sign_ctx_init(&sctx, ictx->method, NULL, db->keys_fd);
- if (apk_pkg_read(db, argv[i], &sctx, NULL) == 0)
+ if (apk_pkg_read(db, argv[i], &sctx, &pkg) == 0)
newpkgs++;
+ if (ictx->rewrite_arch != NULL)
+ pkg->arch = ictx->rewrite_arch;
apk_sign_ctx_free(&sctx);
}
}
@@ -214,6 +223,8 @@ static struct apk_option index_options[] = {
{ 'd', "description", "Embed TEXT as description and version "
"information of the repository index",
required_argument, "TEXT" },
+ { 0x10000, "rewrite-arch", "Use ARCH as architery for all packages",
+ required_argument, "ARCH" },
};
static struct apk_applet apk_index = {
diff --git a/src/info.c b/src/info.c
index c9dc39c..3ae51f0 100644
--- a/src/info.c
+++ b/src/info.c
@@ -33,6 +33,8 @@ struct info_ctx {
#define APK_INFO_RDEPENDS 0x10
#define APK_INFO_CONTENTS 0x20
#define APK_INFO_TRIGGERS 0x40
+#define APK_INFO_INSTALL_IF 0x80
+#define APK_INFO_RINSTALL_IF 0x100
static void verbose_print_pkg(struct apk_package *pkg, int minimal_verbosity)
{
@@ -168,15 +170,22 @@ static void info_print_size(struct apk_package *pkg)
static void info_print_depends(struct apk_package *pkg)
{
+ apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n");
+ char dep[256];
int i;
- char *separator = apk_verbosity > 1 ? " " : "\n";
+
if (apk_verbosity == 1)
printf(PKG_VER_FMT " depends on:\n",
PKG_VER_PRINTF(pkg));
if (apk_verbosity > 1)
printf("%s: ", pkg->name->name);
- for (i = 0; i < pkg->depends->num; i++)
- printf("%s%s", pkg->depends->item[i].name->name, separator);
+ for (i = 0; i < pkg->depends->num; i++) {
+ apk_blob_t b = APK_BLOB_BUF(dep);
+ apk_blob_push_dep(&b, &pkg->depends->item[i]);
+ apk_blob_push_blob(&b, separator);
+ b = apk_blob_pushed(APK_BLOB_BUF(dep), b);
+ fwrite(b.ptr, b.len, 1, stdout);
+ }
}
static void info_print_required_by(struct apk_package *pkg)
@@ -211,6 +220,58 @@ static void info_print_required_by(struct apk_package *pkg)
}
}
+static void info_print_install_if(struct apk_package *pkg)
+{
+ apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n");
+ char dep[256];
+ int i;
+
+ if (apk_verbosity == 1)
+ printf(PKG_VER_FMT " has auto-install rule:\n",
+ PKG_VER_PRINTF(pkg));
+ if (apk_verbosity > 1)
+ printf("%s: ", pkg->name->name);
+ for (i = 0; i < pkg->install_if->num; i++) {
+ apk_blob_t b = APK_BLOB_BUF(dep);
+ apk_blob_push_dep(&b, &pkg->install_if->item[i]);
+ apk_blob_push_blob(&b, separator);
+ b = apk_blob_pushed(APK_BLOB_BUF(dep), b);
+ fwrite(b.ptr, b.len, 1, stdout);
+ }
+}
+
+static void info_print_rinstall_if(struct apk_package *pkg)
+{
+ int i, j, k;
+ char *separator = apk_verbosity > 1 ? " " : "\n";
+
+ if (apk_verbosity == 1)
+ printf(PKG_VER_FMT " affects auto-installation of:\n",
+ PKG_VER_PRINTF(pkg));
+ if (apk_verbosity > 1)
+ printf("%s: ", pkg->name->name);
+ for (i = 0; i < pkg->name->rinstall_if->num; i++) {
+ struct apk_name *name0 = pkg->name->rinstall_if->item[i];
+
+ /* Check only the package that is installed, and that
+ * it actually has this package in install_if. */
+ for (j = 0; j < name0->pkgs->num; j++) {
+ struct apk_package *pkg0 = name0->pkgs->item[j];
+
+ if (pkg0->ipkg == NULL)
+ continue;
+ for (k = 0; k < pkg0->install_if->num; k++) {
+ if (pkg0->install_if->item[k].name != pkg->name)
+ continue;
+ printf(PKG_VER_FMT "%s",
+ PKG_VER_PRINTF(pkg0),
+ separator);
+ break;
+ }
+ }
+ }
+}
+
static void info_print_contents(struct apk_package *pkg)
{
struct apk_installed_package *ipkg = pkg->ipkg;
@@ -260,9 +321,12 @@ static void info_subaction(struct info_ctx *ctx, struct apk_package *pkg)
info_print_required_by,
info_print_contents,
info_print_triggers,
+ info_print_install_if,
+ info_print_rinstall_if,
};
const int requireipkg =
- APK_INFO_CONTENTS | APK_INFO_TRIGGERS | APK_INFO_RDEPENDS;
+ APK_INFO_CONTENTS | APK_INFO_TRIGGERS | APK_INFO_RDEPENDS |
+ APK_INFO_RINSTALL_IF;
int i;
for (i = 0; i < ARRAY_SIZE(subactions); i++) {
@@ -317,6 +381,12 @@ static int info_parse(void *ctx, struct apk_db_options *dbopts,
case 'r':
ictx->subaction_mask |= APK_INFO_RDEPENDS;
break;
+ case 'I':
+ ictx->subaction_mask |= APK_INFO_INSTALL_IF;
+ break;
+ case 'i':
+ ictx->subaction_mask |= APK_INFO_RINSTALL_IF;
+ break;
case 's':
ictx->subaction_mask |= APK_INFO_SIZE;
break;
@@ -354,6 +424,8 @@ static struct apk_option info_options[] = {
{ 'W', "who-owns", "Print the package owning the specified file" },
{ 'R', "depends", "List packages that the PACKAGE depends on" },
{ 'r', "rdepends", "List all packages depending on PACKAGE" },
+ { 'i', "install-if", "List the PACKAGE's install-if rule" },
+ { 'I', "rinstall-if", "List all packages having install-if referencing PACKAGE" },
{ 'w', "webpage", "Show URL for more information about PACKAGE" },
{ 's', "size", "Show installed size of PACKAGE" },
{ 'd', "description", "Print description for PACKAGE" },
diff --git a/src/io.c b/src/io.c
index 7eecbf8..e4b3710 100644
--- a/src/io.c
+++ b/src/io.c
@@ -739,6 +739,37 @@ size_t apk_ostream_write_string(struct apk_ostream *os, const char *string)
return len;
}
+int apk_move_file(int atfd, const char *from, const char *to)
+{
+ struct apk_istream *is;
+ struct stat64 st;
+ int rc, tofd;
+
+ if (renameat(atfd, from, atfd, to) == 0)
+ return 0;
+
+ if (fstatat64(atfd, from, &st, 0) != 0)
+ return -errno;
+
+ is = apk_istream_from_file(atfd, from);
+ if (is == NULL)
+ return -ENOENT;
+
+ tofd = openat(atfd, to, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (tofd < 0) {
+ rc = -errno;
+ goto close_is;
+ }
+
+ rc = apk_istream_splice(is, tofd, st.st_size, NULL, NULL);
+ close(tofd);
+ unlinkat(atfd, from, 0);
+close_is:
+ is->close(is);
+ return rc;
+}
+
struct cache_item {
apk_hash_node hash_node;
unsigned int genid;
diff --git a/src/lua-apk.c b/src/lua-apk.c
index 835d379..cb36784 100644
--- a/src/lua-apk.c
+++ b/src/lua-apk.c
@@ -9,7 +9,8 @@
#include "apk_database.h"
#define LIBNAME "apk"
-#define APKDB_META "apk_database"
+#define APK_DB_META "apk_database"
+#define APK_IPKG_META "apk_installed_package"
int apk_verbosity;
unsigned int apk_flags;
@@ -131,9 +132,9 @@ static struct apk_database *checkdb(lua_State *L, int index)
{
struct apk_database *db;
luaL_checktype(L, index, LUA_TUSERDATA);
- db = (struct apk_database *) luaL_checkudata(L, index, APKDB_META);
+ db = (struct apk_database *) luaL_checkudata(L, index, APK_DB_META);
if (db == NULL)
- luaL_typerror(L, index, APKDB_META);
+ luaL_typerror(L, index, APK_DB_META);
return db;
}
@@ -152,7 +153,7 @@ static int Papk_db_open(lua_State *L)
opts.open_flags |= APK_OPENF_READ;
db = lua_newuserdata(L, sizeof(struct apk_database));
- luaL_getmetatable(L, APKDB_META);
+ luaL_getmetatable(L, APK_DB_META);
lua_setmetatable(L, -2);
r = apk_db_open(db, &opts);
@@ -168,7 +169,6 @@ static int Papk_db_close(lua_State *L)
return 0;
}
-
static int push_package(lua_State *L, struct apk_package *pkg)
{
if (pkg == NULL) {
@@ -193,12 +193,82 @@ static int Papk_who_owns(lua_State *L)
return push_package(L, pkg);
}
+static int Papk_exists(lua_State *L)
+{
+ struct apk_database *db = checkdb(L, 1);
+ const char *depstr = luaL_checkstring(L, 2);
+ struct apk_dependency dep;
+ struct apk_name *name;
+ struct apk_package *pkg;
+ int i, r;
+
+ r = apk_dep_from_blob(&dep, db, APK_BLOB_STR(depstr));
+ if (r != 0)
+ goto ret_nil;
+
+ name = dep.name;
+ for (i = 0; i < name->pkgs->num; i++) {
+ pkg = name->pkgs->item[i];
+ if (pkg->ipkg != NULL)
+ break;
+ }
+ if (i >= name->pkgs->num)
+ goto ret_nil;
+
+ if (!apk_dep_is_satisfied(&dep, pkg))
+ goto ret_nil;
+
+ return push_package(L, pkg);
+ret_nil:
+ lua_pushnil(L);
+ return 1;
+}
+
+// Iterator of all installed packages
+struct apk_installed_package_iterator {
+ struct list_head *end;
+ struct apk_installed_package *node;
+};
+
+static int iterate_installed(lua_State *L)
+{
+ struct apk_installed_package_iterator *i;
+ struct apk_installed_package *ipkg;
+ i = (struct apk_installed_package_iterator *)lua_touserdata(L, lua_upvalueindex(1));
+ ipkg = i->node;
+
+ if (&ipkg->installed_pkgs_list == i->end)
+ return 0;
+
+ i->node = list_entry(ipkg->installed_pkgs_list.next,
+ typeof(*ipkg), installed_pkgs_list);
+ return push_package(L, ipkg->pkg);
+
+}
+static int Pinstalled(lua_State *L)
+{
+ struct apk_database *db = checkdb(L, 1);
+ struct apk_installed_package_iterator *i;
+
+ i = (struct apk_installed_package_iterator *) lua_newuserdata(L, sizeof(*i));
+ i->end = &db->installed.packages;
+ i->node = list_entry((&db->installed.packages)->next,
+ struct apk_installed_package,
+ installed_pkgs_list);
+
+ lua_pushcclosure(L, iterate_installed, 1);
+ return 1;
+}
+
static const luaL_reg reg_apk_methods[] = {
{"version_validate", Pversion_validate},
{"version_compare", Pversion_compare},
{"version_is_less", Pversion_is_less},
{"db_open", Papk_db_open},
{"who_owns", Papk_who_owns},
+ {"exists", Papk_exists},
+ {"is_installed", Papk_exists},
+ {"installed", Pinstalled},
{NULL, NULL}
};
@@ -214,7 +284,7 @@ LUALIB_API int luaopen_apk(lua_State *L)
lua_pushliteral(L, APK_VERSION);
lua_settable(L, -3);
- luaL_newmetatable(L, APKDB_META);
+ luaL_newmetatable(L, APK_DB_META);
luaL_register(L, NULL, reg_apk_db_meta_methods);
lua_pushliteral(L, "__index");
lua_pushvalue(L, -3);
diff --git a/src/package.c b/src/package.c
index 1a5d502..2699420 100644
--- a/src/package.c
+++ b/src/package.c
@@ -659,6 +659,18 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg,
case 'i':
apk_deps_parse(db, &pkg->install_if, value);
break;
+ case 'o':
+ pkg->origin = apk_blob_atomize_dup(value);
+ break;
+ case 'm':
+ pkg->maintainer = apk_blob_atomize_dup(value);
+ break;
+ case 't':
+ pkg->build_time = apk_blob_pull_uint(&value, 10);
+ break;
+ case 'c':
+ pkg->commit = apk_blob_cstr(value);
+ break;
case 'F': case 'M': case 'R': case 'Z':
/* installed db entries which are handled in database.c */
return 1;
@@ -691,6 +703,10 @@ static int read_info_line(void *ctx, apk_blob_t line)
{ "arch", 'A' },
{ "depend", 'D' },
{ "install_if", 'i' },
+ { "origin", 'o' },
+ { "maintainer", 'm' },
+ { "builddate", 't' },
+ { "commit", 'c' },
};
struct read_info_ctx *ri = (struct read_info_ctx *) ctx;
apk_blob_t l, r;
@@ -800,6 +816,8 @@ void apk_pkg_free(struct apk_package *pkg)
free(pkg->url);
if (pkg->description)
free(pkg->description);
+ if (pkg->commit)
+ free(pkg->commit);
free(pkg);
}
@@ -968,6 +986,22 @@ int apk_pkg_write_index_entry(struct apk_package *info,
apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->url));
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nL:"));
apk_blob_push_blob(&bbuf, *info->license);
+ if (info->origin) {
+ apk_blob_push_blob(&bbuf, APK_BLOB_STR("\no:"));
+ apk_blob_push_blob(&bbuf, *info->origin);
+ }
+ if (info->maintainer) {
+ apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nm:"));
+ apk_blob_push_blob(&bbuf, *info->maintainer);
+ }
+ if (info->build_time) {
+ apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nt:"));
+ apk_blob_push_uint(&bbuf, info->build_time, 10);
+ }
+ if (info->commit) {
+ apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nc:"));
+ apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->commit));
+ }
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
if (APK_BLOB_IS_NULL(bbuf))
diff --git a/src/state.c b/src/state.c
index 4a4641d..6de3629 100644
--- a/src/state.c
+++ b/src/state.c
@@ -138,14 +138,20 @@ static struct apk_name_choices *name_choices_new(struct apk_database *db,
if (dep->name != name)
continue;
- for (j = 0; j < nc->num; ) {
- if (apk_dep_is_satisfied(dep, nc->pkgs[j])) {
- j++;
- } else {
- nc->pkgs[j] = nc->pkgs[nc->num - 1];
- nc->num--;
+ if (apk_flags & APK_PREFER_AVAILABLE) {
+ dep->version = apk_blob_atomize(APK_BLOB_NULL);
+ dep->result_mask = APK_DEPMASK_REQUIRE;
+ } else {
+ for (j = 0; j < nc->num; ) {
+ if (apk_dep_is_satisfied(dep, nc->pkgs[j])) {
+ j++;
+ } else {
+ nc->pkgs[j] = nc->pkgs[nc->num - 1];
+ nc->num--;
+ }
}
}
+ break;
}
return nc;
@@ -232,6 +238,50 @@ void apk_state_unref(struct apk_state *state)
free(state);
}
+static struct apk_package *get_locked_or_installed_package(
+ struct apk_state *state,
+ struct apk_name *name)
+{
+ int i;
+
+ if (ns_locked(state->name[name->id]))
+ return ns_to_pkg(state->name[name->id]);
+
+ if (!ns_empty(state->name[name->id])) {
+ struct apk_name_choices *ns =
+ ns_to_choices(state->name[name->id]);
+
+ for (i = 0; i < ns->num; i++) {
+ if (ns->pkgs[i]->ipkg != NULL)
+ return ns->pkgs[i];
+ }
+ return NULL;
+ }
+
+ for (i = 0; i < name->pkgs->num; i++) {
+ if (name->pkgs->item[i]->ipkg != NULL)
+ return name->pkgs->item[i];
+ }
+ return NULL;
+}
+
+static int check_dependency_array(struct apk_state *state,
+ struct apk_dependency_array *da)
+{
+ struct apk_package *pkg;
+ int i;
+
+ for (i = 0; i < da->num; i++) {
+ pkg = get_locked_or_installed_package(state, da->item[i].name);
+ if (pkg == NULL && da->item[i].result_mask != APK_DEPMASK_CONFLICT)
+ return 0;
+ if (!apk_dep_is_satisfied(&da->item[i], pkg))
+ return 0;
+ }
+
+ return da->num;
+}
+
static int apk_state_add_change(struct apk_state *state,
struct apk_package *oldpkg,
struct apk_package *newpkg)
@@ -334,20 +384,22 @@ int apk_state_prune_dependency(struct apk_state *state,
return c->num;
}
-int apk_state_lock_dependency(struct apk_state *state,
- struct apk_dependency *dep)
+int apk_state_autolock_name(struct apk_state *state, struct apk_name *name,
+ int install_if)
{
- struct apk_name *name = dep->name;
struct apk_name_choices *c;
- struct apk_package *installed = NULL, *latest = NULL, *use;
- int i, r;
-
- r = apk_state_prune_dependency(state, dep);
- if (r <= 0)
- return r;
+ struct apk_package *installed = NULL, *latest = NULL, *use;
+ int i;
if (ns_pending(state->name[name->id]))
return apk_state_lock_name(state, name, ns_to_pkg(state->name[name->id]));
+ if (ns_locked(state->name[name->id]))
+ return 0;
+ if (ns_empty(state->name[name->id])) {
+ /* This name has not been visited yet.
+ * Construct list of candidates. */
+ state->name[name->id] = ns_from_choices(name_choices_new(state->db, name));
+ }
c = ns_to_choices(state->name[name->id]);
#if 1
@@ -355,6 +407,10 @@ int apk_state_lock_dependency(struct apk_state *state,
for (i = 0; i < c->num; i++) {
struct apk_package *pkg = c->pkgs[i];
+ if (install_if &&
+ !check_dependency_array(state, pkg->install_if))
+ continue;
+
if (pkg->ipkg != NULL)
installed = pkg;
else if (!apk_state_pkg_available(state, pkg))
@@ -396,7 +452,13 @@ int apk_state_lock_dependency(struct apk_state *state,
use = latest;
}
if (use == NULL)
- return -1;
+ return -2;
+
+ /* Install_if check did not result in package selection change:
+ * do not lock the package yet as the preferency might change
+ * later. */
+ if (install_if && use->ipkg != NULL)
+ return 0;
return apk_state_lock_name(state, name, use);
#else
@@ -411,6 +473,18 @@ int apk_state_lock_dependency(struct apk_state *state,
#endif
}
+int apk_state_lock_dependency(struct apk_state *state,
+ struct apk_dependency *dep)
+{
+ int r;
+
+ r = apk_state_prune_dependency(state, dep);
+ if (r <= 0)
+ return r;
+
+ return apk_state_autolock_name(state, dep->name, FALSE);
+}
+
static int apk_state_fix_package(struct apk_state *state,
struct apk_package *pkg)
{
@@ -420,12 +494,18 @@ static int apk_state_fix_package(struct apk_state *state,
return 0;
for (i = 0; i < pkg->depends->num; i++) {
- r = apk_state_lock_dependency(state,
- &pkg->depends->item[i]);
- if (r != 0)
- ret = -1;
+ if (pkg->depends->item[i].name->flags & APK_NAME_TOPLEVEL_OVERRIDE) {
+ r = apk_state_prune_dependency(state,
+ &pkg->depends->item[i]);
+ if (r < 0)
+ ret = -1;
+ } else {
+ r = apk_state_lock_dependency(state,
+ &pkg->depends->item[i]);
+ if (r != 0)
+ ret = -1;
+ }
}
-
return ret;
}
@@ -467,48 +547,19 @@ static int for_each_broken_reverse_depency(struct apk_state *state,
void *ctx)
{
struct apk_package *pkg0;
- int i, j, r;
+ int i, r;
for (i = 0; i < name->rdepends->num; i++) {
struct apk_name *name0 = name->rdepends->item[i];
- if (ns_locked(state->name[name0->id])) {
- pkg0 = ns_to_pkg(state->name[name0->id]);
- if (pkg0 == NULL)
- continue;
- r = call_if_dependency_broke(state, pkg0, name,
- cb, ctx);
- if (r != 0)
- return r;
- } else if (!ns_empty(state->name[name0->id])) {
- struct apk_name_choices *ns =
- ns_to_choices(state->name[name0->id]);
-
- for (j = 0; j < ns->num; j++) {
- if (ns->pkgs[j]->ipkg == NULL)
- continue;
- r = call_if_dependency_broke(state,
- ns->pkgs[j],
- name, cb, ctx);
- if (r != 0)
- return r;
- break;
- }
- } else {
- for (j = 0; j < name0->pkgs->num; j++) {
- pkg0 = name0->pkgs->item[j];
-
- if (pkg0->ipkg == NULL)
- continue;
+ pkg0 = get_locked_or_installed_package(state, name0);
+ if (pkg0 == NULL)
+ continue;
- r = call_if_dependency_broke(state,
- name0->pkgs->item[j],
- name, cb, ctx);
- if (r != 0)
- return r;
- break;
- }
- }
+ r = call_if_dependency_broke(state, pkg0, name,
+ cb, ctx);
+ if (r != 0)
+ return r;
}
return 0;
@@ -578,15 +629,19 @@ int apk_state_lock_name(struct apk_state *state,
}
/* If the chosen package is installed, all is done here */
- if (oldpkg == newpkg &&
- (newpkg == NULL ||
- !(newpkg->name->flags & APK_NAME_REINSTALL)))
- return 0;
+ if ((oldpkg != newpkg) ||
+ (newpkg != NULL && (newpkg->name->flags & APK_NAME_REINSTALL))) {
+ /* Track change */
+ r = apk_state_add_change(state, oldpkg, newpkg);
+ if (r != 0)
+ return r;
+ }
- /* Track change */
- r = apk_state_add_change(state, oldpkg, newpkg);
- if (r != 0)
- return r;
+ /* Check all reverse install_if's */
+ if (newpkg != NULL) {
+ for (i = 0; i < newpkg->name->rinstall_if->num; i++)
+ apk_state_autolock_name(state, newpkg->name->rinstall_if->item[i], TRUE);
+ }
return 0;
}
@@ -655,22 +710,19 @@ static void apk_count_change(struct apk_change *change, struct apk_stats *stats)
stats->packages ++;
}
-static inline void apk_draw_progress(int percent, int last)
+static void apk_draw_progress(int percent)
{
- char tmp[128];
- char reset[128];
+ const int bar_width = (apk_screen_width - 7);
int i;
- snprintf(tmp, sizeof(tmp), "-[ ]- %3i%%", percent);
- for (i = 0; (i < (percent/5)) && (i < (sizeof(tmp)-2)); i++)
- tmp[2+i] = '#';
- memset(reset, '\b', strlen(tmp));
- fwrite(tmp, strlen(tmp), 1, stderr);
- if (!last)
- fwrite(reset, strlen(tmp), 1, stderr);
- else if (apk_verbosity > 0)
- fwrite("\n", 1, 1, stderr);
+ fprintf(stderr, "\e7%3i%% [", percent);
+ for (i = 0; i < bar_width * percent / 100; i++)
+ fputc('#', stderr);
+ for (; i < bar_width; i++)
+ fputc(' ', stderr);
+ fputc(']', stderr);
fflush(stderr);
+ fputs("\e8\e[0K", stderr);
}
struct progress {
@@ -692,7 +744,7 @@ static void progress_cb(void *ctx, size_t progress)
prog->total.bytes + prog->total.packages);
if (prog->count != count)
- apk_draw_progress(count, 0);
+ apk_draw_progress(count);
prog->count = count;
}
@@ -799,6 +851,23 @@ static int apk_state_autoclean(struct apk_state *state,
return r;
}
}
+
+ for (i = 0; i < pkg->name->rinstall_if->num; i++) {
+ struct apk_name *n = pkg->name->rinstall_if->item[i];
+
+ if (ns_locked(state->name[n->id]))
+ continue;
+ if (n->flags & APK_NAME_TOPLEVEL)
+ continue;
+
+ r = apk_state_autolock_name(state, n, TRUE);
+ if (r == -2) {
+ r = apk_state_lock_name(state, n, NULL);
+ if (r != 0)
+ return r;
+ }
+ }
+
return 0;
}
@@ -874,11 +943,11 @@ void apk_state_print_errors(struct apk_state *state)
printf("\n");
}
-int apk_state_commit(struct apk_state *state,
- struct apk_database *db)
+int apk_state_commit(struct apk_state *state)
{
struct progress prog;
struct apk_change *change;
+ struct apk_database *db = state->db;
int n = 0, r = 0, size_diff = 0, toplevel = FALSE, deleteonly = TRUE;
/* Count what needs to be done */
@@ -940,6 +1009,8 @@ int apk_state_commit(struct apk_state *state,
list_for_each_entry(change, &state->change_list_head, change_list) {
n++;
apk_print_change(db, change->oldpkg, change->newpkg, n, state->num_changes);
+ if (apk_flags & APK_PROGRESS)
+ apk_draw_progress(prog.count);
prog.pkg = change->newpkg;
if (!(apk_flags & APK_SIMULATE)) {
@@ -961,7 +1032,7 @@ int apk_state_commit(struct apk_state *state,
apk_count_change(change, &prog.done);
}
if (apk_flags & APK_PROGRESS)
- apk_draw_progress(100, 1);
+ apk_draw_progress(100);
update_state:
apk_db_run_triggers(db);
diff --git a/src/upgrade.c b/src/upgrade.c
index 795e62f..ec0dc91 100644
--- a/src/upgrade.c
+++ b/src/upgrade.c
@@ -33,21 +33,10 @@ static int upgrade_parse(void *ctx, struct apk_db_options *dbopts,
int apk_do_self_upgrade(struct apk_database *db, struct apk_state *state)
{
struct apk_dependency dep;
- int r, i;
+ int r;
apk_dep_from_blob(&dep, db, APK_BLOB_STR("apk-tools"));
- if (apk_flags & APK_PREFER_AVAILABLE) {
- for (i = 0; i < db->world->num; i++) {
- struct apk_dependency *dep0 = &db->world->item[i];
- if (dep0->name != dep.name)
- continue;
- dep0->version = apk_blob_atomize(APK_BLOB_NULL);
- dep0->result_mask = APK_DEPMASK_REQUIRE;
- break;
- }
- }
-
r = apk_state_lock_dependency(state, &dep);
if (r != 0 || state->num_changes == 0)
return r;
@@ -57,13 +46,13 @@ int apk_do_self_upgrade(struct apk_database *db, struct apk_state *state)
return 0;
}
- apk_message("Uprading first to new apk-tools:");
+ apk_message("Upgrading critical system libraries and apk-tools:");
state->print_ok = 0;
- r = apk_state_commit(state, db);
+ r = apk_state_commit(state);
apk_state_unref(state);
apk_db_close(db);
- apk_message("Performing rest of the operation:");
+ apk_message("Continuing the upgrade transaction with new apk-tools:");
execvp(apk_argv[0], apk_argv);
apk_error("PANIC! Failed to re-execute new apk-tools!");
@@ -74,7 +63,6 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg
{
struct apk_state *state = NULL;
struct apk_name_array *missing;
- apk_blob_t *null_atom = apk_blob_atomize(APK_BLOB_NULL);
int i, r = 0;
apk_flags |= APK_UPGRADE;
@@ -92,11 +80,7 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg
for (i = 0; i < db->world->num; i++) {
struct apk_dependency *dep = &db->world->item[i];
- if (dep->version != null_atom &&
- (apk_flags & APK_PREFER_AVAILABLE)) {
- dep->result_mask = APK_DEPMASK_REQUIRE;
- dep->version = null_atom;
- }
+
if (dep->name->pkgs->num != 0)
r |= apk_state_lock_dependency(state, dep);
else
@@ -117,7 +101,7 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg
if (i != 0)
printf("\n");
- r = apk_state_commit(state, db);
+ r = apk_state_commit(state);
} else
apk_state_print_errors(state);
err:
diff --git a/src/url.c b/src/url.c
index d007860..0a17a7a 100644
--- a/src/url.c
+++ b/src/url.c
@@ -70,6 +70,10 @@ static int fork_wget(const char *url, pid_t *ppid)
close(fds[0]);
dup2(open("/dev/null", O_RDONLY), STDIN_FILENO);
dup2(fds[1], STDOUT_FILENO);
+ execlp("wget", "wget", "-q", "-O", "-", url, NULL);
+ /* fall back to busybox wget
+ * See http://redmine.alpinelinux.org/issues/347
+ */
execlp("busybox", "wget", "-q", "-O", "-", url, NULL);
exit(0);
}