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> 66dff462c3SKris Kennaway 67dff462c3SKris Kennaway extern FILE *zopen(const char *fname, const char *mode); 688fae3551SRodney W. Grimes 69e22d0006SAndrew Gallatin #ifdef __alpha__ 70e22d0006SAndrew Gallatin #define ok(number) ALPHA_K0SEG_TO_PHYS(number) 71e22d0006SAndrew Gallatin #endif 72e22d0006SAndrew Gallatin 73e22d0006SAndrew Gallatin #ifdef __i386__ 74241ca228SPeter Wemm #define ok(number) ((number) - kernbase) 75e22d0006SAndrew Gallatin #endif 768fae3551SRodney W. Grimes 778fae3551SRodney W. Grimes struct nlist current_nl[] = { /* Namelist for currently running system. */ 7893fcd374SLuoqi Chen #define X_DUMPLO 0 798fae3551SRodney W. Grimes { "_dumplo" }, 8093fcd374SLuoqi Chen #define X_TIME 1 8190455566SPoul-Henning Kamp { "_time_second" }, 8293fcd374SLuoqi Chen #define X_DUMPSIZE 2 838fae3551SRodney W. Grimes { "_dumpsize" }, 8493fcd374SLuoqi Chen #define X_VERSION 3 858fae3551SRodney W. Grimes { "_version" }, 8693fcd374SLuoqi Chen #define X_PANICSTR 4 878fae3551SRodney W. Grimes { "_panicstr" }, 8893fcd374SLuoqi Chen #define X_DUMPMAG 5 898fae3551SRodney W. Grimes { "_dumpmag" }, 90241ca228SPeter Wemm #define X_KERNBASE 6 91241ca228SPeter Wemm { "_kernbase" }, 928fae3551SRodney W. Grimes { "" }, 938fae3551SRodney W. Grimes }; 9493fcd374SLuoqi Chen int cursyms[] = { X_DUMPLO, X_VERSION, X_DUMPMAG, -1 }; 958fae3551SRodney W. Grimes int dumpsyms[] = { X_TIME, X_DUMPSIZE, X_VERSION, X_PANICSTR, X_DUMPMAG, -1 }; 968fae3551SRodney W. Grimes 978fae3551SRodney W. Grimes struct nlist dump_nl[] = { /* Name list for dumped system. */ 9893fcd374SLuoqi Chen { "_dumplo" }, /* Entries MUST be the same as */ 9993fcd374SLuoqi Chen { "_time_second" }, /* those in current_nl[]. */ 1008fae3551SRodney W. Grimes { "_dumpsize" }, 1018fae3551SRodney W. Grimes { "_version" }, 1028fae3551SRodney W. Grimes { "_panicstr" }, 1038fae3551SRodney W. Grimes { "_dumpmag" }, 104241ca228SPeter Wemm { "_kernbase" }, 1058fae3551SRodney W. Grimes { "" }, 1068fae3551SRodney W. Grimes }; 1078fae3551SRodney W. Grimes 1088fae3551SRodney W. Grimes /* Types match kernel declarations. */ 1099b0a8ba3SPeter Wemm u_long dumpmag; /* magic number in dump */ 1109b0a8ba3SPeter Wemm 1119b0a8ba3SPeter Wemm /* Based on kernel variables, but with more convenient types. */ 112332dbf57SPaul Saab off_t dumplo; /* where dump starts on dumpdev */ 1131c08773eSPeter Wemm off_t dumpsize; /* amount of memory dumped */ 1148fae3551SRodney W. Grimes 115c74e16f9SDag-Erling Smørgrav char *kernel; /* user-specified kernel */ 1167365d61dSPeter Wemm char *savedir; /* directory to save dumps in */ 117c74e16f9SDag-Erling Smørgrav char ddname[MAXPATHLEN]; /* name of dump device */ 1188fae3551SRodney W. Grimes dev_t dumpdev; /* dump device */ 1192837fe55SPaul Saab int dumpfd; /* read/write descriptor on char dev */ 1208fae3551SRodney W. Grimes time_t now; /* current date */ 121c74e16f9SDag-Erling Smørgrav char panic_mesg[1024]; /* panic message */ 122c74e16f9SDag-Erling Smørgrav int panicstr; /* flag: dump was caused by panic */ 123c74e16f9SDag-Erling Smørgrav char vers[1024]; /* version of kernel that crashed */ 1248fae3551SRodney W. Grimes 125241ca228SPeter Wemm #ifdef __i386__ 126241ca228SPeter Wemm u_long kernbase; /* offset of kvm to core file */ 127241ca228SPeter Wemm #endif 128241ca228SPeter Wemm 1298fae3551SRodney W. Grimes int clear, compress, force, verbose; /* flags */ 130532c1901SDag-Erling Smørgrav int keep; /* keep dump on device */ 1318fae3551SRodney W. Grimes 1328fae3551SRodney W. Grimes void check_kmem __P((void)); 1338fae3551SRodney W. Grimes int check_space __P((void)); 1348fae3551SRodney W. Grimes void clear_dump __P((void)); 135c43f30e1SPoul-Henning Kamp void DumpRead __P((int fd, void *bp, int size, off_t off, int flag)); 136c43f30e1SPoul-Henning Kamp void DumpWrite __P((int fd, void *bp, int size, off_t off, int flag)); 1378fae3551SRodney W. Grimes int dump_exists __P((void)); 138c74e16f9SDag-Erling Smørgrav void find_dev __P((dev_t)); 1398fae3551SRodney W. Grimes int get_crashtime __P((void)); 140927e7941SJoerg Wunsch void get_dumpsize __P((void)); 1418fae3551SRodney W. Grimes void kmem_setup __P((void)); 1428fae3551SRodney W. Grimes void Lseek __P((int, off_t, int)); 1434be4929cSGarrett Wollman int Open __P((const char *, int rw)); 1448fae3551SRodney W. Grimes int Read __P((int, void *, int)); 1458fae3551SRodney W. Grimes void save_core __P((void)); 1468fae3551SRodney W. Grimes void usage __P((void)); 1478fae3551SRodney W. Grimes void Write __P((int, void *, int)); 1488fae3551SRodney W. Grimes 1498fae3551SRodney W. Grimes int 1508fae3551SRodney W. Grimes main(argc, argv) 1518fae3551SRodney W. Grimes int argc; 1528fae3551SRodney W. Grimes char *argv[]; 1538fae3551SRodney W. Grimes { 1548fae3551SRodney W. Grimes int ch; 1558fae3551SRodney W. Grimes 1568fae3551SRodney W. Grimes openlog("savecore", LOG_PERROR, LOG_DAEMON); 1578fae3551SRodney W. Grimes 158867dd038SDag-Erling Smørgrav while ((ch = getopt(argc, argv, "cdfkN:vz")) != -1) 1598fae3551SRodney W. Grimes switch(ch) { 1608fae3551SRodney W. Grimes case 'c': 1618fae3551SRodney W. Grimes clear = 1; 1628fae3551SRodney W. Grimes break; 1638fae3551SRodney W. Grimes case 'd': /* Not documented. */ 1648fae3551SRodney W. Grimes case 'v': 1658fae3551SRodney W. Grimes verbose = 1; 1668fae3551SRodney W. Grimes break; 1678fae3551SRodney W. Grimes case 'f': 1688fae3551SRodney W. Grimes force = 1; 1698fae3551SRodney W. Grimes break; 170532c1901SDag-Erling Smørgrav case 'k': 171532c1901SDag-Erling Smørgrav keep = 1; 172532c1901SDag-Erling Smørgrav break; 1738fae3551SRodney W. Grimes case 'N': 174b3bfc719SDavid Greenman kernel = optarg; 1758fae3551SRodney W. Grimes break; 1768fae3551SRodney W. Grimes case 'z': 1778fae3551SRodney W. Grimes compress = 1; 1788fae3551SRodney W. Grimes break; 1798fae3551SRodney W. Grimes case '?': 1808fae3551SRodney W. Grimes default: 1818fae3551SRodney W. Grimes usage(); 1828fae3551SRodney W. Grimes } 1838fae3551SRodney W. Grimes argc -= optind; 1848fae3551SRodney W. Grimes argv += optind; 1858fae3551SRodney W. Grimes 1868fae3551SRodney W. Grimes if (!clear) { 1878fae3551SRodney W. Grimes if (argc != 1 && argc != 2) 1888fae3551SRodney W. Grimes usage(); 1897365d61dSPeter Wemm savedir = argv[0]; 1908fae3551SRodney W. Grimes } 1918fae3551SRodney W. Grimes if (argc == 2) 192b3bfc719SDavid Greenman kernel = argv[1]; 1938fae3551SRodney W. Grimes 1948fae3551SRodney W. Grimes (void)time(&now); 1958fae3551SRodney W. Grimes kmem_setup(); 1968fae3551SRodney W. Grimes 1978fae3551SRodney W. Grimes if (clear) { 1988fae3551SRodney W. Grimes clear_dump(); 1998fae3551SRodney W. Grimes exit(0); 2008fae3551SRodney W. Grimes } 2018fae3551SRodney W. Grimes 2028fae3551SRodney W. Grimes if (!dump_exists() && !force) 2038fae3551SRodney W. Grimes exit(1); 2048fae3551SRodney W. Grimes 2058fae3551SRodney W. Grimes check_kmem(); 2068fae3551SRodney W. Grimes 2078fae3551SRodney W. Grimes if (panicstr) 2088fae3551SRodney W. Grimes syslog(LOG_ALERT, "reboot after panic: %s", panic_mesg); 2098fae3551SRodney W. Grimes else 2108fae3551SRodney W. Grimes syslog(LOG_ALERT, "reboot"); 2118fae3551SRodney W. Grimes 2124731e263SBill Fenner get_dumpsize(); 2134731e263SBill Fenner 2148fae3551SRodney W. Grimes if ((!get_crashtime() || !check_space()) && !force) 2158fae3551SRodney W. Grimes exit(1); 2168fae3551SRodney W. Grimes 2178fae3551SRodney W. Grimes save_core(); 2188fae3551SRodney W. Grimes 219532c1901SDag-Erling Smørgrav if (!keep) 2208fae3551SRodney W. Grimes clear_dump(); 221532c1901SDag-Erling Smørgrav 2228fae3551SRodney W. Grimes exit(0); 2238fae3551SRodney W. Grimes } 2248fae3551SRodney W. Grimes 2258fae3551SRodney W. Grimes void 2268fae3551SRodney W. Grimes kmem_setup() 2278fae3551SRodney W. Grimes { 2288fae3551SRodney W. Grimes int kmem, i; 2294be4929cSGarrett Wollman const char *dump_sys; 23093fcd374SLuoqi Chen size_t len; 231e0ab5cb5SPaul Saab long kdumplo; /* block number where dump starts on dumpdev */ 232532c1901SDag-Erling Smørgrav char *p; 2338fae3551SRodney W. Grimes 2348fae3551SRodney W. Grimes /* 2358fae3551SRodney W. Grimes * Some names we need for the currently running system, others for 2368fae3551SRodney W. Grimes * the system that was running when the dump was made. The values 2378fae3551SRodney W. Grimes * obtained from the current system are used to look for things in 2388fae3551SRodney W. Grimes * /dev/kmem that cannot be found in the dump_sys namelist, but are 2398fae3551SRodney W. Grimes * presumed to be the same (since the disk partitions are probably 2408fae3551SRodney W. Grimes * the same!) 2418fae3551SRodney W. Grimes */ 2424be4929cSGarrett Wollman if ((nlist(getbootfile(), current_nl)) == -1) 243c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: nlist: %m", getbootfile()); 2448fae3551SRodney W. Grimes for (i = 0; cursyms[i] != -1; i++) 2458fae3551SRodney W. Grimes if (current_nl[cursyms[i]].n_value == 0) { 2468fae3551SRodney W. Grimes syslog(LOG_ERR, "%s: %s not in namelist", 2474be4929cSGarrett Wollman getbootfile(), current_nl[cursyms[i]].n_name); 2488fae3551SRodney W. Grimes exit(1); 2498fae3551SRodney W. Grimes } 2508fae3551SRodney W. Grimes 2514be4929cSGarrett Wollman dump_sys = kernel ? kernel : getbootfile(); 2528fae3551SRodney W. Grimes if ((nlist(dump_sys, dump_nl)) == -1) 253c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: nlist: %m", dump_sys); 2548fae3551SRodney W. Grimes for (i = 0; dumpsyms[i] != -1; i++) 2558fae3551SRodney W. Grimes if (dump_nl[dumpsyms[i]].n_value == 0) { 2568fae3551SRodney W. Grimes syslog(LOG_ERR, "%s: %s not in namelist", 2578fae3551SRodney W. Grimes dump_sys, dump_nl[dumpsyms[i]].n_name); 2588fae3551SRodney W. Grimes exit(1); 2598fae3551SRodney W. Grimes } 2608fae3551SRodney W. Grimes 261241ca228SPeter Wemm #ifdef __i386__ 262241ca228SPeter Wemm if (dump_nl[X_KERNBASE].n_value != 0) 263241ca228SPeter Wemm kernbase = dump_nl[X_KERNBASE].n_value; 264241ca228SPeter Wemm else 265241ca228SPeter Wemm kernbase = KERNBASE; 266241ca228SPeter Wemm #endif 267241ca228SPeter Wemm 26893fcd374SLuoqi Chen len = sizeof dumpdev; 269532c1901SDag-Erling Smørgrav if (sysctlbyname("kern.dumpdev", &dumpdev, &len, NULL, 0) == -1) { 27093fcd374SLuoqi Chen syslog(LOG_ERR, "sysctl: kern.dumpdev: %m"); 27193fcd374SLuoqi Chen exit(1); 27293fcd374SLuoqi Chen } 2738fae3551SRodney W. Grimes if (dumpdev == NODEV) { 2748fae3551SRodney W. Grimes syslog(LOG_WARNING, "no core dump (no dumpdev)"); 2758fae3551SRodney W. Grimes exit(1); 2768fae3551SRodney W. Grimes } 27793fcd374SLuoqi Chen 27893fcd374SLuoqi Chen kmem = Open(_PATH_KMEM, O_RDONLY); 2798fae3551SRodney W. Grimes Lseek(kmem, (off_t)current_nl[X_DUMPLO].n_value, L_SET); 2808df53a80SPaul Saab (void)Read(kmem, &kdumplo, sizeof(kdumplo)); 281e0ab5cb5SPaul Saab dumplo = (off_t)kdumplo * DEV_BSIZE; 2828fae3551SRodney W. Grimes if (verbose) 283e0ab5cb5SPaul Saab (void)printf("dumplo = %lld (%ld * %d)\n", 284e0ab5cb5SPaul Saab (long long)dumplo, kdumplo, DEV_BSIZE); 2858fae3551SRodney W. Grimes Lseek(kmem, (off_t)current_nl[X_DUMPMAG].n_value, L_SET); 2868fae3551SRodney W. Grimes (void)Read(kmem, &dumpmag, sizeof(dumpmag)); 287c74e16f9SDag-Erling Smørgrav find_dev(dumpdev); 2888fae3551SRodney W. Grimes dumpfd = Open(ddname, O_RDWR); 289b3bfc719SDavid Greenman if (kernel) 2908fae3551SRodney W. Grimes return; 2918fae3551SRodney W. Grimes 292dff462c3SKris Kennaway Lseek(kmem, (off_t)current_nl[X_VERSION].n_value, SEEK_SET); 293532c1901SDag-Erling Smørgrav Read(kmem, vers, sizeof(vers)); 294532c1901SDag-Erling Smørgrav vers[sizeof(vers) - 1] = '\0'; 295532c1901SDag-Erling Smørgrav p = strchr(vers, '\n'); 296532c1901SDag-Erling Smørgrav if (p) 297532c1901SDag-Erling Smørgrav p[1] = '\0'; 298532c1901SDag-Erling Smørgrav 299532c1901SDag-Erling Smørgrav /* Don't fclose(fp), we use kmem later. */ 3008fae3551SRodney W. Grimes } 3018fae3551SRodney W. Grimes 3028fae3551SRodney W. Grimes void 3038fae3551SRodney W. Grimes check_kmem() 3048fae3551SRodney W. Grimes { 305c43f30e1SPoul-Henning Kamp char core_vers[1024], *p; 3068fae3551SRodney W. Grimes 307c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, core_vers, sizeof(core_vers), 308c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_VERSION].n_value)), L_SET); 309c43f30e1SPoul-Henning Kamp core_vers[sizeof(core_vers) - 1] = '\0'; 310c43f30e1SPoul-Henning Kamp p = strchr(core_vers, '\n'); 311c43f30e1SPoul-Henning Kamp if (p) 312c43f30e1SPoul-Henning Kamp p[1] = '\0'; 313b3bfc719SDavid Greenman if (strcmp(vers, core_vers) && kernel == 0) 3148fae3551SRodney W. Grimes syslog(LOG_WARNING, 315c43f30e1SPoul-Henning Kamp "warning: %s version mismatch:\n\t\"%s\"\nand\t\"%s\"\n", 3164be4929cSGarrett Wollman getbootfile(), vers, core_vers); 317c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, &panicstr, sizeof(panicstr), 3188fae3551SRodney W. Grimes (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), L_SET); 3198fae3551SRodney W. Grimes if (panicstr) { 320c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, panic_mesg, sizeof(panic_mesg), 321c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(panicstr)), L_SET); 3228fae3551SRodney W. Grimes } 3238fae3551SRodney W. Grimes } 3248fae3551SRodney W. Grimes 325c74e16f9SDag-Erling Smørgrav /* 326c74e16f9SDag-Erling Smørgrav * Clear the magic number in the dump header. 327c74e16f9SDag-Erling Smørgrav */ 3288fae3551SRodney W. Grimes void 3298fae3551SRodney W. Grimes clear_dump() 3308fae3551SRodney W. Grimes { 331c74e16f9SDag-Erling Smørgrav int newdumpmag; 3328fae3551SRodney W. Grimes 333c74e16f9SDag-Erling Smørgrav newdumpmag = 0; 334c74e16f9SDag-Erling Smørgrav DumpWrite(dumpfd, &newdumpmag, sizeof(newdumpmag), 335c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); 3362837fe55SPaul Saab close(dumpfd); 3378fae3551SRodney W. Grimes } 3388fae3551SRodney W. Grimes 339c74e16f9SDag-Erling Smørgrav /* 340c74e16f9SDag-Erling Smørgrav * Check if a dump exists by looking for a magic number in the dump 341c74e16f9SDag-Erling Smørgrav * header. 342c74e16f9SDag-Erling Smørgrav */ 3438fae3551SRodney W. Grimes int 3448fae3551SRodney W. Grimes dump_exists() 3458fae3551SRodney W. Grimes { 3468fae3551SRodney W. Grimes int newdumpmag; 3478fae3551SRodney W. Grimes 348c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, &newdumpmag, sizeof(newdumpmag), 349c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); 3508fae3551SRodney W. Grimes if (newdumpmag != dumpmag) { 3518fae3551SRodney W. Grimes if (verbose) 3528fae3551SRodney W. Grimes syslog(LOG_WARNING, "magic number mismatch (%x != %x)", 3538fae3551SRodney W. Grimes newdumpmag, dumpmag); 3548fae3551SRodney W. Grimes syslog(LOG_WARNING, "no core dump"); 3558fae3551SRodney W. Grimes return (0); 3568fae3551SRodney W. Grimes } 3578fae3551SRodney W. Grimes return (1); 3588fae3551SRodney W. Grimes } 3598fae3551SRodney W. Grimes 3608fae3551SRodney W. Grimes char buf[1024 * 1024]; 361532c1901SDag-Erling Smørgrav #define BLOCKSIZE (1<<12) 362532c1901SDag-Erling Smørgrav #define BLOCKMASK (~(BLOCKSIZE-1)) 3638fae3551SRodney W. Grimes 364c74e16f9SDag-Erling Smørgrav /* 365c74e16f9SDag-Erling Smørgrav * Save the core dump. 366c74e16f9SDag-Erling Smørgrav */ 3678fae3551SRodney W. Grimes void 3688fae3551SRodney W. Grimes save_core() 3698fae3551SRodney W. Grimes { 3708fae3551SRodney W. Grimes register FILE *fp; 371c548151fSDag-Erling Smørgrav register int bounds, ifd, nr, nw; 372532c1901SDag-Erling Smørgrav int hs, he; /* start and end of hole */ 3732837fe55SPaul Saab char path[MAXPATHLEN]; 374927e7941SJoerg Wunsch mode_t oumask; 3758fae3551SRodney W. Grimes 3768fae3551SRodney W. Grimes /* 3778fae3551SRodney W. Grimes * Get the current number and update the bounds file. Do the update 3788fae3551SRodney W. Grimes * now, because may fail later and don't want to overwrite anything. 3798fae3551SRodney W. Grimes */ 3807365d61dSPeter Wemm (void)snprintf(path, sizeof(path), "%s/bounds", savedir); 3818fae3551SRodney W. Grimes if ((fp = fopen(path, "r")) == NULL) 3828fae3551SRodney W. Grimes goto err1; 3838fae3551SRodney W. Grimes if (fgets(buf, sizeof(buf), fp) == NULL) { 3848fae3551SRodney W. Grimes if (ferror(fp)) 385c74e16f9SDag-Erling Smørgrav err1: syslog(LOG_WARNING, "%s: %m", path); 3868fae3551SRodney W. Grimes bounds = 0; 3878fae3551SRodney W. Grimes } else 3888fae3551SRodney W. Grimes bounds = atoi(buf); 3898fae3551SRodney W. Grimes if (fp != NULL) 3908fae3551SRodney W. Grimes (void)fclose(fp); 3918fae3551SRodney W. Grimes if ((fp = fopen(path, "w")) == NULL) 3928fae3551SRodney W. Grimes syslog(LOG_ERR, "%s: %m", path); 3938fae3551SRodney W. Grimes else { 3948fae3551SRodney W. Grimes (void)fprintf(fp, "%d\n", bounds + 1); 3958fae3551SRodney W. Grimes (void)fclose(fp); 3968fae3551SRodney W. Grimes } 3978fae3551SRodney W. Grimes 3988fae3551SRodney W. Grimes /* Create the core file. */ 399927e7941SJoerg Wunsch oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ 4008fae3551SRodney W. Grimes (void)snprintf(path, sizeof(path), "%s/vmcore.%d%s", 401dff462c3SKris Kennaway savedir, bounds, compress ? ".gz" : ""); 402c548151fSDag-Erling Smørgrav if (compress) 403dff462c3SKris Kennaway fp = zopen(path, "w"); 404c548151fSDag-Erling Smørgrav else 405c548151fSDag-Erling Smørgrav fp = fopen(path, "w"); 406c548151fSDag-Erling Smørgrav if (fp == NULL) { 407c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", path); 4088fae3551SRodney W. Grimes exit(1); 4098fae3551SRodney W. Grimes } 410927e7941SJoerg Wunsch (void)umask(oumask); 4118fae3551SRodney W. Grimes 4128fae3551SRodney W. Grimes /* Seek to the start of the core. */ 4132837fe55SPaul Saab Lseek(dumpfd, (off_t)dumplo, L_SET); 4148fae3551SRodney W. Grimes 4158fae3551SRodney W. Grimes /* Copy the core file. */ 4168fae3551SRodney W. Grimes syslog(LOG_NOTICE, "writing %score to %s", 4178fae3551SRodney W. Grimes compress ? "compressed " : "", path); 4188fae3551SRodney W. Grimes for (; dumpsize > 0; dumpsize -= nr) { 4198fae3551SRodney W. Grimes (void)printf("%6dK\r", dumpsize / 1024); 4208fae3551SRodney W. Grimes (void)fflush(stdout); 4212837fe55SPaul Saab nr = read(dumpfd, buf, MIN(dumpsize, sizeof(buf))); 4228fae3551SRodney W. Grimes if (nr <= 0) { 4238fae3551SRodney W. Grimes if (nr == 0) 4248fae3551SRodney W. Grimes syslog(LOG_WARNING, 4258fae3551SRodney W. Grimes "WARNING: EOF on dump device"); 4268fae3551SRodney W. Grimes else 4272837fe55SPaul Saab syslog(LOG_ERR, "%s: %m", ddname); 4288fae3551SRodney W. Grimes goto err2; 4298fae3551SRodney W. Grimes } 430dff462c3SKris Kennaway 431dff462c3SKris Kennaway if (compress) { 432dff462c3SKris Kennaway nw = fwrite(buf, 1, nr, fp); 433dff462c3SKris Kennaway } else { 434532c1901SDag-Erling Smørgrav for (nw = 0; nw < nr; nw = he) { 435532c1901SDag-Erling Smørgrav /* find a contiguous block of zeroes */ 436532c1901SDag-Erling Smørgrav for (hs = nw; hs < nr; hs += BLOCKSIZE) { 437532c1901SDag-Erling Smørgrav for (he = hs; he < nr && buf[he] == 0; ++he) 438532c1901SDag-Erling Smørgrav /* nothing */ ; 439532c1901SDag-Erling Smørgrav /* is the hole long enough to matter? */ 440532c1901SDag-Erling Smørgrav if (he >= hs + BLOCKSIZE) 441532c1901SDag-Erling Smørgrav break; 442532c1901SDag-Erling Smørgrav } 443532c1901SDag-Erling Smørgrav 444532c1901SDag-Erling Smørgrav /* back down to a block boundary */ 445532c1901SDag-Erling Smørgrav he &= BLOCKMASK; 446532c1901SDag-Erling Smørgrav 447532c1901SDag-Erling Smørgrav /* 448532c1901SDag-Erling Smørgrav * 1) Don't go beyond the end of the buffer. 449532c1901SDag-Erling Smørgrav * 2) If the end of the buffer is less than 450532c1901SDag-Erling Smørgrav * BLOCKSIZE bytes away, we're at the end 451532c1901SDag-Erling Smørgrav * of the file, so just grab what's left. 452532c1901SDag-Erling Smørgrav */ 453532c1901SDag-Erling Smørgrav if (hs + BLOCKSIZE > nr) 454532c1901SDag-Erling Smørgrav hs = he = nr; 455532c1901SDag-Erling Smørgrav 456532c1901SDag-Erling Smørgrav /* 457532c1901SDag-Erling Smørgrav * At this point, we have a partial ordering: 458532c1901SDag-Erling Smørgrav * nw <= hs <= he <= nr 459532c1901SDag-Erling Smørgrav * If hs > nw, buf[nw..hs] contains non-zero data. 460532c1901SDag-Erling Smørgrav * If he > hs, buf[hs..he] is all zeroes. 461532c1901SDag-Erling Smørgrav */ 462532c1901SDag-Erling Smørgrav if (hs > nw) 463532c1901SDag-Erling Smørgrav if (fwrite(buf + nw, hs - nw, 1, fp) != 1) 464532c1901SDag-Erling Smørgrav break; 465532c1901SDag-Erling Smørgrav if (he > hs) 466532c1901SDag-Erling Smørgrav if (fseek(fp, he - hs, SEEK_CUR) == -1) 467532c1901SDag-Erling Smørgrav break; 468532c1901SDag-Erling Smørgrav } 469dff462c3SKris Kennaway } 4708fae3551SRodney W. Grimes if (nw != nr) { 471c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", path); 4728fae3551SRodney W. Grimes err2: syslog(LOG_WARNING, 4738fae3551SRodney W. Grimes "WARNING: vmcore may be incomplete"); 4748fae3551SRodney W. Grimes (void)printf("\n"); 4758fae3551SRodney W. Grimes exit(1); 4768fae3551SRodney W. Grimes } 4778fae3551SRodney W. Grimes } 4782837fe55SPaul Saab 4798fae3551SRodney W. Grimes (void)fclose(fp); 4808fae3551SRodney W. Grimes 4818fae3551SRodney W. Grimes /* Copy the kernel. */ 4824be4929cSGarrett Wollman ifd = Open(kernel ? kernel : getbootfile(), O_RDONLY); 483b3bfc719SDavid Greenman (void)snprintf(path, sizeof(path), "%s/kernel.%d%s", 484dff462c3SKris Kennaway savedir, bounds, compress ? ".gz" : ""); 485c548151fSDag-Erling Smørgrav if (compress) 486dff462c3SKris Kennaway fp = zopen(path, "w"); 487c548151fSDag-Erling Smørgrav else 488c548151fSDag-Erling Smørgrav fp = fopen(path, "w"); 489c548151fSDag-Erling Smørgrav if (fp == NULL) { 490c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", path); 4918fae3551SRodney W. Grimes exit(1); 4928fae3551SRodney W. Grimes } 4938fae3551SRodney W. Grimes syslog(LOG_NOTICE, "writing %skernel to %s", 4948fae3551SRodney W. Grimes compress ? "compressed " : "", path); 4958fae3551SRodney W. Grimes while ((nr = read(ifd, buf, sizeof(buf))) > 0) { 4968fae3551SRodney W. Grimes nw = fwrite(buf, 1, nr, fp); 4978fae3551SRodney W. Grimes if (nw != nr) { 498c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", path); 4998fae3551SRodney W. Grimes syslog(LOG_WARNING, 500b3bfc719SDavid Greenman "WARNING: kernel may be incomplete"); 5018fae3551SRodney W. Grimes exit(1); 5028fae3551SRodney W. Grimes } 5038fae3551SRodney W. Grimes } 5048fae3551SRodney W. Grimes if (nr < 0) { 505c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "%s: %m", kernel ? kernel : getbootfile()); 5068fae3551SRodney W. Grimes syslog(LOG_WARNING, 507b3bfc719SDavid Greenman "WARNING: kernel may be incomplete"); 5088fae3551SRodney W. Grimes exit(1); 5098fae3551SRodney W. Grimes } 5108fae3551SRodney W. Grimes (void)fclose(fp); 5112837fe55SPaul Saab close(ifd); 5128fae3551SRodney W. Grimes } 5138fae3551SRodney W. Grimes 514c74e16f9SDag-Erling Smørgrav /* 515c74e16f9SDag-Erling Smørgrav * Verify that the specified device node exists and matches the 516c74e16f9SDag-Erling Smørgrav * specified device. 517c74e16f9SDag-Erling Smørgrav */ 518c74e16f9SDag-Erling Smørgrav int 519c74e16f9SDag-Erling Smørgrav verify_dev(name, dev) 520c74e16f9SDag-Erling Smørgrav char *name; 521c74e16f9SDag-Erling Smørgrav register dev_t dev; 522c74e16f9SDag-Erling Smørgrav { 523c74e16f9SDag-Erling Smørgrav struct stat sb; 524c74e16f9SDag-Erling Smørgrav 525c74e16f9SDag-Erling Smørgrav if (lstat(name, &sb) == -1) 526c74e16f9SDag-Erling Smørgrav return (-1); 527c74e16f9SDag-Erling Smørgrav if (!S_ISCHR(sb.st_mode) || sb.st_rdev != dev) 528c74e16f9SDag-Erling Smørgrav return (-1); 529c74e16f9SDag-Erling Smørgrav return (0); 530c74e16f9SDag-Erling Smørgrav } 531c74e16f9SDag-Erling Smørgrav 532c74e16f9SDag-Erling Smørgrav /* 533c74e16f9SDag-Erling Smørgrav * Find the dump device. 534c74e16f9SDag-Erling Smørgrav * 535c74e16f9SDag-Erling Smørgrav * 1) try devname(3); see if it returns something sensible 536c74e16f9SDag-Erling Smørgrav * 2) scan /dev for the desired node 537c74e16f9SDag-Erling Smørgrav * 3) as a last resort, try to create the node we need 538c74e16f9SDag-Erling Smørgrav */ 539c74e16f9SDag-Erling Smørgrav void 5404805de87SAndrey A. Chernov find_dev(dev) 5418fae3551SRodney W. Grimes register dev_t dev; 5428fae3551SRodney W. Grimes { 543c74e16f9SDag-Erling Smørgrav struct dirent *ent; 544c74e16f9SDag-Erling Smørgrav char *dn, *dnp; 545c74e16f9SDag-Erling Smørgrav DIR *d; 5468fae3551SRodney W. Grimes 547c74e16f9SDag-Erling Smørgrav strcpy(ddname, _PATH_DEV); 548c74e16f9SDag-Erling Smørgrav dnp = ddname + sizeof _PATH_DEV - 1; 549c548151fSDag-Erling Smørgrav if ((dn = devname(dev, S_IFCHR)) != NULL) { 550c74e16f9SDag-Erling Smørgrav strcpy(dnp, dn); 551c74e16f9SDag-Erling Smørgrav if (verify_dev(ddname, dev) == 0) 552c74e16f9SDag-Erling Smørgrav return; 553c548151fSDag-Erling Smørgrav } 554c74e16f9SDag-Erling Smørgrav if ((d = opendir(_PATH_DEV)) != NULL) { 555c74e16f9SDag-Erling Smørgrav while ((ent = readdir(d))) { 556c74e16f9SDag-Erling Smørgrav strcpy(dnp, ent->d_name); 557c74e16f9SDag-Erling Smørgrav if (verify_dev(ddname, dev) == 0) { 558c74e16f9SDag-Erling Smørgrav closedir(d); 559c74e16f9SDag-Erling Smørgrav return; 560c74e16f9SDag-Erling Smørgrav } 561c74e16f9SDag-Erling Smørgrav } 562c74e16f9SDag-Erling Smørgrav closedir(d); 563c74e16f9SDag-Erling Smørgrav } 564c74e16f9SDag-Erling Smørgrav strcpy(dnp, "dump"); 565c74e16f9SDag-Erling Smørgrav if (mknod(ddname, S_IFCHR|S_IRUSR|S_IWUSR, dev) == 0) 566c74e16f9SDag-Erling Smørgrav return; 567c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "can't find device %d/%#x", major(dev), minor(dev)); 5688fae3551SRodney W. Grimes exit(1); 5698fae3551SRodney W. Grimes } 5708fae3551SRodney W. Grimes 571c74e16f9SDag-Erling Smørgrav /* 572c74e16f9SDag-Erling Smørgrav * Extract the date and time of the crash from the dump header, and 573c74e16f9SDag-Erling Smørgrav * make sure it looks sane (within one week of current date and time). 574c74e16f9SDag-Erling Smørgrav */ 5758fae3551SRodney W. Grimes int 5768fae3551SRodney W. Grimes get_crashtime() 5778fae3551SRodney W. Grimes { 5788fae3551SRodney W. Grimes time_t dumptime; /* Time the dump was taken. */ 5798fae3551SRodney W. Grimes 580c43f30e1SPoul-Henning Kamp DumpRead(dumpfd, &dumptime, sizeof(dumptime), 581c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET); 5828fae3551SRodney W. Grimes if (dumptime == 0) { 5838fae3551SRodney W. Grimes if (verbose) 5848fae3551SRodney W. Grimes syslog(LOG_ERR, "dump time is zero"); 5858fae3551SRodney W. Grimes return (0); 5868fae3551SRodney W. Grimes } 5878fae3551SRodney W. Grimes (void)printf("savecore: system went down at %s", ctime(&dumptime)); 588656dcd43SGarrett Wollman #define LEEWAY (7 * 86400) 5898fae3551SRodney W. Grimes if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) { 5908fae3551SRodney W. Grimes (void)printf("dump time is unreasonable\n"); 5918fae3551SRodney W. Grimes return (0); 5928fae3551SRodney W. Grimes } 5938fae3551SRodney W. Grimes return (1); 5948fae3551SRodney W. Grimes } 5958fae3551SRodney W. Grimes 596c74e16f9SDag-Erling Smørgrav /* 597c74e16f9SDag-Erling Smørgrav * Extract the size of the dump from the dump header. 598c74e16f9SDag-Erling Smørgrav */ 599927e7941SJoerg Wunsch void 6004731e263SBill Fenner get_dumpsize() 6014731e263SBill Fenner { 6029b0a8ba3SPeter Wemm int kdumpsize; 6031c08773eSPeter Wemm 6044731e263SBill Fenner /* Read the dump size. */ 6059b0a8ba3SPeter Wemm DumpRead(dumpfd, &kdumpsize, sizeof(kdumpsize), 606c43f30e1SPoul-Henning Kamp (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET); 6079b0a8ba3SPeter Wemm dumpsize = kdumpsize * getpagesize(); 6084731e263SBill Fenner } 6094731e263SBill Fenner 610c74e16f9SDag-Erling Smørgrav /* 611c74e16f9SDag-Erling Smørgrav * Check that sufficient space is available on the disk that holds the 612c74e16f9SDag-Erling Smørgrav * save directory. 613c74e16f9SDag-Erling Smørgrav */ 6144731e263SBill Fenner int 6158fae3551SRodney W. Grimes check_space() 6168fae3551SRodney W. Grimes { 6178fae3551SRodney W. Grimes register FILE *fp; 6184be4929cSGarrett Wollman const char *tkernel; 6194731e263SBill Fenner off_t minfree, spacefree, totfree, kernelsize, needed; 6208fae3551SRodney W. Grimes struct stat st; 6218fae3551SRodney W. Grimes struct statfs fsbuf; 6228fae3551SRodney W. Grimes char buf[100], path[MAXPATHLEN]; 6238fae3551SRodney W. Grimes 6244be4929cSGarrett Wollman tkernel = kernel ? kernel : getbootfile(); 625b3bfc719SDavid Greenman if (stat(tkernel, &st) < 0) { 626b3bfc719SDavid Greenman syslog(LOG_ERR, "%s: %m", tkernel); 6278fae3551SRodney W. Grimes exit(1); 6288fae3551SRodney W. Grimes } 6298df9b2ceSJoerg Wunsch kernelsize = st.st_blocks * S_BLKSIZE; 6304731e263SBill Fenner 6317365d61dSPeter Wemm if (statfs(savedir, &fsbuf) < 0) { 6327365d61dSPeter Wemm syslog(LOG_ERR, "%s: %m", savedir); 6338fae3551SRodney W. Grimes exit(1); 6348fae3551SRodney W. Grimes } 6350bade8bdSDavid Greenman spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024; 6364731e263SBill Fenner totfree = ((off_t) fsbuf.f_bfree * fsbuf.f_bsize) / 1024; 6378fae3551SRodney W. Grimes 6387365d61dSPeter Wemm (void)snprintf(path, sizeof(path), "%s/minfree", savedir); 6398fae3551SRodney W. Grimes if ((fp = fopen(path, "r")) == NULL) 6408fae3551SRodney W. Grimes minfree = 0; 6418fae3551SRodney W. Grimes else { 6428fae3551SRodney W. Grimes if (fgets(buf, sizeof(buf), fp) == NULL) 6438fae3551SRodney W. Grimes minfree = 0; 6448fae3551SRodney W. Grimes else 6458fae3551SRodney W. Grimes minfree = atoi(buf); 6468fae3551SRodney W. Grimes (void)fclose(fp); 6478fae3551SRodney W. Grimes } 6488fae3551SRodney W. Grimes 649b3bfc719SDavid Greenman needed = (dumpsize + kernelsize) / 1024; 6504731e263SBill Fenner if (((minfree > 0) ? spacefree : totfree) - needed < minfree) { 6518fae3551SRodney W. Grimes syslog(LOG_WARNING, 6527c815b0dSDavid E. O'Brien "no dump, not enough free space on device (%lld available, need %lld)", 653e9ae1d4bSBruce Evans (long long)(minfree > 0 ? spacefree : totfree), 654e9ae1d4bSBruce Evans (long long)needed); 6558fae3551SRodney W. Grimes return (0); 6568fae3551SRodney W. Grimes } 6574731e263SBill Fenner if (spacefree - needed < 0) 6588fae3551SRodney W. Grimes syslog(LOG_WARNING, 6598fae3551SRodney W. Grimes "dump performed, but free space threshold crossed"); 6608fae3551SRodney W. Grimes return (1); 6618fae3551SRodney W. Grimes } 6628fae3551SRodney W. Grimes 6638fae3551SRodney W. Grimes int 6648fae3551SRodney W. Grimes Open(name, rw) 6654be4929cSGarrett Wollman const char *name; 6668fae3551SRodney W. Grimes int rw; 6678fae3551SRodney W. Grimes { 6688fae3551SRodney W. Grimes int fd; 6698fae3551SRodney W. Grimes 6708fae3551SRodney W. Grimes if ((fd = open(name, rw, 0)) < 0) { 6718fae3551SRodney W. Grimes syslog(LOG_ERR, "%s: %m", name); 6728fae3551SRodney W. Grimes exit(1); 6738fae3551SRodney W. Grimes } 6748fae3551SRodney W. Grimes return (fd); 6758fae3551SRodney W. Grimes } 6768fae3551SRodney W. Grimes 6778fae3551SRodney W. Grimes int 6788fae3551SRodney W. Grimes Read(fd, bp, size) 6798fae3551SRodney W. Grimes int fd, size; 6808fae3551SRodney W. Grimes void *bp; 6818fae3551SRodney W. Grimes { 6828fae3551SRodney W. Grimes int nr; 6838fae3551SRodney W. Grimes 6848fae3551SRodney W. Grimes nr = read(fd, bp, size); 6858fae3551SRodney W. Grimes if (nr != size) { 6868fae3551SRodney W. Grimes syslog(LOG_ERR, "read: %m"); 6878fae3551SRodney W. Grimes exit(1); 6888fae3551SRodney W. Grimes } 6898fae3551SRodney W. Grimes return (nr); 6908fae3551SRodney W. Grimes } 6918fae3551SRodney W. Grimes 6928fae3551SRodney W. Grimes void 6938fae3551SRodney W. Grimes Lseek(fd, off, flag) 6948fae3551SRodney W. Grimes int fd, flag; 6958fae3551SRodney W. Grimes off_t off; 6968fae3551SRodney W. Grimes { 6978fae3551SRodney W. Grimes off_t ret; 6988fae3551SRodney W. Grimes 6998fae3551SRodney W. Grimes ret = lseek(fd, off, flag); 7008fae3551SRodney W. Grimes if (ret == -1) { 7018fae3551SRodney W. Grimes syslog(LOG_ERR, "lseek: %m"); 7028fae3551SRodney W. Grimes exit(1); 7038fae3551SRodney W. Grimes } 7048fae3551SRodney W. Grimes } 7058fae3551SRodney W. Grimes 706c43f30e1SPoul-Henning Kamp /* 707c43f30e1SPoul-Henning Kamp * DumpWrite and DumpRead block io requests to the * dump device. 708c43f30e1SPoul-Henning Kamp */ 709c43f30e1SPoul-Henning Kamp #define DUMPBUFSIZE 8192 710c43f30e1SPoul-Henning Kamp void 711c43f30e1SPoul-Henning Kamp DumpWrite(fd, bp, size, off, flag) 712c43f30e1SPoul-Henning Kamp int fd, size, flag; 713c43f30e1SPoul-Henning Kamp void *bp; 714c43f30e1SPoul-Henning Kamp off_t off; 715c43f30e1SPoul-Henning Kamp { 716c43f30e1SPoul-Henning Kamp unsigned char buf[DUMPBUFSIZE], *p, *q; 717c43f30e1SPoul-Henning Kamp off_t pos; 718c43f30e1SPoul-Henning Kamp int i, j; 719c43f30e1SPoul-Henning Kamp 720c43f30e1SPoul-Henning Kamp if (flag != L_SET) { 721c43f30e1SPoul-Henning Kamp syslog(LOG_ERR, "lseek: not LSET"); 722c43f30e1SPoul-Henning Kamp exit(2); 723c43f30e1SPoul-Henning Kamp } 724c43f30e1SPoul-Henning Kamp q = bp; 725c43f30e1SPoul-Henning Kamp while (size) { 726c43f30e1SPoul-Henning Kamp pos = off & ~(DUMPBUFSIZE - 1); 727c43f30e1SPoul-Henning Kamp Lseek(fd, pos, flag); 728c43f30e1SPoul-Henning Kamp (void)Read(fd, buf, sizeof(buf)); 729c43f30e1SPoul-Henning Kamp j = off & (DUMPBUFSIZE - 1); 730c43f30e1SPoul-Henning Kamp p = buf + j; 731c43f30e1SPoul-Henning Kamp i = size; 732c43f30e1SPoul-Henning Kamp if (i > DUMPBUFSIZE - j) 733c43f30e1SPoul-Henning Kamp i = DUMPBUFSIZE - j; 734c43f30e1SPoul-Henning Kamp memcpy(p, q, i); 735c43f30e1SPoul-Henning Kamp Lseek(fd, pos, flag); 736c43f30e1SPoul-Henning Kamp (void)Write(fd, buf, sizeof(buf)); 737c43f30e1SPoul-Henning Kamp size -= i; 738c43f30e1SPoul-Henning Kamp q += i; 739c43f30e1SPoul-Henning Kamp off += i; 740c43f30e1SPoul-Henning Kamp } 741c43f30e1SPoul-Henning Kamp } 742c43f30e1SPoul-Henning Kamp 743c43f30e1SPoul-Henning Kamp void 744c43f30e1SPoul-Henning Kamp DumpRead(fd, bp, size, off, flag) 745c43f30e1SPoul-Henning Kamp int fd, size, flag; 746c43f30e1SPoul-Henning Kamp void *bp; 747c43f30e1SPoul-Henning Kamp off_t off; 748c43f30e1SPoul-Henning Kamp { 749c43f30e1SPoul-Henning Kamp unsigned char buf[DUMPBUFSIZE], *p, *q; 750c43f30e1SPoul-Henning Kamp off_t pos; 751c43f30e1SPoul-Henning Kamp int i, j; 752c43f30e1SPoul-Henning Kamp 753c43f30e1SPoul-Henning Kamp if (flag != L_SET) { 754c43f30e1SPoul-Henning Kamp syslog(LOG_ERR, "lseek: not LSET"); 755c43f30e1SPoul-Henning Kamp exit(2); 756c43f30e1SPoul-Henning Kamp } 757c43f30e1SPoul-Henning Kamp q = bp; 758c43f30e1SPoul-Henning Kamp while (size) { 759c43f30e1SPoul-Henning Kamp pos = off & ~(DUMPBUFSIZE - 1); 760c43f30e1SPoul-Henning Kamp Lseek(fd, pos, flag); 761c43f30e1SPoul-Henning Kamp (void)Read(fd, buf, sizeof(buf)); 762c43f30e1SPoul-Henning Kamp j = off & (DUMPBUFSIZE - 1); 763c43f30e1SPoul-Henning Kamp p = buf + j; 764c43f30e1SPoul-Henning Kamp i = size; 765c43f30e1SPoul-Henning Kamp if (i > DUMPBUFSIZE - j) 766c43f30e1SPoul-Henning Kamp i = DUMPBUFSIZE - j; 767c43f30e1SPoul-Henning Kamp memcpy(q, p, i); 768c43f30e1SPoul-Henning Kamp size -= i; 769c43f30e1SPoul-Henning Kamp q += i; 770c43f30e1SPoul-Henning Kamp off += i; 771c43f30e1SPoul-Henning Kamp } 772c43f30e1SPoul-Henning Kamp } 773c43f30e1SPoul-Henning Kamp 7748fae3551SRodney W. Grimes void 7758fae3551SRodney W. Grimes Write(fd, bp, size) 7768fae3551SRodney W. Grimes int fd, size; 7778fae3551SRodney W. Grimes void *bp; 7788fae3551SRodney W. Grimes { 7798fae3551SRodney W. Grimes int n; 7808fae3551SRodney W. Grimes 7818fae3551SRodney W. Grimes if ((n = write(fd, bp, size)) < size) { 782c74e16f9SDag-Erling Smørgrav syslog(LOG_ERR, "write: %m"); 7838fae3551SRodney W. Grimes exit(1); 7848fae3551SRodney W. Grimes } 7858fae3551SRodney W. Grimes } 7868fae3551SRodney W. Grimes 7878fae3551SRodney W. Grimes void 7888fae3551SRodney W. Grimes usage() 7898fae3551SRodney W. Grimes { 7904c98f36dSDag-Erling Smørgrav (void)syslog(LOG_ERR, "usage: savecore [-cfkvz] [-N system] directory"); 7918fae3551SRodney W. Grimes exit(1); 7928fae3551SRodney W. Grimes } 793