aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/cp.c2
-rw-r--r--coreutils/date.c102
-rw-r--r--coreutils/dd.c116
-rw-r--r--coreutils/factor.c209
-rw-r--r--coreutils/id.c2
-rw-r--r--coreutils/ln.c4
-rw-r--r--coreutils/md5_sha1_sum.c2
-rw-r--r--coreutils/mkdir.c2
-rw-r--r--coreutils/mknod.c4
-rw-r--r--coreutils/nl.c2
-rw-r--r--coreutils/od_bloaty.c4
-rw-r--r--coreutils/paste.c2
-rw-r--r--coreutils/rmdir.c2
-rw-r--r--coreutils/sort.c2
-rw-r--r--coreutils/split.c2
-rw-r--r--coreutils/stat.c4
-rw-r--r--coreutils/stty.c4
-rw-r--r--coreutils/test.c2
-rw-r--r--coreutils/timeout.c4
-rw-r--r--coreutils/uniq.c2
-rw-r--r--coreutils/uudecode.c162
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
188static void maybe_set_utc(int opt)
189{
190 if (opt & OPT_UTC)
191 putenv((char*)"TZ=UTC0");
192}
193
194int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 175int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
195int date_main(int argc UNUSED_PARAM, char **argv) 176int 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
155static void dd_output_status(int UNUSED_PARAM cur_signal) 159static 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
203static 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
216static 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
198static bool write_and_stats(const void *buf, size_t len, size_t obs, 234static 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
302static 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
260int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 312int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
261int dd_main(int argc UNUSED_PARAM, char **argv) 313int 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) )
57static 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 */
99static 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 */
124static 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}
131static NOINLINE void print_h(half_t n)
132{
133 print_w(n);
134}
135
136static void factorize(wide_t N);
137
45static half_t isqrt_odd(wide_t N) 138static 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
54static NOINLINE void factorize(wide_t N) 162static 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
182int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 235int factor_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
183int factor_main(int argc UNUSED_PARAM, char **argv) 236int 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)
1155static int 1155static int
1156parse_old_offset(const char *s, off_t *offset) 1156parse_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
47static const struct suffix_mult split_suffixes[] = { 47static 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")
209static const char *human_fstype(uint32_t f_type) 209static 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
490static const struct mode_info mode_info[] = { 490static 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
908static const struct suffix_mult stty_suffixes[] = { 908static 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
309static const struct operator_t ops_table[] = { 309static 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
190int base64_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 200//applet:IF_BASE32(APPLET_ODDNAME(base32, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base32))
191int 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
209static 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
265void bb_b32encode(char *p, const void *src, int length); /* undefined */
266# endif
267
268int baseNUM_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
269int 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);