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