Include quotearg.h.
[platform/upstream/coreutils.git] / src / tac.c
1 /* tac - concatenate and print files in reverse
2    Copyright (C) 1988-1991, 1995-2004 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 2, or (at your option)
7    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, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 /* Written by Jay Lepreau (lepreau@cs.utah.edu).
19    GNU enhancements by David MacKenzie (djm@gnu.ai.mit.edu). */
20
21 /* Copy each FILE, or the standard input if none are given or when a
22    FILE name of "-" is encountered, to the standard output with the
23    order of the records reversed.  The records are separated by
24    instances of a string, or a newline if none is given.  By default, the
25    separator string is attached to the end of the record that it
26    follows in the file.
27
28    Options:
29    -b, --before                 The separator is attached to the beginning
30                                 of the record that it precedes in the file.
31    -r, --regex                  The separator is a regular expression.
32    -s, --separator=separator    Use SEPARATOR as the record separator.
33
34    To reverse a file byte by byte, use (in bash, ksh, or sh):
35 tac -r -s '.\|
36 ' file */
37
38 #include <config.h>
39
40 #include <stdio.h>
41 #include <getopt.h>
42 #include <sys/types.h>
43 #include "system.h"
44
45 #include <regex.h>
46
47 #include "error.h"
48 #include "quote.h"
49 #include "quotearg.h"
50 #include "safe-read.h"
51
52 /* The official name of this program (e.g., no `g' prefix).  */
53 #define PROGRAM_NAME "tac"
54
55 #define AUTHORS "Jay Lepreau", "David MacKenzie"
56
57 #if defined __MSDOS__ || defined _WIN32
58 /* Define this to non-zero on systems for which the regular mechanism
59    (of unlinking an open file and expecting to be able to write, seek
60    back to the beginning, then reread it) doesn't work.  E.g., on Windows
61    and DOS systems.  */
62 # define DONT_UNLINK_WHILE_OPEN 1
63 #endif
64
65
66 #ifndef DEFAULT_TMPDIR
67 # define DEFAULT_TMPDIR "/tmp"
68 #endif
69
70 /* The number of bytes per atomic read. */
71 #define INITIAL_READSIZE 8192
72
73 /* The number of bytes per atomic write. */
74 #define WRITESIZE 8192
75
76 /* The name this program was run with. */
77 char *program_name;
78
79 /* The string that separates the records of the file. */
80 static char *separator;
81
82 /* True if we have ever read standard input.  */
83 static bool have_read_stdin = false;
84
85 /* If true, print `separator' along with the record preceding it
86    in the file; otherwise with the record following it. */
87 static bool separator_ends_record;
88
89 /* 0 if `separator' is to be matched as a regular expression;
90    otherwise, the length of `separator', used as a sentinel to
91    stop the search. */
92 static size_t sentinel_length;
93
94 /* The length of a match with `separator'.  If `sentinel_length' is 0,
95    `match_length' is computed every time a match succeeds;
96    otherwise, it is simply the length of `separator'. */
97 static size_t match_length;
98
99 /* The input buffer. */
100 static char *G_buffer;
101
102 /* The number of bytes to read at once into `buffer'. */
103 static size_t read_size;
104
105 /* The size of `buffer'.  This is read_size * 2 + sentinel_length + 2.
106    The extra 2 bytes allow `past_end' to have a value beyond the
107    end of `G_buffer' and `match_start' to run off the front of `G_buffer'. */
108 static size_t G_buffer_size;
109
110 /* The compiled regular expression representing `separator'. */
111 static struct re_pattern_buffer compiled_separator;
112
113 static struct option const longopts[] =
114 {
115   {"before", no_argument, NULL, 'b'},
116   {"regex", no_argument, NULL, 'r'},
117   {"separator", required_argument, NULL, 's'},
118   {GETOPT_HELP_OPTION_DECL},
119   {GETOPT_VERSION_OPTION_DECL},
120   {NULL, 0, NULL, 0}
121 };
122
123 void
124 usage (int status)
125 {
126   if (status != EXIT_SUCCESS)
127     fprintf (stderr, _("Try `%s --help' for more information.\n"),
128              program_name);
129   else
130     {
131       printf (_("\
132 Usage: %s [OPTION]... [FILE]...\n\
133 "),
134               program_name);
135       fputs (_("\
136 Write each FILE to standard output, last line first.\n\
137 With no FILE, or when FILE is -, read standard input.\n\
138 \n\
139 "), stdout);
140       fputs (_("\
141 Mandatory arguments to long options are mandatory for short options too.\n\
142 "), stdout);
143       fputs (_("\
144   -b, --before             attach the separator before instead of after\n\
145   -r, --regex              interpret the separator as a regular expression\n\
146   -s, --separator=STRING   use STRING as the separator instead of newline\n\
147 "), stdout);
148       fputs (HELP_OPTION_DESCRIPTION, stdout);
149       fputs (VERSION_OPTION_DESCRIPTION, stdout);
150       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
151     }
152   exit (status);
153 }
154
155 /* Print the characters from START to PAST_END - 1.
156    If START is NULL, just flush the buffer. */
157
158 static void
159 output (const char *start, const char *past_end)
160 {
161   static char buffer[WRITESIZE];
162   static size_t bytes_in_buffer = 0;
163   size_t bytes_to_add = past_end - start;
164   size_t bytes_available = WRITESIZE - bytes_in_buffer;
165
166   if (start == 0)
167     {
168       fwrite (buffer, 1, bytes_in_buffer, stdout);
169       bytes_in_buffer = 0;
170       return;
171     }
172
173   /* Write out as many full buffers as possible. */
174   while (bytes_to_add >= bytes_available)
175     {
176       memcpy (buffer + bytes_in_buffer, start, bytes_available);
177       bytes_to_add -= bytes_available;
178       start += bytes_available;
179       fwrite (buffer, 1, WRITESIZE, stdout);
180       bytes_in_buffer = 0;
181       bytes_available = WRITESIZE;
182     }
183
184   memcpy (buffer + bytes_in_buffer, start, bytes_to_add);
185   bytes_in_buffer += bytes_to_add;
186 }
187
188 /* Print in reverse the file open on descriptor FD for reading FILE.
189    Return true if successful.  */
190
191 static bool
192 tac_seekable (int input_fd, const char *file)
193 {
194   /* Pointer to the location in `G_buffer' where the search for
195      the next separator will begin. */
196   char *match_start;
197
198   /* Pointer to one past the rightmost character in `G_buffer' that
199      has not been printed yet. */
200   char *past_end;
201
202   /* Length of the record growing in `G_buffer'. */
203   size_t saved_record_size;
204
205   /* Offset in the file of the next read. */
206   off_t file_pos;
207
208   /* True if `output' has not been called yet for any file.
209      Only used when the separator is attached to the preceding record. */
210   bool first_time = true;
211   char first_char = *separator; /* Speed optimization, non-regexp. */
212   char *separator1 = separator + 1; /* Speed optimization, non-regexp. */
213   size_t match_length1 = match_length - 1; /* Speed optimization, non-regexp. */
214   struct re_registers regs;
215
216   /* Find the size of the input file. */
217   file_pos = lseek (input_fd, (off_t) 0, SEEK_END);
218   if (file_pos < 1)
219     return true;                        /* It's an empty file. */
220
221   /* Arrange for the first read to lop off enough to leave the rest of the
222      file a multiple of `read_size'.  Since `read_size' can change, this may
223      not always hold during the program run, but since it usually will, leave
224      it here for i/o efficiency (page/sector boundaries and all that).
225      Note: the efficiency gain has not been verified. */
226   saved_record_size = file_pos % read_size;
227   if (saved_record_size == 0)
228     saved_record_size = read_size;
229   file_pos -= saved_record_size;
230   /* `file_pos' now points to the start of the last (probably partial) block
231      in the input file. */
232
233   if (lseek (input_fd, file_pos, SEEK_SET) < 0)
234     error (0, errno, _("%s: seek failed"), quotearg_colon (file));
235
236   if (safe_read (input_fd, G_buffer, saved_record_size) != saved_record_size)
237     {
238       error (0, errno, _("%s: read error"), quotearg_colon (file));
239       return false;
240     }
241
242   match_start = past_end = G_buffer + saved_record_size;
243   /* For non-regexp search, move past impossible positions for a match. */
244   if (sentinel_length)
245     match_start -= match_length1;
246
247   for (;;)
248     {
249       /* Search backward from `match_start' - 1 to `G_buffer' for a match
250          with `separator'; for speed, use strncmp if `separator' contains no
251          metacharacters.
252          If the match succeeds, set `match_start' to point to the start of
253          the match and `match_length' to the length of the match.
254          Otherwise, make `match_start' < `G_buffer'. */
255       if (sentinel_length == 0)
256         {
257           ptrdiff_t i = match_start - G_buffer;
258           int ret;
259
260           if (! (INT_MIN < i && i <= INT_MAX))
261             error (EXIT_FAILURE, 0, _("record too large"));
262
263           ret = re_search (&compiled_separator, G_buffer, i, i - 1, -i, &regs);
264           if (ret == -1)
265             match_start = G_buffer - 1;
266           else if (ret == -2)
267             {
268               error (EXIT_FAILURE, 0,
269                      _("error in regular expression search"));
270             }
271           else
272             {
273               match_start = G_buffer + regs.start[0];
274               match_length = regs.end[0] - regs.start[0];
275             }
276         }
277       else
278         {
279           /* `match_length' is constant for non-regexp boundaries. */
280           while (*--match_start != first_char
281                  || (match_length1 && strncmp (match_start + 1, separator1,
282                                                match_length1)))
283             /* Do nothing. */ ;
284         }
285
286       /* Check whether we backed off the front of `G_buffer' without finding
287          a match for `separator'. */
288       if (match_start < G_buffer)
289         {
290           if (file_pos == 0)
291             {
292               /* Hit the beginning of the file; print the remaining record. */
293               output (G_buffer, past_end);
294               return true;
295             }
296
297           saved_record_size = past_end - G_buffer;
298           if (saved_record_size > read_size)
299             {
300               /* `G_buffer_size' is about twice `read_size', so since
301                  we want to read in another `read_size' bytes before
302                  the data already in `G_buffer', we need to increase
303                  `G_buffer_size'. */
304               char *newbuffer;
305               size_t offset = sentinel_length ? sentinel_length : 1;
306               ptrdiff_t match_start_offset = match_start - G_buffer;
307               ptrdiff_t past_end_offset = past_end - G_buffer;
308               size_t old_G_buffer_size = G_buffer_size;
309
310               read_size *= 2;
311               G_buffer_size = read_size * 2 + sentinel_length + 2;
312               if (G_buffer_size < old_G_buffer_size)
313                 xalloc_die ();
314               newbuffer = xrealloc (G_buffer - offset, G_buffer_size);
315               newbuffer += offset;
316               /* Adjust the pointers for the new buffer location.  */
317               match_start = newbuffer + match_start_offset;
318               past_end = newbuffer + past_end_offset;
319               G_buffer = newbuffer;
320             }
321
322           /* Back up to the start of the next bufferfull of the file.  */
323           if (file_pos >= read_size)
324             file_pos -= read_size;
325           else
326             {
327               read_size = file_pos;
328               file_pos = 0;
329             }
330           if (lseek (input_fd, file_pos, SEEK_SET) < 0)
331             error (0, errno, _("%s: seek failed"), quotearg_colon (file));
332
333           /* Shift the pending record data right to make room for the new.
334              The source and destination regions probably overlap.  */
335           memmove (G_buffer + read_size, G_buffer, saved_record_size);
336           past_end = G_buffer + read_size + saved_record_size;
337           /* For non-regexp searches, avoid unneccessary scanning. */
338           if (sentinel_length)
339             match_start = G_buffer + read_size;
340           else
341             match_start = past_end;
342
343           if (safe_read (input_fd, G_buffer, read_size) != read_size)
344             {
345               error (0, errno, _("%s: read error"), quotearg_colon (file));
346               return false;
347             }
348         }
349       else
350         {
351           /* Found a match of `separator'. */
352           if (separator_ends_record)
353             {
354               char *match_end = match_start + match_length;
355
356               /* If this match of `separator' isn't at the end of the
357                  file, print the record. */
358               if (!first_time || match_end != past_end)
359                 output (match_end, past_end);
360               past_end = match_end;
361               first_time = false;
362             }
363           else
364             {
365               output (match_start, past_end);
366               past_end = match_start;
367             }
368
369           /* For non-regex matching, we can back up.  */
370           if (sentinel_length > 0)
371             match_start -= match_length - 1;
372         }
373     }
374 }
375
376 #if DONT_UNLINK_WHILE_OPEN
377
378 static const char *file_to_remove;
379 static FILE *fp_to_close;
380
381 static void
382 unlink_tempfile (void)
383 {
384   fclose (fp_to_close);
385   unlink (file_to_remove);
386 }
387
388 static void
389 record_or_unlink_tempfile (char const *fn, FILE *fp)
390 {
391   if (!file_to_remove)
392     {
393       file_to_remove = fn;
394       fp_to_close = fp;
395       atexit (unlink_tempfile);
396     }
397 }
398
399 #else
400
401 static void
402 record_or_unlink_tempfile (char const *fn, FILE *fp ATTRIBUTE_UNUSED)
403 {
404   unlink (fn);
405 }
406
407 #endif
408
409 /* Copy from file descriptor INPUT_FD (corresponding to the named FILE) to
410    a temporary file, and set *G_TMP and *G_TEMPFILE to the resulting stream
411    and file name.  Return true if successful.  */
412
413 static bool
414 copy_to_temp (FILE **g_tmp, char **g_tempfile, int input_fd, char const *file)
415 {
416   static char *template = NULL;
417   static char *tempdir;
418   char *tempfile;
419   FILE *tmp;
420   int fd;
421
422   if (template == NULL)
423     {
424       char const * const Template = "%s/tacXXXXXX";
425       tempdir = getenv ("TMPDIR");
426       if (tempdir == NULL)
427         tempdir = DEFAULT_TMPDIR;
428
429       /* Subtract 2 for `%s' and add 1 for the trailing NUL byte.  */
430       template = xmalloc (strlen (tempdir) + strlen (Template) - 2 + 1);
431       sprintf (template, Template, tempdir);
432     }
433
434   /* FIXME: there's a small window between a successful mkstemp call
435      and the unlink that's performed by record_or_unlink_tempfile.
436      If we're interrupted in that interval, this code fails to remove
437      the temporary file.  On systems that define DONT_UNLINK_WHILE_OPEN,
438      the window is much larger -- it extends to the atexit-called
439      unlink_tempfile.
440      FIXME: clean up upon fatal signal.  Don't block them, in case
441      $TMPFILE is a remote file system.  */
442
443   tempfile = template;
444   fd = mkstemp (template);
445   if (fd == -1)
446     {
447       error (0, errno, _("cannot create temporary file %s"), quote (tempfile));
448       return false;
449     }
450
451   tmp = fdopen (fd, "w+");
452   if (tmp == NULL)
453     {
454       error (0, errno, _("cannot open %s for writing"), quote (tempfile));
455       close (fd);
456       unlink (tempfile);
457       return false;
458     }
459
460   record_or_unlink_tempfile (tempfile, tmp);
461
462   while (1)
463     {
464       size_t bytes_read = safe_read (input_fd, G_buffer, read_size);
465       if (bytes_read == 0)
466         break;
467       if (bytes_read == SAFE_READ_ERROR)
468         {
469           error (0, errno, _("%s: read error"), quotearg_colon (file));
470           goto Fail;
471         }
472
473       if (fwrite (G_buffer, 1, bytes_read, tmp) != bytes_read)
474         {
475           error (0, errno, _("%s: write error"), quotearg_colon (tempfile));
476           goto Fail;
477         }
478     }
479
480   if (fflush (tmp) != 0)
481     {
482       error (0, errno, _("%s: write error"), quotearg_colon (tempfile));
483       goto Fail;
484     }
485
486   SET_BINARY (fileno (tmp));
487   *g_tmp = tmp;
488   *g_tempfile = tempfile;
489   return true;
490
491  Fail:
492   fclose (tmp);
493   return false;
494 }
495
496 /* Copy INPUT_FD to a temporary, then tac that file.
497    Return true if successful.  */
498
499 static bool
500 tac_nonseekable (int input_fd, const char *file)
501 {
502   FILE *tmp_stream;
503   char *tmp_file;
504   copy_to_temp (&tmp_stream, &tmp_file, input_fd, file);
505   return tac_seekable (fileno (tmp_stream), tmp_file);
506 }
507
508 /* Print FILE in reverse, copying it to a temporary
509    file first if it is not seekable.
510    Return true if successful.  */
511
512 static bool
513 tac_file (const char *filename)
514 {
515   bool ok;
516   off_t file_size;
517   int fd;
518
519   if (STREQ (filename, "-"))
520     {
521       have_read_stdin = true;
522       fd = STDIN_FILENO;
523       filename = _("standard input");
524     }
525   else
526     {
527       fd = open (filename, O_RDONLY);
528       if (fd < 0)
529         {
530           error (0, errno, _("cannot open %s for reading"), quote (filename));
531           return false;
532         }
533     }
534
535   /* We need binary I/O, since `tac' relies
536      on `lseek' and byte counts.
537
538      Binary output will leave the lines' ends (NL or
539      CR/LF) intact when the output is a disk file.
540      Writing a file with CR/LF pairs at end of lines in
541      text mode has no visible effect on console output,
542      since two CRs in a row are just like one CR.  */
543   SET_BINARY2 (fd, STDOUT_FILENO);
544
545   file_size = lseek (fd, (off_t) 0, SEEK_END);
546
547   ok = (0 <= file_size
548         ? tac_seekable (fd, filename)
549         : tac_nonseekable (fd, filename));
550
551   if (fd != STDIN_FILENO && close (fd) == -1)
552     {
553       error (0, errno, _("%s: read error"), quotearg_colon (filename));
554       ok = false;
555     }
556   return ok;
557 }
558
559 #if 0
560 /* BUF_END points one byte past the end of the buffer to be searched.  */
561
562 /* FIXME: describe */
563
564 static void
565 tac_mem (const char *buf, size_t n_bytes, FILE *out)
566 {
567   const char *nl;
568   const char *bol;
569
570   if (n_bytes == 0)
571     return;
572
573   nl = memrchr (buf, buf + n_bytes, '\n');
574   bol = (nl == NULL ? buf : nl + 1);
575
576   /* If the last line of the input file has no terminating newline,
577      treat it as a special case.  */
578   if (bol < buf + n_bytes)
579     {
580       /* Print out the line from bol to end of input.  */
581       fwrite (bol, 1, (buf + n_bytes) - bol, out);
582
583       /* Add a newline here.  Otherwise, the first and second lines
584          of output would appear to have been joined.  */
585       fputc ('\n', out);
586     }
587
588   while ((nl = memrchr (buf, bol - 1, '\n')) != NULL)
589     {
590       /* Output the line (which includes a trailing newline)
591          from NL+1 to BOL-1.  */
592       fwrite (nl + 1, 1, bol - (nl + 1), out);
593
594       bol = nl + 1;
595     }
596
597   /* If there's anything left, output the last line: BUF .. BOL-1.
598      When the first byte of the input is a newline, there is nothing
599      left to do here.  */
600   if (buf < bol)
601     fwrite (buf, 1, bol - buf, out);
602
603   /* FIXME: this is work in progress.... */
604 }
605
606 /* FIXME: describe */
607
608 static bool
609 tac_stdin_to_mem (void)
610 {
611   char *buf = NULL;
612   size_t bufsiz = 8 * BUFSIZ;
613   size_t delta = 8 * BUFSIZ;
614   size_t n_bytes = 0;
615
616   while (1)
617     {
618       size_t bytes_read;
619       char *new_buf = realloc (buf, bufsiz);
620
621       if (new_buf == NULL)
622         {
623           /* Write contents of buf to a temporary file, ... */
624           /* FIXME */
625
626           /* Free the buffer and fall back on the code that relies on a
627              temporary file.  */
628           free (buf);
629           /* FIXME */
630           abort ();
631         }
632
633       buf = new_buf;
634       bytes_read = safe_read (STDIN_FILENO, buf + n_bytes, bufsiz - n_bytes);
635       if (bytes_read == 0)
636         break;
637       if (bytes_read == SAFE_READ_ERROR)
638         error (EXIT_FAILURE, errno, _("stdin: read error"));
639       n_bytes += bytes_read;
640
641       bufsiz += delta;
642     }
643
644   tac_mem (buf, n_bytes, stdout);
645
646   return true;
647 }
648 #endif
649
650 int
651 main (int argc, char **argv)
652 {
653   const char *error_message;    /* Return value from re_compile_pattern. */
654   int optc;
655   bool ok;
656   size_t half_buffer_size;
657
658   /* Initializer for file_list if no file-arguments
659      were specified on the command line.  */
660   static char const *const default_file_list[] = {"-", NULL};
661   char const *const *file;
662
663   initialize_main (&argc, &argv);
664   program_name = argv[0];
665   setlocale (LC_ALL, "");
666   bindtextdomain (PACKAGE, LOCALEDIR);
667   textdomain (PACKAGE);
668
669   atexit (close_stdout);
670
671   separator = "\n";
672   sentinel_length = 1;
673   separator_ends_record = true;
674
675   while ((optc = getopt_long (argc, argv, "brs:", longopts, NULL)) != -1)
676     {
677       switch (optc)
678         {
679         case 'b':
680           separator_ends_record = false;
681           break;
682         case 'r':
683           sentinel_length = 0;
684           break;
685         case 's':
686           separator = optarg;
687           if (*separator == 0)
688             error (EXIT_FAILURE, 0, _("separator cannot be empty"));
689           break;
690         case_GETOPT_HELP_CHAR;
691         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
692         default:
693           usage (EXIT_FAILURE);
694         }
695     }
696
697   if (sentinel_length == 0)
698     {
699       compiled_separator.allocated = 100;
700       compiled_separator.buffer = xmalloc (compiled_separator.allocated);
701       compiled_separator.fastmap = xmalloc (256);
702       compiled_separator.translate = 0;
703       error_message = re_compile_pattern (separator, strlen (separator),
704                                           &compiled_separator);
705       if (error_message)
706         error (EXIT_FAILURE, 0, "%s", error_message);
707     }
708   else
709     match_length = sentinel_length = strlen (separator);
710
711   read_size = INITIAL_READSIZE;
712   while (sentinel_length >= read_size / 2)
713     {
714       if (SIZE_MAX / 2 < read_size)
715         xalloc_die ();
716       read_size *= 2;
717     }
718   half_buffer_size = read_size + sentinel_length + 1;
719   G_buffer_size = 2 * half_buffer_size;
720   if (! (read_size < half_buffer_size && half_buffer_size < G_buffer_size))
721     xalloc_die ();
722   G_buffer = xmalloc (G_buffer_size);
723   if (sentinel_length)
724     {
725       strcpy (G_buffer, separator);
726       G_buffer += sentinel_length;
727     }
728   else
729     {
730       ++G_buffer;
731     }
732
733   file = (optind < argc
734           ? (char const *const *) &argv[optind]
735           : default_file_list);
736
737   {
738     size_t i;
739     ok = true;
740     for (i = 0; file[i]; ++i)
741       ok &= tac_file (file[i]);
742   }
743
744   /* Flush the output buffer. */
745   output ((char *) NULL, (char *) NULL);
746
747   if (have_read_stdin && close (STDIN_FILENO) < 0)
748     error (EXIT_FAILURE, errno, "-");
749   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
750 }