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