diff --git a/src/add.c b/src/add.c index 03fc96a..d147fa6 100644 --- a/src/add.c +++ b/src/add.c @@ -77,6 +77,22 @@ static int cup(void) return 0; } +static int non_repository_check(struct apk_database *db) +{ + if (apk_flags & APK_FORCE) + return 0; + if (apk_db_cache_active(db)) + return 0; + if (apk_db_permanent(db)) + return 0; + + apk_error("You tried to add a non-repository package to system, " + "but it would be lost on next reboot. Enable package caching " + "(apk cache --help) or use --force if you know what you are " + "doing."); + return 1; +} + static int add_main(void *ctx, int argc, char **argv) { @@ -97,6 +113,9 @@ static int add_main(void *ctx, int argc, char **argv) return r; if (actx->virtpkg) { + if (non_repository_check(&db)) + goto err; + virtpkg = apk_pkg_new(); if (virtpkg == NULL) { apk_error("Failed to allocate virtual meta package"); @@ -119,14 +138,8 @@ static int add_main(void *ctx, int argc, char **argv) struct apk_package *pkg = NULL; struct apk_sign_ctx sctx; - if (!apk_db_cache_active(&db) && - !apk_db_permanent(&db) && - !(apk_flags & APK_FORCE)) { - apk_error("Use --force or enable package " - "caching to install non-repository " - "packages."); + if (non_repository_check(&db)) goto err; - } apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY_AND_GENERATE, NULL); diff --git a/src/apk_database.h b/src/apk_database.h index 46e6152..d2f27eb 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -83,6 +83,7 @@ struct apk_database { int root_fd, lock_fd; unsigned name_id, num_repos; const char *cache_dir; + int permanent; struct apk_dependency_array *world; struct apk_string_array *protected_paths; diff --git a/src/database.c b/src/database.c index bf0a0a6..ce90aea 100644 --- a/src/database.c +++ b/src/database.c @@ -1,7 +1,7 @@ /* database.c - Alpine Package Keeper (APK) * * Copyright (C) 2005-2008 Natanael Copa - * Copyright (C) 2008 Timo Teräs + * Copyright (C) 2008-2009 Timo Teräs * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -395,6 +395,23 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package * return idb; } +static void apk_db_cache_get_name(char *buf, size_t bufsz, + struct apk_database *db, + struct apk_checksum *csum, + const char *file, int temp) +{ + char csumstr[APK_CACHE_CSUM_BYTES*2+1]; + apk_blob_t bbuf = APK_BLOB_BUF(csumstr); + + apk_blob_push_hexdump(&bbuf, + APK_BLOB_PTR_LEN((char *) csum->data, + APK_CACHE_CSUM_BYTES)); + apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN("", 1)); + + snprintf(buf, bufsz, "%s/%s/%s.%s%s", + db->root, db->cache_dir, csumstr, file, temp ? ".new" : ""); +} + int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) { struct apk_package *pkg = NULL; @@ -410,9 +427,9 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) if (pkg == NULL) continue; - if (repo != -1) + if (repo >= 0) pkg->repos |= BIT(repo); - else + else if (repo == -1) apk_pkg_set_state(db, pkg, APK_PKG_INSTALLED); if (apk_db_pkg_add(db, pkg) != pkg && repo == -1) { @@ -678,6 +695,12 @@ static int apk_db_read_state(struct apk_database *db, int flags) apk_db_index_read(db, bs, -1); bs->close(bs, NULL); } + + bs = apk_bstream_from_file("etc/apk/cache/installed"); + if (bs != NULL) { + apk_db_index_read(db, bs, -2); + bs->close(bs, NULL); + } } if (!(flags & APK_OPENF_NO_SCRIPTS)) { @@ -696,6 +719,73 @@ static int apk_db_read_state(struct apk_database *db, int flags) return 0; } +struct index_write_ctx { + struct apk_ostream *os; + int count; + int force; +}; + +static int write_index_entry(apk_hash_item item, void *ctx) +{ + struct index_write_ctx *iwctx = (struct index_write_ctx *) ctx; + struct apk_package *pkg = (struct apk_package *) item; + int r; + + if (!iwctx->force && pkg->filename == NULL) + return 0; + + r = apk_pkg_write_index_entry(pkg, iwctx->os); + if (r < 0) + return r; + + if (iwctx->os->write(iwctx->os, "\n", 1) != 1) + return -1; + + iwctx->count++; + return 0; +} + +static int apk_db_index_write_nr_cache(struct apk_database *db) +{ + struct index_write_ctx ctx = { NULL, 0, TRUE }; + struct apk_package *pkg; + struct apk_ostream *os; + int r; + + if (!apk_db_cache_active(db)) + return 0; + + /* Write list of installed non-repository packages to + * cached index file */ + ctx.os = os = apk_ostream_to_file("etc/apk/cache/installed.new", 0644); + if (os == NULL) + return -1; + + list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) { + if (pkg->repos != 0) + continue; + r = write_index_entry(pkg, &ctx); + if (r != 0) + return r; + } + + os->close(os); + if (rename("etc/apk/cache/installed.new", + "etc/apk/cache/installed") < 0) + return -errno; + + return ctx.count; +} + +int apk_db_index_write(struct apk_database *db, struct apk_ostream *os) +{ + struct index_write_ctx ctx = { os, 0, FALSE }; + + apk_hash_foreach(&db->available.packages, write_index_entry, &ctx); + + return ctx.count; +} + static int add_protected_path(void *ctx, apk_blob_t blob) { struct apk_database *db = (struct apk_database *) ctx; @@ -746,6 +836,7 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags) apk_hash_init(&db->installed.files, &file_hash_ops, 10000); list_init(&db->installed.packages); db->cache_dir = apk_static_cache_dir; + db->permanent = 1; if (root != NULL) { fchdir(apk_cwd_fd); @@ -759,6 +850,8 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags) msg = "Unable to open root"; goto ret_errno; } + if (fstat(db->root_fd, &st) != 0 || major(st.st_dev) == 0) + db->permanent = 0; fchdir(db->root_fd); if (stat(apk_linked_cache_dir, &st) == 0 && S_ISDIR(st.st_mode)) @@ -834,6 +927,9 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags) if (!(flags & APK_OPENF_NO_REPOS)) { list_for_each_entry(repo, &apk_repository_list.list, list) apk_db_add_repository(db, APK_BLOB_STR(repo->url)); + + if (apk_flags & APK_UPDATE_CACHE) + apk_db_index_write_nr_cache(db); } fchdir(apk_cwd_fd); @@ -895,6 +991,7 @@ int apk_db_write_config(struct apk_database *db) return -errno; unlink("var/lib/apk/scripts"); + apk_db_index_write_nr_cache(db); return 0; } @@ -943,13 +1040,7 @@ int apk_db_cache_active(struct apk_database *db) int apk_db_permanent(struct apk_database *db) { - struct stat st; - - if (fstat(db->root_fd, &st) != 0) - return 0; - if (major(st.st_dev) == 0) - return 0; - return 1; + return db->permanent; } struct apk_package *apk_db_get_pkg(struct apk_database *db, @@ -978,56 +1069,6 @@ struct apk_package *apk_db_get_file_owner(struct apk_database *db, return dbf->diri->pkg; } -struct index_write_ctx { - struct apk_ostream *os; - int count; -}; - -static int write_index_entry(apk_hash_item item, void *ctx) -{ - struct index_write_ctx *iwctx = (struct index_write_ctx *) ctx; - struct apk_package *pkg = (struct apk_package *) item; - int r; - - if (pkg->filename == NULL) - return 0; - - r = apk_pkg_write_index_entry(pkg, iwctx->os); - if (r < 0) - return r; - - if (iwctx->os->write(iwctx->os, "\n", 1) != 1) - return -1; - - iwctx->count++; - return 0; -} - -int apk_db_index_write(struct apk_database *db, struct apk_ostream *os) -{ - struct index_write_ctx ctx = { os, 0 }; - - apk_hash_foreach(&db->available.packages, write_index_entry, &ctx); - - return ctx.count; -} - -static void apk_db_cache_get_name(char *buf, size_t bufsz, - struct apk_database *db, - struct apk_checksum *csum, - const char *file, int temp) -{ - char csumstr[APK_CACHE_CSUM_BYTES*2+1]; - apk_blob_t bbuf = APK_BLOB_BUF(csumstr); - - apk_blob_push_hexdump(&bbuf, - APK_BLOB_PTR_LEN((char *) csum->data, APK_CACHE_CSUM_BYTES)); - apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN("", 1)); - - snprintf(buf, bufsz, "%s/%s/%s.%s%s", - db->root, db->cache_dir, csumstr, file, temp ? ".new" : ""); -} - static struct apk_bstream *apk_db_cache_open(struct apk_database *db, struct apk_checksum *csum, const char *file)