split.c (2305B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <ctype.h> 3 #include <limits.h> 4 #include <stdint.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #include "util.h" 10 11 static int itostr(char *, int, int); 12 static FILE *nextfile(FILE *, char *, int, int); 13 14 static void 15 usage(void) 16 { 17 eprintf("usage: split [-d] [-a len] [-b [bytes[k|m|g]]] [-l [lines]] [input [prefix]]\n"); 18 } 19 20 static int base = 26, start = 'a'; 21 22 int 23 main(int argc, char *argv[]) 24 { 25 int plen, slen = 2; 26 int ch; 27 char name[NAME_MAX+1]; 28 char *prefix = "x"; 29 char *file = NULL; 30 char *tmp, *end; 31 uint64_t size = 1000, scale = 1, n; 32 int always = 0; 33 FILE *in = stdin, *out = NULL; 34 35 ARGBEGIN { 36 case 'b': 37 always = 1; 38 tmp = ARGF(); 39 if (!tmp) 40 break; 41 42 size = strtoull(tmp, &end, 10); 43 if (!*end) 44 break; 45 switch (toupper((int)*end)) { 46 case 'K': 47 scale = 1024; 48 break; 49 case 'M': 50 scale = 1024L * 1024L; 51 break; 52 case 'G': 53 scale = 1024L * 1024L * 1024L; 54 break; 55 default: 56 usage(); 57 } 58 if (size > (UINT64_MAX/scale)) 59 eprintf("'%s': out of range\n", tmp); 60 size *= scale; 61 break; 62 case 'l': 63 always = 0; 64 tmp = ARGF(); 65 if (tmp) 66 size = estrtol(tmp, 10); 67 break; 68 case 'a': 69 slen = estrtol(EARGF(usage()), 10); 70 break; 71 case 'd': 72 base = 10; 73 start = '0'; 74 break; 75 default: 76 usage(); 77 } ARGEND; 78 79 if (*argv) 80 file = *argv++; 81 if (*argv) 82 prefix = *argv++; 83 if (*argv) 84 usage(); 85 86 plen = strlen(prefix); 87 if (plen+slen > NAME_MAX) 88 eprintf("names cannot exceed %d bytes\n", NAME_MAX); 89 strlcpy(name, prefix, sizeof(name)); 90 91 if (file && strcmp(file, "-") != 0) { 92 in = fopen(file, "r"); 93 if (!in) 94 eprintf("'%s':", file); 95 } 96 97 Nextfile: 98 while ((out = nextfile(out, name, plen, slen))) { 99 n = 0; 100 while ((ch = getc(in)) != EOF) { 101 putc(ch, out); 102 n += (always || ch == '\n'); 103 if (n >= size) 104 goto Nextfile; 105 } 106 fclose(out); 107 break; 108 } 109 return 0; 110 } 111 112 int 113 itostr(char *str, int x, int n) 114 { 115 str[n] = '\0'; 116 while (n-- > 0) { 117 str[n] = start + (x % base); 118 x /= base; 119 } 120 if (x) 121 return -1; 122 return 0; 123 } 124 125 FILE * 126 nextfile(FILE *f, char *buf, int plen, int slen) 127 { 128 static int n = 0; 129 int s; 130 131 if (f) 132 fclose(f); 133 s = itostr(buf+plen, n++, slen); 134 if (s < 0) 135 return NULL; 136 137 f = fopen(buf, "w"); 138 if (!f) 139 eprintf("'%s':", buf); 140 return f; 141 }