Index: sbin/savecore/savecore.c =================================================================== --- sbin/savecore/savecore.c +++ sbin/savecore/savecore.c @@ -298,12 +298,19 @@ return (1); } +static int +compare_magic(struct kerneldumpheader *kdh, const char *magic) +{ + + return (strncmp(magic, kdh->magic, sizeof(kdh->magic))); +} + #define BLOCKSIZE (1<<12) #define BLOCKMASK (~(BLOCKSIZE-1)) static int -DoRegularFile(int fd, off_t dumpsize, char *buf, const char *device, - const char *filename, FILE *fp) +DoRegularFile(int fd, off_t dumpsize, u_int sectorsize, int sparse, char *buf, + const char *device, const char *filename, FILE *fp) { int he, hs, nr, nw, wl; off_t dmpcnt, origsize; @@ -315,8 +322,8 @@ wl = BUFFERSIZE; if (wl > dumpsize) wl = dumpsize; - nr = read(fd, buf, wl); - if (nr != wl) { + nr = read(fd, buf, roundup(wl, sectorsize)); + if (nr != (int)roundup(wl, sectorsize)) { if (nr == 0) syslog(LOG_WARNING, "WARNING: EOF on dump device"); @@ -325,7 +332,7 @@ nerr++; return (-1); } - if (compress) { + if (!sparse) { nw = fwrite(buf, 1, wl, fp); } else { for (nw = 0; nw < nr; nw = he) { @@ -448,13 +455,13 @@ static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX]; static char *buf = NULL; struct kerneldumpheader kdhf, kdhl; - off_t mediasize, dumpsize, firsthd, lasthd; + off_t mediasize, dumpextent, dumplength, firsthd, lasthd; FILE *info, *fp; mode_t oumask; int fd, fdinfo, error; int bounds, status; u_int sectorsize, xostyle; - int istextdump; + int istextdump, isgzipdump; bounds = getbounds(); mediasize = 0; @@ -509,8 +516,8 @@ (long long)lasthd, device); goto closefd; } - istextdump = 0; - if (strncmp(kdhl.magic, TEXTDUMPMAGIC, sizeof kdhl) == 0) { + isgzipdump = istextdump = 0; + if (compare_magic(&kdhl, TEXTDUMPMAGIC) == 0) { if (verbose) printf("textdump magic on last dump header on %s\n", device); @@ -524,8 +531,8 @@ if (force == 0) goto closefd; } - } else if (memcmp(kdhl.magic, KERNELDUMPMAGIC, sizeof kdhl.magic) == - 0) { + } else if (compare_magic(&kdhl, KERNELDUMPMAGIC) == 0 || + compare_magic(&kdhl, GZDUMPMAGIC) == 0) { if (dtoh32(kdhl.version) != KERNELDUMPVERSION) { syslog(LOG_ERR, "unknown version (%d) in last dump header on %s", @@ -535,6 +542,12 @@ if (force == 0) goto closefd; } + if (compare_magic(&kdhl, GZDUMPMAGIC) == 0) { + isgzipdump = 1; + if (compress && verbose) + printf("dump is already compressed\n"); + compress = 0; + } } else { if (verbose) printf("magic mismatch on last dump header on %s\n", @@ -544,12 +557,10 @@ if (force == 0) goto closefd; - if (memcmp(kdhl.magic, KERNELDUMPMAGIC_CLEARED, - sizeof kdhl.magic) == 0) { + if (compare_magic(&kdhl, KERNELDUMPMAGIC_CLEARED) == 0) { if (verbose) printf("forcing magic on %s\n", device); - memcpy(kdhl.magic, KERNELDUMPMAGIC, - sizeof kdhl.magic); + memcpy(kdhl.magic, KERNELDUMPMAGIC, sizeof kdhl.magic); } else { syslog(LOG_ERR, "unable to force dump - bad magic"); goto closefd; @@ -577,8 +588,9 @@ if (force == 0) goto closefd; } - dumpsize = dtoh64(kdhl.dumplength); - firsthd = lasthd - dumpsize - sizeof kdhf; + dumpextent = dtoh64(kdhl.dumpextent); + dumplength = dtoh64(kdhl.dumplength); + firsthd = lasthd - dumpextent - sizeof kdhf; lseek(fd, firsthd, SEEK_SET); error = read(fd, &kdhf, sizeof kdhf); if (error != sizeof kdhf) { @@ -623,7 +635,7 @@ if (verbose) printf("Checking for available free space\n"); - if (!check_space(savedir, dumpsize, bounds)) { + if (!check_space(savedir, dumplength, bounds)) { nerr++; goto closefd; } @@ -649,6 +661,9 @@ snprintf(corename, sizeof(corename), "%s.%d.gz", istextdump ? "textdump.tar" : "vmcore", bounds); fp = zopen(corename, "w"); + } else if (isgzipdump) { + snprintf(corename, sizeof(corename), "vmcore.%d.gz", bounds); + fp = fopen(corename, "w"); } else { snprintf(corename, sizeof(corename), "%s.%d", istextdump ? "textdump.tar" : "vmcore", bounds); @@ -689,15 +704,15 @@ fclose(info); syslog(LOG_NOTICE, "writing %score to %s/%s", - compress ? "compressed " : "", savedir, corename); + (compress || isgzipdump) ? "compressed " : "", savedir, corename); if (istextdump) { - if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device, + if (DoTextdumpFile(fd, dumplength, lasthd, buf, device, corename, fp) < 0) goto closeall; } else { - if (DoRegularFile(fd, dumpsize, buf, device, corename, fp) - < 0) + if (DoRegularFile(fd, dumplength, sectorsize, + !(compress || isgzipdump), buf, device, corename, fp) < 0) goto closeall; } if (verbose) @@ -714,7 +729,7 @@ syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", savedir, "info.last"); } - if (compress) { + if (compress || isgzipdump) { snprintf(linkname, sizeof(linkname), "%s.last.gz", istextdump ? "textdump.tar" : "vmcore"); } else {