Module Name:    src
Committed By:   kre
Date:           Thu Sep 21 22:53:19 UTC 2017

Modified Files:
        src/usr.bin/stat: stat.c

Log Message:
Handle the new %f (as an addition to the strftime format - -t arg)
correctly, in particular %%f does not contain the %f format, and like
all strftime conversions, %f can occur more than once (not that it is
likely to happen, but just in case...)


To generate a diff of this commit:
cvs rdiff -u -r1.42 -r1.43 src/usr.bin/stat/stat.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/stat/stat.c
diff -u src/usr.bin/stat/stat.c:1.42 src/usr.bin/stat/stat.c:1.43
--- src/usr.bin/stat/stat.c:1.42	Thu Sep 21 18:50:08 2017
+++ src/usr.bin/stat/stat.c	Thu Sep 21 22:53:19 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: stat.c,v 1.42 2017/09/21 18:50:08 kre Exp $ */
+/*	$NetBSD: stat.c,v 1.43 2017/09/21 22:53:19 kre Exp $ */
 
 /*
  * Copyright (c) 2002-2011 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if !defined(lint)
-__RCSID("$NetBSD: stat.c,v 1.42 2017/09/21 18:50:08 kre Exp $");
+__RCSID("$NetBSD: stat.c,v 1.43 2017/09/21 22:53:19 kre Exp $");
 #endif
 
 #if ! HAVE_NBTOOL_CONFIG_H
@@ -568,26 +568,62 @@ static const char *
 fmttime(char *buf, size_t len, const char *fmt, time_t secs, long nsecs)
 {
 	struct tm tm;
-	char *fmt2;
+	const char *fpb, *fp1, *fp2;	/* pointers into fmt */
+	char *fmt2 = NULL;		/* replacement fmt (if not NULL) */
+				/* XXX init of next twp for stupid gcc only */
+	char *f2p = NULL;		/* ptr into fmt2 - last added */
+	size_t flen = 0;
+	size_t o;
+	int sl;
 
 	if (localtime_r(&secs, &tm) == NULL) {
 		secs = 0;
 		(void)localtime_r(&secs, &tm);
 	}
-	if ((fmt2 = strstr(fmt, "%f")) != NULL) {
-		size_t flen = strlen(fmt) + 1024;
-		size_t o = (size_t)(fmt2 - fmt);
-
-		fmt2 = calloc(flen, 1);
-		if (fmt2 != NULL) {
-			int sl;
-
-			memcpy(fmt2, fmt, o);
-			sl = snprintf(fmt2 + o, flen - o, "%.9ld", nsecs);
-			if (sl == -1)
-				sl = 0;
-			strcpy(fmt2 + sl + o, fmt + o + 2);
+	for (fp1 = fpb = fmt; (fp2 = strchr(fp1, '%')) != NULL; ) {
+		if (fp2[1] != 'f') {
+			/* make sure we don't find the 2nd '%' in "%%" */
+			fp1 = fp2 + 1 + (fp2[1] != '\0');
+			continue;
+		}
+		if (fmt2 == NULL) {
+			/* allow for ~100 %f's in the format ... */
+			flen = strlen(fmt) + 1024;
+
+			if ((fmt2 = calloc(flen, 1)) == NULL) {
+				fp1 = fp2 + 2;
+				continue;
+			}
+			f2p = fmt2;
+
+			o = (size_t)(fp2 - fpb);
+			memcpy(f2p, fpb, o);	/* must fit */
 			fmt = fmt2;
+		} else {
+			o = (size_t)(fp2 - fpb);
+			if (flen > o)
+				memcpy(f2p, fpb, o);
+		}
+		if (flen < o + 10) {	/* 9 digits + \0 == 10 */
+			*f2p = '\0';
+			break;
+		}
+		f2p += o;
+		flen -= o;
+		sl = snprintf(f2p, flen, "%.9ld", nsecs);
+		if (sl == -1)
+			sl = 0;
+		f2p += sl;
+		*f2p = '\0';
+		flen -= sl;
+		fp1 = fp2 + 2;
+		fpb = fp1;
+	}
+	if (fmt2 != NULL) {
+		o = strlen(fpb);
+		if (flen > o) {
+			memcpy(f2p, fpb, o);
+			f2p[o] = '\0';
 		}
 	}
 
@@ -785,7 +821,6 @@ format1(const struct stat *st,
 		data = secs;
 		sdata = fmttime(path, sizeof(path), timefmt, secs, nsecs);
 
-		sdata = path;
 		formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
 		    FMTF_FLOAT | FMTF_STRING;
 		if (ofmt == 0)

Reply via email to