1 /* $NetBSD: split.c,v 1.26 2011/09/16 15:39:29 joerg Exp $ */
4 * Copyright (c) 1987, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)split.c 8.3 (Berkeley) 4/25/94";
42 __RCSID("$NetBSD: split.c,v 1.26 2011/09/16 15:39:29 joerg Exp $");
45 #include <sys/param.h>
56 #define DEFLINE 1000 /* Default num lines per file. */
58 static int file_open
; /* If a file open. */
59 static int ifd
= STDIN_FILENO
, ofd
= -1; /* Input/output file descriptors. */
60 static char *fname
; /* File name prefix. */
61 static size_t sfxlen
= 2; /* suffix length. */
63 static void newfile(void);
64 static void split1(off_t
, int) __dead
;
65 static void split2(off_t
) __dead
;
66 static void split3(off_t
) __dead
;
67 static void usage(void) __dead
;
68 static size_t bigwrite(int, void const *, size_t);
71 main(int argc
, char *argv
[])
76 off_t bytecnt
= 0; /* Byte count to split on. */
77 off_t numlines
= 0; /* Line count to split on. */
78 off_t chunks
= 0; /* Number of chunks to split into. */
80 while ((ch
= getopt(argc
, argv
, "0123456789b:l:a:n:")) != -1)
82 case '0': case '1': case '2': case '3': case '4':
83 case '5': case '6': case '7': case '8': case '9':
85 * Undocumented kludge: split was originally designed
86 * to take a number after a dash.
90 if (p
[0] == '-' && p
[1] == ch
&& !p
[2])
94 numlines
= strtoull(p
, &ep
, 10);
95 if (numlines
== 0 || *ep
!= '\0')
96 errx(1, "%s: illegal line count.", p
);
99 case 'b': /* Byte count. */
100 if (!isdigit((unsigned char)optarg
[0]) ||
101 (bytecnt
= strtoull(optarg
, &ep
, 10)) == 0 ||
102 (*ep
!= '\0' && *ep
!= 'k' && *ep
!= 'm'))
103 errx(1, "%s: illegal byte count.", optarg
);
107 bytecnt
*= 1024 * 1024;
109 case 'l': /* Line count. */
112 if (!isdigit((unsigned char)optarg
[0]) ||
113 (numlines
= strtoull(optarg
, &ep
, 10)) == 0 ||
115 errx(1, "%s: illegal line count.", optarg
);
117 case 'a': /* Suffix length. */
118 if (!isdigit((unsigned char)optarg
[0]) ||
119 (sfxlen
= (size_t)strtoul(optarg
, &ep
, 10)) == 0 ||
121 errx(1, "%s: illegal suffix length.", optarg
);
123 case 'n': /* Chunks. */
124 if (!isdigit((unsigned char)optarg
[0]) ||
125 (chunks
= (size_t)strtoul(optarg
, &ep
, 10)) == 0 ||
127 errx(1, "%s: illegal number of chunks.", optarg
);
136 if (strcmp(*argv
, "-") != 0 &&
137 (ifd
= open(*argv
, O_RDONLY
, 0)) < 0)
143 base
= (*argv
!= NULL
) ? *argv
++ : "x";
144 if ((fname
= malloc(strlen(base
) + sfxlen
+ 1)) == NULL
)
145 err(EXIT_FAILURE
, NULL
);
146 (void)strcpy(fname
, base
); /* File name prefix. */
153 else if (bytecnt
|| chunks
)
156 if (bytecnt
&& chunks
)
171 * Split the input by bytes.
174 split1(off_t bytecnt
, int maxcnt
)
185 switch (len
= read(ifd
, bfr
, MAXBSIZE
)) {
194 if (!maxcnt
|| (nfiles
< maxcnt
)) {
200 if (bcnt
+ len
>= bytecnt
) {
201 /* LINTED: bytecnt - bcnt <= len */
202 dist
= bytecnt
- bcnt
;
203 if (bigwrite(ofd
, bfr
, dist
) != (size_t)dist
)
206 for (C
= bfr
+ dist
; len
>= bytecnt
;
207 /* LINTED: bytecnt <= len */
208 len
-= bytecnt
, C
+= bytecnt
) {
209 if (!maxcnt
|| (nfiles
< maxcnt
)) {
213 /* LINTED: as above */
215 C
, bytecnt
) != (size_t)bytecnt
)
219 if (!maxcnt
|| (nfiles
< maxcnt
)) {
223 /* LINTED: len >= 0 */
224 if (bigwrite(ofd
, C
, len
) != (size_t)len
)
231 /* LINTED: len >= 0 */
232 if (bigwrite(ofd
, bfr
, len
) != (size_t)len
)
240 * Split the input by lines.
243 split2(off_t numlines
)
252 switch (len
= read(ifd
, bfr
, MAXBSIZE
)) {
264 for (Cs
= Ce
= bfr
; len
--; Ce
++)
265 if (*Ce
== '\n' && ++lcnt
== numlines
) {
267 if (bigwrite(ofd
, Cs
, bcnt
) != (size_t)bcnt
)
278 if (bigwrite(ofd
, Cs
, bcnt
) != (size_t)bcnt
)
286 * Split the input into specified number of chunks
293 if (fstat(ifd
, &sb
) == -1) {
298 if (chunks
> sb
.st_size
) {
299 errx(1, "can't split into more than %d files",
304 split1(sb
.st_size
/chunks
, chunks
);
309 * Open a new output file.
319 fpnt
= fname
+ strlen(fname
);
321 } else if (close(ofd
) != 0)
325 for (i
= sfxlen
- 1; i
>= 0; i
--) {
326 fpnt
[i
] = quot
% 26 + 'a';
330 errx(1, "too many files.");
332 if ((ofd
= open(fname
, O_WRONLY
| O_CREAT
| O_TRUNC
, DEFFILEMODE
)) < 0)
337 bigwrite(int fd
, const void *buf
, size_t len
)
339 const char *ptr
= buf
;
344 if ((w
= write(fd
, ptr
, len
)) == -1)
357 (void)fprintf(stderr
,
358 "usage: %s [-b byte_count] [-l line_count] [-n chunk_count] [-a suffix_length] "
359 "[file [prefix]]\n", getprogname());