[Midnightbsd-cvs] src [10483] trunk/sbin/savecore/savecore.c: sync

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Jun 6 21:04:37 EDT 2018


Revision: 10483
          http://svnweb.midnightbsd.org/src/?rev=10483
Author:   laffer1
Date:     2018-06-06 21:04:36 -0400 (Wed, 06 Jun 2018)
Log Message:
-----------
sync

Modified Paths:
--------------
    trunk/sbin/savecore/Makefile
    trunk/sbin/savecore/savecore.8
    trunk/sbin/savecore/savecore.c

Property Changed:
----------------
    trunk/sbin/savecore/savecore.8

Modified: trunk/sbin/savecore/Makefile
===================================================================
--- trunk/sbin/savecore/Makefile	2018-06-07 00:37:07 UTC (rev 10482)
+++ trunk/sbin/savecore/Makefile	2018-06-07 01:04:36 UTC (rev 10483)
@@ -1,4 +1,5 @@
 # $MidnightBSD$
+# $FreeBSD: stable/10/sbin/savecore/Makefile 198236 2009-10-19 16:00:24Z ru $
 
 PROG=	savecore
 DPADD=	${LIBZ}

Modified: trunk/sbin/savecore/savecore.8
===================================================================
--- trunk/sbin/savecore/savecore.8	2018-06-07 00:37:07 UTC (rev 10482)
+++ trunk/sbin/savecore/savecore.8	2018-06-07 01:04:36 UTC (rev 10483)
@@ -1,3 +1,4 @@
+.\" $MidnightBSD$
 .\" Copyright (c) 1980, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
@@ -26,9 +27,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     From: @(#)savecore.8	8.1 (Berkeley) 6/5/93
-.\" $MidnightBSD$
+.\" $FreeBSD: stable/10/sbin/savecore/savecore.8 244320 2012-12-16 23:06:12Z pjd $
 .\"
-.Dd December 24, 2008
+.Dd December 17, 2012
 .Dt SAVECORE 8
 .Os
 .Sh NAME
@@ -37,12 +38,15 @@
 .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 Fl m Ar maxdumps
 .Op Ar directory Op Ar device ...
 .Sh DESCRIPTION
 The
@@ -57,7 +61,7 @@
 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.
@@ -75,6 +79,12 @@
 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.


Property changes on: trunk/sbin/savecore/savecore.8
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Modified: trunk/sbin/savecore/savecore.c
===================================================================
--- trunk/sbin/savecore/savecore.c	2018-06-07 00:37:07 UTC (rev 10482)
+++ trunk/sbin/savecore/savecore.c	2018-06-07 01:04:36 UTC (rev 10483)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2002 Poul-Henning Kamp
  * Copyright (c) 2002 Networks Associates Technology, Inc.
@@ -61,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/10/sbin/savecore/savecore.c 321212 2017-07-19 16:38:55Z ngie $");
 
 #include <sys/param.h>
 #include <sys/disk.h>
@@ -68,10 +69,12 @@
 #include <sys/kerneldump.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fstab.h>
 #include <paths.h>
+#include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -89,6 +92,7 @@
 
 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 *);
 
@@ -149,7 +153,10 @@
 	}
 
 	if (fgets(buf, sizeof buf, fp) == NULL) {
-		syslog(LOG_WARNING, "unable to read from bounds, using 0");
+		if (feof(fp))
+			syslog(LOG_WARNING, "bounds file is empty, using 0");
+		else
+			syslog(LOG_WARNING, "bounds file: %s", strerror(errno));
 		fclose(fp);
 		return (ret);
 	}
@@ -158,6 +165,7 @@
 	ret = (int)strtol(buf, NULL, 10);
 	if (ret == 0 && (errno == EINVAL || errno == ERANGE))
 		syslog(LOG_WARNING, "invalid value found in bounds, using 0");
+	fclose(fp);
 	return (ret);
 }
 
@@ -177,42 +185,122 @@
 	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);
+}
+
+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.
  */
 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;
+	off_t available, 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;
+	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)
 			minfree = 0;
-		else
-			minfree = atoi(buf);
+		else {
+			char *endp;
+
+			errno = 0;
+			minfree = strtoll(buf, &endp, 10);
+			if (minfree == 0 && errno != 0)
+				minfree = -1;
+			else {
+				while (*endp != '\0' && isspace(*endp))
+					endp++;
+				if (*endp != '\0' || minfree < 0)
+					minfree = -1;
+			}
+			if (minfree < 0)
+				syslog(LOG_WARNING,
+				    "`minfree` didn't contain a valid size "
+				    "(`%s`). Defaulting to 0", buf);
+		}
 		(void)fclose(fp);
 	}
 
+	available = minfree > 0 ? spacefree - minfree : totfree;
 	needed = dumpsize / 1024 + 2;	/* 2 for info file */
