Blame db_conversion.diff

Bernhard M. Wiedemann 6f42b1
--- ./lib/backend/bdb_ro.c.orig	2020-03-24 20:45:19.121907476 +0000
Bernhard M. Wiedemann 6f42b1
+++ ./lib/backend/bdb_ro.c	2020-03-24 20:46:17.141727988 +0000
Bernhard M. Wiedemann 018f1b
@@ -795,6 +795,7 @@ static unsigned int bdbro_pkgdbKey(dbiIn
Bernhard M. Wiedemann 018f1b
 struct rpmdbOps_s bdbro_dbops = {
Bernhard M. Wiedemann 018f1b
     .name       = "bdb_ro",
Bernhard M. Wiedemann 018f1b
     .path       = "Packages",
Bernhard M. Wiedemann 018f1b
+    .readonly   = 1,
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
     .open       = bdbro_Open,
Bernhard M. Wiedemann 018f1b
     .close      = bdbro_Close,
Bernhard M. Wiedemann 6f42b1
--- ./lib/backend/dbi.c.orig	2020-03-24 20:45:19.121907476 +0000
Bernhard M. Wiedemann 6f42b1
+++ ./lib/backend/dbi.c	2020-03-24 20:46:17.141727988 +0000
Bernhard M. Wiedemann 018f1b
@@ -105,11 +105,20 @@ dbDetectBackend(rpmdb rdb)
Bernhard M. Wiedemann 018f1b
     }
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
     rdb->db_descr = rdb->db_ops->name;
Bernhard M. Wiedemann 018f1b
+    rdb->db_ops_config = ops_config;
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
     if (db_backend)
Bernhard M. Wiedemann 018f1b
 	free(db_backend);
Bernhard M. Wiedemann 018f1b
 }
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
+int dbiNeedConversion(rpmdb rdb)
Bernhard M. Wiedemann 018f1b
+{
Bernhard M. Wiedemann 018f1b
+    if (!rdb->db_ops)
Bernhard M. Wiedemann 018f1b
+	dbDetectBackend(rdb);
Bernhard M. Wiedemann 018f1b
+    return rdb->db_ops->readonly && rdb->db_ops_config
Bernhard M. Wiedemann 018f1b
+	&& rdb->db_ops_config->path && !rdb->db_ops_config->readonly;
Bernhard M. Wiedemann 018f1b
+}
Bernhard M. Wiedemann 018f1b
+
Bernhard M. Wiedemann 018f1b
 const char * dbiName(dbiIndex dbi)
