diff options
Diffstat (limited to 'coreutils')
-rw-r--r-- | coreutils/cp.c | 2 | ||||
-rw-r--r-- | coreutils/date.c | 102 | ||||
-rw-r--r-- | coreutils/dd.c | 116 | ||||
-rw-r--r-- | coreutils/factor.c | 209 | ||||
-rw-r--r-- | coreutils/id.c | 2 | ||||
-rw-r--r-- | coreutils/ln.c | 4 | ||||
-rw-r--r-- | coreutils/md5_sha1_sum.c | 2 | ||||
-rw-r--r-- | coreutils/mkdir.c | 2 | ||||
-rw-r--r-- | coreutils/mknod.c | 4 | ||||
-rw-r--r-- | coreutils/nl.c | 2 | ||||
-rw-r--r-- | coreutils/od_bloaty.c | 4 | ||||
-rw-r--r-- | coreutils/paste.c | 2 | ||||
-rw-r--r-- | coreutils/rmdir.c | 2 | ||||
-rw-r--r-- | coreutils/sort.c | 2 | ||||
-rw-r--r-- | coreutils/split.c | 2 | ||||
-rw-r--r-- | coreutils/stat.c | 4 | ||||
-rw-r--r-- | coreutils/stty.c | 4 | ||||
-rw-r--r-- | coreutils/test.c | 2 | ||||
-rw-r--r-- | coreutils/timeout.c | 4 | ||||
-rw-r--r-- | coreutils/uniq.c | 2 | ||||
-rw-r--r-- | coreutils/uudecode.c | 162 |
21 files changed, 424 insertions, 211 deletions
diff --git a/coreutils/cp.c b/coreutils/cp.c index cfeb19fc4..9b9b8f7bf 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c | |||
@@ -38,7 +38,7 @@ | |||
38 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */ | 38 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */ |
39 | 39 | ||
40 | //usage:#define cp_trivial_usage | 40 | //usage:#define cp_trivial_usage |
41 | //usage: "[OPTIONS] SOURCE... DEST" | 41 | //usage: "[-arPLHpfilsTu] SOURCE... DEST" |
42 | //usage:#define cp_full_usage "\n\n" | 42 | //usage:#define cp_full_usage "\n\n" |
43 | //usage: "Copy SOURCE(s) to DEST\n" | 43 | //usage: "Copy SOURCE(s) to DEST\n" |
44 | //usage: "\n -a Same as -dpR" | 44 | //usage: "\n -a Same as -dpR" |
diff --git a/coreutils/date.c b/coreutils/date.c index 1a3ae506c..d64ff94b9 100644 --- a/coreutils/date.c +++ b/coreutils/date.c | |||
@@ -93,40 +93,27 @@ | |||
93 | */ | 93 | */ |
94 | 94 | ||
95 | //usage:#define date_trivial_usage | 95 | //usage:#define date_trivial_usage |
96 | //usage: "[OPTIONS] [+FMT] [TIME]" | 96 | //usage: "[OPTIONS] [+FMT] [[-s] TIME]" |
97 | //usage:#define date_full_usage "\n\n" | 97 | //usage:#define date_full_usage "\n\n" |
98 | //usage: "Display time (using +FMT), or set time\n" | 98 | //usage: "Display time (using +FMT), or set time\n" |
99 | //usage: IF_NOT_LONG_OPTS( | ||
100 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
101 | //usage: "\n [-s] TIME Set time to TIME" | ||
102 | //usage: ) | ||
103 | //usage: "\n -u Work in UTC (don't convert to local time)" | 99 | //usage: "\n -u Work in UTC (don't convert to local time)" |
104 | //usage: "\n -R Output RFC-2822 compliant date string" | 100 | //usage: IF_NOT_PLATFORM_MINGW32( |
105 | //usage: ) IF_LONG_OPTS( | 101 | //usage: "\n [-s] TIME Set time to TIME" |
106 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
107 | //usage: "\n [-s,--set] TIME Set time to TIME" | ||
108 | //usage: ) | ||
109 | //usage: "\n -u,--utc Work in UTC (don't convert to local time)" | ||
110 | //usage: "\n -R,--rfc-2822 Output RFC-2822 compliant date string" | ||
111 | //usage: ) | 102 | //usage: ) |
103 | //usage: "\n -d TIME Display TIME, not 'now'" | ||
112 | //usage: IF_FEATURE_DATE_ISOFMT( | 104 | //usage: IF_FEATURE_DATE_ISOFMT( |
113 | //usage: "\n -I[SPEC] Output ISO-8601 compliant date string" | 105 | //usage: "\n -D FMT FMT (strptime format) for -s/-d TIME conversion" |
114 | //usage: "\n SPEC='date' (default) for date only," | 106 | ////////^^^^^^^^^^^^^^^^^^^^^^ busybox invention, not compat |
115 | //usage: "\n 'hours', 'minutes', or 'seconds' for date and" | ||
116 | //usage: "\n time to the indicated precision" | ||
117 | //usage: ) | 107 | //usage: ) |
118 | //usage: IF_NOT_LONG_OPTS( | ||
119 | //usage: "\n -r FILE Display last modification time of FILE" | 108 | //usage: "\n -r FILE Display last modification time of FILE" |
120 | //usage: "\n -d TIME Display TIME, not 'now'" | 109 | //usage: "\n -R Output RFC-2822 date" |
121 | //usage: ) IF_LONG_OPTS( | ||
122 | //usage: "\n -r,--reference FILE Display last modification time of FILE" | ||
123 | //usage: "\n -d,--date TIME Display TIME, not 'now'" | ||
124 | //usage: ) | ||
125 | //usage: IF_FEATURE_DATE_ISOFMT( | 110 | //usage: IF_FEATURE_DATE_ISOFMT( |
126 | //usage: "\n -D FMT Use FMT (strptime format) for -d TIME conversion" | 111 | //usage: "\n -I[SPEC] Output ISO-8601 date" |
112 | //usage: "\n SPEC=date (default), hours, minutes, seconds or ns" | ||
127 | //usage: ) | 113 | //usage: ) |
128 | //usage: "\n" | 114 | //usage: "\n" |
129 | //usage: "\nRecognized TIME formats:" | 115 | //usage: "\nRecognized TIME formats:" |
116 | //usage: "\n @seconds_since_1970" | ||
130 | //usage: "\n hh:mm[:ss]" | 117 | //usage: "\n hh:mm[:ss]" |
131 | //usage: "\n [YYYY.]MM.DD-hh:mm[:ss]" | 118 | //usage: "\n [YYYY.]MM.DD-hh:mm[:ss]" |
132 | //usage: "\n YYYY-MM-DD hh:mm[:ss]" | 119 | //usage: "\n YYYY-MM-DD hh:mm[:ss]" |
@@ -152,15 +139,15 @@ enum { | |||
152 | OPT_UTC = (1 << 2), /* u */ | 139 | OPT_UTC = (1 << 2), /* u */ |
153 | OPT_DATE = (1 << 3), /* d */ | 140 | OPT_DATE = (1 << 3), /* d */ |
154 | OPT_REFERENCE = (1 << 4), /* r */ | 141 | OPT_REFERENCE = (1 << 4), /* r */ |
155 | OPT_TIMESPEC = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ | 142 | OPT_ISO8601 = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ |
156 | OPT_HINT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ | 143 | OPT_STR2DT = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ |
157 | #else | 144 | #else |
158 | OPT_SET = (0), /* s */ | 145 | OPT_SET = (0), /* s */ |
159 | OPT_UTC = (1 << 1), /* u */ | 146 | OPT_UTC = (1 << 1), /* u */ |
160 | OPT_DATE = (1 << 2), /* d */ | 147 | OPT_DATE = (1 << 2), /* d */ |
161 | OPT_REFERENCE = (1 << 3), /* r */ | 148 | OPT_REFERENCE = (1 << 3), /* r */ |
162 | OPT_TIMESPEC = (1 << 4) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ | 149 | OPT_ISO8601 = (1 << 4) * ENABLE_FEATURE_DATE_ISOFMT, /* I */ |
163 | OPT_HINT = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ | 150 | OPT_STR2DT = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* D */ |
164 | #endif | 151 | #endif |
165 | }; | 152 | }; |
166 | 153 | ||
@@ -185,12 +172,6 @@ static const char date_longopts[] ALIGN1 = | |||
185 | * - after xasprintf we use other xfuncs | 172 | * - after xasprintf we use other xfuncs |
186 | */ | 173 | */ |
187 | 174 | ||
188 | static void maybe_set_utc(int opt) | ||
189 | { | ||
190 | if (opt & OPT_UTC) | ||
191 | putenv((char*)"TZ=UTC0"); | ||
192 | } | ||
193 | |||
194 | int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 175 | int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
195 | int date_main(int argc UNUSED_PARAM, char **argv) | 176 | int date_main(int argc UNUSED_PARAM, char **argv) |
196 | { | 177 | { |
@@ -198,7 +179,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
198 | struct tm tm_time; | 179 | struct tm tm_time; |
199 | char buf_fmt_dt2str[64]; | 180 | char buf_fmt_dt2str[64]; |
200 | unsigned opt; | 181 | unsigned opt; |
201 | int ifmt = -1; | 182 | int isofmt = -1; |
202 | char *date_str; | 183 | char *date_str; |
203 | char *fmt_dt2str; | 184 | char *fmt_dt2str; |
204 | char *fmt_str2dt; | 185 | char *fmt_str2dt; |
@@ -229,15 +210,16 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
229 | ); | 210 | ); |
230 | argv += optind; | 211 | argv += optind; |
231 | 212 | ||
232 | maybe_set_utc(opt); | 213 | if (opt & OPT_UTC) |
214 | putenv((char*)"TZ=UTC0"); | ||
233 | 215 | ||
234 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_TIMESPEC)) { | 216 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_ISO8601)) { |
235 | ifmt = 0; /* default is date */ | 217 | isofmt = 0; /* default is date */ |
236 | if (isofmt_arg) { | 218 | if (isofmt_arg) { |
237 | static const char isoformats[] ALIGN1 = | 219 | static const char isoformats[] ALIGN1 = |
238 | "date\0""hours\0""minutes\0""seconds\0"; /* ns? */ | 220 | "date\0""hours\0""minutes\0""seconds\0ns\0"; |
239 | ifmt = index_in_substrings(isoformats, isofmt_arg); | 221 | isofmt = index_in_substrings(isoformats, isofmt_arg); |
240 | if (ifmt < 0) | 222 | if (isofmt < 0) |
241 | bb_show_usage(); | 223 | bb_show_usage(); |
242 | } | 224 | } |
243 | } | 225 | } |
@@ -247,7 +229,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
247 | fmt_dt2str = &argv[0][1]; /* skip over the '+' */ | 229 | fmt_dt2str = &argv[0][1]; /* skip over the '+' */ |
248 | argv++; | 230 | argv++; |
249 | } | 231 | } |
250 | if (!(opt & (OPT_SET | OPT_DATE))) { | 232 | if (!(opt & (OPT_SET | OPT_DATE))) { /* neither -s TIME nor -d TIME? */ |
251 | opt |= OPT_SET; | 233 | opt |= OPT_SET; |
252 | date_str = argv[0]; /* can be NULL */ | 234 | date_str = argv[0]; /* can be NULL */ |
253 | if (date_str) { | 235 | if (date_str) { |
@@ -315,7 +297,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
315 | tm_time.tm_hour = 0; | 297 | tm_time.tm_hour = 0; |
316 | 298 | ||
317 | /* Process any date input to UNIX time since 1 Jan 1970 */ | 299 | /* Process any date input to UNIX time since 1 Jan 1970 */ |
318 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_HINT)) { | 300 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & OPT_STR2DT)) { |
319 | if (strptime(date_str, fmt_str2dt, &tm_time) == NULL) | 301 | if (strptime(date_str, fmt_str2dt, &tm_time) == NULL) |
320 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | 302 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
321 | } else { | 303 | } else { |
@@ -341,24 +323,34 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
341 | if (fmt_dt2str == NULL) { | 323 | if (fmt_dt2str == NULL) { |
342 | int i; | 324 | int i; |
343 | fmt_dt2str = buf_fmt_dt2str; | 325 | fmt_dt2str = buf_fmt_dt2str; |
344 | if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) { | 326 | if (ENABLE_FEATURE_DATE_ISOFMT && isofmt >= 0) { |
345 | /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds */ | 327 | /* -I[SPEC]: 0:date 1:hours 2:minutes 3:seconds 4:ns*/ |
346 | strcpy(fmt_dt2str, "%Y-%m-%dT%H:%M:%S"); | 328 | strcpy(fmt_dt2str, "%Y-%m-%dT%H:%M:%S"); |
347 | i = 8 + 3 * ifmt; | 329 | i = 8 + 3 * isofmt; |
348 | if (ifmt != 0) { | 330 | if (isofmt != 0) { |
349 | /* TODO: if (ifmt==4) i += sprintf(&fmt_dt2str[i], ",%09u", nanoseconds); */ | 331 | int n; |
350 | format_utc: | 332 | if (isofmt == 4) { |
351 | fmt_dt2str[i++] = '%'; | 333 | i -= 3; |
352 | fmt_dt2str[i++] = (opt & OPT_UTC) ? 'Z' : 'z'; | 334 | i += sprintf(&fmt_dt2str[i], ",%09u", (unsigned)ts.tv_nsec); |
335 | } | ||
336 | /* %z prints "+hhmm" timezone, but coreutils-8.30 prints "+hh:mm"! */ | ||
337 | /* ...therefore this atrocity: */ | ||
338 | n = strftime(&fmt_dt2str[i], 8, "%z", &tm_time); | ||
339 | i += n; | ||
340 | if (n == 5 && (fmt_dt2str[i-5] == '+' || fmt_dt2str[i-5] == '-')) { | ||
341 | /* "mm" -> ":mm" */ | ||
342 | fmt_dt2str[i ] = fmt_dt2str[i - 1]; | ||
343 | fmt_dt2str[i - 1] = fmt_dt2str[i - 2]; | ||
344 | fmt_dt2str[i - 2] = ':'; | ||
345 | i++; | ||
346 | } | ||
353 | } | 347 | } |
354 | fmt_dt2str[i] = '\0'; | 348 | fmt_dt2str[i] = '\0'; |
355 | } else if (opt & OPT_RFC2822) { | 349 | } else if (opt & OPT_RFC2822) { |
356 | /* -R. undo busybox.c setlocale */ | 350 | /* -R. undo busybox.c setlocale */ |
357 | if (ENABLE_LOCALE_SUPPORT) | 351 | if (ENABLE_LOCALE_SUPPORT) |
358 | setlocale(LC_TIME, "C"); | 352 | setlocale(LC_TIME, "C"); |
359 | strcpy(fmt_dt2str, "%a, %d %b %Y %H:%M:%S "); | 353 | fmt_dt2str = (char*)"%a, %d %b %Y %H:%M:%S %z"; |
360 | i = sizeof("%a, %d %b %Y %H:%M:%S ")-1; | ||
361 | goto format_utc; | ||
362 | } else { /* default case */ | 354 | } else { /* default case */ |
363 | fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; | 355 | fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; |
364 | } | 356 | } |
@@ -410,10 +402,6 @@ int date_main(int argc UNUSED_PARAM, char **argv) | |||
410 | /* With no format string, just print a blank line */ | 402 | /* With no format string, just print a blank line */ |
411 | date_buf[0] = '\0'; | 403 | date_buf[0] = '\0'; |
412 | } else { | 404 | } else { |
413 | /* Handle special conversions */ | ||
414 | if (is_prefixed_with(fmt_dt2str, "%f")) { | ||
415 | fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S"; | ||
416 | } | ||
417 | /* Generate output string */ | 405 | /* Generate output string */ |
418 | strftime(date_buf, COMMON_BUFSIZE, fmt_dt2str, &tm_time); | 406 | strftime(date_buf, COMMON_BUFSIZE, fmt_dt2str, &tm_time); |
419 | } | 407 | } |
diff --git a/coreutils/dd.c b/coreutils/dd.c index 042355e24..c150ef5bc 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
@@ -59,7 +59,7 @@ | |||
59 | //usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n" | 59 | //usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n" |
60 | //usage: IF_FEATURE_DD_IBS_OBS( | 60 | //usage: IF_FEATURE_DD_IBS_OBS( |
61 | //usage: " [conv=notrunc|noerror|sync|fsync]\n" | 61 | //usage: " [conv=notrunc|noerror|sync|fsync]\n" |
62 | //usage: " [iflag=skip_bytes|fullblock] [oflag=seek_bytes|append]" | 62 | //usage: " [iflag=skip_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]" |
63 | //usage: ) | 63 | //usage: ) |
64 | //usage:#define dd_full_usage "\n\n" | 64 | //usage:#define dd_full_usage "\n\n" |
65 | //usage: "Copy a file with converting and formatting\n" | 65 | //usage: "Copy a file with converting and formatting\n" |
@@ -82,9 +82,11 @@ | |||
82 | //usage: "\n conv=fsync Physically write data out before finishing" | 82 | //usage: "\n conv=fsync Physically write data out before finishing" |
83 | //usage: "\n conv=swab Swap every pair of bytes" | 83 | //usage: "\n conv=swab Swap every pair of bytes" |
84 | //usage: "\n iflag=skip_bytes skip=N is in bytes" | 84 | //usage: "\n iflag=skip_bytes skip=N is in bytes" |
85 | //usage: "\n iflag=fullblock Read full blocks" | ||
86 | //usage: "\n oflag=seek_bytes seek=N is in bytes" | 85 | //usage: "\n oflag=seek_bytes seek=N is in bytes" |
87 | //usage: "\n oflag=append Open output file in append mode" | 86 | //usage: "\n iflag=direct O_DIRECT input" |
87 | //usage: "\n oflag=direct O_DIRECT output" | ||
88 | //usage: "\n iflag=fullblock Read full blocks" | ||
89 | //usage: "\n oflag=append Open output in append mode" | ||
88 | //usage: ) | 90 | //usage: ) |
89 | //usage: IF_FEATURE_DD_STATUS( | 91 | //usage: IF_FEATURE_DD_STATUS( |
90 | //usage: "\n status=noxfer Suppress rate output" | 92 | //usage: "\n status=noxfer Suppress rate output" |
@@ -140,16 +142,18 @@ enum { | |||
140 | FLAG_IFLAG_SHIFT = 5, | 142 | FLAG_IFLAG_SHIFT = 5, |
141 | FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, | 143 | FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, |
142 | FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, | 144 | FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, |
145 | FLAG_IDIRECT = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, | ||
143 | /* end of input flags */ | 146 | /* end of input flags */ |
144 | /* start of output flags */ | 147 | /* start of output flags */ |
145 | FLAG_OFLAG_SHIFT = 7, | 148 | FLAG_OFLAG_SHIFT = 8, |
146 | FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, | 149 | FLAG_SEEK_BYTES = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, |
147 | FLAG_APPEND = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, | 150 | FLAG_APPEND = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, |
151 | FLAG_ODIRECT = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS, | ||
148 | /* end of output flags */ | 152 | /* end of output flags */ |
149 | FLAG_TWOBUFS = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, | 153 | FLAG_TWOBUFS = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS, |
150 | FLAG_COUNT = 1 << 10, | 154 | FLAG_COUNT = 1 << 12, |
151 | FLAG_STATUS_NONE = 1 << 11, | 155 | FLAG_STATUS_NONE = 1 << 13, |
152 | FLAG_STATUS_NOXFER = 1 << 12, | 156 | FLAG_STATUS_NOXFER = 1 << 14, |
153 | }; | 157 | }; |
154 | 158 | ||
155 | static void dd_output_status(int UNUSED_PARAM cur_signal) | 159 | static void dd_output_status(int UNUSED_PARAM cur_signal) |
@@ -195,12 +199,50 @@ static void dd_output_status(int UNUSED_PARAM cur_signal) | |||
195 | #endif | 199 | #endif |
196 | } | 200 | } |
197 | 201 | ||
202 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
203 | static int clear_O_DIRECT(int fd) | ||
204 | { | ||
205 | if (errno == EINVAL) { | ||
206 | int fl = fcntl(fd, F_GETFL); | ||
207 | if (fl & O_DIRECT) { | ||
208 | fcntl(fd, F_SETFL, fl & ~O_DIRECT); | ||
209 | return 1; | ||
210 | } | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | #endif | ||
215 | |||
216 | static ssize_t dd_read(void *ibuf, size_t ibs) | ||
217 | { | ||
218 | ssize_t n; | ||
219 | |||
220 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
221 | read_again: | ||
222 | if (G.flags & FLAG_FULLBLOCK) | ||
223 | n = full_read(ifd, ibuf, ibs); | ||
224 | else | ||
225 | #endif | ||
226 | n = safe_read(ifd, ibuf, ibs); | ||
227 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
228 | if (n < 0 && (G.flags & FLAG_IDIRECT) && clear_O_DIRECT(ifd)) | ||
229 | goto read_again; | ||
230 | #endif | ||
231 | return n; | ||
232 | } | ||
233 | |||
198 | static bool write_and_stats(const void *buf, size_t len, size_t obs, | 234 | static bool write_and_stats(const void *buf, size_t len, size_t obs, |
199 | const char *filename) | 235 | const char *filename) |
200 | { | 236 | { |
201 | ssize_t n; | 237 | ssize_t n; |
202 | 238 | ||
239 | IF_FEATURE_DD_IBS_OBS(write_again:) | ||
203 | n = full_write(ofd, buf, len); | 240 | n = full_write(ofd, buf, len); |
241 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
242 | if (n < 0 && (G.flags & FLAG_ODIRECT) && clear_O_DIRECT(ofd)) | ||
243 | goto write_again; | ||
244 | #endif | ||
245 | |||
204 | #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE | 246 | #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE |
205 | if (n > 0) | 247 | if (n > 0) |
206 | G.total_bytes += n; | 248 | G.total_bytes += n; |
@@ -257,6 +299,16 @@ static int parse_comma_flags(char *val, const char *words, const char *error_in) | |||
257 | } | 299 | } |
258 | #endif | 300 | #endif |
259 | 301 | ||
302 | static void *alloc_buf(size_t size) | ||
303 | { | ||
304 | #if !ENABLE_PLATFORM_MINGW32 | ||
305 | /* Important for "{i,o}flag=direct" - buffers must be page aligned */ | ||
306 | if (size >= bb_getpagesize()) | ||
307 | return xmmap_anon(size); | ||
308 | #endif | ||
309 | return xmalloc(size); | ||
310 | } | ||
311 | |||
260 | int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 312 | int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
261 | int dd_main(int argc UNUSED_PARAM, char **argv) | 313 | int dd_main(int argc UNUSED_PARAM, char **argv) |
262 | { | 314 | { |
@@ -270,9 +322,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
270 | static const char conv_words[] ALIGN1 = | 322 | static const char conv_words[] ALIGN1 = |
271 | "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; | 323 | "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; |
272 | static const char iflag_words[] ALIGN1 = | 324 | static const char iflag_words[] ALIGN1 = |
273 | "skip_bytes\0""fullblock\0"; | 325 | "skip_bytes\0""fullblock\0""direct\0"; |
274 | static const char oflag_words[] ALIGN1 = | 326 | static const char oflag_words[] ALIGN1 = |
275 | "seek_bytes\0append\0"; | 327 | "seek_bytes\0append\0""direct\0"; |
276 | #endif | 328 | #endif |
277 | #if ENABLE_FEATURE_DD_STATUS | 329 | #if ENABLE_FEATURE_DD_STATUS |
278 | static const char status_words[] ALIGN1 = | 330 | static const char status_words[] ALIGN1 = |
@@ -313,7 +365,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
313 | //swab swap every pair of input bytes: will abort on non-even reads | 365 | //swab swap every pair of input bytes: will abort on non-even reads |
314 | OP_iflag_skip_bytes, | 366 | OP_iflag_skip_bytes, |
315 | OP_iflag_fullblock, | 367 | OP_iflag_fullblock, |
368 | OP_iflag_direct, | ||
316 | OP_oflag_seek_bytes, | 369 | OP_oflag_seek_bytes, |
370 | OP_oflag_direct, | ||
317 | #endif | 371 | #endif |
318 | }; | 372 | }; |
319 | smallint exitcode = EXIT_FAILURE; | 373 | smallint exitcode = EXIT_FAILURE; |
@@ -429,13 +483,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
429 | #endif | 483 | #endif |
430 | } /* end of "for (argv[i])" */ | 484 | } /* end of "for (argv[i])" */ |
431 | 485 | ||
432 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | 486 | ibuf = alloc_buf(ibs); |
433 | ibuf = xmalloc(ibs); | ||
434 | obuf = ibuf; | 487 | obuf = ibuf; |
435 | #if ENABLE_FEATURE_DD_IBS_OBS | 488 | #if ENABLE_FEATURE_DD_IBS_OBS |
436 | if (ibs != obs) { | 489 | if (ibs != obs) { |
437 | G.flags |= FLAG_TWOBUFS; | 490 | G.flags |= FLAG_TWOBUFS; |
438 | obuf = xmalloc(obs); | 491 | obuf = alloc_buf(obs); |
439 | } | 492 | } |
440 | #endif | 493 | #endif |
441 | 494 | ||
@@ -447,10 +500,15 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
447 | #endif | 500 | #endif |
448 | 501 | ||
449 | if (infile) { | 502 | if (infile) { |
503 | int iflag = O_RDONLY; | ||
504 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
505 | if (G.flags & FLAG_IDIRECT) | ||
506 | iflag |= O_DIRECT; | ||
507 | #endif | ||
450 | #if !ENABLE_PLATFORM_MINGW32 | 508 | #if !ENABLE_PLATFORM_MINGW32 |
451 | xmove_fd(xopen(infile, O_RDONLY), ifd); | 509 | xmove_fd(xopen(infile, iflag), ifd); |
452 | #else | 510 | #else |
453 | xmove_fd(mingw_xopen(infile, O_RDONLY), ifd); | 511 | xmove_fd(mingw_xopen(infile, iflag), ifd); |
454 | update_dev_fd(get_dev_type(infile), ifd); | 512 | update_dev_fd(get_dev_type(infile), ifd); |
455 | #endif | 513 | #endif |
456 | } else { | 514 | } else { |
@@ -463,7 +521,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
463 | oflag |= O_TRUNC; | 521 | oflag |= O_TRUNC; |
464 | if (G.flags & FLAG_APPEND) | 522 | if (G.flags & FLAG_APPEND) |
465 | oflag |= O_APPEND; | 523 | oflag |= O_APPEND; |
466 | 524 | #if ENABLE_FEATURE_DD_IBS_OBS | |
525 | if (G.flags & FLAG_ODIRECT) | ||
526 | oflag |= O_DIRECT; | ||
527 | #endif | ||
467 | xmove_fd(xopen(outfile, oflag), ofd); | 528 | xmove_fd(xopen(outfile, oflag), ofd); |
468 | 529 | ||
469 | #if ENABLE_PLATFORM_MINGW32 | 530 | #if ENABLE_PLATFORM_MINGW32 |
@@ -508,13 +569,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
508 | size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; | 569 | size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; |
509 | if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { | 570 | if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { |
510 | do { | 571 | do { |
511 | ssize_t n; | 572 | ssize_t n = dd_read(ibuf, blocksz); |
512 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
513 | if (G.flags & FLAG_FULLBLOCK) | ||
514 | n = full_read(ifd, ibuf, blocksz); | ||
515 | else | ||
516 | #endif | ||
517 | n = safe_read(ifd, ibuf, blocksz); | ||
518 | if (n < 0) | 573 | if (n < 0) |
519 | goto die_infile; | 574 | goto die_infile; |
520 | if (n == 0) | 575 | if (n == 0) |
@@ -529,14 +584,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
529 | } | 584 | } |
530 | 585 | ||
531 | while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { | 586 | while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { |
532 | ssize_t n; | 587 | ssize_t n = dd_read(ibuf, ibs); |
533 | |||
534 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
535 | if (G.flags & FLAG_FULLBLOCK) | ||
536 | n = full_read(ifd, ibuf, ibs); | ||
537 | else | ||
538 | #endif | ||
539 | n = safe_read(ifd, ibuf, ibs); | ||
540 | if (n == 0) | 588 | if (n == 0) |
541 | break; | 589 | break; |
542 | if (n < 0) { | 590 | if (n < 0) { |
@@ -631,11 +679,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
631 | if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) | 679 | if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) |
632 | dd_output_status(0); | 680 | dd_output_status(0); |
633 | 681 | ||
682 | #if 0 /* can't just free(), they can be mmap()ed */ | ||
634 | if (ENABLE_FEATURE_CLEAN_UP) { | 683 | if (ENABLE_FEATURE_CLEAN_UP) { |
635 | free(obuf); | 684 | free(obuf); |
636 | if (G.flags & FLAG_TWOBUFS) | 685 | if (G.flags & FLAG_TWOBUFS) |
637 | free(ibuf); | 686 | free(ibuf); |
638 | } | 687 | } |
688 | #endif | ||
639 | 689 | ||
640 | return exitcode; | 690 | return exitcode; |
641 | } | 691 | } |
diff --git a/coreutils/factor.c b/coreutils/factor.c index 47fe179dc..a7a5a5030 100644 --- a/coreutils/factor.c +++ b/coreutils/factor.c | |||
@@ -19,6 +19,7 @@ | |||
19 | //usage: "Print prime factors" | 19 | //usage: "Print prime factors" |
20 | 20 | ||
21 | #include "libbb.h" | 21 | #include "libbb.h" |
22 | #include "common_bufsiz.h" | ||
22 | 23 | ||
23 | #if 0 | 24 | #if 0 |
24 | # define dbg(...) bb_error_msg(__VA_ARGS__) | 25 | # define dbg(...) bb_error_msg(__VA_ARGS__) |
@@ -42,9 +43,116 @@ typedef unsigned long half_t; | |||
42 | #error Cant find an integer type which is half as wide as ullong | 43 | #error Cant find an integer type which is half as wide as ullong |
43 | #endif | 44 | #endif |
44 | 45 | ||
46 | /* The trial divisor increment wheel. Use it to skip over divisors that | ||
47 | * are composites of 2, 3, 5, 7, or 11. | ||
48 | * Larger wheels improve sieving only slightly, but quickly grow in size | ||
49 | * (adding just one prime, 13, results in 5766 element sieve). | ||
50 | */ | ||
51 | #define R(a,b,c,d,e,f,g,h,i,j,A,B,C,D,E,F,G,H,I,J) \ | ||
52 | (((uint64_t)(a<<0) | (b<<3) | (c<<6) | (d<<9) | (e<<12) | (f<<15) | (g<<18) | (h<<21) | (i<<24) | (j<<27)) << 1) | \ | ||
53 | (((uint64_t)(A<<0) | (B<<3) | (C<<6) | (D<<9) | (E<<12) | (F<<15) | (G<<18) | (H<<21) | (I<<24) | (J<<27)) << 31) | ||
54 | #define P(a,b,c,d,e,f,g,h,i,j,A,B,C,D,E,F,G,H,I,J) \ | ||
55 | R( (a/2),(b/2),(c/2),(d/2),(e/2),(f/2),(g/2),(h/2),(i/2),(j/2), \ | ||
56 | (A/2),(B/2),(C/2),(D/2),(E/2),(F/2),(G/2),(H/2),(I/2),(J/2) ) | ||
57 | static const uint64_t packed_wheel[] = { | ||
58 | /*1, 2, 2, 4, 2,*/ | ||
59 | P( 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4), //01 | ||
60 | P( 2, 4, 2, 4,14, 4, 6, 2,10, 2, 6, 6, 4, 2, 4, 6, 2,10, 2, 4), //02 | ||
61 | P( 2,12,10, 2, 4, 2, 4, 6, 2, 6, 4, 6, 6, 6, 2, 6, 4, 2, 6, 4), //03 | ||
62 | P( 6, 8, 4, 2, 4, 6, 8, 6,10, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2), //04 | ||
63 | P( 6, 4, 2, 6,10, 2,10, 2, 4, 2, 4, 6, 8, 4, 2, 4,12, 2, 6, 4), //05 | ||
64 | P( 2, 6, 4, 6,12, 2, 4, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6,10, 2), //06 | ||
65 | P( 4, 6, 2, 6, 4, 2, 4, 2,10, 2,10, 2, 4, 6, 6, 2, 6, 6, 4, 6), //07 | ||
66 | P( 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 6, 4, 8, 6, 4, 6, 2, 4, 6), //08 | ||
67 | P( 8, 6, 4, 2,10, 2, 6, 4, 2, 4, 2,10, 2,10, 2, 4, 2, 4, 8, 6), //09 | ||
68 | P( 4, 2, 4, 6, 6, 2, 6, 4, 8, 4, 6, 8, 4, 2, 4, 2, 4, 8, 6, 4), //10 | ||
69 | P( 6, 6, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4, 2,10, 2,10, 2), //11 | ||
70 | P( 6, 4, 6, 2, 6, 4, 2, 4, 6, 6, 8, 4, 2, 6,10, 8, 4, 2, 4, 2), //12 | ||
71 | P( 4, 8,10, 6, 2, 4, 8, 6, 6, 4, 2, 4, 6, 2, 6, 4, 6, 2,10, 2), //13 | ||
72 | P(10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 6, 6, 4, 6, 8), //14 | ||
73 | P( 4, 2, 4, 2, 4, 8, 6, 4, 8, 4, 6, 2, 6, 6, 4, 2, 4, 6, 8, 4), //15 | ||
74 | P( 2, 4, 2,10, 2,10, 2, 4, 2, 4, 6, 2,10, 2, 4, 6, 8, 6, 4, 2), //16 | ||
75 | P( 6, 4, 6, 8, 4, 6, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6, 4, 6), //17 | ||
76 | P( 6, 2, 6, 6, 4, 2,10, 2,10, 2, 4, 2, 4, 6, 2, 6, 4, 2,10, 6), //18 | ||
77 | P( 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2,12, 6, 4, 6, 2, 4, 6, 2), //19 | ||
78 | P(12, 4, 2, 4, 8, 6, 4, 2, 4, 2,10, 2,10, 6, 2, 4, 6, 2, 6, 4), //20 | ||
79 | P( 2, 4, 6, 6, 2, 6, 4, 2,10, 6, 8, 6, 4, 2, 4, 8, 6, 4, 6, 2), //21 | ||
80 | P( 4, 6, 2, 6, 6, 6, 4, 6, 2, 6, 4, 2, 4, 2,10,12, 2, 4, 2,10), //22 | ||
81 | P( 2, 6, 4, 2, 4, 6, 6, 2,10, 2, 6, 4,14, 4, 2, 4, 2, 4, 8, 6), //23 | ||
82 | P( 4, 6, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4,12, 2,12), //24 | ||
83 | }; | ||
84 | #undef P | ||
85 | #undef R | ||
86 | #define WHEEL_START 5 | ||
87 | #define WHEEL_SIZE (5 + 24 * 20) | ||
88 | #define square_count (((uint8_t*)&bb_common_bufsiz1)[0]) | ||
89 | #define wheel_tab (((uint8_t*)&bb_common_bufsiz1) + 1) | ||
90 | /* | ||
91 | * Why, you ask? | ||
92 | * plain byte array: | ||
93 | * function old new delta | ||
94 | * wheel_tab - 485 +485 | ||
95 | * 3-bit-packed insanity: | ||
96 | * packed_wheel - 192 +192 | ||
97 | * factor_main 108 171 +63 | ||
98 | */ | ||
99 | static void unpack_wheel(void) | ||
100 | { | ||
101 | int i; | ||
102 | uint8_t *p; | ||
103 | |||
104 | setup_common_bufsiz(); | ||
105 | wheel_tab[0] = 1; | ||
106 | wheel_tab[1] = 2; | ||
107 | wheel_tab[2] = 2; | ||
108 | wheel_tab[3] = 4; | ||
109 | wheel_tab[4] = 2; | ||
110 | p = &wheel_tab[5]; | ||
111 | for (i = 0; i < ARRAY_SIZE(packed_wheel); i++) { | ||
112 | uint64_t v = packed_wheel[i]; | ||
113 | while ((v & 0xe) != 0) { | ||
114 | *p = v & 0xe; | ||
115 | //printf("%2u,", *p); | ||
116 | p++; | ||
117 | v >>= 3; | ||
118 | } | ||
119 | //printf("\n"); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | /* Prevent inlining, factorize() needs all help it can get with reducing register pressure */ | ||
124 | static NOINLINE void print_w(wide_t n) | ||
125 | { | ||
126 | unsigned rep = square_count; | ||
127 | do | ||
128 | printf(" %"LL_FMT"u", n); | ||
129 | while (--rep != 0); | ||
130 | } | ||
131 | static NOINLINE void print_h(half_t n) | ||
132 | { | ||
133 | print_w(n); | ||
134 | } | ||
135 | |||
136 | static void factorize(wide_t N); | ||
137 | |||
45 | static half_t isqrt_odd(wide_t N) | 138 | static half_t isqrt_odd(wide_t N) |
46 | { | 139 | { |
47 | half_t s = isqrt(N); | 140 | half_t s = isqrt(N); |
141 | /* s^2 is <= N, (s+1)^2 > N */ | ||
142 | |||
143 | /* If s^2 in fact is EQUAL to N, it's very lucky. | ||
144 | * Examples: | ||
145 | * factor 18446743988964486098 = 2 * 3037000493 * 3037000493 | ||
146 | * factor 18446743902517389507 = 3 * 2479700513 * 2479700513 | ||
147 | */ | ||
148 | if ((wide_t)s * s == N) { | ||
149 | /* factorize sqrt(N), printing each factor twice */ | ||
150 | square_count *= 2; | ||
151 | factorize(s); | ||
152 | /* Let caller know we recursed */ | ||
153 | return 0; | ||
154 | } | ||
155 | |||
48 | /* Subtract 1 from even s, odd s won't change: */ | 156 | /* Subtract 1 from even s, odd s won't change: */ |
49 | /* (doesnt work for zero, but we know that s != 0 here) */ | 157 | /* (doesnt work for zero, but we know that s != 0 here) */ |
50 | s = (s - 1) | 1; | 158 | s = (s - 1) | 1; |
@@ -53,43 +161,20 @@ static half_t isqrt_odd(wide_t N) | |||
53 | 161 | ||
54 | static NOINLINE void factorize(wide_t N) | 162 | static NOINLINE void factorize(wide_t N) |
55 | { | 163 | { |
164 | unsigned w; | ||
56 | half_t factor; | 165 | half_t factor; |
57 | half_t max_factor; | 166 | half_t max_factor; |
58 | // unsigned count3; | ||
59 | // unsigned count5; | ||
60 | // unsigned count7; | ||
61 | // ^^^^^^^^^^^^^^^ commented-out simple sieving code (easier to grasp). | ||
62 | // Faster sieving, using one word for potentially up to 6 counters: | ||
63 | // count upwards in each mask, counter "triggers" when it sets its mask to "100[0]..." | ||
64 | // 10987654321098765432109876543210 - bits 31-0 in 32-bit word | ||
65 | // 17777713333311111777775555333 - bit masks for counters for primes 3,5,7,11,13,17 | ||
66 | // 100000100001000010001001 - value for adding 1 to each mask | ||
67 | // 10000010000010000100001000100 - value for checking that any mask reached msb | ||
68 | enum { | ||
69 | SHIFT_3 = 1 << 0, | ||
70 | SHIFT_5 = 1 << 3, | ||
71 | SHIFT_7 = 1 << 7, | ||
72 | INCREMENT_EACH = SHIFT_3 | SHIFT_5 | SHIFT_7, | ||
73 | MULTIPLE_OF_3 = 1 << 2, | ||
74 | MULTIPLE_OF_5 = 1 << 6, | ||
75 | MULTIPLE_OF_7 = 1 << 11, | ||
76 | MULTIPLE_DETECTED = MULTIPLE_OF_3 | MULTIPLE_OF_5 | MULTIPLE_OF_7, | ||
77 | }; | ||
78 | unsigned sieve_word; | ||
79 | 167 | ||
80 | if (N < 4) | 168 | if (N < 4) |
81 | goto end; | 169 | goto end; |
82 | 170 | ||
83 | while (!(N & 1)) { | ||
84 | printf(" 2"); | ||
85 | N >>= 1; | ||
86 | } | ||
87 | |||
88 | /* The code needs to be optimized for the case where | 171 | /* The code needs to be optimized for the case where |
89 | * there are large prime factors. For example, | 172 | * there are large prime factors. For example, |
90 | * this is not hard: | 173 | * this is not hard: |
91 | * 8262075252869367027 = 3 7 17 23 47 101 113 127 131 137 823 | 174 | * 8262075252869367027 = 3 7 17 23 47 101 113 127 131 137 823 |
92 | * (the largest factor to test is only ~sqrt(823) = 28) | 175 | * (the largest divisor to test for largest factor 823 |
176 | * is only ~sqrt(823) = 28, the entire factorization needs | ||
177 | * only ~33 trial divisions) | ||
93 | * but this is: | 178 | * but this is: |
94 | * 18446744073709551601 = 53 348051774975651917 | 179 | * 18446744073709551601 = 53 348051774975651917 |
95 | * the last factor requires testing up to | 180 | * the last factor requires testing up to |
@@ -98,70 +183,37 @@ static NOINLINE void factorize(wide_t N) | |||
98 | * factor 18446744073709551557 (0xffffffffffffffc5). | 183 | * factor 18446744073709551557 (0xffffffffffffffc5). |
99 | */ | 184 | */ |
100 | max_factor = isqrt_odd(N); | 185 | max_factor = isqrt_odd(N); |
101 | // count3 = 3; | 186 | if (!max_factor) |
102 | // count5 = 6; | 187 | return; /* square was detected and recursively factored */ |
103 | // count7 = 9; | 188 | factor = 2; |
104 | sieve_word = 0 | 189 | w = 0; |
105 | /* initial count for SHIFT_n is (n-1)/2*3: */ | ||
106 | + (MULTIPLE_OF_3 - 3 * SHIFT_3) | ||
107 | + (MULTIPLE_OF_5 - 6 * SHIFT_5) | ||
108 | + (MULTIPLE_OF_7 - 9 * SHIFT_7) | ||
109 | //+ (MULTIPLE_OF_11 - 15 * SHIFT_11) | ||
110 | //+ (MULTIPLE_OF_13 - 18 * SHIFT_13) | ||
111 | //+ (MULTIPLE_OF_17 - 24 * SHIFT_17) | ||
112 | ; | ||
113 | factor = 3; | ||
114 | for (;;) { | 190 | for (;;) { |
191 | half_t fw; | ||
192 | |||
115 | /* The division is the most costly part of the loop. | 193 | /* The division is the most costly part of the loop. |
116 | * On 64bit CPUs, takes at best 12 cycles, often ~20. | 194 | * On 64bit CPUs, takes at best 12 cycles, often ~20. |
117 | */ | 195 | */ |
118 | while ((N % factor) == 0) { /* not likely */ | 196 | while ((N % factor) == 0) { /* not likely */ |
119 | N = N / factor; | 197 | N = N / factor; |
120 | printf(" %"HALF_FMT"u", factor); | 198 | print_h(factor); |
121 | max_factor = isqrt_odd(N); | 199 | max_factor = isqrt_odd(N); |
200 | if (!max_factor) | ||
201 | return; /* square was detected */ | ||
122 | } | 202 | } |
123 | next_factor: | ||
124 | if (factor >= max_factor) | 203 | if (factor >= max_factor) |
125 | break; | 204 | break; |
126 | factor += 2; | 205 | fw = factor + wheel_tab[w]; |
127 | /* Rudimentary wheel sieving: skip multiples of 3, 5 and 7: | 206 | if (fw < factor) |
128 | * Every third odd number is divisible by three and thus isn't a prime: | 207 | break; /* overflow */ |
129 | * 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47... | 208 | factor = fw; |
130 | * ^ ^ ^ ^ ^ ^ ^ _ ^ ^ _ ^ ^ ^ ^ | 209 | w++; |
131 | * (^ = primes, _ = would-be-primes-if-not-divisible-by-5) | 210 | if (w < WHEEL_SIZE) |
132 | * The numbers with space under them are excluded by sieve 3. | ||
133 | */ | ||
134 | // count7--; | ||
135 | // count5--; | ||
136 | // count3--; | ||
137 | // if (count3 && count5 && count7) | ||
138 | // continue; | ||
139 | sieve_word += INCREMENT_EACH; | ||
140 | if (!(sieve_word & MULTIPLE_DETECTED)) | ||
141 | continue; | 211 | continue; |
142 | /* | 212 | w = WHEEL_START; |
143 | * "factor" is multiple of 3 33% of the time (count3 reached 0), | ||
144 | * else, multiple of 5 13% of the time, | ||
145 | * else, multiple of 7 7.6% of the time. | ||
146 | * Cumulatively, with 3,5,7 sieving we are here 54.3% of the time. | ||
147 | */ | ||
148 | // if (count3 == 0) | ||
149 | // count3 = 3; | ||
150 | if (sieve_word & MULTIPLE_OF_3) | ||
151 | sieve_word -= SHIFT_3 * 3; | ||
152 | // if (count5 == 0) | ||
153 | // count5 = 5; | ||
154 | if (sieve_word & MULTIPLE_OF_5) | ||
155 | sieve_word -= SHIFT_5 * 5; | ||
156 | // if (count7 == 0) | ||
157 | // count7 = 7; | ||
158 | if (sieve_word & MULTIPLE_OF_7) | ||
159 | sieve_word -= SHIFT_7 * 7; | ||
160 | goto next_factor; | ||
161 | } | 213 | } |
162 | end: | 214 | end: |
163 | if (N > 1) | 215 | if (N > 1) |
164 | printf(" %"LL_FMT"u", N); | 216 | print_w(N); |
165 | bb_putchar('\n'); | 217 | bb_putchar('\n'); |
166 | } | 218 | } |
167 | 219 | ||
@@ -176,12 +228,15 @@ static void factorize_numstr(const char *numstr) | |||
176 | if (errno) | 228 | if (errno) |
177 | bb_show_usage(); | 229 | bb_show_usage(); |
178 | printf("%"LL_FMT"u:", N); | 230 | printf("%"LL_FMT"u:", N); |
231 | square_count = 1; | ||
179 | factorize(N); | 232 | factorize(N); |
180 | } | 233 | } |
181 | 234 | ||
182 | int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 235 | int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
183 | int factor_main(int argc UNUSED_PARAM, char **argv) | 236 | int factor_main(int argc UNUSED_PARAM, char **argv) |
184 | { | 237 | { |
238 | unpack_wheel(); | ||
239 | |||
185 | //// coreutils has undocumented option ---debug (three dashes) | 240 | //// coreutils has undocumented option ---debug (three dashes) |
186 | //getopt32(argv, ""); | 241 | //getopt32(argv, ""); |
187 | //argv += optind; | 242 | //argv += optind; |
diff --git a/coreutils/id.c b/coreutils/id.c index f20cd7d09..78d5f2a50 100644 --- a/coreutils/id.c +++ b/coreutils/id.c | |||
@@ -33,7 +33,7 @@ | |||
33 | /* BB_AUDIT SUSv3 compliant. */ | 33 | /* BB_AUDIT SUSv3 compliant. */ |
34 | 34 | ||
35 | //usage:#define id_trivial_usage | 35 | //usage:#define id_trivial_usage |
36 | //usage: "[OPTIONS] [USER]" | 36 | //usage: "[-ugGnr"IF_SELINUX("Z")"] [USER]" |
37 | //usage:#define id_full_usage "\n\n" | 37 | //usage:#define id_full_usage "\n\n" |
38 | //usage: "Print information about USER or the current user\n" | 38 | //usage: "Print information about USER or the current user\n" |
39 | //usage: IF_SELINUX( | 39 | //usage: IF_SELINUX( |
diff --git a/coreutils/ln.c b/coreutils/ln.c index 5591e8335..2dcf79c07 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c | |||
@@ -21,14 +21,14 @@ | |||
21 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */ | 21 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */ |
22 | 22 | ||
23 | //usage:#define ln_trivial_usage | 23 | //usage:#define ln_trivial_usage |
24 | //usage: "[OPTIONS] TARGET... LINK|DIR" | 24 | //usage: "[-sfnbtv] [-S SUF] TARGET... LINK|DIR" |
25 | //usage:#define ln_full_usage "\n\n" | 25 | //usage:#define ln_full_usage "\n\n" |
26 | //usage: "Create a link LINK or DIR/TARGET to the specified TARGET(s)\n" | 26 | //usage: "Create a link LINK or DIR/TARGET to the specified TARGET(s)\n" |
27 | //usage: "\n -s Make symlinks instead of hardlinks" | 27 | //usage: "\n -s Make symlinks instead of hardlinks" |
28 | //usage: "\n -f Remove existing destinations" | 28 | //usage: "\n -f Remove existing destinations" |
29 | //usage: "\n -n Don't dereference symlinks - treat like normal file" | 29 | //usage: "\n -n Don't dereference symlinks - treat like normal file" |
30 | //usage: "\n -b Make a backup of the target (if exists) before link operation" | 30 | //usage: "\n -b Make a backup of the target (if exists) before link operation" |
31 | //usage: "\n -S suf Use suffix instead of ~ when making backup files" | 31 | //usage: "\n -S SUF Use suffix instead of ~ when making backup files" |
32 | //usage: "\n -T Treat LINK as a file, not DIR" | 32 | //usage: "\n -T Treat LINK as a file, not DIR" |
33 | //usage: "\n -v Verbose" | 33 | //usage: "\n -v Verbose" |
34 | //usage: | 34 | //usage: |
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index ba26c985a..4efa23061 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c | |||
@@ -117,8 +117,8 @@ | |||
117 | //usage: "\n -c Check sums against list in FILEs" | 117 | //usage: "\n -c Check sums against list in FILEs" |
118 | //usage: "\n -s Don't output anything, status code shows success" | 118 | //usage: "\n -s Don't output anything, status code shows success" |
119 | //usage: "\n -w Warn about improperly formatted checksum lines" | 119 | //usage: "\n -w Warn about improperly formatted checksum lines" |
120 | //usage: "\n -a BITS 224 (default), 256, 384, 512" | ||
121 | //usage: ) | 120 | //usage: ) |
121 | //usage: "\n -a BITS 224 (default), 256, 384, 512" | ||
122 | 122 | ||
123 | //FIXME: GNU coreutils 8.25 has no -s option, it has only these two long opts: | 123 | //FIXME: GNU coreutils 8.25 has no -s option, it has only these two long opts: |
124 | // --quiet don't print OK for each successfully verified file | 124 | // --quiet don't print OK for each successfully verified file |
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index 0ee1d1f72..d5e0f512b 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c | |||
@@ -27,7 +27,7 @@ | |||
27 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */ | 27 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/mkdir.html */ |
28 | 28 | ||
29 | //usage:#define mkdir_trivial_usage | 29 | //usage:#define mkdir_trivial_usage |
30 | //usage: "[OPTIONS] DIRECTORY..." | 30 | //usage: "[-m MODE] [-p] DIRECTORY..." |
31 | //usage:#define mkdir_full_usage "\n\n" | 31 | //usage:#define mkdir_full_usage "\n\n" |
32 | //usage: "Create DIRECTORY\n" | 32 | //usage: "Create DIRECTORY\n" |
33 | //usage: "\n -m MODE Mode" | 33 | //usage: "\n -m MODE Mode" |
diff --git a/coreutils/mknod.c b/coreutils/mknod.c index eee0ac71d..b10fe4fc3 100644 --- a/coreutils/mknod.c +++ b/coreutils/mknod.c | |||
@@ -36,7 +36,9 @@ | |||
36 | //usage: "$ mknod /dev/fd0 b 2 0\n" | 36 | //usage: "$ mknod /dev/fd0 b 2 0\n" |
37 | //usage: "$ mknod -m 644 /tmp/pipe p\n" | 37 | //usage: "$ mknod -m 644 /tmp/pipe p\n" |
38 | 38 | ||
39 | #include <sys/sysmacros.h> // For makedev | 39 | #ifdef __linux__ |
40 | # include <sys/sysmacros.h> // For makedev | ||
41 | #endif | ||
40 | 42 | ||
41 | #include "libbb.h" | 43 | #include "libbb.h" |
42 | #include "libcoreutils/coreutils.h" | 44 | #include "libcoreutils/coreutils.h" |
diff --git a/coreutils/nl.c b/coreutils/nl.c index aea019c56..800b73c26 100644 --- a/coreutils/nl.c +++ b/coreutils/nl.c | |||
@@ -19,7 +19,7 @@ | |||
19 | //usage:#define nl_full_usage "\n\n" | 19 | //usage:#define nl_full_usage "\n\n" |
20 | //usage: "Write FILEs to standard output with line numbers added\n" | 20 | //usage: "Write FILEs to standard output with line numbers added\n" |
21 | //usage: "\n -b STYLE Which lines to number - a: all, t: nonempty, n: none" | 21 | //usage: "\n -b STYLE Which lines to number - a: all, t: nonempty, n: none" |
22 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^TODO: support "pBRE": number only lines thatmatch regexp BRE" | 22 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^TODO: support "pBRE": number only lines that match regexp BRE" |
23 | ////usage: "\n -f STYLE footer lines" | 23 | ////usage: "\n -f STYLE footer lines" |
24 | ////usage: "\n -h STYLE header lines" | 24 | ////usage: "\n -h STYLE header lines" |
25 | ////usage: "\n -d CC use CC for separating logical pages" | 25 | ////usage: "\n -d CC use CC for separating logical pages" |
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index ea1ab9de8..76ee5137a 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c | |||
@@ -634,7 +634,7 @@ decode_one_format(const char *s_orig, const char *s, struct tspec *tspec) | |||
634 | bytes_to_unsigned_dec_digits, | 634 | bytes_to_unsigned_dec_digits, |
635 | bytes_to_hex_digits, | 635 | bytes_to_hex_digits, |
636 | }; | 636 | }; |
637 | static const char doux_fmtstring[][sizeof(" %%0%u%s")] = { | 637 | static const char doux_fmtstring[][sizeof(" %%0%u%s")] ALIGN1 = { |
638 | " %%%u%s", | 638 | " %%%u%s", |
639 | " %%0%u%s", | 639 | " %%0%u%s", |
640 | " %%%u%s", | 640 | " %%%u%s", |
@@ -1155,7 +1155,7 @@ dump_strings(off_t address, off_t end_offset) | |||
1155 | static int | 1155 | static int |
1156 | parse_old_offset(const char *s, off_t *offset) | 1156 | parse_old_offset(const char *s, off_t *offset) |
1157 | { | 1157 | { |
1158 | static const struct suffix_mult Bb[] = { | 1158 | static const struct suffix_mult Bb[] ALIGN_SUFFIX = { |
1159 | { "B", 1024 }, | 1159 | { "B", 1024 }, |
1160 | { "b", 512 }, | 1160 | { "b", 512 }, |
1161 | { "", 0 } | 1161 | { "", 0 } |
diff --git a/coreutils/paste.c b/coreutils/paste.c index 11743297a..fd2aa5027 100644 --- a/coreutils/paste.c +++ b/coreutils/paste.c | |||
@@ -18,7 +18,7 @@ | |||
18 | //kbuild:lib-$(CONFIG_PASTE) += paste.o | 18 | //kbuild:lib-$(CONFIG_PASTE) += paste.o |
19 | 19 | ||
20 | //usage:#define paste_trivial_usage | 20 | //usage:#define paste_trivial_usage |
21 | //usage: "[OPTIONS] [FILE]..." | 21 | //usage: "[-d LIST] [-s] [FILE]..." |
22 | //usage:#define paste_full_usage "\n\n" | 22 | //usage:#define paste_full_usage "\n\n" |
23 | //usage: "Paste lines from each input file, separated with tab\n" | 23 | //usage: "Paste lines from each input file, separated with tab\n" |
24 | //usage: "\n -d LIST Use delimiters from LIST, not tab" | 24 | //usage: "\n -d LIST Use delimiters from LIST, not tab" |
diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c index 5092a5dfc..addf41188 100644 --- a/coreutils/rmdir.c +++ b/coreutils/rmdir.c | |||
@@ -20,7 +20,7 @@ | |||
20 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */ | 20 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */ |
21 | 21 | ||
22 | //usage:#define rmdir_trivial_usage | 22 | //usage:#define rmdir_trivial_usage |
23 | //usage: "[OPTIONS] DIRECTORY..." | 23 | //usage: "[-p] DIRECTORY..." |
24 | //usage:#define rmdir_full_usage "\n\n" | 24 | //usage:#define rmdir_full_usage "\n\n" |
25 | //usage: "Remove DIRECTORY if it is empty\n" | 25 | //usage: "Remove DIRECTORY if it is empty\n" |
26 | //usage: "\n -p Include parents" | 26 | //usage: "\n -p Include parents" |
diff --git a/coreutils/sort.c b/coreutils/sort.c index 07c327645..b194847d1 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c | |||
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | //usage:#define sort_trivial_usage | 44 | //usage:#define sort_trivial_usage |
45 | //usage: "[-nru" | 45 | //usage: "[-nru" |
46 | //usage: IF_FEATURE_SORT_BIG("gMcszbdfiokt] [-o FILE] [-k start[.offset][opts][,end[.offset][opts]] [-t CHAR") | 46 | //usage: IF_FEATURE_SORT_BIG("gMcszbdfiokt] [-o FILE] [-k START[.OFS][OPTS][,END[.OFS][OPTS]] [-t CHAR") |
47 | //usage: "] [FILE]..." | 47 | //usage: "] [FILE]..." |
48 | //usage:#define sort_full_usage "\n\n" | 48 | //usage:#define sort_full_usage "\n\n" |
49 | //usage: "Sort lines of text\n" | 49 | //usage: "Sort lines of text\n" |
diff --git a/coreutils/split.c b/coreutils/split.c index ecbc9d2d8..3fcfd95f2 100644 --- a/coreutils/split.c +++ b/coreutils/split.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "common_bufsiz.h" | 44 | #include "common_bufsiz.h" |
45 | 45 | ||
46 | #if ENABLE_FEATURE_SPLIT_FANCY | 46 | #if ENABLE_FEATURE_SPLIT_FANCY |
47 | static const struct suffix_mult split_suffixes[] = { | 47 | static const struct suffix_mult split_suffixes[] ALIGN_SUFFIX = { |
48 | { "b", 512 }, | 48 | { "b", 512 }, |
49 | { "k", 1024 }, | 49 | { "k", 1024 }, |
50 | { "m", 1024*1024 }, | 50 | { "m", 1024*1024 }, |
diff --git a/coreutils/stat.c b/coreutils/stat.c index c332e5dc8..0a3f251f3 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c | |||
@@ -40,7 +40,7 @@ | |||
40 | //kbuild:lib-$(CONFIG_STAT) += stat.o | 40 | //kbuild:lib-$(CONFIG_STAT) += stat.o |
41 | 41 | ||
42 | //usage:#define stat_trivial_usage | 42 | //usage:#define stat_trivial_usage |
43 | //usage: "[OPTIONS] FILE..." | 43 | //usage: "[-lt"IF_FEATURE_STAT_FILESYSTEM("f")"] "IF_FEATURE_STAT_FORMAT("[-c FMT] ")"FILE..." |
44 | //usage:#define stat_full_usage "\n\n" | 44 | //usage:#define stat_full_usage "\n\n" |
45 | //usage: "Display file" | 45 | //usage: "Display file" |
46 | //usage: IF_FEATURE_STAT_FILESYSTEM(" (default) or filesystem") | 46 | //usage: IF_FEATURE_STAT_FILESYSTEM(" (default) or filesystem") |
@@ -209,7 +209,7 @@ FS_TYPE(0x62656572, "sysfs") | |||
209 | static const char *human_fstype(uint32_t f_type) | 209 | static const char *human_fstype(uint32_t f_type) |
210 | { | 210 | { |
211 | # define FS_TYPE(type, name) type, | 211 | # define FS_TYPE(type, name) type, |
212 | static const uint32_t fstype[] = { | 212 | static const uint32_t fstype[] ALIGN4 = { |
213 | FS_TYPE_LIST | 213 | FS_TYPE_LIST |
214 | }; | 214 | }; |
215 | # undef FS_TYPE | 215 | # undef FS_TYPE |
diff --git a/coreutils/stty.c b/coreutils/stty.c index 40e812799..19253964c 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c | |||
@@ -487,7 +487,7 @@ static const char mode_name[] ALIGN1 = | |||
487 | #undef MI_ENTRY | 487 | #undef MI_ENTRY |
488 | #define MI_ENTRY(N,T,F,B,M) { T, F, M, B }, | 488 | #define MI_ENTRY(N,T,F,B,M) { T, F, M, B }, |
489 | 489 | ||
490 | static const struct mode_info mode_info[] = { | 490 | static const struct mode_info mode_info[] ALIGN4 = { |
491 | /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */ | 491 | /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */ |
492 | MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) | 492 | MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) |
493 | MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) | 493 | MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) |
@@ -905,7 +905,7 @@ static void display_window_size(int fancy) | |||
905 | } | 905 | } |
906 | } | 906 | } |
907 | 907 | ||
908 | static const struct suffix_mult stty_suffixes[] = { | 908 | static const struct suffix_mult stty_suffixes[] ALIGN_SUFFIX = { |
909 | { "b", 512 }, | 909 | { "b", 512 }, |
910 | { "k", 1024 }, | 910 | { "k", 1024 }, |
911 | { "B", 1024 }, | 911 | { "B", 1024 }, |
diff --git a/coreutils/test.c b/coreutils/test.c index ac7b546a3..7c6574334 100644 --- a/coreutils/test.c +++ b/coreutils/test.c | |||
@@ -306,7 +306,7 @@ struct operator_t { | |||
306 | unsigned char op_num, op_type; | 306 | unsigned char op_num, op_type; |
307 | }; | 307 | }; |
308 | 308 | ||
309 | static const struct operator_t ops_table[] = { | 309 | static const struct operator_t ops_table[] ALIGN2 = { |
310 | { /* "-r" */ FILRD , UNOP }, | 310 | { /* "-r" */ FILRD , UNOP }, |
311 | { /* "-w" */ FILWR , UNOP }, | 311 | { /* "-w" */ FILWR , UNOP }, |
312 | { /* "-x" */ FILEX , UNOP }, | 312 | { /* "-x" */ FILEX , UNOP }, |
diff --git a/coreutils/timeout.c b/coreutils/timeout.c index 06c134a37..204a7ab92 100644 --- a/coreutils/timeout.c +++ b/coreutils/timeout.c | |||
@@ -41,7 +41,7 @@ | |||
41 | //usage:#define timeout_trivial_usage | 41 | //usage:#define timeout_trivial_usage |
42 | //usage: "[-s SIG] SECS PROG ARGS" | 42 | //usage: "[-s SIG] SECS PROG ARGS" |
43 | //usage:#define timeout_full_usage "\n\n" | 43 | //usage:#define timeout_full_usage "\n\n" |
44 | //usage: "Runs PROG. Sends SIG to it if it is not gone in SECS seconds.\n" | 44 | //usage: "Run PROG. Send SIG to it if it is not gone in SECS seconds.\n" |
45 | //usage: "Default SIG: TERM." | 45 | //usage: "Default SIG: TERM." |
46 | 46 | ||
47 | #include "libbb.h" | 47 | #include "libbb.h" |
@@ -130,7 +130,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |||
130 | grandchild: | 130 | grandchild: |
131 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ | 131 | /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ |
132 | while (1) { | 132 | while (1) { |
133 | sleep(1); | 133 | sleep1(); |
134 | if (--timeout <= 0) | 134 | if (--timeout <= 0) |
135 | break; | 135 | break; |
136 | if (kill(parent, 0)) { | 136 | if (kill(parent, 0)) { |
diff --git a/coreutils/uniq.c b/coreutils/uniq.c index 317f45531..e1594286f 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c | |||
@@ -20,7 +20,7 @@ | |||
20 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */ | 20 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/uniq.html */ |
21 | 21 | ||
22 | //usage:#define uniq_trivial_usage | 22 | //usage:#define uniq_trivial_usage |
23 | //usage: "[-cdu][-f,s,w N] [INPUT [OUTPUT]]" | 23 | //usage: "[-cdui] [-f,s,w N] [INPUT [OUTPUT]]" |
24 | //usage:#define uniq_full_usage "\n\n" | 24 | //usage:#define uniq_full_usage "\n\n" |
25 | //usage: "Discard duplicate lines\n" | 25 | //usage: "Discard duplicate lines\n" |
26 | //usage: "\n -c Prefix lines by the number of occurrences" | 26 | //usage: "\n -c Prefix lines by the number of occurrences" |
diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 5b2edd649..164b208ea 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c | |||
@@ -168,9 +168,11 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) | |||
168 | } | 168 | } |
169 | #endif | 169 | #endif |
170 | 170 | ||
171 | //applet:IF_BASE64(APPLET(base64, BB_DIR_BIN, BB_SUID_DROP)) | 171 | //config:config BASE32 |
172 | 172 | //config: bool "base32 (4.9 kb)" | |
173 | //kbuild:lib-$(CONFIG_BASE64) += uudecode.o | 173 | //config: default y |
174 | //config: help | ||
175 | //config: Base32 encode and decode | ||
174 | 176 | ||
175 | //config:config BASE64 | 177 | //config:config BASE64 |
176 | //config: bool "base64 (4.9 kb)" | 178 | //config: bool "base64 (4.9 kb)" |
@@ -178,49 +180,165 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) | |||
178 | //config: help | 180 | //config: help |
179 | //config: Base64 encode and decode | 181 | //config: Base64 encode and decode |
180 | 182 | ||
183 | //usage:#define base32_trivial_usage | ||
184 | //usage: "[-d] [-w COL] [FILE]" | ||
185 | //usage:#define base32_full_usage "\n\n" | ||
186 | //usage: "Base32 encode or decode FILE to standard output" | ||
187 | //usage: "\n -d Decode data" | ||
188 | //usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" | ||
189 | ////usage: "\n -i When decoding, ignore non-alphabet characters" | ||
190 | |||
181 | //usage:#define base64_trivial_usage | 191 | //usage:#define base64_trivial_usage |
182 | //usage: "[-d] [FILE]" | 192 | //usage: "[-d] [-w COL] [FILE]" |
183 | //usage:#define base64_full_usage "\n\n" | 193 | //usage:#define base64_full_usage "\n\n" |
184 | //usage: "Base64 encode or decode FILE to standard output" | 194 | //usage: "Base64 encode or decode FILE to standard output" |
185 | //usage: "\n -d Decode data" | 195 | //usage: "\n -d Decode data" |
186 | ////usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" | 196 | //usage: "\n -w COL Wrap lines at COL (default 76, 0 disables)" |
187 | ////usage: "\n -i When decoding, ignore non-alphabet characters" | 197 | ////usage: "\n -i When decoding, ignore non-alphabet characters" |
188 | 198 | ||
189 | #if ENABLE_BASE64 | 199 | // APPLET_ODDNAME:name main location suid_type help |
190 | int base64_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 200 | //applet:IF_BASE32(APPLET_ODDNAME(base32, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base32)) |
191 | int base64_main(int argc UNUSED_PARAM, char **argv) | 201 | //applet:IF_BASE64(APPLET_ODDNAME(base64, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base64)) |
202 | |||
203 | //kbuild:lib-$(CONFIG_BASE64) += uudecode.o | ||
204 | //kbuild:lib-$(CONFIG_BASE32) += uudecode.o | ||
205 | |||
206 | #if ENABLE_BASE32 || ENABLE_BASE64 | ||
207 | |||
208 | # if ENABLE_BASE32 | ||
209 | static void bb_b32encode(char *p, const void *src, int length) | ||
210 | { | ||
211 | #define tbl bb_uuenc_tbl_base32 | ||
212 | const unsigned char *s = src; | ||
213 | |||
214 | /* Transform 5x8 bits to 8x5 bits */ | ||
215 | while (length > 0) { | ||
216 | unsigned cur, next; | ||
217 | |||
218 | length--; | ||
219 | cur = *s++; | ||
220 | *p++ = tbl[cur >> 3]; // xxxxx--- -------- -------- -------- -------- | ||
221 | cur &= 7; | ||
222 | |||
223 | next = 0; | ||
224 | if (--length >= 0) | ||
225 | next = *s++; | ||
226 | *p++ = tbl[(cur << 2) + (next >> 6)]; // -----xxx xx------ -------- -------- -------- | ||
227 | cur = next & 0x3f; | ||
228 | |||
229 | *p++ = tbl[cur >> 1]; // -------- --xxxxx- -------- -------- -------- | ||
230 | cur &= 1; | ||
231 | |||
232 | next = 0; | ||
233 | if (--length >= 0) | ||
234 | next = *s++; | ||
235 | *p++ = tbl[(cur << 4) + (next >> 4)]; // -------- -------x xxxx---- -------- -------- | ||
236 | cur = next & 0xf; | ||
237 | |||
238 | next = 0; | ||
239 | if (--length >= 0) | ||
240 | next = *s++; | ||
241 | *p++ = tbl[(cur << 1) + (next >> 7)]; // -------- -------- ----xxxx x------- -------- | ||
242 | cur = next & 0x7f; | ||
243 | |||
244 | *p++ = tbl[cur >> 2]; // -------- -------- -------- -xxxxx-- -------- | ||
245 | cur &= 3; | ||
246 | |||
247 | next = 0; | ||
248 | if (--length >= 0) | ||
249 | next = *s++; | ||
250 | *p++ = tbl[(cur << 3) + (next >> 5)]; // -------- -------- -------- ------xx xxx----- | ||
251 | cur = next & 0x1f; | ||
252 | |||
253 | *p++ = tbl[cur]; // -------- -------- -------- -------- ---xxxxx | ||
254 | } | ||
255 | #undef tbl | ||
256 | /* Zero-terminate */ | ||
257 | *p = '\0'; | ||
258 | /* Pad as necessary */ | ||
259 | length = ((-length) * 3) >> 1; /* -4 => 6 pad chars, -3 => 4, -2 => 3, -1 => 1 */ | ||
260 | while (length--) { | ||
261 | *--p = '='; | ||
262 | } | ||
263 | } | ||
264 | # else | ||
265 | void bb_b32encode(char *p, const void *src, int length); /* undefined */ | ||
266 | # endif | ||
267 | |||
268 | int baseNUM_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
269 | int baseNUM_main(int argc UNUSED_PARAM, char **argv) | ||
192 | { | 270 | { |
193 | FILE *src_stream; | 271 | FILE *src_stream; |
194 | unsigned opts; | 272 | unsigned opts; |
273 | unsigned col = 76; | ||
195 | 274 | ||
196 | opts = getopt32(argv, "^" "d" "\0" "?1"/* 1 arg max*/); | 275 | opts = getopt32(argv, "^" "dw:+" "\0" "?1"/* 1 arg max*/, &col); |
197 | argv += optind; | 276 | argv += optind; |
198 | 277 | ||
199 | if (!argv[0]) | 278 | if (!argv[0]) |
200 | *--argv = (char*)"-"; | 279 | *--argv = (char*)"-"; |
201 | src_stream = xfopen_stdin(argv[0]); | 280 | src_stream = xfopen_stdin(argv[0]); |
202 | if (opts) { | 281 | if (opts & 1) { |
203 | read_base64(src_stream, stdout, /*flags:*/ (unsigned char)EOF); | 282 | /* -d: decode */ |
283 | int flags = (unsigned char)EOF; | ||
284 | if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) | ||
285 | flags = ((unsigned char)EOF) | BASE64_32; | ||
286 | read_base64(src_stream, stdout, flags); | ||
204 | } else { | 287 | } else { |
205 | enum { | 288 | enum { |
206 | SRC_BUF_SIZE = 76 / 4 * 3, /* this *MUST* be a multiple of 3 */ | 289 | SRC_BUF_SIZE = 3 * 5 * 32, /* this *MUST* be a multiple of 3 and 5 */ |
207 | DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), | 290 | DST_BUF_SIZE = 8 * ((SRC_BUF_SIZE + 4) / 5), /* max growth on encode (base32 case) */ |
208 | }; | 291 | }; |
209 | char src_buf[SRC_BUF_SIZE]; | 292 | /* Use one buffer for both input and output: |
210 | char dst_buf[DST_BUF_SIZE + 1]; | 293 | * encoding reads input "left-to-right", |
211 | int src_fd = fileno(src_stream); | 294 | * it's safe to place source at the end of the buffer and |
295 | * overwrite it while encoding, just be careful to have a gap. | ||
296 | */ | ||
297 | char dst_buf[((DST_BUF_SIZE + /*gap:*/ 16) /*round up to 16:*/ | 0xf) + 1]; | ||
298 | #define src_buf (dst_buf + sizeof(dst_buf) - SRC_BUF_SIZE) | ||
299 | int src_fd, rem; | ||
300 | |||
301 | src_fd = fileno(src_stream); | ||
302 | rem = 0; | ||
212 | while (1) { | 303 | while (1) { |
213 | size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE); | 304 | size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE); |
214 | if (!size) | ||
215 | break; | ||
216 | if ((ssize_t)size < 0) | 305 | if ((ssize_t)size < 0) |
217 | bb_simple_perror_msg_and_die(bb_msg_read_error); | 306 | bb_simple_perror_msg_and_die(bb_msg_read_error); |
307 | if (size == 0) { | ||
308 | if (rem != 0) bb_putchar('\n'); | ||
309 | break; | ||
310 | } | ||
311 | |||
218 | /* Encode the buffer we just read in */ | 312 | /* Encode the buffer we just read in */ |
219 | bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); | 313 | if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) { |
220 | xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3)); | 314 | bb_b32encode(dst_buf, src_buf, size); |
221 | bb_putchar('\n'); | 315 | size = 8 * ((size + 4) / 5); |
222 | fflush(stdout); | 316 | } else { |
317 | bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); | ||
318 | size = 4 * ((size + 2) / 3); | ||
319 | } | ||
320 | |||
321 | if (col == 0) { | ||
322 | fputs(dst_buf, stdout); | ||
323 | } else { | ||
324 | char *result = dst_buf; | ||
325 | if (rem == 0) | ||
326 | rem = col; | ||
327 | while (1) { | ||
328 | int out = size < rem ? size : rem; | ||
329 | rem -= out; | ||
330 | printf(rem != 0 ? "%.*s" : "%.*s\n", out, result); | ||
331 | if (rem != 0) | ||
332 | break; | ||
333 | size -= out; | ||
334 | if (size == 0) | ||
335 | break; | ||
336 | result += out; | ||
337 | rem = col; | ||
338 | } | ||
339 | } | ||
223 | } | 340 | } |
341 | #undef src_buf | ||
224 | } | 342 | } |
225 | 343 | ||
226 | fflush_stdout_and_exit(EXIT_SUCCESS); | 344 | fflush_stdout_and_exit(EXIT_SUCCESS); |