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