blob: 86fd20437414030ed28868de30b86823249fa4c5 [file] [log] [blame]
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +00001/* 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: not yet SUSV3 compliant; FIXME: add -bN{k,m}
9 * SUSv3 requirements:
10 * http://www.opengroup.org/onlinepubs/009695399/utilities/split.html
11 */
12#include "busybox.h"
13static unsigned suffix_len = 2;
Bernhard Reutner-Fischercd43dfd2007-03-26 10:46:31 +000014static 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 { NULL, 0 }
24};
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +000025
26/* Increment the suffix part of the filename.
27 * Returns 0 on success and 1 on error (if we are out of files)
28 */
29static bool next_file(char **old)
30{
31 size_t end = strlen(*old);
32 unsigned i = 1;
33 char *curr;
34
35 do {
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +000036 curr = *old + end - i;
37 if (*curr < 'z') {
Bernhard Reutner-Fischercd43dfd2007-03-26 10:46:31 +000038 *curr += 1;
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +000039 break;
40 }
Bernhard Reutner-Fischercd43dfd2007-03-26 10:46:31 +000041 *curr = 'a';
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +000042 i++;
43 } while (i <= suffix_len);
44 if ((*curr == 'z') && (i == suffix_len))
45 return 1;
46 return 0;
47}
48#define SPLIT_OPT_l (1<<0)
49#define SPLIT_OPT_b (1<<1)
Bernhard Reutner-Fischercd43dfd2007-03-26 10:46:31 +000050#define SPLIT_OPT_a (1<<2)
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +000051
52int split_main(int argc, char **argv);
53int split_main(int argc, char **argv)
54{
55 char *pfx;
Bernhard Reutner-Fischercd43dfd2007-03-26 10:46:31 +000056 char *count_p;
57 char *sfx_len;
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +000058 unsigned cnt = 1000;
59 char *input_file;
60
61//XXX: FIXME opt_complementary = "+2"; /* at most 2 non-option arguments */
62 getopt32(argc, argv, "l:b:a:", &count_p, &count_p, &sfx_len);
63 argv += optind;
64
Bernhard Reutner-Fischercd43dfd2007-03-26 10:46:31 +000065 if (option_mask32 & (SPLIT_OPT_l|SPLIT_OPT_b))
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +000066 cnt = xatoi(count_p);
Bernhard Reutner-Fischercd43dfd2007-03-26 10:46:31 +000067 if (option_mask32 & SPLIT_OPT_a)
Bernhard Reutner-Fischer10f8f5f2007-03-25 21:50:18 +000068 suffix_len = xatoul(sfx_len);
69
70 if (!*argv)
71 *--argv = (char*) "-";
72 input_file = *argv;
73 if (NAME_MAX < strlen(*argv) + suffix_len)
74 bb_error_msg_and_die("Suffix too long");
75
76 {
77 char *char_p = xzalloc(suffix_len);
78 memset(char_p, 'a', suffix_len);
79 pfx = xasprintf("%s%s", (argc > optind + 1) ? *++argv : "x", char_p);
80 if (ENABLE_FEATURE_CLEAN_UP)
81 free(char_p);
82 }
83//XXX:FIXME: unify those two file-handling schemata below (FILE vs fd) !
84 if (option_mask32 & SPLIT_OPT_b) {
85 char *buf;
86 ssize_t i;
87 ssize_t bytes = 0;
88 int inp = xopen(input_file, O_RDONLY);
89 int flags = O_WRONLY | O_CREAT | O_TRUNC;
90 do {
91 int out = xopen(pfx, flags);
92 buf = xzalloc(cnt);
93 lseek(inp, bytes, SEEK_SET);
94 bytes += i = full_read(inp, buf, cnt);
95 xwrite(out, buf, i);
96 close(out);
97 free(buf);
98 if (next_file(&pfx))
99 flags = O_WRONLY | O_APPEND;
100 } while(i > 0);
101 } else { /* -l */
102 FILE *fp = fopen_or_warn_stdin(input_file);
103 char *buf;
104 do {
105 unsigned i = cnt;
106 int flags = O_WRONLY | O_CREAT | O_TRUNC;
107 int out = xopen(pfx, flags);
108 buf = NULL;
109 while (i--) {
110 buf = xmalloc_fgets(fp);
111 if (buf == NULL)
112 break;
113 xwrite(out, buf, buf ? strlen(buf) : 0);
114 free(buf);
115 };
116 close(out);
117
118 if (next_file(&pfx))
119 flags = O_WRONLY | O_APPEND;
120 } while (buf);
121 if (ENABLE_FEATURE_CLEAN_UP)
122 fclose_if_not_stdin(fp);
123 }
124
125 if (ENABLE_FEATURE_CLEAN_UP) {
126 free(pfx);
127 }
128 return EXIT_SUCCESS;
129}