1 /* $NetBSD: split.c,v 1.24 2008/07/21 14:19:26 lukem 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.24 2008/07/21 14:19:26 lukem 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 int main(int, char **);
64 static void newfile(void);
65 static void split1(off_t
, int);
66 static void split2(off_t
);
67 static void split3(off_t
);
68 static void usage(void) __dead
;
69 static size_t bigwrite(int, void const *, size_t);
72 main(int argc
, char *argv
[])
77 off_t bytecnt
= 0; /* Byte count to split on. */
78 off_t numlines
= 0; /* Line count to split on. */
79 off_t chunks
= 0; /* Number of chunks to split into. */
81 while ((ch
= getopt(argc
, argv
, "0123456789b:l:a:n:")) != -1)
83 case '0': case '1': case '2': case '3': case '4':
84 case '5': case '6': case '7': case '8': case '9':
86 * Undocumented kludge: split was originally designed
87 * to take a number after a dash.
91 if (p
[0] == '-' && p
[1] == ch
&& !p
[2])
95 numlines
= strtoull(p
, &ep
, 10);
96 if (numlines
== 0 || *ep
!= '\0')
97 errx(1, "%s: illegal line count.", p
);
100 case 'b': /* Byte count. */
101 if (!isdigit((unsigned char)optarg
[0]) ||
102 (bytecnt
= strtoull(optarg
, &ep
, 10)) == 0 ||
103 (*ep
!= '\0' && *ep
!= 'k' && *ep
!= 'm'))
104 errx(1, "%s: illegal byte count.", optarg
);
108 bytecnt
*= 1024 * 1024;
110 case 'l': /* Line count. */
113 if (!isdigit((unsigned char)optarg
[0]) ||
114 (numlines
= strtoull(optarg
, &ep
, 10)) == 0 ||
116 errx(1, "%s: illegal line count.", optarg
);
118 case 'a': /* Suffix length. */
119 if (!isdigit((unsigned char)optarg
[0]) ||
120 (sfxlen
= (size_t)strtoul(optarg
, &ep
, 10)) == 0 ||
122 errx(1, "%s: illegal suffix length.", optarg
);
124 case 'n': /* Chunks. */
125 if (!isdigit((unsigned char)optarg
[0]) ||
126 (chunks
= (size_t)strtoul(optarg
, &ep
, 10)) == 0 ||
128 errx(1, "%s: illegal number of chunks.", optarg
);
137 if (strcmp(*argv
, "-") != 0 &&
138 (ifd
= open(*argv
, O_RDONLY
, 0)) < 0)
144 base
= (*argv
!= NULL
) ? *argv
++ : "x";
145 if ((fname
= malloc(strlen(base
) + sfxlen
+ 1)) == NULL
)
146 err(EXIT_FAILURE
, NULL
);
147 (void)strcpy(fname
, base
); /* File name prefix. */
154 else if (bytecnt
|| chunks
)
157 if (bytecnt
&& chunks
)
172 * Split the input by bytes.
175 split1(off_t bytecnt
, int maxcnt
)
186 switch (len
= read(ifd
, bfr
, MAXBSIZE
)) {
195 if (!maxcnt
|| (nfiles
< maxcnt
)) {
201 if (bcnt
+ len
>= bytecnt
) {
202 /* LINTED: bytecnt - bcnt <= len */
203 dist
= bytecnt
- bcnt
;
204 if (bigwrite(ofd
, bfr
, dist
) != (size_t)dist
)
207 for (C
= bfr
+ dist
; len
>= bytecnt
;
208 /* LINTED: bytecnt <= len */
209 len
-= bytecnt
, C
+= bytecnt
) {
210 if (!maxcnt
|| (nfiles
< maxcnt
)) {
214 /* LINTED: as above */
216 C
, bytecnt
) != (size_t)bytecnt
)
220 if (!maxcnt
|| (nfiles
< maxcnt
)) {
224 /* LINTED: len >= 0 */
225 if (bigwrite(ofd
, C
, len
) != (size_t)len
)
232 /* LINTED: len >= 0 */
233 if (bigwrite(ofd
, bfr
, len
) != (size_t)len
)
241 * Split the input by lines.
244 split2(off_t numlines
)
253 switch (len
= read(ifd
, bfr
, MAXBSIZE
)) {
265 for (Cs
= Ce
= bfr
; len
--; Ce
++)
266 if (*Ce
== '\n' && ++lcnt
== numlines
) {
268 if (bigwrite(ofd
, Cs
, bcnt
) != (size_t)bcnt
)
279 if (bigwrite(ofd
, Cs
, bcnt
) != (size_t)bcnt
)
287 * Split the input into specified number of chunks
294 if (fstat(ifd
, &sb
) == -1) {
299 if (chunks
> sb
.st_size
) {
300 errx(1, "can't split into more than %d files",
305 split1(sb
.st_size
/chunks
, chunks
);
310 * Open a new output file.
320 fpnt
= fname
+ strlen(fname
);
322 } else if (close(ofd
) != 0)
326 for (i
= sfxlen
- 1; i
>= 0; i
--) {
327 fpnt
[i
] = quot
% 26 + 'a';
331 errx(1, "too many files.");
333 if ((ofd
= open(fname
, O_WRONLY
| O_CREAT
| O_TRUNC
, DEFFILEMODE
)) < 0)
338 bigwrite(int fd
, const void *buf
, size_t len
)
340 const char *ptr
= buf
;
345 if ((w
= write(fd
, ptr
, len
)) == -1)
358 (void)fprintf(stderr
,
359 "usage: %s [-b byte_count] [-l line_count] [-n chunk_count] [-a suffix_length] "
360 "[file [prefix]]\n", getprogname());