[pacman-dev] [PATCH 1/2] alpm: check for invalid sync db before replacing original

ivy.foster at gmail.com ivy.foster at gmail.com
Thu Sep 8 00:22:48 UTC 2016


From: Ivy Foster <ivy.foster at gmail.com>

Closes #46107

Signed-off-by: Ivy Foster <ivy.foster at gmail.com>
---
 lib/libalpm/alpm.h    |  1 +
 lib/libalpm/be_sync.c | 26 +++++++++++++++++++++++++-
 lib/libalpm/error.c   |  2 ++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 168d71b..0dd68a7 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -75,6 +75,7 @@ typedef enum _alpm_errno_t {
 	ALPM_ERR_DB_VERSION,
 	ALPM_ERR_DB_WRITE,
 	ALPM_ERR_DB_REMOVE,
+	ALPM_ERR_DB_BACKUP,
 	/* Servers */
 	ALPM_ERR_SERVER_BAD_URL,
 	ALPM_ERR_SERVER_NONE,
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index 32a669d..ee438f8 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -182,6 +182,9 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
 	mode_t oldmask;
 	alpm_handle_t *handle;
 	alpm_siglevel_t level;
+	char *newdb;
+	char *olddb;
+	size_t len;
 
 	/* Sanity checks */
 	ASSERT(db != NULL, return -1);
@@ -218,10 +221,23 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
 
 	dbext = db->handle->dbext;
 
+	len = strlen(syncpath) + strlen(db->treename) + strlen(dbext) + 2;
+	/* TODO fix leak syncpath and umask unset */
+	MALLOC(newdb, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+	snprintf(newdb, len, "%s/%s%s", syncpath, db->treename, dbext);
+	len += 4;
+	/* TODO fix leak syncpath and umask unset */
+	MALLOC(olddb, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
+	snprintf(olddb, len, "%s.bak", newdb);
+	if (rename(newdb, olddb) == -1) {
+		ret = -1;
+		handle->pm_errno = ALPM_ERR_DB_BACKUP;
+		goto cleanup;
+	}
+
 	for(i = db->servers; i; i = i->next) {
 		const char *server = i->data, *final_db_url = NULL;
 		struct dload_payload payload;
-		size_t len;
 		int sig_ret = 0;
 
 		memset(&payload, 0, sizeof(struct dload_payload));
@@ -315,15 +331,23 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
 		}
 	}
 
+cleanup:
 	if(ret == -1) {
 		/* pm_errno was set by the download code */
 		_alpm_log(handle, ALPM_LOG_DEBUG, "failed to sync db: %s\n",
 				alpm_strerror(handle->pm_errno));
+		if (handle->pm_errno != ALPM_ERR_DB_BACKUP && rename(olddb, newdb) == -1) {
+			_alpm_log(handle, ALPM_LOG_DEBUG, "failed to replace original db: %s\n",
+					alpm_strerror(ALPM_ERR_DB_BACKUP));
+		}
 	} else {
+		unlink(olddb);
 		handle->pm_errno = 0;
 	}
 
 	_alpm_handle_unlock(handle);
+	free(newdb);
+	free(olddb);
 	free(syncpath);
 	umask(oldmask);
 	return ret;
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index 2d6d071..e707d43 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -78,6 +78,8 @@ const char SYMEXPORT *alpm_strerror(alpm_errno_t err)
 			return _("could not update database");
 		case ALPM_ERR_DB_REMOVE:
 			return _("could not remove database entry");
+		case ALPM_ERR_DB_BACKUP:
+			return _("could not back up old database");
 		/* Servers */
 		case ALPM_ERR_SERVER_BAD_URL:
 			return _("invalid url for server");
-- 
2.9.3


More information about the pacman-dev mailing list