aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/dd.c78
-rw-r--r--coreutils/df.c33
-rw-r--r--coreutils/du.c2
-rw-r--r--coreutils/expr.c6
-rw-r--r--coreutils/factor.c4
-rw-r--r--coreutils/id.c20
-rw-r--r--coreutils/ls.c85
-rw-r--r--coreutils/nproc.c17
-rw-r--r--coreutils/od_bloaty.c7
-rw-r--r--coreutils/printf.c68
-rw-r--r--coreutils/shred.c10
-rw-r--r--coreutils/shuf.c2
-rw-r--r--coreutils/sort.c5
-rw-r--r--coreutils/split.c8
-rw-r--r--coreutils/stat.c5
-rw-r--r--coreutils/stty.c148
-rw-r--r--coreutils/sum.c4
-rw-r--r--coreutils/test.c4
-rw-r--r--coreutils/timeout.c73
-rw-r--r--coreutils/truncate.c6
20 files changed, 553 insertions, 32 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 8bb782781..e6b88acf5 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -59,8 +59,13 @@
59//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]" 59//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]"
60//usage: IF_FEATURE_DD_IBS_OBS("\n" 60//usage: IF_FEATURE_DD_IBS_OBS("\n"
61//usage: " [conv=notrunc|noerror|sync|fsync]\n" 61//usage: " [conv=notrunc|noerror|sync|fsync]\n"
62//usage: IF_NOT_PLATFORM_MINGW32(
62//usage: " [iflag=skip_bytes|count_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]" 63//usage: " [iflag=skip_bytes|count_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]"
63//usage: ) 64//usage: )
65//usage: IF_PLATFORM_MINGW32(
66//usage: " [iflag=skip_bytes|count_bytes|fullblock] [oflag=seek_bytes|append]"
67//usage: )
68//usage: )
64//usage:#define dd_full_usage "\n\n" 69//usage:#define dd_full_usage "\n\n"
65//usage: "Copy a file with converting and formatting\n" 70//usage: "Copy a file with converting and formatting\n"
66//usage: "\n if=FILE Read from FILE instead of stdin" 71//usage: "\n if=FILE Read from FILE instead of stdin"
@@ -84,8 +89,10 @@
84//usage: "\n iflag=skip_bytes skip=N is in bytes" 89//usage: "\n iflag=skip_bytes skip=N is in bytes"
85//usage: "\n iflag=count_bytes count=N is in bytes" 90//usage: "\n iflag=count_bytes count=N is in bytes"
86//usage: "\n oflag=seek_bytes seek=N is in bytes" 91//usage: "\n oflag=seek_bytes seek=N is in bytes"
92//usage: IF_NOT_PLATFORM_MINGW32(
87//usage: "\n iflag=direct O_DIRECT input" 93//usage: "\n iflag=direct O_DIRECT input"
88//usage: "\n oflag=direct O_DIRECT output" 94//usage: "\n oflag=direct O_DIRECT output"
95//usage: )
89//usage: "\n iflag=fullblock Read full blocks" 96//usage: "\n iflag=fullblock Read full blocks"
90//usage: "\n oflag=append Open output in append mode" 97//usage: "\n oflag=append Open output in append mode"
91//usage: ) 98//usage: )
@@ -94,6 +101,9 @@
94//usage: "\n status=none Suppress all output" 101//usage: "\n status=none Suppress all output"
95//usage: ) 102//usage: )
96//usage: "\n" 103//usage: "\n"
104//usage: IF_PLATFORM_MINGW32(
105//usage: "\nif=/dev/zero and if=/dev/urandom are supported"
106//usage: )
97//usage: "\nN may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G" 107//usage: "\nN may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G"
98//usage: 108//usage:
99//usage:#define dd_example_usage 109//usage:#define dd_example_usage
@@ -104,6 +114,10 @@
104#include "libbb.h" 114#include "libbb.h"
105#include "common_bufsiz.h" 115#include "common_bufsiz.h"
106 116
117#if ENABLE_PLATFORM_MINGW32
118# undef O_DIRECT
119#endif
120
107/* This is a NOEXEC applet. Be very careful! */ 121/* This is a NOEXEC applet. Be very careful! */
108 122
109 123
@@ -141,13 +155,13 @@ enum {
141 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, 155 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
142 FLAG_COUNT_BYTES = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, 156 FLAG_COUNT_BYTES = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
143 FLAG_FULLBLOCK = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, 157 FLAG_FULLBLOCK = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
144 FLAG_IDIRECT = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, 158 FLAG_IDIRECT = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS * ENABLE_PLATFORM_POSIX,
145 /* end of input flags */ 159 /* end of input flags */
146 /* start of output flags */ 160 /* start of output flags */
147 FLAG_OFLAG_SHIFT = 9, 161 FLAG_OFLAG_SHIFT = 9,
148 FLAG_SEEK_BYTES = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, 162 FLAG_SEEK_BYTES = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS,
149 FLAG_APPEND = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS, 163 FLAG_APPEND = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS,
150 FLAG_ODIRECT = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS, 164 FLAG_ODIRECT = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS * ENABLE_PLATFORM_POSIX,
151 /* end of output flags */ 165 /* end of output flags */
152 FLAG_TWOBUFS = (1 << 12) * ENABLE_FEATURE_DD_IBS_OBS, 166 FLAG_TWOBUFS = (1 << 12) * ENABLE_FEATURE_DD_IBS_OBS,
153 FLAG_COUNT = 1 << 13, 167 FLAG_COUNT = 1 << 13,
@@ -220,7 +234,9 @@ static ssize_t dd_read(void *ibuf, size_t ibs)
220 ssize_t n; 234 ssize_t n;
221 235
222#if ENABLE_FEATURE_DD_IBS_OBS 236#if ENABLE_FEATURE_DD_IBS_OBS
237# if !ENABLE_PLATFORM_MINGW32
223 read_again: 238 read_again:
239# endif
224 if (G.flags & FLAG_FULLBLOCK) 240 if (G.flags & FLAG_FULLBLOCK)
225 n = full_read(ifd, ibuf, ibs); 241 n = full_read(ifd, ibuf, ibs);
226 else 242 else
@@ -240,7 +256,9 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs,
240{ 256{
241 ssize_t n; 257 ssize_t n;
242 258
259#if !ENABLE_PLATFORM_MINGW32
243 IF_FEATURE_DD_IBS_OBS(write_again:) 260 IF_FEATURE_DD_IBS_OBS(write_again:)
261#endif
244 n = full_write(ofd, buf, len); 262 n = full_write(ofd, buf, len);
245#if ENABLE_FEATURE_DD_IBS_OBS 263#if ENABLE_FEATURE_DD_IBS_OBS
246# ifdef O_DIRECT 264# ifdef O_DIRECT
@@ -307,12 +325,25 @@ static int parse_comma_flags(char *val, const char *words, const char *error_in)
307 325
308static void *alloc_buf(size_t size) 326static void *alloc_buf(size_t size)
309{ 327{
328#if !ENABLE_PLATFORM_MINGW32
310 /* Important for "{i,o}flag=direct" - buffers must be page aligned */ 329 /* Important for "{i,o}flag=direct" - buffers must be page aligned */
311 if (size >= bb_getpagesize()) 330 if (size >= bb_getpagesize())
312 return xmmap_anon(size); 331 return xmmap_anon(size);
332#endif
313 return xmalloc(size); 333 return xmalloc(size);
314} 334}
315 335
336#if ENABLE_PLATFORM_MINGW32
337// Does 'path' refer to a physical drive in the win32 device namespace?
338static int is_drive_path(const char *path)
339{
340 char *s = auto_string(strdup(path));
341
342 bs_to_slash(s);
343 return strncasecmp(s, "//./PhysicalDrive", 17) == 0;
344}
345#endif
346
316int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 347int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
317int dd_main(int argc UNUSED_PARAM, char **argv) 348int dd_main(int argc UNUSED_PARAM, char **argv)
318{ 349{
@@ -326,9 +357,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
326 static const char conv_words[] ALIGN1 = 357 static const char conv_words[] ALIGN1 =
327 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; 358 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
328 static const char iflag_words[] ALIGN1 = 359 static const char iflag_words[] ALIGN1 =
329 "skip_bytes\0""count_bytes\0""fullblock\0""direct\0"; 360 "skip_bytes\0""count_bytes\0""fullblock\0"IF_PLATFORM_POSIX("direct\0");
330 static const char oflag_words[] ALIGN1 = 361 static const char oflag_words[] ALIGN1 =
331 "seek_bytes\0append\0""direct\0"; 362 "seek_bytes\0append\0"IF_PLATFORM_POSIX("direct\0");
332#endif 363#endif
333#if ENABLE_FEATURE_DD_STATUS 364#if ENABLE_FEATURE_DD_STATUS
334 static const char status_words[] ALIGN1 = 365 static const char status_words[] ALIGN1 =
@@ -429,11 +460,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
429#if ENABLE_FEATURE_DD_IBS_OBS 460#if ENABLE_FEATURE_DD_IBS_OBS
430 if (what == OP_ibs) { 461 if (what == OP_ibs) {
431 /* Must fit into positive ssize_t */ 462 /* Must fit into positive ssize_t */
432 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 463 ibs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes);
433 /*continue;*/ 464 /*continue;*/
434 } 465 }
435 if (what == OP_obs) { 466 if (what == OP_obs) {
436 obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 467 obs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes);
437 /*continue;*/ 468 /*continue;*/
438 } 469 }
439 if (what == OP_conv) { 470 if (what == OP_conv) {
@@ -450,7 +481,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
450 } 481 }
451#endif 482#endif
452 if (what == OP_bs) { 483 if (what == OP_bs) {
453 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 484 ibs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes);
454 obs = ibs; 485 obs = ibs;
455 /*continue;*/ 486 /*continue;*/
456 } 487 }
@@ -515,7 +546,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
515# endif 546# endif
516 } 547 }
517#endif 548#endif
518 xmove_fd(xopen(infile, iflag), ifd); 549 xmove_fd(MINGW_SPECIAL(xopen)(infile, iflag), ifd);
550#if ENABLE_PLATFORM_MINGW32
551 update_special_fd(get_dev_type(infile), ifd);
552#endif
519 } else { 553 } else {
520 infile = bb_msg_standard_input; 554 infile = bb_msg_standard_input;
521 } 555 }
@@ -535,8 +569,35 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
535# endif 569# endif
536 } 570 }
537#endif 571#endif
572#if ENABLE_PLATFORM_MINGW32
573 if (is_drive_path(outfile)) {
574 // Turn off options not supported by Windows device files.
575 oflag &= ~(O_CREAT | O_TRUNC);
576 }
577#endif
538 xmove_fd(xopen(outfile, oflag), ofd); 578 xmove_fd(xopen(outfile, oflag), ofd);
539 579
580#if ENABLE_PLATFORM_MINGW32
581 {
582 off_t len = (off_t)seek * ((G.flags & FLAG_SEEK_BYTES) ? 1 : obs);
583 struct stat st;
584 int ret = fstat(ofd, &st);
585
586 if (ret == 0 && !(G.flags & FLAG_APPEND) && len > st.st_size)
587 make_sparse(ofd, st.st_size, len);
588
589 if (seek && !(G.flags & FLAG_NOTRUNC)) {
590 if (ftruncate(ofd, len) < 0) {
591 if (ret < 0
592 || S_ISREG(st.st_mode)
593 || S_ISDIR(st.st_mode)
594 ) {
595 goto die_outfile;
596 }
597 }
598 }
599 }
600#else
540 if (seek && !(G.flags & FLAG_NOTRUNC)) { 601 if (seek && !(G.flags & FLAG_NOTRUNC)) {
541 size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs; 602 size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs;
542 if (ftruncate(ofd, seek * blocksz) < 0) { 603 if (ftruncate(ofd, seek * blocksz) < 0) {
@@ -550,6 +611,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
550 } 611 }
551 } 612 }
552 } 613 }
614#endif
553 } else { 615 } else {
554 outfile = bb_msg_standard_output; 616 outfile = bb_msg_standard_output;
555 } 617 }
diff --git a/coreutils/df.c b/coreutils/df.c
index 03aa78148..01c41db38 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -64,7 +64,9 @@
64//usage: "[-Pk" 64//usage: "[-Pk"
65//usage: IF_FEATURE_HUMAN_READABLE("mh") 65//usage: IF_FEATURE_HUMAN_READABLE("mh")
66//usage: "T" 66//usage: "T"
67//usage: IF_FEATURE_DF_FANCY("ai] [-B SIZE") 67//usage: IF_FEATURE_DF_FANCY("a"
68//usage: IF_PLATFORM_POSIX("i")
69//usage: "] [-B SIZE")
68//usage: "] [-t TYPE] [FILESYSTEM]..." 70//usage: "] [-t TYPE] [FILESYSTEM]..."
69//usage:#define df_full_usage "\n\n" 71//usage:#define df_full_usage "\n\n"
70//usage: "Print filesystem usage statistics\n" 72//usage: "Print filesystem usage statistics\n"
@@ -78,7 +80,9 @@
78//usage: "\n -t TYPE Print only mounts of this type" 80//usage: "\n -t TYPE Print only mounts of this type"
79//usage: IF_FEATURE_DF_FANCY( 81//usage: IF_FEATURE_DF_FANCY(
80//usage: "\n -a Show all filesystems" 82//usage: "\n -a Show all filesystems"
83//usage: IF_PLATFORM_POSIX(
81//usage: "\n -i Inodes" 84//usage: "\n -i Inodes"
85//usage: )
82//usage: "\n -B SIZE Blocksize" 86//usage: "\n -B SIZE Blocksize"
83//usage: ) 87//usage: )
84//usage: 88//usage:
@@ -109,6 +113,12 @@ static unsigned long kscale(unsigned long b, unsigned long bs)
109} 113}
110#endif 114#endif
111 115
116#if ENABLE_PLATFORM_MINGW32
117# define ENABLE_FEATURE_DF_FANCY_POSIX 0
118#else
119# define ENABLE_FEATURE_DF_FANCY_POSIX ENABLE_FEATURE_DF_FANCY
120#endif
121
112int df_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 122int df_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
113int df_main(int argc UNUSED_PARAM, char **argv) 123int df_main(int argc UNUSED_PARAM, char **argv)
114{ 124{
@@ -124,11 +134,11 @@ int df_main(int argc UNUSED_PARAM, char **argv)
124 OPT_FSTYPE = (1 << 2), 134 OPT_FSTYPE = (1 << 2),
125 OPT_t = (1 << 3), 135 OPT_t = (1 << 3),
126 OPT_ALL = (1 << 4) * ENABLE_FEATURE_DF_FANCY, 136 OPT_ALL = (1 << 4) * ENABLE_FEATURE_DF_FANCY,
127 OPT_INODE = (1 << 5) * ENABLE_FEATURE_DF_FANCY, 137 OPT_INODE = (1 << 5) * ENABLE_FEATURE_DF_FANCY_POSIX,
128 OPT_BSIZE = (1 << 6) * ENABLE_FEATURE_DF_FANCY, 138 OPT_BSIZE = (1 << (5 + ENABLE_FEATURE_DF_FANCY_POSIX)) * ENABLE_FEATURE_DF_FANCY,
129 OPT_HUMAN = (1 << (4 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, 139 OPT_HUMAN = (1 << (4 + 2*ENABLE_FEATURE_DF_FANCY + ENABLE_FEATURE_DF_FANCY_POSIX)) * ENABLE_FEATURE_HUMAN_READABLE,
130 OPT_HUMANDEC = (1 << (5 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, 140 OPT_HUMANDEC = (1 << (5 + 2*ENABLE_FEATURE_DF_FANCY + ENABLE_FEATURE_DF_FANCY_POSIX)) * ENABLE_FEATURE_HUMAN_READABLE,
131 OPT_MEGA = (1 << (6 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, 141 OPT_MEGA = (1 << (6 + 2*ENABLE_FEATURE_DF_FANCY + ENABLE_FEATURE_DF_FANCY_POSIX)) * ENABLE_FEATURE_HUMAN_READABLE,
132 }; 142 };
133 const char *disp_units_hdr = NULL; 143 const char *disp_units_hdr = NULL;
134 char *chp, *opt_t; 144 char *chp, *opt_t;
@@ -144,7 +154,11 @@ int df_main(int argc UNUSED_PARAM, char **argv)
144 154
145 opt = getopt32(argv, "^" 155 opt = getopt32(argv, "^"
146 "kPTt:" 156 "kPTt:"
157#if ENABLE_PLATFORM_POSIX
147 IF_FEATURE_DF_FANCY("aiB:") 158 IF_FEATURE_DF_FANCY("aiB:")
159#else
160 IF_FEATURE_DF_FANCY("aB:")
161#endif
148 IF_FEATURE_HUMAN_READABLE("hHm") 162 IF_FEATURE_HUMAN_READABLE("hHm")
149 "\0" 163 "\0"
150#if ENABLE_FEATURE_HUMAN_READABLE && ENABLE_FEATURE_DF_FANCY 164#if ENABLE_FEATURE_HUMAN_READABLE && ENABLE_FEATURE_DF_FANCY
@@ -155,6 +169,9 @@ int df_main(int argc UNUSED_PARAM, char **argv)
155 , &opt_t 169 , &opt_t
156 IF_FEATURE_DF_FANCY(, &chp) 170 IF_FEATURE_DF_FANCY(, &chp)
157 ); 171 );
172 /* -k overrides $POSIXLY_CORRECT: */
173 if (opt & OPT_KILO)
174 df_disp_hr = 1024;
158 if (opt & OPT_MEGA) 175 if (opt & OPT_MEGA)
159 df_disp_hr = 1024*1024; 176 df_disp_hr = 1024*1024;
160 177
@@ -185,8 +202,8 @@ int df_main(int argc UNUSED_PARAM, char **argv)
185 if (disp_units_hdr == NULL) { 202 if (disp_units_hdr == NULL) {
186#if ENABLE_FEATURE_HUMAN_READABLE 203#if ENABLE_FEATURE_HUMAN_READABLE
187 disp_units_hdr = xasprintf("%s-blocks", 204 disp_units_hdr = xasprintf("%s-blocks",
188 /* print df_disp_hr, show no fractionals, 205 /* print df_disp_hr; show no fractionals;
189 * use suffixes if OPT_POSIX is set in opt */ 206 * if -P, unit=1 (print it in full, no KMG suffixes) */
190 make_human_readable_str(df_disp_hr, 0, !!(opt & OPT_POSIX)) 207 make_human_readable_str(df_disp_hr, 0, !!(opt & OPT_POSIX))
191 ); 208 );
192#else 209#else
diff --git a/coreutils/du.c b/coreutils/du.c
index 4652b6300..338998fc9 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -137,7 +137,7 @@ static void print(unsigned long long size, const char *filename)
137 size >>= 10; 137 size >>= 10;
138 } 138 }
139 } 139 }
140 printf("%llu\t%s\n", size, filename); 140 printf("%"LL_FMT"u\t%s\n", size, filename);
141#endif 141#endif
142} 142}
143 143
diff --git a/coreutils/expr.c b/coreutils/expr.c
index 47ebe2fca..c00559e4c 100644
--- a/coreutils/expr.c
+++ b/coreutils/expr.c
@@ -84,7 +84,7 @@
84#if ENABLE_EXPR_MATH_SUPPORT_64 84#if ENABLE_EXPR_MATH_SUPPORT_64
85typedef int64_t arith_t; 85typedef int64_t arith_t;
86 86
87#define PF_REZ "ll" 87#define PF_REZ LL_FMT
88#define PF_REZ_TYPE (long long) 88#define PF_REZ_TYPE (long long)
89#define STRTOL(s, e, b) strtoll(s, e, b) 89#define STRTOL(s, e, b) strtoll(s, e, b)
90#else 90#else
@@ -97,6 +97,10 @@ typedef long arith_t;
97 97
98/* TODO: use bb_strtol[l]? It's easier to check for errors... */ 98/* TODO: use bb_strtol[l]? It's easier to check for errors... */
99 99
100#if ENABLE_PLATFORM_MINGW32
101# define STRING BB_STRING
102#endif
103
100/* The kinds of value we can have. */ 104/* The kinds of value we can have. */
101enum { 105enum {
102 INTEGER, 106 INTEGER,
diff --git a/coreutils/factor.c b/coreutils/factor.c
index 90e9ed761..9de5ea8eb 100644
--- a/coreutils/factor.c
+++ b/coreutils/factor.c
@@ -124,7 +124,7 @@ static NOINLINE void print_w(wide_t n)
124{ 124{
125 unsigned rep = square_count; 125 unsigned rep = square_count;
126 do 126 do
127 printf(" %llu", n); 127 printf(" %"LL_FMT"u", n);
128 while (--rep != 0); 128 while (--rep != 0);
129} 129}
130static NOINLINE void print_h(half_t n) 130static NOINLINE void print_h(half_t n)
@@ -226,7 +226,7 @@ static void factorize_numstr(const char *numstr)
226 N = bb_strtoull(numstr, NULL, 10); 226 N = bb_strtoull(numstr, NULL, 10);
227 if (errno) 227 if (errno)
228 bb_show_usage(); 228 bb_show_usage();
229 printf("%llu:", N); 229 printf("%"LL_FMT"u:", N);
230 square_count = 1; 230 square_count = 1;
231 factorize(N); 231 factorize(N);
232} 232}
diff --git a/coreutils/id.c b/coreutils/id.c
index a4f178bda..0e1286294 100644
--- a/coreutils/id.c
+++ b/coreutils/id.c
@@ -112,6 +112,7 @@ static int print_user(uid_t id, const char *prefix)
112 return print_common(id, uid2uname(id), prefix); 112 return print_common(id, uid2uname(id), prefix);
113} 113}
114 114
115#if !ENABLE_PLATFORM_MINGW32
115/* On error set *n < 0 and return >= 0 116/* On error set *n < 0 and return >= 0
116 * If *n is too small, update it and return < 0 117 * If *n is too small, update it and return < 0
117 * (ok to trash groups[] in both cases) 118 * (ok to trash groups[] in both cases)
@@ -142,6 +143,7 @@ static int get_groups(const char *username, gid_t rgid, gid_t *groups, int *n)
142 /* if *n >= 0, return -1 (got new *n), else return 0 (error): */ 143 /* if *n >= 0, return -1 (got new *n), else return 0 (error): */
143 return -(*n >= 0); 144 return -(*n >= 0);
144} 145}
146#endif
145 147
146int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 148int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
147int id_main(int argc UNUSED_PARAM, char **argv) 149int id_main(int argc UNUSED_PARAM, char **argv)
@@ -184,16 +186,26 @@ int id_main(int argc UNUSED_PARAM, char **argv)
184 euid = ruid = p->pw_uid; 186 euid = ruid = p->pw_uid;
185 egid = rgid = p->pw_gid; 187 egid = rgid = p->pw_gid;
186 } else { 188 } else {
189#if ENABLE_PLATFORM_MINGW32
190 // We don't distinguish real/effective ids on Windows.
191 euid = ruid = getuid();
192 egid = rgid = getegid();
193#else
187 egid = getegid(); 194 egid = getegid();
188 rgid = getgid(); 195 rgid = getgid();
189 euid = geteuid(); 196 euid = geteuid();
190 ruid = getuid(); 197 ruid = getuid();
198#endif
191 } 199 }
192 /* JUST_ALL_GROUPS ignores -r PRINT_REAL flag even if man page for */ 200 /* JUST_ALL_GROUPS ignores -r PRINT_REAL flag even if man page for */
193 /* id says: print the real ID instead of the effective ID, with -ugG */ 201 /* id says: print the real ID instead of the effective ID, with -ugG */
194 /* in fact in this case egid is always printed if egid != rgid */ 202 /* in fact in this case egid is always printed if egid != rgid */
195 if (!opt || (opt & JUST_ALL_GROUPS)) { 203 if (!opt || (opt & JUST_ALL_GROUPS)) {
204#if ENABLE_PLATFORM_MINGW32
205 gid_t groups[1];
206#else
196 gid_t *groups; 207 gid_t *groups;
208#endif
197 int n; 209 int n;
198 210
199 if (!opt) { 211 if (!opt) {
@@ -210,6 +222,11 @@ int id_main(int argc UNUSED_PARAM, char **argv)
210 if (egid != rgid) 222 if (egid != rgid)
211 status |= print_group(egid, " "); 223 status |= print_group(egid, " ");
212 } 224 }
225#if ENABLE_PLATFORM_MINGW32
226 // We only admit to having one group id on Windows.
227 n = 1;
228 groups[0] = rgid;
229#else
213 /* We are supplying largish buffer, trying 230 /* We are supplying largish buffer, trying
214 * to not run get_groups() twice. That might be slow 231 * to not run get_groups() twice. That might be slow
215 * ("user database in remote SQL server" case) */ 232 * ("user database in remote SQL server" case) */
@@ -220,6 +237,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
220 groups = xrealloc(groups, n * sizeof(groups[0])); 237 groups = xrealloc(groups, n * sizeof(groups[0]));
221 get_groups(username, rgid, groups, &n); 238 get_groups(username, rgid, groups, &n);
222 } 239 }
240#endif
223 if (n > 0) { 241 if (n > 0) {
224 /* Print the list */ 242 /* Print the list */
225 prefix = " groups="; 243 prefix = " groups=";
@@ -234,7 +252,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
234 bb_simple_error_msg_and_die("can't get groups"); 252 bb_simple_error_msg_and_die("can't get groups");
235 return EXIT_FAILURE; 253 return EXIT_FAILURE;
236 } 254 }
237 if (ENABLE_FEATURE_CLEAN_UP) 255 if (ENABLE_FEATURE_CLEAN_UP && !ENABLE_PLATFORM_MINGW32)
238 free(groups); 256 free(groups);
239#if ENABLE_SELINUX 257#if ENABLE_SELINUX
240 if (is_selinux_enabled()) { 258 if (is_selinux_enabled()) {
diff --git a/coreutils/ls.c b/coreutils/ls.c
index cc809b797..5d2e96a1e 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -109,8 +109,11 @@
109//usage:#define ls_full_usage "\n\n" 109//usage:#define ls_full_usage "\n\n"
110//usage: "List directory contents\n" 110//usage: "List directory contents\n"
111//usage: "\n -1 One column output" 111//usage: "\n -1 One column output"
112//usage: "\n -a Include names starting with ." 112//usage: "\n -a Include names starting with ." IF_PLATFORM_MINGW32(" and hidden files")
113//usage: "\n -A Like -a, but exclude . and .." 113//usage: "\n -A Like -a, but exclude . and .."
114//usage: IF_PLATFORM_MINGW32(
115//usage: "\n -aa,-AA Like -a,-A but omit hidden system files"
116//usage: )
114////usage: "\n -C List by columns" - don't show, this is a default anyway 117////usage: "\n -C List by columns" - don't show, this is a default anyway
115//usage: "\n -x List by lines" 118//usage: "\n -x List by lines"
116//usage: "\n -d List directory names, not contents" 119//usage: "\n -d List directory names, not contents"
@@ -316,6 +319,9 @@ struct dnode {
316 int dn_rdev_min; 319 int dn_rdev_min;
317// dev_t dn_dev; 320// dev_t dn_dev;
318// blksize_t dn_blksize; 321// blksize_t dn_blksize;
322#if ENABLE_PLATFORM_MINGW32
323 DWORD dn_attr;
324#endif
319}; 325};
320 326
321struct globals { 327struct globals {
@@ -337,6 +343,10 @@ struct globals {
337 /* Do time() just once. Saves one syscall per file for "ls -l" */ 343 /* Do time() just once. Saves one syscall per file for "ls -l" */
338 time_t current_time_t; 344 time_t current_time_t;
339#endif 345#endif
346#if ENABLE_PLATFORM_MINGW32
347 int a_count, A_count;
348# define HIDSYS (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)
349#endif
340} FIX_ALIASING; 350} FIX_ALIASING;
341#define G (*(struct globals*)bb_common_bufsiz1) 351#define G (*(struct globals*)bb_common_bufsiz1)
342#define INIT_G() do { \ 352#define INIT_G() do { \
@@ -497,7 +507,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
497 lpath = xmalloc_readlink_or_warn(dn->fullname); 507 lpath = xmalloc_readlink_or_warn(dn->fullname);
498 508
499 if (opt & OPT_i) /* show inode# */ 509 if (opt & OPT_i) /* show inode# */
500 column += printf("%7llu ", (long long) dn->dn_ino); 510#if !ENABLE_FEATURE_EXTRA_FILE_DATA
511 column += printf("%7"LL_FMT"u ", (long long) dn->dn_ino);
512#else
513 column += printf("%19"LL_FMT"u ", (long long) dn->dn_ino);
514#endif
501 if (opt & OPT_s) { /* show allocated blocks */ 515 if (opt & OPT_s) { /* show allocated blocks */
502 if (opt & OPT_h) { 516 if (opt & OPT_h) {
503 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", 517 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ",
@@ -659,7 +673,11 @@ static void display_files(struct dnode **dn, unsigned nfiles)
659 } 673 }
660 column_width += 2 674 column_width += 2
661 + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */ 675 + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */
676#if !ENABLE_FEATURE_EXTRA_FILE_DATA
662 + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */ 677 + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */
678#else
679 + ((option_mask32 & OPT_i) ? 20 : 0) /* inode# width */
680#endif
663 + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */ 681 + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */
664 ; 682 ;
665 ncols = (unsigned)G_terminal_width / column_width; 683 ncols = (unsigned)G_terminal_width / column_width;
@@ -740,6 +758,9 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
740 758
741 /* cur->dstat = statbuf: */ 759 /* cur->dstat = statbuf: */
742 cur->dn_mode = statbuf.st_mode ; 760 cur->dn_mode = statbuf.st_mode ;
761#if ENABLE_PLATFORM_MINGW32
762 cur->dn_attr = statbuf.st_attr ;
763#endif
743 cur->dn_size = statbuf.st_size ; 764 cur->dn_size = statbuf.st_size ;
744#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES 765#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
745 cur->dn_time = statbuf.st_mtime ; 766 cur->dn_time = statbuf.st_mtime ;
@@ -920,6 +941,15 @@ static void sort_and_display_files(struct dnode **dn, unsigned nfiles)
920# define sort_and_display_files(dn, nfiles) display_files(dn, nfiles) 941# define sort_and_display_files(dn, nfiles) display_files(dn, nfiles)
921#endif 942#endif
922 943
944#if ENABLE_PLATFORM_MINGW32
945static int hide_file(DWORD attr)
946{
947 return
948 ((attr & FILE_ATTRIBUTE_HIDDEN) && !(option_mask32 & (OPT_a|OPT_A))) ||
949 (((attr & HIDSYS) == HIDSYS) && MAX(G.a_count, G.A_count) > 1);
950}
951#endif
952
923/* Returns NULL-terminated malloced vector of pointers (or NULL) */ 953/* Returns NULL-terminated malloced vector of pointers (or NULL) */
924static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p) 954static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p)
925{ 955{
@@ -927,6 +957,9 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p)
927 struct dirent *entry; 957 struct dirent *entry;
928 DIR *dir; 958 DIR *dir;
929 unsigned i, nfiles; 959 unsigned i, nfiles;
960#if ENABLE_PLATFORM_MINGW32
961 struct stat statbuf;
962#endif
930 963
931 *nfiles_p = 0; 964 *nfiles_p = 0;
932 dir = warn_opendir(path); 965 dir = warn_opendir(path);
@@ -949,9 +982,29 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p)
949 continue; /* if only -A, skip . and .. but show other dotfiles */ 982 continue; /* if only -A, skip . and .. but show other dotfiles */
950 } 983 }
951 } 984 }
985#if ENABLE_PLATFORM_MINGW32
986 if (has_dos_drive_prefix(path) && path[2] == '\0')
987 fullname = xasprintf("%s%s", path, entry->d_name);
988 else
989#endif
952 fullname = concat_path_file(path, entry->d_name); 990 fullname = concat_path_file(path, entry->d_name);
991#if ENABLE_PLATFORM_MINGW32
992 /* When showing link targets we must first check the
993 * attributes of the link itself to see if it's hidden. */
994 if ((option_mask32 & OPT_L) && !lstat(fullname, &statbuf)) {
995 if (hide_file(statbuf.st_attr)) {
996 free(fullname);
997 continue;
998 }
999 }
1000#endif
953 cur = my_stat(fullname, bb_basename(fullname), 0); 1001 cur = my_stat(fullname, bb_basename(fullname), 0);
1002#if !ENABLE_PLATFORM_MINGW32
954 if (!cur) { 1003 if (!cur) {
1004#else
1005 if (!cur || hide_file(cur->dn_attr)) {
1006 /* skip invalid or hidden files */
1007#endif
955 free(fullname); 1008 free(fullname);
956 continue; 1009 continue;
957 } 1010 }
@@ -1060,6 +1113,18 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
1060 } 1113 }
1061} 1114}
1062 1115
1116#if ENABLE_PLATFORM_MINGW32
1117static char *fix_backslash(char *p)
1118{
1119 const char *flag = getenv("BB_FIX_BACKSLASH");
1120 int value = flag ? atoi(flag) : 0;
1121
1122 if (value == 1)
1123 bs_to_slash(p);
1124 return p;
1125}
1126#endif
1127
1063 1128
1064int ls_main(int argc UNUSED_PARAM, char **argv) 1129int ls_main(int argc UNUSED_PARAM, char **argv)
1065{ /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */ 1130{ /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */
@@ -1129,9 +1194,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1129 IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */ 1194 IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */
1130 /* -w NUM: */ 1195 /* -w NUM: */
1131 IF_FEATURE_LS_WIDTH(":w+") 1196 IF_FEATURE_LS_WIDTH(":w+")
1197 IF_PLATFORM_MINGW32(":aa:AA")
1132 , ls_longopts 1198 , ls_longopts
1133 IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width) 1199 IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width)
1134 IF_FEATURE_LS_COLOR(, &color_opt) 1200 IF_FEATURE_LS_COLOR(, &color_opt)
1201 IF_PLATFORM_MINGW32(, &G.a_count, &G.A_count)
1135 ); 1202 );
1136#if 0 /* option bits debug */ 1203#if 0 /* option bits debug */
1137 bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first); 1204 bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first);
@@ -1155,6 +1222,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1155 /* set G_show_color = 1/0 */ 1222 /* set G_show_color = 1/0 */
1156 if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && !is_TERM_dumb()) { 1223 if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && !is_TERM_dumb()) {
1157 char *p = getenv("LS_COLORS"); 1224 char *p = getenv("LS_COLORS");
1225# if ENABLE_PLATFORM_MINGW32
1226 /* No colour if unset or empty: https://no-color.org */
1227 char *no_c = getenv("NO_COLOR");
1228 if (!no_c || no_c[0] == '\0')
1229# endif
1158 /* LS_COLORS is unset, or (not empty && not "none") ? */ 1230 /* LS_COLORS is unset, or (not empty && not "none") ? */
1159 if (!p || (p[0] && strcmp(p, "none") != 0)) { 1231 if (!p || (p[0] && strcmp(p, "none") != 0)) {
1160 if (isatty(STDOUT_FILENO)) { 1232 if (isatty(STDOUT_FILENO)) {
@@ -1204,6 +1276,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1204 option_mask32 |= OPT_dirs_first; 1276 option_mask32 |= OPT_dirs_first;
1205 } 1277 }
1206 1278
1279#if ENABLE_FEATURE_EXTRA_FILE_DATA
1280 /* Enable accurate link counts for directories */
1281 if (opt & OPT_l)
1282 count_subdirs(NULL);
1283#endif
1284
1207 argv += optind; 1285 argv += optind;
1208 if (!argv[0]) 1286 if (!argv[0])
1209 *--argv = (char*)"."; 1287 *--argv = (char*)".";
@@ -1215,6 +1293,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1215 dn = NULL; 1293 dn = NULL;
1216 nfiles = 0; 1294 nfiles = 0;
1217 do { 1295 do {
1296#if ENABLE_PLATFORM_MINGW32
1297 *argv = fix_backslash(*argv);
1298#endif
1218 cur = my_stat(*argv, *argv, 1299 cur = my_stat(*argv, *argv,
1219 /* follow links on command line unless -l, -i, -s or -F: */ 1300 /* follow links on command line unless -l, -i, -s or -F: */
1220 !(option_mask32 & (OPT_l|OPT_i|OPT_s|OPT_F)) 1301 !(option_mask32 & (OPT_l|OPT_i|OPT_s|OPT_F))
diff --git a/coreutils/nproc.c b/coreutils/nproc.c
index df63bf57a..44408b5f5 100644
--- a/coreutils/nproc.c
+++ b/coreutils/nproc.c
@@ -28,6 +28,9 @@
28int nproc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 28int nproc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
29int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 29int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
30{ 30{
31#if ENABLE_PLATFORM_MINGW32
32 DWORD_PTR affinity, process_affinity, system_affinity;
33#endif
31 int count = 0; 34 int count = 0;
32#if ENABLE_LONG_OPTS 35#if ENABLE_LONG_OPTS
33 int ignore = 0; 36 int ignore = 0;
@@ -36,7 +39,10 @@ int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
36 "all\0" No_argument "\xff" 39 "all\0" No_argument "\xff"
37 , &ignore 40 , &ignore
38 ); 41 );
42#endif
39 43
44#if !ENABLE_PLATFORM_MINGW32
45#if ENABLE_LONG_OPTS
40 if (opts & (1 << 1)) { 46 if (opts & (1 << 1)) {
41 DIR *cpusd = opendir("/sys/devices/system/cpu"); 47 DIR *cpusd = opendir("/sys/devices/system/cpu");
42 if (cpusd) { 48 if (cpusd) {
@@ -61,6 +67,17 @@ int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
61 } 67 }
62 IF_FEATURE_CLEAN_UP(free(mask);) 68 IF_FEATURE_CLEAN_UP(free(mask);)
63 } 69 }
70#else /* ENABLE_PLATFORM_MINGW32 */
71 if (GetProcessAffinityMask(GetCurrentProcess(), &process_affinity,
72 &system_affinity)) {
73 affinity = IF_LONG_OPTS((opts & (1 << 1)) ? system_affinity :)
74 process_affinity;
75 while (affinity) {
76 count += affinity & 1;
77 affinity >>= 1;
78 }
79 }
80#endif /* ENABLE_PLATFORM_MINGW32 */
64 81
65 IF_LONG_OPTS(count -= ignore;) 82 IF_LONG_OPTS(count -= ignore;)
66 if (count <= 0) 83 if (count <= 0)
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c
index e886a4ed2..641d93503 100644
--- a/coreutils/od_bloaty.c
+++ b/coreutils/od_bloaty.c
@@ -110,6 +110,13 @@ typedef long long llong;
110# define LDBL_DIG DBL_DIG 110# define LDBL_DIG DBL_DIG
111#endif 111#endif
112 112
113#if ENABLE_PLATFORM_MINGW32
114/* symbol conflict */
115#define CHAR SIZE_CHAR
116#define SHORT SIZE_SHORT
117#define LONG SIZE_LONG
118#define INT SIZE_INT
119#endif
113enum size_spec { 120enum size_spec {
114 NO_SIZE, 121 NO_SIZE,
115 CHAR, 122 CHAR,
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 4edcfa9b5..379c00cc6 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -152,6 +152,71 @@ static double my_xstrtod(const char *arg)
152 return result; 152 return result;
153} 153}
154 154
155#if ENABLE_PLATFORM_MINGW32
156static int buflen = 0;
157static int bufmax = 0;
158static char *buffer = NULL;
159
160static void my_flush(void)
161{
162 if (buffer)
163 full_write(STDOUT_FILENO, buffer, buflen);
164 free(buffer);
165 buffer = NULL;
166 buflen = bufmax = 0;
167}
168
169static void copy_to_buffer(const char *str, int len)
170{
171 char *newbuf;
172
173 if (buflen + len >= bufmax) {
174 bufmax += 256 + len;
175 if ((newbuf = realloc(buffer, bufmax)) == NULL) {
176 my_flush();
177 return;
178 }
179 buffer = newbuf;
180 }
181 memcpy(buffer + buflen, str, len);
182 buflen += len;
183
184 if (buflen > 40 && buffer[buflen-1] == '\n')
185 my_flush();
186}
187
188static int my_putchar(int ch)
189{
190 char str[1] = { (char)ch };
191 copy_to_buffer(str, 1);
192 return ch;
193}
194
195static int my_printf(const char *format, ...)
196{
197 va_list list;
198 char *str;
199 int len;
200
201 va_start(list, format);
202 len = vasprintf(&str, format, list);
203 va_end(list);
204
205 if (len >= 0) {
206 copy_to_buffer(str, len);
207 free(str);
208 }
209 return len;
210}
211
212#undef bb_putchar
213#undef putchar
214#undef printf
215#define bb_putchar(c) my_putchar(c)
216#define putchar(c) my_putchar(c)
217#define printf(...) my_printf(__VA_ARGS__)
218#endif
219
155/* Handles %b; return 1 if output is to be short-circuited by \c */ 220/* Handles %b; return 1 if output is to be short-circuited by \c */
156static int print_esc_string(const char *str) 221static int print_esc_string(const char *str)
157{ 222{
@@ -444,6 +509,9 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
444 do { 509 do {
445 argv = argv2; 510 argv = argv2;
446 argv2 = print_formatted(format, argv, &conv_err); 511 argv2 = print_formatted(format, argv, &conv_err);
512#if ENABLE_PLATFORM_MINGW32
513 my_flush();
514#endif
447 } while (argv2 > argv && *argv2); 515 } while (argv2 > argv && *argv2);
448 516
449 /* coreutils compat (bash doesn't do this): 517 /* coreutils compat (bash doesn't do this):
diff --git a/coreutils/shred.c b/coreutils/shred.c
index 7c0be612a..9e53b4820 100644
--- a/coreutils/shred.c
+++ b/coreutils/shred.c
@@ -60,9 +60,9 @@ int shred_main(int argc UNUSED_PARAM, char **argv)
60 opt = getopt32(argv, "^" "fuzn:+vxs:" "\0" "-1"/*min 1 arg*/, &num_iter, &opt_s); 60 opt = getopt32(argv, "^" "fuzn:+vxs:" "\0" "-1"/*min 1 arg*/, &num_iter, &opt_s);
61 argv += optind; 61 argv += optind;
62 62
63 zero_fd = xopen("/dev/zero", O_RDONLY); 63 zero_fd = MINGW_SPECIAL(xopen)("/dev/zero", O_RDONLY);
64 if (num_iter != 0) 64 if (num_iter != 0)
65 rand_fd = xopen("/dev/urandom", O_RDONLY); 65 rand_fd = MINGW_SPECIAL(xopen)("/dev/urandom", O_RDONLY);
66 66
67 for (;;) { 67 for (;;) {
68 struct stat sb; 68 struct stat sb;
@@ -102,8 +102,14 @@ int shred_main(int argc UNUSED_PARAM, char **argv)
102 } 102 }
103 if (opt & OPT_u) { 103 if (opt & OPT_u) {
104 ftruncate(fd, 0); 104 ftruncate(fd, 0);
105#if ENABLE_PLATFORM_MINGW32
106 xclose(fd);
107#endif
105 xunlink(fname); 108 xunlink(fname);
106 } 109 }
110#if ENABLE_PLATFORM_MINGW32
111 else
112#endif
107 xclose(fd); 113 xclose(fd);
108 } 114 }
109 115
diff --git a/coreutils/shuf.c b/coreutils/shuf.c
index 0d23382a2..bd3f6840c 100644
--- a/coreutils/shuf.c
+++ b/coreutils/shuf.c
@@ -212,7 +212,7 @@ int shuf_main(int argc, char **argv)
212 printf("%.*s%0*llu%c", pfx_len, pfx, padding_width, lo + (uintptr_t)lines[i], eol); 212 printf("%.*s%0*llu%c", pfx_len, pfx, padding_width, lo + (uintptr_t)lines[i], eol);
213 else 213 else
214#endif 214#endif
215 printf("%llu%c", lo + (uintptr_t)lines[i], eol); 215 printf("%"LL_FMT"u%c", lo + (uintptr_t)lines[i], eol);
216 } else 216 } else
217 printf("%s%c", lines[i], eol); 217 printf("%s%c", lines[i], eol);
218 } 218 }
diff --git a/coreutils/sort.c b/coreutils/sort.c
index 2e952f81c..949948203 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -43,7 +43,12 @@
43 43
44//usage:#define sort_trivial_usage 44//usage:#define sort_trivial_usage
45//usage: "[-nru" 45//usage: "[-nru"
46//usage: IF_NOT_PLATFORM_MINGW32(
46//usage: IF_FEATURE_SORT_BIG("ghMcszbdfiokt] [-o FILE] [-k START[.OFS][OPTS][,END[.OFS][OPTS]] [-t CHAR") 47//usage: IF_FEATURE_SORT_BIG("ghMcszbdfiokt] [-o FILE] [-k START[.OFS][OPTS][,END[.OFS][OPTS]] [-t CHAR")
48//usage: )
49//usage: IF_PLATFORM_MINGW32(
50//usage: IF_FEATURE_SORT_BIG("ghMVcszbdfiokt] [-o FILE] [-k START[.OFS][OPTS][,END[.OFS][OPTS]] [-t CHAR")
51//usage: )
47//usage: "] [FILE]..." 52//usage: "] [FILE]..."
48//usage:#define sort_full_usage "\n\n" 53//usage:#define sort_full_usage "\n\n"
49//usage: "Sort lines of text\n" 54//usage: "Sort lines of text\n"
diff --git a/coreutils/split.c b/coreutils/split.c
index b6d1b9a7b..8d0e485d4 100644
--- a/coreutils/split.c
+++ b/coreutils/split.c
@@ -78,8 +78,10 @@ static char *next_file(char *old, unsigned suffix_len)
78 return old; 78 return old;
79} 79}
80 80
81#if !ENABLE_PLATFORM_MINGW32
81#define read_buffer bb_common_bufsiz1 82#define read_buffer bb_common_bufsiz1
82enum { READ_BUFFER_SIZE = COMMON_BUFSIZE - 1 }; 83enum { READ_BUFFER_SIZE = COMMON_BUFSIZE - 1 };
84#endif
83 85
84#define SPLIT_OPT_l (1<<0) 86#define SPLIT_OPT_l (1<<0)
85#define SPLIT_OPT_b (1<<1) 87#define SPLIT_OPT_b (1<<1)
@@ -97,8 +99,12 @@ int split_main(int argc UNUSED_PARAM, char **argv)
97 unsigned opt; 99 unsigned opt;
98 ssize_t bytes_read, to_write; 100 ssize_t bytes_read, to_write;
99 char *src; 101 char *src;
100 102#if ENABLE_PLATFORM_MINGW32
103 size_t READ_BUFFER_SIZE = 16*1024;
104 char *read_buffer = xmalloc(16*1024);
105#else
101 setup_common_bufsiz(); 106 setup_common_bufsiz();
107#endif
102 108
103 opt = getopt32(argv, "^" 109 opt = getopt32(argv, "^"
104 "l:b:a:+" /* -a N */ 110 "l:b:a:+" /* -a N */
diff --git a/coreutils/stat.c b/coreutils/stat.c
index 2c2909e7e..dc20c2356 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -190,6 +190,7 @@ FS_TYPE(0x012FF7B4, "xenix") \
190FS_TYPE(0x012FF7B5, "sysv4") \ 190FS_TYPE(0x012FF7B5, "sysv4") \
191FS_TYPE(0x012FF7B6, "sysv2") \ 191FS_TYPE(0x012FF7B6, "sysv2") \
192FS_TYPE(0x012FF7B7, "coh") \ 192FS_TYPE(0x012FF7B7, "coh") \
193IF_PLATFORM_MINGW32(FS_TYPE(0x15013346, "udf")) \
193FS_TYPE(0x00011954, "ufs") \ 194FS_TYPE(0x00011954, "ufs") \
194FS_TYPE(0x012FD16D, "xia") \ 195FS_TYPE(0x012FD16D, "xia") \
195FS_TYPE(0x5346544e, "ntfs") \ 196FS_TYPE(0x5346544e, "ntfs") \
@@ -784,6 +785,10 @@ int stat_main(int argc UNUSED_PARAM, char **argv)
784 selinux_or_die(); 785 selinux_or_die();
785 } 786 }
786#endif 787#endif
788#if ENABLE_FEATURE_EXTRA_FILE_DATA
789 /* Enable accurate link counts for directories */
790 count_subdirs(NULL);
791#endif
787 ok = 1; 792 ok = 1;
788 argv += optind; 793 argv += optind;
789 for (i = 0; argv[i]; ++i) 794 for (i = 0; argv[i]; ++i)
diff --git a/coreutils/stty.c b/coreutils/stty.c
index c88ef07f4..92d5838c0 100644
--- a/coreutils/stty.c
+++ b/coreutils/stty.c
@@ -20,14 +20,30 @@
20//kbuild:lib-$(CONFIG_STTY) += stty.o 20//kbuild:lib-$(CONFIG_STTY) += stty.o
21 21
22//usage:#define stty_trivial_usage 22//usage:#define stty_trivial_usage
23//usage: IF_NOT_PLATFORM_MINGW32(
23//usage: "[-a|g] [-F DEVICE] [SETTING]..." 24//usage: "[-a|g] [-F DEVICE] [SETTING]..."
25//usage: )
26//usage: IF_PLATFORM_MINGW32(
27//usage: "[-a] [SETTING]..."
28//usage: )
24//usage:#define stty_full_usage "\n\n" 29//usage:#define stty_full_usage "\n\n"
30//usage: IF_NOT_PLATFORM_MINGW32(
25//usage: "Without arguments, prints baud rate, line discipline,\n" 31//usage: "Without arguments, prints baud rate, line discipline,\n"
26//usage: "and deviations from stty sane\n" 32//usage: "and deviations from stty sane\n"
27//usage: "\n -F DEVICE Open device instead of stdin" 33//usage: "\n -F DEVICE Open device instead of stdin"
34//usage: )
35//usage: IF_PLATFORM_MINGW32(
36//usage: "Without arguments, prints deviations from stty sane\n"
37//usage: )
28//usage: "\n -a Print all current settings in human-readable form" 38//usage: "\n -a Print all current settings in human-readable form"
39//usage: IF_NOT_PLATFORM_MINGW32(
29//usage: "\n -g Print in stty-readable form" 40//usage: "\n -g Print in stty-readable form"
30//usage: "\n [SETTING] See manpage" 41//usage: "\n [SETTING] See manpage"
42//usage: )
43//usage: IF_PLATFORM_MINGW32(
44//usage: "\n [SETTING] [-]echo [-]cooked [-]raw sane"
45//usage: "\n cols N rows N size"
46//usage: )
31 47
32/* If no args are given, write to stdout the baud rate and settings that 48/* If no args are given, write to stdout the baud rate and settings that
33 * have been changed from their defaults. Mode reading and changes 49 * have been changed from their defaults. Mode reading and changes
@@ -294,6 +310,7 @@ struct mode_info {
294 const tcflag_t bits; /* Bits to set for this mode */ 310 const tcflag_t bits; /* Bits to set for this mode */
295}; 311};
296 312
313#if !ENABLE_PLATFORM_MINGW32
297enum { 314enum {
298 /* Must match mode_name[] and mode_info[] order! */ 315 /* Must match mode_name[] and mode_info[] order! */
299 IDX_evenp = 0, 316 IDX_evenp = 0,
@@ -320,19 +337,30 @@ enum {
320 IDX_LCASE, 337 IDX_LCASE,
321#endif 338#endif
322}; 339};
340#else
341enum {
342 /* Must match mode_name[] and mode_info[] order! */
343 IDX_sane = 0,
344 IDX_cooked,
345 IDX_raw,
346};
347#endif
323 348
324#define MI_ENTRY(N,T,F,B,M) N "\0" 349#define MI_ENTRY(N,T,F,B,M) N "\0"
325 350
326/* Mode names given on command line */ 351/* Mode names given on command line */
327static const char mode_name[] ALIGN1 = 352static const char mode_name[] ALIGN1 =
353#if !ENABLE_PLATFORM_MINGW32
328 MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) 354 MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 )
329 MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) 355 MI_ENTRY("parity", combination, REV | OMIT, 0, 0 )
330 MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 ) 356 MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 )
331 MI_ENTRY("nl", combination, REV | OMIT, 0, 0 ) 357 MI_ENTRY("nl", combination, REV | OMIT, 0, 0 )
332 MI_ENTRY("ek", combination, OMIT, 0, 0 ) 358 MI_ENTRY("ek", combination, OMIT, 0, 0 )
359#endif
333 MI_ENTRY("sane", combination, OMIT, 0, 0 ) 360 MI_ENTRY("sane", combination, OMIT, 0, 0 )
334 MI_ENTRY("cooked", combination, REV | OMIT, 0, 0 ) 361 MI_ENTRY("cooked", combination, REV | OMIT, 0, 0 )
335 MI_ENTRY("raw", combination, REV | OMIT, 0, 0 ) 362 MI_ENTRY("raw", combination, REV | OMIT, 0, 0 )
363#if !ENABLE_PLATFORM_MINGW32
336 MI_ENTRY("pass8", combination, REV | OMIT, 0, 0 ) 364 MI_ENTRY("pass8", combination, REV | OMIT, 0, 0 )
337 MI_ENTRY("litout", combination, REV | OMIT, 0, 0 ) 365 MI_ENTRY("litout", combination, REV | OMIT, 0, 0 )
338 MI_ENTRY("cbreak", combination, REV | OMIT, 0, 0 ) 366 MI_ENTRY("cbreak", combination, REV | OMIT, 0, 0 )
@@ -454,7 +482,9 @@ static const char mode_name[] ALIGN1 =
454#if IEXTEN 482#if IEXTEN
455 MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ) 483 MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 )
456#endif 484#endif
485#endif /* !ENABLE_PLATFORM_MINGW32 */
457 MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ) 486 MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 )
487#if !ENABLE_PLATFORM_MINGW32
458 MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ) 488 MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 )
459 MI_ENTRY("crterase", local, OMIT | REV, ECHOE, 0 ) 489 MI_ENTRY("crterase", local, OMIT | REV, ECHOE, 0 )
460 MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ) 490 MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 )
@@ -482,6 +512,7 @@ static const char mode_name[] ALIGN1 =
482#ifdef EXTPROC 512#ifdef EXTPROC
483 MI_ENTRY("extproc", local, SANE_UNSET | REV, EXTPROC, 0 ) 513 MI_ENTRY("extproc", local, SANE_UNSET | REV, EXTPROC, 0 )
484#endif 514#endif
515#endif /* !ENABLE_PLATFORM_MINGW32 */
485 ; 516 ;
486 517
487#undef MI_ENTRY 518#undef MI_ENTRY
@@ -489,14 +520,17 @@ static const char mode_name[] ALIGN1 =
489 520
490static const struct mode_info mode_info[] ALIGN4 = { 521static const struct mode_info mode_info[] ALIGN4 = {
491 /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */ 522 /* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */
523#if !ENABLE_PLATFORM_MINGW32
492 MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 ) 524 MI_ENTRY("evenp", combination, REV | OMIT, 0, 0 )
493 MI_ENTRY("parity", combination, REV | OMIT, 0, 0 ) 525 MI_ENTRY("parity", combination, REV | OMIT, 0, 0 )
494 MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 ) 526 MI_ENTRY("oddp", combination, REV | OMIT, 0, 0 )
495 MI_ENTRY("nl", combination, REV | OMIT, 0, 0 ) 527 MI_ENTRY("nl", combination, REV | OMIT, 0, 0 )
496 MI_ENTRY("ek", combination, OMIT, 0, 0 ) 528 MI_ENTRY("ek", combination, OMIT, 0, 0 )
529#endif
497 MI_ENTRY("sane", combination, OMIT, 0, 0 ) 530 MI_ENTRY("sane", combination, OMIT, 0, 0 )
498 MI_ENTRY("cooked", combination, REV | OMIT, 0, 0 ) 531 MI_ENTRY("cooked", combination, REV | OMIT, 0, 0 )
499 MI_ENTRY("raw", combination, REV | OMIT, 0, 0 ) 532 MI_ENTRY("raw", combination, REV | OMIT, 0, 0 )
533#if !ENABLE_PLATFORM_MINGW32
500 MI_ENTRY("pass8", combination, REV | OMIT, 0, 0 ) 534 MI_ENTRY("pass8", combination, REV | OMIT, 0, 0 )
501 MI_ENTRY("litout", combination, REV | OMIT, 0, 0 ) 535 MI_ENTRY("litout", combination, REV | OMIT, 0, 0 )
502 MI_ENTRY("cbreak", combination, REV | OMIT, 0, 0 ) 536 MI_ENTRY("cbreak", combination, REV | OMIT, 0, 0 )
@@ -618,7 +652,9 @@ static const struct mode_info mode_info[] ALIGN4 = {
618#if IEXTEN 652#if IEXTEN
619 MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 ) 653 MI_ENTRY("iexten", local, SANE_SET | REV, IEXTEN, 0 )
620#endif 654#endif
655#endif /* !ENABLE_PLATFORM_MINGW32 */
621 MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 ) 656 MI_ENTRY("echo", local, SANE_SET | REV, ECHO, 0 )
657#if !ENABLE_PLATFORM_MINGW32
622 MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 ) 658 MI_ENTRY("echoe", local, SANE_SET | REV, ECHOE, 0 )
623 MI_ENTRY("crterase", local, OMIT | REV, ECHOE, 0 ) 659 MI_ENTRY("crterase", local, OMIT | REV, ECHOE, 0 )
624 MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 ) 660 MI_ENTRY("echok", local, SANE_SET | REV, ECHOK, 0 )
@@ -646,6 +682,7 @@ static const struct mode_info mode_info[] ALIGN4 = {
646#ifdef EXTPROC 682#ifdef EXTPROC
647 MI_ENTRY("extproc", local, SANE_UNSET | REV, EXTPROC, 0 ) 683 MI_ENTRY("extproc", local, SANE_UNSET | REV, EXTPROC, 0 )
648#endif 684#endif
685#endif /* !ENABLE_PLATFORM_MINGW32 */
649}; 686};
650 687
651enum { 688enum {
@@ -653,6 +690,7 @@ enum {
653}; 690};
654 691
655 692
693#if !ENABLE_PLATFORM_MINGW32
656/* Control characters */ 694/* Control characters */
657struct control_info { 695struct control_info {
658 const uint8_t saneval; /* Value to set for 'stty sane' */ 696 const uint8_t saneval; /* Value to set for 'stty sane' */
@@ -786,6 +824,7 @@ static const struct control_info control_info[] ALIGN2 = {
786enum { 824enum {
787 NUM_control_info = ARRAY_SIZE(control_info) 825 NUM_control_info = ARRAY_SIZE(control_info)
788}; 826};
827#endif
789 828
790 829
791struct globals { 830struct globals {
@@ -803,6 +842,7 @@ struct globals {
803 G.current_col = 0; /* we are noexec, must clear */ \ 842 G.current_col = 0; /* we are noexec, must clear */ \
804} while (0) 843} while (0)
805 844
845#if !ENABLE_PLATFORM_MINGW32
806static void set_speed_or_die(enum speed_setting type, const char *arg, 846static void set_speed_or_die(enum speed_setting type, const char *arg,
807 struct termios *mode) 847 struct termios *mode)
808{ 848{
@@ -817,6 +857,7 @@ static void set_speed_or_die(enum speed_setting type, const char *arg,
817 cfsetospeed(mode, baud); 857 cfsetospeed(mode, baud);
818 } 858 }
819} 859}
860#endif
820 861
821static NORETURN void perror_on_device_and_die(const char *fmt) 862static NORETURN void perror_on_device_and_die(const char *fmt)
822{ 863{
@@ -918,6 +959,7 @@ static const struct mode_info *find_mode(const char *name)
918 return i >= 0 ? &mode_info[i] : NULL; 959 return i >= 0 ? &mode_info[i] : NULL;
919} 960}
920 961
962#if !ENABLE_PLATFORM_MINGW32
921static const struct control_info *find_control(const char *name) 963static const struct control_info *find_control(const char *name)
922{ 964{
923 int i = index_in_strings(control_name, name); 965 int i = index_in_strings(control_name, name);
@@ -954,7 +996,32 @@ static int find_param(const char *name)
954 i |= 0x80; 996 i |= 0x80;
955 return i; 997 return i;
956} 998}
999#else
1000enum {
1001 param_need_arg = 0x80,
1002 param_rows = 1 | 0x80,
1003 param_cols = 2 | 0x80,
1004 param_columns = 3 | 0x80,
1005 param_size = 4,
1006};
957 1007
1008static int find_param(const char *name)
1009{
1010 static const char params[] ALIGN1 =
1011 "rows\0" /* 1 */
1012 "cols\0" /* 2 */
1013 "columns\0" /* 3 */
1014 "size\0"; /* 4 */
1015 int i = index_in_strings(params, name) + 1;
1016 if (i == 0)
1017 return 0;
1018 if (i != 4)
1019 i |= 0x80;
1020 return i;
1021}
1022#endif
1023
1024#if !ENABLE_PLATFORM_MINGW32
958static int recover_mode(const char *arg, struct termios *mode) 1025static int recover_mode(const char *arg, struct termios *mode)
959{ 1026{
960 int i, n; 1027 int i, n;
@@ -1013,6 +1080,9 @@ static void display_speed(const struct termios *mode, int fancy)
1013 if (fancy) fmt_str += 9; 1080 if (fancy) fmt_str += 9;
1014 wrapf(fmt_str, tty_baud_to_value(ispeed), tty_baud_to_value(ospeed)); 1081 wrapf(fmt_str, tty_baud_to_value(ispeed), tty_baud_to_value(ospeed));
1015} 1082}
1083#else
1084# define display_speed(m, f) ((void)0)
1085#endif
1016 1086
1017static void do_display(const struct termios *mode, int all) 1087static void do_display(const struct termios *mode, int all)
1018{ 1088{
@@ -1030,6 +1100,7 @@ static void do_display(const struct termios *mode, int all)
1030 newline(); 1100 newline();
1031#endif 1101#endif
1032 1102
1103#if !ENABLE_PLATFORM_MINGW32
1033 for (i = 0; i != CIDX_min; ++i) { 1104 for (i = 0; i != CIDX_min; ++i) {
1034 char ch; 1105 char ch;
1035 char buf10[10]; 1106 char buf10[10];
@@ -1059,6 +1130,7 @@ static void do_display(const struct termios *mode, int all)
1059#endif 1130#endif
1060 wrapf("min = %u; time = %u;", mode->c_cc[VMIN], mode->c_cc[VTIME]); 1131 wrapf("min = %u; time = %u;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1061 newline(); 1132 newline();
1133#endif
1062 1134
1063 for (i = 0; i < NUM_mode_info; ++i) { 1135 for (i = 0; i < NUM_mode_info; ++i) {
1064 if (mode_info[i].flags & OMIT) 1136 if (mode_info[i].flags & OMIT)
@@ -1086,6 +1158,7 @@ static void do_display(const struct termios *mode, int all)
1086 1158
1087static void sane_mode(struct termios *mode) 1159static void sane_mode(struct termios *mode)
1088{ 1160{
1161#if !ENABLE_PLATFORM_MINGW32
1089 int i; 1162 int i;
1090 1163
1091 for (i = 0; i < NUM_control_info; ++i) { 1164 for (i = 0; i < NUM_control_info; ++i) {
@@ -1110,6 +1183,11 @@ static void sane_mode(struct termios *mode)
1110 *bitsp = val & ~mode_info[i].bits; 1183 *bitsp = val & ~mode_info[i].bits;
1111 } 1184 }
1112 } 1185 }
1186#else
1187 mode->c_lflag |= ECHO;
1188 mode->w_mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT |
1189 ENABLE_PROCESSED_INPUT;
1190#endif
1113} 1191}
1114 1192
1115static void set_mode(const struct mode_info *info, int reversed, 1193static void set_mode(const struct mode_info *info, int reversed,
@@ -1129,6 +1207,7 @@ static void set_mode(const struct mode_info *info, int reversed,
1129 } 1207 }
1130 1208
1131 /* !bitsp - it's a "combination" mode */ 1209 /* !bitsp - it's a "combination" mode */
1210#if !ENABLE_PLATFORM_MINGW32
1132 if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) { 1211 if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) {
1133 if (reversed) 1212 if (reversed)
1134 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; 1213 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
@@ -1150,9 +1229,14 @@ static void set_mode(const struct mode_info *info, int reversed,
1150 } else if (info == &mode_info[IDX_ek]) { 1229 } else if (info == &mode_info[IDX_ek]) {
1151 mode->c_cc[VERASE] = CERASE; 1230 mode->c_cc[VERASE] = CERASE;
1152 mode->c_cc[VKILL] = CKILL; 1231 mode->c_cc[VKILL] = CKILL;
1153 } else if (info == &mode_info[IDX_sane]) { 1232 }
1233 else
1234#endif /* !ENABLE_PLATFORM_MINGW32 */
1235 if (info == &mode_info[IDX_sane]) {
1154 sane_mode(mode); 1236 sane_mode(mode);
1155 } else if (info == &mode_info[IDX_cbreak]) { 1237 }
1238#if !ENABLE_PLATFORM_MINGW32
1239 else if (info == &mode_info[IDX_cbreak]) {
1156 if (reversed) 1240 if (reversed)
1157 mode->c_lflag |= ICANON; 1241 mode->c_lflag |= ICANON;
1158 else 1242 else
@@ -1175,11 +1259,14 @@ static void set_mode(const struct mode_info *info, int reversed,
1175 mode->c_iflag &= ~ISTRIP; 1259 mode->c_iflag &= ~ISTRIP;
1176 mode->c_oflag &= ~OPOST; 1260 mode->c_oflag &= ~OPOST;
1177 } 1261 }
1178 } else if (info == &mode_info[IDX_raw] || info == &mode_info[IDX_cooked]) { 1262 }
1263#endif /* !ENABLE_PLATFORM_MINGW32 */
1264 else if (info == &mode_info[IDX_raw] || info == &mode_info[IDX_cooked]) {
1179 if ((info == &mode_info[IDX_raw] && reversed) 1265 if ((info == &mode_info[IDX_raw] && reversed)
1180 || (info == &mode_info[IDX_cooked] && !reversed) 1266 || (info == &mode_info[IDX_cooked] && !reversed)
1181 ) { 1267 ) {
1182 /* Cooked mode */ 1268 /* Cooked mode */
1269#if !ENABLE_PLATFORM_MINGW32
1183 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON; 1270 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1184 mode->c_oflag |= OPOST; 1271 mode->c_oflag |= OPOST;
1185 mode->c_lflag |= ISIG | ICANON; 1272 mode->c_lflag |= ISIG | ICANON;
@@ -1189,15 +1276,23 @@ static void set_mode(const struct mode_info *info, int reversed,
1189#if VTIME == VEOL 1276#if VTIME == VEOL
1190 mode->c_cc[VEOL] = CEOL; 1277 mode->c_cc[VEOL] = CEOL;
1191#endif 1278#endif
1279#else
1280 mode->w_mode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
1281#endif
1192 } else { 1282 } else {
1193 /* Raw mode */ 1283 /* Raw mode */
1284#if !ENABLE_PLATFORM_MINGW32
1194 mode->c_iflag = 0; 1285 mode->c_iflag = 0;
1195 mode->c_oflag &= ~OPOST; 1286 mode->c_oflag &= ~OPOST;
1196 mode->c_lflag &= ~(ISIG | ICANON | XCASE); 1287 mode->c_lflag &= ~(ISIG | ICANON | XCASE);
1197 mode->c_cc[VMIN] = 1; 1288 mode->c_cc[VMIN] = 1;
1198 mode->c_cc[VTIME] = 0; 1289 mode->c_cc[VTIME] = 0;
1290#else
1291 mode->w_mode &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
1292#endif
1199 } 1293 }
1200 } 1294 }
1295#if !ENABLE_PLATFORM_MINGW32
1201#if IXANY 1296#if IXANY
1202 else if (info == &mode_info[IDX_decctlq]) { 1297 else if (info == &mode_info[IDX_decctlq]) {
1203 if (reversed) 1298 if (reversed)
@@ -1244,8 +1339,10 @@ static void set_mode(const struct mode_info *info, int reversed,
1244 mode->c_lflag |= ECHOE | ECHOCTL | ECHOKE; 1339 mode->c_lflag |= ECHOE | ECHOCTL | ECHOKE;
1245 if (IXANY) mode->c_iflag &= ~IXANY; 1340 if (IXANY) mode->c_iflag &= ~IXANY;
1246 } 1341 }
1342#endif /*!ENABLE_PLATFORM_MINGW32 */
1247} 1343}
1248 1344
1345#if !ENABLE_PLATFORM_MINGW32
1249static void set_control_char_or_die(const struct control_info *info, 1346static void set_control_char_or_die(const struct control_info *info,
1250 const char *arg, struct termios *mode) 1347 const char *arg, struct termios *mode)
1251{ 1348{
@@ -1265,6 +1362,7 @@ static void set_control_char_or_die(const struct control_info *info,
1265 value = xatoul_range_sfx(arg, 0, 0xff, stty_suffixes); 1362 value = xatoul_range_sfx(arg, 0, 0xff, stty_suffixes);
1266 mode->c_cc[info->offset] = value; 1363 mode->c_cc[info->offset] = value;
1267} 1364}
1365#endif
1268 1366
1269#define STTY_require_set_attr (1 << 0) 1367#define STTY_require_set_attr (1 << 0)
1270#define STTY_speed_was_set (1 << 1) 1368#define STTY_speed_was_set (1 << 1)
@@ -1277,7 +1375,9 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1277{ 1375{
1278 struct termios mode; 1376 struct termios mode;
1279 void (*output_func)(const struct termios *, int); 1377 void (*output_func)(const struct termios *, int);
1378#if !ENABLE_PLATFORM_MINGW32
1280 const char *file_name = NULL; 1379 const char *file_name = NULL;
1380#endif
1281 int display_all = 0; 1381 int display_all = 0;
1282 int stty_state; 1382 int stty_state;
1283 int k; 1383 int k;
@@ -1291,7 +1391,9 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1291 k = 0; 1391 k = 0;
1292 while (argv[++k]) { 1392 while (argv[++k]) {
1293 const struct mode_info *mp; 1393 const struct mode_info *mp;
1394#if !ENABLE_PLATFORM_MINGW32
1294 const struct control_info *cp; 1395 const struct control_info *cp;
1396#endif
1295 const char *arg = argv[k]; 1397 const char *arg = argv[k];
1296 const char *argnext = argv[k+1]; 1398 const char *argnext = argv[k+1];
1297 int param; 1399 int param;
@@ -1314,6 +1416,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1314 output_func = do_display; 1416 output_func = do_display;
1315 display_all = 1; 1417 display_all = 1;
1316 break; 1418 break;
1419#if !ENABLE_PLATFORM_MINGW32
1317 case 'g': 1420 case 'g':
1318 stty_state |= STTY_recoverable_output; 1421 stty_state |= STTY_recoverable_output;
1319 output_func = display_recoverable; 1422 output_func = display_recoverable;
@@ -1334,11 +1437,14 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1334 } 1437 }
1335 } 1438 }
1336 goto end_option; 1439 goto end_option;
1440#endif
1337 default: 1441 default:
1338 goto invalid_argument; 1442 goto invalid_argument;
1339 } 1443 }
1340 } 1444 }
1445#if !ENABLE_PLATFORM_MINGW32
1341 end_option: 1446 end_option:
1447#endif
1342 continue; 1448 continue;
1343 } 1449 }
1344 1450
@@ -1348,6 +1454,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1348 continue; 1454 continue;
1349 } 1455 }
1350 1456
1457#if !ENABLE_PLATFORM_MINGW32
1351 cp = find_control(arg); 1458 cp = find_control(arg);
1352 if (cp) { 1459 if (cp) {
1353 if (!argnext) 1460 if (!argnext)
@@ -1358,6 +1465,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1358 ++k; 1465 ++k;
1359 continue; 1466 continue;
1360 } 1467 }
1468#endif
1361 1469
1362 param = find_param(arg); 1470 param = find_param(arg);
1363 if (param & param_need_arg) { 1471 if (param & param_need_arg) {
@@ -1381,7 +1489,11 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1381 xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes); 1489 xatoul_range_sfx(argnext, 1, INT_MAX, stty_suffixes);
1382 break; 1490 break;
1383 case param_size: 1491 case param_size:
1492# if ENABLE_PLATFORM_MINGW32
1493 break;
1494# endif
1384#endif 1495#endif
1496#if !ENABLE_PLATFORM_MINGW32
1385 case param_speed: 1497 case param_speed:
1386 break; 1498 break;
1387 case param_ispeed: 1499 case param_ispeed:
@@ -1392,15 +1504,19 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1392 /* called for the side effect of xfunc death only */ 1504 /* called for the side effect of xfunc death only */
1393 set_speed_or_die(output_speed, argnext, &mode); 1505 set_speed_or_die(output_speed, argnext, &mode);
1394 break; 1506 break;
1507#endif
1395 default: 1508 default:
1509#if !ENABLE_PLATFORM_MINGW32
1396 if (recover_mode(arg, &mode) == 1) break; 1510 if (recover_mode(arg, &mode) == 1) break;
1397 if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) break; 1511 if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) break;
1512#endif
1398 invalid_argument: 1513 invalid_argument:
1399 bb_error_msg_and_die("invalid argument '%s'", arg); 1514 bb_error_msg_and_die("invalid argument '%s'", arg);
1400 } 1515 }
1401 stty_state &= ~STTY_noargs; 1516 stty_state &= ~STTY_noargs;
1402 } 1517 }
1403 1518
1519#if !ENABLE_PLATFORM_MINGW32
1404 /* Specifying both -a and -g is an error */ 1520 /* Specifying both -a and -g is an error */
1405 if ((stty_state & (STTY_verbose_output | STTY_recoverable_output)) == 1521 if ((stty_state & (STTY_verbose_output | STTY_recoverable_output)) ==
1406 (STTY_verbose_output | STTY_recoverable_output) 1522 (STTY_verbose_output | STTY_recoverable_output)
@@ -1413,13 +1529,22 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1413 ) { 1529 ) {
1414 bb_simple_error_msg_and_die("modes may not be set when -a or -g is used"); 1530 bb_simple_error_msg_and_die("modes may not be set when -a or -g is used");
1415 } 1531 }
1532#else
1533 /* Specifying -a with non-options is an error */
1534 if ((stty_state & STTY_verbose_output) && !(stty_state & STTY_noargs)
1535 ) {
1536 bb_simple_error_msg_and_die("modes may not be set when -a is used");
1537 }
1538#endif
1416 1539
1540#if !ENABLE_PLATFORM_MINGW32
1417 /* Now it is safe to start doing things */ 1541 /* Now it is safe to start doing things */
1418 if (file_name) { 1542 if (file_name) {
1419 G.device_name = file_name; 1543 G.device_name = file_name;
1420 xmove_fd(xopen_nonblocking(G.device_name), STDIN_FILENO); 1544 xmove_fd(xopen_nonblocking(G.device_name), STDIN_FILENO);
1421 ndelay_off(STDIN_FILENO); 1545 ndelay_off(STDIN_FILENO);
1422 } 1546 }
1547#endif
1423 1548
1424 /* Initialize to all zeroes so there is no risk memcmp will report a 1549 /* Initialize to all zeroes so there is no risk memcmp will report a
1425 spurious difference in an uninitialized portion of the structure */ 1550 spurious difference in an uninitialized portion of the structure */
@@ -1437,7 +1562,9 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1437 k = 0; 1562 k = 0;
1438 while (argv[++k]) { 1563 while (argv[++k]) {
1439 const struct mode_info *mp; 1564 const struct mode_info *mp;
1565#if !ENABLE_PLATFORM_MINGW32
1440 const struct control_info *cp; 1566 const struct control_info *cp;
1567#endif
1441 const char *arg = argv[k]; 1568 const char *arg = argv[k];
1442 const char *argnext = argv[k+1]; 1569 const char *argnext = argv[k+1];
1443 int param; 1570 int param;
@@ -1459,6 +1586,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1459 continue; 1586 continue;
1460 } 1587 }
1461 1588
1589#if !ENABLE_PLATFORM_MINGW32
1462 cp = find_control(arg); 1590 cp = find_control(arg);
1463 if (cp) { 1591 if (cp) {
1464 ++k; 1592 ++k;
@@ -1466,6 +1594,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1466 stty_state |= STTY_require_set_attr; 1594 stty_state |= STTY_require_set_attr;
1467 continue; 1595 continue;
1468 } 1596 }
1597#endif
1469 1598
1470 param = find_param(arg); 1599 param = find_param(arg);
1471 if (param & param_need_arg) { 1600 if (param & param_need_arg) {
@@ -1491,6 +1620,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1491 set_window_size(xatoul_sfx(argnext, stty_suffixes), -1); 1620 set_window_size(xatoul_sfx(argnext, stty_suffixes), -1);
1492 break; 1621 break;
1493#endif 1622#endif
1623#if !ENABLE_PLATFORM_MINGW32
1494 case param_speed: 1624 case param_speed:
1495 display_speed(&mode, 0); 1625 display_speed(&mode, 0);
1496 break; 1626 break;
@@ -1502,7 +1632,9 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1502 set_speed_or_die(output_speed, argnext, &mode); 1632 set_speed_or_die(output_speed, argnext, &mode);
1503 stty_state |= (STTY_require_set_attr | STTY_speed_was_set); 1633 stty_state |= (STTY_require_set_attr | STTY_speed_was_set);
1504 break; 1634 break;
1635#endif
1505 default: 1636 default:
1637#if !ENABLE_PLATFORM_MINGW32
1506 if (recover_mode(arg, &mode) == 1) 1638 if (recover_mode(arg, &mode) == 1)
1507 stty_state |= STTY_require_set_attr; 1639 stty_state |= STTY_require_set_attr;
1508 else /* true: if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) */{ 1640 else /* true: if (tty_value_to_baud(xatou(arg)) != (speed_t) -1) */{
@@ -1510,15 +1642,24 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1510 stty_state |= (STTY_require_set_attr | STTY_speed_was_set); 1642 stty_state |= (STTY_require_set_attr | STTY_speed_was_set);
1511 } /* else - impossible (caught in the first pass): 1643 } /* else - impossible (caught in the first pass):
1512 bb_error_msg_and_die("invalid argument '%s'", arg); */ 1644 bb_error_msg_and_die("invalid argument '%s'", arg); */
1645#endif
1513 } 1646 }
1514 } 1647 }
1515 1648
1516 if (stty_state & STTY_require_set_attr) { 1649 if (stty_state & STTY_require_set_attr) {
1650#if !ENABLE_PLATFORM_MINGW32
1517 struct termios new_mode; 1651 struct termios new_mode;
1652#else
1653 if (mode.c_lflag & ECHO)
1654 mode.w_mode |= ENABLE_ECHO_INPUT;
1655 else
1656 mode.w_mode &= ~ENABLE_ECHO_INPUT;
1657#endif
1518 1658
1519 if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode)) 1659 if (tcsetattr(STDIN_FILENO, TCSADRAIN, &mode))
1520 perror_on_device_and_die("%s"); 1660 perror_on_device_and_die("%s");
1521 1661
1662#if !ENABLE_PLATFORM_MINGW32
1522 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if 1663 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1523 it performs *any* of the requested operations. This means it 1664 it performs *any* of the requested operations. This means it
1524 can report 'success' when it has actually failed to perform 1665 can report 'success' when it has actually failed to perform
@@ -1554,6 +1695,7 @@ int stty_main(int argc UNUSED_PARAM, char **argv)
1554#endif 1695#endif
1555 perror_on_device_and_die("%s: cannot perform all requested operations"); 1696 perror_on_device_and_die("%s: cannot perform all requested operations");
1556 } 1697 }
1698#endif
1557 } 1699 }
1558 1700
1559 return EXIT_SUCCESS; 1701 return EXIT_SUCCESS;
diff --git a/coreutils/sum.c b/coreutils/sum.c
index 78e69acc6..7c7cc6b6b 100644
--- a/coreutils/sum.c
+++ b/coreutils/sum.c
@@ -82,9 +82,9 @@ static unsigned sum_file(const char *file, unsigned type)
82 if (type >= SUM_SYSV) { 82 if (type >= SUM_SYSV) {
83 r = (s & 0xffff) + ((s & 0xffffffff) >> 16); 83 r = (s & 0xffff) + ((s & 0xffffffff) >> 16);
84 s = (r & 0xffff) + (r >> 16); 84 s = (r & 0xffff) + (r >> 16);
85 printf("%u %llu %s\n", s, (total_bytes + 511) / 512, file); 85 printf("%u %"LL_FMT"u %s\n", s, (total_bytes + 511) / 512, file);
86 } else 86 } else
87 printf("%05u %5llu %s\n", s, (total_bytes + 1023) / 1024, file); 87 printf("%05u %5"LL_FMT"u %s\n", s, (total_bytes + 1023) / 1024, file);
88 return 1; 88 return 1;
89#undef buf 89#undef buf
90} 90}
diff --git a/coreutils/test.c b/coreutils/test.c
index b63e33cc0..3d38ead00 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -1022,10 +1022,14 @@ int test_main(int argc, char **argv)
1022 1022
1023 info.euid = -1; 1023 info.euid = -1;
1024 info.egid = -1; 1024 info.egid = -1;
1025#if !ENABLE_PLATFORM_MINGW32
1025 info.ngroups = 0; 1026 info.ngroups = 0;
1026 info.supplementary_array = NULL; 1027 info.supplementary_array = NULL;
1028#endif
1027 r = test_main2(&info, argc, argv); 1029 r = test_main2(&info, argc, argv);
1030#if !ENABLE_PLATFORM_MINGW32
1028 free(info.supplementary_array); 1031 free(info.supplementary_array);
1032#endif
1029 1033
1030 return r; 1034 return r;
1031} 1035}
diff --git a/coreutils/timeout.c b/coreutils/timeout.c
index 84299a0a5..58f96192b 100644
--- a/coreutils/timeout.c
+++ b/coreutils/timeout.c
@@ -43,10 +43,35 @@
43//usage:#define timeout_full_usage "\n\n" 43//usage:#define timeout_full_usage "\n\n"
44//usage: "Run PROG. Send 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//usage: IF_PLATFORM_MINGW32("\n")
46//usage: "If it still exists in KILL_SECS seconds, send KILL.\n" 47//usage: "If it still exists in KILL_SECS seconds, send KILL.\n"
47 48
48#include "libbb.h" 49#include "libbb.h"
49 50
51#if ENABLE_PLATFORM_MINGW32
52static HANDLE child = INVALID_HANDLE_VALUE;
53
54static void kill_child(void)
55{
56 if (child != INVALID_HANDLE_VALUE) {
57 pid_t pid = (pid_t)GetProcessId(child);
58 if (pid)
59 kill(pid, SIGTERM);
60 }
61}
62
63/* Return TRUE if child exits before timeout expires */
64static NOINLINE int timeout_wait(duration_t timeout, HANDLE proc, DWORD *status)
65{
66 DWORD t = (DWORD)(timeout * 1000);
67 if (WaitForSingleObject(proc, t) == WAIT_OBJECT_0) {
68 /* process is gone */
69 GetExitCodeProcess(proc, status);
70 return TRUE;
71 }
72 return FALSE;
73}
74#else
50static NOINLINE int timeout_wait(duration_t timeout, pid_t pid) 75static NOINLINE int timeout_wait(duration_t timeout, pid_t pid)
51{ 76{
52 /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */ 77 /* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */
@@ -66,13 +91,19 @@ static NOINLINE int timeout_wait(duration_t timeout, pid_t pid)
66 } 91 }
67 return EXIT_FAILURE; 92 return EXIT_FAILURE;
68} 93}
94#endif
69 95
70int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 96int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
71int timeout_main(int argc UNUSED_PARAM, char **argv) 97int timeout_main(int argc UNUSED_PARAM, char **argv)
72{ 98{
73 int signo; 99 int signo;
100#if !ENABLE_PLATFORM_MINGW32
74 int status; 101 int status;
75 int parent = 0; 102 int parent = 0;
103#else
104 intptr_t ret;
105 DWORD status = EXIT_SUCCESS;
106#endif
76 duration_t timeout; 107 duration_t timeout;
77 duration_t kill_timeout; 108 duration_t kill_timeout;
78 pid_t pid; 109 pid_t pid;
@@ -82,15 +113,27 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
82 const char *opt_s = "TERM"; 113 const char *opt_s = "TERM";
83 char *opt_k = NULL; 114 char *opt_k = NULL;
84 115
116#if ENABLE_PLATFORM_MINGW32
117 xfunc_error_retval = 125;
118#endif
119
85 /* -p option is not documented, it is needed to support NOMMU. */ 120 /* -p option is not documented, it is needed to support NOMMU. */
86 121
87 /* -t SECONDS; -p PARENT_PID */ 122 /* -t SECONDS; -p PARENT_PID */
88 /* '+': stop at first non-option */ 123 /* '+': stop at first non-option */
124#if !ENABLE_PLATFORM_MINGW32
89 getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent); 125 getopt32(argv, "+s:k:" USE_FOR_NOMMU("p:+"), &opt_s, &opt_k, &parent);
126#else
127 getopt32(argv, "+s:k:", &opt_s, &opt_k);
128#endif
90 /*argv += optind; - no, wait for bb_daemonize_or_rexec! */ 129 /*argv += optind; - no, wait for bb_daemonize_or_rexec! */
91 130
92 signo = get_signum(opt_s); 131 signo = get_signum(opt_s);
132#if !ENABLE_PLATFORM_MINGW32
93 if (signo < 0) 133 if (signo < 0)
134#else
135 if (!is_valid_signal(signo))
136#endif
94 bb_error_msg_and_die("unknown signal '%s'", opt_s); 137 bb_error_msg_and_die("unknown signal '%s'", opt_s);
95 138
96 kill_timeout = 0; 139 kill_timeout = 0;
@@ -103,6 +146,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
103 if (!argv[optind]) /* no PROG? */ 146 if (!argv[optind]) /* no PROG? */
104 bb_show_usage(); 147 bb_show_usage();
105 148
149#if !ENABLE_PLATFORM_MINGW32
106 /* We want to create a grandchild which will watch 150 /* We want to create a grandchild which will watch
107 * and kill the grandparent. Other methods: 151 * and kill the grandparent. Other methods:
108 * making parent watch child disrupts parent<->child link 152 * making parent watch child disrupts parent<->child link
@@ -155,4 +199,33 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
155 argv[1] = sv2; 199 argv[1] = sv2;
156#endif 200#endif
157 BB_EXECVP_or_die(argv); 201 BB_EXECVP_or_die(argv);
202#else /* ENABLE_PLATFORM_MINGW32 */
203 argv += optind;
204 if ((ret=mingw_spawn_proc((const char **)argv)) == -1) {
205 xfunc_error_retval = errno == EACCES ? 126 : 127;
206 bb_perror_msg_and_die("can't execute '%s'", argv[0]);
207 }
208
209 child = (HANDLE)ret;
210 atexit(kill_child);
211 if (timeout_wait(timeout, child, &status))
212 goto finish;
213 status = signo == SIGKILL ? 137 : 124;
214
215 pid = (pid_t)GetProcessId(child);
216 if (pid) {
217 kill(pid, signo);
218
219 if (kill_timeout > 0) {
220 if (timeout_wait(kill_timeout, child, &status))
221 goto finish;
222 kill(pid, SIGKILL);
223 status = 137;
224 }
225 }
226 finish:
227 CloseHandle(child);
228 child = INVALID_HANDLE_VALUE;
229 return status;
230#endif
158} 231}
diff --git a/coreutils/truncate.c b/coreutils/truncate.c
index 8826e6b4c..87a47bb09 100644
--- a/coreutils/truncate.c
+++ b/coreutils/truncate.c
@@ -73,6 +73,12 @@ int truncate_main(int argc UNUSED_PARAM, char **argv)
73 * do not report error, exitcode is also 0. 73 * do not report error, exitcode is also 0.
74 */ 74 */
75 } else { 75 } else {
76#if ENABLE_PLATFORM_MINGW32
77 struct stat st;
78
79 if (fstat(fd, &st) == 0 && size > st.st_size)
80 make_sparse(fd, st.st_size, size);
81#endif
76 if (ftruncate(fd, size) == -1) { 82 if (ftruncate(fd, size) == -1) {
77 bb_perror_msg("%s: truncate", *argv); 83 bb_perror_msg("%s: truncate", *argv);
78 ret = EXIT_FAILURE; 84 ret = EXIT_FAILURE;