- revert back to vmcore.#
- reimplement -z - use syslog() - improve consistancy of messages - allow -f to recover cleared dumps - return bufsize to 1024 * 1024 - return the ability to write sparse files - update man page - fix minfree to require 2k for info file instead of the kernel size - include Berkeley copyright too due to amount of old code copied Submitted by: Chad David <davidc@acns.ab.ca>
This commit is contained in:
parent
560bc9d245
commit
160b239125
@ -1,7 +1,8 @@
|
||||
# $FreeBSD$
|
||||
PROG= savecore
|
||||
WARNS= 4
|
||||
NOMAN= sorry, not yet.
|
||||
LDADD= -lmd
|
||||
MAN8= savecore.8
|
||||
DPADD+= ${LIBZ}
|
||||
LDADD+= -lz
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -43,12 +43,14 @@
|
||||
.Fl c
|
||||
.Nm
|
||||
.Op Fl fkvz
|
||||
.Op Fl N Ar system
|
||||
.Ar directory
|
||||
.Op Ar directory Op Ar device ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm Savecore
|
||||
copies the currently running kernel and its associated core dump into
|
||||
copies a core dump into
|
||||
.Fa directory ,
|
||||
or the current working directory if no
|
||||
.Fa directory
|
||||
argument is given,
|
||||
and enters a reboot message and information about the core dump into
|
||||
the system log.
|
||||
.Pp
|
||||
@ -59,15 +61,9 @@ Clear the dump, so that future invocations of
|
||||
.Nm
|
||||
will ignore it.
|
||||
.It Fl f
|
||||
Force a dump to be taken even if the dump doesn't appear correct or there
|
||||
is insufficient disk space.
|
||||
Force a dump to be taken even if the dump was cleared.
|
||||
.It Fl k
|
||||
Do not clear the dump after saving it.
|
||||
.It Fl N
|
||||
Use
|
||||
.Ar system
|
||||
as the kernel instead of the running kernel (as determined from
|
||||
.Xr getbootfile 3 ) .
|
||||
.It Fl v
|
||||
Print out some additional debugging information.
|
||||
.It Fl z
|
||||
@ -76,12 +72,17 @@ Compress the core dump and kernel (see
|
||||
.El
|
||||
.Pp
|
||||
.Nm Savecore
|
||||
checks the core dump in various ways to make sure that it is current and
|
||||
that it corresponds to the currently running system.
|
||||
looks for dumps on each device specified by the
|
||||
.Ar device
|
||||
argument(s), or on each device in
|
||||
.Pa /etc/fstab
|
||||
marked as "dump" or "swap".
|
||||
.Nm Savecore
|
||||
checks the core dump in various ways to make sure that it is complete.
|
||||
If it passes these checks, it saves the core image in
|
||||
.Ar directory Ns Pa /vmcore.#
|
||||
and the system in
|
||||
.Ar directory Ns Pa /kernel.#
|
||||
and information about the core in
|
||||
.Ar directory Ns Pa /info.#
|
||||
The ``#'' is the number from the first line of the file
|
||||
.Ar directory Ns Pa /bounds ,
|
||||
and it is incremented and stored back into the file each time
|
||||
@ -111,7 +112,7 @@ is meant to be called near the end of the initialization file
|
||||
(see
|
||||
.Xr rc 8 ) .
|
||||
.Sh BUGS
|
||||
The minfree code does not consider the effect of compression.
|
||||
The minfree code does not consider the effect of compression or sparse files.
|
||||
.Sh SEE ALSO
|
||||
.Xr gzip 1 ,
|
||||
.Xr getbootfile 3 ,
|
||||
|
@ -31,35 +31,68 @@
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (c) 1986, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/kerneldump.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fstab.h>
|
||||
#include <md5.h>
|
||||
#include <paths.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int clear, force, keep, verbose; /* flags */
|
||||
int nfound, nsaved, nerr; /* statistics */
|
||||
int compress, clear, force, keep, verbose; /* flags */
|
||||
int nfound, nsaved, nerr; /* statistics */
|
||||
|
||||
extern FILE *zopen(const char *, const char *);
|
||||
|
||||
static void
|
||||
printheader(FILE *f, const struct kerneldumpheader *h, const char *device,
|
||||
const char *md5)
|
||||
int bounds)
|
||||
{
|
||||
uint64_t dumplen;
|
||||
time_t t;
|
||||
@ -77,10 +110,51 @@ printheader(FILE *f, const struct kerneldumpheader *h, const char *device,
|
||||
fprintf(f, " Hostname: %s\n", h->hostname);
|
||||
fprintf(f, " Versionstring: %s", h->versionstring);
|
||||
fprintf(f, " Panicstring: %s\n", h->panicstring);
|
||||
fprintf(f, " MD5: %s\n", md5);
|
||||
fprintf(f, " Bounds: %d\n", bounds);
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
static int
|
||||
getbounds(void) {
|
||||
FILE *fp;
|
||||
char buf[6];
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
|
||||
if ((fp = fopen("bounds", "r")) == NULL) {
|
||||
syslog(LOG_WARNING, "unable to open bounds file, using 0");
|
||||
goto newfile;
|
||||
}
|
||||
|
||||
if (fgets(buf, sizeof buf, fp) == NULL) {
|
||||
syslog(LOG_WARNING, "unable to read from bounds, using 0");
|
||||
fclose(fp);
|
||||
goto newfile;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
ret = (int)strtol(buf, NULL, 10);
|
||||
if (ret == 0 && (errno == EINVAL || errno == ERANGE))
|
||||
syslog(LOG_WARNING, "invalid value found in bounds, using 0");
|
||||
|
||||
newfile:
|
||||
|
||||
if ((fp = fopen("bounds", "w")) == NULL) {
|
||||
syslog(LOG_WARNING, "unable to write to bounds file: %m");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf("bounds number: %d\n", ret);
|
||||
|
||||
fprintf(fp, "%d\n", (ret + 1));
|
||||
fclose(fp);
|
||||
|
||||
done:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that sufficient space is available on the disk that holds the
|
||||
* save directory.
|
||||
@ -89,19 +163,14 @@ static int
|
||||
check_space(char *savedir, off_t dumpsize)
|
||||
{
|
||||
FILE *fp;
|
||||
const char *tkernel;
|
||||
off_t minfree, spacefree, totfree, kernelsize, needed;
|
||||
struct stat st;
|
||||
off_t minfree, spacefree, totfree, needed;
|
||||
struct statfs fsbuf;
|
||||
char buf[100], path[MAXPATHLEN];
|
||||
|
||||
tkernel = getbootfile();
|
||||
if (stat(tkernel, &st) < 0)
|
||||
err(1, "%s", tkernel);
|
||||
kernelsize = st.st_blocks * S_BLKSIZE;
|
||||
|
||||
if (statfs(savedir, &fsbuf) < 0)
|
||||
err(1, "%s", savedir);
|
||||
if (statfs(savedir, &fsbuf) < 0) {
|
||||
syslog(LOG_ERR, "%s: %m", savedir);
|
||||
exit(1);
|
||||
}
|
||||
spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024;
|
||||
totfree = ((off_t) fsbuf.f_bfree * fsbuf.f_bsize) / 1024;
|
||||
|
||||
@ -116,71 +185,92 @@ check_space(char *savedir, off_t dumpsize)
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
||||
needed = (dumpsize + kernelsize) / 1024;
|
||||
needed = dumpsize / 1024 + 2; /* 2 for info file */
|
||||
if (((minfree > 0) ? spacefree : totfree) - needed < minfree) {
|
||||
warnx("no dump, not enough free space on device"
|
||||
" (%lld available, need %lld)",
|
||||
syslog(LOG_WARNING,
|
||||
"no dump, not enough free space on device (%lld available, need %lld)",
|
||||
(long long)(minfree > 0 ? spacefree : totfree),
|
||||
(long long)needed);
|
||||
return (0);
|
||||
}
|
||||
if (spacefree - needed < 0)
|
||||
warnx("dump performed, but free space threshold crossed");
|
||||
syslog(LOG_WARNING,
|
||||
"dump performed, but free space threshold crossed");
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
#define BLOCKSIZE (1<<12)
|
||||
#define BLOCKMASK (~(BLOCKSIZE-1))
|
||||
|
||||
static void
|
||||
DoFile(char *savedir, const char *device)
|
||||
{
|
||||
struct kerneldumpheader kdhf, kdhl;
|
||||
char buf[BUFSIZ];
|
||||
struct stat sb;
|
||||
off_t mediasize, dumpsize, firsthd, lasthd;
|
||||
char *md5;
|
||||
FILE *info;
|
||||
int fd, fdcore, fdinfo, error, wl;
|
||||
char buf[1024 * 1024];
|
||||
off_t mediasize, dumpsize, firsthd, lasthd, dmpcnt;
|
||||
FILE *info, *fp;
|
||||
int fd, fdinfo, error, wl;
|
||||
int nr, nw, hs, he;
|
||||
int bounds;
|
||||
u_int sectorsize;
|
||||
mode_t oumask;
|
||||
|
||||
dmpcnt = 0;
|
||||
mediasize = 0;
|
||||
|
||||
if (verbose)
|
||||
printf("Checking for kernel dump on device %s\n", device);
|
||||
printf("checking for kernel dump on device %s\n", device);
|
||||
|
||||
mediasize = 0;
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
warn("%s", device);
|
||||
syslog(LOG_ERR, "%s: %m", device);
|
||||
return;
|
||||
}
|
||||
error = ioctl(fd, DIOCGMEDIASIZE, &mediasize);
|
||||
if (!error)
|
||||
error = ioctl(fd, DIOCGSECTORSIZE, §orsize);
|
||||
if (error) {
|
||||
warn("couldn't find media and/or sector size of %s", device);
|
||||
syslog(LOG_ERR,
|
||||
"couldn't find media and/or sector size of %s: %m", device);
|
||||
goto closefd;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("Mediasize = %lld\n", (long long)mediasize);
|
||||
printf("Sectorsize = %u\n", sectorsize);
|
||||
printf("mediasize = %lld\n", (long long)mediasize);
|
||||
printf("sectorsize = %u\n", sectorsize);
|
||||
}
|
||||
|
||||
lasthd = mediasize - sectorsize;
|
||||
lseek(fd, lasthd, SEEK_SET);
|
||||
error = read(fd, &kdhl, sizeof kdhl);
|
||||
if (error != sizeof kdhl) {
|
||||
warn("error reading last dump header at offset %lld in %s",
|
||||
syslog(LOG_ERR,
|
||||
"error reading last dump header at offset %lld in %s: %m",
|
||||
(long long)lasthd, device);
|
||||
goto closefd;
|
||||
}
|
||||
if (memcmp(kdhl.magic, KERNELDUMPMAGIC, sizeof kdhl.magic)) {
|
||||
if (verbose)
|
||||
warnx("magic mismatch on last dump header on %s",
|
||||
printf("magic mismatch on last dump header on %s\n",
|
||||
device);
|
||||
goto closefd;
|
||||
|
||||
if (force == 0)
|
||||
goto closefd;
|
||||
|
||||
if (memcmp(kdhl.magic, KERNELDUMPMAGIC_CLEARED,
|
||||
sizeof kdhl.magic) == 0) {
|
||||
if (verbose)
|
||||
printf("forcing magic on %s\n", device);
|
||||
memcpy(kdhl.magic, KERNELDUMPMAGIC,
|
||||
sizeof kdhl.magic);
|
||||
} else {
|
||||
syslog(LOG_ERR, "unable to force dump - bad magic");
|
||||
goto closefd;
|
||||
}
|
||||
}
|
||||
if (dtoh32(kdhl.version) != KERNELDUMPVERSION) {
|
||||
warnx("unknown version (%d) in last dump header on %s",
|
||||
syslog(LOG_ERR,
|
||||
"unknown version (%d) in last dump header on %s",
|
||||
dtoh32(kdhl.version), device);
|
||||
goto closefd;
|
||||
}
|
||||
@ -190,7 +280,8 @@ DoFile(char *savedir, const char *device)
|
||||
goto nuke;
|
||||
|
||||
if (kerneldump_parity(&kdhl)) {
|
||||
warnx("parity error on last dump header on %s", device);
|
||||
syslog(LOG_ERR,
|
||||
"parity error on last dump header on %s", device);
|
||||
nerr++;
|
||||
goto closefd;
|
||||
}
|
||||
@ -199,109 +290,170 @@ DoFile(char *savedir, const char *device)
|
||||
lseek(fd, firsthd, SEEK_SET);
|
||||
error = read(fd, &kdhf, sizeof kdhf);
|
||||
if (error != sizeof kdhf) {
|
||||
warn("error reading first dump header at offset %lld in %s",
|
||||
syslog(LOG_ERR,
|
||||
"error reading first dump header at offset %lld in %s: %m",
|
||||
(long long)firsthd, device);
|
||||
nerr++;
|
||||
goto closefd;
|
||||
}
|
||||
if (memcmp(&kdhl, &kdhf, sizeof kdhl)) {
|
||||
warn("first and last dump headers disagree on %s", device);
|
||||
nerr++;
|
||||
goto closefd;
|
||||
}
|
||||
md5 = MD5Data((unsigned char *)&kdhl, sizeof kdhl, NULL);
|
||||
sprintf(buf, "%s.info", md5);
|
||||
|
||||
/*
|
||||
* See if the dump has been saved already. Don't save the dump
|
||||
* again, unless 'force' is in effect.
|
||||
*/
|
||||
if (stat(buf, &sb) == 0) {
|
||||
if (!force) {
|
||||
if (verbose)
|
||||
printf("Dump on device %s already saved\n",
|
||||
device);
|
||||
goto closefd;
|
||||
}
|
||||
} else if (errno != ENOENT) {
|
||||
warn("error while checking for pre-saved core file");
|
||||
syslog(LOG_ERR,
|
||||
"first and last dump headers disagree on %s", device);
|
||||
nerr++;
|
||||
goto closefd;
|
||||
}
|
||||
|
||||
if (kdhl.panicstring[0])
|
||||
syslog(LOG_ALERT, "reboot after panic: %s", kdhl.panicstring);
|
||||
else
|
||||
syslog(LOG_ALERT, "reboot");
|
||||
|
||||
if (verbose)
|
||||
printf("Checking for available free space\n");
|
||||
if (!check_space(savedir, dumpsize)) {
|
||||
nerr++;
|
||||
goto closefd;
|
||||
}
|
||||
|
||||
bounds = getbounds();
|
||||
|
||||
sprintf(buf, "info.%d", bounds);
|
||||
|
||||
/*
|
||||
* Create or overwrite any existing files.
|
||||
*/
|
||||
fdinfo = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (fdinfo < 0) {
|
||||
warn("%s", buf);
|
||||
syslog(LOG_ERR, "%s: %m", buf);
|
||||
nerr++;
|
||||
goto closefd;
|
||||
}
|
||||
sprintf(buf, "%s.core", md5);
|
||||
fdcore = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (fdcore < 0) {
|
||||
warn("%s", buf);
|
||||
oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/
|
||||
if (compress) {
|
||||
sprintf(buf, "vmcore.%d.gz", bounds);
|
||||
fp = zopen(buf, "w");
|
||||
} else {
|
||||
sprintf(buf, "vmcore.%d", bounds);
|
||||
fp = fopen(buf, "w");
|
||||
}
|
||||
if (fp == NULL) {
|
||||
syslog(LOG_ERR, "%s: %m", buf);
|
||||
close(fdinfo);
|
||||
nerr++;
|
||||
goto closefd;
|
||||
}
|
||||
(void)umask(oumask);
|
||||
|
||||
info = fdopen(fdinfo, "w");
|
||||
|
||||
if (verbose)
|
||||
printheader(stdout, &kdhl, device, md5);
|
||||
printheader(stdout, &kdhl, device, bounds);
|
||||
|
||||
printf("Saving dump to file %s\n", buf);
|
||||
printheader(info, &kdhl, device, bounds);
|
||||
fclose(info);
|
||||
|
||||
printheader(info, &kdhl, device, md5);
|
||||
syslog(LOG_NOTICE, "writing %score to %s",
|
||||
compress ? "compressed " : "", buf);
|
||||
|
||||
while (dumpsize > 0) {
|
||||
wl = sizeof(buf);
|
||||
if (wl > dumpsize)
|
||||
wl = dumpsize;
|
||||
error = read(fd, buf, wl);
|
||||
if (error != wl) {
|
||||
warn("read error on %s", device);
|
||||
nr = read(fd, buf, wl);
|
||||
if (nr != wl) {
|
||||
if (nr == 0)
|
||||
syslog(LOG_WARNING,
|
||||
"WARNING: EOF on dump device");
|
||||
else
|
||||
syslog(LOG_ERR, "read error on %s: %m", device);
|
||||
nerr++;
|
||||
goto closeall;
|
||||
}
|
||||
error = write(fdcore, buf, wl);
|
||||
if (error != wl) {
|
||||
warn("write error on %s.core file", md5);
|
||||
if (compress) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 (fseek(fp, he - hs, SEEK_CUR) == -1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nw != wl) {
|
||||
syslog(LOG_ERR,
|
||||
"write error on vmcore.%d file: %m", bounds);
|
||||
syslog(LOG_WARNING,
|
||||
"WARNING: vmcore may be incomplete");
|
||||
nerr++;
|
||||
goto closeall;
|
||||
}
|
||||
if (verbose) {
|
||||
dmpcnt += wl;
|
||||
printf("%llu\r", dmpcnt);
|
||||
fflush(stdout);
|
||||
}
|
||||
dumpsize -= wl;
|
||||
}
|
||||
if (verbose)
|
||||
printf("\n");
|
||||
|
||||
if (fclose(fp) < 0) {
|
||||
syslog(LOG_ERR, "error on vmcore.%d: %m", bounds);
|
||||
nerr++;
|
||||
goto closeall;
|
||||
}
|
||||
nsaved++;
|
||||
close(fdinfo);
|
||||
close(fdcore);
|
||||
|
||||
if (verbose)
|
||||
printf("Dump saved\n");
|
||||
printf("dump saved\n");
|
||||
|
||||
nuke:
|
||||
nuke:
|
||||
if (clear || !keep) {
|
||||
if (verbose)
|
||||
printf("Clearing dump header\n");
|
||||
memset(&kdhl, 0, sizeof kdhl);
|
||||
printf("clearing dump header\n");
|
||||
memcpy(kdhl.magic, KERNELDUMPMAGIC_CLEARED, sizeof kdhl.magic);
|
||||
lseek(fd, lasthd, SEEK_SET);
|
||||
error = write(fd, &kdhl, sizeof kdhl);
|
||||
if (error != sizeof kdhl)
|
||||
warn("error while clearing the dump header");
|
||||
syslog(LOG_ERR,
|
||||
"error while clearing the dump header: %m");
|
||||
}
|
||||
close(fd);
|
||||
return;
|
||||
|
||||
closeall:
|
||||
close(fdinfo);
|
||||
close(fdcore);
|
||||
closeall:
|
||||
fclose(fp);
|
||||
|
||||
closefd:
|
||||
closefd:
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@ -319,9 +471,13 @@ main(int argc, char **argv)
|
||||
struct fstab *fsp;
|
||||
char *savedir;
|
||||
|
||||
openlog("savecore", LOG_PERROR, LOG_DAEMON);
|
||||
|
||||
savedir = strdup(".");
|
||||
if (savedir == NULL)
|
||||
errx(1, "Cannot allocate memory");
|
||||
if (savedir == NULL) {
|
||||
syslog(LOG_ERR, "Cannot allocate memory");
|
||||
exit(1);
|
||||
}
|
||||
while ((ch = getopt(argc, argv, "cdfkN:vz")) != -1)
|
||||
switch(ch) {
|
||||
case 'c':
|
||||
@ -336,9 +492,11 @@ main(int argc, char **argv)
|
||||
case 'f':
|
||||
force = 1;
|
||||
break;
|
||||
case 'z':
|
||||
compress = 1;
|
||||
break;
|
||||
case 'd': /* Obsolete */
|
||||
case 'N':
|
||||
case 'z':
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -347,8 +505,10 @@ main(int argc, char **argv)
|
||||
argv += optind;
|
||||
if (argc >= 1) {
|
||||
error = chdir(argv[0]);
|
||||
if (error)
|
||||
err(1, "chdir(%s)", argv[0]);
|
||||
if (error) {
|
||||
syslog(LOG_ERR, "chdir(%s): %m", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
savedir = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
@ -370,12 +530,12 @@ main(int argc, char **argv)
|
||||
|
||||
/* Emit minimal output. */
|
||||
if (nfound == 0)
|
||||
printf("No dumps found\n");
|
||||
syslog(LOG_WARNING, "no dumps found");
|
||||
else if (nsaved == 0) {
|
||||
if (nerr != 0)
|
||||
printf("Unsaved dumps found but not saved\n");
|
||||
syslog(LOG_WARNING, "unsaved dumps found but not saved");
|
||||
else
|
||||
printf("No unsaved dumps found\n");
|
||||
syslog(LOG_WARNING, "no unsaved dumps found");
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user