From dm@home.dinoex.sub.org  Wed Aug  1 03:19:24 2001
Return-Path: <dm@home.dinoex.sub.org>
Received: from net2.dinoex.sub.org (net2.dinoex.de [212.184.201.182])
	by hub.freebsd.org (Postfix) with ESMTP id 9563337B401
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  1 Aug 2001 03:19:22 -0700 (PDT)
	(envelope-from dm@home.dinoex.sub.org)
Received: from home.dinoex.sub.org (home [217.6.200.196])
	by net2.dinoex.sub.org (8.11.4/8.11.4) with ESMTP id f71AIo819995
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 1 Aug 2001 12:18:51 +0200 (CEST)
	(envelope-from dm@home.dinoex.sub.org)
Received: (from dm@localhost)
	by home.dinoex.sub.org (8.11.5/8.11.4) id f71AHwF66500; Wed, 1 Aug 2001 12:17:58 +0200 (CEST)
	(envelope-from dm)
Message-Id: <200108011017.f71AHwF66500@home.dinoex.sub.org>
Date: Wed, 1 Aug 2001 12:17:58 +0200 (CEST)
From: dirk.meyer@dinoex.sub.org
Reply-To: dirk.meyer@dinoex.sub.org
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [PATCH] newsyslog can support time as extension
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         29363
>Category:       bin
>Synopsis:       [patch] newsyslog(8) can support time as extension
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    simon
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 01 03:20:01 PDT 2001
>Closed-Date:    Fri Mar 15 23:41:37 UTC 2013
>Last-Modified:  Fri Mar 15 23:41:37 UTC 2013
>Originator:     Dirk Meyer
>Release:        FreeBSD 4.3-STABLE i386
>Organization:
privat
>Environment:

System: FreeBSD 4.3-STABLE: Fri Jul 20 22:04:45 CEST 2001 i386

Description:

-------

 If I recall, I suggested that this support optional renaming of files with
 a pre-defined text string of %x variables, which would expand into defined
 values, like the date(1) command:

          messages.072501-01:10.gz

 You wouldn't necessarily need to modify the newsyslog.conf file, but could
 implement this as a commandline switch, which would control this globally
 (not very flexible, but less invasive).  So, one could modify the crontab
 to do:

 0       *       *       *       *       root    newsyslog -T %m%d%y-%H-%M

-------

>Description:
>How-To-Repeat:

>Fix:

Diff for 4.3 Current

Index: newsyslog.8
===================================================================
RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.8,v
retrieving revision 1.32
diff -u -r1.32 newsyslog.8
--- newsyslog.8	2001/07/30 15:17:17	1.32
+++ newsyslog.8	2001/08/01 10:09:09
@@ -28,6 +28,7 @@
 .Op Fl Fnrv
 .Op Fl f Ar config_file
 .Op Fl a Ar directory
+.Op Fl T Ar timeformat
 .Op Ar
 .Sh DESCRIPTION
 .Nm Newsyslog
@@ -354,6 +355,14 @@
 to trim the logs, even if the trim conditions have not been met.  This
 option is useful for diagnosing system problems by providing you with
 fresh logs that contain only the problems.
+.It Fl T
+Time based extension
+.Nm
+to rename all logs that get trimmed into with an extension based on the
+argument given by this option. This option can be any strfime(3) string.
+ This function is intended for permantely storing of logfiles.  If the
+patten results to an already existing file, operations breaks without
+cleanup, leaving stale logs in place, that might be ovewritten.
 .El
 .Pp
 If additional command line arguments are given,
Index: newsyslog.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.c,v
retrieving revision 1.37
diff -u -r1.37 newsyslog.c
--- newsyslog.c	2001/07/31 16:25:55	1.37
+++ newsyslog.c	2001/08/01 10:09:12
@@ -90,7 +90,9 @@
 int needroot = 1;		/* Root privs are necessary */
 int noaction = 0;		/* Don't do anything, just show it */
 int force = 0;			/* Force the trim no matter what */
-char *archdirname;		/* Directory path to old logfiles archive */
+int timename = 0;		/* Use time of rotation as suffix */
+const char *archdirname;	/* Directory path to old logfiles archive */
+const char *timearg;		/* Pattern to expand into extension */
 const char *conf = _PATH_CONF;	/* Configuration file to use */
 time_t timenow;
 
@@ -227,7 +229,7 @@
 	if ((p = strchr(hostname, '.'))) {
 		*p = '\0';
 	}
-	while ((c = getopt(argc, argv, "nrvFf:a:t:")) != -1)
+	while ((c = getopt(argc, argv, "nrvFf:a:t:T:")) != -1)
 		switch (c) {
 		case 'n':
 			noaction++;
@@ -248,6 +250,10 @@
 		case 'F':
 			force++;
 			break;
+		case 'T':
+			timename++;
+			timearg = optarg;
+			break;
 		default:
 			usage();
 		}
@@ -516,6 +522,7 @@
 	int notified, need_notification, fd, _numdays;
 	struct stat st;
 	pid_t pid;
+	time_t now;
 
 #ifdef _IBMR2
 	/*
@@ -633,6 +640,16 @@
 		if (noaction)
 			printf("mv %s to %s\n", log, file1);
 		else {
+			/* change file1 to hold the new name */
+			if (timename) {
+				now = time( NULL );
+				(void) strftime(file2, sizeof(file2), timearg, localtime( &now ) );
+				if (archtodir)
+					(void) snprintf(file1, sizeof(file1), "%s/%s.%s", dirpart, namepart, file2);
+				else
+					(void) snprintf(file1, sizeof(file1), "%s.%s", log, file2);
+			}
+
 			if (archtodir)
 				movefile(log, file1, perm, owner_uid,
 				    group_gid);
@@ -683,26 +700,18 @@
 			    "log %s not compressed because daemon not notified",
 			    log);
 		else if (noaction)
