diff options
author | Ron Yorston <rmy@pobox.com> | 2012-09-07 11:48:25 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-09-07 11:48:25 +0100 |
commit | fecf687cc358883de2da21de33346f0df204c80b (patch) | |
tree | d22c606157926fb659374ae68d55e3a874bacf25 | |
parent | b25a7c28a0f684087fa6ccbbc7e265a9cac0f0fa (diff) | |
parent | 6d463de46b418e6c4c8d1397033608f78b33ab21 (diff) | |
download | busybox-w32-fecf687cc358883de2da21de33346f0df204c80b.tar.gz busybox-w32-fecf687cc358883de2da21de33346f0df204c80b.tar.bz2 busybox-w32-fecf687cc358883de2da21de33346f0df204c80b.zip |
Merge branch 'busybox' into merge
Conflicts:
include/libbb.h
shell/ash.c
99 files changed, 1499 insertions, 801 deletions
diff --git a/Makefile.flags b/Makefile.flags index 4cbef0597..fbb348a39 100644 --- a/Makefile.flags +++ b/Makefile.flags | |||
@@ -25,6 +25,7 @@ CFLAGS += $(call cc-option,-Wstrict-prototypes,) | |||
25 | CFLAGS += $(call cc-option,-Wunused -Wunused-parameter,) | 25 | CFLAGS += $(call cc-option,-Wunused -Wunused-parameter,) |
26 | CFLAGS += $(call cc-option,-Wunused-function -Wunused-value,) | 26 | CFLAGS += $(call cc-option,-Wunused-function -Wunused-value,) |
27 | CFLAGS += $(call cc-option,-Wmissing-prototypes -Wmissing-declarations,) | 27 | CFLAGS += $(call cc-option,-Wmissing-prototypes -Wmissing-declarations,) |
28 | CFLAGS += $(call cc-option,-Wno-format-security,) | ||
28 | # warn about C99 declaration after statement | 29 | # warn about C99 declaration after statement |
29 | CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) | 30 | CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) |
30 | # If you want to add more -Wsomething above, make sure that it is | 31 | # If you want to add more -Wsomething above, make sure that it is |
@@ -52,6 +53,9 @@ CFLAGS += $(call cc-option,-fno-builtin-strlen -finline-limit=0 -fomit-frame-poi | |||
52 | CFLAGS += $(call cc-option,-fno-guess-branch-probability,) | 53 | CFLAGS += $(call cc-option,-fno-guess-branch-probability,) |
53 | CFLAGS += $(call cc-option,-funsigned-char -static-libgcc,) | 54 | CFLAGS += $(call cc-option,-funsigned-char -static-libgcc,) |
54 | CFLAGS += $(call cc-option,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,) | 55 | CFLAGS += $(call cc-option,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,) |
56 | # Defeat .eh_frame bloat (gcc 4.6.3 x86-32 defconfig: 20% smaller busybox binary): | ||
57 | CFLAGS += $(call cc-option,-fno-unwind-tables,) | ||
58 | CFLAGS += $(call cc-option,-fno-asynchronous-unwind-tables,) | ||
55 | 59 | ||
56 | # FIXME: These warnings are at least partially to be concerned about and should | 60 | # FIXME: These warnings are at least partially to be concerned about and should |
57 | # be fixed.. | 61 | # be fixed.. |
diff --git a/applets/individual.c b/applets/individual.c index 1e74e4ce5..4c468df06 100644 --- a/applets/individual.c +++ b/applets/individual.c | |||
@@ -14,7 +14,7 @@ const char *applet_name; | |||
14 | int main(int argc, char **argv) | 14 | int main(int argc, char **argv) |
15 | { | 15 | { |
16 | applet_name = argv[0]; | 16 | applet_name = argv[0]; |
17 | return APPLET_main(argc,argv); | 17 | return APPLET_main(argc, argv); |
18 | } | 18 | } |
19 | 19 | ||
20 | void bb_show_usage(void) | 20 | void bb_show_usage(void) |
diff --git a/archival/dpkg.c b/archival/dpkg.c index bf9e9992c..dae8a9747 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -1665,20 +1665,25 @@ static void unpack_package(deb_file_t *deb_file) | |||
1665 | archive_handle = init_archive_deb_ar(deb_file->filename); | 1665 | archive_handle = init_archive_deb_ar(deb_file->filename); |
1666 | init_archive_deb_data(archive_handle); | 1666 | init_archive_deb_data(archive_handle); |
1667 | archive_handle->dpkg__sub_archive->accept = conffile_list; | 1667 | archive_handle->dpkg__sub_archive->accept = conffile_list; |
1668 | /* Why ARCHIVE_REMEMBER_NAMES? | ||
1669 | * We want names collected in ->passed list even if conffile_list | ||
1670 | * is NULL (otherwise get_header_tar may optimize name saving out): | ||
1671 | */ | ||
1672 | archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_REMEMBER_NAMES | ARCHIVE_UNLINK_OLD; | ||
1668 | archive_handle->dpkg__sub_archive->filter = filter_rename_config; | 1673 | archive_handle->dpkg__sub_archive->filter = filter_rename_config; |
1669 | archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix; | 1674 | archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix; |
1670 | archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */ | 1675 | archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */ |
1671 | archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD; | ||
1672 | unpack_ar_archive(archive_handle); | 1676 | unpack_ar_archive(archive_handle); |
1673 | 1677 | ||
1674 | /* Create the list file */ | 1678 | /* Create the list file */ |
1675 | list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list"); | 1679 | list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list"); |
1676 | out_stream = xfopen_for_write(list_filename); | 1680 | out_stream = xfopen_for_write(list_filename); |
1681 | archive_handle->dpkg__sub_archive->passed = llist_rev(archive_handle->dpkg__sub_archive->passed); | ||
1677 | while (archive_handle->dpkg__sub_archive->passed) { | 1682 | while (archive_handle->dpkg__sub_archive->passed) { |
1683 | char *filename = llist_pop(&archive_handle->dpkg__sub_archive->passed); | ||
1678 | /* the leading . has been stripped by data_extract_all_prefix already */ | 1684 | /* the leading . has been stripped by data_extract_all_prefix already */ |
1679 | fputs(archive_handle->dpkg__sub_archive->passed->data, out_stream); | 1685 | fprintf(out_stream, "%s\n", filename); |
1680 | fputc('\n', out_stream); | 1686 | free(filename); |
1681 | archive_handle->dpkg__sub_archive->passed = archive_handle->dpkg__sub_archive->passed->link; | ||
1682 | } | 1687 | } |
1683 | fclose(out_stream); | 1688 | fclose(out_stream); |
1684 | 1689 | ||
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index e2134be4c..58457fc22 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src | |||
@@ -45,7 +45,7 @@ lib-$(CONFIG_UNXZ) += decompress_unxz.o | |||
45 | lib-$(CONFIG_CPIO) += get_header_cpio.o | 45 | lib-$(CONFIG_CPIO) += get_header_cpio.o |
46 | lib-$(CONFIG_DPKG) += $(DPKG_FILES) | 46 | lib-$(CONFIG_DPKG) += $(DPKG_FILES) |
47 | lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES) | 47 | lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES) |
48 | lib-$(CONFIG_GUNZIP) += decompress_gunzip.o | 48 | lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o |
49 | lib-$(CONFIG_RPM2CPIO) += decompress_gunzip.o get_header_cpio.o | 49 | lib-$(CONFIG_RPM2CPIO) += decompress_gunzip.o get_header_cpio.o |
50 | lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o | 50 | lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o |
51 | lib-$(CONFIG_TAR) += get_header_tar.o | 51 | lib-$(CONFIG_TAR) += get_header_tar.o |
diff --git a/archival/libarchive/filter_accept_reject_list.c b/archival/libarchive/filter_accept_reject_list.c index 39c811337..248374941 100644 --- a/archival/libarchive/filter_accept_reject_list.c +++ b/archival/libarchive/filter_accept_reject_list.c | |||
@@ -24,11 +24,13 @@ char FAST_FUNC filter_accept_reject_list(archive_handle_t *archive_handle) | |||
24 | if (reject_entry) { | 24 | if (reject_entry) { |
25 | return EXIT_FAILURE; | 25 | return EXIT_FAILURE; |
26 | } | 26 | } |
27 | accept_entry = find_list_entry2(archive_handle->accept, key); | ||
28 | 27 | ||
29 | /* Fail if an accept list was specified and the key wasnt in there */ | 28 | /* Fail if an accept list was specified and the key wasnt in there */ |
30 | if ((accept_entry == NULL) && archive_handle->accept) { | 29 | if (archive_handle->accept) { |
31 | return EXIT_FAILURE; | 30 | accept_entry = find_list_entry2(archive_handle->accept, key); |
31 | if (!accept_entry) { | ||
32 | return EXIT_FAILURE; | ||
33 | } | ||
32 | } | 34 | } |
33 | 35 | ||
34 | /* Accepted */ | 36 | /* Accepted */ |
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index 80a709144..bc09756ba 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c | |||
@@ -84,7 +84,7 @@ static unsigned long long getOctal(char *str, int len) | |||
84 | first >>= 1; /* now 7th bit = 6th bit */ | 84 | first >>= 1; /* now 7th bit = 6th bit */ |
85 | v = first; /* sign-extend 8 bits to 64 */ | 85 | v = first; /* sign-extend 8 bits to 64 */ |
86 | while (--len != 0) | 86 | while (--len != 0) |
87 | v = (v << 8) + (unsigned char) *str++; | 87 | v = (v << 8) + (uint8_t) *++str; |
88 | } | 88 | } |
89 | return v; | 89 | return v; |
90 | } | 90 | } |
@@ -452,9 +452,11 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
452 | if (cp) | 452 | if (cp) |
453 | *cp = '\0'; | 453 | *cp = '\0'; |
454 | archive_handle->action_data(archive_handle); | 454 | archive_handle->action_data(archive_handle); |
455 | if (archive_handle->accept || archive_handle->reject) | 455 | if (archive_handle->accept || archive_handle->reject |
456 | || (archive_handle->ah_flags & ARCHIVE_REMEMBER_NAMES) | ||
457 | ) { | ||
456 | llist_add_to(&archive_handle->passed, file_header->name); | 458 | llist_add_to(&archive_handle->passed, file_header->name); |
457 | else /* Caller isn't interested in list of unpacked files */ | 459 | } else /* Caller isn't interested in list of unpacked files */ |
458 | free(file_header->name); | 460 | free(file_header->name); |
459 | } else { | 461 | } else { |
460 | data_skip(archive_handle); | 462 | data_skip(archive_handle); |
diff --git a/archival/tar.c b/archival/tar.c index 9fa5a0f44..e27950b6c 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -60,8 +60,8 @@ | |||
60 | 60 | ||
61 | #if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2 | 61 | #if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2 |
62 | /* Do not pass gzip flag to writeTarFile() */ | 62 | /* Do not pass gzip flag to writeTarFile() */ |
63 | #define writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude, gzip) \ | 63 | #define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \ |
64 | writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude) | 64 | writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude) |
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | 67 | ||
@@ -600,7 +600,7 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) | |||
600 | 600 | ||
601 | /* gcc 4.2.1 inlines it, making code bigger */ | 601 | /* gcc 4.2.1 inlines it, making code bigger */ |
602 | static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, | 602 | static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, |
603 | int dereferenceFlag, const llist_t *include, | 603 | int recurseFlags, const llist_t *include, |
604 | const llist_t *exclude, int gzip) | 604 | const llist_t *exclude, int gzip) |
605 | { | 605 | { |
606 | int errorFlag = FALSE; | 606 | int errorFlag = FALSE; |
@@ -623,8 +623,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, | |||
623 | 623 | ||
624 | /* Read the directory/files and iterate over them one at a time */ | 624 | /* Read the directory/files and iterate over them one at a time */ |
625 | while (include) { | 625 | while (include) { |
626 | if (!recursive_action(include->data, ACTION_RECURSE | | 626 | if (!recursive_action(include->data, recurseFlags, |
627 | (dereferenceFlag ? ACTION_FOLLOWLINKS : 0), | ||
628 | writeFileToTarball, writeFileToTarball, &tbInfo, 0) | 627 | writeFileToTarball, writeFileToTarball, &tbInfo, 0) |
629 | ) { | 628 | ) { |
630 | errorFlag = TRUE; | 629 | errorFlag = TRUE; |
@@ -664,7 +663,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, | |||
664 | } | 663 | } |
665 | #else | 664 | #else |
666 | int writeTarFile(int tar_fd, int verboseFlag, | 665 | int writeTarFile(int tar_fd, int verboseFlag, |
667 | int dereferenceFlag, const llist_t *include, | 666 | int recurseFlags, const llist_t *include, |
668 | const llist_t *exclude, int gzip); | 667 | const llist_t *exclude, int gzip); |
669 | #endif /* FEATURE_TAR_CREATE */ | 668 | #endif /* FEATURE_TAR_CREATE */ |
670 | 669 | ||
@@ -696,6 +695,7 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
696 | //usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" | 695 | //usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" |
697 | //usage: IF_FEATURE_SEAMLESS_Z("Z") | 696 | //usage: IF_FEATURE_SEAMLESS_Z("Z") |
698 | //usage: IF_FEATURE_SEAMLESS_GZ("z") | 697 | //usage: IF_FEATURE_SEAMLESS_GZ("z") |
698 | //usage: IF_FEATURE_SEAMLESS_XZ("J") | ||
699 | //usage: IF_FEATURE_SEAMLESS_BZ2("j") | 699 | //usage: IF_FEATURE_SEAMLESS_BZ2("j") |
700 | //usage: IF_FEATURE_SEAMLESS_LZMA("a") | 700 | //usage: IF_FEATURE_SEAMLESS_LZMA("a") |
701 | //usage: IF_FEATURE_TAR_CREATE("h") | 701 | //usage: IF_FEATURE_TAR_CREATE("h") |
@@ -722,6 +722,9 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
722 | //usage: IF_FEATURE_SEAMLESS_GZ( | 722 | //usage: IF_FEATURE_SEAMLESS_GZ( |
723 | //usage: "\n z (De)compress using gzip" | 723 | //usage: "\n z (De)compress using gzip" |
724 | //usage: ) | 724 | //usage: ) |
725 | //usage: IF_FEATURE_SEAMLESS_XZ( | ||
726 | //usage: "\n J (De)compress using xz" | ||
727 | //usage: ) | ||
725 | //usage: IF_FEATURE_SEAMLESS_BZ2( | 728 | //usage: IF_FEATURE_SEAMLESS_BZ2( |
726 | //usage: "\n j (De)compress using bzip2" | 729 | //usage: "\n j (De)compress using bzip2" |
727 | //usage: ) | 730 | //usage: ) |
@@ -751,6 +754,7 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
751 | // o no-same-owner | 754 | // o no-same-owner |
752 | // p same-permissions | 755 | // p same-permissions |
753 | // k keep-old | 756 | // k keep-old |
757 | // no-recursion | ||
754 | // numeric-owner | 758 | // numeric-owner |
755 | // no-same-permissions | 759 | // no-same-permissions |
756 | // overwrite | 760 | // overwrite |
@@ -767,9 +771,11 @@ enum { | |||
767 | IF_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,) | 771 | IF_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,) |
768 | IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,) | 772 | IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,) |
769 | IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,) | 773 | IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,) |
770 | IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) // 16th bit | 774 | IF_FEATURE_SEAMLESS_XZ( OPTBIT_XZ ,) // 16th bit |
775 | IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) | ||
771 | IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,) | 776 | IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,) |
772 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS | 777 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS |
778 | OPTBIT_NORECURSION, | ||
773 | IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,) | 779 | IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,) |
774 | OPTBIT_NUMERIC_OWNER, | 780 | OPTBIT_NUMERIC_OWNER, |
775 | OPTBIT_NOPRESERVE_PERM, | 781 | OPTBIT_NOPRESERVE_PERM, |
@@ -791,14 +797,16 @@ enum { | |||
791 | OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_INCLUDE_FROM)) + 0, // T | 797 | OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_INCLUDE_FROM)) + 0, // T |
792 | OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X | 798 | OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X |
793 | OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z | 799 | OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z |
800 | OPT_XZ = IF_FEATURE_SEAMLESS_XZ( (1 << OPTBIT_XZ )) + 0, // J | ||
794 | OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z | 801 | OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z |
795 | OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m | 802 | OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m |
803 | OPT_NORECURSION = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NORECURSION )) + 0, // no-recursion | ||
796 | OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command | 804 | OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command |
797 | OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner | 805 | OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner |
798 | OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions | 806 | OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions |
799 | OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite | 807 | OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite |
800 | 808 | ||
801 | OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_COMPRESS), | 809 | OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_COMPRESS), |
802 | }; | 810 | }; |
803 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS | 811 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS |
804 | static const char tar_longopts[] ALIGN1 = | 812 | static const char tar_longopts[] ALIGN1 = |
@@ -831,12 +839,16 @@ static const char tar_longopts[] ALIGN1 = | |||
831 | # if ENABLE_FEATURE_SEAMLESS_GZ | 839 | # if ENABLE_FEATURE_SEAMLESS_GZ |
832 | "gzip\0" No_argument "z" | 840 | "gzip\0" No_argument "z" |
833 | # endif | 841 | # endif |
842 | # if ENABLE_FEATURE_SEAMLESS_XZ | ||
843 | "xz\0" No_argument "J" | ||
844 | # endif | ||
834 | # if ENABLE_FEATURE_SEAMLESS_Z | 845 | # if ENABLE_FEATURE_SEAMLESS_Z |
835 | "compress\0" No_argument "Z" | 846 | "compress\0" No_argument "Z" |
836 | # endif | 847 | # endif |
837 | # if ENABLE_FEATURE_TAR_NOPRESERVE_TIME | 848 | # if ENABLE_FEATURE_TAR_NOPRESERVE_TIME |
838 | "touch\0" No_argument "m" | 849 | "touch\0" No_argument "m" |
839 | # endif | 850 | # endif |
851 | "no-recursion\0" No_argument "\xfa" | ||
840 | # if ENABLE_FEATURE_TAR_TO_COMMAND | 852 | # if ENABLE_FEATURE_TAR_TO_COMMAND |
841 | "to-command\0" Required_argument "\xfb" | 853 | "to-command\0" Required_argument "\xfb" |
842 | # endif | 854 | # endif |
@@ -923,6 +935,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
923 | IF_FEATURE_SEAMLESS_LZMA("a" ) | 935 | IF_FEATURE_SEAMLESS_LZMA("a" ) |
924 | IF_FEATURE_TAR_FROM( "T:X:") | 936 | IF_FEATURE_TAR_FROM( "T:X:") |
925 | IF_FEATURE_SEAMLESS_GZ( "z" ) | 937 | IF_FEATURE_SEAMLESS_GZ( "z" ) |
938 | IF_FEATURE_SEAMLESS_XZ( "J" ) | ||
926 | IF_FEATURE_SEAMLESS_Z( "Z" ) | 939 | IF_FEATURE_SEAMLESS_Z( "Z" ) |
927 | IF_FEATURE_TAR_NOPRESERVE_TIME("m") | 940 | IF_FEATURE_TAR_NOPRESERVE_TIME("m") |
928 | , &base_dir // -C dir | 941 | , &base_dir // -C dir |
@@ -1052,7 +1065,9 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1052 | zipMode = 2; | 1065 | zipMode = 2; |
1053 | #endif | 1066 | #endif |
1054 | /* NB: writeTarFile() closes tar_handle->src_fd */ | 1067 | /* NB: writeTarFile() closes tar_handle->src_fd */ |
1055 | return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE, | 1068 | return writeTarFile(tar_handle->src_fd, verboseFlag, |
1069 | (opt & OPT_DEREFERENCE ? ACTION_FOLLOWLINKS : 0) | ||
1070 | | (opt & OPT_NORECURSION ? 0 : ACTION_RECURSE), | ||
1056 | tar_handle->accept, | 1071 | tar_handle->accept, |
1057 | tar_handle->reject, zipMode); | 1072 | tar_handle->reject, zipMode); |
1058 | } | 1073 | } |
@@ -1073,6 +1088,9 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1073 | if (opt & OPT_LZMA) | 1088 | if (opt & OPT_LZMA) |
1074 | USE_FOR_MMU(xformer = unpack_lzma_stream;) | 1089 | USE_FOR_MMU(xformer = unpack_lzma_stream;) |
1075 | USE_FOR_NOMMU(xformer_prog = "unlzma";) | 1090 | USE_FOR_NOMMU(xformer_prog = "unlzma";) |
1091 | if (opt & OPT_XZ) | ||
1092 | USE_FOR_MMU(xformer = unpack_xz_stream;) | ||
1093 | USE_FOR_NOMMU(xformer_prog = "unxz";) | ||
1076 | 1094 | ||
1077 | open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); | 1095 | open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); |
1078 | /* Can't lseek over pipes */ | 1096 | /* Can't lseek over pipes */ |
diff --git a/archival/unzip.c b/archival/unzip.c index 3c76cdafc..046027cc6 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -20,16 +20,16 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | //usage:#define unzip_trivial_usage | 22 | //usage:#define unzip_trivial_usage |
23 | //usage: "[-opts[modifiers]] FILE[.zip] [LIST] [-x XLIST] [-d DIR]" | 23 | //usage: "[-lnopq] FILE[.zip] [FILE]... [-x FILE...] [-d DIR]" |
24 | //usage:#define unzip_full_usage "\n\n" | 24 | //usage:#define unzip_full_usage "\n\n" |
25 | //usage: "Extract files from ZIP archives\n" | 25 | //usage: "Extract FILEs from ZIP archive\n" |
26 | //usage: "\n -l List archive contents (with -q for short form)" | 26 | //usage: "\n -l List contents (with -q for short form)" |
27 | //usage: "\n -n Never overwrite files (default)" | 27 | //usage: "\n -n Never overwrite files (default: ask)" |
28 | //usage: "\n -o Overwrite" | 28 | //usage: "\n -o Overwrite" |
29 | //usage: "\n -p Send output to stdout" | 29 | //usage: "\n -p Print to stdout" |
30 | //usage: "\n -q Quiet" | 30 | //usage: "\n -q Quiet" |
31 | //usage: "\n -x XLST Exclude these files" | 31 | //usage: "\n -x FILE Exclude FILEs" |
32 | //usage: "\n -d DIR Extract files into DIR" | 32 | //usage: "\n -d DIR Extract into DIR" |
33 | 33 | ||
34 | #include "libbb.h" | 34 | #include "libbb.h" |
35 | #include "bb_archive.h" | 35 | #include "bb_archive.h" |
@@ -277,6 +277,7 @@ int unzip_main(int argc, char **argv) | |||
277 | IF_NOT_DESKTOP(const) smallint verbose = 0; | 277 | IF_NOT_DESKTOP(const) smallint verbose = 0; |
278 | smallint listing = 0; | 278 | smallint listing = 0; |
279 | smallint overwrite = O_PROMPT; | 279 | smallint overwrite = O_PROMPT; |
280 | smallint x_opt_seen; | ||
280 | #if ENABLE_DESKTOP | 281 | #if ENABLE_DESKTOP |
281 | uint32_t cdf_offset; | 282 | uint32_t cdf_offset; |
282 | #endif | 283 | #endif |
@@ -290,7 +291,6 @@ int unzip_main(int argc, char **argv) | |||
290 | llist_t *zreject = NULL; | 291 | llist_t *zreject = NULL; |
291 | char *base_dir = NULL; | 292 | char *base_dir = NULL; |
292 | int i, opt; | 293 | int i, opt; |
293 | int opt_range = 0; | ||
294 | char key_buf[80]; | 294 | char key_buf[80]; |
295 | struct stat stat_buf; | 295 | struct stat stat_buf; |
296 | 296 | ||
@@ -335,81 +335,81 @@ int unzip_main(int argc, char **argv) | |||
335 | * 204372 1 file | 335 | * 204372 1 file |
336 | */ | 336 | */ |
337 | 337 | ||
338 | x_opt_seen = 0; | ||
338 | /* '-' makes getopt return 1 for non-options */ | 339 | /* '-' makes getopt return 1 for non-options */ |
339 | while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { | 340 | while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { |
340 | switch (opt_range) { | 341 | switch (opt) { |
341 | case 0: /* Options */ | 342 | case 'd': /* Extract to base directory */ |
342 | switch (opt) { | 343 | base_dir = optarg; |
343 | case 'l': /* List */ | 344 | break; |
344 | listing = 1; | ||
345 | break; | ||
346 | 345 | ||
347 | case 'n': /* Never overwrite existing files */ | 346 | case 'l': /* List */ |
348 | overwrite = O_NEVER; | 347 | listing = 1; |
349 | break; | 348 | break; |
350 | 349 | ||
351 | case 'o': /* Always overwrite existing files */ | 350 | case 'n': /* Never overwrite existing files */ |
352 | overwrite = O_ALWAYS; | 351 | overwrite = O_NEVER; |
353 | break; | 352 | break; |
354 | 353 | ||
355 | case 'p': /* Extract files to stdout and fall through to set verbosity */ | 354 | case 'o': /* Always overwrite existing files */ |
356 | dst_fd = STDOUT_FILENO; | 355 | overwrite = O_ALWAYS; |
356 | break; | ||
357 | 357 | ||
358 | case 'q': /* Be quiet */ | 358 | case 'p': /* Extract files to stdout and fall through to set verbosity */ |
359 | quiet++; | 359 | dst_fd = STDOUT_FILENO; |
360 | break; | ||
361 | 360 | ||
362 | case 'v': /* Verbose list */ | 361 | case 'q': /* Be quiet */ |
363 | IF_DESKTOP(verbose++;) | 362 | quiet++; |
364 | listing = 1; | 363 | break; |
365 | break; | ||
366 | 364 | ||
367 | case 1: /* The zip file */ | 365 | case 'v': /* Verbose list */ |
368 | /* +5: space for ".zip" and NUL */ | 366 | IF_DESKTOP(verbose++;) |
369 | src_fn = xmalloc(strlen(optarg) + 5); | 367 | listing = 1; |
370 | strcpy(src_fn, optarg); | 368 | break; |
371 | opt_range++; | ||
372 | break; | ||
373 | 369 | ||
374 | default: | 370 | case 'x': |
375 | bb_show_usage(); | 371 | x_opt_seen = 1; |
376 | } | ||
377 | break; | 372 | break; |
378 | 373 | ||
379 | case 1: /* Include files */ | 374 | case 1: |
380 | if (opt == 1) { | 375 | if (!src_fn) { |
376 | /* The zip file */ | ||
377 | /* +5: space for ".zip" and NUL */ | ||
378 | src_fn = xmalloc(strlen(optarg) + 5); | ||
379 | strcpy(src_fn, optarg); | ||
380 | } else if (!x_opt_seen) { | ||
381 | /* Include files */ | ||
381 | llist_add_to(&zaccept, optarg); | 382 | llist_add_to(&zaccept, optarg); |
382 | break; | 383 | } else { |
383 | } | 384 | /* Exclude files */ |
384 | if (opt == 'd') { | ||
385 | base_dir = optarg; | ||
386 | opt_range += 2; | ||
387 | break; | ||
388 | } | ||
389 | if (opt == 'x') { | ||
390 | opt_range++; | ||
391 | break; | ||
392 | } | ||
393 | bb_show_usage(); | ||
394 | |||
395 | case 2 : /* Exclude files */ | ||
396 | if (opt == 1) { | ||
397 | llist_add_to(&zreject, optarg); | 385 | llist_add_to(&zreject, optarg); |
398 | break; | ||
399 | } | 386 | } |
400 | if (opt == 'd') { /* Extract to base directory */ | 387 | break; |
401 | base_dir = optarg; | ||
402 | opt_range++; | ||
403 | break; | ||
404 | } | ||
405 | /* fall through */ | ||
406 | 388 | ||
407 | default: | 389 | default: |
408 | bb_show_usage(); | 390 | bb_show_usage(); |
409 | } | 391 | } |
410 | } | 392 | } |
411 | 393 | ||
412 | if (src_fn == NULL) { | 394 | #ifndef __GLIBC__ |
395 | /* | ||
396 | * This code is needed for non-GNU getopt | ||
397 | * which doesn't understand "-" in option string. | ||
398 | * The -x option won't work properly in this case: | ||
399 | * "unzip a.zip q -x w e" will be interpreted as | ||
400 | * "unzip a.zip q w e -x" = "unzip a.zip q w e" | ||
401 | */ | ||
402 | argv += optind; | ||
403 | if (argv[0]) { | ||
404 | /* +5: space for ".zip" and NUL */ | ||
405 | src_fn = xmalloc(strlen(argv[0]) + 5); | ||
406 | strcpy(src_fn, argv[0]); | ||
407 | while (*++argv) | ||
408 | llist_add_to(&zaccept, *argv); | ||
409 | } | ||
410 | #endif | ||
411 | |||
412 | if (!src_fn) { | ||
413 | bb_show_usage(); | 413 | bb_show_usage(); |
414 | } | 414 | } |
415 | 415 | ||
@@ -420,17 +420,20 @@ int unzip_main(int argc, char **argv) | |||
420 | if (overwrite == O_PROMPT) | 420 | if (overwrite == O_PROMPT) |
421 | overwrite = O_NEVER; | 421 | overwrite = O_NEVER; |
422 | } else { | 422 | } else { |
423 | static const char extn[][5] = {"", ".zip", ".ZIP"}; | 423 | static const char extn[][5] = { ".zip", ".ZIP" }; |
424 | int orig_src_fn_len = strlen(src_fn); | 424 | char *ext = src_fn + strlen(src_fn); |
425 | int src_fd = -1; | 425 | int src_fd; |
426 | 426 | ||
427 | for (i = 0; (i < 3) && (src_fd == -1); i++) { | 427 | i = 0; |
428 | strcpy(src_fn + orig_src_fn_len, extn[i]); | 428 | for (;;) { |
429 | src_fd = open(src_fn, O_RDONLY); | 429 | src_fd = open(src_fn, O_RDONLY); |
430 | } | 430 | if (src_fd >= 0) |
431 | if (src_fd == -1) { | 431 | break; |
432 | src_fn[orig_src_fn_len] = '\0'; | 432 | if (++i > 2) { |
433 | bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); | 433 | *ext = '\0'; |
434 | bb_error_msg_and_die("can't open %s[.zip]", src_fn); | ||
435 | } | ||
436 | strcpy(ext, extn[i - 1]); | ||
434 | } | 437 | } |
435 | xmove_fd(src_fd, zip_fd); | 438 | xmove_fd(src_fd, zip_fd); |
436 | } | 439 | } |
@@ -596,7 +599,7 @@ int unzip_main(int argc, char **argv) | |||
596 | printf(" creating: %s\n", dst_fn); | 599 | printf(" creating: %s\n", dst_fn); |
597 | } | 600 | } |
598 | unzip_create_leading_dirs(dst_fn); | 601 | unzip_create_leading_dirs(dst_fn); |
599 | if (bb_make_directory(dst_fn, dir_mode, 0)) { | 602 | if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) { |
600 | xfunc_die(); | 603 | xfunc_die(); |
601 | } | 604 | } |
602 | } else { | 605 | } else { |
diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig index 15e12b1d2..b45afd956 100644 --- a/configs/TEST_nommu_defconfig +++ b/configs/TEST_nommu_defconfig | |||
@@ -341,7 +341,6 @@ CONFIG_FEATURE_VI_READONLY=y | |||
341 | CONFIG_FEATURE_VI_SETOPTS=y | 341 | CONFIG_FEATURE_VI_SETOPTS=y |
342 | CONFIG_FEATURE_VI_SET=y | 342 | CONFIG_FEATURE_VI_SET=y |
343 | CONFIG_FEATURE_VI_WIN_RESIZE=y | 343 | CONFIG_FEATURE_VI_WIN_RESIZE=y |
344 | CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y | ||
345 | CONFIG_FEATURE_ALLOW_EXEC=y | 344 | CONFIG_FEATURE_ALLOW_EXEC=y |
346 | 345 | ||
347 | # | 346 | # |
diff --git a/configs/TEST_noprintf_defconfig b/configs/TEST_noprintf_defconfig index f4338df71..809b60cd8 100644 --- a/configs/TEST_noprintf_defconfig +++ b/configs/TEST_noprintf_defconfig | |||
@@ -346,7 +346,6 @@ CONFIG_FEATURE_VI_MAX_LEN=0 | |||
346 | # CONFIG_FEATURE_VI_SET is not set | 346 | # CONFIG_FEATURE_VI_SET is not set |
347 | # CONFIG_FEATURE_VI_WIN_RESIZE is not set | 347 | # CONFIG_FEATURE_VI_WIN_RESIZE is not set |
348 | # CONFIG_FEATURE_VI_ASK_TERMINAL is not set | 348 | # CONFIG_FEATURE_VI_ASK_TERMINAL is not set |
349 | # CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set | ||
350 | # CONFIG_FEATURE_ALLOW_EXEC is not set | 349 | # CONFIG_FEATURE_ALLOW_EXEC is not set |
351 | 350 | ||
352 | # | 351 | # |
diff --git a/configs/TEST_rh9_defconfig b/configs/TEST_rh9_defconfig index 193d8f615..565b826d0 100644 --- a/configs/TEST_rh9_defconfig +++ b/configs/TEST_rh9_defconfig | |||
@@ -358,7 +358,6 @@ CONFIG_FEATURE_VI_READONLY=y | |||
358 | CONFIG_FEATURE_VI_SETOPTS=y | 358 | CONFIG_FEATURE_VI_SETOPTS=y |
359 | CONFIG_FEATURE_VI_SET=y | 359 | CONFIG_FEATURE_VI_SET=y |
360 | CONFIG_FEATURE_VI_WIN_RESIZE=y | 360 | CONFIG_FEATURE_VI_WIN_RESIZE=y |
361 | CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y | ||
362 | CONFIG_FEATURE_ALLOW_EXEC=y | 361 | CONFIG_FEATURE_ALLOW_EXEC=y |
363 | 362 | ||
364 | # | 363 | # |
diff --git a/configs/android2_defconfig b/configs/android2_defconfig index b5166e0fc..4dfbdb526 100644 --- a/configs/android2_defconfig +++ b/configs/android2_defconfig | |||
@@ -363,7 +363,6 @@ CONFIG_FEATURE_VI_MAX_LEN=0 | |||
363 | # CONFIG_FEATURE_VI_SET is not set | 363 | # CONFIG_FEATURE_VI_SET is not set |
364 | # CONFIG_FEATURE_VI_WIN_RESIZE is not set | 364 | # CONFIG_FEATURE_VI_WIN_RESIZE is not set |
365 | # CONFIG_FEATURE_VI_ASK_TERMINAL is not set | 365 | # CONFIG_FEATURE_VI_ASK_TERMINAL is not set |
366 | # CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set | ||
367 | # CONFIG_AWK is not set | 366 | # CONFIG_AWK is not set |
368 | # CONFIG_FEATURE_AWK_LIBM is not set | 367 | # CONFIG_FEATURE_AWK_LIBM is not set |
369 | CONFIG_CMP=y | 368 | CONFIG_CMP=y |
diff --git a/configs/android_defconfig b/configs/android_defconfig index a9a8d5e1f..e35830e7f 100644 --- a/configs/android_defconfig +++ b/configs/android_defconfig | |||
@@ -386,7 +386,6 @@ CONFIG_FEATURE_VI_SETOPTS=y | |||
386 | CONFIG_FEATURE_VI_SET=y | 386 | CONFIG_FEATURE_VI_SET=y |
387 | CONFIG_FEATURE_VI_WIN_RESIZE=y | 387 | CONFIG_FEATURE_VI_WIN_RESIZE=y |
388 | CONFIG_FEATURE_VI_ASK_TERMINAL=y | 388 | CONFIG_FEATURE_VI_ASK_TERMINAL=y |
389 | CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y | ||
390 | CONFIG_AWK=y | 389 | CONFIG_AWK=y |
391 | CONFIG_FEATURE_AWK_LIBM=y | 390 | CONFIG_FEATURE_AWK_LIBM=y |
392 | CONFIG_CMP=y | 391 | CONFIG_CMP=y |
diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig index bf8827a58..01cc2dd15 100644 --- a/configs/android_ndk_defconfig +++ b/configs/android_ndk_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.20.0.git | 3 | # Busybox version: 1.21.0.git |
4 | # Fri Mar 2 16:53:26 2012 | 4 | # Mon May 28 21:51:18 2012 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | 7 | ||
@@ -20,11 +20,11 @@ CONFIG_PLATFORM_LINUX=y | |||
20 | CONFIG_FEATURE_BUFFERS_USE_MALLOC=y | 20 | CONFIG_FEATURE_BUFFERS_USE_MALLOC=y |
21 | # CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set | 21 | # CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set |
22 | # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set | 22 | # CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set |
23 | # CONFIG_SHOW_USAGE is not set | 23 | CONFIG_SHOW_USAGE=y |
24 | # CONFIG_FEATURE_VERBOSE_USAGE is not set | 24 | CONFIG_FEATURE_VERBOSE_USAGE=y |
25 | # CONFIG_FEATURE_COMPRESS_USAGE is not set | 25 | CONFIG_FEATURE_COMPRESS_USAGE=y |
26 | # CONFIG_FEATURE_INSTALLER is not set | 26 | CONFIG_FEATURE_INSTALLER=y |
27 | # CONFIG_INSTALL_NO_USR is not set | 27 | CONFIG_INSTALL_NO_USR=y |
28 | # CONFIG_LOCALE_SUPPORT is not set | 28 | # CONFIG_LOCALE_SUPPORT is not set |
29 | # CONFIG_UNICODE_SUPPORT is not set | 29 | # CONFIG_UNICODE_SUPPORT is not set |
30 | # CONFIG_UNICODE_USING_LOCALE is not set | 30 | # CONFIG_UNICODE_USING_LOCALE is not set |
@@ -36,7 +36,7 @@ CONFIG_LAST_SUPPORTED_WCHAR=0 | |||
36 | # CONFIG_UNICODE_BIDI_SUPPORT is not set | 36 | # CONFIG_UNICODE_BIDI_SUPPORT is not set |
37 | # CONFIG_UNICODE_NEUTRAL_TABLE is not set | 37 | # CONFIG_UNICODE_NEUTRAL_TABLE is not set |
38 | # CONFIG_UNICODE_PRESERVE_BROKEN is not set | 38 | # CONFIG_UNICODE_PRESERVE_BROKEN is not set |
39 | # CONFIG_LONG_OPTS is not set | 39 | CONFIG_LONG_OPTS=y |
40 | # CONFIG_FEATURE_DEVPTS is not set | 40 | # CONFIG_FEATURE_DEVPTS is not set |
41 | # CONFIG_FEATURE_CLEAN_UP is not set | 41 | # CONFIG_FEATURE_CLEAN_UP is not set |
42 | # CONFIG_FEATURE_UTMP is not set | 42 | # CONFIG_FEATURE_UTMP is not set |
@@ -67,7 +67,6 @@ CONFIG_EXTRA_CFLAGS="-DANDROID -D__ANDROID__ -DSK_RELEASE -nostdlib -march=armv7 | |||
67 | CONFIG_EXTRA_LDFLAGS="-Xlinker -z -Xlinker muldefs -nostdlib -Bdynamic -Xlinker -dynamic-linker -Xlinker /system/bin/linker -Xlinker -z -Xlinker nocopyreloc -Xlinker --no-undefined ${SYSROOT}/usr/lib/crtbegin_dynamic.o ${SYSROOT}/usr/lib/crtend_android.o" | 67 | CONFIG_EXTRA_LDFLAGS="-Xlinker -z -Xlinker muldefs -nostdlib -Bdynamic -Xlinker -dynamic-linker -Xlinker /system/bin/linker -Xlinker -z -Xlinker nocopyreloc -Xlinker --no-undefined ${SYSROOT}/usr/lib/crtbegin_dynamic.o ${SYSROOT}/usr/lib/crtend_android.o" |
68 | CONFIG_EXTRA_LDLIBS="dl m c gcc" | 68 | CONFIG_EXTRA_LDLIBS="dl m c gcc" |
69 | 69 | ||
70 | |||
71 | # | 70 | # |
72 | # Debugging Options | 71 | # Debugging Options |
73 | # | 72 | # |
@@ -112,7 +111,7 @@ CONFIG_FEATURE_EDITING_HISTORY=0 | |||
112 | # CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set | 111 | # CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set |
113 | # CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set | 112 | # CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set |
114 | # CONFIG_FEATURE_NON_POSIX_CP is not set | 113 | # CONFIG_FEATURE_NON_POSIX_CP is not set |
115 | # CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set | 114 | CONFIG_FEATURE_VERBOSE_CP_MESSAGE=y |
116 | CONFIG_FEATURE_COPYBUF_KB=4 | 115 | CONFIG_FEATURE_COPYBUF_KB=4 |
117 | # CONFIG_FEATURE_SKIP_ROOTFS is not set | 116 | # CONFIG_FEATURE_SKIP_ROOTFS is not set |
118 | # CONFIG_MONOTONIC_SYSCALL is not set | 117 | # CONFIG_MONOTONIC_SYSCALL is not set |
@@ -239,7 +238,7 @@ CONFIG_FEATURE_LS_RECURSIVE=y | |||
239 | CONFIG_FEATURE_LS_SORTFILES=y | 238 | CONFIG_FEATURE_LS_SORTFILES=y |
240 | CONFIG_FEATURE_LS_TIMESTAMPS=y | 239 | CONFIG_FEATURE_LS_TIMESTAMPS=y |
241 | CONFIG_FEATURE_LS_USERNAME=y | 240 | CONFIG_FEATURE_LS_USERNAME=y |
242 | # CONFIG_FEATURE_LS_COLOR is not set | 241 | CONFIG_FEATURE_LS_COLOR=y |
243 | # CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set | 242 | # CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set |
244 | CONFIG_MD5SUM=y | 243 | CONFIG_MD5SUM=y |
245 | CONFIG_MKDIR=y | 244 | CONFIG_MKDIR=y |
@@ -372,7 +371,6 @@ CONFIG_FEATURE_VI_SETOPTS=y | |||
372 | CONFIG_FEATURE_VI_SET=y | 371 | CONFIG_FEATURE_VI_SET=y |
373 | CONFIG_FEATURE_VI_WIN_RESIZE=y | 372 | CONFIG_FEATURE_VI_WIN_RESIZE=y |
374 | CONFIG_FEATURE_VI_ASK_TERMINAL=y | 373 | CONFIG_FEATURE_VI_ASK_TERMINAL=y |
375 | CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y | ||
376 | CONFIG_AWK=y | 374 | CONFIG_AWK=y |
377 | CONFIG_FEATURE_AWK_LIBM=y | 375 | CONFIG_FEATURE_AWK_LIBM=y |
378 | CONFIG_CMP=y | 376 | CONFIG_CMP=y |
@@ -516,7 +514,7 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y | |||
516 | # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set | 514 | # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set |
517 | # CONFIG_FEATURE_MODUTILS_ALIAS is not set | 515 | # CONFIG_FEATURE_MODUTILS_ALIAS is not set |
518 | # CONFIG_FEATURE_MODUTILS_SYMBOLS is not set | 516 | # CONFIG_FEATURE_MODUTILS_SYMBOLS is not set |
519 | CONFIG_DEFAULT_MODULES_DIR="/lib/modules" | 517 | CONFIG_DEFAULT_MODULES_DIR="/system/lib/modules" |
520 | CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" | 518 | CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" |
521 | 519 | ||
522 | # | 520 | # |
@@ -647,8 +645,8 @@ CONFIG_SETSERIAL=y | |||
647 | # CONFIG_UBIRSVOL is not set | 645 | # CONFIG_UBIRSVOL is not set |
648 | # CONFIG_UBIUPDATEVOL is not set | 646 | # CONFIG_UBIUPDATEVOL is not set |
649 | # CONFIG_ADJTIMEX is not set | 647 | # CONFIG_ADJTIMEX is not set |
650 | # CONFIG_BBCONFIG is not set | 648 | CONFIG_BBCONFIG=y |
651 | # CONFIG_FEATURE_COMPRESS_BBCONFIG is not set | 649 | CONFIG_FEATURE_COMPRESS_BBCONFIG=y |
652 | CONFIG_BEEP=y | 650 | CONFIG_BEEP=y |
653 | CONFIG_FEATURE_BEEP_FREQ=4000 | 651 | CONFIG_FEATURE_BEEP_FREQ=4000 |
654 | CONFIG_FEATURE_BEEP_LENGTH_MS=30 | 652 | CONFIG_FEATURE_BEEP_LENGTH_MS=30 |
@@ -883,6 +881,7 @@ CONFIG_SENDMAIL=y | |||
883 | # Process Utilities | 881 | # Process Utilities |
884 | # | 882 | # |
885 | CONFIG_IOSTAT=y | 883 | CONFIG_IOSTAT=y |
884 | CONFIG_LSOF=y | ||
886 | CONFIG_MPSTAT=y | 885 | CONFIG_MPSTAT=y |
887 | CONFIG_NMETER=y | 886 | CONFIG_NMETER=y |
888 | CONFIG_PMAP=y | 887 | CONFIG_PMAP=y |
diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig index bdd0d66d0..aa346e34c 100644 --- a/configs/cygwin_defconfig +++ b/configs/cygwin_defconfig | |||
@@ -363,7 +363,6 @@ CONFIG_FEATURE_VI_SETOPTS=y | |||
363 | CONFIG_FEATURE_VI_SET=y | 363 | CONFIG_FEATURE_VI_SET=y |
364 | CONFIG_FEATURE_VI_WIN_RESIZE=y | 364 | CONFIG_FEATURE_VI_WIN_RESIZE=y |
365 | CONFIG_FEATURE_VI_ASK_TERMINAL=y | 365 | CONFIG_FEATURE_VI_ASK_TERMINAL=y |
366 | CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y | ||
367 | CONFIG_AWK=y | 366 | CONFIG_AWK=y |
368 | CONFIG_FEATURE_AWK_LIBM=y | 367 | CONFIG_FEATURE_AWK_LIBM=y |
369 | CONFIG_CMP=y | 368 | CONFIG_CMP=y |
diff --git a/configs/freebsd_defconfig b/configs/freebsd_defconfig index dcb5d953c..ec3ed03c4 100644 --- a/configs/freebsd_defconfig +++ b/configs/freebsd_defconfig | |||
@@ -367,7 +367,6 @@ CONFIG_FEATURE_VI_SETOPTS=y | |||
367 | CONFIG_FEATURE_VI_SET=y | 367 | CONFIG_FEATURE_VI_SET=y |
368 | CONFIG_FEATURE_VI_WIN_RESIZE=y | 368 | CONFIG_FEATURE_VI_WIN_RESIZE=y |
369 | CONFIG_FEATURE_VI_ASK_TERMINAL=y | 369 | CONFIG_FEATURE_VI_ASK_TERMINAL=y |
370 | CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y | ||
371 | CONFIG_FEATURE_ALLOW_EXEC=y | 370 | CONFIG_FEATURE_ALLOW_EXEC=y |
372 | 371 | ||
373 | # | 372 | # |
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index 8497722ba..7a6f22b03 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | //usage:#if ENABLE_DESKTOP | 26 | //usage:#if ENABLE_DESKTOP |
27 | //usage:#define od_trivial_usage | 27 | //usage:#define od_trivial_usage |
28 | //usage: "[-abcdfhilovxs] [-t TYPE] [-A RADIX] [-N SIZE] [-j SKIP] [-S MINSTR] [-w WIDTH] [FILE...]" | 28 | //usage: "[-abcdfhilovxs] [-t TYPE] [-A RADIX] [-N SIZE] [-j SKIP] [-S MINSTR] [-w WIDTH] [FILE]..." |
29 | // We don't support: | 29 | // We don't support: |
30 | // ... [FILE] [[+]OFFSET[.][b]] | 30 | // ... [FILE] [[+]OFFSET[.][b]] |
31 | // Support is buggy for: | 31 | // Support is buggy for: |
diff --git a/coreutils/stat.c b/coreutils/stat.c index 2797719dd..3fb212f0f 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c | |||
@@ -99,9 +99,15 @@ static const char *file_type(const struct stat *st) | |||
99 | if (S_ISFIFO(st->st_mode)) return "fifo"; | 99 | if (S_ISFIFO(st->st_mode)) return "fifo"; |
100 | if (S_ISLNK(st->st_mode)) return "symbolic link"; | 100 | if (S_ISLNK(st->st_mode)) return "symbolic link"; |
101 | if (S_ISSOCK(st->st_mode)) return "socket"; | 101 | if (S_ISSOCK(st->st_mode)) return "socket"; |
102 | #ifdef S_TYPEISMQ | ||
102 | if (S_TYPEISMQ(st)) return "message queue"; | 103 | if (S_TYPEISMQ(st)) return "message queue"; |
104 | #endif | ||
105 | #ifdef S_TYPEISSEM | ||
103 | if (S_TYPEISSEM(st)) return "semaphore"; | 106 | if (S_TYPEISSEM(st)) return "semaphore"; |
107 | #endif | ||
108 | #ifdef S_TYPEISSHM | ||
104 | if (S_TYPEISSHM(st)) return "shared memory object"; | 109 | if (S_TYPEISSHM(st)) return "shared memory object"; |
110 | #endif | ||
105 | #ifdef S_TYPEISTMO | 111 | #ifdef S_TYPEISTMO |
106 | if (S_TYPEISTMO(st)) return "typed memory object"; | 112 | if (S_TYPEISTMO(st)) return "typed memory object"; |
107 | #endif | 113 | #endif |
diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c index 8f08f6dc6..005b30420 100644 --- a/debianutils/run_parts.c +++ b/debianutils/run_parts.c | |||
@@ -4,14 +4,13 @@ | |||
4 | * | 4 | * |
5 | * Copyright (C) 2007 Bernhard Reutner-Fischer | 5 | * Copyright (C) 2007 Bernhard Reutner-Fischer |
6 | * | 6 | * |
7 | * Based on a older version that was in busybox which was 1k big.. | 7 | * Based on a older version that was in busybox which was 1k big. |
8 | * Copyright (C) 2001 by Emanuele Aina <emanuele.aina@tiscali.it> | 8 | * Copyright (C) 2001 by Emanuele Aina <emanuele.aina@tiscali.it> |
9 | * | 9 | * |
10 | * Based on the Debian run-parts program, version 1.15 | 10 | * Based on the Debian run-parts program, version 1.15 |
11 | * Copyright (C) 1996 Jeff Noxon <jeff@router.patch.net>, | 11 | * Copyright (C) 1996 Jeff Noxon <jeff@router.patch.net>, |
12 | * Copyright (C) 1996-1999 Guy Maor <maor@debian.org> | 12 | * Copyright (C) 1996-1999 Guy Maor <maor@debian.org> |
13 | * | 13 | * |
14 | * | ||
15 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 14 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
16 | */ | 15 | */ |
17 | 16 | ||
@@ -19,7 +18,7 @@ | |||
19 | * attempt to write a program! :-) . */ | 18 | * attempt to write a program! :-) . */ |
20 | 19 | ||
21 | /* This piece of code is heavily based on the original version of run-parts, | 20 | /* This piece of code is heavily based on the original version of run-parts, |
22 | * taken from debian-utils. I've only removed the long options and a the | 21 | * taken from debian-utils. I've only removed the long options and the |
23 | * report mode. As the original run-parts support only long options, I've | 22 | * report mode. As the original run-parts support only long options, I've |
24 | * broken compatibility because the BusyBox policy doesn't allow them. | 23 | * broken compatibility because the BusyBox policy doesn't allow them. |
25 | * The supported options are: | 24 | * The supported options are: |
@@ -31,15 +30,15 @@ | |||
31 | */ | 30 | */ |
32 | 31 | ||
33 | //usage:#define run_parts_trivial_usage | 32 | //usage:#define run_parts_trivial_usage |
34 | //usage: "[-t] "IF_FEATURE_RUN_PARTS_FANCY("[-l] ")"[-a ARG] [-u MASK] DIRECTORY" | 33 | //usage: "[-t"IF_FEATURE_RUN_PARTS_FANCY("l")"] [-a ARG]... [-u MASK] DIRECTORY" |
35 | //usage:#define run_parts_full_usage "\n\n" | 34 | //usage:#define run_parts_full_usage "\n\n" |
36 | //usage: "Run a bunch of scripts in DIRECTORY\n" | 35 | //usage: "Run a bunch of scripts in DIRECTORY\n" |
37 | //usage: "\n -t Print what would be run, but don't actually run anything" | 36 | //usage: "\n -t Dry run" |
38 | //usage: "\n -a ARG Pass ARG as argument for every program" | ||
39 | //usage: "\n -u MASK Set the umask to MASK before running every program" | ||
40 | //usage: IF_FEATURE_RUN_PARTS_FANCY( | 37 | //usage: IF_FEATURE_RUN_PARTS_FANCY( |
41 | //usage: "\n -l Print names of all matching files even if they are not executable" | 38 | //usage: "\n -l Print names of matching files even if they are not executable" |
42 | //usage: ) | 39 | //usage: ) |
40 | //usage: "\n -a ARG Pass ARG as argument to programs" | ||
41 | //usage: "\n -u MASK Set umask to MASK before running programs" | ||
43 | //usage: | 42 | //usage: |
44 | //usage:#define run_parts_example_usage | 43 | //usage:#define run_parts_example_usage |
45 | //usage: "$ run-parts -a start /etc/init.d\n" | 44 | //usage: "$ run-parts -a start /etc/init.d\n" |
diff --git a/editors/awk.c b/editors/awk.c index 71abca215..42f6ef866 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -696,6 +696,10 @@ static char nextchar(char **s) | |||
696 | pps = *s; | 696 | pps = *s; |
697 | if (c == '\\') | 697 | if (c == '\\') |
698 | c = bb_process_escape_sequence((const char**)s); | 698 | c = bb_process_escape_sequence((const char**)s); |
699 | /* Example awk statement: | ||
700 | * s = "abc\"def" | ||
701 | * we must treat \" as " | ||
702 | */ | ||
699 | if (c == '\\' && *s == pps) { /* unrecognized \z? */ | 703 | if (c == '\\' && *s == pps) { /* unrecognized \z? */ |
700 | c = *(*s); /* yes, fetch z */ | 704 | c = *(*s); /* yes, fetch z */ |
701 | if (c) | 705 | if (c) |
@@ -704,6 +708,15 @@ static char nextchar(char **s) | |||
704 | return c; | 708 | return c; |
705 | } | 709 | } |
706 | 710 | ||
711 | /* TODO: merge with strcpy_and_process_escape_sequences()? | ||
712 | */ | ||
713 | static void unescape_string_in_place(char *s1) | ||
714 | { | ||
715 | char *s = s1; | ||
716 | while ((*s1 = nextchar(&s)) != '\0') | ||
717 | s1++; | ||
718 | } | ||
719 | |||
707 | static ALWAYS_INLINE int isalnum_(int c) | 720 | static ALWAYS_INLINE int isalnum_(int c) |
708 | { | 721 | { |
709 | return (isalnum(c) || c == '_'); | 722 | return (isalnum(c) || c == '_'); |
@@ -1799,6 +1812,18 @@ static void handle_special(var *v) | |||
1799 | is_f0_split = FALSE; | 1812 | is_f0_split = FALSE; |
1800 | 1813 | ||
1801 | } else if (v == intvar[FS]) { | 1814 | } else if (v == intvar[FS]) { |
1815 | /* | ||
1816 | * The POSIX-2008 standard says that changing FS should have no effect on the | ||
1817 | * current input line, but only on the next one. The language is: | ||
1818 | * | ||
1819 | * > Before the first reference to a field in the record is evaluated, the record | ||
1820 | * > shall be split into fields, according to the rules in Regular Expressions, | ||
1821 | * > using the value of FS that was current at the time the record was read. | ||
1822 | * | ||
1823 | * So, split up current line before assignment to FS: | ||
1824 | */ | ||
1825 | split_f0(); | ||
1826 | |||
1802 | mk_splitter(getvar_s(v), &fsplitter); | 1827 | mk_splitter(getvar_s(v), &fsplitter); |
1803 | 1828 | ||
1804 | } else if (v == intvar[RS]) { | 1829 | } else if (v == intvar[RS]) { |
@@ -2992,7 +3017,7 @@ static int awk_exit(int r) | |||
2992 | * otherwise return 0 */ | 3017 | * otherwise return 0 */ |
2993 | static int is_assignment(const char *expr) | 3018 | static int is_assignment(const char *expr) |
2994 | { | 3019 | { |
2995 | char *exprc, *val, *s, *s1; | 3020 | char *exprc, *val; |
2996 | 3021 | ||
2997 | if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) { | 3022 | if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) { |
2998 | return FALSE; | 3023 | return FALSE; |
@@ -3002,10 +3027,7 @@ static int is_assignment(const char *expr) | |||
3002 | val = exprc + (val - expr); | 3027 | val = exprc + (val - expr); |
3003 | *val++ = '\0'; | 3028 | *val++ = '\0'; |
3004 | 3029 | ||
3005 | s = s1 = val; | 3030 | unescape_string_in_place(val); |
3006 | while ((*s1 = nextchar(&s)) != '\0') | ||
3007 | s1++; | ||
3008 | |||
3009 | setvar_u(newvar(exprc), val); | 3031 | setvar_u(newvar(exprc), val); |
3010 | free(exprc); | 3032 | free(exprc); |
3011 | return TRUE; | 3033 | return TRUE; |
@@ -3118,8 +3140,10 @@ int awk_main(int argc, char **argv) | |||
3118 | opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL); | 3140 | opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f, NULL); |
3119 | argv += optind; | 3141 | argv += optind; |
3120 | argc -= optind; | 3142 | argc -= optind; |
3121 | if (opt & 0x1) | 3143 | if (opt & 0x1) { /* -F */ |
3122 | setvar_s(intvar[FS], opt_F); // -F | 3144 | unescape_string_in_place(opt_F); |
3145 | setvar_s(intvar[FS], opt_F); | ||
3146 | } | ||
3123 | while (list_v) { /* -v */ | 3147 | while (list_v) { /* -v */ |
3124 | if (!is_assignment(llist_pop(&list_v))) | 3148 | if (!is_assignment(llist_pop(&list_v))) |
3125 | bb_show_usage(); | 3149 | bb_show_usage(); |
diff --git a/editors/sed.c b/editors/sed.c index a2df93165..070af611a 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -53,7 +53,9 @@ | |||
53 | * Todo: | 53 | * Todo: |
54 | * - Create a wrapper around regex to make libc's regex conform with sed | 54 | * - Create a wrapper around regex to make libc's regex conform with sed |
55 | * | 55 | * |
56 | * Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html | 56 | * Reference |
57 | * http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html | ||
58 | * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html | ||
57 | */ | 59 | */ |
58 | 60 | ||
59 | //usage:#define sed_trivial_usage | 61 | //usage:#define sed_trivial_usage |
@@ -63,7 +65,7 @@ | |||
63 | //usage: " -e CMD Add CMD to sed commands to be executed" | 65 | //usage: " -e CMD Add CMD to sed commands to be executed" |
64 | //usage: "\n -f FILE Add FILE contents to sed commands to be executed" | 66 | //usage: "\n -f FILE Add FILE contents to sed commands to be executed" |
65 | //usage: "\n -i[SFX] Edit files in-place (otherwise sends to stdout)" | 67 | //usage: "\n -i[SFX] Edit files in-place (otherwise sends to stdout)" |
66 | //usage: "\n Optionally backs files up, appending SFX" | 68 | //usage: "\n Optionally back files up, appending SFX" |
67 | //usage: "\n -n Suppress automatic printing of pattern space" | 69 | //usage: "\n -n Suppress automatic printing of pattern space" |
68 | //usage: "\n -r Use extended regex syntax" | 70 | //usage: "\n -r Use extended regex syntax" |
69 | //usage: "\n" | 71 | //usage: "\n" |
@@ -492,8 +494,10 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
492 | } | 494 | } |
493 | /* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ | 495 | /* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ |
494 | else if (idx <= IDX_c) { /* a,i,c */ | 496 | else if (idx <= IDX_c) { /* a,i,c */ |
495 | if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c') | 497 | if (idx < IDX_c) { /* a,i */ |
496 | bb_error_msg_and_die("only a beginning address can be specified for edit commands"); | 498 | if (sed_cmd->end_line || sed_cmd->end_match) |
499 | bb_error_msg_and_die("command '%c' uses only one address", sed_cmd->cmd); | ||
500 | } | ||
497 | for (;;) { | 501 | for (;;) { |
498 | if (*cmdstr == '\n' || *cmdstr == '\\') { | 502 | if (*cmdstr == '\n' || *cmdstr == '\\') { |
499 | cmdstr++; | 503 | cmdstr++; |
@@ -510,8 +514,10 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
510 | } | 514 | } |
511 | /* handle file cmds: (r)ead */ | 515 | /* handle file cmds: (r)ead */ |
512 | else if (idx <= IDX_w) { /* r,w */ | 516 | else if (idx <= IDX_w) { /* r,w */ |
513 | if (sed_cmd->end_line || sed_cmd->end_match) | 517 | if (idx < IDX_w) { /* r */ |
514 | bb_error_msg_and_die("command only uses one address"); | 518 | if (sed_cmd->end_line || sed_cmd->end_match) |
519 | bb_error_msg_and_die("command '%c' uses only one address", sed_cmd->cmd); | ||
520 | } | ||
515 | cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string); | 521 | cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string); |
516 | if (sed_cmd->cmd == 'w') { | 522 | if (sed_cmd->cmd == 'w') { |
517 | sed_cmd->sw_file = xfopen_for_write(sed_cmd->string); | 523 | sed_cmd->sw_file = xfopen_for_write(sed_cmd->string); |
@@ -673,7 +679,7 @@ static void do_subst_w_backrefs(char *line, char *replace) | |||
673 | 679 | ||
674 | /* go through the replacement string */ | 680 | /* go through the replacement string */ |
675 | for (i = 0; replace[i]; i++) { | 681 | for (i = 0; replace[i]; i++) { |
676 | /* if we find a backreference (\1, \2, etc.) print the backref'ed * text */ | 682 | /* if we find a backreference (\1, \2, etc.) print the backref'ed text */ |
677 | if (replace[i] == '\\') { | 683 | if (replace[i] == '\\') { |
678 | unsigned backref = replace[++i] - '0'; | 684 | unsigned backref = replace[++i] - '0'; |
679 | if (backref <= 9) { | 685 | if (backref <= 9) { |
@@ -707,8 +713,10 @@ static void do_subst_w_backrefs(char *line, char *replace) | |||
707 | static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p) | 713 | static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p) |
708 | { | 714 | { |
709 | char *line = *line_p; | 715 | char *line = *line_p; |
710 | int altered = 0; | ||
711 | unsigned match_count = 0; | 716 | unsigned match_count = 0; |
717 | bool altered = 0; | ||
718 | bool prev_match_empty = 1; | ||
719 | bool tried_at_eol = 0; | ||
712 | regex_t *current_regex; | 720 | regex_t *current_regex; |
713 | 721 | ||
714 | current_regex = sed_cmd->sub_match; | 722 | current_regex = sed_cmd->sub_match; |
@@ -735,50 +743,75 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p) | |||
735 | 743 | ||
736 | /* Now loop through, substituting for matches */ | 744 | /* Now loop through, substituting for matches */ |
737 | do { | 745 | do { |
746 | int start = G.regmatch[0].rm_so; | ||
747 | int end = G.regmatch[0].rm_eo; | ||
738 | int i; | 748 | int i; |
739 | 749 | ||
740 | /* Work around bug in glibc regexec, demonstrated by: | ||
741 | * echo " a.b" | busybox sed 's [^ .]* x g' | ||
742 | * The match_count check is so not to break | ||
743 | * echo "hi" | busybox sed 's/^/!/g' | ||
744 | */ | ||
745 | if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) { | ||
746 | pipe_putc(*line++); | ||
747 | goto next; | ||
748 | } | ||
749 | |||
750 | match_count++; | 750 | match_count++; |
751 | 751 | ||
752 | /* If we aren't interested in this match, output old line to | 752 | /* If we aren't interested in this match, output old line to |
753 | end of match and continue */ | 753 | * end of match and continue */ |
754 | if (sed_cmd->which_match | 754 | if (sed_cmd->which_match |
755 | && (sed_cmd->which_match != match_count) | 755 | && (sed_cmd->which_match != match_count) |
756 | ) { | 756 | ) { |
757 | for (i = 0; i < G.regmatch[0].rm_eo; i++) | 757 | for (i = 0; i < end; i++) |
758 | pipe_putc(*line++); | ||
759 | /* Null match? Print one more char */ | ||
760 | if (start == end && *line) | ||
758 | pipe_putc(*line++); | 761 | pipe_putc(*line++); |
759 | goto next; | 762 | goto next; |
760 | } | 763 | } |
761 | 764 | ||
762 | /* print everything before the match */ | 765 | /* Print everything before the match */ |
763 | for (i = 0; i < G.regmatch[0].rm_so; i++) | 766 | for (i = 0; i < start; i++) |
764 | pipe_putc(line[i]); | 767 | pipe_putc(line[i]); |
765 | 768 | ||
766 | /* then print the substitution string */ | 769 | /* Then print the substitution string, |
767 | do_subst_w_backrefs(line, sed_cmd->string); | 770 | * unless we just matched empty string after non-empty one. |
771 | * Example: string "cccd", pattern "c*", repl "R": | ||
772 | * result is "RdR", not "RRdR": first match "ccc", | ||
773 | * second is "" before "d", third is "" after "d". | ||
774 | * Second match is NOT replaced! | ||
775 | */ | ||
776 | if (prev_match_empty || start != 0 || start != end) { | ||
777 | //dbg("%d %d %d", prev_match_empty, start, end); | ||
778 | dbg("inserting replacement at %d in '%s'", start, line); | ||
779 | do_subst_w_backrefs(line, sed_cmd->string); | ||
780 | /* Flag that something has changed */ | ||
781 | altered = 1; | ||
782 | } else { | ||
783 | dbg("NOT inserting replacement at %d in '%s'", start, line); | ||
784 | } | ||
785 | |||
786 | /* If matched string is empty (f.e. "c*" pattern), | ||
787 | * copy verbatim one char after it before attempting more matches | ||
788 | */ | ||
789 | prev_match_empty = (start == end); | ||
790 | if (prev_match_empty) { | ||
791 | if (!line[end]) { | ||
792 | tried_at_eol = 1; | ||
793 | } else { | ||
794 | pipe_putc(line[end]); | ||
795 | end++; | ||
796 | } | ||
797 | } | ||
768 | 798 | ||
769 | /* advance past the match */ | 799 | /* Advance past the match */ |
770 | line += G.regmatch[0].rm_eo; | 800 | dbg("line += %d", end); |
771 | /* flag that something has changed */ | 801 | line += end; |
772 | altered++; | ||
773 | 802 | ||
774 | /* if we're not doing this globally, get out now */ | 803 | /* if we're not doing this globally, get out now */ |
775 | if (sed_cmd->which_match != 0) | 804 | if (sed_cmd->which_match != 0) |
776 | break; | 805 | break; |
777 | next: | 806 | next: |
778 | if (*line == '\0') | 807 | /* Exit if we are at EOL and already tried matching at it */ |
779 | break; | 808 | if (*line == '\0') { |
809 | if (tried_at_eol) | ||
810 | break; | ||
811 | tried_at_eol = 1; | ||
812 | } | ||
780 | 813 | ||
781 | //maybe (G.regmatch[0].rm_eo ? REG_NOTBOL : 0) instead of unconditional REG_NOTBOL? | 814 | //maybe (end ? REG_NOTBOL : 0) instead of unconditional REG_NOTBOL? |
782 | } while (regexec(current_regex, line, 10, G.regmatch, REG_NOTBOL) != REG_NOMATCH); | 815 | } while (regexec(current_regex, line, 10, G.regmatch, REG_NOTBOL) != REG_NOMATCH); |
783 | 816 | ||
784 | /* Copy rest of string into output pipeline */ | 817 | /* Copy rest of string into output pipeline */ |
@@ -1127,7 +1160,7 @@ static void process_files(void) | |||
1127 | case 's': | 1160 | case 's': |
1128 | if (!do_subst_command(sed_cmd, &pattern_space)) | 1161 | if (!do_subst_command(sed_cmd, &pattern_space)) |
1129 | break; | 1162 | break; |
1130 | dbg("do_subst_command succeeeded:'%s'", pattern_space); | 1163 | dbg("do_subst_command succeeded:'%s'", pattern_space); |
1131 | substituted |= 1; | 1164 | substituted |= 1; |
1132 | 1165 | ||
1133 | /* handle p option */ | 1166 | /* handle p option */ |
diff --git a/editors/vi.c b/editors/vi.c index 6fae221ac..821583ec1 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -136,14 +136,6 @@ | |||
136 | //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. | 136 | //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. |
137 | //config: | 137 | //config: |
138 | //config: This is not clean but helps a lot on serial lines and such. | 138 | //config: This is not clean but helps a lot on serial lines and such. |
139 | //config: | ||
140 | //config:config FEATURE_VI_OPTIMIZE_CURSOR | ||
141 | //config: bool "Optimize cursor movement" | ||
142 | //config: default y | ||
143 | //config: depends on VI | ||
144 | //config: help | ||
145 | //config: This will make the cursor movement faster, but requires more memory | ||
146 | //config: and it makes the applet a tiny bit larger. | ||
147 | 139 | ||
148 | //applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP)) | 140 | //applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP)) |
149 | 141 | ||
@@ -154,12 +146,12 @@ | |||
154 | //usage:#define vi_full_usage "\n\n" | 146 | //usage:#define vi_full_usage "\n\n" |
155 | //usage: "Edit FILE\n" | 147 | //usage: "Edit FILE\n" |
156 | //usage: IF_FEATURE_VI_COLON( | 148 | //usage: IF_FEATURE_VI_COLON( |
157 | //usage: "\n -c Initial command to run ($EXINIT also available)" | 149 | //usage: "\n -c CMD Initial command to run ($EXINIT also available)" |
158 | //usage: ) | 150 | //usage: ) |
159 | //usage: IF_FEATURE_VI_READONLY( | 151 | //usage: IF_FEATURE_VI_READONLY( |
160 | //usage: "\n -R Read-only" | 152 | //usage: "\n -R Read-only" |
161 | //usage: ) | 153 | //usage: ) |
162 | //usage: "\n -H Short help regarding available features" | 154 | //usage: "\n -H List available features" |
163 | 155 | ||
164 | #include "libbb.h" | 156 | #include "libbb.h" |
165 | /* Should be after libbb.h: on some systems regex.h needs sys/types.h: */ | 157 | /* Should be after libbb.h: on some systems regex.h needs sys/types.h: */ |
@@ -202,20 +194,29 @@ enum { | |||
202 | MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN, | 194 | MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN, |
203 | }; | 195 | }; |
204 | 196 | ||
205 | /* vt102 typical ESC sequence */ | 197 | /* VT102 ESC sequences. |
206 | /* terminal standout start/normal ESC sequence */ | 198 | * See "Xterm Control Sequences" |
207 | #define SOs "\033[7m" | 199 | * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html |
208 | #define SOn "\033[0m" | 200 | */ |
209 | /* terminal bell sequence */ | 201 | /* Inverse/Normal text */ |
210 | #define bell "\007" | 202 | #define ESC_BOLD_TEXT "\033[7m" |
211 | /* Clear-end-of-line and Clear-end-of-screen ESC sequence */ | 203 | #define ESC_NORM_TEXT "\033[0m" |
212 | #define Ceol "\033[K" | 204 | /* Bell */ |
213 | #define Ceos "\033[J" | 205 | #define ESC_BELL "\007" |
214 | /* Cursor motion arbitrary destination ESC sequence */ | 206 | /* Clear-to-end-of-line */ |
215 | #define CMrc "\033[%u;%uH" | 207 | #define ESC_CLEAR2EOL "\033[K" |
216 | /* Cursor motion up and down ESC sequence */ | 208 | /* Clear-to-end-of-screen. |
217 | #define CMup "\033[A" | 209 | * (We use default param here. |
218 | #define CMdown "\n" | 210 | * Full sequence is "ESC [ <num> J", |
211 | * <num> is 0/1/2 = "erase below/above/all".) | ||
212 | */ | ||
213 | #define ESC_CLEAR2EOS "\033[J" | ||
214 | /* Cursor to given coordinate (1,1: top left) */ | ||
215 | #define ESC_SET_CURSOR_POS "\033[%u;%uH" | ||
216 | //UNUSED | ||
217 | ///* Cursor up and down */ | ||
218 | //#define ESC_CURSOR_UP "\033[A" | ||
219 | //#define ESC_CURSOR_DOWN "\n" | ||
219 | 220 | ||
220 | #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK | 221 | #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK |
221 | // cmds modifying text[] | 222 | // cmds modifying text[] |
@@ -303,9 +304,6 @@ struct globals { | |||
303 | int lmc_len; // length of last_modifying_cmd | 304 | int lmc_len; // length of last_modifying_cmd |
304 | char *ioq, *ioq_start; // pointer to string for get_one_char to "read" | 305 | char *ioq, *ioq_start; // pointer to string for get_one_char to "read" |
305 | #endif | 306 | #endif |
306 | #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | ||
307 | int last_row; // where the cursor was last moved to | ||
308 | #endif | ||
309 | #if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME | 307 | #if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME |
310 | int my_pid; | 308 | int my_pid; |
311 | #endif | 309 | #endif |
@@ -389,7 +387,6 @@ struct globals { | |||
389 | #define lmc_len (G.lmc_len ) | 387 | #define lmc_len (G.lmc_len ) |
390 | #define ioq (G.ioq ) | 388 | #define ioq (G.ioq ) |
391 | #define ioq_start (G.ioq_start ) | 389 | #define ioq_start (G.ioq_start ) |
392 | #define last_row (G.last_row ) | ||
393 | #define my_pid (G.my_pid ) | 390 | #define my_pid (G.my_pid ) |
394 | #define last_search_pattern (G.last_search_pattern) | 391 | #define last_search_pattern (G.last_search_pattern) |
395 | 392 | ||
@@ -470,10 +467,7 @@ static int file_size(const char *); // what is the byte size of "fn" | |||
470 | // file_insert might reallocate text[]! | 467 | // file_insert might reallocate text[]! |
471 | static int file_insert(const char *, char *, int); | 468 | static int file_insert(const char *, char *, int); |
472 | static int file_write(char *, char *, char *); | 469 | static int file_write(char *, char *, char *); |
473 | #if !ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | 470 | static void place_cursor(int, int); |
474 | #define place_cursor(a, b, optimize) place_cursor(a, b) | ||
475 | #endif | ||
476 | static void place_cursor(int, int, int); | ||
477 | static void screen_erase(void); | 471 | static void screen_erase(void); |
478 | static void clear_to_eol(void); | 472 | static void clear_to_eol(void); |
479 | static void clear_to_eos(void); | 473 | static void clear_to_eos(void); |
@@ -558,7 +552,8 @@ int vi_main(int argc, char **argv) | |||
558 | } | 552 | } |
559 | #endif | 553 | #endif |
560 | 554 | ||
561 | vi_setops = VI_AUTOINDENT | VI_SHOWMATCH | VI_IGNORECASE; | 555 | // autoindent is not default in vim 7.3 |
556 | vi_setops = /*VI_AUTOINDENT |*/ VI_SHOWMATCH | VI_IGNORECASE; | ||
562 | // 1- process $HOME/.exrc file (not inplemented yet) | 557 | // 1- process $HOME/.exrc file (not inplemented yet) |
563 | // 2- process EXINIT variable from environment | 558 | // 2- process EXINIT variable from environment |
564 | // 3- process command line args | 559 | // 3- process command line args |
@@ -584,7 +579,7 @@ int vi_main(int argc, char **argv) | |||
584 | #if ENABLE_FEATURE_VI_COLON | 579 | #if ENABLE_FEATURE_VI_COLON |
585 | case 'c': // cmd line vi command | 580 | case 'c': // cmd line vi command |
586 | if (*optarg) | 581 | if (*optarg) |
587 | initial_cmds[initial_cmds[0] != 0] = xstrndup(optarg, MAX_INPUT_LEN); | 582 | initial_cmds[initial_cmds[0] != NULL] = xstrndup(optarg, MAX_INPUT_LEN); |
588 | break; | 583 | break; |
589 | #endif | 584 | #endif |
590 | case 'H': | 585 | case 'H': |
@@ -599,15 +594,19 @@ int vi_main(int argc, char **argv) | |||
599 | // The argv array can be used by the ":next" and ":rewind" commands | 594 | // The argv array can be used by the ":next" and ":rewind" commands |
600 | argv += optind; | 595 | argv += optind; |
601 | argc -= optind; | 596 | argc -= optind; |
602 | save_argc = argc; | ||
603 | optind = 0; | ||
604 | 597 | ||
605 | //----- This is the main file handling loop -------------- | 598 | //----- This is the main file handling loop -------------- |
599 | save_argc = argc; | ||
600 | optind = 0; | ||
601 | // "Save cursor, use alternate screen buffer, clear screen" | ||
602 | write1("\033[?1049h"); | ||
606 | while (1) { | 603 | while (1) { |
607 | edit_file(argv[optind]); /* param might be NULL */ | 604 | edit_file(argv[optind]); /* param might be NULL */ |
608 | if (++optind >= argc) | 605 | if (++optind >= argc) |
609 | break; | 606 | break; |
610 | } | 607 | } |
608 | // "Use normal screen buffer, restore cursor" | ||
609 | write1("\033[?1049l"); | ||
611 | //----------------------------------------------------------- | 610 | //----------------------------------------------------------- |
612 | 611 | ||
613 | return 0; | 612 | return 0; |
@@ -1191,7 +1190,7 @@ static void colon(char *buf) | |||
1191 | char *argp; | 1190 | char *argp; |
1192 | #endif | 1191 | #endif |
1193 | i = 0; // offset into args | 1192 | i = 0; // offset into args |
1194 | // only blank is regarded as args delmiter. What about tab '\t' ? | 1193 | // only blank is regarded as args delimiter. What about tab '\t'? |
1195 | if (!args[0] || strcasecmp(args, "all") == 0) { | 1194 | if (!args[0] || strcasecmp(args, "all") == 0) { |
1196 | // print out values of all options | 1195 | // print out values of all options |
1197 | #if ENABLE_FEATURE_VI_SETOPTS | 1196 | #if ENABLE_FEATURE_VI_SETOPTS |
@@ -2176,7 +2175,7 @@ static void show_help(void) | |||
2176 | "\n\tPattern searches with / and ?" | 2175 | "\n\tPattern searches with / and ?" |
2177 | #endif | 2176 | #endif |
2178 | #if ENABLE_FEATURE_VI_DOT_CMD | 2177 | #if ENABLE_FEATURE_VI_DOT_CMD |
2179 | "\n\tLast command repeat with \'.\'" | 2178 | "\n\tLast command repeat with ." |
2180 | #endif | 2179 | #endif |
2181 | #if ENABLE_FEATURE_VI_YANKMARK | 2180 | #if ENABLE_FEATURE_VI_YANKMARK |
2182 | "\n\tLine marking with 'x" | 2181 | "\n\tLine marking with 'x" |
@@ -2187,7 +2186,7 @@ static void show_help(void) | |||
2187 | //redundant: usage text says this too: "\n\tReadonly with -R command line arg" | 2186 | //redundant: usage text says this too: "\n\tReadonly with -R command line arg" |
2188 | #endif | 2187 | #endif |
2189 | #if ENABLE_FEATURE_VI_SET | 2188 | #if ENABLE_FEATURE_VI_SET |
2190 | "\n\tSome colon mode commands with \':\'" | 2189 | "\n\tSome colon mode commands with :" |
2191 | #endif | 2190 | #endif |
2192 | #if ENABLE_FEATURE_VI_SETOPTS | 2191 | #if ENABLE_FEATURE_VI_SETOPTS |
2193 | "\n\tSettable options with \":set\"" | 2192 | "\n\tSettable options with \":set\"" |
@@ -2601,107 +2600,56 @@ static int file_write(char *fn, char *first, char *last) | |||
2601 | // 23,0 ... 23,79 <- status line | 2600 | // 23,0 ... 23,79 <- status line |
2602 | 2601 | ||
2603 | //----- Move the cursor to row x col (count from 0, not 1) ------- | 2602 | //----- Move the cursor to row x col (count from 0, not 1) ------- |
2604 | static void place_cursor(int row, int col, int optimize) | 2603 | static void place_cursor(int row, int col) |
2605 | { | 2604 | { |
2606 | char cm1[sizeof(CMrc) + sizeof(int)*3 * 2]; | 2605 | char cm1[sizeof(ESC_SET_CURSOR_POS) + sizeof(int)*3 * 2]; |
2607 | #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | ||
2608 | enum { | ||
2609 | SZ_UP = sizeof(CMup), | ||
2610 | SZ_DN = sizeof(CMdown), | ||
2611 | SEQ_SIZE = SZ_UP > SZ_DN ? SZ_UP : SZ_DN, | ||
2612 | }; | ||
2613 | char cm2[SEQ_SIZE * 5 + 32]; // bigger than worst case size | ||
2614 | #endif | ||
2615 | char *cm; | ||
2616 | 2606 | ||
2617 | if (row < 0) row = 0; | 2607 | if (row < 0) row = 0; |
2618 | if (row >= rows) row = rows - 1; | 2608 | if (row >= rows) row = rows - 1; |
2619 | if (col < 0) col = 0; | 2609 | if (col < 0) col = 0; |
2620 | if (col >= columns) col = columns - 1; | 2610 | if (col >= columns) col = columns - 1; |
2621 | 2611 | ||
2622 | //----- 1. Try the standard terminal ESC sequence | 2612 | sprintf(cm1, ESC_SET_CURSOR_POS, row + 1, col + 1); |
2623 | sprintf(cm1, CMrc, row + 1, col + 1); | 2613 | write1(cm1); |
2624 | cm = cm1; | ||
2625 | |||
2626 | #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | ||
2627 | if (optimize && col < 16) { | ||
2628 | char *screenp; | ||
2629 | int Rrow = last_row; | ||
2630 | int diff = Rrow - row; | ||
2631 | |||
2632 | if (diff < -5 || diff > 5) | ||
2633 | goto skip; | ||
2634 | |||
2635 | //----- find the minimum # of chars to move cursor ------------- | ||
2636 | //----- 2. Try moving with discreet chars (Newline, [back]space, ...) | ||
2637 | cm2[0] = '\0'; | ||
2638 | |||
2639 | // move to the correct row | ||
2640 | while (row < Rrow) { | ||
2641 | // the cursor has to move up | ||
2642 | strcat(cm2, CMup); | ||
2643 | Rrow--; | ||
2644 | } | ||
2645 | while (row > Rrow) { | ||
2646 | // the cursor has to move down | ||
2647 | strcat(cm2, CMdown); | ||
2648 | Rrow++; | ||
2649 | } | ||
2650 | |||
2651 | // now move to the correct column | ||
2652 | strcat(cm2, "\r"); // start at col 0 | ||
2653 | // just send out orignal source char to get to correct place | ||
2654 | screenp = &screen[row * columns]; // start of screen line | ||
2655 | strncat(cm2, screenp, col); | ||
2656 | |||
2657 | // pick the shortest cursor motion to send out | ||
2658 | if (strlen(cm2) < strlen(cm)) { | ||
2659 | cm = cm2; | ||
2660 | } | ||
2661 | skip: ; | ||
2662 | } | ||
2663 | last_row = row; | ||
2664 | #endif /* FEATURE_VI_OPTIMIZE_CURSOR */ | ||
2665 | write1(cm); | ||
2666 | } | 2614 | } |
2667 | 2615 | ||
2668 | //----- Erase from cursor to end of line ----------------------- | 2616 | //----- Erase from cursor to end of line ----------------------- |
2669 | static void clear_to_eol(void) | 2617 | static void clear_to_eol(void) |
2670 | { | 2618 | { |
2671 | write1(Ceol); // Erase from cursor to end of line | 2619 | write1(ESC_CLEAR2EOL); |
2672 | } | 2620 | } |
2673 | 2621 | ||
2674 | static void go_bottom_and_clear_to_eol(void) | 2622 | static void go_bottom_and_clear_to_eol(void) |
2675 | { | 2623 | { |
2676 | place_cursor(rows - 1, 0, FALSE); // go to bottom of screen | 2624 | place_cursor(rows - 1, 0); |
2677 | clear_to_eol(); // erase to end of line | 2625 | clear_to_eol(); |
2678 | } | 2626 | } |
2679 | 2627 | ||
2680 | //----- Erase from cursor to end of screen ----------------------- | 2628 | //----- Erase from cursor to end of screen ----------------------- |
2681 | static void clear_to_eos(void) | 2629 | static void clear_to_eos(void) |
2682 | { | 2630 | { |
2683 | write1(Ceos); // Erase from cursor to end of screen | 2631 | write1(ESC_CLEAR2EOS); |
2684 | } | 2632 | } |
2685 | 2633 | ||
2686 | //----- Start standout mode ------------------------------------ | 2634 | //----- Start standout mode ------------------------------------ |
2687 | static void standout_start(void) // send "start reverse video" sequence | 2635 | static void standout_start(void) |
2688 | { | 2636 | { |
2689 | write1(SOs); // Start reverse video mode | 2637 | write1(ESC_BOLD_TEXT); |
2690 | } | 2638 | } |
2691 | 2639 | ||
2692 | //----- End standout mode -------------------------------------- | 2640 | //----- End standout mode -------------------------------------- |
2693 | static void standout_end(void) // send "end reverse video" sequence | 2641 | static void standout_end(void) |
2694 | { | 2642 | { |
2695 | write1(SOn); // End reverse video mode | 2643 | write1(ESC_NORM_TEXT); |
2696 | } | 2644 | } |
2697 | 2645 | ||
2698 | //----- Flash the screen -------------------------------------- | 2646 | //----- Flash the screen -------------------------------------- |
2699 | static void flash(int h) | 2647 | static void flash(int h) |
2700 | { | 2648 | { |
2701 | standout_start(); // send "start reverse video" sequence | 2649 | standout_start(); |
2702 | redraw(TRUE); | 2650 | redraw(TRUE); |
2703 | mysleep(h); | 2651 | mysleep(h); |
2704 | standout_end(); // send "end reverse video" sequence | 2652 | standout_end(); |
2705 | redraw(TRUE); | 2653 | redraw(TRUE); |
2706 | } | 2654 | } |
2707 | 2655 | ||
@@ -2712,7 +2660,7 @@ static void Indicate_Error(void) | |||
2712 | return; // generate a random command | 2660 | return; // generate a random command |
2713 | #endif | 2661 | #endif |
2714 | if (!err_method) { | 2662 | if (!err_method) { |
2715 | write1(bell); // send out a bell character | 2663 | write1(ESC_BELL); |
2716 | } else { | 2664 | } else { |
2717 | flash(10); | 2665 | flash(10); |
2718 | } | 2666 | } |
@@ -2758,7 +2706,7 @@ static void show_status_line(void) | |||
2758 | } | 2706 | } |
2759 | have_status_msg = 0; | 2707 | have_status_msg = 0; |
2760 | } | 2708 | } |
2761 | place_cursor(crow, ccol, FALSE); // put cursor back in correct place | 2709 | place_cursor(crow, ccol); // put cursor back in correct place |
2762 | } | 2710 | } |
2763 | fflush_all(); | 2711 | fflush_all(); |
2764 | } | 2712 | } |
@@ -2770,12 +2718,12 @@ static void status_line_bold(const char *format, ...) | |||
2770 | va_list args; | 2718 | va_list args; |
2771 | 2719 | ||
2772 | va_start(args, format); | 2720 | va_start(args, format); |
2773 | strcpy(status_buffer, SOs); // Terminal standout mode on | 2721 | strcpy(status_buffer, ESC_BOLD_TEXT); |
2774 | vsprintf(status_buffer + sizeof(SOs)-1, format, args); | 2722 | vsprintf(status_buffer + sizeof(ESC_BOLD_TEXT)-1, format, args); |
2775 | strcat(status_buffer, SOn); // Terminal standout mode off | 2723 | strcat(status_buffer, ESC_NORM_TEXT); |
2776 | va_end(args); | 2724 | va_end(args); |
2777 | 2725 | ||
2778 | have_status_msg = 1 + sizeof(SOs) + sizeof(SOn) - 2; | 2726 | have_status_msg = 1 + sizeof(ESC_BOLD_TEXT) + sizeof(ESC_NORM_TEXT) - 2; |
2779 | } | 2727 | } |
2780 | 2728 | ||
2781 | // format status buffer | 2729 | // format status buffer |
@@ -2807,8 +2755,8 @@ static void print_literal(char *buf, const char *s) | |||
2807 | c = *s; | 2755 | c = *s; |
2808 | c_is_no_print = (c & 0x80) && !Isprint(c); | 2756 | c_is_no_print = (c & 0x80) && !Isprint(c); |
2809 | if (c_is_no_print) { | 2757 | if (c_is_no_print) { |
2810 | strcpy(d, SOn); | 2758 | strcpy(d, ESC_NORM_TEXT); |
2811 | d += sizeof(SOn)-1; | 2759 | d += sizeof(ESC_NORM_TEXT)-1; |
2812 | c = '.'; | 2760 | c = '.'; |
2813 | } | 2761 | } |
2814 | if (c < ' ' || c == 0x7f) { | 2762 | if (c < ' ' || c == 0x7f) { |
@@ -2820,8 +2768,8 @@ static void print_literal(char *buf, const char *s) | |||
2820 | *d++ = c; | 2768 | *d++ = c; |
2821 | *d = '\0'; | 2769 | *d = '\0'; |
2822 | if (c_is_no_print) { | 2770 | if (c_is_no_print) { |
2823 | strcpy(d, SOs); | 2771 | strcpy(d, ESC_BOLD_TEXT); |
2824 | d += sizeof(SOs)-1; | 2772 | d += sizeof(ESC_BOLD_TEXT)-1; |
2825 | } | 2773 | } |
2826 | if (*s == '\n') { | 2774 | if (*s == '\n') { |
2827 | *d++ = '$'; | 2775 | *d++ = '$'; |
@@ -2903,8 +2851,8 @@ static int format_edit_status(void) | |||
2903 | //----- Force refresh of all Lines ----------------------------- | 2851 | //----- Force refresh of all Lines ----------------------------- |
2904 | static void redraw(int full_screen) | 2852 | static void redraw(int full_screen) |
2905 | { | 2853 | { |
2906 | place_cursor(0, 0, FALSE); // put cursor in correct place | 2854 | place_cursor(0, 0); |
2907 | clear_to_eos(); // tell terminal to erase display | 2855 | clear_to_eos(); |
2908 | screen_erase(); // erase the internal screen buffer | 2856 | screen_erase(); // erase the internal screen buffer |
2909 | last_status_cksum = 0; // force status update | 2857 | last_status_cksum = 0; // force status update |
2910 | refresh(full_screen); // this will redraw the entire display | 2858 | refresh(full_screen); // this will redraw the entire display |
@@ -3044,22 +2992,13 @@ static void refresh(int full_screen) | |||
3044 | if (changed) { | 2992 | if (changed) { |
3045 | // copy changed part of buffer to virtual screen | 2993 | // copy changed part of buffer to virtual screen |
3046 | memcpy(sp+cs, out_buf+cs, ce-cs+1); | 2994 | memcpy(sp+cs, out_buf+cs, ce-cs+1); |
3047 | 2995 | place_cursor(li, cs); | |
3048 | // move cursor to column of first change | ||
3049 | //if (offset != old_offset) { | ||
3050 | // // place_cursor is still too stupid | ||
3051 | // // to handle offsets correctly | ||
3052 | // place_cursor(li, cs, FALSE); | ||
3053 | //} else { | ||
3054 | place_cursor(li, cs, TRUE); | ||
3055 | //} | ||
3056 | |||
3057 | // write line out to terminal | 2996 | // write line out to terminal |
3058 | fwrite(&sp[cs], ce - cs + 1, 1, stdout); | 2997 | fwrite(&sp[cs], ce - cs + 1, 1, stdout); |
3059 | } | 2998 | } |
3060 | } | 2999 | } |
3061 | 3000 | ||
3062 | place_cursor(crow, ccol, TRUE); | 3001 | place_cursor(crow, ccol); |
3063 | 3002 | ||
3064 | old_offset = offset; | 3003 | old_offset = offset; |
3065 | #undef old_offset | 3004 | #undef old_offset |
@@ -3229,9 +3168,9 @@ static void do_cmd(int c) | |||
3229 | break; | 3168 | break; |
3230 | case 12: // ctrl-L force redraw whole screen | 3169 | case 12: // ctrl-L force redraw whole screen |
3231 | case 18: // ctrl-R force redraw | 3170 | case 18: // ctrl-R force redraw |
3232 | place_cursor(0, 0, FALSE); // put cursor in correct place | 3171 | place_cursor(0, 0); |
3233 | clear_to_eos(); // tel terminal to erase display | 3172 | clear_to_eos(); |
3234 | mysleep(10); | 3173 | //mysleep(10); // why??? |
3235 | screen_erase(); // erase the internal screen buffer | 3174 | screen_erase(); // erase the internal screen buffer |
3236 | last_status_cksum = 0; // force status update | 3175 | last_status_cksum = 0; // force status update |
3237 | refresh(TRUE); // this will redraw the entire display | 3176 | refresh(TRUE); // this will redraw the entire display |
@@ -4150,7 +4089,7 @@ static void crash_test() | |||
4150 | 4089 | ||
4151 | if (msg[0]) { | 4090 | if (msg[0]) { |
4152 | printf("\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", | 4091 | printf("\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", |
4153 | totalcmds, last_input_char, msg, SOs, SOn); | 4092 | totalcmds, last_input_char, msg, ESC_BOLD_TEXT, ESC_NORM_TEXT); |
4154 | fflush_all(); | 4093 | fflush_all(); |
4155 | while (safe_read(STDIN_FILENO, d, 1) > 0) { | 4094 | while (safe_read(STDIN_FILENO, d, 1) > 0) { |
4156 | if (d[0] == '\n' || d[0] == '\r') | 4095 | if (d[0] == '\n' || d[0] == '\r') |
diff --git a/examples/mdev.conf b/examples/mdev.conf index cdbb4fcfe..51795694d 100644 --- a/examples/mdev.conf +++ b/examples/mdev.conf | |||
@@ -7,8 +7,14 @@ | |||
7 | # instead of the default 0:0 660. | 7 | # instead of the default 0:0 660. |
8 | # | 8 | # |
9 | # Syntax: | 9 | # Syntax: |
10 | # %s %d:%d %s | 10 | # [-]devicename_regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...] |
11 | # devicename_regex user:group mode | 11 | # [-]$ENVVAR=regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...] |
12 | # [-]@maj,min[-min2] user:group mode [=path]|[>path]|[!] [@|$|*cmd args...] | ||
13 | # | ||
14 | # [-]: do not stop on this match, continue reading mdev.conf | ||
15 | # =: move, >: move and create a symlink | ||
16 | # !: do not create device node | ||
17 | # @|$|*: run@cmd if $ACTION=add, $cmd if $ACTION=remove, *cmd in all cases | ||
12 | 18 | ||
13 | null 0:0 666 | 19 | null 0:0 666 |
14 | zero 0:0 666 | 20 | zero 0:0 666 |
diff --git a/examples/mdev_fat.conf b/examples/mdev_fat.conf index df329b4b5..ceba3a797 100644 --- a/examples/mdev_fat.conf +++ b/examples/mdev_fat.conf | |||
@@ -7,10 +7,14 @@ | |||
7 | # instead of the default 0:0 660. | 7 | # instead of the default 0:0 660. |
8 | # | 8 | # |
9 | # Syntax: | 9 | # Syntax: |
10 | # [-]devicename_regex user:group mode [>|=path] [@|$|*cmd args...] | 10 | # [-]devicename_regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...] |
11 | # [-]$ENVVAR=regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...] | ||
12 | # [-]@maj,min[-min2] user:group mode [=path]|[>path]|[!] [@|$|*cmd args...] | ||
11 | # | 13 | # |
14 | # [-]: do not stop on this match, continue reading mdev.conf | ||
12 | # =: move, >: move and create a symlink | 15 | # =: move, >: move and create a symlink |
13 | # @|$|*: run $cmd on delete, @cmd on create, *cmd on both | 16 | # !: do not create device node |
17 | # @|$|*: run cmd if $ACTION=remove, @cmd if $ACTION=add, *cmd in all cases | ||
14 | 18 | ||
15 | # support module loading on hotplug | 19 | # support module loading on hotplug |
16 | $MODALIAS=.* root:root 660 @modprobe "$MODALIAS" | 20 | $MODALIAS=.* root:root 660 @modprobe "$MODALIAS" |
@@ -49,7 +53,6 @@ sr[0-9]* root:cdrom 660 @ln -sf $MDEV cdrom | |||
49 | fd[0-9]* root:floppy 660 | 53 | fd[0-9]* root:floppy 660 |
50 | 54 | ||
51 | # net devices | 55 | # net devices |
52 | -net/.* root:root 600 @nameif | ||
53 | tun[0-9]* root:root 600 =net/ | 56 | tun[0-9]* root:root 600 =net/ |
54 | tap[0-9]* root:root 600 =net/ | 57 | tap[0-9]* root:root 600 =net/ |
55 | 58 | ||
diff --git a/findutils/find.c b/findutils/find.c index fc0fc5c9f..b521e5b08 100644 --- a/findutils/find.c +++ b/findutils/find.c | |||
@@ -728,10 +728,27 @@ static int FAST_FUNC fileAction(const char *fileName, | |||
728 | int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM)) | 728 | int depth IF_NOT_FEATURE_FIND_MAXDEPTH(UNUSED_PARAM)) |
729 | { | 729 | { |
730 | int r; | 730 | int r; |
731 | int same_fs = 1; | ||
732 | |||
733 | #if ENABLE_FEATURE_FIND_XDEV | ||
734 | if (S_ISDIR(statbuf->st_mode) && G.xdev_count) { | ||
735 | int i; | ||
736 | for (i = 0; i < G.xdev_count; i++) { | ||
737 | if (G.xdev_dev[i] == statbuf->st_dev) | ||
738 | goto found; | ||
739 | } | ||
740 | //bb_error_msg("'%s': not same fs", fileName); | ||
741 | same_fs = 0; | ||
742 | found: ; | ||
743 | } | ||
744 | #endif | ||
731 | 745 | ||
732 | #if ENABLE_FEATURE_FIND_MAXDEPTH | 746 | #if ENABLE_FEATURE_FIND_MAXDEPTH |
733 | if (depth < G.minmaxdepth[0]) | 747 | if (depth < G.minmaxdepth[0]) { |
734 | return TRUE; /* skip this, continue recursing */ | 748 | if (same_fs) |
749 | return TRUE; /* skip this, continue recursing */ | ||
750 | return SKIP; /* stop recursing */ | ||
751 | } | ||
735 | if (depth > G.minmaxdepth[1]) | 752 | if (depth > G.minmaxdepth[1]) |
736 | return SKIP; /* stop recursing */ | 753 | return SKIP; /* stop recursing */ |
737 | #endif | 754 | #endif |
@@ -747,21 +764,11 @@ static int FAST_FUNC fileAction(const char *fileName, | |||
747 | return SKIP; | 764 | return SKIP; |
748 | } | 765 | } |
749 | #endif | 766 | #endif |
750 | #if ENABLE_FEATURE_FIND_XDEV | ||
751 | /* -xdev stops on mountpoints, but AFTER mountpoit itself | 767 | /* -xdev stops on mountpoints, but AFTER mountpoit itself |
752 | * is processed as usual */ | 768 | * is processed as usual */ |
753 | if (S_ISDIR(statbuf->st_mode)) { | 769 | if (!same_fs) { |
754 | if (G.xdev_count) { | 770 | return SKIP; |
755 | int i; | ||
756 | for (i = 0; i < G.xdev_count; i++) { | ||
757 | if (G.xdev_dev[i] == statbuf->st_dev) | ||
758 | goto found; | ||
759 | } | ||
760 | return SKIP; | ||
761 | found: ; | ||
762 | } | ||
763 | } | 771 | } |
764 | #endif | ||
765 | 772 | ||
766 | /* Cannot return 0: our caller, recursive_action(), | 773 | /* Cannot return 0: our caller, recursive_action(), |
767 | * will perror() and skip dirs (if called on dir) */ | 774 | * will perror() and skip dirs (if called on dir) */ |
@@ -831,6 +838,11 @@ static action*** parse_params(char **argv) | |||
831 | PARM_name , | 838 | PARM_name , |
832 | PARM_iname , | 839 | PARM_iname , |
833 | IF_FEATURE_FIND_PATH( PARM_path ,) | 840 | IF_FEATURE_FIND_PATH( PARM_path ,) |
841 | #if ENABLE_DESKTOP | ||
842 | /* -wholename is a synonym for -path */ | ||
843 | /* We support it because Linux kernel's "make tags" uses it */ | ||
844 | IF_FEATURE_FIND_PATH( PARM_wholename ,) | ||
845 | #endif | ||
834 | IF_FEATURE_FIND_PATH( PARM_ipath ,) | 846 | IF_FEATURE_FIND_PATH( PARM_ipath ,) |
835 | IF_FEATURE_FIND_REGEX( PARM_regex ,) | 847 | IF_FEATURE_FIND_REGEX( PARM_regex ,) |
836 | IF_FEATURE_FIND_TYPE( PARM_type ,) | 848 | IF_FEATURE_FIND_TYPE( PARM_type ,) |
@@ -869,6 +881,9 @@ static action*** parse_params(char **argv) | |||
869 | "-name\0" | 881 | "-name\0" |
870 | "-iname\0" | 882 | "-iname\0" |
871 | IF_FEATURE_FIND_PATH( "-path\0" ) | 883 | IF_FEATURE_FIND_PATH( "-path\0" ) |
884 | #if ENABLE_DESKTOP | ||
885 | IF_FEATURE_FIND_PATH( "-wholename\0") | ||
886 | #endif | ||
872 | IF_FEATURE_FIND_PATH( "-ipath\0" ) | 887 | IF_FEATURE_FIND_PATH( "-ipath\0" ) |
873 | IF_FEATURE_FIND_REGEX( "-regex\0" ) | 888 | IF_FEATURE_FIND_REGEX( "-regex\0" ) |
874 | IF_FEATURE_FIND_TYPE( "-type\0" ) | 889 | IF_FEATURE_FIND_TYPE( "-type\0" ) |
@@ -1076,7 +1091,7 @@ static action*** parse_params(char **argv) | |||
1076 | ap->iname = (parm == PARM_iname); | 1091 | ap->iname = (parm == PARM_iname); |
1077 | } | 1092 | } |
1078 | #if ENABLE_FEATURE_FIND_PATH | 1093 | #if ENABLE_FEATURE_FIND_PATH |
1079 | else if (parm == PARM_path || parm == PARM_ipath) { | 1094 | else if (parm == PARM_path IF_DESKTOP(|| parm == PARM_wholename) || parm == PARM_ipath) { |
1080 | action_path *ap; | 1095 | action_path *ap; |
1081 | dbg("%d", __LINE__); | 1096 | dbg("%d", __LINE__); |
1082 | ap = ALLOC_ACTION(path); | 1097 | ap = ALLOC_ACTION(path); |
diff --git a/include/applets.src.h b/include/applets.src.h index 252a060fb..597b1c9a6 100644 --- a/include/applets.src.h +++ b/include/applets.src.h | |||
@@ -70,12 +70,12 @@ INSERT | |||
70 | IF_TEST(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) | 70 | IF_TEST(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) |
71 | IF_TEST(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) | 71 | IF_TEST(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) |
72 | IF_ACPID(APPLET(acpid, BB_DIR_SBIN, BB_SUID_DROP)) | 72 | IF_ACPID(APPLET(acpid, BB_DIR_SBIN, BB_SUID_DROP)) |
73 | IF_ADDGROUP(APPLET(addgroup, BB_DIR_BIN, BB_SUID_DROP)) | 73 | IF_ADDGROUP(APPLET(addgroup, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
74 | IF_ADDUSER(APPLET(adduser, BB_DIR_BIN, BB_SUID_DROP)) | 74 | IF_ADDUSER(APPLET(adduser, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
75 | IF_ADJTIMEX(APPLET(adjtimex, BB_DIR_SBIN, BB_SUID_DROP)) | 75 | IF_ADJTIMEX(APPLET(adjtimex, BB_DIR_SBIN, BB_SUID_DROP)) |
76 | IF_AR(APPLET(ar, BB_DIR_USR_BIN, BB_SUID_DROP)) | 76 | IF_AR(APPLET(ar, BB_DIR_USR_BIN, BB_SUID_DROP)) |
77 | IF_ARP(APPLET(arp, BB_DIR_SBIN, BB_SUID_DROP)) | 77 | IF_ARP(APPLET(arp, BB_DIR_SBIN, BB_SUID_DROP)) |
78 | IF_ARPING(APPLET(arping, BB_DIR_USR_BIN, BB_SUID_DROP)) | 78 | IF_ARPING(APPLET(arping, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
79 | IF_AWK(APPLET_NOEXEC(awk, awk, BB_DIR_USR_BIN, BB_SUID_DROP, awk)) | 79 | IF_AWK(APPLET_NOEXEC(awk, awk, BB_DIR_USR_BIN, BB_SUID_DROP, awk)) |
80 | IF_BASENAME(APPLET_NOFORK(basename, basename, BB_DIR_USR_BIN, BB_SUID_DROP, basename)) | 80 | IF_BASENAME(APPLET_NOFORK(basename, basename, BB_DIR_USR_BIN, BB_SUID_DROP, basename)) |
81 | IF_BBCONFIG(APPLET(bbconfig, BB_DIR_BIN, BB_SUID_DROP)) | 81 | IF_BBCONFIG(APPLET(bbconfig, BB_DIR_BIN, BB_SUID_DROP)) |
@@ -86,7 +86,7 @@ IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) | |||
86 | IF_CAL(APPLET(cal, BB_DIR_USR_BIN, BB_SUID_DROP)) | 86 | IF_CAL(APPLET(cal, BB_DIR_USR_BIN, BB_SUID_DROP)) |
87 | IF_CAT(APPLET_NOFORK(cat, cat, BB_DIR_BIN, BB_SUID_DROP, cat)) | 87 | IF_CAT(APPLET_NOFORK(cat, cat, BB_DIR_BIN, BB_SUID_DROP, cat)) |
88 | IF_CATV(APPLET(catv, BB_DIR_BIN, BB_SUID_DROP)) | 88 | IF_CATV(APPLET(catv, BB_DIR_BIN, BB_SUID_DROP)) |
89 | IF_CHAT(APPLET(chat, BB_DIR_USR_BIN, BB_SUID_DROP)) | 89 | IF_CHAT(APPLET(chat, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
90 | IF_CHATTR(APPLET(chattr, BB_DIR_BIN, BB_SUID_DROP)) | 90 | IF_CHATTR(APPLET(chattr, BB_DIR_BIN, BB_SUID_DROP)) |
91 | IF_CHCON(APPLET(chcon, BB_DIR_USR_BIN, BB_SUID_DROP)) | 91 | IF_CHCON(APPLET(chcon, BB_DIR_USR_BIN, BB_SUID_DROP)) |
92 | IF_CHGRP(APPLET_NOEXEC(chgrp, chgrp, BB_DIR_BIN, BB_SUID_DROP, chgrp)) | 92 | IF_CHGRP(APPLET_NOEXEC(chgrp, chgrp, BB_DIR_BIN, BB_SUID_DROP, chgrp)) |
@@ -111,8 +111,8 @@ IF_CUT(APPLET_NOEXEC(cut, cut, BB_DIR_USR_BIN, BB_SUID_DROP, cut)) | |||
111 | IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) | 111 | IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) |
112 | IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd)) | 112 | IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd)) |
113 | IF_DEALLOCVT(APPLET(deallocvt, BB_DIR_USR_BIN, BB_SUID_DROP)) | 113 | IF_DEALLOCVT(APPLET(deallocvt, BB_DIR_USR_BIN, BB_SUID_DROP)) |
114 | IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, BB_DIR_BIN, BB_SUID_DROP, delgroup)) | 114 | IF_DELGROUP(APPLET_ODDNAME(delgroup, deluser, BB_DIR_USR_SBIN, BB_SUID_DROP, delgroup)) |
115 | IF_DELUSER(APPLET(deluser, BB_DIR_BIN, BB_SUID_DROP)) | 115 | IF_DELUSER(APPLET(deluser, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
116 | IF_DEVFSD(APPLET(devfsd, BB_DIR_SBIN, BB_SUID_DROP)) | 116 | IF_DEVFSD(APPLET(devfsd, BB_DIR_SBIN, BB_SUID_DROP)) |
117 | IF_DEVMEM(APPLET(devmem, BB_DIR_SBIN, BB_SUID_DROP)) | 117 | IF_DEVMEM(APPLET(devmem, BB_DIR_SBIN, BB_SUID_DROP)) |
118 | IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP)) | 118 | IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP)) |
@@ -136,7 +136,7 @@ IF_EJECT(APPLET(eject, BB_DIR_USR_BIN, BB_SUID_DROP)) | |||
136 | IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env)) | 136 | IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env)) |
137 | IF_ENVDIR(APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir)) | 137 | IF_ENVDIR(APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir)) |
138 | IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid)) | 138 | IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid)) |
139 | IF_ETHER_WAKE(APPLET_ODDNAME(ether-wake, ether_wake, BB_DIR_USR_BIN, BB_SUID_DROP, ether_wake)) | 139 | IF_ETHER_WAKE(APPLET_ODDNAME(ether-wake, ether_wake, BB_DIR_USR_SBIN, BB_SUID_DROP, ether_wake)) |
140 | IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP)) | 140 | IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP)) |
141 | IF_EXPR(APPLET(expr, BB_DIR_USR_BIN, BB_SUID_DROP)) | 141 | IF_EXPR(APPLET(expr, BB_DIR_USR_BIN, BB_SUID_DROP)) |
142 | IF_FAKEIDENTD(APPLET(fakeidentd, BB_DIR_USR_SBIN, BB_SUID_DROP)) | 142 | IF_FAKEIDENTD(APPLET(fakeidentd, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
@@ -144,7 +144,7 @@ IF_FALSE(APPLET_NOFORK(false, false, BB_DIR_BIN, BB_SUID_DROP, false)) | |||
144 | IF_FBSET(APPLET(fbset, BB_DIR_USR_SBIN, BB_SUID_DROP)) | 144 | IF_FBSET(APPLET(fbset, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
145 | IF_FBSPLASH(APPLET(fbsplash, BB_DIR_SBIN, BB_SUID_DROP)) | 145 | IF_FBSPLASH(APPLET(fbsplash, BB_DIR_SBIN, BB_SUID_DROP)) |
146 | IF_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, BB_DIR_BIN, BB_SUID_DROP, fdflush)) | 146 | IF_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, BB_DIR_BIN, BB_SUID_DROP, fdflush)) |
147 | IF_FDFORMAT(APPLET(fdformat, BB_DIR_USR_BIN, BB_SUID_DROP)) | 147 | IF_FDFORMAT(APPLET(fdformat, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
148 | IF_FDISK(APPLET(fdisk, BB_DIR_SBIN, BB_SUID_DROP)) | 148 | IF_FDISK(APPLET(fdisk, BB_DIR_SBIN, BB_SUID_DROP)) |
149 | IF_FGCONSOLE(APPLET(fgconsole, BB_DIR_USR_BIN, BB_SUID_DROP)) | 149 | IF_FGCONSOLE(APPLET(fgconsole, BB_DIR_USR_BIN, BB_SUID_DROP)) |
150 | /* Benefits from suid root: better access to /dev/BLOCKDEVs: */ | 150 | /* Benefits from suid root: better access to /dev/BLOCKDEVs: */ |
@@ -182,7 +182,7 @@ IF_HWCLOCK(APPLET(hwclock, BB_DIR_SBIN, BB_SUID_DROP)) | |||
182 | IF_IFCONFIG(APPLET(ifconfig, BB_DIR_SBIN, BB_SUID_DROP)) | 182 | IF_IFCONFIG(APPLET(ifconfig, BB_DIR_SBIN, BB_SUID_DROP)) |
183 | IF_IFUPDOWN(APPLET_ODDNAME(ifdown, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifdown)) | 183 | IF_IFUPDOWN(APPLET_ODDNAME(ifdown, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifdown)) |
184 | IF_IFENSLAVE(APPLET(ifenslave, BB_DIR_SBIN, BB_SUID_DROP)) | 184 | IF_IFENSLAVE(APPLET(ifenslave, BB_DIR_SBIN, BB_SUID_DROP)) |
185 | IF_IFPLUGD(APPLET(ifplugd, BB_DIR_USR_BIN, BB_SUID_DROP)) | 185 | IF_IFPLUGD(APPLET(ifplugd, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
186 | IF_IFUPDOWN(APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup)) | 186 | IF_IFUPDOWN(APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup)) |
187 | IF_INETD(APPLET(inetd, BB_DIR_USR_SBIN, BB_SUID_DROP)) | 187 | IF_INETD(APPLET(inetd, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
188 | IF_INOTIFYD(APPLET(inotifyd, BB_DIR_SBIN, BB_SUID_DROP)) | 188 | IF_INOTIFYD(APPLET(inotifyd, BB_DIR_SBIN, BB_SUID_DROP)) |
@@ -193,20 +193,20 @@ IF_IONICE(APPLET(ionice, BB_DIR_BIN, BB_SUID_DROP)) | |||
193 | || ENABLE_FEATURE_IP_LINK \ | 193 | || ENABLE_FEATURE_IP_LINK \ |
194 | || ENABLE_FEATURE_IP_TUNNEL \ | 194 | || ENABLE_FEATURE_IP_TUNNEL \ |
195 | || ENABLE_FEATURE_IP_RULE | 195 | || ENABLE_FEATURE_IP_RULE |
196 | IF_IP(APPLET(ip, BB_DIR_BIN, BB_SUID_DROP)) | 196 | IF_IP(APPLET(ip, BB_DIR_SBIN, BB_SUID_DROP)) |
197 | #endif | 197 | #endif |
198 | IF_IPADDR(APPLET(ipaddr, BB_DIR_BIN, BB_SUID_DROP)) | 198 | IF_IPADDR(APPLET(ipaddr, BB_DIR_SBIN, BB_SUID_DROP)) |
199 | IF_IPCALC(APPLET(ipcalc, BB_DIR_BIN, BB_SUID_DROP)) | 199 | IF_IPCALC(APPLET(ipcalc, BB_DIR_BIN, BB_SUID_DROP)) |
200 | IF_IPCRM(APPLET(ipcrm, BB_DIR_USR_BIN, BB_SUID_DROP)) | 200 | IF_IPCRM(APPLET(ipcrm, BB_DIR_USR_BIN, BB_SUID_DROP)) |
201 | IF_IPCS(APPLET(ipcs, BB_DIR_USR_BIN, BB_SUID_DROP)) | 201 | IF_IPCS(APPLET(ipcs, BB_DIR_USR_BIN, BB_SUID_DROP)) |
202 | IF_IPLINK(APPLET(iplink, BB_DIR_BIN, BB_SUID_DROP)) | 202 | IF_IPLINK(APPLET(iplink, BB_DIR_SBIN, BB_SUID_DROP)) |
203 | IF_IPROUTE(APPLET(iproute, BB_DIR_BIN, BB_SUID_DROP)) | 203 | IF_IPROUTE(APPLET(iproute, BB_DIR_SBIN, BB_SUID_DROP)) |
204 | IF_IPRULE(APPLET(iprule, BB_DIR_BIN, BB_SUID_DROP)) | 204 | IF_IPRULE(APPLET(iprule, BB_DIR_SBIN, BB_SUID_DROP)) |
205 | IF_IPTUNNEL(APPLET(iptunnel, BB_DIR_BIN, BB_SUID_DROP)) | 205 | IF_IPTUNNEL(APPLET(iptunnel, BB_DIR_SBIN, BB_SUID_DROP)) |
206 | IF_KBD_MODE(APPLET(kbd_mode, BB_DIR_USR_BIN, BB_SUID_DROP)) | 206 | IF_KBD_MODE(APPLET(kbd_mode, BB_DIR_BIN, BB_SUID_DROP)) |
207 | IF_KILL(APPLET(kill, BB_DIR_BIN, BB_SUID_DROP)) | 207 | IF_KILL(APPLET(kill, BB_DIR_BIN, BB_SUID_DROP)) |
208 | IF_KILLALL(APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall)) | 208 | IF_KILLALL(APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall)) |
209 | IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall5)) | 209 | IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_SBIN, BB_SUID_DROP, killall5)) |
210 | IF_KLOGD(APPLET(klogd, BB_DIR_SBIN, BB_SUID_DROP)) | 210 | IF_KLOGD(APPLET(klogd, BB_DIR_SBIN, BB_SUID_DROP)) |
211 | IF_LAST(APPLET(last, BB_DIR_USR_BIN, BB_SUID_DROP)) | 211 | IF_LAST(APPLET(last, BB_DIR_USR_BIN, BB_SUID_DROP)) |
212 | //IF_LENGTH(APPLET_NOFORK(length, length, BB_DIR_USR_BIN, BB_SUID_DROP, length)) | 212 | //IF_LENGTH(APPLET_NOFORK(length, length, BB_DIR_USR_BIN, BB_SUID_DROP, length)) |
@@ -288,7 +288,7 @@ IF_PWD(APPLET_NOFORK(pwd, pwd, BB_DIR_BIN, BB_SUID_DROP, pwd)) | |||
288 | IF_RAIDAUTORUN(APPLET(raidautorun, BB_DIR_SBIN, BB_SUID_DROP)) | 288 | IF_RAIDAUTORUN(APPLET(raidautorun, BB_DIR_SBIN, BB_SUID_DROP)) |
289 | IF_RDATE(APPLET(rdate, BB_DIR_USR_SBIN, BB_SUID_DROP)) | 289 | IF_RDATE(APPLET(rdate, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
290 | IF_RDEV(APPLET(rdev, BB_DIR_USR_SBIN, BB_SUID_DROP)) | 290 | IF_RDEV(APPLET(rdev, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
291 | IF_READAHEAD(APPLET(readahead, BB_DIR_USR_BIN, BB_SUID_DROP)) | 291 | IF_READAHEAD(APPLET(readahead, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
292 | IF_READLINK(APPLET(readlink, BB_DIR_USR_BIN, BB_SUID_DROP)) | 292 | IF_READLINK(APPLET(readlink, BB_DIR_USR_BIN, BB_SUID_DROP)) |
293 | IF_READPROFILE(APPLET(readprofile, BB_DIR_USR_SBIN, BB_SUID_DROP)) | 293 | IF_READPROFILE(APPLET(readprofile, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
294 | IF_REALPATH(APPLET(realpath, BB_DIR_USR_BIN, BB_SUID_DROP)) | 294 | IF_REALPATH(APPLET(realpath, BB_DIR_USR_BIN, BB_SUID_DROP)) |
@@ -303,7 +303,7 @@ IF_RMDIR(APPLET_NOFORK(rmdir, rmdir, BB_DIR_BIN, BB_SUID_DROP, rmdir)) | |||
303 | IF_ROUTE(APPLET(route, BB_DIR_SBIN, BB_SUID_DROP)) | 303 | IF_ROUTE(APPLET(route, BB_DIR_SBIN, BB_SUID_DROP)) |
304 | IF_RPM(APPLET(rpm, BB_DIR_BIN, BB_SUID_DROP)) | 304 | IF_RPM(APPLET(rpm, BB_DIR_BIN, BB_SUID_DROP)) |
305 | IF_RPM2CPIO(APPLET(rpm2cpio, BB_DIR_USR_BIN, BB_SUID_DROP)) | 305 | IF_RPM2CPIO(APPLET(rpm2cpio, BB_DIR_USR_BIN, BB_SUID_DROP)) |
306 | IF_RTCWAKE(APPLET(rtcwake, BB_DIR_USR_BIN, BB_SUID_DROP)) | 306 | IF_RTCWAKE(APPLET(rtcwake, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
307 | IF_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, BB_DIR_BIN, BB_SUID_DROP, run_parts)) | 307 | IF_RUN_PARTS(APPLET_ODDNAME(run-parts, run_parts, BB_DIR_BIN, BB_SUID_DROP, run_parts)) |
308 | IF_RUNCON(APPLET(runcon, BB_DIR_USR_BIN, BB_SUID_DROP)) | 308 | IF_RUNCON(APPLET(runcon, BB_DIR_USR_BIN, BB_SUID_DROP)) |
309 | IF_RUNLEVEL(APPLET(runlevel, BB_DIR_SBIN, BB_SUID_DROP)) | 309 | IF_RUNLEVEL(APPLET(runlevel, BB_DIR_SBIN, BB_SUID_DROP)) |
@@ -365,7 +365,7 @@ IF_TELNETD(APPLET(telnetd, BB_DIR_USR_SBIN, BB_SUID_DROP)) | |||
365 | IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) | 365 | IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) |
366 | #if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT | 366 | #if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT |
367 | IF_TFTP(APPLET(tftp, BB_DIR_USR_BIN, BB_SUID_DROP)) | 367 | IF_TFTP(APPLET(tftp, BB_DIR_USR_BIN, BB_SUID_DROP)) |
368 | IF_TFTPD(APPLET(tftpd, BB_DIR_USR_BIN, BB_SUID_DROP)) | 368 | IF_TFTPD(APPLET(tftpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
369 | #endif | 369 | #endif |
370 | IF_TIME(APPLET(time, BB_DIR_USR_BIN, BB_SUID_DROP)) | 370 | IF_TIME(APPLET(time, BB_DIR_USR_BIN, BB_SUID_DROP)) |
371 | IF_TIMEOUT(APPLET(timeout, BB_DIR_USR_BIN, BB_SUID_DROP)) | 371 | IF_TIMEOUT(APPLET(timeout, BB_DIR_USR_BIN, BB_SUID_DROP)) |
diff --git a/include/bb_archive.h b/include/bb_archive.h index 2043d8570..7bb5615da 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h | |||
@@ -121,6 +121,7 @@ typedef struct archive_handle_t { | |||
121 | #define ARCHIVE_DONT_RESTORE_PERM (1 << 6) | 121 | #define ARCHIVE_DONT_RESTORE_PERM (1 << 6) |
122 | #define ARCHIVE_NUMERIC_OWNER (1 << 7) | 122 | #define ARCHIVE_NUMERIC_OWNER (1 << 7) |
123 | #define ARCHIVE_O_TRUNC (1 << 8) | 123 | #define ARCHIVE_O_TRUNC (1 << 8) |
124 | #define ARCHIVE_REMEMBER_NAMES (1 << 9) | ||
124 | 125 | ||
125 | 126 | ||
126 | /* POSIX tar Header Block, from POSIX 1003.1-1990 */ | 127 | /* POSIX tar Header Block, from POSIX 1003.1-1990 */ |
diff --git a/include/bb_e2fs_defs.h b/include/bb_e2fs_defs.h index 7974497ca..b400f8c11 100644 --- a/include/bb_e2fs_defs.h +++ b/include/bb_e2fs_defs.h | |||
@@ -406,25 +406,43 @@ struct ext2_super_block { | |||
406 | * Performance hints. Directory preallocation should only | 406 | * Performance hints. Directory preallocation should only |
407 | * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. | 407 | * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. |
408 | */ | 408 | */ |
409 | uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ | 409 | uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ |
410 | uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ | 410 | uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ |
411 | uint16_t s_reserved_gdt_blocks; /* Per group table for online growth */ | 411 | uint16_t s_reserved_gdt_blocks; /* Per group table for online growth */ |
412 | /* | 412 | /* |
413 | * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. | 413 | * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. |
414 | */ | 414 | */ |
415 | uint8_t s_journal_uuid[16]; /* uuid of journal superblock */ | 415 | /*D0*/ uint8_t s_journal_uuid[16]; /* uuid of journal superblock */ |
416 | uint32_t s_journal_inum; /* inode number of journal file */ | 416 | /*E0*/ uint32_t s_journal_inum; /* inode number of journal file */ |
417 | uint32_t s_journal_dev; /* device number of journal file */ | 417 | uint32_t s_journal_dev; /* device number of journal file */ |
418 | uint32_t s_last_orphan; /* start of list of inodes to delete */ | 418 | uint32_t s_last_orphan; /* start of list of inodes to delete */ |
419 | uint32_t s_hash_seed[4]; /* HTREE hash seed */ | 419 | uint32_t s_hash_seed[4]; /* HTREE hash seed */ |
420 | uint8_t s_def_hash_version; /* Default hash version to use */ | 420 | uint8_t s_def_hash_version; /* Default hash version to use */ |
421 | uint8_t s_jnl_backup_type; /* Default type of journal backup */ | 421 | uint8_t s_jnl_backup_type; /* Default type of journal backup */ |
422 | uint16_t s_reserved_word_pad; | 422 | uint16_t s_reserved_word_pad; |
423 | uint32_t s_default_mount_opts; | 423 | /*100*/ uint32_t s_default_mount_opts; |
424 | uint32_t s_first_meta_bg; /* First metablock group */ | 424 | uint32_t s_first_meta_bg; /* First metablock group */ |
425 | /* ext3 additions */ | ||
425 | uint32_t s_mkfs_time; /* When the filesystem was created */ | 426 | uint32_t s_mkfs_time; /* When the filesystem was created */ |
426 | uint32_t s_jnl_blocks[17]; /* Backup of the journal inode */ | 427 | uint32_t s_jnl_blocks[17]; /* Backup of the journal inode */ |
427 | uint32_t s_reserved[172]; /* Padding to the end of the block */ | 428 | /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */ |
429 | /*150*/ uint32_t s_blocks_count_hi; /* Blocks count */ | ||
430 | uint32_t s_r_blocks_count_hi; /* Reserved blocks count */ | ||
431 | uint32_t s_free_blocks_count_hi; /* Free blocks count */ | ||
432 | uint16_t s_min_extra_isize; /* All inodes have at least # bytes */ | ||
433 | uint16_t s_want_extra_isize; /* New inodes should reserve # bytes */ | ||
434 | uint32_t s_flags; /* Miscellaneous flags */ | ||
435 | uint16_t s_raid_stride; /* RAID stride */ | ||
436 | uint16_t s_mmp_interval; /* # seconds to wait in MMP checking */ | ||
437 | uint64_t s_mmp_block; /* Block for multi-mount protection */ | ||
438 | uint32_t s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ | ||
439 | uint8_t s_log_groups_per_flex; /* FLEX_BG group size */ | ||
440 | uint8_t s_reserved_char_pad2; | ||
441 | uint16_t s_reserved_pad; | ||
442 | uint32_t s_reserved[162]; /* Padding to the end of the block */ | ||
443 | }; | ||
444 | struct BUG_ext2_super_block { | ||
445 | char bug[sizeof(struct ext2_super_block) == 1024 ? 1 : -1]; | ||
428 | }; | 446 | }; |
429 | 447 | ||
430 | /* | 448 | /* |
@@ -463,6 +481,7 @@ struct ext2_super_block { | |||
463 | #define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ | 481 | #define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ |
464 | ( EXT2_SB(sb)->s_feature_incompat & (mask) ) | 482 | ( EXT2_SB(sb)->s_feature_incompat & (mask) ) |
465 | 483 | ||
484 | /* for s_feature_compat */ | ||
466 | #define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 | 485 | #define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 |
467 | #define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 | 486 | #define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 |
468 | #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 | 487 | #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 |
@@ -470,23 +489,45 @@ struct ext2_super_block { | |||
470 | #define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010 | 489 | #define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010 |
471 | #define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 | 490 | #define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 |
472 | 491 | ||
492 | /* for s_feature_ro_compat */ | ||
473 | #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 | 493 | #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 |
474 | #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 | 494 | #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 |
475 | /* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */ | 495 | #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 /* not used */ |
496 | #define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 | ||
497 | #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 | ||
498 | #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 | ||
499 | #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 | ||
476 | 500 | ||
501 | /* for s_feature_incompat */ | ||
477 | #define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 | 502 | #define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 |
478 | #define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 | 503 | #define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 |
479 | #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ | 504 | #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 |
480 | #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ | 505 | #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 |
481 | #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 | 506 | #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 |
482 | #define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 | 507 | #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 |
508 | #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 | ||
509 | #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 | ||
510 | #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 | ||
483 | 511 | ||
484 | 512 | ||
485 | #define EXT2_FEATURE_COMPAT_SUPP 0 | 513 | #define EXT2_FEATURE_COMPAT_SUPP 0 |
486 | #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE) | ||
487 | #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ | 514 | #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ |
488 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ | 515 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ |
489 | EXT2_FEATURE_RO_COMPAT_BTREE_DIR) | 516 | EXT2_FEATURE_RO_COMPAT_BTREE_DIR) |
517 | #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ | ||
518 | EXT2_FEATURE_INCOMPAT_META_BG) | ||
519 | #define EXT2_FEATURE_INCOMPAT_UNSUPPORTED (~EXT2_FEATURE_INCOMPAT_SUPP) | ||
520 | #define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED (~EXT2_FEATURE_RO_COMPAT_SUPP) | ||
521 | |||
522 | #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ | ||
523 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ | ||
524 | EXT2_FEATURE_RO_COMPAT_BTREE_DIR) | ||
525 | #define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ | ||
526 | EXT3_FEATURE_INCOMPAT_RECOVER| \ | ||
527 | EXT2_FEATURE_INCOMPAT_META_BG) | ||
528 | #define EXT3_FEATURE_INCOMPAT_UNSUPPORTED (~EXT3_FEATURE_INCOMPAT_SUPP) | ||
529 | #define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED (~EXT3_FEATURE_RO_COMPAT_SUPP) | ||
530 | |||
490 | 531 | ||
491 | /* | 532 | /* |
492 | * Default values for user and/or group using reserved blocks | 533 | * Default values for user and/or group using reserved blocks |
diff --git a/include/busybox.h b/include/busybox.h index 315ef8f26..b1e31e5ee 100644 --- a/include/busybox.h +++ b/include/busybox.h | |||
@@ -13,10 +13,10 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
13 | 13 | ||
14 | /* Defined in appletlib.c (by including generated applet_tables.h) */ | 14 | /* Defined in appletlib.c (by including generated applet_tables.h) */ |
15 | /* Keep in sync with applets/applet_tables.c! */ | 15 | /* Keep in sync with applets/applet_tables.c! */ |
16 | extern const char applet_names[]; | 16 | extern const char applet_names[] ALIGN1; |
17 | extern int (*const applet_main[])(int argc, char **argv); | 17 | extern int (*const applet_main[])(int argc, char **argv); |
18 | extern const uint16_t applet_nameofs[]; | 18 | extern const uint16_t applet_nameofs[]; |
19 | extern const uint8_t applet_install_loc[]; | 19 | extern const uint8_t applet_install_loc[] ALIGN1; |
20 | 20 | ||
21 | #if ENABLE_FEATURE_SUID || ENABLE_FEATURE_PREFER_APPLETS | 21 | #if ENABLE_FEATURE_SUID || ENABLE_FEATURE_PREFER_APPLETS |
22 | # define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x0fff)) | 22 | # define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x0fff)) |
diff --git a/include/libbb.h b/include/libbb.h index a78772b6a..5012209f8 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -346,6 +346,7 @@ enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */ | |||
346 | FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 9, /* -c */ | 346 | FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 9, /* -c */ |
347 | FILEUTILS_SET_SECURITY_CONTEXT = 1 << 10, | 347 | FILEUTILS_SET_SECURITY_CONTEXT = 1 << 10, |
348 | #endif | 348 | #endif |
349 | FILEUTILS_IGNORE_CHMOD_ERR = 1 << 11, | ||
349 | }; | 350 | }; |
350 | #define FILEUTILS_CP_OPTSTR "pdRfilsLH" IF_SELINUX("c") | 351 | #define FILEUTILS_CP_OPTSTR "pdRfilsLH" IF_SELINUX("c") |
351 | extern int remove_file(const char *path, int flags) FAST_FUNC; | 352 | extern int remove_file(const char *path, int flags) FAST_FUNC; |
@@ -1301,6 +1302,7 @@ int sd_listen_fds(void); | |||
1301 | #define SETUP_ENV_CHANGEENV (1 << 0) | 1302 | #define SETUP_ENV_CHANGEENV (1 << 0) |
1302 | #define SETUP_ENV_CLEARENV (1 << 1) | 1303 | #define SETUP_ENV_CLEARENV (1 << 1) |
1303 | #define SETUP_ENV_TO_TMP (1 << 2) | 1304 | #define SETUP_ENV_TO_TMP (1 << 2) |
1305 | #define SETUP_ENV_NO_CHDIR (1 << 4) | ||
1304 | extern void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC; | 1306 | extern void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC; |
1305 | extern int correct_password(const struct passwd *pw) FAST_FUNC; | 1307 | extern int correct_password(const struct passwd *pw) FAST_FUNC; |
1306 | /* Returns a malloced string */ | 1308 | /* Returns a malloced string */ |
@@ -1629,8 +1631,8 @@ unsigned get_cpu_count(void) FAST_FUNC; | |||
1629 | char *percent_decode_in_place(char *str, int strict) FAST_FUNC; | 1631 | char *percent_decode_in_place(char *str, int strict) FAST_FUNC; |
1630 | 1632 | ||
1631 | 1633 | ||
1632 | extern const char bb_uuenc_tbl_base64[]; | 1634 | extern const char bb_uuenc_tbl_base64[] ALIGN1; |
1633 | extern const char bb_uuenc_tbl_std[]; | 1635 | extern const char bb_uuenc_tbl_std[] ALIGN1; |
1634 | void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; | 1636 | void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; |
1635 | enum { | 1637 | enum { |
1636 | BASE64_FLAG_UU_STOP = 0x100, | 1638 | BASE64_FLAG_UU_STOP = 0x100, |
@@ -1711,29 +1713,24 @@ extern const char *applet_name; | |||
1711 | * Therefore now we use #defines. | 1713 | * Therefore now we use #defines. |
1712 | */ | 1714 | */ |
1713 | /* "BusyBox vN.N.N (timestamp or extra_version)" */ | 1715 | /* "BusyBox vN.N.N (timestamp or extra_version)" */ |
1714 | extern const char bb_banner[]; | 1716 | extern const char bb_banner[] ALIGN1; |
1715 | extern const char bb_msg_memory_exhausted[]; | 1717 | extern const char bb_msg_memory_exhausted[] ALIGN1; |
1716 | extern const char bb_msg_invalid_date[]; | 1718 | extern const char bb_msg_invalid_date[] ALIGN1; |
1717 | #define bb_msg_read_error "read error" | 1719 | #define bb_msg_read_error "read error" |
1718 | #define bb_msg_write_error "write error" | 1720 | #define bb_msg_write_error "write error" |
1719 | extern const char bb_msg_unknown[]; | 1721 | extern const char bb_msg_unknown[] ALIGN1; |
1720 | extern const char bb_msg_can_not_create_raw_socket[]; | 1722 | extern const char bb_msg_can_not_create_raw_socket[] ALIGN1; |
1721 | extern const char bb_msg_perm_denied_are_you_root[]; | 1723 | extern const char bb_msg_perm_denied_are_you_root[] ALIGN1; |
1722 | extern const char bb_msg_you_must_be_root[]; | 1724 | extern const char bb_msg_you_must_be_root[] ALIGN1; |
1723 | extern const char bb_msg_requires_arg[]; | 1725 | extern const char bb_msg_requires_arg[] ALIGN1; |
1724 | extern const char bb_msg_invalid_arg[]; | 1726 | extern const char bb_msg_invalid_arg[] ALIGN1; |
1725 | extern const char bb_msg_standard_input[]; | 1727 | extern const char bb_msg_standard_input[] ALIGN1; |
1726 | extern const char bb_msg_standard_output[]; | 1728 | extern const char bb_msg_standard_output[] ALIGN1; |
1727 | 1729 | ||
1728 | /* NB: (bb_hexdigits_upcase[i] | 0x20) -> lowercase hex digit */ | 1730 | /* NB: (bb_hexdigits_upcase[i] | 0x20) -> lowercase hex digit */ |
1729 | extern const char bb_hexdigits_upcase[]; | 1731 | extern const char bb_hexdigits_upcase[] ALIGN1; |
1730 | 1732 | ||
1731 | extern const char bb_path_wtmp_file[]; | 1733 | extern const char bb_path_wtmp_file[] ALIGN1; |
1732 | #if ENABLE_PLATFORM_MINGW32 | ||
1733 | #define bb_busybox_exec_path get_busybox_exec_path() | ||
1734 | #else | ||
1735 | extern const char bb_busybox_exec_path[]; | ||
1736 | #endif | ||
1737 | 1734 | ||
1738 | /* Busybox mount uses either /proc/mounts or /etc/mtab to | 1735 | /* Busybox mount uses either /proc/mounts or /etc/mtab to |
1739 | * get the list of currently mounted filesystems */ | 1736 | * get the list of currently mounted filesystems */ |
@@ -1747,9 +1744,14 @@ extern const char bb_busybox_exec_path[]; | |||
1747 | #define bb_path_motd_file "/etc/motd" | 1744 | #define bb_path_motd_file "/etc/motd" |
1748 | 1745 | ||
1749 | #define bb_dev_null "/dev/null" | 1746 | #define bb_dev_null "/dev/null" |
1747 | #if ENABLE_PLATFORM_MINGW32 | ||
1748 | #define bb_busybox_exec_path get_busybox_exec_path() | ||
1749 | #else | ||
1750 | extern const char bb_busybox_exec_path[] ALIGN1; | ||
1751 | #endif | ||
1750 | /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, | 1752 | /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, |
1751 | * but I want to save a few bytes here */ | 1753 | * but I want to save a few bytes here */ |
1752 | extern const char bb_PATH_root_path[]; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */ | 1754 | extern const char bb_PATH_root_path[] ALIGN1; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */ |
1753 | #define bb_default_root_path (bb_PATH_root_path + sizeof("PATH")) | 1755 | #define bb_default_root_path (bb_PATH_root_path + sizeof("PATH")) |
1754 | #define bb_default_path (bb_PATH_root_path + sizeof("PATH=/sbin:/usr/sbin")) | 1756 | #define bb_default_path (bb_PATH_root_path + sizeof("PATH=/sbin:/usr/sbin")) |
1755 | 1757 | ||
@@ -1779,7 +1781,7 @@ extern struct globals *const ptr_to_globals; | |||
1779 | * If you change LIBBB_DEFAULT_LOGIN_SHELL, | 1781 | * If you change LIBBB_DEFAULT_LOGIN_SHELL, |
1780 | * don't forget to change increment constant. */ | 1782 | * don't forget to change increment constant. */ |
1781 | #define LIBBB_DEFAULT_LOGIN_SHELL "-/bin/sh" | 1783 | #define LIBBB_DEFAULT_LOGIN_SHELL "-/bin/sh" |
1782 | extern const char bb_default_login_shell[]; | 1784 | extern const char bb_default_login_shell[] ALIGN1; |
1783 | /* "/bin/sh" */ | 1785 | /* "/bin/sh" */ |
1784 | #define DEFAULT_SHELL (bb_default_login_shell+1) | 1786 | #define DEFAULT_SHELL (bb_default_login_shell+1) |
1785 | /* "sh" */ | 1787 | /* "sh" */ |
diff --git a/include/platform.h b/include/platform.h index 925cce60c..78d42fed9 100644 --- a/include/platform.h +++ b/include/platform.h | |||
@@ -301,7 +301,8 @@ typedef unsigned smalluint; | |||
301 | #define fdprintf dprintf | 301 | #define fdprintf dprintf |
302 | 302 | ||
303 | /* Useful for defeating gcc's alignment of "char message[]"-like data */ | 303 | /* Useful for defeating gcc's alignment of "char message[]"-like data */ |
304 | #if 1 /* if needed: !defined(arch1) && !defined(arch2) */ | 304 | #if !defined(__s390__) |
305 | /* on s390[x], non-word-aligned data accesses require larger code */ | ||
305 | # define ALIGN1 __attribute__((aligned(1))) | 306 | # define ALIGN1 __attribute__((aligned(1))) |
306 | # define ALIGN2 __attribute__((aligned(2))) | 307 | # define ALIGN2 __attribute__((aligned(2))) |
307 | # define ALIGN4 __attribute__((aligned(4))) | 308 | # define ALIGN4 __attribute__((aligned(4))) |
@@ -351,6 +352,12 @@ typedef unsigned smalluint; | |||
351 | # define MAXSYMLINKS SYMLOOP_MAX | 352 | # define MAXSYMLINKS SYMLOOP_MAX |
352 | #endif | 353 | #endif |
353 | 354 | ||
355 | #if defined(ANDROID) || defined(__ANDROID__) | ||
356 | # define BB_ADDITIONAL_PATH ":/system/sbin:/system/bin:/system/xbin" | ||
357 | # define SYS_ioprio_set __NR_ioprio_set | ||
358 | # define SYS_ioprio_get __NR_ioprio_get | ||
359 | #endif | ||
360 | |||
354 | 361 | ||
355 | /* ---- Who misses what? ------------------------------------ */ | 362 | /* ---- Who misses what? ------------------------------------ */ |
356 | 363 | ||
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 76c4d8ff3..0c0d14499 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -629,11 +629,11 @@ static int busybox_main(char **argv) | |||
629 | full_write2_str(bb_banner); /* reuse const string */ | 629 | full_write2_str(bb_banner); /* reuse const string */ |
630 | full_write2_str(" multi-call binary.\n"); /* reuse */ | 630 | full_write2_str(" multi-call binary.\n"); /* reuse */ |
631 | full_write2_str( | 631 | full_write2_str( |
632 | "Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko\n" | 632 | "BusyBox is copyrighted by many authors between 1998-2012.\n" |
633 | "and others. Licensed under GPLv2.\n" | 633 | "Licensed under GPLv2. See source distribution for detailed\n" |
634 | "See source distribution for full notice.\n" | 634 | "copyright notices.\n" |
635 | "\n" | 635 | "\n" |
636 | "Usage: busybox [function] [arguments]...\n" | 636 | "Usage: busybox [function [arguments]...]\n" |
637 | " or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n" | 637 | " or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n" |
638 | IF_FEATURE_INSTALLER( | 638 | IF_FEATURE_INSTALLER( |
639 | " or: busybox --install [-s] [DIR]\n" | 639 | " or: busybox --install [-s] [DIR]\n" |
diff --git a/libbb/correct_password.c b/libbb/correct_password.c index 6301589e6..7cabd33d0 100644 --- a/libbb/correct_password.c +++ b/libbb/correct_password.c | |||
@@ -41,12 +41,6 @@ int FAST_FUNC correct_password(const struct passwd *pw) | |||
41 | char *unencrypted, *encrypted; | 41 | char *unencrypted, *encrypted; |
42 | const char *correct; | 42 | const char *correct; |
43 | int r; | 43 | int r; |
44 | #if ENABLE_FEATURE_SHADOWPASSWDS | ||
45 | /* Using _r function to avoid pulling in static buffers */ | ||
46 | struct spwd spw; | ||
47 | char buffer[256]; | ||
48 | #endif | ||
49 | |||
50 | /* fake salt. crypt() can choke otherwise. */ | 44 | /* fake salt. crypt() can choke otherwise. */ |
51 | correct = "aa"; | 45 | correct = "aa"; |
52 | if (!pw) { | 46 | if (!pw) { |
@@ -55,7 +49,10 @@ int FAST_FUNC correct_password(const struct passwd *pw) | |||
55 | } | 49 | } |
56 | correct = pw->pw_passwd; | 50 | correct = pw->pw_passwd; |
57 | #if ENABLE_FEATURE_SHADOWPASSWDS | 51 | #if ENABLE_FEATURE_SHADOWPASSWDS |
52 | /* Using _r function to avoid pulling in static buffers */ | ||
58 | if ((correct[0] == 'x' || correct[0] == '*') && !correct[1]) { | 53 | if ((correct[0] == 'x' || correct[0] == '*') && !correct[1]) { |
54 | struct spwd spw; | ||
55 | char buffer[256]; | ||
59 | /* getspnam_r may return 0 yet set result to NULL. | 56 | /* getspnam_r may return 0 yet set result to NULL. |
60 | * At least glibc 2.4 does this. Be extra paranoid here. */ | 57 | * At least glibc 2.4 does this. Be extra paranoid here. */ |
61 | struct spwd *result = NULL; | 58 | struct spwd *result = NULL; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 6990b91b6..65dffe56d 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -2552,9 +2552,9 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2552 | /* Delete word forward */ | 2552 | /* Delete word forward */ |
2553 | int nc, sc = cursor; | 2553 | int nc, sc = cursor; |
2554 | ctrl_right(); | 2554 | ctrl_right(); |
2555 | nc = cursor; | 2555 | nc = cursor - sc; |
2556 | input_backward(cursor - sc); | 2556 | input_backward(nc); |
2557 | while (--nc >= cursor) | 2557 | while (--nc >= 0) |
2558 | input_delete(1); | 2558 | input_delete(1); |
2559 | break; | 2559 | break; |
2560 | } | 2560 | } |
diff --git a/libbb/make_directory.c b/libbb/make_directory.c index 8057f2cec..6f59fda29 100644 --- a/libbb/make_directory.c +++ b/libbb/make_directory.c | |||
@@ -114,6 +114,10 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags) | |||
114 | * an error. */ | 114 | * an error. */ |
115 | if ((mode != -1) && (chmod(path, mode) < 0)) { | 115 | if ((mode != -1) && (chmod(path, mode) < 0)) { |
116 | fail_msg = "set permissions of"; | 116 | fail_msg = "set permissions of"; |
117 | if (flags & FILEUTILS_IGNORE_CHMOD_ERR) { | ||
118 | flags = 0; | ||
119 | goto print_err; | ||
120 | } | ||
117 | break; | 121 | break; |
118 | } | 122 | } |
119 | goto ret0; | 123 | goto ret0; |
@@ -123,8 +127,9 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags) | |||
123 | *s2 = c; | 127 | *s2 = c; |
124 | } /* while (1) */ | 128 | } /* while (1) */ |
125 | 129 | ||
126 | bb_perror_msg("can't %s directory '%s'", fail_msg, path); | ||
127 | flags = -1; | 130 | flags = -1; |
131 | print_err: | ||
132 | bb_perror_msg("can't %s directory '%s'", fail_msg, path); | ||
128 | goto ret; | 133 | goto ret; |
129 | ret0: | 134 | ret0: |
130 | flags = 0; | 135 | flags = 0; |
diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c new file mode 100644 index 000000000..c50308ba8 --- /dev/null +++ b/libbb/missing_syscalls.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright 2012, Denys Vlasenko | ||
3 | * | ||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | */ | ||
6 | |||
7 | //kbuild:lib-$(CONFIG_PLATFORM_POSIX) += missing_syscalls.o | ||
8 | |||
9 | /*#include <linux/timex.h> - for struct timex, but may collide with <time.h> */ | ||
10 | #include <sys/syscall.h> | ||
11 | #include "libbb.h" | ||
12 | |||
13 | #if defined(ANDROID) || defined(__ANDROID__) | ||
14 | pid_t getsid(pid_t pid) | ||
15 | { | ||
16 | return syscall(__NR_getsid, pid); | ||
17 | } | ||
18 | |||
19 | int stime(const time_t *t) | ||
20 | { | ||
21 | struct timeval tv; | ||
22 | tv.tv_sec = *t; | ||
23 | tv.tv_usec = 0; | ||
24 | return settimeofday(&tv, NULL); | ||
25 | } | ||
26 | |||
27 | int sethostname(const char *name, size_t len) | ||
28 | { | ||
29 | return syscall(__NR_sethostname, name, len); | ||
30 | } | ||
31 | |||
32 | struct timex; | ||
33 | int adjtimex(struct timex *buf) | ||
34 | { | ||
35 | return syscall(__NR_adjtimex, buf); | ||
36 | } | ||
37 | |||
38 | int pivot_root(const char *new_root, const char *put_old) | ||
39 | { | ||
40 | return syscall(__NR_pivot_root, new_root, put_old); | ||
41 | } | ||
42 | #endif | ||
diff --git a/libbb/procps.c b/libbb/procps.c index dbae46e33..1080e0165 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -426,7 +426,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | |||
426 | if (n < 11) | 426 | if (n < 11) |
427 | continue; /* bogus data, get next /proc/XXX */ | 427 | continue; /* bogus data, get next /proc/XXX */ |
428 | # if ENABLE_FEATURE_TOP_SMP_PROCESS | 428 | # if ENABLE_FEATURE_TOP_SMP_PROCESS |
429 | if (n < 11+15) | 429 | if (n == 11) |
430 | sp->last_seen_on_cpu = 0; | 430 | sp->last_seen_on_cpu = 0; |
431 | # endif | 431 | # endif |
432 | 432 | ||
diff --git a/libbb/read_key.c b/libbb/read_key.c index 8d72d2a63..ace23defb 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c | |||
@@ -15,7 +15,10 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
15 | const char *seq; | 15 | const char *seq; |
16 | int n; | 16 | int n; |
17 | 17 | ||
18 | /* Known escape sequences for cursor and function keys */ | 18 | /* Known escape sequences for cursor and function keys. |
19 | * See "Xterm Control Sequences" | ||
20 | * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html | ||
21 | */ | ||
19 | static const char esccmds[] ALIGN1 = { | 22 | static const char esccmds[] ALIGN1 = { |
20 | 'O','A' |0x80,KEYCODE_UP , | 23 | 'O','A' |0x80,KEYCODE_UP , |
21 | 'O','B' |0x80,KEYCODE_DOWN , | 24 | 'O','B' |0x80,KEYCODE_DOWN , |
@@ -44,6 +47,8 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
44 | /* ESC [ 1 ; 4 x, where x = A/B/C/D: Alt-Shift-<arrow> */ | 47 | /* ESC [ 1 ; 4 x, where x = A/B/C/D: Alt-Shift-<arrow> */ |
45 | /* ESC [ 1 ; 5 x, where x = A/B/C/D: Ctrl-<arrow> - implemented below */ | 48 | /* ESC [ 1 ; 5 x, where x = A/B/C/D: Ctrl-<arrow> - implemented below */ |
46 | /* ESC [ 1 ; 6 x, where x = A/B/C/D: Ctrl-Shift-<arrow> */ | 49 | /* ESC [ 1 ; 6 x, where x = A/B/C/D: Ctrl-Shift-<arrow> */ |
50 | /* ESC [ 1 ; 7 x, where x = A/B/C/D: Ctrl-Alt-<arrow> */ | ||
51 | /* ESC [ 1 ; 8 x, where x = A/B/C/D: Ctrl-Alt-Shift-<arrow> */ | ||
47 | '[','H' |0x80,KEYCODE_HOME , /* xterm */ | 52 | '[','H' |0x80,KEYCODE_HOME , /* xterm */ |
48 | '[','F' |0x80,KEYCODE_END , /* xterm */ | 53 | '[','F' |0x80,KEYCODE_END , /* xterm */ |
49 | /* [ESC] ESC [ [2] H - [Alt-][Shift-]Home (End similarly?) */ | 54 | /* [ESC] ESC [ [2] H - [Alt-][Shift-]Home (End similarly?) */ |
@@ -64,10 +69,10 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
64 | '[','7','~' |0x80,KEYCODE_HOME , /* vt100? linux vt? or what? */ | 69 | '[','7','~' |0x80,KEYCODE_HOME , /* vt100? linux vt? or what? */ |
65 | '[','8','~' |0x80,KEYCODE_END , /* vt100? linux vt? or what? */ | 70 | '[','8','~' |0x80,KEYCODE_END , /* vt100? linux vt? or what? */ |
66 | #if 0 | 71 | #if 0 |
67 | '[','1','1','~'|0x80,KEYCODE_FUN1 , | 72 | '[','1','1','~'|0x80,KEYCODE_FUN1 , /* old xterm, deprecated by ESC O P */ |
68 | '[','1','2','~'|0x80,KEYCODE_FUN2 , | 73 | '[','1','2','~'|0x80,KEYCODE_FUN2 , /* old xterm... */ |
69 | '[','1','3','~'|0x80,KEYCODE_FUN3 , | 74 | '[','1','3','~'|0x80,KEYCODE_FUN3 , /* old xterm... */ |
70 | '[','1','4','~'|0x80,KEYCODE_FUN4 , | 75 | '[','1','4','~'|0x80,KEYCODE_FUN4 , /* old xterm... */ |
71 | '[','1','5','~'|0x80,KEYCODE_FUN5 , | 76 | '[','1','5','~'|0x80,KEYCODE_FUN5 , |
72 | /* [ESC] ESC [ 1 5 [;2] ~ - [Alt-][Shift-]F5 */ | 77 | /* [ESC] ESC [ 1 5 [;2] ~ - [Alt-][Shift-]F5 */ |
73 | '[','1','7','~'|0x80,KEYCODE_FUN6 , | 78 | '[','1','7','~'|0x80,KEYCODE_FUN6 , |
diff --git a/libbb/setup_environment.c b/libbb/setup_environment.c index 73229ca6c..4258656fe 100644 --- a/libbb/setup_environment.c +++ b/libbb/setup_environment.c | |||
@@ -37,9 +37,11 @@ void FAST_FUNC setup_environment(const char *shell, int flags, const struct pass | |||
37 | 37 | ||
38 | /* Change the current working directory to be the home directory | 38 | /* Change the current working directory to be the home directory |
39 | * of the user */ | 39 | * of the user */ |
40 | if (chdir(pw->pw_dir)) { | 40 | if (!(flags & SETUP_ENV_NO_CHDIR)) { |
41 | xchdir((flags & SETUP_ENV_TO_TMP) ? "/tmp" : "/"); | 41 | if (chdir(pw->pw_dir) != 0) { |
42 | bb_error_msg("can't chdir to home directory '%s'", pw->pw_dir); | 42 | bb_error_msg("can't change directory to '%s'", pw->pw_dir); |
43 | xchdir((flags & SETUP_ENV_TO_TMP) ? "/tmp" : "/"); | ||
44 | } | ||
43 | } | 45 | } |
44 | 46 | ||
45 | if (flags & SETUP_ENV_CLEARENV) { | 47 | if (flags & SETUP_ENV_CLEARENV) { |
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index d8a42ba0b..05aa07ce8 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -355,13 +355,13 @@ void FAST_FUNC xsetuid(uid_t uid) | |||
355 | void FAST_FUNC xchdir(const char *path) | 355 | void FAST_FUNC xchdir(const char *path) |
356 | { | 356 | { |
357 | if (chdir(path)) | 357 | if (chdir(path)) |
358 | bb_perror_msg_and_die("chdir(%s)", path); | 358 | bb_perror_msg_and_die("can't change directory to '%s'", path); |
359 | } | 359 | } |
360 | 360 | ||
361 | void FAST_FUNC xchroot(const char *path) | 361 | void FAST_FUNC xchroot(const char *path) |
362 | { | 362 | { |
363 | if (chroot(path)) | 363 | if (chroot(path)) |
364 | bb_perror_msg_and_die("can't change root directory to %s", path); | 364 | bb_perror_msg_and_die("can't change root directory to '%s'", path); |
365 | xchdir("/"); | 365 | xchdir("/"); |
366 | } | 366 | } |
367 | 367 | ||
diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c index 9a1454430..e492b6e5a 100644 --- a/loginutils/add-remove-shell.c +++ b/loginutils/add-remove-shell.c | |||
@@ -8,8 +8,8 @@ | |||
8 | * for details. | 8 | * for details. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | //applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_BIN, BB_SUID_DROP, add_shell )) | 11 | //applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell )) |
12 | //applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_BIN, BB_SUID_DROP, remove_shell)) | 12 | //applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell)) |
13 | 13 | ||
14 | //kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o | 14 | //kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o |
15 | //kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o | 15 | //kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o |
diff --git a/loginutils/getty.c b/loginutils/getty.c index bbb5a96b4..e5d13bed6 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c | |||
@@ -548,8 +548,15 @@ int getty_main(int argc UNUSED_PARAM, char **argv) | |||
548 | * a session leader - which is quite possible for getty! | 548 | * a session leader - which is quite possible for getty! |
549 | */ | 549 | */ |
550 | pid = getpid(); | 550 | pid = getpid(); |
551 | if (getsid(0) != pid) | 551 | if (getsid(0) != pid) { |
552 | //for debugging: | ||
553 | //bb_perror_msg_and_die("setsid failed:" | ||
554 | // " pid %d ppid %d" | ||
555 | // " sid %d pgid %d", | ||
556 | // pid, getppid(), | ||
557 | // getsid(0), getpgid(0)); | ||
552 | bb_perror_msg_and_die("setsid"); | 558 | bb_perror_msg_and_die("setsid"); |
559 | } | ||
553 | /* Looks like we are already a session leader. | 560 | /* Looks like we are already a session leader. |
554 | * In this case (setsid failed) we may still have ctty, | 561 | * In this case (setsid failed) we may still have ctty, |
555 | * and it may be different from tty we need to control! | 562 | * and it may be different from tty we need to control! |
diff --git a/loginutils/login.c b/loginutils/login.c index bf43f3aba..6ec8dc42e 100644 --- a/loginutils/login.c +++ b/loginutils/login.c | |||
@@ -37,7 +37,8 @@ static const struct pam_conv conv = { | |||
37 | enum { | 37 | enum { |
38 | TIMEOUT = 60, | 38 | TIMEOUT = 60, |
39 | EMPTY_USERNAME_COUNT = 10, | 39 | EMPTY_USERNAME_COUNT = 10, |
40 | USERNAME_SIZE = 32, | 40 | /* Some users found 32 chars limit to be too low: */ |
41 | USERNAME_SIZE = 64, | ||
41 | TTYNAME_SIZE = 32, | 42 | TTYNAME_SIZE = 32, |
42 | }; | 43 | }; |
43 | 44 | ||
diff --git a/loginutils/passwd.c b/loginutils/passwd.c index b83db0083..a7006f054 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include "libbb.h" | 16 | #include "libbb.h" |
17 | #include <syslog.h> | 17 | #include <syslog.h> |
18 | #include <sys/resource.h> /* setrlimit */ | ||
18 | 19 | ||
19 | static void nuke_str(char *str) | 20 | static void nuke_str(char *str) |
20 | { | 21 | { |
diff --git a/loginutils/su.c b/loginutils/su.c index 57ea738f4..2ec05e125 100644 --- a/loginutils/su.c +++ b/loginutils/su.c | |||
@@ -131,7 +131,8 @@ int su_main(int argc UNUSED_PARAM, char **argv) | |||
131 | change_identity(pw); | 131 | change_identity(pw); |
132 | setup_environment(opt_shell, | 132 | setup_environment(opt_shell, |
133 | ((flags & SU_OPT_l) / SU_OPT_l * SETUP_ENV_CLEARENV) | 133 | ((flags & SU_OPT_l) / SU_OPT_l * SETUP_ENV_CLEARENV) |
134 | + (!(flags & SU_OPT_mp) * SETUP_ENV_CHANGEENV), | 134 | + (!(flags & SU_OPT_mp) * SETUP_ENV_CHANGEENV) |
135 | + (!(flags & SU_OPT_l) * SETUP_ENV_NO_CHDIR), | ||
135 | pw); | 136 | pw); |
136 | IF_SELINUX(set_current_security_context(NULL);) | 137 | IF_SELINUX(set_current_security_context(NULL);) |
137 | 138 | ||
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c index 988439b25..37ca66559 100644 --- a/miscutils/fbsplash.c +++ b/miscutils/fbsplash.c | |||
@@ -50,6 +50,10 @@ struct globals { | |||
50 | struct fb_var_screeninfo scr_var; | 50 | struct fb_var_screeninfo scr_var; |
51 | struct fb_fix_screeninfo scr_fix; | 51 | struct fb_fix_screeninfo scr_fix; |
52 | unsigned bytes_per_pixel; | 52 | unsigned bytes_per_pixel; |
53 | // cached (8 - scr_var.COLOR.length): | ||
54 | unsigned red_shift; | ||
55 | unsigned green_shift; | ||
56 | unsigned blue_shift; | ||
53 | }; | 57 | }; |
54 | #define G (*ptr_to_globals) | 58 | #define G (*ptr_to_globals) |
55 | #define INIT_G() do { \ | 59 | #define INIT_G() do { \ |
@@ -139,6 +143,9 @@ static void fb_open(const char *strfb_device) | |||
139 | break; | 143 | break; |
140 | } | 144 | } |
141 | 145 | ||
146 | G.red_shift = 8 - G.scr_var.red.length; | ||
147 | G.green_shift = 8 - G.scr_var.green.length; | ||
148 | G.blue_shift = 8 - G.scr_var.blue.length; | ||
142 | G.bytes_per_pixel = (G.scr_var.bits_per_pixel + 7) >> 3; | 149 | G.bytes_per_pixel = (G.scr_var.bits_per_pixel + 7) >> 3; |
143 | 150 | ||
144 | // map the device in memory | 151 | // map the device in memory |
@@ -155,10 +162,13 @@ static void fb_open(const char *strfb_device) | |||
155 | 162 | ||
156 | 163 | ||
157 | /** | 164 | /** |
158 | * Return pixel value of the passed RGB color | 165 | * Return pixel value of the passed RGB color. |
166 | * This is performance critical fn. | ||
159 | */ | 167 | */ |
160 | static unsigned fb_pixel_value(unsigned r, unsigned g, unsigned b) | 168 | static unsigned fb_pixel_value(unsigned r, unsigned g, unsigned b) |
161 | { | 169 | { |
170 | /* We assume that the r,g,b values are <= 255 */ | ||
171 | |||
162 | if (G.bytes_per_pixel == 1) { | 172 | if (G.bytes_per_pixel == 1) { |
163 | r = r & 0xe0; // 3-bit red | 173 | r = r & 0xe0; // 3-bit red |
164 | g = (g >> 3) & 0x1c; // 3-bit green | 174 | g = (g >> 3) & 0x1c; // 3-bit green |
@@ -166,10 +176,17 @@ static unsigned fb_pixel_value(unsigned r, unsigned g, unsigned b) | |||
166 | return r + g + b; | 176 | return r + g + b; |
167 | } | 177 | } |
168 | if (G.bytes_per_pixel == 2) { | 178 | if (G.bytes_per_pixel == 2) { |
169 | r = (r & 0xf8) << 8; // 5-bit red | 179 | // ARM PL110 on Integrator/CP has RGBA5551 bit arrangement. |
170 | g = (g & 0xfc) << 3; // 6-bit green | 180 | // We want to support bit locations like that. |
171 | b = b >> 3; // 5-bit blue | 181 | // |
172 | return r + g + b; | 182 | // First shift out unused bits |
183 | r = r >> G.red_shift; | ||
184 | g = g >> G.green_shift; | ||
185 | b = b >> G.blue_shift; | ||
186 | // Then shift the remaining bits to their offset | ||
187 | return (r << G.scr_var.red.offset) + | ||
188 | (g << G.scr_var.green.offset) + | ||
189 | (b << G.scr_var.blue.offset); | ||
173 | } | 190 | } |
174 | // RGB 888 | 191 | // RGB 888 |
175 | return b + (g << 8) + (r << 16); | 192 | return b + (g << 8) + (r << 16); |
diff --git a/miscutils/man.c b/miscutils/man.c index 236fdcebd..b8b15b83b 100644 --- a/miscutils/man.c +++ b/miscutils/man.c | |||
@@ -129,27 +129,21 @@ static int show_manpage(const char *pager, char *man_filename, int man, int leve | |||
129 | #endif | 129 | #endif |
130 | #if ENABLE_FEATURE_SEAMLESS_XZ | 130 | #if ENABLE_FEATURE_SEAMLESS_XZ |
131 | strcpy(ext, "xz"); | 131 | strcpy(ext, "xz"); |
132 | if (run_pipe(pager, man_filename, man, level)) | 132 | if (run_pipe(pager, filename_with_zext, man, level)) |
133 | return 1; | 133 | return 1; |
134 | #endif | 134 | #endif |
135 | #if ENABLE_FEATURE_SEAMLESS_BZ2 | 135 | #if ENABLE_FEATURE_SEAMLESS_BZ2 |
136 | strcpy(ext, "bz2"); | 136 | strcpy(ext, "bz2"); |
137 | if (run_pipe(pager, man_filename, man, level)) | 137 | if (run_pipe(pager, filename_with_zext, man, level)) |
138 | return 1; | 138 | return 1; |
139 | #endif | 139 | #endif |
140 | #if ENABLE_FEATURE_SEAMLESS_GZ | 140 | #if ENABLE_FEATURE_SEAMLESS_GZ |
141 | strcpy(ext, "gz"); | 141 | strcpy(ext, "gz"); |
142 | if (run_pipe(pager, man_filename, man, level)) | 142 | if (run_pipe(pager, filename_with_zext, man, level)) |
143 | return 1; | 143 | return 1; |
144 | #endif | 144 | #endif |
145 | 145 | ||
146 | #if SEAMLESS_COMPRESSION | 146 | return run_pipe(pager, man_filename, man, level); |
147 | ext[-1] = '\0'; | ||
148 | #endif | ||
149 | if (run_pipe(pager, man_filename, man, level)) | ||
150 | return 1; | ||
151 | |||
152 | return 0; | ||
153 | } | 147 | } |
154 | 148 | ||
155 | int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 149 | int man_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index 2ba6e3fe5..c636a5aa2 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c | |||
@@ -129,7 +129,7 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv) | |||
129 | xmove_fd(tmp_fd, IS_NANDDUMP ? STDOUT_FILENO : STDIN_FILENO); | 129 | xmove_fd(tmp_fd, IS_NANDDUMP ? STDOUT_FILENO : STDIN_FILENO); |
130 | } | 130 | } |
131 | 131 | ||
132 | fd = xopen(argv[0], O_RDWR); | 132 | fd = xopen(argv[0], IS_NANDWRITE ? O_RDWR : O_RDONLY); |
133 | xioctl(fd, MEMGETINFO, &meminfo); | 133 | xioctl(fd, MEMGETINFO, &meminfo); |
134 | 134 | ||
135 | mtdoffset = xstrtou(opt_s, 0); | 135 | mtdoffset = xstrtou(opt_s, 0); |
diff --git a/miscutils/time.c b/miscutils/time.c index 945f15f0d..ffed38632 100644 --- a/miscutils/time.c +++ b/miscutils/time.c | |||
@@ -16,6 +16,7 @@ | |||
16 | //usage: "\n -v Verbose" | 16 | //usage: "\n -v Verbose" |
17 | 17 | ||
18 | #include "libbb.h" | 18 | #include "libbb.h" |
19 | #include <sys/resource.h> /* getrusage */ | ||
19 | 20 | ||
20 | /* Information on the resources used by a child process. */ | 21 | /* Information on the resources used by a child process. */ |
21 | typedef struct { | 22 | typedef struct { |
diff --git a/modutils/modinfo.c b/modutils/modinfo.c index c0910ffed..7c978d1da 100644 --- a/modutils/modinfo.c +++ b/modutils/modinfo.c | |||
@@ -24,9 +24,9 @@ | |||
24 | 24 | ||
25 | 25 | ||
26 | enum { | 26 | enum { |
27 | OPT_TAGS = (1 << 8) - 1, | 27 | OPT_TAGS = (1 << 12) - 1, /* shortcut count */ |
28 | OPT_F = (1 << 8), /* field name */ | 28 | OPT_F = (1 << 12), /* field name */ |
29 | OPT_0 = (1 << 9), /* \0 as separator */ | 29 | OPT_0 = (1 << 13), /* \0 as separator */ |
30 | }; | 30 | }; |
31 | 31 | ||
32 | struct modinfo_env { | 32 | struct modinfo_env { |
@@ -49,13 +49,17 @@ static void modinfo(const char *path, const char *version, | |||
49 | { | 49 | { |
50 | static const char *const shortcuts[] = { | 50 | static const char *const shortcuts[] = { |
51 | "filename", | 51 | "filename", |
52 | "description", | ||
53 | "author", | ||
54 | "license", | 52 | "license", |
53 | "author", | ||
54 | "description", | ||
55 | "version", | ||
56 | "alias", | ||
57 | "srcversion", | ||
58 | "depends", | ||
59 | "uts_release", | ||
55 | "vermagic", | 60 | "vermagic", |
56 | "parm", | 61 | "parm", |
57 | "firmware", | 62 | "firmware", |
58 | "depends", | ||
59 | }; | 63 | }; |
60 | size_t len; | 64 | size_t len; |
61 | int j, length; | 65 | int j, length; |
@@ -97,8 +101,11 @@ static void modinfo(const char *path, const char *version, | |||
97 | if (ptr == NULL) /* no occurance left, done */ | 101 | if (ptr == NULL) /* no occurance left, done */ |
98 | break; | 102 | break; |
99 | if (strncmp(ptr, pattern, length) == 0 && ptr[length] == '=') { | 103 | if (strncmp(ptr, pattern, length) == 0 && ptr[length] == '=') { |
100 | ptr += length + 1; | 104 | /* field prefixes are 0x80 or 0x00 */ |
101 | ptr += display(ptr, pattern, (1<<j) != tags); | 105 | if ((ptr[-1] & 0x7F) == '\0') { |
106 | ptr += length + 1; | ||
107 | ptr += display(ptr, pattern, (1<<j) != tags); | ||
108 | } | ||
102 | } | 109 | } |
103 | ++ptr; | 110 | ++ptr; |
104 | } | 111 | } |
@@ -131,7 +138,7 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv) | |||
131 | 138 | ||
132 | env.field = NULL; | 139 | env.field = NULL; |
133 | opt_complementary = "-1"; /* minimum one param */ | 140 | opt_complementary = "-1"; /* minimum one param */ |
134 | opts = getopt32(argv, "fdalvpF:0", &env.field); | 141 | opts = getopt32(argv, "nladvAsDumpF:0", &env.field); |
135 | env.tags = opts & OPT_TAGS ? opts & OPT_TAGS : OPT_TAGS; | 142 | env.tags = opts & OPT_TAGS ? opts & OPT_TAGS : OPT_TAGS; |
136 | argv += optind; | 143 | argv += optind; |
137 | 144 | ||
diff --git a/networking/Config.src b/networking/Config.src index fb7dca7d4..e2376d548 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -945,8 +945,8 @@ config WGET | |||
945 | bool "wget" | 945 | bool "wget" |
946 | default y | 946 | default y |
947 | help | 947 | help |
948 | wget is a utility for non-interactive download of files from HTTP, | 948 | wget is a utility for non-interactive download of files from HTTP |
949 | HTTPS, and FTP servers. | 949 | and FTP servers. |
950 | 950 | ||
951 | config FEATURE_WGET_STATUSBAR | 951 | config FEATURE_WGET_STATUSBAR |
952 | bool "Enable a nifty process meter (+2k)" | 952 | bool "Enable a nifty process meter (+2k)" |
diff --git a/networking/brctl.c b/networking/brctl.c index 19f474fce..7289e641f 100644 --- a/networking/brctl.c +++ b/networking/brctl.c | |||
@@ -67,7 +67,7 @@ | |||
67 | # include <linux/if_bridge.h> | 67 | # include <linux/if_bridge.h> |
68 | 68 | ||
69 | /* FIXME: These 4 funcs are not really clean and could be improved */ | 69 | /* FIXME: These 4 funcs are not really clean and could be improved */ |
70 | static ALWAYS_INLINE void strtotimeval(struct timeval *tv, | 70 | static ALWAYS_INLINE void bb_strtotimeval(struct timeval *tv, |
71 | const char *time_str) | 71 | const char *time_str) |
72 | { | 72 | { |
73 | double secs; | 73 | double secs; |
@@ -104,7 +104,7 @@ static void jiffies_to_tv(struct timeval *tv, unsigned long jiffies) | |||
104 | static unsigned long str_to_jiffies(const char *time_str) | 104 | static unsigned long str_to_jiffies(const char *time_str) |
105 | { | 105 | { |
106 | struct timeval tv; | 106 | struct timeval tv; |
107 | strtotimeval(&tv, time_str); | 107 | bb_strtotimeval(&tv, time_str); |
108 | return tv_to_jiffies(&tv); | 108 | return tv_to_jiffies(&tv); |
109 | } | 109 | } |
110 | 110 | ||
diff --git a/networking/ftpd.c b/networking/ftpd.c index 1c97df564..33db964fa 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c | |||
@@ -821,7 +821,7 @@ handle_size_or_mdtm(int need_size) | |||
821 | gmtime_r(&statbuf.st_mtime, &broken_out); | 821 | gmtime_r(&statbuf.st_mtime, &broken_out); |
822 | sprintf(buf, STR(FTP_STATFILE_OK)" %04u%02u%02u%02u%02u%02u\r\n", | 822 | sprintf(buf, STR(FTP_STATFILE_OK)" %04u%02u%02u%02u%02u%02u\r\n", |
823 | broken_out.tm_year + 1900, | 823 | broken_out.tm_year + 1900, |
824 | broken_out.tm_mon, | 824 | broken_out.tm_mon + 1, |
825 | broken_out.tm_mday, | 825 | broken_out.tm_mday, |
826 | broken_out.tm_hour, | 826 | broken_out.tm_hour, |
827 | broken_out.tm_min, | 827 | broken_out.tm_min, |
@@ -927,6 +927,7 @@ handle_upload_common(int is_append, int is_unique) | |||
927 | || fstat(local_file_fd, &statbuf) != 0 | 927 | || fstat(local_file_fd, &statbuf) != 0 |
928 | || !S_ISREG(statbuf.st_mode) | 928 | || !S_ISREG(statbuf.st_mode) |
929 | ) { | 929 | ) { |
930 | free(tempname); | ||
930 | WRITE_ERR(FTP_UPLOADFAIL); | 931 | WRITE_ERR(FTP_UPLOADFAIL); |
931 | if (local_file_fd >= 0) | 932 | if (local_file_fd >= 0) |
932 | goto close_local_and_bail; | 933 | goto close_local_and_bail; |
diff --git a/networking/httpd.c b/networking/httpd.c index 12218a0a3..a942794f5 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -1414,7 +1414,7 @@ static void send_cgi_and_exit( | |||
1414 | if (script != url) { /* paranoia */ | 1414 | if (script != url) { /* paranoia */ |
1415 | *script = '\0'; | 1415 | *script = '\0'; |
1416 | if (chdir(url + 1) != 0) { | 1416 | if (chdir(url + 1) != 0) { |
1417 | bb_perror_msg("chdir(%s)", url + 1); | 1417 | bb_perror_msg("can't change directory to '%s'", url + 1); |
1418 | goto error_execing_cgi; | 1418 | goto error_execing_cgi; |
1419 | } | 1419 | } |
1420 | // not needed: *script = '/'; | 1420 | // not needed: *script = '/'; |
diff --git a/networking/httpd_indexcgi.c b/networking/httpd_indexcgi.c index d732cd4f8..562cd7fbe 100644 --- a/networking/httpd_indexcgi.c +++ b/networking/httpd_indexcgi.c | |||
@@ -35,6 +35,7 @@ httpd_indexcgi.c -o index.cgi | |||
35 | * 2576 4 2048 4628 1214 index.cgi.o | 35 | * 2576 4 2048 4628 1214 index.cgi.o |
36 | */ | 36 | */ |
37 | 37 | ||
38 | #define _GNU_SOURCE 1 /* for strchrnul */ | ||
38 | #include <sys/types.h> | 39 | #include <sys/types.h> |
39 | #include <sys/stat.h> | 40 | #include <sys/stat.h> |
40 | #include <errno.h> | 41 | #include <errno.h> |
diff --git a/networking/ifplugd.c b/networking/ifplugd.c index d8358cdfd..88bf448fa 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c | |||
@@ -22,9 +22,9 @@ | |||
22 | //usage: "\n -r PROG Script to run" | 22 | //usage: "\n -r PROG Script to run" |
23 | //usage: "\n -x ARG Extra argument for script" | 23 | //usage: "\n -x ARG Extra argument for script" |
24 | //usage: "\n -I Don't exit on nonzero exit code from script" | 24 | //usage: "\n -I Don't exit on nonzero exit code from script" |
25 | //usage: "\n -p Don't run script on daemon startup" | 25 | //usage: "\n -p Don't run \"up\" script on startup" |
26 | //usage: "\n -q Don't run script on daemon quit" | 26 | //usage: "\n -q Don't run \"down\" script on exit" |
27 | //usage: "\n -l Run script on startup even if no cable is detected" | 27 | //usage: "\n -l Always run script on startup" |
28 | //usage: "\n -t SECS Poll time in seconds" | 28 | //usage: "\n -t SECS Poll time in seconds" |
29 | //usage: "\n -u SECS Delay before running script after link up" | 29 | //usage: "\n -u SECS Delay before running script after link up" |
30 | //usage: "\n -d SECS Delay after link down" | 30 | //usage: "\n -d SECS Delay after link down" |
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 9b3498696..ad0a9971b 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -1058,7 +1058,7 @@ static int iface_up(struct interface_defn_t *iface) | |||
1058 | 1058 | ||
1059 | static int iface_down(struct interface_defn_t *iface) | 1059 | static int iface_down(struct interface_defn_t *iface) |
1060 | { | 1060 | { |
1061 | if (!iface->method->down(iface,check)) return -1; | 1061 | if (!iface->method->down(iface, check)) return -1; |
1062 | set_environ(iface, "stop", "pre-down"); | 1062 | set_environ(iface, "stop", "pre-down"); |
1063 | if (!execute_all(iface, "down")) return 0; | 1063 | if (!execute_all(iface, "down")) return 0; |
1064 | if (!iface->method->down(iface, doit)) return 0; | 1064 | if (!iface->method->down(iface, doit)) return 0; |
diff --git a/networking/inetd.c b/networking/inetd.c index 26b66992d..00baf6971 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
@@ -165,6 +165,8 @@ | |||
165 | //usage: "\n (default: 0 - disabled)" | 165 | //usage: "\n (default: 0 - disabled)" |
166 | 166 | ||
167 | #include <syslog.h> | 167 | #include <syslog.h> |
168 | #include <sys/resource.h> /* setrlimit */ | ||
169 | #include <sys/socket.h> /* un.h may need this */ | ||
168 | #include <sys/un.h> | 170 | #include <sys/un.h> |
169 | 171 | ||
170 | #include "libbb.h" | 172 | #include "libbb.h" |
diff --git a/networking/libiproute/ll_proto.c b/networking/libiproute/ll_proto.c index 7aac8364d..da2b53cbf 100644 --- a/networking/libiproute/ll_proto.c +++ b/networking/libiproute/ll_proto.c | |||
@@ -14,19 +14,10 @@ | |||
14 | 14 | ||
15 | #include <netinet/if_ether.h> | 15 | #include <netinet/if_ether.h> |
16 | 16 | ||
17 | #if !ENABLE_WERROR | 17 | /* Please conditionalize exotic protocols on CONFIG_something */ |
18 | #warning de-bloat | ||
19 | #endif | ||
20 | /* Before re-enabling this, please (1) conditionalize exotic protocols | ||
21 | * on CONFIG_something, and (2) decouple strings and numbers | ||
22 | * (use llproto_ids[] = n,n,n..; and llproto_names[] = "loop\0" "pup\0" ...;) | ||
23 | */ | ||
24 | 18 | ||
25 | #define __PF(f,n) { ETH_P_##f, #n }, | 19 | static const uint16_t llproto_ids[] = { |
26 | static struct { | 20 | #define __PF(f,n) ETH_P_##f, |
27 | int id; | ||
28 | const char *name; | ||
29 | } llproto_names[] = { | ||
30 | __PF(LOOP,loop) | 21 | __PF(LOOP,loop) |
31 | __PF(PUP,pup) | 22 | __PF(PUP,pup) |
32 | #ifdef ETH_P_PUPAT | 23 | #ifdef ETH_P_PUPAT |
@@ -86,33 +77,104 @@ __PF(IRDA,irda) | |||
86 | __PF(ECONET,econet) | 77 | __PF(ECONET,econet) |
87 | #endif | 78 | #endif |
88 | 79 | ||
89 | { 0x8100, "802.1Q" }, | 80 | 0x8100, |
90 | { ETH_P_IP, "ipv4" }, | 81 | ETH_P_IP |
91 | }; | 82 | }; |
92 | #undef __PF | 83 | #undef __PF |
93 | 84 | ||
85 | /* Keep declarations above and below in sync! */ | ||
86 | |||
87 | static const char llproto_names[] = | ||
88 | #define __PF(f,n) #n "\0" | ||
89 | __PF(LOOP,loop) | ||
90 | __PF(PUP,pup) | ||
91 | #ifdef ETH_P_PUPAT | ||
92 | __PF(PUPAT,pupat) | ||
93 | #endif | ||
94 | __PF(IP,ip) | ||
95 | __PF(X25,x25) | ||
96 | __PF(ARP,arp) | ||
97 | __PF(BPQ,bpq) | ||
98 | #ifdef ETH_P_IEEEPUP | ||
99 | __PF(IEEEPUP,ieeepup) | ||
100 | #endif | ||
101 | #ifdef ETH_P_IEEEPUPAT | ||
102 | __PF(IEEEPUPAT,ieeepupat) | ||
103 | #endif | ||
104 | __PF(DEC,dec) | ||
105 | __PF(DNA_DL,dna_dl) | ||
106 | __PF(DNA_RC,dna_rc) | ||
107 | __PF(DNA_RT,dna_rt) | ||
108 | __PF(LAT,lat) | ||
109 | __PF(DIAG,diag) | ||
110 | __PF(CUST,cust) | ||
111 | __PF(SCA,sca) | ||
112 | __PF(RARP,rarp) | ||
113 | __PF(ATALK,atalk) | ||
114 | __PF(AARP,aarp) | ||
115 | __PF(IPX,ipx) | ||
116 | __PF(IPV6,ipv6) | ||
117 | #ifdef ETH_P_PPP_DISC | ||
118 | __PF(PPP_DISC,ppp_disc) | ||
119 | #endif | ||
120 | #ifdef ETH_P_PPP_SES | ||
121 | __PF(PPP_SES,ppp_ses) | ||
122 | #endif | ||
123 | #ifdef ETH_P_ATMMPOA | ||
124 | __PF(ATMMPOA,atmmpoa) | ||
125 | #endif | ||
126 | #ifdef ETH_P_ATMFATE | ||
127 | __PF(ATMFATE,atmfate) | ||
128 | #endif | ||
129 | |||
130 | __PF(802_3,802_3) | ||
131 | __PF(AX25,ax25) | ||
132 | __PF(ALL,all) | ||
133 | __PF(802_2,802_2) | ||
134 | __PF(SNAP,snap) | ||
135 | __PF(DDCMP,ddcmp) | ||
136 | __PF(WAN_PPP,wan_ppp) | ||
137 | __PF(PPP_MP,ppp_mp) | ||
138 | __PF(LOCALTALK,localtalk) | ||
139 | __PF(PPPTALK,ppptalk) | ||
140 | __PF(TR_802_2,tr_802_2) | ||
141 | __PF(MOBITEX,mobitex) | ||
142 | __PF(CONTROL,control) | ||
143 | __PF(IRDA,irda) | ||
144 | #ifdef ETH_P_ECONET | ||
145 | __PF(ECONET,econet) | ||
146 | #endif | ||
147 | |||
148 | "802.1Q" "\0" | ||
149 | "ipv4" "\0" | ||
150 | ; | ||
151 | #undef __PF | ||
152 | |||
94 | 153 | ||
95 | const char* FAST_FUNC ll_proto_n2a(unsigned short id, char *buf, int len) | 154 | const char* FAST_FUNC ll_proto_n2a(unsigned short id, char *buf, int len) |
96 | { | 155 | { |
97 | unsigned i; | 156 | unsigned i; |
98 | id = ntohs(id); | 157 | id = ntohs(id); |
99 | for (i = 0; i < ARRAY_SIZE(llproto_names); i++) { | 158 | for (i = 0; i < ARRAY_SIZE(llproto_ids); i++) { |
100 | if (llproto_names[i].id == id) | 159 | if (llproto_ids[i] == id) |
101 | return llproto_names[i].name; | 160 | return nth_string(llproto_names, i); |
102 | } | 161 | } |
103 | snprintf(buf, len, "[%d]", id); | 162 | snprintf(buf, len, "[%u]", id); |
104 | return buf; | 163 | return buf; |
105 | } | 164 | } |
106 | 165 | ||
107 | int FAST_FUNC ll_proto_a2n(unsigned short *id, char *buf) | 166 | int FAST_FUNC ll_proto_a2n(unsigned short *id, char *buf) |
108 | { | 167 | { |
109 | unsigned i; | 168 | unsigned i; |
110 | for (i = 0; i < ARRAY_SIZE(llproto_names); i++) { | 169 | const char *name = llproto_names; |
111 | if (strcasecmp(llproto_names[i].name, buf) == 0) { | 170 | for (i = 0; i < ARRAY_SIZE(llproto_ids); i++) { |
112 | i = llproto_names[i].id; | 171 | if (strcasecmp(name, buf) == 0) { |
113 | goto good; | 172 | i = llproto_ids[i]; |
114 | } | 173 | goto good; |
174 | } | ||
175 | name += strlen(name) + 1; | ||
115 | } | 176 | } |
177 | errno = 0; | ||
116 | i = bb_strtou(buf, NULL, 0); | 178 | i = bb_strtou(buf, NULL, 0); |
117 | if (errno || i > 0xffff) | 179 | if (errno || i > 0xffff) |
118 | return -1; | 180 | return -1; |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 603801ec6..5b92db6f6 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "libbb.h" | 46 | #include "libbb.h" |
47 | #include <math.h> | 47 | #include <math.h> |
48 | #include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */ | 48 | #include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */ |
49 | #include <sys/resource.h> /* setpriority */ | ||
49 | #include <sys/timex.h> | 50 | #include <sys/timex.h> |
50 | #ifndef IPTOS_LOWDELAY | 51 | #ifndef IPTOS_LOWDELAY |
51 | # define IPTOS_LOWDELAY 0x10 | 52 | # define IPTOS_LOWDELAY 0x10 |
@@ -220,14 +221,14 @@ typedef struct { | |||
220 | typedef struct { | 221 | typedef struct { |
221 | len_and_sockaddr *p_lsa; | 222 | len_and_sockaddr *p_lsa; |
222 | char *p_dotted; | 223 | char *p_dotted; |
223 | /* when to send new query (if p_fd == -1) | ||
224 | * or when receive times out (if p_fd >= 0): */ | ||
225 | int p_fd; | 224 | int p_fd; |
226 | int datapoint_idx; | 225 | int datapoint_idx; |
227 | uint32_t lastpkt_refid; | 226 | uint32_t lastpkt_refid; |
228 | uint8_t lastpkt_status; | 227 | uint8_t lastpkt_status; |
229 | uint8_t lastpkt_stratum; | 228 | uint8_t lastpkt_stratum; |
230 | uint8_t reachable_bits; | 229 | uint8_t reachable_bits; |
230 | /* when to send new query (if p_fd == -1) | ||
231 | * or when receive times out (if p_fd >= 0): */ | ||
231 | double next_action_time; | 232 | double next_action_time; |
232 | double p_xmttime; | 233 | double p_xmttime; |
233 | double lastpkt_recv_time; | 234 | double lastpkt_recv_time; |
@@ -895,6 +896,11 @@ step_time(double offset) | |||
895 | 896 | ||
896 | /* Correct various fields which contain time-relative values: */ | 897 | /* Correct various fields which contain time-relative values: */ |
897 | 898 | ||
899 | /* Globals: */ | ||
900 | G.cur_time += offset; | ||
901 | G.last_update_recv_time += offset; | ||
902 | G.last_script_run += offset; | ||
903 | |||
898 | /* p->lastpkt_recv_time, p->next_action_time and such: */ | 904 | /* p->lastpkt_recv_time, p->next_action_time and such: */ |
899 | for (item = G.ntp_peers; item != NULL; item = item->link) { | 905 | for (item = G.ntp_peers; item != NULL; item = item->link) { |
900 | peer_t *pp = (peer_t *) item->data; | 906 | peer_t *pp = (peer_t *) item->data; |
@@ -902,11 +908,16 @@ step_time(double offset) | |||
902 | //bb_error_msg("offset:%+f pp->next_action_time:%f -> %f", | 908 | //bb_error_msg("offset:%+f pp->next_action_time:%f -> %f", |
903 | // offset, pp->next_action_time, pp->next_action_time + offset); | 909 | // offset, pp->next_action_time, pp->next_action_time + offset); |
904 | pp->next_action_time += offset; | 910 | pp->next_action_time += offset; |
911 | if (pp->p_fd >= 0) { | ||
912 | /* We wait for reply from this peer too. | ||
913 | * But due to step we are doing, reply's data is no longer | ||
914 | * useful (in fact, it'll be bogus). Stop waiting for it. | ||
915 | */ | ||
916 | close(pp->p_fd); | ||
917 | pp->p_fd = -1; | ||
918 | set_next(pp, RETRY_INTERVAL); | ||
919 | } | ||
905 | } | 920 | } |
906 | /* Globals: */ | ||
907 | G.cur_time += offset; | ||
908 | G.last_update_recv_time += offset; | ||
909 | G.last_script_run += offset; | ||
910 | } | 921 | } |
911 | 922 | ||
912 | 923 | ||
@@ -1623,22 +1634,30 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1623 | ) { | 1634 | ) { |
1624 | //TODO: always do this? | 1635 | //TODO: always do this? |
1625 | interval = retry_interval(); | 1636 | interval = retry_interval(); |
1626 | goto set_next_and_close_sock; | 1637 | goto set_next_and_ret; |
1627 | } | 1638 | } |
1628 | xfunc_die(); | 1639 | xfunc_die(); |
1629 | } | 1640 | } |
1630 | 1641 | ||
1631 | if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { | 1642 | if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { |
1632 | bb_error_msg("malformed packet received from %s", p->p_dotted); | 1643 | bb_error_msg("malformed packet received from %s", p->p_dotted); |
1633 | goto bail; | 1644 | return; |
1634 | } | 1645 | } |
1635 | 1646 | ||
1636 | if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl | 1647 | if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl |
1637 | || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl | 1648 | || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl |
1638 | ) { | 1649 | ) { |
1639 | goto bail; | 1650 | /* Somebody else's packet */ |
1651 | return; | ||
1640 | } | 1652 | } |
1641 | 1653 | ||
1654 | /* We do not expect any more packets from this peer for now. | ||
1655 | * Closing the socket informs kernel about it. | ||
1656 | * We open a new socket when we send a new query. | ||
1657 | */ | ||
1658 | close(p->p_fd); | ||
1659 | p->p_fd = -1; | ||
1660 | |||
1642 | if ((msg.m_status & LI_ALARM) == LI_ALARM | 1661 | if ((msg.m_status & LI_ALARM) == LI_ALARM |
1643 | || msg.m_stratum == 0 | 1662 | || msg.m_stratum == 0 |
1644 | || msg.m_stratum > NTP_MAXSTRATUM | 1663 | || msg.m_stratum > NTP_MAXSTRATUM |
@@ -1647,8 +1666,8 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1647 | // "DENY", "RSTR" - peer does not like us at all | 1666 | // "DENY", "RSTR" - peer does not like us at all |
1648 | // "RATE" - peer is overloaded, reduce polling freq | 1667 | // "RATE" - peer is overloaded, reduce polling freq |
1649 | interval = poll_interval(0); | 1668 | interval = poll_interval(0); |
1650 | bb_error_msg("reply from %s: not synced, next query in %us", p->p_dotted, interval); | 1669 | bb_error_msg("reply from %s: peer is unsynced, next query in %us", p->p_dotted, interval); |
1651 | goto set_next_and_close_sock; | 1670 | goto set_next_and_ret; |
1652 | } | 1671 | } |
1653 | 1672 | ||
1654 | // /* Verify valid root distance */ | 1673 | // /* Verify valid root distance */ |
@@ -1794,16 +1813,8 @@ recv_and_process_peer_pkt(peer_t *p) | |||
1794 | /* Decide when to send new query for this peer */ | 1813 | /* Decide when to send new query for this peer */ |
1795 | interval = poll_interval(0); | 1814 | interval = poll_interval(0); |
1796 | 1815 | ||
1797 | set_next_and_close_sock: | 1816 | set_next_and_ret: |
1798 | set_next(p, interval); | 1817 | set_next(p, interval); |
1799 | /* We do not expect any more packets from this peer for now. | ||
1800 | * Closing the socket informs kernel about it. | ||
1801 | * We open a new socket when we send a new query. | ||
1802 | */ | ||
1803 | close(p->p_fd); | ||
1804 | p->p_fd = -1; | ||
1805 | bail: | ||
1806 | return; | ||
1807 | } | 1818 | } |
1808 | 1819 | ||
1809 | #if ENABLE_FEATURE_NTPD_SERVER | 1820 | #if ENABLE_FEATURE_NTPD_SERVER |
diff --git a/networking/ntpd_simple.c b/networking/ntpd_simple.c index 4ad44e4f3..1b7c66b84 100644 --- a/networking/ntpd_simple.c +++ b/networking/ntpd_simple.c | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | #include "libbb.h" | 8 | #include "libbb.h" |
9 | #include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */ | 9 | #include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */ |
10 | #include <sys/resource.h> /* setpriority */ | ||
10 | #ifndef IPTOS_LOWDELAY | 11 | #ifndef IPTOS_LOWDELAY |
11 | # define IPTOS_LOWDELAY 0x10 | 12 | # define IPTOS_LOWDELAY 0x10 |
12 | #endif | 13 | #endif |
diff --git a/networking/tftp.c b/networking/tftp.c index ce48a1edd..630fdaf9a 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
@@ -116,7 +116,7 @@ enum { | |||
116 | struct globals { | 116 | struct globals { |
117 | /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */ | 117 | /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */ |
118 | uint8_t error_pkt[4 + 32]; | 118 | uint8_t error_pkt[4 + 32]; |
119 | char *user_opt; | 119 | struct passwd *pw; |
120 | /* used in tftpd_main(), a bit big for stack: */ | 120 | /* used in tftpd_main(), a bit big for stack: */ |
121 | char block_buf[TFTP_BLKSIZE_DEFAULT]; | 121 | char block_buf[TFTP_BLKSIZE_DEFAULT]; |
122 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR | 122 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR |
@@ -130,13 +130,10 @@ struct globals { | |||
130 | struct BUG_G_too_big { | 130 | struct BUG_G_too_big { |
131 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; | 131 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; |
132 | }; | 132 | }; |
133 | #define block_buf (G.block_buf ) | ||
134 | #define user_opt (G.user_opt ) | ||
135 | #define error_pkt (G.error_pkt ) | ||
136 | #define INIT_G() do { } while (0) | 133 | #define INIT_G() do { } while (0) |
137 | 134 | ||
138 | #define error_pkt_reason (error_pkt[3]) | 135 | #define G_error_pkt_reason (G.error_pkt[3]) |
139 | #define error_pkt_str (error_pkt + 4) | 136 | #define G_error_pkt_str ((char*)(G.error_pkt + 4)) |
140 | 137 | ||
141 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR | 138 | #if ENABLE_FEATURE_TFTP_PROGRESS_BAR |
142 | static void tftp_progress_update(void) | 139 | static void tftp_progress_update(void) |
@@ -272,12 +269,11 @@ static int tftp_protocol( | |||
272 | xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len); | 269 | xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len); |
273 | 270 | ||
274 | /* Is there an error already? Send pkt and bail out */ | 271 | /* Is there an error already? Send pkt and bail out */ |
275 | if (error_pkt_reason || error_pkt_str[0]) | 272 | if (G_error_pkt_reason || G_error_pkt_str[0]) |
276 | goto send_err_pkt; | 273 | goto send_err_pkt; |
277 | 274 | ||
278 | if (user_opt) { | 275 | if (G.pw) { |
279 | struct passwd *pw = xgetpwnam(user_opt); | 276 | change_identity(G.pw); /* initgroups, setgid, setuid */ |
280 | change_identity(pw); /* initgroups, setgid, setuid */ | ||
281 | } | 277 | } |
282 | } | 278 | } |
283 | 279 | ||
@@ -329,8 +325,8 @@ static int tftp_protocol( | |||
329 | /* Open file (must be after changing user) */ | 325 | /* Open file (must be after changing user) */ |
330 | local_fd = open(local_file, open_mode, 0666); | 326 | local_fd = open(local_file, open_mode, 0666); |
331 | if (local_fd < 0) { | 327 | if (local_fd < 0) { |
332 | error_pkt_reason = ERR_NOFILE; | 328 | G_error_pkt_reason = ERR_NOFILE; |
333 | strcpy((char*)error_pkt_str, "can't open file"); | 329 | strcpy(G_error_pkt_str, "can't open file"); |
334 | goto send_err_pkt; | 330 | goto send_err_pkt; |
335 | } | 331 | } |
336 | /* gcc 4.3.1 would NOT optimize it out as it should! */ | 332 | /* gcc 4.3.1 would NOT optimize it out as it should! */ |
@@ -575,7 +571,7 @@ static int tftp_protocol( | |||
575 | if (res) { | 571 | if (res) { |
576 | blksize = tftp_blksize_check(res, blksize); | 572 | blksize = tftp_blksize_check(res, blksize); |
577 | if (blksize < 0) { | 573 | if (blksize < 0) { |
578 | error_pkt_reason = ERR_BAD_OPT; | 574 | G_error_pkt_reason = ERR_BAD_OPT; |
579 | goto send_err_pkt; | 575 | goto send_err_pkt; |
580 | } | 576 | } |
581 | io_bufsize = blksize + 4; | 577 | io_bufsize = blksize + 4; |
@@ -614,8 +610,8 @@ static int tftp_protocol( | |||
614 | if (recv_blk == block_nr) { | 610 | if (recv_blk == block_nr) { |
615 | int sz = full_write(local_fd, &rbuf[4], len - 4); | 611 | int sz = full_write(local_fd, &rbuf[4], len - 4); |
616 | if (sz != len - 4) { | 612 | if (sz != len - 4) { |
617 | strcpy((char*)error_pkt_str, bb_msg_write_error); | 613 | strcpy(G_error_pkt_str, bb_msg_write_error); |
618 | error_pkt_reason = ERR_WRITE; | 614 | G_error_pkt_reason = ERR_WRITE; |
619 | goto send_err_pkt; | 615 | goto send_err_pkt; |
620 | } | 616 | } |
621 | if (sz != blksize) { | 617 | if (sz != blksize) { |
@@ -664,12 +660,12 @@ static int tftp_protocol( | |||
664 | return finished == 0; /* returns 1 on failure */ | 660 | return finished == 0; /* returns 1 on failure */ |
665 | 661 | ||
666 | send_read_err_pkt: | 662 | send_read_err_pkt: |
667 | strcpy((char*)error_pkt_str, bb_msg_read_error); | 663 | strcpy(G_error_pkt_str, bb_msg_read_error); |
668 | send_err_pkt: | 664 | send_err_pkt: |
669 | if (error_pkt_str[0]) | 665 | if (G_error_pkt_str[0]) |
670 | bb_error_msg("%s", (char*)error_pkt_str); | 666 | bb_error_msg("%s", G_error_pkt_str); |
671 | error_pkt[1] = TFTP_ERROR; | 667 | G.error_pkt[1] = TFTP_ERROR; |
672 | xsendto(socket_fd, error_pkt, 4 + 1 + strlen((char*)error_pkt_str), | 668 | xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str), |
673 | &peer_lsa->u.sa, peer_lsa->len); | 669 | &peer_lsa->u.sa, peer_lsa->len); |
674 | return EXIT_FAILURE; | 670 | return EXIT_FAILURE; |
675 | #undef remote_file | 671 | #undef remote_file |
@@ -761,7 +757,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
761 | { | 757 | { |
762 | len_and_sockaddr *our_lsa; | 758 | len_and_sockaddr *our_lsa; |
763 | len_and_sockaddr *peer_lsa; | 759 | len_and_sockaddr *peer_lsa; |
764 | char *local_file, *mode; | 760 | char *local_file, *mode, *user_opt; |
765 | const char *error_msg; | 761 | const char *error_msg; |
766 | int opt, result, opcode; | 762 | int opt, result, opcode; |
767 | IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;) | 763 | IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;) |
@@ -789,18 +785,22 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
789 | openlog(applet_name, LOG_PID, LOG_DAEMON); | 785 | openlog(applet_name, LOG_PID, LOG_DAEMON); |
790 | logmode = LOGMODE_SYSLOG; | 786 | logmode = LOGMODE_SYSLOG; |
791 | } | 787 | } |
788 | if (opt & TFTPD_OPT_u) { | ||
789 | /* Must be before xchroot */ | ||
790 | G.pw = xgetpwnam(user_opt); | ||
791 | } | ||
792 | if (argv[0]) { | 792 | if (argv[0]) { |
793 | xchroot(argv[0]); | 793 | xchroot(argv[0]); |
794 | } | 794 | } |
795 | 795 | ||
796 | result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf), | 796 | result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf), |
797 | 0 /* flags */, | 797 | 0 /* flags */, |
798 | &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len); | 798 | &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len); |
799 | 799 | ||
800 | error_msg = "malformed packet"; | 800 | error_msg = "malformed packet"; |
801 | opcode = ntohs(*(uint16_t*)block_buf); | 801 | opcode = ntohs(*(uint16_t*)G.block_buf); |
802 | if (result < 4 || result >= sizeof(block_buf) | 802 | if (result < 4 || result >= sizeof(G.block_buf) |
803 | || block_buf[result-1] != '\0' | 803 | || G.block_buf[result-1] != '\0' |
804 | || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */ | 804 | || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */ |
805 | IF_GETPUT(&&) | 805 | IF_GETPUT(&&) |
806 | IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */ | 806 | IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */ |
@@ -808,27 +808,27 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
808 | ) { | 808 | ) { |
809 | goto err; | 809 | goto err; |
810 | } | 810 | } |
811 | local_file = block_buf + 2; | 811 | local_file = G.block_buf + 2; |
812 | if (local_file[0] == '.' || strstr(local_file, "/.")) { | 812 | if (local_file[0] == '.' || strstr(local_file, "/.")) { |
813 | error_msg = "dot in file name"; | 813 | error_msg = "dot in file name"; |
814 | goto err; | 814 | goto err; |
815 | } | 815 | } |
816 | mode = local_file + strlen(local_file) + 1; | 816 | mode = local_file + strlen(local_file) + 1; |
817 | /* RFC 1350 says mode string is case independent */ | 817 | /* RFC 1350 says mode string is case independent */ |
818 | if (mode >= block_buf + result || strcasecmp(mode, "octet") != 0) { | 818 | if (mode >= G.block_buf + result || strcasecmp(mode, "octet") != 0) { |
819 | goto err; | 819 | goto err; |
820 | } | 820 | } |
821 | # if ENABLE_FEATURE_TFTP_BLOCKSIZE | 821 | # if ENABLE_FEATURE_TFTP_BLOCKSIZE |
822 | { | 822 | { |
823 | char *res; | 823 | char *res; |
824 | char *opt_str = mode + sizeof("octet"); | 824 | char *opt_str = mode + sizeof("octet"); |
825 | int opt_len = block_buf + result - opt_str; | 825 | int opt_len = G.block_buf + result - opt_str; |
826 | if (opt_len > 0) { | 826 | if (opt_len > 0) { |
827 | res = tftp_get_option("blksize", opt_str, opt_len); | 827 | res = tftp_get_option("blksize", opt_str, opt_len); |
828 | if (res) { | 828 | if (res) { |
829 | blksize = tftp_blksize_check(res, 65564); | 829 | blksize = tftp_blksize_check(res, 65564); |
830 | if (blksize < 0) { | 830 | if (blksize < 0) { |
831 | error_pkt_reason = ERR_BAD_OPT; | 831 | G_error_pkt_reason = ERR_BAD_OPT; |
832 | /* will just send error pkt */ | 832 | /* will just send error pkt */ |
833 | goto do_proto; | 833 | goto do_proto; |
834 | } | 834 | } |
@@ -846,7 +846,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
846 | if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) { | 846 | if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) { |
847 | if (opt & TFTPD_OPT_r) { | 847 | if (opt & TFTPD_OPT_r) { |
848 | /* This would mean "disk full" - not true */ | 848 | /* This would mean "disk full" - not true */ |
849 | /*error_pkt_reason = ERR_WRITE;*/ | 849 | /*G_error_pkt_reason = ERR_WRITE;*/ |
850 | error_msg = bb_msg_write_error; | 850 | error_msg = bb_msg_write_error; |
851 | goto err; | 851 | goto err; |
852 | } | 852 | } |
@@ -855,7 +855,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
855 | IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */ | 855 | IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */ |
856 | } | 856 | } |
857 | 857 | ||
858 | /* NB: if error_pkt_str or error_pkt_reason is set up, | 858 | /* NB: if G_error_pkt_str or G_error_pkt_reason is set up, |
859 | * tftp_protocol() just sends one error pkt and returns */ | 859 | * tftp_protocol() just sends one error pkt and returns */ |
860 | 860 | ||
861 | do_proto: | 861 | do_proto: |
@@ -870,7 +870,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) | |||
870 | 870 | ||
871 | return result; | 871 | return result; |
872 | err: | 872 | err: |
873 | strcpy((char*)error_pkt_str, error_msg); | 873 | strcpy(G_error_pkt_str, error_msg); |
874 | goto do_proto; | 874 | goto do_proto; |
875 | } | 875 | } |
876 | 876 | ||
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index cfd58679a..0e8e45fd2 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 15 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
16 | 16 | ||
17 | extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */ | 17 | extern const uint8_t MAC_BCAST_ADDR[6] ALIGN2; /* six all-ones */ |
18 | 18 | ||
19 | 19 | ||
20 | /*** DHCP packet ***/ | 20 | /*** DHCP packet ***/ |
@@ -187,8 +187,8 @@ struct option_set { | |||
187 | }; | 187 | }; |
188 | 188 | ||
189 | extern const struct dhcp_optflag dhcp_optflags[]; | 189 | extern const struct dhcp_optflag dhcp_optflags[]; |
190 | extern const char dhcp_option_strings[]; | 190 | extern const char dhcp_option_strings[] ALIGN1; |
191 | extern const uint8_t dhcp_option_lengths[]; | 191 | extern const uint8_t dhcp_option_lengths[] ALIGN1; |
192 | 192 | ||
193 | unsigned FAST_FUNC udhcp_option_idx(const char *name); | 193 | unsigned FAST_FUNC udhcp_option_idx(const char *name); |
194 | 194 | ||
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 7c9f52ae7..dda4a9112 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -965,8 +965,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
965 | SERVER_PORT = CLIENT_PORT - 1; | 965 | SERVER_PORT = CLIENT_PORT - 1; |
966 | } | 966 | } |
967 | #endif | 967 | #endif |
968 | if (opt & OPT_o) | ||
969 | client_config.no_default_options = 1; | ||
970 | while (list_O) { | 968 | while (list_O) { |
971 | char *optstr = llist_pop(&list_O); | 969 | char *optstr = llist_pop(&list_O); |
972 | unsigned n = bb_strtou(optstr, NULL, 0); | 970 | unsigned n = bb_strtou(optstr, NULL, 0); |
@@ -976,6 +974,16 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
976 | } | 974 | } |
977 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); | 975 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); |
978 | } | 976 | } |
977 | if (!(opt & OPT_o)) { | ||
978 | /* | ||
979 | unsigned i, n; | ||
980 | for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) { | ||
981 | if (dhcp_optflags[i].flags & OPTION_REQ) { | ||
982 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); | ||
983 | } | ||
984 | } | ||
985 | */ | ||
986 | } | ||
979 | while (list_x) { | 987 | while (list_x) { |
980 | char *optstr = llist_pop(&list_x); | 988 | char *optstr = llist_pop(&list_x); |
981 | char *colon = strchr(optstr, ':'); | 989 | char *colon = strchr(optstr, ':'); |
@@ -1066,8 +1074,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1066 | retval = 0; | 1074 | retval = 0; |
1067 | /* If we already timed out, fall through with retval = 0, else... */ | 1075 | /* If we already timed out, fall through with retval = 0, else... */ |
1068 | if ((int)tv.tv_sec > 0) { | 1076 | if ((int)tv.tv_sec > 0) { |
1077 | log1("Waiting on select %u seconds", (int)tv.tv_sec); | ||
1069 | timestamp_before_wait = (unsigned)monotonic_sec(); | 1078 | timestamp_before_wait = (unsigned)monotonic_sec(); |
1070 | log1("Waiting on select..."); | ||
1071 | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); | 1079 | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); |
1072 | if (retval < 0) { | 1080 | if (retval < 0) { |
1073 | /* EINTR? A signal was caught, don't panic */ | 1081 | /* EINTR? A signal was caught, don't panic */ |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index ddb328dd5..bc1db7087 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -589,7 +589,6 @@ static void init_packet(struct dhcp_packet *packet, char type) | |||
589 | 589 | ||
590 | static void add_client_options(struct dhcp_packet *packet) | 590 | static void add_client_options(struct dhcp_packet *packet) |
591 | { | 591 | { |
592 | uint8_t c; | ||
593 | int i, end, len; | 592 | int i, end, len; |
594 | 593 | ||
595 | udhcp_add_simple_option(packet, DHCP_MAX_SIZE, htons(IP_UDP_DHCP_SIZE)); | 594 | udhcp_add_simple_option(packet, DHCP_MAX_SIZE, htons(IP_UDP_DHCP_SIZE)); |
@@ -599,13 +598,9 @@ static void add_client_options(struct dhcp_packet *packet) | |||
599 | * No bounds checking because it goes towards the head of the packet. */ | 598 | * No bounds checking because it goes towards the head of the packet. */ |
600 | end = udhcp_end_option(packet->options); | 599 | end = udhcp_end_option(packet->options); |
601 | len = 0; | 600 | len = 0; |
602 | for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) { | 601 | for (i = 1; i < DHCP_END; i++) { |
603 | if (( (dhcp_optflags[i].flags & OPTION_REQ) | 602 | if (client_config.opt_mask[i >> 3] & (1 << (i & 7))) { |
604 | && !client_config.no_default_options | 603 | packet->options[end + OPT_DATA + len] = i; |
605 | ) | ||
606 | || (client_config.opt_mask[c >> 3] & (1 << (c & 7))) | ||
607 | ) { | ||
608 | packet->options[end + OPT_DATA + len] = c; | ||
609 | len++; | 604 | len++; |
610 | } | 605 | } |
611 | } | 606 | } |
@@ -1257,8 +1252,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1257 | SERVER_PORT = CLIENT_PORT - 1; | 1252 | SERVER_PORT = CLIENT_PORT - 1; |
1258 | } | 1253 | } |
1259 | #endif | 1254 | #endif |
1260 | if (opt & OPT_o) | ||
1261 | client_config.no_default_options = 1; | ||
1262 | while (list_O) { | 1255 | while (list_O) { |
1263 | char *optstr = llist_pop(&list_O); | 1256 | char *optstr = llist_pop(&list_O); |
1264 | unsigned n = bb_strtou(optstr, NULL, 0); | 1257 | unsigned n = bb_strtou(optstr, NULL, 0); |
@@ -1268,6 +1261,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1268 | } | 1261 | } |
1269 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); | 1262 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); |
1270 | } | 1263 | } |
1264 | if (!(opt & OPT_o)) { | ||
1265 | unsigned i, n; | ||
1266 | for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) { | ||
1267 | if (dhcp_optflags[i].flags & OPTION_REQ) { | ||
1268 | client_config.opt_mask[n >> 3] |= 1 << (n & 7); | ||
1269 | } | ||
1270 | } | ||
1271 | } | ||
1271 | while (list_x) { | 1272 | while (list_x) { |
1272 | char *optstr = llist_pop(&list_x); | 1273 | char *optstr = llist_pop(&list_x); |
1273 | char *colon = strchr(optstr, ':'); | 1274 | char *colon = strchr(optstr, ':'); |
@@ -1362,8 +1363,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1362 | retval = 0; | 1363 | retval = 0; |
1363 | /* If we already timed out, fall through with retval = 0, else... */ | 1364 | /* If we already timed out, fall through with retval = 0, else... */ |
1364 | if ((int)tv.tv_sec > 0) { | 1365 | if ((int)tv.tv_sec > 0) { |
1366 | log1("Waiting on select %u seconds", (int)tv.tv_sec); | ||
1365 | timestamp_before_wait = (unsigned)monotonic_sec(); | 1367 | timestamp_before_wait = (unsigned)monotonic_sec(); |
1366 | log1("Waiting on select..."); | ||
1367 | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); | 1368 | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); |
1368 | if (retval < 0) { | 1369 | if (retval < 0) { |
1369 | /* EINTR? A signal was caught, don't panic */ | 1370 | /* EINTR? A signal was caught, don't panic */ |
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index 2b3599120..2859a0772 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h | |||
@@ -9,7 +9,6 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
9 | 9 | ||
10 | struct client_config_t { | 10 | struct client_config_t { |
11 | uint8_t client_mac[6]; /* Our mac address */ | 11 | uint8_t client_mac[6]; /* Our mac address */ |
12 | char no_default_options; /* Do not include default options in request */ | ||
13 | IF_FEATURE_UDHCP_PORT(uint16_t port;) | 12 | IF_FEATURE_UDHCP_PORT(uint16_t port;) |
14 | int ifindex; /* Index number of the interface to use */ | 13 | int ifindex; /* Index number of the interface to use */ |
15 | uint8_t opt_mask[256 / 8]; /* Bitmask of options to send (-O option) */ | 14 | uint8_t opt_mask[256 / 8]; /* Bitmask of options to send (-O option) */ |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index dd55e70f4..9ad95954d 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -377,6 +377,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
377 | /* Setup the signal pipe */ | 377 | /* Setup the signal pipe */ |
378 | udhcp_sp_setup(); | 378 | udhcp_sp_setup(); |
379 | 379 | ||
380 | continue_with_autotime: | ||
380 | timeout_end = monotonic_sec() + server_config.auto_time; | 381 | timeout_end = monotonic_sec() + server_config.auto_time; |
381 | while (1) { /* loop until universe collapses */ | 382 | while (1) { /* loop until universe collapses */ |
382 | fd_set rfds; | 383 | fd_set rfds; |
@@ -406,8 +407,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
406 | } | 407 | } |
407 | if (retval == 0) { | 408 | if (retval == 0) { |
408 | write_leases(); | 409 | write_leases(); |
409 | timeout_end = monotonic_sec() + server_config.auto_time; | 410 | goto continue_with_autotime; |
410 | continue; | ||
411 | } | 411 | } |
412 | if (retval < 0 && errno != EINTR) { | 412 | if (retval < 0 && errno != EINTR) { |
413 | log1("Error on select"); | 413 | log1("Error on select"); |
@@ -419,10 +419,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
419 | bb_info_msg("Received SIGUSR1"); | 419 | bb_info_msg("Received SIGUSR1"); |
420 | write_leases(); | 420 | write_leases(); |
421 | /* why not just reset the timeout, eh */ | 421 | /* why not just reset the timeout, eh */ |
422 | timeout_end = monotonic_sec() + server_config.auto_time; | 422 | goto continue_with_autotime; |
423 | continue; | ||
424 | case SIGTERM: | 423 | case SIGTERM: |
425 | bb_info_msg("Received SIGTERM"); | 424 | bb_info_msg("Received SIGTERM"); |
425 | write_leases(); | ||
426 | goto ret0; | 426 | goto ret0; |
427 | case 0: /* no signal: read a packet */ | 427 | case 0: /* no signal: read a packet */ |
428 | break; | 428 | break; |
diff --git a/networking/udhcp/socket.c b/networking/udhcp/socket.c index a5220ba74..a42106960 100644 --- a/networking/udhcp/socket.c +++ b/networking/udhcp/socket.c | |||
@@ -80,6 +80,7 @@ int FAST_FUNC udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) | |||
80 | { | 80 | { |
81 | int fd; | 81 | int fd; |
82 | struct sockaddr_in addr; | 82 | struct sockaddr_in addr; |
83 | char *colon; | ||
83 | 84 | ||
84 | log1("Opening listen socket on *:%d %s", port, inf); | 85 | log1("Opening listen socket on *:%d %s", port, inf); |
85 | fd = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); | 86 | fd = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); |
@@ -88,10 +89,17 @@ int FAST_FUNC udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) | |||
88 | if (setsockopt_broadcast(fd) == -1) | 89 | if (setsockopt_broadcast(fd) == -1) |
89 | bb_perror_msg_and_die("SO_BROADCAST"); | 90 | bb_perror_msg_and_die("SO_BROADCAST"); |
90 | 91 | ||
91 | /* NB: bug 1032 says this doesn't work on ethernet aliases (ethN:M) */ | 92 | /* SO_BINDTODEVICE doesn't work on ethernet aliases (ethN:M) */ |
93 | colon = strrchr(inf, ':'); | ||
94 | if (colon) | ||
95 | *colon = '\0'; | ||
96 | |||
92 | if (setsockopt_bindtodevice(fd, inf)) | 97 | if (setsockopt_bindtodevice(fd, inf)) |
93 | xfunc_die(); /* warning is already printed */ | 98 | xfunc_die(); /* warning is already printed */ |
94 | 99 | ||
100 | if (colon) | ||
101 | *colon = ':'; | ||
102 | |||
95 | memset(&addr, 0, sizeof(addr)); | 103 | memset(&addr, 0, sizeof(addr)); |
96 | addr.sin_family = AF_INET; | 104 | addr.sin_family = AF_INET; |
97 | addr.sin_port = htons(port); | 105 | addr.sin_port = htons(port); |
diff --git a/networking/wget.c b/networking/wget.c index 1991a1072..4eafebe40 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
@@ -13,8 +13,9 @@ | |||
13 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( | 13 | //usage: IF_FEATURE_WGET_LONG_OPTIONS( |
14 | //usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" | 14 | //usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" |
15 | //usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" | 15 | //usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" |
16 | //usage: " [--no-check-certificate] [-U|--user-agent AGENT]" | 16 | /* Since we ignore these opts, we don't show them in --help */ |
17 | //usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." | 17 | /* //usage: " [--no-check-certificate] [--no-cache]" */ |
18 | //usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." | ||
18 | //usage: ) | 19 | //usage: ) |
19 | //usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( | 20 | //usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( |
20 | //usage: "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" | 21 | //usage: "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" |
@@ -35,8 +36,11 @@ | |||
35 | 36 | ||
36 | #include "libbb.h" | 37 | #include "libbb.h" |
37 | 38 | ||
38 | //#define log_io(...) bb_error_msg(__VA_ARGS__) | 39 | #if 0 |
39 | #define log_io(...) ((void)0) | 40 | # define log_io(...) bb_error_msg(__VA_ARGS__) |
41 | #else | ||
42 | # define log_io(...) ((void)0) | ||
43 | #endif | ||
40 | 44 | ||
41 | 45 | ||
42 | struct host_info { | 46 | struct host_info { |
@@ -316,8 +320,6 @@ static char *gethdr(FILE *fp) | |||
316 | char *s, *hdrval; | 320 | char *s, *hdrval; |
317 | int c; | 321 | int c; |
318 | 322 | ||
319 | /* *istrunc = 0; */ | ||
320 | |||
321 | /* retrieve header line */ | 323 | /* retrieve header line */ |
322 | c = fgets_and_trim(fp); | 324 | c = fgets_and_trim(fp); |
323 | 325 | ||
@@ -348,6 +350,15 @@ static char *gethdr(FILE *fp) | |||
348 | return hdrval; | 350 | return hdrval; |
349 | } | 351 | } |
350 | 352 | ||
353 | static void reset_beg_range_to_zero(void) | ||
354 | { | ||
355 | bb_error_msg("restart failed"); | ||
356 | G.beg_range = 0; | ||
357 | xlseek(G.output_fd, 0, SEEK_SET); | ||
358 | /* Done at the end instead: */ | ||
359 | /* ftruncate(G.output_fd, 0); */ | ||
360 | } | ||
361 | |||
351 | static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) | 362 | static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) |
352 | { | 363 | { |
353 | FILE *sfp; | 364 | FILE *sfp; |
@@ -415,10 +426,12 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ | |||
415 | 426 | ||
416 | *dfpp = open_socket(lsa); | 427 | *dfpp = open_socket(lsa); |
417 | 428 | ||
418 | if (G.beg_range) { | 429 | if (G.beg_range != 0) { |
419 | sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); | 430 | sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); |
420 | if (ftpcmd(G.wget_buf, NULL, sfp) == 350) | 431 | if (ftpcmd(G.wget_buf, NULL, sfp) == 350) |
421 | G.content_len -= G.beg_range; | 432 | G.content_len -= G.beg_range; |
433 | else | ||
434 | reset_beg_range_to_zero(); | ||
422 | } | 435 | } |
423 | 436 | ||
424 | if (ftpcmd("RETR ", target->path, sfp) > 150) | 437 | if (ftpcmd("RETR ", target->path, sfp) > 150) |
@@ -431,7 +444,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp) | |||
431 | { | 444 | { |
432 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT | 445 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT |
433 | # if ENABLE_FEATURE_WGET_TIMEOUT | 446 | # if ENABLE_FEATURE_WGET_TIMEOUT |
434 | unsigned second_cnt; | 447 | unsigned second_cnt = G.timeout_seconds; |
435 | # endif | 448 | # endif |
436 | struct pollfd polldata; | 449 | struct pollfd polldata; |
437 | 450 | ||
@@ -452,7 +465,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp) | |||
452 | * which messes up progress bar and/or timeout logic. | 465 | * which messes up progress bar and/or timeout logic. |
453 | * Because of nonblocking I/O, we need to dance | 466 | * Because of nonblocking I/O, we need to dance |
454 | * very carefully around EAGAIN. See explanation at | 467 | * very carefully around EAGAIN. See explanation at |
455 | * clearerr() call. | 468 | * clearerr() calls. |
456 | */ | 469 | */ |
457 | ndelay_on(polldata.fd); | 470 | ndelay_on(polldata.fd); |
458 | #endif | 471 | #endif |
@@ -460,32 +473,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp) | |||
460 | int n; | 473 | int n; |
461 | unsigned rdsz; | 474 | unsigned rdsz; |
462 | 475 | ||
463 | rdsz = sizeof(G.wget_buf); | ||
464 | if (G.got_clen) { | ||
465 | if (G.content_len < (off_t)sizeof(G.wget_buf)) { | ||
466 | if ((int)G.content_len <= 0) | ||
467 | break; | ||
468 | rdsz = (unsigned)G.content_len; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT | 476 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT |
473 | # if ENABLE_FEATURE_WGET_TIMEOUT | ||
474 | second_cnt = G.timeout_seconds; | ||
475 | # endif | ||
476 | while (1) { | ||
477 | if (safe_poll(&polldata, 1, 1000) != 0) | ||
478 | break; /* error, EOF, or data is available */ | ||
479 | # if ENABLE_FEATURE_WGET_TIMEOUT | ||
480 | if (second_cnt != 0 && --second_cnt == 0) { | ||
481 | progress_meter(PROGRESS_END); | ||
482 | bb_error_msg_and_die("download timed out"); | ||
483 | } | ||
484 | # endif | ||
485 | /* Needed for "stalled" indicator */ | ||
486 | progress_meter(PROGRESS_BUMP); | ||
487 | } | ||
488 | |||
489 | /* fread internally uses read loop, which in our case | 477 | /* fread internally uses read loop, which in our case |
490 | * is usually exited when we get EAGAIN. | 478 | * is usually exited when we get EAGAIN. |
491 | * In this case, libc sets error marker on the stream. | 479 | * In this case, libc sets error marker on the stream. |
@@ -495,36 +483,71 @@ static void NOINLINE retrieve_file_data(FILE *dfp) | |||
495 | * into if (n <= 0) ... | 483 | * into if (n <= 0) ... |
496 | */ | 484 | */ |
497 | clearerr(dfp); | 485 | clearerr(dfp); |
498 | errno = 0; | ||
499 | #endif | 486 | #endif |
487 | errno = 0; | ||
488 | rdsz = sizeof(G.wget_buf); | ||
489 | if (G.got_clen) { | ||
490 | if (G.content_len < (off_t)sizeof(G.wget_buf)) { | ||
491 | if ((int)G.content_len <= 0) | ||
492 | break; | ||
493 | rdsz = (unsigned)G.content_len; | ||
494 | } | ||
495 | } | ||
500 | n = fread(G.wget_buf, 1, rdsz, dfp); | 496 | n = fread(G.wget_buf, 1, rdsz, dfp); |
501 | /* man fread: | 497 | |
498 | if (n > 0) { | ||
499 | xwrite(G.output_fd, G.wget_buf, n); | ||
500 | #if ENABLE_FEATURE_WGET_STATUSBAR | ||
501 | G.transferred += n; | ||
502 | #endif | ||
503 | if (G.got_clen) { | ||
504 | G.content_len -= n; | ||
505 | if (G.content_len == 0) | ||
506 | break; | ||
507 | } | ||
508 | #if ENABLE_FEATURE_WGET_TIMEOUT | ||
509 | second_cnt = G.timeout_seconds; | ||
510 | #endif | ||
511 | continue; | ||
512 | } | ||
513 | |||
514 | /* n <= 0. | ||
515 | * man fread: | ||
502 | * If error occurs, or EOF is reached, the return value | 516 | * If error occurs, or EOF is reached, the return value |
503 | * is a short item count (or zero). | 517 | * is a short item count (or zero). |
504 | * fread does not distinguish between EOF and error. | 518 | * fread does not distinguish between EOF and error. |
505 | */ | 519 | */ |
506 | if (n <= 0) { | 520 | if (errno != EAGAIN) { |
507 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT | 521 | if (ferror(dfp)) { |
508 | if (errno == EAGAIN) /* poll lied, there is no data? */ | 522 | progress_meter(PROGRESS_END); |
509 | continue; /* yes */ | ||
510 | #endif | ||
511 | if (ferror(dfp)) | ||
512 | bb_perror_msg_and_die(bb_msg_read_error); | 523 | bb_perror_msg_and_die(bb_msg_read_error); |
524 | } | ||
513 | break; /* EOF, not error */ | 525 | break; /* EOF, not error */ |
514 | } | 526 | } |
515 | 527 | ||
516 | xwrite(G.output_fd, G.wget_buf, n); | 528 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT |
517 | 529 | /* It was EAGAIN. There is no data. Wait up to one second | |
518 | #if ENABLE_FEATURE_WGET_STATUSBAR | 530 | * then abort if timed out, or update the bar and try reading again. |
519 | G.transferred += n; | 531 | */ |
532 | if (safe_poll(&polldata, 1, 1000) == 0) { | ||
533 | # if ENABLE_FEATURE_WGET_TIMEOUT | ||
534 | if (second_cnt != 0 && --second_cnt == 0) { | ||
535 | progress_meter(PROGRESS_END); | ||
536 | bb_error_msg_and_die("download timed out"); | ||
537 | } | ||
538 | # endif | ||
539 | /* We used to loop back to poll here, | ||
540 | * but there is no great harm in letting fread | ||
541 | * to try reading anyway. | ||
542 | */ | ||
543 | } | ||
544 | /* Need to do it _every_ second for "stalled" indicator | ||
545 | * to be shown properly. | ||
546 | */ | ||
520 | progress_meter(PROGRESS_BUMP); | 547 | progress_meter(PROGRESS_BUMP); |
521 | #endif | 548 | #endif |
522 | if (G.got_clen) { | 549 | } /* while (reading data) */ |
523 | G.content_len -= n; | 550 | |
524 | if (G.content_len == 0) | ||
525 | break; | ||
526 | } | ||
527 | } | ||
528 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT | 551 | #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT |
529 | clearerr(dfp); | 552 | clearerr(dfp); |
530 | ndelay_off(polldata.fd); /* else fgets can get very unhappy */ | 553 | ndelay_off(polldata.fd); /* else fgets can get very unhappy */ |
@@ -540,6 +563,24 @@ static void NOINLINE retrieve_file_data(FILE *dfp) | |||
540 | if (G.content_len == 0) | 563 | if (G.content_len == 0) |
541 | break; /* all done! */ | 564 | break; /* all done! */ |
542 | G.got_clen = 1; | 565 | G.got_clen = 1; |
566 | /* | ||
567 | * Note that fgets may result in some data being buffered in dfp. | ||
568 | * We loop back to fread, which will retrieve this data. | ||
569 | * Also note that code has to be arranged so that fread | ||
570 | * is done _before_ one-second poll wait - poll doesn't know | ||
571 | * about stdio buffering and can result in spurious one second waits! | ||
572 | */ | ||
573 | } | ||
574 | |||
575 | /* If -c failed, we restart from the beginning, | ||
576 | * but we do not truncate file then, we do it only now, at the end. | ||
577 | * This lets user to ^C if his 99% complete 10 GB file download | ||
578 | * failed to restart *without* losing the almost complete file. | ||
579 | */ | ||
580 | { | ||
581 | off_t pos = lseek(G.output_fd, 0, SEEK_CUR); | ||
582 | if (pos != (off_t)-1) | ||
583 | ftruncate(G.output_fd, pos); | ||
543 | } | 584 | } |
544 | 585 | ||
545 | /* Draw full bar and free its resources */ | 586 | /* Draw full bar and free its resources */ |
@@ -597,13 +638,11 @@ static void download_one_url(const char *url) | |||
597 | if (G.fname_out[0] == '/' || !G.fname_out[0]) | 638 | if (G.fname_out[0] == '/' || !G.fname_out[0]) |
598 | G.fname_out = (char*)"index.html"; | 639 | G.fname_out = (char*)"index.html"; |
599 | /* -P DIR is considered only if there was no -O FILE */ | 640 | /* -P DIR is considered only if there was no -O FILE */ |
641 | if (G.dir_prefix) | ||
642 | G.fname_out = fname_out_alloc = concat_path_file(G.dir_prefix, G.fname_out); | ||
600 | else { | 643 | else { |
601 | if (G.dir_prefix) | 644 | /* redirects may free target.path later, need to make a copy */ |
602 | G.fname_out = fname_out_alloc = concat_path_file(G.dir_prefix, G.fname_out); | 645 | G.fname_out = fname_out_alloc = xstrdup(G.fname_out); |
603 | else { | ||
604 | /* redirects may free target.path later, need to make a copy */ | ||
605 | G.fname_out = fname_out_alloc = xstrdup(G.fname_out); | ||
606 | } | ||
607 | } | 646 | } |
608 | } | 647 | } |
609 | #if ENABLE_FEATURE_WGET_STATUSBAR | 648 | #if ENABLE_FEATURE_WGET_STATUSBAR |
@@ -675,7 +714,7 @@ static void download_one_url(const char *url) | |||
675 | } | 714 | } |
676 | #endif | 715 | #endif |
677 | 716 | ||
678 | if (G.beg_range) | 717 | if (G.beg_range != 0) |
679 | fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range); | 718 | fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range); |
680 | 719 | ||
681 | #if ENABLE_FEATURE_WGET_LONG_OPTIONS | 720 | #if ENABLE_FEATURE_WGET_LONG_OPTIONS |
@@ -742,15 +781,23 @@ However, in real world it was observed that some web servers | |||
742 | (e.g. Boa/0.94.14rc21) simply use code 204 when file size is zero. | 781 | (e.g. Boa/0.94.14rc21) simply use code 204 when file size is zero. |
743 | */ | 782 | */ |
744 | case 204: | 783 | case 204: |
784 | if (G.beg_range != 0) { | ||
785 | /* "Range:..." was not honored by the server. | ||
786 | * Restart download from the beginning. | ||
787 | */ | ||
788 | reset_beg_range_to_zero(); | ||
789 | } | ||
745 | break; | 790 | break; |
746 | case 300: /* redirection */ | 791 | case 300: /* redirection */ |
747 | case 301: | 792 | case 301: |
748 | case 302: | 793 | case 302: |
749 | case 303: | 794 | case 303: |
750 | break; | 795 | break; |
751 | case 206: | 796 | case 206: /* Partial Content */ |
752 | if (G.beg_range) | 797 | if (G.beg_range != 0) |
798 | /* "Range:..." worked. Good. */ | ||
753 | break; | 799 | break; |
800 | /* Partial Content even though we did not ask for it??? */ | ||
754 | /* fall through */ | 801 | /* fall through */ |
755 | default: | 802 | default: |
756 | bb_error_msg_and_die("server returned error: %s", sanitize_string(G.wget_buf)); | 803 | bb_error_msg_and_die("server returned error: %s", sanitize_string(G.wget_buf)); |
@@ -878,6 +925,8 @@ int wget_main(int argc UNUSED_PARAM, char **argv) | |||
878 | "post-data\0" Required_argument "\xfd" | 925 | "post-data\0" Required_argument "\xfd" |
879 | /* Ignored (we don't do ssl) */ | 926 | /* Ignored (we don't do ssl) */ |
880 | "no-check-certificate\0" No_argument "\xfc" | 927 | "no-check-certificate\0" No_argument "\xfc" |
928 | /* Ignored (we don't support caching) */ | ||
929 | "no-cache\0" No_argument "\xfb" | ||
881 | ; | 930 | ; |
882 | #endif | 931 | #endif |
883 | 932 | ||
diff --git a/printutils/lpr.c b/printutils/lpr.c index 748879542..70cda7717 100644 --- a/printutils/lpr.c +++ b/printutils/lpr.c | |||
@@ -89,6 +89,10 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[]) | |||
89 | unsigned opts; | 89 | unsigned opts; |
90 | int fd; | 90 | int fd; |
91 | 91 | ||
92 | queue = getenv("PRINTER"); | ||
93 | if (!queue) | ||
94 | queue = "lp"; | ||
95 | |||
92 | // parse options | 96 | // parse options |
93 | // TODO: set opt_complementary: s,d,f are mutually exclusive | 97 | // TODO: set opt_complementary: s,d,f are mutually exclusive |
94 | opts = getopt32(argv, | 98 | opts = getopt32(argv, |
@@ -98,16 +102,7 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[]) | |||
98 | ); | 102 | ); |
99 | argv += optind; | 103 | argv += optind; |
100 | 104 | ||
101 | // if queue is not specified -> use $PRINTER | 105 | { |
102 | if (!(opts & OPT_P)) | ||
103 | queue = getenv("PRINTER"); | ||
104 | // if queue is still not specified -> | ||
105 | if (!queue) { | ||
106 | // ... queue defaults to "lp" | ||
107 | // server defaults to "localhost" | ||
108 | queue = "lp"; | ||
109 | // if queue is specified -> | ||
110 | } else { | ||
111 | // queue name is to the left of '@' | 106 | // queue name is to the left of '@' |
112 | char *s = strchr(queue, '@'); | 107 | char *s = strchr(queue, '@'); |
113 | if (s) { | 108 | if (s) { |
@@ -186,6 +181,17 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[]) | |||
186 | dfd = xopen(*argv, O_RDONLY); | 181 | dfd = xopen(*argv, O_RDONLY); |
187 | } | 182 | } |
188 | 183 | ||
184 | st.st_size = 0; /* paranoia: fstat may theoretically fail */ | ||
185 | fstat(dfd, &st); | ||
186 | |||
187 | /* Apparently, some servers are buggy and won't accept 0-sized jobs. | ||
188 | * Standard lpr works around it by refusing to send such jobs: | ||
189 | */ | ||
190 | if (st.st_size == 0) { | ||
191 | bb_error_msg("nothing to print"); | ||
192 | continue; | ||
193 | } | ||
194 | |||
189 | /* "The name ... should start with ASCII "cfA", | 195 | /* "The name ... should start with ASCII "cfA", |
190 | * followed by a three digit job number, followed | 196 | * followed by a three digit job number, followed |
191 | * by the host name which has constructed the file." | 197 | * by the host name which has constructed the file." |
@@ -210,7 +216,7 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[]) | |||
210 | , (opts & LPR_m) ? user : "" | 216 | , (opts & LPR_m) ? user : "" |
211 | , remote_filename | 217 | , remote_filename |
212 | ); | 218 | ); |
213 | // delete possible "\nX\n" patterns | 219 | // delete possible "\nX\n" (that is, one-char) patterns |
214 | c = controlfile; | 220 | c = controlfile; |
215 | while ((c = strchr(c, '\n')) != NULL) { | 221 | while ((c = strchr(c, '\n')) != NULL) { |
216 | if (c[1] && c[2] == '\n') { | 222 | if (c[1] && c[2] == '\n') { |
@@ -239,8 +245,6 @@ int lpqr_main(int argc UNUSED_PARAM, char *argv[]) | |||
239 | // send data file, with name "dfaXXX" | 245 | // send data file, with name "dfaXXX" |
240 | if (opts & LPR_V) | 246 | if (opts & LPR_V) |
241 | bb_error_msg("sending data file"); | 247 | bb_error_msg("sending data file"); |
242 | st.st_size = 0; /* paranoia: fstat may theoretically fail */ | ||
243 | fstat(dfd, &st); | ||
244 | fdprintf(fd, "\x3" "%"OFF_FMT"u d%s\n", st.st_size, remote_filename); | 248 | fdprintf(fd, "\x3" "%"OFF_FMT"u d%s\n", st.st_size, remote_filename); |
245 | get_response_or_say_and_die(fd, "sending data file"); | 249 | get_response_or_say_and_die(fd, "sending data file"); |
246 | if (bb_copyfd_size(dfd, fd, st.st_size) != st.st_size) { | 250 | if (bb_copyfd_size(dfd, fd, st.st_size) != st.st_size) { |
diff --git a/procps/powertop.c b/procps/powertop.c index 008cdfca4..b4c45edbc 100644 --- a/procps/powertop.c +++ b/procps/powertop.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * Licensed under GPLv2, see file LICENSE in this source tree. | 9 | * Licensed under GPLv2, see file LICENSE in this source tree. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | //applet:IF_POWERTOP(APPLET(powertop, BB_DIR_BIN, BB_SUID_DROP)) | 12 | //applet:IF_POWERTOP(APPLET(powertop, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
13 | 13 | ||
14 | //kbuild:lib-$(CONFIG_POWERTOP) += powertop.o | 14 | //kbuild:lib-$(CONFIG_POWERTOP) += powertop.o |
15 | 15 | ||
diff --git a/procps/ps.c b/procps/ps.c index aa004aa22..dc6fda61d 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -69,6 +69,31 @@ | |||
69 | /* Absolute maximum on output line length */ | 69 | /* Absolute maximum on output line length */ |
70 | enum { MAX_WIDTH = 2*1024 }; | 70 | enum { MAX_WIDTH = 2*1024 }; |
71 | 71 | ||
72 | #if ENABLE_FEATURE_PS_TIME || ENABLE_FEATURE_PS_LONG | ||
73 | static long get_uptime(void) | ||
74 | { | ||
75 | #ifdef __linux__ | ||
76 | struct sysinfo info; | ||
77 | if (sysinfo(&info) < 0) | ||
78 | return 0; | ||
79 | return info.uptime; | ||
80 | #elif 1 | ||
81 | char buf[64]; | ||
82 | long uptime; | ||
83 | if (open_read_close("/proc/uptime", buf, sizeof(buf)) <= 0) | ||
84 | bb_perror_msg_and_die("can't read %s", "/proc/uptime"); | ||
85 | buf[sizeof(buf)-1] = '\0'; | ||
86 | sscanf(buf, "%l", &uptime); | ||
87 | return uptime; | ||
88 | #else | ||
89 | struct timespec ts; | ||
90 | if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) | ||
91 | return 0; | ||
92 | return ts.tv_sec; | ||
93 | #endif | ||
94 | } | ||
95 | #endif | ||
96 | |||
72 | #if ENABLE_DESKTOP | 97 | #if ENABLE_DESKTOP |
73 | 98 | ||
74 | #include <sys/times.h> /* for times() */ | 99 | #include <sys/times.h> /* for times() */ |
@@ -197,8 +222,6 @@ static inline unsigned get_HZ_by_waiting(void) | |||
197 | 222 | ||
198 | static unsigned get_kernel_HZ(void) | 223 | static unsigned get_kernel_HZ(void) |
199 | { | 224 | { |
200 | //char buf[64]; | ||
201 | struct sysinfo info; | ||
202 | 225 | ||
203 | if (kernel_HZ) | 226 | if (kernel_HZ) |
204 | return kernel_HZ; | 227 | return kernel_HZ; |
@@ -208,12 +231,7 @@ static unsigned get_kernel_HZ(void) | |||
208 | if (kernel_HZ == (unsigned)-1) | 231 | if (kernel_HZ == (unsigned)-1) |
209 | kernel_HZ = get_HZ_by_waiting(); | 232 | kernel_HZ = get_HZ_by_waiting(); |
210 | 233 | ||
211 | //if (open_read_close("/proc/uptime", buf, sizeof(buf)) <= 0) | 234 | seconds_since_boot = get_uptime(); |
212 | // bb_perror_msg_and_die("can't read %s", "/proc/uptime"); | ||
213 | //buf[sizeof(buf)-1] = '\0'; | ||
214 | ///sscanf(buf, "%llu", &seconds_since_boot); | ||
215 | sysinfo(&info); | ||
216 | seconds_since_boot = info.uptime; | ||
217 | 235 | ||
218 | return kernel_HZ; | 236 | return kernel_HZ; |
219 | } | 237 | } |
@@ -645,7 +663,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
645 | }; | 663 | }; |
646 | #if ENABLE_FEATURE_PS_LONG | 664 | #if ENABLE_FEATURE_PS_LONG |
647 | time_t now = now; | 665 | time_t now = now; |
648 | struct sysinfo info; | 666 | long uptime; |
649 | #endif | 667 | #endif |
650 | int opts = 0; | 668 | int opts = 0; |
651 | /* If we support any options, parse argv */ | 669 | /* If we support any options, parse argv */ |
@@ -705,7 +723,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
705 | puts("S UID PID PPID VSZ RSS TTY STIME TIME CMD"); | 723 | puts("S UID PID PPID VSZ RSS TTY STIME TIME CMD"); |
706 | #if ENABLE_FEATURE_PS_LONG | 724 | #if ENABLE_FEATURE_PS_LONG |
707 | now = time(NULL); | 725 | now = time(NULL); |
708 | sysinfo(&info); | 726 | uptime = get_uptime(); |
709 | #endif | 727 | #endif |
710 | } | 728 | } |
711 | else { | 729 | else { |
@@ -737,7 +755,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
737 | char tty[2 * sizeof(int)*3 + 2]; | 755 | char tty[2 * sizeof(int)*3 + 2]; |
738 | char *endp; | 756 | char *endp; |
739 | unsigned sut = (p->stime + p->utime) / 100; | 757 | unsigned sut = (p->stime + p->utime) / 100; |
740 | unsigned elapsed = info.uptime - (p->start_time / 100); | 758 | unsigned elapsed = uptime - (p->start_time / 100); |
741 | time_t start = now - elapsed; | 759 | time_t start = now - elapsed; |
742 | struct tm *tm = localtime(&start); | 760 | struct tm *tm = localtime(&start); |
743 | 761 | ||
diff --git a/procps/sysctl.c b/procps/sysctl.c index 5296d0f58..878656862 100644 --- a/procps/sysctl.c +++ b/procps/sysctl.c | |||
@@ -12,21 +12,23 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | //usage:#define sysctl_trivial_usage | 14 | //usage:#define sysctl_trivial_usage |
15 | //usage: "[OPTIONS] [VALUE]..." | 15 | //usage: "[OPTIONS] [KEY[=VALUE]]..." |
16 | //usage:#define sysctl_full_usage "\n\n" | 16 | //usage:#define sysctl_full_usage "\n\n" |
17 | //usage: "Configure kernel parameters at runtime\n" | 17 | //usage: "Show/set kernel parameters\n" |
18 | //usage: "\n -n Don't print key names" | ||
19 | //usage: "\n -e Don't warn about unknown keys" | 18 | //usage: "\n -e Don't warn about unknown keys" |
20 | //usage: "\n -w Change sysctl setting" | 19 | //usage: "\n -n Don't show key names" |
21 | //usage: "\n -p FILE Load sysctl settings from FILE (default /etc/sysctl.conf)" | 20 | //usage: "\n -a Show all values" |
22 | //usage: "\n -a Display all values" | 21 | /* Same as -a, no need to show it */ |
23 | //usage: "\n -A Display all values in table form" | 22 | /* //usage: "\n -A Show all values in table form" */ |
23 | //usage: "\n -w Set values" | ||
24 | //usage: "\n -p FILE Set values from FILE (default /etc/sysctl.conf)" | ||
25 | //usage: "\n -q Set values silently" | ||
24 | //usage: | 26 | //usage: |
25 | //usage:#define sysctl_example_usage | 27 | //usage:#define sysctl_example_usage |
26 | //usage: "sysctl [-n] [-e] variable...\n" | 28 | //usage: "sysctl [-n] [-e] variable...\n" |
27 | //usage: "sysctl [-n] [-e] -w variable=value...\n" | 29 | //usage: "sysctl [-n] [-e] [-q] -w variable=value...\n" |
28 | //usage: "sysctl [-n] [-e] -a\n" | 30 | //usage: "sysctl [-n] [-e] -a\n" |
29 | //usage: "sysctl [-n] [-e] -p file (default /etc/sysctl.conf)\n" | 31 | //usage: "sysctl [-n] [-e] [-q] -p file (default /etc/sysctl.conf)\n" |
30 | //usage: "sysctl [-n] [-e] -A\n" | 32 | //usage: "sysctl [-n] [-e] -A\n" |
31 | 33 | ||
32 | #include "libbb.h" | 34 | #include "libbb.h" |
@@ -37,9 +39,11 @@ enum { | |||
37 | FLAG_TABLE_FORMAT = 1 << 2, /* not implemented */ | 39 | FLAG_TABLE_FORMAT = 1 << 2, /* not implemented */ |
38 | FLAG_SHOW_ALL = 1 << 3, | 40 | FLAG_SHOW_ALL = 1 << 3, |
39 | FLAG_PRELOAD_FILE = 1 << 4, | 41 | FLAG_PRELOAD_FILE = 1 << 4, |
42 | /* TODO: procps 3.2.8 seems to not require -w for KEY=VAL to work: */ | ||
40 | FLAG_WRITE = 1 << 5, | 43 | FLAG_WRITE = 1 << 5, |
44 | FLAG_QUIET = 1 << 6, | ||
41 | }; | 45 | }; |
42 | #define OPTION_STR "neAapw" | 46 | #define OPTION_STR "neAapwq" |
43 | 47 | ||
44 | static void sysctl_dots_to_slashes(char *name) | 48 | static void sysctl_dots_to_slashes(char *name) |
45 | { | 49 | { |
@@ -144,9 +148,11 @@ static int sysctl_act_on_setting(char *setting) | |||
144 | //TODO: procps 3.2.7 writes "value\n", note trailing "\n" | 148 | //TODO: procps 3.2.7 writes "value\n", note trailing "\n" |
145 | xwrite_str(fd, value); | 149 | xwrite_str(fd, value); |
146 | close(fd); | 150 | close(fd); |
147 | if (option_mask32 & FLAG_SHOW_KEYS) | 151 | if (!(option_mask32 & FLAG_QUIET)) { |
148 | printf("%s = ", outname); | 152 | if (option_mask32 & FLAG_SHOW_KEYS) |
149 | puts(value); | 153 | printf("%s = ", outname); |
154 | puts(value); | ||
155 | } | ||
150 | } else { | 156 | } else { |
151 | char c; | 157 | char c; |
152 | 158 | ||
diff --git a/runit/chpst.c b/runit/chpst.c index ac296babf..ed72c8b8c 100644 --- a/runit/chpst.c +++ b/runit/chpst.c | |||
@@ -91,6 +91,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
91 | //usage: "\n a SIGXCPU after N seconds" | 91 | //usage: "\n a SIGXCPU after N seconds" |
92 | 92 | ||
93 | #include "libbb.h" | 93 | #include "libbb.h" |
94 | #include <sys/resource.h> /* getrlimit */ | ||
94 | 95 | ||
95 | /* | 96 | /* |
96 | Five applets here: chpst, envdir, envuidgid, setuidgid, softlimit. | 97 | Five applets here: chpst, envdir, envuidgid, setuidgid, softlimit. |
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index d3f69f8f5..1b0b6ab07 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c | |||
@@ -9,6 +9,8 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define _XOPEN_SOURCE 700 | 11 | #define _XOPEN_SOURCE 700 |
12 | /* On Darwin, this may be needed to get SIGWINCH: */ | ||
13 | #define _DARWIN_C_SOURCE 1 | ||
12 | 14 | ||
13 | #include <sys/ioctl.h> | 15 | #include <sys/ioctl.h> |
14 | #include <sys/wait.h> | 16 | #include <sys/wait.h> |
diff --git a/shell/ash.c b/shell/ash.c index f7c12f8e1..46bf6ed49 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -37,8 +37,9 @@ | |||
37 | * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) | 37 | * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) |
38 | * define DEBUG=2 to compile in and turn on debugging. | 38 | * define DEBUG=2 to compile in and turn on debugging. |
39 | * | 39 | * |
40 | * When debugging is on, debugging info will be written to ./trace and | 40 | * When debugging is on (DEBUG is 1 and "set -o debug" was executed), |
41 | * a quit signal will generate a core dump. | 41 | * debugging info will be written to ./trace and a quit signal |
42 | * will generate a core dump. | ||
42 | */ | 43 | */ |
43 | #define DEBUG 0 | 44 | #define DEBUG 0 |
44 | /* Tweak debug output verbosity here */ | 45 | /* Tweak debug output verbosity here */ |
@@ -1955,6 +1956,10 @@ static const struct { | |||
1955 | const char *var_text; | 1956 | const char *var_text; |
1956 | void (*var_func)(const char *) FAST_FUNC; | 1957 | void (*var_func)(const char *) FAST_FUNC; |
1957 | } varinit_data[] = { | 1958 | } varinit_data[] = { |
1959 | /* | ||
1960 | * Note: VEXPORT would not work correctly here for NOFORK applets: | ||
1961 | * some environment strings may be constant. | ||
1962 | */ | ||
1958 | { VSTRFIXED|VTEXTFIXED , defifsvar , NULL }, | 1963 | { VSTRFIXED|VTEXTFIXED , defifsvar , NULL }, |
1959 | #if ENABLE_ASH_MAIL | 1964 | #if ENABLE_ASH_MAIL |
1960 | { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL" , changemail }, | 1965 | { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL" , changemail }, |
@@ -5401,14 +5406,15 @@ openredirect(union node *redir) | |||
5401 | char *fname; | 5406 | char *fname; |
5402 | int f; | 5407 | int f; |
5403 | 5408 | ||
5409 | fname = redir->nfile.expfname; | ||
5404 | #if ENABLE_PLATFORM_MINGW32 | 5410 | #if ENABLE_PLATFORM_MINGW32 |
5405 | /* Support for /dev/null */ | 5411 | /* Support for /dev/null */ |
5406 | switch (redir->nfile.type) { | 5412 | switch (redir->nfile.type) { |
5407 | case NFROM: | 5413 | case NFROM: |
5408 | if (!strcmp(redir->nfile.expfname, "/dev/null")) | 5414 | if (!strcmp(fname, "/dev/null")) |
5409 | return open("nul",O_RDWR); | 5415 | return open("nul",O_RDWR); |
5410 | if (!strncmp(redir->nfile.expfname, "/dev/", 5)) { | 5416 | if (!strncmp(fname, "/dev/", 5)) { |
5411 | ash_msg("Unhandled device %s\n", redir->nfile.expfname); | 5417 | ash_msg("Unhandled device %s\n", fname); |
5412 | return -1; | 5418 | return -1; |
5413 | } | 5419 | } |
5414 | break; | 5420 | break; |
@@ -5417,10 +5423,10 @@ openredirect(union node *redir) | |||
5417 | case NTO: | 5423 | case NTO: |
5418 | case NCLOBBER: | 5424 | case NCLOBBER: |
5419 | case NAPPEND: | 5425 | case NAPPEND: |
5420 | if (!strcmp(redir->nfile.expfname, "/dev/null")) | 5426 | if (!strcmp(fname, "/dev/null")) |
5421 | return open("nul",O_RDWR); | 5427 | return open("nul",O_RDWR); |
5422 | if (!strncmp(redir->nfile.expfname, "/dev/", 5)) { | 5428 | if (!strncmp(fname, "/dev/", 5)) { |
5423 | ash_msg("Unhandled device %s\n", redir->nfile.expfname); | 5429 | ash_msg("Unhandled device %s\n", fname); |
5424 | return -1; | 5430 | return -1; |
5425 | } | 5431 | } |
5426 | break; | 5432 | break; |
@@ -5428,13 +5434,11 @@ openredirect(union node *redir) | |||
5428 | #endif | 5434 | #endif |
5429 | switch (redir->nfile.type) { | 5435 | switch (redir->nfile.type) { |
5430 | case NFROM: | 5436 | case NFROM: |
5431 | fname = redir->nfile.expfname; | ||
5432 | f = open(fname, O_RDONLY); | 5437 | f = open(fname, O_RDONLY); |
5433 | if (f < 0) | 5438 | if (f < 0) |
5434 | goto eopen; | 5439 | goto eopen; |
5435 | break; | 5440 | break; |
5436 | case NFROMTO: | 5441 | case NFROMTO: |
5437 | fname = redir->nfile.expfname; | ||
5438 | f = open(fname, O_RDWR|O_CREAT, 0666); | 5442 | f = open(fname, O_RDWR|O_CREAT, 0666); |
5439 | if (f < 0) | 5443 | if (f < 0) |
5440 | goto ecreate; | 5444 | goto ecreate; |
@@ -5445,7 +5449,6 @@ openredirect(union node *redir) | |||
5445 | #endif | 5449 | #endif |
5446 | /* Take care of noclobber mode. */ | 5450 | /* Take care of noclobber mode. */ |
5447 | if (Cflag) { | 5451 | if (Cflag) { |
5448 | fname = redir->nfile.expfname; | ||
5449 | f = noclobberopen(fname); | 5452 | f = noclobberopen(fname); |
5450 | if (f < 0) | 5453 | if (f < 0) |
5451 | goto ecreate; | 5454 | goto ecreate; |
@@ -5453,13 +5456,11 @@ openredirect(union node *redir) | |||
5453 | } | 5456 | } |
5454 | /* FALLTHROUGH */ | 5457 | /* FALLTHROUGH */ |
5455 | case NCLOBBER: | 5458 | case NCLOBBER: |
5456 | fname = redir->nfile.expfname; | ||
5457 | f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666); | 5459 | f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666); |
5458 | if (f < 0) | 5460 | if (f < 0) |
5459 | goto ecreate; | 5461 | goto ecreate; |
5460 | break; | 5462 | break; |
5461 | case NAPPEND: | 5463 | case NAPPEND: |
5462 | fname = redir->nfile.expfname; | ||
5463 | f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666); | 5464 | f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666); |
5464 | if (f < 0) | 5465 | if (f < 0) |
5465 | goto ecreate; | 5466 | goto ecreate; |
@@ -6491,7 +6492,9 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
6491 | length++; | 6492 | length++; |
6492 | goto addquote; | 6493 | goto addquote; |
6493 | case CTLVAR: | 6494 | case CTLVAR: |
6495 | TRACE(("argstr: evalvar('%s')\n", p)); | ||
6494 | p = evalvar(p, flags, var_str_list); | 6496 | p = evalvar(p, flags, var_str_list); |
6497 | TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock())); | ||
6495 | goto start; | 6498 | goto start; |
6496 | case CTLBACKQ: | 6499 | case CTLBACKQ: |
6497 | c = '\0'; | 6500 | c = '\0'; |
@@ -7199,8 +7202,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) | |||
7199 | patloc = expdest - (char *)stackblock(); | 7202 | patloc = expdest - (char *)stackblock(); |
7200 | if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, | 7203 | if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, |
7201 | startloc, varflags, | 7204 | startloc, varflags, |
7202 | //TODO: | EXP_REDIR too? All other such places do it too | 7205 | /* quotes: */ flags & (EXP_FULL | EXP_CASE | EXP_REDIR), |
7203 | /* quotes: */ flags & (EXP_FULL | EXP_CASE), | ||
7204 | var_str_list) | 7206 | var_str_list) |
7205 | ) { | 7207 | ) { |
7206 | int amount = expdest - ( | 7208 | int amount = expdest - ( |
@@ -7602,6 +7604,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag) | |||
7602 | STARTSTACKSTR(expdest); | 7604 | STARTSTACKSTR(expdest); |
7603 | ifsfirst.next = NULL; | 7605 | ifsfirst.next = NULL; |
7604 | ifslastp = NULL; | 7606 | ifslastp = NULL; |
7607 | TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag)); | ||
7605 | argstr(arg->narg.text, flag, | 7608 | argstr(arg->narg.text, flag, |
7606 | /* var_str_list: */ arglist ? arglist->list : NULL); | 7609 | /* var_str_list: */ arglist ? arglist->list : NULL); |
7607 | p = _STPUTC('\0', expdest); | 7610 | p = _STPUTC('\0', expdest); |
@@ -7610,6 +7613,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag) | |||
7610 | return; /* here document expanded */ | 7613 | return; /* here document expanded */ |
7611 | } | 7614 | } |
7612 | p = grabstackstr(p); | 7615 | p = grabstackstr(p); |
7616 | TRACE(("expandarg: p:'%s'\n", p)); | ||
7613 | exparg.lastp = &exparg.list; | 7617 | exparg.lastp = &exparg.list; |
7614 | /* | 7618 | /* |
7615 | * TODO - EXP_REDIR | 7619 | * TODO - EXP_REDIR |
@@ -7620,8 +7624,10 @@ expandarg(union node *arg, struct arglist *arglist, int flag) | |||
7620 | exparg.lastp = &exparg.list; | 7624 | exparg.lastp = &exparg.list; |
7621 | expandmeta(exparg.list /*, flag*/); | 7625 | expandmeta(exparg.list /*, flag*/); |
7622 | } else { | 7626 | } else { |
7623 | if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ | 7627 | if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */ |
7624 | rmescapes(p, 0); | 7628 | rmescapes(p, 0); |
7629 | TRACE(("expandarg: rmescapes:'%s'\n", p)); | ||
7630 | } | ||
7625 | sp = stzalloc(sizeof(*sp)); | 7631 | sp = stzalloc(sizeof(*sp)); |
7626 | sp->text = p; | 7632 | sp->text = p; |
7627 | *exparg.lastp = sp; | 7633 | *exparg.lastp = sp; |
@@ -9090,6 +9096,7 @@ expredir(union node *n) | |||
9090 | case NCLOBBER: | 9096 | case NCLOBBER: |
9091 | case NAPPEND: | 9097 | case NAPPEND: |
9092 | expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); | 9098 | expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); |
9099 | TRACE(("expredir expanded to '%s'\n", fn.list->text)); | ||
9093 | #if ENABLE_ASH_BASH_COMPAT | 9100 | #if ENABLE_ASH_BASH_COMPAT |
9094 | store_expfname: | 9101 | store_expfname: |
9095 | #endif | 9102 | #endif |
@@ -13343,6 +13350,10 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
13343 | } | 13350 | } |
13344 | } | 13351 | } |
13345 | 13352 | ||
13353 | /* "read -s" needs to save/restore termios, can't allow ^C | ||
13354 | * to jump out of it. | ||
13355 | */ | ||
13356 | INT_OFF; | ||
13346 | r = shell_builtin_read(setvar2, | 13357 | r = shell_builtin_read(setvar2, |
13347 | argptr, | 13358 | argptr, |
13348 | bltinlookup("IFS"), /* can be NULL */ | 13359 | bltinlookup("IFS"), /* can be NULL */ |
@@ -13352,6 +13363,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
13352 | opt_t, | 13363 | opt_t, |
13353 | opt_u | 13364 | opt_u |
13354 | ); | 13365 | ); |
13366 | INT_ON; | ||
13355 | 13367 | ||
13356 | if ((uintptr_t)r > 1) | 13368 | if ((uintptr_t)r > 1) |
13357 | ash_msg_and_raise_error(r); | 13369 | ash_msg_and_raise_error(r); |
diff --git a/shell/ash_test/ash-redir/redirA.right b/shell/ash_test/ash-redir/redirA.right new file mode 100644 index 000000000..31406e336 --- /dev/null +++ b/shell/ash_test/ash-redir/redirA.right | |||
@@ -0,0 +1,2 @@ | |||
1 | tmp11 | ||
2 | tmp11 | ||
diff --git a/shell/ash_test/ash-redir/redirA.tests b/shell/ash_test/ash-redir/redirA.tests new file mode 100755 index 000000000..56833f938 --- /dev/null +++ b/shell/ash_test/ash-redir/redirA.tests | |||
@@ -0,0 +1,11 @@ | |||
1 | x="tmp11:tmp22" | ||
2 | |||
3 | # Bug was incorrectly expanding variables in >redir | ||
4 | echo "${x%:*}" >"${x%:*}" | ||
5 | echo tmp1* | ||
6 | rm tmp1* | ||
7 | |||
8 | # Also try unquoted | ||
9 | echo "${x%:*}" >${x%:*} | ||
10 | echo tmp1* | ||
11 | rm tmp1* | ||
diff --git a/shell/shell_common.c b/shell/shell_common.c index 0ffe21e0b..f7503cac5 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -18,6 +18,9 @@ | |||
18 | */ | 18 | */ |
19 | #include "libbb.h" | 19 | #include "libbb.h" |
20 | #include "shell_common.h" | 20 | #include "shell_common.h" |
21 | #if !ENABLE_PLATFORM_MINGW32 | ||
22 | #include <sys/resource.h> /* getrlimit */ | ||
23 | #endif | ||
21 | 24 | ||
22 | const char defifsvar[] ALIGN1 = "IFS= \t\n"; | 25 | const char defifsvar[] ALIGN1 = "IFS= \t\n"; |
23 | 26 | ||
@@ -169,7 +172,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
169 | int timeout; | 172 | int timeout; |
170 | 173 | ||
171 | if ((bufpos & 0xff) == 0) | 174 | if ((bufpos & 0xff) == 0) |
172 | buffer = xrealloc(buffer, bufpos + 0x100); | 175 | buffer = xrealloc(buffer, bufpos + 0x101); |
173 | 176 | ||
174 | timeout = -1; | 177 | timeout = -1; |
175 | if (end_ms) { | 178 | if (end_ms) { |
diff --git a/shell/shell_common.h b/shell/shell_common.h index f06bc4120..993ed5951 100644 --- a/shell/shell_common.h +++ b/shell/shell_common.h | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | 22 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN |
23 | 23 | ||
24 | extern const char defifsvar[]; /* "IFS= \t\n" */ | 24 | extern const char defifsvar[] ALIGN1; /* "IFS= \t\n" */ |
25 | #define defifs (defifsvar + 4) | 25 | #define defifs (defifsvar + 4) |
26 | 26 | ||
27 | int FAST_FUNC is_well_formed_var_name(const char *s, char terminator); | 27 | int FAST_FUNC is_well_formed_var_name(const char *s, char terminator); |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 5a323047d..f9c3b6b4d 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -16,6 +16,13 @@ testing "awk -F case 5" "awk -F '[#]' '{ print NF }'" "4\n" "" "#abc##zz\n" | |||
16 | testing "awk -F case 6" "awk -F '[#]' '{ print NF }'" "4\n" "" "z#abc##zz\n" | 16 | testing "awk -F case 6" "awk -F '[#]' '{ print NF }'" "4\n" "" "z#abc##zz\n" |
17 | testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n" | 17 | testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n" |
18 | 18 | ||
19 | # conditions and operators | ||
20 | testing "awk if operator == " "awk 'BEGIN{if(23==23) print \"foo\"}'" "foo\n" "" "" | ||
21 | testing "awk if operator != " "awk 'BEGIN{if(23!=23) print \"bar\"}'" "" "" "" | ||
22 | testing "awk if operator >= " "awk 'BEGIN{if(23>=23) print \"foo\"}'" "foo\n" "" "" | ||
23 | testing "awk if operator < " "awk 'BEGIN{if(2 < 13) print \"foo\"}'" "foo\n" "" "" | ||
24 | testing "awk if string == " "awk 'BEGIN{if(\"a\"==\"ab\") print \"bar\"}'" "" "" "" | ||
25 | |||
19 | # 4294967295 = 0xffffffff | 26 | # 4294967295 = 0xffffffff |
20 | testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" | 27 | testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" |
21 | optional DESKTOP | 28 | optional DESKTOP |
@@ -36,6 +43,11 @@ testing "awk long field sep" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ | |||
36 | "" \ | 43 | "" \ |
37 | "a--\na--b--\na--b--c--\na--b--c--d--" | 44 | "a--\na--b--\na--b--c--\na--b--c--d--" |
38 | 45 | ||
46 | testing "awk -F handles escapes" "awk -F'\\x21' '{print \$1}'" \ | ||
47 | "a\n" \ | ||
48 | "" \ | ||
49 | "a!b\n" | ||
50 | |||
39 | # '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'), | 51 | # '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'), |
40 | # but gawk 3.1.5 does not bail out on it. | 52 | # but gawk 3.1.5 does not bail out on it. |
41 | testing "awk gsub falls back to non-extended-regex" \ | 53 | testing "awk gsub falls back to non-extended-regex" \ |
@@ -205,4 +217,11 @@ end d | |||
205 | testing "awk handles empty ()" \ | 217 | testing "awk handles empty ()" \ |
206 | "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" "" | 218 | "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" "" |
207 | 219 | ||
220 | testing "awk FS assignment" "awk '{FS=\":\"; print \$1}'" \ | ||
221 | "a:b\ne\n" \ | ||
222 | "" \ | ||
223 | "a:b c:d\ne:f g:h" | ||
224 | |||
225 | # testing "description" "command" "result" "infile" "stdin" | ||
226 | |||
208 | exit $FAILCOUNT | 227 | exit $FAILCOUNT |
diff --git a/testsuite/du/du-k-works b/testsuite/du/du-k-works index 229a948ee..36dcaa85d 100644 --- a/testsuite/du/du-k-works +++ b/testsuite/du/du-k-works | |||
@@ -3,4 +3,5 @@ cd du.testdir | |||
3 | dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null | 3 | dd if=/dev/zero of=file1 bs=1k count=64 2>/dev/null |
4 | dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null | 4 | dd if=/dev/zero of=file2 bs=1k count=16 2>/dev/null |
5 | test x"`busybox du -k .`" = x"80 ." \ | 5 | test x"`busybox du -k .`" = x"80 ." \ |
6 | -o x"`busybox du -k .`" = x"84 ." \ | ||
6 | -o x"`busybox du -k .`" = x"88 ." | 7 | -o x"`busybox du -k .`" = x"88 ." |
diff --git a/testsuite/mkfs.minix.tests b/testsuite/mkfs.minix.tests index 8a33c1681..7eecaf230 100755 --- a/testsuite/mkfs.minix.tests +++ b/testsuite/mkfs.minix.tests | |||
@@ -8,6 +8,14 @@ | |||
8 | 8 | ||
9 | # testing "test name" "options" "expected result" "file input" "stdin" | 9 | # testing "test name" "options" "expected result" "file input" "stdin" |
10 | 10 | ||
11 | # '\n' produces 10 on little endian, but not on big endian | ||
12 | cr=`echo | od -i | sed 's/.* //g;2d'` | ||
13 | if [ x"$cr" = x"10" ]; then | ||
14 | hash=4f35f7afeba07d56055bed1f29ae20b7 | ||
15 | else | ||
16 | hash=5adbc1b3ccd20ca5d0ab5bc1e13ac3fc | ||
17 | fi | ||
18 | |||
11 | testing "mkfs.minix" \ | 19 | testing "mkfs.minix" \ |
12 | "dd if=/dev/zero of=input bs=1k count=1024 2>/dev/null; mkfs.minix input; md5sum <input" \ | 20 | "dd if=/dev/zero of=input bs=1k count=1024 2>/dev/null; mkfs.minix input; md5sum <input" \ |
13 | "352 inodes\n"\ | 21 | "352 inodes\n"\ |
@@ -15,7 +23,7 @@ testing "mkfs.minix" \ | |||
15 | "Firstdatazone=15 (15)\n"\ | 23 | "Firstdatazone=15 (15)\n"\ |
16 | "Zonesize=1024\n"\ | 24 | "Zonesize=1024\n"\ |
17 | "Maxsize=268966912\n"\ | 25 | "Maxsize=268966912\n"\ |
18 | "4f35f7afeba07d56055bed1f29ae20b7 -\n" \ | 26 | "$hash -\n" \ |
19 | "" \ | 27 | "" \ |
20 | "" | 28 | "" |
21 | 29 | ||
diff --git a/testsuite/mount.tests b/testsuite/mount.tests index c5891be83..a0bc50888 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests | |||
@@ -36,7 +36,8 @@ testing "mount -o remount,mand" \ | |||
36 | "mount -o loop mount.image1m $testdir "\ | 36 | "mount -o loop mount.image1m $testdir "\ |
37 | "&& grep -Fc $testdir </proc/mounts "\ | 37 | "&& grep -Fc $testdir </proc/mounts "\ |
38 | "&& mount -o remount,mand $testdir "\ | 38 | "&& mount -o remount,mand $testdir "\ |
39 | "&& grep -F $testdir </proc/mounts | grep -c '[, ]mand[, ]'" \ | 39 | "&& grep -F $testdir </proc/mounts | grep -c '[, ]mand[, ]'"\ |
40 | "|| grep -F $testdir </proc/mounts" \ | ||
40 | "1\n""1\n" \ | 41 | "1\n""1\n" \ |
41 | "" "" | 42 | "" "" |
42 | 43 | ||
@@ -83,4 +84,28 @@ b | |||
83 | "" "" | 84 | "" "" |
84 | SKIP= | 85 | SKIP= |
85 | 86 | ||
87 | |||
88 | testing "mount RO loop" "\ | ||
89 | exec 2>&1 | ||
90 | umount -d mount.dir 2>/dev/null | ||
91 | rmdir mount.dir 2>/dev/null | ||
92 | mkdir -p mount.dir | ||
93 | ( | ||
94 | cd mount.dir || { echo 'cd error'; exit 1; } | ||
95 | mkdir z1 z2 || { echo 'mkdir error'; exit 1; } | ||
96 | mount -t tmpfs tmpfs z1 || { echo 'mount tmpfs error'; exit 1; } | ||
97 | dd if=/dev/zero of=z1/e2img count=10 bs=1M 2>/dev/null || { echo 'dd error'; exit 1; } | ||
98 | mke2fs -F z1/e2img 2>/dev/null >&2 || { echo 'mke2fs error'; exit 1; } | ||
99 | mount -r -o loop -t ext2 z1/e2img z2 || { echo 'mount -r -o loop error'; exit 1; } | ||
100 | mount -o remount,ro z1 || { echo 'mount -o remount,ro error'; exit 1; } | ||
101 | ) | ||
102 | umount -d mount.dir/z2 | ||
103 | ##losetup -d /dev/loop* | ||
104 | umount -d mount.dir/z1 | ||
105 | rm -rf mount.dir | ||
106 | echo DONE | ||
107 | " \ | ||
108 | "DONE\n" "" "" | ||
109 | |||
110 | |||
86 | exit $FAILCOUNT | 111 | exit $FAILCOUNT |
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 9fa8e190c..468565f47 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
@@ -52,10 +52,8 @@ testing "sed with empty match" "sed 's/z*//g'" "string\n" "" "string\n" | |||
52 | testing "sed s//p" "sed -e s/foo/bar/p -e s/bar/baz/p" "bar\nbaz\nbaz\n" \ | 52 | testing "sed s//p" "sed -e s/foo/bar/p -e s/bar/baz/p" "bar\nbaz\nbaz\n" \ |
53 | "" "foo\n" | 53 | "" "foo\n" |
54 | testing "sed -n s//p" "sed -ne s/abc/def/p" "def\n" "" "abc\n" | 54 | testing "sed -n s//p" "sed -ne s/abc/def/p" "def\n" "" "abc\n" |
55 | test x"$SKIP_KNOWN_BUGS" = x"" && { | ||
56 | testing "sed s//g (exhaustive)" "sed -e 's/[[:space:]]*/,/g'" ",1,2,3,4,5,\n" \ | 55 | testing "sed s//g (exhaustive)" "sed -e 's/[[:space:]]*/,/g'" ",1,2,3,4,5,\n" \ |
57 | "" "12345\n" | 56 | "" "12345\n" |
58 | } | ||
59 | testing "sed s arbitrary delimiter" "sed -e 's woo boing '" "boing\n" "" "woo\n" | 57 | testing "sed s arbitrary delimiter" "sed -e 's woo boing '" "boing\n" "" "woo\n" |
60 | testing "sed s chains" "sed -e s/foo/bar/ -e s/bar/baz/" "baz\n" "" "foo\n" | 58 | testing "sed s chains" "sed -e s/foo/bar/ -e s/bar/baz/" "baz\n" "" "foo\n" |
61 | testing "sed s chains2" "sed -e s/foo/bar/ -e s/baz/nee/" "bar\n" "" "foo\n" | 59 | testing "sed s chains2" "sed -e s/foo/bar/ -e s/baz/nee/" "bar\n" "" "foo\n" |
@@ -296,6 +294,22 @@ testing "sed -i finishes ranges correctly" \ | |||
296 | "sed '1,2d' -i input; echo \$?; cat input" \ | 294 | "sed '1,2d' -i input; echo \$?; cat input" \ |
297 | "0\n3\n4\n" "1\n2\n3\n4\n" "" | 295 | "0\n3\n4\n" "1\n2\n3\n4\n" "" |
298 | 296 | ||
297 | testing "sed zero chars match/replace advances correctly 1" \ | ||
298 | "sed 's/l*/@/g'" \ | ||
299 | "@h@e@o@\n" "" "helllo\n" | ||
300 | |||
301 | testing "sed zero chars match/replace advances correctly 2" \ | ||
302 | "sed 's [^ .]* x g'" \ | ||
303 | "x x.x\n" "" " a.b\n" | ||
304 | |||
305 | testing "sed zero chars match/replace logic must not falsely trigger here 1" \ | ||
306 | "sed 's/a/A/g'" \ | ||
307 | "_AAA1AA\n" "" "_aaa1aa\n" | ||
308 | |||
309 | testing "sed zero chars match/replace logic must not falsely trigger here 2" \ | ||
310 | "sed 's/ *$/_/g'" \ | ||
311 | "qwerty_\n" "" "qwerty\n" | ||
312 | |||
299 | # testing "description" "commands" "result" "infile" "stdin" | 313 | # testing "description" "commands" "result" "infile" "stdin" |
300 | 314 | ||
301 | exit $FAILCOUNT | 315 | exit $FAILCOUNT |
diff --git a/util-linux/Config.src b/util-linux/Config.src index 57a52cefb..3355e9729 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src | |||
@@ -762,6 +762,13 @@ config FEATURE_VOLUMEID_XFS | |||
762 | help | 762 | help |
763 | TODO | 763 | TODO |
764 | 764 | ||
765 | config FEATURE_VOLUMEID_NILFS | ||
766 | bool "nilfs filesystem" | ||
767 | default y | ||
768 | depends on VOLUMEID | ||
769 | help | ||
770 | TODO | ||
771 | |||
765 | config FEATURE_VOLUMEID_NTFS | 772 | config FEATURE_VOLUMEID_NTFS |
766 | bool "ntfs filesystem" | 773 | bool "ntfs filesystem" |
767 | default y | 774 | default y |
diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 1b22f3a01..5d2792948 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c | |||
@@ -75,6 +75,7 @@ struct acpi_event { | |||
75 | static const struct acpi_event f_evt_tab[] = { | 75 | static const struct acpi_event f_evt_tab[] = { |
76 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" }, | 76 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" }, |
77 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" }, | 77 | { "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" }, |
78 | { "EV_SW", 0x05, "SW_LID", 0x00, 1, "button/lid LID0 00000080" }, | ||
78 | }; | 79 | }; |
79 | 80 | ||
80 | struct acpi_action { | 81 | struct acpi_action { |
diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 196c2aa24..e9aacce4f 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c | |||
@@ -271,7 +271,7 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, | |||
271 | } | 271 | } |
272 | p = token[1]; | 272 | p = token[1]; |
273 | i = index_in_strings( | 273 | i = index_in_strings( |
274 | "geometry\0timings\0interlaced\0double\0vsync\0hsync\0csync\0extsync\0", | 274 | "geometry\0timings\0interlaced\0double\0vsync\0hsync\0csync\0extsync\0rgba\0", |
275 | token[0]); | 275 | token[0]); |
276 | switch (i) { | 276 | switch (i) { |
277 | case 0: | 277 | case 0: |
@@ -342,6 +342,30 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, | |||
342 | ss(&base->sync, FB_SYNC_EXT, p, "false"); | 342 | ss(&base->sync, FB_SYNC_EXT, p, "false"); |
343 | //bb_info_msg("EXTSYNC[%s]", p); | 343 | //bb_info_msg("EXTSYNC[%s]", p); |
344 | break; | 344 | break; |
345 | case 8: { | ||
346 | int red_offset, red_length; | ||
347 | int green_offset, green_length; | ||
348 | int blue_offset, blue_length; | ||
349 | int transp_offset, transp_length; | ||
350 | |||
351 | sscanf(p, "%d/%d,%d/%d,%d/%d,%d/%d", | ||
352 | &red_offset, &red_length, | ||
353 | &green_offset, &green_length, | ||
354 | &blue_offset, &blue_length, | ||
355 | &transp_offset, &transp_length); | ||
356 | base->red.offset = red_offset; | ||
357 | base->red.length = red_length; | ||
358 | base->red.msb_right = 0; | ||
359 | base->green.offset = green_offset; | ||
360 | base->green.length = green_length; | ||
361 | base->green.msb_right = 0; | ||
362 | base->blue.offset = blue_offset; | ||
363 | base->blue.length = blue_length; | ||
364 | base->blue.msb_right = 0; | ||
365 | base->transp.offset = transp_offset; | ||
366 | base->transp.length = transp_length; | ||
367 | base->transp.msb_right = 0; | ||
368 | } | ||
345 | } | 369 | } |
346 | } | 370 | } |
347 | return 0; | 371 | return 0; |
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 0a34122b4..79871d30e 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
@@ -92,7 +92,9 @@ | |||
92 | //usage: "\n" | 92 | //usage: "\n" |
93 | //usage: "If /dev/mdev.seq file exists, mdev will wait for its value\n" | 93 | //usage: "If /dev/mdev.seq file exists, mdev will wait for its value\n" |
94 | //usage: "to match $SEQNUM variable. This prevents plug/unplug races.\n" | 94 | //usage: "to match $SEQNUM variable. This prevents plug/unplug races.\n" |
95 | //usage: "To activate this feature, create empty /dev/mdev.seq at boot." | 95 | //usage: "To activate this feature, create empty /dev/mdev.seq at boot.\n" |
96 | //usage: "\n" | ||
97 | //usage: "If /dev/mdev.log file exists, debug log will be appended to it." | ||
96 | 98 | ||
97 | #include "libbb.h" | 99 | #include "libbb.h" |
98 | #include "xregex.h" | 100 | #include "xregex.h" |
@@ -139,10 +141,101 @@ | |||
139 | * This happens regardless of /sys/class/.../dev existence. | 141 | * This happens regardless of /sys/class/.../dev existence. |
140 | */ | 142 | */ |
141 | 143 | ||
144 | /* Kernel's hotplug environment constantly changes. | ||
145 | * Here are new cases I observed on 3.1.0: | ||
146 | * | ||
147 | * Case with $DEVNAME and $DEVICE, not just $DEVPATH: | ||
148 | * ACTION=add | ||
149 | * BUSNUM=001 | ||
150 | * DEVICE=/proc/bus/usb/001/003 | ||
151 | * DEVNAME=bus/usb/001/003 | ||
152 | * DEVNUM=003 | ||
153 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5 | ||
154 | * DEVTYPE=usb_device | ||
155 | * MAJOR=189 | ||
156 | * MINOR=2 | ||
157 | * PRODUCT=18d1/4e12/227 | ||
158 | * SUBSYSTEM=usb | ||
159 | * TYPE=0/0/0 | ||
160 | * | ||
161 | * Case with $DEVICE, but no $DEVNAME - apparenty, usb iface notification? | ||
162 | * "Please load me a module" thing? | ||
163 | * ACTION=add | ||
164 | * DEVICE=/proc/bus/usb/001/003 | ||
165 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0 | ||
166 | * DEVTYPE=usb_interface | ||
167 | * INTERFACE=8/6/80 | ||
168 | * MODALIAS=usb:v18D1p4E12d0227dc00dsc00dp00ic08isc06ip50 | ||
169 | * PRODUCT=18d1/4e12/227 | ||
170 | * SUBSYSTEM=usb | ||
171 | * TYPE=0/0/0 | ||
172 | * | ||
173 | * ACTION=add | ||
174 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5 | ||
175 | * DEVTYPE=scsi_host | ||
176 | * SUBSYSTEM=scsi | ||
177 | * | ||
178 | * ACTION=add | ||
179 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/scsi_host/host5 | ||
180 | * SUBSYSTEM=scsi_host | ||
181 | * | ||
182 | * ACTION=add | ||
183 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0 | ||
184 | * DEVTYPE=scsi_target | ||
185 | * SUBSYSTEM=scsi | ||
186 | * | ||
187 | * Case with strange $MODALIAS: | ||
188 | * ACTION=add | ||
189 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0/5:0:0:0 | ||
190 | * DEVTYPE=scsi_device | ||
191 | * MODALIAS=scsi:t-0x00 | ||
192 | * SUBSYSTEM=scsi | ||
193 | * | ||
194 | * ACTION=add | ||
195 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0/5:0:0:0/scsi_disk/5:0:0:0 | ||
196 | * SUBSYSTEM=scsi_disk | ||
197 | * | ||
198 | * ACTION=add | ||
199 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0/5:0:0:0/scsi_device/5:0:0:0 | ||
200 | * SUBSYSTEM=scsi_device | ||
201 | * | ||
202 | * Case with explicit $MAJOR/$MINOR (no need to read /sys/$DEVPATH/dev?): | ||
203 | * ACTION=add | ||
204 | * DEVNAME=bsg/5:0:0:0 | ||
205 | * DEVPATH=/devices/pci0000:00/0000:00:02.1/usb1/1-5/1-5:1.0/host5/target5:0:0/5:0:0:0/bsg/5:0:0:0 | ||
206 | * MAJOR=253 | ||
207 | * MINOR=1 | ||
208 | * SUBSYSTEM=bsg | ||
209 | * | ||
210 | * ACTION=add | ||
211 | * DEVPATH=/devices/virtual/bdi/8:16 | ||
212 | * SUBSYSTEM=bdi | ||
213 | * | ||
214 | * ACTION=add | ||
215 | * DEVNAME=sdb | ||
216 | * DEVPATH=/block/sdb | ||
217 | * DEVTYPE=disk | ||
218 | * MAJOR=8 | ||
219 | * MINOR=16 | ||
220 | * SUBSYSTEM=block | ||
221 | * | ||
222 | * Case with ACTION=change: | ||
223 | * ACTION=change | ||
224 | * DEVNAME=sdb | ||
225 | * DEVPATH=/block/sdb | ||
226 | * DEVTYPE=disk | ||
227 | * DISK_MEDIA_CHANGE=1 | ||
228 | * MAJOR=8 | ||
229 | * MINOR=16 | ||
230 | * SUBSYSTEM=block | ||
231 | */ | ||
232 | |||
233 | static const char keywords[] ALIGN1 = "add\0remove\0change\0"; | ||
234 | enum { OP_add, OP_remove }; | ||
235 | |||
142 | struct rule { | 236 | struct rule { |
143 | bool keep_matching; | 237 | bool keep_matching; |
144 | bool regex_compiled; | 238 | bool regex_compiled; |
145 | bool regex_has_slash; | ||
146 | mode_t mode; | 239 | mode_t mode; |
147 | int maj, min0, min1; | 240 | int maj, min0, min1; |
148 | struct bb_uidgid_t ugid; | 241 | struct bb_uidgid_t ugid; |
@@ -154,6 +247,7 @@ struct rule { | |||
154 | 247 | ||
155 | struct globals { | 248 | struct globals { |
156 | int root_major, root_minor; | 249 | int root_major, root_minor; |
250 | smallint verbose; | ||
157 | char *subsystem; | 251 | char *subsystem; |
158 | #if ENABLE_FEATURE_MDEV_CONF | 252 | #if ENABLE_FEATURE_MDEV_CONF |
159 | const char *filename; | 253 | const char *filename; |
@@ -245,7 +339,6 @@ static void parse_next_rule(void) | |||
245 | } | 339 | } |
246 | xregcomp(&G.cur_rule.match, val, REG_EXTENDED); | 340 | xregcomp(&G.cur_rule.match, val, REG_EXTENDED); |
247 | G.cur_rule.regex_compiled = 1; | 341 | G.cur_rule.regex_compiled = 1; |
248 | G.cur_rule.regex_has_slash = (strchr(val, '/') != NULL); | ||
249 | } | 342 | } |
250 | 343 | ||
251 | /* 2nd field: uid:gid - device ownership */ | 344 | /* 2nd field: uid:gid - device ownership */ |
@@ -366,13 +459,16 @@ static char *build_alias(char *alias, const char *device_name) | |||
366 | * after NUL, but we promise to not mangle (IOW: to restore if needed) | 459 | * after NUL, but we promise to not mangle (IOW: to restore if needed) |
367 | * path string. | 460 | * path string. |
368 | * NB2: "mdev -s" may call us many times, do not leak memory/fds! | 461 | * NB2: "mdev -s" may call us many times, do not leak memory/fds! |
462 | * | ||
463 | * device_name = $DEVNAME (may be NULL) | ||
464 | * path = /sys/$DEVPATH | ||
369 | */ | 465 | */ |
370 | static void make_device(char *path, int delete) | 466 | static void make_device(char *device_name, char *path, int operation) |
371 | { | 467 | { |
372 | char *device_name, *subsystem_slash_devname; | ||
373 | int major, minor, type, len; | 468 | int major, minor, type, len; |
374 | 469 | ||
375 | dbg("%s('%s', delete:%d)", __func__, path, delete); | 470 | if (G.verbose) |
471 | bb_error_msg("device: %s, %s", device_name, path); | ||
376 | 472 | ||
377 | /* Try to read major/minor string. Note that the kernel puts \n after | 473 | /* Try to read major/minor string. Note that the kernel puts \n after |
378 | * the data, so we don't need to worry about null terminating the string | 474 | * the data, so we don't need to worry about null terminating the string |
@@ -380,7 +476,7 @@ static void make_device(char *path, int delete) | |||
380 | * We also depend on path having writeable space after it. | 476 | * We also depend on path having writeable space after it. |
381 | */ | 477 | */ |
382 | major = -1; | 478 | major = -1; |
383 | if (!delete) { | 479 | if (operation == OP_add) { |
384 | char *dev_maj_min = path + strlen(path); | 480 | char *dev_maj_min = path + strlen(path); |
385 | 481 | ||
386 | strcpy(dev_maj_min, "/dev"); | 482 | strcpy(dev_maj_min, "/dev"); |
@@ -391,40 +487,27 @@ static void make_device(char *path, int delete) | |||
391 | return; | 487 | return; |
392 | /* no "dev" file, but we can still run scripts | 488 | /* no "dev" file, but we can still run scripts |
393 | * based on device name */ | 489 | * based on device name */ |
394 | } else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) != 2) { | 490 | } else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) == 2) { |
491 | if (G.verbose) | ||
492 | bb_error_msg("maj,min: %u,%u", major, minor); | ||
493 | } else { | ||
395 | major = -1; | 494 | major = -1; |
396 | } | 495 | } |
397 | } | 496 | } |
398 | /* else: for delete, -1 still deletes the node, but < -1 suppresses that */ | 497 | /* else: for delete, -1 still deletes the node, but < -1 suppresses that */ |
399 | 498 | ||
400 | /* Determine device name, type, major and minor */ | 499 | /* Determine device name, type, major and minor */ |
401 | device_name = (char*) bb_basename(path); | 500 | if (!device_name) |
501 | device_name = (char*) bb_basename(path); | ||
402 | /* http://kernel.org/doc/pending/hotplug.txt says that only | 502 | /* http://kernel.org/doc/pending/hotplug.txt says that only |
403 | * "/sys/block/..." is for block devices. "/sys/bus" etc is not. | 503 | * "/sys/block/..." is for block devices. "/sys/bus" etc is not. |
404 | * But since 2.6.25 block devices are also in /sys/class/block. | 504 | * But since 2.6.25 block devices are also in /sys/class/block. |
405 | * We use strstr("/block/") to forestall future surprises. */ | 505 | * We use strstr("/block/") to forestall future surprises. |
506 | */ | ||
406 | type = S_IFCHR; | 507 | type = S_IFCHR; |
407 | if (strstr(path, "/block/") || (G.subsystem && strncmp(G.subsystem, "block", 5) == 0)) | 508 | if (strstr(path, "/block/") || (G.subsystem && strncmp(G.subsystem, "block", 5) == 0)) |
408 | type = S_IFBLK; | 509 | type = S_IFBLK; |
409 | 510 | ||
410 | /* Make path point to "subsystem/device_name" */ | ||
411 | subsystem_slash_devname = NULL; | ||
412 | /* Check for coldplug invocations first */ | ||
413 | if (strncmp(path, "/sys/block/", 11) == 0) /* legacy case */ | ||
414 | path += sizeof("/sys/") - 1; | ||
415 | else if (strncmp(path, "/sys/class/", 11) == 0) | ||
416 | path += sizeof("/sys/class/") - 1; | ||
417 | else { | ||
418 | /* Example of a hotplug invocation: | ||
419 | * SUBSYSTEM="block" | ||
420 | * DEVPATH="/sys" + "/devices/virtual/mtd/mtd3/mtdblock3" | ||
421 | * ("/sys" is added by mdev_main) | ||
422 | * - path does not contain subsystem | ||
423 | */ | ||
424 | subsystem_slash_devname = concat_path_file(G.subsystem, device_name); | ||
425 | path = subsystem_slash_devname; | ||
426 | } | ||
427 | |||
428 | #if ENABLE_FEATURE_MDEV_CONF | 511 | #if ENABLE_FEATURE_MDEV_CONF |
429 | G.rule_idx = 0; /* restart from the beginning (think mdev -s) */ | 512 | G.rule_idx = 0; /* restart from the beginning (think mdev -s) */ |
430 | #endif | 513 | #endif |
@@ -434,10 +517,10 @@ static void make_device(char *path, int delete) | |||
434 | char *command; | 517 | char *command; |
435 | char *alias; | 518 | char *alias; |
436 | char aliaslink = aliaslink; /* for compiler */ | 519 | char aliaslink = aliaslink; /* for compiler */ |
437 | const char *node_name; | 520 | char *node_name; |
438 | const struct rule *rule; | 521 | const struct rule *rule; |
439 | 522 | ||
440 | str_to_match = ""; | 523 | str_to_match = device_name; |
441 | 524 | ||
442 | rule = next_rule(); | 525 | rule = next_rule(); |
443 | 526 | ||
@@ -455,10 +538,8 @@ static void make_device(char *path, int delete) | |||
455 | dbg("getenv('%s'):'%s'", rule->envvar, str_to_match); | 538 | dbg("getenv('%s'):'%s'", rule->envvar, str_to_match); |
456 | if (!str_to_match) | 539 | if (!str_to_match) |
457 | continue; | 540 | continue; |
458 | } else { | ||
459 | /* regex to match [subsystem/]device_name */ | ||
460 | str_to_match = (rule->regex_has_slash ? path : device_name); | ||
461 | } | 541 | } |
542 | /* else: str_to_match = device_name */ | ||
462 | 543 | ||
463 | if (rule->regex_compiled) { | 544 | if (rule->regex_compiled) { |
464 | int regex_match = regexec(&rule->match, str_to_match, ARRAY_SIZE(off), off, 0); | 545 | int regex_match = regexec(&rule->match, str_to_match, ARRAY_SIZE(off), off, 0); |
@@ -537,7 +618,7 @@ static void make_device(char *path, int delete) | |||
537 | /* Are we running this command now? | 618 | /* Are we running this command now? |
538 | * Run $cmd on delete, @cmd on create, *cmd on both | 619 | * Run $cmd on delete, @cmd on create, *cmd on both |
539 | */ | 620 | */ |
540 | if (s2 - s != delete) { | 621 | if (s2 - s != (operation == OP_remove) || *s2 == '*') { |
541 | /* We are here if: '*', | 622 | /* We are here if: '*', |
542 | * or: '@' and delete = 0, | 623 | * or: '@' and delete = 0, |
543 | * or: '$' and delete = 1 | 624 | * or: '$' and delete = 1 |
@@ -556,21 +637,30 @@ static void make_device(char *path, int delete) | |||
556 | dbg("alias2:'%s'", alias); | 637 | dbg("alias2:'%s'", alias); |
557 | } | 638 | } |
558 | 639 | ||
559 | if (!delete && major >= 0) { | 640 | if (operation == OP_add && major >= 0) { |
560 | dbg("mknod('%s',%o,(%d,%d))", node_name, rule->mode | type, major, minor); | 641 | char *slash = strrchr(node_name, '/'); |
642 | if (slash) { | ||
643 | *slash = '\0'; | ||
644 | bb_make_directory(node_name, 0755, FILEUTILS_RECUR); | ||
645 | *slash = '/'; | ||
646 | } | ||
647 | if (G.verbose) | ||
648 | bb_error_msg("mknod: %s (%d,%d) %o", node_name, major, minor, rule->mode | type); | ||
561 | if (mknod(node_name, rule->mode | type, makedev(major, minor)) && errno != EEXIST) | 649 | if (mknod(node_name, rule->mode | type, makedev(major, minor)) && errno != EEXIST) |
562 | bb_perror_msg("can't create '%s'", node_name); | 650 | bb_perror_msg("can't create '%s'", node_name); |
563 | if (major == G.root_major && minor == G.root_minor) | ||
564 | symlink(node_name, "root"); | ||
565 | if (ENABLE_FEATURE_MDEV_CONF) { | 651 | if (ENABLE_FEATURE_MDEV_CONF) { |
566 | chmod(node_name, rule->mode); | 652 | chmod(node_name, rule->mode); |
567 | chown(node_name, rule->ugid.uid, rule->ugid.gid); | 653 | chown(node_name, rule->ugid.uid, rule->ugid.gid); |
568 | } | 654 | } |
655 | if (major == G.root_major && minor == G.root_minor) | ||
656 | symlink(node_name, "root"); | ||
569 | if (ENABLE_FEATURE_MDEV_RENAME && alias) { | 657 | if (ENABLE_FEATURE_MDEV_RENAME && alias) { |
570 | if (aliaslink == '>') { | 658 | if (aliaslink == '>') { |
571 | //TODO: on devtmpfs, device_name already exists and symlink() fails. | 659 | //TODO: on devtmpfs, device_name already exists and symlink() fails. |
572 | //End result is that instead of symlink, we have two nodes. | 660 | //End result is that instead of symlink, we have two nodes. |
573 | //What should be done? | 661 | //What should be done? |
662 | if (G.verbose) | ||
663 | bb_error_msg("symlink: %s", device_name); | ||
574 | symlink(node_name, device_name); | 664 | symlink(node_name, device_name); |
575 | } | 665 | } |
576 | } | 666 | } |
@@ -582,17 +672,24 @@ static void make_device(char *path, int delete) | |||
582 | char *s1 = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem); | 672 | char *s1 = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem); |
583 | putenv(s); | 673 | putenv(s); |
584 | putenv(s1); | 674 | putenv(s1); |
675 | if (G.verbose) | ||
676 | bb_error_msg("running: %s", command); | ||
585 | if (system(command) == -1) | 677 | if (system(command) == -1) |
586 | bb_perror_msg("can't run '%s'", command); | 678 | bb_perror_msg("can't run '%s'", command); |
587 | bb_unsetenv_and_free(s1); | 679 | bb_unsetenv_and_free(s1); |
588 | bb_unsetenv_and_free(s); | 680 | bb_unsetenv_and_free(s); |
589 | } | 681 | } |
590 | 682 | ||
591 | if (delete && major >= -1) { | 683 | if (operation == OP_remove && major >= -1) { |
592 | if (ENABLE_FEATURE_MDEV_RENAME && alias) { | 684 | if (ENABLE_FEATURE_MDEV_RENAME && alias) { |
593 | if (aliaslink == '>') | 685 | if (aliaslink == '>') { |
686 | if (G.verbose) | ||
687 | bb_error_msg("unlink: %s", device_name); | ||
594 | unlink(device_name); | 688 | unlink(device_name); |
689 | } | ||
595 | } | 690 | } |
691 | if (G.verbose) | ||
692 | bb_error_msg("unlink: %s", node_name); | ||
596 | unlink(node_name); | 693 | unlink(node_name); |
597 | } | 694 | } |
598 | 695 | ||
@@ -605,8 +702,6 @@ static void make_device(char *path, int delete) | |||
605 | if (!ENABLE_FEATURE_MDEV_CONF || !rule->keep_matching) | 702 | if (!ENABLE_FEATURE_MDEV_CONF || !rule->keep_matching) |
606 | break; | 703 | break; |
607 | } /* for (;;) */ | 704 | } /* for (;;) */ |
608 | |||
609 | free(subsystem_slash_devname); | ||
610 | } | 705 | } |
611 | 706 | ||
612 | /* File callback for /sys/ traversal */ | 707 | /* File callback for /sys/ traversal */ |
@@ -624,7 +719,7 @@ static int FAST_FUNC fileAction(const char *fileName, | |||
624 | 719 | ||
625 | strcpy(scratch, fileName); | 720 | strcpy(scratch, fileName); |
626 | scratch[len] = '\0'; | 721 | scratch[len] = '\0'; |
627 | make_device(scratch, /*delete:*/ 0); | 722 | make_device(/*DEVNAME:*/ NULL, scratch, OP_add); |
628 | 723 | ||
629 | return TRUE; | 724 | return TRUE; |
630 | } | 725 | } |
@@ -661,37 +756,45 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM, | |||
661 | static void load_firmware(const char *firmware, const char *sysfs_path) | 756 | static void load_firmware(const char *firmware, const char *sysfs_path) |
662 | { | 757 | { |
663 | int cnt; | 758 | int cnt; |
664 | int firmware_fd, loading_fd, data_fd; | 759 | int firmware_fd, loading_fd; |
665 | 760 | ||
666 | /* check for /lib/firmware/$FIRMWARE */ | 761 | /* check for /lib/firmware/$FIRMWARE */ |
667 | xchdir("/lib/firmware"); | 762 | xchdir("/lib/firmware"); |
668 | firmware_fd = xopen(firmware, O_RDONLY); | 763 | firmware_fd = open(firmware, O_RDONLY); /* can fail */ |
669 | |||
670 | /* in case we goto out ... */ | ||
671 | data_fd = -1; | ||
672 | 764 | ||
673 | /* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */ | 765 | /* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */ |
674 | xchdir(sysfs_path); | 766 | xchdir(sysfs_path); |
675 | for (cnt = 0; cnt < 30; ++cnt) { | 767 | for (cnt = 0; cnt < 30; ++cnt) { |
676 | loading_fd = open("loading", O_WRONLY); | 768 | loading_fd = open("loading", O_WRONLY); |
677 | if (loading_fd != -1) | 769 | if (loading_fd >= 0) |
678 | goto loading; | 770 | goto loading; |
679 | sleep(1); | 771 | sleep(1); |
680 | } | 772 | } |
681 | goto out; | 773 | goto out; |
682 | 774 | ||
683 | loading: | 775 | loading: |
684 | /* tell kernel we're loading by "echo 1 > /sys/$DEVPATH/loading" */ | 776 | cnt = 0; |
685 | if (full_write(loading_fd, "1", 1) != 1) | 777 | if (firmware_fd >= 0) { |
686 | goto out; | 778 | int data_fd; |
687 | 779 | ||
688 | /* load firmware into /sys/$DEVPATH/data */ | 780 | /* tell kernel we're loading by "echo 1 > /sys/$DEVPATH/loading" */ |
689 | data_fd = open("data", O_WRONLY); | 781 | if (full_write(loading_fd, "1", 1) != 1) |
690 | if (data_fd == -1) | 782 | goto out; |
691 | goto out; | 783 | |
692 | cnt = bb_copyfd_eof(firmware_fd, data_fd); | 784 | /* load firmware into /sys/$DEVPATH/data */ |
785 | data_fd = open("data", O_WRONLY); | ||
786 | if (data_fd < 0) | ||
787 | goto out; | ||
788 | cnt = bb_copyfd_eof(firmware_fd, data_fd); | ||
789 | if (ENABLE_FEATURE_CLEAN_UP) | ||
790 | close(data_fd); | ||
791 | } | ||
693 | 792 | ||
694 | /* tell kernel result by "echo [0|-1] > /sys/$DEVPATH/loading" */ | 793 | /* Tell kernel result by "echo [0|-1] > /sys/$DEVPATH/loading" |
794 | * Note: we emit -1 also if firmware file wasn't found. | ||
795 | * There are cases when otherwise kernel would wait for minutes | ||
796 | * before timing out. | ||
797 | */ | ||
695 | if (cnt > 0) | 798 | if (cnt > 0) |
696 | full_write(loading_fd, "0", 1); | 799 | full_write(loading_fd, "0", 1); |
697 | else | 800 | else |
@@ -701,7 +804,6 @@ static void load_firmware(const char *firmware, const char *sysfs_path) | |||
701 | if (ENABLE_FEATURE_CLEAN_UP) { | 804 | if (ENABLE_FEATURE_CLEAN_UP) { |
702 | close(firmware_fd); | 805 | close(firmware_fd); |
703 | close(loading_fd); | 806 | close(loading_fd); |
704 | close(data_fd); | ||
705 | } | 807 | } |
706 | } | 808 | } |
707 | 809 | ||
@@ -762,9 +864,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
762 | char *fw; | 864 | char *fw; |
763 | char *seq; | 865 | char *seq; |
764 | char *action; | 866 | char *action; |
765 | char *env_path; | 867 | char *env_devname; |
766 | static const char keywords[] ALIGN1 = "remove\0add\0"; | 868 | char *env_devpath; |
767 | enum { OP_remove = 0, OP_add }; | ||
768 | smalluint op; | 869 | smalluint op; |
769 | 870 | ||
770 | /* Hotplug: | 871 | /* Hotplug: |
@@ -773,12 +874,13 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
773 | * DEVPATH is like "/block/sda" or "/class/input/mice" | 874 | * DEVPATH is like "/block/sda" or "/class/input/mice" |
774 | */ | 875 | */ |
775 | action = getenv("ACTION"); | 876 | action = getenv("ACTION"); |
776 | env_path = getenv("DEVPATH"); | 877 | op = index_in_strings(keywords, action); |
878 | env_devname = getenv("DEVNAME"); /* can be NULL */ | ||
879 | env_devpath = getenv("DEVPATH"); | ||
777 | G.subsystem = getenv("SUBSYSTEM"); | 880 | G.subsystem = getenv("SUBSYSTEM"); |
778 | if (!action || !env_path /*|| !G.subsystem*/) | 881 | if (!action || !env_devpath /*|| !G.subsystem*/) |
779 | bb_show_usage(); | 882 | bb_show_usage(); |
780 | fw = getenv("FIRMWARE"); | 883 | fw = getenv("FIRMWARE"); |
781 | op = index_in_strings(keywords, action); | ||
782 | /* If it exists, does /dev/mdev.seq match $SEQNUM? | 884 | /* If it exists, does /dev/mdev.seq match $SEQNUM? |
783 | * If it does not match, earlier mdev is running | 885 | * If it does not match, earlier mdev is running |
784 | * in parallel, and we need to wait */ | 886 | * in parallel, and we need to wait */ |
@@ -804,16 +906,25 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
804 | } while (--timeout); | 906 | } while (--timeout); |
805 | } | 907 | } |
806 | 908 | ||
807 | snprintf(temp, PATH_MAX, "/sys%s", env_path); | 909 | { |
910 | int logfd = open("/dev/mdev.log", O_WRONLY | O_APPEND); | ||
911 | if (logfd >= 0) { | ||
912 | xmove_fd(logfd, STDERR_FILENO); | ||
913 | G.verbose = 1; | ||
914 | bb_error_msg("seq: %s action: %s", seq, action); | ||
915 | } | ||
916 | } | ||
917 | |||
918 | snprintf(temp, PATH_MAX, "/sys%s", env_devpath); | ||
808 | if (op == OP_remove) { | 919 | if (op == OP_remove) { |
809 | /* Ignoring "remove firmware". It was reported | 920 | /* Ignoring "remove firmware". It was reported |
810 | * to happen and to cause erroneous deletion | 921 | * to happen and to cause erroneous deletion |
811 | * of device nodes. */ | 922 | * of device nodes. */ |
812 | if (!fw) | 923 | if (!fw) |
813 | make_device(temp, /*delete:*/ 1); | 924 | make_device(env_devname, temp, op); |
814 | } | 925 | } |
815 | else if (op == OP_add) { | 926 | else if (op == OP_add) { |
816 | make_device(temp, /*delete:*/ 0); | 927 | make_device(env_devname, temp, op); |
817 | if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) { | 928 | if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) { |
818 | if (fw) | 929 | if (fw) |
819 | load_firmware(fw, temp); | 930 | load_firmware(fw, temp); |
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c index 69b25c946..3258d7eee 100644 --- a/util-linux/mkfs_ext2.c +++ b/util-linux/mkfs_ext2.c | |||
@@ -53,11 +53,6 @@ | |||
53 | #define ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT 0 | 53 | #define ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT 0 |
54 | #define ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX 1 | 54 | #define ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX 1 |
55 | 55 | ||
56 | // from e2fsprogs | ||
57 | #define s_reserved_gdt_blocks s_padding1 | ||
58 | #define s_mkfs_time s_reserved[0] | ||
59 | #define s_flags s_reserved[22] | ||
60 | |||
61 | #define EXT2_HASH_HALF_MD4 1 | 56 | #define EXT2_HASH_HALF_MD4 1 |
62 | #define EXT2_FLAGS_SIGNED_HASH 0x0001 | 57 | #define EXT2_FLAGS_SIGNED_HASH 0x0001 |
63 | #define EXT2_FLAGS_UNSIGNED_HASH 0x0002 | 58 | #define EXT2_FLAGS_UNSIGNED_HASH 0x0002 |
@@ -482,8 +477,10 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv) | |||
482 | STORE_LE(sb->s_magic, EXT2_SUPER_MAGIC); | 477 | STORE_LE(sb->s_magic, EXT2_SUPER_MAGIC); |
483 | STORE_LE(sb->s_inode_size, inodesize); | 478 | STORE_LE(sb->s_inode_size, inodesize); |
484 | // set "Required extra isize" and "Desired extra isize" fields to 28 | 479 | // set "Required extra isize" and "Desired extra isize" fields to 28 |
485 | if (inodesize != sizeof(*inode)) | 480 | if (inodesize != sizeof(*inode)) { |
486 | STORE_LE(sb->s_reserved[21], 0x001C001C); | 481 | STORE_LE(sb->s_min_extra_isize, 0x001c); |
482 | STORE_LE(sb->s_want_extra_isize, 0x001c); | ||
483 | } | ||
487 | STORE_LE(sb->s_first_ino, EXT2_GOOD_OLD_FIRST_INO); | 484 | STORE_LE(sb->s_first_ino, EXT2_GOOD_OLD_FIRST_INO); |
488 | STORE_LE(sb->s_log_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); | 485 | STORE_LE(sb->s_log_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); |
489 | STORE_LE(sb->s_log_frag_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); | 486 | STORE_LE(sb->s_log_frag_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); |
diff --git a/util-linux/mount.c b/util-linux/mount.c index f1da30fac..525fdcce9 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c | |||
@@ -113,6 +113,12 @@ | |||
113 | #ifndef MS_RELATIME | 113 | #ifndef MS_RELATIME |
114 | # define MS_RELATIME (1 << 21) | 114 | # define MS_RELATIME (1 << 21) |
115 | #endif | 115 | #endif |
116 | #ifndef MS_STRICTATIME | ||
117 | # define MS_STRICTATIME (1 << 24) | ||
118 | #endif | ||
119 | |||
120 | /* Any ~MS_FOO value has this bit set: */ | ||
121 | #define BB_MS_INVERTED_VALUE (1u << 31) | ||
116 | 122 | ||
117 | #include "libbb.h" | 123 | #include "libbb.h" |
118 | #if ENABLE_FEATURE_MOUNT_LABEL | 124 | #if ENABLE_FEATURE_MOUNT_LABEL |
@@ -218,6 +224,7 @@ static const int32_t mount_options[] = { | |||
218 | IF_DESKTOP(/* "user" */ MOUNT_USERS,) | 224 | IF_DESKTOP(/* "user" */ MOUNT_USERS,) |
219 | IF_DESKTOP(/* "users" */ MOUNT_USERS,) | 225 | IF_DESKTOP(/* "users" */ MOUNT_USERS,) |
220 | /* "_netdev" */ 0, | 226 | /* "_netdev" */ 0, |
227 | IF_DESKTOP(/* "comment" */ 0,) /* systemd uses this in fstab */ | ||
221 | ) | 228 | ) |
222 | 229 | ||
223 | IF_FEATURE_MOUNT_FLAGS( | 230 | IF_FEATURE_MOUNT_FLAGS( |
@@ -239,6 +246,7 @@ static const int32_t mount_options[] = { | |||
239 | /* "nomand" */ ~MS_MANDLOCK, | 246 | /* "nomand" */ ~MS_MANDLOCK, |
240 | /* "relatime" */ MS_RELATIME, | 247 | /* "relatime" */ MS_RELATIME, |
241 | /* "norelatime" */ ~MS_RELATIME, | 248 | /* "norelatime" */ ~MS_RELATIME, |
249 | /* "strictatime" */ MS_STRICTATIME, | ||
242 | /* "loud" */ ~MS_SILENT, | 250 | /* "loud" */ ~MS_SILENT, |
243 | /* "rbind" */ MS_BIND|MS_RECURSIVE, | 251 | /* "rbind" */ MS_BIND|MS_RECURSIVE, |
244 | 252 | ||
@@ -275,6 +283,7 @@ static const char mount_option_str[] = | |||
275 | IF_DESKTOP("user\0") | 283 | IF_DESKTOP("user\0") |
276 | IF_DESKTOP("users\0") | 284 | IF_DESKTOP("users\0") |
277 | "_netdev\0" | 285 | "_netdev\0" |
286 | IF_DESKTOP("comment\0") /* systemd uses this in fstab */ | ||
278 | ) | 287 | ) |
279 | IF_FEATURE_MOUNT_FLAGS( | 288 | IF_FEATURE_MOUNT_FLAGS( |
280 | // vfs flags | 289 | // vfs flags |
@@ -295,6 +304,7 @@ static const char mount_option_str[] = | |||
295 | "nomand\0" | 304 | "nomand\0" |
296 | "relatime\0" | 305 | "relatime\0" |
297 | "norelatime\0" | 306 | "norelatime\0" |
307 | "strictatime\0" | ||
298 | "loud\0" | 308 | "loud\0" |
299 | "rbind\0" | 309 | "rbind\0" |
300 | 310 | ||
@@ -450,9 +460,9 @@ static void append_mount_options(char **oldopts, const char *newopts) | |||
450 | 460 | ||
451 | // Use the mount_options list to parse options into flags. | 461 | // Use the mount_options list to parse options into flags. |
452 | // Also update list of unrecognized options if unrecognized != NULL | 462 | // Also update list of unrecognized options if unrecognized != NULL |
453 | static long parse_mount_options(char *options, char **unrecognized) | 463 | static unsigned long parse_mount_options(char *options, char **unrecognized) |
454 | { | 464 | { |
455 | long flags = MS_SILENT; | 465 | unsigned long flags = MS_SILENT; |
456 | 466 | ||
457 | // Loop through options | 467 | // Loop through options |
458 | for (;;) { | 468 | for (;;) { |
@@ -465,15 +475,19 @@ static long parse_mount_options(char *options, char **unrecognized) | |||
465 | // FIXME: use hasmntopt() | 475 | // FIXME: use hasmntopt() |
466 | // Find this option in mount_options | 476 | // Find this option in mount_options |
467 | for (i = 0; i < ARRAY_SIZE(mount_options); i++) { | 477 | for (i = 0; i < ARRAY_SIZE(mount_options); i++) { |
468 | if (strcasecmp(option_str, options) == 0) { | 478 | /* We support "option=" match for "comment=" thingy */ |
469 | long fl = mount_options[i]; | 479 | unsigned opt_len = strlen(option_str); |
470 | if (fl < 0) | 480 | if (strncasecmp(option_str, options, opt_len) == 0 |
481 | && (options[opt_len] == '\0' || options[opt_len] == '=') | ||
482 | ) { | ||
483 | unsigned long fl = mount_options[i]; | ||
484 | if (fl & BB_MS_INVERTED_VALUE) | ||
471 | flags &= fl; | 485 | flags &= fl; |
472 | else | 486 | else |
473 | flags |= fl; | 487 | flags |= fl; |
474 | goto found; | 488 | goto found; |
475 | } | 489 | } |
476 | option_str += strlen(option_str) + 1; | 490 | option_str += opt_len + 1; |
477 | } | 491 | } |
478 | // We did not recognize this option. | 492 | // We did not recognize this option. |
479 | // If "unrecognized" is not NULL, append option there. | 493 | // If "unrecognized" is not NULL, append option there. |
@@ -548,7 +562,7 @@ void delete_block_backed_filesystems(void); | |||
548 | 562 | ||
549 | // Perform actual mount of specific filesystem at specific location. | 563 | // Perform actual mount of specific filesystem at specific location. |
550 | // NB: mp->xxx fields may be trashed on exit | 564 | // NB: mp->xxx fields may be trashed on exit |
551 | static int mount_it_now(struct mntent *mp, long vfsflags, char *filteropts) | 565 | static int mount_it_now(struct mntent *mp, unsigned long vfsflags, char *filteropts) |
552 | { | 566 | { |
553 | int rc = 0; | 567 | int rc = 0; |
554 | 568 | ||
@@ -1080,7 +1094,7 @@ static void error_msg_rpc(const char *msg) | |||
1080 | } | 1094 | } |
1081 | 1095 | ||
1082 | /* NB: mp->xxx fields may be trashed on exit */ | 1096 | /* NB: mp->xxx fields may be trashed on exit */ |
1083 | static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts) | 1097 | static NOINLINE int nfsmount(struct mntent *mp, unsigned long vfsflags, char *filteropts) |
1084 | { | 1098 | { |
1085 | CLIENT *mclient; | 1099 | CLIENT *mclient; |
1086 | char *hostname; | 1100 | char *hostname; |
@@ -1711,7 +1725,7 @@ static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts) | |||
1711 | * For older kernels, you must build busybox with ENABLE_FEATURE_MOUNT_NFS. | 1725 | * For older kernels, you must build busybox with ENABLE_FEATURE_MOUNT_NFS. |
1712 | * (However, note that then you lose any chances that NFS over IPv6 would work). | 1726 | * (However, note that then you lose any chances that NFS over IPv6 would work). |
1713 | */ | 1727 | */ |
1714 | static int nfsmount(struct mntent *mp, long vfsflags, char *filteropts) | 1728 | static int nfsmount(struct mntent *mp, unsigned long vfsflags, char *filteropts) |
1715 | { | 1729 | { |
1716 | len_and_sockaddr *lsa; | 1730 | len_and_sockaddr *lsa; |
1717 | char *opts; | 1731 | char *opts; |
@@ -1753,7 +1767,7 @@ static int nfsmount(struct mntent *mp, long vfsflags, char *filteropts) | |||
1753 | static int singlemount(struct mntent *mp, int ignore_busy) | 1767 | static int singlemount(struct mntent *mp, int ignore_busy) |
1754 | { | 1768 | { |
1755 | int rc = -1; | 1769 | int rc = -1; |
1756 | long vfsflags; | 1770 | unsigned long vfsflags; |
1757 | char *loopFile = NULL, *filteropts = NULL; | 1771 | char *loopFile = NULL, *filteropts = NULL; |
1758 | llist_t *fl = NULL; | 1772 | llist_t *fl = NULL; |
1759 | struct stat st; | 1773 | struct stat st; |
@@ -1854,7 +1868,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
1854 | if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) { | 1868 | if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) { |
1855 | loopFile = bb_simplify_path(mp->mnt_fsname); | 1869 | loopFile = bb_simplify_path(mp->mnt_fsname); |
1856 | mp->mnt_fsname = NULL; // will receive malloced loop dev name | 1870 | mp->mnt_fsname = NULL; // will receive malloced loop dev name |
1857 | if (set_loop(&mp->mnt_fsname, loopFile, 0, /*ro:*/ 0) < 0) { | 1871 | if (set_loop(&mp->mnt_fsname, loopFile, 0, /*ro:*/ (vfsflags & MS_RDONLY)) < 0) { |
1858 | if (errno == EPERM || errno == EACCES) | 1872 | if (errno == EPERM || errno == EACCES) |
1859 | bb_error_msg(bb_msg_perm_denied_are_you_root); | 1873 | bb_error_msg(bb_msg_perm_denied_are_you_root); |
1860 | else | 1874 | else |
@@ -1992,6 +2006,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
1992 | FILE *fstab; | 2006 | FILE *fstab; |
1993 | int i, j; | 2007 | int i, j; |
1994 | int rc = EXIT_SUCCESS; | 2008 | int rc = EXIT_SUCCESS; |
2009 | unsigned long cmdopt_flags; | ||
1995 | unsigned opt; | 2010 | unsigned opt; |
1996 | struct mntent mtpair[2], *mtcur = mtpair; | 2011 | struct mntent mtpair[2], *mtcur = mtpair; |
1997 | IF_NOT_DESKTOP(const int nonroot = 0;) | 2012 | IF_NOT_DESKTOP(const int nonroot = 0;) |
@@ -2066,16 +2081,16 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
2066 | // Past this point, we are handling either "mount -a [opts]" | 2081 | // Past this point, we are handling either "mount -a [opts]" |
2067 | // or "mount [opts] single_param" | 2082 | // or "mount [opts] single_param" |
2068 | 2083 | ||
2069 | i = parse_mount_options(cmdopts, NULL); // FIXME: should be "long", not "int" | 2084 | cmdopt_flags = parse_mount_options(cmdopts, NULL); |
2070 | if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags | 2085 | if (nonroot && (cmdopt_flags & ~MS_SILENT)) // Non-root users cannot specify flags |
2071 | bb_error_msg_and_die(bb_msg_you_must_be_root); | 2086 | bb_error_msg_and_die(bb_msg_you_must_be_root); |
2072 | 2087 | ||
2073 | // If we have a shared subtree flag, don't worry about fstab or mtab. | 2088 | // If we have a shared subtree flag, don't worry about fstab or mtab. |
2074 | if (ENABLE_FEATURE_MOUNT_FLAGS | 2089 | if (ENABLE_FEATURE_MOUNT_FLAGS |
2075 | && (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) | 2090 | && (cmdopt_flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) |
2076 | ) { | 2091 | ) { |
2077 | // verbose_mount(source, target, type, flags, data) | 2092 | // verbose_mount(source, target, type, flags, data) |
2078 | rc = verbose_mount("", argv[0], "", i, ""); | 2093 | rc = verbose_mount("", argv[0], "", cmdopt_flags, ""); |
2079 | if (rc) | 2094 | if (rc) |
2080 | bb_simple_perror_msg_and_die(argv[0]); | 2095 | bb_simple_perror_msg_and_die(argv[0]); |
2081 | return rc; | 2096 | return rc; |
@@ -2083,7 +2098,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
2083 | 2098 | ||
2084 | // Open either fstab or mtab | 2099 | // Open either fstab or mtab |
2085 | fstabname = "/etc/fstab"; | 2100 | fstabname = "/etc/fstab"; |
2086 | if (i & MS_REMOUNT) { | 2101 | if (cmdopt_flags & MS_REMOUNT) { |
2087 | // WARNING. I am not sure this matches util-linux's | 2102 | // WARNING. I am not sure this matches util-linux's |
2088 | // behavior. It's possible util-linux does not | 2103 | // behavior. It's possible util-linux does not |
2089 | // take -o opts from mtab (takes only mount source). | 2104 | // take -o opts from mtab (takes only mount source). |
@@ -2182,7 +2197,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
2182 | // End of fstab/mtab is reached. | 2197 | // End of fstab/mtab is reached. |
2183 | // Were we looking for something specific? | 2198 | // Were we looking for something specific? |
2184 | if (argv[0]) { // yes | 2199 | if (argv[0]) { // yes |
2185 | long l; | 2200 | unsigned long l; |
2186 | 2201 | ||
2187 | // If we didn't find anything, complain | 2202 | // If we didn't find anything, complain |
2188 | if (!mtcur->mnt_fsname) | 2203 | if (!mtcur->mnt_fsname) |
diff --git a/util-linux/rdate.c b/util-linux/rdate.c index 1f36d8f37..6e35cd519 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * The Rdate command will ask a time server for the RFC 868 time | 3 | * The Rdate command will ask a time server for the RFC 868 time |
4 | * and optionally set the system time. | 4 | * and optionally set the system time. |
5 | * | 5 | * |
6 | * by Sterling Huxley <sterling@europa.com> | 6 | * by Sterling Huxley <sterling@europa.com> |
7 | * | 7 | * |
@@ -11,9 +11,9 @@ | |||
11 | //usage:#define rdate_trivial_usage | 11 | //usage:#define rdate_trivial_usage |
12 | //usage: "[-sp] HOST" | 12 | //usage: "[-sp] HOST" |
13 | //usage:#define rdate_full_usage "\n\n" | 13 | //usage:#define rdate_full_usage "\n\n" |
14 | //usage: "Get and possibly set the system date and time from a remote HOST\n" | 14 | //usage: "Get and possibly set the system date/time from a remote HOST\n" |
15 | //usage: "\n -s Set the system date and time (default)" | 15 | //usage: "\n -s Set the system date/time (default)" |
16 | //usage: "\n -p Print the date and time" | 16 | //usage: "\n -p Print the date/time" |
17 | 17 | ||
18 | #include "libbb.h" | 18 | #include "libbb.h" |
19 | 19 | ||
@@ -35,15 +35,16 @@ static time_t askremotedate(const char *host) | |||
35 | 35 | ||
36 | fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37)); | 36 | fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37)); |
37 | 37 | ||
38 | if (safe_read(fd, (void *)&nett, 4) != 4) /* read time from server */ | 38 | if (safe_read(fd, &nett, 4) != 4) /* read time from server */ |
39 | bb_error_msg_and_die("%s did not send the complete time", host); | 39 | bb_error_msg_and_die("%s did not send the complete time", host); |
40 | close(fd); | 40 | if (ENABLE_FEATURE_CLEAN_UP) |
41 | close(fd); | ||
41 | 42 | ||
42 | /* convert from network byte order to local byte order. | 43 | /* Convert from network byte order to local byte order. |
43 | * RFC 868 time is the number of seconds | 44 | * RFC 868 time is the number of seconds |
44 | * since 00:00 (midnight) 1 January 1900 GMT | 45 | * since 00:00 (midnight) 1 January 1900 GMT |
45 | * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT | 46 | * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT |
46 | * Subtract the RFC 868 time to get Linux epoch | 47 | * Subtract the RFC 868 time to get Linux epoch. |
47 | */ | 48 | */ |
48 | 49 | ||
49 | return ntohl(nett) - RFC_868_BIAS; | 50 | return ntohl(nett) - RFC_868_BIAS; |
@@ -53,14 +54,14 @@ int rdate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
53 | int rdate_main(int argc UNUSED_PARAM, char **argv) | 54 | int rdate_main(int argc UNUSED_PARAM, char **argv) |
54 | { | 55 | { |
55 | time_t remote_time; | 56 | time_t remote_time; |
56 | unsigned long flags; | 57 | unsigned flags; |
57 | 58 | ||
58 | opt_complementary = "-1"; | 59 | opt_complementary = "-1"; |
59 | flags = getopt32(argv, "sp"); | 60 | flags = getopt32(argv, "sp"); |
60 | 61 | ||
61 | remote_time = askremotedate(argv[optind]); | 62 | remote_time = askremotedate(argv[optind]); |
62 | 63 | ||
63 | if ((flags & 2) == 0) { | 64 | if (!(flags & 2)) { /* no -p (-s may be present) */ |
64 | time_t current_time; | 65 | time_t current_time; |
65 | 66 | ||
66 | time(¤t_time); | 67 | time(¤t_time); |
@@ -71,7 +72,7 @@ int rdate_main(int argc UNUSED_PARAM, char **argv) | |||
71 | bb_perror_msg_and_die("can't set time of day"); | 72 | bb_perror_msg_and_die("can't set time of day"); |
72 | } | 73 | } |
73 | 74 | ||
74 | if ((flags & 1) == 0) | 75 | if (flags != 1) /* not lone -s */ |
75 | printf("%s", ctime(&remote_time)); | 76 | printf("%s", ctime(&remote_time)); |
76 | 77 | ||
77 | return EXIT_SUCCESS; | 78 | return EXIT_SUCCESS; |
diff --git a/util-linux/volume_id/Kbuild.src b/util-linux/volume_id/Kbuild.src index 70da65482..39a2d8cf4 100644 --- a/util-linux/volume_id/Kbuild.src +++ b/util-linux/volume_id/Kbuild.src | |||
@@ -31,6 +31,7 @@ lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o | |||
31 | ### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o | 31 | ### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o |
32 | ### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o | 32 | ### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o |
33 | ### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o | 33 | ### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o |
34 | lib-$(CONFIG_FEATURE_VOLUMEID_NILFS) += nilfs.o | ||
34 | lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o | 35 | lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o |
35 | lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o | 36 | lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o |
36 | lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o | 37 | lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o |
diff --git a/util-linux/volume_id/btrfs.c b/util-linux/volume_id/btrfs.c index 777b80923..ee71d2e00 100644 --- a/util-linux/volume_id/btrfs.c +++ b/util-linux/volume_id/btrfs.c | |||
@@ -102,6 +102,7 @@ int FAST_FUNC volume_id_probe_btrfs(struct volume_id *id /*,uint64_t off*/) | |||
102 | // N.B.: btrfs natively supports 256 (>VOLUME_ID_LABEL_SIZE) size labels | 102 | // N.B.: btrfs natively supports 256 (>VOLUME_ID_LABEL_SIZE) size labels |
103 | volume_id_set_label_string(id, sb->label, VOLUME_ID_LABEL_SIZE); | 103 | volume_id_set_label_string(id, sb->label, VOLUME_ID_LABEL_SIZE); |
104 | volume_id_set_uuid(id, sb->fsid, UUID_DCE); | 104 | volume_id_set_uuid(id, sb->fsid, UUID_DCE); |
105 | IF_FEATURE_BLKID_TYPE(id->type = "btrfs";) | ||
105 | 106 | ||
106 | return 0; | 107 | return 0; |
107 | } | 108 | } |
diff --git a/util-linux/volume_id/ext.c b/util-linux/volume_id/ext.c index b5194a7b5..97451067f 100644 --- a/util-linux/volume_id/ext.c +++ b/util-linux/volume_id/ext.c | |||
@@ -19,28 +19,8 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include "volume_id_internal.h" | 21 | #include "volume_id_internal.h" |
22 | #include "bb_e2fs_defs.h" | ||
22 | 23 | ||
23 | struct ext2_super_block { | ||
24 | uint32_t inodes_count; | ||
25 | uint32_t blocks_count; | ||
26 | uint32_t r_blocks_count; | ||
27 | uint32_t free_blocks_count; | ||
28 | uint32_t free_inodes_count; | ||
29 | uint32_t first_data_block; | ||
30 | uint32_t log_block_size; | ||
31 | uint32_t dummy3[7]; | ||
32 | uint8_t magic[2]; | ||
33 | uint16_t state; | ||
34 | uint32_t dummy5[8]; | ||
35 | uint32_t feature_compat; | ||
36 | uint32_t feature_incompat; | ||
37 | uint32_t feature_ro_compat; | ||
38 | uint8_t uuid[16]; | ||
39 | uint8_t volume_name[16]; | ||
40 | } PACKED; | ||
41 | |||
42 | #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004 | ||
43 | #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008 | ||
44 | #define EXT_SUPERBLOCK_OFFSET 0x400 | 24 | #define EXT_SUPERBLOCK_OFFSET 0x400 |
45 | 25 | ||
46 | int FAST_FUNC volume_id_probe_ext(struct volume_id *id /*,uint64_t off*/) | 26 | int FAST_FUNC volume_id_probe_ext(struct volume_id *id /*,uint64_t off*/) |
@@ -54,23 +34,27 @@ int FAST_FUNC volume_id_probe_ext(struct volume_id *id /*,uint64_t off*/) | |||
54 | if (es == NULL) | 34 | if (es == NULL) |
55 | return -1; | 35 | return -1; |
56 | 36 | ||
57 | if (es->magic[0] != 0123 || es->magic[1] != 0357) { | 37 | if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) { |
58 | dbg("ext: no magic found"); | 38 | dbg("ext: no magic found"); |
59 | return -1; | 39 | return -1; |
60 | } | 40 | } |
61 | 41 | ||
62 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); | 42 | // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); |
63 | // volume_id_set_label_raw(id, es->volume_name, 16); | 43 | // volume_id_set_label_raw(id, es->volume_name, 16); |
64 | volume_id_set_label_string(id, es->volume_name, 16); | 44 | volume_id_set_label_string(id, (void*)es->s_volume_name, 16); |
65 | volume_id_set_uuid(id, es->uuid, UUID_DCE); | 45 | volume_id_set_uuid(id, es->s_uuid, UUID_DCE); |
66 | dbg("ext: label '%s' uuid '%s'", id->label, id->uuid); | 46 | dbg("ext: label '%s' uuid '%s'", id->label, id->uuid); |
67 | 47 | ||
68 | #if ENABLE_FEATURE_BLKID_TYPE | 48 | #if ENABLE_FEATURE_BLKID_TYPE |
69 | if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) | 49 | if ((es->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_HUGE_FILE | EXT4_FEATURE_RO_COMPAT_DIR_NLINK)) |
50 | || (es->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS | EXT4_FEATURE_INCOMPAT_64BIT)) | ||
51 | ) { | ||
52 | id->type = "ext4"; | ||
53 | } | ||
54 | else if (es->s_feature_compat & cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL)) | ||
70 | id->type = "ext3"; | 55 | id->type = "ext3"; |
71 | else | 56 | else |
72 | id->type = "ext2"; | 57 | id->type = "ext2"; |
73 | #endif | 58 | #endif |
74 | |||
75 | return 0; | 59 | return 0; |
76 | } | 60 | } |
diff --git a/util-linux/volume_id/nilfs.c b/util-linux/volume_id/nilfs.c new file mode 100644 index 000000000..ffa86d43c --- /dev/null +++ b/util-linux/volume_id/nilfs.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * volume_id - reads filesystem label and uuid | ||
3 | * | ||
4 | * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> | ||
5 | * Copyright (C) 2012 S-G Bergh <sgb@systemasis.org> | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2.1 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include "volume_id_internal.h" | ||
23 | |||
24 | #define NILFS_UUID_SIZE 16 | ||
25 | #define NILFS_LABEL_SIZE 80 | ||
26 | #define NILFS_SB1_OFFSET 0x400 | ||
27 | #define NILFS_SB2_OFFSET 0x1000 | ||
28 | #define NILFS_MAGIC 0x3434 | ||
29 | |||
30 | struct nilfs2_super_block { | ||
31 | /* 0x00 */ uint32_t s_rev_level; // Major revision level. | ||
32 | /* 0x04 */ uint16_t s_minor_rev_level; // Minor revision level. | ||
33 | /* 0x06 */ uint16_t s_magic; // Magic signature. | ||
34 | /* 0x08 */ uint16_t s_bytes; | ||
35 | /* 0x0A */ uint16_t s_flags; | ||
36 | /* 0x0C */ uint32_t s_crc_seed; | ||
37 | /* 0x10 */ uint32_t s_sum; | ||
38 | /* 0x14 */ uint32_t s_log_block_size; | ||
39 | /* 0x18 */ uint64_t s_nsegments; | ||
40 | /* 0x20 */ uint64_t s_dev_size; // Block device size in bytes. | ||
41 | /* 0x28 */ uint64_t s_first_data_block; | ||
42 | /* 0x30 */ uint32_t s_blocks_per_segment; | ||
43 | /* 0x34 */ uint32_t s_r_segments_percentage; | ||
44 | /* 0x38 */ uint64_t s_last_cno; | ||
45 | /* 0x40 */ uint64_t s_last_pseg; | ||
46 | /* 0x48 */ uint64_t s_last_seq; | ||
47 | /* 0x50 */ uint64_t s_free_blocks_count; | ||
48 | /* 0x58 */ uint64_t s_ctime; | ||
49 | /* 0x60 */ uint64_t s_mtime; | ||
50 | /* 0x68 */ uint64_t s_wtime; | ||
51 | /* 0x70 */ uint16_t s_mnt_count; | ||
52 | /* 0x72 */ uint16_t s_max_mnt_count; | ||
53 | /* 0x74 */ uint16_t s_state; | ||
54 | /* 0x76 */ uint16_t s_errors; | ||
55 | /* 0x78 */ uint64_t s_lastcheck; | ||
56 | /* 0x80 */ uint32_t s_checkinterval; | ||
57 | /* 0x84 */ uint32_t s_creator_os; | ||
58 | /* 0x88 */ uint16_t s_def_resuid; | ||
59 | /* 0x8A */ uint16_t s_def_resgid; | ||
60 | /* 0x8C */ uint32_t s_first_ino; | ||
61 | /* 0x90 */ uint16_t s_inode_size; | ||
62 | /* 0x92 */ uint16_t s_dat_entry_size; | ||
63 | /* 0x94 */ uint16_t s_checkpoint_size; | ||
64 | /* 0x96 */ uint16_t s_segment_usage_size; | ||
65 | /* 0x98 */ uint8_t s_uuid[NILFS_UUID_SIZE]; // 128-bit UUID for volume. | ||
66 | /* 0xA8 */ uint8_t s_volume_name[NILFS_LABEL_SIZE]; // Volume label. | ||
67 | /* 0xF8 */ // ... | ||
68 | } PACKED; | ||
69 | |||
70 | int FAST_FUNC volume_id_probe_nilfs(struct volume_id *id /*,uint64_t off*/) | ||
71 | { | ||
72 | struct nilfs2_super_block *sb; | ||
73 | |||
74 | // Primary super block | ||
75 | dbg("nilfs: probing at offset 0x%x", NILFS_SB1_OFFSET); | ||
76 | |||
77 | sb = volume_id_get_buffer(id, NILFS_SB1_OFFSET, sizeof(*sb)); | ||
78 | |||
79 | if (sb == NULL) | ||
80 | return -1; | ||
81 | |||
82 | if (sb->s_magic != NILFS_MAGIC) | ||
83 | return -1; | ||
84 | |||
85 | // The secondary superblock is not always used, so ignore it for now. | ||
86 | // When used it is at 4K from the end of the partition (sb->s_dev_size - NILFS_SB2_OFFSET). | ||
87 | |||
88 | volume_id_set_label_string(id, sb->s_volume_name, NILFS_LABEL_SIZE < VOLUME_ID_LABEL_SIZE ? | ||
89 | NILFS_LABEL_SIZE : VOLUME_ID_LABEL_SIZE); | ||
90 | volume_id_set_uuid(id, sb->s_uuid, UUID_DCE); | ||
91 | |||
92 | if (sb->s_rev_level == 2) | ||
93 | IF_FEATURE_BLKID_TYPE(id->type = "nilfs2"); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
diff --git a/util-linux/volume_id/util.c b/util-linux/volume_id/util.c index dd75c7ba1..69e43dda8 100644 --- a/util-linux/volume_id/util.c +++ b/util-linux/volume_id/util.c | |||
@@ -31,25 +31,29 @@ void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum end | |||
31 | c = (buf[i+1] << 8) | buf[i]; | 31 | c = (buf[i+1] << 8) | buf[i]; |
32 | else | 32 | else |
33 | c = (buf[i] << 8) | buf[i+1]; | 33 | c = (buf[i] << 8) | buf[i+1]; |
34 | if (c == 0) { | 34 | if (c == 0) |
35 | str[j] = '\0'; | ||
36 | break; | 35 | break; |
37 | } else if (c < 0x80) { | 36 | if (j+1 >= len) |
38 | if (j+1 >= len) | 37 | break; |
39 | break; | 38 | if (c < 0x80) { |
40 | str[j++] = (uint8_t) c; | 39 | /* 0xxxxxxx */ |
41 | } else if (c < 0x800) { | ||
42 | if (j+2 >= len) | ||
43 | break; | ||
44 | str[j++] = (uint8_t) (0xc0 | (c >> 6)); | ||
45 | str[j++] = (uint8_t) (0x80 | (c & 0x3f)); | ||
46 | } else { | 40 | } else { |
47 | if (j+3 >= len) | 41 | uint8_t topbits = 0xc0; |
42 | if (j+2 >= len) | ||
48 | break; | 43 | break; |
49 | str[j++] = (uint8_t) (0xe0 | (c >> 12)); | 44 | if (c < 0x800) { |
50 | str[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); | 45 | /* 110yyyxx 10xxxxxx */ |
51 | str[j++] = (uint8_t) (0x80 | (c & 0x3f)); | 46 | } else { |
47 | if (j+3 >= len) | ||
48 | break; | ||
49 | /* 1110yyyy 10yyyyxx 10xxxxxx */ | ||
50 | str[j++] = (uint8_t) (0xe0 | (c >> 12)); | ||
51 | topbits = 0x80; | ||
52 | } | ||
53 | str[j++] = (uint8_t) (topbits | ((c >> 6) & 0x3f)); | ||
54 | c = 0x80 | (c & 0x3f); | ||
52 | } | 55 | } |
56 | str[j++] = (uint8_t) c; | ||
53 | } | 57 | } |
54 | str[j] = '\0'; | 58 | str[j] = '\0'; |
55 | } | 59 | } |
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c index f41d4e0d9..c1d615283 100644 --- a/util-linux/volume_id/volume_id.c +++ b/util-linux/volume_id/volume_id.c | |||
@@ -130,6 +130,9 @@ static const probe_fptr fs2[] = { | |||
130 | #if ENABLE_FEATURE_VOLUMEID_UFS | 130 | #if ENABLE_FEATURE_VOLUMEID_UFS |
131 | volume_id_probe_ufs, | 131 | volume_id_probe_ufs, |
132 | #endif | 132 | #endif |
133 | #if ENABLE_FEATURE_VOLUMEID_NILFS | ||
134 | volume_id_probe_nilfs, | ||
135 | #endif | ||
133 | #if ENABLE_FEATURE_VOLUMEID_NTFS | 136 | #if ENABLE_FEATURE_VOLUMEID_NTFS |
134 | volume_id_probe_ntfs, | 137 | volume_id_probe_ntfs, |
135 | #endif | 138 | #endif |
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index 1c64046e5..1c2e0ffa6 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h | |||
@@ -212,6 +212,8 @@ int FAST_FUNC volume_id_probe_luks(struct volume_id *id /*,uint64_t off*/); | |||
212 | 212 | ||
213 | //int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id /*,uint64_t off*/); | 213 | //int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id /*,uint64_t off*/); |
214 | 214 | ||
215 | int FAST_FUNC volume_id_probe_nilfs(struct volume_id *id /*,uint64_t off*/); | ||
216 | |||
215 | int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/); | 217 | int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/); |
216 | 218 | ||
217 | int FAST_FUNC volume_id_probe_ocfs2(struct volume_id *id /*,uint64_t off*/); | 219 | int FAST_FUNC volume_id_probe_ocfs2(struct volume_id *id /*,uint64_t off*/); |