summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-01-17 11:07:56 +0200
committerTimo Teras <timo.teras@iki.fi>2009-01-17 11:08:48 +0200
commita98b57b1ae6f9fb04ddcc6876451632d519a0081 (patch)
treeacafb1cf2dd44fbbab363fc714582da5b9e21c62
parent24b424a4580555579b11ab1d66ee3dab7751dfb5 (diff)
downloadapk-tools-a98b57b1ae6f9fb04ddcc6876451632d519a0081.tar.gz
apk-tools-a98b57b1ae6f9fb04ddcc6876451632d519a0081.tar.bz2
apk-tools-a98b57b1ae6f9fb04ddcc6876451632d519a0081.tar.xz
apk-tools-a98b57b1ae6f9fb04ddcc6876451632d519a0081.zip
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.
-rw-r--r--src/add.c27
-rw-r--r--src/apk_database.h9
-rw-r--r--src/audit.c2
-rw-r--r--src/database.c144
-rw-r--r--src/del.c2
-rw-r--r--src/index.c2
-rw-r--r--src/info.c2
-rw-r--r--src/ver.c2
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 <malloc.h>
#include <string.h>
#include <stdlib.h>
+#include <sys/file.h>
#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) {