/* head -- output first part of file(s) This is the head utility
Copyright (C) 1989-2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */ The GNUv3 license
/* Options: (see usage)
Reads from standard input if no files are given or when a filename of
''-'' is encountered.
By default, filename headers are printed only if more than one file
is given.
By default, prints the first 10 lines (head -n 10).
David MacKenzie <djm@gnu.ai.mit.edu> */
#include <config.h> Provides system specific information
#include <stdio.h> Provides standard I/O capability
#include <getopt.h> ...!includes auto-comment...
#include <sys/types.h> Provides system data types
#include "system.h" ...!includes auto-comment...
#include "die.h" ...!includes auto-comment...
#include "error.h" ...!includes auto-comment...
#include "full-read.h" ...!includes auto-comment...
#include "quote.h" ...!includes auto-comment...
#include "safe-read.h" ...!includes auto-comment...
#include "stat-size.h" ...!includes auto-comment...
#include "xbinary-io.h" ...!includes auto-comment...
#include "xdectoint.h" ...!includes auto-comment...
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "head" Line 44
#define AUTHORS \ Line 46
proper_name ("David MacKenzie"), \ Line 47
proper_name ("Jim Meyering") Line 48
/* Number of lines/chars/blocks to head. */
#define DEFAULT_NUMBER 10 Line 51
/* Useful only when eliding tail bytes or lines.
If true, skip the is-regular-file test used to determine whether
to use the lseek optimization. Instead, use the more general (and
more expensive) code unconditionally. Intended solely for testing. */
static bool presume_input_pipe; Line 57
/* If true, print filename headers. */
static bool print_headers; Line 60
/* Character to split lines by. */
static char line_end; Line 63
/* When to print the filename banners. */
enum header_mode Line 66
{
multiple_files, always, never Line 68
}; Block 1
/* Have we ever read standard input? */
static bool have_read_stdin; Line 72
enum Copy_fd_status Line 74
{
COPY_FD_OK = 0, Line 76
COPY_FD_READ_ERROR, Line 77
COPY_FD_UNEXPECTED_EOF Line 78
}; Block 2
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum Line 83
{
PRESUME_INPUT_PIPE_OPTION = CHAR_MAX + 1 Line 85
}; Block 3
static struct option const long_options[] = Line 88
{
{"bytes", required_argument, NULL, 'c'}, Line 90
{"lines", required_argument, NULL, 'n'}, Line 91
{"-presume-input-pipe", no_argument, NULL, Line 92
PRESUME_INPUT_PIPE_OPTION}, /* do not document */ Line 93
{"quiet", no_argument, NULL, 'q'}, Line 94
{"silent", no_argument, NULL, 'q'}, Line 95
{"verbose", no_argument, NULL, 'v'}, Line 96
{"zero-terminated", no_argument, NULL, 'z'}, Line 97
{GETOPT_HELP_OPTION_DECL}, Line 98
{GETOPT_VERSION_OPTION_DECL}, Line 99
{NULL, 0, NULL, 0} Line 100
}; Block 4
void Line 103
usage (int status) Line 104
{
if (status != EXIT_SUCCESS) Line 106
emit_try_help (); ...!common auto-comment...
else Line 108
{
printf (_("\ Line 110
Usage: %s [OPTION]... [FILE]...\n\ Line 111
"), Line 112
program_name); Line 113
printf (_("\ Line 114
Print the first %d lines of each FILE to standard output.\n\ Line 115
With more than one FILE, precede each with a header giving the file name.\n\ Line 116
"), DEFAULT_NUMBER); Line 117
emit_stdin_note (); ...!common auto-comment...
emit_mandatory_arg_note (); ...!common auto-comment...
printf (_("\ Line 122
-c, --bytes=[-]NUM print the first NUM bytes of each file;\n\ Line 123
with the leading '-', print all but the last\n\ Line 124
NUM bytes of each file\n\ Line 125
-n, --lines=[-]NUM print the first NUM lines instead of the first %d;\n\Line 126
with the leading '-', print all but the last\n\ Line 127
NUM lines of each file\n\ Line 128
"), DEFAULT_NUMBER); Line 129
fputs (_("\ Line 130
-q, --quiet, --silent never print headers giving file names\n\ Line 131
-v, --verbose always print headers giving file names\n\ Line 132
"), stdout); Line 133
fputs (_("\ Line 134
-z, --zero-terminated line delimiter is NUL, not newline\n\ Line 135
"), stdout); Line 136
fputs (HELP_OPTION_DESCRIPTION, stdout); Line 137
fputs (VERSION_OPTION_DESCRIPTION, stdout); Line 138
fputs (_("\ Line 139
\n\
NUM may have a multiplier suffix:\n\ Line 141
b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\ Line 142
GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\ Line 143
Binary prefixes can be used, too: KiB=K, MiB=M, and so on.\n\ Line 144
"), stdout); Line 145
emit_ancillary_info (PROGRAM_NAME); Line 146
}
exit (status); Line 148
} Block 5
static void Line 151
diagnose_copy_fd_failure (enum Copy_fd_status err, char const *filename) Line 152
{
switch (err) Line 154
{
case COPY_FD_READ_ERROR: Line 156
error (0, errno, _("error reading %s"), quoteaf (filename)); Line 157
break; Line 158
case COPY_FD_UNEXPECTED_EOF: Line 159
error (0, errno, _("%s: file has shrunk too much"), quotef (filename)); Line 160
break; Line 161
default: Line 162
abort (); ...!common auto-comment...
}
} Block 6
static void Line 167
write_header (const char *filename) Line 168
{
static bool first_file = true; Line 170
printf ("%s==> %s <==\n", (first_file ? "" : "\n"), filename); Line 172
first_file = false; Line 173
} Block 7
/* Write N_BYTES from BUFFER to stdout.
Exit immediately on error with a single diagnostic. */
static void Line 179
xwrite_stdout (char const *buffer, size_t n_bytes) Line 180
{
if (n_bytes > 0 && fwrite (buffer, 1, n_bytes, stdout) < n_bytes) Line 182...!syscalls auto-comment...
{
clearerr (stdout); /* To avoid redundant close_stdout diagnostic. */ Line 184
die (EXIT_FAILURE, errno, _("error writing %s"), Line 185
quoteaf ("standard output")); Line 186
}
} Block 8
/* Copy no more than N_BYTES from file descriptor SRC_FD to stdout.
Return an appropriate indication of success or read failure. */
static enum Copy_fd_status Line 193
copy_fd (int src_fd, uintmax_t n_bytes) Line 194
{
char buf[BUFSIZ]; Line 196
const size_t buf_size = sizeof (buf); Line 197
/* Copy the file contents. */
while (0 < n_bytes) Line 200
{
size_t n_to_read = MIN (buf_size, n_bytes); Line 202
size_t n_read = safe_read (src_fd, buf, n_to_read); Line 203...!syscalls auto-comment...
if (n_read == SAFE_READ_ERROR) Line 204
return COPY_FD_READ_ERROR; Line 205
n_bytes -= n_read; Line 207
if (n_read == 0 && n_bytes != 0) Line 209
return COPY_FD_UNEXPECTED_EOF; Line 210
xwrite_stdout (buf, n_read); Line 212
}
return COPY_FD_OK; Line 215
} Block 9
/* Call lseek (FD, OFFSET, WHENCE), where file descriptor FD
corresponds to the file FILENAME. WHENCE must be SEEK_SET or
SEEK_CUR. Return the resulting offset. Give a diagnostic and
return -1 if lseek fails. */
static off_t Line 223
elseek (int fd, off_t offset, int whence, char const *filename) Line 224
{
off_t new_offset = lseek (fd, offset, whence); Line 226
char buf[INT_BUFSIZE_BOUND (offset)]; Line 227
if (new_offset < 0) Line 229
error (0, errno, Line 230
_(whence == SEEK_SET Line 231
? N_("%s: cannot seek to offset %s") Line 232
: N_("%s: cannot seek to relative offset %s")), Line 233
quotef (filename), Line 234
offtostr (offset, buf)); Line 235
return new_offset; Line 237
} Block 10
/* For an input file with name FILENAME and descriptor FD,
output all but the last N_ELIDE_0 bytes.
If CURRENT_POS is nonnegative, assume that the input file is
positioned at CURRENT_POS and that it should be repositioned to
just before the elided bytes before returning.
Return true upon success.
Give a diagnostic and return false upon error. */
static bool Line 247
elide_tail_bytes_pipe (const char *filename, int fd, uintmax_t n_elide_0, Line 248
off_t current_pos) Line 249
{
size_t n_elide = n_elide_0; Line 251
uintmax_t desired_pos = current_pos; Line 252
bool ok = true; Line 253
#ifndef HEAD_TAIL_PIPE_READ_BUFSIZE Line 255
# define HEAD_TAIL_PIPE_READ_BUFSIZE BUFSIZ Line 256
#endif Line 257
#define READ_BUFSIZE HEAD_TAIL_PIPE_READ_BUFSIZE Line 258
/* If we're eliding no more than this many bytes, then it's ok to allocate
more memory in order to use a more time-efficient algorithm.
FIXME: use a fraction of available memory instead, as in sort.
FIXME: is this even worthwhile? */
#ifndef HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD Line 264
# define HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD 1024 * 1024 Line 265
#endif Line 266
#if HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD < 2 * READ_BUFSIZE Line 268
"HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD must be at least 2 * READ_BUFSIZE" Line 269
#endif Line 270
if (SIZE_MAX < n_elide_0 + READ_BUFSIZE) Line 272
{
char umax_buf[INT_BUFSIZE_BOUND (n_elide_0)]; Line 274
die (EXIT_FAILURE, 0, _("%s: number of bytes is too large"), Line 275
umaxtostr (n_elide_0, umax_buf)); Line 276
}
/* Two cases to consider...
1) n_elide is small enough that we can afford to double-buffer:
allocate 2 * (READ_BUFSIZE + n_elide) bytes
2) n_elide is too big for that, so we allocate only
(READ_BUFSIZE + n_elide) bytes
FIXME: profile, to see if double-buffering is worthwhile
CAUTION: do not fail (out of memory) when asked to elide
a ridiculous amount, but when given only a small input. */
if (n_elide <= HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD) Line 290
{
bool first = true; Line 292
bool eof = false; Line 293
size_t n_to_read = READ_BUFSIZE + n_elide; Line 294
bool i; Line 295
char *b[2]; Line 296
b[0] = xnmalloc (2, n_to_read); Line 297
b[1] = b[0] + n_to_read; Line 298
for (i = false; ! eof ; i = !i) Line 300
{
size_t n_read = full_read (fd, b[i], n_to_read); Line 302...!syscalls auto-comment...
size_t delta = 0; Line 303
if (n_read < n_to_read) Line 304
{
if (errno != 0) Line 306
{
error (0, errno, _("error reading %s"), quoteaf (filename)); Line 308
ok = false; Line 309
break; Line 310
}
/* reached EOF */
if (n_read <= n_elide) Line 314
{
if (first) Line 316
{
/* The input is no larger than the number of bytes
to elide. So there's nothing to output, and
we're done. */
}
else Line 322
{
delta = n_elide - n_read; Line 324
}
}
eof = true; Line 327
}
/* Output any (but maybe just part of the) elided data from
the previous round. */
if (! first) Line 332
{
desired_pos += n_elide - delta; Line 334
xwrite_stdout (b[!i] + READ_BUFSIZE, n_elide - delta); Line 335
}
first = false; Line 337
if (n_elide < n_read) Line 339
{
desired_pos += n_read - n_elide; Line 341
xwrite_stdout (b[i], n_read - n_elide); Line 342
}
}
free (b[0]); Line 346
}
else Line 348
{
/* Read blocks of size READ_BUFSIZE, until we've read at least n_elide
bytes. Then, for each new buffer we read, also write an old one. */
bool eof = false; Line 353
size_t n_read; Line 354
bool buffered_enough; Line 355
size_t i, i_next; Line 356
char **b = NULL; Line 357
/* Round n_elide up to a multiple of READ_BUFSIZE. */
size_t rem = READ_BUFSIZE - (n_elide % READ_BUFSIZE); Line 359
size_t n_elide_round = n_elide + rem; Line 360
size_t n_bufs = n_elide_round / READ_BUFSIZE + 1; Line 361
size_t n_alloc = 0; Line 362
size_t n_array_alloc = 0; Line 363
buffered_enough = false; Line 365
for (i = 0, i_next = 1; !eof; i = i_next, i_next = (i_next + 1) % n_bufs) Line 366
{
if (n_array_alloc == i) Line 368
{
/* reallocate between 16 and n_bufs entries. */
if (n_array_alloc == 0) Line 371
n_array_alloc = MIN (n_bufs, 16); Line 372
else if (n_array_alloc <= n_bufs / 2) Line 373
n_array_alloc *= 2; Line 374
else Line 375
n_array_alloc = n_bufs; Line 376
b = xnrealloc (b, n_array_alloc, sizeof *b); Line 377
}
if (! buffered_enough) Line 380
{
b[i] = xmalloc (READ_BUFSIZE); Line 382
n_alloc = i + 1; Line 383
}
n_read = full_read (fd, b[i], READ_BUFSIZE); Line 385...!syscalls auto-comment...
if (n_read < READ_BUFSIZE) Line 386
{
if (errno != 0) Line 388
{
error (0, errno, _("error reading %s"), quoteaf (filename)); Line 390
ok = false; Line 391
goto free_mem; Line 392
}
eof = true; Line 394
}
if (i + 1 == n_bufs) Line 397
buffered_enough = true; Line 398
if (buffered_enough) Line 400
{
desired_pos += n_read; Line 402
xwrite_stdout (b[i_next], n_read); Line 403
}
}
/* Output any remainder: rem bytes from b[i] + n_read. */
if (rem) Line 408
{
if (buffered_enough) Line 410
{
size_t n_bytes_left_in_b_i = READ_BUFSIZE - n_read; Line 412
desired_pos += rem; Line 413
if (rem < n_bytes_left_in_b_i) Line 414
{
xwrite_stdout (b[i] + n_read, rem); Line 416
}
else Line 418
{
xwrite_stdout (b[i] + n_read, n_bytes_left_in_b_i); Line 420
xwrite_stdout (b[i_next], rem - n_bytes_left_in_b_i); Line 421
}
}
else if (i + 1 == n_bufs) Line 424
{
/* This happens when n_elide < file_size < n_elide_round.
|READ_BUF.|
| | rem |
|---------!---------!---------!---------|
|---- n_elide ---------|
| | x |
| |y |
|---- file size -----------|
| |n_read|
|---- n_elide_round ----------|
*/
size_t y = READ_BUFSIZE - rem; Line 438
size_t x = n_read - y; Line 439
desired_pos += x; Line 440
xwrite_stdout (b[i_next], x); Line 441
}
}
free_mem: Line 445
for (i = 0; i < n_alloc; i++) Line 446
free (b[i]); Line 447
free (b); Line 448
}
if (0 <= current_pos && elseek (fd, desired_pos, SEEK_SET, filename) < 0) Line 451
ok = false; Line 452
return ok; Line 453
} Block 11
/* For the file FILENAME with descriptor FD, output all but the last N_ELIDE
bytes. If SIZE is nonnegative, this is a regular file positioned
at CURRENT_POS with SIZE bytes. Return true on success.
Give a diagnostic and return false upon error. */
/* NOTE: if the input file shrinks by more than N_ELIDE bytes between
the length determination and the actual reading, then head fails. */
static bool Line 464
elide_tail_bytes_file (const char *filename, int fd, uintmax_t n_elide, Line 465
struct stat const *st, off_t current_pos) Line 466
{
off_t size = st->st_size; Line 468
if (presume_input_pipe || current_pos < 0 || size <= ST_BLKSIZE (*st)) Line 469
return elide_tail_bytes_pipe (filename, fd, n_elide, current_pos); Line 470
else Line 471
{
/* Be careful here. The current position may actually be
beyond the end of the file. */
off_t diff = size - current_pos; Line 475
off_t bytes_remaining = diff < 0 ? 0 : diff; Line 476
if (bytes_remaining <= n_elide) Line 478
return true; Line 479
enum Copy_fd_status err = copy_fd (fd, bytes_remaining - n_elide); Line 481
if (err == COPY_FD_OK) Line 482
return true; Line 483
diagnose_copy_fd_failure (err, filename); Line 485
return false; Line 486
}
} Block 12
/* For an input file with name FILENAME and descriptor FD,
output all but the last N_ELIDE_0 bytes.
If CURRENT_POS is nonnegative, the input file is positioned there
and should be repositioned to just before the elided bytes.
Buffer the specified number of lines as a linked list of LBUFFERs,
adding them as needed. Return true if successful. */
static bool Line 497
elide_tail_lines_pipe (const char *filename, int fd, uintmax_t n_elide, Line 498
off_t current_pos) Line 499
{
struct linebuffer Line 501
{
char buffer[BUFSIZ]; Line 503
size_t nbytes; Line 504
size_t nlines; Line 505
struct linebuffer *next; Line 506
};
uintmax_t desired_pos = current_pos; Line 508
typedef struct linebuffer LBUFFER; Line 509
LBUFFER *first, *last, *tmp; Line 510
size_t total_lines = 0; /* Total number of newlines in all buffers. */ Line 511
bool ok = true; Line 512
size_t n_read; /* Size in bytes of most recent read */ Line 513
first = last = xmalloc (sizeof (LBUFFER)); Line 515
first->nbytes = first->nlines = 0; Line 516
first->next = NULL; Line 517
tmp = xmalloc (sizeof (LBUFFER)); Line 518
/* Always read into a fresh buffer.
Read, (producing no output) until we've accumulated at least
n_elide newlines, or until EOF, whichever comes first. */
while (1) Line 523
{
n_read = safe_read (fd, tmp->buffer, BUFSIZ); Line 525...!syscalls auto-comment...
if (n_read == 0 || n_read == SAFE_READ_ERROR) Line 526
break; Line 527
if (! n_elide) Line 529
{
desired_pos += n_read; Line 531
xwrite_stdout (tmp->buffer, n_read); Line 532
continue; Line 533
}
tmp->nbytes = n_read; Line 536
tmp->nlines = 0; Line 537
tmp->next = NULL; Line 538
/* Count the number of newlines just read. */
{
char const *buffer_end = tmp->buffer + n_read; Line 542
char const *p = tmp->buffer; Line 543
while ((p = memchr (p, line_end, buffer_end - p))) Line 544
{
++p; Line 546
++tmp->nlines; Line 547
}
}
total_lines += tmp->nlines; Line 550
/* If there is enough room in the last buffer read, just append the new
one to it. This is because when reading from a pipe, 'n_read' can
often be very small. */
if (tmp->nbytes + last->nbytes < BUFSIZ) Line 555
{
memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes); Line 557
last->nbytes += tmp->nbytes; Line 558
last->nlines += tmp->nlines; Line 559
}
else Line 561
{
/* If there's not enough room, link the new buffer onto the end of
the list, then either free up the oldest buffer for the next
read if that would leave enough lines, or else malloc a new one.
Some compaction mechanism is possible but probably not
worthwhile. */
last = last->next = tmp; Line 568
if (n_elide < total_lines - first->nlines) Line 569
{
desired_pos += first->nbytes; Line 571
xwrite_stdout (first->buffer, first->nbytes); Line 572
tmp = first; Line 573
total_lines -= first->nlines; Line 574
first = first->next; Line 575
}
else Line 577
tmp = xmalloc (sizeof (LBUFFER)); Line 578
}
}
free (tmp); Line 582
if (n_read == SAFE_READ_ERROR) Line 584
{
error (0, errno, _("error reading %s"), quoteaf (filename)); Line 586
ok = false; Line 587
goto free_lbuffers; Line 588
}
/* If we read any bytes at all, count the incomplete line
on files that don't end with a newline. */
if (last->nbytes && last->buffer[last->nbytes - 1] != line_end) Line 593
{
++last->nlines; Line 595
++total_lines; Line 596
}
for (tmp = first; n_elide < total_lines - tmp->nlines; tmp = tmp->next) Line 599
{
desired_pos += tmp->nbytes; Line 601
xwrite_stdout (tmp->buffer, tmp->nbytes); Line 602
total_lines -= tmp->nlines; Line 603
}
/* Print the first 'total_lines - n_elide' lines of tmp->buffer. */
if (n_elide < total_lines) Line 607
{
size_t n = total_lines - n_elide; Line 609
char const *buffer_end = tmp->buffer + tmp->nbytes; Line 610
char const *p = tmp->buffer; Line 611
while (n && (p = memchr (p, line_end, buffer_end - p))) Line 612
{
++p; Line 614
++tmp->nlines; Line 615
--n; Line 616
}
desired_pos += p - tmp->buffer; Line 618
xwrite_stdout (tmp->buffer, p - tmp->buffer); Line 619
}
free_lbuffers: Line 622
while (first) Line 623
{
tmp = first->next; Line 625
free (first); Line 626
first = tmp; Line 627
}
if (0 <= current_pos && elseek (fd, desired_pos, SEEK_SET, filename) < 0) Line 630
ok = false; Line 631
return ok; Line 632
} Block 13
/* Output all but the last N_LINES lines of the input stream defined by
FD, START_POS, and SIZE.
START_POS is the starting position of the read pointer for the file
associated with FD (may be nonzero).
SIZE is the file size in bytes.
Return true upon success.
Give a diagnostic and return false upon error.
NOTE: this code is very similar to that of tail.c's file_lines function.
Unfortunately, factoring out some common core looks like it'd result
in a less efficient implementation or a messy interface. */
static bool Line 646
elide_tail_lines_seekable (const char *pretty_filename, int fd, Line 647
uintmax_t n_lines, Line 648
off_t start_pos, off_t size) Line 649
{
char buffer[BUFSIZ]; Line 651
size_t bytes_read; Line 652
off_t pos = size; Line 653
/* Set 'bytes_read' to the size of the last, probably partial, buffer;
0 < 'bytes_read' <= 'BUFSIZ'. */
bytes_read = (pos - start_pos) % BUFSIZ; Line 657
if (bytes_read == 0) Line 658
bytes_read = BUFSIZ; Line 659
/* Make 'pos' a multiple of 'BUFSIZ' (0 if the file is short), so that all
reads will be on block boundaries, which might increase efficiency. */
pos -= bytes_read; Line 662
if (elseek (fd, pos, SEEK_SET, pretty_filename) < 0) Line 663
return false; Line 664
bytes_read = safe_read (fd, buffer, bytes_read); Line 665...!syscalls auto-comment...
if (bytes_read == SAFE_READ_ERROR) Line 666
{
error (0, errno, _("error reading %s"), quoteaf (pretty_filename)); Line 668
return false; Line 669
}
/* n_lines == 0 case needs special treatment. */
const bool all_lines = !n_lines; Line 673
/* Count the incomplete line on files that don't end with a newline. */
if (n_lines && bytes_read && buffer[bytes_read - 1] != line_end) Line 676
--n_lines; Line 677
while (1) Line 679
{
/* Scan backward, counting the newlines in this bufferfull. */
size_t n = bytes_read; Line 683
while (n) Line 684
{
if (all_lines) Line 686
n -= 1; Line 687
else Line 688
{
char const *nl; Line 690
nl = memrchr (buffer, line_end, n); Line 691
if (nl == NULL) Line 692
break; Line 693
n = nl - buffer; Line 694
}
if (n_lines-- == 0) Line 696
{
/* Found it. */
/* If necessary, restore the file pointer and copy
input to output up to position, POS. */
if (start_pos < pos) Line 701
{
enum Copy_fd_status err; Line 703
if (elseek (fd, start_pos, SEEK_SET, pretty_filename) < 0) Line 704
return false; Line 705
err = copy_fd (fd, pos - start_pos); Line 707
if (err != COPY_FD_OK) Line 708
{
diagnose_copy_fd_failure (err, pretty_filename); Line 710
return false; Line 711
}
}
/* Output the initial portion of the buffer
in which we found the desired newline byte. */
xwrite_stdout (buffer, n + 1); Line 717
/* Set file pointer to the byte after what we've output. */
return 0 <= elseek (fd, pos + n + 1, SEEK_SET, pretty_filename); Line 720
}
}
/* Not enough newlines in that bufferfull. */
if (pos == start_pos) Line 725
{
/* Not enough lines in the file. */
return true; Line 728
}
pos -= BUFSIZ; Line 730
if (elseek (fd, pos, SEEK_SET, pretty_filename) < 0) Line 731
return false; Line 732
bytes_read = safe_read (fd, buffer, BUFSIZ); Line 734...!syscalls auto-comment...
if (bytes_read == SAFE_READ_ERROR) Line 735
{
error (0, errno, _("error reading %s"), quoteaf (pretty_filename)); Line 737
return false; Line 738
}
/* FIXME: is this dead code?
Consider the test, pos == start_pos, above. */
if (bytes_read == 0) Line 743
return true; Line 744
}
} Block 14
/* For the file FILENAME with descriptor FD, output all but the last N_ELIDE
lines. If SIZE is nonnegative, this is a regular file positioned
at START_POS with SIZE bytes. Return true on success.
Give a diagnostic and return nonzero upon error. */
static bool Line 753
elide_tail_lines_file (const char *filename, int fd, uintmax_t n_elide, Line 754
struct stat const *st, off_t current_pos) Line 755
{
off_t size = st->st_size; Line 757
if (presume_input_pipe || current_pos < 0 || size <= ST_BLKSIZE (*st)) Line 758
return elide_tail_lines_pipe (filename, fd, n_elide, current_pos); Line 759
else Line 760
{
/* Find the offset, OFF, of the Nth newline from the end,
but not counting the last byte of the file.
If found, write from current position to OFF, inclusive.
Otherwise, just return true. */
return (size <= current_pos Line 767
|| elide_tail_lines_seekable (filename, fd, n_elide, Line 768
current_pos, size)); Line 769
}
} Block 15
static bool Line 773
head_bytes (const char *filename, int fd, uintmax_t bytes_to_write) Line 774
{
char buffer[BUFSIZ]; Line 776
size_t bytes_to_read = BUFSIZ; Line 777
while (bytes_to_write) Line 779
{
size_t bytes_read; Line 781
if (bytes_to_write < bytes_to_read) Line 782
bytes_to_read = bytes_to_write; Line 783
bytes_read = safe_read (fd, buffer, bytes_to_read); Line 784...!syscalls auto-comment...
if (bytes_read == SAFE_READ_ERROR) Line 785
{
error (0, errno, _("error reading %s"), quoteaf (filename)); Line 787
return false; Line 788
}
if (bytes_read == 0) Line 790
break; Line 791
xwrite_stdout (buffer, bytes_read); Line 792
bytes_to_write -= bytes_read; Line 793
}
return true; Line 795
} Block 16
static bool Line 798
head_lines (const char *filename, int fd, uintmax_t lines_to_write) Line 799
{
char buffer[BUFSIZ]; Line 801
while (lines_to_write) Line 803
{
size_t bytes_read = safe_read (fd, buffer, BUFSIZ); Line 805...!syscalls auto-comment...
size_t bytes_to_write = 0; Line 806
if (bytes_read == SAFE_READ_ERROR) Line 808
{
error (0, errno, _("error reading %s"), quoteaf (filename)); Line 810
return false; Line 811
}
if (bytes_read == 0) Line 813
break; Line 814
while (bytes_to_write < bytes_read) Line 815
if (buffer[bytes_to_write++] == line_end && --lines_to_write == 0) Line 816
{
off_t n_bytes_past_EOL = bytes_read - bytes_to_write; Line 818
/* If we have read more data than that on the specified number
of lines, try to seek back to the position we would have
gotten to had we been reading one byte at a time. */
if (lseek (fd, -n_bytes_past_EOL, SEEK_CUR) < 0) Line 822
{
struct stat st; Line 824
if (fstat (fd, &st) != 0 || S_ISREG (st.st_mode)) Line 825...!syscalls auto-comment......!syscalls auto-comment...
elseek (fd, -n_bytes_past_EOL, SEEK_CUR, filename); Line 826
}
break; Line 828
}
xwrite_stdout (buffer, bytes_to_write); Line 830
}
return true; Line 832
} Block 17
static bool Line 835
head (const char *filename, int fd, uintmax_t n_units, bool count_lines, Line 836
bool elide_from_end) Line 837
{
if (print_headers) Line 839
write_header (filename); Line 840
if (elide_from_end) Line 842
{
off_t current_pos = -1; Line 844
struct stat st; Line 845
if (fstat (fd, &st) != 0) Line 846...!syscalls auto-comment......!syscalls auto-comment...
{
error (0, errno, _("cannot fstat %s"), Line 848
quoteaf (filename)); Line 849
return false; Line 850
}
if (! presume_input_pipe && usable_st_size (&st)) Line 852
{
current_pos = elseek (fd, 0, SEEK_CUR, filename); Line 854
if (current_pos < 0) Line 855
return false; Line 856
}
if (count_lines) Line 858
return elide_tail_lines_file (filename, fd, n_units, &st, current_pos); Line 859
else Line 860
return elide_tail_bytes_file (filename, fd, n_units, &st, current_pos); Line 861
}
if (count_lines) Line 863
return head_lines (filename, fd, n_units); Line 864
else Line 865
return head_bytes (filename, fd, n_units); Line 866
} Block 18
static bool Line 869
head_file (const char *filename, uintmax_t n_units, bool count_lines, Line 870
bool elide_from_end) Line 871
{
int fd; Line 873
bool ok; Line 874
bool is_stdin = STREQ (filename, "-"); Line 875
if (is_stdin) Line 877
{
have_read_stdin = true; Line 879
fd = STDIN_FILENO; Line 880
filename = _("standard input"); Line 881
xset_binary_mode (STDIN_FILENO, O_BINARY); Line 882
}
else Line 884
{
fd = open (filename, O_RDONLY | O_BINARY); Line 886...!syscalls auto-comment...
if (fd < 0) Line 887
{
error (0, errno, _("cannot open %s for reading"), quoteaf (filename));Line 889
return false; Line 890
}
}
ok = head (filename, fd, n_units, count_lines, elide_from_end); Line 894
if (!is_stdin && close (fd) != 0) Line 895...!syscalls auto-comment...
{
error (0, errno, _("failed to close %s"), quoteaf (filename)); Line 897
return false; Line 898
}
return ok; Line 900
} Block 19
/* Convert a string of decimal digits, N_STRING, with an optional suffix
to an integral value. Upon successful conversion,
return that value. If it cannot be converted, give a diagnostic and exit.
COUNT_LINES indicates whether N_STRING is a number of bytes or a number
of lines. It is used solely to give a more specific diagnostic. */
static uintmax_t Line 909
string_to_integer (bool count_lines, const char *n_string) Line 910
{
return xdectoumax (n_string, 0, UINTMAX_MAX, "bkKmMGTPEZY0", Line 912
count_lines ? _("invalid number of lines") Line 913
: _("invalid number of bytes"), 0); Line 914
} Block 20
int
main (int argc, char **argv) Line 918
{
enum header_mode header_mode = multiple_files; Line 920
bool ok = true; Line 921
int c; Line 922
size_t i; Line 923
/* Number of items to print. */
uintmax_t n_units = DEFAULT_NUMBER; Line 926
/* If true, interpret the numeric argument as the number of lines.
Otherwise, interpret it as the number of bytes. */
bool count_lines = true; Line 930
/* Elide the specified number of lines or bytes, counting from
the end of the file. */
bool elide_from_end = false; Line 934
/* Initializer for file_list if no file-arguments
were specified on the command line. */
static char const *const default_file_list[] = {"-", NULL}; Line 938
char const *const *file_list; Line 939
initialize_main (&argc, &argv); VMS-specific entry point handling wildcard expansion
set_program_name (argv[0]); Retains program name and discards path
setlocale (LC_ALL, ""); Sets up internationalization (i18n)
bindtextdomain (PACKAGE, LOCALEDIR); Assigns i18n directorySets text domain for _() [gettext()] function
textdomain (PACKAGE); Sets text domain for _() [gettext()] function
atexit (close_stdout); Close stdout on exit (see gnulib)
have_read_stdin = false; Line 949
print_headers = false; Line 951
line_end = '\n'; Line 953
if (1 < argc && argv[1][0] == '-' && ISDIGIT (argv[1][1])) Line 955
{
char *a = argv[1]; Line 957
char *n_string = ++a; Line 958
char *end_n_string; Line 959
char multiplier_char = 0; Line 960
/* Old option syntax; a dash, one or more digits, and one or
more option letters. Move past the number. */
do ++a; Line 964
while (ISDIGIT (*a)); Line 965
/* Pointer to the byte after the last digit. */
end_n_string = a; Line 968
/* Parse any appended option letters. */
for (; *a; a++) Line 971
{
switch (*a) Line 973
{
case 'c': Line 975
count_lines = false; Line 976
multiplier_char = 0; Line 977
break; Line 978
case 'b': Line 980
case 'k': Line 981
case 'm': Line 982
count_lines = false; Line 983
multiplier_char = *a; Line 984
break; Line 985
case 'l': Line 987
count_lines = true; Line 988
break; Line 989
case 'q': Line 991
header_mode = never; Line 992
break; Line 993
case 'v': Line 995
header_mode = always; Line 996
break; Line 997
case 'z': Line 999
line_end = '\0'; Line 1000
break; Line 1001
default: Line 1003
error (0, 0, _("invalid trailing option -- %c"), *a); Line 1004
usage (EXIT_FAILURE); Line 1005
}
}
/* Append the multiplier character (if any) onto the end of
the digit string. Then add NUL byte if necessary. */
*end_n_string = multiplier_char; Line 1011
if (multiplier_char) Line 1012
*(++end_n_string) = 0; Line 1013
n_units = string_to_integer (count_lines, n_string); Line 1015
/* Make the options we just parsed invisible to getopt. */
argv[1] = argv[0]; Line 1018
argv++; Line 1019
argc--; Line 1020
}
while ((c = getopt_long (argc, argv, "c:n:qvz0123456789", long_options, NULL))Line 1023
!= -1) Line 1024
{
switch (c) Line 1026
{
case PRESUME_INPUT_PIPE_OPTION: Line 1028
presume_input_pipe = true; Line 1029
break; Line 1030
case 'c': Line 1032
count_lines = false; Line 1033
elide_from_end = (*optarg == '-'); Line 1034
if (elide_from_end) Line 1035
++optarg; Line 1036
n_units = string_to_integer (count_lines, optarg); Line 1037
break; Line 1038
case 'n': Line 1040
count_lines = true; Line 1041
elide_from_end = (*optarg == '-'); Line 1042
if (elide_from_end) Line 1043
++optarg; Line 1044
n_units = string_to_integer (count_lines, optarg); Line 1045
break; Line 1046
case 'q': Line 1048
header_mode = never; Line 1049
break; Line 1050
case 'v': Line 1052
header_mode = always; Line 1053
break; Line 1054
case 'z': Line 1056
line_end = '\0'; Line 1057
break; Line 1058
case_GETOPT_HELP_CHAR; Line 1060
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); Line 1062
default: Line 1064
if (ISDIGIT (c)) Line 1065
error (0, 0, _("invalid trailing option -- %c"), c); Line 1066
usage (EXIT_FAILURE); Line 1067
}
}
if (header_mode == always Line 1071
|| (header_mode == multiple_files && optind < argc - 1)) Line 1072
print_headers = true; Line 1073
if ( ! count_lines && elide_from_end && OFF_T_MAX < n_units) Line 1075
{
char umax_buf[INT_BUFSIZE_BOUND (n_units)]; Line 1077
die (EXIT_FAILURE, EOVERFLOW, "%s: %s", _("invalid number of bytes"), Line 1078
quote (umaxtostr (n_units, umax_buf))); Line 1079
}
file_list = (optind < argc Line 1082
? (char const *const *) &argv[optind] Line 1083
: default_file_list); Line 1084
xset_binary_mode (STDOUT_FILENO, O_BINARY); Line 1086
for (i = 0; file_list[i]; ++i) Line 1088
ok &= head_file (file_list[i], n_units, count_lines, elide_from_end); Line 1089
if (have_read_stdin && close (STDIN_FILENO) < 0) Line 1091...!syscalls auto-comment...
die (EXIT_FAILURE, errno, "-"); Line 1092
return ok ? EXIT_SUCCESS : EXIT_FAILURE; Line 1094
} Block 21