Bernhard M. Wiedemann 018f1b
 {
Bernhard M. Wiedemann 018f1b
     return dbi->dbi_file;
Bernhard M. Wiedemann 6f42b1
--- ./lib/backend/dbi.h.orig	2020-03-24 20:45:19.121907476 +0000
Bernhard M. Wiedemann 6f42b1
+++ ./lib/backend/dbi.h	2020-03-24 20:46:17.141727988 +0000
Bernhard M. Wiedemann 018f1b
@@ -10,6 +10,7 @@ enum rpmdbFlags {
Bernhard M. Wiedemann 018f1b
     RPMDB_FLAG_JUSTCHECK	= (1 << 0),
Bernhard M. Wiedemann 018f1b
     RPMDB_FLAG_REBUILD		= (1 << 1),
Bernhard M. Wiedemann 018f1b
     RPMDB_FLAG_VERIFYONLY	= (1 << 2),
Bernhard M. Wiedemann 018f1b
+    RPMDB_FLAG_CONVERT		= (1 << 3),
Bernhard M. Wiedemann 018f1b
 };
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
 typedef enum dbCtrlOp_e {
Bernhard M. Wiedemann 018f1b
@@ -62,6 +63,7 @@ struct rpmdb_s {
Bernhard M. Wiedemann 018f1b
     int		db_buildindex;	/*!< Index rebuild indicator */
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
     const struct rpmdbOps_s * db_ops;	/*!< backend ops */
Bernhard M. Wiedemann 018f1b
+    const struct rpmdbOps_s * db_ops_config;	/*!< configured backend ops */
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
     /* dbenv and related parameters */
Bernhard M. Wiedemann 018f1b
     void * db_dbenv;		/*!< Backend private handle */
Bernhard M. Wiedemann 018f1b
@@ -201,6 +203,14 @@ RPM_GNUC_INTERNAL
Bernhard M. Wiedemann 018f1b
 const char * dbiName(dbiIndex dbi);
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
 /** \ingroup dbi
Bernhard M. Wiedemann 018f1b
+ * Check if the database needs to be converted to a different format
Bernhard M. Wiedemann 018f1b
+ * @param db           rpm database
Bernhard M. Wiedemann 018f1b
+ * @return             boolean
Bernhard M. Wiedemann 018f1b
+ */
Bernhard M. Wiedemann 018f1b
+RPM_GNUC_INTERNAL
Bernhard M. Wiedemann 018f1b
+int dbiNeedConversion(rpmdb rdb);
Bernhard M. Wiedemann 018f1b
+
Bernhard M. Wiedemann 018f1b
+/** \ingroup dbi
Bernhard M. Wiedemann 018f1b
  * Open a database cursor.
Bernhard M. Wiedemann 018f1b
  * @param dbi		index database handle
Bernhard M. Wiedemann 018f1b
  * @param flags		DBC_WRITE if writing, or 0 (DBC_READ) for reading
Bernhard M. Wiedemann 018f1b
@@ -246,6 +256,7 @@ const void * idxdbKey(dbiIndex dbi, dbiC
Bernhard M. Wiedemann 018f1b
 struct rpmdbOps_s {
Bernhard M. Wiedemann 018f1b
     const char *name; /* backend name */
Bernhard M. Wiedemann 018f1b
     const char *path; /* main database name */
Bernhard M. Wiedemann 018f1b
+    int readonly;     /* cannot modify database */
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
     int (*open)(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags);
Bernhard M. Wiedemann 018f1b
     int (*close)(dbiIndex dbi, unsigned int flags);
Bernhard M. Wiedemann 6f42b1
--- ./lib/rpmdb.c.orig	2020-03-24 20:45:19.117907488 +0000
Bernhard M. Wiedemann 6f42b1
+++ ./lib/rpmdb.c	2020-03-24 21:01:54.870821518 +0000
Bernhard M. Wiedemann 018f1b
@@ -513,8 +513,16 @@ static int openDatabase(const char * pre
Bernhard M. Wiedemann 018f1b
 	    rpmsqActivate(1);
Bernhard M. Wiedemann 018f1b
 	}
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
+	/* Convert the database if needed */
Bernhard M. Wiedemann 018f1b
+	if (!db->db_pkgs && !justCheck && (mode & O_ACCMODE) == O_RDWR && dbiNeedConversion(db)) {
Bernhard M. Wiedemann 018f1b
+	    rpmlog(RPMLOG_WARNING, _("Converting database from %s to %s format\n"), db->db_ops->name, db->db_ops_config->name);
Bernhard M. Wiedemann 018f1b
+	    rc = rpmdbRebuild(prefix, NULL, NULL, RPMDB_FLAG_CONVERT);
Bernhard M. Wiedemann 018f1b
+	    db->db_ops = NULL;		/* force re-detection of backend */
Bernhard M. Wiedemann 018f1b
+	}
Bernhard M. Wiedemann 018f1b
+
Bernhard M. Wiedemann 018f1b
 	/* Just the primary Packages database opened here */
Bernhard M. Wiedemann 018f1b
-	rc = pkgdbOpen(db, db->db_flags, NULL);
Bernhard M. Wiedemann 018f1b
+	if (!rc)
Bernhard M. Wiedemann 018f1b
+	    rc = pkgdbOpen(db, db->db_flags, NULL);
Bernhard M. Wiedemann 018f1b
 	if (!db->db_descr)
Bernhard M. Wiedemann 018f1b
 	    db->db_descr = "unknown db";
Bernhard M. Wiedemann 018f1b
     }
Bernhard M. Wiedemann 018f1b
@@ -2316,6 +2324,15 @@ int rpmdbAdd(rpmdb db, Header h)
Bernhard M. Wiedemann 018f1b
     if (db == NULL)
Bernhard M. Wiedemann 018f1b
 	return 0;
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
+    if ((db->db_flags & RPMDB_FLAG_CONVERT) != 0) {
Bernhard M. Wiedemann 018f1b
+	/* keep old instance numbers when converting */
Bernhard M. Wiedemann 018f1b
+	hdrNum = headerGetInstance(h);
Bernhard M. Wiedemann 018f1b
+	if (hdrNum == 0) {
Bernhard M. Wiedemann 018f1b
+	    ret = -1;
Bernhard M. Wiedemann 018f1b
+	    goto exit;
Bernhard M. Wiedemann 018f1b
+	}
Bernhard M. Wiedemann 018f1b
+    }
Bernhard M. Wiedemann 018f1b
+
Bernhard M. Wiedemann 018f1b
     hdrBlob = headerExport(h, &hdrLen);
Bernhard M. Wiedemann 018f1b
     if (hdrBlob == NULL || hdrLen == 0) {
Bernhard M. Wiedemann 018f1b
 	ret = -1;
Bernhard M. Wiedemann 018f1b
@@ -2331,7 +2348,8 @@ int rpmdbAdd(rpmdb db, Header h)
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
     /* Add header to primary index */
Bernhard M. Wiedemann 018f1b
     dbc = dbiCursorInit(dbi, DBC_WRITE);
Bernhard M. Wiedemann 018f1b
-    ret = pkgdbNew(dbi, dbc, &hdrNum);
Bernhard M. Wiedemann 018f1b
+    if ((db->db_flags & RPMDB_FLAG_CONVERT) == 0)
Bernhard M. Wiedemann 018f1b
+	ret = pkgdbNew(dbi, dbc, &hdrNum);
Bernhard M. Wiedemann 018f1b
     if (ret == 0)
Bernhard M. Wiedemann 018f1b
 	ret = pkgdbPut(dbi, dbc, hdrNum, hdrBlob, hdrLen);
Bernhard M. Wiedemann 018f1b
     dbiCursorFree(dbi, dbc);
Bernhard M. Wiedemann 018f1b
@@ -2491,7 +2509,8 @@ static int rpmdbSetPermissions(char * sr
Bernhard M. Wiedemann 018f1b
 }
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
 int rpmdbRebuild(const char * prefix, rpmts ts,
Bernhard M. Wiedemann 018f1b
-		rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, char ** msg))
Bernhard M. Wiedemann 018f1b
+		rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, char ** msg),
Bernhard M. Wiedemann 018f1b
+		int newdbflags)
Bernhard M. Wiedemann 018f1b
 {
Bernhard M. Wiedemann 018f1b
     rpmdb olddb;
Bernhard M. Wiedemann 018f1b
     char * dbpath = NULL;
Bernhard M. Wiedemann 6f42b1
@@ -2512,7 +2531,22 @@ int rpmdbRebuild(const char * prefix, rp
Bernhard M. Wiedemann 6f42b1
     }
Bernhard M. Wiedemann 6f42b1
     rootdbpath = rpmGetPath(prefix, dbpath, NULL);
Bernhard M. Wiedemann 6f42b1
 
Bernhard M. Wiedemann 6f42b1
-    newdbpath = rpmGetPath("%{?_dbpath_rebuild}", NULL);
Bernhard M. Wiedemann 6f42b1
+    if ((newdbflags & RPMDB_FLAG_CONVERT) != 0) {
Bernhard M. Wiedemann 6f42b1
+	char lbuf[PATH_MAX];
Bernhard M. Wiedemann 6f42b1
+	ssize_t s = readlink(rootdbpath, lbuf, PATH_MAX);
Bernhard M. Wiedemann 6f42b1
+	if (s > 0 && s < PATH_MAX) {
Bernhard M. Wiedemann 6f42b1
+	    lbuf[s] = 0;
Bernhard M. Wiedemann 6f42b1
+	    free(dbpath);
Bernhard M. Wiedemann 6f42b1
+	    if (lbuf[0] == '/')
Bernhard M. Wiedemann 6f42b1
+		dbpath = strdup(lbuf);
Bernhard M. Wiedemann 6f42b1
+	    else
Bernhard M. Wiedemann 6f42b1
+		dbpath = rpmGetPath("%{?_dbpath}", "/../", lbuf, NULL);
Bernhard M. Wiedemann 6f42b1
+	    free(rootdbpath);
Bernhard M. Wiedemann 6f42b1
+	    rootdbpath = rpmGetPath(prefix, dbpath, NULL);
Bernhard M. Wiedemann 6f42b1
+	}
Bernhard M. Wiedemann 6f42b1
+	newdbpath = strdup("");
Bernhard M. Wiedemann 6f42b1
+    } else
Bernhard M. Wiedemann 6f42b1
+	newdbpath = rpmGetPath("%{?_dbpath_rebuild}", NULL);
Bernhard M. Wiedemann 6f42b1
     if (rstreq(newdbpath, "") || rstreq(newdbpath, dbpath)) {
Bernhard M. Wiedemann 6f42b1
 	newdbpath = _free(newdbpath);
Bernhard M. Wiedemann 6f42b1
 	rasprintf(&newdbpath, "%srebuilddb.%d", dbpath, (int) getpid());
Bernhard M. Wiedemann 6f42b1
@@ -2536,7 +2570,7 @@ int rpmdbRebuild(const char * prefix, rp
Bernhard M. Wiedemann 018f1b
 	goto exit;
Bernhard M. Wiedemann 018f1b
     }
Bernhard M. Wiedemann 018f1b
     if (openDatabase(prefix, newdbpath, &newdb,
Bernhard M. Wiedemann 018f1b
-		     (O_RDWR | O_CREAT), 0644, RPMDB_FLAG_REBUILD)) {
Bernhard M. Wiedemann 018f1b
+		     (O_RDWR | O_CREAT), 0644, RPMDB_FLAG_REBUILD | newdbflags)) {
Bernhard M. Wiedemann 018f1b
 	rc = 1;
Bernhard M. Wiedemann 018f1b
 	goto exit;
Bernhard M. Wiedemann 018f1b
     }
Bernhard M. Wiedemann 6f42b1
--- ./lib/rpmdb_internal.h.orig	2019-06-26 14:17:31.412985694 +0000
Bernhard M. Wiedemann 6f42b1
+++ ./lib/rpmdb_internal.h	2020-03-24 20:46:17.141727988 +0000
Bernhard M. Wiedemann 018f1b
@@ -63,11 +63,13 @@ int rpmdbClose (rpmdb db);
Bernhard M. Wiedemann 018f1b
  * @param prefix	path to top of install tree
Bernhard M. Wiedemann 018f1b
  * @param ts		transaction set (or NULL)
Bernhard M. Wiedemann 018f1b
  * @param (*hdrchk)	headerCheck() vector (or NULL)
Bernhard M. Wiedemann 018f1b
+ * @param newdbflags	extra flags for the new database
Bernhard M. Wiedemann 018f1b
  * @return		0 on success
Bernhard M. Wiedemann 018f1b
  */
Bernhard M. Wiedemann 018f1b
 RPM_GNUC_INTERNAL
Bernhard M. Wiedemann 018f1b
 int rpmdbRebuild(const char * prefix, rpmts ts,
Bernhard M. Wiedemann 018f1b
-		rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, char ** msg));
Bernhard M. Wiedemann 018f1b
+		rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, char ** msg),
Bernhard M. Wiedemann 018f1b
+		int newdbflags);
Bernhard M. Wiedemann 018f1b
 
