aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-11-12 08:27:51 +0000
committerRon Yorston <rmy@pobox.com>2020-11-12 08:27:51 +0000
commitead8b92e3d66ab45235e137f85fb3a529dcc64ef (patch)
treeaf268270382dad969218063d4a8120fc91a9e631 /libbb
parent567728c22dddea4ed33b8a69641ba2e0c3f1f600 (diff)
parent64981b4c8e88812c322bee3832f1d421ff670ed5 (diff)
downloadbusybox-w32-ead8b92e3d66ab45235e137f85fb3a529dcc64ef.tar.gz
busybox-w32-ead8b92e3d66ab45235e137f85fb3a529dcc64ef.tar.bz2
busybox-w32-ead8b92e3d66ab45235e137f85fb3a529dcc64ef.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb')
-rw-r--r--libbb/appletlib.c9
-rw-r--r--libbb/dump.c70
-rw-r--r--libbb/hash_md5_sha.c75
-rw-r--r--libbb/inet_cksum.c4
-rw-r--r--libbb/kernel_version.c20
-rw-r--r--libbb/loop.c4
-rw-r--r--libbb/ptr_to_globals.c4
-rw-r--r--libbb/recursive_action.c72
-rw-r--r--libbb/update_passwd.c15
9 files changed, 153 insertions, 120 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 77a9c3b7d..6ed86e12b 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -25,6 +25,11 @@
25 * 25 *
26 * FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :( 26 * FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :(
27 */ 27 */
28
29/* Define this accessor before we #define "errno" our way */
30#include <errno.h>
31static inline int *get_perrno(void) { return &errno; }
32
28#include "busybox.h" 33#include "busybox.h"
29 34
30#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ 35#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
@@ -318,8 +323,8 @@ void lbb_prepare(const char *applet
318void lbb_prepare(const char *applet 323void lbb_prepare(const char *applet
319 IF_FEATURE_INDIVIDUAL(, char **argv)) 324 IF_FEATURE_INDIVIDUAL(, char **argv))
320{ 325{
321#ifdef __GLIBC__ 326#ifdef bb_cached_errno_ptr
322 (*(int **)not_const_pp(&bb_errno)) = __errno_location(); 327 (*(int **)not_const_pp(&bb_errno)) = get_perrno();
323 barrier(); 328 barrier();
324#endif 329#endif
325 applet_name = applet; 330 applet_name = applet;
diff --git a/libbb/dump.c b/libbb/dump.c
index 8029cca0e..1ba1132b3 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -13,13 +13,19 @@
13#include "libbb.h" 13#include "libbb.h"
14#include "dump.h" 14#include "dump.h"
15 15
16static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789"; 16#define F_IGNORE 0x01 /* %_A */
17 17#define F_SETREP 0x02 /* rep count set, not default */
18static const char size_conv_str[] ALIGN1 = 18#define F_ADDRESS 0x001 /* print offset */
19"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; 19#define F_BPAD 0x002 /* blank pad */
20 20#define F_C 0x004 /* %_c */
21static const char int_convs[] ALIGN1 = "diouxX"; 21#define F_CHAR 0x008 /* %c */
22 22#define F_DBL 0x010 /* %[EefGf] */
23#define F_INT 0x020 /* %[di] */
24#define F_P 0x040 /* %_p */
25#define F_STR 0x080 /* %s */
26#define F_U 0x100 /* %_u */
27#define F_UINT 0x200 /* %[ouXx] */
28#define F_TEXT 0x400 /* no conversions */
23 29
24typedef struct priv_dumper_t { 30typedef struct priv_dumper_t {
25 dumper_t pub; 31 dumper_t pub;
@@ -39,6 +45,13 @@ typedef struct priv_dumper_t {
39 unsigned char *get__savp; 45 unsigned char *get__savp;
40} priv_dumper_t; 46} priv_dumper_t;
41 47
48static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789";
49
50static const char size_conv_str[] ALIGN1 =
51"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG";
52
53static const char int_convs[] ALIGN1 = "diouxX";
54
42dumper_t* FAST_FUNC alloc_dumper(void) 55dumper_t* FAST_FUNC alloc_dumper(void)
43{ 56{
44 priv_dumper_t *dumper = xzalloc(sizeof(*dumper)); 57 priv_dumper_t *dumper = xzalloc(sizeof(*dumper));
@@ -48,7 +61,6 @@ dumper_t* FAST_FUNC alloc_dumper(void)
48 return &dumper->pub; 61 return &dumper->pub;
49} 62}
50 63
51
52static NOINLINE int bb_dump_size(FS *fs) 64static NOINLINE int bb_dump_size(FS *fs)
53{ 65{
54 FU *fu; 66 FU *fu;
@@ -284,7 +296,9 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
284 * repeat it as necessary. 296 * repeat it as necessary.
285 * 297 *
286 * if rep count is greater than 1, no trailing whitespace 298 * if rep count is greater than 1, no trailing whitespace
287 * gets output from the last iteration of the format unit. 299 * gets output from the last iteration of the format unit:
300 * 2/1 "%02x " prints "XX XX", not "XX XX "
301 * 2/1 "%02x\n" prints "XX\nXX", not "XX\nXX\n"
288 */ 302 */
289 for (fu = fs->nextfu; fu; fu = fu->nextfu) { 303 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
290 if (!fu->nextfu 304 if (!fu->nextfu
@@ -394,7 +408,6 @@ static unsigned char *get(priv_dumper_t *dumper)
394 if (dumper->pub.dump_vflag != DUP) { 408 if (dumper->pub.dump_vflag != DUP) {
395 puts("*"); 409 puts("*");
396 } 410 }
397 return NULL;
398 } 411 }
399 memset(dumper->get__curp + nread, 0, need); 412 memset(dumper->get__curp + nread, 0, need);
400 dumper->eaddress = dumper->address + nread; 413 dumper->eaddress = dumper->address + nread;
@@ -453,7 +466,7 @@ static void bpad(PR *pr)
453 for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1) 466 for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1)
454 if (pr->nospace) 467 if (pr->nospace)
455 pr->nospace--; 468 pr->nospace--;
456 while ((*p2++ = *p1++) != 0) 469 while ((*p2++ = *p1++) != '\0')
457 continue; 470 continue;
458} 471}
459 472
@@ -520,36 +533,43 @@ static void conv_u(PR *pr, unsigned char *p)
520 533
521static void display(priv_dumper_t* dumper) 534static void display(priv_dumper_t* dumper)
522{ 535{
523 FS *fs; 536 unsigned char *bp;
524 FU *fu;
525 PR *pr;
526 int cnt;
527 unsigned char *bp, *savebp;
528 off_t saveaddress;
529 unsigned char savech = '\0'; 537 unsigned char savech = '\0';
530 538
531 while ((bp = get(dumper)) != NULL) { 539 while ((bp = get(dumper)) != NULL) {
540 FS *fs;
541 unsigned char *savebp;
542 off_t saveaddress;
543
532 fs = dumper->pub.fshead; 544 fs = dumper->pub.fshead;
533 savebp = bp; 545 savebp = bp;
534 saveaddress = dumper->address; 546 saveaddress = dumper->address;
535 for (; fs; fs = fs->nextfs, bp = savebp, dumper->address = saveaddress) { 547 for (; fs; fs = fs->nextfs, bp = savebp, dumper->address = saveaddress) {
548 FU *fu;
536 for (fu = fs->nextfu; fu; fu = fu->nextfu) { 549 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
550 int cnt;
537 if (fu->flags & F_IGNORE) { 551 if (fu->flags & F_IGNORE) {
538 break; 552 break;
539 } 553 }
540 for (cnt = fu->reps; cnt; --cnt) { 554 for (cnt = fu->reps; cnt; --cnt) {
555 PR *pr;
541 for (pr = fu->nextpr; pr; dumper->address += pr->bcnt, 556 for (pr = fu->nextpr; pr; dumper->address += pr->bcnt,
542 bp += pr->bcnt, pr = pr->nextpr) { 557 bp += pr->bcnt, pr = pr->nextpr) {
543 if (dumper->eaddress && dumper->address >= dumper->eaddress 558 if (dumper->eaddress
544 && !(pr->flags & (F_TEXT | F_BPAD)) 559 && dumper->address >= dumper->eaddress
545 ) { 560 ) {
546 bpad(pr); 561 if (dumper->pub.eofstring) {
562 /* xxd support: requested to not pad incomplete blocks */
563 fputs(dumper->pub.eofstring, stdout);
564 return;
565 }
566 if (!(pr->flags & (F_TEXT | F_BPAD)))
567 bpad(pr);
547 } 568 }
548 if (cnt == 1 && pr->nospace) { 569 if (cnt == 1 && pr->nospace) {
549 savech = *pr->nospace; 570 savech = *pr->nospace;
550 *pr->nospace = '\0'; 571 *pr->nospace = '\0';
551 } 572 }
552/* PRINT; */
553 switch (pr->flags) { 573 switch (pr->flags) {
554 case F_ADDRESS: 574 case F_ADDRESS:
555 printf(pr->fmt, (unsigned) dumper->address); 575 printf(pr->fmt, (unsigned) dumper->address);
@@ -638,7 +658,9 @@ static void display(priv_dumper_t* dumper)
638 } 658 }
639 } 659 }
640 } 660 }
661
641 if (dumper->endfu) { 662 if (dumper->endfu) {
663 PR *pr;
642 /* 664 /*
643 * if eaddress not set, error or file size was multiple 665 * if eaddress not set, error or file size was multiple
644 * of blocksize, and no partial block ever found. 666 * of blocksize, and no partial block ever found.
@@ -695,8 +717,7 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
695{ 717{
696 const char *p; 718 const char *p;
697 FS *tfs; 719 FS *tfs;
698 FU *tfu, **nextfupp; 720 FU **nextfupp;
699 const char *savep;
700 721
701 /* start new linked list of format units */ 722 /* start new linked list of format units */
702 tfs = xzalloc(sizeof(FS)); /*DBU:[dave@cray.com] start out NULL */ 723 tfs = xzalloc(sizeof(FS)); /*DBU:[dave@cray.com] start out NULL */
@@ -713,6 +734,9 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
713 /* take the format string and break it up into format units */ 734 /* take the format string and break it up into format units */
714 p = fmt; 735 p = fmt;
715 for (;;) { 736 for (;;) {
737 FU *tfu;
738 const char *savep;
739
716 p = skip_whitespace(p); 740 p = skip_whitespace(p);
717 if (*p == '\0') { 741 if (*p == '\0') {
718 break; 742 break;
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index 9db79ea8b..d8f210173 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -38,35 +38,6 @@ static ALWAYS_INLINE uint64_t rotl64(uint64_t x, unsigned n)
38 return (x << n) | (x >> (64 - n)); 38 return (x << n) | (x >> (64 - n));
39} 39}
40 40
41/* Feed data through a temporary buffer.
42 * The internal buffer remembers previous data until it has 64
43 * bytes worth to pass on.
44 */
45static void FAST_FUNC common64_hash(md5_ctx_t *ctx, const void *buffer, size_t len)
46{
47 unsigned bufpos = ctx->total64 & 63;
48
49 ctx->total64 += len;
50
51 while (1) {
52 unsigned remaining = 64 - bufpos;
53 if (remaining > len)
54 remaining = len;
55 /* Copy data into aligned buffer */
56 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
57 len -= remaining;
58 buffer = (const char *)buffer + remaining;
59 bufpos += remaining;
60 /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */
61 bufpos -= 64;
62 if (bufpos != 0)
63 break;
64 /* Buffer is filled up, process it */
65 ctx->process_block(ctx);
66 /*bufpos = 0; - already is */
67 }
68}
69
70/* Process the remaining bytes in the buffer */ 41/* Process the remaining bytes in the buffer */
71static void FAST_FUNC common64_end(md5_ctx_t *ctx, int swap_needed) 42static void FAST_FUNC common64_end(md5_ctx_t *ctx, int swap_needed)
72{ 43{
@@ -449,7 +420,29 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx)
449/* Used also for sha1 and sha256 */ 420/* Used also for sha1 and sha256 */
450void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) 421void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len)
451{ 422{
452 common64_hash(ctx, buffer, len); 423 unsigned bufpos = ctx->total64 & 63;
424
425 ctx->total64 += len;
426
427 while (1) {
428 unsigned remaining = 64 - bufpos;
429 if (remaining > len)
430 remaining = len;
431 /* Copy data into aligned buffer */
432 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
433 len -= remaining;
434 buffer = (const char *)buffer + remaining;
435 bufpos += remaining;
436
437 /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */
438 bufpos -= 64;
439 if (bufpos != 0)
440 break;
441
442 /* Buffer is filled up, process it */
443 ctx->process_block(ctx);
444 /*bufpos = 0; - already is */
445 }
453} 446}
454 447
455/* Process the remaining bytes in the buffer and put result from CTX 448/* Process the remaining bytes in the buffer and put result from CTX
@@ -816,7 +809,7 @@ void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
816 int i; 809 int i;
817 /* Two extra iterations zero out ctx->total64[2] */ 810 /* Two extra iterations zero out ctx->total64[2] */
818 uint64_t *tp = ctx->total64; 811 uint64_t *tp = ctx->total64;
819 for (i = 0; i < 2+8; i++) 812 for (i = 0; i < 8 + 2; i++)
820 tp[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i]; 813 tp[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i];
821 /*ctx->total64[0] = ctx->total64[1] = 0; - already done */ 814 /*ctx->total64[0] = ctx->total64[1] = 0; - already done */
822} 815}
@@ -832,22 +825,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
832 ctx->total64[0] += len; 825 ctx->total64[0] += len;
833 if (ctx->total64[0] < len) 826 if (ctx->total64[0] < len)
834 ctx->total64[1]++; 827 ctx->total64[1]++;
835# if 0
836 remaining = 128 - bufpos;
837 828
838 /* Hash whole blocks */
839 while (len >= remaining) {
840 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
841 buffer = (const char *)buffer + remaining;
842 len -= remaining;
843 remaining = 128;
844 bufpos = 0;
845 sha512_process_block128(ctx);
846 }
847
848 /* Save last, partial blosk */
849 memcpy(ctx->wbuffer + bufpos, buffer, len);
850# else
851 while (1) { 829 while (1) {
852 remaining = 128 - bufpos; 830 remaining = 128 - bufpos;
853 if (remaining > len) 831 if (remaining > len)
@@ -857,15 +835,16 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
857 len -= remaining; 835 len -= remaining;
858 buffer = (const char *)buffer + remaining; 836 buffer = (const char *)buffer + remaining;
859 bufpos += remaining; 837 bufpos += remaining;
838
860 /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */ 839 /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */
861 bufpos -= 128; 840 bufpos -= 128;
862 if (bufpos != 0) 841 if (bufpos != 0)
863 break; 842 break;
843
864 /* Buffer is filled up, process it */ 844 /* Buffer is filled up, process it */
865 sha512_process_block128(ctx); 845 sha512_process_block128(ctx);
866 /*bufpos = 0; - already is */ 846 /*bufpos = 0; - already is */
867 } 847 }
868# endif
869} 848}
870#endif /* NEED_SHA512 */ 849#endif /* NEED_SHA512 */
871 850
@@ -1398,10 +1377,12 @@ void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len)
1398 bufpos++; 1377 bufpos++;
1399 remaining--; 1378 remaining--;
1400 } 1379 }
1380
1401 /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */ 1381 /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */
1402 bufpos -= ctx->input_block_bytes; 1382 bufpos -= ctx->input_block_bytes;
1403 if (bufpos != 0) 1383 if (bufpos != 0)
1404 break; 1384 break;
1385
1405 /* Buffer is filled up, process it */ 1386 /* Buffer is filled up, process it */
1406 sha3_process_block72(ctx->state); 1387 sha3_process_block72(ctx->state);
1407 /*bufpos = 0; - already is */ 1388 /*bufpos = 0; - already is */
diff --git a/libbb/inet_cksum.c b/libbb/inet_cksum.c
index 3d5dc3adf..fee8648f3 100644
--- a/libbb/inet_cksum.c
+++ b/libbb/inet_cksum.c
@@ -6,8 +6,10 @@
6 6
7#include "libbb.h" 7#include "libbb.h"
8 8
9uint16_t FAST_FUNC inet_cksum(uint16_t *addr, int nleft) 9uint16_t FAST_FUNC inet_cksum(const void *ptr, int nleft)
10{ 10{
11 const uint16_t *addr = ptr;
12
11 /* 13 /*
12 * Our algorithm is simple, using a 32 bit accumulator, 14 * Our algorithm is simple, using a 32 bit accumulator,
13 * we add sequential 16 bit words to it, and at the end, fold 15 * we add sequential 16 bit words to it, and at the end, fold
diff --git a/libbb/kernel_version.c b/libbb/kernel_version.c
index 7769a091b..6bb32ce5f 100644
--- a/libbb/kernel_version.c
+++ b/libbb/kernel_version.c
@@ -19,15 +19,17 @@ int FAST_FUNC get_linux_version_code(void)
19{ 19{
20 struct utsname name; 20 struct utsname name;
21 char *t; 21 char *t;
22 int i, r; 22 int r;
23 23
24 uname(&name); /* never fails */ 24 uname(&name); /* never fails */
25 t = name.release; 25 t = name.release - 1;
26 r = 0; 26 r = 1;
27 for (i = 0; i < 3; i++) { 27 do {
28 t = strtok(t, "."); 28 r <<= 8;
29 r = r * 256 + (t ? atoi(t) : 0); 29 if (t) {
30 t = NULL; 30 r += atoi(++t);
31 } 31 t = strchr(t, '.');
32 return r; 32 }
33 } while (r < 0x1000000);
34 return r - 0x1000000;
33} 35}
diff --git a/libbb/loop.c b/libbb/loop.c
index ada0c7638..85b2724e5 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -102,7 +102,8 @@ int FAST_FUNC get_free_loop(void)
102 * search will re-use an existing loop device already bound to that 102 * search will re-use an existing loop device already bound to that
103 * file/offset if it finds one. 103 * file/offset if it finds one.
104 */ 104 */
105int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, unsigned flags) 105int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset,
106 unsigned long long sizelimit, unsigned flags)
106{ 107{
107 char dev[LOOP_NAMESIZE]; 108 char dev[LOOP_NAMESIZE];
108 char *try; 109 char *try;
@@ -185,6 +186,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
185 memset(&loopinfo, 0, sizeof(loopinfo)); 186 memset(&loopinfo, 0, sizeof(loopinfo));
186 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); 187 safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
187 loopinfo.lo_offset = offset; 188 loopinfo.lo_offset = offset;
189 loopinfo.lo_sizelimit = sizelimit;
188 /* 190 /*
189 * Used by mount to set LO_FLAGS_AUTOCLEAR. 191 * Used by mount to set LO_FLAGS_AUTOCLEAR.
190 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file. 192 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file.
diff --git a/libbb/ptr_to_globals.c b/libbb/ptr_to_globals.c
index 8ba9cd154..2232c6864 100644
--- a/libbb/ptr_to_globals.c
+++ b/libbb/ptr_to_globals.c
@@ -14,7 +14,7 @@ struct globals;
14 * but here we make it live in R/W memory */ 14 * but here we make it live in R/W memory */
15struct globals *ptr_to_globals; 15struct globals *ptr_to_globals;
16 16
17#ifdef __GLIBC__ 17#ifdef errno
18int *bb_errno; 18int *bb_errno;
19#endif 19#endif
20 20
@@ -27,7 +27,7 @@ int *bb_errno;
27 * on weird architectures, compilers, linkers and so on */ 27 * on weird architectures, compilers, linkers and so on */
28struct globals *const ptr_to_globals __attribute__ ((section (".data"))); 28struct globals *const ptr_to_globals __attribute__ ((section (".data")));
29 29
30#ifdef __GLIBC__ 30#ifdef errno
31int *const bb_errno __attribute__ ((section (".data"))); 31int *const bb_errno __attribute__ ((section (".data")));
32#endif 32#endif
33 33
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c
index 0831ecc3a..b1c4bfad7 100644
--- a/libbb/recursive_action.c
+++ b/libbb/recursive_action.c
@@ -21,10 +21,9 @@
21 * is so stinking huge. 21 * is so stinking huge.
22 */ 22 */
23 23
24static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM, 24static int FAST_FUNC true_action(struct recursive_state *state UNUSED_PARAM,
25 struct stat *statbuf UNUSED_PARAM, 25 const char *fileName UNUSED_PARAM,
26 void* userData UNUSED_PARAM, 26 struct stat *statbuf UNUSED_PARAM)
27 int depth UNUSED_PARAM)
28{ 27{
29 return TRUE; 28 return TRUE;
30} 29}
@@ -65,12 +64,7 @@ static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM,
65 * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir. 64 * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir.
66 */ 65 */
67 66
68int FAST_FUNC recursive_action(const char *fileName, 67static int recursive_action1(recursive_state_t *state, const char *fileName)
69 unsigned flags,
70 int FAST_FUNC (*fileAction)(const char *fileName, struct stat *statbuf, void* userData, int depth),
71 int FAST_FUNC (*dirAction)(const char *fileName, struct stat *statbuf, void* userData, int depth),
72 void* userData,
73 unsigned depth)
74{ 68{
75 struct stat statbuf; 69 struct stat statbuf;
76 unsigned follow; 70 unsigned follow;
@@ -78,24 +72,21 @@ int FAST_FUNC recursive_action(const char *fileName,
78 DIR *dir; 72 DIR *dir;
79 struct dirent *next; 73 struct dirent *next;
80 74
81 if (!fileAction) fileAction = true_action;
82 if (!dirAction) dirAction = true_action;
83
84 follow = ACTION_FOLLOWLINKS; 75 follow = ACTION_FOLLOWLINKS;
85 if (depth == 0) 76 if (state->depth == 0)
86 follow = ACTION_FOLLOWLINKS | ACTION_FOLLOWLINKS_L0; 77 follow = ACTION_FOLLOWLINKS | ACTION_FOLLOWLINKS_L0;
87 follow &= flags; 78 follow &= state->flags;
88 status = (follow ? stat : lstat)(fileName, &statbuf); 79 status = (follow ? stat : lstat)(fileName, &statbuf);
89 if (status < 0) { 80 if (status < 0) {
90#ifdef DEBUG_RECURS_ACTION 81#ifdef DEBUG_RECURS_ACTION
91 bb_error_msg("status=%d flags=%x", status, flags); 82 bb_error_msg("status=%d flags=%x", status, state->flags);
92#endif 83#endif
93 if ((flags & ACTION_DANGLING_OK) 84 if ((state->flags & ACTION_DANGLING_OK)
94 && errno == ENOENT 85 && errno == ENOENT
95 && lstat(fileName, &statbuf) == 0 86 && lstat(fileName, &statbuf) == 0
96 ) { 87 ) {
97 /* Dangling link */ 88 /* Dangling link */
98 return fileAction(fileName, &statbuf, userData, depth); 89 return state->fileAction(state, fileName, &statbuf);
99 } 90 }
100 goto done_nak_warn; 91 goto done_nak_warn;
101 } 92 }
@@ -103,20 +94,20 @@ int FAST_FUNC recursive_action(const char *fileName,
103 /* If S_ISLNK(m), then we know that !S_ISDIR(m). 94 /* If S_ISLNK(m), then we know that !S_ISDIR(m).
104 * Then we can skip checking first part: if it is true, then 95 * Then we can skip checking first part: if it is true, then
105 * (!dir) is also true! */ 96 * (!dir) is also true! */
106 if ( /* (!(flags & ACTION_FOLLOWLINKS) && S_ISLNK(statbuf.st_mode)) || */ 97 if ( /* (!(state->flags & ACTION_FOLLOWLINKS) && S_ISLNK(statbuf.st_mode)) || */
107 !S_ISDIR(statbuf.st_mode) 98 !S_ISDIR(statbuf.st_mode)
108 ) { 99 ) {
109 return fileAction(fileName, &statbuf, userData, depth); 100 return state->fileAction(state, fileName, &statbuf);
110 } 101 }
111 102
112 /* It's a directory (or a link to one, and followLinks is set) */ 103 /* It's a directory (or a link to one, and followLinks is set) */
113 104
114 if (!(flags & ACTION_RECURSE)) { 105 if (!(state->flags & ACTION_RECURSE)) {
115 return dirAction(fileName, &statbuf, userData, depth); 106 return state->dirAction(state, fileName, &statbuf);
116 } 107 }
117 108
118 if (!(flags & ACTION_DEPTHFIRST)) { 109 if (!(state->flags & ACTION_DEPTHFIRST)) {
119 status = dirAction(fileName, &statbuf, userData, depth); 110 status = state->dirAction(state, fileName, &statbuf);
120 if (status == FALSE) 111 if (status == FALSE)
121 goto done_nak_warn; 112 goto done_nak_warn;
122 if (status == SKIP) 113 if (status == SKIP)
@@ -140,11 +131,13 @@ int FAST_FUNC recursive_action(const char *fileName,
140 continue; 131 continue;
141 132
142 /* process every file (NB: ACTION_RECURSE is set in flags) */ 133 /* process every file (NB: ACTION_RECURSE is set in flags) */
143 s = recursive_action(nextFile, flags, fileAction, dirAction, 134 state->depth++;
144 userData, depth + 1); 135 s = recursive_action1(state, nextFile);
145 if (s == FALSE) 136 if (s == FALSE)
146 status = FALSE; 137 status = FALSE;
147 free(nextFile); 138 free(nextFile);
139 state->depth--;
140
148//#define RECURSE_RESULT_ABORT -1 141//#define RECURSE_RESULT_ABORT -1
149// if (s == RECURSE_RESULT_ABORT) { 142// if (s == RECURSE_RESULT_ABORT) {
150// closedir(dir); 143// closedir(dir);
@@ -153,15 +146,36 @@ int FAST_FUNC recursive_action(const char *fileName,
153 } 146 }
154 closedir(dir); 147 closedir(dir);
155 148
156 if (flags & ACTION_DEPTHFIRST) { 149 if (state->flags & ACTION_DEPTHFIRST) {
157 if (!dirAction(fileName, &statbuf, userData, depth)) 150 if (!state->dirAction(state, fileName, &statbuf))
158 goto done_nak_warn; 151 goto done_nak_warn;
159 } 152 }
160 153
161 return status; 154 return status;
162 155
163 done_nak_warn: 156 done_nak_warn:
164 if (!(flags & ACTION_QUIET)) 157 if (!(state->flags & ACTION_QUIET))
165 bb_simple_perror_msg(fileName); 158 bb_simple_perror_msg(fileName);
166 return FALSE; 159 return FALSE;
167} 160}
161
162int FAST_FUNC recursive_action(const char *fileName,
163 unsigned flags,
164 int FAST_FUNC (*fileAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
165 int FAST_FUNC (*dirAction)(struct recursive_state *state, const char *fileName, struct stat* statbuf),
166 void *userData)
167{
168 /* Keeping a part of variables of recusive descent in a "state structure"
169 * instead of passing ALL of them down as parameters of recursive_action1()
170 * relieves register pressure, both in recursive_action1()
171 * and in every file/dirAction().
172 */
173 recursive_state_t state;
174 state.flags = flags;
175 state.depth = 0;
176 state.userData = userData;
177 state.fileAction = fileAction ? fileAction : true_action;
178 state.dirAction = dirAction ? dirAction : true_action;
179
180 return recursive_action1(&state, fileName);
181}
diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c
index c605c4c64..7b67f30cd 100644
--- a/libbb/update_passwd.c
+++ b/libbb/update_passwd.c
@@ -18,17 +18,20 @@
18#if ENABLE_SELINUX 18#if ENABLE_SELINUX
19static void check_selinux_update_passwd(const char *username) 19static void check_selinux_update_passwd(const char *username)
20{ 20{
21 security_context_t context; 21 security_context_t seuser;
22 char *seuser; 22 char *p;
23 23
24 if (getuid() != (uid_t)0 || is_selinux_enabled() == 0) 24 if (getuid() != (uid_t)0 || is_selinux_enabled() == 0)
25 return; /* No need to check */ 25 return; /* No need to check */
26 26
27 if (getprevcon_raw(&context) < 0) 27 if (getprevcon_raw(&seuser) < 0)
28 bb_simple_perror_msg_and_die("getprevcon failed"); 28 bb_simple_perror_msg_and_die("getprevcon failed");
29 seuser = strtok(context, ":"); 29
30 if (!seuser) 30 p = strchr(seuser, ':');
31 bb_error_msg_and_die("invalid context '%s'", context); 31 if (!p)
32 bb_error_msg_and_die("invalid context '%s'", seuser);
33 *p = '\0';
34
32 if (strcmp(seuser, username) != 0) { 35 if (strcmp(seuser, username) != 0) {
33 security_class_t tclass; 36 security_class_t tclass;
34 access_vector_t av; 37 access_vector_t av;