source: MondoRescue/branches/3.3/mindi-busybox/coreutils/split.c@ 3906

Last change on this file since 3906 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 3.5 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * split - split a file into pieces
4 * Copyright (c) 2007 Bernhard Reutner-Fischer
5 *
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */
8/* BB_AUDIT: SUSv3 compliant
9 * SUSv3 requirements:
10 * http://www.opengroup.org/onlinepubs/009695399/utilities/split.html
11 */
12
13//usage:#define split_trivial_usage
14//usage: "[OPTIONS] [INPUT [PREFIX]]"
15//usage:#define split_full_usage "\n\n"
16//usage: " -b N[k|m] Split by N (kilo|mega)bytes"
17//usage: "\n -l N Split by N lines"
18//usage: "\n -a N Use N letters as suffix"
19//usage:
20//usage:#define split_example_usage
21//usage: "$ split TODO foo\n"
22//usage: "$ cat TODO | split -a 2 -l 2 TODO_\n"
23
24#include "libbb.h"
25#include "common_bufsiz.h"
26
27#if ENABLE_FEATURE_SPLIT_FANCY
28static const struct suffix_mult split_suffixes[] = {
29 { "b", 512 },
30 { "k", 1024 },
31 { "m", 1024*1024 },
32 { "g", 1024*1024*1024 },
33 { "", 0 }
34};
35#endif
36
37/* Increment the suffix part of the filename.
38 * Returns NULL if we are out of filenames.
39 */
40static char *next_file(char *old, unsigned suffix_len)
41{
42 size_t end = strlen(old);
43 unsigned i = 1;
44 char *curr;
45
46 while (1) {
47 curr = old + end - i;
48 if (*curr < 'z') {
49 *curr += 1;
50 break;
51 }
52 i++;
53 if (i > suffix_len) {
54 return NULL;
55 }
56 *curr = 'a';
57 }
58
59 return old;
60}
61
62#define read_buffer bb_common_bufsiz1
63enum { READ_BUFFER_SIZE = COMMON_BUFSIZE - 1 };
64
65#define SPLIT_OPT_l (1<<0)
66#define SPLIT_OPT_b (1<<1)
67#define SPLIT_OPT_a (1<<2)
68
69int split_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
70int split_main(int argc UNUSED_PARAM, char **argv)
71{
72 unsigned suffix_len = 2;
73 char *pfx;
74 char *count_p;
75 const char *sfx;
76 off_t cnt = 1000;
77 off_t remaining = 0;
78 unsigned opt;
79 ssize_t bytes_read, to_write;
80 char *src;
81
82 setup_common_bufsiz();
83
84 opt_complementary = "?2:a+"; /* max 2 args; -a N */
85 opt = getopt32(argv, "l:b:a:", &count_p, &count_p, &suffix_len);
86
87 if (opt & SPLIT_OPT_l)
88 cnt = XATOOFF(count_p);
89 if (opt & SPLIT_OPT_b) // FIXME: also needs XATOOFF
90 cnt = xatoull_sfx(count_p,
91 IF_FEATURE_SPLIT_FANCY(split_suffixes)
92 IF_NOT_FEATURE_SPLIT_FANCY(km_suffixes)
93 );
94 sfx = "x";
95
96 argv += optind;
97 if (argv[0]) {
98 int fd;
99 if (argv[1])
100 sfx = argv[1];
101 fd = xopen_stdin(argv[0]);
102 xmove_fd(fd, STDIN_FILENO);
103 } else {
104 argv[0] = (char *) bb_msg_standard_input;
105 }
106
107 if (NAME_MAX < strlen(sfx) + suffix_len)
108 bb_error_msg_and_die("suffix too long");
109
110 {
111 char *char_p = xzalloc(suffix_len + 1);
112 memset(char_p, 'a', suffix_len);
113 pfx = xasprintf("%s%s", sfx, char_p);
114 if (ENABLE_FEATURE_CLEAN_UP)
115 free(char_p);
116 }
117
118 while (1) {
119 bytes_read = safe_read(STDIN_FILENO, read_buffer, READ_BUFFER_SIZE);
120 if (!bytes_read)
121 break;
122 if (bytes_read < 0)
123 bb_simple_perror_msg_and_die(argv[0]);
124 src = read_buffer;
125 do {
126 if (!remaining) {
127 if (!pfx)
128 bb_error_msg_and_die("suffixes exhausted");
129 xmove_fd(xopen(pfx, O_WRONLY | O_CREAT | O_TRUNC), 1);
130 pfx = next_file(pfx, suffix_len);
131 remaining = cnt;
132 }
133
134 if (opt & SPLIT_OPT_b) {
135 /* split by bytes */
136 to_write = (bytes_read < remaining) ? bytes_read : remaining;
137 remaining -= to_write;
138 } else {
139 /* split by lines */
140 /* can be sped up by using _memrchr_
141 * and writing many lines at once... */
142 char *end = memchr(src, '\n', bytes_read);
143 if (end) {
144 --remaining;
145 to_write = end - src + 1;
146 } else {
147 to_write = bytes_read;
148 }
149 }
150
151 xwrite(STDOUT_FILENO, src, to_write);
152 bytes_read -= to_write;
153 src += to_write;
154 } while (bytes_read);
155 }
156 return EXIT_SUCCESS;
157}
Note: See TracBrowser for help on using the repository browser.