-			printf("Compress %s.0\n", log);
+			printf("Compress %s\n", file1);
 		else {
 			if (notified) {
 				if (verbose)
 					printf("small pause to allow daemon to close log\n");
 				sleep(10);
-			}
-			if (archtodir) {
-				(void) snprintf(file1, sizeof(file1), "%s/%s",
-				    dirpart, namepart);
-				if (flags & CE_COMPACT)
-					compress_log(file1);
-				else if (flags & CE_BZCOMPACT)
-					bzcompress_log(file1);
-			} else {
-				if (flags & CE_COMPACT)
-					compress_log(log);
-				else if (flags & CE_BZCOMPACT)
-					bzcompress_log(log);
 			}
+			compress_log(file1);
+			if (flags & CE_COMPACT)
+				compress_log(file1);
+			else if (flags & CE_BZCOMPACT)
+				bzcompress_log(file1);
 		}
 	}
 }
@@ -729,7 +738,7 @@
 	pid_t pid;
 	char tmp[MAXPATHLEN];
 
-	(void) snprintf(tmp, sizeof(tmp), "%s.0", log);
+	(void) snprintf(tmp, sizeof(tmp), "%s", log);
 	pid = fork();
 	if (pid < 0)
 		err(1, "gzip fork");


Diff for 4.3 Stable before BZIP support.

Index: newsyslog/newsyslog.8
===================================================================
RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.8,v
retrieving revision 1.31
diff -u -r1.31 newsyslog.8
--- newsyslog/newsyslog.8	2001/07/19 15:52:02	1.31
+++ newsyslog/newsyslog.8	2001/07/24 13:49:04
@@ -28,6 +28,7 @@
 .Op Fl Fnrv
 .Op Fl f Ar config_file
 .Op Fl a Ar directory
+.Op Fl T Ar timeformat
 .Op Ar
 .Sh DESCRIPTION
 .Nm Newsyslog
@@ -349,6 +350,14 @@
 to trim the logs, even if the trim conditions have not been met.  This
 option is useful for diagnosing system problems by providing you with
 fresh logs that contain only the problems.
+.It Fl T
+Time based extension
+.Nm
+to rename all logs that get trimmed into with an extension based on the
+argument given by this option. This option can be any strfime(3) string.
+ This function is intended for permantely storing of logfiles.  If the
+patten results to an already existing file, operations breaks without
+cleanup, leaving stale logs in place, that might be ovewritten.
 .El
 .Pp
 If additional command line arguments are given,
Index: newsyslog/newsyslog.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.c,v
retrieving revision 1.31
diff -u -r1.31 newsyslog.c
--- newsyslog/newsyslog.c	2001/07/09 09:24:00	1.31
+++ newsyslog/newsyslog.c	2001/07/24 13:49:07
@@ -86,7 +86,9 @@
 int needroot = 1;		/* Root privs are necessary */
 int noaction = 0;		/* Don't do anything, just show it */
 int force = 0;			/* Force the trim no matter what */
+int timename = 0;		/* Use time of rotation as suffix */
 char *archdirname;		/* Directory path to old logfiles archive */
+char *timearg;			/* Pattern to expand into extension */
 char *conf = _PATH_CONF;	/* Configuration file to use */
 time_t timenow;
 
@@ -214,7 +216,7 @@
 	if ((p = strchr(hostname, '.'))) {
 		*p = '\0';
 	}
-	while ((c = getopt(argc, argv, "nrvFf:a:t:")) != -1)
+	while ((c = getopt(argc, argv, "nrvFf:a:t:T:")) != -1)
 		switch (c) {
 		case 'n':
 			noaction++;
@@ -235,6 +237,10 @@
 		case 'F':
 			force++;
 			break;
+		case 'T':
+			timename++;
+			timearg = optarg;
+			break;
 		default:
 			usage();
 		}
@@ -483,6 +489,7 @@
 	int notified, need_notification, fd, _numdays;
 	struct stat st;
 	pid_t pid;
+	time_t now;
 
 #ifdef _IBMR2
 	/*
@@ -581,6 +588,16 @@
 		if (noaction)
 			printf("mv %s to %s\n", log, file1);
 		else {
+			/* change file1 to hold the new name */
+			if (timename) {
+				now = time( NULL );
+				(void) strftime(file2, sizeof(file2), timearg, localtime( &now ) );
+				if (archtodir)
+					(void) snprintf(file1, sizeof(file1), "%s/%s.%s", dirpart, namepart, file2);
+				else
+					(void) snprintf(file1, sizeof(file1), "%s.%s", log, file2);
+			}
+
 			if (archtodir)
 				movefile(log, file1, perm, owner_uid, group_gid);
 			else
@@ -628,19 +645,14 @@
 		if (need_notification && !notified)
 			warnx("log %s not compressed because daemon not notified", log);
 		else if (noaction)
-			printf("Compress %s.0\n", log);
+			printf("Compress %s\n", file1);
 		else {
 			if (notified) {
 				if (verbose)
 					printf("small pause to allow daemon to close log\n");
 				sleep(10);
-			}
-			if (archtodir) {
-				(void) snprintf(file1, sizeof(file1), "%s/%s", dirpart, namepart);
-				compress_log(file1);
-			} else {
-				compress_log(log);
 			}
+			compress_log(file1);
 		}
 	}
 }
@@ -667,7 +679,7 @@
 	pid_t pid;
 	char tmp[MAXPATHLEN];
 
-	(void) snprintf(tmp, sizeof(tmp), "%s.0", log);
+	(void) snprintf(tmp, sizeof(tmp), "%s", log);
 	pid = fork();
 	if (pid < 0)
 		err(1, "fork");
>Release-Note:
>Audit-Trail:

From: dirk.meyer@dinoex.sub.org (Dirk Meyer)
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: bin/29363: [PATCH] newsyslog can support time as
	extension
Date: Wed, 01 Aug 2001 12:33:27 +0200

 The stable patch had an stale line (conflicts).
 here the correct version.
 
 Index: newsyslog.8
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.8,v
 retrieving revision 1.32
 diff -u -r1.32 newsyslog.8
 --- newsyslog.8	2001/07/30 15:17:17	1.32
 +++ newsyslog.8	2001/08/01 10:28:56
 @@ -28,6 +28,7 @@
  .Op Fl Fnrv
  .Op Fl f Ar config_file
  .Op Fl a Ar directory
 +.Op Fl T Ar timeformat
  .Op Ar
  .Sh DESCRIPTION
  .Nm Newsyslog
 @@ -354,6 +355,14 @@
  to trim the logs, even if the trim conditions have not been met.  This
  option is useful for diagnosing system problems by providing you with
  fresh logs that contain only the problems.
 +.It Fl T
 +Time based extension
 +.Nm
 +to rename all logs that get trimmed into with an extension based on the
 +argument given by this option. This option can be any strfime(3) string.
 + This function is intended for permantely storing of logfiles.  If the
 +patten results to an already existing file, operations breaks without
 +cleanup, leaving stale logs in place, that might be ovewritten.
  .El
  .Pp
  If additional command line arguments are given,
 Index: newsyslog.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.c,v
 retrieving revision 1.37
 diff -u -r1.37 newsyslog.c
 --- newsyslog.c	2001/07/31 16:25:55	1.37
 +++ newsyslog.c	2001/08/01 10:28:59
 @@ -90,7 +90,9 @@
  int needroot = 1;		/* Root privs are necessary */
  int noaction = 0;		/* Don't do anything, just show it */
  int force = 0;			/* Force the trim no matter what */
 -char *archdirname;		/* Directory path to old logfiles archive */
 +int timename = 0;		/* Use time of rotation as suffix */
 +const char *archdirname;	/* Directory path to old logfiles archive */
 +const char *timearg;		/* Pattern to expand into extension */
  const char *conf = _PATH_CONF;	/* Configuration file to use */
  time_t timenow;
  
 @@ -227,7 +229,7 @@
  	if ((p = strchr(hostname, '.'))) {
  		*p = '\0';
  	}
 -	while ((c = getopt(argc, argv, "nrvFf:a:t:")) != -1)
 +	while ((c = getopt(argc, argv, "nrvFf:a:t:T:")) != -1)
  		switch (c) {
  		case 'n':
  			noaction++;
 @@ -248,6 +250,10 @@
  		case 'F':
  			force++;
  			break;
 +		case 'T':
 +			timename++;
 +			timearg = optarg;
 +			break;
  		default:
  			usage();
  		}
 @@ -516,6 +522,7 @@
  	int notified, need_notification, fd, _numdays;
  	struct stat st;
  	pid_t pid;
 +	time_t now;
  
  #ifdef _IBMR2
  	/*
 @@ -633,6 +640,16 @@
  		if (noaction)
  			printf("mv %s to %s\n", log, file1);
  		else {
 +			/* change file1 to hold the new name */
 +			if (timename) {
 +				now = time( NULL );
 +				(void) strftime(file2, sizeof(file2), timearg, localtime( &now ) );
 +				if (archtodir)
 +					(void) snprintf(file1, sizeof(file1), "%s/%s.%s", dirpart, namepart, file2);
 +				else
 +					(void) snprintf(file1, sizeof(file1), "%s.%s", log, file2);
 +			}
 +
  			if (archtodir)
  				movefile(log, file1, perm, owner_uid,
  				    group_gid);
 @@ -683,26 +700,17 @@
  			    "log %s not compressed because daemon not notified",
  			    log);
  		else if (noaction)
 -			printf("Compress %s.0\n", log);
 +			printf("Compress %s\n", file1);
  		else {
  			if (notified) {
  				if (verbose)
  					printf("small pause to allow daemon to close log\n");
  				sleep(10);
 -			}
 -			if (archtodir) {
 -				(void) snprintf(file1, sizeof(file1), "%s/%s",
 -				    dirpart, namepart);
 -				if (flags & CE_COMPACT)
 -					compress_log(file1);
 -				else if (flags & CE_BZCOMPACT)
 -					bzcompress_log(file1);
 -			} else {
 -				if (flags & CE_COMPACT)
 -					compress_log(log);
 -				else if (flags & CE_BZCOMPACT)
 -					bzcompress_log(log);
  			}
 +			if (flags & CE_COMPACT)
 +				compress_log(file1);
 +			else if (flags & CE_BZCOMPACT)
 +				bzcompress_log(file1);
  		}
  	}
  }
 @@ -729,7 +737,7 @@
  	pid_t pid;
  	char tmp[MAXPATHLEN];
  
 -	(void) snprintf(tmp, sizeof(tmp), "%s.0", log);
 +	(void) snprintf(tmp, sizeof(tmp), "%s", log);
  	pid = fork();
  	if (pid < 0)
  		err(1, "gzip fork");

From: dirk.meyer@dinoex.sub.org (Dirk Meyer)
To: FreeBSD-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: bin/29363: [BPATCH] newsyslog can support time as
	extension
Date: Wed, 29 Jan 2003 06:29:24 +0100

 Here the merge to CURRENT:
 
 This patch does:
 - Add option T for timeformat
 - reduce warnings using const
 - Fix warnings on non static funtions sob() and son()
 - reduce duplicate code, by using the filename already set
 
 Tested and verified with the arguments:
 $ newsyslog -v -n -T %Y-%m-%d-%H:%M -a /tmp
 $ newsyslog -v -n -T %Y-%m-%d-%H:%M
 $ newsyslog -v -n
 (and without -n) 
 
 kind regards Dirk
 
 - Dirk Meyer, Im Grund 4, 34317 Habichtswald, Germany
 - [dirk.meyer@dinoex.sub.org],[dirk.meyer@guug.de],[dinoex@FreeBSD.org]
 
 Index: newsyslog/newsyslog.8
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.8,v
 retrieving revision 1.38
 diff -u -r1.38 newsyslog.8
 --- newsyslog/newsyslog.8	27 Dec 2002 12:15:38 -0000	1.38
 +++ newsyslog/newsyslog.8	29 Jan 2003 04:04:41 -0000
 @@ -28,6 +28,7 @@
  .Op Fl Fnrv
  .Op Fl f Ar config_file
  .Op Fl a Ar directory
 +.Op Fl T Ar timeformat
  .Op Ar
  .Sh DESCRIPTION
  The
 @@ -387,6 +388,14 @@
  to trim the logs, even if the trim conditions have not been met.  This
  option is useful for diagnosing system problems by providing you with
  fresh logs that contain only the problems.
 +.It Fl T
 +Time based extension
 +.Nm
 +to rename all logs that get trimmed into with an extension based on the
 +argument given by this option. This option can be any strfime(3) string.
 + This function is intended for permantely storing of logfiles.  If the
 +patten results to an already existing file, operations breaks without
 +cleanup, leaving stale logs in place, that might be ovewritten.
  .El
  .Pp
  If additional command line arguments are given,
 Index: newsyslog/newsyslog.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.c,v
 retrieving revision 1.49
 diff -u -r1.49 newsyslog.c
 --- newsyslog/newsyslog.c	21 Dec 2002 22:27:26 -0000	1.49
 +++ newsyslog/newsyslog.c	29 Jan 2003 04:04:45 -0000
 @@ -95,7 +95,9 @@
  int needroot = 1;		/* Root privs are necessary */
  int noaction = 0;		/* Don't do anything, just show it */
  int force = 0;			/* Force the trim no matter what */
 -char *archdirname;		/* Directory path to old logfiles archive */
 +int timename = 0;		/* Use time of rotation as suffix */
 +const char *archdirname;	/* Directory path to old logfiles archive */
 +const char *timearg;		/* Pattern to expand into extension */
  const char *conf = _PATH_CONF;	/* Configuration file to use */
  time_t timenow;
  
 @@ -248,7 +250,7 @@
  	if ((p = strchr(hostname, '.'))) {
  		*p = '\0';
  	}
 -	while ((c = getopt(argc, argv, "nrvFf:a:")) != -1)
 +	while ((c = getopt(argc, argv, "nrvFf:a:T:")) != -1)
  		switch (c) {
  		case 'n':
  			noaction++;
 @@ -269,6 +271,10 @@
  		case 'F':
  			force++;
  			break;
 +		case 'T':
 +			timename++;
 +			timearg = optarg;
 +			break;
  		default:
  			usage();
  		}
 @@ -554,6 +560,7 @@
  	int notified, need_notification, fd, _numdays;
  	struct stat st;
  	pid_t pid;
 +	time_t now;
  
  #ifdef _IBMR2
  	/*
 @@ -668,6 +675,18 @@
  		else
  			(void) unlink(log);
  	} else {
 +		if (timename) {
 +			/* change file1 to hold the new name */
 +			now = time( NULL );
 +			(void) strftime(file2, sizeof(file2), timearg,
 +				localtime( &now ) );
 +			if (archtodir)
 +				(void) snprintf(file1, sizeof(file1),
 +					"%s/%s.%s", dirpart, namepart, file2);
 +			else
 +				(void) snprintf(file1, sizeof(file1),
 +					"%s.%s", log, file2);
 +		}
  		if (noaction)
  			printf("mv %s to %s\n", log, file1);
  		else {
 @@ -729,30 +748,19 @@
  			    "log %s not compressed because daemon not notified",
  			    log);
  		else if (noaction)
 -			printf("Compress %s.0\n", log);
 +			printf("Compress %s\n", file1);
  		else {
  			if (notified) {
  				if (verbose)
  					printf("small pause to allow daemon to close log\n");
  				sleep(10);
  			}
 -			if (archtodir) {
 -				(void) snprintf(file1, sizeof(file1), "%s/%s",
 -				    dirpart, namepart);
 -				if (flags & CE_COMPACT)
 -					compress_log(file1,
 -					    flags & CE_COMPACTWAIT);
 -				else if (flags & CE_BZCOMPACT)
 -					bzcompress_log(file1,
 -					    flags & CE_COMPACTWAIT);
 -			} else {
 -				if (flags & CE_COMPACT)
 -					compress_log(log,
 -					    flags & CE_COMPACTWAIT);
 -				else if (flags & CE_BZCOMPACT)
 -					bzcompress_log(log,
 -					    flags & CE_COMPACTWAIT);
 -			}
 +			if (flags & CE_COMPACT)
 +				compress_log(file1,
 +				    flags & CE_COMPACTWAIT);
 +			else if (flags & CE_BZCOMPACT)
 +				bzcompress_log(file1,
 +				    flags & CE_COMPACTWAIT);
  		}
  	}
  }
 @@ -781,7 +789,7 @@
  
  	while (dowait && (wait(NULL) > 0 || errno == EINTR))
  		;
 -	(void) snprintf(tmp, sizeof(tmp), "%s.0", log);
 +	(void) snprintf(tmp, sizeof(tmp), "%s", log);
  	pid = fork();
  	if (pid < 0)
  		err(1, "gzip fork");
 @@ -800,7 +808,7 @@
  
  	while (dowait && (wait(NULL) > 0 || errno == EINTR))
  		;
 -	snprintf(tmp, sizeof(tmp), "%s.0", log);
 +	snprintf(tmp, sizeof(tmp), "%s", log);
  	pid = fork();
  	if (pid < 0)
  		err(1, "bzip2 fork");
 @@ -888,7 +896,7 @@
  }
  
  /* Skip Over Blanks */
 -char *
 +static char *
  sob(char *p)
  {
  	while (p && *p && isspace(*p))
 @@ -897,7 +905,7 @@
  }
  
  /* Skip Over Non-Blanks */
 -char *
 +static char *
  son(char *p)
  {
  	while (p && *p && !isspace(*p))
Responsible-Changed-From-To: freebsd-bugs->gad 
Responsible-Changed-By: gad 
Responsible-Changed-When: Mon Mar 3 05:28:05 PST 2003 
Responsible-Changed-Why:  
I am doing a lot of work on newsyslog lately, and I will look into doing 
some option along the lines of what you have implemented here.  I might do 
it slightly different, as I have some other "suffix-naming" options that 
I might want to implement. 

Note that it may take me a few weeks before I actually get to this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=29363 

From: dirk.meyer@dinoex.sub.org (Dirk Meyer)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/29363: [PATCH] newsyslog can support time as
	extension
Date: Sun, 19 Mar 2006 12:28:14 +0100

 Patch updated to current and tested.
 
 kind regards Dirk
 (ports committer only)
 
 - Dirk Meyer, Im Grund 4, 34317 Habichtswald, Germany
 - [dirk.meyer@dinoex.sub.org],[dirk.meyer@guug.de],[dinoex@FreeBSD.org]
 
 Index: newsyslog.8
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.8,v
 retrieving revision 1.51
 diff -u -r1.51 newsyslog.8
 --- newsyslog.8	14 Jun 2005 12:26:35 -0000	1.51
 +++ newsyslog.8	19 Mar 2006 11:22:50 -0000
 @@ -30,6 +30,7 @@
  .Op Fl a Ar directory
  .Op Fl d Ar directory
  .Op Fl f Ar config_file
 +.Op Fl T Ar timeformat
  .Op Ar
  .Sh DESCRIPTION
  The
 @@ -211,6 +212,14 @@
  will return faster, since
  .Nm
  normally waits a few seconds after any signal that is sent.
 +.It Fl T Ar timeformat
 +Time based extension
 +.Nm
 +to rename all logs that get trimmed into with an extension based on the
 +argument given by this option. This option can be any strfime(3) string.
 + This function is intended for permantely storing of logfiles.  If the
 +patten results to an already existing file, operations breaks without
 +cleanup, leaving stale logs in place, that might be ovewritten.
  .El
  .Pp
  If additional command line arguments are given,
 Index: newsyslog.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.c,v
 retrieving revision 1.103
 diff -u -r1.103 newsyslog.c
 --- newsyslog.c	20 Jan 2006 05:18:01 -0000	1.103
 +++ newsyslog.c	19 Mar 2006 11:22:54 -0000
 @@ -182,14 +182,16 @@
  int norotate = 0;		/* Don't rotate */
  int nosignal;			/* Do not send any signals */
  int force = 0;			/* Force the trim no matter what */
 +int timename = 0;		/* Use time of rotation as suffix */
  int rotatereq = 0;		/* -R = Always rotate the file(s) as given */
  				/*    on the command (this also requires   */
  				/*    that a list of files *are* given on  */
  				/*    the run command). */
  char *requestor;		/* The name given on a -R request */
 -char *archdirname;		/* Directory path to old logfiles archive */
 -char *destdir = NULL;		/* Directory to treat at root for logs */
 +const char *archdirname;	/* Directory path to old logfiles archive */
 +const char *destdir = NULL;	/* Directory to treat at root for logs */
  const char *conf;		/* Configuration file to use */
 +const char *timearg;		/* Pattern to expand into extension */
  
  struct ptime_data *dbg_timenow;	/* A "timenow" value set via -D option */
  struct ptime_data *timenow;	/* The time to use for checking at-fields */
 @@ -699,7 +701,7 @@
  		*p = '\0';
  
  	/* Parse command line options. */
 -	while ((ch = getopt(argc, argv, "a:d:f:nrsvCD:FNR:")) != -1)
 +	while ((ch = getopt(argc, argv, "a:d:f:nrsvCD:FNR:T:")) != -1)
  		switch (ch) {
  		case 'a':
  			archtodir++;
 @@ -747,6 +749,10 @@
  			rotatereq++;
  			requestor = strdup(optarg);
  			break;
 +		case 'T':
 +			timename++;
 +			timearg = optarg;
 +			break;
  		case 'm':	/* Used by OpenBSD for "monitor mode" */
  		default:
  			usage();
 @@ -849,7 +855,7 @@
  
  	fprintf(stderr,
  	    "usage: newsyslog [-CFNnrsv] [-a directory] [-d directory] [-f config-file]\n"
 -	    "                 [ [-R requestor] filename ... ]\n");
 +	    "                 [-T timeformat] [ [-R requestor] filename ... ]\n");
  	exit(1);
  }
  
 @@ -1586,6 +1592,19 @@
  	}
  
  	if (ent->numlogs > 0) {
 +		if (timename) {
 +			time_t now;
 +			/* change file1 to hold the new name */
 +			now = time( NULL );
 +			(void) strftime(file2, sizeof(file2), timearg,
 +				localtime( &now ) );
 +			if (archtodir)
 +				(void) snprintf(file1, sizeof(file1),
 +					"%s/%s.%s", dirpart, namepart, file2);
 +			else
 +				(void) snprintf(file1, sizeof(file1),
 +					"%s.%s", ent->log, file2);
 +		}
  		if (noaction) {
  			/*
  			 * Note that savelog() may succeed with using link()

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/29363: commit references a PR
Date: Thu, 22 Jul 2010 11:23:33 +0000 (UTC)

 Author: simon
 Date: Thu Jul 22 11:23:18 2010
 New Revision: 210372
 URL: http://svn.freebsd.org/changeset/base/210372
 
 Log:
   Add support for creating the archived log filenames using a time-stamp
   instead of the traditional simple counter.
   
   Using the time-stamp based file-names, once a log file is archived, it
   will not change name until it is deleted.  This means that many backup
   systems will only perform one backup of the archived log file, instead
   for performing a new backup of the logfile upon each logfile rotation.
   
   This implementation is separate from the patches in the mentioned PR,
   as I wasn't aware of the existence of the PR until after I had
   implemented the same functionality as the patches in the PR provide.
   Unlike the PR, this new code does honor the 'log count' in
   newsyslog.conf so old logfiles are deleted.  This new code does not
   currently support never deleting the archived logfiles.
   
   PR:		bin/29363
   MFC after:	3 weeks
 
 Modified:
   head/usr.sbin/newsyslog/newsyslog.8
   head/usr.sbin/newsyslog/newsyslog.c
 
 Modified: head/usr.sbin/newsyslog/newsyslog.8
 ==============================================================================
 --- head/usr.sbin/newsyslog/newsyslog.8	Thu Jul 22 10:24:28 2010	(r210371)
 +++ head/usr.sbin/newsyslog/newsyslog.8	Thu Jul 22 11:23:18 2010	(r210372)
 @@ -30,6 +30,7 @@
  .Op Fl a Ar directory
  .Op Fl d Ar directory
  .Op Fl f Ar config_file
 +.Op Fl t Ar timefmt
  .Op Ar
  .Sh DESCRIPTION
  The
 @@ -50,6 +51,11 @@ the last period's logs in it,
  has the next to last
  period's logs in it, and so on, up to a user-specified number of
  archived logs.
 +It is also possible to let archived log filenames be created using the
 +time the log file was archived instead of the sequential number using
 +the
 +.Fl t
 +option.
  Optionally the archived logs can be compressed to save
  space.
  .Pp
 @@ -141,6 +147,31 @@ However, this option is most likely to b
  with the
  .Fl R
  option, and in that case the compression will be done.
 +.It Fl t Ar timefmt
 +If specified
 +.Nm
 +will create the
 +.Dq rotated
 +logfiles using the specified time format instead of the default
 +sequential filenames.
 +The time format is described in the
 +.Xr strftime 3
 +manual page.
 +If the
 +.Ar timefmt
 +argument is set to an empty string or the string
 +.Dq DEFAULT ,
 +the default built in time format
 +is used.
 +If the
 +.Ar timefmt
 +string is changed the old files created using the previous time format
 +will not be be automatically removed (unless the new format is very
 +similar to the old format).
 +This is also the case when changing from sequential filenames to time
 +based file names, and the other way around.
 +The time format should contain at least year, month, day, and hour to
 +make sure rotating of old logfiles can select the correct logfiles.
  .It Fl C
  If specified once, then
  .Nm
 
 Modified: head/usr.sbin/newsyslog/newsyslog.c
 ==============================================================================
 --- head/usr.sbin/newsyslog/newsyslog.c	Thu Jul 22 10:24:28 2010	(r210371)
 +++ head/usr.sbin/newsyslog/newsyslog.c	Thu Jul 22 11:23:18 2010	(r210372)
 @@ -69,9 +69,11 @@ __FBSDID("$FreeBSD$");
  #include <sys/stat.h>
  #include <sys/wait.h>
  
 +#include <assert.h>
  #include <ctype.h>
  #include <err.h>
  #include <errno.h>
 +#include <dirent.h>
  #include <fcntl.h>
  #include <fnmatch.h>
  #include <glob.h>
 @@ -80,6 +82,7 @@ __FBSDID("$FreeBSD$");
  #include <pwd.h>
  #include <signal.h>
  #include <stdio.h>
 +#include <libgen.h>
  #include <stdlib.h>
  #include <string.h>
  #include <time.h>
 @@ -112,6 +115,9 @@ __FBSDID("$FreeBSD$");
  #define	DEFAULT_MARKER	"<default>"
  #define	DEBUG_MARKER	"<debug>"
  #define	INCLUDE_MARKER	"<include>"
 +#define	DEFAULT_TIMEFNAME_FMT	"%Y%m%dT%H%M%S"
 +
 +#define	MAX_OLDLOGS 65536	/* Default maximum number of old logfiles */
  
  struct conf_entry {
  	STAILQ_ENTRY(conf_entry) cf_nextp;
 @@ -155,6 +161,11 @@ struct include_entry {
  	const char *file;	/* Name of file to process */
  };
  
 +struct oldlog_entry {
 +	char *fname;		/* Filename of the log file */
 +	time_t t;		/* Parses timestamp of the logfile */
 +};
 +
  typedef enum {
  	FREE_ENT, KEEP_ENT
  }	fk_entry;
 @@ -182,6 +193,7 @@ int rotatereq = 0;		/* -R = Always rotat
  				/*    that a list of files *are* given on  */
  				/*    the run command). */
  char *requestor;		/* The name given on a -R request */
 +char *timefnamefmt = NULL;	/* Use time based filenames instead of .0 etc */
  char *archdirname;		/* Directory path to old logfiles archive */
  char *destdir = NULL;		/* Directory to treat at root for logs */
  const char *conf;		/* Configuration file to use */
 @@ -585,7 +597,7 @@ parse_args(int argc, char **argv)
  		*p = '\0';
  
  	/* Parse command line options. */
 -	while ((ch = getopt(argc, argv, "a:d:f:nrsvCD:FNPR:")) != -1)
 +	while ((ch = getopt(argc, argv, "a:d:f:nrst:vCD:FNPR:")) != -1)
  		switch (ch) {
  		case 'a':
  			archtodir++;
 @@ -606,6 +618,13 @@ parse_args(int argc, char **argv)
  		case 's':
  			nosignal = 1;
  			break;
 +		case 't':
 +			if (optarg[0] == '\0' ||
 +			    strcmp(optarg, "DEFAULT") == 0)
 +				timefnamefmt = strdup(DEFAULT_TIMEFNAME_FMT);
 +			else
 +				timefnamefmt = strdup(optarg);
 +			break;
  		case 'v':
  			verbose++;
  			break;
 @@ -728,7 +747,7 @@ usage(void)
  
  	fprintf(stderr,
  	    "usage: newsyslog [-CFNnrsv] [-a directory] [-d directory] [-f config-file]\n"
 -	    "                 [ [-R requestor] filename ... ]\n");
 +	    "                 [-t timefmt ] [ [-R requestor] filename ... ]\n");
  	exit(1);
  }
  
 @@ -1365,6 +1384,177 @@ missing_field(char *p, char *errline)
  }
  
  /*
 + * In our sort we return it in the reverse of what qsort normally
 + * would do, as we want the newest files first.  If we have two
 + * entries with the same time we don't really care about order.
 + *
 + * Support function for qsort() in delete_oldest_timelog().
 + */
 +static int
 +oldlog_entry_compare(const void *a, const void *b)
 +{
 +	const struct oldlog_entry *ola = a, *olb = b;
 +
 +	if (ola->t > olb->t)
 +		return (-1);
 +	else if (ola->t < olb->t)
 +		return (1);
 +	else
 +		return (0);
 +}
 +
 +/*
 + * Delete the oldest logfiles, when using time based filenames.
 + */
 +static void
 +delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir)
 +{
 +	char *logfname, *s, *dir, errbuf[80];
 +	int logcnt, max_logcnt, dirfd, i;
 +	struct oldlog_entry *oldlogs;
 +	size_t logfname_len;
 +	struct dirent *dp;
 +	const char *cdir;
 +	struct tm tm;
 +	DIR *dirp;
 +
 +	oldlogs = malloc(MAX_OLDLOGS * sizeof(struct oldlog_entry));
 +	max_logcnt = MAX_OLDLOGS;
 +	logcnt = 0;
 +
 +	if (archive_dir != NULL && archive_dir[0] != '\0')
 +		cdir = archive_dir;
 +	else
 +		if ((cdir = dirname(ent->log)) == NULL)
 +			err(1, "dirname()");
 +	if ((dir = strdup(cdir)) == NULL)
 +		err(1, "strdup()");
 +
 +	if ((s = basename(ent->log)) == NULL)
 +		err(1, "basename()");
 +	if ((logfname = strdup(s)) == NULL)
 +		err(1, "strdup()");
 +	logfname_len = strlen(logfname);
 +	if (strcmp(logfname, "/") == 0)
 +		errx(1, "Invalid log filename - became '/'");
 +
 +	if (verbose > 2)
 +		printf("Searching for old logs in %s\n", dir);
 +
 +	/* First we create a 'list' of all archived logfiles */
 +	if ((dirp = opendir(dir)) == NULL)
 +		err(1, "Cannot open log directory '%s'", dir);
 +	dirfd = dirfd(dirp);
 +	while ((dp = readdir(dirp)) != NULL) {
 +		if (dp->d_type != DT_REG)
 +			continue;
 +
 +		/* Ignore everything but files with our logfile prefix */
 +		if (strncmp(dp->d_name, logfname, logfname_len) != 0)
 +			continue;
 +		/* Ignore the actual non-rotated logfile */
 +		if (dp->d_namlen == logfname_len)
 +			continue;
 +		/*
 +		 * Make sure we created have found a logfile, so the
 +		 * postfix is valid, IE format is: '.<time>(.[bg]z)?'.
 +		 */
 +		if (dp->d_name[logfname_len] != '.') {
 +			if (verbose)
 +				printf("Ignoring %s which has unexpected "
 +				    "extension '%s'\n", dp->d_name,
 +				    &dp->d_name[logfname_len]);
 +			continue;
 +		}
 +		if ((s = strptime(&dp->d_name[logfname_len + 1],
 +			    timefnamefmt, &tm)) == NULL) {
 +			/*
 +			 * We could special case "old" sequentially
 +			 * named logfiles here, but we do not as that
 +			 * would require special handling to decide
 +			 * which one was the oldest compared to "new"
 +			 * time based logfiles.
 +			 */
 +			if (verbose)
 +				printf("Ignoring %s which does not "
 +				    "match time format\n", dp->d_name);
 +			continue;
 +		}
 +		if (*s != '\0' && !(strcmp(s, BZCOMPRESS_POSTFIX) == 0 ||
 +			strcmp(s, COMPRESS_POSTFIX) == 0))  {
 +			    if (verbose)
 +				printf("Ignoring %s which has unexpected "
 +				    "extension '%s'\n", dp->d_name, s);
 +			continue;
 +		}
 +
 +		/*
 +		 * We should now have old an old rotated logfile, so
 +		 * add it to the 'list'.
 +		 */
 +		if ((oldlogs[logcnt].t = timegm(&tm)) == -1)
 +			err(1, "Could not convert time string to time value");
 +		if ((oldlogs[logcnt].fname = strdup(dp->d_name)) == NULL)
 +			err(1, "strdup()");
 +		logcnt++;
 +
 +		/*
 +		 * It is very unlikely we ever run out of space in the
 +		 * logfile array from the default size, but lets
 +		 * handle it anyway...
 +		 */
 +		if (logcnt >= max_logcnt) {
 +			max_logcnt *= 4;
 +			/* Detect integer overflow */
 +			if (max_logcnt < logcnt)
 +				errx(1, "Too many old logfiles found");
 +			oldlogs = realloc(oldlogs,
 +			    max_logcnt * sizeof(struct oldlog_entry));
 +			if (oldlogs == NULL)
 +				err(1, "realloc()");
 +		}
 +	}
 +
 +	/* Second, if needed we delete oldest archived logfiles */
 +	if (logcnt > 0 && logcnt >= ent->numlogs && ent->numlogs > 1) {
 +		oldlogs = realloc(oldlogs, logcnt *
 +		    sizeof(struct oldlog_entry));
 +		if (oldlogs == NULL)
 +			err(1, "realloc()");
 +
 +		/*
 +		 * We now sort the logs in the order of newest to
 +		 * oldest.  That way we can simply skip over the
 +		 * number of records we want to keep.
 +		 */
 +		qsort(oldlogs, logcnt, sizeof(struct oldlog_entry),
 +		    oldlog_entry_compare);
 +		for (i = ent->numlogs - 1; i < logcnt; i++) {
 +			if (noaction)
 +				printf("\trm -f %s/%s\n", dir,
 +				    oldlogs[i].fname);
 +			else if (unlinkat(dirfd, oldlogs[i].fname, 0) != 0) {
 +				snprintf(errbuf, sizeof(errbuf),
 +				    "Could not delet old logfile '%s'",
 +				    oldlogs[i].fname);
 +				perror(errbuf);
 +			}
 +		}
 +	} else if (verbose > 1)
 +		printf("No old logs to delete for logfile %s\n", ent->log);
 +
 +	/* Third, cleanup */
 +	closedir(dirp);
 +	for (i = 0; i < logcnt; i++) {
 +		assert(oldlogs[i].fname != NULL);
 +		free(oldlogs[i].fname);
 +	}
 +	free(oldlogs);
 +	free(logfname);
 +	free(dir);
 +}
 +
 +/*
   * Only add to the queue if the file hasn't already been added. This is
   * done to prevent circular include loops.
   */
 @@ -1398,10 +1588,13 @@ do_rotate(const struct conf_entry *ent)
  	char file1[MAXPATHLEN], file2[MAXPATHLEN];
  	char zfile1[MAXPATHLEN], zfile2[MAXPATHLEN];
  	char jfile1[MAXPATHLEN];
 +	char datetimestr[30];
  	int flags, numlogs_c;
  	fk_entry free_or_keep;
  	struct sigwork_entry *swork;
  	struct stat st;
 +	struct tm tm;
 +	time_t now;
  
  	flags = ent->flags;
  	free_or_keep = FREE_ENT;
 @@ -1435,32 +1628,59 @@ do_rotate(const struct conf_entry *ent)
  		/* name of oldest log */
  		(void) snprintf(file1, sizeof(file1), "%s/%s.%d", dirpart,
  		    namepart, ent->numlogs);
 -		(void) snprintf(zfile1, sizeof(zfile1), "%s%s", file1,
 -		    COMPRESS_POSTFIX);
 -		snprintf(jfile1, sizeof(jfile1), "%s%s", file1,
 -		    BZCOMPRESS_POSTFIX);
  	} else {
 +		/*
 +		 * Tell delete_oldest_timelog() we are not using an
 +		 * archive dir.
 +		 */
 +		dirpart[0] = '\0';
 +
  		/* name of oldest log */
  		(void) snprintf(file1, sizeof(file1), "%s.%d", ent->log,
  		    ent->numlogs);
 +	}
 +
 +	/* Delete old logs */
 +	if (timefnamefmt != NULL)
 +		delete_oldest_timelog(ent, dirpart);
 +	else {
 +		/* name of oldest log */
  		(void) snprintf(zfile1, sizeof(zfile1), "%s%s", file1,
  		    COMPRESS_POSTFIX);
  		snprintf(jfile1, sizeof(jfile1), "%s%s", file1,
  		    BZCOMPRESS_POSTFIX);
 -	}
  
 -	if (noaction) {
 -		printf("\trm -f %s\n", file1);
 -		printf("\trm -f %s\n", zfile1);
 -		printf("\trm -f %s\n", jfile1);
 -	} else {
 -		(void) unlink(file1);
 -		(void) unlink(zfile1);
 -		(void) unlink(jfile1);
 +		if (noaction) {
 +			printf("\trm -f %s\n", file1);
 +			printf("\trm -f %s\n", zfile1);
 +			printf("\trm -f %s\n", jfile1);
 +		} else {
 +			(void) unlink(file1);
 +			(void) unlink(zfile1);
 +			(void) unlink(jfile1);
 +		}
  	}
  
 +	if (timefnamefmt != NULL) {
 +		/* If time functions fails we can't really do any sensible */
 +		if (time(&now) == (time_t)-1 ||
 +		    localtime_r(&now, &tm) == NULL)
 +			bzero(&tm, sizeof(tm));
 +
 +		strftime(datetimestr, sizeof(datetimestr), timefnamefmt, &tm);
 +		if (archtodir)
 +			(void) snprintf(file1, sizeof(file1), "%s/%s.%s",
 +			    dirpart, namepart, datetimestr);
 +		else
 +			(void) snprintf(file1, sizeof(file1), "%s.%s",
 +			    ent->log, datetimestr);
 +
 +		/* Don't run the code to move down logs */
 +		numlogs_c = 0;
 +	} else
 +		numlogs_c = ent->numlogs;		/* copy for countdown */
 +
  	/* Move down log files */
 -	numlogs_c = ent->numlogs;		/* copy for countdown */
  	while (numlogs_c--) {
  
  		(void) strlcpy(file2, file1, sizeof(file2));
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: eadler 
State-Changed-When: Sat Feb 26 21:10:13 EST 2011 
State-Changed-Why:  
Has been patched 


Responsible-Changed-From-To: gad->simon 
Responsible-Changed-By: eadler 
Responsible-Changed-When: Sat Feb 26 21:10:13 EST 2011 
Responsible-Changed-Why:  
Has been patched 

http://www.freebsd.org/cgi/query-pr.cgi?pr=29363 
State-Changed-From-To: patched->closed 
State-Changed-By: eadler 
State-Changed-When: Fri Mar 15 23:41:36 UTC 2013 
State-Changed-Why:  
MFCed/fixed by now or it will never be MFCed 

http://www.freebsd.org/cgi/query-pr.cgi?pr=29363 
>Unformatted:
