Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Dec 2017 17:56:03 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r326749 - head/usr.bin/wc
Message-ID:  <201712101756.vBAHu3Qa052647@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Sun Dec 10 17:56:03 2017
New Revision: 326749
URL: https://svnweb.freebsd.org/changeset/base/326749

Log:
  wc(1): Restore regular file char count fast path
  
  fstat(2) is going to be a lot faster than reading all of the bytes in a
  file, if we just need a character count for a regular file.  This fast path
  was accidentally broken in r326736.
  
  PR:		224160
  Reported by:	bde
  Sponsored by:	Dell EMC Isilon

Modified:
  head/usr.bin/wc/wc.c

Modified: head/usr.bin/wc/wc.c
==============================================================================
--- head/usr.bin/wc/wc.c	Sun Dec 10 16:42:59 2017	(r326748)
+++ head/usr.bin/wc/wc.c	Sun Dec 10 17:56:03 2017	(r326749)
@@ -213,51 +213,10 @@ cnt(const char *file)
 	if (doword || (domulti && MB_CUR_MAX != 1))
 		goto word;
 	/*
-	 * Line counting is split out because it's a lot faster to get
-	 * lines than to get words, since the word count requires some
-	 * logic.
+	 * If all we need is the number of characters and it's a regular file,
+	 * just stat it.
 	 */
-	if (doline || dochar) {
-		while ((len = read(fd, buf, MAXBSIZE))) {
-			if (len == -1) {
-				xo_warn("%s: read", file);
-				(void)close(fd);
-				return (1);
-			}
-			if (siginfo) {
-				show_cnt(file, linect, wordct, charct,
-				    llct);
-			}
-			charct += len;
-			if (doline) {
-				for (p = buf; len--; ++p)
-					if (*p == '\n') {
-						if (tmpll > llct)
-							llct = tmpll;
-						tmpll = 0;
-						++linect;
-					} else
-						tmpll++;
-			}
-		}
-		reset_siginfo();
-		if (doline)
-			tlinect += linect;
-		if (dochar)
-			tcharct += charct;
-		if (dolongline) {
-			if (llct > tlongline)
-				tlongline = llct;
-		}
-		show_cnt(file, linect, wordct, charct, llct);
-		(void)close(fd);
-		return (0);
-	}
-	/*
-	 * If all we need is the number of characters and it's a
-	 * regular file, just stat the puppy.
-	 */
-	if (dochar || domulti) {
+	if (doline == 0) {
 		if (fstat(fd, &sb)) {
 			xo_warn("%s: fstat", file);
 			(void)close(fd);
@@ -272,6 +231,44 @@ cnt(const char *file)
 			return (0);
 		}
 	}
+	/*
+	 * For files we can't stat, or if we need line counting, slurp the
+	 * file.  Line counting is split out because it's a lot faster to get
+	 * lines than to get words, since the word count requires locale
+	 * handling.
+	 */
+	while ((len = read(fd, buf, MAXBSIZE))) {
+		if (len == -1) {
+			xo_warn("%s: read", file);
+			(void)close(fd);
+			return (1);
+		}
+		if (siginfo)
+			show_cnt(file, linect, wordct, charct, llct);
+		charct += len;
+		if (doline) {
+			for (p = buf; len--; ++p)
+				if (*p == '\n') {
+					if (tmpll > llct)
+						llct = tmpll;
+					tmpll = 0;
+					++linect;
+				} else
+					tmpll++;
+		}
+	}
+	reset_siginfo();
+	if (doline)
+		tlinect += linect;
+	if (dochar)
+		tcharct += charct;
+	if (dolongline) {
+		if (llct > tlongline)
+			tlongline = llct;
+	}
+	show_cnt(file, linect, wordct, charct, llct);
+	(void)close(fd);
+	return (0);
 
 	/* Do it the hard way... */
 word:	gotsp = 1;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201712101756.vBAHu3Qa052647>