Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144452926
D27245.id79630.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D27245.id79630.diff
View Options
Index: sbin/savecore/savecore.8
===================================================================
--- sbin/savecore/savecore.8
+++ sbin/savecore/savecore.8
@@ -28,7 +28,7 @@
.\" From: @(#)savecore.8 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd March 17, 2018
+.Dd November 17, 2020
.Dt SAVECORE 8
.Os
.Sh NAME
@@ -45,7 +45,7 @@
.Op Ar device ...
.Nm
.Op Fl -libxo
-.Op Fl fkvz
+.Op Fl fkuvz
.Op Fl m Ar maxdumps
.Op Ar directory Op Ar device ...
.Sh DESCRIPTION
@@ -92,6 +92,8 @@
.Ar maxdumps
the counter will restart from
.Dv 0 .
+.It Fl u
+Uncompress the dump in case it was compressed by the kernel.
.It Fl v
Print out some additional debugging information.
Specify twice for more information.
Index: sbin/savecore/savecore.c
===================================================================
--- sbin/savecore/savecore.c
+++ sbin/savecore/savecore.c
@@ -86,6 +86,8 @@
#include <syslog.h>
#include <time.h>
#include <unistd.h>
+#define Z_SOLO
+#include <zlib.h>
#include <libcasper.h>
#include <casper/cap_fileargs.h>
@@ -102,7 +104,7 @@
static cap_channel_t *capsyslog;
static fileargs_t *capfa;
-static bool checkfor, compress, clear, force, keep; /* flags */
+static bool checkfor, compress, uncompress, clear, force, keep; /* flags */
static int verbose;
static int nfound, nsaved, nerr; /* statistics */
static int maxdumps;
@@ -441,22 +443,83 @@
#define BLOCKSIZE (1<<12)
#define BLOCKMASK (~(BLOCKSIZE-1))
+static size_t
+sparsefwrite(const char *buf, size_t nr, FILE *fp)
+{
+ size_t nw, he, hs;
+
+ for (nw = 0; nw < nr; nw = he) {
+ /* find a contiguous block of zeroes */
+ for (hs = nw; hs < nr; hs += BLOCKSIZE) {
+ for (he = hs; he < nr && buf[he] == 0; ++he)
+ /* nothing */ ;
+ /* is the hole long enough to matter? */
+ if (he >= hs + BLOCKSIZE)
+ break;
+ }
+
+ /* back down to a block boundary */
+ he &= BLOCKMASK;
+
+ /*
+ * 1) Don't go beyond the end of the buffer.
+ * 2) If the end of the buffer is less than
+ * BLOCKSIZE bytes away, we're at the end
+ * of the file, so just grab what's left.
+ */
+ if (hs + BLOCKSIZE > nr)
+ hs = he = nr;
+
+ /*
+ * At this point, we have a partial ordering:
+ * nw <= hs <= he <= nr
+ * If hs > nw, buf[nw..hs] contains non-zero
+ * data. If he > hs, buf[hs..he] is all zeroes.
+ */
+ if (hs > nw)
+ if (fwrite(buf + nw, hs - nw, 1, fp) != 1)
+ break;
+ if (he > hs)
+ if (fseeko(fp, he - hs, SEEK_CUR) == -1)
+ break;
+ }
+
+ return (nw);
+}
+
static int
DoRegularFile(int fd, off_t dumpsize, u_int sectorsize, bool sparse, char *buf,
const char *device, const char *filename, FILE *fp)
{
- int he, hs, nr, nw, wl;
+ z_stream z;
+ char *zbuf;
+ size_t nr, nw, wl;
off_t dmpcnt, origsize;
+ int zerr;
+ bool firstblock;
dmpcnt = 0;
origsize = dumpsize;
- he = 0;
+ if (uncompress) {
+ memset(&z, 0, sizeof z);
+ z.zalloc = Z_NULL;
+ z.zfree = Z_NULL;
+ if (inflateInit2(&z, -MAX_WBITS) != Z_OK) {
+ logmsg(LOG_ERR, "failed to initialize zlib: %s", z.msg);
+ return (-1);
+ }
+ if ((zbuf = malloc(BUFFERSIZE)) == NULL) {
+ logmsg(LOG_ERR, "%m");
+ return (-1);
+ }
+ firstblock = true;
+ }
while (dumpsize > 0) {
wl = BUFFERSIZE;
- if (wl > dumpsize)
+ if (wl > (size_t)dumpsize)
wl = dumpsize;
nr = read(fd, buf, roundup(wl, sectorsize));
- if (nr != (int)roundup(wl, sectorsize)) {
+ if (nr != roundup(wl, sectorsize)) {
if (nr == 0)
logmsg(LOG_WARNING,
"WARNING: EOF on dump device");
@@ -465,48 +528,40 @@
nerr++;
return (-1);
}
- if (!sparse) {
- nw = fwrite(buf, 1, wl, fp);
- } else {
- for (nw = 0; nw < nr; nw = he) {
- /* find a contiguous block of zeroes */
- for (hs = nw; hs < nr; hs += BLOCKSIZE) {
- for (he = hs; he < nr && buf[he] == 0;
- ++he)
- /* nothing */ ;
- /* is the hole long enough to matter? */
- if (he >= hs + BLOCKSIZE)
- break;
- }
+ if (uncompress) {
+ const size_t hdrlen = 10;
- /* back down to a block boundary */
- he &= BLOCKMASK;
-
- /*
- * 1) Don't go beyond the end of the buffer.
- * 2) If the end of the buffer is less than
- * BLOCKSIZE bytes away, we're at the end
- * of the file, so just grab what's left.
- */
- if (hs + BLOCKSIZE > nr)
- hs = he = nr;
-
- /*
- * At this point, we have a partial ordering:
- * nw <= hs <= he <= nr
- * If hs > nw, buf[nw..hs] contains non-zero
- * data. If he > hs, buf[hs..he] is all zeroes.
- */
- if (hs > nw)
- if (fwrite(buf + nw, hs - nw, 1, fp)
- != 1)
- break;
- if (he > hs)
- if (fseeko(fp, he - hs, SEEK_CUR) == -1)
- break;
+ z.next_in = buf;
+ z.avail_in = nr;
+ nw = 0;
+ /*
+ * Since contrib/zlib for some reason is compiled
+ * without GUNZIP define, we need to skip the gzip
+ * header manually. Kernel puts minimal 10 byte
+ * header, see sys/kern/subr_compressor.c:gz_reset().
+ */
+ if (firstblock) {
+ z.next_in += hdrlen;
+ z.avail_in -= hdrlen;
+ firstblock = false;
}
- }
- if (nw != wl) {
+ do {
+ z.next_out = zbuf;
+ z.avail_out = BUFFERSIZE;
+ zerr = inflate(&z, Z_NO_FLUSH);
+ if (zerr != Z_OK && zerr != Z_STREAM_END) {
+ logmsg(LOG_ERR,
+ "decompression failed: %s", z.msg);
+ return (-1);
+ }
+ nw += sparsefwrite(zbuf,
+ BUFFERSIZE - z.avail_out, fp);
+ } while (z.avail_in > 0 && zerr != Z_STREAM_END);
+ } else if (!sparse) {
+ nw = fwrite(buf, 1, wl, fp);
+ } else
+ nw = sparsefwrite(buf, wl, fp);
+ if (!uncompress && nw != wl) {
logmsg(LOG_ERR,
"write error on %s file: %m", filename);
logmsg(LOG_WARNING,
@@ -694,11 +749,21 @@
case KERNELDUMP_COMP_NONE:
break;
case KERNELDUMP_COMP_GZIP:
+ if (compress && verbose)
+ printf("dump is already compressed\n");
+ if (uncompress && verbose)
+ printf("dump to be uncompressed\n");
+ compress = false;
+ iscompressed = true;
+ break;
case KERNELDUMP_COMP_ZSTD:
if (compress && verbose)
printf("dump is already compressed\n");
+ if (uncompress && verbose)
+ printf("ZSTD dump can't be uncompressed\n");
compress = false;
iscompressed = true;
+ uncompress = false;
break;
default:
logmsg(LOG_ERR, "unknown compression type %d on %s",
@@ -820,7 +885,7 @@
snprintf(corename, sizeof(corename), "%s.%d.gz",
istextdump ? "textdump.tar" :
(isencrypted ? "vmcore_encrypted" : "vmcore"), bounds);
- else if (iscompressed && !isencrypted)
+ else if (iscompressed && !isencrypted && !uncompress)
snprintf(corename, sizeof(corename), "vmcore.%d.%s", bounds,
(kdhl.compression == KERNELDUMP_COMP_GZIP) ? "gz" : "zst");
else
@@ -927,7 +992,7 @@
"key.last");
}
}
- if (compress || iscompressed) {
+ if ((compress || iscompressed) && !uncompress) {
snprintf(linkname, sizeof(linkname), "%s.last.%s",
istextdump ? "textdump.tar" :
(isencrypted ? "vmcore_encrypted" : "vmcore"),
@@ -1123,7 +1188,7 @@
if (argc < 0)
exit(1);
- while ((ch = getopt(argc, argv, "Ccfkm:vz")) != -1)
+ while ((ch = getopt(argc, argv, "Ccfkm:uvz")) != -1)
switch(ch) {
case 'C':
checkfor = true;
@@ -1144,6 +1209,9 @@
exit(1);
}
break;
+ case 'u':
+ uncompress = true;
+ break;
case 'v':
verbose++;
break;
@@ -1159,6 +1227,8 @@
if (clear && (compress || keep))
usage();
if (maxdumps > 0 && (checkfor || clear))
+ usage();
+ if (compress && uncompress)
usage();
argc -= optind;
argv += optind;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 12:40 PM (5 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28580341
Default Alt Text
D27245.id79630.diff (7 KB)
Attached To
Mode
D27245: savecore: uncompress cores
Attached
Detach File
Event Timeline
Log In to Comment