From 389f3e3c15c55ab2fcda8488f853b194a3018c5d Mon Sep 17 00:00:00 2001 From: pjd Date: Fri, 14 Dec 2012 15:01:23 +0000 Subject: Whitespace cleanups. --- sbin/savecore/savecore.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index b3f2902..bbde36c 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -194,7 +194,7 @@ check_space(const char *savedir, off_t dumpsize) syslog(LOG_ERR, "%s: %m", savedir); exit(1); } - spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024; + spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024; totfree = ((off_t) fsbuf.f_bfree * fsbuf.f_bsize) / 1024; (void)snprintf(path, sizeof(path), "%s/minfree", savedir); @@ -209,7 +209,7 @@ check_space(const char *savedir, off_t dumpsize) } needed = dumpsize / 1024 + 2; /* 2 for info file */ - if (((minfree > 0) ? spacefree : totfree) - needed < minfree) { + if (((minfree > 0) ? spacefree : totfree) - needed < minfree) { syslog(LOG_WARNING, "no dump, not enough free space on device (%lld available, need %lld)", (long long)(minfree > 0 ? spacefree : totfree), @@ -262,7 +262,7 @@ DoRegularFile(int fd, off_t dumpsize, char *buf, const char *device, if (he >= hs + BLOCKSIZE) break; } - + /* back down to a block boundary */ he &= BLOCKMASK; @@ -433,7 +433,7 @@ DoFile(const char *savedir, const char *device) syslog(LOG_ERR, "unknown version (%d) in last dump header on %s", dtoh32(kdhl.version), device); - + status = STATUS_BAD; if (force == 0) goto closefd; @@ -444,7 +444,7 @@ DoFile(const char *savedir, const char *device) syslog(LOG_ERR, "unknown version (%d) in last dump header on %s", dtoh32(kdhl.version), device); - + status = STATUS_BAD; if (force == 0) goto closefd; @@ -472,7 +472,7 @@ DoFile(const char *savedir, const char *device) syslog(LOG_ERR, "unknown version (%d) in last dump header on %s", dtoh32(kdhl.version), device); - + status = STATUS_BAD; if (force == 0) goto closefd; -- cgit v1.1 From a555e4822220799d8567f55fdb4d62de343e5d4e Mon Sep 17 00:00:00 2001 From: pjd Date: Fri, 14 Dec 2012 15:03:12 +0000 Subject: If we are not going to clear the dump (we are either just checking if the dump exists or we want to keep it), open device read-only. Obtained from: WHEEL Systems --- sbin/savecore/savecore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index bbde36c..2b9b6d8 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -394,7 +394,7 @@ DoFile(const char *savedir, const char *device) if (verbose) printf("checking for kernel dump on device %s\n", device); - fd = open(device, O_RDWR); + fd = open(device, (checkfor || keep) ? O_RDONLY : O_RDWR); if (fd < 0) { syslog(LOG_ERR, "%s: %m", device); return; @@ -612,7 +612,7 @@ DoFile(const char *savedir, const char *device) printf("dump saved\n"); nuke: - if (clear || !keep) { + if (!keep) { if (verbose) printf("clearing dump header\n"); memcpy(kdhl.magic, KERNELDUMPMAGIC_CLEARED, sizeof kdhl.magic); -- cgit v1.1 From ab75315eecbefcf8a215a0a13500f0923fc962f9 Mon Sep 17 00:00:00 2001 From: pjd Date: Fri, 14 Dec 2012 15:04:39 +0000 Subject: The clear option (-c) is not compatible with keep (-k) and compress (-z) options. Obtained from: WHEEL Systems --- sbin/savecore/savecore.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index 2b9b6d8..c11c15e 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -681,6 +681,8 @@ main(int argc, char **argv) } if (checkfor && (clear || force || keep)) usage(); + if (clear && (compress || keep)) + usage(); argc -= optind; argv += optind; if (argc >= 1) { -- cgit v1.1 From 1d3ec906ca23ea5f5ff60e8ebe9b3bcc4f9033d2 Mon Sep 17 00:00:00 2001 From: pjd Date: Fri, 14 Dec 2012 15:12:08 +0000 Subject: - When checking if a dump exists on the given device there is no need to provide dump directory. Eliminate this redundant argument. This changes the usage, but the only risk here is that a warning will be printed about directory given as device. - Update usage of -C option. - When clearing dump header from the given device there is also no need to provide dump directory, although additional arguments for -c were not documented. - Document that -v can be used with -c and that list of devices can be given. Obtained from: WHEEL Systems --- sbin/savecore/savecore.8 | 6 ++++-- sbin/savecore/savecore.c | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.8 b/sbin/savecore/savecore.8 index 01be723..3e22f5a 100644 --- a/sbin/savecore/savecore.8 +++ b/sbin/savecore/savecore.8 @@ -28,7 +28,7 @@ .\" From: @(#)savecore.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd December 24, 2008 +.Dd December 14, 2012 .Dt SAVECORE 8 .Os .Sh NAME @@ -37,10 +37,12 @@ .Sh SYNOPSIS .Nm .Fl c +.Op Fl v +.Op Ar device ... .Nm .Fl C .Op Fl v -.Op Ar directory device +.Op Ar device ... .Nm .Op Fl fkvz .Op Ar directory Op Ar device ... diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index c11c15e..a1fe848 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -636,8 +636,8 @@ static void usage(void) { fprintf(stderr, "%s\n%s\n%s\n", - "usage: savecore -c", - " savecore -C [-v] [directory device]", + "usage: savecore -c [-v] [device ...]", + " savecore -C [-v] [device ...]", " savecore [-fkvz] [directory [device ...]]"); exit (1); } @@ -685,7 +685,7 @@ main(int argc, char **argv) usage(); argc -= optind; argv += optind; - if (argc >= 1) { + if (argc >= 1 && !checkfor && !clear) { error = chdir(argv[0]); if (error) { syslog(LOG_ERR, "chdir(%s): %m", argv[0]); -- cgit v1.1 From e18befc88a006695eec98af0b3091ca54c2c7ab8 Mon Sep 17 00:00:00 2001 From: pjd Date: Sun, 16 Dec 2012 22:59:25 +0000 Subject: Prefer snprintf() over sprintf(). Obtained from: WHEEL Systems --- sbin/savecore/savecore.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index a1fe848..26eae53 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -543,7 +543,7 @@ DoFile(const char *savedir, const char *device) writebounds(bounds + 1); - sprintf(buf, "info.%d", bounds); + snprintf(buf, sizeof(buf), "info.%d", bounds); /* * Create or overwrite any existing dump header files. @@ -556,12 +556,12 @@ DoFile(const char *savedir, const char *device) } oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ if (compress) { - sprintf(filename, "%s.%d.gz", istextdump ? "textdump.tar" : - "vmcore", bounds); + snprintf(filename, sizeof(filename), "%s.%d.gz", + istextdump ? "textdump.tar" : "vmcore", bounds); fp = zopen(filename, "w"); } else { - sprintf(filename, "%s.%d", istextdump ? "textdump.tar" : - "vmcore", bounds); + snprintf(filename, sizeof(filename), "%s.%d", + istextdump ? "textdump.tar" : "vmcore", bounds); fp = fopen(filename, "w"); } if (fp == NULL) { -- cgit v1.1 From 1df9cc8b3f57738840eed7cdc84638812fbddc72 Mon Sep 17 00:00:00 2001 From: pjd Date: Sun, 16 Dec 2012 22:59:58 +0000 Subject: Sort flags properly. Obtained from: WHEEL Systems --- sbin/savecore/savecore.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index 26eae53..747377c 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -663,15 +663,15 @@ main(int argc, char **argv) case 'c': clear = 1; break; + case 'f': + force = 1; + break; case 'k': keep = 1; break; case 'v': verbose++; break; - case 'f': - force = 1; - break; case 'z': compress = 1; break; -- cgit v1.1 From f3f8bbc49800ecc3f3414633a1a66235d04e949d Mon Sep 17 00:00:00 2001 From: pjd Date: Sun, 16 Dec 2012 23:04:31 +0000 Subject: Make use of the fact that we changed working directory to the dump directory earlier. Obtained from: WHEEL Systems --- sbin/savecore/savecore.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index 747377c..3a2547a 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -188,17 +188,16 @@ check_space(const char *savedir, off_t dumpsize) FILE *fp; off_t minfree, spacefree, totfree, needed; struct statfs fsbuf; - char buf[100], path[MAXPATHLEN]; + char buf[100]; - if (statfs(savedir, &fsbuf) < 0) { + if (statfs(".", &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; - (void)snprintf(path, sizeof(path), "%s/minfree", savedir); - if ((fp = fopen(path, "r")) == NULL) + if ((fp = fopen("minfree", "r")) == NULL) minfree = 0; else { if (fgets(buf, sizeof(buf), fp) == NULL) -- cgit v1.1 From c5cbd42d14b9d344c2cfe474407c43ddfbc75995 Mon Sep 17 00:00:00 2001 From: pjd Date: Sun, 16 Dec 2012 23:06:12 +0000 Subject: Implement -m option to savecore(8) that allows to limit number of kernel dumps stored. Once the limit is reached it restarts from 0. Reviewed by: avg Obtained from: WHEEL Systems --- sbin/savecore/savecore.8 | 11 ++++- sbin/savecore/savecore.c | 106 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 96 insertions(+), 21 deletions(-) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.8 b/sbin/savecore/savecore.8 index 3e22f5a..c7d7e95 100644 --- a/sbin/savecore/savecore.8 +++ b/sbin/savecore/savecore.8 @@ -28,7 +28,7 @@ .\" From: @(#)savecore.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd December 14, 2012 +.Dd December 17, 2012 .Dt SAVECORE 8 .Os .Sh NAME @@ -45,6 +45,7 @@ .Op Ar device ... .Nm .Op Fl fkvz +.Op Fl m Ar maxdumps .Op Ar directory Op Ar device ... .Sh DESCRIPTION The @@ -59,7 +60,7 @@ and enters a reboot message and information about the core dump into the system log. .Pp The options are as follows: -.Bl -tag -width indent +.Bl -tag -width ".Fl m Ar maxdumps" .It Fl C Check to see if a dump exists, and display a brief message to indicate the status. @@ -77,6 +78,12 @@ Force a dump to be taken even if either the dump was cleared or if the dump header information is inconsistent. .It Fl k Do not clear the dump after saving it. +.It Fl m Ar maxdumps +Maximum number of dumps to store. +Once the number of stored dumps is equal to +.Ar maxdumps +the counter will restart from +.Dv 0 . .It Fl v Print out some additional debugging information. Specify twice for more information. diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index 3a2547a..ca1cf13 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -90,6 +90,7 @@ __FBSDID("$FreeBSD$"); static int checkfor, compress, clear, force, keep, verbose; /* flags */ static int nfound, nsaved, nerr; /* statistics */ +static int maxdumps; extern FILE *zopen(const char *, const char *); @@ -178,12 +179,62 @@ writebounds(int bounds) { fclose(fp); } +static off_t +file_size(const char *path) +{ + struct stat sb; + + /* Ignore all errors, those file may not exists. */ + if (stat(path, &sb) == -1) + return (0); + return (sb.st_size); +} + +static off_t +saved_dump_size(int bounds) +{ + static char path[PATH_MAX]; + off_t dumpsize; + + dumpsize = 0; + + (void)snprintf(path, sizeof(path), "info.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "vmcore.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds); + dumpsize += file_size(path); + + return (dumpsize); +} + +static void +saved_dump_remove(int bounds) +{ + static char path[PATH_MAX]; + + (void)snprintf(path, sizeof(path), "info.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "vmcore.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds); + (void)unlink(path); +} + /* * Check that sufficient space is available on the disk that holds the * save directory. */ static int -check_space(const char *savedir, off_t dumpsize) +check_space(const char *savedir, off_t dumpsize, int bounds) { FILE *fp; off_t minfree, spacefree, totfree, needed; @@ -208,7 +259,8 @@ check_space(const char *savedir, off_t dumpsize) } needed = dumpsize / 1024 + 2; /* 2 for info file */ - if (((minfree > 0) ? spacefree : totfree) - needed < minfree) { + needed -= saved_dump_size(bounds); + if ((minfree > 0 ? spacefree : totfree) - needed < minfree) { syslog(LOG_WARNING, "no dump, not enough free space on device (%lld available, need %lld)", (long long)(minfree > 0 ? spacefree : totfree), @@ -367,7 +419,7 @@ DoTextdumpFile(int fd, off_t dumpsize, off_t lasthd, char *buf, static void DoFile(const char *savedir, const char *device) { - static char filename[PATH_MAX]; + static char infoname[PATH_MAX], corename[PATH_MAX]; static char *buf = NULL; struct kerneldumpheader kdhf, kdhl; off_t mediasize, dumpsize, firsthd, lasthd; @@ -382,6 +434,9 @@ DoFile(const char *savedir, const char *device) mediasize = 0; status = STATUS_UNKNOWN; + if (maxdumps > 0 && bounds == maxdumps) + bounds = 0; + if (buf == NULL) { buf = malloc(BUFFERSIZE); if (buf == NULL) { @@ -535,19 +590,22 @@ DoFile(const char *savedir, const char *device) if (verbose) printf("Checking for available free space\n"); - if (!check_space(savedir, dumpsize)) { + + if (!check_space(savedir, dumpsize, bounds)) { nerr++; goto closefd; } writebounds(bounds + 1); - snprintf(buf, sizeof(buf), "info.%d", bounds); + saved_dump_remove(bounds); + + snprintf(infoname, sizeof(infoname), "info.%d", bounds); /* * Create or overwrite any existing dump header files. */ - fdinfo = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fdinfo = open(infoname, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fdinfo < 0) { syslog(LOG_ERR, "%s: %m", buf); nerr++; @@ -555,16 +613,16 @@ DoFile(const char *savedir, const char *device) } oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ if (compress) { - snprintf(filename, sizeof(filename), "%s.%d.gz", + snprintf(corename, sizeof(corename), "%s.%d.gz", istextdump ? "textdump.tar" : "vmcore", bounds); - fp = zopen(filename, "w"); + fp = zopen(corename, "w"); } else { - snprintf(filename, sizeof(filename), "%s.%d", + snprintf(corename, sizeof(corename), "%s.%d", istextdump ? "textdump.tar" : "vmcore", bounds); - fp = fopen(filename, "w"); + fp = fopen(corename, "w"); } if (fp == NULL) { - syslog(LOG_ERR, "%s: %m", filename); + syslog(LOG_ERR, "%s: %m", corename); close(fdinfo); nerr++; goto closefd; @@ -585,15 +643,15 @@ DoFile(const char *savedir, const char *device) printheader(info, &kdhl, device, bounds, status); fclose(info); - syslog(LOG_NOTICE, "writing %score to %s", - compress ? "compressed " : "", filename); + syslog(LOG_NOTICE, "writing %score to %s/%s", + compress ? "compressed " : "", savedir, corename); if (istextdump) { if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device, - filename, fp) < 0) + corename, fp) < 0) goto closeall; } else { - if (DoRegularFile(fd, dumpsize, buf, device, filename, fp) + if (DoRegularFile(fd, dumpsize, buf, device, corename, fp) < 0) goto closeall; } @@ -601,10 +659,11 @@ DoFile(const char *savedir, const char *device) printf("\n"); if (fclose(fp) < 0) { - syslog(LOG_ERR, "error on %s: %m", filename); + syslog(LOG_ERR, "error on %s: %m", corename); nerr++; goto closeall; } + nsaved++; if (verbose) @@ -637,8 +696,8 @@ usage(void) fprintf(stderr, "%s\n%s\n%s\n", "usage: savecore -c [-v] [device ...]", " savecore -C [-v] [device ...]", - " savecore [-fkvz] [directory [device ...]]"); - exit (1); + " savecore [-fkvz] [-m maxdumps] [directory [device ...]]"); + exit(1); } int @@ -654,7 +713,7 @@ main(int argc, char **argv) openlog("savecore", LOG_PERROR, LOG_DAEMON); signal(SIGINFO, infohandler); - while ((ch = getopt(argc, argv, "Ccfkvz")) != -1) + while ((ch = getopt(argc, argv, "Ccfkm:vz")) != -1) switch(ch) { case 'C': checkfor = 1; @@ -668,6 +727,13 @@ main(int argc, char **argv) case 'k': keep = 1; break; + case 'm': + maxdumps = atoi(optarg); + if (maxdumps <= 0) { + syslog(LOG_ERR, "Invalid maxdump value"); + exit(1); + } + break; case 'v': verbose++; break; @@ -682,6 +748,8 @@ main(int argc, char **argv) usage(); if (clear && (compress || keep)) usage(); + if (maxdumps > 0 && (checkfor || clear)) + usage(); argc -= optind; argv += optind; if (argc >= 1 && !checkfor && !clear) { -- cgit v1.1 From 81a7aa503ccef5a267f9644672eb54b5256125de Mon Sep 17 00:00:00 2001 From: pjd Date: Sun, 16 Dec 2012 23:09:27 +0000 Subject: With rotating kernel dumps the higest dump number is not necessarily the last one. To make it easier to find the last one create symlinks with 'last' suffix that will point to the files of the last coredump, eg.: info.last -> info.5 textdump.tar.last.gz -> textdump.tar.5.gz Reviewed by: avg Obtained from: WHEEL Systems --- sbin/savecore/savecore.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'sbin/savecore') diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index ca1cf13..bdbf7e3 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -229,6 +229,17 @@ saved_dump_remove(int bounds) (void)unlink(path); } +static void +symlinks_remove(void) +{ + + (void)unlink("info.last"); + (void)unlink("vmcore.last"); + (void)unlink("vmcore.last.gz"); + (void)unlink("textdump.tar.last"); + (void)unlink("textdump.tar.last.gz"); +} + /* * Check that sufficient space is available on the disk that holds the * save directory. @@ -419,7 +430,7 @@ DoTextdumpFile(int fd, off_t dumpsize, off_t lasthd, char *buf, static void DoFile(const char *savedir, const char *device) { - static char infoname[PATH_MAX], corename[PATH_MAX]; + 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; @@ -664,6 +675,23 @@ DoFile(const char *savedir, const char *device) goto closeall; } + symlinks_remove(); + if (symlink(infoname, "info.last") == -1) { + syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", + savedir, "info.last"); + } + if (compress) { + snprintf(linkname, sizeof(linkname), "%s.last.gz", + istextdump ? "textdump.tar" : "vmcore"); + } else { + snprintf(linkname, sizeof(linkname), "%s.last", + istextdump ? "textdump.tar" : "vmcore"); + } + if (symlink(corename, linkname) == -1) { + syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", + savedir, linkname); + } + nsaved++; if (verbose) -- cgit v1.1