aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Kuzmich <ilya.kuzmich@gmail.com>2017-05-28 18:29:19 +0300
committerRob Landley <rob@landley.net>2017-06-27 14:55:29 -0500
commit77997b8e774318631b373a443dc073d3b38b5d84 (patch)
tree1c7dc8c8a7ce757bfe5a447221714239c5a5ea27
parentf30035e88bad1748e8e5546ef43409862db1d91e (diff)
downloadtoybox-77997b8e774318631b373a443dc073d3b38b5d84.tar.gz
teach head -c
Not POSIX, but implemented in coreutils, busybox and freebsd.
-rwxr-xr-xtests/head.test4
-rw-r--r--toys/posix/head.c17
2 files changed, 16 insertions, 5 deletions
diff --git a/tests/head.test b/tests/head.test
index 6ed027c4..4e4c01bd 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 63eb85b0..6153b42f 100644
--- a/toys/posix/head.c
+++ b/toys/posix/head.c
@@ -3,8 +3,9 @@
* Copyright 2006 Timothy Elliott <tle@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#<0qv[-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);
}