- 	if (((minfree > 0) ? spacefree : totfree) - needed < minfree) {
+	needed -= saved_dump_size(bounds);
+	if (available < needed) {
 		syslog(LOG_WARNING,
-	"no dump, not enough free space on device (%lld available, need %lld)",
-		    (long long)(minfree > 0 ? spacefree : totfree),
-		    (long long)needed);
+		    "no dump: not enough free space on device (need at least "
+		    "%jdkB for dump; %jdkB available; %jdkB reserved)",
+		    (intmax_t)needed,
+		    (intmax_t)available + minfree,
+		    (intmax_t)minfree);
 		return (0);
 	}
 	if (spacefree - needed < 0)
@@ -261,7 +349,7 @@
 					if (he >= hs + BLOCKSIZE)
 						break;
 				}
-			
+
 				/* back down to a block boundary */
 				he &= BLOCKMASK;
 
@@ -367,7 +455,7 @@
 static void
 DoFile(const char *savedir, const char *device)
 {
-	static char filename[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;
@@ -382,6 +470,9 @@
 	mediasize = 0;
 	status = STATUS_UNKNOWN;
 
+	if (maxdumps > 0 && bounds == maxdumps)
+		bounds = 0;
+
 	if (buf == NULL) {
 		buf = malloc(BUFFERSIZE);
 		if (buf == NULL) {
@@ -393,7 +484,7 @@
 	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;
@@ -409,8 +500,8 @@
 	}
 
 	if (verbose) {
-		printf("mediasize = %lld\n", (long long)mediasize);
-		printf("sectorsize = %u\n", sectorsize);
+		printf("mediasize = %lld bytes\n", (long long)mediasize);
+		printf("sectorsize = %u bytes\n", sectorsize);
 	}
 
 	lasthd = mediasize - sectorsize;
@@ -432,7 +523,7 @@
 			syslog(LOG_ERR,
 			    "unknown version (%d) in last dump header on %s",
 			    dtoh32(kdhl.version), device);
-	
+
 			status = STATUS_BAD;
 			if (force == 0)
 				goto closefd;
@@ -443,7 +534,7 @@
 			syslog(LOG_ERR,
 			    "unknown version (%d) in last dump header on %s",
 			    dtoh32(kdhl.version), device);
-	
+
 			status = STATUS_BAD;
 			if (force == 0)
 				goto closefd;
@@ -471,7 +562,7 @@
 			syslog(LOG_ERR,
 			    "unknown version (%d) in last dump header on %s",
 			    dtoh32(kdhl.version), device);
-	
+
 			status = STATUS_BAD;
 			if (force == 0)
 				goto closefd;
@@ -535,7 +626,8 @@
 
 	if (verbose)
 		printf("Checking for available free space\n");
-	if (!check_space(savedir, dumpsize)) {
+
+	if (!check_space(savedir, dumpsize, bounds)) {
 		nerr++;
 		goto closefd;
 	}
@@ -542,29 +634,31 @@
 
 	writebounds(bounds + 1);
 
-	sprintf(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);
+		syslog(LOG_ERR, "%s: %m", infoname);
 		nerr++;
 		goto closefd;
 	}
 	oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/
 	if (compress) {
-		sprintf(filename, "%s.%d.gz", istextdump ? "textdump.tar" :
-		    "vmcore", bounds);
-		fp = zopen(filename, "w");
+		snprintf(corename, sizeof(corename), "%s.%d.gz",
+		    istextdump ? "textdump.tar" : "vmcore", bounds);
+		fp = zopen(corename, "w");
 	} else {
-		sprintf(filename, "%s.%d", istextdump ? "textdump.tar" :
-		    "vmcore", bounds);
-		fp = fopen(filename, "w");
+		snprintf(corename, sizeof(corename), "%s.%d",
+		    istextdump ? "textdump.tar" : "vmcore", bounds);
+		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 +679,15 @@
 	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 +695,28 @@
 		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;
+		goto closefd;
 	}
+
+	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)
@@ -611,7 +723,7 @@
 		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);
@@ -635,10 +747,10 @@
 usage(void)
 {
 	fprintf(stderr, "%s\n%s\n%s\n",
-	    "usage: savecore -c",
-	    "       savecore -C [-v] [directory device]",
-	    "       savecore [-fkvz] [directory [device ...]]");
-	exit (1);
+	    "usage: savecore -c [-v] [device ...]",
+	    "       savecore -C [-v] [device ...]",
+	    "       savecore [-fkvz] [-m maxdumps] [directory [device ...]]");
+	exit(1);
 }
 
 int
@@ -654,7 +766,7 @@
 	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;
@@ -662,15 +774,22 @@
 		case 'c':
 			clear = 1;
 			break;
+		case 'f':
+			force = 1;
+			break;
 		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;
-		case 'f':
-			force = 1;
-			break;
 		case 'z':
 			compress = 1;
 			break;
@@ -680,9 +799,13 @@
 		}
 	if (checkfor && (clear || force || keep))
 		usage();
+	if (clear && (compress || keep))
+		usage();
+	if (maxdumps > 0 && (checkfor || clear))
+		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]);



More information about the Midnightbsd-cvs mailing list