]> git.pld-linux.org Git - packages/rpm.git/commitdiff
- add and use simple internal tool to reset LSN of rpm database
authorJan Rękorajski <baggins@pld-linux.org>
Sun, 25 Nov 2012 18:25:41 +0000 (19:25 +0100)
committerJan Rękorajski <baggins@pld-linux.org>
Sun, 25 Nov 2012 18:25:41 +0000 (19:25 +0100)
dbupgrade.sh
rpmdb_reset.c [new file with mode: 0644]

index e95132decb4b292151f07175ec15a5af1f7508bf..0f035b209559aa766b0d961a24e67a80a4a32bbe 100755 (executable)
@@ -1,11 +1,6 @@
 #!/bin/sh
 
-if [ ! -x /usr/bin/db5.2_load ]; then
-       echo "This script needs /usr/bin/db5.2_load to operate."
-       exit
-fi
-
-if /usr/bin/db5.2_load -r lsn /var/lib/rpm/Packages ; then
+if /usr/lib/rpm/bin/rpmdb_reset -r lsn /var/lib/rpm/Packages ; then
        /bin/rm --interactive=never -f /var/lib/rpm/__db.00* >/dev/null 2>/dev/null || :
        /bin/rm --interactive=never -f /var/lib/rpm/log/* >/dev/null 2>/dev/null || :
 else
@@ -14,7 +9,7 @@ else
        echo
        echo "You have to run:"
        echo
-       echo "  /usr/bin/db5.2_load -r lsn /var/lib/rpm/Packages"
+       echo "  /usr/lib/rpm/bin/rpmdb_reset -r lsn /var/lib/rpm/Packages"
        echo "  /bin/rm -f /var/lib/rpm/__db.00*"
        echo "  /bin/rm -f /var/lib/rpm/log/*"
        echo "  /usr/lib/rpm/bin/dbconvert --rebuilddb"
diff --git a/rpmdb_reset.c b/rpmdb_reset.c
new file mode 100644 (file)
index 0000000..efa1707
--- /dev/null
@@ -0,0 +1,247 @@
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <db.h>
+
+typedef struct {                       /* XXX: Globals. */
+       const char *progname;           /* Program name. */
+       char    *hdrbuf;                /* Input file header. */
+       u_long  lineno;                 /* Input file line number. */
+       u_long  origline;               /* Original file line number. */
+       int     endodata;               /* Reached the end of a database. */
+       int     endofile;               /* Reached the end of the input. */
+       int     version;                /* Input version. */
+       char    *home;                  /* Env home. */
+       char    *passwd;                /* Env passwd. */
+       int     private;                /* Private env. */
+       u_int32_t cache;                /* Env cache size. */
+} LDG;
+
+int    db_init __P((DB_ENV *, char *, u_int32_t, int *));
+int    env_create __P((DB_ENV **, LDG *));
+int    main __P((int, char *[]));
+int    usage __P((void));
+int    version_check __P((void));
+
+const char *progname = "rpmdb_reset";
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       enum { NOTSET, FILEID_RESET, LSN_RESET, STANDARD_LOAD } mode;
+       extern char *optarg;
+       extern int optind;
+       DBTYPE dbtype;
+       DB_ENV  *dbenv;
+       LDG ldg;
+       u_int ldf;
+       int ch, exitval, ret;
+
+       if ((exitval = version_check()) != 0)
+               goto done;
+
+       ldg.progname = progname;
+       ldg.lineno = 0;
+       ldg.endodata = ldg.endofile = 0;
+       ldg.version = 1;
+       ldg.cache = (1024 * 1024);
+       ldg.hdrbuf = NULL;
+       ldg.home = NULL;
+       ldg.passwd = NULL;
+
+       mode = NOTSET;
+       ldf = 0;
+       exitval = 0;
+       dbtype = DB_UNKNOWN;
+
+       /*
+        * There are two modes for db_load: -r and everything else.  The -r
+        * option zeroes out the database LSN's or resets the file ID, it
+        * doesn't really "load" a new database.  The functionality is in
+        * db_load because we don't have a better place to put it, and we
+        * don't want to create a new utility for just that functionality.
+        */
+       while ((ch = getopt(argc, argv, "h:r:V")) != EOF)
+               switch (ch) {
+               case 'h':
+                       ldg.home = optarg;
+                       break;
+               case 'r':
+                       if (strcmp(optarg, "lsn") == 0)
+                               mode = LSN_RESET;
+                       else if (strcmp(optarg, "fileid") == 0)
+                               mode = FILEID_RESET;
+                       else {
+                               exitval = usage();
+                               goto done;
+                       }
+                       break;
+               case 'V':
+                       printf("%s\n", db_version(NULL, NULL, NULL));
+                       return (EXIT_SUCCESS);
+               case '?':
+               default:
+                       exitval = usage();
+                       goto done;
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 1 || mode == NOTSET) {
+               exitval = usage();
+               goto done;
+       }
+
+       /*
+        * Create an environment object initialized for error reporting, and
+        * then open it.
+        */
+       if (env_create(&dbenv, &ldg) != 0)
+               goto err;
+
+       /* If we're resetting the LSNs, that's an entirely separate path. */
+       switch (mode) {
+       case FILEID_RESET:
+               exitval = dbenv->fileid_reset(dbenv, argv[0], 0);
+               break;
+       case LSN_RESET:
+               exitval = dbenv->lsn_reset(dbenv, argv[0], 0);
+               break;
+       case NOTSET:
+               break;
+       }
+
+       if (0) {
+err:           exitval = 1;
+       }
+       if ((ret = dbenv->close(dbenv, 0)) != 0) {
+               exitval = 1;
+               fprintf(stderr,
+                   "%s: dbenv->close: %s\n", ldg.progname, db_strerror(ret));
+       }
+
+       if (ldg.passwd != NULL)
+               free(ldg.passwd);
+
+done:
+       return (exitval);
+}
+
+/*
+ * env_create --
+ *     Create the environment and initialize it for error reporting.
+ */
+int
+env_create(dbenvp, ldg)
+       DB_ENV **dbenvp;
+       LDG *ldg;
+{
+       DB_ENV *dbenv;
+       int ret;
+
+       if ((ret = db_env_create(dbenvp, 0)) != 0) {
+               fprintf(stderr, "%s: db_env_create: %s\n",
+                   ldg->progname, db_strerror(ret));
+               return (ret);
+       }
+       dbenv = *dbenvp;
+       dbenv->set_errfile(dbenv, stderr);
+       dbenv->set_errpfx(dbenv, ldg->progname);
+       if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
+           ldg->passwd, DB_ENCRYPT_AES)) != 0) {
+               dbenv->err(dbenv, ret, "set_passwd");
+               return (ret);
+       }
+       if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)
+               return (ret);
+       dbenv->app_private = ldg;
+
+       return (0);
+}
+
+/*
+ * db_init --
+ *     Initialize the environment.
+ */
+int
+db_init(dbenv, home, cache, is_private)
+       DB_ENV *dbenv;
+       char *home;
+       u_int32_t cache;
+       int *is_private;
+{
+       u_int32_t flags;
+       int ret;
+
+       *is_private = 0;
+       /* We may be loading into a live environment.  Try and join. */
+       flags = DB_USE_ENVIRON |
+           DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
+       if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
+               return (0);
+       if (ret == DB_VERSION_MISMATCH)
+               goto err;
+
+       /*
+        * We're trying to load a database.
+        *
+        * An environment is required because we may be trying to look at
+        * databases in directories other than the current one.  We could
+        * avoid using an environment iff the -h option wasn't specified,
+        * but that seems like more work than it's worth.
+        *
+        * No environment exists (or, at least no environment that includes
+        * an mpool region exists).  Create one, but make it private so that
+        * no files are actually created.
+        */
+#define        LF_SET(f)       ((flags) |= (f))
+#define        LF_CLR(f)       ((flags) &= ~(f))
+       LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);
+       LF_SET(DB_CREATE | DB_PRIVATE);
+       *is_private = 1;
+       if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
+               dbenv->err(dbenv, ret, "set_cachesize");
+               return (1);
+       }
+       if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)
+               return (0);
+
+       /* An environment is required. */
+err:   dbenv->err(dbenv, ret, "DB_ENV->open");
+       return (1);
+}
+
+/*
+ * usage --
+ *     Display the usage message.
+ */
+int
+usage()
+{
+       (void)fprintf(stderr, "usage: %s %s\n\t%s %s\n",
+           progname, "[-V]",
+           progname, "-r lsn | fileid [-h home] db_file");
+       return (EXIT_FAILURE);
+}
+
+int
+version_check()
+{
+       int v_major, v_minor, v_patch;
+
+       /* Make sure we're loaded with the right version of the DB library. */
+       (void)db_version(&v_major, &v_minor, &v_patch);
+       if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
+               fprintf(stderr,
+                   "%s: version %d.%d doesn't match library version %d.%d\n",
+                   progname, DB_VERSION_MAJOR,
+                   DB_VERSION_MINOR, v_major, v_minor);
+               return (EXIT_FAILURE);
+       }
+       return (0);
+}
This page took 0.155617 seconds and 4 git commands to generate.