static char *sccsid
= "@(#)savecore.c 4.15 (Berkeley) 85/06/03";
#define DAY (60L*60L*24L)
#define eq(a,b) (!strcmp(a,b))
#define ok(number) ((number)&0x7fffffff)
#define ok(number) (number)
#define SHUTDOWNLOG "/usr/adm/shutdownlog"
struct nlist current_nl
[] = { /* namelist for currently running system */
struct nlist dump_nl
[] = { /* name list for dumped system */
{ "_dumpdev" }, /* entries MUST be the same as */
{ "_dumplo" }, /* those in current_nl[] */
char *dirname
; /* directory to save dumps in */
char *ddname
; /* name of dump device */
dev_t dumpdev
; /* dump device */
time_t dumptime
; /* time the dump was taken */
int dumplo
; /* where dump starts on dumpdev */
int dumpsize
; /* amount of memory dumped */
int dumpmag
; /* magic number in dump */
time_t now
; /* current date */
while ((argc
> 1) && (argv
[1][0] == '-')) {
fprintf(stderr
, "savecore: illegal flag -%c\n",
"usage: savecore [-v] dirname [ system ]\n");
if (argc
!= 2 && argc
!= 3) {
fprintf(stderr
, "usage: savecore [-v] dirname [ system ]\n");
if (access(dirname
, 2) < 0) {
dumpfd
= Open(ddname
, 0);
Lseek(dumpfd
, (off_t
)(dumplo
+ ok(dump_nl
[X_DUMPMAG
].n_value
)), 0);
Read(dumpfd
, (char *)&word
, sizeof word
);
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
);
dumpfd
= Open(ddname
, 1);
Lseek(dumpfd
, (off_t
)(dumplo
+ ok(dump_nl
[X_DUMPMAG
].n_value
)), 0);
Write(dumpfd
, (char *)&zero
, sizeof zero
);
strcpy(devname
, "/dev/");
if (stat(devname
, &statb
)) {
if ((statb
.st_mode
&S_IFMT
) != type
)
if (dev
== statb
.st_rdev
) {
dp
= (char *)malloc(strlen(devname
)+1);
fprintf(stderr
, "savecore: Can't find device %d,%d\n",
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");
if (current_nl
[X_DUMPLO
].n_value
== 0) {
fprintf(stderr
, "savecore: /vmunix: dumplo not in namelist\n");
if (dump_nl
[X_TIME
].n_value
== 0) {
fprintf(stderr
, "savecore: %s: time not in namelist\n",
if (dump_nl
[X_DUMPSIZE
].n_value
== 0) {
fprintf(stderr
, "savecore: %s: dumpsize 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",
if (dump_nl
[X_VERSION
].n_value
== 0) {
fprintf(stderr
, "savecore: %s: version not in namelist\n",
if (dump_nl
[X_PANICSTR
].n_value
== 0) {
fprintf(stderr
, "savecore: %s: panicstr not in namelist\n",
/* we need DUMPMAG in both images */
if (current_nl
[X_DUMPMAG
].n_value
== 0) {
fprintf(stderr
, "savecore: /vmunix: dumpmag not in namelist\n");
if (dump_nl
[X_DUMPMAG
].n_value
== 0) {
fprintf(stderr
, "savecore: %s: dumpmag not in namelist\n",
kmem
= Open("/dev/kmem", 0);
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
));
ddname
= find_dev(dumpdev
, S_IFBLK
);
if ((fp
= fdopen(kmem
, "r")) == NULL
) {
fprintf(stderr
, "savecore: Couldn't fdopen kmem\n");
fseek(fp
, (long)current_nl
[X_VERSION
].n_value
, 0);
fgets(vers
, sizeof vers
, fp
);
if ((fp
= fopen(ddname
, "r")) == NULL
) {
fseek(fp
, (off_t
)(dumplo
+ok(dump_nl
[X_VERSION
].n_value
)), 0);
fgets(core_vers
, sizeof core_vers
, fp
);
if (!eq(vers
, core_vers
) && (system
== 0))
"savecore: Warning: vmunix version mismatch:\n\t%sand\n\t%s",
fseek(fp
, (off_t
)(dumplo
+ ok(dump_nl
[X_PANICSTR
].n_value
)), 0);
fread((char *)&panicstr
, sizeof panicstr
, 1, fp
);
fseek(fp
, dumplo
+ ok(panicstr
), 0);
time_t clobber
= (time_t)0;
Lseek(dumpfd
, (off_t
)(dumplo
+ ok(dump_nl
[X_TIME
].n_value
)), 0);
Read(dumpfd
, (char *)&dumptime
, sizeof dumptime
);
printf("dump time not found\n");
printf("System went down at %s", ctime(&dumptime
));
if (dumptime
< now
- LEEWAY
|| dumptime
> now
+ LEEWAY
) {
printf("Dump time is unreasonable\n");
register char *cp
= (char *)malloc(strlen(file
) + strlen(dirname
) + 2);
(void) strcpy(cp
, dirname
);
if (stat(dirname
, &dsb
) < 0) {
ddev
= find_dev(dsb
.st_dev
, S_IFBLK
);
Lseek(dfd
, (long)(SBLOCK
* DEV_BSIZE
), 0);
Read(dfd
, (char *)&fs
, sizeof fs
);
spacefree
= fs
.fs_cstotal
.cs_nbfree
* fs
.fs_bsize
/ 1024;
if (read_number("minfree") > spacefree
) {
"savecore: Dump omitted, not enough space on device\n");
if (fs
.fs_cstotal
.cs_nbfree
* fs
.fs_frag
+ fs
.fs_cstotal
.cs_nffree
<
fs
.fs_dsize
* fs
.fs_minfree
/ 100)
"Dump performed, but free space threshold crossed\n");
if ((fp
= fopen(path(fn
), "r")) == NULL
)
if (fgets(lin
, 80, fp
) == NULL
) {
register char *cp
= buffer
;
register int ifd
, ofd
, bounds
;
bounds
= read_number("bounds");
ifd
= Open(system
?system
:"/vmunix", 0);
while((n
= Read(ifd
, cp
, BUFSIZ
)) > 0)
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);
printf("Saving %d bytes of image in vmcore.%d\n", NBPG
*dumpsize
,
n
= Read(ifd
, cp
, (dumpsize
> 32 ? 32 : dumpsize
) * NBPG
);
fp
= fopen(path("bounds"), "w");
fprintf(fp
, "%d\n", bounds
+1);
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
struct tm
*tm
, *localtime();
fp
= fopen("/usr/adm/shutdownlog", "a");
fprintf(fp
, "%02d:%02d %s %s %2d, %4d. Reboot", tm
->tm_hour
,
tm
->tm_min
, days
[tm
->tm_wday
], months
[tm
->tm_mon
],
tm
->tm_mday
, tm
->tm_year
+ 1900);
fprintf(fp
, " after panic: %s\n", panic_mesg
);
* Versions of std routines that exit on error.
if ((fd
= open(name
, rw
)) < 0) {
if ((ret
= read(fd
, buff
, size
)) < 0) {
if ((ret
= lseek(fd
, off
, flag
)) == -1L) {
if ((fd
= creat(file
, mode
)) < 0) {
if (write(fd
, buf
, size
) < size
) {