aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-02-22 10:00:45 +0000
committerRon Yorston <rmy@pobox.com>2016-02-22 10:00:45 +0000
commit371c20c008254a36e7157df6c13dc2e4cf87d6fd (patch)
treea214c03f6617dffa60df2192b312a46c93b7c19f
parentab879a41ab674129ef1593cda181cc8b64d0dadf (diff)
parent3a5cc989025eefe03fda0552b253a4a8f015a761 (diff)
downloadbusybox-w32-371c20c008254a36e7157df6c13dc2e4cf87d6fd.tar.gz
busybox-w32-371c20c008254a36e7157df6c13dc2e4cf87d6fd.tar.bz2
busybox-w32-371c20c008254a36e7157df6c13dc2e4cf87d6fd.zip
Merge branch 'busybox' into merge
-rw-r--r--Config.in10
-rw-r--r--Makefile.flags5
-rw-r--r--coreutils/dd.c78
-rw-r--r--coreutils/dos2unix.c20
-rw-r--r--coreutils/printf.c12
-rw-r--r--coreutils/truncate.c4
-rw-r--r--docs/posix_conformance.txt1
-rw-r--r--editors/patch.c11
-rw-r--r--editors/sed.c11
-rw-r--r--include/libbb.h5
-rw-r--r--include/platform.h6
-rw-r--r--init/init.c28
-rw-r--r--libbb/missing_syscalls.c2
-rw-r--r--libbb/pw_encrypt.c10
-rw-r--r--loginutils/chpasswd.c31
-rw-r--r--loginutils/login.c43
-rw-r--r--miscutils/nandwrite.c22
-rw-r--r--miscutils/setsid.c19
-rw-r--r--modutils/modprobe.c10
-rw-r--r--networking/interface.c1
-rw-r--r--networking/libiproute/iproute.c52
-rw-r--r--networking/ntpd.c54
-rw-r--r--networking/udhcp/dhcpc.c2
-rwxr-xr-xscripts/trylink2
-rw-r--r--shell/ash.c3
-rw-r--r--sysklogd/klogd.c1
-rwxr-xr-xtestsuite/sed.tests6
-rw-r--r--util-linux/blkdiscard.c83
-rw-r--r--util-linux/mount.c10
-rw-r--r--util-linux/swaponoff.c13
-rw-r--r--util-linux/volume_id/bcache.c110
-rw-r--r--util-linux/volume_id/volume_id.c3
-rw-r--r--util-linux/volume_id/volume_id_internal.h2
33 files changed, 530 insertions, 140 deletions
diff --git a/Config.in b/Config.in
index 36ca6447d..a504c745e 100644
--- a/Config.in
+++ b/Config.in
@@ -724,6 +724,16 @@ config DEBUG_PESSIMIZE
724 in a much bigger executable that more closely matches the source 724 in a much bigger executable that more closely matches the source
725 code. 725 code.
726 726
727config DEBUG_SANITIZE
728 bool "Enable runtime sanitizers (ASAN/LSAN/USAN/etc...)"
729 default n
730 help
731 Say Y here if you want to enable runtime sanitizers. These help
732 catch bad memory accesses (e.g. buffer overflows), but will make
733 the executable larger and slow down runtime a bit.
734
735 If you aren't developing/testing busybox, say N here.
736
727config UNIT_TEST 737config UNIT_TEST
728 bool "Build unit tests" 738 bool "Build unit tests"
729 default n 739 default n
diff --git a/Makefile.flags b/Makefile.flags
index c3ac5b458..28034cb07 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -76,6 +76,11 @@ else
76CFLAGS += $(call cc-option,-Os,$(call cc-option,-O2,)) 76CFLAGS += $(call cc-option,-Os,$(call cc-option,-O2,))
77endif 77endif
78endif 78endif
79ifeq ($(CONFIG_DEBUG_SANITIZE),y)
80CFLAGS += $(call cc-option,-fsanitize=address,)
81CFLAGS += $(call cc-option,-fsanitize=leak,)
82CFLAGS += $(call cc-option,-fsanitize=undefined,)
83endif
79 84
80# If arch/$(ARCH)/Makefile did not override it (with, say, -fPIC)... 85# If arch/$(ARCH)/Makefile did not override it (with, say, -fPIC)...
81ARCH_FPIC ?= -fpic 86ARCH_FPIC ?= -fpic
diff --git a/coreutils/dd.c b/coreutils/dd.c
index ccb91f69d..7bd3e2084 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -55,7 +55,7 @@
55 55
56//usage:#define dd_trivial_usage 56//usage:#define dd_trivial_usage
57//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" 57//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n"
58//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") 58//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes]")
59//usage:#define dd_full_usage "\n\n" 59//usage:#define dd_full_usage "\n\n"
60//usage: "Copy a file with converting and formatting\n" 60//usage: "Copy a file with converting and formatting\n"
61//usage: "\n if=FILE Read from FILE instead of stdin" 61//usage: "\n if=FILE Read from FILE instead of stdin"
@@ -76,6 +76,7 @@
76//usage: "\n conv=sync Pad blocks with zeros" 76//usage: "\n conv=sync Pad blocks with zeros"
77//usage: "\n conv=fsync Physically write data out before finishing" 77//usage: "\n conv=fsync Physically write data out before finishing"
78//usage: "\n conv=swab Swap every pair of bytes" 78//usage: "\n conv=swab Swap every pair of bytes"
79//usage: "\n iflag=skip_bytes skip=N is in bytes"
79//usage: ) 80//usage: )
80//usage: IF_FEATURE_DD_STATUS( 81//usage: IF_FEATURE_DD_STATUS(
81//usage: "\n status=noxfer Suppress rate output" 82//usage: "\n status=noxfer Suppress rate output"
@@ -122,11 +123,15 @@ enum {
122 FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, 123 FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS,
123 FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, 124 FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS,
124 /* end of conv flags */ 125 /* end of conv flags */
125 FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, 126 /* start of input flags */
126 FLAG_COUNT = 1 << 6, 127 FLAG_IFLAG_SHIFT = 5,
127 FLAG_STATUS = 1 << 7, 128 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
128 FLAG_STATUS_NONE = 1 << 7, 129 /* end of input flags */
129 FLAG_STATUS_NOXFER = 1 << 8, 130 FLAG_TWOBUFS = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
131 FLAG_COUNT = 1 << 7,
132 FLAG_STATUS = 1 << 8,
133 FLAG_STATUS_NONE = 1 << 9,
134 FLAG_STATUS_NOXFER = 1 << 10,
130}; 135};
131 136
132static void dd_output_status(int UNUSED_PARAM cur_signal) 137static void dd_output_status(int UNUSED_PARAM cur_signal)
@@ -203,18 +208,47 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs,
203# define XATOU_SFX xatoul_sfx 208# define XATOU_SFX xatoul_sfx
204#endif 209#endif
205 210
211#if ENABLE_FEATURE_DD_IBS_OBS
212static int parse_comma_flags(char *val, const char *words, const char *error_in)
213{
214 int flags = 0;
215 while (1) {
216 int n;
217 char *arg;
218 /* find ',', replace them with NUL so we can use val for
219 * index_in_strings() without copying.
220 * We rely on val being non-null, else strchr would fault.
221 */
222 arg = strchr(val, ',');
223 if (arg)
224 *arg = '\0';
225 n = index_in_strings(words, val);
226 if (n < 0)
227 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, error_in);
228 flags |= (1 << n);
229 if (!arg) /* no ',' left, so this was the last specifier */
230 break;
231 *arg = ','; /* to preserve ps listing */
232 val = arg + 1; /* skip this keyword and ',' */
233 }
234 return flags;
235}
236#endif
237
206int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 238int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
207int dd_main(int argc UNUSED_PARAM, char **argv) 239int dd_main(int argc UNUSED_PARAM, char **argv)
208{ 240{
209 static const char keywords[] ALIGN1 = 241 static const char keywords[] ALIGN1 =
210 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0") 242 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0")
211#if ENABLE_FEATURE_DD_IBS_OBS 243#if ENABLE_FEATURE_DD_IBS_OBS
212 "ibs\0""obs\0""conv\0" 244 "ibs\0""obs\0""conv\0""iflag\0"
213#endif 245#endif
214 ; 246 ;
215#if ENABLE_FEATURE_DD_IBS_OBS 247#if ENABLE_FEATURE_DD_IBS_OBS
216 static const char conv_words[] ALIGN1 = 248 static const char conv_words[] ALIGN1 =
217 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; 249 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
250 static const char iflag_words[] ALIGN1 =
251 "skip_bytes\0";
218#endif 252#endif
219#if ENABLE_FEATURE_DD_STATUS 253#if ENABLE_FEATURE_DD_STATUS
220 static const char status_words[] ALIGN1 = 254 static const char status_words[] ALIGN1 =
@@ -232,6 +266,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
232 OP_ibs, 266 OP_ibs,
233 OP_obs, 267 OP_obs,
234 OP_conv, 268 OP_conv,
269 OP_iflag,
235 /* Must be in the same order as FLAG_XXX! */ 270 /* Must be in the same order as FLAG_XXX! */
236 OP_conv_notrunc = 0, 271 OP_conv_notrunc = 0,
237 OP_conv_sync, 272 OP_conv_sync,
@@ -251,6 +286,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
251 //ibm from ASCII to alternate EBCDIC 286 //ibm from ASCII to alternate EBCDIC
252 /* Partially implemented: */ 287 /* Partially implemented: */
253 //swab swap every pair of input bytes: will abort on non-even reads 288 //swab swap every pair of input bytes: will abort on non-even reads
289 OP_iflag_skip_bytes,
254#endif 290#endif
255 }; 291 };
256 smallint exitcode = EXIT_FAILURE; 292 smallint exitcode = EXIT_FAILURE;
@@ -316,24 +352,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
316 /*continue;*/ 352 /*continue;*/
317 } 353 }
318 if (what == OP_conv) { 354 if (what == OP_conv) {
319 while (1) { 355 G.flags |= parse_comma_flags(val, conv_words, "conv");
320 int n; 356 /*continue;*/
321 /* find ',', replace them with NUL so we can use val for 357 }
322 * index_in_strings() without copying. 358 if (what == OP_iflag) {
323 * We rely on val being non-null, else strchr would fault. 359 G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT;
324 */
325 arg = strchr(val, ',');
326 if (arg)
327 *arg = '\0';
328 n = index_in_strings(conv_words, val);
329 if (n < 0)
330 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, "conv");
331 G.flags |= (1 << n);
332 if (!arg) /* no ',' left, so this was the last specifier */
333 break;
334 /* *arg = ','; - to preserve ps listing? */
335 val = arg + 1; /* skip this keyword and ',' */
336 }
337 /*continue;*/ 360 /*continue;*/
338 } 361 }
339#endif 362#endif
@@ -427,9 +450,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
427 outfile = bb_msg_standard_output; 450 outfile = bb_msg_standard_output;
428 } 451 }
429 if (skip && !devzero) { 452 if (skip && !devzero) {
430 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { 453 size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs;
454 if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) {
431 do { 455 do {
432 ssize_t n = safe_read(ifd, ibuf, ibs); 456 ssize_t n = safe_read(ifd, ibuf, blocksz);
433 if (n < 0) 457 if (n < 0)
434 goto die_infile; 458 goto die_infile;
435 if (n == 0) 459 if (n == 0)
diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c
index 07398bdfa..ccb74a113 100644
--- a/coreutils/dos2unix.c
+++ b/coreutils/dos2unix.c
@@ -41,7 +41,7 @@ enum {
41static void convert(char *fn, int conv_type) 41static void convert(char *fn, int conv_type)
42{ 42{
43 FILE *in, *out; 43 FILE *in, *out;
44 int i; 44 int ch;
45 char *temp_fn = temp_fn; /* for compiler */ 45 char *temp_fn = temp_fn; /* for compiler */
46 char *resolved_fn = resolved_fn; 46 char *resolved_fn = resolved_fn;
47 47
@@ -49,28 +49,30 @@ static void convert(char *fn, int conv_type)
49 out = stdout; 49 out = stdout;
50 if (fn != NULL) { 50 if (fn != NULL) {
51 struct stat st; 51 struct stat st;
52 int fd;
52 53
53 resolved_fn = xmalloc_follow_symlinks(fn); 54 resolved_fn = xmalloc_follow_symlinks(fn);
54 if (resolved_fn == NULL) 55 if (resolved_fn == NULL)
55 bb_simple_perror_msg_and_die(fn); 56 bb_simple_perror_msg_and_die(fn);
56 in = xfopen_for_read(resolved_fn); 57 in = xfopen_for_read(resolved_fn);
57 fstat(fileno(in), &st); 58 xfstat(fileno(in), &st, resolved_fn);
58 59
59 temp_fn = xasprintf("%sXXXXXX", resolved_fn); 60 temp_fn = xasprintf("%sXXXXXX", resolved_fn);
60 i = xmkstemp(temp_fn); 61 fd = xmkstemp(temp_fn);
61 if (fchmod(i, st.st_mode) == -1) 62 if (fchmod(fd, st.st_mode) == -1)
62 bb_simple_perror_msg_and_die(temp_fn); 63 bb_simple_perror_msg_and_die(temp_fn);
64 fchown(fd, st.st_uid, st.st_gid);
63 65
64 out = xfdopen_for_write(i); 66 out = xfdopen_for_write(fd);
65 } 67 }
66 68
67 while ((i = fgetc(in)) != EOF) { 69 while ((ch = fgetc(in)) != EOF) {
68 if (i == '\r') 70 if (ch == '\r')
69 continue; 71 continue;
70 if (i == '\n') 72 if (ch == '\n')
71 if (conv_type == CT_UNIX2DOS) 73 if (conv_type == CT_UNIX2DOS)
72 fputc('\r', out); 74 fputc('\r', out);
73 fputc(i, out); 75 fputc(ch, out);
74 } 76 }
75 77
76 if (fn != NULL) { 78 if (fn != NULL) {
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 3dd43a978..9ee7350d0 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -131,8 +131,8 @@ static double my_xstrtod(const char *arg)
131 return result; 131 return result;
132} 132}
133 133
134/* Handles %b */ 134/* Handles %b; return 1 if output is to be short-circuited by \c */
135static void print_esc_string(const char *str) 135static int print_esc_string(const char *str)
136{ 136{
137 char c; 137 char c;
138 while ((c = *str) != '\0') { 138 while ((c = *str) != '\0') {
@@ -145,6 +145,9 @@ static void print_esc_string(const char *str)
145 str++; 145 str++;
146 } 146 }
147 } 147 }
148 else if (*str == 'c') {
149 return 1;
150 }
148 { 151 {
149 /* optimization: don't force arg to be on-stack, 152 /* optimization: don't force arg to be on-stack,
150 * use another variable for that. */ 153 * use another variable for that. */
@@ -155,6 +158,8 @@ static void print_esc_string(const char *str)
155 } 158 }
156 putchar(c); 159 putchar(c);
157 } 160 }
161
162 return 0;
158} 163}
159 164
160static void print_direc(char *format, unsigned fmt_length, 165static void print_direc(char *format, unsigned fmt_length,
@@ -280,7 +285,8 @@ static char **print_formatted(char *f, char **argv, int *conv_err)
280 } 285 }
281 if (*f == 'b') { 286 if (*f == 'b') {
282 if (*argv) { 287 if (*argv) {
283 print_esc_string(*argv); 288 if (print_esc_string(*argv))
289 return saved_argv; /* causes main() to exit */
284 ++argv; 290 ++argv;
285 } 291 }
286 break; 292 break;
diff --git a/coreutils/truncate.c b/coreutils/truncate.c
index e5fa656c8..8d845f218 100644
--- a/coreutils/truncate.c
+++ b/coreutils/truncate.c
@@ -40,7 +40,7 @@ int truncate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
40int truncate_main(int argc UNUSED_PARAM, char **argv) 40int truncate_main(int argc UNUSED_PARAM, char **argv)
41{ 41{
42 unsigned opts; 42 unsigned opts;
43 int flags = O_RDWR; 43 int flags = O_WRONLY | O_NONBLOCK;
44 int ret = EXIT_SUCCESS; 44 int ret = EXIT_SUCCESS;
45 char *size_str; 45 char *size_str;
46 off_t size; 46 off_t size;
@@ -64,7 +64,7 @@ int truncate_main(int argc UNUSED_PARAM, char **argv)
64 64
65 argv += optind; 65 argv += optind;
66 while (*argv) { 66 while (*argv) {
67 int fd = open(*argv, flags); 67 int fd = open(*argv, flags, 0666);
68 if (fd < 0) { 68 if (fd < 0) {
69 if (errno != ENOENT || !(opts & OPT_NOCREATE)) { 69 if (errno != ENOENT || !(opts & OPT_NOCREATE)) {
70 bb_perror_msg("%s: open", *argv); 70 bb_perror_msg("%s: open", *argv);
diff --git a/docs/posix_conformance.txt b/docs/posix_conformance.txt
index 5b616d701..c0582dc23 100644
--- a/docs/posix_conformance.txt
+++ b/docs/posix_conformance.txt
@@ -178,6 +178,7 @@ dd POSIX options:
178 conv=noerror | yes | | 178 conv=noerror | yes | |
179 conv=notrunc | yes | | 179 conv=notrunc | yes | |
180 conv=sync | yes | | 180 conv=sync | yes | |
181 iflag=skip_bytes| yes | |
181dd Busybox specific options: 182dd Busybox specific options:
182 conv=fsync 183 conv=fsync
183 184
diff --git a/editors/patch.c b/editors/patch.c
index cb25e4140..988021d77 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -372,10 +372,6 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
372 xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO); 372 xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO);
373 } 373 }
374 } 374 }
375 if (argv[0]) {
376 oldname = xstrdup(argv[0]);
377 newname = xstrdup(argv[0]);
378 }
379 375
380 // Loop through the lines in the patch 376 // Loop through the lines in the patch
381 for(;;) { 377 for(;;) {
@@ -486,10 +482,10 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
486 // or if new hunk is empty (zero context) after patching 482 // or if new hunk is empty (zero context) after patching
487 if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) { 483 if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) {
488 name = reverse ? newname : oldname; 484 name = reverse ? newname : oldname;
489 empty++; 485 empty = 1;
490 } 486 }
491 487
492 // handle -p path truncation. 488 // Handle -p path truncation.
493 for (i = 0, s = name; *s;) { 489 for (i = 0, s = name; *s;) {
494 if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i) 490 if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i)
495 break; 491 break;
@@ -500,6 +496,9 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
500 i++; 496 i++;
501 name = s; 497 name = s;
502 } 498 }
499 // If "patch FILE_TO_PATCH", completely ignore name from patch
500 if (argv[0])
501 name = argv[0];
503 502
504 if (empty) { 503 if (empty) {
505 // File is empty after the patches have been applied 504 // File is empty after the patches have been applied
diff --git a/editors/sed.c b/editors/sed.c
index a8c35388b..4c7f75521 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -113,7 +113,7 @@ typedef struct sed_cmd_s {
113 int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($). -2-N = +N */ 113 int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($). -2-N = +N */
114 int end_line_orig; 114 int end_line_orig;
115 115
116 FILE *sw_file; /* File (sw) command writes to, -1 for none. */ 116 FILE *sw_file; /* File (sw) command writes to, NULL for none. */
117 char *string; /* Data string for (saicytb) commands. */ 117 char *string; /* Data string for (saicytb) commands. */
118 118
119 unsigned which_match; /* (s) Which match to replace (0 for all) */ 119 unsigned which_match; /* (s) Which match to replace (0 for all) */
@@ -179,7 +179,7 @@ static void sed_free_and_close_stuff(void)
179 sed_cmd_t *sed_cmd_next = sed_cmd->next; 179 sed_cmd_t *sed_cmd_next = sed_cmd->next;
180 180
181 if (sed_cmd->sw_file) 181 if (sed_cmd->sw_file)
182 xprint_and_close_file(sed_cmd->sw_file); 182 fclose(sed_cmd->sw_file);
183 183
184 if (sed_cmd->beg_match) { 184 if (sed_cmd->beg_match) {
185 regfree(sed_cmd->beg_match); 185 regfree(sed_cmd->beg_match);
@@ -426,8 +426,11 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
426 /* Write to file */ 426 /* Write to file */
427 case 'w': 427 case 'w':
428 { 428 {
429 char *temp; 429 char *fname;
430 idx += parse_file_cmd(/*sed_cmd,*/ substr+idx, &temp); 430 idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname);
431 sed_cmd->sw_file = xfopen_for_write(fname);
432 sed_cmd->sw_last_char = '\n';
433 free(fname);
431 break; 434 break;
432 } 435 }
433 /* Ignore case (gnu exension) */ 436 /* Ignore case (gnu exension) */
diff --git a/include/libbb.h b/include/libbb.h
index 7959884e3..cb61faad9 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -20,6 +20,7 @@
20#include <netdb.h> 20#include <netdb.h>
21#include <setjmp.h> 21#include <setjmp.h>
22#include <signal.h> 22#include <signal.h>
23#include <paths.h>
23#if defined __UCLIBC__ /* TODO: and glibc? */ 24#if defined __UCLIBC__ /* TODO: and glibc? */
24/* use inlined versions of these: */ 25/* use inlined versions of these: */
25# define sigfillset(s) __sigfillset(s) 26# define sigfillset(s) __sigfillset(s)
@@ -106,7 +107,11 @@
106# define updwtmpx updwtmp 107# define updwtmpx updwtmp
107# define _PATH_UTMPX _PATH_UTMP 108# define _PATH_UTMPX _PATH_UTMP
108# else 109# else
110# include <utmp.h>
109# include <utmpx.h> 111# include <utmpx.h>
112# if defined _PATH_UTMP && !defined _PATH_UTMPX
113# define _PATH_UTMPX _PATH_UTMP
114# endif
110# endif 115# endif
111#endif 116#endif
112#if ENABLE_LOCALE_SUPPORT 117#if ENABLE_LOCALE_SUPPORT
diff --git a/include/platform.h b/include/platform.h
index 1cbffc102..94368539e 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -517,9 +517,13 @@ typedef unsigned smalluint;
517 517
518#if defined(ANDROID) || defined(__ANDROID__) 518#if defined(ANDROID) || defined(__ANDROID__)
519# if __ANDROID_API__ < 8 519# if __ANDROID_API__ < 8
520 /* ANDROID < 8 has no [f]dprintf at all */
520# undef HAVE_DPRINTF 521# undef HAVE_DPRINTF
521# else 522# elif __ANDROID_API__ < 21
523 /* ANDROID < 21 has fdprintf */
522# define dprintf fdprintf 524# define dprintf fdprintf
525# else
526 /* ANDROID >= 21 has standard dprintf */
523# endif 527# endif
524# if __ANDROID_API__ < 21 528# if __ANDROID_API__ < 21
525# undef HAVE_TTYNAME_R 529# undef HAVE_TTYNAME_R
diff --git a/init/init.c b/init/init.c
index 80c5d0f74..25bfaec8c 100644
--- a/init/init.c
+++ b/init/init.c
@@ -102,6 +102,21 @@
102//config: 102//config:
103//config: Note that on Linux, init attempts to detect serial terminal and 103//config: Note that on Linux, init attempts to detect serial terminal and
104//config: sets TERM to "vt102" if one is found. 104//config: sets TERM to "vt102" if one is found.
105//config:
106//config:config FEATURE_INIT_MODIFY_CMDLINE
107//config: bool "Modify the command-line to \"init\""
108//config: default y
109//config: depends on INIT
110//config: help
111//config: When launched as PID 1 and after parsing its arguments, init
112//config: wipes all the arguments but argv[0] and rewrites argv[0] to
113//config: contain only "init", so that its command-line appears solely as
114//config: "init" in tools such as ps.
115//config: If this option is set to Y, init will keep its original behavior,
116//config: otherwise, all the arguments including argv[0] will be preserved,
117//config: be they parsed or ignored by init.
118//config: The original command-line used to launch init can then be
119//config: retrieved in /proc/1/cmdline on Linux, for example.
105 120
106//applet:IF_INIT(APPLET(init, BB_DIR_SBIN, BB_SUID_DROP)) 121//applet:IF_INIT(APPLET(init, BB_DIR_SBIN, BB_SUID_DROP))
107//applet:IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc)) 122//applet:IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc))
@@ -112,7 +127,6 @@
112 127
113#include "libbb.h" 128#include "libbb.h"
114#include <syslog.h> 129#include <syslog.h>
115#include <paths.h>
116#include <sys/resource.h> 130#include <sys/resource.h>
117#ifdef __linux__ 131#ifdef __linux__
118# include <linux/vt.h> 132# include <linux/vt.h>
@@ -1139,11 +1153,13 @@ int init_main(int argc UNUSED_PARAM, char **argv)
1139 } 1153 }
1140#endif 1154#endif
1141 1155
1142 /* Make the command line just say "init" - thats all, nothing else */ 1156 if (ENABLE_FEATURE_INIT_MODIFY_CMDLINE) {
1143 strncpy(argv[0], "init", strlen(argv[0])); 1157 /* Make the command line just say "init" - that's all, nothing else */
1144 /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */ 1158 strncpy(argv[0], "init", strlen(argv[0]));
1145 while (*++argv) 1159 /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
1146 nuke_str(*argv); 1160 while (*++argv)
1161 nuke_str(*argv);
1162 }
1147 1163
1148 /* Set up signal handlers */ 1164 /* Set up signal handlers */
1149 if (!DEBUG_INIT) { 1165 if (!DEBUG_INIT) {
diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c
index e3c1e924b..093412811 100644
--- a/libbb/missing_syscalls.c
+++ b/libbb/missing_syscalls.c
@@ -40,8 +40,10 @@ int pivot_root(const char *new_root, const char *put_old)
40 return syscall(__NR_pivot_root, new_root, put_old); 40 return syscall(__NR_pivot_root, new_root, put_old);
41} 41}
42 42
43# if __ANDROID_API__ < 21
43int tcdrain(int fd) 44int tcdrain(int fd)
44{ 45{
45 return ioctl(fd, TCSBRK, 1); 46 return ioctl(fd, TCSBRK, 1);
46} 47}
48# endif
47#endif 49#endif
diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c
index bfc7030a8..dbc15e5fc 100644
--- a/libbb/pw_encrypt.c
+++ b/libbb/pw_encrypt.c
@@ -52,14 +52,18 @@ char* FAST_FUNC crypt_make_pw_salt(char salt[MAX_PW_SALT_LEN], const char *algo)
52{ 52{
53 int len = 2/2; 53 int len = 2/2;
54 char *salt_ptr = salt; 54 char *salt_ptr = salt;
55 if (algo[0] != 'd') { /* not des */ 55
56 /* Standard chpasswd uses uppercase algos ("MD5", not "md5").
57 * Need to be case-insensitive in the code below.
58 */
59 if ((algo[0]|0x20) != 'd') { /* not des */
56 len = 8/2; /* so far assuming md5 */ 60 len = 8/2; /* so far assuming md5 */
57 *salt_ptr++ = '$'; 61 *salt_ptr++ = '$';
58 *salt_ptr++ = '1'; 62 *salt_ptr++ = '1';
59 *salt_ptr++ = '$'; 63 *salt_ptr++ = '$';
60#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA 64#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
61 if (algo[0] == 's') { /* sha */ 65 if ((algo[0]|0x20) == 's') { /* sha */
62 salt[1] = '5' + (strcmp(algo, "sha512") == 0); 66 salt[1] = '5' + (strcasecmp(algo, "sha512") == 0);
63 len = 16/2; 67 len = 16/2;
64 } 68 }
65#endif 69#endif
diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c
index 6c41d17be..a022a42d6 100644
--- a/loginutils/chpasswd.c
+++ b/loginutils/chpasswd.c
@@ -24,26 +24,27 @@
24//kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o 24//kbuild:lib-$(CONFIG_CHPASSWD) += chpasswd.o
25 25
26//usage:#define chpasswd_trivial_usage 26//usage:#define chpasswd_trivial_usage
27//usage: IF_LONG_OPTS("[--md5|--encrypted]") IF_NOT_LONG_OPTS("[-m|-e]") 27//usage: IF_LONG_OPTS("[--md5|--encrypted|--crypt-method]") IF_NOT_LONG_OPTS("[-m|-e|-c]")
28//usage:#define chpasswd_full_usage "\n\n" 28//usage:#define chpasswd_full_usage "\n\n"
29//usage: "Read user:password from stdin and update /etc/passwd\n" 29//usage: "Read user:password from stdin and update /etc/passwd\n"
30//usage: IF_LONG_OPTS( 30//usage: IF_LONG_OPTS(
31//usage: "\n -e,--encrypted Supplied passwords are in encrypted form" 31//usage: "\n -e,--encrypted Supplied passwords are in encrypted form"
32//usage: "\n -m,--md5 Use MD5 encryption instead of DES" 32//usage: "\n -m,--md5 Use MD5 encryption instead of DES"
33//usage: "\n -c,--crypt-method Use the specified method to encrypt the passwords"
33//usage: ) 34//usage: )
34//usage: IF_NOT_LONG_OPTS( 35//usage: IF_NOT_LONG_OPTS(
35//usage: "\n -e Supplied passwords are in encrypted form" 36//usage: "\n -e Supplied passwords are in encrypted form"
36//usage: "\n -m Use MD5 encryption instead of DES" 37//usage: "\n -m Use MD5 encryption instead of DES"
38//usage: "\n -c Use the specified method to encrypt the passwords"
37//usage: ) 39//usage: )
38 40
39//TODO: implement -c ALGO
40
41#include "libbb.h" 41#include "libbb.h"
42 42
43#if ENABLE_LONG_OPTS 43#if ENABLE_LONG_OPTS
44static const char chpasswd_longopts[] ALIGN1 = 44static const char chpasswd_longopts[] ALIGN1 =
45 "encrypted\0" No_argument "e" 45 "encrypted\0" No_argument "e"
46 "md5\0" No_argument "m" 46 "md5\0" No_argument "m"
47 "crypt-method\0" Required_argument "c"
47 ; 48 ;
48#endif 49#endif
49 50
@@ -54,14 +55,15 @@ int chpasswd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
54int chpasswd_main(int argc UNUSED_PARAM, char **argv) 55int chpasswd_main(int argc UNUSED_PARAM, char **argv)
55{ 56{
56 char *name; 57 char *name;
58 const char *algo = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO;
57 int opt; 59 int opt;
58 60
59 if (getuid() != 0) 61 if (getuid() != 0)
60 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); 62 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
61 63
62 opt_complementary = "m--e:e--m"; 64 opt_complementary = "m--ec:e--mc:c--em";
63 IF_LONG_OPTS(applet_long_options = chpasswd_longopts;) 65 IF_LONG_OPTS(applet_long_options = chpasswd_longopts;)
64 opt = getopt32(argv, "em"); 66 opt = getopt32(argv, "emc:", &algo);
65 67
66 while ((name = xmalloc_fgetline(stdin)) != NULL) { 68 while ((name = xmalloc_fgetline(stdin)) != NULL) {
67 char *free_me; 69 char *free_me;
@@ -77,15 +79,14 @@ int chpasswd_main(int argc UNUSED_PARAM, char **argv)
77 79
78 free_me = NULL; 80 free_me = NULL;
79 if (!(opt & OPT_ENC)) { 81 if (!(opt & OPT_ENC)) {
80 char salt[sizeof("$N$XXXXXXXX")]; 82 char salt[MAX_PW_SALT_LEN];
81 83
82 crypt_make_salt(salt, 1);
83 if (opt & OPT_MD5) { 84 if (opt & OPT_MD5) {
84 salt[0] = '$'; 85 /* Force MD5 if the -m flag is set */
85 salt[1] = '1'; 86 algo = "md5";
86 salt[2] = '$';
87 crypt_make_salt(salt + 3, 4);
88 } 87 }
88
89 crypt_make_pw_salt(salt, algo);
89 free_me = pass = pw_encrypt(pass, salt, 0); 90 free_me = pass = pw_encrypt(pass, salt, 0);
90 } 91 }
91 92
diff --git a/loginutils/login.c b/loginutils/login.c
index 67fe82e86..4ebc18502 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -78,6 +78,49 @@
78 * Apparently they like to confuse people. */ 78 * Apparently they like to confuse people. */
79# include <security/pam_appl.h> 79# include <security/pam_appl.h>
80# include <security/pam_misc.h> 80# include <security/pam_misc.h>
81
82# if 0
83/* This supposedly can be used to avoid double password prompt,
84 * if used instead of standard misc_conv():
85 *
86 * "When we want to authenticate first with local method and then with tacacs for example,
87 * the password is asked for local method and if not good is asked a second time for tacacs.
88 * So if we want to authenticate a user with tacacs, and the user exists localy, the password is
89 * asked two times before authentication is accepted."
90 *
91 * However, code looks shaky. For example, why misc_conv() return value is ignored?
92 * Are msg[i] and resp[i] indexes handled correctly?
93 */
94static char *passwd = NULL;
95static int my_conv(int num_msg, const struct pam_message **msg,
96 struct pam_response **resp, void *data)
97{
98 int i;
99 for (i = 0; i < num_msg; i++) {
100 switch (msg[i]->msg_style) {
101 case PAM_PROMPT_ECHO_OFF:
102 if (passwd == NULL) {
103 misc_conv(num_msg, msg, resp, data);
104 passwd = xstrdup(resp[i]->resp);
105 return PAM_SUCCESS;
106 }
107
108 resp[0] = xzalloc(sizeof(struct pam_response));
109 resp[0]->resp = passwd;
110 passwd = NULL;
111 resp[0]->resp_retcode = PAM_SUCCESS;
112 resp[1] = NULL;
113 return PAM_SUCCESS;
114
115 default:
116 break;
117 }
118 }
119
120 return PAM_SUCCESS;
121}
122# endif
123
81static const struct pam_conv conv = { 124static const struct pam_conv conv = {
82 misc_conv, 125 misc_conv,
83 NULL 126 NULL
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
index 247fc72f4..c95cbb21e 100644
--- a/miscutils/nandwrite.c
+++ b/miscutils/nandwrite.c
@@ -29,16 +29,18 @@
29//kbuild:lib-$(CONFIG_NANDDUMP) += nandwrite.o 29//kbuild:lib-$(CONFIG_NANDDUMP) += nandwrite.o
30 30
31//usage:#define nandwrite_trivial_usage 31//usage:#define nandwrite_trivial_usage
32//usage: "[-p] [-s ADDR] MTD_DEVICE [FILE]" 32//usage: "[-np] [-s ADDR] MTD_DEVICE [FILE]"
33//usage:#define nandwrite_full_usage "\n\n" 33//usage:#define nandwrite_full_usage "\n\n"
34//usage: "Write to MTD_DEVICE\n" 34//usage: "Write to MTD_DEVICE\n"
35//usage: "\n -n Write without ecc"
35//usage: "\n -p Pad to page size" 36//usage: "\n -p Pad to page size"
36//usage: "\n -s ADDR Start address" 37//usage: "\n -s ADDR Start address"
37 38
38//usage:#define nanddump_trivial_usage 39//usage:#define nanddump_trivial_usage
39//usage: "[-o]" IF_LONG_OPTS(" [--bb=padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE" 40//usage: "[-no]" IF_LONG_OPTS(" [--bb=padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE"
40//usage:#define nanddump_full_usage "\n\n" 41//usage:#define nanddump_full_usage "\n\n"
41//usage: "Dump MTD_DEVICE\n" 42//usage: "Dump MTD_DEVICE\n"
43//usage: "\n -n Read without ecc"
42//usage: "\n -o Dump oob data" 44//usage: "\n -o Dump oob data"
43//usage: "\n -s ADDR Start address" 45//usage: "\n -s ADDR Start address"
44//usage: "\n -l LEN Length" 46//usage: "\n -l LEN Length"
@@ -57,10 +59,11 @@
57 59
58#define OPT_p (1 << 0) /* nandwrite only */ 60#define OPT_p (1 << 0) /* nandwrite only */
59#define OPT_o (1 << 0) /* nanddump only */ 61#define OPT_o (1 << 0) /* nanddump only */
60#define OPT_s (1 << 1) 62#define OPT_n (1 << 1)
61#define OPT_f (1 << 2) 63#define OPT_s (1 << 2)
62#define OPT_l (1 << 3) 64#define OPT_f (1 << 3)
63#define OPT_bb (1 << 4) /* must be the last one in the list */ 65#define OPT_l (1 << 4)
66#define OPT_bb (1 << 5) /* must be the last one in the list */
64 67
65#define BB_PADBAD (1 << 0) 68#define BB_PADBAD (1 << 0)
66#define BB_SKIPBAD (1 << 1) 69#define BB_SKIPBAD (1 << 1)
@@ -125,10 +128,10 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
125 applet_long_options = 128 applet_long_options =
126 "bb\0" Required_argument "\xff"; /* no short equivalent */ 129 "bb\0" Required_argument "\xff"; /* no short equivalent */
127#endif 130#endif
128 opts = getopt32(argv, "os:f:l:", &opt_s, &opt_f, &opt_l, &opt_bb); 131 opts = getopt32(argv, "ons:f:l:", &opt_s, &opt_f, &opt_l, &opt_bb);
129 } else { /* nandwrite */ 132 } else { /* nandwrite */
130 opt_complementary = "-1:?2"; 133 opt_complementary = "-1:?2";
131 opts = getopt32(argv, "ps:", &opt_s); 134 opts = getopt32(argv, "pns:", &opt_s);
132 } 135 }
133 argv += optind; 136 argv += optind;
134 137
@@ -144,6 +147,9 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
144 fd = xopen(argv[0], IS_NANDWRITE ? O_RDWR : O_RDONLY); 147 fd = xopen(argv[0], IS_NANDWRITE ? O_RDWR : O_RDONLY);
145 xioctl(fd, MEMGETINFO, &meminfo); 148 xioctl(fd, MEMGETINFO, &meminfo);
146 149
150 if (opts & OPT_n)
151 xioctl(fd, MTDFILEMODE, (void *)MTD_FILE_MODE_RAW);
152
147 mtdoffset = xstrtou(opt_s, 0); 153 mtdoffset = xstrtou(opt_s, 0);
148 if (IS_NANDDUMP && (opts & OPT_l)) { 154 if (IS_NANDDUMP && (opts & OPT_l)) {
149 unsigned length = xstrtou(opt_l, 0); 155 unsigned length = xstrtou(opt_l, 0);
diff --git a/miscutils/setsid.c b/miscutils/setsid.c
index 637081b6c..1b27377b2 100644
--- a/miscutils/setsid.c
+++ b/miscutils/setsid.c
@@ -15,19 +15,22 @@
15 */ 15 */
16 16
17//usage:#define setsid_trivial_usage 17//usage:#define setsid_trivial_usage
18//usage: "PROG ARGS" 18//usage: "[-c] PROG ARGS"
19//usage:#define setsid_full_usage "\n\n" 19//usage:#define setsid_full_usage "\n\n"
20//usage: "Run PROG in a new session. PROG will have no controlling terminal\n" 20//usage: "Run PROG in a new session. PROG will have no controlling terminal\n"
21//usage: "and will not be affected by keyboard signals (Ctrl-C etc).\n" 21//usage: "and will not be affected by keyboard signals (^C etc).\n"
22//usage: "See setsid(2) for details." 22//usage: "\n -c Set controlling terminal to stdin"
23 23
24#include "libbb.h" 24#include "libbb.h"
25 25
26int setsid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 26int setsid_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
27int setsid_main(int argc UNUSED_PARAM, char **argv) 27int setsid_main(int argc UNUSED_PARAM, char **argv)
28{ 28{
29 if (!argv[1]) 29 unsigned opt;
30 bb_show_usage(); 30
31 opt_complementary = "-1"; /* at least one arg */
32 opt = getopt32(argv, "c");
33 argv += optind;
31 34
32 /* setsid() is allowed only when we are not a process group leader. 35 /* setsid() is allowed only when we are not a process group leader.
33 * Otherwise our PID serves as PGID of some existing process group 36 * Otherwise our PID serves as PGID of some existing process group
@@ -61,6 +64,10 @@ int setsid_main(int argc UNUSED_PARAM, char **argv)
61 setsid(); 64 setsid();
62 } 65 }
63 66
64 argv++; 67 if (opt) {
68 /* -c: set (with stealing) controlling tty */
69 ioctl(0, TIOCSCTTY, 1);
70 }
71
65 BB_EXECVP_or_die(argv); 72 BB_EXECVP_or_die(argv);
66} 73}
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index ec490b74d..997ee3c67 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -220,8 +220,16 @@ static int FAST_FUNC config_file_action(const char *filename,
220 parser_t *p; 220 parser_t *p;
221 struct module_entry *m; 221 struct module_entry *m;
222 int rc = TRUE; 222 int rc = TRUE;
223 const char *base, *ext;
223 224
224 if (bb_basename(filename)[0] == '.') 225 /* Skip files that begin with a ".". */
226 base = bb_basename(filename);
227 if (base[0] == '.')
228 goto error;
229
230 /* Skip files that do not end with a ".conf". */
231 ext = strrchr(base, '.');
232 if (ext == NULL || strcmp(ext + 1, "conf"))
225 goto error; 233 goto error;
226 234
227 p = config_open2(filename, fopen_for_read); 235 p = config_open2(filename, fopen_for_read);
diff --git a/networking/interface.c b/networking/interface.c
index 24bd13c57..e5723b428 100644
--- a/networking/interface.c
+++ b/networking/interface.c
@@ -881,6 +881,7 @@ static void ife_print6(struct interface *ptr)
881 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", 881 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
882 addr6p[0], addr6p[1], addr6p[2], addr6p[3], 882 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
883 addr6p[4], addr6p[5], addr6p[6], addr6p[7]); 883 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
884 memset(&sap, 0, sizeof(sap));
884 inet_pton(AF_INET6, addr6, 885 inet_pton(AF_INET6, addr6,
885 (struct sockaddr *) &sap.sin6_addr); 886 (struct sockaddr *) &sap.sin6_addr);
886 sap.sin6_family = AF_INET6; 887 sap.sin6_family = AF_INET6;
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c
index d232ee6fd..82827488f 100644
--- a/networking/libiproute/iproute.c
+++ b/networking/libiproute/iproute.c
@@ -313,12 +313,13 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
313static int iproute_modify(int cmd, unsigned flags, char **argv) 313static int iproute_modify(int cmd, unsigned flags, char **argv)
314{ 314{
315 static const char keywords[] ALIGN1 = 315 static const char keywords[] ALIGN1 =
316 "src\0""via\0""mtu\0""lock\0""protocol\0"IF_FEATURE_IP_RULE("table\0") 316 "src\0""via\0""mtu\0""lock\0""scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0")
317 "dev\0""oif\0""to\0""metric\0""onlink\0"; 317 "dev\0""oif\0""to\0""metric\0""onlink\0";
318 enum { 318 enum {
319 ARG_src, 319 ARG_src,
320 ARG_via, 320 ARG_via,
321 ARG_mtu, PARM_lock, 321 ARG_mtu, PARM_lock,
322 ARG_scope,
322 ARG_protocol, 323 ARG_protocol,
323IF_FEATURE_IP_RULE(ARG_table,) 324IF_FEATURE_IP_RULE(ARG_table,)
324 ARG_dev, 325 ARG_dev,
@@ -344,6 +345,7 @@ IF_FEATURE_IP_RULE(ARG_table,)
344 unsigned mxlock = 0; 345 unsigned mxlock = 0;
345 char *d = NULL; 346 char *d = NULL;
346 smalluint ok = 0; 347 smalluint ok = 0;
348 smalluint scope_ok = 0;
347 int arg; 349 int arg;
348 350
349 memset(&req, 0, sizeof(req)); 351 memset(&req, 0, sizeof(req));
@@ -352,15 +354,18 @@ IF_FEATURE_IP_RULE(ARG_table,)
352 req.n.nlmsg_flags = NLM_F_REQUEST | flags; 354 req.n.nlmsg_flags = NLM_F_REQUEST | flags;
353 req.n.nlmsg_type = cmd; 355 req.n.nlmsg_type = cmd;
354 req.r.rtm_family = preferred_family; 356 req.r.rtm_family = preferred_family;
355 if (RT_TABLE_MAIN) /* if it is zero, memset already did it */ 357 if (RT_TABLE_MAIN != 0) /* if it is zero, memset already did it */
356 req.r.rtm_table = RT_TABLE_MAIN; 358 req.r.rtm_table = RT_TABLE_MAIN;
357 if (RT_SCOPE_NOWHERE) 359 if (RT_SCOPE_NOWHERE != 0)
358 req.r.rtm_scope = RT_SCOPE_NOWHERE; 360 req.r.rtm_scope = RT_SCOPE_NOWHERE;
359 361
360 if (cmd != RTM_DELROUTE) { 362 if (cmd != RTM_DELROUTE) {
361 req.r.rtm_protocol = RTPROT_BOOT; 363 if (RTPROT_BOOT != 0)
362 req.r.rtm_scope = RT_SCOPE_UNIVERSE; 364 req.r.rtm_protocol = RTPROT_BOOT;
363 req.r.rtm_type = RTN_UNICAST; 365 if (RT_SCOPE_UNIVERSE != 0)
366 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
367 if (RTN_UNICAST != 0)
368 req.r.rtm_type = RTN_UNICAST;
364 } 369 }
365 370
366 mxrta->rta_type = RTA_METRICS; 371 mxrta->rta_type = RTA_METRICS;
@@ -393,6 +398,13 @@ IF_FEATURE_IP_RULE(ARG_table,)
393 } 398 }
394 mtu = get_unsigned(*argv, "mtu"); 399 mtu = get_unsigned(*argv, "mtu");
395 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); 400 rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu);
401 } else if (arg == ARG_scope) {
402 uint32_t scope;
403 NEXT_ARG();
404 if (rtnl_rtscope_a2n(&scope, *argv))
405 invarg_1_to_2(*argv, "scope");
406 req.r.rtm_scope = scope;
407 scope_ok = 1;
396 } else if (arg == ARG_protocol) { 408 } else if (arg == ARG_protocol) {
397 uint32_t prot; 409 uint32_t prot;
398 NEXT_ARG(); 410 NEXT_ARG();
@@ -469,20 +481,22 @@ IF_FEATURE_IP_RULE(ARG_table,)
469 addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta)); 481 addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta));
470 } 482 }
471 483
472 if (req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT) 484 if (!scope_ok) {
473 req.r.rtm_scope = RT_SCOPE_HOST; 485 if (req.r.rtm_type == RTN_LOCAL || req.r.rtm_type == RTN_NAT)
474 else 486 req.r.rtm_scope = RT_SCOPE_HOST;
475 if (req.r.rtm_type == RTN_BROADCAST 487 else
476 || req.r.rtm_type == RTN_MULTICAST 488 if (req.r.rtm_type == RTN_BROADCAST
477 || req.r.rtm_type == RTN_ANYCAST 489 || req.r.rtm_type == RTN_MULTICAST
478 ) { 490 || req.r.rtm_type == RTN_ANYCAST
479 req.r.rtm_scope = RT_SCOPE_LINK; 491 ) {
480 }
481 else if (req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) {
482 if (cmd == RTM_DELROUTE)
483 req.r.rtm_scope = RT_SCOPE_NOWHERE;
484 else if (!(ok & gw_ok))
485 req.r.rtm_scope = RT_SCOPE_LINK; 492 req.r.rtm_scope = RT_SCOPE_LINK;
493 }
494 else if (req.r.rtm_type == RTN_UNICAST || req.r.rtm_type == RTN_UNSPEC) {
495 if (cmd == RTM_DELROUTE)
496 req.r.rtm_scope = RT_SCOPE_NOWHERE;
497 else if (!(ok & gw_ok))
498 req.r.rtm_scope = RT_SCOPE_LINK;
499 }
486 } 500 }
487 501
488 if (req.r.rtm_family == AF_UNSPEC) { 502 if (req.r.rtm_family == AF_UNSPEC) {
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 9732c9b1a..1651670d9 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -112,7 +112,7 @@
112 * 112 *
113 * Made some changes to speed up re-syncing after our clock goes bad 113 * Made some changes to speed up re-syncing after our clock goes bad
114 * (tested with suspending my laptop): 114 * (tested with suspending my laptop):
115 * - if largish offset (>= STEP_THRESHOLD * 8 == 1 sec) is seen 115 * - if largish offset (>= STEP_THRESHOLD == 1 sec) is seen
116 * from a peer, schedule next query for this peer soon 116 * from a peer, schedule next query for this peer soon
117 * without drastically lowering poll interval for everybody. 117 * without drastically lowering poll interval for everybody.
118 * This makes us collect enough data for step much faster: 118 * This makes us collect enough data for step much faster:
@@ -131,11 +131,14 @@
131#define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */ 131#define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */
132 132
133/* Step threshold (sec). std ntpd uses 0.128. 133/* Step threshold (sec). std ntpd uses 0.128.
134 */
135#define STEP_THRESHOLD 1
136/* Slew threshold (sec): adjtimex() won't accept offsets larger than this.
134 * Using exact power of 2 (1/8) results in smaller code 137 * Using exact power of 2 (1/8) results in smaller code
135 */ 138 */
136#define STEP_THRESHOLD 0.125 139#define SLEW_THRESHOLD 0.125
137/* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ 140/* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */
138#define WATCH_THRESHOLD 128 141#define WATCH_THRESHOLD 128
139/* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ 142/* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */
140//UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ 143//UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */
141 144
@@ -143,7 +146,7 @@
143 * If we got |offset| > BIGOFF from a peer, cap next query interval 146 * If we got |offset| > BIGOFF from a peer, cap next query interval
144 * for this peer by this many seconds: 147 * for this peer by this many seconds:
145 */ 148 */
146#define BIGOFF (STEP_THRESHOLD * 8) 149#define BIGOFF STEP_THRESHOLD
147#define BIGOFF_INTERVAL (1 << 7) /* 128 s */ 150#define BIGOFF_INTERVAL (1 << 7) /* 128 s */
148 151
149#define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */ 152#define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */
@@ -157,10 +160,10 @@
157#define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ 160#define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */
158/* 161/*
159 * Actively lower poll when we see such big offsets. 162 * Actively lower poll when we see such big offsets.
160 * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively 163 * With SLEW_THRESHOLD = 0.125, it means we try to sync more aggressively
161 * if offset increases over ~0.04 sec 164 * if offset increases over ~0.04 sec
162 */ 165 */
163//#define POLLDOWN_OFFSET (STEP_THRESHOLD / 3) 166//#define POLLDOWN_OFFSET (SLEW_THRESHOLD / 3)
164#define MINDISP 0.01 /* minimum dispersion (sec) */ 167#define MINDISP 0.01 /* minimum dispersion (sec) */
165#define MAXDISP 16 /* maximum dispersion (sec) */ 168#define MAXDISP 16 /* maximum dispersion (sec) */
166#define MAXSTRAT 16 /* maximum stratum (infinity metric) */ 169#define MAXSTRAT 16 /* maximum stratum (infinity metric) */
@@ -720,7 +723,7 @@ static void
720reset_peer_stats(peer_t *p, double offset) 723reset_peer_stats(peer_t *p, double offset)
721{ 724{
722 int i; 725 int i;
723 bool small_ofs = fabs(offset) < 16 * STEP_THRESHOLD; 726 bool small_ofs = fabs(offset) < STEP_THRESHOLD;
724 727
725 /* Used to set p->filter_datapoint[i].d_dispersion = MAXDISP 728 /* Used to set p->filter_datapoint[i].d_dispersion = MAXDISP
726 * and clear reachable bits, but this proved to be too agressive: 729 * and clear reachable bits, but this proved to be too agressive:
@@ -771,7 +774,7 @@ add_peers(const char *s)
771 p->p_fd = -1; 774 p->p_fd = -1;
772 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); 775 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
773 p->next_action_time = G.cur_time; /* = set_next(p, 0); */ 776 p->next_action_time = G.cur_time; /* = set_next(p, 0); */
774 reset_peer_stats(p, 16 * STEP_THRESHOLD); 777 reset_peer_stats(p, STEP_THRESHOLD);
775 778
776 llist_add_to(&G.ntp_peers, p); 779 llist_add_to(&G.ntp_peers, p);
777 G.peer_cnt++; 780 G.peer_cnt++;
@@ -1638,14 +1641,7 @@ update_local_clock(peer_t *p)
1638 tmx.freq = G.discipline_freq_drift * 65536e6; 1641 tmx.freq = G.discipline_freq_drift * 65536e6;
1639#endif 1642#endif
1640 tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR; 1643 tmx.modes = ADJ_OFFSET | ADJ_STATUS | ADJ_TIMECONST;// | ADJ_MAXERROR | ADJ_ESTERROR;
1641 tmx.offset = (offset * 1000000); /* usec */ 1644 tmx.constant = (int)G.poll_exp - 4;
1642 tmx.status = STA_PLL;
1643 if (G.ntp_status & LI_PLUSSEC)
1644 tmx.status |= STA_INS;
1645 if (G.ntp_status & LI_MINUSSEC)
1646 tmx.status |= STA_DEL;
1647
1648 tmx.constant = (int)G.poll_exp - 4 > 0 ? (int)G.poll_exp - 4 : 0;
1649 /* EXPERIMENTAL. 1645 /* EXPERIMENTAL.
1650 * The below if statement should be unnecessary, but... 1646 * The below if statement should be unnecessary, but...
1651 * It looks like Linux kernel's PLL is far too gentle in changing 1647 * It looks like Linux kernel's PLL is far too gentle in changing
@@ -1656,8 +1652,27 @@ update_local_clock(peer_t *p)
1656 * To be on a safe side, let's do it only if offset is significantly 1652 * To be on a safe side, let's do it only if offset is significantly
1657 * larger than jitter. 1653 * larger than jitter.
1658 */ 1654 */
1659 if (tmx.constant > 0 && G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE) 1655 if (G.offset_to_jitter_ratio >= TIMECONST_HACK_GATE)
1660 tmx.constant--; 1656 tmx.constant--;
1657 tmx.offset = (long)(offset * 1000000); /* usec */
1658 if (SLEW_THRESHOLD < STEP_THRESHOLD) {
1659 if (tmx.offset > (long)(SLEW_THRESHOLD * 1000000)) {
1660 tmx.offset = (long)(SLEW_THRESHOLD * 1000000);
1661 tmx.constant--;
1662 }
1663 if (tmx.offset < -(long)(SLEW_THRESHOLD * 1000000)) {
1664 tmx.offset = -(long)(SLEW_THRESHOLD * 1000000);
1665 tmx.constant--;
1666 }
1667 }
1668 if (tmx.constant < 0)
1669 tmx.constant = 0;
1670
1671 tmx.status = STA_PLL;
1672 if (G.ntp_status & LI_PLUSSEC)
1673 tmx.status |= STA_INS;
1674 if (G.ntp_status & LI_MINUSSEC)
1675 tmx.status |= STA_DEL;
1661 1676
1662 //tmx.esterror = (uint32_t)(clock_jitter * 1e6); 1677 //tmx.esterror = (uint32_t)(clock_jitter * 1e6);
1663 //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6); 1678 //tmx.maxerror = (uint32_t)((sys_rootdelay / 2 + sys_rootdisp) * 1e6);
@@ -1931,6 +1946,9 @@ recv_and_process_peer_pkt(peer_t *p)
1931 increase_interval: 1946 increase_interval:
1932 adjust_poll(MINPOLL); 1947 adjust_poll(MINPOLL);
1933 } else { 1948 } else {
1949 VERB3 if (rc > 0)
1950 bb_error_msg("want smaller poll interval: offset/jitter > %u",
1951 POLLADJ_GATE);
1934 adjust_poll(-G.poll_exp * 2); 1952 adjust_poll(-G.poll_exp * 2);
1935 } 1953 }
1936 } 1954 }
@@ -1939,7 +1957,7 @@ recv_and_process_peer_pkt(peer_t *p)
1939 pick_normal_interval: 1957 pick_normal_interval:
1940 interval = poll_interval(INT_MAX); 1958 interval = poll_interval(INT_MAX);
1941 if (fabs(offset) >= BIGOFF && interval > BIGOFF_INTERVAL) { 1959 if (fabs(offset) >= BIGOFF && interval > BIGOFF_INTERVAL) {
1942 /* If we are synced, offsets are less than STEP_THRESHOLD, 1960 /* If we are synced, offsets are less than SLEW_THRESHOLD,
1943 * or at the very least not much larger than it. 1961 * or at the very least not much larger than it.
1944 * Now we see a largish one. 1962 * Now we see a largish one.
1945 * Either this peer is feeling bad, or packet got corrupted, 1963 * Either this peer is feeling bad, or packet got corrupted,
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 915f65935..48097bc24 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -201,6 +201,8 @@ static int good_hostname(const char *name)
201 //Do we want this? 201 //Do we want this?
202 //return ((name - start) < 1025); /* NS_MAXDNAME */ 202 //return ((name - start) < 1025); /* NS_MAXDNAME */
203 name++; 203 name++;
204 if (*name == '\0')
205 return 1; // We allow trailing dot too
204 } 206 }
205} 207}
206#else 208#else
diff --git a/scripts/trylink b/scripts/trylink
index 6e1187ed0..3c431edc3 100755
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -54,7 +54,7 @@ check_cc() {
54 # "eval" may be needed if CFLAGS can contain 54 # "eval" may be needed if CFLAGS can contain
55 # '... -D"BB_VER=KBUILD_STR(1.N.M)" ...' 55 # '... -D"BB_VER=KBUILD_STR(1.N.M)" ...'
56 # and we need shell to process quotes! 56 # and we need shell to process quotes!
57 $CC $CFLAGS $1 "$tempname".c -o "$tempname" >/dev/null 2>&1 57 $CC $CFLAGS $LDFLAGS $1 "$tempname".c -o "$tempname" >/dev/null 2>&1
58 r=$? 58 r=$?
59 rm -f "$tempname" "$tempname".c "$tempname".o 59 rm -f "$tempname" "$tempname".c "$tempname".o
60 return $r 60 return $r
diff --git a/shell/ash.c b/shell/ash.c
index de5c44ead..57d192822 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -51,7 +51,6 @@
51 51
52#define JOBS ENABLE_ASH_JOB_CONTROL 52#define JOBS ENABLE_ASH_JOB_CONTROL
53 53
54#include <paths.h>
55#include <setjmp.h> 54#include <setjmp.h>
56#include <fnmatch.h> 55#include <fnmatch.h>
57#include <sys/times.h> 56#include <sys/times.h>
@@ -8823,7 +8822,7 @@ evaltree(union node *n, int flags)
8823 n->nbinary.ch1, 8822 n->nbinary.ch1,
8824 (flags | ((is_or >> 1) - 1)) & EV_TESTED 8823 (flags | ((is_or >> 1) - 1)) & EV_TESTED
8825 ); 8824 );
8826 if (!exitstatus == is_or) 8825 if ((!exitstatus) == is_or)
8827 break; 8826 break;
8828 if (!evalskip) { 8827 if (!evalskip) {
8829 n = n->nbinary.ch2; 8828 n = n->nbinary.ch2;
diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c
index ca8b848bd..03d65b37f 100644
--- a/sysklogd/klogd.c
+++ b/sysklogd/klogd.c
@@ -98,7 +98,6 @@ static void klogd_close(void)
98 98
99#else 99#else
100 100
101# include <paths.h>
102# ifndef _PATH_KLOG 101# ifndef _PATH_KLOG
103# ifdef __GNU__ 102# ifdef __GNU__
104# define _PATH_KLOG "/dev/klog" 103# define _PATH_KLOG "/dev/klog"
diff --git a/testsuite/sed.tests b/testsuite/sed.tests
index 34479e55f..5d2356b64 100755
--- a/testsuite/sed.tests
+++ b/testsuite/sed.tests
@@ -365,6 +365,12 @@ testing "sed /regex/,+0<cmd> -i works" \
365 "1\n2\n3\n4\n5\n6\n7\n8\n" \ 365 "1\n2\n3\n4\n5\n6\n7\n8\n" \
366 "1\n2\n4\n5\n6\n7\n8\n" \ 366 "1\n2\n4\n5\n6\n7\n8\n" \
367 367
368testing "sed 's///w FILE'" \
369 "sed 's/qwe/ZZZ/wz'; cat z; rm z" \
370 "123\nZZZ\nasd\n""ZZZ\n" \
371 "" \
372 "123\nqwe\nasd\n"
373
368# testing "description" "commands" "result" "infile" "stdin" 374# testing "description" "commands" "result" "infile" "stdin"
369 375
370exit $FAILCOUNT 376exit $FAILCOUNT
diff --git a/util-linux/blkdiscard.c b/util-linux/blkdiscard.c
new file mode 100644
index 000000000..ace88a1f0
--- /dev/null
+++ b/util-linux/blkdiscard.c
@@ -0,0 +1,83 @@
1/*
2 * Mini blkdiscard implementation for busybox
3 *
4 * Copyright (C) 2015 by Ari Sundholm <ari@tuxera.com> and Tuxera Inc.
5 *
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */
8
9//config:config BLKDISCARD
10//config: bool "blkdiscard"
11//config: default y
12//config: help
13//config: blkdiscard discards sectors on a given device.
14
15//kbuild:lib-$(CONFIG_BLKDISCARD) += blkdiscard.o
16//applet:IF_BLKDISCARD(APPLET(blkdiscard, BB_DIR_USR_BIN, BB_SUID_DROP))
17
18//usage:#define blkdiscard_trivial_usage
19//usage: "[-o OFS] [-l LEN] [-s] DEVICE"
20//usage:#define blkdiscard_full_usage "\n\n"
21//usage: "Discard sectors on DEVICE\n"
22//usage: "\n -o OFS Byte offset into device"
23//usage: "\n -l LEN Number of bytes to discard"
24//usage: "\n -s Perform a secure discard"
25//usage:
26//usage:#define blkdiscard_example_usage
27//usage: "$ blkdiscard -o 0 -l 1G /dev/sdb"
28
29#include "libbb.h"
30#include <linux/fs.h>
31
32int blkdiscard_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
33int blkdiscard_main(int argc UNUSED_PARAM, char **argv)
34{
35 unsigned opts;
36 const char *offset_str = "0";
37 const char *length_str;
38 uint64_t offset; /* Leaving these two variables out does not */
39 uint64_t length; /* shrink code size and hampers readability. */
40 uint64_t range[2];
41// struct stat st;
42 int fd;
43
44 enum {
45 OPT_OFFSET = (1 << 0),
46 OPT_LENGTH = (1 << 1),
47 OPT_SECURE = (1 << 2),
48 };
49
50 opt_complementary = "=1";
51 opts = getopt32(argv, "o:l:s", &offset_str, &length_str);
52 argv += optind;
53
54 fd = xopen(argv[0], O_RDWR|O_EXCL);
55//Why bother, BLK[SEC]DISCARD will fail on non-blockdevs anyway?
56// xfstat(fd, &st);
57// if (!S_ISBLK(st.st_mode))
58// bb_error_msg_and_die("%s: not a block device", argv[0]);
59
60 offset = xatoull_sfx(offset_str, kMG_suffixes);
61
62 if (opts & OPT_LENGTH)
63 length = xatoull_sfx(length_str, kMG_suffixes);
64 else {
65 xioctl(fd, BLKGETSIZE64, &length);
66 length -= offset;
67 }
68
69 range[0] = offset;
70 range[1] = length;
71 ioctl_or_perror_and_die(fd,
72 (opts & OPT_SECURE) ? BLKSECDISCARD : BLKDISCARD,
73 &range,
74 "%s: %s failed",
75 argv[0],
76 (opts & OPT_SECURE) ? "BLKSECDISCARD" : "BLKDISCARD"
77 );
78
79 if (ENABLE_FEATURE_CLEAN_UP)
80 close(fd);
81
82 return EXIT_SUCCESS;
83}
diff --git a/util-linux/mount.c b/util-linux/mount.c
index cb40c802d..c428f5827 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -259,9 +259,11 @@ static struct mntent *getmntent_r(FILE* stream, struct mntent* result,
259 259
260// Not real flags, but we want to be able to check for this. 260// Not real flags, but we want to be able to check for this.
261enum { 261enum {
262 MOUNT_USERS = (1 << 28) * ENABLE_DESKTOP, 262 MOUNT_USERS = (1 << 27) * ENABLE_DESKTOP,
263 MOUNT_NOFAIL = (1 << 28) * ENABLE_DESKTOP,
263 MOUNT_NOAUTO = (1 << 29), 264 MOUNT_NOAUTO = (1 << 29),
264 MOUNT_SWAP = (1 << 30), 265 MOUNT_SWAP = (1 << 30),
266 MOUNT_FAKEFLAGS = MOUNT_USERS | MOUNT_NOFAIL | MOUNT_NOAUTO | MOUNT_SWAP
265}; 267};
266 268
267 269
@@ -326,6 +328,7 @@ static const int32_t mount_options[] = {
326 /* "swap" */ MOUNT_SWAP, 328 /* "swap" */ MOUNT_SWAP,
327 IF_DESKTOP(/* "user" */ MOUNT_USERS,) 329 IF_DESKTOP(/* "user" */ MOUNT_USERS,)
328 IF_DESKTOP(/* "users" */ MOUNT_USERS,) 330 IF_DESKTOP(/* "users" */ MOUNT_USERS,)
331 IF_DESKTOP(/* "nofail" */ MOUNT_NOFAIL,)
329 /* "_netdev" */ 0, 332 /* "_netdev" */ 0,
330 IF_DESKTOP(/* "comment=" */ 0,) /* systemd uses this in fstab */ 333 IF_DESKTOP(/* "comment=" */ 0,) /* systemd uses this in fstab */
331 ) 334 )
@@ -385,6 +388,7 @@ static const char mount_option_str[] =
385 "swap\0" 388 "swap\0"
386 IF_DESKTOP("user\0") 389 IF_DESKTOP("user\0")
387 IF_DESKTOP("users\0") 390 IF_DESKTOP("users\0")
391 IF_DESKTOP("nofail\0")
388 "_netdev\0" 392 "_netdev\0"
389 IF_DESKTOP("comment=\0") /* systemd uses this in fstab */ 393 IF_DESKTOP("comment=\0") /* systemd uses this in fstab */
390 ) 394 )
@@ -672,6 +676,8 @@ static int mount_it_now(struct mntent *mp, unsigned long vfsflags, char *filtero
672{ 676{
673 int rc = 0; 677 int rc = 0;
674 678
679 vfsflags &= ~(unsigned long)MOUNT_FAKEFLAGS;
680
675 if (FAKE_IT) { 681 if (FAKE_IT) {
676 if (verbose >= 2) 682 if (verbose >= 2)
677 bb_error_msg("would do mount('%s','%s','%s',0x%08lx,'%s')", 683 bb_error_msg("would do mount('%s','%s','%s',0x%08lx,'%s')",
@@ -2061,6 +2067,8 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2061 2067
2062 if (errno == EBUSY && ignore_busy) 2068 if (errno == EBUSY && ignore_busy)
2063 return 0; 2069 return 0;
2070 if (errno == ENOENT && (vfsflags & MOUNT_NOFAIL))
2071 return 0;
2064 if (rc != 0) 2072 if (rc != 0)
2065 bb_perror_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir); 2073 bb_perror_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
2066 return rc; 2074 return rc;
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index 5cd1fbe70..c29dd3071 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -22,11 +22,10 @@
22//usage: ) 22//usage: )
23//usage: 23//usage:
24//usage:#define swapoff_trivial_usage 24//usage:#define swapoff_trivial_usage
25//usage: "[-a] [-e] [DEVICE]" 25//usage: "[-a] [DEVICE]"
26//usage:#define swapoff_full_usage "\n\n" 26//usage:#define swapoff_full_usage "\n\n"
27//usage: "Stop swapping on DEVICE\n" 27//usage: "Stop swapping on DEVICE\n"
28//usage: "\n -a Stop swapping on all swap devices" 28//usage: "\n -a Stop swapping on all swap devices"
29//usage: "\n -e Silently skip devices that do not exist"
30 29
31#include "libbb.h" 30#include "libbb.h"
32#include <mntent.h> 31#include <mntent.h>
@@ -97,11 +96,8 @@ static int swap_enable_disable(char *device)
97{ 96{
98 int err = 0; 97 int err = 0;
99 int quiet = 0; 98 int quiet = 0;
100 struct stat st;
101 99
102 resolve_mount_spec(&device); 100 resolve_mount_spec(&device);
103 if (!OPT_IFEXISTS)
104 xstat(device, &st);
105 101
106 if (do_swapoff) { 102 if (do_swapoff) {
107 err = swapoff(device); 103 err = swapoff(device);
@@ -109,6 +105,7 @@ static int swap_enable_disable(char *device)
109 quiet = (OPT_ALL && (errno == EINVAL || errno == ENOENT)); 105 quiet = (OPT_ALL && (errno == EINVAL || errno == ENOENT));
110 } else { 106 } else {
111 /* swapon */ 107 /* swapon */
108 struct stat st;
112 err = stat(device, &st); 109 err = stat(device, &st);
113 if (!err) { 110 if (!err) {
114 if (ENABLE_DESKTOP && S_ISREG(st.st_mode)) { 111 if (ENABLE_DESKTOP && S_ISREG(st.st_mode)) {
@@ -119,9 +116,11 @@ static int swap_enable_disable(char *device)
119 } 116 }
120 err = swapon(device, g_flags); 117 err = swapon(device, g_flags);
121 /* Don't complain on swapon -a if device is already in use */ 118 /* Don't complain on swapon -a if device is already in use */
122 /* Don't complain if file does not exist with -e option */ 119 quiet = (OPT_ALL && errno == EBUSY);
123 quiet = (OPT_ALL && errno == EBUSY) || (OPT_IFEXISTS && errno == ENOENT);
124 } 120 }
121 /* Don't complain if file does not exist with -e option */
122 if (err && OPT_IFEXISTS && errno == ENOENT)
123 err = 0;
125 } 124 }
126 125
127 if (err && !quiet) { 126 if (err && !quiet) {
diff --git a/util-linux/volume_id/bcache.c b/util-linux/volume_id/bcache.c
new file mode 100644
index 000000000..648e44de5
--- /dev/null
+++ b/util-linux/volume_id/bcache.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright (C) 2013 Rolf Fokkens <rolf@fokkens.nl>
3 *
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
6 *
7 * Based on code fragments from bcache-tools by Kent Overstreet:
8 * http://evilpiepirate.org/git/bcache-tools.git
9 */
10
11//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BCACHE) += bcache.o
12
13//config:
14//config:config FEATURE_VOLUMEID_BCACHE
15//config: bool "bcache filesystem"
16//config: default y
17//config: depends on VOLUMEID
18//config: help
19//config: TODO
20//config:
21
22#include "volume_id_internal.h"
23
24#define SB_LABEL_SIZE 32
25#define SB_JOURNAL_BUCKETS 256U
26
27static const char bcache_magic[] = {
28 0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
29 0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81
30};
31
32struct bcache_super_block {
33 uint64_t csum;
34 uint64_t offset; /* sector where this sb was written */
35 uint64_t version;
36
37 uint8_t magic[16];
38
39 uint8_t uuid[16];
40 union {
41 uint8_t set_uuid[16];
42 uint64_t set_magic;
43 };
44 uint8_t label[SB_LABEL_SIZE];
45
46 uint64_t flags;
47 uint64_t seq;
48 uint64_t pad[8];
49
50 union {
51 struct {
52 /* Cache devices */
53 uint64_t nbuckets; /* device size */
54
55 uint16_t block_size; /* sectors */
56 uint16_t bucket_size; /* sectors */
57
58 uint16_t nr_in_set;
59 uint16_t nr_this_dev;
60 };
61 struct {
62 /* Backing devices */
63 uint64_t data_offset;
64
65 /*
66 * block_size from the cache device section is still used by
67 * backing devices, so don't add anything here until we fix
68 * things to not need it for backing devices anymore
69 */
70 };
71 };
72
73 uint32_t last_mount; /* time_t */
74
75 uint16_t first_bucket;
76 union {
77 uint16_t njournal_buckets;
78 uint16_t keys;
79 };
80 uint64_t d[SB_JOURNAL_BUCKETS]; /* journal buckets */
81};
82
83/* magic string */
84#define BCACHE_SB_MAGIC bcache_magic
85/* magic string len */
86#define BCACHE_SB_MAGIC_LEN sizeof (bcache_magic)
87/* super block offset */
88#define BCACHE_SB_OFF 0x1000
89/* supper block offset in kB */
90#define BCACHE_SB_KBOFF (BCACHE_SB_OFF >> 10)
91/* magic string offset within super block */
92#define BCACHE_SB_MAGIC_OFF offsetof (struct bcache_super_block, magic)
93
94int FAST_FUNC volume_id_probe_bcache(struct volume_id *id /*,uint64_t off*/)
95{
96 struct bcache_super_block *sb;
97
98 sb = volume_id_get_buffer(id, BCACHE_SB_OFF, sizeof(*sb));
99 if (sb == NULL)
100 return -1;
101
102 if (memcmp(sb->magic, BCACHE_SB_MAGIC, BCACHE_SB_MAGIC_LEN) != 0)
103 return -1;
104
105 volume_id_set_label_string(id, sb->label, SB_LABEL_SIZE);
106 volume_id_set_uuid(id, sb->uuid, UUID_DCE);
107 IF_FEATURE_BLKID_TYPE(id->type = "bcache";)
108
109 return 0;
110}
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c
index 5c459a0e2..3f71e0084 100644
--- a/util-linux/volume_id/volume_id.c
+++ b/util-linux/volume_id/volume_id.c
@@ -107,6 +107,9 @@ static const probe_fptr fs1[] = {
107#if ENABLE_FEATURE_VOLUMEID_XFS 107#if ENABLE_FEATURE_VOLUMEID_XFS
108 volume_id_probe_xfs, 108 volume_id_probe_xfs,
109#endif 109#endif
110#if ENABLE_FEATURE_VOLUMEID_BCACHE
111 volume_id_probe_bcache,
112#endif
110}; 113};
111 114
112/* fill buffer with maximum */ 115/* fill buffer with maximum */
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h
index 6e2dbd7bb..3061ac4d5 100644
--- a/util-linux/volume_id/volume_id_internal.h
+++ b/util-linux/volume_id/volume_id_internal.h
@@ -169,6 +169,8 @@ int FAST_FUNC volume_id_probe_linux_raid(struct volume_id *id /*,uint64_t off*/,
169 169
170/* FS */ 170/* FS */
171 171
172int FAST_FUNC volume_id_probe_bcache(struct volume_id *id /*,uint64_t off*/);
173
172int FAST_FUNC volume_id_probe_btrfs(struct volume_id *id /*,uint64_t off*/); 174int FAST_FUNC volume_id_probe_btrfs(struct volume_id *id /*,uint64_t off*/);
173 175
174int FAST_FUNC volume_id_probe_cramfs(struct volume_id *id /*,uint64_t off*/); 176int FAST_FUNC volume_id_probe_cramfs(struct volume_id *id /*,uint64_t off*/);