From a98b57b1ae6f9fb04ddcc6876451632d519a0081 Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Sat, 17 Jan 2009 11:07:56 +0200 Subject: db: database locking and creation to part of opening it Add flags field to db open call. Also make error reporting quite a bit more detailed. --- src/add.c | 27 ++-------- src/apk_database.h | 9 ++-- src/audit.c | 2 +- src/database.c | 144 +++++++++++++++++++++++++++++++++++------------------ src/del.c | 2 +- src/index.c | 2 +- src/info.c | 2 +- src/ver.c | 2 +- 8 files changed, 111 insertions(+), 79 deletions(-) diff --git a/src/add.c b/src/add.c index 9101db2..7aa0b23 100644 --- a/src/add.c +++ b/src/add.c @@ -14,10 +14,8 @@ #include "apk_applet.h" #include "apk_database.h" -#define FLAG_INITDB 0x0001 - struct add_ctx { - unsigned int flags; + unsigned int open_flags; }; static int add_parse(void *ctx, int optch, int optindex, const char *optarg) @@ -26,7 +24,7 @@ static int add_parse(void *ctx, int optch, int optindex, const char *optarg) switch (optch) { case 0x10000: - actx->flags |= FLAG_INITDB; + actx->open_flags |= APK_OPENF_CREATE; break; case 'u': apk_upgrade = 1; @@ -43,24 +41,9 @@ static int add_main(void *ctx, int argc, char **argv) struct apk_database db; int i, r, ret = 1; - r = apk_db_open(&db, apk_root); - if ((r == -ENOENT) && (actx->flags & FLAG_INITDB)) { - if (strcmp(apk_root, "/") == 0) { - apk_error("Will not recreate system root."); - return 1; - } - r = apk_db_create(apk_root); - if (r != 0) { - apk_error("Failed to create apkdb: %s", - strerror(-r)); - return 1; - } - r = apk_db_open(&db, apk_root); - } - if (r != 0) { - apk_error("APK database not present (use --initdb to create one)"); - return 1; - } + r = apk_db_open(&db, apk_root, actx->open_flags | APK_OPENF_WRITE); + if (r != 0) + return r; for (i = 0; i < argc; i++) { struct apk_dependency dep; diff --git a/src/apk_database.h b/src/apk_database.h index 9710939..0306997 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -63,7 +63,7 @@ struct apk_repository { struct apk_database { char *root; - int root_fd; + int root_fd, lock_fd; unsigned pkg_id, num_repos; struct apk_dependency_array *world; @@ -100,8 +100,11 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db, apk_blob_t dir, apk_blob_t name); -int apk_db_create(const char *root); -int apk_db_open(struct apk_database *db, const char *root); +#define APK_OPENF_READ 0x0000 +#define APK_OPENF_WRITE 0x0001 +#define APK_OPENF_CREATE 0x0002 + +int apk_db_open(struct apk_database *db, const char *root, unsigned int flags); void apk_db_close(struct apk_database *db); struct apk_package *apk_db_pkg_add_file(struct apk_database *db, const char *file); diff --git a/src/audit.c b/src/audit.c index c080f2f..f45b9b9 100644 --- a/src/audit.c +++ b/src/audit.c @@ -116,7 +116,7 @@ static int audit_main(void *ctx, int argc, char **argv) return 2; } - r = apk_db_open(&db, apk_root); + r = apk_db_open(&db, apk_root, APK_OPENF_READ); if (r != 0) { apk_error("APK database not present"); return 1; diff --git a/src/database.c b/src/database.c index 190b264..5f3de74 100644 --- a/src/database.c +++ b/src/database.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "apk_defines.h" #include "apk_package.h" @@ -550,41 +551,11 @@ static int apk_db_scriptdb_read(struct apk_database *db, struct apk_istream *is) return 0; } -int apk_db_create(const char *root) -{ - apk_blob_t deps = APK_BLOB_STR("busybox alpine-baselayout " - "apk-tools alpine-conf\n"); - int fd; - - fchdir(apk_cwd_fd); - mkdir(root, 0755); - if (chdir(root) == -1) - return -errno; - - mkdir("tmp", 01777); - mkdir("dev", 0755); - mknod("dev/null", 0666, makedev(1, 3)); - mkdir("var", 0755); - mkdir("var/lib", 0755); - mkdir("var/lib/apk", 0755); - - fd = creat("var/lib/apk/world", 0644); - if (fd < 0) - return -errno; - write(fd, deps.ptr, deps.len); - close(fd); - - return 0; -} - static int apk_db_read_state(struct apk_database *db) { struct apk_istream *is; apk_blob_t blob; - if (db->root == NULL) - return 0; - /* Read: * 1. installed repository * 2. source repositories @@ -624,10 +595,33 @@ static int add_protected_path(void *ctx, apk_blob_t blob) return 0; } -int apk_db_open(struct apk_database *db, const char *root) +static int apk_db_create(struct apk_database *db) +{ + apk_blob_t deps = APK_BLOB_STR("busybox alpine-baselayout " + "apk-tools alpine-conf"); + int fd; + + fchdir(db->root_fd); + mkdir("tmp", 01777); + mkdir("dev", 0755); + mknod("dev/null", 0666, makedev(1, 3)); + mkdir("var", 0755); + mkdir("var/lib", 0755); + mkdir("var/lib/apk", 0755); + + fd = creat("var/lib/apk/world", 0644); + if (fd < 0) + return -errno; + write(fd, deps.ptr, deps.len); + close(fd); + + return 0; +} + +int apk_db_open(struct apk_database *db, const char *root, unsigned int flags) { apk_blob_t blob; - const char *apk_repos = getenv("APK_REPOS"); + const char *apk_repos = getenv("APK_REPOS"), *msg; int r; memset(db, 0, sizeof(*db)); @@ -641,20 +635,45 @@ int apk_db_open(struct apk_database *db, const char *root) fchdir(apk_cwd_fd); db->root = strdup(root); db->root_fd = open(root, O_RDONLY); + if (db->root_fd < 0 && (flags & APK_OPENF_CREATE)) { + mkdir(db->root, 0755); + db->root_fd = open(root, O_RDONLY); + } if (db->root_fd < 0) { - free(db->root); - return -errno; + msg = "Unable to open root"; + goto ret_errno; + } + + fchdir(db->root_fd); + if (flags & APK_OPENF_WRITE) { + db->lock_fd = open("var/lib/apk/lock", + O_CREAT | O_WRONLY, 0400); + if (db->lock_fd < 0 || + flock(db->lock_fd, LOCK_EX | LOCK_NB) < 0) { + msg = "Unable to lock database"; + goto ret_errno; + } } } blob = APK_BLOB_STR("etc:-etc/init.d"); apk_blob_for_each_segment(blob, ":", add_protected_path, db); - r = apk_db_read_state(db); - if (r != 0) - return r; - if (root != NULL) { + 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 read database state"; + goto ret_r; + } + if (apk_repos == NULL) apk_repos = "/etc/apk/repositories"; blob = apk_blob_from_file(apk_repos); @@ -662,15 +681,29 @@ int apk_db_open(struct apk_database *db, const char *root) r = apk_blob_for_each_segment(blob, "\n", apk_db_add_repository, db); free(blob.ptr); - if (r != 0) - return r; + if (r != 0) { + msg = "Unable to load repositories"; + goto ret_r; + } } } - if (apk_repository != NULL) - apk_db_add_repository(db, APK_BLOB_STR(apk_repository)); + if (apk_repository != NULL) { + r = apk_db_add_repository(db, APK_BLOB_STR(apk_repository)); + if (r != 0) { + msg = "Unable to load repositories"; + goto ret_r; + } + } return 0; + +ret_errno: + r = -errno; +ret_r: + apk_error("%s: %s", msg, strerror(-r)); + apk_db_close(db); + return r; } struct write_ctx { @@ -687,6 +720,11 @@ static int apk_db_write_config(struct apk_database *db) if (db->root == NULL) return 0; + if (db->lock_fd == 0) { + apk_error("Refusing to write db without write lock!"); + return -1; + } + fchdir(db->root_fd); os = apk_ostream_to_file("var/lib/apk/world", 0644); @@ -698,12 +736,15 @@ static int apk_db_write_config(struct apk_database *db) os->write(os, buf, n); os->close(os); - os = apk_ostream_to_file("var/lib/apk/installed", 0644); + os = apk_ostream_to_file("var/lib/apk/installed.new", 0644); if (os == NULL) return -1; apk_db_write_fdb(db, os); os->close(os); + if (rename("var/lib/apk/installed.new", "var/lib/apk/installed") < 0) + return -errno; + os = apk_ostream_to_file("var/lib/apk/scripts", 0644); if (os == NULL) return -1; @@ -728,20 +769,25 @@ void apk_db_close(struct apk_database *db) for (i = 0; i < db->num_repos; i++) free(db->repos[i].url); - for (i = 0; i < db->protected_paths->num; i++) - free(db->protected_paths->item[i]); - free(db->protected_paths); - free(db->world); + if (db->protected_paths) { + for (i = 0; i < db->protected_paths->num; i++) + free(db->protected_paths->item[i]); + free(db->protected_paths); + } + if (db->world) + free(db->world); apk_hash_free(&db->available.names); apk_hash_free(&db->available.packages); apk_hash_free(&db->installed.files); apk_hash_free(&db->installed.dirs); - if (db->root != NULL) { + if (db->root_fd) close(db->root_fd); + if (db->lock_fd) + close(db->lock_fd); + if (db->root != NULL) free(db->root); - } } struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum) diff --git a/src/del.c b/src/del.c index 546a4db..3e480a9 100644 --- a/src/del.c +++ b/src/del.c @@ -18,7 +18,7 @@ static int del_main(void *ctx, int argc, char **argv) struct apk_database db; int i, j; - if (apk_db_open(&db, apk_root) < 0) + if (apk_db_open(&db, apk_root, APK_OPENF_WRITE) < 0) return -1; if (db.world == NULL) diff --git a/src/index.c b/src/index.c index c272b74..08fc342 100644 --- a/src/index.c +++ b/src/index.c @@ -44,7 +44,7 @@ static int index_main(void *ctx, int argc, char **argv) struct apk_ostream *os; int total, i; - apk_db_open(&db, NULL); + apk_db_open(&db, NULL, APK_OPENF_READ); for (i = 0; i < argc; i++) apk_db_pkg_add_file(&db, argv[i]); diff --git a/src/info.c b/src/info.c index 1cde91d..8a87eee 100644 --- a/src/info.c +++ b/src/info.c @@ -111,7 +111,7 @@ static int info_main(void *ctx, int argc, char **argv) struct apk_database db; int r; - if (apk_db_open(&db, apk_root) < 0) + if (apk_db_open(&db, apk_root, APK_OPENF_READ) < 0) return -1; if (ictx->action != NULL) diff --git a/src/ver.c b/src/ver.c index 6665e8f..1232166 100644 --- a/src/ver.c +++ b/src/ver.c @@ -43,7 +43,7 @@ static int ver_main(void *ctx, int argc, char **argv) return 0; } - if (apk_db_open(&db, apk_root) < 0) + if (apk_db_open(&db, apk_root, APK_OPENF_READ) < 0) return -1; list_for_each_entry(pkg, &db.installed.packages, installed_pkgs_list) { -- cgit v1.2.3