summaryrefslogtreecommitdiffstats
path: root/lib/libalpm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm')
-rw-r--r--lib/libalpm/alpm.c2
-rw-r--r--lib/libalpm/alpm.h6
-rw-r--r--lib/libalpm/be_local.c117
-rw-r--r--lib/libalpm/be_sync.c114
-rw-r--r--lib/libalpm/db.c63
-rw-r--r--lib/libalpm/db.h18
-rw-r--r--lib/libalpm/error.c2
-rw-r--r--lib/libalpm/handle.c54
-rw-r--r--lib/libalpm/handle.h3
-rw-r--r--lib/libalpm/trans.c72
10 files changed, 266 insertions, 185 deletions
diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c
index 9b9719d1..b0bbbe8c 100644
--- a/lib/libalpm/alpm.c
+++ b/lib/libalpm/alpm.c
@@ -70,7 +70,7 @@ pmhandle_t SYMEXPORT *alpm_initialize(const char *root, const char *dbpath,
snprintf(myhandle->lockfile, lockfilelen, "%s%s", myhandle->dbpath, lf);
if(_alpm_db_register_local(myhandle) == NULL) {
- myerr = PM_ERR_DB_CREATE;
+ myerr = myhandle->pm_errno;
goto cleanup;
}
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 715e502a..579b45f2 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -357,9 +357,12 @@ alpm_list_t *alpm_option_get_syncdbs(pmhandle_t *handle);
/** Register a sync database of packages.
* @param handle the context handle
* @param treename the name of the sync repository
+ * @param check_sig what level of signature checking to perform on the
+ * database; note that this must be a '.sig' file type verification
* @return a pmdb_t* on success (the value), NULL on error
*/
-pmdb_t *alpm_db_register_sync(pmhandle_t *handle, const char *treename);
+pmdb_t *alpm_db_register_sync(pmhandle_t *handle, const char *treename,
+ pgp_verify_t check_sig);
/** Unregister a package database.
* @param db pointer to the package database to unregister
@@ -999,6 +1002,7 @@ enum _pmerrno_t {
PM_ERR_DB_NULL,
PM_ERR_DB_NOT_NULL,
PM_ERR_DB_NOT_FOUND,
+ PM_ERR_DB_INVALID,
PM_ERR_DB_VERSION,
PM_ERR_DB_WRITE,
PM_ERR_DB_REMOVE,
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index 4b2a3017..96f04c51 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -314,6 +314,62 @@ static int is_dir(const char *path, struct dirent *entry)
return 0;
}
+static int local_db_validate(pmdb_t *db)
+{
+ struct dirent *ent = NULL;
+ const char *dbpath;
+ DIR *dbdir;
+ int ret = -1;
+
+ if(db->status & DB_STATUS_VALID) {
+ return 0;
+ }
+
+ dbpath = _alpm_db_path(db);
+ if(dbpath == NULL) {
+ RET_ERR(db->handle, PM_ERR_DB_OPEN, -1);
+ }
+ dbdir = opendir(dbpath);
+ if(dbdir == NULL) {
+ if(errno == ENOENT) {
+ /* database dir doesn't exist yet */
+ db->status |= DB_STATUS_VALID;
+ return 0;
+ } else {
+ RET_ERR(db->handle, PM_ERR_DB_OPEN, -1);
+ }
+ }
+
+ while((ent = readdir(dbdir)) != NULL) {
+ const char *name = ent->d_name;
+ char path[PATH_MAX];
+
+ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
+ continue;
+ }
+ if(!is_dir(dbpath, ent)) {
+ continue;
+ }
+
+ snprintf(path, PATH_MAX, "%s%s/depends", dbpath, name);
+ if(access(path, F_OK) == 0) {
+ /* we found a depends file- bail */
+ db->handle->pm_errno = PM_ERR_DB_VERSION;
+ goto done;
+ }
+ }
+ /* we found no depends file after full scan */
+ db->status |= DB_STATUS_VALID;
+ ret = 0;
+
+done:
+ if(dbdir) {
+ closedir(dbdir);
+ }
+
+ return ret;
+}
+
static int local_db_populate(pmdb_t *db)
{
size_t est_count;
@@ -328,6 +384,7 @@ static int local_db_populate(pmdb_t *db)
/* pm_errno set in _alpm_db_path() */
return -1;
}
+
dbdir = opendir(dbpath);
if(dbdir == NULL) {
if(errno == ENOENT) {
@@ -867,62 +924,9 @@ int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info)
return ret;
}
-static int local_db_version(pmdb_t *db)
-{
- struct dirent *ent = NULL;
- const char *dbpath;
- DIR *dbdir;
- int version;
-
- dbpath = _alpm_db_path(db);
- if(dbpath == NULL) {
- RET_ERR(db->handle, PM_ERR_DB_OPEN, -1);
- }
- dbdir = opendir(dbpath);
- if(dbdir == NULL) {
- if(errno == ENOENT) {
- /* database dir doesn't exist yet */
- version = 2;
- goto done;
- } else {
- RET_ERR(db->handle, PM_ERR_DB_OPEN, -1);
- }
- }
-
- while((ent = readdir(dbdir)) != NULL) {
- const char *name = ent->d_name;
- char path[PATH_MAX];
-
- if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
- continue;
- }
- if(!is_dir(dbpath, ent)) {
- continue;
- }
-
- snprintf(path, PATH_MAX, "%s%s/depends", dbpath, name);
- if(access(path, F_OK) == 0) {
- /* we found a depends file- bail */
- version = 1;
- goto done;
- }
- }
- /* we found no depends file after full scan */
- version = 2;
-
-done:
- if(dbdir) {
- closedir(dbdir);
- }
-
- _alpm_log(db->handle, PM_LOG_DEBUG, "local database version %d\n", version);
- return version;
-}
-
struct db_operations local_db_ops = {
.populate = local_db_populate,
.unregister = _alpm_db_unregister,
- .version = local_db_version,
};
pmdb_t *_alpm_db_register_local(pmhandle_t *handle)
@@ -933,11 +937,18 @@ pmdb_t *_alpm_db_register_local(pmhandle_t *handle)
db = _alpm_db_new("local", 1);
if(db == NULL) {
+ handle->pm_errno = PM_ERR_DB_CREATE;
return NULL;
}
db->ops = &local_db_ops;
db->handle = handle;
+ if(local_db_validate(db)) {
+ /* pm_errno set in local_db_validate() */
+ _alpm_db_free(db);
+ return NULL;
+ }
+
handle->db_local = db;
return db;
}
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index e5fc6a70..f51ab97a 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -20,7 +20,9 @@
#include "config.h"
+#include <errno.h>
#include <sys/stat.h>
+#include <unistd.h>
/* libarchive */
#include <archive.h>
@@ -65,32 +67,68 @@ static char *get_sync_dir(pmhandle_t *handle)
return syncpath;
}
+static int sync_db_validate(pmdb_t *db)
+{
+ pgp_verify_t check_sig;
+
+ if(db->status & DB_STATUS_VALID) {
+ return 0;
+ }
+
+ /* this takes into account the default verification level if UNKNOWN
+ * was assigned to this db */
+ check_sig = _alpm_db_get_sigverify_level(db);
+
+ if(check_sig != PM_PGP_VERIFY_NEVER) {
+ int ret;
+ const char *dbpath = _alpm_db_path(db);
+ if(!dbpath) {
+ /* pm_errno set in _alpm_db_path() */
+ return -1;
+ }
+
+ /* we can skip any validation if the database doesn't exist */
+ if(access(dbpath, R_OK) != 0 && errno == ENOENT) {
+ goto valid;
+ return 0;
+ }
+
+ _alpm_log(db->handle, PM_LOG_DEBUG, "checking signature for %s\n",
+ db->treename);
+ ret = _alpm_gpgme_checksig(db->handle, dbpath, NULL);
+ if((check_sig == PM_PGP_VERIFY_ALWAYS && ret != 0) ||
+ (check_sig == PM_PGP_VERIFY_OPTIONAL && ret == 1)) {
+ RET_ERR(db->handle, PM_ERR_SIG_INVALID, -1);
+ }
+ }
+
+valid:
+ db->status |= DB_STATUS_VALID;
+ return 0;
+}
+
/** Update a package database
*
* An update of the package database \a db will be attempted. Unless
* \a force is true, the update will only be performed if the remote
* database was modified since the last update.
*
- * A transaction is necessary for this operation, in order to obtain a
- * database lock. During this transaction the front-end will be informed
- * of the download progress of the database via the download callback.
+ * This operation requires a database lock, and will return an applicable error
+ * if the lock could not be obtained.
*
* Example:
* @code
* alpm_list_t *syncs = alpm_option_get_syncdbs();
- * if(alpm_trans_init(0, NULL, NULL, NULL) == 0) {
- * for(i = syncs; i; i = alpm_list_next(i)) {
- * pmdb_t *db = alpm_list_getdata(i);
- * result = alpm_db_update(0, db);
- * alpm_trans_release();
+ * for(i = syncs; i; i = alpm_list_next(i)) {
+ * pmdb_t *db = alpm_list_getdata(i);
+ * result = alpm_db_update(0, db);
*
- * if(result < 0) {
- * printf("Unable to update database: %s\n", alpm_strerrorlast());
- * } else if(result == 1) {
- * printf("Database already up to date\n");
- * } else {
- * printf("Database updated\n");
- * }
+ * if(result < 0) {
+ * printf("Unable to update database: %s\n", alpm_strerrorlast());
+ * } else if(result == 1) {
+ * printf("Database already up to date\n");
+ * } else {
+ * printf("Database updated\n");
* }
* }
* @endcode
@@ -120,15 +158,21 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
ASSERT(db != handle->db_local, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1));
ASSERT(db->servers != NULL, RET_ERR(handle, PM_ERR_SERVER_NONE, -1));
- /* make sure we have a sane umask */
- oldmask = umask(0022);
-
syncpath = get_sync_dir(handle);
if(!syncpath) {
return -1;
}
+
+ /* make sure we have a sane umask */
+ oldmask = umask(0022);
+
check_sig = _alpm_db_get_sigverify_level(db);
+ /* attempt to grab a lock */
+ if(_alpm_handle_lock(handle)) {
+ RET_ERR(handle, PM_ERR_HANDLE_LOCK, -1);
+ }
+
for(i = db->servers; i; i = i->next) {
const char *server = i->data;
char *fileurl;
@@ -144,6 +188,15 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
if(ret == 0 && (check_sig == PM_PGP_VERIFY_ALWAYS ||
check_sig == PM_PGP_VERIFY_OPTIONAL)) {
+ /* an existing sig file is no good at this point */
+ char *sigpath = _alpm_db_sig_path(db);
+ if(!sigpath) {
+ ret = -1;
+ break;
+ }
+ unlink(sigpath);
+ free(sigpath);
+
int errors_ok = (check_sig == PM_PGP_VERIFY_OPTIONAL);
/* if we downloaded a DB, we want the .sig from the same server */
snprintf(fileurl, len, "%s/%s.db.sig", server, db->treename);
@@ -173,8 +226,18 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
/* Cache needs to be rebuilt */
_alpm_db_free_pkgcache(db);
+ db->status &= ~DB_STATUS_VALID;
+ if(sync_db_validate(db)) {
+ /* pm_errno should be set */
+ ret = -1;
+ }
+
cleanup:
+ if(_alpm_handle_unlock(handle)) {
+ _alpm_log(handle, PM_LOG_WARNING, _("could not remove lock file %s\n"),
+ alpm_option_get_lockfile(handle));
+ }
free(syncpath);
umask(oldmask);
return ret;
@@ -512,18 +575,13 @@ error:
return -1;
}
-static int sync_db_version(pmdb_t UNUSED *db)
-{
- return 2;
-}
-
struct db_operations sync_db_ops = {
.populate = sync_db_populate,
.unregister = _alpm_db_unregister,
- .version = sync_db_version,
};
-pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename)
+pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename,
+ pgp_verify_t level)
{
pmdb_t *db;
@@ -535,6 +593,12 @@ pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename)
}
db->ops = &sync_db_ops;
db->handle = handle;
+ db->pgp_verify = level;
+
+ if(sync_db_validate(db)) {
+ _alpm_db_free(db);
+ return NULL;
+ }
handle->dbs_sync = alpm_list_add(handle->dbs_sync, db);
return db;
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index c3a7abd2..b20421a3 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -45,7 +45,8 @@
*/
/** Register a sync database of packages. */
-pmdb_t SYMEXPORT *alpm_db_register_sync(pmhandle_t *handle, const char *treename)
+pmdb_t SYMEXPORT *alpm_db_register_sync(pmhandle_t *handle, const char *treename,
+ pgp_verify_t check_sig)
{
/* Sanity checks */
CHECK_HANDLE(handle, return NULL);
@@ -54,7 +55,7 @@ pmdb_t SYMEXPORT *alpm_db_register_sync(pmhandle_t *handle, const char *treename
/* Do not register a database if a transaction is on-going */
ASSERT(handle->trans == NULL, RET_ERR(handle, PM_ERR_TRANS_NOT_NULL, NULL));
- return _alpm_db_register_sync(handle, treename);
+ return _alpm_db_register_sync(handle, treename, check_sig);
}
/* Helper function for alpm_db_unregister{_all} */
@@ -369,14 +370,6 @@ const char *_alpm_db_path(pmdb_t *db)
return db->_path;
}
-int _alpm_db_version(pmdb_t *db)
-{
- if(!db) {
- return -1;
- }
- return db->ops->version(db);
-}
-
char *_alpm_db_sig_path(pmdb_t *db)
{
char *sigpath;
@@ -475,11 +468,8 @@ alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles)
/* Returns a new package cache from db.
* It frees the cache if it already exists.
*/
-int _alpm_db_load_pkgcache(pmdb_t *db)
+static int load_pkgcache(pmdb_t *db)
{
- if(db == NULL) {
- return -1;
- }
_alpm_db_free_pkgcache(db);
_alpm_log(db->handle, PM_LOG_DEBUG, "loading package cache for repository '%s'\n",
@@ -490,23 +480,23 @@ int _alpm_db_load_pkgcache(pmdb_t *db)
return -1;
}
- db->pkgcache_loaded = 1;
+ db->status |= DB_STATUS_PKGCACHE;
return 0;
}
void _alpm_db_free_pkgcache(pmdb_t *db)
{
- if(db == NULL || !db->pkgcache_loaded) {
+ if(db == NULL || !(db->status & DB_STATUS_PKGCACHE)) {
return;
}
- _alpm_log(db->handle, PM_LOG_DEBUG, "freeing package cache for repository '%s'\n",
- db->treename);
+ _alpm_log(db->handle, PM_LOG_DEBUG,
+ "freeing package cache for repository '%s'\n", db->treename);
alpm_list_free_inner(_alpm_db_get_pkgcache(db),
(alpm_list_fn_free)_alpm_pkg_free);
_alpm_pkghash_free(db->pkgcache);
- db->pkgcache_loaded = 0;
+ db->status &= ~DB_STATUS_PKGCACHE;
_alpm_db_free_grpcache(db);
}
@@ -517,13 +507,12 @@ pmpkghash_t *_alpm_db_get_pkgcache_hash(pmdb_t *db)
return NULL;
}
- if(!db->pkgcache_loaded) {
- _alpm_db_load_pkgcache(db);
+ if(!(db->status & DB_STATUS_VALID)) {
+ RET_ERR(db->handle, PM_ERR_DB_INVALID, NULL);
}
- /* hmmm, still NULL ?*/
- if(!db->pkgcache) {
- _alpm_log(db->handle, PM_LOG_DEBUG, "warning: pkgcache is NULL for db '%s'\n", db->treename);
+ if(!(db->status & DB_STATUS_PKGCACHE)) {
+ load_pkgcache(db);
}
return db->pkgcache;
@@ -545,7 +534,7 @@ int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg)
{
pmpkg_t *newpkg;
- if(db == NULL || !db->pkgcache_loaded || pkg == NULL) {
+ if(db == NULL || pkg == NULL || !(db->status & DB_STATUS_PKGCACHE)) {
return -1;
}
@@ -567,7 +556,7 @@ int _alpm_db_remove_pkgfromcache(pmdb_t *db, pmpkg_t *pkg)
{
pmpkg_t *data = NULL;
- if(db == NULL || !db->pkgcache_loaded || pkg == NULL) {
+ if(db == NULL || pkg == NULL || !(db->status & DB_STATUS_PKGCACHE)) {
return -1;
}
@@ -597,8 +586,6 @@ pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target)
pmpkghash_t *pkgcache = _alpm_db_get_pkgcache_hash(db);
if(!pkgcache) {
- _alpm_log(db->handle, PM_LOG_DEBUG, "warning: failed to get '%s' from NULL pkgcache\n",
- target);
return NULL;
}
@@ -607,7 +594,7 @@ pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target)
/* Returns a new group cache from db.
*/
-int _alpm_db_load_grpcache(pmdb_t *db)
+static int load_grpcache(pmdb_t *db)
{
alpm_list_t *lp;
@@ -653,7 +640,7 @@ int _alpm_db_load_grpcache(pmdb_t *db)
}
}
- db->grpcache_loaded = 1;
+ db->status |= DB_STATUS_GRPCACHE;
return 0;
}
@@ -661,19 +648,19 @@ void _alpm_db_free_grpcache(pmdb_t *db)
{
alpm_list_t *lg;
- if(db == NULL || !db->grpcache_loaded) {
+ if(db == NULL || !(db->status & DB_STATUS_GRPCACHE)) {
return;
}
- _alpm_log(db->handle, PM_LOG_DEBUG, "freeing group cache for repository '%s'\n",
- db->treename);
+ _alpm_log(db->handle, PM_LOG_DEBUG,
+ "freeing group cache for repository '%s'\n", db->treename);
for(lg = db->grpcache; lg; lg = lg->next) {
_alpm_grp_free(lg->data);
lg->data = NULL;
}
FREELIST(db->grpcache);
- db->grpcache_loaded = 0;
+ db->status &= ~DB_STATUS_GRPCACHE;
}
alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db)
@@ -682,8 +669,12 @@ alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db)
return NULL;
}
- if(!db->grpcache_loaded) {
- _alpm_db_load_grpcache(db);
+ if(!(db->status & DB_STATUS_VALID)) {
+ RET_ERR(db->handle, PM_ERR_DB_INVALID, NULL);
+ }
+
+ if(!(db->status & DB_STATUS_GRPCACHE)) {
+ load_grpcache(db);
}
return db->grpcache;
diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h
index e3faeeb4..03187342 100644
--- a/lib/libalpm/db.h
+++ b/lib/libalpm/db.h
@@ -43,10 +43,16 @@ typedef enum _pmdbinfrq_t {
INFRQ_ALL = 0x1F
} pmdbinfrq_t;
+/** Database status. Bitflags. */
+enum _pmdbstatus_t {
+ DB_STATUS_VALID = (1 << 0),
+ DB_STATUS_PKGCACHE = (1 << 1),
+ DB_STATUS_GRPCACHE = (1 << 2)
+};
+
struct db_operations {
int (*populate) (pmdb_t *);
void (*unregister) (pmdb_t *);
- int (*version) (pmdb_t *);
};
/* Database */
@@ -55,10 +61,10 @@ struct __pmdb_t {
char *treename;
/* do not access directly, use _alpm_db_path(db) for lazy access */
char *_path;
- int pkgcache_loaded;
- int grpcache_loaded;
/* also indicates whether we are RO or RW */
int is_local;
+ /* flags determining validity, loaded caches, etc. */
+ enum _pmdbstatus_t status;
pmpkghash_t *pkgcache;
alpm_list_t *grpcache;
alpm_list_t *servers;
@@ -73,11 +79,11 @@ pmdb_t *_alpm_db_new(const char *treename, int is_local);
void _alpm_db_free(pmdb_t *db);
const char *_alpm_db_path(pmdb_t *db);
char *_alpm_db_sig_path(pmdb_t *db);
-int _alpm_db_version(pmdb_t *db);
int _alpm_db_cmp(const void *d1, const void *d2);
alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles);
pmdb_t *_alpm_db_register_local(pmhandle_t *handle);
-pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename);
+pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename,
+ pgp_verify_t level);
void _alpm_db_unregister(pmdb_t *db);
/* be_*.c, backend specific calls */
@@ -88,7 +94,6 @@ int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info);
/* cache bullshit */
/* packages */
-int _alpm_db_load_pkgcache(pmdb_t *db);
void _alpm_db_free_pkgcache(pmdb_t *db);
int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg);
int _alpm_db_remove_pkgfromcache(pmdb_t *db, pmpkg_t *pkg);
@@ -97,7 +102,6 @@ alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db);
int _alpm_db_ensure_pkgcache(pmdb_t *db, pmdbinfrq_t infolevel);
pmpkg_t *_alpm_db_get_pkgfromcache(pmdb_t *db, const char *target);
/* groups */
-int _alpm_db_load_grpcache(pmdb_t *db);
void _alpm_db_free_grpcache(pmdb_t *db);
alpm_list_t *_alpm_db_get_grpcache(pmdb_t *db);
pmgrp_t *_alpm_db_get_grpfromcache(pmdb_t *db, const char *target);
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index d893f866..1e4e705b 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -70,6 +70,8 @@ const char SYMEXPORT *alpm_strerror(enum _pmerrno_t err)
return _("database already registered");
case PM_ERR_DB_NOT_FOUND:
return _("could not find database");
+ case PM_ERR_DB_INVALID:
+ return _("invalid or corrupted database");
case PM_ERR_DB_VERSION:
return _("database is incorrect version");
case PM_ERR_DB_WRITE:
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index b535e0f3..acd35409 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -22,12 +22,14 @@
#include "config.h"
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <syslog.h>
#include <sys/stat.h>
+#include <fcntl.h>
/* libalpm */
#include "handle.h"
@@ -86,6 +88,58 @@ void _alpm_handle_free(pmhandle_t *handle)
FREE(handle);
}
+/** Lock the database */
+int _alpm_handle_lock(pmhandle_t *handle)
+{
+ int fd;
+ char *dir, *ptr;
+
+ ASSERT(handle->lockfile != NULL, return -1);
+ ASSERT(handle->lckstream == NULL, return 0);
+
+ /* create the dir of the lockfile first */
+ dir = strdup(handle->lockfile);
+ ptr = strrchr(dir, '/');
+ if(ptr) {
+ *ptr = '\0';
+ }
+ if(_alpm_makepath(dir)) {
+ FREE(dir);
+ return -1;
+ }
+ FREE(dir);
+
+ do {
+ fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000);
+ } while(fd == -1 && errno == EINTR);
+ if(fd > 0) {
+ FILE *f = fdopen(fd, "w");
+ fprintf(f, "%ld\n", (long)getpid());
+ fflush(f);
+ fsync(fd);
+ handle->lckstream = f;
+ return 0;
+ }
+ return -1;
+}
+
+/** Remove a lock file */
+int _alpm_handle_unlock(pmhandle_t *handle)
+{
+ ASSERT(handle->lockfile != NULL, return -1);
+ ASSERT(handle->lckstream != NULL, return 0);
+
+ if(handle->lckstream != NULL) {
+ fclose(handle->lckstream);
+ handle->lckstream = NULL;
+ }
+ if(unlink(handle->lockfile) && errno != ENOENT) {
+ return -1;
+ }
+ return 0;
+}
+
+
alpm_cb_log SYMEXPORT alpm_option_get_logcb(pmhandle_t *handle)
{
CHECK_HANDLE(handle, return NULL);
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index 2de6efdd..4ffd00c4 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -78,6 +78,9 @@ struct __pmhandle_t {
pmhandle_t *_alpm_handle_new(void);
void _alpm_handle_free(pmhandle_t *handle);
+int _alpm_handle_lock(pmhandle_t *handle);
+int _alpm_handle_unlock(pmhandle_t *handle);
+
enum _pmerrno_t _alpm_set_directory_option(const char *value,
char **storage, int must_exist);
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index f0744937..507ea027 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -30,7 +30,6 @@
#include <sys/types.h>
#include <errno.h>
#include <limits.h>
-#include <fcntl.h>
/* libalpm */
#include "trans.h"
@@ -48,69 +47,28 @@
* @{
*/
-/* Create a lock file */
-static int make_lock(pmhandle_t *handle)
-{
- int fd;
- char *dir, *ptr;
-
- ASSERT(handle->lockfile != NULL, return -1);
-
- /* create the dir of the lockfile first */
- dir = strdup(handle->lockfile);
- ptr = strrchr(dir, '/');
- if(ptr) {
- *ptr = '\0';
- }
- if(_alpm_makepath(dir)) {
- FREE(dir);
- return -1;
- }
- FREE(dir);
-
- do {
- fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000);
- } while(fd == -1 && errno == EINTR);
- if(fd > 0) {
- FILE *f = fdopen(fd, "w");
- fprintf(f, "%ld\n", (long)getpid());
- fflush(f);
- fsync(fd);
- handle->lckstream = f;
- return 0;
- }
- return -1;
-}
-
-/* Remove a lock file */
-static int remove_lock(pmhandle_t *handle)
-{
- if(handle->lckstream != NULL) {
- fclose(handle->lckstream);
- handle->lckstream = NULL;
- }
- if(unlink(handle->lockfile) == -1 && errno != ENOENT) {
- return -1;
- }
- return 0;
-}
-
/** Initialize the transaction. */
int SYMEXPORT alpm_trans_init(pmhandle_t *handle, pmtransflag_t flags,
alpm_trans_cb_event event, alpm_trans_cb_conv conv,
alpm_trans_cb_progress progress)
{
pmtrans_t *trans;
- const int required_db_version = 2;
- int db_version;
+ alpm_list_t *i;
/* Sanity checks */
CHECK_HANDLE(handle, return -1);
ASSERT(handle->trans == NULL, RET_ERR(handle, PM_ERR_TRANS_NOT_NULL, -1));
+ for(i = handle->dbs_sync; i; i = i->next) {
+ const pmdb_t *db = i->data;
+ if(!(db->status & DB_STATUS_VALID)) {
+ RET_ERR(handle, PM_ERR_DB_INVALID, -1);
+ }
+ }
+
/* lock db */
if(!(flags & PM_TRANS_FLAG_NOLOCK)) {
- if(make_lock(handle)) {
+ if(_alpm_handle_lock(handle)) {
RET_ERR(handle, PM_ERR_HANDLE_LOCK, -1);
}
}
@@ -122,16 +80,6 @@ int SYMEXPORT alpm_trans_init(pmhandle_t *handle, pmtransflag_t flags,
trans->cb_progress = progress;
trans->state = STATE_INITIALIZED;
- /* check database version */
- db_version = _alpm_db_version(handle->db_local);
- if(db_version < required_db_version) {
- _alpm_log(handle, PM_LOG_ERROR,
- _("%s database version is too old\n"), handle->db_local->treename);
- remove_lock(handle);
- _alpm_trans_free(trans);
- RET_ERR(handle, PM_ERR_DB_VERSION, -1);
- }
-
handle->trans = trans;
return 0;
@@ -282,7 +230,7 @@ int SYMEXPORT alpm_trans_release(pmhandle_t *handle)
/* unlock db */
if(!nolock_flag) {
- if(remove_lock(handle)) {
+ if(_alpm_handle_unlock(handle)) {
_alpm_log(handle, PM_LOG_WARNING, _("could not remove lock file %s\n"),
alpm_option_get_lockfile(handle));
alpm_logaction(handle, "warning: could not remove lock file %s\n",