1/* vi: set sw=4 ts=4: */ 2/* 3 * split - split a file into pieces 4 * Copyright (c) 2007 Bernhard Fischer 5 * 6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 7 */ 8/* BB_AUDIT: SUSv3 compliant 9 * SUSv3 requirements: 10 * http://www.opengroup.org/onlinepubs/009695399/utilities/split.html 11 */ 12#include "libbb.h" 13 14static const struct suffix_mult split_suffices[] = { 15#if ENABLE_FEATURE_SPLIT_FANCY 16 { "b", 512 }, 17#endif 18 { "k", 1024 }, 19 { "m", 1024*1024 }, 20#if ENABLE_FEATURE_SPLIT_FANCY 21 { "g", 1024*1024*1024 }, 22#endif 23 { } 24}; 25 26/* Increment the suffix part of the filename. 27 * Returns NULL if we are out of filenames. 28 */ 29static char *next_file(char *old, unsigned suffix_len) 30{ 31 size_t end = strlen(old); 32 unsigned i = 1; 33 char *curr; 34 35 do { 36 curr = old + end - i; 37 if (*curr < 'z') { 38 *curr += 1; 39 break; 40 } 41 i++; 42 if (i > suffix_len) { 43 return NULL; 44 } 45 *curr = 'a'; 46 } while (1); 47 48 return old; 49} 50 51#define read_buffer bb_common_bufsiz1 52enum { READ_BUFFER_SIZE = COMMON_BUFSIZE - 1 }; 53 54#define SPLIT_OPT_l (1<<0) 55#define SPLIT_OPT_b (1<<1) 56#define SPLIT_OPT_a (1<<2) 57 58int split_main(int argc, char **argv); 59int split_main(int argc, char **argv) 60{ 61 unsigned suffix_len = 2; 62 char *pfx; 63 char *count_p; 64 const char *sfx; 65 off_t cnt = 1000; 66 off_t remaining = 0; 67 unsigned opt; 68 ssize_t bytes_read, to_write; 69 char *src; 70 71 opt_complementary = "?2"; 72 opt = getopt32(argv, "l:b:a:", &count_p, &count_p, &sfx); 73 74 if (opt & SPLIT_OPT_l) 75 cnt = xatoul(count_p); 76 if (opt & SPLIT_OPT_b) 77 cnt = xatoul_sfx(count_p, split_suffices); 78 if (opt & SPLIT_OPT_a) 79 suffix_len = xatou(sfx); 80 sfx = "x"; 81 82 argv += optind; 83 if (argv[0]) { 84 if (argv[1]) 85 sfx = argv[1]; 86 xmove_fd(xopen(argv[0], O_RDONLY), 0); 87 } else { 88 argv[0] = (char *) bb_msg_standard_input; 89 } 90 91 if (NAME_MAX < strlen(sfx) + suffix_len) 92 bb_error_msg_and_die("suffix too long"); 93 94 { 95 char *char_p = xzalloc(suffix_len + 1); 96 memset(char_p, 'a', suffix_len); 97 pfx = xasprintf("%s%s", sfx, char_p); 98 if (ENABLE_FEATURE_CLEAN_UP) 99 free(char_p); 100 } 101 102 while (1) { 103 bytes_read = safe_read(0, read_buffer, READ_BUFFER_SIZE); 104 if (!bytes_read) 105 break; 106 if (bytes_read < 0) 107 bb_perror_msg_and_die("%s", argv[0]); 108 src = read_buffer; 109 do { 110 if (!remaining) { 111 if (!pfx) 112 bb_error_msg_and_die("suffixes exhausted"); 113 xmove_fd(xopen(pfx, O_WRONLY | O_CREAT | O_TRUNC), 1); 114 pfx = next_file(pfx, suffix_len); 115 remaining = cnt; 116 } 117 118 if (opt & SPLIT_OPT_b) { 119 /* split by bytes */ 120 to_write = (bytes_read < remaining) ? bytes_read : remaining; 121 remaining -= to_write; 122 } else { 123 /* split by lines */ 124 /* can be sped up by using _memrchr_ 125 * and writing many lines at once... */ 126 char *end = memchr(src, '\n', bytes_read); 127 if (end) { 128 --remaining; 129 to_write = end - src + 1; 130 } else { 131 to_write = bytes_read; 132 } 133 } 134 135 xwrite(1, src, to_write); 136 bytes_read -= to_write; 137 src += to_write; 138 } while (bytes_read); 139 } 140 return 0; 141} 142