Subject: bin/1778: testdb() in /usr/sbin/kvm_mkdb fails
To: None <gnats-bugs@gnats.netbsd.org>
From: Erik Fair <fair@quartz.clock.org>
List: netbsd-bugs
Date: 11/21/1995 01:14:01
>Number: 1778
>Category: bin
>Synopsis: testdb() in /usr/sbin/kvm_mkdb fails
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Nov 21 04:20:04 1995
>Last-Modified:
>Originator: Erik Fair
>Organization:
Internet Clock Watchers
>Release: NetBSD-current 11/18/95
>Environment:
Sun 3/60
NetBSD-current
System: NetBSD quartz.clock.org 1.1_ALPHA NetBSD 1.1_ALPHA (QUARTZ) #2: Mon Nov 20 16:51:57 PST 1995 fair@quartz.clock.org:/usr/src/sys/arch/sun3/compile/QUARTZ sun3
>Description:
testdb() in /usr/sbin/kvm_mkdb fails to detect a new kernel running,
and /usr/sbin/kvm_mkdb does not rebuild /var/db/kvm_netbsd.db
thus do programs which use libkvm (ps, netstat, vmstat, dmesg)
fail completely, or produce bad output.
>How-To-Repeat:
not well understood. code examination did not reveal bug.
bad database was nuked prior to testing (oops).
>Fix:
work-around: rm /var/db/kvm_netbsd.db prior to running
/usr/sbin/kvm_mkdb in /etc/rc
a suggested fix: test st_mtime from stat(2) of database and kernel;
rebuild database if kernel is found to be more recent. Diffs follow.
*** extern.h.orig Mon Nov 20 23:25:31 1995
--- extern.h Mon Nov 20 23:49:04 1995
***************
*** 36,39 ****
void create_knlist __P((char *, DB *));
void error __P((char *));
! int testdb __P(());
--- 36,40 ----
void create_knlist __P((char *, DB *));
void error __P((char *));
! int kvmdb_valid __P(());
! char *Pname;
*** kvm_mkdb.c.orig Mon Nov 20 23:24:23 1995
--- kvm_mkdb.c Mon Nov 20 23:52:27 1995
***************
*** 76,81 ****
--- 76,83 ----
int ch;
char *p, *nlistpath, *nlistname, dbtemp[MAXPATHLEN], dbname[MAXPATHLEN];
+ Pname = ((Pname = strrchr(argv[0], '/')) ? Pname + 1 : argv[0]);
+
while ((ch = getopt(argc, argv, "")) != EOF)
switch (ch) {
case '?':
***************
*** 89,95 ****
usage();
/* If the existing db file matches the currently running kernel, exit */
! if (testdb())
exit(0);
#define basename(cp) ((p = rindex((cp), '/')) != NULL ? p + 1 : (cp))
--- 91,97 ----
usage();
/* If the existing db file matches the currently running kernel, exit */
! if (kvmdb_valid())
exit(0);
#define basename(cp) ((p = rindex((cp), '/')) != NULL ? p + 1 : (cp))
*** testdb.c.orig Mon Nov 20 23:10:23 1995
--- testdb.c Tue Nov 21 00:27:52 1995
***************
*** 37,43 ****
--- 37,45 ----
#endif /* not lint */
#include <sys/param.h>
+ #include <sys/types.h>
#include <sys/file.h>
+ #include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <kvm.h>
***************
*** 49,79 ****
#include "extern.h"
/* Return true if the db file is valid, else false */
int
! testdb()
{
register DB *db;
register int cc, kd, ret, dbversionlen;
register char *cp, *uf;
DBT rec;
struct nlist nitem;
char dbname[MAXPATHLEN], dbversion[_POSIX2_LINE_MAX];
char kversion[_POSIX2_LINE_MAX];
! ret = 0;
db = NULL;
! if ((kd = open(_PATH_KMEM, O_RDONLY, 0)) < 0)
goto close;
uf = _PATH_UNIX;
if ((cp = rindex(uf, '/')) != 0)
uf = cp + 1;
(void) snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf);
if ((db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL)) == NULL)
goto close;
/* Read the version out of the database */
rec.data = VRS_KEY;
rec.size = sizeof(VRS_KEY) - 1;
--- 51,102 ----
#include "extern.h"
+ #define TRUE 1
+ #define FALSE 0
+
/* Return true if the db file is valid, else false */
int
! kvmdb_valid()
{
register DB *db;
register int cc, kd, ret, dbversionlen;
register char *cp, *uf;
DBT rec;
struct nlist nitem;
+ struct stat kernel_sb, db_sb;
char dbname[MAXPATHLEN], dbversion[_POSIX2_LINE_MAX];
char kversion[_POSIX2_LINE_MAX];
! ret = FALSE;
db = NULL;
! if ((kd = open(_PATH_KMEM, O_RDONLY, 0)) < 0) {
! fprintf(stderr, "%s: open(%s): %s\n", Pname, _PATH_KMEM, strerror(errno));
!
goto close;
+ }
+
uf = _PATH_UNIX;
+ if (stat(uf, &kernel_sb) < 0) {
+ fprintf(stderr, "%s: stat(%s): %s\n", Pname, uf, strerror(errno));
+ goto close;
+ }
+
if ((cp = rindex(uf, '/')) != 0)
uf = cp + 1;
(void) snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf);
if ((db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL)) == NULL)
goto close;
+ if (stat(dbname, &db_sb) < 0) {
+ fprintf(stderr, "%s: stat(%s): %s\n", Pname, dbname, strerror(errno));
+ goto close;
+ }
+
+ if (kernel_sb.st_mtime > db_sb.st_mtime)
+ return(FALSE);
+
/* Read the version out of the database */
rec.data = VRS_KEY;
rec.size = sizeof(VRS_KEY) - 1;
***************
*** 104,110 ****
goto close;
/* If they match, we win */
! ret = bcmp(dbversion, kversion, dbversionlen) == 0;
close: if (kd >= 0)
(void)close(kd);
--- 127,133 ----
goto close;
/* If they match, we win */
! ret = ((bcmp(dbversion, kversion, dbversionlen) == 0) ? TRUE : FALSE);
close: if (kd >= 0)
(void)close(kd);
>Audit-Trail:
>Unformatted: