[Toybox] [PATCH v2 1/1] teach head -c

Ilya Kuzmich ilya.kuzmich at gmail.com
Sun May 28 09:07:22 PDT 2017


Not POSIX, but implemented in coreutils, busybox and freebsd.

Signed-off-by: Ilya Kuzmich <ilya.kuzmich at gmail.com>
---
 tests/head.test   |  4 ++++
 toys/posix/head.c | 17 ++++++++++++-----
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/tests/head.test b/tests/head.test
index 6ed027c..4e4c01b 100755
--- a/tests/head.test
+++ b/tests/head.test
@@ -27,3 +27,7 @@ testing "-q, multiple files" "head -q -n 2 input file1" "one\ntwo\nfoo\nbar\n" \
 	"one\ntwo\nthree\n" ""
 rm file1
 
+testing "-c 3" "head -c 3" "one" "" "one\ntwo"
+testing "-c bigger than input" "head -c 3" "a" "" "a"
+testing "-c 3 -n 1" "head -c 3 -n 1" "one\n" "" "one\ntwo"
+testing "-n 1 -c 3" "head -n 1 -c 3" "one" "" "one\ntwo"
diff --git a/toys/posix/head.c b/toys/posix/head.c
index f5fd281..43ac28a 100644
--- a/toys/posix/head.c
+++ b/toys/posix/head.c
@@ -3,8 +3,9 @@
  * Copyright 2006 Timothy Elliott <tle at holymonkey.com>
  *
  * See http://opengroup.org/onlinepubs/9699919799/utilities/head.html
+ * See http://man7.org/linux/man-pages/man1/head.1.html
 
-USE_HEAD(NEWTOY(head, "?n#<0=10qv", TOYFLAG_USR|TOYFLAG_BIN))
+USE_HEAD(NEWTOY(head, "?n#<0=10c#qv[-nc]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config HEAD
   bool "head"
@@ -16,6 +17,7 @@ config HEAD
     stdin. Filename "-" is a synonym for stdin.
 
     -n	Number of lines to copy
+    -c	Number of bytes to copy
     -q	Never print headers
     -v	Always print headers
 */
@@ -24,13 +26,14 @@ config HEAD
 #include "toys.h"
 
 GLOBALS(
+  long bytes;
   long lines;
   int file_no;
 )
 
 static void do_head(int fd, char *name)
 {
-  int i, len, lines=TT.lines, size=sizeof(toybuf);
+  int i, len, lines=TT.lines, bytes=TT.bytes;
 
   if ((toys.optc > 1 && !(toys.optflags & FLAG_q)) || toys.optflags & FLAG_v) {
     // Print an extra newline for all but the first file
@@ -39,12 +42,16 @@ static void do_head(int fd, char *name)
     xflush();
   }
 
-  while (lines) {
-    len = read(fd, toybuf, size);
+  while (toys.optflags & FLAG_c ? bytes : lines) {
+    len = read(fd, toybuf, sizeof(toybuf));
     if (len<0) perror_msg_raw(name);
     if (len<1) break;
 
-    for(i=0; i<len;) if (toybuf[i++] == '\n' && !--lines) break;
+    if (bytes) {
+      i = bytes >= len ? len : bytes;
+      bytes -= i;
+    } else
+      for(i=0; i<len;) if (toybuf[i++] == '\n' && !--lines) break;
 
     xwrite(1, toybuf, i);
   }
-- 
2.7.4




More information about the Toybox mailing list