(FAIL_ONLY_ONE_WAY): New macro. Factor out some duplication.
[platform/upstream/coreutils.git] / src / split.c
1 /* split.c -- split a file into pieces.
2    Copyright (C) 88, 91, 1995-2002 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 \f
18 /* By tege@sics.se, with rms.
19
20    To do:
21    * Implement -t CHAR or -t REGEX to specify break characters other
22      than newline. */
23
24 #include <config.h>
25
26 #include <stdio.h>
27 #include <getopt.h>
28 #include <sys/types.h>
29
30 #include "system.h"
31 #include "closeout.h"
32 #include "dirname.h"
33 #include "error.h"
34 #include "full-write.h"
35 #include "posixver.h"
36 #include "safe-read.h"
37 #include "xstrtol.h"
38
39 /* The official name of this program (e.g., no `g' prefix).  */
40 #define PROGRAM_NAME "split"
41
42 #define AUTHORS N_ ("Torbjorn Granlund and Richard M. Stallman")
43
44 #define DEFAULT_SUFFIX_LENGTH 2
45
46 /* The name this program was run with. */
47 char *program_name;
48
49 /* Base name of output files.  */
50 static char const *outbase;
51
52 /* Name of output files.  */
53 static char *outfile;
54
55 /* Pointer to the end of the prefix in OUTFILE.
56    Suffixes are inserted here.  */
57 static char *outfile_mid;
58
59 /* Length of OUTFILE's suffix.  */
60 static size_t suffix_length = DEFAULT_SUFFIX_LENGTH;
61
62 /* Name of input file.  May be "-".  */
63 static char *infile;
64
65 /* Descriptor on which input file is open.  */
66 static int input_desc;
67
68 /* Descriptor on which output file is open.  */
69 static int output_desc;
70
71 /* If nonzero, print a diagnostic on standard error just before each
72    output file is opened. */
73 static int verbose;
74
75 static struct option const longopts[] =
76 {
77   {"bytes", required_argument, NULL, 'b'},
78   {"lines", required_argument, NULL, 'l'},
79   {"line-bytes", required_argument, NULL, 'C'},
80   {"suffix-length", required_argument, NULL, 'a'},
81   {"verbose", no_argument, NULL, 2},
82   {GETOPT_HELP_OPTION_DECL},
83   {GETOPT_VERSION_OPTION_DECL},
84   {NULL, 0, NULL, 0}
85 };
86
87 void
88 usage (int status)
89 {
90   if (status != 0)
91     fprintf (stderr, _("Try `%s --help' for more information.\n"),
92              program_name);
93   else
94     {
95       printf (_("\
96 Usage: %s [OPTION] [INPUT [PREFIX]]\n\
97 "),
98               program_name);
99     fputs (_("\
100 Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default\n\
101 PREFIX is `x'.  With no INPUT, or when INPUT is -, read standard input.\n\
102 \n\
103 "), stdout);
104       fputs (_("\
105 Mandatory arguments to long options are mandatory for short options too.\n\
106 "), stdout);
107       fprintf (stdout, _("\
108   -a, --suffix-length=N   use suffixes of length N (default %d)\n\
109   -b, --bytes=SIZE        put SIZE bytes per output file\n\
110   -C, --line-bytes=SIZE   put at most SIZE bytes of lines per output file\n\
111   -l, --lines=NUMBER      put NUMBER lines per output file\n\
112 "), DEFAULT_SUFFIX_LENGTH);
113       fputs (_("\
114       --verbose           print a diagnostic to standard error just\n\
115                             before each output file is opened\n\
116 "), stdout);
117       fputs (HELP_OPTION_DESCRIPTION, stdout);
118       fputs (VERSION_OPTION_DESCRIPTION, stdout);
119       fputs (_("\
120 \n\
121 SIZE may have a multiplier suffix: b for 512, k for 1K, m for 1 Meg.\n\
122 "), stdout);
123       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
124     }
125   exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
126 }
127
128 /* Compute the next sequential output file name and store it into the
129    string `outfile'.  */
130
131 static void
132 next_file_name (void)
133 {
134   if (! outfile)
135     {
136       /* Allocate and initialize the first file name.  */
137
138       size_t outbase_length = strlen (outbase);
139       size_t outfile_length = outbase_length + suffix_length;
140       if (outfile_length + 1 < outbase_length)
141         xalloc_die ();
142       outfile = xmalloc (outfile_length + 1);
143       outfile_mid = outfile + outbase_length;
144       memcpy (outfile, outbase, outbase_length);
145       memset (outfile_mid, 'a', suffix_length);
146       outfile[outfile_length] = 0;
147
148 #if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX
149       /* POSIX requires that if the output file name is too long for
150          its directory, `split' must fail without creating any files.
151          This must be checked for explicitly on operating systems that
152          silently truncate file names.  */
153       {
154         char *dir = dir_name (outfile);
155         long name_max = pathconf (dir, _PC_NAME_MAX);
156         if (0 <= name_max && name_max < base_len (base_name (outfile)))
157           error (EXIT_FAILURE, ENAMETOOLONG, "%s", outfile);
158         free (dir);
159       }
160 #endif
161     }
162   else
163     {
164       /* Increment the suffix in place, if possible.  */
165
166       char *p;
167       for (p = outfile_mid + suffix_length; outfile_mid < p; *--p = 'a')
168         if (p[-1]++ != 'z')
169           return;
170       error (EXIT_FAILURE, 0, _("Output file suffixes exhausted"));
171     }
172 }
173
174 /* Write BYTES bytes at BP to an output file.
175    If NEW_FILE_FLAG is nonzero, open the next output file.
176    Otherwise add to the same output file already in use.  */
177
178 static void
179 cwrite (int new_file_flag, const char *bp, int bytes)
180 {
181   if (new_file_flag)
182     {
183       if (output_desc >= 0 && close (output_desc) < 0)
184         error (EXIT_FAILURE, errno, "%s", outfile);
185
186       next_file_name ();
187       if (verbose)
188         fprintf (stderr, _("creating file `%s'\n"), outfile);
189       output_desc = open (outfile,
190                           O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
191       if (output_desc < 0)
192         error (EXIT_FAILURE, errno, "%s", outfile);
193     }
194   if (full_write (output_desc, bp, bytes) != (size_t) bytes)
195     error (EXIT_FAILURE, errno, "%s", outfile);
196 }
197
198 /* Read NCHARS bytes from the input file into BUF.
199    Return the number of bytes successfully read.
200    If this is less than NCHARS, do not call `stdread' again.  */
201
202 static int
203 stdread (char *buf, int nchars)
204 {
205   int n_read;
206   int to_be_read = nchars;
207
208   while (to_be_read)
209     {
210       n_read = safe_read (input_desc, buf, to_be_read);
211       if (n_read < 0)
212         return -1;
213       if (n_read == 0)
214         break;
215       to_be_read -= n_read;
216       buf += n_read;
217     }
218   return nchars - to_be_read;
219 }
220
221 /* Split into pieces of exactly NCHARS bytes.
222    Use buffer BUF, whose size is BUFSIZE.  */
223
224 static void
225 bytes_split (int nchars, char *buf, int bufsize)
226 {
227   int n_read;
228   int new_file_flag = 1;
229   int to_read;
230   int to_write = nchars;
231   char *bp_out;
232
233   do
234     {
235       n_read = stdread (buf, bufsize);
236       if (n_read < 0)
237         error (EXIT_FAILURE, errno, "%s", infile);
238       bp_out = buf;
239       to_read = n_read;
240       for (;;)
241         {
242           if (to_read < to_write)
243             {
244               if (to_read)      /* do not write 0 bytes! */
245                 {
246                   cwrite (new_file_flag, bp_out, to_read);
247                   to_write -= to_read;
248                   new_file_flag = 0;
249                 }
250               break;
251             }
252           else
253             {
254               cwrite (new_file_flag, bp_out, to_write);
255               bp_out += to_write;
256               to_read -= to_write;
257               new_file_flag = 1;
258               to_write = nchars;
259             }
260         }
261     }
262   while (n_read == bufsize);
263 }
264
265 /* Split into pieces of exactly NLINES lines.
266    Use buffer BUF, whose size is BUFSIZE.  */
267
268 static void
269 lines_split (int nlines, char *buf, int bufsize)
270 {
271   int n_read;
272   char *bp, *bp_out, *eob;
273   int new_file_flag = 1;
274   int n = 0;
275
276   do
277     {
278       n_read = stdread (buf, bufsize);
279       if (n_read < 0)
280         error (EXIT_FAILURE, errno, "%s", infile);
281       bp = bp_out = buf;
282       eob = bp + n_read;
283       *eob = '\n';
284       for (;;)
285         {
286           while (*bp++ != '\n')
287             ;                   /* this semicolon takes most of the time */
288           if (bp > eob)
289             {
290               if (eob != bp_out) /* do not write 0 bytes! */
291                 {
292                   cwrite (new_file_flag, bp_out, eob - bp_out);
293                   new_file_flag = 0;
294                 }
295               break;
296             }
297           else
298             if (++n >= nlines)
299               {
300                 cwrite (new_file_flag, bp_out, bp - bp_out);
301                 bp_out = bp;
302                 new_file_flag = 1;
303                 n = 0;
304               }
305         }
306     }
307   while (n_read == bufsize);
308 }
309 \f
310 /* Split into pieces that are as large as possible while still not more
311    than NCHARS bytes, and are split on line boundaries except
312    where lines longer than NCHARS bytes occur. */
313
314 static void
315 line_bytes_split (int nchars)
316 {
317   int n_read;
318   char *bp;
319   int eof = 0;
320   int n_buffered = 0;
321   char *buf = (char *) xmalloc (nchars);
322
323   do
324     {
325       /* Fill up the full buffer size from the input file.  */
326
327       n_read = stdread (buf + n_buffered, nchars - n_buffered);
328       if (n_read < 0)
329         error (EXIT_FAILURE, errno, "%s", infile);
330
331       n_buffered += n_read;
332       if (n_buffered != nchars)
333         eof = 1;
334
335       /* Find where to end this chunk.  */
336       bp = buf + n_buffered;
337       if (n_buffered == nchars)
338         {
339           while (bp > buf && bp[-1] != '\n')
340             bp--;
341         }
342
343       /* If chunk has no newlines, use all the chunk.  */
344       if (bp == buf)
345         bp = buf + n_buffered;
346
347       /* Output the chars as one output file.  */
348       cwrite (1, buf, bp - buf);
349
350       /* Discard the chars we just output; move rest of chunk
351          down to be the start of the next chunk.  Source and
352          destination probably overlap.  */
353       n_buffered -= bp - buf;
354       if (n_buffered > 0)
355         memmove (buf, bp, n_buffered);
356     }
357   while (!eof);
358   free (buf);
359 }
360
361 #define FAIL_ONLY_ONE_WAY()                                     \
362   do                                                            \
363     {                                                           \
364       error (0, 0, _("cannot split in more than one way"));     \
365       usage (EXIT_FAILURE);                                     \
366     }                                                           \
367   while (0)
368
369 int
370 main (int argc, char **argv)
371 {
372   struct stat stat_buf;
373   int num;                      /* numeric argument from command line */
374   enum
375     {
376       type_undef, type_bytes, type_byteslines, type_lines, type_digits
377     } split_type = type_undef;
378   int in_blk_size;              /* optimal block size of input file device */
379   char *buf;                    /* file i/o buffer */
380   int accum = 0;
381   int c;
382   int digits_optind = 0;
383
384   program_name = argv[0];
385   setlocale (LC_ALL, "");
386   bindtextdomain (PACKAGE, LOCALEDIR);
387   textdomain (PACKAGE);
388
389   atexit (close_stdout);
390
391   /* Parse command line options.  */
392
393   infile = "-";
394   outbase = "x";
395
396   while (1)
397     {
398       /* This is the argv-index of the option we will read next.  */
399       int this_optind = optind ? optind : 1;
400       long int tmp_long;
401
402       c = getopt_long (argc, argv, "0123456789C:a:b:l:", longopts, NULL);
403       if (c == -1)
404         break;
405
406       switch (c)
407         {
408         case 0:
409           break;
410
411         case 'a':
412           {
413             unsigned long tmp;
414             if (xstrtoul (optarg, NULL, 10, &tmp, "") != LONGINT_OK
415                 || SIZE_MAX < tmp)
416               {
417                 error (0, 0, _("%s: invalid suffix length"), optarg);
418                 usage (EXIT_FAILURE);
419               }
420             suffix_length = tmp;
421           }
422           break;
423
424         case 'b':
425           if (split_type != type_undef)
426             FAIL_ONLY_ONE_WAY ();
427           split_type = type_bytes;
428           if (xstrtol (optarg, NULL, 10, &tmp_long, "bkm") != LONGINT_OK
429               || tmp_long < 0 || tmp_long > INT_MAX)
430             {
431               error (0, 0, _("%s: invalid number of bytes"), optarg);
432               usage (EXIT_FAILURE);
433             }
434           accum = (int) tmp_long;
435           break;
436
437         case 'l':
438           if (split_type != type_undef)
439             FAIL_ONLY_ONE_WAY ();
440           split_type = type_lines;
441           if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
442               || tmp_long < 0 || tmp_long > INT_MAX)
443             {
444               error (0, 0, _("%s: invalid number of lines"), optarg);
445               usage (EXIT_FAILURE);
446             }
447           accum = (int) tmp_long;
448           break;
449
450         case 'C':
451           if (split_type != type_undef)
452             FAIL_ONLY_ONE_WAY ();
453           split_type = type_byteslines;
454           if (xstrtol (optarg, NULL, 10, &tmp_long, "bkm") != LONGINT_OK
455               || tmp_long < 0 ||  tmp_long > INT_MAX)
456             {
457               error (0, 0, _("%s: invalid number of bytes"), optarg);
458               usage (EXIT_FAILURE);
459             }
460           accum = (int) tmp_long;
461           break;
462
463         case '0':
464         case '1':
465         case '2':
466         case '3':
467         case '4':
468         case '5':
469         case '6':
470         case '7':
471         case '8':
472         case '9':
473           if (split_type != type_undef && split_type != type_digits)
474             FAIL_ONLY_ONE_WAY ();
475           if (digits_optind != 0 && digits_optind != this_optind)
476             accum = 0;          /* More than one number given; ignore other. */
477           digits_optind = this_optind;
478           split_type = type_digits;
479           accum = accum * 10 + c - '0';
480           break;
481
482         case 2:
483           verbose = 1;
484           break;
485
486         case_GETOPT_HELP_CHAR;
487
488         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
489
490         default:
491           usage (EXIT_FAILURE);
492         }
493     }
494
495   if (digits_optind && 200112 <= posix2_version ())
496     {
497       error (0, 0, _("`-%d' option is obsolete; use `-l %d'"), accum, accum);
498       usage (EXIT_FAILURE);
499     }
500
501   /* Handle default case.  */
502   if (split_type == type_undef)
503     {
504       split_type = type_lines;
505       accum = 1000;
506     }
507
508   if (accum < 1)
509     {
510       error (0, 0, _("invalid number"));
511       usage (EXIT_FAILURE);
512     }
513   num = accum;
514
515   /* Get out the filename arguments.  */
516
517   if (optind < argc)
518     infile = argv[optind++];
519
520   if (optind < argc)
521     outbase = argv[optind++];
522
523   if (optind < argc)
524     {
525       error (0, 0, _("too many arguments"));
526       usage (EXIT_FAILURE);
527     }
528
529   /* Open the input file.  */
530   if (STREQ (infile, "-"))
531     input_desc = 0;
532   else
533     {
534       input_desc = open (infile, O_RDONLY);
535       if (input_desc < 0)
536         error (EXIT_FAILURE, errno, "%s", infile);
537     }
538   /* Binary I/O is safer when bytecounts are used.  */
539   SET_BINARY (input_desc);
540
541   /* No output file is open now.  */
542   output_desc = -1;
543
544   /* Get the optimal block size of input device and make a buffer.  */
545
546   if (fstat (input_desc, &stat_buf) < 0)
547     error (EXIT_FAILURE, errno, "%s", infile);
548   in_blk_size = ST_BLKSIZE (stat_buf);
549
550   buf = xmalloc (in_blk_size + 1);
551
552   switch (split_type)
553     {
554     case type_digits:
555     case type_lines:
556       lines_split (num, buf, in_blk_size);
557       break;
558
559     case type_bytes:
560       bytes_split (num, buf, in_blk_size);
561       break;
562
563     case type_byteslines:
564       line_bytes_split (num);
565       break;
566
567     default:
568       abort ();
569     }
570
571   if (close (input_desc) < 0)
572     error (EXIT_FAILURE, errno, "%s", infile);
573   if (output_desc >= 0 && close (output_desc) < 0)
574     error (EXIT_FAILURE, errno, "%s", outfile);
575
576   exit (EXIT_SUCCESS);
577 }