[pacman-dev] [PATCH] WIP: check local DB version

Dan McGee dan at archlinux.org
Sun Feb 27 14:55:13 EST 2011


---
Any feedback on this going in? One of the checklist items on my 3.5.0 release
list.

-Dan

 lib/libalpm/alpm.c     |    2 +
 lib/libalpm/alpm.h     |    1 +
 lib/libalpm/be_local.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/libalpm/be_sync.c  |    6 +++++
 lib/libalpm/db.c       |    8 +++++++
 lib/libalpm/db.h       |    4 ++-
 lib/libalpm/error.c    |    2 +
 lib/libalpm/trans.c    |   15 +++++++++++-
 src/pacman/util.c      |    4 +++
 9 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/lib/libalpm/alpm.c b/lib/libalpm/alpm.c
index 7c3bfc2..4f95832 100644
--- a/lib/libalpm/alpm.c
+++ b/lib/libalpm/alpm.c
@@ -56,6 +56,8 @@ int SYMEXPORT alpm_initialize(void)
 	}
 	if(_alpm_db_register_local() == NULL) {
 		/* error code should be set */
+		_alpm_handle_free(handle);
+		handle = NULL;
 		return(-1);
 	}
 
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index cf3a913..0f3b716 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -497,6 +497,7 @@ enum _pmerrno_t {
 	PM_ERR_DB_NULL,
 	PM_ERR_DB_NOT_NULL,
 	PM_ERR_DB_NOT_FOUND,
+	PM_ERR_DB_VERSION,
 	PM_ERR_DB_WRITE,
 	PM_ERR_DB_REMOVE,
 	/* Servers */
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index c1e86a6..a0d8b73 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -924,9 +924,63 @@ 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(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(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) {
+			printf("found %s\n", path);
+			/* 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(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(void)
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index 69f7663..2191494 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -443,9 +443,15 @@ error:
 	return(0);
 }
 
+static int sync_db_version(pmdb_t *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(const char *treename)
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index 2a8db8e..fb64fae 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -405,6 +405,14 @@ 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));
+}
+
 int _alpm_db_cmp(const void *d1, const void *d2)
 {
 	pmdb_t *db1 = (pmdb_t *)d1;
diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h
index a530a2e..75776d7 100644
--- a/lib/libalpm/db.h
+++ b/lib/libalpm/db.h
@@ -45,6 +45,7 @@ typedef enum _pmdbinfrq_t {
 struct db_operations {
 	int (*populate) (pmdb_t *);
 	void (*unregister) (pmdb_t *);
+	int (*version) (pmdb_t *);
 };
 
 /* Database */
@@ -65,14 +66,15 @@ struct __pmdb_t {
 
 
 /* db.c, database general calls */
+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);
+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(void);
 pmdb_t *_alpm_db_register_sync(const char *treename);
 void _alpm_db_unregister(pmdb_t *db);
-pmdb_t *_alpm_db_new(const char *treename, int is_local);
 
 /* be_*.c, backend specific calls */
 int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq);
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index 2cc6685..21fbb48 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -77,6 +77,8 @@ const char SYMEXPORT *alpm_strerror(int err)
 			return _("database already registered");
 		case PM_ERR_DB_NOT_FOUND:
 			return _("could not find database");
+		case PM_ERR_DB_VERSION:
+			return _("database is incorrect version");
 		case PM_ERR_DB_WRITE:
 			return _("could not update database");
 		case PM_ERR_DB_REMOVE:
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index 9f61796..7a3ee83 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -59,10 +59,11 @@
  * @return 0 on success, -1 on error (pm_errno is set accordingly)
  */
 int SYMEXPORT alpm_trans_init(pmtransflag_t flags,
-                              alpm_trans_cb_event event, alpm_trans_cb_conv conv,
-                              alpm_trans_cb_progress progress)
+		alpm_trans_cb_event event, alpm_trans_cb_conv conv,
+		alpm_trans_cb_progress progress)
 {
 	pmtrans_t *trans;
+	const int localdb_version = 2;
 
 	ALPM_LOG_FUNC;
 
@@ -79,6 +80,16 @@ int SYMEXPORT alpm_trans_init(pmtransflag_t flags,
 		}
 	}
 
+	/* check database version */
+	if(_alpm_db_version(handle->db_local) < localdb_version) {
+		_alpm_log(PM_LOG_ERROR,
+				_("%s database version %d is too old, version %d required\n"),
+				handle->db_local->treename, _alpm_db_version(handle->db_local),
+				localdb_version);
+		_alpm_lckrm();
+		RET_ERR(PM_ERR_DB_VERSION, -1);
+	}
+
 	trans = _alpm_trans_new();
 	if(trans == NULL) {
 		RET_ERR(PM_ERR_MEMORY, -1);
diff --git a/src/pacman/util.c b/src/pacman/util.c
index c08ebb1..9d50afb 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -63,6 +63,10 @@ int trans_init(pmtransflag_t flags)
 			fprintf(stderr, _("  if you're sure a package manager is not already\n"
 						"  running, you can remove %s\n"), alpm_option_get_lockfile());
 		}
+		else if(pm_errno == PM_ERR_DB_VERSION) {
+			fprintf(stderr, _("  try running pacman-db-upgrade\n"));
+		}
+
 		return(-1);
 	}
 	return(0);
-- 
1.7.4.1



More information about the pacman-dev mailing list