I've just hit this bug myself and did some digging to figure out what's
going on.

When BerkleyDB is told to open "packages.legacy.db" it uses the
previous state information and actually tries to open "packages.db",
which does not exist at the time. Reprepro takes a path that makes it
treat it as an empty database instead, so when the new packages.db is
rebuilt, you lose everything.

I tried closing and re-opening the environment to clear that state
after the rename and it works as expected afterwards.

I dug a bit further and found that bdb provides functions to handle a
database rename or delete.

https://docs.oracle.com/cd/E17276_01/html/api_reference/C/envdbrename.html


https://docs.oracle.com/cd/E17276_01/html/api_reference/C/envdbremove.html

I've attached a patch that uses these instead and that seems to solve
the problem for me.

Kind regards,

Serge
From 39e484c27992eb1375e63b2c85c3be15e245e583 Mon Sep 17 00:00:00 2001
From: Serge Schneider <se...@raspberrypi.com>
Date: Tue, 16 Jul 2024 13:22:03 +0100
Subject: [PATCH] database.c: Use DB_ENV->dbrename() and DB_ENV->dbremove() in
 database_translate_legacy_packages

See #1017983
---
 database.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/database.c b/database.c
index b01c8ed..cf52eca 100644
--- a/database.c
+++ b/database.c
@@ -2061,7 +2061,6 @@ static retvalue database_translate_legacy_packages(void) {
 	const char *chunk, *packagename;
 	char *identifier, *key, *legacy_filename, *packages_filename, *packageversion;
 	retvalue r, result;
-	int ret, e;
 	size_t chunk_len;
 	DBT Key, Data;
 
@@ -2072,19 +2071,15 @@ static retvalue database_translate_legacy_packages(void) {
 		fprintf(stderr, "Cannot find directory '%s'!\n", global.dbdir);
 		return RET_ERROR;
 	}
-
 	packages_filename = dbfilename("packages.db");
 	legacy_filename = dbfilename("packages.legacy.db");
-	ret = rename(packages_filename, legacy_filename);
-	if (ret != 0) {
-		e = errno;
-		fprintf(stderr, "error %d renaming %s to %s: %s\n",
-				e, packages_filename, legacy_filename, strerror(e));
-		return (e != 0)?e:EINVAL;
+	r = rdb_env->dbrename(rdb_env, NULL, "packages.db", NULL, "packages.legacy.db", 0);
+	if (r != 0) {
+		fprintf(stderr, "Error: DB_ENV->dbrename: %s\n", db_strerror(r));
+		return r;
 	}
 	if (verbose >= 15)
 		fprintf(stderr, "trace: Moved '%s' to '%s'.\n", packages_filename, legacy_filename);
-
 	r = database_table("packages.legacy.db", NULL, dbt_BTREE, DB_RDONLY, &legacy_databases);
 	assert (r != RET_NOTHING);
 	if (RET_WAS_ERROR(r))
@@ -2167,12 +2162,12 @@ static retvalue database_translate_legacy_packages(void) {
 	RET_ENDUPDATE(result, r);
 
 	if (RET_IS_OK(result)) {
-		e = deletefile(legacy_filename);
-		if (e != 0) {
+		r = rdb_env->dbremove(rdb_env, NULL, "packages.legacy.db", NULL, 0);
+		if (r != 0) {
 			fprintf(stderr, "Could not delete '%s'!\n"
 "It can now safely be deleted and it all that is left to be done!\n",
 					legacy_filename);
-			return RET_ERRNO(e);
+			return r;
 		}
 	}
 
-- 
2.34.1

Reply via email to