- fix: for busted db1, attempt chain reconnection to following record.
authorjbj <devnull@localhost>
Wed, 30 May 2001 22:42:43 +0000 (22:42 +0000)
committerjbj <devnull@localhost>
Wed, 30 May 2001 22:42:43 +0000 (22:42 +0000)
CVS patchset: 4819
CVS date: 2001/05/30 22:42:43

CHANGES
lib/rpmrc.c
rpm.spec.in
rpmdb/Makefile.am
rpmdb/db1.c
rpmdb/falloc.c
rpmdb/tfalloc.c [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index e8f371a..8e02134 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -70,6 +70,7 @@
        - popt: return POPT_ERROR_ERRNO on config open/read/close failure.
        - fix: popt exec doesn't add '--', --target et al no longer need '='.
        - fix: popt consume-next-arg "!#:+" w/o side effect (#41956).
+       - fix: for busted db1, attempt chain reconnection to following record.
 
 4.0 -> 4.0.[12]
        - add doxygen and lclint annotations most everywhere.
index 158d08c..0c281c6 100644 (file)
@@ -979,7 +979,7 @@ static void defaultMachine(/*@out@*/ const char ** arch, /*@out@*/ const char **
 
     if (!gotDefaults) {
        rc = uname(&un);
-       if (rc) return;
+       if (rc < 0) return;
 
 #if !defined(__linux__)
 #ifdef SNI
index 3151a81..8c69622 100644 (file)
@@ -31,8 +31,6 @@ BuildRequires: db3-devel
 # XXX linked binaries like /bin/rpm.
 %ifnarch ia64
 Requires: glibc >= 2.1.92
-# XXX needed to avoid libdb.so.2 satisfied by compat/libc5 provides.
-Requires: db1 = 1.85
 %endif
 %endif
 
@@ -119,9 +117,9 @@ capabilities.
 
 %build
 %ifos linux
-CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{__prefix} --sysconfdir=/etc --localstatedir=/var --infodir='${prefix}%{__share}/info' --mandir='${prefix}%{__share}/man' # --enable-db1
+CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{__prefix} --sysconfdir=/etc --localstatedir=/var --infodir='${prefix}%{__share}/info' --mandir='${prefix}%{__share}/man'
 %else
-CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{__prefix} # --enable-db1
+CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{__prefix}
 %endif
 
 make
@@ -141,9 +139,17 @@ mkdir -p ${RPM_BUILD_ROOT}/etc/logrotate.d
 install -m 755 scripts/rpm.log ${RPM_BUILD_ROOT}/etc/logrotate.d/rpm
 
 mkdir -p $RPM_BUILD_ROOT/etc/rpm
-#cat << E_O_F > $RPM_BUILD_ROOT/etc/rpm/macros.db1
-#%%_dbapi              1
-#E_O_F
+cat << E_O_F > $RPM_BUILD_ROOT/etc/rpm/macros.db1
+%%_dbapi               1
+E_O_F
+
+mkdir -p $RPM_BUILD_ROOT/var/lib/rpm
+for dbi in \
+       Basenames Conflictname Dirnames Group Installtid Name Providename \
+       Provideversion Removetid Requirename Requireversion Triggername
+do
+    touch $RPM_BUILD_ROOT/var/lib/rpm/dbi
+done
 
 %endif
 
@@ -163,27 +169,36 @@ rm -rf $RPM_BUILD_ROOT
 
 %pre
 %ifos linux
-if [ -f /var/lib/rpm/packages.rpm ]; then
+if [ -f /var/lib/rpm/Packages -a -f /var/lib/rpm/packages.rpm ]; then
     echo "
-
-This version of rpm does not have db1 support, install rpm-4.0.2 and
-do rpm --rebuilddb to convert your database from db1 to db3 format.
-
+You have both
+       /var/lib/rpm/packages.rpm       db1 format installed package headers
+       /var/lib/rpm/Packages           db3 format installed package headers
+Please remove (or at least rename) one of those files, and re-install.
 "
     exit 1
 fi
-/usr/sbin/groupadd -g 37 rpm
-/usr/sbin/useradd  -d /var/lib/rpm -u 37 -g 37 rpm
+/usr/sbin/groupadd -g 37 @RPMGROUP@                            > /dev/null 2>&1
+/usr/sbin/useradd  -d /var/lib/rpm -u 37 -g 37 @RPMUSER@       > /dev/null 2>&1
 %endif
 exit 0
 
 %post
 %ifos linux
 /sbin/ldconfig
+if [ -f /var/lib/rpm/packages.rpm ]; then
+    : # do nothing
+elif [ -f /var/lib/rpm/Packages ]; then
+    # undo db1 configuration
+    rm -f /etc/rpm/macros.db1
+else
+    # initialize db3 database
+    rm -f /etc/rpm/macros.db1
+    /bin/rpm --initdb
+fi
+/bin/chown @RPMUSER@.@RPMGROUP@ /var/lib/rpm/[A-Z]* /var/lib/rpm/*.rpm
 %endif
-# initialize db3 database
-/bin/rpm --initdb
-/bin/chown @RPMUSER@.@RPMGROUP@ /var/lib/rpm/[A-Z]*
+exit 0
 
 %ifos linux
 %postun
@@ -215,7 +230,22 @@ fi
 %config(missingok)     /etc/cron.daily/rpm
 %config(missingok)     /etc/logrotate.d/rpm
 %dir                   /etc/rpm
-#%config(missingok)    /etc/rpm/macros.db1
+%config(missingok)     /etc/rpm/macros.db1
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %dir /var/lib/rpm
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Basenames
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Conflictname
+#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/__db.001
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Dirnames
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Group
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Installtid
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Name
+#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Packages
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Providename
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Provideversion
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Removetid
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Requirename
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Requireversion
+%attr(0755, @RPMUSER@, @RPMGROUP@)     %ghost /var/lib/rpm/Triggername
 %endif
 
 %attr(0755, @RPMUSER@, @RPMGROUP@)     %{__prefix}/bin/rpm2cpio
@@ -241,22 +271,6 @@ fi
 %attr(0644, @RPMUSER@, @RPMGROUP@)     %{__prefix}/lib/rpm/rpmpopt*
 %attr(0644, @RPMUSER@, @RPMGROUP@)     %{__prefix}/lib/rpm/rpmrc
 
-%attr(0755, @RPMUSER@, @RPMGROUP@)     %dir /var/lib/rpm
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Basenames
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Conflictname
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/__db.001
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Dirnames
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Group
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Installtid
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Name
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Packages
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Providename
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Provideversion
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Removetid
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Requirename
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Requireversion
-#%attr(0755, @RPMUSER@, @RPMGROUP@)    %ghost /var/lib/rpm/Triggername
-
 %ifarch i386 i486 i586 i686 athlon
 %attr(-, @RPMUSER@, @RPMGROUP@)        %{__prefix}/lib/rpm/i[3456]86*
 %endif
index 0e4a712..1951317 100644 (file)
@@ -30,7 +30,7 @@ lib_LTLIBRARIES = librpmdb.la
 librpmdb_la_SOURCES = $(DBLIBSRCS) dbconfig.c fprint.c rpmhash.c rpmdb.c
 librpmdb_la_LDFLAGS = @libdb3@
 librpmdb_la_LIBADD = $(DBLIBOBJS) $(DB3LOBJS)
-librpmdb_la_DEPENDENCIES = $(DBLIBOBJS) createlinks
+librpmdb_la_DEPENDENCIES = $(DBLIBOBJS) .created
 
 # XXX Add internal libtool dependence
 install-data-local:
@@ -41,11 +41,11 @@ install-data-local:
 falloc.lo: falloc.c $(top_srcdir)/system.h $(top_srcdir)/rpmio/rpmio.h falloc.h
        $(LIBTOOL) --mode=compile $(COMPILE) -c $<
 
-.PHONY: createlinks
-createlinks:
+.created:
        for lo in $(DB3LOBJS); do \
          [ -f $$lo ] || $(LN_S) $(top_builddir)/$(WITH_DB_SUBDIR)/$$lo $$lo ; \
        done
+       touch $@
 
 clean-local:
        rm -f $(DB3LOBJS)
@@ -57,3 +57,6 @@ sources:
 .PHONY:        lclint
 lclint:
        lclint $(DEFS) $(INCLUDES) $(librpmdb_la_SOURCES)
+
+tfalloc: librpmdb.la tfalloc.o
+       $(LINK) -all-static $@.o $< $(mylibpaths) $(mylibs) $(LIBS)
index b016f85..e742a0a 100644 (file)
@@ -128,14 +128,17 @@ static int db1sync(dbiIndex dbi, /*@unused@*/ unsigned int flags) {
     return rc;
 }
 
-/*@null@*/ static void * doGetRecord(FD_t pkgs, unsigned int offset)
+/*@null@*/ static void * doGetRecord(dbiIndex dbi, unsigned int offset)
 {
+    FD_t pkgs = dbi->dbi_db;
     void * uh = NULL;
     Header h = NULL;
     const char ** fileNames;
     int fileCount = 0;
+    int lasto = 0;
     int i;
 
+retry:
     if (offset >= fadGetFileSize(pkgs))
        goto exit;
 
@@ -144,7 +147,8 @@ static int db1sync(dbiIndex dbi, /*@unused@*/ unsigned int flags) {
     h = headerRead(pkgs, HEADER_MAGIC_NO);
 
     /* let's sanity check this record a bit, otherwise just skip it */
-    if (!(     headerIsEntry(h, RPMTAG_NAME) &&
+    if (h != NULL &&
+       !(      headerIsEntry(h, RPMTAG_NAME) &&
                headerIsEntry(h, RPMTAG_VERSION) &&
                headerIsEntry(h, RPMTAG_RELEASE) &&
                headerIsEntry(h, RPMTAG_BUILDTIME)))
@@ -152,8 +156,26 @@ static int db1sync(dbiIndex dbi, /*@unused@*/ unsigned int flags) {
        h = headerFree(h);
     }
 
-    if (h == NULL)
+    if (h == NULL) {
+       /* XXX HACK: try to reconnect broken chain. */
+       if (lasto == 0) {
+           rpmMessage(RPMMESS_WARNING,
+  _("Broken package chain at offset %d(0x%08x), attempting to reconnect ...\n"),
+                       (int) offset, offset);
+           lasto = (offset ? offset : -1);
+           offset = fadNextOffset(pkgs, offset);
+           if (offset > 0)
+               goto retry;
+       }
        goto exit;
+    }
+
+    if (lasto) {
+       rpmMessage(RPMMESS_WARNING,
+               _("Reconnecting broken chain at offset %d(0x%08x).\n"),
+               (int) offset, offset);
+       dbi->dbi_lastoffset = offset;
+    }
 
     /* Retrofit "Provide: name = EVR" for binary packages. */
     providePackageNVR(h);
@@ -169,7 +191,8 @@ static int db1sync(dbiIndex dbi, /*@unused@*/ unsigned int flags) {
      * list.
      */
     if (!headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, NULL, 
-                          (const void **) &fileNames, &fileCount)) goto exit;
+                          (const void **) &fileNames, &fileCount))
+       goto exit;
 
     for (i = 0; i < fileCount; i++) 
        if (*fileNames[i] != '/') break;
@@ -274,13 +297,8 @@ static int db1cget(dbiIndex dbi, /*@unused@*/ DBC * dbcursor, void ** keyp,
            memcpy(data.data, &offset, sizeof(offset));
            data.size = sizeof(offset);
        } else {                /* XXX simulated retrieval */
-           data.data = doGetRecord(pkgs, offset);
+           data.data = doGetRecord(dbi, offset);
            data.size = 0;      /* XXX WRONG */
-           if (data.data == NULL) {
-if (keyp)      *keyp = key.data;
-if (keylen)    *keylen = key.size;
-               rc = EFAULT;
-           }
        }
     }
 #ifdef DYING
index f1d0af2..2eeaab7 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "system.h"
 #include <rpmio_internal.h>
+#include <rpmmessages.h>
 #include <rpmerr.h>
 #include "falloc.h"
 #include "debug.h"
@@ -379,6 +380,42 @@ void fadFree(FD_t fd, unsigned int offset)
     }
 }
 
+static int insane = 0;
+
+static int fadSanity(FD_t fd, int offset, struct faHeader * fh)
+{
+    int rc = 0;
+
+    if (fh->size <= 0 || fh->size > 0x00200000 || (fh->size & 0x3f) != 0)
+       rc |= 0x1;
+
+    if (fh->freeNext &&
+       !(      fh->freeNext > sizeof(struct faFileHeader) &&
+               fh->freeNext < fadGetFileSize(fd) &&
+               (fh->freeNext & 0x3f) == sizeof(struct faFileHeader)) )
+       rc |= 0x2;
+
+    if (fh->freePrev &&
+       !(      fh->freePrev > sizeof(struct faFileHeader) &&
+               fh->freePrev < fadGetFileSize(fd) &&
+               (fh->freePrev & 0x3f) == sizeof(struct faFileHeader)) )
+       rc |= 0x4;
+
+    if (fh->isFree & ~1)
+       rc |= 0x8;
+
+    if (!insane && rc) {
+       rpmMessage(RPMMESS_DEBUG,
+    "offset %d(0x%08x) rc %d: size 0x%08x next %d(0x%08x) prev %d(0x%08x) isFree 0x%08x\n",
+               offset, (unsigned) offset, rc,
+               (unsigned) fh->size,
+               (int) fh->freeNext, fh->freeNext,
+               (int) fh->freePrev, fh->freePrev,
+               (unsigned) fh->isFree);
+    }
+    return rc;
+}
+
 int fadFirstOffset(FD_t fd)
 {
     return fadNextOffset(fd, 0);
@@ -388,6 +425,7 @@ int fadNextOffset(FD_t fd, unsigned int lastOffset)
 {
     struct faHeader header;
     int offset;
+    int rc;
 
     offset = (lastOffset)
        ? (lastOffset - sizeof(header))
@@ -400,17 +438,45 @@ int fadNextOffset(FD_t fd, unsigned int lastOffset)
     if (Pread(fd, &header, sizeof(header), offset) != sizeof(header))
        return 0;
 
-    if (!lastOffset && !header.isFree)
+    if (!lastOffset && header.isFree == 0)
        return (offset + sizeof(header));
 
+    /*
+     * XXX Try to reconnect at next record found. This isn't perfect
+     * XXX but handles many common db1 corruption problems.
+     */
+    rc = fadSanity(fd, offset, &header);
+    if (rc) {
+       struct faHeader myheader;
+       int o = offset + sizeof(header); 
+
+       memset(&myheader, 0, sizeof(myheader));
+       insane = 1;
+       for (   o = offset + 0x40;
+               o < fadGetFileSize(fd);
+               o += 0x40)
+       {
+           rc = Pread(fd, &myheader, sizeof(myheader), o);
+           if (rc != sizeof(header))
+               return 0;
+           rc = fadSanity(fd, o, &myheader);
+           if (rc == 0)
+               break;
+       }
+       insane = 0;
+       if (o >= fadGetFileSize(fd))
+           return 0;
+       return (o + sizeof(header));
+    }
+
     do {
        offset += header.size;
 
        if (Pread(fd, &header, sizeof(header), offset) != sizeof(header))
            return 0;
 
-       if (!header.isFree) break;
-    } while (offset < fadGetFileSize(fd) && header.isFree);
+       if (header.isFree == 0) break;
+    } while (offset < fadGetFileSize(fd) && header.isFree == 1);
 
     if (offset < fadGetFileSize(fd)) {
        /* Sanity check this to make sure we're not going in loops */
diff --git a/rpmdb/tfalloc.c b/rpmdb/tfalloc.c
new file mode 100644 (file)
index 0000000..a4df0b8
--- /dev/null
@@ -0,0 +1,30 @@
+#include "system.h"
+#include <rpmlib.h>
+#include "rpmio_internal.h"
+#include "falloc.h"
+#include "debug.h"
+
+#define        RPMDBFN "/var/lib/rpm/packages.rpm"
+static const char * rpmdbfn = RPMDBFN;
+
+int main(int argc, const char ** argv)
+{
+    int lasto = 0;
+    FD_t fd;
+
+
+    fd = fadOpen(rpmdbfn, O_RDONLY, 0644);
+    if (fd == NULL) {
+       fprintf(stderr, "fadOpen(%s) failed\n", rpmdbfn);
+       exit(1);
+    }
+fprintf(stderr, "%s: size %d(0x%08x)\n", rpmdbfn, fadGetFileSize(fd), (unsigned) fadGetFileSize(fd));
+
+    while ((lasto = fadNextOffset(fd, lasto)) > 0) {
+fprintf(stderr, "%10d\n", lasto);
+    }
+
+    (void) Fclose(fd);
+
+    return 0;
+}