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