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.cute-signatures
parent
24b424a458
commit
a98b57b1ae
27
src/add.c
27
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
136
src/database.c
136
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,9 +769,12 @@ void apk_db_close(struct apk_database *db)
|
|||
|
||||
for (i = 0; i < db->num_repos; i++)
|
||||
free(db->repos[i].url);
|
||||
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);
|
||||
|
@ -738,11 +782,13 @@ void apk_db_close(struct apk_database *db)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue