Add copyright
[unix-history] / usr / src / sbin / savecore / savecore.c
index 48c68ac..99151c4 100644 (file)
@@ -1,4 +1,19 @@
-static char *sccsid = "@(#)savecore.c  4.4 (Berkeley) 81/04/28";
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif not lint
+
+#ifndef lint
+static char sccsid[] = "@(#)savecore.c 5.1 (Berkeley) %G%";
+#endif not lint
+
 /*
  * savecore
  */
 /*
  * savecore
  */
@@ -8,40 +23,58 @@ static       char *sccsid = "@(#)savecore.c  4.4 (Berkeley) 81/04/28";
 #include <sys/param.h>
 #include <sys/dir.h>
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/dir.h>
 #include <sys/stat.h>
-#include <sys/filsys.h>
-#include <time.h>
+#include <sys/time.h>
 
 #define        DAY     (60L*60L*24L)
 #define        LEEWAY  (3*DAY)
 
 #define eq(a,b) (!strcmp(a,b))
 
 #define        DAY     (60L*60L*24L)
 #define        LEEWAY  (3*DAY)
 
 #define eq(a,b) (!strcmp(a,b))
+#ifdef vax
 #define ok(number) ((number)&0x7fffffff)
 #define ok(number) ((number)&0x7fffffff)
+#else
+#define ok(number) (number)
+#endif
 
 #define SHUTDOWNLOG "/usr/adm/shutdownlog"
 
 
 #define SHUTDOWNLOG "/usr/adm/shutdownlog"
 
-struct nlist nl[] = {
+struct nlist current_nl[] = {  /* namelist for currently running system */
 #define X_DUMPDEV      0
        { "_dumpdev" },
 #define X_DUMPLO       1
        { "_dumplo" },
 #define X_TIME         2
        { "_time" },
 #define X_DUMPDEV      0
        { "_dumpdev" },
 #define X_DUMPLO       1
        { "_dumplo" },
 #define X_TIME         2
        { "_time" },
-#define X_PHYSMEM      3
-       { "_physmem" },
+#define        X_DUMPSIZE      3
+       { "_dumpsize" },
 #define X_VERSION      4
        { "_version" },
 #define X_PANICSTR     5
        { "_panicstr" },
 #define X_VERSION      4
        { "_version" },
 #define X_PANICSTR     5
        { "_panicstr" },
-       { 0 },
+#define        X_DUMPMAG       6
+       { "_dumpmag" },
+       { "" },
 };
 
 };
 
+struct nlist dump_nl[] = {     /* name list for dumped system */
+       { "_dumpdev" },         /* entries MUST be the same as */
+       { "_dumplo" },          /*      those in current_nl[]  */
+       { "_time" },
+       { "_dumpsize" },
+       { "_version" },
+       { "_panicstr" },
+       { "_dumpmag" },
+       { "" },
+};
+
+char   *system;
 char   *dirname;                       /* directory to save dumps in */
 char   *ddname;                        /* name of dump device */
 char   *find_dev();
 dev_t  dumpdev;                        /* dump device */
 time_t dumptime;                       /* time the dump was taken */
 int    dumplo;                         /* where dump starts on dumpdev */
 char   *dirname;                       /* directory to save dumps in */
 char   *ddname;                        /* name of dump device */
 char   *find_dev();
 dev_t  dumpdev;                        /* dump device */
 time_t dumptime;                       /* time the dump was taken */
 int    dumplo;                         /* where dump starts on dumpdev */
-int    physmem;                        /* amount of memory in machine */
+int    dumpsize;                       /* amount of memory dumped */
+int    dumpmag;                        /* magic number in dump */
 time_t now;                            /* current date */
 char   *path();
 unsigned malloc();
 time_t now;                            /* current date */
 char   *path();
 unsigned malloc();
@@ -50,29 +83,72 @@ char        vers[80];
 char   core_vers[80];
 char   panic_mesg[80];
 int    panicstr;
 char   core_vers[80];
 char   panic_mesg[80];
 int    panicstr;
-int    do_the_dump = 1;
 off_t  lseek();
 off_t  Lseek();
 off_t  lseek();
 off_t  Lseek();
+int    Verbose;
 
 main(argc, argv)
        char **argv;
        int argc;
 {
 
 
 main(argc, argv)
        char **argv;
        int argc;
 {
 
-       if (argc != 2) {
-               fprintf(stderr, "usage: savecore dirname\n");
+       while ((argc > 1) && (argv[1][0] == '-')) {
+               switch (argv[1][1]) {
+               case 'v':
+               case 'd':
+                       Verbose = 1;
+                       break;
+               default:
+                       fprintf(stderr, "savecore: illegal flag -%c\n",
+                               argv[1][1]);
+                       fprintf(stderr,
+                               "usage: savecore [-v] dirname [ system ]\n");
+                       exit(1);
+               }
+               argc--;
+               argv++;
+       }
+
+       if (argc != 2 && argc != 3) {
+               fprintf(stderr, "usage: savecore [-v] dirname [ system ]\n");
                exit(1);
        }
        dirname = argv[1];
                exit(1);
        }
        dirname = argv[1];
+       if (argc == 3)
+               system = argv[2];
        if (access(dirname, 2) < 0) {
                perror(dirname);
                exit(1);
        }
        if (access(dirname, 2) < 0) {
                perror(dirname);
                exit(1);
        }
-       (void) time(&now);
        read_kmem();
        read_kmem();
-       log_entry();
-       if (do_the_dump && get_crashtime() && check_space())
-               save_core();
+}
+
+int
+dump_exists()
+{
+       register int dumpfd;
+       int word;
+
+       dumpfd = Open(ddname, 0);
+       Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), 0);
+       Read(dumpfd, (char *)&word, sizeof word);
+       close(dumpfd);
+       if (Verbose && (word != dumpmag)) {
+               printf("dumplo = %d (%d bytes)\n", dumplo/512, dumplo);
+               printf("magic number mismatch: %x != %x\n", word, dumpmag);
+       }
+       return (word == dumpmag);
+}
+
+clear_dump()
+{
+       register int dumpfd;
+       int zero = 0;
+
+       dumpfd = Open(ddname, 1);
+       Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), 0);
+       Write(dumpfd, (char *)&zero, sizeof zero);
+       close(dumpfd);
 }
 
 char *
 }
 
 char *
@@ -80,18 +156,10 @@ find_dev(dev, type)
        register dev_t dev;
        register int type;
 {
        register dev_t dev;
        register int type;
 {
-       register int dfd = Open("/dev", 0);
-       struct direct dir;
        struct stat statb;
        struct stat statb;
-       static char devname[DIRSIZ + 1];
        char *dp;
 
        strcpy(devname, "/dev/");
        char *dp;
 
        strcpy(devname, "/dev/");
-       while(Read(dfd, (char *)&dir, sizeof dir) > 0) {
-               if (dir.d_ino == 0)
-                       continue;
-               strncpy(devname + 5, dir.d_name, DIRSIZ);
-               devname[DIRSIZ] = '\0';
                if (stat(devname, &statb)) {
                        perror(devname);
                        continue;
                if (stat(devname, &statb)) {
                        perror(devname);
                        continue;
@@ -99,14 +167,13 @@ find_dev(dev, type)
                if ((statb.st_mode&S_IFMT) != type)
                        continue;
                if (dev == statb.st_rdev) {
                if ((statb.st_mode&S_IFMT) != type)
                        continue;
                if (dev == statb.st_rdev) {
-                       close(dfd);
                        dp = (char *)malloc(strlen(devname)+1);
                        strcpy(dp, devname);
                        return dp;
                }
        }
                        dp = (char *)malloc(strlen(devname)+1);
                        strcpy(dp, devname);
                        return dp;
                }
        }
-       close(dfd);
-       fprintf(stderr, "Can't find device %d,%d\n", major(dev), minor(dev));
+       fprintf(stderr, "savecore: Can't find device %d,%d\n",
+               major(dev), minor(dev));
        exit(1);
        /*NOTREACHED*/
 }
        exit(1);
        /*NOTREACHED*/
 }
@@ -116,64 +183,103 @@ read_kmem()
        int kmem;
        FILE *fp;
        register char *cp;
        int kmem;
        FILE *fp;
        register char *cp;
-
-       nlist("/vmunix", nl);
-       if (nl[X_DUMPDEV].n_value == 0) {
-               fprintf(stderr, "/vmunix: dumpdev not in namelist\n");
+       char *dump_sys;
+       
+       dump_sys = system ? system : "/vmunix";
+
+       nlist("/vmunix", current_nl);
+       nlist(dump_sys, dump_nl);
+
+       /*
+        * Some names we need for the currently running system,
+        * others for the system that was running when the dump was made.
+        * The values obtained from the current system are used
+        * to look for things in /dev/kmem that cannot be found
+        * in the dump_sys namelist, but are presumed to be the same
+        * (since the disk partitions are probably the same!)
+        */
+       if (current_nl[X_DUMPDEV].n_value == 0) {
+               fprintf(stderr, "savecore: /vmunix: dumpdev not in namelist\n");
+               exit(1);
+       }
+       if (current_nl[X_DUMPLO].n_value == 0) {
+               fprintf(stderr, "savecore: /vmunix: dumplo not in namelist\n");
                exit(1);
        }
                exit(1);
        }
-       if (nl[X_DUMPLO].n_value == 0) {
-               fprintf(stderr, "/vmunix: dumplo not in namelist\n");
+       if (dump_nl[X_TIME].n_value == 0) {
+               fprintf(stderr, "savecore: %s: time not in namelist\n",
+                               dump_sys);
                exit(1);
        }
                exit(1);
        }
-       if (nl[X_TIME].n_value == 0) {
-               fprintf(stderr, "/vmunix: time not in namelist\n");
+       if (dump_nl[X_DUMPSIZE].n_value == 0) {
+               fprintf(stderr, "savecore: %s: dumpsize not in namelist\n",
+                               dump_sys);
                exit(1);
        }
                exit(1);
        }
-       if (nl[X_PHYSMEM].n_value == 0) {
-               fprintf(stderr, "/vmunix: physmem not in namelist\n");
+       /* we need VERSION in both images */
+       if (current_nl[X_VERSION].n_value == 0) {
+               fprintf(stderr, "savecore: /vmunix: version not in namelist\n",
+                               dump_sys);
                exit(1);
        }
                exit(1);
        }
-       if (nl[X_VERSION].n_value == 0) {
-               fprintf(stderr, "/vmunix: version not in namelist\n");
+       if (dump_nl[X_VERSION].n_value == 0) {
+               fprintf(stderr, "savecore: %s: version not in namelist\n",
+                               dump_sys);
                exit(1);
        }
                exit(1);
        }
-       if (nl[X_PANICSTR].n_value == 0) {
-               fprintf(stderr, "/vmunix: panicstr not in namelist\n");
+       if (dump_nl[X_PANICSTR].n_value == 0) {
+               fprintf(stderr, "savecore: %s: panicstr not in namelist\n",
+                               dump_sys);
+               exit(1);
+       }
+       /* we need DUMPMAG in both images */
+       if (current_nl[X_DUMPMAG].n_value == 0) {
+               fprintf(stderr, "savecore: /vmunix: dumpmag not in namelist\n");
+               exit(1);
+       }
+       if (dump_nl[X_DUMPMAG].n_value == 0) {
+               fprintf(stderr, "savecore: %s: dumpmag not in namelist\n",
+                               dump_sys);
                exit(1);
        }
        kmem = Open("/dev/kmem", 0);
                exit(1);
        }
        kmem = Open("/dev/kmem", 0);
-       Lseek(kmem, (long)nl[X_DUMPDEV].n_value, 0);
-       Read(kmem, (char *)&dumpdev, sizeof dumpdev);
-       Lseek(kmem, (long)nl[X_DUMPLO].n_value, 0);
-       Read(kmem, (char *)&dumplo, sizeof dumplo);
-       Lseek(kmem, (long)nl[X_PHYSMEM].n_value, 0);
-       Read(kmem, (char *)&physmem, sizeof physmem);
+       Lseek(kmem, (long)current_nl[X_DUMPDEV].n_value, 0);
+       Read(kmem, (char *)&dumpdev, sizeof (dumpdev));
+       Lseek(kmem, (long)current_nl[X_DUMPLO].n_value, 0);
+       Read(kmem, (char *)&dumplo, sizeof (dumplo));
+       Lseek(kmem, (long)current_nl[X_DUMPMAG].n_value, 0);
+       Read(kmem, (char *)&dumpmag, sizeof (dumpmag));
        dumplo *= 512L;
        ddname = find_dev(dumpdev, S_IFBLK);
        if ((fp = fdopen(kmem, "r")) == NULL) {
        dumplo *= 512L;
        ddname = find_dev(dumpdev, S_IFBLK);
        if ((fp = fdopen(kmem, "r")) == NULL) {
-               fprintf(stderr, "Couldn't fdopen kmem\n");
+               fprintf(stderr, "savecore: Couldn't fdopen kmem\n");
                exit(1);
        }
                exit(1);
        }
-       fseek(fp, (long)nl[X_VERSION].n_value, 0);
+       if (system)
+               return;
+       fseek(fp, (long)current_nl[X_VERSION].n_value, 0);
        fgets(vers, sizeof vers, fp);
        fclose(fp);
        fgets(vers, sizeof vers, fp);
        fclose(fp);
+}
+
+check_kmem()
+{
+       FILE *fp;
+       register char *cp;
+
        if ((fp = fopen(ddname, "r")) == NULL) {
                perror(ddname);
                exit(1);
        }
        if ((fp = fopen(ddname, "r")) == NULL) {
                perror(ddname);
                exit(1);
        }
-       fseek(fp, (off_t)(dumplo+ok(nl[X_VERSION].n_value)), 0);
+       fseek(fp, (off_t)(dumplo+ok(dump_nl[X_VERSION].n_value)), 0);
        fgets(core_vers, sizeof core_vers, fp);
        fclose(fp);
        fgets(core_vers, sizeof core_vers, fp);
        fclose(fp);
-       if (!eq(vers, core_vers)) {
-               fprintf(stderr, "Vmunix version mismatch:\n\t%sand\n\t%s",
-                   vers,core_vers);
-               fprintf(stderr, "; image not saved\n");
-               do_the_dump = 0;
-               return;
-       }
+       if (!eq(vers, core_vers) && (system == 0))
+               fprintf(stderr,
+                  "savecore: Warning: vmunix version mismatch:\n\t%sand\n\t%s",
+                  vers, core_vers);
        fp = fopen(ddname, "r");
        fp = fopen(ddname, "r");
-       fseek(fp, (off_t)(dumplo + ok(nl[X_PANICSTR].n_value)), 0);
+       fseek(fp, (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), 0);
        fread((char *)&panicstr, sizeof panicstr, 1, fp);
        if (panicstr) {
                fseek(fp, dumplo + ok(panicstr), 0);
        fread((char *)&panicstr, sizeof panicstr, 1, fp);
        if (panicstr) {
                fseek(fp, dumplo + ok(panicstr), 0);
@@ -183,27 +289,27 @@ read_kmem()
                while (*cp++);
        }
        fclose(fp);
                while (*cp++);
        }
        fclose(fp);
-}      
+}
 
 get_crashtime()
 {
        int dumpfd;
        time_t clobber = (time_t)0;
 
 
 get_crashtime()
 {
        int dumpfd;
        time_t clobber = (time_t)0;
 
-       dumpfd = Open(ddname, 2);
-       Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_TIME].n_value)), 0);
+       Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), 0);
        Read(dumpfd, (char *)&dumptime, sizeof dumptime);
        Read(dumpfd, (char *)&dumptime, sizeof dumptime);
-       Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_TIME].n_value)), 0);
-       Write(dumpfd, (char *)&clobber, sizeof clobber);
        close(dumpfd);
        close(dumpfd);
-       if (dumptime == 0)
-               return 0;
+       if (dumptime == 0) {
+               if (Verbose)
+                       printf("dump time not found\n");
+               return (0);
+       }
        printf("System went down at %s", ctime(&dumptime));
        if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) {
                printf("Dump time is unreasonable\n");
        printf("System went down at %s", ctime(&dumptime));
        if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) {
                printf("Dump time is unreasonable\n");
-               return 0;
+               return (0);
        }
        }
-       return 1;
+       return (1);
 }
 
 char *
 }
 
 char *
@@ -215,15 +321,15 @@ path(file)
        (void) strcpy(cp, dirname);
        (void) strcat(cp, "/");
        (void) strcat(cp, file);
        (void) strcpy(cp, dirname);
        (void) strcat(cp, "/");
        (void) strcat(cp, file);
-       return cp;
+       return (cp);
 }
 
 check_space()
 {
        struct stat dsb;
        register char *ddev;
 }
 
 check_space()
 {
        struct stat dsb;
        register char *ddev;
-       register int dfd;
-       struct filsys sblk;
+       int dfd, spacefree;
+       struct fs fs;
 
        if (stat(dirname, &dsb) < 0) {
                perror(dirname);
 
        if (stat(dirname, &dsb) < 0) {
                perror(dirname);
@@ -231,13 +337,19 @@ check_space()
        }
        ddev = find_dev(dsb.st_dev, S_IFBLK);
        dfd = Open(ddev, 0);
        }
        ddev = find_dev(dsb.st_dev, S_IFBLK);
        dfd = Open(ddev, 0);
-       Lseek(dfd, 1L<<BSHIFT, 0);
-       Read(dfd, (char *)&sblk, sizeof sblk);
+       Lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0);
+       Read(dfd, (char *)&fs, sizeof fs);
        close(dfd);
        close(dfd);
-       if (read_number("minfree") > sblk.s_tfree) {
-               fprintf(stderr, "Dump omitted, not enough space on device\n");
+       spacefree = fs.fs_cstotal.cs_nbfree * fs.fs_bsize / 1024;
+       if (read_number("minfree") > spacefree) {
+               fprintf(stderr,
+                  "savecore: Dump omitted, not enough space on device\n");
                return (0);
        }
                return (0);
        }
+       if (fs.fs_cstotal.cs_nbfree * fs.fs_frag + fs.fs_cstotal.cs_nffree <
+           fs.fs_dsize * fs.fs_minfree / 100)
+               fprintf(stderr,
+                       "Dump performed, but free space threshold crossed\n");
        return (1);
 }
 
        return (1);
 }
 
@@ -248,13 +360,13 @@ read_number(fn)
        register FILE *fp;
 
        if ((fp = fopen(path(fn), "r")) == NULL)
        register FILE *fp;
 
        if ((fp = fopen(path(fn), "r")) == NULL)
-               return 0;
+               return (0);
        if (fgets(lin, 80, fp) == NULL) {
                fclose(fp);
        if (fgets(lin, 80, fp) == NULL) {
                fclose(fp);
-               return 0;
+               return (0);
        }
        fclose(fp);
        }
        fclose(fp);
-       return atoi(lin);
+       return (atoi(lin));
 }
 
 save_core()
 }
 
 save_core()
@@ -266,20 +378,23 @@ save_core()
        register FILE *fp;
 
        bounds = read_number("bounds");
        register FILE *fp;
 
        bounds = read_number("bounds");
-       ifd = Open("/vmunix", 0);
-       ofd = Create(path(sprintf(cp, "vmunix.%d", bounds)), 0666);
+       ifd = Open(system?system:"/vmunix", 0);
        while((n = Read(ifd, cp, BUFSIZ)) > 0)
                Write(ofd, cp, n);
        close(ifd);
        close(ofd);
        ifd = Open(ddname, 0);
        while((n = Read(ifd, cp, BUFSIZ)) > 0)
                Write(ofd, cp, n);
        close(ifd);
        close(ofd);
        ifd = Open(ddname, 0);
-       ofd = Create(path(sprintf(cp, "vmcore.%d", bounds)), 0666);
+       Lseek(ifd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), 0);
+       Read(ifd, (char *)&dumpsize, sizeof (dumpsize));
+       sprintf(cp, "vmcore.%d", bounds);
+       ofd = Create(path(cp), 0644);
        Lseek(ifd, (off_t)dumplo, 0);
        Lseek(ifd, (off_t)dumplo, 0);
-       printf("Saving %d bytes of image in vmcore.%d\n", NBPG*physmem, bounds);
-       while(physmem > 0) {
-               n = Read(ifd, cp, (physmem > 32 ? 32 : physmem) * NBPG);
+       printf("Saving %d bytes of image in vmcore.%d\n", NBPG*dumpsize,
+               bounds);
+       while (dumpsize > 0) {
+               n = Read(ifd, cp, (dumpsize > 32 ? 32 : dumpsize) * NBPG);
                Write(ofd, cp, n);
                Write(ofd, cp, n);
-               physmem -= n/NBPG;
+               dumpsize -= n/NBPG;
        }
        close(ifd);
        close(ofd);
        }
        close(ifd);
        close(ofd);
@@ -377,7 +492,6 @@ Create(file, mode)
 Write(fd, buf, size)
        int fd, size;
        char *buf;
 Write(fd, buf, size)
        int fd, size;
        char *buf;
-
 {
 
        if (write(fd, buf, size) < size) {
 {
 
        if (write(fd, buf, size) < size) {