Bernhard M. Wiedemann 018f1b
 /** \ingroup rpmdb
Bernhard M. Wiedemann 018f1b
  * Verify database components.
Bernhard M. Wiedemann 6f42b1
--- ./lib/rpmts.c.orig	2020-03-24 20:45:19.105907526 +0000
Bernhard M. Wiedemann 6f42b1
+++ ./lib/rpmts.c	2020-03-24 20:46:17.145727976 +0000
Bernhard M. Wiedemann 018f1b
@@ -143,9 +143,9 @@ int rpmtsRebuildDB(rpmts ts)
Bernhard M. Wiedemann 018f1b
     txn = rpmtxnBegin(ts, RPMTXN_WRITE);
Bernhard M. Wiedemann 018f1b
     if (txn) {
Bernhard M. Wiedemann 018f1b
 	if (!(ts->vsflags & RPMVSF_NOHDRCHK))
Bernhard M. Wiedemann 018f1b
-	    rc = rpmdbRebuild(ts->rootDir, ts, headerCheck);
Bernhard M. Wiedemann 018f1b
+	    rc = rpmdbRebuild(ts->rootDir, ts, headerCheck, 0);
Bernhard M. Wiedemann 018f1b
 	else
Bernhard M. Wiedemann 018f1b
-	    rc = rpmdbRebuild(ts->rootDir, NULL, NULL);
Bernhard M. Wiedemann 018f1b
+	    rc = rpmdbRebuild(ts->rootDir, NULL, NULL, 0);
Bernhard M. Wiedemann 018f1b
 	rpmtxnEnd(txn);
Bernhard M. Wiedemann 018f1b
     }
Bernhard M. Wiedemann 018f1b
     return rc;