LCOV - code coverage report
Current view: top level - src - head.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 280 400 70.0 %
Date: 2018-01-30 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /* head -- output first part of file(s)
       2             :    Copyright (C) 89, 90, 91, 1995-2006 Free Software Foundation, Inc.
       3             : 
       4             :    This program is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation, either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      16             : 
      17             : /* Options: (see usage)
      18             :    Reads from standard input if no files are given or when a filename of
      19             :    ``-'' is encountered.
      20             :    By default, filename headers are printed only if more than one file
      21             :    is given.
      22             :    By default, prints the first 10 lines (head -n 10).
      23             : 
      24             :    David MacKenzie <djm@gnu.ai.mit.edu> */
      25             : 
      26             : #include <config.h>
      27             : 
      28             : #include <stdio.h>
      29             : #include <getopt.h>
      30             : #include <sys/types.h>
      31             : 
      32             : #include "system.h"
      33             : 
      34             : #include "error.h"
      35             : #include "full-write.h"
      36             : #include "full-read.h"
      37             : #include "inttostr.h"
      38             : #include "quote.h"
      39             : #include "safe-read.h"
      40             : #include "xstrtol.h"
      41             : 
      42             : /* The official name of this program (e.g., no `g' prefix).  */
      43             : #define PROGRAM_NAME "head"
      44             : 
      45             : #define AUTHORS "David MacKenzie", "Jim Meyering"
      46             : 
      47             : /* Number of lines/chars/blocks to head. */
      48             : #define DEFAULT_NUMBER 10
      49             : 
      50             : /* Useful only when eliding tail bytes or lines.
      51             :    If true, skip the is-regular-file test used to determine whether
      52             :    to use the lseek optimization.  Instead, use the more general (and
      53             :    more expensive) code unconditionally. Intended solely for testing.  */
      54             : static bool presume_input_pipe;
      55             : 
      56             : /* If true, print filename headers. */
      57             : static bool print_headers;
      58             : 
      59             : /* When to print the filename banners. */
      60             : enum header_mode
      61             : {
      62             :   multiple_files, always, never
      63             : };
      64             : 
      65             : /* The name this program was run with. */
      66             : char *program_name;
      67             : 
      68             : /* Have we ever read standard input?  */
      69             : static bool have_read_stdin;
      70             : 
      71             : enum Copy_fd_status
      72             :   {
      73             :     COPY_FD_OK = 0,
      74             :     COPY_FD_READ_ERROR,
      75             :     COPY_FD_WRITE_ERROR,
      76             :     COPY_FD_UNEXPECTED_EOF
      77             :   };
      78             : 
      79             : /* For long options that have no equivalent short option, use a
      80             :    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
      81             : enum
      82             : {
      83             :   PRESUME_INPUT_PIPE_OPTION = CHAR_MAX + 1
      84             : };
      85             : 
      86             : static struct option const long_options[] =
      87             : {
      88             :   {"bytes", required_argument, NULL, 'c'},
      89             :   {"lines", required_argument, NULL, 'n'},
      90             :   {"-presume-input-pipe", no_argument, NULL,
      91             :    PRESUME_INPUT_PIPE_OPTION}, /* do not document */
      92             :   {"quiet", no_argument, NULL, 'q'},
      93             :   {"silent", no_argument, NULL, 'q'},
      94             :   {"verbose", no_argument, NULL, 'v'},
      95             :   {GETOPT_HELP_OPTION_DECL},
      96             :   {GETOPT_VERSION_OPTION_DECL},
      97             :   {NULL, 0, NULL, 0}
      98             : };
      99             : 
     100             : void
     101          13 : usage (int status)
     102             : {
     103          13 :   if (status != EXIT_SUCCESS)
     104          12 :     fprintf (stderr, _("Try `%s --help' for more information.\n"),
     105             :              program_name);
     106             :   else
     107             :     {
     108           1 :       printf (_("\
     109             : Usage: %s [OPTION]... [FILE]...\n\
     110             : "),
     111             :               program_name);
     112           1 :       fputs (_("\
     113             : Print the first 10 lines of each FILE to standard output.\n\
     114             : With more than one FILE, precede each with a header giving the file name.\n\
     115             : With no FILE, or when FILE is -, read standard input.\n\
     116             : \n\
     117             : "), stdout);
     118           1 :       fputs (_("\
     119             : Mandatory arguments to long options are mandatory for short options too.\n\
     120             : "), stdout);
     121           1 :       fputs (_("\
     122             :   -c, --bytes=[-]N         print the first N bytes of each file;\n\
     123             :                              with the leading `-', print all but the last\n\
     124             :                              N bytes of each file\n\
     125             :   -n, --lines=[-]N         print the first N lines instead of the first 10;\n\
     126             :                              with the leading `-', print all but the last\n\
     127             :                              N lines of each file\n\
     128             : "), stdout);
     129           1 :       fputs (_("\
     130             :   -q, --quiet, --silent    never print headers giving file names\n\
     131             :   -v, --verbose            always print headers giving file names\n\
     132             : "), stdout);
     133           1 :       fputs (HELP_OPTION_DESCRIPTION, stdout);
     134           1 :       fputs (VERSION_OPTION_DESCRIPTION, stdout);
     135           1 :       fputs (_("\
     136             : \n\
     137             : N may have a multiplier suffix:\n\
     138             : b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\
     139             : GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\
     140             : "), stdout);
     141           1 :       emit_bug_reporting_address ();
     142             :     }
     143          13 :   exit (status);
     144             : }
     145             : 
     146             : static void
     147           0 : diagnose_copy_fd_failure (enum Copy_fd_status err, char const *filename)
     148             : {
     149           0 :   switch (err)
     150             :     {
     151           0 :     case COPY_FD_READ_ERROR:
     152           0 :       error (0, errno, _("error reading %s"), quote (filename));
     153           0 :       break;
     154           0 :     case COPY_FD_WRITE_ERROR:
     155           0 :       error (0, errno, _("error writing %s"), quote (filename));
     156           0 :       break;
     157           0 :     case COPY_FD_UNEXPECTED_EOF:
     158           0 :       error (0, errno, _("%s: file has shrunk too much"), quote (filename));
     159           0 :       break;
     160           0 :     default:
     161           0 :       abort ();
     162             :     }
     163           0 : }
     164             : 
     165             : static void
     166          32 : write_header (const char *filename)
     167             : {
     168             :   static bool first_file = true;
     169             : 
     170          32 :   printf ("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
     171          32 :   first_file = false;
     172          32 : }
     173             : 
     174             : /* Copy no more than N_BYTES from file descriptor SRC_FD to O_STREAM.
     175             :    Return an appropriate indication of success or failure. */
     176             : 
     177             : static enum Copy_fd_status
     178           1 : copy_fd (int src_fd, FILE *o_stream, uintmax_t n_bytes)
     179             : {
     180             :   char buf[BUFSIZ];
     181           1 :   const size_t buf_size = sizeof (buf);
     182             : 
     183             :   /* Copy the file contents.  */
     184           3 :   while (0 < n_bytes)
     185             :     {
     186           1 :       size_t n_to_read = MIN (buf_size, n_bytes);
     187           1 :       size_t n_read = safe_read (src_fd, buf, n_to_read);
     188           1 :       if (n_read == SAFE_READ_ERROR)
     189           0 :         return COPY_FD_READ_ERROR;
     190             : 
     191           1 :       n_bytes -= n_read;
     192             : 
     193           1 :       if (n_read == 0 && n_bytes != 0)
     194           0 :         return COPY_FD_UNEXPECTED_EOF;
     195             : 
     196           1 :       if (fwrite (buf, 1, n_read, o_stream) < n_read)
     197           0 :         return COPY_FD_WRITE_ERROR;
     198             :     }
     199             : 
     200           1 :   return COPY_FD_OK;
     201             : }
     202             : 
     203             : /* Print all but the last N_ELIDE lines from the input available via
     204             :    the non-seekable file descriptor FD.  Return true upon success.
     205             :    Give a diagnostic and return false upon error.  */
     206             : static bool
     207           5 : elide_tail_bytes_pipe (const char *filename, int fd, uintmax_t n_elide_0)
     208             : {
     209           5 :   size_t n_elide = n_elide_0;
     210             : 
     211             : #ifndef HEAD_TAIL_PIPE_READ_BUFSIZE
     212             : # define HEAD_TAIL_PIPE_READ_BUFSIZE BUFSIZ
     213             : #endif
     214             : #define READ_BUFSIZE HEAD_TAIL_PIPE_READ_BUFSIZE
     215             : 
     216             :   /* If we're eliding no more than this many bytes, then it's ok to allocate
     217             :      more memory in order to use a more time-efficient algorithm.
     218             :      FIXME: use a fraction of available memory instead, as in sort.
     219             :      FIXME: is this even worthwhile?  */
     220             : #ifndef HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD
     221             : # define HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD 1024 * 1024
     222             : #endif
     223             : 
     224             : #if HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD < 2 * READ_BUFSIZE
     225             :   "HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD must be at least 2 * READ_BUFSIZE"
     226             : #endif
     227             : 
     228             :   if (SIZE_MAX < n_elide_0 + READ_BUFSIZE)
     229             :     {
     230             :       char umax_buf[INT_BUFSIZE_BOUND (uintmax_t)];
     231             :       error (EXIT_FAILURE, 0, _("%s: number of bytes is too large"),
     232             :              umaxtostr (n_elide_0, umax_buf));
     233             :     }
     234             : 
     235             :   /* Two cases to consider...
     236             :      1) n_elide is small enough that we can afford to double-buffer:
     237             :         allocate 2 * (READ_BUFSIZE + n_elide) bytes
     238             :      2) n_elide is too big for that, so we allocate only
     239             :         (READ_BUFSIZE + n_elide) bytes
     240             : 
     241             :      FIXME: profile, to see if double-buffering is worthwhile
     242             : 
     243             :      CAUTION: do not fail (out of memory) when asked to elide
     244             :      a ridiculous amount, but when given only a small input.  */
     245             : 
     246           5 :   if (n_elide <= HEAD_TAIL_PIPE_BYTECOUNT_THRESHOLD)
     247             :     {
     248           3 :       bool ok = true;
     249           3 :       bool first = true;
     250           3 :       bool eof = false;
     251           3 :       size_t n_to_read = READ_BUFSIZE + n_elide;
     252             :       bool i;
     253             :       char *b[2];
     254           3 :       b[0] = xnmalloc (2, n_to_read);
     255           3 :       b[1] = b[0] + n_to_read;
     256             : 
     257           6 :       for (i = false; ! eof ; i = !i)
     258             :         {
     259           3 :           size_t n_read = full_read (fd, b[i], n_to_read);
     260           3 :           size_t delta = 0;
     261           3 :           if (n_read < n_to_read)
     262             :             {
     263           3 :               if (errno != 0)
     264             :                 {
     265           0 :                   error (0, errno, _("error reading %s"), quote (filename));
     266           0 :                   ok = false;
     267           0 :                   break;
     268             :                 }
     269             : 
     270             :               /* reached EOF */
     271           3 :               if (n_read <= n_elide)
     272             :                 {
     273           0 :                   if (first)
     274             :                     {
     275             :                       /* The input is no larger than the number of bytes
     276             :                          to elide.  So there's nothing to output, and
     277             :                          we're done.  */
     278             :                     }
     279             :                   else
     280             :                     {
     281           0 :                       delta = n_elide - n_read;
     282             :                     }
     283             :                 }
     284           3 :               eof = true;
     285             :             }
     286             : 
     287             :           /* Output any (but maybe just part of the) elided data from
     288             :              the previous round.  */
     289           3 :           if ( ! first)
     290             :             {
     291             :               /* Don't bother checking for errors here.
     292             :                  If there's a failure, the test of the following
     293             :                  fwrite or in close_stdout will catch it.  */
     294           0 :               fwrite (b[!i] + READ_BUFSIZE, 1, n_elide - delta, stdout);
     295             :             }
     296           3 :           first = false;
     297             : 
     298           3 :           if (n_elide < n_read
     299           3 :               && fwrite (b[i], 1, n_read - n_elide, stdout) < n_read - n_elide)
     300             :             {
     301           0 :               error (0, errno, _("write error"));
     302           0 :               ok = false;
     303           0 :               break;
     304             :             }
     305             :         }
     306             : 
     307           3 :       free (b[0]);
     308           3 :       return ok;
     309             :     }
     310             :   else
     311             :     {
     312             :       /* Read blocks of size READ_BUFSIZE, until we've read at least n_elide
     313             :          bytes.  Then, for each new buffer we read, also write an old one.  */
     314             : 
     315           2 :       bool ok = true;
     316           2 :       bool eof = false;
     317             :       size_t n_read;
     318             :       bool buffered_enough;
     319             :       size_t i, i_next;
     320             :       char **b;
     321             :       /* Round n_elide up to a multiple of READ_BUFSIZE.  */
     322           2 :       size_t rem = READ_BUFSIZE - (n_elide % READ_BUFSIZE);
     323           2 :       size_t n_elide_round = n_elide + rem;
     324           2 :       size_t n_bufs = n_elide_round / READ_BUFSIZE + 1;
     325           2 :       b = xcalloc (n_bufs, sizeof *b);
     326             : 
     327           2 :       buffered_enough = false;
     328           4 :       for (i = 0, i_next = 1; !eof; i = i_next, i_next = (i_next + 1) % n_bufs)
     329             :         {
     330           2 :           if (b[i] == NULL)
     331           2 :             b[i] = xmalloc (READ_BUFSIZE);
     332           2 :           n_read = full_read (fd, b[i], READ_BUFSIZE);
     333           2 :           if (n_read < READ_BUFSIZE)
     334             :             {
     335           2 :               if (errno != 0)
     336             :                 {
     337           0 :                   error (0, errno, _("error reading %s"), quote (filename));
     338           0 :                   ok = false;
     339           0 :                   goto free_mem;
     340             :                 }
     341           2 :               eof = true;
     342             :             }
     343             : 
     344           2 :           if (i + 1 == n_bufs)
     345           0 :             buffered_enough = true;
     346             : 
     347           2 :           if (buffered_enough)
     348             :             {
     349           0 :               if (fwrite (b[i_next], 1, n_read, stdout) < n_read)
     350             :                 {
     351           0 :                   error (0, errno, _("write error"));
     352           0 :                   ok = false;
     353           0 :                   goto free_mem;
     354             :                 }
     355             :             }
     356             :         }
     357             : 
     358             :       /* Output any remainder: rem bytes from b[i] + n_read.  */
     359           2 :       if (rem)
     360             :         {
     361           2 :           if (buffered_enough)
     362             :             {
     363           0 :               size_t n_bytes_left_in_b_i = READ_BUFSIZE - n_read;
     364           0 :               if (rem < n_bytes_left_in_b_i)
     365             :                 {
     366           0 :                   fwrite (b[i] + n_read, 1, rem, stdout);
     367             :                 }
     368             :               else
     369             :                 {
     370           0 :                   fwrite (b[i] + n_read, 1, n_bytes_left_in_b_i, stdout);
     371           0 :                   fwrite (b[i_next], 1, rem - n_bytes_left_in_b_i, stdout);
     372             :                 }
     373             :             }
     374           2 :           else if (i + 1 == n_bufs)
     375             :             {
     376             :               /* This happens when n_elide < file_size < n_elide_round.
     377             : 
     378             :                  |READ_BUF.|
     379             :                  |                      |  rem |
     380             :                  |---------!---------!---------!---------|
     381             :                  |---- n_elide ---------|
     382             :                  |                      | x |
     383             :                  |                   |y |
     384             :                  |---- file size -----------|
     385             :                  |                   |n_read|
     386             :                  |---- n_elide_round ----------|
     387             :                */
     388           0 :               size_t y = READ_BUFSIZE - rem;
     389           0 :               size_t x = n_read - y;
     390           0 :               fwrite (b[i_next], 1, x, stdout);
     391             :             }
     392             :         }
     393             : 
     394           4 :     free_mem:;
     395         554 :       for (i = 0; i < n_bufs; i++)
     396         552 :         free (b[i]);
     397           2 :       free (b);
     398             : 
     399           2 :       return ok;
     400             :     }
     401             : }
     402             : 
     403             : /* Print all but the last N_ELIDE lines from the input available
     404             :    via file descriptor FD.  Return true upon success.
     405             :    Give a diagnostic and return false upon error.  */
     406             : 
     407             : /* NOTE: if the input file shrinks by more than N_ELIDE bytes between
     408             :    the length determination and the actual reading, then head fails.  */
     409             : 
     410             : static bool
     411           9 : elide_tail_bytes_file (const char *filename, int fd, uintmax_t n_elide)
     412             : {
     413             :   struct stat stats;
     414             : 
     415           9 :   if (presume_input_pipe || fstat (fd, &stats) || ! S_ISREG (stats.st_mode))
     416             :     {
     417           5 :       return elide_tail_bytes_pipe (filename, fd, n_elide);
     418             :     }
     419             :   else
     420             :     {
     421             :       off_t current_pos, end_pos;
     422             :       uintmax_t bytes_remaining;
     423             :       off_t diff;
     424             :       enum Copy_fd_status err;
     425             : 
     426           4 :       if ((current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) == -1
     427           4 :           || (end_pos = lseek (fd, (off_t) 0, SEEK_END)) == -1)
     428             :         {
     429           0 :           error (0, errno, _("cannot lseek %s"), quote (filename));
     430           0 :           return false;
     431             :         }
     432             : 
     433             :       /* Be careful here.  The current position may actually be
     434             :          beyond the end of the file.  */
     435           4 :       bytes_remaining = (diff = end_pos - current_pos) < 0 ? 0 : diff;
     436             : 
     437           4 :       if (bytes_remaining <= n_elide)
     438           3 :         return true;
     439             : 
     440             :       /* Seek back to `current' position, then copy the required
     441             :          number of bytes from fd.  */
     442           1 :       if (lseek (fd, (off_t) 0, current_pos) == -1)
     443             :         {
     444           0 :           error (0, errno, _("%s: cannot lseek back to original position"),
     445             :                  quote (filename));
     446           0 :           return false;
     447             :         }
     448             : 
     449           1 :       err = copy_fd (fd, stdout, bytes_remaining - n_elide);
     450           1 :       if (err == COPY_FD_OK)
     451           1 :         return true;
     452             : 
     453           0 :       diagnose_copy_fd_failure (err, filename);
     454           0 :       return false;
     455             :     }
     456             : }
     457             : 
     458             : /* Print all but the last N_ELIDE lines from the input stream
     459             :    open for reading via file descriptor FD.
     460             :    Buffer the specified number of lines as a linked list of LBUFFERs,
     461             :    adding them as needed.  Return true if successful.  */
     462             : 
     463             : static bool
     464           1 : elide_tail_lines_pipe (const char *filename, int fd, uintmax_t n_elide)
     465             : {
     466             :   struct linebuffer
     467             :   {
     468             :     char buffer[BUFSIZ];
     469             :     size_t nbytes;
     470             :     size_t nlines;
     471             :     struct linebuffer *next;
     472             :   };
     473             :   typedef struct linebuffer LBUFFER;
     474             :   LBUFFER *first, *last, *tmp;
     475           1 :   size_t total_lines = 0;       /* Total number of newlines in all buffers.  */
     476           1 :   bool ok = true;
     477             :   size_t n_read;                /* Size in bytes of most recent read */
     478             : 
     479           1 :   first = last = xmalloc (sizeof (LBUFFER));
     480           1 :   first->nbytes = first->nlines = 0;
     481           1 :   first->next = NULL;
     482           1 :   tmp = xmalloc (sizeof (LBUFFER));
     483             : 
     484             :   /* Always read into a fresh buffer.
     485             :      Read, (producing no output) until we've accumulated at least
     486             :      n_elide newlines, or until EOF, whichever comes first.  */
     487             :   while (1)
     488             :     {
     489           1 :       n_read = safe_read (fd, tmp->buffer, BUFSIZ);
     490           1 :       if (n_read == 0 || n_read == SAFE_READ_ERROR)
     491             :         break;
     492           0 :       tmp->nbytes = n_read;
     493           0 :       tmp->nlines = 0;
     494           0 :       tmp->next = NULL;
     495             : 
     496             :       /* Count the number of newlines just read.  */
     497             :       {
     498           0 :         char const *buffer_end = tmp->buffer + n_read;
     499           0 :         char const *p = tmp->buffer;
     500           0 :         while ((p = memchr (p, '\n', buffer_end - p)))
     501             :           {
     502           0 :             ++p;
     503           0 :             ++tmp->nlines;
     504             :           }
     505             :       }
     506           0 :       total_lines += tmp->nlines;
     507             : 
     508             :       /* If there is enough room in the last buffer read, just append the new
     509             :          one to it.  This is because when reading from a pipe, `n_read' can
     510             :          often be very small.  */
     511           0 :       if (tmp->nbytes + last->nbytes < BUFSIZ)
     512             :         {
     513           0 :           memcpy (&last->buffer[last->nbytes], tmp->buffer, tmp->nbytes);
     514           0 :           last->nbytes += tmp->nbytes;
     515           0 :           last->nlines += tmp->nlines;
     516             :         }
     517             :       else
     518             :         {
     519             :           /* If there's not enough room, link the new buffer onto the end of
     520             :              the list, then either free up the oldest buffer for the next
     521             :              read if that would leave enough lines, or else malloc a new one.
     522             :              Some compaction mechanism is possible but probably not
     523             :              worthwhile.  */
     524           0 :           last = last->next = tmp;
     525           0 :           if (n_elide < total_lines - first->nlines)
     526             :             {
     527           0 :               fwrite (first->buffer, 1, first->nbytes, stdout);
     528           0 :               tmp = first;
     529           0 :               total_lines -= first->nlines;
     530           0 :               first = first->next;
     531             :             }
     532             :           else
     533           0 :             tmp = xmalloc (sizeof (LBUFFER));
     534             :         }
     535             :     }
     536             : 
     537           1 :   free (tmp);
     538             : 
     539           1 :   if (n_read == SAFE_READ_ERROR)
     540             :     {
     541           0 :       error (0, errno, _("error reading %s"), quote (filename));
     542           0 :       ok = false;
     543           0 :       goto free_lbuffers;
     544             :     }
     545             : 
     546             :   /* If we read any bytes at all, count the incomplete line
     547             :      on files that don't end with a newline.  */
     548           1 :   if (last->nbytes && last->buffer[last->nbytes - 1] != '\n')
     549             :     {
     550           0 :       ++last->nlines;
     551           0 :       ++total_lines;
     552             :     }
     553             : 
     554           1 :   for (tmp = first; n_elide < total_lines - tmp->nlines; tmp = tmp->next)
     555             :     {
     556           0 :       fwrite (tmp->buffer, 1, tmp->nbytes, stdout);
     557           0 :       total_lines -= tmp->nlines;
     558             :     }
     559             : 
     560             :   /* Print the first `total_lines - n_elide' lines of tmp->buffer.  */
     561           1 :   if (n_elide < total_lines)
     562             :     {
     563           0 :       size_t n = total_lines - n_elide;
     564           0 :       char const *buffer_end = tmp->buffer + tmp->nbytes;
     565           0 :       char const *p = tmp->buffer;
     566           0 :       while (n && (p = memchr (p, '\n', buffer_end - p)))
     567             :         {
     568           0 :           ++p;
     569           0 :           ++tmp->nlines;
     570           0 :           --n;
     571             :         }
     572           0 :       fwrite (tmp->buffer, 1, p - tmp->buffer, stdout);
     573             :     }
     574             : 
     575           2 : free_lbuffers:
     576           3 :   while (first)
     577             :     {
     578           1 :       tmp = first->next;
     579           1 :       free (first);
     580           1 :       first = tmp;
     581             :     }
     582           1 :   return ok;
     583             : }
     584             : 
     585             : /* Output all but the last N_LINES lines of the input stream defined by
     586             :    FD, START_POS, and END_POS.
     587             :    START_POS is the starting position of the read pointer for the file
     588             :    associated with FD (may be nonzero).
     589             :    END_POS is the file offset of EOF (one larger than offset of last byte).
     590             :    Return true upon success.
     591             :    Give a diagnostic and return false upon error.
     592             : 
     593             :    NOTE: this code is very similar to that of tail.c's file_lines function.
     594             :    Unfortunately, factoring out some common core looks like it'd result
     595             :    in a less efficient implementation or a messy interface.  */
     596             : static bool
     597           5 : elide_tail_lines_seekable (const char *pretty_filename, int fd,
     598             :                            uintmax_t n_lines,
     599             :                            off_t start_pos, off_t end_pos)
     600             : {
     601             :   char buffer[BUFSIZ];
     602             :   size_t bytes_read;
     603           5 :   off_t pos = end_pos;
     604             : 
     605             :   /* Set `bytes_read' to the size of the last, probably partial, buffer;
     606             :      0 < `bytes_read' <= `BUFSIZ'.  */
     607           5 :   bytes_read = (pos - start_pos) % BUFSIZ;
     608           5 :   if (bytes_read == 0)
     609           0 :     bytes_read = BUFSIZ;
     610             :   /* Make `pos' a multiple of `BUFSIZ' (0 if the file is short), so that all
     611             :      reads will be on block boundaries, which might increase efficiency.  */
     612           5 :   pos -= bytes_read;
     613           5 :   if (lseek (fd, pos, SEEK_SET) < 0)
     614             :     {
     615             :       char offset_buf[INT_BUFSIZE_BOUND (off_t)];
     616           0 :       error (0, errno, _("%s: cannot seek to offset %s"),
     617             :              pretty_filename, offtostr (pos, offset_buf));
     618           0 :       return false;
     619             :     }
     620           5 :   bytes_read = safe_read (fd, buffer, bytes_read);
     621           5 :   if (bytes_read == SAFE_READ_ERROR)
     622             :     {
     623           1 :       error (0, errno, _("error reading %s"), quote (pretty_filename));
     624           1 :       return false;
     625             :     }
     626             : 
     627             :   /* Count the incomplete line on files that don't end with a newline.  */
     628           4 :   if (bytes_read && buffer[bytes_read - 1] != '\n')
     629           1 :     --n_lines;
     630             : 
     631             :   while (1)
     632           0 :     {
     633             :       /* Scan backward, counting the newlines in this bufferfull.  */
     634             : 
     635           4 :       size_t n = bytes_read;
     636           9 :       while (n)
     637             :         {
     638             :           char const *nl;
     639           5 :           nl = memrchr (buffer, '\n', n);
     640           5 :           if (nl == NULL)
     641           0 :             break;
     642           5 :           n = nl - buffer;
     643           5 :           if (n_lines-- == 0)
     644             :             {
     645             :               /* Found it.  */
     646             :               /* If necessary, restore the file pointer and copy
     647             :                  input to output up to position, POS.  */
     648           4 :               if (start_pos < pos)
     649             :                 {
     650             :                   enum Copy_fd_status err;
     651           0 :                   if (lseek (fd, start_pos, SEEK_SET) < 0)
     652             :                     {
     653             :                       /* Failed to reposition file pointer.  */
     654           0 :                       error (0, errno,
     655             :                          "%s: unable to restore file pointer to initial offset",
     656             :                              quote (pretty_filename));
     657           0 :                       return false;
     658             :                     }
     659             : 
     660           0 :                   err = copy_fd (fd, stdout, pos - start_pos);
     661           0 :                   if (err != COPY_FD_OK)
     662             :                     {
     663           0 :                       diagnose_copy_fd_failure (err, pretty_filename);
     664           0 :                       return false;
     665             :                     }
     666             :                 }
     667             : 
     668             :               /* Output the initial portion of the buffer
     669             :                  in which we found the desired newline byte.
     670             :                  Don't bother testing for failure for such a small amount.
     671             :                  Any failure will be detected upon close.  */
     672           4 :               fwrite (buffer, 1, n + 1, stdout);
     673           4 :               return true;
     674             :             }
     675             :         }
     676             : 
     677             :       /* Not enough newlines in that bufferfull.  */
     678           0 :       if (pos == start_pos)
     679             :         {
     680             :           /* Not enough lines in the file.  */
     681           0 :           return true;
     682             :         }
     683           0 :       pos -= BUFSIZ;
     684           0 :       if (lseek (fd, pos, SEEK_SET) < 0)
     685             :         {
     686             :           char offset_buf[INT_BUFSIZE_BOUND (off_t)];
     687           0 :           error (0, errno, _("%s: cannot seek to offset %s"),
     688             :                  pretty_filename, offtostr (pos, offset_buf));
     689           0 :           return false;
     690             :         }
     691             : 
     692           0 :       bytes_read = safe_read (fd, buffer, BUFSIZ);
     693           0 :       if (bytes_read == SAFE_READ_ERROR)
     694             :         {
     695           0 :           error (0, errno, _("error reading %s"), quote (pretty_filename));
     696           0 :           return false;
     697             :         }
     698             : 
     699             :       /* FIXME: is this dead code?
     700             :          Consider the test, pos == start_pos, above. */
     701           0 :       if (bytes_read == 0)
     702           0 :         return true;
     703             :     }
     704             : }
     705             : 
     706             : /* Print all but the last N_ELIDE lines from the input available
     707             :    via file descriptor FD.  Return true upon success.
     708             :    Give a diagnostic and return nonzero upon error.  */
     709             : 
     710             : static bool
     711           6 : elide_tail_lines_file (const char *filename, int fd, uintmax_t n_elide)
     712             : {
     713           6 :   if (!presume_input_pipe)
     714             :     {
     715             :       /* Find the offset, OFF, of the Nth newline from the end,
     716             :          but not counting the last byte of the file.
     717             :          If found, write from current position to OFF, inclusive.
     718             :          Otherwise, just return true.  */
     719             : 
     720           6 :       off_t start_pos = lseek (fd, (off_t) 0, SEEK_CUR);
     721           6 :       off_t end_pos = lseek (fd, (off_t) 0, SEEK_END);
     722           6 :       if (0 <= start_pos && start_pos < end_pos)
     723             :         {
     724             :           /* If the file is empty, we're done.  */
     725           5 :           if (end_pos == 0)
     726           0 :             return true;
     727             : 
     728           5 :           return elide_tail_lines_seekable (filename, fd, n_elide,
     729             :                                             start_pos, end_pos);
     730             :         }
     731             : 
     732             :       /* lseek failed or the end offset precedes start.
     733             :          Fall through.  */
     734             :     }
     735             : 
     736           1 :   return elide_tail_lines_pipe (filename, fd, n_elide);
     737             : }
     738             : 
     739             : static bool
     740          13 : head_bytes (const char *filename, int fd, uintmax_t bytes_to_write)
     741             : {
     742             :   char buffer[BUFSIZ];
     743          13 :   size_t bytes_to_read = BUFSIZ;
     744             : 
     745          32 :   while (bytes_to_write)
     746             :     {
     747             :       size_t bytes_read;
     748          10 :       if (bytes_to_write < bytes_to_read)
     749           6 :         bytes_to_read = bytes_to_write;
     750          10 :       bytes_read = safe_read (fd, buffer, bytes_to_read);
     751          10 :       if (bytes_read == SAFE_READ_ERROR)
     752             :         {
     753           0 :           error (0, errno, _("error reading %s"), quote (filename));
     754           0 :           return false;
     755             :         }
     756          10 :       if (bytes_read == 0)
     757           4 :         break;
     758           6 :       if (fwrite (buffer, 1, bytes_read, stdout) < bytes_read)
     759           0 :         error (EXIT_FAILURE, errno, _("write error"));
     760           6 :       bytes_to_write -= bytes_read;
     761             :     }
     762          13 :   return true;
     763             : }
     764             : 
     765             : static bool
     766          43 : head_lines (const char *filename, int fd, uintmax_t lines_to_write)
     767             : {
     768             :   char buffer[BUFSIZ];
     769             : 
     770         102 :   while (lines_to_write)
     771             :     {
     772          35 :       size_t bytes_read = safe_read (fd, buffer, BUFSIZ);
     773          35 :       size_t bytes_to_write = 0;
     774             : 
     775          35 :       if (bytes_read == SAFE_READ_ERROR)
     776             :         {
     777           3 :           error (0, errno, _("error reading %s"), quote (filename));
     778           3 :           return false;
     779             :         }
     780          32 :       if (bytes_read == 0)
     781          16 :         break;
     782         136 :       while (bytes_to_write < bytes_read)
     783         107 :         if (buffer[bytes_to_write++] == '\n' && --lines_to_write == 0)
     784             :           {
     785           3 :             off_t n_bytes_past_EOL = bytes_read - bytes_to_write;
     786             :             /* If we have read more data than that on the specified number
     787             :                of lines, try to seek back to the position we would have
     788             :                gotten to had we been reading one byte at a time.  */
     789           3 :             if (lseek (fd, -n_bytes_past_EOL, SEEK_CUR) < 0)
     790             :               {
     791           0 :                 int e = errno;
     792             :                 struct stat st;
     793           0 :                 if (fstat (fd, &st) != 0 || S_ISREG (st.st_mode))
     794           0 :                   error (0, e, _("cannot reposition file pointer for %s"),
     795             :                          quote (filename));
     796             :               }
     797           3 :             break;
     798             :           }
     799          16 :       if (fwrite (buffer, 1, bytes_to_write, stdout) < bytes_to_write)
     800           0 :         error (EXIT_FAILURE, errno, _("write error"));
     801             :     }
     802          40 :   return true;
     803             : }
     804             : 
     805             : static bool
     806          71 : head (const char *filename, int fd, uintmax_t n_units, bool count_lines,
     807             :       bool elide_from_end)
     808             : {
     809          71 :   if (print_headers)
     810          32 :     write_header (filename);
     811             : 
     812          71 :   if (elide_from_end)
     813             :     {
     814          15 :       if (count_lines)
     815             :         {
     816           6 :           return elide_tail_lines_file (filename, fd, n_units);
     817             :         }
     818             :       else
     819             :         {
     820           9 :           return elide_tail_bytes_file (filename, fd, n_units);
     821             :         }
     822             :     }
     823          56 :   if (count_lines)
     824          43 :     return head_lines (filename, fd, n_units);
     825             :   else
     826          13 :     return head_bytes (filename, fd, n_units);
     827             : }
     828             : 
     829             : static bool
     830          85 : head_file (const char *filename, uintmax_t n_units, bool count_lines,
     831             :            bool elide_from_end)
     832             : {
     833             :   int fd;
     834             :   bool ok;
     835          85 :   bool is_stdin = STREQ (filename, "-");
     836             : 
     837          85 :   if (is_stdin)
     838             :     {
     839          64 :       have_read_stdin = true;
     840          64 :       fd = STDIN_FILENO;
     841          64 :       filename = _("standard input");
     842             :       if (O_BINARY && ! isatty (STDIN_FILENO))
     843             :         freopen (NULL, "rb", stdin);
     844             :     }
     845             :   else
     846             :     {
     847          21 :       fd = open (filename, O_RDONLY | O_BINARY);
     848          21 :       if (fd < 0)
     849             :         {
     850          14 :           error (0, errno, _("cannot open %s for reading"), quote (filename));
     851          14 :           return false;
     852             :         }
     853             :     }
     854             : 
     855          71 :   ok = head (filename, fd, n_units, count_lines, elide_from_end);
     856          71 :   if (!is_stdin && close (fd) != 0)
     857             :     {
     858           0 :       error (0, errno, _("closing %s"), quote (filename));
     859           0 :       return false;
     860             :     }
     861          71 :   return ok;
     862             : }
     863             : 
     864             : /* Convert a string of decimal digits, N_STRING, with an optional suffinx
     865             :    to an integral value.  Upon successful conversion,
     866             :    return that value.  If it cannot be converted, give a diagnostic and exit.
     867             :    COUNT_LINES indicates whether N_STRING is a number of bytes or a number
     868             :    of lines.  It is used solely to give a more specific diagnostic.  */
     869             : 
     870             : static uintmax_t
     871          68 : string_to_integer (bool count_lines, const char *n_string)
     872             : {
     873             :   strtol_error s_err;
     874             :   uintmax_t n;
     875             : 
     876          68 :   s_err = xstrtoumax (n_string, NULL, 10, &n, "bkKmMGTPEZY0");
     877             : 
     878          68 :   if (s_err == LONGINT_OVERFLOW)
     879             :     {
     880           2 :       error (EXIT_FAILURE, 0,
     881             :              _("%s: %s is so large that it is not representable"), n_string,
     882             :              count_lines ? _("number of lines") : _("number of bytes"));
     883             :     }
     884             : 
     885          66 :   if (s_err != LONGINT_OK)
     886             :     {
     887          15 :       error (EXIT_FAILURE, 0, "%s: %s", n_string,
     888             :              (count_lines
     889             :               ? _("invalid number of lines")
     890             :               : _("invalid number of bytes")));
     891             :     }
     892             : 
     893          51 :   return n;
     894             : }
     895             : 
     896             : int
     897          91 : main (int argc, char **argv)
     898             : {
     899          91 :   enum header_mode header_mode = multiple_files;
     900          91 :   bool ok = true;
     901             :   int c;
     902             :   size_t i;
     903             : 
     904             :   /* Number of items to print. */
     905          91 :   uintmax_t n_units = DEFAULT_NUMBER;
     906             : 
     907             :   /* If true, interpret the numeric argument as the number of lines.
     908             :      Otherwise, interpret it as the number of bytes.  */
     909          91 :   bool count_lines = true;
     910             : 
     911             :   /* Elide the specified number of lines or bytes, counting from
     912             :      the end of the file.  */
     913          91 :   bool elide_from_end = false;
     914             : 
     915             :   /* Initializer for file_list if no file-arguments
     916             :      were specified on the command line.  */
     917             :   static char const *const default_file_list[] = {"-", NULL};
     918             :   char const *const *file_list;
     919             : 
     920             :   initialize_main (&argc, &argv);
     921          91 :   program_name = argv[0];
     922          91 :   setlocale (LC_ALL, "");
     923             :   bindtextdomain (PACKAGE, LOCALEDIR);
     924             :   textdomain (PACKAGE);
     925             : 
     926          91 :   atexit (close_stdout);
     927             : 
     928          91 :   have_read_stdin = false;
     929             : 
     930          91 :   print_headers = false;
     931             : 
     932          91 :   if (1 < argc && argv[1][0] == '-' && ISDIGIT (argv[1][1]))
     933             :     {
     934          30 :       char *a = argv[1];
     935          30 :       char *n_string = ++a;
     936             :       char *end_n_string;
     937          30 :       char multiplier_char = 0;
     938             : 
     939             :       /* Old option syntax; a dash, one or more digits, and one or
     940             :          more option letters.  Move past the number. */
     941         139 :       do ++a;
     942         139 :       while (ISDIGIT (*a));
     943             : 
     944             :       /* Pointer to the byte after the last digit.  */
     945          30 :       end_n_string = a;
     946             : 
     947             :       /* Parse any appended option letters. */
     948          43 :       for (; *a; a++)
     949             :         {
     950          14 :           switch (*a)
     951             :             {
     952           1 :             case 'c':
     953           1 :               count_lines = false;
     954           1 :               multiplier_char = 0;
     955           1 :               break;
     956             : 
     957           4 :             case 'b':
     958             :             case 'k':
     959             :             case 'm':
     960           4 :               count_lines = false;
     961           4 :               multiplier_char = *a;
     962           4 :               break;
     963             : 
     964           1 :             case 'l':
     965           1 :               count_lines = true;
     966           1 :               break;
     967             : 
     968           5 :             case 'q':
     969           5 :               header_mode = never;
     970           5 :               break;
     971             : 
     972           2 :             case 'v':
     973           2 :               header_mode = always;
     974           2 :               break;
     975             : 
     976           1 :             default:
     977           1 :               error (0, 0, _("invalid trailing option -- %c"), *a);
     978           1 :               usage (EXIT_FAILURE);
     979             :             }
     980             :         }
     981             : 
     982             :       /* Append the multiplier character (if any) onto the end of
     983             :          the digit string.  Then add NUL byte if necessary.  */
     984          29 :       *end_n_string = multiplier_char;
     985          29 :       if (multiplier_char)
     986           4 :         *(++end_n_string) = 0;
     987             : 
     988          29 :       n_units = string_to_integer (count_lines, n_string);
     989             : 
     990             :       /* Make the options we just parsed invisible to getopt. */
     991          29 :       argv[1] = argv[0];
     992          29 :       argv++;
     993          29 :       argc--;
     994             :     }
     995             : 
     996         207 :   while ((c = getopt_long (argc, argv, "c:n:qv0123456789", long_options, NULL))
     997             :          != -1)
     998             :     {
     999          56 :       switch (c)
    1000             :         {
    1001           1 :         case PRESUME_INPUT_PIPE_OPTION:
    1002           1 :           presume_input_pipe = true;
    1003           1 :           break;
    1004             : 
    1005          29 :         case 'c':
    1006          29 :           count_lines = false;
    1007          29 :           elide_from_end = (*optarg == '-');
    1008          29 :           if (elide_from_end)
    1009          17 :             ++optarg;
    1010          29 :           n_units = string_to_integer (count_lines, optarg);
    1011          16 :           break;
    1012             : 
    1013          10 :         case 'n':
    1014          10 :           count_lines = true;
    1015          10 :           elide_from_end = (*optarg == '-');
    1016          10 :           if (elide_from_end)
    1017           9 :             ++optarg;
    1018          10 :           n_units = string_to_integer (count_lines, optarg);
    1019           6 :           break;
    1020             : 
    1021           3 :         case 'q':
    1022           3 :           header_mode = never;
    1023           3 :           break;
    1024             : 
    1025           1 :         case 'v':
    1026           1 :           header_mode = always;
    1027           1 :           break;
    1028             : 
    1029           1 :         case_GETOPT_HELP_CHAR;
    1030             : 
    1031           0 :         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
    1032             : 
    1033          11 :         default:
    1034          11 :           if (ISDIGIT (c))
    1035           1 :             error (0, 0, _("invalid trailing option -- %c"), c);
    1036          11 :           usage (EXIT_FAILURE);
    1037             :         }
    1038             :     }
    1039             : 
    1040          61 :   if (header_mode == always
    1041          58 :       || (header_mode == multiple_files && optind < argc - 1))
    1042          19 :     print_headers = true;
    1043             : 
    1044          61 :   if ( ! count_lines && elide_from_end && OFF_T_MAX < n_units)
    1045             :     {
    1046             :       char umax_buf[INT_BUFSIZE_BOUND (uintmax_t)];
    1047           0 :       error (EXIT_FAILURE, 0, _("%s: number of bytes is too large"),
    1048             :              umaxtostr (n_units, umax_buf));
    1049             :     }
    1050             : 
    1051         122 :   file_list = (optind < argc
    1052          37 :                ? (char const *const *) &argv[optind]
    1053          98 :                : default_file_list);
    1054             : 
    1055             :   if (O_BINARY && ! isatty (STDOUT_FILENO))
    1056             :     freopen (NULL, "wb", stdout);
    1057             : 
    1058         146 :   for (i = 0; file_list[i]; ++i)
    1059          85 :     ok &= head_file (file_list[i], n_units, count_lines, elide_from_end);
    1060             : 
    1061          61 :   if (have_read_stdin && close (STDIN_FILENO) < 0)
    1062           0 :     error (EXIT_FAILURE, errno, "-");
    1063             : 
    1064          61 :   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
    1065             : }

Generated by: LCOV version 1.10