1 /* $MirOS: src/usr.bin/splitb/splitb.c,v 1.7 2013/10/31 20:07:10 tg Exp $ */
2
3 /*-
4 * Copyright © 2005, 2013
5 * Thorsten Glaser <tg@mirbsd.org>
6 *
7 * Provided that these terms and disclaimer and all copyright notices
8 * are retained or reproduced in an accompanying document, permission
9 * is granted to deal in this work without restriction, including un‐
10 * limited rights to use, publicly perform, distribute, sell, modify,
11 * merge, give away, or sublicence.
12 *
13 * This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
14 * the utmost extent permitted by applicable law, neither express nor
15 * implied; without malicious intent or gross negligence. In no event
16 * may a licensor, author or contributor be held liable for indirect,
17 * direct, other damage, loss, or other issues arising in any way out
18 * of dealing in the work, even if advised of the possibility of such
19 * damage or existence of a defect, except proven that it results out
20 * of said person’s immediate fault when using the work as intended.
21 *-
22 * Inspired by work done for Telefax 400, Deutsche Telekom AG.
23 */
24
25 #ifdef linux
26 #define _FILE_OFFSET_BITS 64
27 #ifndef __dead
28 #define __dead __attribute__((__noreturn__))
29 #endif
30 #endif
31
32 #include <sys/param.h>
33 #include <err.h>
34 #include <fcntl.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 int main(int, char **);
42 __dead void usage(int);
43
44 int
main(int argc,char ** argv)45 main(int argc, char **argv)
46 {
47 int i, ifd, ofd, ch, pfl = 3;
48 long l = 1, lw = 0, bufsiz = 1024 * 1024;
49 ssize_t k;
50 bool quiet = false, dec = false;
51 char *ft = strdup("split"), fn[PATH_MAX], *buf;
52 int64_t sum = 0;
53
54 while ((ch = getopt(argc, argv, "B:b:dhkqt:w:")) != -1) {
55 switch (ch) {
56 case 'h':
57 usage(1);
58 break;
59 case 'B':
60 if ((bufsiz = strtol(optarg, NULL, 0)) <=0)
61 errx(1, "bufsize cannot be negative");
62 else if ((bufsiz == 1) && !quiet)
63 warnx("bufsize 1 provides low performance");
64 else if (bufsiz > 1024 * 1024 * 1024)
65 errx(1, "bufsize > 1 GiB makes no sense");
66 break;
67 case 'b':
68 if ((l = strtol(optarg, NULL, 0)) <= 0)
69 usage(0);
70 break;
71 case 'd':
72 dec = !dec;
73 break;
74 case 'k':
75 bufsiz = 1024;
76 break;
77 case 'q':
78 quiet = true;
79 break;
80 case 't':
81 ft = strdup(optarg);
82 break;
83 case 'w':
84 if ((pfl = (int)strtol(optarg, NULL, 0)) < 1)
85 usage(0);
86 break;
87 default:
88 usage(0);
89 break;
90 }
91 }
92 argc -= optind;
93 argv += optind;
94
95 if ((size_t)pfl > (PATH_MAX - 2 - strlen(ft)))
96 usage(0);
97
98 if (argc) {
99 if ((ifd = open(*argv, O_RDONLY)) == -1)
100 err(1, "cannot open input file");
101 } else
102 ifd = STDIN_FILENO;
103
104 if ((buf = malloc((size_t)bufsiz)) == NULL)
105 err(1, "cannot allocate memory");
106
107 i = 0;
108 ofd = -1;
109 while ((k = read(ifd, buf, (size_t)bufsiz)) > 0) {
110 sum += k;
111 if (ofd == -1) {
112 snprintf(fn, sizeof(fn),
113 dec ? "%s.%0*d" : "%s.%0*X",
114 ft, pfl, i);
115 if ((ofd = open(fn, O_WRONLY | O_CREAT | O_TRUNC,
116 0666)) == -1)
117 err(1, "cannot open output file");
118 lw = 0;
119 if (!quiet)
120 printf("Writing to %s...", fn);
121 fflush(stdout);
122 }
123 if (write(ofd, buf, (size_t)k) != k)
124 err(1, "cannot write to output file");
125 if (k != bufsiz) {
126 close(ofd);
127 break;
128 }
129 if (++lw == l) {
130 close(ofd);
131 ofd = -1;
132 if (!quiet)
133 printf("done\n");
134 fflush(stdout);
135 ++i;
136 }
137 }
138 if (ofd != -1) {
139 close(ofd);
140 if (!quiet)
141 printf("done\n");
142 ++i;
143 }
144 printf("%lld bytes written to %d output files.\n", sum, i);
145 return 0;
146 }
147
148 __dead void
usage(int loud)149 usage(int loud)
150 {
151 extern const char *__progname;
152
153 printf("Usage: %s [-dhkq] [-B bufsiz] [-b blocks] [-t template]\n"
154 " [-w width] [inputfile]\n%s",
155 __progname, loud ?
156 "A buffer consists of bufsiz Bytes, or 1 KiB (1024 Bytes)\n"
157 "if -k is given, or 1 MiB (1048576 Bytes) if neither -B\n"
158 "nor -k is used on the command line. Default width for\n"
159 "the file postfix is 3; stdin is the default inputfile.\n"
160 : "");
161 exit(loud ? 0 : 1);
162 }
163