/* See LICENSE file for copyright and license details. */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <ctype.h> #include <limits.h> #include "util.h" static int itostr(char *, int, int); static FILE *nextfile(FILE *, char *, int, int); static void usage(void); static int base = 26, start = 'a'; int main(int argc, char **argv) { int plen, slen = 2; int ch; char name[NAME_MAX+1]; char *prefix = "x"; char *file = NULL; char *tmp, *end; uint64_t sizes['M'+1]; uint64_t size = 1000, scale, n; int always = 0; FILE *in=stdin, *out=NULL; sizes['K'] = 1024; sizes['M'] = 1024L*1024L; sizes['G'] = 1024L*1024L*1024L; ARGBEGIN { case 'b': always = 1; tmp = ARGF(); if(tmp == NULL) break; size = strtoull(tmp, &end, 10); if(*end == '\0') break; if(strchr("KMG", toupper(*end)) == NULL || end[1] != '\0') usage(); scale = sizes[toupper(*end)]; if(size > (UINT64_MAX/scale)) eprintf("split: '%s': out of range\n", tmp); size *= scale; break; case 'l': always = 0; tmp = ARGF(); if(tmp) size = estrtol(tmp, 10); break; case 'a': slen = estrtol(EARGF(usage()), 10); break; case 'd': base = 10; start = '0'; break; default: usage(); } ARGEND; if(*argv) file = *argv++; if(*argv) prefix = *argv++; if(*argv) usage(); plen = strlen(prefix); if(plen+slen > NAME_MAX) eprintf("split: names cannot exceed %d bytes", NAME_MAX); strcpy(name, prefix); if(file && strcmp(file, "-") != 0) { in = fopen(file, "r"); if(!in) eprintf("split: '%s':", file); } Nextfile: while((out = nextfile(out, name, plen, slen))) { n = 0; while((ch = getc(in)) != EOF) { putc(ch, out); n += (always || ch == '\n'); if(n >= size) goto Nextfile; } fclose(out); break; } return EXIT_SUCCESS; } void usage(void) { eprintf("usage: split [-d] [-a len] [-b [bytes[k|m|g]]] [-l [lines]] [input [prefix]]\n"); } int itostr(char *str, int x, int n) { str[n] = '\0'; while(n-- > 0) { str[n] = start + (x % base); x /= base; } if(x) return -1; return 0; } FILE * nextfile(FILE *f, char *buf, int plen, int slen) { static int n = 0; int s; if(f) fclose(f); s = itostr(buf+plen, n++, slen); if(s == -1) return NULL; f = fopen(buf, "w"); if(!f) eprintf("split: '%s':", buf); return f; }