18fae3551SRodney W. Grimes /*- 28fae3551SRodney W. Grimes * Copyright (c) 1986, 1992, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 68fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 78fae3551SRodney W. Grimes * are met: 88fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 98fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 108fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 128fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 138fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 148fae3551SRodney W. Grimes * must display the following acknowledgement: 158fae3551SRodney W. Grimes * This product includes software developed by the University of 168fae3551SRodney W. Grimes * California, Berkeley and its contributors. 178fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 188fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 198fae3551SRodney W. Grimes * without specific prior written permission. 208fae3551SRodney W. Grimes * 218fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 228fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 238fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 248fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 258fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 268fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 278fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 288fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 298fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 308fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 318fae3551SRodney W. Grimes * SUCH DAMAGE. 328fae3551SRodney W. Grimes */ 338fae3551SRodney W. Grimes 348fae3551SRodney W. Grimes #ifndef lint 35f9b52c93SPhilippe Charnier static const char copyright[] = 368fae3551SRodney W. Grimes "@(#) Copyright (c) 1986, 1992, 1993\n\ 378fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 388fae3551SRodney W. Grimes #endif /* not lint */ 398fae3551SRodney W. Grimes 408fae3551SRodney W. Grimes #ifndef lint 41f9b52c93SPhilippe Charnier #if 0 428fae3551SRodney W. Grimes static char sccsid[] = "@(#)savecore.c 8.3 (Berkeley) 1/2/94"; 43f9b52c93SPhilippe Charnier #endif 44f9b52c93SPhilippe Charnier static const char rcsid[] = 457f3dea24SPeter Wemm "$FreeBSD$"; 468fae3551SRodney W. Grimes #endif /* not lint */ 478fae3551SRodney W. Grimes 488fae3551SRodney W. Grimes #include <sys/param.h> 498fae3551SRodney W. Grimes #include <sys/stat.h> 508fae3551SRodney W. Grimes #include <sys/mount.h> 518fae3551SRodney W. Grimes #include <sys/syslog.h> 5293fcd374SLuoqi Chen #include <sys/sysctl.h> 538fae3551SRodney W. Grimes 54c33d4167SRodney W. Grimes #include <vm/vm.h> 559f5cdc15SRodney W. Grimes #include <vm/vm_param.h> 5665219883SPeter Wemm #include <vm/pmap.h> 57c33d4167SRodney W. Grimes 58c74e16f9SDag-Erling Smørgrav #include <dirent.h> 598fae3551SRodney W. Grimes #include <fcntl.h> 608fae3551SRodney W. Grimes #include <nlist.h> 618fae3551SRodney W. Grimes #include <paths.h> 628fae3551SRodney W. Grimes #include <stdio.h> 638fae3551SRodney W. Grimes #include <stdlib.h> 648fae3551SRodney W. Grimes #include <string.h> 658fae3551SRodney W. Grimes #include <unistd.h> 666127186dSWolfram Schneider #include "zopen.h" 678fae3551SRodney W. Grimes 68e22d0006SAndrew Gallatin #ifdef __alpha__ 69e22d0006SAndrew Gallatin #define ok(number) ALPHA_K0SEG_TO_PHYS(number) 70e22d0006SAndrew Gallatin #endif 71e22d0006SAndrew Gallatin 72e22d0006SAndrew Gallatin #ifdef __i386__ 738fae3551SRodney W. Grimes #define ok(number) ((number) - KERNBASE) 74e22d0006SAndrew Gallatin #endif 758fae3551SRodney W. Grimes 768fae3551SRodney W. Grimes struct nlist current_nl[] = { /* Namelist for currently running system. */ 7793fcd374SLuoqi Chen #define X_DUMPLO 0 788fae3551SRodney W. Grimes { "_dumplo" }, 7993fcd374SLuoqi Chen #define X_TIME 1 8090455566SPoul-Henning Kamp { "_time_second" }, 8193fcd374SLuoqi Chen #define X_DUMPSIZE 2 828fae3551SRodney W. Grimes { "_dumpsize" }, 8393fcd374SLuoqi Chen #define X_VERSION 3 848fae3551SRodney W. Grimes { "_version" }, 8593fcd374SLuoqi Chen #define X_PANICSTR 4 868fae3551SRodney W. Grimes { "_panicstr" }, 8793fcd374SLuoqi Chen #define X_DUMPMAG 5 888fae3551SRodney W. Grimes { "_dumpmag" }, 898fae3551SRodney W. Grimes { "" }, 908fae3551SRodney W. Grimes }; 9193fcd374SLuoqi Chen int cursyms[] = { X_DUMPLO, X_VERSION, X_DUMPMAG, -1 }; 928fae3551SRodney W. Grimes int dumpsyms[] = { X_TIME, X_DUMPSIZE, X_VERSION, X_PANICSTR, X_DUMPMAG, -1 }; 938fae3551SRodney W. Grimes 948fae3551SRodney W. Grimes struct nlist dump_nl[] = { /* Name list for dumped system. */ 9593fcd374SLuoqi Chen { "_dumplo" }, /* Entries MUST be the same as */ 9693fcd374SLuoqi Chen { "_time_second" }, /* those in current_nl[]. */ 978fae3551SRodney W. Grimes { "_dumpsize" }, 988fae3551SRodney W. Grimes { "_version" }, 998fae3551SRodney W. Grimes { "_panicstr" }, 1008fae3551SRodney W. Grimes { "_dumpmag" }, 1018fae3551SRodney W. Grimes { "" }, 1028fae3551SRodney W. Grimes }; 1038fae3551SRodney W. Grimes 1048fae3551SRodney W. Grimes /* Types match kernel declarations. */ 105332dbf57SPaul Saab off_t dumplo; /* where dump starts on dumpdev */ 1068fae3551SRodney W. Grimes int dumpmag; /* magic number in dump */ 1078fae3551SRodney W. Grimes int dumpsize; /* amount of memory dumped */ 1088fae3551SRodney W. Grimes 109c74e16f9SDag-Erling Smørgrav char *kernel; /* user-specified kernel */ 1107365d61dSPeter Wemm char *savedir; /* directory to save dumps in */ 111c74e16f9SDag-Erling Smørgrav char ddname[MAXPATHLEN]; /* name of dump device */ 1128fae3551SRodney W. Grimes dev_t dumpdev; /* dump device */ 1132837fe55SPaul Saab int dumpfd; /* read/write descriptor on char dev */ 1148fae3551SRodney W. Grimes time_t now; /* current date */ 115c74e16f9SDag-Erling Smørgrav char panic_mesg[1024]; /* panic message */ 116c74e16f9SDag-Erling Smørgrav int panicstr; /* flag: dump was caused by panic */ 117c74e16f9SDag-Erling Smørgrav char vers[1024]; /* version of kernel that crashed */ 1188fae3551SRodney W. Grimes 1198fae3551SRodney W. Grimes int clear, compress, force, verbose; /* flags */ 120532c1901SDag-Erling Smørgrav int keep; /* keep dump on device */ 1218fae3551SRodney W. Grimes 1228fae3551SRodney W. Grimes void check_kmem __P((void)); 1238fae3551SRodney W. Grimes int check_space __P((void)); 1248fae3551SRodney W. Grimes void clear_dump __P((void)); 125c43f30e1SPoul-Henning Kamp void DumpRead __P((int fd, void *bp, int size, off_t off, int flag)); 126c43f30e1SPoul-Henning Kamp void DumpWrite __P((int fd, void *bp, int size, off_t off, int flag)); 1278fae3551SRodney W. Grimes int dump_exists __P((void)); 128c74e16f9SDag-Erling Smørgrav void find_dev __P((dev_t)); 1298fae3551SRodney W. Grimes int get_crashtime __P((void)); 130927e7941SJoerg Wunsch void get_dumpsize __P((void)); 1318fae3551SRodney W. Grimes void kmem_setup __P((void)); 1328fae3551SRodney W. Grimes void log __P((int, char *, ...)); 1338fae3551SRodney W. Grimes void Lseek __P((int, off_t, int)); 1344be4929cSGarrett Wollman int Open __P((const char *, int rw)); 1358fae3551SRodney W. Grimes int Read __P((int, void *, int)); 1368fae3551SRodney W. Grimes void save_core __P((void)); 1378fae3551SRodney W. Grimes void usage __P((void)); 1388fae3551SRodney W. Grimes void Write __P((int, void *, int)); 1398fae3551SRodney W. Grimes 1408fae3551SRodney W. Grimes int 1418fae3551SRodney W. Grimes main(argc, argv) 1428fae3551SRodney W. Grimes int argc; 1438fae3551SRodney W. Grimes char *argv[]; 1448fae3551SRodney W. Grimes { 1458fae3551SRodney W. Grimes int ch; 1468fae3551SRodney W. Grimes 1478fae3551SRodney W. Grimes openlog("savecore", LOG_PERROR, LOG_DAEMON); 1488fae3551SRodney W. Grimes 149532c1901SDag-Erling Smørgrav while ((ch = getopt(argc, argv, "dfkN:vz")) != -1) 1508fae3551SRodney W. Grimes switch(ch) { 1518fae3551SRodney W. Grimes case 'c': 1528fae3551SRodney W. Grimes clear = 1; 1538fae3551SRodney W. Grimes break; 1548fae3551SRodney W. Grimes case 'd': /* Not documented. */ 1558fae3551SRodney W. Grimes case 'v': 1568fae3551SRodney W. Grimes verbose = 1; 1578fae3551SRodney W. Grimes break; 1588fae3551SRodney W. Grimes case 'f': 1598fae3551SRodney W. Grimes force = 1; 1608fae3551SRodney W. Grimes break; 161532c1901SDag-Erling Smørgrav case 'k': 162532c1901SDag-Erling Smørgrav keep = 1; 163532c1901SDag-Erling Smørgrav break; 1648fae3551SRodney W. Grimes case 'N': 165b3bfc719SDavid Greenman kernel = optarg; 1668fae3551SRodney W. Grimes break; 1678fae3551SRodney W. Grimes case 'z': 1688fae3551SRodney W. Grimes compress = 1; 1698fae3551SRodney W. Grimes break; 1708fae3551SRodney W. Grimes case '?': 1718fae3551SRodney W. Grimes default: 1728fae3551SRodney W. Grimes usage(); 1738fae3551SRodney W. Grimes } 1748fae3551SRodney W. Grimes argc -= optind; 1758fae3551SRodney W. Grimes argv += optind; 1768fae3551SRodney W. Grimes 1778fae3551SRodney W. Grimes if (!clear) { 1788fae3551SRodney W. Grimes if (argc != 1 && argc != 2) 1798fae3551SRodney W. Grimes usage(); 1807365d61dSPeter Wemm savedir = argv[0]; 1818fae3551SRodney W. Grimes } 1828fae3551SRodney W. Grimes if (argc == 2) 183b3bfc719SDavid Greenman kernel = argv[1]; 1848fae3551SRodney W. Grimes 1858fae3551SRodney W. Grimes (void)time(&now); 1868fae3551SRodney W. Grimes kmem_setup(); 1878fae3551SRodney W. Grimes 1888fae3551SRodney W. Grimes if (clear) { 1898fae3551SRodney W. Grimes clear_dump(); 1908fae3551SRodney W. Grimes exit(0); 1918fae3551SRodney W. Grimes } 1928fae3551SRodney W. Grimes 1938fae3551SRodney W. Grimes if (!dump_exists() && !force) 1948fae3551SRodney W. Grimes exit(1); 1958fae3551SRodney W. Grimes 1968fae3551SRodney W. Grimes check_kmem(); 1978fae3551SRodney W. Grimes 1988fae3551SRodney W. Grimes if (panicstr) 1998fae3551SRodney W. Grimes syslog(LOG_ALERT, "reboot after panic: %s", panic_mesg); 2008fae3551SRodney W. Grimes else 2018fae3551SRodney W. Grimes syslog(LOG_ALERT, "reboot"); 2028fae3551SRodney W. Grimes 2034731e263SBill Fenner get_dumpsize(); 2044731e263SBill Fenner 2058fae3551SRodney W. Grimes if ((!get_crashtime() || !check_space()) && !force) 2068fae3551SRodney W. Grimes exit(1); 2078fae3551SRodney W. Grimes 2088fae3551SRodney W. Grimes save_core(); 2098fae3551SRodney W. Grimes 210532c1901SDag-Erling Smørgrav if (!keep) 2118fae3551SRodney W. Grimes clear_dump(); 212532c1901SDag-Erling Smørgrav 2138fae3551SRodney W. Grimes exit(0); 2148fae3551SRodney W. Grimes } 2158fae3551SRodney W. Grimes 2168fae3551SRodney W. Grimes void 2178fae3551SRodney W. Grimes kmem_setup() 2188fae3551SRodney W. Grimes { 2198fae3551SRodney W. Grimes int kmem, i; 2204be4929cSGarrett Wollman const char *dump_sys; 22193fcd374SLuoqi Chen size_t len; 222e0ab5cb5SPaul Saab long kdumplo; /* block number where dump starts on dumpdev */ 223532c1901SDag-Erling Smørgrav char *p; 2248fae3551SRodney W. Grimes 2258fae3551SRodney W. Grimes /* 2268fae3551SRodney W. Grimes * Some names we need for the currently running system, others for 2278fae3551SRodney W. Grimes * the system that was running when the dump was made. The values 2288fae3551SRodney W. Grimes * obtained from the current system are used to look for things in 2298fae3551SRodney W. Grimes * /dev/kmem that cannot be found in the dump_sys namelist, but are 2308fae3551SRodney W. Grimes * presumed to be the same (since the disk partitions are probably 2318fae3551SRodney W. Grimes * the same!) 2328fae3551SRodney W. Grimes */ 2334be4929cSGarrett Wollman if ((nlist(getbootfile(), current_nl)) == -1) 234c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: nlist: %m", getbootfile()); 2358fae3551SRodney W. Grimes for (i = 0; cursyms[i] != -1; i++) 2368fae3551SRodney W. Grimes if (current_nl[cursyms[i]].n_value == 0) { 2378fae3551SRodney W. Grimes syslog(LOG_ERR, "%s: %s not in namelist", 2384be4929cSGarrett Wollman getbootfile(), current_nl[cursyms[i]].n_name); 2398fae3551SRodney W. Grimes exit(1); 2408fae3551SRodney W. Grimes } 2418fae3551SRodney W. Grimes 2424be4929cSGarrett Wollman dump_sys = kernel ? kernel : getbootfile(); 2438fae3551SRodney W. Grimes if ((nlist(dump_sys, dump_nl)) == -1) 244c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: nlist: %m", dump_sys); 2458fae3551SRodney W. Grimes for (i = 0; dumpsyms[i] != -1; i++) 2468fae3551SRodney W. Grimes if (dump_nl[dumpsyms[i]].n_value == 0) { 2478fae3551SRodney W. Grimes syslog(LOG_ERR, "%s: %s not in namelist", 2488fae3551SRodney W. Grimes dump_sys, dump_nl[dumpsyms[i]].n_name); 2498fae3551SRodney W. Grimes exit(1); 2508fae3551SRodney W. Grimes } 2518fae3551SRodney W. Grimes 25293fcd374SLuoqi Chen len = sizeof dumpdev; 253532c1901SDag-Erling Smørgrav if (sysctlbyname("kern.dumpdev", &dumpdev, &len, NULL, 0) == -1) { 25493fcd374SLuoqi Chen syslog(LOG_ERR, "sysctl: kern.dumpdev: %m"); 25593fcd374SLuoqi Chen exit(1); 25693fcd374SLuoqi Chen } 2578fae3551SRodney W. Grimes if (dumpdev == NODEV) { 2588fae3551SRodney W. Grimes syslog(LOG_WARNING, "no core dump (no dumpdev)"); 2598fae3551SRodney W. Grimes exit(1); 2608fae3551SRodney W. Grimes } 26193fcd374SLuoqi Chen 26293fcd374SLuoqi Chen kmem = Open(_PATH_KMEM, O_RDONLY); 2638fae3551SRodney W. Grimes Lseek(kmem, (off_t)current_nl[X_DUMPLO].n_value, L_SET); 2648df53a80SPaul Saab (void)Read(kmem, &kdumplo, sizeof(kdumplo)); 265e0ab5cb5SPaul Saab dumplo = (off_t)kdumplo * DEV_BSIZE; 2668fae3551SRodney W. Grimes if (verbose) 267e0ab5cb5SPaul Saab (void)printf("dumplo = %lld (%ld * %d)\n", 268e0ab5cb5SPaul Saab (long long)dumplo, kdumplo, DEV_BSIZE); 2698fae3551SRodney W. Grimes Lseek(kmem, (off_t)current_nl[X_DUMPMAG].n_value, L_SET); 2708fae3551SRodney W. Grimes (void)Read(kmem, &dumpmag, sizeof(dumpmag)); 271c74e16f9SDag-Erling Smørgrav find_dev(dumpdev); 2728fae3551SRodney W. Grimes dumpfd = Open(ddname, O_RDWR); 273b3bfc719SDavid Greenman if (kernel) 2748fae3551SRodney W. Grimes return; 2758fae3551SRodney W. Grimes 276532c1901SDag-Erling Smørgrav lseek(kmem, (off_t)current_nl[X_VERSION].n_value, SEEK_SET); 277532c1901SDag-Erling Smørgrav Read(kmem, vers, sizeof(vers)); 278532c1901SDag-Erling Smørgrav vers[sizeof(vers) - 1] = '\0'; 279532c1901SDag-Erling Smørgrav p = strchr(vers, '\n'); 280532c1901SDag-Erling Smørgrav if (p) 281532c1901SDag-Erling Smørgrav p[1] = '\0'; 282532c1901SDag-Erling Smørgrav 283532c1901SDag-Erling Smørgrav /* Don't fclose(fp), we use kmem later. */ 2848fae3551SRodney W. Grimes } 2858fae3551SRodney W. Grimes 2868fae3551SRodney W. Grimes void 2878fae3551SRodney W. Grimes check_kmem() 2888fae3551SRodney W. Grimes { 289c43f30e1SPoul-Henning Kamp char core_vers[1024], *p; 2908fae3551SRodney W. Grimes 291c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, core_vers, sizeof(core_vers), 292c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_VERSION].n_value)), L_SET); 293c43f30e1SPoul-Henning Kamp core_vers[sizeof(core_vers) - 1] = '\0'; 294c43f30e1SPoul-Henning Kamp p = strchr(core_vers, '\n'); 295c43f30e1SPoul-Henning Kamp if (p) 296c43f30e1SPoul-Henning Kamp p[1] = '\0'; 297b3bfc719SDavid Greenman if (strcmp(vers, core_vers) && kernel == 0) 2988fae3551SRodney W. Grimes syslog(LOG_WARNING, 299c43f30e1SPoul-Henning Kamp "warning: %s version mismatch:\n\t\"%s\"\nand\t\"%s\"\n", 3004be4929cSGarrett Wollman getbootfile(), vers, core_vers); 301c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, &panicstr, sizeof(panicstr), 3028fae3551SRodney W. Grimes (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), L_SET); 3038fae3551SRodney W. Grimes if (panicstr) { 304c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, panic_mesg, sizeof(panic_mesg), 305c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(panicstr)), L_SET); 3068fae3551SRodney W. Grimes } 3078fae3551SRodney W. Grimes } 3088fae3551SRodney W. Grimes 309c74e16f9SDag-Erling Smørgrav /* 310c74e16f9SDag-Erling Smørgrav * Clear the magic number in the dump header. 311c74e16f9SDag-Erling Smørgrav */ 3128fae3551SRodney W. Grimes void 3138fae3551SRodney W. Grimes clear_dump() 3148fae3551SRodney W. Grimes { 315c74e16f9SDag-Erling Smørgrav int newdumpmag; 3168fae3551SRodney W. Grimes 317c74e16f9SDag-Erling Smørgrav newdumpmag = 0; 318c74e16f9SDag-Erling Smørgrav DumpWrite(dumpfd, &newdumpmag, sizeof(newdumpmag), 319c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); 3202837fe55SPaul Saab close(dumpfd); 3218fae3551SRodney W. Grimes } 3228fae3551SRodney W. Grimes 323c74e16f9SDag-Erling Smørgrav /* 324c74e16f9SDag-Erling Smørgrav * Check if a dump exists by looking for a magic number in the dump 325c74e16f9SDag-Erling Smørgrav * header. 326c74e16f9SDag-Erling Smørgrav */ 3278fae3551SRodney W. Grimes int 3288fae3551SRodney W. Grimes dump_exists() 3298fae3551SRodney W. Grimes { 3308fae3551SRodney W. Grimes int newdumpmag; 3318fae3551SRodney W. Grimes 332c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, &newdumpmag, sizeof(newdumpmag), 333c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); 3348fae3551SRodney W. Grimes if (newdumpmag != dumpmag) { 3358fae3551SRodney W. Grimes if (verbose) 3368fae3551SRodney W. Grimes syslog(LOG_WARNING, "magic number mismatch (%x != %x)", 3378fae3551SRodney W. Grimes newdumpmag, dumpmag); 3388fae3551SRodney W. Grimes syslog(LOG_WARNING, "no core dump"); 3398fae3551SRodney W. Grimes return (0); 3408fae3551SRodney W. Grimes } 3418fae3551SRodney W. Grimes return (1); 3428fae3551SRodney W. Grimes } 3438fae3551SRodney W. Grimes 3448fae3551SRodney W. Grimes char buf[1024 * 1024]; 345532c1901SDag-Erling Smørgrav #define BLOCKSIZE (1<<12) 346532c1901SDag-Erling Smørgrav #define BLOCKMASK (~(BLOCKSIZE-1)) 3478fae3551SRodney W. Grimes 348c74e16f9SDag-Erling Smørgrav /* 349c74e16f9SDag-Erling Smørgrav * Save the core dump. 350c74e16f9SDag-Erling Smørgrav */ 3518fae3551SRodney W. Grimes void 3528fae3551SRodney W. Grimes save_core() 3538fae3551SRodney W. Grimes { 3548fae3551SRodney W. Grimes register FILE *fp; 355c548151fSDag-Erling Smørgrav register int bounds, ifd, nr, nw; 356532c1901SDag-Erling Smørgrav int hs, he; /* start and end of hole */ 3572837fe55SPaul Saab char path[MAXPATHLEN]; 358927e7941SJoerg Wunsch mode_t oumask; 3598fae3551SRodney W. Grimes 3608fae3551SRodney W. Grimes /* 3618fae3551SRodney W. Grimes * Get the current number and update the bounds file. Do the update 3628fae3551SRodney W. Grimes * now, because may fail later and don't want to overwrite anything. 3638fae3551SRodney W. Grimes */ 3647365d61dSPeter Wemm (void)snprintf(path, sizeof(path), "%s/bounds", savedir); 3658fae3551SRodney W. Grimes if ((fp = fopen(path, "r")) == NULL) 3668fae3551SRodney W. Grimes goto err1; 3678fae3551SRodney W. Grimes if (fgets(buf, sizeof(buf), fp) == NULL) { 3688fae3551SRodney W. Grimes if (ferror(fp)) 369c74e16f9SDag-Erling Smørgrav err1: syslog(LOG_WARNING, "%s: %m", path); 3708fae3551SRodney W. Grimes bounds = 0; 3718fae3551SRodney W. Grimes } else 3728fae3551SRodney W. Grimes bounds = atoi(buf); 3738fae3551SRodney W. Grimes if (fp != NULL) 3748fae3551SRodney W. Grimes (void)fclose(fp); 3758fae3551SRodney W. Grimes if ((fp = fopen(path, "w")) == NULL) 3768fae3551SRodney W. Grimes syslog(LOG_ERR, "%s: %m", path); 3778fae3551SRodney W. Grimes else { 3788fae3551SRodney W. Grimes (void)fprintf(fp, "%d\n", bounds + 1); 3798fae3551SRodney W. Grimes (void)fclose(fp); 3808fae3551SRodney W. Grimes } 3818fae3551SRodney W. Grimes 3828fae3551SRodney W. Grimes /* Create the core file. */ 383927e7941SJoerg Wunsch oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ 3848fae3551SRodney W. Grimes (void)snprintf(path, sizeof(path), "%s/vmcore.%d%s", 3857365d61dSPeter Wemm savedir, bounds, compress ? ".Z" : ""); 386c548151fSDag-Erling Smørgrav if (compress) 387c548151fSDag-Erling Smørgrav fp = zopen(path, "w", 0); 388c548151fSDag-Erling Smørgrav else 389c548151fSDag-Erling Smørgrav fp = fopen(path, "w"); 390c548151fSDag-Erling Smørgrav if (fp == NULL) { 391c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", path); 3928fae3551SRodney W. Grimes exit(1); 3938fae3551SRodney W. Grimes } 394927e7941SJoerg Wunsch (void)umask(oumask); 3958fae3551SRodney W. Grimes 3968fae3551SRodney W. Grimes /* Seek to the start of the core. */ 3972837fe55SPaul Saab Lseek(dumpfd, (off_t)dumplo, L_SET); 3988fae3551SRodney W. Grimes 3998fae3551SRodney W. Grimes /* Copy the core file. */ 4008fae3551SRodney W. Grimes syslog(LOG_NOTICE, "writing %score to %s", 4018fae3551SRodney W. Grimes compress ? "compressed " : "", path); 4028fae3551SRodney W. Grimes for (; dumpsize > 0; dumpsize -= nr) { 4038fae3551SRodney W. Grimes (void)printf("%6dK\r", dumpsize / 1024); 4048fae3551SRodney W. Grimes (void)fflush(stdout); 4052837fe55SPaul Saab nr = read(dumpfd, buf, MIN(dumpsize, sizeof(buf))); 4068fae3551SRodney W. Grimes if (nr <= 0) { 4078fae3551SRodney W. Grimes if (nr == 0) 4088fae3551SRodney W. Grimes syslog(LOG_WARNING, 4098fae3551SRodney W. Grimes "WARNING: EOF on dump device"); 4108fae3551SRodney W. Grimes else 4112837fe55SPaul Saab syslog(LOG_ERR, "%s: %m", ddname); 4128fae3551SRodney W. Grimes goto err2; 4138fae3551SRodney W. Grimes } 414532c1901SDag-Erling Smørgrav for (nw = 0; nw < nr; nw = he) { 415532c1901SDag-Erling Smørgrav /* find a contiguous block of zeroes */ 416532c1901SDag-Erling Smørgrav for (hs = nw; hs < nr; hs += BLOCKSIZE) { 417532c1901SDag-Erling Smørgrav for (he = hs; he < nr && buf[he] == 0; ++he) 418532c1901SDag-Erling Smørgrav /* nothing */ ; 419532c1901SDag-Erling Smørgrav 420532c1901SDag-Erling Smørgrav /* is the hole long enough to matter? */ 421532c1901SDag-Erling Smørgrav if (he >= hs + BLOCKSIZE) 422532c1901SDag-Erling Smørgrav break; 423532c1901SDag-Erling Smørgrav } 424532c1901SDag-Erling Smørgrav 425532c1901SDag-Erling Smørgrav /* back down to a block boundary */ 426532c1901SDag-Erling Smørgrav he &= BLOCKMASK; 427532c1901SDag-Erling Smørgrav 428532c1901SDag-Erling Smørgrav /* 429532c1901SDag-Erling Smørgrav * 1) Don't go beyond the end of the buffer. 430532c1901SDag-Erling Smørgrav * 2) If the end of the buffer is less than 431532c1901SDag-Erling Smørgrav * BLOCKSIZE bytes away, we're at the end 432532c1901SDag-Erling Smørgrav * of the file, so just grab what's left. 433532c1901SDag-Erling Smørgrav */ 434532c1901SDag-Erling Smørgrav if (hs + BLOCKSIZE > nr) 435532c1901SDag-Erling Smørgrav hs = he = nr; 436532c1901SDag-Erling Smørgrav 437532c1901SDag-Erling Smørgrav /* 438532c1901SDag-Erling Smørgrav * At this point, we have a partial ordering: 439532c1901SDag-Erling Smørgrav * nw <= hs <= he <= nr 440532c1901SDag-Erling Smørgrav * If hs > nw, buf[nw..hs] contains non-zero data. 441532c1901SDag-Erling Smørgrav * If he > hs, buf[hs..he] is all zeroes. 442532c1901SDag-Erling Smørgrav */ 443532c1901SDag-Erling Smørgrav if (hs > nw) 444532c1901SDag-Erling Smørgrav if (fwrite(buf + nw, hs - nw, 1, fp) != 1) 445532c1901SDag-Erling Smørgrav break; 446532c1901SDag-Erling Smørgrav if (he > hs) 447532c1901SDag-Erling Smørgrav if (fseek(fp, he - hs, SEEK_CUR) == -1) 448532c1901SDag-Erling Smørgrav break; 449532c1901SDag-Erling Smørgrav } 4508fae3551SRodney W. Grimes if (nw != nr) { 451c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", path); 4528fae3551SRodney W. Grimes err2: syslog(LOG_WARNING, 4538fae3551SRodney W. Grimes "WARNING: vmcore may be incomplete"); 4548fae3551SRodney W. Grimes (void)printf("\n"); 4558fae3551SRodney W. Grimes exit(1); 4568fae3551SRodney W. Grimes } 4578fae3551SRodney W. Grimes } 4582837fe55SPaul Saab 4598fae3551SRodney W. Grimes (void)fclose(fp); 4608fae3551SRodney W. Grimes 4618fae3551SRodney W. Grimes /* Copy the kernel. */ 4624be4929cSGarrett Wollman ifd = Open(kernel ? kernel : getbootfile(), O_RDONLY); 463b3bfc719SDavid Greenman (void)snprintf(path, sizeof(path), "%s/kernel.%d%s", 4647365d61dSPeter Wemm savedir, bounds, compress ? ".Z" : ""); 465c548151fSDag-Erling Smørgrav if (compress) 466c548151fSDag-Erling Smørgrav fp = zopen(path, "w", 0); 467c548151fSDag-Erling Smørgrav else 468c548151fSDag-Erling Smørgrav fp = fopen(path, "w"); 469c548151fSDag-Erling Smørgrav if (fp == NULL) { 470c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", path); 4718fae3551SRodney W. Grimes exit(1); 4728fae3551SRodney W. Grimes } 4738fae3551SRodney W. Grimes syslog(LOG_NOTICE, "writing %skernel to %s", 4748fae3551SRodney W. Grimes compress ? "compressed " : "", path); 4758fae3551SRodney W. Grimes while ((nr = read(ifd, buf, sizeof(buf))) > 0) { 4768fae3551SRodney W. Grimes nw = fwrite(buf, 1, nr, fp); 4778fae3551SRodney W. Grimes if (nw != nr) { 478c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", path); 4798fae3551SRodney W. Grimes syslog(LOG_WARNING, 480b3bfc719SDavid Greenman "WARNING: kernel may be incomplete"); 4818fae3551SRodney W. Grimes exit(1); 4828fae3551SRodney W. Grimes } 4838fae3551SRodney W. Grimes } 4848fae3551SRodney W. Grimes if (nr < 0) { 485c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", kernel ? kernel : getbootfile()); 4868fae3551SRodney W. Grimes syslog(LOG_WARNING, 487b3bfc719SDavid Greenman "WARNING: kernel may be incomplete"); 4888fae3551SRodney W. Grimes exit(1); 4898fae3551SRodney W. Grimes } 4908fae3551SRodney W. Grimes (void)fclose(fp); 4912837fe55SPaul Saab close(ifd); 4928fae3551SRodney W. Grimes } 4938fae3551SRodney W. Grimes 494c74e16f9SDag-Erling Smørgrav /* 495c74e16f9SDag-Erling Smørgrav * Verify that the specified device node exists and matches the 496c74e16f9SDag-Erling Smørgrav * specified device. 497c74e16f9SDag-Erling Smørgrav */ 498c74e16f9SDag-Erling Smørgrav int 499c74e16f9SDag-Erling Smørgrav verify_dev(name, dev) 500c74e16f9SDag-Erling Smørgrav char *name; 501c74e16f9SDag-Erling Smørgrav register dev_t dev; 502c74e16f9SDag-Erling Smørgrav { 503c74e16f9SDag-Erling Smørgrav struct stat sb; 504c74e16f9SDag-Erling Smørgrav 505c74e16f9SDag-Erling Smørgrav if (lstat(name, &sb) == -1) 506c74e16f9SDag-Erling Smørgrav return (-1); 507c74e16f9SDag-Erling Smørgrav if (!S_ISCHR(sb.st_mode) || sb.st_rdev != dev) 508c74e16f9SDag-Erling Smørgrav return (-1); 509c74e16f9SDag-Erling Smørgrav return (0); 510c74e16f9SDag-Erling Smørgrav } 511c74e16f9SDag-Erling Smørgrav 512c74e16f9SDag-Erling Smørgrav /* 513c74e16f9SDag-Erling Smørgrav * Find the dump device. 514c74e16f9SDag-Erling Smørgrav * 515c74e16f9SDag-Erling Smørgrav * 1) try devname(3); see if it returns something sensible 516c74e16f9SDag-Erling Smørgrav * 2) scan /dev for the desired node 517c74e16f9SDag-Erling Smørgrav * 3) as a last resort, try to create the node we need 518c74e16f9SDag-Erling Smørgrav */ 519c74e16f9SDag-Erling Smørgrav void 5204805de87SAndrey A. Chernov find_dev(dev) 5218fae3551SRodney W. Grimes register dev_t dev; 5228fae3551SRodney W. Grimes { 523c74e16f9SDag-Erling Smørgrav struct dirent *ent; 524c74e16f9SDag-Erling Smørgrav char *dn, *dnp; 525c74e16f9SDag-Erling Smørgrav DIR *d; 5268fae3551SRodney W. Grimes 527c74e16f9SDag-Erling Smørgrav strcpy(ddname, _PATH_DEV); 528c74e16f9SDag-Erling Smørgrav dnp = ddname + sizeof _PATH_DEV - 1; 529c548151fSDag-Erling Smørgrav if ((dn = devname(dev, S_IFCHR)) != NULL) { 530c74e16f9SDag-Erling Smørgrav strcpy(dnp, dn); 531c74e16f9SDag-Erling Smørgrav if (verify_dev(ddname, dev) == 0) 532c74e16f9SDag-Erling Smørgrav return; 533c548151fSDag-Erling Smørgrav } 534c74e16f9SDag-Erling Smørgrav if ((d = opendir(_PATH_DEV)) != NULL) { 535c74e16f9SDag-Erling Smørgrav while ((ent = readdir(d))) { 536c74e16f9SDag-Erling Smørgrav strcpy(dnp, ent->d_name); 537c74e16f9SDag-Erling Smørgrav if (verify_dev(ddname, dev) == 0) { 538c74e16f9SDag-Erling Smørgrav closedir(d); 539c74e16f9SDag-Erling Smørgrav return; 540c74e16f9SDag-Erling Smørgrav } 541c74e16f9SDag-Erling Smørgrav } 542c74e16f9SDag-Erling Smørgrav closedir(d); 543c74e16f9SDag-Erling Smørgrav } 544c74e16f9SDag-Erling Smørgrav strcpy(dnp, "dump"); 545c74e16f9SDag-Erling Smørgrav if (mknod(ddname, S_IFCHR|S_IRUSR|S_IWUSR, dev) == 0) 546c74e16f9SDag-Erling Smørgrav return; 547c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "can't find device %d/%#x", major(dev), minor(dev)); 5488fae3551SRodney W. Grimes exit(1); 5498fae3551SRodney W. Grimes } 5508fae3551SRodney W. Grimes 551c74e16f9SDag-Erling Smørgrav /* 552c74e16f9SDag-Erling Smørgrav * Extract the date and time of the crash from the dump header, and 553c74e16f9SDag-Erling Smørgrav * make sure it looks sane (within one week of current date and time). 554c74e16f9SDag-Erling Smørgrav */ 5558fae3551SRodney W. Grimes int 5568fae3551SRodney W. Grimes get_crashtime() 5578fae3551SRodney W. Grimes { 5588fae3551SRodney W. Grimes time_t dumptime; /* Time the dump was taken. */ 5598fae3551SRodney W. Grimes 560c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, &dumptime, sizeof(dumptime), 561c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET); 5628fae3551SRodney W. Grimes if (dumptime == 0) { 5638fae3551SRodney W. Grimes if (verbose) 5648fae3551SRodney W. Grimes syslog(LOG_ERR, "dump time is zero"); 5658fae3551SRodney W. Grimes return (0); 5668fae3551SRodney W. Grimes } 5678fae3551SRodney W. Grimes (void)printf("savecore: system went down at %s", ctime(&dumptime)); 568656dcd43SGarrett Wollman #define LEEWAY (7 * 86400) 5698fae3551SRodney W. Grimes if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) { 5708fae3551SRodney W. Grimes (void)printf("dump time is unreasonable\n"); 5718fae3551SRodney W. Grimes return (0); 5728fae3551SRodney W. Grimes } 5738fae3551SRodney W. Grimes return (1); 5748fae3551SRodney W. Grimes } 5758fae3551SRodney W. Grimes 576c74e16f9SDag-Erling Smørgrav /* 577c74e16f9SDag-Erling Smørgrav * Extract the size of the dump from the dump header. 578c74e16f9SDag-Erling Smørgrav */ 579927e7941SJoerg Wunsch void 5804731e263SBill Fenner get_dumpsize() 5814731e263SBill Fenner { 5824731e263SBill Fenner /* Read the dump size. */ 583c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, &dumpsize, sizeof(dumpsize), 584c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET); 5854731e263SBill Fenner dumpsize *= getpagesize(); 5864731e263SBill Fenner } 5874731e263SBill Fenner 588c74e16f9SDag-Erling Smørgrav /* 589c74e16f9SDag-Erling Smørgrav * Check that sufficient space is available on the disk that holds the 590c74e16f9SDag-Erling Smørgrav * save directory. 591c74e16f9SDag-Erling Smørgrav */ 5924731e263SBill Fenner int 5938fae3551SRodney W. Grimes check_space() 5948fae3551SRodney W. Grimes { 5958fae3551SRodney W. Grimes register FILE *fp; 5964be4929cSGarrett Wollman const char *tkernel; 5974731e263SBill Fenner off_t minfree, spacefree, totfree, kernelsize, needed; 5988fae3551SRodney W. Grimes struct stat st; 5998fae3551SRodney W. Grimes struct statfs fsbuf; 6008fae3551SRodney W. Grimes char buf[100], path[MAXPATHLEN]; 6018fae3551SRodney W. Grimes 6024be4929cSGarrett Wollman tkernel = kernel ? kernel : getbootfile(); 603b3bfc719SDavid Greenman if (stat(tkernel, &st) < 0) { 604b3bfc719SDavid Greenman syslog(LOG_ERR, "%s: %m", tkernel); 6058fae3551SRodney W. Grimes exit(1); 6068fae3551SRodney W. Grimes } 6078df9b2ceSJoerg Wunsch kernelsize = st.st_blocks * S_BLKSIZE; 6084731e263SBill Fenner 6097365d61dSPeter Wemm if (statfs(savedir, &fsbuf) < 0) { 6107365d61dSPeter Wemm syslog(LOG_ERR, "%s: %m", savedir); 6118fae3551SRodney W. Grimes exit(1); 6128fae3551SRodney W. Grimes } 6130bade8bdSDavid Greenman spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024; 6144731e263SBill Fenner totfree = ((off_t) fsbuf.f_bfree * fsbuf.f_bsize) / 1024; 6158fae3551SRodney W. Grimes 6167365d61dSPeter Wemm (void)snprintf(path, sizeof(path), "%s/minfree", savedir); 6178fae3551SRodney W. Grimes if ((fp = fopen(path, "r")) == NULL) 6188fae3551SRodney W. Grimes minfree = 0; 6198fae3551SRodney W. Grimes else { 6208fae3551SRodney W. Grimes if (fgets(buf, sizeof(buf), fp) == NULL) 6218fae3551SRodney W. Grimes minfree = 0; 6228fae3551SRodney W. Grimes else 6238fae3551SRodney W. Grimes minfree = atoi(buf); 6248fae3551SRodney W. Grimes (void)fclose(fp); 6258fae3551SRodney W. Grimes } 6268fae3551SRodney W. Grimes 627b3bfc719SDavid Greenman needed = (dumpsize + kernelsize) / 1024; 6284731e263SBill Fenner if (((minfree > 0) ? spacefree : totfree) - needed < minfree) { 6298fae3551SRodney W. Grimes syslog(LOG_WARNING, 6307c815b0dSDavid E. O'Brien "no dump, not enough free space on device (%lld available, need %lld)", 631e9ae1d4bSBruce Evans (long long)(minfree > 0 ? spacefree : totfree), 632e9ae1d4bSBruce Evans (long long)needed); 6338fae3551SRodney W. Grimes return (0); 6348fae3551SRodney W. Grimes } 6354731e263SBill Fenner if (spacefree - needed < 0) 6368fae3551SRodney W. Grimes syslog(LOG_WARNING, 6378fae3551SRodney W. Grimes "dump performed, but free space threshold crossed"); 6388fae3551SRodney W. Grimes return (1); 6398fae3551SRodney W. Grimes } 6408fae3551SRodney W. Grimes 6418fae3551SRodney W. Grimes int 6428fae3551SRodney W. Grimes Open(name, rw) 6434be4929cSGarrett Wollman const char *name; 6448fae3551SRodney W. Grimes int rw; 6458fae3551SRodney W. Grimes { 6468fae3551SRodney W. Grimes int fd; 6478fae3551SRodney W. Grimes 6488fae3551SRodney W. Grimes if ((fd = open(name, rw, 0)) < 0) { 6498fae3551SRodney W. Grimes syslog(LOG_ERR, "%s: %m", name); 6508fae3551SRodney W. Grimes exit(1); 6518fae3551SRodney W. Grimes } 6528fae3551SRodney W. Grimes return (fd); 6538fae3551SRodney W. Grimes } 6548fae3551SRodney W. Grimes 6558fae3551SRodney W. Grimes int 6568fae3551SRodney W. Grimes Read(fd, bp, size) 6578fae3551SRodney W. Grimes int fd, size; 6588fae3551SRodney W. Grimes void *bp; 6598fae3551SRodney W. Grimes { 6608fae3551SRodney W. Grimes int nr; 6618fae3551SRodney W. Grimes 6628fae3551SRodney W. Grimes nr = read(fd, bp, size); 6638fae3551SRodney W. Grimes if (nr != size) { 6648fae3551SRodney W. Grimes syslog(LOG_ERR, "read: %m"); 6658fae3551SRodney W. Grimes exit(1); 6668fae3551SRodney W. Grimes } 6678fae3551SRodney W. Grimes return (nr); 6688fae3551SRodney W. Grimes } 6698fae3551SRodney W. Grimes 6708fae3551SRodney W. Grimes void 6718fae3551SRodney W. Grimes Lseek(fd, off, flag) 6728fae3551SRodney W. Grimes int fd, flag; 6738fae3551SRodney W. Grimes off_t off; 6748fae3551SRodney W. Grimes { 6758fae3551SRodney W. Grimes off_t ret; 6768fae3551SRodney W. Grimes 6778fae3551SRodney W. Grimes ret = lseek(fd, off, flag); 6788fae3551SRodney W. Grimes if (ret == -1) { 6798fae3551SRodney W. Grimes syslog(LOG_ERR, "lseek: %m"); 6808fae3551SRodney W. Grimes exit(1); 6818fae3551SRodney W. Grimes } 6828fae3551SRodney W. Grimes } 6838fae3551SRodney W. Grimes 684c43f30e1SPoul-Henning Kamp /* 685c43f30e1SPoul-Henning Kamp * DumpWrite and DumpRead block io requests to the * dump device. 686c43f30e1SPoul-Henning Kamp */ 687c43f30e1SPoul-Henning Kamp #define DUMPBUFSIZE 8192 688c43f30e1SPoul-Henning Kamp void 689c43f30e1SPoul-Henning Kamp DumpWrite(fd, bp, size, off, flag) 690c43f30e1SPoul-Henning Kamp int fd, size, flag; 691c43f30e1SPoul-Henning Kamp void *bp; 692c43f30e1SPoul-Henning Kamp off_t off; 693c43f30e1SPoul-Henning Kamp { 694c43f30e1SPoul-Henning Kamp unsigned char buf[DUMPBUFSIZE], *p, *q; 695c43f30e1SPoul-Henning Kamp off_t pos; 696c43f30e1SPoul-Henning Kamp int i, j; 697c43f30e1SPoul-Henning Kamp 698c43f30e1SPoul-Henning Kamp if (flag != L_SET) { 699c43f30e1SPoul-Henning Kamp syslog(LOG_ERR, "lseek: not LSET"); 700c43f30e1SPoul-Henning Kamp exit(2); 701c43f30e1SPoul-Henning Kamp } 702c43f30e1SPoul-Henning Kamp q = bp; 703c43f30e1SPoul-Henning Kamp while (size) { 704c43f30e1SPoul-Henning Kamp pos = off & ~(DUMPBUFSIZE - 1); 705c43f30e1SPoul-Henning Kamp Lseek(fd, pos, flag); 706c43f30e1SPoul-Henning Kamp (void)Read(fd, buf, sizeof(buf)); 707c43f30e1SPoul-Henning Kamp j = off & (DUMPBUFSIZE - 1); 708c43f30e1SPoul-Henning Kamp p = buf + j; 709c43f30e1SPoul-Henning Kamp i = size; 710c43f30e1SPoul-Henning Kamp if (i > DUMPBUFSIZE - j) 711c43f30e1SPoul-Henning Kamp i = DUMPBUFSIZE - j; 712c43f30e1SPoul-Henning Kamp memcpy(p, q, i); 713c43f30e1SPoul-Henning Kamp Lseek(fd, pos, flag); 714c43f30e1SPoul-Henning Kamp (void)Write(fd, buf, sizeof(buf)); 715c43f30e1SPoul-Henning Kamp size -= i; 716c43f30e1SPoul-Henning Kamp q += i; 717c43f30e1SPoul-Henning Kamp off += i; 718c43f30e1SPoul-Henning Kamp } 719c43f30e1SPoul-Henning Kamp } 720c43f30e1SPoul-Henning Kamp 721c43f30e1SPoul-Henning Kamp void 722c43f30e1SPoul-Henning Kamp DumpRead(fd, bp, size, off, flag) 723c43f30e1SPoul-Henning Kamp int fd, size, flag; 724c43f30e1SPoul-Henning Kamp void *bp; 725c43f30e1SPoul-Henning Kamp off_t off; 726c43f30e1SPoul-Henning Kamp { 727c43f30e1SPoul-Henning Kamp unsigned char buf[DUMPBUFSIZE], *p, *q; 728c43f30e1SPoul-Henning Kamp off_t pos; 729c43f30e1SPoul-Henning Kamp int i, j; 730c43f30e1SPoul-Henning Kamp 731c43f30e1SPoul-Henning Kamp if (flag != L_SET) { 732c43f30e1SPoul-Henning Kamp syslog(LOG_ERR, "lseek: not LSET"); 733c43f30e1SPoul-Henning Kamp exit(2); 734c43f30e1SPoul-Henning Kamp } 735c43f30e1SPoul-Henning Kamp q = bp; 736c43f30e1SPoul-Henning Kamp while (size) { 737c43f30e1SPoul-Henning Kamp pos = off & ~(DUMPBUFSIZE - 1); 738c43f30e1SPoul-Henning Kamp Lseek(fd, pos, flag); 739c43f30e1SPoul-Henning Kamp (void)Read(fd, buf, sizeof(buf)); 740c43f30e1SPoul-Henning Kamp j = off & (DUMPBUFSIZE - 1); 741c43f30e1SPoul-Henning Kamp p = buf + j; 742c43f30e1SPoul-Henning Kamp i = size; 743c43f30e1SPoul-Henning Kamp if (i > DUMPBUFSIZE - j) 744c43f30e1SPoul-Henning Kamp i = DUMPBUFSIZE - j; 745c43f30e1SPoul-Henning Kamp memcpy(q, p, i); 746c43f30e1SPoul-Henning Kamp size -= i; 747c43f30e1SPoul-Henning Kamp q += i; 748c43f30e1SPoul-Henning Kamp off += i; 749c43f30e1SPoul-Henning Kamp } 750c43f30e1SPoul-Henning Kamp } 751c43f30e1SPoul-Henning Kamp 7528fae3551SRodney W. Grimes void 7538fae3551SRodney W. Grimes Write(fd, bp, size) 7548fae3551SRodney W. Grimes int fd, size; 7558fae3551SRodney W. Grimes void *bp; 7568fae3551SRodney W. Grimes { 7578fae3551SRodney W. Grimes int n; 7588fae3551SRodney W. Grimes 7598fae3551SRodney W. Grimes if ((n = write(fd, bp, size)) < size) { 760c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "write: %m"); 7618fae3551SRodney W. Grimes exit(1); 7628fae3551SRodney W. Grimes } 7638fae3551SRodney W. Grimes } 7648fae3551SRodney W. Grimes 7658fae3551SRodney W. Grimes void 7668fae3551SRodney W. Grimes usage() 7678fae3551SRodney W. Grimes { 7688fae3551SRodney W. Grimes (void)syslog(LOG_ERR, "usage: savecore [-cfvz] [-N system] directory"); 7698fae3551SRodney W. Grimes exit(1); 7708fae3551SRodney W. Grimes } 771