From cc54f00167e420f4e2bc4094e76c604da3c540a6 Mon Sep 17 00:00:00 2001 From: jbj Date: Wed, 30 May 2001 22:42:43 +0000 Subject: [PATCH] - fix: for busted db1, attempt chain reconnection to following record. CVS patchset: 4819 CVS date: 2001/05/30 22:42:43 --- CHANGES | 1 + lib/rpmrc.c | 2 +- rpm.spec.in | 82 +++++++++++++++++++++++++++-------------------- rpmdb/Makefile.am | 9 ++++-- rpmdb/db1.c | 38 ++++++++++++++++------ rpmdb/falloc.c | 72 +++++++++++++++++++++++++++++++++++++++-- rpmdb/tfalloc.c | 30 +++++++++++++++++ 7 files changed, 183 insertions(+), 51 deletions(-) create mode 100644 rpmdb/tfalloc.c diff --git a/CHANGES b/CHANGES index e8f371aa6..8e0213452 100644 --- 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. diff --git a/lib/rpmrc.c b/lib/rpmrc.c index 158d08ce6..0c281c61c 100644 --- a/lib/rpmrc.c +++ b/lib/rpmrc.c @@ -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 diff --git a/rpm.spec.in b/rpm.spec.in index 3151a81ee..8c69622fc 100644 --- a/rpm.spec.in +++ b/rpm.spec.in @@ -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 diff --git a/rpmdb/Makefile.am b/rpmdb/Makefile.am index 0e4a71295..19513171b 100644 --- a/rpmdb/Makefile.am +++ b/rpmdb/Makefile.am @@ -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) diff --git a/rpmdb/db1.c b/rpmdb/db1.c index b016f854e..e742a0a96 100644 --- a/rpmdb/db1.c +++ b/rpmdb/db1.c @@ -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 diff --git a/rpmdb/falloc.c b/rpmdb/falloc.c index f1d0af290..2eeaab761 100644 --- a/rpmdb/falloc.c +++ b/rpmdb/falloc.c @@ -13,6 +13,7 @@ #include "system.h" #include +#include #include #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 index 000000000..a4df0b875 --- /dev/null +++ b/rpmdb/tfalloc.c @@ -0,0 +1,30 @@ +#include "system.h" +#include +#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; +}