diff options
author | Ron Yorston <rmy@pobox.com> | 2020-11-12 08:27:51 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-11-12 08:27:51 +0000 |
commit | ead8b92e3d66ab45235e137f85fb3a529dcc64ef (patch) | |
tree | af268270382dad969218063d4a8120fc91a9e631 /libbb | |
parent | 567728c22dddea4ed33b8a69641ba2e0c3f1f600 (diff) | |
parent | 64981b4c8e88812c322bee3832f1d421ff670ed5 (diff) | |
download | busybox-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.c | 9 | ||||
-rw-r--r-- | libbb/dump.c | 70 | ||||
-rw-r--r-- | libbb/hash_md5_sha.c | 75 | ||||
-rw-r--r-- | libbb/inet_cksum.c | 4 | ||||
-rw-r--r-- | libbb/kernel_version.c | 20 | ||||
-rw-r--r-- | libbb/loop.c | 4 | ||||
-rw-r--r-- | libbb/ptr_to_globals.c | 4 | ||||
-rw-r--r-- | libbb/recursive_action.c | 72 | ||||
-rw-r--r-- | libbb/update_passwd.c | 15 |
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> | ||
31 | static 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 | |||
318 | void lbb_prepare(const char *applet | 323 | void 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 | ||
16 | static 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 */ | |
18 | static 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 */ | |
21 | static 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 | ||
24 | typedef struct priv_dumper_t { | 30 | typedef 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 | ||
48 | static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789"; | ||
49 | |||
50 | static const char size_conv_str[] ALIGN1 = | ||
51 | "\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; | ||
52 | |||
53 | static const char int_convs[] ALIGN1 = "diouxX"; | ||
54 | |||
42 | dumper_t* FAST_FUNC alloc_dumper(void) | 55 | dumper_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 | |||
52 | static NOINLINE int bb_dump_size(FS *fs) | 64 | static 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 | ||
521 | static void display(priv_dumper_t* dumper) | 534 | static 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 | */ | ||
45 | static 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 */ |
71 | static void FAST_FUNC common64_end(md5_ctx_t *ctx, int swap_needed) | 42 | static 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 */ |
450 | void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) | 421 | void 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 | ||
9 | uint16_t FAST_FUNC inet_cksum(uint16_t *addr, int nleft) | 9 | uint16_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 | */ |
105 | int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, unsigned flags) | 105 | int 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 */ |
15 | struct globals *ptr_to_globals; | 15 | struct globals *ptr_to_globals; |
16 | 16 | ||
17 | #ifdef __GLIBC__ | 17 | #ifdef errno |
18 | int *bb_errno; | 18 | int *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 */ |
28 | struct globals *const ptr_to_globals __attribute__ ((section (".data"))); | 28 | struct globals *const ptr_to_globals __attribute__ ((section (".data"))); |
29 | 29 | ||
30 | #ifdef __GLIBC__ | 30 | #ifdef errno |
31 | int *const bb_errno __attribute__ ((section (".data"))); | 31 | int *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 | ||
24 | static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM, | 24 | static 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 | ||
68 | int FAST_FUNC recursive_action(const char *fileName, | 67 | static 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 | |||
162 | int 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 |
19 | static void check_selinux_update_passwd(const char *username) | 19 | static 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; |