Changeset View
Changeset View
Standalone View
Standalone View
sbin/savecore/savecore.c
Show First 20 Lines • Show All 292 Lines • ▼ Show 20 Lines | "no dump, not enough free space on device (%lld available, need %lld)", | ||||
return (0); | return (0); | ||||
} | } | ||||
if (spacefree - needed < 0) | if (spacefree - needed < 0) | ||||
syslog(LOG_WARNING, | syslog(LOG_WARNING, | ||||
"dump performed, but free space threshold crossed"); | "dump performed, but free space threshold crossed"); | ||||
return (1); | 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 BLOCKSIZE (1<<12) | ||||
#define BLOCKMASK (~(BLOCKSIZE-1)) | #define BLOCKMASK (~(BLOCKSIZE-1)) | ||||
static int | static int | ||||
DoRegularFile(int fd, off_t dumpsize, char *buf, const char *device, | DoRegularFile(int fd, off_t dumpsize, u_int sectorsize, int sparse, char *buf, | ||||
const char *filename, FILE *fp) | const char *device, const char *filename, FILE *fp) | ||||
{ | { | ||||
int he, hs, nr, nw, wl; | int he, hs, nr, nw, wl; | ||||
off_t dmpcnt, origsize; | off_t dmpcnt, origsize; | ||||
dmpcnt = 0; | dmpcnt = 0; | ||||
origsize = dumpsize; | origsize = dumpsize; | ||||
he = 0; | he = 0; | ||||
while (dumpsize > 0) { | while (dumpsize > 0) { | ||||
wl = BUFFERSIZE; | wl = BUFFERSIZE; | ||||
if (wl > dumpsize) | if (wl > dumpsize) | ||||
wl = dumpsize; | wl = dumpsize; | ||||
nr = read(fd, buf, wl); | nr = read(fd, buf, roundup(wl, sectorsize)); | ||||
if (nr != wl) { | if (nr != (int)roundup(wl, sectorsize)) { | ||||
if (nr == 0) | if (nr == 0) | ||||
syslog(LOG_WARNING, | syslog(LOG_WARNING, | ||||
"WARNING: EOF on dump device"); | "WARNING: EOF on dump device"); | ||||
else | else | ||||
syslog(LOG_ERR, "read error on %s: %m", device); | syslog(LOG_ERR, "read error on %s: %m", device); | ||||
nerr++; | nerr++; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (compress) { | if (!sparse) { | ||||
nw = fwrite(buf, 1, wl, fp); | nw = fwrite(buf, 1, wl, fp); | ||||
} else { | } else { | ||||
for (nw = 0; nw < nr; nw = he) { | for (nw = 0; nw < nr; nw = he) { | ||||
/* find a contiguous block of zeroes */ | /* find a contiguous block of zeroes */ | ||||
for (hs = nw; hs < nr; hs += BLOCKSIZE) { | for (hs = nw; hs < nr; hs += BLOCKSIZE) { | ||||
for (he = hs; he < nr && buf[he] == 0; | for (he = hs; he < nr && buf[he] == 0; | ||||
++he) | ++he) | ||||
/* nothing */ ; | /* nothing */ ; | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
DoFile(const char *savedir, const char *device) | DoFile(const char *savedir, const char *device) | ||||
{ | { | ||||
xo_handle_t *xostdout, *xoinfo; | xo_handle_t *xostdout, *xoinfo; | ||||
static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX]; | static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX]; | ||||
static char *buf = NULL; | static char *buf = NULL; | ||||
struct kerneldumpheader kdhf, kdhl; | struct kerneldumpheader kdhf, kdhl; | ||||
off_t mediasize, dumpsize, firsthd, lasthd; | off_t mediasize, dumpextent, dumplength, firsthd, lasthd; | ||||
FILE *info, *fp; | FILE *info, *fp; | ||||
mode_t oumask; | mode_t oumask; | ||||
int fd, fdinfo, error; | int fd, fdinfo, error; | ||||
int bounds, status; | int bounds, status; | ||||
u_int sectorsize, xostyle; | u_int sectorsize, xostyle; | ||||
int istextdump; | int istextdump, isgzipdump; | ||||
bounds = getbounds(); | bounds = getbounds(); | ||||
mediasize = 0; | mediasize = 0; | ||||
status = STATUS_UNKNOWN; | status = STATUS_UNKNOWN; | ||||
xostdout = xo_create_to_file(stdout, XO_STYLE_TEXT, 0); | xostdout = xo_create_to_file(stdout, XO_STYLE_TEXT, 0); | ||||
if (xostdout == NULL) { | if (xostdout == NULL) { | ||||
syslog(LOG_ERR, "%s: %m", infoname); | syslog(LOG_ERR, "%s: %m", infoname); | ||||
Show All 38 Lines | DoFile(const char *savedir, const char *device) | ||||
lseek(fd, lasthd, SEEK_SET); | lseek(fd, lasthd, SEEK_SET); | ||||
error = read(fd, &kdhl, sizeof kdhl); | error = read(fd, &kdhl, sizeof kdhl); | ||||
if (error != sizeof kdhl) { | if (error != sizeof kdhl) { | ||||
syslog(LOG_ERR, | syslog(LOG_ERR, | ||||
"error reading last dump header at offset %lld in %s: %m", | "error reading last dump header at offset %lld in %s: %m", | ||||
(long long)lasthd, device); | (long long)lasthd, device); | ||||
goto closefd; | goto closefd; | ||||
} | } | ||||
istextdump = 0; | isgzipdump = istextdump = 0; | ||||
if (strncmp(kdhl.magic, TEXTDUMPMAGIC, sizeof kdhl) == 0) { | if (compare_magic(&kdhl, TEXTDUMPMAGIC) == 0) { | ||||
if (verbose) | if (verbose) | ||||
printf("textdump magic on last dump header on %s\n", | printf("textdump magic on last dump header on %s\n", | ||||
device); | device); | ||||
istextdump = 1; | istextdump = 1; | ||||
if (dtoh32(kdhl.version) != KERNELDUMP_TEXT_VERSION) { | if (dtoh32(kdhl.version) != KERNELDUMP_TEXT_VERSION) { | ||||
syslog(LOG_ERR, | syslog(LOG_ERR, | ||||
"unknown version (%d) in last dump header on %s", | "unknown version (%d) in last dump header on %s", | ||||
dtoh32(kdhl.version), device); | dtoh32(kdhl.version), device); | ||||
status = STATUS_BAD; | status = STATUS_BAD; | ||||
if (force == 0) | if (force == 0) | ||||
goto closefd; | goto closefd; | ||||
} | } | ||||
} else if (memcmp(kdhl.magic, KERNELDUMPMAGIC, sizeof kdhl.magic) == | } else if (compare_magic(&kdhl, KERNELDUMPMAGIC) == 0 || | ||||
0) { | compare_magic(&kdhl, GZDUMPMAGIC) == 0) { | ||||
if (dtoh32(kdhl.version) != KERNELDUMPVERSION) { | if (dtoh32(kdhl.version) != KERNELDUMPVERSION) { | ||||
syslog(LOG_ERR, | syslog(LOG_ERR, | ||||
"unknown version (%d) in last dump header on %s", | "unknown version (%d) in last dump header on %s", | ||||
dtoh32(kdhl.version), device); | dtoh32(kdhl.version), device); | ||||
status = STATUS_BAD; | status = STATUS_BAD; | ||||
if (force == 0) | if (force == 0) | ||||
goto closefd; | goto closefd; | ||||
} | } | ||||
if (compare_magic(&kdhl, GZDUMPMAGIC) == 0) { | |||||
isgzipdump = 1; | |||||
if (compress && verbose) | |||||
printf("dump is already compressed\n"); | |||||
compress = 0; | |||||
} | |||||
} else { | } else { | ||||
if (verbose) | if (verbose) | ||||
printf("magic mismatch on last dump header on %s\n", | printf("magic mismatch on last dump header on %s\n", | ||||
device); | device); | ||||
status = STATUS_BAD; | status = STATUS_BAD; | ||||
if (force == 0) | if (force == 0) | ||||
goto closefd; | goto closefd; | ||||
if (memcmp(kdhl.magic, KERNELDUMPMAGIC_CLEARED, | if (compare_magic(&kdhl, KERNELDUMPMAGIC_CLEARED) == 0) { | ||||
sizeof kdhl.magic) == 0) { | |||||
if (verbose) | if (verbose) | ||||
printf("forcing magic on %s\n", device); | printf("forcing magic on %s\n", device); | ||||
memcpy(kdhl.magic, KERNELDUMPMAGIC, | memcpy(kdhl.magic, KERNELDUMPMAGIC, sizeof kdhl.magic); | ||||
bdrewery: sizeof() | |||||
sizeof kdhl.magic); | |||||
} else { | } else { | ||||
syslog(LOG_ERR, "unable to force dump - bad magic"); | syslog(LOG_ERR, "unable to force dump - bad magic"); | ||||
goto closefd; | goto closefd; | ||||
} | } | ||||
if (dtoh32(kdhl.version) != KERNELDUMPVERSION) { | if (dtoh32(kdhl.version) != KERNELDUMPVERSION) { | ||||
syslog(LOG_ERR, | syslog(LOG_ERR, | ||||
"unknown version (%d) in last dump header on %s", | "unknown version (%d) in last dump header on %s", | ||||
dtoh32(kdhl.version), device); | dtoh32(kdhl.version), device); | ||||
Show All 11 Lines | DoFile(const char *savedir, const char *device) | ||||
if (kerneldump_parity(&kdhl)) { | if (kerneldump_parity(&kdhl)) { | ||||
syslog(LOG_ERR, | syslog(LOG_ERR, | ||||
"parity error on last dump header on %s", device); | "parity error on last dump header on %s", device); | ||||
nerr++; | nerr++; | ||||
status = STATUS_BAD; | status = STATUS_BAD; | ||||
if (force == 0) | if (force == 0) | ||||
goto closefd; | goto closefd; | ||||
} | } | ||||
dumpsize = dtoh64(kdhl.dumplength); | dumpextent = dtoh64(kdhl.dumpextent); | ||||
firsthd = lasthd - dumpsize - sizeof kdhf; | dumplength = dtoh64(kdhl.dumplength); | ||||
firsthd = lasthd - dumpextent - sizeof kdhf; | |||||
bdreweryUnsubmitted Not Done Inline Actionssizeof() bdrewery: sizeof() | |||||
lseek(fd, firsthd, SEEK_SET); | lseek(fd, firsthd, SEEK_SET); | ||||
error = read(fd, &kdhf, sizeof kdhf); | error = read(fd, &kdhf, sizeof kdhf); | ||||
if (error != sizeof kdhf) { | if (error != sizeof kdhf) { | ||||
syslog(LOG_ERR, | syslog(LOG_ERR, | ||||
"error reading first dump header at offset %lld in %s: %m", | "error reading first dump header at offset %lld in %s: %m", | ||||
(long long)firsthd, device); | (long long)firsthd, device); | ||||
nerr++; | nerr++; | ||||
goto closefd; | goto closefd; | ||||
Show All 28 Lines | DoFile(const char *savedir, const char *device) | ||||
if (kdhl.panicstring[0]) | if (kdhl.panicstring[0]) | ||||
syslog(LOG_ALERT, "reboot after panic: %s", kdhl.panicstring); | syslog(LOG_ALERT, "reboot after panic: %s", kdhl.panicstring); | ||||
else | else | ||||
syslog(LOG_ALERT, "reboot"); | syslog(LOG_ALERT, "reboot"); | ||||
if (verbose) | if (verbose) | ||||
printf("Checking for available free space\n"); | printf("Checking for available free space\n"); | ||||
if (!check_space(savedir, dumpsize, bounds)) { | if (!check_space(savedir, dumplength, bounds)) { | ||||
nerr++; | nerr++; | ||||
goto closefd; | goto closefd; | ||||
} | } | ||||
writebounds(bounds + 1); | writebounds(bounds + 1); | ||||
saved_dump_remove(bounds); | saved_dump_remove(bounds); | ||||
Show All 9 Lines | if (fdinfo < 0) { | ||||
goto closefd; | goto closefd; | ||||
} | } | ||||
oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ | oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ | ||||
if (compress) { | if (compress) { | ||||
snprintf(corename, sizeof(corename), "%s.%d.gz", | snprintf(corename, sizeof(corename), "%s.%d.gz", | ||||
istextdump ? "textdump.tar" : "vmcore", bounds); | istextdump ? "textdump.tar" : "vmcore", bounds); | ||||
fp = zopen(corename, "w"); | fp = zopen(corename, "w"); | ||||
} else if (isgzipdump) { | |||||
snprintf(corename, sizeof(corename), "vmcore.%d.gz", bounds); | |||||
fp = fopen(corename, "w"); | |||||
} else { | } else { | ||||
snprintf(corename, sizeof(corename), "%s.%d", | snprintf(corename, sizeof(corename), "%s.%d", | ||||
istextdump ? "textdump.tar" : "vmcore", bounds); | istextdump ? "textdump.tar" : "vmcore", bounds); | ||||
fp = fopen(corename, "w"); | fp = fopen(corename, "w"); | ||||
} | } | ||||
if (fp == NULL) { | if (fp == NULL) { | ||||
syslog(LOG_ERR, "%s: %m", corename); | syslog(LOG_ERR, "%s: %m", corename); | ||||
close(fdinfo); | close(fdinfo); | ||||
Show All 24 Lines | DoFile(const char *savedir, const char *device) | ||||
printheader(xoinfo, &kdhl, device, bounds, status); | printheader(xoinfo, &kdhl, device, bounds, status); | ||||
xo_close_container_h(xoinfo, "crashdump"); | xo_close_container_h(xoinfo, "crashdump"); | ||||
xo_flush_h(xoinfo); | xo_flush_h(xoinfo); | ||||
xo_finish_h(xoinfo); | xo_finish_h(xoinfo); | ||||
fclose(info); | fclose(info); | ||||
syslog(LOG_NOTICE, "writing %score to %s/%s", | syslog(LOG_NOTICE, "writing %score to %s/%s", | ||||
compress ? "compressed " : "", savedir, corename); | (compress || isgzipdump) ? "compressed " : "", savedir, corename); | ||||
Done Inline ActionsI don't have operator precedence memorized for these ones. Can we add a pair of parentheses around (compress || isgzipdump)? cem: I don't have operator precedence memorized for these ones. Can we add a pair of parentheses… | |||||
if (istextdump) { | if (istextdump) { | ||||
if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device, | if (DoTextdumpFile(fd, dumplength, lasthd, buf, device, | ||||
corename, fp) < 0) | corename, fp) < 0) | ||||
goto closeall; | goto closeall; | ||||
} else { | } else { | ||||
if (DoRegularFile(fd, dumpsize, buf, device, corename, fp) | if (DoRegularFile(fd, dumplength, sectorsize, | ||||
< 0) | !(compress || isgzipdump), buf, device, corename, fp) < 0) | ||||
goto closeall; | goto closeall; | ||||
} | } | ||||
if (verbose) | if (verbose) | ||||
printf("\n"); | printf("\n"); | ||||
if (fclose(fp) < 0) { | if (fclose(fp) < 0) { | ||||
syslog(LOG_ERR, "error on %s: %m", corename); | syslog(LOG_ERR, "error on %s: %m", corename); | ||||
nerr++; | nerr++; | ||||
goto closefd; | goto closefd; | ||||
} | } | ||||
symlinks_remove(); | symlinks_remove(); | ||||
if (symlink(infoname, "info.last") == -1) { | if (symlink(infoname, "info.last") == -1) { | ||||
syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", | syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", | ||||
savedir, "info.last"); | savedir, "info.last"); | ||||
} | } | ||||
if (compress) { | if (compress || isgzipdump) { | ||||
snprintf(linkname, sizeof(linkname), "%s.last.gz", | snprintf(linkname, sizeof(linkname), "%s.last.gz", | ||||
istextdump ? "textdump.tar" : "vmcore"); | istextdump ? "textdump.tar" : "vmcore"); | ||||
} else { | } else { | ||||
snprintf(linkname, sizeof(linkname), "%s.last", | snprintf(linkname, sizeof(linkname), "%s.last", | ||||
istextdump ? "textdump.tar" : "vmcore"); | istextdump ? "textdump.tar" : "vmcore"); | ||||
} | } | ||||
if (symlink(corename, linkname) == -1) { | if (symlink(corename, linkname) == -1) { | ||||
syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", | syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", | ||||
▲ Show 20 Lines • Show All 145 Lines • Show Last 20 Lines |
sizeof()