diff options
| author | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
| commit | 3fd34651ea72ea1c335d3170f234cb0517fd897f (patch) | |
| tree | 36e8fc40cffd464ffda4759020777dd3ca23ca31 | |
| parent | e3ac39098326de084a805d0dd31db9666b734f20 (diff) | |
| parent | d6ae4fb446daedfe3073d67be655942e9fa7eb18 (diff) | |
| download | busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.gz busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.bz2 busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.zip | |
Merge branch 'busybox' into merge
130 files changed, 2217 insertions, 1327 deletions
| @@ -184,12 +184,13 @@ config UNICODE_USING_LOCALE | |||
| 184 | Internal implementation is smaller. | 184 | Internal implementation is smaller. |
| 185 | 185 | ||
| 186 | config FEATURE_CHECK_UNICODE_IN_ENV | 186 | config FEATURE_CHECK_UNICODE_IN_ENV |
| 187 | bool "Check $LANG environment variable" | 187 | bool "Check $LC_ALL, $LC_CTYPE and $LANG environment variables" |
| 188 | default n | 188 | default n |
| 189 | depends on UNICODE_SUPPORT && !UNICODE_USING_LOCALE | 189 | depends on UNICODE_SUPPORT && !UNICODE_USING_LOCALE |
| 190 | help | 190 | help |
| 191 | With this option on, Unicode support is activated | 191 | With this option on, Unicode support is activated |
| 192 | only if LANG variable has the value of the form "xxxx.utf8" | 192 | only if locale-related variables have the value of the form |
| 193 | "xxxx.utf8" | ||
| 193 | 194 | ||
| 194 | Otherwise, Unicode support will be always enabled and active. | 195 | Otherwise, Unicode support will be always enabled and active. |
| 195 | 196 | ||
diff --git a/Makefile.custom b/Makefile.custom index 6da79e6e4..3561e5768 100644 --- a/Makefile.custom +++ b/Makefile.custom | |||
| @@ -3,7 +3,12 @@ | |||
| 3 | # ========================================================================== | 3 | # ========================================================================== |
| 4 | 4 | ||
| 5 | busybox.links: $(srctree)/applets/busybox.mkll $(objtree)/include/autoconf.h include/applets.h | 5 | busybox.links: $(srctree)/applets/busybox.mkll $(objtree)/include/autoconf.h include/applets.h |
| 6 | $(Q)-$(SHELL) $^ >$@ | 6 | $(Q)-$(SHELL) $^ > $@ |
| 7 | |||
| 8 | busybox.cfg.suid: $(srctree)/applets/busybox.mksuid $(objtree)/include/autoconf.h include/applets.h | ||
| 9 | $(Q)-SUID="yes" $(SHELL) $^ > $@ | ||
| 10 | busybox.cfg.nosuid: $(srctree)/applets/busybox.mksuid $(objtree)/include/autoconf.h include/applets.h | ||
| 11 | $(Q)-SUID="DROP" $(SHELL) $^ > $@ | ||
| 7 | 12 | ||
| 8 | .PHONY: install | 13 | .PHONY: install |
| 9 | ifeq ($(CONFIG_INSTALL_APPLET_SYMLINKS),y) | 14 | ifeq ($(CONFIG_INSTALL_APPLET_SYMLINKS),y) |
| @@ -128,15 +128,6 @@ patch | |||
| 128 | And while we're at it, a new patch filename quoting format is apparently | 128 | And while we're at it, a new patch filename quoting format is apparently |
| 129 | coming soon: http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2 | 129 | coming soon: http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2 |
| 130 | --- | 130 | --- |
| 131 | stty / catv | ||
| 132 | stty's visible() function and catv's guts are identical. Merge them into | ||
| 133 | an appropriate libbb function. | ||
| 134 | --- | ||
| 135 | struct suffix_mult | ||
| 136 | Several duplicate users of: grep -r "1024\*1024" * -B2 -A1 | ||
| 137 | Merge to a single size_suffixes[] in libbb. | ||
| 138 | Users: head tail od_bloaty hexdump and (partially as it wouldn't hurt) svlogd | ||
| 139 | --- | ||
| 140 | tail | 131 | tail |
| 141 | ./busybox tail -f foo.c~ TODO | 132 | ./busybox tail -f foo.c~ TODO |
| 142 | should not print fmt=header_fmt for subsequent date >> TODO; i.e. only | 133 | should not print fmt=header_fmt for subsequent date >> TODO; i.e. only |
| @@ -234,8 +225,6 @@ Minor stuff: | |||
| 234 | See grep -r strtod | 225 | See grep -r strtod |
| 235 | Alot of duplication that wants cleanup. | 226 | Alot of duplication that wants cleanup. |
| 236 | --- | 227 | --- |
| 237 | in_ether duplicated in network/{interface,ifconfig}.c | ||
| 238 | --- | ||
| 239 | unify progress_meter. wget, flash_eraseall, pipe_progress, fbsplash, setfiles. | 228 | unify progress_meter. wget, flash_eraseall, pipe_progress, fbsplash, setfiles. |
| 240 | --- | 229 | --- |
| 241 | support start-stop-daemon -d <chdir-path> | 230 | support start-stop-daemon -d <chdir-path> |
diff --git a/applets/busybox.mksuid b/applets/busybox.mksuid new file mode 100755 index 000000000..6492c079a --- /dev/null +++ b/applets/busybox.mksuid | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | # Make list of configuration variables regarding suid handling | ||
| 3 | |||
| 4 | # input $1: full path to autoconf.h | ||
| 5 | # input $2: full path to applets.h | ||
| 6 | # input $3: full path to .config | ||
| 7 | # output (stdout): list of CONFIG_ that do or may require suid | ||
| 8 | |||
| 9 | # If the environment variable SUID is not set or set to DROP, | ||
| 10 | # lists all config options that do not require suid permissions. | ||
| 11 | # Otherwise, lists all config options for applets that DO or MAY require | ||
| 12 | # suid permissions. | ||
| 13 | |||
| 14 | # Maintainer: Bernhard Reutner-Fischer | ||
| 15 | |||
| 16 | export LC_ALL=POSIX | ||
| 17 | export LC_CTYPE=POSIX | ||
| 18 | |||
| 19 | CONFIG_H=${1:-include/autoconf.h} | ||
| 20 | APPLETS_H=${2:-include/applets.h} | ||
| 21 | DOT_CONFIG=${3:-.config} | ||
| 22 | |||
| 23 | case ${SUID:-DROP} in | ||
| 24 | [dD][rR][oO][pP]) USE="DROP" ;; | ||
| 25 | *) USE="suid" ;; | ||
| 26 | esac | ||
| 27 | |||
| 28 | $HOSTCC -E -DMAKE_SUID -include $CONFIG_H $APPLETS_H | | ||
| 29 | awk -v USE=${USE} ' | ||
| 30 | /^SUID[ \t]/{ | ||
| 31 | if (USE == "DROP") { | ||
| 32 | if ($2 != "BB_SUID_DROP") next | ||
| 33 | } else { | ||
| 34 | if ($2 == "BB_SUID_DROP") next | ||
| 35 | } | ||
| 36 | cfg = $NF | ||
| 37 | gsub("\"", "", cfg) | ||
| 38 | cfg = substr(cfg, 8) | ||
| 39 | s[i++] = "CONFIG_" cfg | ||
| 40 | s[i++] = "CONFIG_FEATURE_" cfg "_.*" | ||
| 41 | } | ||
| 42 | END{ | ||
| 43 | while (getline < ARGV[2]) { | ||
| 44 | for (j in s) { | ||
| 45 | if ($0 ~ "^" s[j] "=y$") { | ||
| 46 | sub(/=.*/, "") | ||
| 47 | |||
| 48 | if (s[j] !~ /\*$/) delete s[j] # can drop this applet now | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | ' - $DOT_CONFIG | ||
| 54 | |||
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index f77ac8383..9d1cd9485 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
| @@ -132,7 +132,10 @@ int FAST_FUNC bbunpack(char **argv, | |||
| 132 | 132 | ||
| 133 | if (filename) { | 133 | if (filename) { |
| 134 | char *del = new_name; | 134 | char *del = new_name; |
| 135 | |||
| 135 | if (status >= 0) { | 136 | if (status >= 0) { |
| 137 | unsigned new_name_len; | ||
| 138 | |||
| 136 | /* TODO: restore other things? */ | 139 | /* TODO: restore other things? */ |
| 137 | if (aux.mtime != 0) { | 140 | if (aux.mtime != 0) { |
| 138 | struct timeval times[2]; | 141 | struct timeval times[2]; |
| @@ -146,24 +149,31 @@ int FAST_FUNC bbunpack(char **argv, | |||
| 146 | utimes(new_name, times); /* ignoring errors */ | 149 | utimes(new_name, times); /* ignoring errors */ |
| 147 | } | 150 | } |
| 148 | 151 | ||
| 149 | /* Delete _compressed_ file */ | 152 | if (ENABLE_DESKTOP) |
| 153 | new_name_len = strlen(new_name); | ||
| 154 | /* Restore source filename (unless tgz -> tar case) */ | ||
| 155 | if (new_name == filename) { | ||
| 156 | new_name_len = strlen(filename); | ||
| 157 | filename[new_name_len] = '.'; | ||
| 158 | } | ||
| 159 | /* Extreme bloat for gunzip compat */ | ||
| 160 | /* Some users do want this info... */ | ||
| 161 | if (ENABLE_DESKTOP && (option_mask32 & OPT_VERBOSE)) { | ||
| 162 | unsigned percent = status | ||
| 163 | ? ((uoff_t)stat_buf.st_size * 100u / (unsigned long long)status) | ||
| 164 | : 0; | ||
| 165 | fprintf(stderr, "%s: %u%% - replaced with %.*s\n", | ||
| 166 | filename, | ||
| 167 | 100u - percent, | ||
| 168 | new_name_len, new_name | ||
| 169 | ); | ||
| 170 | } | ||
| 171 | /* Delete _source_ file */ | ||
| 150 | del = filename; | 172 | del = filename; |
| 151 | /* restore extension (unless tgz -> tar case) */ | ||
| 152 | if (new_name == filename) | ||
| 153 | filename[strlen(filename)] = '.'; | ||
| 154 | } | 173 | } |
| 155 | if (ENABLE_PLATFORM_MINGW32) | 174 | if (ENABLE_PLATFORM_MINGW32) |
| 156 | xclose(STDIN_FILENO); | 175 | xclose(STDIN_FILENO); |
| 157 | xunlink(del); | 176 | xunlink(del); |
| 158 | |||
| 159 | #if 0 /* Currently buggy - wrong name: "a.gz: 261% - replaced with a.gz" */ | ||
| 160 | /* Extreme bloat for gunzip compat */ | ||
| 161 | if (ENABLE_DESKTOP && (option_mask32 & OPT_VERBOSE) && status >= 0) { | ||
| 162 | fprintf(stderr, "%s: %u%% - replaced with %s\n", | ||
| 163 | filename, (unsigned)(stat_buf.st_size*100 / (status+1)), new_name); | ||
| 164 | } | ||
| 165 | #endif | ||
| 166 | |||
| 167 | free_name: | 177 | free_name: |
| 168 | if (new_name != filename) | 178 | if (new_name != filename) |
| 169 | free(new_name); | 179 | free(new_name); |
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index 58457fc22..968fdf8ab 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src | |||
| @@ -38,31 +38,45 @@ DPKG_FILES:= \ | |||
| 38 | 38 | ||
| 39 | INSERT | 39 | INSERT |
| 40 | 40 | ||
| 41 | lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o | ||
| 42 | lib-$(CONFIG_BUNZIP2) += decompress_bunzip2.o | ||
| 43 | lib-$(CONFIG_UNLZMA) += decompress_unlzma.o | ||
| 44 | lib-$(CONFIG_UNXZ) += decompress_unxz.o | ||
| 45 | lib-$(CONFIG_CPIO) += get_header_cpio.o | ||
| 46 | lib-$(CONFIG_DPKG) += $(DPKG_FILES) | 41 | lib-$(CONFIG_DPKG) += $(DPKG_FILES) |
| 47 | lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES) | 42 | lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES) |
| 48 | lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o | 43 | |
| 49 | lib-$(CONFIG_RPM2CPIO) += decompress_gunzip.o get_header_cpio.o | 44 | lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o |
| 50 | lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o | 45 | lib-$(CONFIG_CPIO) += get_header_cpio.o |
| 51 | lib-$(CONFIG_TAR) += get_header_tar.o | 46 | lib-$(CONFIG_TAR) += get_header_tar.o |
| 52 | lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o | 47 | lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o |
| 53 | lib-$(CONFIG_UNZIP) += decompress_gunzip.o | ||
| 54 | lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o | 48 | lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o |
| 55 | lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o | 49 | lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o |
| 50 | lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o | ||
| 51 | lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o | ||
| 52 | lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o | ||
| 53 | lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o | ||
| 54 | lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o | ||
| 55 | lib-$(CONFIG_UNZIP) += open_transformer.o decompress_gunzip.o | ||
| 56 | lib-$(CONFIG_RPM2CPIO) += open_transformer.o decompress_gunzip.o get_header_cpio.o | ||
| 57 | lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o | ||
| 58 | |||
| 59 | lib-$(CONFIG_GZIP) += open_transformer.o | ||
| 60 | lib-$(CONFIG_BZIP2) += open_transformer.o | ||
| 61 | lib-$(CONFIG_LZOP) += open_transformer.o | ||
| 62 | lib-$(CONFIG_MAN) += open_transformer.o | ||
| 63 | lib-$(CONFIG_SETFONT) += open_transformer.o | ||
| 64 | lib-$(CONFIG_FEATURE_2_4_MODULES) += open_transformer.o | ||
| 56 | lib-$(CONFIG_MODINFO) += open_transformer.o | 65 | lib-$(CONFIG_MODINFO) += open_transformer.o |
| 57 | lib-$(CONFIG_INSMOD) += open_transformer.o | 66 | lib-$(CONFIG_INSMOD) += open_transformer.o |
| 67 | lib-$(CONFIG_DEPMOD) += open_transformer.o | ||
| 68 | lib-$(CONFIG_RMMOD) += open_transformer.o | ||
| 69 | lib-$(CONFIG_LSMOD) += open_transformer.o | ||
| 70 | lib-$(CONFIG_MODPROBE) += open_transformer.o | ||
| 71 | lib-$(CONFIG_MODPROBE_SMALL) += open_transformer.o | ||
| 72 | |||
| 58 | lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o | 73 | lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o |
| 59 | lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_gunzip.o | 74 | lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_gunzip.o |
| 60 | lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o | 75 | lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o |
| 61 | lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o | 76 | lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o |
| 62 | lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o | 77 | lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o |
| 63 | lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o | 78 | lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o |
| 64 | lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += decompress_bunzip2.o | 79 | lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o |
| 65 | lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o | ||
| 66 | 80 | ||
| 67 | ifneq ($(lib-y),) | 81 | ifneq ($(lib-y),) |
| 68 | lib-y += $(COMMON_FILES) | 82 | lib-y += $(COMMON_FILES) |
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c index a2ce33b51..5b32c2ec8 100644 --- a/archival/libarchive/data_extract_to_command.c +++ b/archival/libarchive/data_extract_to_command.c | |||
| @@ -103,7 +103,7 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle) | |||
| 103 | archive_handle->tar__to_command_shell, | 103 | archive_handle->tar__to_command_shell, |
| 104 | "-c", | 104 | "-c", |
| 105 | archive_handle->tar__to_command, | 105 | archive_handle->tar__to_command, |
| 106 | NULL); | 106 | (char *)0); |
| 107 | bb_perror_msg_and_die("can't execute '%s'", archive_handle->tar__to_command_shell); | 107 | bb_perror_msg_and_die("can't execute '%s'", archive_handle->tar__to_command_shell); |
| 108 | } | 108 | } |
| 109 | close(p[0]); | 109 | close(p[0]); |
diff --git a/archival/tar.c b/archival/tar.c index 648d1256d..3129781d2 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
| @@ -569,7 +569,7 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) | |||
| 569 | xmove_fd(gzipDataPipe.rd, 0); | 569 | xmove_fd(gzipDataPipe.rd, 0); |
| 570 | xmove_fd(tar_fd, 1); | 570 | xmove_fd(tar_fd, 1); |
| 571 | /* exec gzip/bzip2 program/applet */ | 571 | /* exec gzip/bzip2 program/applet */ |
| 572 | BB_EXECLP(zip_exec, zip_exec, "-f", NULL); | 572 | BB_EXECLP(zip_exec, zip_exec, "-f", (char *)0); |
| 573 | vfork_exec_errno = errno; | 573 | vfork_exec_errno = errno; |
| 574 | _exit(EXIT_FAILURE); | 574 | _exit(EXIT_FAILURE); |
| 575 | } | 575 | } |
| @@ -681,14 +681,12 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
| 681 | char *cp = last_char_is(line, '/'); | 681 | char *cp = last_char_is(line, '/'); |
| 682 | if (cp > line) | 682 | if (cp > line) |
| 683 | *cp = '\0'; | 683 | *cp = '\0'; |
| 684 | llist_add_to(&newlist, line); | 684 | llist_add_to_end(&newlist, line); |
| 685 | } | 685 | } |
| 686 | fclose(src_stream); | 686 | fclose(src_stream); |
| 687 | } | 687 | } |
| 688 | return newlist; | 688 | return newlist; |
| 689 | } | 689 | } |
| 690 | #else | ||
| 691 | # define append_file_list_to_list(x) 0 | ||
| 692 | #endif | 690 | #endif |
| 693 | 691 | ||
| 694 | //usage:#define tar_trivial_usage | 692 | //usage:#define tar_trivial_usage |
diff --git a/archival/unzip.c b/archival/unzip.c index e4c824850..673e5fe08 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
| @@ -163,7 +163,17 @@ enum { zip_fd = 3 }; | |||
| 163 | 163 | ||
| 164 | #if ENABLE_DESKTOP | 164 | #if ENABLE_DESKTOP |
| 165 | 165 | ||
| 166 | #define PEEK_FROM_END 16384 | 166 | /* Seen in the wild: |
| 167 | * Self-extracting PRO2K3XP_32.exe contains 19078464 byte zip archive, | ||
| 168 | * where CDE was nearly 48 kbytes before EOF. | ||
| 169 | * (Surprisingly, it also apparently has *another* CDE structure | ||
| 170 | * closer to the end, with bogus cdf_offset). | ||
| 171 | * To make extraction work, bumped PEEK_FROM_END from 16k to 64k. | ||
| 172 | */ | ||
| 173 | #define PEEK_FROM_END (64*1024) | ||
| 174 | |||
| 175 | /* This value means that we failed to find CDF */ | ||
| 176 | #define BAD_CDF_OFFSET ((uint32_t)0xffffffff) | ||
| 167 | 177 | ||
| 168 | /* NB: does not preserve file position! */ | 178 | /* NB: does not preserve file position! */ |
| 169 | static uint32_t find_cdf_offset(void) | 179 | static uint32_t find_cdf_offset(void) |
| @@ -180,6 +190,7 @@ static uint32_t find_cdf_offset(void) | |||
| 180 | xlseek(zip_fd, end, SEEK_SET); | 190 | xlseek(zip_fd, end, SEEK_SET); |
| 181 | full_read(zip_fd, buf, PEEK_FROM_END); | 191 | full_read(zip_fd, buf, PEEK_FROM_END); |
| 182 | 192 | ||
| 193 | cde_header.formatted.cdf_offset = BAD_CDF_OFFSET; | ||
| 183 | p = buf; | 194 | p = buf; |
| 184 | while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { | 195 | while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { |
| 185 | if (*p != 'P') { | 196 | if (*p != 'P') { |
| @@ -195,11 +206,17 @@ static uint32_t find_cdf_offset(void) | |||
| 195 | /* we found CDE! */ | 206 | /* we found CDE! */ |
| 196 | memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN); | 207 | memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN); |
| 197 | FIX_ENDIANNESS_CDE(cde_header); | 208 | FIX_ENDIANNESS_CDE(cde_header); |
| 198 | free(buf); | 209 | /* |
| 199 | return cde_header.formatted.cdf_offset; | 210 | * I've seen .ZIP files with seemingly valid CDEs |
| 211 | * where cdf_offset points past EOF - ?? | ||
| 212 | * Ignore such CDEs: | ||
| 213 | */ | ||
| 214 | if (cde_header.formatted.cdf_offset < end + (p - buf)) | ||
| 215 | break; | ||
| 216 | cde_header.formatted.cdf_offset = BAD_CDF_OFFSET; | ||
| 200 | } | 217 | } |
| 201 | //free(buf); | 218 | free(buf); |
| 202 | bb_error_msg_and_die("can't find file table"); | 219 | return cde_header.formatted.cdf_offset; |
| 203 | }; | 220 | }; |
| 204 | 221 | ||
| 205 | static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) | 222 | static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) |
| @@ -211,13 +228,15 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) | |||
| 211 | if (!cdf_offset) | 228 | if (!cdf_offset) |
| 212 | cdf_offset = find_cdf_offset(); | 229 | cdf_offset = find_cdf_offset(); |
| 213 | 230 | ||
| 214 | xlseek(zip_fd, cdf_offset + 4, SEEK_SET); | 231 | if (cdf_offset != BAD_CDF_OFFSET) { |
| 215 | xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); | 232 | xlseek(zip_fd, cdf_offset + 4, SEEK_SET); |
| 216 | FIX_ENDIANNESS_CDF(*cdf_ptr); | 233 | xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); |
| 217 | cdf_offset += 4 + CDF_HEADER_LEN | 234 | FIX_ENDIANNESS_CDF(*cdf_ptr); |
| 218 | + cdf_ptr->formatted.file_name_length | 235 | cdf_offset += 4 + CDF_HEADER_LEN |
| 219 | + cdf_ptr->formatted.extra_field_length | 236 | + cdf_ptr->formatted.file_name_length |
| 220 | + cdf_ptr->formatted.file_comment_length; | 237 | + cdf_ptr->formatted.extra_field_length |
| 238 | + cdf_ptr->formatted.file_comment_length; | ||
| 239 | } | ||
| 221 | 240 | ||
| 222 | xlseek(zip_fd, org, SEEK_SET); | 241 | xlseek(zip_fd, org, SEEK_SET); |
| 223 | return cdf_offset; | 242 | return cdf_offset; |
| @@ -226,8 +245,9 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) | |||
| 226 | 245 | ||
| 227 | static void unzip_skip(off_t skip) | 246 | static void unzip_skip(off_t skip) |
| 228 | { | 247 | { |
| 229 | if (lseek(zip_fd, skip, SEEK_CUR) == (off_t)-1) | 248 | if (skip != 0) |
| 230 | bb_copyfd_exact_size(zip_fd, -1, skip); | 249 | if (lseek(zip_fd, skip, SEEK_CUR) == (off_t)-1) |
| 250 | bb_copyfd_exact_size(zip_fd, -1, skip); | ||
| 231 | } | 251 | } |
| 232 | 252 | ||
| 233 | static void unzip_create_leading_dirs(const char *fn) | 253 | static void unzip_create_leading_dirs(const char *fn) |
| @@ -528,21 +548,31 @@ int unzip_main(int argc, char **argv) | |||
| 528 | bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); | 548 | bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); |
| 529 | } | 549 | } |
| 530 | 550 | ||
| 531 | { | 551 | if (cdf_offset != BAD_CDF_OFFSET) { |
| 532 | cdf_header_t cdf_header; | 552 | cdf_header_t cdf_header; |
| 533 | cdf_offset = read_next_cdf(cdf_offset, &cdf_header); | 553 | cdf_offset = read_next_cdf(cdf_offset, &cdf_header); |
| 554 | /* | ||
| 555 | * Note: cdf_offset can become BAD_CDF_OFFSET after the above call. | ||
| 556 | */ | ||
| 534 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { | 557 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { |
| 535 | /* 0x0008 - streaming. [u]cmpsize can be reliably gotten | 558 | /* 0x0008 - streaming. [u]cmpsize can be reliably gotten |
| 536 | * only from Central Directory. See unzip_doc.txt */ | 559 | * only from Central Directory. See unzip_doc.txt |
| 560 | */ | ||
| 537 | zip_header.formatted.crc32 = cdf_header.formatted.crc32; | 561 | zip_header.formatted.crc32 = cdf_header.formatted.crc32; |
| 538 | zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; | 562 | zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; |
| 539 | zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; | 563 | zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; |
| 540 | } | 564 | } |
| 541 | if ((cdf_header.formatted.version_made_by >> 8) == 3) { | 565 | if ((cdf_header.formatted.version_made_by >> 8) == 3) { |
| 542 | /* this archive is created on Unix */ | 566 | /* This archive is created on Unix */ |
| 543 | dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); | 567 | dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); |
| 544 | } | 568 | } |
| 545 | } | 569 | } |
| 570 | if (cdf_offset == BAD_CDF_OFFSET | ||
| 571 | && (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) | ||
| 572 | ) { | ||
| 573 | /* If it's a streaming zip, we _require_ CDF */ | ||
| 574 | bb_error_msg_and_die("can't find file table"); | ||
| 575 | } | ||
| 546 | #endif | 576 | #endif |
| 547 | 577 | ||
| 548 | /* Read filename */ | 578 | /* Read filename */ |
diff --git a/coreutils/catv.c b/coreutils/catv.c index 214b4311a..e3499c597 100644 --- a/coreutils/catv.c +++ b/coreutils/catv.c | |||
| @@ -25,14 +25,23 @@ int catv_main(int argc UNUSED_PARAM, char **argv) | |||
| 25 | { | 25 | { |
| 26 | int retval = EXIT_SUCCESS; | 26 | int retval = EXIT_SUCCESS; |
| 27 | int fd; | 27 | int fd; |
| 28 | unsigned flags; | 28 | unsigned opts; |
| 29 | |||
| 30 | flags = getopt32(argv, "etv"); | ||
| 31 | #define CATV_OPT_e (1<<0) | 29 | #define CATV_OPT_e (1<<0) |
| 32 | #define CATV_OPT_t (1<<1) | 30 | #define CATV_OPT_t (1<<1) |
| 33 | #define CATV_OPT_v (1<<2) | 31 | #define CATV_OPT_v (1<<2) |
| 34 | flags ^= CATV_OPT_v; | 32 | typedef char BUG_const_mismatch[ |
| 33 | CATV_OPT_e == VISIBLE_ENDLINE && CATV_OPT_t == VISIBLE_SHOW_TABS | ||
| 34 | ? 1 : -1 | ||
| 35 | ]; | ||
| 36 | |||
| 37 | opts = getopt32(argv, "etv"); | ||
| 35 | argv += optind; | 38 | argv += optind; |
| 39 | #if 0 /* These consts match, we can just pass "opts" to visible() */ | ||
| 40 | if (opts & CATV_OPT_e) | ||
| 41 | flags |= VISIBLE_ENDLINE; | ||
| 42 | if (opts & CATV_OPT_t) | ||
| 43 | flags |= VISIBLE_SHOW_TABS; | ||
| 44 | #endif | ||
| 36 | 45 | ||
| 37 | /* Read from stdin if there's nothing else to do. */ | 46 | /* Read from stdin if there's nothing else to do. */ |
| 38 | if (!argv[0]) | 47 | if (!argv[0]) |
| @@ -50,29 +59,17 @@ int catv_main(int argc UNUSED_PARAM, char **argv) | |||
| 50 | res = read(fd, read_buf, COMMON_BUFSIZE); | 59 | res = read(fd, read_buf, COMMON_BUFSIZE); |
| 51 | if (res < 0) | 60 | if (res < 0) |
| 52 | retval = EXIT_FAILURE; | 61 | retval = EXIT_FAILURE; |
| 53 | if (res < 1) | 62 | if (res <= 0) |
| 54 | break; | 63 | break; |
| 55 | for (i = 0; i < res; i++) { | 64 | for (i = 0; i < res; i++) { |
| 56 | unsigned char c = read_buf[i]; | 65 | unsigned char c = read_buf[i]; |
| 57 | 66 | if (opts & CATV_OPT_v) { | |
| 58 | if (c > 126 && (flags & CATV_OPT_v)) { | 67 | putchar(c); |
| 59 | if (c == 127) { | 68 | } else { |
| 60 | printf("^?"); | 69 | char buf[sizeof("M-^c")]; |
| 61 | continue; | 70 | visible(c, buf, opts); |
| 62 | } | 71 | fputs(buf, stdout); |
| 63 | printf("M-"); | ||
| 64 | c -= 128; | ||
| 65 | } | ||
| 66 | if (c < 32) { | ||
| 67 | if (c == 10) { | ||
| 68 | if (flags & CATV_OPT_e) | ||
| 69 | bb_putchar('$'); | ||
| 70 | } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) { | ||
| 71 | printf("^%c", c+'@'); | ||
| 72 | continue; | ||
| 73 | } | ||
| 74 | } | 72 | } |
| 75 | bb_putchar(c); | ||
| 76 | } | 73 | } |
| 77 | } | 74 | } |
| 78 | if (ENABLE_FEATURE_CLEAN_UP && fd) | 75 | if (ENABLE_FEATURE_CLEAN_UP && fd) |
diff --git a/coreutils/dd.c b/coreutils/dd.c index f6869cb26..db61f665e 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
| @@ -30,10 +30,10 @@ | |||
| 30 | //usage: "\n conv=noerror Continue after read errors" | 30 | //usage: "\n conv=noerror Continue after read errors" |
| 31 | //usage: "\n conv=sync Pad blocks with zeros" | 31 | //usage: "\n conv=sync Pad blocks with zeros" |
| 32 | //usage: "\n conv=fsync Physically write data out before finishing" | 32 | //usage: "\n conv=fsync Physically write data out before finishing" |
| 33 | //usage: "\n conv=swab Swap every pair of bytes" | ||
| 33 | //usage: ) | 34 | //usage: ) |
| 34 | //usage: "\n" | 35 | //usage: "\n" |
| 35 | //usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024)," | 36 | //usage: "\nN may be suffixed by c (1), w (2), b (512), kD (1000), k (1024), MD, M, GD, G" |
| 36 | //usage: "\nMD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)" | ||
| 37 | //usage: | 37 | //usage: |
| 38 | //usage:#define dd_example_usage | 38 | //usage:#define dd_example_usage |
| 39 | //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" | 39 | //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" |
| @@ -151,13 +151,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 151 | enum { | 151 | enum { |
| 152 | /* Must be in the same order as OP_conv_XXX! */ | 152 | /* Must be in the same order as OP_conv_XXX! */ |
| 153 | /* (see "flags |= (1 << what)" below) */ | 153 | /* (see "flags |= (1 << what)" below) */ |
| 154 | FLAG_NOTRUNC = 1 << 0, | 154 | FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS, |
| 155 | FLAG_SYNC = 1 << 1, | 155 | FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS, |
| 156 | FLAG_NOERROR = 1 << 2, | 156 | FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS, |
| 157 | FLAG_FSYNC = 1 << 3, | 157 | FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, |
| 158 | FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, | ||
| 158 | /* end of conv flags */ | 159 | /* end of conv flags */ |
| 159 | FLAG_TWOBUFS = 1 << 4, | 160 | FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, |
| 160 | FLAG_COUNT = 1 << 5, | 161 | FLAG_COUNT = 1 << 6, |
| 161 | }; | 162 | }; |
| 162 | static const char keywords[] ALIGN1 = | 163 | static const char keywords[] ALIGN1 = |
| 163 | "bs\0""count\0""seek\0""skip\0""if\0""of\0" | 164 | "bs\0""count\0""seek\0""skip\0""if\0""of\0" |
| @@ -167,7 +168,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 167 | ; | 168 | ; |
| 168 | #if ENABLE_FEATURE_DD_IBS_OBS | 169 | #if ENABLE_FEATURE_DD_IBS_OBS |
| 169 | static const char conv_words[] ALIGN1 = | 170 | static const char conv_words[] ALIGN1 = |
| 170 | "notrunc\0""sync\0""noerror\0""fsync\0"; | 171 | "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; |
| 171 | #endif | 172 | #endif |
| 172 | enum { | 173 | enum { |
| 173 | OP_bs = 0, | 174 | OP_bs = 0, |
| @@ -185,11 +186,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 185 | OP_conv_sync, | 186 | OP_conv_sync, |
| 186 | OP_conv_noerror, | 187 | OP_conv_noerror, |
| 187 | OP_conv_fsync, | 188 | OP_conv_fsync, |
| 189 | OP_conv_swab, | ||
| 188 | /* Unimplemented conv=XXX: */ | 190 | /* Unimplemented conv=XXX: */ |
| 189 | //nocreat do not create the output file | 191 | //nocreat do not create the output file |
| 190 | //excl fail if the output file already exists | 192 | //excl fail if the output file already exists |
| 191 | //fdatasync physically write output file data before finishing | 193 | //fdatasync physically write output file data before finishing |
| 192 | //swab swap every pair of input bytes | ||
| 193 | //lcase change upper case to lower case | 194 | //lcase change upper case to lower case |
| 194 | //ucase change lower case to upper case | 195 | //ucase change lower case to upper case |
| 195 | //block pad newline-terminated records with spaces to cbs-size | 196 | //block pad newline-terminated records with spaces to cbs-size |
| @@ -197,23 +198,34 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 197 | //ascii from EBCDIC to ASCII | 198 | //ascii from EBCDIC to ASCII |
| 198 | //ebcdic from ASCII to EBCDIC | 199 | //ebcdic from ASCII to EBCDIC |
| 199 | //ibm from ASCII to alternate EBCDIC | 200 | //ibm from ASCII to alternate EBCDIC |
| 201 | /* Partially implemented: */ | ||
| 202 | //swab swap every pair of input bytes: will abort on non-even reads | ||
| 200 | #endif | 203 | #endif |
| 201 | }; | 204 | }; |
| 202 | int exitcode = EXIT_FAILURE; | 205 | smallint exitcode = EXIT_FAILURE; |
| 203 | int devzero = 0; | 206 | int devzero = 0; |
| 204 | size_t ibs = 512, obs = 512; | 207 | int i; |
| 205 | ssize_t n, w; | 208 | size_t ibs = 512; |
| 206 | char *ibuf, *obuf; | 209 | char *ibuf; |
| 207 | /* And these are all zeroed at once! */ | 210 | #if ENABLE_FEATURE_DD_IBS_OBS |
| 211 | size_t obs = 512; | ||
| 212 | char *obuf; | ||
| 213 | #else | ||
| 214 | # define obs ibs | ||
| 215 | # define obuf ibuf | ||
| 216 | #endif | ||
| 217 | /* These are all zeroed at once! */ | ||
| 208 | struct { | 218 | struct { |
| 209 | int flags; | 219 | int flags; |
| 210 | size_t oc; | 220 | size_t oc; |
| 221 | ssize_t prev_read_size; /* for detecting swab failure */ | ||
| 211 | off_t count; | 222 | off_t count; |
| 212 | off_t seek, skip; | 223 | off_t seek, skip; |
| 213 | const char *infile, *outfile; | 224 | const char *infile, *outfile; |
| 214 | } Z; | 225 | } Z; |
| 215 | #define flags (Z.flags ) | 226 | #define flags (Z.flags ) |
| 216 | #define oc (Z.oc ) | 227 | #define oc (Z.oc ) |
| 228 | #define prev_read_size (Z.prev_read_size) | ||
| 217 | #define count (Z.count ) | 229 | #define count (Z.count ) |
| 218 | #define seek (Z.seek ) | 230 | #define seek (Z.seek ) |
| 219 | #define skip (Z.skip ) | 231 | #define skip (Z.skip ) |
| @@ -224,10 +236,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 224 | INIT_G(); | 236 | INIT_G(); |
| 225 | //fflush_all(); - is this needed because of NOEXEC? | 237 | //fflush_all(); - is this needed because of NOEXEC? |
| 226 | 238 | ||
| 227 | for (n = 1; argv[n]; n++) { | 239 | for (i = 1; argv[i]; i++) { |
| 228 | int what; | 240 | int what; |
| 229 | char *val; | 241 | char *val; |
| 230 | char *arg = argv[n]; | 242 | char *arg = argv[i]; |
| 231 | 243 | ||
| 232 | #if ENABLE_DESKTOP | 244 | #if ENABLE_DESKTOP |
| 233 | /* "dd --". NB: coreutils 6.9 will complain if they see | 245 | /* "dd --". NB: coreutils 6.9 will complain if they see |
| @@ -256,6 +268,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 256 | } | 268 | } |
| 257 | if (what == OP_conv) { | 269 | if (what == OP_conv) { |
| 258 | while (1) { | 270 | while (1) { |
| 271 | int n; | ||
| 259 | /* find ',', replace them with NUL so we can use val for | 272 | /* find ',', replace them with NUL so we can use val for |
| 260 | * index_in_strings() without copying. | 273 | * index_in_strings() without copying. |
| 261 | * We rely on val being non-null, else strchr would fault. | 274 | * We rely on val being non-null, else strchr would fault. |
| @@ -263,20 +276,21 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 263 | arg = strchr(val, ','); | 276 | arg = strchr(val, ','); |
| 264 | if (arg) | 277 | if (arg) |
| 265 | *arg = '\0'; | 278 | *arg = '\0'; |
| 266 | what = index_in_strings(conv_words, val); | 279 | n = index_in_strings(conv_words, val); |
| 267 | if (what < 0) | 280 | if (n < 0) |
| 268 | bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); | 281 | bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); |
| 269 | flags |= (1 << what); | 282 | flags |= (1 << n); |
| 270 | if (!arg) /* no ',' left, so this was the last specifier */ | 283 | if (!arg) /* no ',' left, so this was the last specifier */ |
| 271 | break; | 284 | break; |
| 272 | /* *arg = ','; - to preserve ps listing? */ | 285 | /* *arg = ','; - to preserve ps listing? */ |
| 273 | val = arg + 1; /* skip this keyword and ',' */ | 286 | val = arg + 1; /* skip this keyword and ',' */ |
| 274 | } | 287 | } |
| 275 | continue; /* we trashed 'what', can't fall through */ | 288 | /*continue;*/ |
| 276 | } | 289 | } |
| 277 | #endif | 290 | #endif |
| 278 | if (what == OP_bs) { | 291 | if (what == OP_bs) { |
| 279 | ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); | 292 | ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); |
| 293 | obs = ibs; | ||
| 280 | /*continue;*/ | 294 | /*continue;*/ |
| 281 | } | 295 | } |
| 282 | /* These can be large: */ | 296 | /* These can be large: */ |
| @@ -301,14 +315,17 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 301 | outfile = val; | 315 | outfile = val; |
| 302 | /*continue;*/ | 316 | /*continue;*/ |
| 303 | } | 317 | } |
| 304 | } /* end of "for (argv[n])" */ | 318 | } /* end of "for (argv[i])" */ |
| 305 | 319 | ||
| 306 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | 320 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever |
| 307 | ibuf = obuf = xmalloc(ibs); | 321 | ibuf = xmalloc(ibs); |
| 322 | obuf = ibuf; | ||
| 323 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
| 308 | if (ibs != obs) { | 324 | if (ibs != obs) { |
| 309 | flags |= FLAG_TWOBUFS; | 325 | flags |= FLAG_TWOBUFS; |
| 310 | obuf = xmalloc(obs); | 326 | obuf = xmalloc(obs); |
| 311 | } | 327 | } |
| 328 | #endif | ||
| 312 | 329 | ||
| 313 | #if ENABLE_FEATURE_DD_SIGNAL_HANDLING | 330 | #if ENABLE_FEATURE_DD_SIGNAL_HANDLING |
| 314 | signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); | 331 | signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); |
| @@ -317,17 +334,17 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 317 | G.begin_time_us = monotonic_us(); | 334 | G.begin_time_us = monotonic_us(); |
| 318 | #endif | 335 | #endif |
| 319 | 336 | ||
| 320 | if (infile != NULL) | 337 | if (infile) { |
| 321 | if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) { | 338 | if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) { |
| 322 | flags |= FLAG_NOERROR; | 339 | flags |= FLAG_NOERROR; |
| 323 | devzero = 1; | 340 | devzero = 1; |
| 324 | } | 341 | } else { |
| 325 | else | ||
| 326 | xmove_fd(xopen(infile, O_RDONLY), ifd); | 342 | xmove_fd(xopen(infile, O_RDONLY), ifd); |
| 327 | else { | 343 | } |
| 344 | } else { | ||
| 328 | infile = bb_msg_standard_input; | 345 | infile = bb_msg_standard_input; |
| 329 | } | 346 | } |
| 330 | if (outfile != NULL) { | 347 | if (outfile) { |
| 331 | int oflag = O_WRONLY | O_CREAT; | 348 | int oflag = O_WRONLY | O_CREAT; |
| 332 | 349 | ||
| 333 | if (!seek && !(flags & FLAG_NOTRUNC)) | 350 | if (!seek && !(flags & FLAG_NOTRUNC)) |
| @@ -352,13 +369,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 352 | } | 369 | } |
| 353 | if (skip && !devzero) { | 370 | if (skip && !devzero) { |
| 354 | if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { | 371 | if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { |
| 355 | while (skip-- > 0) { | 372 | do { |
| 356 | n = safe_read(ifd, ibuf, ibs); | 373 | ssize_t n = safe_read(ifd, ibuf, ibs); |
| 357 | if (n < 0) | 374 | if (n < 0) |
| 358 | goto die_infile; | 375 | goto die_infile; |
| 359 | if (n == 0) | 376 | if (n == 0) |
| 360 | break; | 377 | break; |
| 361 | } | 378 | } while (--skip != 0); |
| 362 | } | 379 | } |
| 363 | } | 380 | } |
| 364 | if (seek) { | 381 | if (seek) { |
| @@ -367,6 +384,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 367 | } | 384 | } |
| 368 | 385 | ||
| 369 | while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { | 386 | while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { |
| 387 | ssize_t n; | ||
| 388 | |||
| 370 | if (devzero) { | 389 | if (devzero) { |
| 371 | memset(ibuf, 0, ibs); | 390 | memset(ibuf, 0, ibs); |
| 372 | n = ibs; | 391 | n = ibs; |
| @@ -386,6 +405,27 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 386 | * conv=noerror just ignores input bad blocks */ | 405 | * conv=noerror just ignores input bad blocks */ |
| 387 | n = 0; | 406 | n = 0; |
| 388 | } | 407 | } |
| 408 | if (flags & FLAG_SWAB) { | ||
| 409 | uint16_t *p16; | ||
| 410 | ssize_t n2; | ||
| 411 | |||
| 412 | /* Our code allows only last read to be odd-sized */ | ||
| 413 | if (prev_read_size & 1) | ||
| 414 | bb_error_msg_and_die("can't swab %lu byte buffer", | ||
| 415 | (unsigned long)prev_read_size); | ||
| 416 | prev_read_size = n; | ||
| 417 | |||
| 418 | /* If n is odd, last byte is not swapped: | ||
| 419 | * echo -n "qwe" | dd conv=swab | ||
| 420 | * prints "wqe". | ||
| 421 | */ | ||
| 422 | p16 = (void*) ibuf; | ||
| 423 | n2 = (n >> 1); | ||
| 424 | while (--n2 >= 0) { | ||
| 425 | *p16 = bswap_16(*p16); | ||
| 426 | p16++; | ||
| 427 | } | ||
| 428 | } | ||
| 389 | if ((size_t)n == ibs) | 429 | if ((size_t)n == ibs) |
| 390 | G.in_full++; | 430 | G.in_full++; |
| 391 | else { | 431 | else { |
| @@ -412,8 +452,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 412 | oc = 0; | 452 | oc = 0; |
| 413 | } | 453 | } |
| 414 | } | 454 | } |
| 415 | } else if (write_and_stats(ibuf, n, obs, outfile)) | 455 | } else { |
| 416 | goto out_status; | 456 | if (write_and_stats(ibuf, n, obs, outfile)) |
| 457 | goto out_status; | ||
| 458 | } | ||
| 417 | 459 | ||
| 418 | if (flags & FLAG_FSYNC) { | 460 | if (flags & FLAG_FSYNC) { |
| 419 | if (fsync(ofd) < 0) | 461 | if (fsync(ofd) < 0) |
| @@ -422,9 +464,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
| 422 | } | 464 | } |
| 423 | 465 | ||
| 424 | if (ENABLE_FEATURE_DD_IBS_OBS && oc) { | 466 | if (ENABLE_FEATURE_DD_IBS_OBS && oc) { |
| 425 | w = full_write_or_warn(obuf, oc, outfile); | 467 | if (write_and_stats(obuf, oc, obs, outfile)) |
| 426 | if (w < 0) goto out_status; | 468 | goto out_status; |
| 427 | if (w > 0) G.out_part++; | ||
| 428 | } | 469 | } |
| 429 | 470 | ||
| 430 | if (!devzero && close(ifd) < 0) { | 471 | if (!devzero && close(ifd) < 0) { |
diff --git a/coreutils/head.c b/coreutils/head.c index 291e1ce37..9388b026a 100644 --- a/coreutils/head.c +++ b/coreutils/head.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */ | 12 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */ |
| 13 | 13 | ||
| 14 | //kbuild:lib-$(CONFIG_HEAD) += head.o | 14 | //kbuild:lib-$(CONFIG_HEAD) += head.o |
| 15 | //kbuild:lib-$(CONFIG_HEAD) += head_tail.o | ||
| 16 | 15 | ||
| 17 | //usage:#define head_trivial_usage | 16 | //usage:#define head_trivial_usage |
| 18 | //usage: "[OPTIONS] [FILE]..." | 17 | //usage: "[OPTIONS] [FILE]..." |
| @@ -35,7 +34,6 @@ | |||
| 35 | //usage: "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n" | 34 | //usage: "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n" |
| 36 | 35 | ||
| 37 | #include "libbb.h" | 36 | #include "libbb.h" |
| 38 | #include "head_tail.h" | ||
| 39 | 37 | ||
| 40 | /* This is a NOEXEC applet. Be very careful! */ | 38 | /* This is a NOEXEC applet. Be very careful! */ |
| 41 | 39 | ||
| @@ -140,7 +138,7 @@ eat_num(bool *negative_N, const char *p) | |||
| 140 | p++; | 138 | p++; |
| 141 | } | 139 | } |
| 142 | #endif | 140 | #endif |
| 143 | return xatoul_sfx(p, head_tail_suffixes); | 141 | return xatoul_sfx(p, bkm_suffixes); |
| 144 | } | 142 | } |
| 145 | 143 | ||
| 146 | static const char head_opts[] ALIGN1 = | 144 | static const char head_opts[] ALIGN1 = |
diff --git a/coreutils/head_tail.c b/coreutils/head_tail.c deleted file mode 100644 index 1658c0d1b..000000000 --- a/coreutils/head_tail.c +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Denys Vlasenko | ||
| 3 | * | ||
| 4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 5 | */ | ||
| 6 | #include "libbb.h" | ||
| 7 | #include "head_tail.h" | ||
| 8 | |||
| 9 | const struct suffix_mult head_tail_suffixes[] = { | ||
| 10 | { "b", 512 }, | ||
| 11 | { "k", 1024 }, | ||
| 12 | { "m", 1024*1024 }, | ||
| 13 | { "", 0 } | ||
| 14 | }; | ||
diff --git a/coreutils/head_tail.h b/coreutils/head_tail.h deleted file mode 100644 index df19e41e0..000000000 --- a/coreutils/head_tail.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Denys Vlasenko | ||
| 3 | * | ||
| 4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 5 | */ | ||
| 6 | extern const struct suffix_mult head_tail_suffixes[]; | ||
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 92a4d4462..1a5342e87 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c | |||
| @@ -151,7 +151,9 @@ static uint8_t *hash_file(const char *filename) | |||
| 151 | update(&context, in_buf, count); | 151 | update(&context, in_buf, count); |
| 152 | } | 152 | } |
| 153 | hash_value = NULL; | 153 | hash_value = NULL; |
| 154 | if (count == 0) { | 154 | if (count < 0) |
| 155 | bb_perror_msg("can't read '%s'", filename); | ||
| 156 | else /* count == 0 */ { | ||
| 155 | final(&context, in_buf); | 157 | final(&context, in_buf); |
| 156 | hash_value = hash_bin_to_hex(in_buf, hash_len); | 158 | hash_value = hash_bin_to_hex(in_buf, hash_len); |
| 157 | } | 159 | } |
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index ee4f72ca1..c4d11601f 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c | |||
| @@ -1173,12 +1173,6 @@ parse_old_offset(const char *s, off_t *offset) | |||
| 1173 | int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1173 | int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 1174 | int od_main(int argc UNUSED_PARAM, char **argv) | 1174 | int od_main(int argc UNUSED_PARAM, char **argv) |
| 1175 | { | 1175 | { |
| 1176 | static const struct suffix_mult bkm[] = { | ||
| 1177 | { "b", 512 }, | ||
| 1178 | { "k", 1024 }, | ||
| 1179 | { "m", 1024*1024 }, | ||
| 1180 | { "", 0 } | ||
| 1181 | }; | ||
| 1182 | #if ENABLE_LONG_OPTS | 1176 | #if ENABLE_LONG_OPTS |
| 1183 | static const char od_longopts[] ALIGN1 = | 1177 | static const char od_longopts[] ALIGN1 = |
| 1184 | "skip-bytes\0" Required_argument "j" | 1178 | "skip-bytes\0" Required_argument "j" |
| @@ -1237,7 +1231,7 @@ int od_main(int argc UNUSED_PARAM, char **argv) | |||
| 1237 | address_pad_len_char = doxn_address_pad_len_char[pos]; | 1231 | address_pad_len_char = doxn_address_pad_len_char[pos]; |
| 1238 | } | 1232 | } |
| 1239 | if (opt & OPT_N) { | 1233 | if (opt & OPT_N) { |
| 1240 | max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm); | 1234 | max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm_suffixes); |
| 1241 | } | 1235 | } |
| 1242 | if (opt & OPT_a) decode_format_string("a"); | 1236 | if (opt & OPT_a) decode_format_string("a"); |
| 1243 | if (opt & OPT_b) decode_format_string("oC"); | 1237 | if (opt & OPT_b) decode_format_string("oC"); |
| @@ -1246,7 +1240,7 @@ int od_main(int argc UNUSED_PARAM, char **argv) | |||
| 1246 | if (opt & OPT_f) decode_format_string("fF"); | 1240 | if (opt & OPT_f) decode_format_string("fF"); |
| 1247 | if (opt & OPT_h) decode_format_string("x2"); | 1241 | if (opt & OPT_h) decode_format_string("x2"); |
| 1248 | if (opt & OPT_i) decode_format_string("d2"); | 1242 | if (opt & OPT_i) decode_format_string("d2"); |
| 1249 | if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm); | 1243 | if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm_suffixes); |
| 1250 | if (opt & OPT_l) decode_format_string("d4"); | 1244 | if (opt & OPT_l) decode_format_string("d4"); |
| 1251 | if (opt & OPT_o) decode_format_string("o2"); | 1245 | if (opt & OPT_o) decode_format_string("o2"); |
| 1252 | while (lst_t) { | 1246 | while (lst_t) { |
| @@ -1255,7 +1249,7 @@ int od_main(int argc UNUSED_PARAM, char **argv) | |||
| 1255 | if (opt & OPT_x) decode_format_string("x2"); | 1249 | if (opt & OPT_x) decode_format_string("x2"); |
| 1256 | if (opt & OPT_s) decode_format_string("d2"); | 1250 | if (opt & OPT_s) decode_format_string("d2"); |
| 1257 | if (opt & OPT_S) { | 1251 | if (opt & OPT_S) { |
| 1258 | string_min = xstrtou_sfx(str_S, 0, bkm); | 1252 | string_min = xstrtou_sfx(str_S, 0, bkm_suffixes); |
| 1259 | } | 1253 | } |
| 1260 | 1254 | ||
| 1261 | // Bloat: | 1255 | // Bloat: |
diff --git a/coreutils/split.c b/coreutils/split.c index 11e640442..1e1673efb 100644 --- a/coreutils/split.c +++ b/coreutils/split.c | |||
| @@ -23,17 +23,15 @@ | |||
| 23 | 23 | ||
| 24 | #include "libbb.h" | 24 | #include "libbb.h" |
| 25 | 25 | ||
| 26 | static const struct suffix_mult split_suffices[] = { | ||
| 27 | #if ENABLE_FEATURE_SPLIT_FANCY | 26 | #if ENABLE_FEATURE_SPLIT_FANCY |
| 27 | static const struct suffix_mult split_suffixes[] = { | ||
| 28 | { "b", 512 }, | 28 | { "b", 512 }, |
| 29 | #endif | ||
| 30 | { "k", 1024 }, | 29 | { "k", 1024 }, |
| 31 | { "m", 1024*1024 }, | 30 | { "m", 1024*1024 }, |
| 32 | #if ENABLE_FEATURE_SPLIT_FANCY | ||
| 33 | { "g", 1024*1024*1024 }, | 31 | { "g", 1024*1024*1024 }, |
| 34 | #endif | ||
| 35 | { "", 0 } | 32 | { "", 0 } |
| 36 | }; | 33 | }; |
| 34 | #endif | ||
| 37 | 35 | ||
| 38 | /* Increment the suffix part of the filename. | 36 | /* Increment the suffix part of the filename. |
| 39 | * Returns NULL if we are out of filenames. | 37 | * Returns NULL if we are out of filenames. |
| @@ -86,7 +84,10 @@ int split_main(int argc UNUSED_PARAM, char **argv) | |||
| 86 | if (opt & SPLIT_OPT_l) | 84 | if (opt & SPLIT_OPT_l) |
| 87 | cnt = XATOOFF(count_p); | 85 | cnt = XATOOFF(count_p); |
| 88 | if (opt & SPLIT_OPT_b) // FIXME: also needs XATOOFF | 86 | if (opt & SPLIT_OPT_b) // FIXME: also needs XATOOFF |
| 89 | cnt = xatoull_sfx(count_p, split_suffices); | 87 | cnt = xatoull_sfx(count_p, |
| 88 | IF_FEATURE_SPLIT_FANCY(split_suffixes) | ||
| 89 | IF_NOT_FEATURE_SPLIT_FANCY(km_suffixes) | ||
| 90 | ); | ||
| 90 | sfx = "x"; | 91 | sfx = "x"; |
| 91 | 92 | ||
| 92 | argv += optind; | 93 | argv += optind; |
diff --git a/coreutils/stty.c b/coreutils/stty.c index 96754dd84..378a848e7 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c | |||
| @@ -246,10 +246,21 @@ enum speed_setting { | |||
| 246 | 246 | ||
| 247 | /* Which member(s) of 'struct termios' a mode uses */ | 247 | /* Which member(s) of 'struct termios' a mode uses */ |
| 248 | enum { | 248 | enum { |
| 249 | /* Do NOT change the order or values, as mode_type_flag() | ||
| 250 | * depends on them */ | ||
| 251 | control, input, output, local, combination | 249 | control, input, output, local, combination |
| 252 | }; | 250 | }; |
| 251 | static tcflag_t *get_ptr_to_tcflag(unsigned type, const struct termios *mode) | ||
| 252 | { | ||
| 253 | static const uint8_t tcflag_offsets[] ALIGN1 = { | ||
| 254 | offsetof(struct termios, c_cflag), /* control */ | ||
| 255 | offsetof(struct termios, c_iflag), /* input */ | ||
| 256 | offsetof(struct termios, c_oflag), /* output */ | ||
| 257 | offsetof(struct termios, c_lflag) /* local */ | ||
| 258 | }; | ||
| 259 | if (type <= local) { | ||
| 260 | return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]); | ||
| 261 | } | ||
| 262 | return NULL; | ||
| 263 | } | ||
| 253 | 264 | ||
| 254 | /* Flags for 'struct mode_info' */ | 265 | /* Flags for 'struct mode_info' */ |
| 255 | #define SANE_SET 1 /* Set in 'sane' mode */ | 266 | #define SANE_SET 1 /* Set in 'sane' mode */ |
| @@ -770,51 +781,6 @@ struct globals { | |||
| 770 | G.max_col = 80; \ | 781 | G.max_col = 80; \ |
| 771 | } while (0) | 782 | } while (0) |
| 772 | 783 | ||
| 773 | |||
| 774 | /* Return a string that is the printable representation of character CH */ | ||
| 775 | /* Adapted from 'cat' by Torbjorn Granlund */ | ||
| 776 | static const char *visible(unsigned ch) | ||
| 777 | { | ||
| 778 | char *bpout = G.buf; | ||
| 779 | |||
| 780 | if (ch == _POSIX_VDISABLE) | ||
| 781 | return "<undef>"; | ||
| 782 | |||
| 783 | if (ch >= 128) { | ||
| 784 | ch -= 128; | ||
| 785 | *bpout++ = 'M'; | ||
| 786 | *bpout++ = '-'; | ||
| 787 | } | ||
| 788 | |||
| 789 | if (ch < 32) { | ||
| 790 | *bpout++ = '^'; | ||
| 791 | *bpout++ = ch + 64; | ||
| 792 | } else if (ch < 127) { | ||
| 793 | *bpout++ = ch; | ||
| 794 | } else { | ||
| 795 | *bpout++ = '^'; | ||
| 796 | *bpout++ = '?'; | ||
| 797 | } | ||
| 798 | |||
| 799 | *bpout = '\0'; | ||
| 800 | return G.buf; | ||
| 801 | } | ||
| 802 | |||
| 803 | static tcflag_t *mode_type_flag(unsigned type, const struct termios *mode) | ||
| 804 | { | ||
| 805 | static const uint8_t tcflag_offsets[] ALIGN1 = { | ||
| 806 | offsetof(struct termios, c_cflag), /* control */ | ||
| 807 | offsetof(struct termios, c_iflag), /* input */ | ||
| 808 | offsetof(struct termios, c_oflag), /* output */ | ||
| 809 | offsetof(struct termios, c_lflag) /* local */ | ||
| 810 | }; | ||
| 811 | |||
| 812 | if (type <= local) { | ||
| 813 | return (tcflag_t*) (((char*)mode) + tcflag_offsets[type]); | ||
| 814 | } | ||
| 815 | return NULL; | ||
| 816 | } | ||
| 817 | |||
| 818 | static void set_speed_or_die(enum speed_setting type, const char *arg, | 784 | static void set_speed_or_die(enum speed_setting type, const char *arg, |
| 819 | struct termios *mode) | 785 | struct termios *mode) |
| 820 | { | 786 | { |
| @@ -1042,6 +1008,7 @@ static void do_display(const struct termios *mode, int all) | |||
| 1042 | #endif | 1008 | #endif |
| 1043 | 1009 | ||
| 1044 | for (i = 0; i != CIDX_min; ++i) { | 1010 | for (i = 0; i != CIDX_min; ++i) { |
| 1011 | char ch; | ||
| 1045 | /* If swtch is the same as susp, don't print both */ | 1012 | /* If swtch is the same as susp, don't print both */ |
| 1046 | #if VSWTCH == VSUSP | 1013 | #if VSWTCH == VSUSP |
| 1047 | if (i == CIDX_swtch) | 1014 | if (i == CIDX_swtch) |
| @@ -1055,8 +1022,12 @@ static void do_display(const struct termios *mode, int all) | |||
| 1055 | continue; | 1022 | continue; |
| 1056 | } | 1023 | } |
| 1057 | #endif | 1024 | #endif |
| 1058 | wrapf("%s = %s;", nth_string(control_name, i), | 1025 | ch = mode->c_cc[control_info[i].offset]; |
| 1059 | visible(mode->c_cc[control_info[i].offset])); | 1026 | if (ch == _POSIX_VDISABLE) |
| 1027 | strcpy(G.buf, "<undef>"); | ||
| 1028 | else | ||
| 1029 | visible(ch, G.buf, 0); | ||
| 1030 | wrapf("%s = %s;", nth_string(control_name, i), G.buf); | ||
| 1060 | } | 1031 | } |
| 1061 | #if VEOF == VMIN | 1032 | #if VEOF == VMIN |
| 1062 | if ((mode->c_lflag & ICANON) == 0) | 1033 | if ((mode->c_lflag & ICANON) == 0) |
| @@ -1072,7 +1043,7 @@ static void do_display(const struct termios *mode, int all) | |||
| 1072 | prev_type = mode_info[i].type; | 1043 | prev_type = mode_info[i].type; |
| 1073 | } | 1044 | } |
| 1074 | 1045 | ||
| 1075 | bitsp = mode_type_flag(mode_info[i].type, mode); | 1046 | bitsp = get_ptr_to_tcflag(mode_info[i].type, mode); |
| 1076 | mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits; | 1047 | mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits; |
| 1077 | if ((*bitsp & mask) == mode_info[i].bits) { | 1048 | if ((*bitsp & mask) == mode_info[i].bits) { |
| 1078 | if (all || (mode_info[i].flags & SANE_UNSET)) | 1049 | if (all || (mode_info[i].flags & SANE_UNSET)) |
| @@ -1091,7 +1062,6 @@ static void do_display(const struct termios *mode, int all) | |||
| 1091 | static void sane_mode(struct termios *mode) | 1062 | static void sane_mode(struct termios *mode) |
| 1092 | { | 1063 | { |
| 1093 | int i; | 1064 | int i; |
| 1094 | tcflag_t *bitsp; | ||
| 1095 | 1065 | ||
| 1096 | for (i = 0; i < NUM_control_info; ++i) { | 1066 | for (i = 0; i < NUM_control_info; ++i) { |
| 1097 | #if VMIN == VEOF | 1067 | #if VMIN == VEOF |
| @@ -1102,14 +1072,17 @@ static void sane_mode(struct termios *mode) | |||
| 1102 | } | 1072 | } |
| 1103 | 1073 | ||
| 1104 | for (i = 0; i < NUM_mode_info; ++i) { | 1074 | for (i = 0; i < NUM_mode_info; ++i) { |
| 1075 | tcflag_t val; | ||
| 1076 | tcflag_t *bitsp = get_ptr_to_tcflag(mode_info[i].type, mode); | ||
| 1077 | |||
| 1078 | if (!bitsp) | ||
| 1079 | continue; | ||
| 1080 | val = *bitsp & ~((unsigned long)mode_info[i].mask); | ||
| 1105 | if (mode_info[i].flags & SANE_SET) { | 1081 | if (mode_info[i].flags & SANE_SET) { |
| 1106 | bitsp = mode_type_flag(mode_info[i].type, mode); | 1082 | *bitsp = val | mode_info[i].bits; |
| 1107 | *bitsp = (*bitsp & ~((unsigned long)mode_info[i].mask)) | 1083 | } else |
| 1108 | | mode_info[i].bits; | 1084 | if (mode_info[i].flags & SANE_UNSET) { |
| 1109 | } else if (mode_info[i].flags & SANE_UNSET) { | 1085 | *bitsp = val & ~mode_info[i].bits; |
| 1110 | bitsp = mode_type_flag(mode_info[i].type, mode); | ||
| 1111 | *bitsp = *bitsp & ~((unsigned long)mode_info[i].mask) | ||
| 1112 | & ~mode_info[i].bits; | ||
| 1113 | } | 1086 | } |
| 1114 | } | 1087 | } |
| 1115 | } | 1088 | } |
| @@ -1119,17 +1092,18 @@ static void set_mode(const struct mode_info *info, int reversed, | |||
| 1119 | { | 1092 | { |
| 1120 | tcflag_t *bitsp; | 1093 | tcflag_t *bitsp; |
| 1121 | 1094 | ||
| 1122 | bitsp = mode_type_flag(info->type, mode); | 1095 | bitsp = get_ptr_to_tcflag(info->type, mode); |
| 1123 | 1096 | ||
| 1124 | if (bitsp) { | 1097 | if (bitsp) { |
| 1098 | tcflag_t val = *bitsp & ~info->mask; | ||
| 1125 | if (reversed) | 1099 | if (reversed) |
| 1126 | *bitsp = *bitsp & ~info->mask & ~info->bits; | 1100 | *bitsp = val & ~info->bits; |
| 1127 | else | 1101 | else |
| 1128 | *bitsp = (*bitsp & ~info->mask) | info->bits; | 1102 | *bitsp = val | info->bits; |
| 1129 | return; | 1103 | return; |
| 1130 | } | 1104 | } |
| 1131 | 1105 | ||
| 1132 | /* Combination mode */ | 1106 | /* !bitsp - it's a "combination" mode */ |
| 1133 | if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) { | 1107 | if (info == &mode_info[IDX_evenp] || info == &mode_info[IDX_parity]) { |
| 1134 | if (reversed) | 1108 | if (reversed) |
| 1135 | mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; | 1109 | mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; |
| @@ -1534,7 +1508,12 @@ int stty_main(int argc UNUSED_PARAM, char **argv) | |||
| 1534 | perror_on_device_and_die("%s"); | 1508 | perror_on_device_and_die("%s"); |
| 1535 | 1509 | ||
| 1536 | if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) { | 1510 | if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) { |
| 1537 | #if CIBAUD | 1511 | /* |
| 1512 | * I think the below chunk is not necessary on Linux. | ||
| 1513 | * If you are deleting it, also delete STTY_speed_was_set bit - | ||
| 1514 | * it is only ever checked here. | ||
| 1515 | */ | ||
| 1516 | #if 0 /* was "if CIBAUD" */ | ||
| 1538 | /* SunOS 4.1.3 (at least) has the problem that after this sequence, | 1517 | /* SunOS 4.1.3 (at least) has the problem that after this sequence, |
| 1539 | tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2); | 1518 | tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2); |
| 1540 | sometimes (m1 != m2). The only difference is in the four bits | 1519 | sometimes (m1 != m2). The only difference is in the four bits |
diff --git a/coreutils/tail.c b/coreutils/tail.c index 19fd8f695..07c71ca4b 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | //kbuild:lib-$(CONFIG_TAIL) += tail.o | 27 | //kbuild:lib-$(CONFIG_TAIL) += tail.o |
| 28 | //kbuild:lib-$(CONFIG_TAIL) += head_tail.o | ||
| 29 | 28 | ||
| 30 | //usage:#define tail_trivial_usage | 29 | //usage:#define tail_trivial_usage |
| 31 | //usage: "[OPTIONS] [FILE]..." | 30 | //usage: "[OPTIONS] [FILE]..." |
| @@ -51,7 +50,6 @@ | |||
| 51 | //usage: "nameserver 10.0.0.1\n" | 50 | //usage: "nameserver 10.0.0.1\n" |
| 52 | 51 | ||
| 53 | #include "libbb.h" | 52 | #include "libbb.h" |
| 54 | #include "head_tail.h" | ||
| 55 | 53 | ||
| 56 | struct globals { | 54 | struct globals { |
| 57 | bool from_top; | 55 | bool from_top; |
| @@ -69,15 +67,6 @@ static void tail_xprint_header(const char *fmt, const char *filename) | |||
| 69 | static ssize_t tail_read(int fd, char *buf, size_t count) | 67 | static ssize_t tail_read(int fd, char *buf, size_t count) |
| 70 | { | 68 | { |
| 71 | ssize_t r; | 69 | ssize_t r; |
| 72 | off_t current; | ||
| 73 | struct stat sbuf; | ||
| 74 | |||
| 75 | /* /proc files report zero st_size, don't lseek them. */ | ||
| 76 | if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { | ||
| 77 | current = lseek(fd, 0, SEEK_CUR); | ||
| 78 | if (sbuf.st_size < current) | ||
| 79 | xlseek(fd, 0, SEEK_SET); | ||
| 80 | } | ||
| 81 | 70 | ||
| 82 | r = full_read(fd, buf, count); | 71 | r = full_read(fd, buf, count); |
| 83 | if (r < 0) { | 72 | if (r < 0) { |
| @@ -98,7 +87,7 @@ static unsigned eat_num(const char *p) | |||
| 98 | p++; | 87 | p++; |
| 99 | G.from_top = 1; | 88 | G.from_top = 1; |
| 100 | } | 89 | } |
| 101 | return xatou_sfx(p, head_tail_suffixes); | 90 | return xatou_sfx(p, bkm_suffixes); |
| 102 | } | 91 | } |
| 103 | 92 | ||
| 104 | int tail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 93 | int tail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| @@ -363,7 +352,19 @@ int tail_main(int argc, char **argv) | |||
| 363 | if (nfiles > header_threshhold) { | 352 | if (nfiles > header_threshhold) { |
| 364 | fmt = header_fmt_str; | 353 | fmt = header_fmt_str; |
| 365 | } | 354 | } |
| 366 | while ((nread = tail_read(fd, tailbuf, BUFSIZ)) > 0) { | 355 | for (;;) { |
| 356 | /* tail -f keeps following files even if they are truncated */ | ||
| 357 | struct stat sbuf; | ||
| 358 | /* /proc files report zero st_size, don't lseek them */ | ||
| 359 | if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { | ||
| 360 | off_t current = lseek(fd, 0, SEEK_CUR); | ||
| 361 | if (sbuf.st_size < current) | ||
| 362 | xlseek(fd, 0, SEEK_SET); | ||
| 363 | } | ||
| 364 | |||
| 365 | nread = tail_read(fd, tailbuf, BUFSIZ); | ||
| 366 | if (nread <= 0) | ||
| 367 | break; | ||
| 367 | if (fmt) { | 368 | if (fmt) { |
| 368 | tail_xprint_header(fmt, filename); | 369 | tail_xprint_header(fmt, filename); |
| 369 | fmt = NULL; | 370 | fmt = NULL; |
diff --git a/docs/tcp.txt b/docs/tcp.txt new file mode 100644 index 000000000..766766387 --- /dev/null +++ b/docs/tcp.txt | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | Some less-widely known details of TCP connections. | ||
| 2 | |||
| 3 | Properly closing the connection. | ||
| 4 | |||
| 5 | After this code sequence: | ||
| 6 | |||
| 7 | sock = socket(AF_INET, SOCK_STREAM, 0); | ||
| 8 | connect(sock, &remote, sizeof(remote)); | ||
| 9 | write(sock, buffer, 1000000); | ||
| 10 | |||
| 11 | a large block of data is only buffered by kernel, it can't be sent all at once. | ||
| 12 | What will happen if we close the socket? | ||
| 13 | |||
| 14 | "A host MAY implement a 'half-duplex' TCP close sequence, so that | ||
| 15 | an application that has called close() cannot continue to read | ||
| 16 | data from the connection. If such a host issues a close() call | ||
| 17 | while received data is still pending in TCP, or if new data is | ||
| 18 | received after close() is called, its TCP SHOULD send a RST | ||
| 19 | to show that data was lost." | ||
| 20 | |||
| 21 | IOW: if we just close(sock) now, kernel can reset the TCP connection, | ||
| 22 | discarding some not-yet sent data. | ||
| 23 | |||
| 24 | What can be done about it? | ||
| 25 | |||
| 26 | Solution #1: block until sending is done: | ||
| 27 | |||
| 28 | /* When enabled, a close(2) or shutdown(2) will not return until | ||
| 29 | * all queued messages for the socket have been successfully sent | ||
| 30 | * or the linger timeout has been reached. | ||
| 31 | */ | ||
| 32 | struct linger { | ||
| 33 | int l_onoff; /* linger active */ | ||
| 34 | int l_linger; /* how many seconds to linger for */ | ||
| 35 | } linger; | ||
| 36 | linger.l_onoff = 1; | ||
| 37 | linger.l_linger = SOME_NUM; | ||
| 38 | setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); | ||
| 39 | close(sock); | ||
| 40 | |||
| 41 | Solution #2: tell kernel that you are done sending. | ||
| 42 | This makes kernel send FIN after all data is written: | ||
| 43 | |||
| 44 | shutdown(sock, SHUT_WR); | ||
| 45 | close(sock); | ||
| 46 | |||
| 47 | However, experiments on Linux 3.9.4 show that kernel can return from | ||
| 48 | shutdown() and from close() before all data is sent, | ||
| 49 | and if peer sends any data to us after this, kernel stll responds with | ||
| 50 | RST before all our data is sent. | ||
| 51 | |||
| 52 | In practice the protocol in use often does not allow peer to send | ||
| 53 | such data to us, in which case this solution is acceptable. | ||
| 54 | |||
| 55 | If you know that peer is going to close its end after it sees our FIN | ||
| 56 | (as EOF), it might be a good idea to perform a read after shutdown(). | ||
| 57 | When read finishes with 0-sized result, we conclude that peer received all | ||
| 58 | the data, saw EOF, and closed its end. | ||
| 59 | |||
| 60 | However, this incurs small performance penalty (we run for a longer time) | ||
| 61 | and requires safeguards (nonblocking reads, timeouts etc) against | ||
| 62 | malicious peers which don't close the connection. | ||
| 63 | |||
| 64 | |||
| 65 | Defeating Nagle. | ||
| 66 | |||
| 67 | Method #1: manually control whether partial sends are allowed: | ||
| 68 | |||
| 69 | This prevents partially filled packets being sent: | ||
| 70 | |||
| 71 | int state = 1; | ||
| 72 | setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)); | ||
| 73 | |||
| 74 | and this forces last, partially filled packet (if any) to be sent: | ||
| 75 | |||
| 76 | int state = 0; | ||
| 77 | setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state)); | ||
| 78 | |||
| 79 | Method #2: make any write to immediately send data, even if it's partial: | ||
| 80 | |||
| 81 | int state = 1; | ||
| 82 | setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &state, sizeof(state)); | ||
diff --git a/editors/awk.c b/editors/awk.c index 0b573a065..77784dfc1 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
| @@ -190,7 +190,7 @@ typedef struct tsplitter_s { | |||
| 190 | 190 | ||
| 191 | /* combined token classes */ | 191 | /* combined token classes */ |
| 192 | #define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN) | 192 | #define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN) |
| 193 | #define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST) | 193 | //#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST) |
| 194 | #define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \ | 194 | #define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \ |
| 195 | | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER) | 195 | | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER) |
| 196 | 196 | ||
| @@ -2015,8 +2015,8 @@ static int fmt_num(char *b, int size, const char *format, double n, int int_as_i | |||
| 2015 | char c; | 2015 | char c; |
| 2016 | const char *s = format; | 2016 | const char *s = format; |
| 2017 | 2017 | ||
| 2018 | if (int_as_int && n == (int)n) { | 2018 | if (int_as_int && n == (long long)n) { |
| 2019 | r = snprintf(b, size, "%d", (int)n); | 2019 | r = snprintf(b, size, "%lld", (long long)n); |
| 2020 | } else { | 2020 | } else { |
| 2021 | do { c = *s; } while (c && *++s); | 2021 | do { c = *s; } while (c && *++s); |
| 2022 | if (strchr("diouxX", c)) { | 2022 | if (strchr("diouxX", c)) { |
| @@ -2662,7 +2662,7 @@ static var *evaluate(node *op, var *res) | |||
| 2662 | const char *sv_progname; | 2662 | const char *sv_progname; |
| 2663 | 2663 | ||
| 2664 | /* The body might be empty, still has to eval the args */ | 2664 | /* The body might be empty, still has to eval the args */ |
| 2665 | if (!op->r.n->info) | 2665 | if (!op->r.n->info && !op->r.f->body.first) |
| 2666 | syntax_error(EMSG_UNDEF_FUNC); | 2666 | syntax_error(EMSG_UNDEF_FUNC); |
| 2667 | 2667 | ||
| 2668 | vbeg = v = nvalloc(op->r.f->nargs + 1); | 2668 | vbeg = v = nvalloc(op->r.f->nargs + 1); |
| @@ -2733,7 +2733,7 @@ static var *evaluate(node *op, var *res) | |||
| 2733 | 2733 | ||
| 2734 | switch (opn) { | 2734 | switch (opn) { |
| 2735 | case F_in: | 2735 | case F_in: |
| 2736 | R_d = (int)L_d; | 2736 | R_d = (long long)L_d; |
| 2737 | break; | 2737 | break; |
| 2738 | 2738 | ||
| 2739 | case F_rn: | 2739 | case F_rn: |
| @@ -2931,7 +2931,7 @@ static var *evaluate(node *op, var *res) | |||
| 2931 | case '%': | 2931 | case '%': |
| 2932 | if (R_d == 0) | 2932 | if (R_d == 0) |
| 2933 | syntax_error(EMSG_DIV_BY_ZERO); | 2933 | syntax_error(EMSG_DIV_BY_ZERO); |
| 2934 | L_d -= (int)(L_d / R_d) * R_d; | 2934 | L_d -= (long long)(L_d / R_d) * R_d; |
| 2935 | break; | 2935 | break; |
| 2936 | } | 2936 | } |
| 2937 | debug_printf_eval("BINARY/REPLACE result:%f\n", L_d); | 2937 | debug_printf_eval("BINARY/REPLACE result:%f\n", L_d); |
diff --git a/editors/sed.c b/editors/sed.c index f8ca5d351..3a0d917aa 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
| @@ -330,7 +330,7 @@ static int get_address(const char *my_str, int *linenum, regex_t ** regex) | |||
| 330 | next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); | 330 | next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); |
| 331 | temp = copy_parsing_escapes(pos, next); | 331 | temp = copy_parsing_escapes(pos, next); |
| 332 | *regex = xzalloc(sizeof(regex_t)); | 332 | *regex = xzalloc(sizeof(regex_t)); |
| 333 | xregcomp(*regex, temp, G.regex_type|REG_NEWLINE); | 333 | xregcomp(*regex, temp, G.regex_type); |
| 334 | free(temp); | 334 | free(temp); |
| 335 | /* Move position to next character after last delimiter */ | 335 | /* Move position to next character after last delimiter */ |
| 336 | pos += (next+1); | 336 | pos += (next+1); |
| @@ -649,6 +649,12 @@ static void add_cmd(const char *cmdstr) | |||
| 649 | sed_cmd->cmd = *cmdstr++; | 649 | sed_cmd->cmd = *cmdstr++; |
| 650 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); | 650 | cmdstr = parse_cmd_args(sed_cmd, cmdstr); |
| 651 | 651 | ||
| 652 | /* cmdstr now points past args. | ||
| 653 | * GNU sed requires a separator, if there are more commands, | ||
| 654 | * else it complains "char N: extra characters after command". | ||
| 655 | * Example: "sed 'p;d'". We also allow "sed 'pd'". | ||
| 656 | */ | ||
| 657 | |||
| 652 | /* Add the command to the command array */ | 658 | /* Add the command to the command array */ |
| 653 | *G.sed_cmd_tail = sed_cmd; | 659 | *G.sed_cmd_tail = sed_cmd; |
| 654 | G.sed_cmd_tail = &sed_cmd->next; | 660 | G.sed_cmd_tail = &sed_cmd->next; |
| @@ -1371,7 +1377,7 @@ static void process_files(void) | |||
| 1371 | /* It is possible to have a command line argument with embedded | 1377 | /* It is possible to have a command line argument with embedded |
| 1372 | * newlines. This counts as multiple command lines. | 1378 | * newlines. This counts as multiple command lines. |
| 1373 | * However, newline can be escaped: 's/e/z\<newline>z/' | 1379 | * However, newline can be escaped: 's/e/z\<newline>z/' |
| 1374 | * We check for this. | 1380 | * add_cmd() handles this. |
| 1375 | */ | 1381 | */ |
| 1376 | 1382 | ||
| 1377 | static void add_cmd_block(char *cmdstr) | 1383 | static void add_cmd_block(char *cmdstr) |
| @@ -1381,22 +1387,8 @@ static void add_cmd_block(char *cmdstr) | |||
| 1381 | cmdstr = sv = xstrdup(cmdstr); | 1387 | cmdstr = sv = xstrdup(cmdstr); |
| 1382 | do { | 1388 | do { |
| 1383 | eol = strchr(cmdstr, '\n'); | 1389 | eol = strchr(cmdstr, '\n'); |
| 1384 | next: | 1390 | if (eol) |
| 1385 | if (eol) { | ||
| 1386 | /* Count preceding slashes */ | ||
| 1387 | int slashes = 0; | ||
| 1388 | char *sl = eol; | ||
| 1389 | |||
| 1390 | while (sl != cmdstr && *--sl == '\\') | ||
| 1391 | slashes++; | ||
| 1392 | /* Odd number of preceding slashes - newline is escaped */ | ||
| 1393 | if (slashes & 1) { | ||
| 1394 | overlapping_strcpy(eol - 1, eol); | ||
| 1395 | eol = strchr(eol, '\n'); | ||
| 1396 | goto next; | ||
| 1397 | } | ||
| 1398 | *eol = '\0'; | 1391 | *eol = '\0'; |
| 1399 | } | ||
| 1400 | add_cmd(cmdstr); | 1392 | add_cmd(cmdstr); |
| 1401 | cmdstr = eol + 1; | 1393 | cmdstr = eol + 1; |
| 1402 | } while (eol); | 1394 | } while (eol); |
diff --git a/editors/vi.c b/editors/vi.c index d6c8c0dd8..ab49b3f7d 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
| @@ -1707,65 +1707,53 @@ static char *new_screen(int ro, int co) | |||
| 1707 | // search for pattern starting at p | 1707 | // search for pattern starting at p |
| 1708 | static char *char_search(char *p, const char *pat, int dir, int range) | 1708 | static char *char_search(char *p, const char *pat, int dir, int range) |
| 1709 | { | 1709 | { |
| 1710 | char *q; | ||
| 1711 | struct re_pattern_buffer preg; | 1710 | struct re_pattern_buffer preg; |
| 1711 | const char *err; | ||
| 1712 | char *q; | ||
| 1712 | int i; | 1713 | int i; |
| 1713 | int size; | 1714 | int size; |
| 1714 | 1715 | ||
| 1715 | re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; | 1716 | re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; |
| 1716 | preg.translate = 0; | 1717 | if (ignorecase) |
| 1717 | preg.fastmap = 0; | 1718 | re_syntax_options = RE_SYNTAX_POSIX_EXTENDED | RE_ICASE; |
| 1718 | preg.buffer = 0; | 1719 | |
| 1719 | preg.allocated = 0; | 1720 | memset(&preg, 0, sizeof(preg)); |
| 1721 | err = re_compile_pattern(pat, strlen(pat), &preg); | ||
| 1722 | if (err != NULL) { | ||
| 1723 | status_line_bold("bad search pattern '%s': %s", pat, err); | ||
| 1724 | return p; | ||
| 1725 | } | ||
| 1720 | 1726 | ||
| 1721 | // assume a LIMITED forward search | 1727 | // assume a LIMITED forward search |
| 1722 | q = next_line(p); | ||
| 1723 | q = end_line(q); | ||
| 1724 | q = end - 1; | 1728 | q = end - 1; |
| 1725 | if (dir == BACK) { | 1729 | if (dir == BACK) |
| 1726 | q = prev_line(p); | ||
| 1727 | q = text; | 1730 | q = text; |
| 1728 | } | ||
| 1729 | // count the number of chars to search over, forward or backward | ||
| 1730 | size = q - p; | ||
| 1731 | if (size < 0) | ||
| 1732 | size = p - q; | ||
| 1733 | // RANGE could be negative if we are searching backwards | 1731 | // RANGE could be negative if we are searching backwards |
| 1734 | range = q - p; | 1732 | range = q - p; |
| 1735 | |||
| 1736 | q = (char *)re_compile_pattern(pat, strlen(pat), (struct re_pattern_buffer *)&preg); | ||
| 1737 | if (q != 0) { | ||
| 1738 | // The pattern was not compiled | ||
| 1739 | status_line_bold("bad search pattern: '%s': %s", pat, q); | ||
| 1740 | i = 0; // return p if pattern not compiled | ||
| 1741 | goto cs1; | ||
| 1742 | } | ||
| 1743 | |||
| 1744 | q = p; | 1733 | q = p; |
| 1734 | size = range; | ||
| 1745 | if (range < 0) { | 1735 | if (range < 0) { |
| 1736 | size = -size; | ||
| 1746 | q = p - size; | 1737 | q = p - size; |
| 1747 | if (q < text) | 1738 | if (q < text) |
| 1748 | q = text; | 1739 | q = text; |
| 1749 | } | 1740 | } |
| 1750 | // search for the compiled pattern, preg, in p[] | 1741 | // search for the compiled pattern, preg, in p[] |
| 1751 | // range < 0- search backward | 1742 | // range < 0: search backward |
| 1752 | // range > 0- search forward | 1743 | // range > 0: search forward |
| 1753 | // 0 < start < size | 1744 | // 0 < start < size |
| 1754 | // re_search() < 0 not found or error | 1745 | // re_search() < 0: not found or error |
| 1755 | // re_search() > 0 index of found pattern | 1746 | // re_search() >= 0: index of found pattern |
| 1756 | // struct pattern char int int int struct reg | 1747 | // struct pattern char int int int struct reg |
| 1757 | // re_search (*pattern_buffer, *string, size, start, range, *regs) | 1748 | // re_search(*pattern_buffer, *string, size, start, range, *regs) |
| 1758 | i = re_search(&preg, q, size, 0, range, 0); | 1749 | i = re_search(&preg, q, size, /*start:*/ 0, range, /*struct re_registers*:*/ NULL); |
| 1759 | if (i == -1) { | 1750 | regfree(&preg); |
| 1760 | p = 0; | 1751 | if (i < 0) |
| 1761 | i = 0; // return NULL if pattern not found | 1752 | return NULL; |
| 1762 | } | 1753 | if (dir == FORWARD) |
| 1763 | cs1: | ||
| 1764 | if (dir == FORWARD) { | ||
| 1765 | p = p + i; | 1754 | p = p + i; |
| 1766 | } else { | 1755 | else |
| 1767 | p = p - i; | 1756 | p = p - i; |
| 1768 | } | ||
| 1769 | return p; | 1757 | return p; |
| 1770 | } | 1758 | } |
| 1771 | 1759 | ||
| @@ -1790,7 +1778,7 @@ static char *char_search(char *p, const char *pat, int dir, int range) | |||
| 1790 | 1778 | ||
| 1791 | len = strlen(pat); | 1779 | len = strlen(pat); |
| 1792 | if (dir == FORWARD) { | 1780 | if (dir == FORWARD) { |
| 1793 | stop = end - 1; // assume range is p - end-1 | 1781 | stop = end - 1; // assume range is p..end-1 |
| 1794 | if (range == LIMITED) | 1782 | if (range == LIMITED) |
| 1795 | stop = next_line(p); // range is to next line | 1783 | stop = next_line(p); // range is to next line |
| 1796 | for (start = p; start < stop; start++) { | 1784 | for (start = p; start < stop; start++) { |
| @@ -1799,7 +1787,7 @@ static char *char_search(char *p, const char *pat, int dir, int range) | |||
| 1799 | } | 1787 | } |
| 1800 | } | 1788 | } |
| 1801 | } else if (dir == BACK) { | 1789 | } else if (dir == BACK) { |
| 1802 | stop = text; // assume range is text - p | 1790 | stop = text; // assume range is text..p |
| 1803 | if (range == LIMITED) | 1791 | if (range == LIMITED) |
| 1804 | stop = prev_line(p); // range is to prev line | 1792 | stop = prev_line(p); // range is to prev line |
| 1805 | for (start = p - len; start >= stop; start--) { | 1793 | for (start = p - len; start >= stop; start--) { |
diff --git a/findutils/find.c b/findutils/find.c index 2235b5049..53d8239c7 100644 --- a/findutils/find.c +++ b/findutils/find.c | |||
| @@ -231,12 +231,13 @@ | |||
| 231 | //kbuild:lib-$(CONFIG_FIND) += find.o | 231 | //kbuild:lib-$(CONFIG_FIND) += find.o |
| 232 | 232 | ||
| 233 | //usage:#define find_trivial_usage | 233 | //usage:#define find_trivial_usage |
| 234 | //usage: "[PATH]... [OPTIONS] [ACTIONS]" | 234 | //usage: "[-HL] [PATH]... [OPTIONS] [ACTIONS]" |
| 235 | //usage:#define find_full_usage "\n\n" | 235 | //usage:#define find_full_usage "\n\n" |
| 236 | //usage: "Search for files and perform actions on them.\n" | 236 | //usage: "Search for files and perform actions on them.\n" |
| 237 | //usage: "First failed action stops processing of current file.\n" | 237 | //usage: "First failed action stops processing of current file.\n" |
| 238 | //usage: "Defaults: PATH is current directory, action is '-print'\n" | 238 | //usage: "Defaults: PATH is current directory, action is '-print'\n" |
| 239 | //usage: "\n -follow Follow symlinks" | 239 | //usage: "\n -L,-follow Follow symlinks" |
| 240 | //usage: "\n -H ...on command line only" | ||
| 240 | //usage: IF_FEATURE_FIND_XDEV( | 241 | //usage: IF_FEATURE_FIND_XDEV( |
| 241 | //usage: "\n -xdev Don't descend directories on other filesystems" | 242 | //usage: "\n -xdev Don't descend directories on other filesystems" |
| 242 | //usage: ) | 243 | //usage: ) |
| @@ -814,6 +815,31 @@ static const char* plus_minus_num(const char* str) | |||
| 814 | } | 815 | } |
| 815 | #endif | 816 | #endif |
| 816 | 817 | ||
| 818 | /* Say no to GCCism */ | ||
| 819 | #define USE_NESTED_FUNCTION 0 | ||
| 820 | |||
| 821 | #if !USE_NESTED_FUNCTION | ||
| 822 | struct pp_locals { | ||
| 823 | action*** appp; | ||
| 824 | unsigned cur_group; | ||
| 825 | unsigned cur_action; | ||
| 826 | IF_FEATURE_FIND_NOT( bool invert_flag; ) | ||
| 827 | }; | ||
| 828 | static action* alloc_action(struct pp_locals *ppl, int sizeof_struct, action_fp f) | ||
| 829 | { | ||
| 830 | action *ap = xzalloc(sizeof_struct); | ||
| 831 | action **app; | ||
| 832 | action ***group = &ppl->appp[ppl->cur_group]; | ||
| 833 | *group = app = xrealloc(*group, (ppl->cur_action+2) * sizeof(ppl->appp[0][0])); | ||
| 834 | app[ppl->cur_action++] = ap; | ||
| 835 | app[ppl->cur_action] = NULL; | ||
| 836 | ap->f = f; | ||
| 837 | IF_FEATURE_FIND_NOT( ap->invert = ppl->invert_flag; ) | ||
| 838 | IF_FEATURE_FIND_NOT( ppl->invert_flag = 0; ) | ||
| 839 | return ap; | ||
| 840 | } | ||
| 841 | #endif | ||
| 842 | |||
| 817 | static action*** parse_params(char **argv) | 843 | static action*** parse_params(char **argv) |
| 818 | { | 844 | { |
| 819 | enum { | 845 | enum { |
| @@ -900,10 +926,18 @@ static action*** parse_params(char **argv) | |||
| 900 | IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0") | 926 | IF_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0") |
| 901 | ; | 927 | ; |
| 902 | 928 | ||
| 929 | #if !USE_NESTED_FUNCTION | ||
| 930 | struct pp_locals ppl; | ||
| 931 | #define appp (ppl.appp ) | ||
| 932 | #define cur_group (ppl.cur_group ) | ||
| 933 | #define cur_action (ppl.cur_action ) | ||
| 934 | #define invert_flag (ppl.invert_flag) | ||
| 935 | #define ALLOC_ACTION(name) (action_##name*)alloc_action(&ppl, sizeof(action_##name), (action_fp) func_##name) | ||
| 936 | #else | ||
| 903 | action*** appp; | 937 | action*** appp; |
| 904 | unsigned cur_group = 0; | 938 | unsigned cur_group; |
| 905 | unsigned cur_action = 0; | 939 | unsigned cur_action; |
| 906 | IF_FEATURE_FIND_NOT( bool invert_flag = 0; ) | 940 | IF_FEATURE_FIND_NOT( bool invert_flag; ) |
| 907 | 941 | ||
| 908 | /* This is the only place in busybox where we use nested function. | 942 | /* This is the only place in busybox where we use nested function. |
| 909 | * So far more standard alternatives were bigger. */ | 943 | * So far more standard alternatives were bigger. */ |
| @@ -912,7 +946,7 @@ static action*** parse_params(char **argv) | |||
| 912 | action* alloc_action(int sizeof_struct, action_fp f) | 946 | action* alloc_action(int sizeof_struct, action_fp f) |
| 913 | { | 947 | { |
| 914 | action *ap; | 948 | action *ap; |
| 915 | appp[cur_group] = xrealloc(appp[cur_group], (cur_action+2) * sizeof(*appp)); | 949 | appp[cur_group] = xrealloc(appp[cur_group], (cur_action+2) * sizeof(appp[0][0])); |
| 916 | appp[cur_group][cur_action++] = ap = xzalloc(sizeof_struct); | 950 | appp[cur_group][cur_action++] = ap = xzalloc(sizeof_struct); |
| 917 | appp[cur_group][cur_action] = NULL; | 951 | appp[cur_group][cur_action] = NULL; |
| 918 | ap->f = f; | 952 | ap->f = f; |
| @@ -920,9 +954,12 @@ static action*** parse_params(char **argv) | |||
| 920 | IF_FEATURE_FIND_NOT( invert_flag = 0; ) | 954 | IF_FEATURE_FIND_NOT( invert_flag = 0; ) |
| 921 | return ap; | 955 | return ap; |
| 922 | } | 956 | } |
| 923 | |||
| 924 | #define ALLOC_ACTION(name) (action_##name*)alloc_action(sizeof(action_##name), (action_fp) func_##name) | 957 | #define ALLOC_ACTION(name) (action_##name*)alloc_action(sizeof(action_##name), (action_fp) func_##name) |
| 958 | #endif | ||
| 925 | 959 | ||
| 960 | cur_group = 0; | ||
| 961 | cur_action = 0; | ||
| 962 | IF_FEATURE_FIND_NOT( invert_flag = 0; ) | ||
| 926 | appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */ | 963 | appp = xzalloc(2 * sizeof(appp[0])); /* appp[0],[1] == NULL */ |
| 927 | 964 | ||
| 928 | while (*argv) { | 965 | while (*argv) { |
| @@ -948,8 +985,8 @@ static action*** parse_params(char **argv) | |||
| 948 | */ | 985 | */ |
| 949 | /* Options */ | 986 | /* Options */ |
| 950 | if (parm == OPT_FOLLOW) { | 987 | if (parm == OPT_FOLLOW) { |
| 951 | dbg("follow enabled: %d", __LINE__); | 988 | dbg("follow enabled: %d", __LINE__); |
| 952 | G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK; | 989 | G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK; |
| 953 | } | 990 | } |
| 954 | #if ENABLE_FEATURE_FIND_XDEV | 991 | #if ENABLE_FEATURE_FIND_XDEV |
| 955 | else if (parm == OPT_XDEV) { | 992 | else if (parm == OPT_XDEV) { |
| @@ -987,7 +1024,7 @@ static action*** parse_params(char **argv) | |||
| 987 | dbg("%d", __LINE__); | 1024 | dbg("%d", __LINE__); |
| 988 | /* start new OR group */ | 1025 | /* start new OR group */ |
| 989 | cur_group++; | 1026 | cur_group++; |
| 990 | appp = xrealloc(appp, (cur_group+2) * sizeof(*appp)); | 1027 | appp = xrealloc(appp, (cur_group+2) * sizeof(appp[0])); |
| 991 | /*appp[cur_group] = NULL; - already NULL */ | 1028 | /*appp[cur_group] = NULL; - already NULL */ |
| 992 | appp[cur_group+1] = NULL; | 1029 | appp[cur_group+1] = NULL; |
| 993 | cur_action = 0; | 1030 | cur_action = 0; |
| @@ -1245,6 +1282,9 @@ static action*** parse_params(char **argv) | |||
| 1245 | dbg("exiting %s", __func__); | 1282 | dbg("exiting %s", __func__); |
| 1246 | return appp; | 1283 | return appp; |
| 1247 | #undef ALLOC_ACTION | 1284 | #undef ALLOC_ACTION |
| 1285 | #undef appp | ||
| 1286 | #undef cur_action | ||
| 1287 | #undef invert_flag | ||
| 1248 | } | 1288 | } |
| 1249 | 1289 | ||
| 1250 | int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1290 | int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| @@ -1254,7 +1294,15 @@ int find_main(int argc UNUSED_PARAM, char **argv) | |||
| 1254 | 1294 | ||
| 1255 | INIT_G(); | 1295 | INIT_G(); |
| 1256 | 1296 | ||
| 1257 | argv++; | 1297 | /* "+": stop on first non-option */ |
| 1298 | i = getopt32(argv, "+HLP"); | ||
| 1299 | if (i & (1<<0)) | ||
| 1300 | G.recurse_flags |= ACTION_FOLLOWLINKS_L0 | ACTION_DANGLING_OK; | ||
| 1301 | if (i & (1<<1)) | ||
| 1302 | G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK; | ||
| 1303 | /* -P is default and is ignored */ | ||
| 1304 | argv += optind; | ||
| 1305 | |||
| 1258 | for (firstopt = 0; argv[firstopt]; firstopt++) { | 1306 | for (firstopt = 0; argv[firstopt]; firstopt++) { |
| 1259 | if (argv[firstopt][0] == '-') | 1307 | if (argv[firstopt][0] == '-') |
| 1260 | break; | 1308 | break; |
diff --git a/findutils/grep.c b/findutils/grep.c index 6b47f4327..5bbe61100 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
| @@ -381,6 +381,8 @@ static int grep_file(FILE *file) | |||
| 381 | opt_f_not_found: ; | 381 | opt_f_not_found: ; |
| 382 | } | 382 | } |
| 383 | } else { | 383 | } else { |
| 384 | char *match_at; | ||
| 385 | |||
| 384 | if (!(gl->flg_mem_alocated_compiled & COMPILED)) { | 386 | if (!(gl->flg_mem_alocated_compiled & COMPILED)) { |
| 385 | gl->flg_mem_alocated_compiled |= COMPILED; | 387 | gl->flg_mem_alocated_compiled |= COMPILED; |
| 386 | #if !ENABLE_EXTRA_COMPAT | 388 | #if !ENABLE_EXTRA_COMPAT |
| @@ -396,32 +398,36 @@ static int grep_file(FILE *file) | |||
| 396 | gl->matched_range.rm_so = 0; | 398 | gl->matched_range.rm_so = 0; |
| 397 | gl->matched_range.rm_eo = 0; | 399 | gl->matched_range.rm_eo = 0; |
| 398 | #endif | 400 | #endif |
| 401 | match_at = line; | ||
| 402 | opt_w_again: | ||
| 399 | if ( | 403 | if ( |
| 400 | #if !ENABLE_EXTRA_COMPAT | 404 | #if !ENABLE_EXTRA_COMPAT |
| 401 | regexec(&gl->compiled_regex, line, 1, &gl->matched_range, 0) == 0 | 405 | regexec(&gl->compiled_regex, match_at, 1, &gl->matched_range, 0) == 0 |
| 402 | #else | 406 | #else |
| 403 | re_search(&gl->compiled_regex, line, line_len, | 407 | re_search(&gl->compiled_regex, match_at, line_len, |
| 404 | /*start:*/ 0, /*range:*/ line_len, | 408 | /*start:*/ 0, /*range:*/ line_len, |
| 405 | &gl->matched_range) >= 0 | 409 | &gl->matched_range) >= 0 |
| 406 | #endif | 410 | #endif |
| 407 | ) { | 411 | ) { |
| 408 | if (option_mask32 & OPT_x) { | 412 | if (option_mask32 & OPT_x) { |
| 409 | found = (gl->matched_range.rm_so == 0 | 413 | found = (gl->matched_range.rm_so == 0 |
| 410 | && line[gl->matched_range.rm_eo] == '\0'); | 414 | && match_at[gl->matched_range.rm_eo] == '\0'); |
| 411 | } else | 415 | } else |
| 412 | if (!(option_mask32 & OPT_w)) { | 416 | if (!(option_mask32 & OPT_w)) { |
| 413 | found = 1; | 417 | found = 1; |
| 414 | } else { | 418 | } else { |
| 415 | char c = ' '; | 419 | char c = ' '; |
| 416 | if (gl->matched_range.rm_so) | 420 | if (gl->matched_range.rm_so) |
| 417 | c = line[gl->matched_range.rm_so - 1]; | 421 | c = match_at[gl->matched_range.rm_so - 1]; |
| 418 | if (!isalnum(c) && c != '_') { | 422 | if (!isalnum(c) && c != '_') { |
| 419 | c = line[gl->matched_range.rm_eo]; | 423 | c = match_at[gl->matched_range.rm_eo]; |
| 420 | if (!c || (!isalnum(c) && c != '_')) | 424 | if (!c || (!isalnum(c) && c != '_')) { |
| 421 | found = 1; | 425 | found = 1; |
| 426 | } else { | ||
| 427 | match_at += gl->matched_range.rm_eo; | ||
| 428 | goto opt_w_again; | ||
| 429 | } | ||
| 422 | } | 430 | } |
| 423 | //BUG: "echo foop foo | grep -w foo" should match, but doesn't: | ||
| 424 | //we bail out on first "mismatch" because it's not a word. | ||
| 425 | } | 431 | } |
| 426 | } | 432 | } |
| 427 | } | 433 | } |
| @@ -718,7 +724,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv) | |||
| 718 | option_mask32 |= OPT_F; | 724 | option_mask32 |= OPT_F; |
| 719 | 725 | ||
| 720 | #if !ENABLE_EXTRA_COMPAT | 726 | #if !ENABLE_EXTRA_COMPAT |
| 721 | if (!(option_mask32 & (OPT_o | OPT_w))) | 727 | if (!(option_mask32 & (OPT_o | OPT_w | OPT_x))) |
| 722 | reflags = REG_NOSUB; | 728 | reflags = REG_NOSUB; |
| 723 | #endif | 729 | #endif |
| 724 | 730 | ||
diff --git a/include/applets.src.h b/include/applets.src.h index 00172b1bc..aa319bbc9 100644 --- a/include/applets.src.h +++ b/include/applets.src.h | |||
| @@ -52,6 +52,12 @@ s - suid type: | |||
| 52 | # define APPLET_NOEXEC(name,main,l,s,name2) LINK l name | 52 | # define APPLET_NOEXEC(name,main,l,s,name2) LINK l name |
| 53 | # define APPLET_NOFORK(name,main,l,s,name2) LINK l name | 53 | # define APPLET_NOFORK(name,main,l,s,name2) LINK l name |
| 54 | 54 | ||
| 55 | #elif defined(MAKE_SUID) | ||
| 56 | # define APPLET(name,l,s) SUID s l name | ||
| 57 | # define APPLET_ODDNAME(name,main,l,s,name2) SUID s l name | ||
| 58 | # define APPLET_NOEXEC(name,main,l,s,name2) SUID s l name | ||
| 59 | # define APPLET_NOFORK(name,main,l,s,name2) SUID s l name | ||
| 60 | |||
| 55 | #else | 61 | #else |
| 56 | static struct bb_applet applets[] = { /* name, main, location, need_suid */ | 62 | static struct bb_applet applets[] = { /* name, main, location, need_suid */ |
| 57 | # define APPLET(name,l,s) { #name, #name, l, s }, | 63 | # define APPLET(name,l,s) { #name, #name, l, s }, |
| @@ -415,7 +421,8 @@ IF_YES(APPLET_NOFORK(yes, yes, BB_DIR_USR_BIN, BB_SUID_DROP, yes)) | |||
| 415 | IF_GUNZIP(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) | 421 | IF_GUNZIP(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) |
| 416 | IF_ZCIP(APPLET(zcip, BB_DIR_SBIN, BB_SUID_DROP)) | 422 | IF_ZCIP(APPLET(zcip, BB_DIR_SBIN, BB_SUID_DROP)) |
| 417 | 423 | ||
| 418 | #if !defined(PROTOTYPES) && !defined(NAME_MAIN_CNAME) && !defined(MAKE_USAGE) | 424 | #if !defined(PROTOTYPES) && !defined(NAME_MAIN_CNAME) && !defined(MAKE_USAGE) \ |
| 425 | && !defined(MAKE_LINKS) && !defined(MAKE_SUID) | ||
| 419 | }; | 426 | }; |
| 420 | #endif | 427 | #endif |
| 421 | 428 | ||
diff --git a/include/bb_e2fs_defs.h b/include/bb_e2fs_defs.h index b400f8c11..3f5e3c45b 100644 --- a/include/bb_e2fs_defs.h +++ b/include/bb_e2fs_defs.h | |||
| @@ -442,7 +442,7 @@ struct ext2_super_block { | |||
| 442 | uint32_t s_reserved[162]; /* Padding to the end of the block */ | 442 | uint32_t s_reserved[162]; /* Padding to the end of the block */ |
| 443 | }; | 443 | }; |
| 444 | struct BUG_ext2_super_block { | 444 | struct BUG_ext2_super_block { |
| 445 | char bug[sizeof(struct ext2_super_block) == 1024 ? 1 : -1]; | 445 | char bug[sizeof(struct ext2_super_block) == 1024 ? 1 : -1]; |
| 446 | }; | 446 | }; |
| 447 | 447 | ||
| 448 | /* | 448 | /* |
diff --git a/include/libbb.h b/include/libbb.h index f5b7d8dc7..9adb037ca 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -496,9 +496,9 @@ int xmkstemp(char *template) FAST_FUNC; | |||
| 496 | off_t fdlength(int fd) FAST_FUNC; | 496 | off_t fdlength(int fd) FAST_FUNC; |
| 497 | 497 | ||
| 498 | uoff_t FAST_FUNC get_volume_size_in_bytes(int fd, | 498 | uoff_t FAST_FUNC get_volume_size_in_bytes(int fd, |
| 499 | const char *override, | 499 | const char *override, |
| 500 | unsigned override_units, | 500 | unsigned override_units, |
| 501 | int extend); | 501 | int extend); |
| 502 | 502 | ||
| 503 | void xpipe(int filedes[2]) FAST_FUNC; | 503 | void xpipe(int filedes[2]) FAST_FUNC; |
| 504 | /* In this form code with pipes is much more readable */ | 504 | /* In this form code with pipes is much more readable */ |
| @@ -691,6 +691,13 @@ const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str); | |||
| 691 | * else it is printed as-is (except for ch = 0x9b) */ | 691 | * else it is printed as-is (except for ch = 0x9b) */ |
| 692 | enum { PRINTABLE_META = 0x100 }; | 692 | enum { PRINTABLE_META = 0x100 }; |
| 693 | void fputc_printable(int ch, FILE *file) FAST_FUNC; | 693 | void fputc_printable(int ch, FILE *file) FAST_FUNC; |
| 694 | /* Return a string that is the printable representation of character ch. | ||
| 695 | * Buffer must hold at least four characters. */ | ||
| 696 | enum { | ||
| 697 | VISIBLE_ENDLINE = 1 << 0, | ||
| 698 | VISIBLE_SHOW_TABS = 1 << 1, | ||
| 699 | }; | ||
| 700 | void visible(unsigned ch, char *buf, int flags) FAST_FUNC; | ||
| 694 | 701 | ||
| 695 | /* dmalloc will redefine these to it's own implementation. It is safe | 702 | /* dmalloc will redefine these to it's own implementation. It is safe |
| 696 | * to have the prototypes here unconditionally. */ | 703 | * to have the prototypes here unconditionally. */ |
| @@ -848,6 +855,9 @@ struct suffix_mult { | |||
| 848 | char suffix[4]; | 855 | char suffix[4]; |
| 849 | unsigned mult; | 856 | unsigned mult; |
| 850 | }; | 857 | }; |
| 858 | extern const struct suffix_mult bkm_suffixes[]; | ||
| 859 | #define km_suffixes (bkm_suffixes + 1) | ||
| 860 | |||
| 851 | #include "xatonum.h" | 861 | #include "xatonum.h" |
| 852 | /* Specialized: */ | 862 | /* Specialized: */ |
| 853 | 863 | ||
| @@ -1125,9 +1135,6 @@ void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC; | |||
| 1125 | 1135 | ||
| 1126 | 1136 | ||
| 1127 | /* Networking */ | 1137 | /* Networking */ |
| 1128 | int create_icmp_socket(void) FAST_FUNC; | ||
| 1129 | int create_icmp6_socket(void) FAST_FUNC; | ||
| 1130 | /* interface.c */ | ||
| 1131 | /* This structure defines protocol families and their handlers. */ | 1138 | /* This structure defines protocol families and their handlers. */ |
| 1132 | struct aftype { | 1139 | struct aftype { |
| 1133 | const char *name; | 1140 | const char *name; |
| @@ -1156,6 +1163,7 @@ struct hwtype { | |||
| 1156 | }; | 1163 | }; |
| 1157 | extern smallint interface_opt_a; | 1164 | extern smallint interface_opt_a; |
| 1158 | int display_interfaces(char *ifname) FAST_FUNC; | 1165 | int display_interfaces(char *ifname) FAST_FUNC; |
| 1166 | int in_ether(const char *bufp, struct sockaddr *sap) FAST_FUNC; | ||
| 1159 | #if ENABLE_FEATURE_HWIB | 1167 | #if ENABLE_FEATURE_HWIB |
| 1160 | int in_ib(const char *bufp, struct sockaddr *sap) FAST_FUNC; | 1168 | int in_ib(const char *bufp, struct sockaddr *sap) FAST_FUNC; |
| 1161 | #else | 1169 | #else |
| @@ -1452,7 +1460,7 @@ void read_key_ungets(char *buffer, const char *str, unsigned len) FAST_FUNC; | |||
| 1452 | /* It's NOT just ENABLEd or disabled. It's a number: */ | 1460 | /* It's NOT just ENABLEd or disabled. It's a number: */ |
| 1453 | # if defined CONFIG_FEATURE_EDITING_HISTORY && CONFIG_FEATURE_EDITING_HISTORY > 0 | 1461 | # if defined CONFIG_FEATURE_EDITING_HISTORY && CONFIG_FEATURE_EDITING_HISTORY > 0 |
| 1454 | # define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0) | 1462 | # define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0) |
| 1455 | unsigned size_from_HISTFILESIZE(const char *hp); | 1463 | unsigned size_from_HISTFILESIZE(const char *hp) FAST_FUNC; |
| 1456 | # else | 1464 | # else |
| 1457 | # define MAX_HISTORY 0 | 1465 | # define MAX_HISTORY 0 |
| 1458 | # endif | 1466 | # endif |
| @@ -1494,6 +1502,7 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC; | |||
| 1494 | * >0 length of input string, including terminating '\n' | 1502 | * >0 length of input string, including terminating '\n' |
| 1495 | */ | 1503 | */ |
| 1496 | int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; | 1504 | int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; |
| 1505 | void show_history(const line_input_t *st) FAST_FUNC; | ||
| 1497 | # if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | 1506 | # if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
| 1498 | void save_history(line_input_t *st); | 1507 | void save_history(line_input_t *st); |
| 1499 | # endif | 1508 | # endif |
| @@ -1825,7 +1834,7 @@ extern const char bb_default_login_shell[] ALIGN1; | |||
| 1825 | # define VC_4 "/dev/vc/4" | 1834 | # define VC_4 "/dev/vc/4" |
| 1826 | # define VC_5 "/dev/vc/5" | 1835 | # define VC_5 "/dev/vc/5" |
| 1827 | # define VC_FORMAT "/dev/vc/%d" | 1836 | # define VC_FORMAT "/dev/vc/%d" |
| 1828 | # define LOOP_FORMAT "/dev/loop/%d" | 1837 | # define LOOP_FORMAT "/dev/loop/%u" |
| 1829 | # define LOOP_NAMESIZE (sizeof("/dev/loop/") + sizeof(int)*3 + 1) | 1838 | # define LOOP_NAMESIZE (sizeof("/dev/loop/") + sizeof(int)*3 + 1) |
| 1830 | # define LOOP_NAME "/dev/loop/" | 1839 | # define LOOP_NAME "/dev/loop/" |
| 1831 | # define FB_0 "/dev/fb/0" | 1840 | # define FB_0 "/dev/fb/0" |
| @@ -1838,7 +1847,7 @@ extern const char bb_default_login_shell[] ALIGN1; | |||
| 1838 | # define VC_4 "/dev/tty4" | 1847 | # define VC_4 "/dev/tty4" |
| 1839 | # define VC_5 "/dev/tty5" | 1848 | # define VC_5 "/dev/tty5" |
| 1840 | # define VC_FORMAT "/dev/tty%d" | 1849 | # define VC_FORMAT "/dev/tty%d" |
| 1841 | # define LOOP_FORMAT "/dev/loop%d" | 1850 | # define LOOP_FORMAT "/dev/loop%u" |
| 1842 | # define LOOP_NAMESIZE (sizeof("/dev/loop") + sizeof(int)*3 + 1) | 1851 | # define LOOP_NAMESIZE (sizeof("/dev/loop") + sizeof(int)*3 + 1) |
| 1843 | # define LOOP_NAME "/dev/loop" | 1852 | # define LOOP_NAME "/dev/loop" |
| 1844 | # define FB_0 "/dev/fb0" | 1853 | # define FB_0 "/dev/fb0" |
diff --git a/include/liblzo_interface.h b/include/liblzo_interface.h index 9a84c0b6b..b7f1b639b 100644 --- a/include/liblzo_interface.h +++ b/include/liblzo_interface.h | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | /* | 30 | /* |
| 31 | static void die_at(int line) | 31 | static void die_at(int line) |
| 32 | { | 32 | { |
| 33 | bb_error_msg_and_die("internal error at %d", line); | 33 | bb_error_msg_and_die("internal error at %d", line); |
| 34 | } | 34 | } |
| 35 | #define assert(v) if (!(v)) die_at(__LINE__) | 35 | #define assert(v) if (!(v)) die_at(__LINE__) |
| 36 | */ | 36 | */ |
diff --git a/include/platform.h b/include/platform.h index 432cb9cae..f18d5b74e 100644 --- a/include/platform.h +++ b/include/platform.h | |||
| @@ -225,6 +225,7 @@ typedef int bb__aliased_int FIX_ALIASING; | |||
| 225 | typedef long bb__aliased_long FIX_ALIASING; | 225 | typedef long bb__aliased_long FIX_ALIASING; |
| 226 | typedef uint16_t bb__aliased_uint16_t FIX_ALIASING; | 226 | typedef uint16_t bb__aliased_uint16_t FIX_ALIASING; |
| 227 | typedef uint32_t bb__aliased_uint32_t FIX_ALIASING; | 227 | typedef uint32_t bb__aliased_uint32_t FIX_ALIASING; |
| 228 | typedef uint64_t bb__aliased_uint64_t FIX_ALIASING; | ||
| 228 | 229 | ||
| 229 | /* NB: unaligned parameter should be a pointer, aligned one - | 230 | /* NB: unaligned parameter should be a pointer, aligned one - |
| 230 | * a lvalue. This makes it more likely to not swap them by mistake | 231 | * a lvalue. This makes it more likely to not swap them by mistake |
diff --git a/init/init.c b/init/init.c index 15aad474f..edb5be696 100644 --- a/init/init.c +++ b/init/init.c | |||
| @@ -140,12 +140,11 @@ | |||
| 140 | * not fully functional init by switching it on! */ | 140 | * not fully functional init by switching it on! */ |
| 141 | #define DEBUG_INIT 0 | 141 | #define DEBUG_INIT 0 |
| 142 | 142 | ||
| 143 | #define COMMAND_SIZE 256 | ||
| 144 | #define CONSOLE_NAME_SIZE 32 | 143 | #define CONSOLE_NAME_SIZE 32 |
| 145 | 144 | ||
| 146 | /* Default sysinit script. */ | 145 | /* Default sysinit script. */ |
| 147 | #ifndef INIT_SCRIPT | 146 | #ifndef INIT_SCRIPT |
| 148 | #define INIT_SCRIPT "/etc/init.d/rcS" | 147 | # define INIT_SCRIPT "/etc/init.d/rcS" |
| 149 | #endif | 148 | #endif |
| 150 | 149 | ||
| 151 | /* Each type of actions can appear many times. They will be | 150 | /* Each type of actions can appear many times. They will be |
| @@ -195,7 +194,7 @@ struct init_action { | |||
| 195 | pid_t pid; | 194 | pid_t pid; |
| 196 | uint8_t action_type; | 195 | uint8_t action_type; |
| 197 | char terminal[CONSOLE_NAME_SIZE]; | 196 | char terminal[CONSOLE_NAME_SIZE]; |
| 198 | char command[COMMAND_SIZE]; | 197 | char command[1]; |
| 199 | }; | 198 | }; |
| 200 | 199 | ||
| 201 | static struct init_action *init_action_list = NULL; | 200 | static struct init_action *init_action_list = NULL; |
| @@ -398,7 +397,7 @@ static void reset_sighandlers_and_unblock_sigs(void) | |||
| 398 | } | 397 | } |
| 399 | 398 | ||
| 400 | /* Wrapper around exec: | 399 | /* Wrapper around exec: |
| 401 | * Takes string (max COMMAND_SIZE chars). | 400 | * Takes string. |
| 402 | * If chars like '>' detected, execs '[-]/bin/sh -c "exec ......."'. | 401 | * If chars like '>' detected, execs '[-]/bin/sh -c "exec ......."'. |
| 403 | * Otherwise splits words on whitespace, deals with leading dash, | 402 | * Otherwise splits words on whitespace, deals with leading dash, |
| 404 | * and uses plain exec(). | 403 | * and uses plain exec(). |
| @@ -406,10 +405,15 @@ static void reset_sighandlers_and_unblock_sigs(void) | |||
| 406 | */ | 405 | */ |
| 407 | static void init_exec(const char *command) | 406 | static void init_exec(const char *command) |
| 408 | { | 407 | { |
| 409 | char *cmd[COMMAND_SIZE / 2]; | 408 | /* +8 allows to write VLA sizes below more efficiently: */ |
| 410 | char buf[COMMAND_SIZE + 6]; /* COMMAND_SIZE+strlen("exec ")+1 */ | 409 | unsigned command_size = strlen(command) + 8; |
| 411 | int dash = (command[0] == '-' /* maybe? && command[1] == '/' */); | 410 | /* strlen(command) + strlen("exec ")+1: */ |
| 412 | 411 | char buf[command_size]; | |
| 412 | /* strlen(command) / 2 + 4: */ | ||
| 413 | char *cmd[command_size / 2]; | ||
| 414 | int dash; | ||
| 415 | |||
| 416 | dash = (command[0] == '-' /* maybe? && command[1] == '/' */); | ||
| 413 | command += dash; | 417 | command += dash; |
| 414 | 418 | ||
| 415 | /* See if any special /bin/sh requiring characters are present */ | 419 | /* See if any special /bin/sh requiring characters are present */ |
| @@ -626,21 +630,21 @@ static void new_init_action(uint8_t action_type, const char *command, const char | |||
| 626 | nextp = &a->next; | 630 | nextp = &a->next; |
| 627 | } | 631 | } |
| 628 | 632 | ||
| 629 | a = xzalloc(sizeof(*a)); | 633 | a = xzalloc(sizeof(*a) + strlen(command)); |
| 630 | 634 | ||
| 631 | /* Append to the end of the list */ | 635 | /* Append to the end of the list */ |
| 632 | append: | 636 | append: |
| 633 | *nextp = a; | 637 | *nextp = a; |
| 634 | a->action_type = action_type; | 638 | a->action_type = action_type; |
| 635 | safe_strncpy(a->command, command, sizeof(a->command)); | 639 | strcpy(a->command, command); |
| 636 | safe_strncpy(a->terminal, cons, sizeof(a->terminal)); | 640 | safe_strncpy(a->terminal, cons, sizeof(a->terminal)); |
| 637 | dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n", | 641 | dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%x tty='%s'\n", |
| 638 | a->command, a->action_type, a->terminal); | 642 | a->command, a->action_type, a->terminal); |
| 639 | } | 643 | } |
| 640 | 644 | ||
| 641 | /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, | 645 | /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, |
| 642 | * then parse_inittab() simply adds in some default | 646 | * then parse_inittab() simply adds in some default |
| 643 | * actions(i.e., runs INIT_SCRIPT and then starts a pair | 647 | * actions (i.e., runs INIT_SCRIPT and then starts a pair |
| 644 | * of "askfirst" shells). If CONFIG_FEATURE_USE_INITTAB | 648 | * of "askfirst" shells). If CONFIG_FEATURE_USE_INITTAB |
| 645 | * _is_ defined, but /etc/inittab is missing, this | 649 | * _is_ defined, but /etc/inittab is missing, this |
| 646 | * results in the same set of default behaviors. | 650 | * results in the same set of default behaviors. |
| @@ -655,23 +659,22 @@ static void parse_inittab(void) | |||
| 655 | #endif | 659 | #endif |
| 656 | { | 660 | { |
| 657 | /* No inittab file - set up some default behavior */ | 661 | /* No inittab file - set up some default behavior */ |
| 658 | /* Reboot on Ctrl-Alt-Del */ | 662 | /* Sysinit */ |
| 659 | new_init_action(CTRLALTDEL, "reboot", ""); | 663 | new_init_action(SYSINIT, INIT_SCRIPT, ""); |
| 660 | /* Umount all filesystems on halt/reboot */ | ||
| 661 | new_init_action(SHUTDOWN, "umount -a -r", ""); | ||
| 662 | /* Swapoff on halt/reboot */ | ||
| 663 | if (ENABLE_SWAPONOFF) | ||
| 664 | new_init_action(SHUTDOWN, "swapoff -a", ""); | ||
| 665 | /* Prepare to restart init when a QUIT is received */ | ||
| 666 | new_init_action(RESTART, "init", ""); | ||
| 667 | /* Askfirst shell on tty1-4 */ | 664 | /* Askfirst shell on tty1-4 */ |
| 668 | new_init_action(ASKFIRST, bb_default_login_shell, ""); | 665 | new_init_action(ASKFIRST, bb_default_login_shell, ""); |
| 669 | //TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users | 666 | //TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users |
| 670 | new_init_action(ASKFIRST, bb_default_login_shell, VC_2); | 667 | new_init_action(ASKFIRST, bb_default_login_shell, VC_2); |
| 671 | new_init_action(ASKFIRST, bb_default_login_shell, VC_3); | 668 | new_init_action(ASKFIRST, bb_default_login_shell, VC_3); |
| 672 | new_init_action(ASKFIRST, bb_default_login_shell, VC_4); | 669 | new_init_action(ASKFIRST, bb_default_login_shell, VC_4); |
| 673 | /* sysinit */ | 670 | /* Reboot on Ctrl-Alt-Del */ |
| 674 | new_init_action(SYSINIT, INIT_SCRIPT, ""); | 671 | new_init_action(CTRLALTDEL, "reboot", ""); |
| 672 | /* Umount all filesystems on halt/reboot */ | ||
| 673 | new_init_action(SHUTDOWN, "umount -a -r", ""); | ||
| 674 | /* Swapoff on halt/reboot */ | ||
| 675 | new_init_action(SHUTDOWN, "swapoff -a", ""); | ||
| 676 | /* Restart init when a QUIT is received */ | ||
| 677 | new_init_action(RESTART, "init", ""); | ||
| 675 | return; | 678 | return; |
| 676 | } | 679 | } |
| 677 | 680 | ||
| @@ -931,10 +934,17 @@ static void reload_inittab(void) | |||
| 931 | 934 | ||
| 932 | /* Remove stale entries and SYSINIT entries. | 935 | /* Remove stale entries and SYSINIT entries. |
| 933 | * We never rerun SYSINIT entries anyway, | 936 | * We never rerun SYSINIT entries anyway, |
| 934 | * removing them too saves a few bytes */ | 937 | * removing them too saves a few bytes |
| 938 | */ | ||
| 935 | nextp = &init_action_list; | 939 | nextp = &init_action_list; |
| 936 | while ((a = *nextp) != NULL) { | 940 | while ((a = *nextp) != NULL) { |
| 937 | if ((a->action_type & ~SYSINIT) == 0) { | 941 | /* |
| 942 | * Why pid == 0 check? | ||
| 943 | * Process can be removed from inittab and added *later*. | ||
| 944 | * If we delete its entry but process still runs, | ||
| 945 | * duplicate is spawned when the entry is re-added. | ||
| 946 | */ | ||
| 947 | if ((a->action_type & ~SYSINIT) == 0 && a->pid == 0) { | ||
| 938 | *nextp = a->next; | 948 | *nextp = a->next; |
| 939 | free(a); | 949 | free(a); |
| 940 | } else { | 950 | } else { |
| @@ -1058,10 +1068,13 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
| 1058 | message(L_CONSOLE | L_LOG, "init started: %s", bb_banner); | 1068 | message(L_CONSOLE | L_LOG, "init started: %s", bb_banner); |
| 1059 | #endif | 1069 | #endif |
| 1060 | 1070 | ||
| 1071 | #if 0 | ||
| 1072 | /* It's 2013, does anyone really still depend on this? */ | ||
| 1073 | /* If you do, consider adding swapon to sysinot actions then! */ | ||
| 1061 | /* struct sysinfo is linux-specific */ | 1074 | /* struct sysinfo is linux-specific */ |
| 1062 | #ifdef __linux__ | 1075 | # ifdef __linux__ |
| 1063 | /* Make sure there is enough memory to do something useful. */ | 1076 | /* Make sure there is enough memory to do something useful. */ |
| 1064 | if (ENABLE_SWAPONOFF) { | 1077 | /*if (ENABLE_SWAPONOFF) - WRONG: we may have non-bbox swapon*/ { |
| 1065 | struct sysinfo info; | 1078 | struct sysinfo info; |
| 1066 | 1079 | ||
| 1067 | if (sysinfo(&info) == 0 | 1080 | if (sysinfo(&info) == 0 |
| @@ -1075,6 +1088,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
| 1075 | run_actions(SYSINIT); /* wait and removing */ | 1088 | run_actions(SYSINIT); /* wait and removing */ |
| 1076 | } | 1089 | } |
| 1077 | } | 1090 | } |
| 1091 | # endif | ||
| 1078 | #endif | 1092 | #endif |
| 1079 | 1093 | ||
| 1080 | /* Check if we are supposed to be in single user mode */ | 1094 | /* Check if we are supposed to be in single user mode */ |
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index ad81ce46b..db79ff62b 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
| @@ -27,8 +27,6 @@ lib-y += concat_subpath_file.o | |||
| 27 | lib-y += copy_file.o | 27 | lib-y += copy_file.o |
| 28 | lib-y += copyfd.o | 28 | lib-y += copyfd.o |
| 29 | lib-y += crc32.o | 29 | lib-y += crc32.o |
| 30 | lib-y += create_icmp6_socket.o | ||
| 31 | lib-y += create_icmp_socket.o | ||
| 32 | lib-y += default_error_retval.o | 30 | lib-y += default_error_retval.o |
| 33 | lib-y += device_open.o | 31 | lib-y += device_open.o |
| 34 | lib-y += dump.o | 32 | lib-y += dump.o |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f0df4e080..44161a219 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | #include "busybox.h" | 29 | #include "busybox.h" |
| 30 | 30 | ||
| 31 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ | 31 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ |
| 32 | || defined(__APPLE__) \ | 32 | || defined(__APPLE__) \ |
| 33 | ) | 33 | ) |
| 34 | # include <malloc.h> /* for mallopt */ | 34 | # include <malloc.h> /* for mallopt */ |
| 35 | #endif | 35 | #endif |
diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c index fe2b50677..77c1bcd95 100644 --- a/libbb/bb_askpass.c +++ b/libbb/bb_askpass.c | |||
| @@ -65,7 +65,9 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) | |||
| 65 | i = 0; | 65 | i = 0; |
| 66 | while (1) { | 66 | while (1) { |
| 67 | int r = read(fd, &ret[i], 1); | 67 | int r = read(fd, &ret[i], 1); |
| 68 | if (r < 0) { | 68 | if ((i == 0 && r == 0) /* EOF (^D) with no password */ |
| 69 | || r < 0 | ||
| 70 | ) { | ||
| 69 | /* read is interrupted by timeout or ^C */ | 71 | /* read is interrupted by timeout or ^C */ |
| 70 | ret = NULL; | 72 | ret = NULL; |
| 71 | break; | 73 | break; |
diff --git a/libbb/create_icmp6_socket.c b/libbb/create_icmp6_socket.c deleted file mode 100644 index 368c69028..000000000 --- a/libbb/create_icmp6_socket.c +++ /dev/null | |||
| @@ -1,38 +0,0 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | ||
| 2 | /* | ||
| 3 | * Utility routines. | ||
| 4 | * | ||
| 5 | * create raw socket for icmp (IPv6 version) protocol | ||
| 6 | * and drop root privileges if running setuid | ||
| 7 | * | ||
| 8 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include "libbb.h" | ||
| 12 | |||
| 13 | #if ENABLE_FEATURE_IPV6 | ||
| 14 | int FAST_FUNC create_icmp6_socket(void) | ||
| 15 | { | ||
| 16 | int sock; | ||
| 17 | #if 0 | ||
| 18 | struct protoent *proto; | ||
| 19 | proto = getprotobyname("ipv6-icmp"); | ||
| 20 | /* if getprotobyname failed, just silently force | ||
| 21 | * proto->p_proto to have the correct value for "ipv6-icmp" */ | ||
| 22 | sock = socket(AF_INET6, SOCK_RAW, | ||
| 23 | (proto ? proto->p_proto : IPPROTO_ICMPV6)); | ||
| 24 | #else | ||
| 25 | sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); | ||
| 26 | #endif | ||
| 27 | if (sock < 0) { | ||
| 28 | if (errno == EPERM) | ||
| 29 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | ||
| 30 | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); | ||
| 31 | } | ||
| 32 | |||
| 33 | /* drop root privs if running setuid */ | ||
| 34 | xsetuid(getuid()); | ||
| 35 | |||
| 36 | return sock; | ||
| 37 | } | ||
| 38 | #endif | ||
diff --git a/libbb/create_icmp_socket.c b/libbb/create_icmp_socket.c deleted file mode 100644 index 585626983..000000000 --- a/libbb/create_icmp_socket.c +++ /dev/null | |||
| @@ -1,36 +0,0 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | ||
| 2 | /* | ||
| 3 | * Utility routines. | ||
| 4 | * | ||
| 5 | * create raw socket for icmp protocol | ||
| 6 | * and drop root privileges if running setuid | ||
| 7 | * | ||
| 8 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include "libbb.h" | ||
| 12 | |||
| 13 | int FAST_FUNC create_icmp_socket(void) | ||
| 14 | { | ||
| 15 | int sock; | ||
| 16 | #if 0 | ||
| 17 | struct protoent *proto; | ||
| 18 | proto = getprotobyname("icmp"); | ||
| 19 | /* if getprotobyname failed, just silently force | ||
| 20 | * proto->p_proto to have the correct value for "icmp" */ | ||
| 21 | sock = socket(AF_INET, SOCK_RAW, | ||
| 22 | (proto ? proto->p_proto : 1)); /* 1 == ICMP */ | ||
| 23 | #else | ||
| 24 | sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */ | ||
| 25 | #endif | ||
| 26 | if (sock < 0) { | ||
| 27 | if (errno == EPERM) | ||
| 28 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | ||
| 29 | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); | ||
| 30 | } | ||
| 31 | |||
| 32 | /* drop root privs if running setuid */ | ||
| 33 | xsetuid(getuid()); | ||
| 34 | |||
| 35 | return sock; | ||
| 36 | } | ||
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index b4d955e5a..3f743ac75 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c | |||
| @@ -84,7 +84,7 @@ static void FAST_FUNC common64_end(md5_ctx_t *ctx, int swap_needed) | |||
| 84 | if (swap_needed) | 84 | if (swap_needed) |
| 85 | t = bb_bswap_64(t); | 85 | t = bb_bswap_64(t); |
| 86 | /* wbuffer is suitably aligned for this */ | 86 | /* wbuffer is suitably aligned for this */ |
| 87 | *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; | 87 | *(bb__aliased_uint64_t *) (&ctx->wbuffer[64 - 8]) = t; |
| 88 | } | 88 | } |
| 89 | ctx->process_block(ctx); | 89 | ctx->process_block(ctx); |
| 90 | if (remaining >= 8) | 90 | if (remaining >= 8) |
| @@ -883,10 +883,10 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) | |||
| 883 | uint64_t t; | 883 | uint64_t t; |
| 884 | t = ctx->total64[0] << 3; | 884 | t = ctx->total64[0] << 3; |
| 885 | t = SWAP_BE64(t); | 885 | t = SWAP_BE64(t); |
| 886 | *(uint64_t *) (&ctx->wbuffer[128 - 8]) = t; | 886 | *(bb__aliased_uint64_t *) (&ctx->wbuffer[128 - 8]) = t; |
| 887 | t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61); | 887 | t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61); |
| 888 | t = SWAP_BE64(t); | 888 | t = SWAP_BE64(t); |
| 889 | *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t; | 889 | *(bb__aliased_uint64_t *) (&ctx->wbuffer[128 - 16]) = t; |
| 890 | } | 890 | } |
| 891 | sha512_process_block128(ctx); | 891 | sha512_process_block128(ctx); |
| 892 | if (remaining >= 16) | 892 | if (remaining >= 16) |
diff --git a/libbb/in_ether.c b/libbb/in_ether.c new file mode 100644 index 000000000..dadadbafe --- /dev/null +++ b/libbb/in_ether.c | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | ||
| 2 | /* | ||
| 3 | * Utility routines. | ||
| 4 | */ | ||
| 5 | |||
| 6 | //kbuild:lib-$(CONFIG_IFCONFIG) += in_ether.o | ||
| 7 | //kbuild:lib-$(CONFIG_IFENSLAVE) += in_ether.o | ||
| 8 | |||
| 9 | #include "libbb.h" | ||
| 10 | #include <net/if_arp.h> | ||
| 11 | #include <net/ethernet.h> | ||
| 12 | |||
| 13 | /* Convert Ethernet address from "XX[:]XX[:]XX[:]XX[:]XX[:]XX" to sockaddr. | ||
| 14 | * Return nonzero on error. | ||
| 15 | */ | ||
| 16 | int FAST_FUNC in_ether(const char *bufp, struct sockaddr *sap) | ||
| 17 | { | ||
| 18 | char *ptr; | ||
| 19 | int i, j; | ||
| 20 | unsigned char val; | ||
| 21 | unsigned char c; | ||
| 22 | |||
| 23 | sap->sa_family = ARPHRD_ETHER; | ||
| 24 | ptr = (char *) sap->sa_data; | ||
| 25 | |||
| 26 | i = ETH_ALEN; | ||
| 27 | goto first; | ||
| 28 | do { | ||
| 29 | /* We might get a semicolon here */ | ||
| 30 | if (*bufp == ':') | ||
| 31 | bufp++; | ||
| 32 | first: | ||
| 33 | j = val = 0; | ||
| 34 | do { | ||
| 35 | c = *bufp; | ||
| 36 | if (((unsigned char)(c - '0')) <= 9) { | ||
| 37 | c -= '0'; | ||
| 38 | } else if ((unsigned char)((c|0x20) - 'a') <= 5) { | ||
| 39 | c = (unsigned char)((c|0x20) - 'a') + 10; | ||
| 40 | } else { | ||
| 41 | if (j && (c == ':' || c == '\0')) | ||
| 42 | /* One-digit byte: __:X:__ */ | ||
| 43 | break; | ||
| 44 | return -1; | ||
| 45 | } | ||
| 46 | ++bufp; | ||
| 47 | val <<= 4; | ||
| 48 | val += c; | ||
| 49 | j ^= 1; | ||
| 50 | } while (j); | ||
| 51 | |||
| 52 | *ptr++ = val; | ||
| 53 | |||
| 54 | } while (--i); | ||
| 55 | |||
| 56 | /* Error if we aren't at end of string */ | ||
| 57 | return *bufp; | ||
| 58 | } | ||
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 7f64a9691..20d75cf56 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
| @@ -38,6 +38,14 @@ | |||
| 38 | * and the \] escape to signal the end of such a sequence. Example: | 38 | * and the \] escape to signal the end of such a sequence. Example: |
| 39 | * | 39 | * |
| 40 | * PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] ' | 40 | * PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] ' |
| 41 | * | ||
| 42 | * Unicode in PS1 is not fully supported: prompt length calulation is wrong, | ||
| 43 | * resulting in line wrap problems with long (multi-line) input. | ||
| 44 | * | ||
| 45 | * Multi-line PS1 (e.g. PS1="\n[\w]\n$ ") has problems with history | ||
| 46 | * browsing: up/down arrows result in scrolling. | ||
| 47 | * It stems from simplistic "cmdedit_y = cmdedit_prmt_len / cmdedit_termw" | ||
| 48 | * calculation of how many lines the prompt takes. | ||
| 41 | */ | 49 | */ |
| 42 | #include "libbb.h" | 50 | #include "libbb.h" |
| 43 | #include "unicode.h" | 51 | #include "unicode.h" |
| @@ -1268,7 +1276,7 @@ line_input_t* FAST_FUNC new_line_input_t(int flags) | |||
| 1268 | 1276 | ||
| 1269 | #if MAX_HISTORY > 0 | 1277 | #if MAX_HISTORY > 0 |
| 1270 | 1278 | ||
| 1271 | unsigned size_from_HISTFILESIZE(const char *hp) | 1279 | unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp) |
| 1272 | { | 1280 | { |
| 1273 | int size = MAX_HISTORY; | 1281 | int size = MAX_HISTORY; |
| 1274 | if (hp) { | 1282 | if (hp) { |
| @@ -1323,6 +1331,17 @@ static int get_next_history(void) | |||
| 1323 | return 0; | 1331 | return 0; |
| 1324 | } | 1332 | } |
| 1325 | 1333 | ||
| 1334 | /* Lists command history. Used by shell 'history' builtins */ | ||
| 1335 | void FAST_FUNC show_history(const line_input_t *st) | ||
| 1336 | { | ||
| 1337 | int i; | ||
| 1338 | |||
| 1339 | if (!st) | ||
| 1340 | return; | ||
| 1341 | for (i = 0; i < st->cnt_history; i++) | ||
| 1342 | printf("%4d %s\n", i, st->history[i]); | ||
| 1343 | } | ||
| 1344 | |||
| 1326 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1345 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY |
| 1327 | /* We try to ensure that concurrent additions to the history | 1346 | /* We try to ensure that concurrent additions to the history |
| 1328 | * do not overwrite each other. | 1347 | * do not overwrite each other. |
| @@ -1762,34 +1781,36 @@ static void ask_terminal(void) | |||
| 1762 | #define ask_terminal() ((void)0) | 1781 | #define ask_terminal() ((void)0) |
| 1763 | #endif | 1782 | #endif |
| 1764 | 1783 | ||
| 1784 | /* Called just once at read_line_input() init time */ | ||
| 1765 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT | 1785 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT |
| 1766 | static void parse_and_put_prompt(const char *prmt_ptr) | 1786 | static void parse_and_put_prompt(const char *prmt_ptr) |
| 1767 | { | 1787 | { |
| 1788 | const char *p; | ||
| 1768 | cmdedit_prompt = prmt_ptr; | 1789 | cmdedit_prompt = prmt_ptr; |
| 1769 | cmdedit_prmt_len = strlen(prmt_ptr); | 1790 | p = strrchr(prmt_ptr, '\n'); |
| 1791 | cmdedit_prmt_len = unicode_strwidth(p ? p+1 : prmt_ptr); | ||
| 1770 | put_prompt(); | 1792 | put_prompt(); |
| 1771 | } | 1793 | } |
| 1772 | #else | 1794 | #else |
| 1773 | static void parse_and_put_prompt(const char *prmt_ptr) | 1795 | static void parse_and_put_prompt(const char *prmt_ptr) |
| 1774 | { | 1796 | { |
| 1775 | int prmt_len = 0; | 1797 | int prmt_size = 0; |
| 1776 | size_t cur_prmt_len = 0; | ||
| 1777 | char flg_not_length = '['; | ||
| 1778 | char *prmt_mem_ptr = xzalloc(1); | 1798 | char *prmt_mem_ptr = xzalloc(1); |
| 1779 | # if ENABLE_USERNAME_OR_HOMEDIR | 1799 | # if ENABLE_USERNAME_OR_HOMEDIR |
| 1780 | char *cwd_buf = NULL; | 1800 | char *cwd_buf = NULL; |
| 1781 | # endif | 1801 | # endif |
| 1782 | char timebuf[sizeof("HH:MM:SS")]; | 1802 | char flg_not_length = '['; |
| 1783 | char cbuf[2]; | 1803 | char cbuf[2]; |
| 1784 | char c; | ||
| 1785 | char *pbuf; | ||
| 1786 | 1804 | ||
| 1787 | cmdedit_prmt_len = 0; | 1805 | /*cmdedit_prmt_len = 0; - already is */ |
| 1788 | 1806 | ||
| 1789 | cbuf[1] = '\0'; /* never changes */ | 1807 | cbuf[1] = '\0'; /* never changes */ |
| 1790 | 1808 | ||
| 1791 | while (*prmt_ptr) { | 1809 | while (*prmt_ptr) { |
| 1810 | char timebuf[sizeof("HH:MM:SS")]; | ||
| 1792 | char *free_me = NULL; | 1811 | char *free_me = NULL; |
| 1812 | char *pbuf; | ||
| 1813 | char c; | ||
| 1793 | 1814 | ||
| 1794 | pbuf = cbuf; | 1815 | pbuf = cbuf; |
| 1795 | c = *prmt_ptr++; | 1816 | c = *prmt_ptr++; |
| @@ -1922,7 +1943,8 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
| 1922 | } | 1943 | } |
| 1923 | case '[': case ']': | 1944 | case '[': case ']': |
| 1924 | if (c == flg_not_length) { | 1945 | if (c == flg_not_length) { |
| 1925 | flg_not_length = (flg_not_length == '[' ? ']' : '['); | 1946 | /* Toggle '['/']' hex 5b/5d */ |
| 1947 | flg_not_length ^= 6; | ||
| 1926 | continue; | 1948 | continue; |
| 1927 | } | 1949 | } |
| 1928 | break; | 1950 | break; |
| @@ -1930,11 +1952,22 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
| 1930 | } /* if */ | 1952 | } /* if */ |
| 1931 | } /* if */ | 1953 | } /* if */ |
| 1932 | cbuf[0] = c; | 1954 | cbuf[0] = c; |
| 1933 | cur_prmt_len = strlen(pbuf); | 1955 | { |
| 1934 | prmt_len += cur_prmt_len; | 1956 | int n = strlen(pbuf); |
| 1935 | if (flg_not_length != ']') | 1957 | prmt_size += n; |
| 1936 | cmdedit_prmt_len += cur_prmt_len; | 1958 | if (c == '\n') |
| 1937 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); | 1959 | cmdedit_prmt_len = 0; |
| 1960 | else if (flg_not_length != ']') { | ||
| 1961 | #if 0 /*ENABLE_UNICODE_SUPPORT*/ | ||
| 1962 | /* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */ | ||
| 1963 | /* FIXME */ | ||
| 1964 | cmdedit_prmt_len += unicode_strwidth(pbuf); | ||
| 1965 | #else | ||
| 1966 | cmdedit_prmt_len += n; | ||
| 1967 | #endif | ||
| 1968 | } | ||
| 1969 | } | ||
| 1970 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); | ||
| 1938 | free(free_me); | 1971 | free(free_me); |
| 1939 | } /* while */ | 1972 | } /* while */ |
| 1940 | 1973 | ||
| @@ -2003,7 +2036,15 @@ static int lineedit_read_key(char *read_key_buffer, int timeout) | |||
| 2003 | S.sent_ESC_br6n = 0; | 2036 | S.sent_ESC_br6n = 0; |
| 2004 | if (cursor == 0) { /* otherwise it may be bogus */ | 2037 | if (cursor == 0) { /* otherwise it may be bogus */ |
| 2005 | int col = ((ic >> 32) & 0x7fff) - 1; | 2038 | int col = ((ic >> 32) & 0x7fff) - 1; |
| 2006 | if (col > cmdedit_prmt_len) { | 2039 | /* |
| 2040 | * Is col > cmdedit_prmt_len? | ||
| 2041 | * If yes (terminal says cursor is farther to the right | ||
| 2042 | * of where we think it should be), | ||
| 2043 | * the prompt wasn't printed starting at col 1, | ||
| 2044 | * there was additional text before it. | ||
| 2045 | */ | ||
| 2046 | if ((int)(col - cmdedit_prmt_len) > 0) { | ||
| 2047 | /* Fix our understanding of current x position */ | ||
| 2007 | cmdedit_x += (col - cmdedit_prmt_len); | 2048 | cmdedit_x += (col - cmdedit_prmt_len); |
| 2008 | while (cmdedit_x >= cmdedit_termw) { | 2049 | while (cmdedit_x >= cmdedit_termw) { |
| 2009 | cmdedit_x -= cmdedit_termw; | 2050 | cmdedit_x -= cmdedit_termw; |
| @@ -2094,6 +2135,7 @@ static int32_t reverse_i_search(void) | |||
| 2094 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; | 2135 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; |
| 2095 | const char *matched_history_line; | 2136 | const char *matched_history_line; |
| 2096 | const char *saved_prompt; | 2137 | const char *saved_prompt; |
| 2138 | unsigned saved_prmt_len; | ||
| 2097 | int32_t ic; | 2139 | int32_t ic; |
| 2098 | 2140 | ||
| 2099 | matched_history_line = NULL; | 2141 | matched_history_line = NULL; |
| @@ -2102,6 +2144,7 @@ static int32_t reverse_i_search(void) | |||
| 2102 | 2144 | ||
| 2103 | /* Save and replace the prompt */ | 2145 | /* Save and replace the prompt */ |
| 2104 | saved_prompt = cmdedit_prompt; | 2146 | saved_prompt = cmdedit_prompt; |
| 2147 | saved_prmt_len = cmdedit_prmt_len; | ||
| 2105 | goto set_prompt; | 2148 | goto set_prompt; |
| 2106 | 2149 | ||
| 2107 | while (1) { | 2150 | while (1) { |
| @@ -2177,7 +2220,7 @@ static int32_t reverse_i_search(void) | |||
| 2177 | free((char*)cmdedit_prompt); | 2220 | free((char*)cmdedit_prompt); |
| 2178 | set_prompt: | 2221 | set_prompt: |
| 2179 | cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf); | 2222 | cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf); |
| 2180 | cmdedit_prmt_len = strlen(cmdedit_prompt); | 2223 | cmdedit_prmt_len = unicode_strwidth(cmdedit_prompt); |
| 2181 | goto do_redraw; | 2224 | goto do_redraw; |
| 2182 | } | 2225 | } |
| 2183 | } | 2226 | } |
| @@ -2199,7 +2242,7 @@ static int32_t reverse_i_search(void) | |||
| 2199 | 2242 | ||
| 2200 | free((char*)cmdedit_prompt); | 2243 | free((char*)cmdedit_prompt); |
| 2201 | cmdedit_prompt = saved_prompt; | 2244 | cmdedit_prompt = saved_prompt; |
| 2202 | cmdedit_prmt_len = strlen(cmdedit_prompt); | 2245 | cmdedit_prmt_len = saved_prmt_len; |
| 2203 | redraw(cmdedit_y, command_len - cursor); | 2246 | redraw(cmdedit_y, command_len - cursor); |
| 2204 | 2247 | ||
| 2205 | return ic; | 2248 | return ic; |
| @@ -2774,8 +2817,9 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
| 2774 | free(command_ps); | 2817 | free(command_ps); |
| 2775 | #endif | 2818 | #endif |
| 2776 | 2819 | ||
| 2777 | if (command_len > 0) | 2820 | if (command_len > 0) { |
| 2778 | remember_in_history(command); | 2821 | remember_in_history(command); |
| 2822 | } | ||
| 2779 | 2823 | ||
| 2780 | if (break_out > 0) { | 2824 | if (break_out > 0) { |
| 2781 | command[command_len++] = '\n'; | 2825 | command[command_len++] = '\n'; |
diff --git a/libbb/printable.c b/libbb/printable.c index f6ada4904..9a423431e 100644 --- a/libbb/printable.c +++ b/libbb/printable.c | |||
| @@ -32,3 +32,27 @@ void FAST_FUNC fputc_printable(int ch, FILE *file) | |||
| 32 | } | 32 | } |
| 33 | fputc(ch, file); | 33 | fputc(ch, file); |
| 34 | } | 34 | } |
| 35 | |||
| 36 | void FAST_FUNC visible(unsigned ch, char *buf, int flags) | ||
| 37 | { | ||
| 38 | if (ch == '\t' && !(flags & VISIBLE_SHOW_TABS)) { | ||
| 39 | goto raw; | ||
| 40 | } | ||
| 41 | if (ch == '\n') { | ||
| 42 | if (flags & VISIBLE_ENDLINE) | ||
| 43 | *buf++ = '$'; | ||
| 44 | } else { | ||
| 45 | if (ch >= 128) { | ||
| 46 | ch -= 128; | ||
| 47 | *buf++ = 'M'; | ||
| 48 | *buf++ = '-'; | ||
| 49 | } | ||
| 50 | if (ch < 32 || ch == 127) { | ||
| 51 | *buf++ = '^'; | ||
| 52 | ch ^= 0x40; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | raw: | ||
| 56 | *buf++ = ch; | ||
| 57 | *buf = '\0'; | ||
| 58 | } | ||
diff --git a/libbb/time.c b/libbb/time.c index 57e14b66c..ea2f72e3b 100644 --- a/libbb/time.c +++ b/libbb/time.c | |||
| @@ -23,14 +23,16 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
| 23 | if (sscanf(date_str, "%u:%u%c", | 23 | if (sscanf(date_str, "%u:%u%c", |
| 24 | &ptm->tm_hour, | 24 | &ptm->tm_hour, |
| 25 | &ptm->tm_min, | 25 | &ptm->tm_min, |
| 26 | &end) >= 2) { | 26 | &end) >= 2 |
| 27 | ) { | ||
| 27 | /* no adjustments needed */ | 28 | /* no adjustments needed */ |
| 28 | } else | 29 | } else |
| 29 | /* mm.dd-HH:MM */ | 30 | /* mm.dd-HH:MM */ |
| 30 | if (sscanf(date_str, "%u.%u-%u:%u%c", | 31 | if (sscanf(date_str, "%u.%u-%u:%u%c", |
| 31 | &ptm->tm_mon, &ptm->tm_mday, | 32 | &ptm->tm_mon, &ptm->tm_mday, |
| 32 | &ptm->tm_hour, &ptm->tm_min, | 33 | &ptm->tm_hour, &ptm->tm_min, |
| 33 | &end) >= 4) { | 34 | &end) >= 4 |
| 35 | ) { | ||
| 34 | /* Adjust month from 1-12 to 0-11 */ | 36 | /* Adjust month from 1-12 to 0-11 */ |
| 35 | ptm->tm_mon -= 1; | 37 | ptm->tm_mon -= 1; |
| 36 | } else | 38 | } else |
| @@ -38,15 +40,13 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
| 38 | if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &ptm->tm_year, | 40 | if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &ptm->tm_year, |
| 39 | &ptm->tm_mon, &ptm->tm_mday, | 41 | &ptm->tm_mon, &ptm->tm_mday, |
| 40 | &ptm->tm_hour, &ptm->tm_min, | 42 | &ptm->tm_hour, &ptm->tm_min, |
| 41 | &end) >= 5) { | 43 | &end) >= 5 |
| 42 | ptm->tm_year -= 1900; /* Adjust years */ | ||
| 43 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | ||
| 44 | } else | ||
| 45 | /* yyyy-mm-dd HH:MM */ | 44 | /* yyyy-mm-dd HH:MM */ |
| 46 | if (sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year, | 45 | || sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year, |
| 47 | &ptm->tm_mon, &ptm->tm_mday, | 46 | &ptm->tm_mon, &ptm->tm_mday, |
| 48 | &ptm->tm_hour, &ptm->tm_min, | 47 | &ptm->tm_hour, &ptm->tm_min, |
| 49 | &end) >= 5) { | 48 | &end) >= 5 |
| 49 | ) { | ||
| 50 | ptm->tm_year -= 1900; /* Adjust years */ | 50 | ptm->tm_year -= 1900; /* Adjust years */ |
| 51 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | 51 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
| 52 | } else | 52 | } else |
| @@ -58,7 +58,6 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
| 58 | return; /* don't fall through to end == ":" check */ | 58 | return; /* don't fall through to end == ":" check */ |
| 59 | } else | 59 | } else |
| 60 | #endif | 60 | #endif |
| 61 | //TODO: coreutils 6.9 also accepts "yyyy-mm-dd HH" (no minutes) | ||
| 62 | { | 61 | { |
| 63 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | 62 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
| 64 | } | 63 | } |
| @@ -68,7 +67,21 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
| 68 | end = '\0'; | 67 | end = '\0'; |
| 69 | /* else end != NUL and we error out */ | 68 | /* else end != NUL and we error out */ |
| 70 | } | 69 | } |
| 71 | } else if (date_str[0] == '@') { | 70 | } else |
| 71 | /* yyyy-mm-dd HH */ | ||
| 72 | if (sscanf(date_str, "%u-%u-%u %u%c", &ptm->tm_year, | ||
| 73 | &ptm->tm_mon, &ptm->tm_mday, | ||
| 74 | &ptm->tm_hour, | ||
| 75 | &end) >= 4 | ||
| 76 | /* yyyy-mm-dd */ | ||
| 77 | || sscanf(date_str, "%u-%u-%u%c", &ptm->tm_year, | ||
| 78 | &ptm->tm_mon, &ptm->tm_mday, | ||
| 79 | &end) >= 3 | ||
| 80 | ) { | ||
| 81 | ptm->tm_year -= 1900; /* Adjust years */ | ||
| 82 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | ||
| 83 | } else | ||
| 84 | if (date_str[0] == '@') { | ||
| 72 | time_t t = bb_strtol(date_str + 1, NULL, 10); | 85 | time_t t = bb_strtol(date_str + 1, NULL, 10); |
| 73 | if (!errno) { | 86 | if (!errno) { |
| 74 | struct tm *lt = localtime(&t); | 87 | struct tm *lt = localtime(&t); |
diff --git a/libbb/unicode.c b/libbb/unicode.c index 99dc1dfa6..9c4da50d3 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c | |||
| @@ -28,19 +28,37 @@ void FAST_FUNC reinit_unicode(const char *LANG) | |||
| 28 | static const char unicode_0x394[] = { 0xce, 0x94, 0 }; | 28 | static const char unicode_0x394[] = { 0xce, 0x94, 0 }; |
| 29 | size_t width; | 29 | size_t width; |
| 30 | 30 | ||
| 31 | /* We pass "" instead of "C" because some libc's have | ||
| 32 | * non-ASCII default locale for setlocale("") call | ||
| 33 | * (this allows users of such libc to have Unicoded | ||
| 34 | * system without having to mess with env). | ||
| 35 | * | ||
| 36 | * We set LC_CTYPE because (a) we may be called with $LC_CTYPE | ||
| 37 | * value in LANG, not with $LC_ALL, (b) internationalized | ||
| 38 | * LC_NUMERIC and LC_TIME are more PITA than benefit | ||
| 39 | * (for one, some utilities have hard time with comma | ||
| 40 | * used as a fractional separator). | ||
| 41 | */ | ||
| 31 | //TODO: avoid repeated calls by caching last string? | 42 | //TODO: avoid repeated calls by caching last string? |
| 32 | setlocale(LC_ALL, (LANG && LANG[0]) ? LANG : "C"); | 43 | setlocale(LC_CTYPE, LANG ? LANG : ""); |
| 33 | 44 | ||
| 34 | /* In unicode, this is a one character string */ | 45 | /* In unicode, this is a one character string */ |
| 35 | // can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused | 46 | width = unicode_strlen(unicode_0x394); |
| 36 | width = mbstowcs(NULL, unicode_0x394, INT_MAX); | ||
| 37 | unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF); | 47 | unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF); |
| 38 | } | 48 | } |
| 39 | 49 | ||
| 40 | void FAST_FUNC init_unicode(void) | 50 | void FAST_FUNC init_unicode(void) |
| 41 | { | 51 | { |
| 42 | if (unicode_status == UNICODE_UNKNOWN) | 52 | /* Some people set only $LC_CTYPE, not $LC_ALL, because they want |
| 43 | reinit_unicode(getenv("LANG")); | 53 | * only Unicode to be activated on their system, not the whole |
| 54 | * shebang of wrong decimal points, strange date formats and so on. | ||
| 55 | */ | ||
| 56 | if (unicode_status == UNICODE_UNKNOWN) { | ||
| 57 | char *s = getenv("LC_ALL"); | ||
| 58 | if (!s) s = getenv("LC_CTYPE"); | ||
| 59 | if (!s) s = getenv("LANG"); | ||
| 60 | reinit_unicode(s); | ||
| 61 | } | ||
| 44 | } | 62 | } |
| 45 | 63 | ||
| 46 | #else | 64 | #else |
| @@ -58,8 +76,12 @@ void FAST_FUNC reinit_unicode(const char *LANG) | |||
| 58 | 76 | ||
| 59 | void FAST_FUNC init_unicode(void) | 77 | void FAST_FUNC init_unicode(void) |
| 60 | { | 78 | { |
| 61 | if (unicode_status == UNICODE_UNKNOWN) | 79 | if (unicode_status == UNICODE_UNKNOWN) { |
| 62 | reinit_unicode(getenv("LANG")); | 80 | char *s = getenv("LC_ALL"); |
| 81 | if (!s) s = getenv("LC_CTYPE"); | ||
| 82 | if (!s) s = getenv("LANG"); | ||
| 83 | reinit_unicode(s); | ||
| 84 | } | ||
| 63 | } | 85 | } |
| 64 | # endif | 86 | # endif |
| 65 | 87 | ||
| @@ -963,7 +985,6 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) | |||
| 963 | 985 | ||
| 964 | /* The rest is mostly same for libc and for "homegrown" support */ | 986 | /* The rest is mostly same for libc and for "homegrown" support */ |
| 965 | 987 | ||
| 966 | #if 0 // UNUSED | ||
| 967 | size_t FAST_FUNC unicode_strlen(const char *string) | 988 | size_t FAST_FUNC unicode_strlen(const char *string) |
| 968 | { | 989 | { |
| 969 | size_t width = mbstowcs(NULL, string, INT_MAX); | 990 | size_t width = mbstowcs(NULL, string, INT_MAX); |
| @@ -971,7 +992,6 @@ size_t FAST_FUNC unicode_strlen(const char *string) | |||
| 971 | return strlen(string); | 992 | return strlen(string); |
| 972 | return width; | 993 | return width; |
| 973 | } | 994 | } |
| 974 | #endif | ||
| 975 | 995 | ||
| 976 | size_t FAST_FUNC unicode_strwidth(const char *string) | 996 | size_t FAST_FUNC unicode_strwidth(const char *string) |
| 977 | { | 997 | { |
diff --git a/libbb/xatonum.c b/libbb/xatonum.c index 62bbe53e7..6f4e023bb 100644 --- a/libbb/xatonum.c +++ b/libbb/xatonum.c | |||
| @@ -68,3 +68,10 @@ uint16_t FAST_FUNC xatou16(const char *numstr) | |||
| 68 | { | 68 | { |
| 69 | return xatou_range(numstr, 0, 0xffff); | 69 | return xatou_range(numstr, 0, 0xffff); |
| 70 | } | 70 | } |
| 71 | |||
| 72 | const struct suffix_mult bkm_suffixes[] = { | ||
| 73 | { "b", 512 }, | ||
| 74 | { "k", 1024 }, | ||
| 75 | { "m", 1024*1024 }, | ||
| 76 | { "", 0 } | ||
| 77 | }; | ||
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 05aa07ce8..a70683241 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
| @@ -541,13 +541,11 @@ int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp) | |||
| 541 | 541 | ||
| 542 | char* FAST_FUNC xmalloc_ttyname(int fd) | 542 | char* FAST_FUNC xmalloc_ttyname(int fd) |
| 543 | { | 543 | { |
| 544 | char *buf = xzalloc(128); | 544 | char buf[128]; |
| 545 | int r = ttyname_r(fd, buf, 127); | 545 | int r = ttyname_r(fd, buf, sizeof(buf) - 1); |
| 546 | if (r) { | 546 | if (r) |
| 547 | free(buf); | 547 | return NULL; |
| 548 | buf = NULL; | 548 | return xstrdup(buf); |
| 549 | } | ||
| 550 | return buf; | ||
| 551 | } | 549 | } |
| 552 | 550 | ||
| 553 | void FAST_FUNC generate_uuid(uint8_t *buf) | 551 | void FAST_FUNC generate_uuid(uint8_t *buf) |
diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index a36f920f4..29f0fbe91 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c | |||
| @@ -92,6 +92,7 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv) | |||
| 92 | { | 92 | { |
| 93 | char salt[MAX_PW_SALT_LEN]; | 93 | char salt[MAX_PW_SALT_LEN]; |
| 94 | char *salt_ptr; | 94 | char *salt_ptr; |
| 95 | char *password; | ||
| 95 | const char *opt_m, *opt_S; | 96 | const char *opt_m, *opt_S; |
| 96 | int fd; | 97 | int fd; |
| 97 | 98 | ||
| @@ -123,15 +124,19 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv) | |||
| 123 | 124 | ||
| 124 | xmove_fd(fd, STDIN_FILENO); | 125 | xmove_fd(fd, STDIN_FILENO); |
| 125 | 126 | ||
| 126 | puts(pw_encrypt( | 127 | password = argv[0]; |
| 127 | argv[0] ? argv[0] : ( | 128 | if (!password) { |
| 128 | /* Only mkpasswd, and only from tty, prompts. | 129 | /* Only mkpasswd, and only from tty, prompts. |
| 129 | * Otherwise it is a plain read. */ | 130 | * Otherwise it is a plain read. */ |
| 130 | (isatty(STDIN_FILENO) && applet_name[0] == 'm') | 131 | password = (isatty(STDIN_FILENO) && applet_name[0] == 'm') |
| 131 | ? bb_ask_stdin("Password: ") | 132 | ? bb_ask_stdin("Password: ") |
| 132 | : xmalloc_fgetline(stdin) | 133 | : xmalloc_fgetline(stdin) |
| 133 | ), | 134 | ; |
| 134 | salt, 1)); | 135 | /* may still be NULL on EOF/error */ |
| 136 | } | ||
| 137 | |||
| 138 | if (password) | ||
| 139 | puts(pw_encrypt(password, salt, 1)); | ||
| 135 | 140 | ||
| 136 | return EXIT_SUCCESS; | 141 | return EXIT_SUCCESS; |
| 137 | } | 142 | } |
diff --git a/loginutils/getty.c b/loginutils/getty.c index e5d13bed6..0f060ae6c 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c | |||
| @@ -695,6 +695,6 @@ int getty_main(int argc UNUSED_PARAM, char **argv) | |||
| 695 | /* We use PATH because we trust that root doesn't set "bad" PATH, | 695 | /* We use PATH because we trust that root doesn't set "bad" PATH, |
| 696 | * and getty is not suid-root applet */ | 696 | * and getty is not suid-root applet */ |
| 697 | /* With -n, logname == NULL, and login will ask for username instead */ | 697 | /* With -n, logname == NULL, and login will ask for username instead */ |
| 698 | BB_EXECLP(G.login, G.login, "--", logname, NULL); | 698 | BB_EXECLP(G.login, G.login, "--", logname, (char *)0); |
| 699 | bb_error_msg_and_die("can't execute '%s'", G.login); | 699 | bb_error_msg_and_die("can't execute '%s'", G.login); |
| 700 | } | 700 | } |
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index bd2b09eed..65e638489 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c | |||
| @@ -79,12 +79,12 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv) | |||
| 79 | char *encrypted; | 79 | char *encrypted; |
| 80 | int r; | 80 | int r; |
| 81 | 81 | ||
| 82 | /* cp points to a static buffer that is zeroed every time */ | 82 | /* cp points to a static buffer */ |
| 83 | cp = bb_ask(STDIN_FILENO, timeout, | 83 | cp = bb_ask(STDIN_FILENO, timeout, |
| 84 | "Give root password for system maintenance\n" | 84 | "Give root password for system maintenance\n" |
| 85 | "(or type Control-D for normal startup):"); | 85 | "(or type Control-D for normal startup):"); |
| 86 | 86 | if (!cp) { | |
| 87 | if (!cp || !*cp) { | 87 | /* ^D, ^C, timeout, or read error */ |
| 88 | bb_info_msg("Normal startup"); | 88 | bb_info_msg("Normal startup"); |
| 89 | return 0; | 89 | return 0; |
| 90 | } | 90 | } |
diff --git a/miscutils/chrt.c b/miscutils/chrt.c index 91b5397c4..f2f559fd7 100644 --- a/miscutils/chrt.c +++ b/miscutils/chrt.c | |||
| @@ -23,9 +23,6 @@ | |||
| 23 | 23 | ||
| 24 | #include <sched.h> | 24 | #include <sched.h> |
| 25 | #include "libbb.h" | 25 | #include "libbb.h" |
| 26 | #ifndef _POSIX_PRIORITY_SCHEDULING | ||
| 27 | #warning your system may be foobared | ||
| 28 | #endif | ||
| 29 | 26 | ||
| 30 | static const struct { | 27 | static const struct { |
| 31 | int policy; | 28 | int policy; |
diff --git a/miscutils/less.c b/miscutils/less.c index 5ce0a1203..60105f42b 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
| @@ -1608,6 +1608,9 @@ static void sigwinch_handler(int sig UNUSED_PARAM) | |||
| 1608 | int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1608 | int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 1609 | int less_main(int argc, char **argv) | 1609 | int less_main(int argc, char **argv) |
| 1610 | { | 1610 | { |
| 1611 | char *tty_name; | ||
| 1612 | int tty_fd; | ||
| 1613 | |||
| 1611 | INIT_G(); | 1614 | INIT_G(); |
| 1612 | 1615 | ||
| 1613 | /* TODO: -x: do not interpret backspace, -xx: tab also */ | 1616 | /* TODO: -x: do not interpret backspace, -xx: tab also */ |
| @@ -1637,10 +1640,28 @@ int less_main(int argc, char **argv) | |||
| 1637 | if (option_mask32 & FLAG_TILDE) | 1640 | if (option_mask32 & FLAG_TILDE) |
| 1638 | empty_line_marker = ""; | 1641 | empty_line_marker = ""; |
| 1639 | 1642 | ||
| 1640 | kbd_fd = open(CURRENT_TTY, O_RDONLY); | 1643 | /* Some versions of less can survive w/o controlling tty, |
| 1641 | if (kbd_fd < 0) | 1644 | * try to do the same. This also allows to specify an alternative |
| 1642 | return bb_cat(argv); | 1645 | * tty via "less 1<>TTY". |
| 1643 | ndelay_on(kbd_fd); | 1646 | * We don't try to use STDOUT_FILENO directly, |
| 1647 | * since we want to set this fd to non-blocking mode, | ||
| 1648 | * and not bother with restoring it on exit. | ||
| 1649 | */ | ||
| 1650 | tty_name = xmalloc_ttyname(STDOUT_FILENO); | ||
| 1651 | if (tty_name) { | ||
| 1652 | tty_fd = open(tty_name, O_RDONLY); | ||
| 1653 | free(tty_name); | ||
| 1654 | if (tty_fd < 0) | ||
| 1655 | goto try_ctty; | ||
| 1656 | } else { | ||
| 1657 | /* Try controlling tty */ | ||
| 1658 | try_ctty: | ||
| 1659 | tty_fd = open(CURRENT_TTY, O_RDONLY); | ||
| 1660 | if (tty_fd < 0) | ||
| 1661 | return bb_cat(argv); | ||
| 1662 | } | ||
| 1663 | ndelay_on(tty_fd); | ||
| 1664 | kbd_fd = tty_fd; /* save in a global */ | ||
| 1644 | 1665 | ||
| 1645 | tcgetattr(kbd_fd, &term_orig); | 1666 | tcgetattr(kbd_fd, &term_orig); |
| 1646 | term_less = term_orig; | 1667 | term_less = term_orig; |
diff --git a/miscutils/man.c b/miscutils/man.c index b8b15b83b..429898643 100644 --- a/miscutils/man.c +++ b/miscutils/man.c | |||
| @@ -162,7 +162,7 @@ int man_main(int argc UNUSED_PARAM, char **argv) | |||
| 162 | opt = getopt32(argv, "+aw"); | 162 | opt = getopt32(argv, "+aw"); |
| 163 | argv += optind; | 163 | argv += optind; |
| 164 | 164 | ||
| 165 | sec_list = xstrdup("1:2:3:4:5:6:7:8:9"); | 165 | sec_list = xstrdup("0p:1:1p:2:3:3p:4:5:6:7:8:9"); |
| 166 | /* Last valid man_path_list[] is [0x10] */ | 166 | /* Last valid man_path_list[] is [0x10] */ |
| 167 | count_mp = 0; | 167 | count_mp = 0; |
| 168 | man_path_list = xzalloc(0x11 * sizeof(man_path_list[0])); | 168 | man_path_list = xzalloc(0x11 * sizeof(man_path_list[0])); |
diff --git a/miscutils/setsid.c b/miscutils/setsid.c index ad2c8a4de..637081b6c 100644 --- a/miscutils/setsid.c +++ b/miscutils/setsid.c | |||
| @@ -31,7 +31,17 @@ int setsid_main(int argc UNUSED_PARAM, char **argv) | |||
| 31 | 31 | ||
| 32 | /* setsid() is allowed only when we are not a process group leader. | 32 | /* setsid() is allowed only when we are not a process group leader. |
| 33 | * Otherwise our PID serves as PGID of some existing process group | 33 | * Otherwise our PID serves as PGID of some existing process group |
| 34 | * and cannot be used as PGID of a new process group. */ | 34 | * and cannot be used as PGID of a new process group. |
| 35 | * | ||
| 36 | * Example: setsid() below fails when run alone in interactive shell: | ||
| 37 | * $ setsid PROG | ||
| 38 | * because shell's child (setsid) is put in a new process group. | ||
| 39 | * But doesn't fail if shell is not interactive | ||
| 40 | * (and therefore doesn't create process groups for pipes), | ||
| 41 | * or if setsid is not the first process in the process group: | ||
| 42 | * $ true | setsid PROG | ||
| 43 | * or if setsid is executed in backquotes (`setsid PROG`)... | ||
| 44 | */ | ||
| 35 | if (setsid() < 0) { | 45 | if (setsid() < 0) { |
| 36 | pid_t pid = fork_or_rexec(argv); | 46 | pid_t pid = fork_or_rexec(argv); |
| 37 | if (pid != 0) { | 47 | if (pid != 0) { |
| @@ -43,7 +53,7 @@ int setsid_main(int argc UNUSED_PARAM, char **argv) | |||
| 43 | * However, the code is larger and upstream | 53 | * However, the code is larger and upstream |
| 44 | * does not do such trick. | 54 | * does not do such trick. |
| 45 | */ | 55 | */ |
| 46 | exit(EXIT_SUCCESS); | 56 | return EXIT_SUCCESS; |
| 47 | } | 57 | } |
| 48 | 58 | ||
| 49 | /* child */ | 59 | /* child */ |
diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c index dd99a44f4..b71393532 100644 --- a/miscutils/ubi_tools.c +++ b/miscutils/ubi_tools.c | |||
| @@ -66,14 +66,6 @@ | |||
| 66 | #endif | 66 | #endif |
| 67 | #include <mtd/ubi-user.h> | 67 | #include <mtd/ubi-user.h> |
| 68 | 68 | ||
| 69 | #define OPTION_M (1 << 0) | ||
| 70 | #define OPTION_D (1 << 1) | ||
| 71 | #define OPTION_n (1 << 2) | ||
| 72 | #define OPTION_N (1 << 3) | ||
| 73 | #define OPTION_s (1 << 4) | ||
| 74 | #define OPTION_a (1 << 5) | ||
| 75 | #define OPTION_t (1 << 6) | ||
| 76 | |||
| 77 | #define do_attach (ENABLE_UBIATTACH && applet_name[3] == 'a') | 69 | #define do_attach (ENABLE_UBIATTACH && applet_name[3] == 'a') |
| 78 | #define do_detach (ENABLE_UBIDETACH && applet_name[3] == 'd') | 70 | #define do_detach (ENABLE_UBIDETACH && applet_name[3] == 'd') |
| 79 | #define do_mkvol (ENABLE_UBIMKVOL && applet_name[3] == 'm') | 71 | #define do_mkvol (ENABLE_UBIMKVOL && applet_name[3] == 'm') |
| @@ -81,191 +73,250 @@ | |||
| 81 | #define do_rsvol (ENABLE_UBIRSVOL && applet_name[4] == 's') | 73 | #define do_rsvol (ENABLE_UBIRSVOL && applet_name[4] == 's') |
| 82 | #define do_update (ENABLE_UBIUPDATEVOL && applet_name[3] == 'u') | 74 | #define do_update (ENABLE_UBIUPDATEVOL && applet_name[3] == 'u') |
| 83 | 75 | ||
| 84 | //usage:#define ubiattach_trivial_usage | 76 | static unsigned get_num_from_file(const char *path, unsigned max, const char *errmsg) |
| 85 | //usage: "-m MTD_NUM [-d UBI_NUM] UBI_CTRL_DEV" | 77 | { |
| 86 | //usage:#define ubiattach_full_usage "\n\n" | 78 | char buf[sizeof(long long)*3]; |
| 87 | //usage: "Attach MTD device to UBI\n" | 79 | unsigned long long num; |
| 88 | //usage: "\n -m MTD_NUM MTD device number to attach" | 80 | |
| 89 | //usage: "\n -d UBI_NUM UBI device number to assign" | 81 | if (open_read_close(path, buf, sizeof(buf)) < 0) |
| 90 | //usage: | 82 | bb_perror_msg_and_die(errmsg, path); |
| 91 | //usage:#define ubidetach_trivial_usage | 83 | /* It can be \n terminated, xatoull won't work well */ |
| 92 | //usage: "-d UBI_NUM UBI_CTRL_DEV" | 84 | if (sscanf(buf, "%llu", &num) != 1 || num > max) |
| 93 | //usage:#define ubidetach_full_usage "\n\n" | 85 | bb_error_msg_and_die(errmsg, path); |
| 94 | //usage: "Detach MTD device from UBI\n" | 86 | return num; |
| 95 | //usage: "\n -d UBI_NUM UBI device number" | 87 | } |
| 96 | //usage: | ||
| 97 | //usage:#define ubimkvol_trivial_usage | ||
| 98 | //usage: "UBI_DEVICE -N NAME -s SIZE" | ||
| 99 | //usage:#define ubimkvol_full_usage "\n\n" | ||
| 100 | //usage: "Create UBI volume\n" | ||
| 101 | //usage: "\n -a ALIGNMENT Volume alignment (default 1)" | ||
| 102 | //usage: "\n -n VOLID Volume ID, if not specified, it" | ||
| 103 | //usage: "\n will be assigned automatically" | ||
| 104 | //usage: "\n -N NAME Volume name" | ||
| 105 | //usage: "\n -s SIZE Size in bytes" | ||
| 106 | //usage: "\n -t TYPE Volume type (static|dynamic)" | ||
| 107 | //usage: | ||
| 108 | //usage:#define ubirmvol_trivial_usage | ||
| 109 | //usage: "UBI_DEVICE -n VOLID" | ||
| 110 | //usage:#define ubirmvol_full_usage "\n\n" | ||
| 111 | //usage: "Remove UBI volume\n" | ||
| 112 | //usage: "\n -n VOLID Volume ID" | ||
| 113 | //usage: | ||
| 114 | //usage:#define ubirsvol_trivial_usage | ||
| 115 | //usage: "UBI_DEVICE -n VOLID -s SIZE" | ||
| 116 | //usage:#define ubirsvol_full_usage "\n\n" | ||
| 117 | //usage: "Resize UBI volume\n" | ||
| 118 | //usage: "\n -n VOLID Volume ID to resize" | ||
| 119 | //usage: "\n -s SIZE Size in bytes" | ||
| 120 | //usage: | ||
| 121 | //usage:#define ubiupdatevol_trivial_usage | ||
| 122 | //usage: "UBI_DEVICE [IMG_FILE]" | ||
| 123 | //usage:#define ubiupdatevol_full_usage "\n\n" | ||
| 124 | //usage: "Update UBI volume\n" | ||
| 125 | //usage: "\n -t Truncate UBI volume" | ||
| 126 | //usage: "\n -s SIZE Bytes in input (if reading stdin)" | ||
| 127 | 88 | ||
| 89 | /* To prevent malloc(1G) accidents */ | ||
| 90 | #define MAX_SANE_ERASEBLOCK (16*1024*1024) | ||
| 128 | 91 | ||
| 129 | int ubi_tools_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 92 | int ubi_tools_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 130 | int ubi_tools_main(int argc UNUSED_PARAM, char **argv) | 93 | int ubi_tools_main(int argc UNUSED_PARAM, char **argv) |
| 131 | { | 94 | { |
| 95 | static const struct suffix_mult size_suffixes[] = { | ||
| 96 | { "KiB", 1024 }, | ||
| 97 | { "MiB", 1024*1024 }, | ||
| 98 | { "GiB", 1024*1024*1024 }, | ||
| 99 | { "", 0 } | ||
| 100 | }; | ||
| 101 | |||
| 132 | unsigned opts; | 102 | unsigned opts; |
| 133 | char *ubi_ctrl; | 103 | char *ubi_ctrl; |
| 134 | //struct stat st; | ||
| 135 | int fd; | 104 | int fd; |
| 136 | int mtd_num; | 105 | int mtd_num; |
| 137 | int dev_num = UBI_DEV_NUM_AUTO; | 106 | int dev_num = UBI_DEV_NUM_AUTO; |
| 138 | int vol_id = UBI_VOL_NUM_AUTO; | 107 | int vol_id = UBI_VOL_NUM_AUTO; |
| 139 | char *vol_name = NULL; | 108 | char *vol_name; |
| 140 | int size_bytes; | 109 | unsigned long long size_bytes = size_bytes; /* for compiler */ |
| 110 | char *size_bytes_str; | ||
| 141 | int alignment = 1; | 111 | int alignment = 1; |
| 142 | char *type = NULL; | 112 | char *type; |
| 113 | union { | ||
| 114 | struct ubi_attach_req attach_req; | ||
| 115 | struct ubi_mkvol_req mkvol_req; | ||
| 116 | struct ubi_rsvol_req rsvol_req; | ||
| 117 | } req_structs; | ||
| 118 | #define attach_req req_structs.attach_req | ||
| 119 | #define mkvol_req req_structs.mkvol_req | ||
| 120 | #define rsvol_req req_structs.rsvol_req | ||
| 121 | char path[sizeof("/sys/class/ubi/ubi%d_%d/usable_eb_size") | ||
| 122 | + 2 * sizeof(int)*3 + /*just in case:*/ 16]; | ||
| 123 | #define path_sys_class_ubi_ubi (path + sizeof("/sys/class/ubi/ubi")-1) | ||
| 124 | |||
| 125 | strcpy(path, "/sys/class/ubi/ubi"); | ||
| 126 | memset(&req_structs, 0, sizeof(req_structs)); | ||
| 127 | |||
| 128 | if (do_mkvol) { | ||
| 129 | opt_complementary = "-1:d+:n+:a+"; | ||
| 130 | opts = getopt32(argv, "md:n:N:s:a:t:", | ||
| 131 | &dev_num, &vol_id, | ||
| 132 | &vol_name, &size_bytes_str, &alignment, &type | ||
| 133 | ); | ||
| 134 | } else { | ||
| 135 | opt_complementary = "-1:m+:d+:n+:a+"; | ||
| 136 | opts = getopt32(argv, "m:d:n:N:s:a:t:", | ||
| 137 | &mtd_num, &dev_num, &vol_id, | ||
| 138 | &vol_name, &size_bytes_str, &alignment, &type | ||
| 139 | ); | ||
| 140 | } | ||
| 141 | #define OPTION_m (1 << 0) | ||
| 142 | #define OPTION_d (1 << 1) | ||
| 143 | #define OPTION_n (1 << 2) | ||
| 144 | #define OPTION_N (1 << 3) | ||
| 145 | #define OPTION_s (1 << 4) | ||
| 146 | #define OPTION_a (1 << 5) | ||
| 147 | #define OPTION_t (1 << 6) | ||
| 143 | 148 | ||
| 144 | opt_complementary = "-1:m+:d+:n+:s+:a+"; | 149 | if (opts & OPTION_s) |
| 145 | opts = getopt32(argv, "m:d:n:N:s:a:t::", | 150 | size_bytes = xatoull_sfx(size_bytes_str, size_suffixes); |
| 146 | &mtd_num, &dev_num, &vol_id, | 151 | argv += optind; |
| 147 | &vol_name, &size_bytes, &alignment, &type | 152 | ubi_ctrl = *argv++; |
| 148 | ); | ||
| 149 | ubi_ctrl = argv[optind]; | ||
| 150 | 153 | ||
| 151 | fd = xopen(ubi_ctrl, O_RDWR); | 154 | fd = xopen(ubi_ctrl, O_RDWR); |
| 152 | //xfstat(fd, &st, ubi_ctrl); | 155 | //xfstat(fd, &st, ubi_ctrl); |
| 153 | //if (!S_ISCHR(st.st_mode)) | 156 | //if (!S_ISCHR(st.st_mode)) |
| 154 | // bb_error_msg_and_die("%s: not a char device", ubi_ctrl); | 157 | // bb_error_msg_and_die("%s: not a char device", ubi_ctrl); |
| 155 | 158 | ||
| 159 | //usage:#define ubiattach_trivial_usage | ||
| 160 | //usage: "-m MTD_NUM [-d UBI_NUM] UBI_CTRL_DEV" | ||
| 161 | //usage:#define ubiattach_full_usage "\n\n" | ||
| 162 | //usage: "Attach MTD device to UBI\n" | ||
| 163 | //usage: "\n -m MTD_NUM MTD device number to attach" | ||
| 164 | //usage: "\n -d UBI_NUM UBI device number to assign" | ||
| 156 | if (do_attach) { | 165 | if (do_attach) { |
| 157 | struct ubi_attach_req req; | 166 | if (!(opts & OPTION_m)) |
| 158 | if (!(opts & OPTION_M)) | ||
| 159 | bb_error_msg_and_die("%s device not specified", "MTD"); | 167 | bb_error_msg_and_die("%s device not specified", "MTD"); |
| 160 | 168 | ||
| 161 | memset(&req, 0, sizeof(req)); | 169 | attach_req.mtd_num = mtd_num; |
| 162 | req.mtd_num = mtd_num; | 170 | attach_req.ubi_num = dev_num; |
| 163 | req.ubi_num = dev_num; | ||
| 164 | 171 | ||
| 165 | xioctl(fd, UBI_IOCATT, &req); | 172 | xioctl(fd, UBI_IOCATT, &attach_req); |
| 166 | } else | 173 | } else |
| 174 | |||
| 175 | //usage:#define ubidetach_trivial_usage | ||
| 176 | //usage: "-d UBI_NUM UBI_CTRL_DEV" | ||
| 177 | //usage:#define ubidetach_full_usage "\n\n" | ||
| 178 | //usage: "Detach MTD device from UBI\n" | ||
| 179 | //usage: "\n -d UBI_NUM UBI device number" | ||
| 167 | if (do_detach) { | 180 | if (do_detach) { |
| 168 | if (!(opts & OPTION_D)) | 181 | if (!(opts & OPTION_d)) |
| 169 | bb_error_msg_and_die("%s device not specified", "UBI"); | 182 | bb_error_msg_and_die("%s device not specified", "UBI"); |
| 170 | 183 | ||
| 184 | /* FIXME? kernel expects int32_t* here: */ | ||
| 171 | xioctl(fd, UBI_IOCDET, &dev_num); | 185 | xioctl(fd, UBI_IOCDET, &dev_num); |
| 172 | } else | 186 | } else |
| 187 | |||
| 188 | //usage:#define ubimkvol_trivial_usage | ||
| 189 | //usage: "UBI_DEVICE -N NAME [-s SIZE | -m]" | ||
| 190 | //usage:#define ubimkvol_full_usage "\n\n" | ||
| 191 | //usage: "Create UBI volume\n" | ||
| 192 | //usage: "\n -a ALIGNMENT Volume alignment (default 1)" | ||
| 193 | //usage: "\n -m Set volume size to maximum available" | ||
| 194 | //usage: "\n -n VOLID Volume ID. If not specified," | ||
| 195 | //usage: "\n assigned automatically" | ||
| 196 | //usage: "\n -N NAME Volume name" | ||
| 197 | //usage: "\n -s SIZE Size in bytes" | ||
| 198 | //usage: "\n -t TYPE Volume type (static|dynamic)" | ||
| 173 | if (do_mkvol) { | 199 | if (do_mkvol) { |
| 174 | struct ubi_mkvol_req req; | 200 | if (opts & OPTION_m) { |
| 175 | int vol_name_len; | 201 | unsigned leb_avail; |
| 202 | unsigned leb_size; | ||
| 203 | unsigned num; | ||
| 204 | char *p; | ||
| 205 | |||
| 206 | if (sscanf(ubi_ctrl, "/dev/ubi%u", &num) != 1) | ||
| 207 | bb_error_msg_and_die("wrong format of UBI device name"); | ||
| 208 | |||
| 209 | p = path_sys_class_ubi_ubi + sprintf(path_sys_class_ubi_ubi, "%u/", num); | ||
| 210 | |||
| 211 | strcpy(p, "avail_eraseblocks"); | ||
| 212 | leb_avail = get_num_from_file(path, UINT_MAX, "Can't get available eraseblocks from '%s'"); | ||
| 213 | |||
| 214 | strcpy(p, "eraseblock_size"); | ||
| 215 | leb_size = get_num_from_file(path, MAX_SANE_ERASEBLOCK, "Can't get eraseblock size from '%s'"); | ||
| 216 | |||
| 217 | size_bytes = leb_avail * (unsigned long long)leb_size; | ||
| 218 | //if (size_bytes <= 0) | ||
| 219 | // bb_error_msg_and_die("%s invalid maximum size calculated", "UBI"); | ||
| 220 | } else | ||
| 176 | if (!(opts & OPTION_s)) | 221 | if (!(opts & OPTION_s)) |
| 177 | bb_error_msg_and_die("%s size not specified", "UBI"); | 222 | bb_error_msg_and_die("size not specified"); |
| 223 | |||
| 178 | if (!(opts & OPTION_N)) | 224 | if (!(opts & OPTION_N)) |
| 179 | bb_error_msg_and_die("%s name not specified", "UBI"); | 225 | bb_error_msg_and_die("name not specified"); |
| 180 | vol_name_len = strlen(vol_name); | 226 | |
| 181 | if (vol_name_len > UBI_MAX_VOLUME_NAME) | 227 | mkvol_req.vol_id = vol_id; |
| 182 | bb_error_msg_and_die("%s volume name too long", "UBI"); | 228 | mkvol_req.vol_type = UBI_DYNAMIC_VOLUME; |
| 183 | 229 | if ((opts & OPTION_t) && type[0] == 's') | |
| 184 | memset(&req, 0, sizeof(req)); | 230 | mkvol_req.vol_type = UBI_STATIC_VOLUME; |
| 185 | req.vol_id = vol_id; | 231 | mkvol_req.alignment = alignment; |
| 186 | if ((opts & OPTION_t) && type) { | 232 | mkvol_req.bytes = size_bytes; /* signed int64_t */ |
| 187 | if (type[0] == 's') | 233 | strncpy(mkvol_req.name, vol_name, UBI_MAX_VOLUME_NAME); |
| 188 | req.vol_type = UBI_STATIC_VOLUME; | 234 | mkvol_req.name_len = strlen(vol_name); |
| 189 | else | 235 | if (mkvol_req.name_len > UBI_MAX_VOLUME_NAME) |
| 190 | req.vol_type = UBI_DYNAMIC_VOLUME; | 236 | bb_error_msg_and_die("volume name too long: '%s'", vol_name); |
| 191 | } else { | ||
| 192 | req.vol_type = UBI_DYNAMIC_VOLUME; | ||
| 193 | } | ||
| 194 | req.alignment = alignment; | ||
| 195 | req.bytes = size_bytes; | ||
| 196 | strncpy(req.name, vol_name, UBI_MAX_VOLUME_NAME); | ||
| 197 | req.name_len = vol_name_len; | ||
| 198 | 237 | ||
| 199 | xioctl(fd, UBI_IOCMKVOL, &req); | 238 | xioctl(fd, UBI_IOCMKVOL, &mkvol_req); |
| 200 | } else | 239 | } else |
| 240 | |||
| 241 | //usage:#define ubirmvol_trivial_usage | ||
| 242 | //usage: "UBI_DEVICE -n VOLID" | ||
| 243 | //usage:#define ubirmvol_full_usage "\n\n" | ||
| 244 | //usage: "Remove UBI volume\n" | ||
| 245 | //usage: "\n -n VOLID Volume ID" | ||
| 201 | if (do_rmvol) { | 246 | if (do_rmvol) { |
| 202 | if (!(opts & OPTION_n)) | 247 | if (!(opts & OPTION_n)) |
| 203 | bb_error_msg_and_die("%s volume id not specified", "UBI"); | 248 | bb_error_msg_and_die("volume id not specified"); |
| 204 | 249 | ||
| 250 | /* FIXME? kernel expects int32_t* here: */ | ||
| 205 | xioctl(fd, UBI_IOCRMVOL, &vol_id); | 251 | xioctl(fd, UBI_IOCRMVOL, &vol_id); |
| 206 | } else | 252 | } else |
| 253 | |||
| 254 | //usage:#define ubirsvol_trivial_usage | ||
| 255 | //usage: "UBI_DEVICE -n VOLID -s SIZE" | ||
| 256 | //usage:#define ubirsvol_full_usage "\n\n" | ||
| 257 | //usage: "Resize UBI volume\n" | ||
| 258 | //usage: "\n -n VOLID Volume ID" | ||
| 259 | //usage: "\n -s SIZE Size in bytes" | ||
| 207 | if (do_rsvol) { | 260 | if (do_rsvol) { |
| 208 | struct ubi_rsvol_req req; | ||
| 209 | if (!(opts & OPTION_s)) | 261 | if (!(opts & OPTION_s)) |
| 210 | bb_error_msg_and_die("%s size not specified", "UBI"); | 262 | bb_error_msg_and_die("size not specified"); |
| 211 | if (!(opts & OPTION_n)) | 263 | if (!(opts & OPTION_n)) |
| 212 | bb_error_msg_and_die("%s volume id not specified", "UBI"); | 264 | bb_error_msg_and_die("volume id not specified"); |
| 213 | 265 | ||
| 214 | memset(&req, 0, sizeof(req)); | 266 | rsvol_req.bytes = size_bytes; /* signed int64_t */ |
| 215 | req.bytes = size_bytes; | 267 | rsvol_req.vol_id = vol_id; |
| 216 | req.vol_id = vol_id; | ||
| 217 | 268 | ||
| 218 | xioctl(fd, UBI_IOCRSVOL, &req); | 269 | xioctl(fd, UBI_IOCRSVOL, &rsvol_req); |
| 219 | } else | 270 | } else |
| 271 | |||
| 272 | //usage:#define ubiupdatevol_trivial_usage | ||
| 273 | //usage: "UBI_DEVICE [-t | [-s SIZE] IMG_FILE]" | ||
| 274 | //usage:#define ubiupdatevol_full_usage "\n\n" | ||
| 275 | //usage: "Update UBI volume\n" | ||
| 276 | //usage: "\n -t Truncate to zero size" | ||
| 277 | //usage: "\n -s SIZE Size in bytes to resize to" | ||
| 220 | if (do_update) { | 278 | if (do_update) { |
| 221 | long long bytes; | 279 | int64_t bytes64; |
| 222 | 280 | ||
| 223 | if (opts & OPTION_t) { | 281 | if (opts & OPTION_t) { |
| 224 | // truncate the volume by starting an update for size 0 | 282 | /* truncate the volume by starting an update for size 0 */ |
| 225 | bytes = 0; | 283 | bytes64 = 0; |
| 226 | xioctl(fd, UBI_IOCVOLUP, &bytes); | 284 | /* this ioctl expects int64_t* parameter */ |
| 285 | xioctl(fd, UBI_IOCVOLUP, &bytes64); | ||
| 227 | } | 286 | } |
| 228 | else { | 287 | else { |
| 229 | struct stat st; | 288 | struct stat st; |
| 230 | char buf[sizeof("/sys/class/ubi/ubi%d_%d/usable_eb_size") + 2 * sizeof(int)*3]; | ||
| 231 | int input_fd; | ||
| 232 | unsigned ubinum, volnum; | 289 | unsigned ubinum, volnum; |
| 233 | unsigned leb_size; | 290 | unsigned leb_size; |
| 234 | ssize_t len; | 291 | ssize_t len; |
| 235 | char *input_data; | 292 | char *input_data; |
| 236 | 293 | ||
| 237 | // Make assumption that device not is in normal format. | 294 | /* Assume that device is in normal format. */ |
| 238 | // Removes need for scanning sysfs tree as full libubi does | 295 | /* Removes need for scanning sysfs tree as full libubi does. */ |
| 239 | if (sscanf(ubi_ctrl, "/dev/ubi%u_%u", &ubinum, &volnum) != 2) | 296 | if (sscanf(ubi_ctrl, "/dev/ubi%u_%u", &ubinum, &volnum) != 2) |
| 240 | bb_error_msg_and_die("%s volume node not in correct format", "UBI"); | 297 | bb_error_msg_and_die("wrong format of UBI device name"); |
| 241 | 298 | ||
| 242 | sprintf(buf, "/sys/class/ubi/ubi%u_%u/usable_eb_size", ubinum, volnum); | 299 | sprintf(path_sys_class_ubi_ubi, "%u_%u/usable_eb_size", ubinum, volnum); |
| 243 | if (open_read_close(buf, buf, sizeof(buf)) <= 0) | 300 | leb_size = get_num_from_file(path, MAX_SANE_ERASEBLOCK, "Can't get usable eraseblock size from '%s'"); |
| 244 | bb_error_msg_and_die("%s could not get LEB size", "UBI"); | 301 | |
| 245 | if (sscanf(buf, "%u", &leb_size) != 1) | 302 | if (!(opts & OPTION_s)) { |
| 246 | bb_error_msg_and_die("%s could not get LEB size", "UBI"); | 303 | if (!*argv) |
| 247 | |||
| 248 | if (opts & OPTION_s) { | ||
| 249 | input_fd = 0; | ||
| 250 | } else { | ||
| 251 | if (!argv[optind+1]) | ||
| 252 | bb_show_usage(); | 304 | bb_show_usage(); |
| 253 | xstat(argv[optind+1], &st); | 305 | xstat(*argv, &st); |
| 254 | size_bytes = st.st_size; | 306 | size_bytes = st.st_size; |
| 255 | input_fd = xopen(argv[optind+1], O_RDONLY); | 307 | xmove_fd(xopen(*argv, O_RDONLY), STDIN_FILENO); |
| 256 | } | 308 | } |
| 257 | 309 | ||
| 258 | bytes = size_bytes; | 310 | bytes64 = size_bytes; |
| 259 | xioctl(fd, UBI_IOCVOLUP, &bytes); | 311 | /* this ioctl expects signed int64_t* parameter */ |
| 312 | xioctl(fd, UBI_IOCVOLUP, &bytes64); | ||
| 260 | 313 | ||
| 261 | input_data = xmalloc(leb_size); | 314 | input_data = xmalloc(leb_size); |
| 262 | while ((len = full_read(input_fd, input_data, leb_size)) > 0) { | 315 | while ((len = full_read(STDIN_FILENO, input_data, leb_size)) > 0) { |
| 263 | xwrite(fd, input_data, len); | 316 | xwrite(fd, input_data, len); |
| 264 | } | 317 | } |
| 265 | if (len < 0) | 318 | if (len < 0) |
| 266 | bb_error_msg_and_die("%s volume update failed", "UBI"); | 319 | bb_perror_msg_and_die("UBI volume update failed"); |
| 267 | if (ENABLE_FEATURE_CLEAN_UP) | ||
| 268 | close(input_fd); | ||
| 269 | } | 320 | } |
| 270 | } | 321 | } |
| 271 | 322 | ||
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index fb6c65990..7f7446d8e 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
| @@ -171,7 +171,7 @@ struct globals { | |||
| 171 | } FIX_ALIASING; | 171 | } FIX_ALIASING; |
| 172 | #define G (*ptr_to_globals) | 172 | #define G (*ptr_to_globals) |
| 173 | #define INIT_G() do { \ | 173 | #define INIT_G() do { \ |
| 174 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 174 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
| 175 | } while (0) | 175 | } while (0) |
| 176 | 176 | ||
| 177 | 177 | ||
diff --git a/networking/httpd.c b/networking/httpd.c index b46eb0fab..cef9b8baf 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
| @@ -1709,8 +1709,8 @@ static int pam_talker(int num_msg, | |||
| 1709 | s = userinfo->pw; | 1709 | s = userinfo->pw; |
| 1710 | break; | 1710 | break; |
| 1711 | case PAM_ERROR_MSG: | 1711 | case PAM_ERROR_MSG: |
| 1712 | case PAM_TEXT_INFO: | 1712 | case PAM_TEXT_INFO: |
| 1713 | s = ""; | 1713 | s = ""; |
| 1714 | break; | 1714 | break; |
| 1715 | default: | 1715 | default: |
| 1716 | free(response); | 1716 | free(response); |
diff --git a/networking/ifconfig.c b/networking/ifconfig.c index 782374b35..8984b0207 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c | |||
| @@ -56,7 +56,7 @@ | |||
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | #if ENABLE_FEATURE_IFCONFIG_SLIP | 58 | #if ENABLE_FEATURE_IFCONFIG_SLIP |
| 59 | # include <net/if_slip.h> | 59 | # include <linux/if_slip.h> |
| 60 | #endif | 60 | #endif |
| 61 | 61 | ||
| 62 | /* I don't know if this is needed for busybox or not. Anyone? */ | 62 | /* I don't know if this is needed for busybox or not. Anyone? */ |
| @@ -265,49 +265,6 @@ static const struct options OptArray[] = { | |||
| 265 | { NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING) } | 265 | { NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING) } |
| 266 | }; | 266 | }; |
| 267 | 267 | ||
| 268 | #if ENABLE_FEATURE_IFCONFIG_HW | ||
| 269 | /* Input an Ethernet address and convert to binary. */ | ||
| 270 | static int in_ether(const char *bufp, struct sockaddr *sap) | ||
| 271 | { | ||
| 272 | char *ptr; | ||
| 273 | int i, j; | ||
| 274 | unsigned char val; | ||
| 275 | unsigned char c; | ||
| 276 | |||
| 277 | sap->sa_family = ARPHRD_ETHER; | ||
| 278 | ptr = (char *) sap->sa_data; | ||
| 279 | |||
| 280 | i = 0; | ||
| 281 | do { | ||
| 282 | j = val = 0; | ||
| 283 | |||
| 284 | /* We might get a semicolon here - not required. */ | ||
| 285 | if (i && (*bufp == ':')) { | ||
| 286 | bufp++; | ||
| 287 | } | ||
| 288 | |||
| 289 | do { | ||
| 290 | c = *bufp; | ||
| 291 | if (((unsigned char)(c - '0')) <= 9) { | ||
| 292 | c -= '0'; | ||
| 293 | } else if ((unsigned char)((c|0x20) - 'a') <= 5) { | ||
| 294 | c = (unsigned char)((c|0x20) - 'a') + 10; | ||
| 295 | } else if (j && (c == ':' || c == 0)) { | ||
| 296 | break; | ||
| 297 | } else { | ||
| 298 | return -1; | ||
| 299 | } | ||
| 300 | ++bufp; | ||
| 301 | val <<= 4; | ||
| 302 | val += c; | ||
| 303 | } while (++j < 2); | ||
| 304 | *ptr++ = val; | ||
| 305 | } while (++i < ETH_ALEN); | ||
| 306 | |||
| 307 | return *bufp; /* Error if we don't end at end of string. */ | ||
| 308 | } | ||
| 309 | #endif | ||
| 310 | |||
| 311 | int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 268 | int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 312 | int ifconfig_main(int argc UNUSED_PARAM, char **argv) | 269 | int ifconfig_main(int argc UNUSED_PARAM, char **argv) |
| 313 | { | 270 | { |
diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 3cdc2c9d2..b578f4c61 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c | |||
| @@ -451,20 +451,24 @@ static smallint detect_link(void) | |||
| 451 | static NOINLINE int check_existence_through_netlink(void) | 451 | static NOINLINE int check_existence_through_netlink(void) |
| 452 | { | 452 | { |
| 453 | int iface_len; | 453 | int iface_len; |
| 454 | char replybuf[1024]; | 454 | /* Buffer was 1K, but on linux-3.9.9 it was reported to be too small. |
| 455 | * netlink.h: "limit to 8K to avoid MSG_TRUNC when PAGE_SIZE is very large". | ||
| 456 | * Note: on error returns (-1) we exit, no need to free replybuf. | ||
| 457 | */ | ||
| 458 | enum { BUF_SIZE = 8 * 1024 }; | ||
| 459 | char *replybuf = xmalloc(BUF_SIZE); | ||
| 455 | 460 | ||
| 456 | iface_len = strlen(G.iface); | 461 | iface_len = strlen(G.iface); |
| 457 | while (1) { | 462 | while (1) { |
| 458 | struct nlmsghdr *mhdr; | 463 | struct nlmsghdr *mhdr; |
| 459 | ssize_t bytes; | 464 | ssize_t bytes; |
| 460 | 465 | ||
| 461 | bytes = recv(netlink_fd, &replybuf, sizeof(replybuf), MSG_DONTWAIT); | 466 | bytes = recv(netlink_fd, replybuf, BUF_SIZE, MSG_DONTWAIT); |
| 462 | if (bytes < 0) { | 467 | if (bytes < 0) { |
| 463 | if (errno == EAGAIN) | 468 | if (errno == EAGAIN) |
| 464 | return G.iface_exists; | 469 | goto ret; |
| 465 | if (errno == EINTR) | 470 | if (errno == EINTR) |
| 466 | continue; | 471 | continue; |
| 467 | |||
| 468 | bb_perror_msg("netlink: recv"); | 472 | bb_perror_msg("netlink: recv"); |
| 469 | return -1; | 473 | return -1; |
| 470 | } | 474 | } |
| @@ -507,6 +511,8 @@ static NOINLINE int check_existence_through_netlink(void) | |||
| 507 | } | 511 | } |
| 508 | } | 512 | } |
| 509 | 513 | ||
| 514 | ret: | ||
| 515 | free(replybuf); | ||
| 510 | return G.iface_exists; | 516 | return G.iface_exists; |
| 511 | } | 517 | } |
| 512 | 518 | ||
diff --git a/networking/interface.c b/networking/interface.c index 9ae8b3f03..bf7d2b1b4 100644 --- a/networking/interface.c +++ b/networking/interface.c | |||
| @@ -722,68 +722,15 @@ static char* FAST_FUNC ether_print(unsigned char *ptr) | |||
| 722 | return buff; | 722 | return buff; |
| 723 | } | 723 | } |
| 724 | 724 | ||
| 725 | static int FAST_FUNC ether_input(const char *bufp, struct sockaddr *sap); | ||
| 726 | |||
| 727 | static const struct hwtype ether_hwtype = { | 725 | static const struct hwtype ether_hwtype = { |
| 728 | .name = "ether", | 726 | .name = "ether", |
| 729 | .title = "Ethernet", | 727 | .title = "Ethernet", |
| 730 | .type = ARPHRD_ETHER, | 728 | .type = ARPHRD_ETHER, |
| 731 | .alen = ETH_ALEN, | 729 | .alen = ETH_ALEN, |
| 732 | .print = ether_print, | 730 | .print = ether_print, |
| 733 | .input = ether_input | 731 | .input = in_ether |
| 734 | }; | 732 | }; |
| 735 | 733 | ||
| 736 | static unsigned hexchar2int(char c) | ||
| 737 | { | ||
| 738 | if (isdigit(c)) | ||
| 739 | return c - '0'; | ||
| 740 | c &= ~0x20; /* a -> A */ | ||
| 741 | if ((unsigned)(c - 'A') <= 5) | ||
| 742 | return c - ('A' - 10); | ||
| 743 | return ~0U; | ||
| 744 | } | ||
| 745 | |||
| 746 | /* Input an Ethernet address and convert to binary. */ | ||
| 747 | static int FAST_FUNC ether_input(const char *bufp, struct sockaddr *sap) | ||
| 748 | { | ||
| 749 | unsigned char *ptr; | ||
| 750 | char c; | ||
| 751 | int i; | ||
| 752 | unsigned val; | ||
| 753 | |||
| 754 | sap->sa_family = ether_hwtype.type; | ||
| 755 | ptr = (unsigned char*) sap->sa_data; | ||
| 756 | |||
| 757 | i = 0; | ||
| 758 | while ((*bufp != '\0') && (i < ETH_ALEN)) { | ||
| 759 | val = hexchar2int(*bufp++) * 0x10; | ||
| 760 | if (val > 0xff) { | ||
| 761 | errno = EINVAL; | ||
| 762 | return -1; | ||
| 763 | } | ||
| 764 | c = *bufp; | ||
| 765 | if (c == ':' || c == 0) | ||
| 766 | val >>= 4; | ||
| 767 | else { | ||
| 768 | val |= hexchar2int(c); | ||
| 769 | if (val > 0xff) { | ||
| 770 | errno = EINVAL; | ||
| 771 | return -1; | ||
| 772 | } | ||
| 773 | } | ||
| 774 | if (c != 0) | ||
| 775 | bufp++; | ||
| 776 | *ptr++ = (unsigned char) val; | ||
| 777 | i++; | ||
| 778 | |||
| 779 | /* We might get a semicolon here - not required. */ | ||
| 780 | if (*bufp == ':') { | ||
| 781 | bufp++; | ||
| 782 | } | ||
| 783 | } | ||
| 784 | return 0; | ||
| 785 | } | ||
| 786 | |||
| 787 | static const struct hwtype ppp_hwtype = { | 734 | static const struct hwtype ppp_hwtype = { |
| 788 | .name = "ppp", | 735 | .name = "ppp", |
| 789 | .title = "Point-to-Point Protocol", | 736 | .title = "Point-to-Point Protocol", |
| @@ -927,7 +874,7 @@ static void print_bytes_scaled(unsigned long long ull, const char *end) | |||
| 927 | static void ife_print6(struct interface *ptr) | 874 | static void ife_print6(struct interface *ptr) |
| 928 | { | 875 | { |
| 929 | FILE *f; | 876 | FILE *f; |
| 930 | char addr6[40], devname[20]; | 877 | char addr6[40], devname[21]; |
| 931 | struct sockaddr_in6 sap; | 878 | struct sockaddr_in6 sap; |
| 932 | int plen, scope, dad_status, if_idx; | 879 | int plen, scope, dad_status, if_idx; |
| 933 | char addr6p[8][5]; | 880 | char addr6p[8][5]; |
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 3fd3f4478..aa4779ad1 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c | |||
| @@ -627,10 +627,12 @@ static int ipaddr_modify(int cmd, char **argv) | |||
| 627 | req.ifa.ifa_family = preferred_family; | 627 | req.ifa.ifa_family = preferred_family; |
| 628 | 628 | ||
| 629 | while (*argv) { | 629 | while (*argv) { |
| 630 | const smalluint arg = index_in_strings(option, *argv); | 630 | unsigned arg = index_in_strings(option, *argv); |
| 631 | if (arg <= 1) { /* peer, remote */ | 631 | /* if search fails, "local" is assumed */ |
| 632 | if ((int)arg >= 0) | ||
| 632 | NEXT_ARG(); | 633 | NEXT_ARG(); |
| 633 | 634 | ||
| 635 | if (arg <= 1) { /* peer, remote */ | ||
| 634 | if (peer_len) { | 636 | if (peer_len) { |
| 635 | duparg("peer", *argv); | 637 | duparg("peer", *argv); |
| 636 | } | 638 | } |
| @@ -643,7 +645,6 @@ static int ipaddr_modify(int cmd, char **argv) | |||
| 643 | req.ifa.ifa_prefixlen = peer.bitlen; | 645 | req.ifa.ifa_prefixlen = peer.bitlen; |
| 644 | } else if (arg <= 3) { /* broadcast, brd */ | 646 | } else if (arg <= 3) { /* broadcast, brd */ |
| 645 | inet_prefix addr; | 647 | inet_prefix addr; |
| 646 | NEXT_ARG(); | ||
| 647 | if (brd_len) { | 648 | if (brd_len) { |
| 648 | duparg("broadcast", *argv); | 649 | duparg("broadcast", *argv); |
| 649 | } | 650 | } |
| @@ -660,7 +661,6 @@ static int ipaddr_modify(int cmd, char **argv) | |||
| 660 | } | 661 | } |
| 661 | } else if (arg == 4) { /* anycast */ | 662 | } else if (arg == 4) { /* anycast */ |
| 662 | inet_prefix addr; | 663 | inet_prefix addr; |
| 663 | NEXT_ARG(); | ||
| 664 | if (any_len) { | 664 | if (any_len) { |
| 665 | duparg("anycast", *argv); | 665 | duparg("anycast", *argv); |
| 666 | } | 666 | } |
| @@ -672,22 +672,18 @@ static int ipaddr_modify(int cmd, char **argv) | |||
| 672 | any_len = addr.bytelen; | 672 | any_len = addr.bytelen; |
| 673 | } else if (arg == 5) { /* scope */ | 673 | } else if (arg == 5) { /* scope */ |
| 674 | uint32_t scope = 0; | 674 | uint32_t scope = 0; |
| 675 | NEXT_ARG(); | ||
| 676 | if (rtnl_rtscope_a2n(&scope, *argv)) { | 675 | if (rtnl_rtscope_a2n(&scope, *argv)) { |
| 677 | invarg(*argv, "scope"); | 676 | invarg(*argv, "scope"); |
| 678 | } | 677 | } |
| 679 | req.ifa.ifa_scope = scope; | 678 | req.ifa.ifa_scope = scope; |
| 680 | scoped = 1; | 679 | scoped = 1; |
| 681 | } else if (arg == 6) { /* dev */ | 680 | } else if (arg == 6) { /* dev */ |
| 682 | NEXT_ARG(); | ||
| 683 | d = *argv; | 681 | d = *argv; |
| 684 | } else if (arg == 7) { /* label */ | 682 | } else if (arg == 7) { /* label */ |
| 685 | NEXT_ARG(); | ||
| 686 | l = *argv; | 683 | l = *argv; |
| 687 | addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1); | 684 | addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l) + 1); |
| 688 | } else { | 685 | } else { |
| 689 | if (arg == 8) /* local */ | 686 | /* local (specified or assumed) */ |
| 690 | NEXT_ARG(); | ||
| 691 | if (local_len) { | 687 | if (local_len) { |
| 692 | duparg2("local", *argv); | 688 | duparg2("local", *argv); |
| 693 | } | 689 | } |
| @@ -724,7 +720,7 @@ static int ipaddr_modify(int cmd, char **argv) | |||
| 724 | } | 720 | } |
| 725 | brd = peer; | 721 | brd = peer; |
| 726 | if (brd.bitlen <= 30) { | 722 | if (brd.bitlen <= 30) { |
| 727 | for (i=31; i>=brd.bitlen; i--) { | 723 | for (i = 31; i >= brd.bitlen; i--) { |
| 728 | if (brd_len == -1) | 724 | if (brd_len == -1) |
| 729 | brd.data[0] |= htonl(1<<(31-i)); | 725 | brd.data[0] |= htonl(1<<(31-i)); |
| 730 | else | 726 | else |
| @@ -754,11 +750,11 @@ int FAST_FUNC do_ipaddr(char **argv) | |||
| 754 | { | 750 | { |
| 755 | static const char commands[] ALIGN1 = | 751 | static const char commands[] ALIGN1 = |
| 756 | "add\0""delete\0""list\0""show\0""lst\0""flush\0"; | 752 | "add\0""delete\0""list\0""show\0""lst\0""flush\0"; |
| 757 | smalluint cmd = 2; | 753 | int cmd = 2; |
| 758 | if (*argv) { | 754 | if (*argv) { |
| 759 | cmd = index_in_substrings(commands, *argv); | 755 | cmd = index_in_substrings(commands, *argv); |
| 760 | if (cmd > 5) | 756 | if (cmd < 0) |
| 761 | bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); | 757 | invarg(*argv, applet_name); |
| 762 | argv++; | 758 | argv++; |
| 763 | if (cmd <= 1) | 759 | if (cmd <= 1) |
| 764 | return ipaddr_modify((cmd == 0) ? RTM_NEWADDR : RTM_DELADDR, argv); | 760 | return ipaddr_modify((cmd == 0) ? RTM_NEWADDR : RTM_DELADDR, argv); |
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index bad2017fe..286e59ebf 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c | |||
| @@ -1,18 +1,33 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
| 2 | /* | 2 | /* |
| 3 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | 3 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
| 4 | * Patrick McHardy <kaber@trash.net> | ||
| 4 | * | 5 | * |
| 5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 6 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| 6 | */ | 7 | */ |
| 7 | #include <net/if.h> | 8 | #include <net/if.h> |
| 8 | #include <net/if_packet.h> | 9 | /*#include <net/if_packet.h> - not needed? */ |
| 9 | #include <netpacket/packet.h> | 10 | #include <netpacket/packet.h> |
| 10 | #include <netinet/if_ether.h> | 11 | #include <netinet/if_ether.h> |
| 11 | 12 | ||
| 13 | #include <linux/if_vlan.h> | ||
| 12 | #include "ip_common.h" /* #include "libbb.h" is inside */ | 14 | #include "ip_common.h" /* #include "libbb.h" is inside */ |
| 13 | #include "rt_names.h" | 15 | #include "rt_names.h" |
| 14 | #include "utils.h" | 16 | #include "utils.h" |
| 15 | 17 | ||
| 18 | #undef ETH_P_8021AD | ||
| 19 | #define ETH_P_8021AD 0x88A8 | ||
| 20 | #undef VLAN_FLAG_REORDER_HDR | ||
| 21 | #define VLAN_FLAG_REORDER_HDR 0x1 | ||
| 22 | #undef VLAN_FLAG_GVRP | ||
| 23 | #define VLAN_FLAG_GVRP 0x2 | ||
| 24 | #undef VLAN_FLAG_LOOSE_BINDING | ||
| 25 | #define VLAN_FLAG_LOOSE_BINDING 0x4 | ||
| 26 | #undef VLAN_FLAG_MVRP | ||
| 27 | #define VLAN_FLAG_MVRP 0x8 | ||
| 28 | #undef IFLA_VLAN_PROTOCOL | ||
| 29 | #define IFLA_VLAN_PROTOCOL 5 | ||
| 30 | |||
| 16 | #ifndef IFLA_LINKINFO | 31 | #ifndef IFLA_LINKINFO |
| 17 | # define IFLA_LINKINFO 18 | 32 | # define IFLA_LINKINFO 18 |
| 18 | # define IFLA_INFO_KIND 1 | 33 | # define IFLA_INFO_KIND 1 |
| @@ -277,12 +292,103 @@ static int ipaddr_list_link(char **argv) | |||
| 277 | return ipaddr_list_or_flush(argv, 0); | 292 | return ipaddr_list_or_flush(argv, 0); |
| 278 | } | 293 | } |
| 279 | 294 | ||
| 295 | static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) | ||
| 296 | { | ||
| 297 | static const char keywords[] ALIGN1 = | ||
| 298 | "id\0" | ||
| 299 | "protocol\0" | ||
| 300 | "reorder_hdr\0" | ||
| 301 | "gvrp\0" | ||
| 302 | "mvrp\0" | ||
| 303 | "loose_binding\0" | ||
| 304 | ; | ||
| 305 | static const char protocols[] ALIGN1 = | ||
| 306 | "802.1q\0" | ||
| 307 | "802.1ad\0" | ||
| 308 | ; | ||
| 309 | static const char str_on_off[] ALIGN1 = | ||
| 310 | "on\0" | ||
| 311 | "off\0" | ||
| 312 | ; | ||
| 313 | enum { | ||
| 314 | ARG_id = 0, | ||
| 315 | ARG_reorder_hdr, | ||
| 316 | ARG_gvrp, | ||
| 317 | ARG_mvrp, | ||
| 318 | ARG_loose_binding, | ||
| 319 | ARG_protocol, | ||
| 320 | }; | ||
| 321 | enum { | ||
| 322 | PROTO_8021Q = 0, | ||
| 323 | PROTO_8021AD, | ||
| 324 | }; | ||
| 325 | enum { | ||
| 326 | PARM_on = 0, | ||
| 327 | PARM_off | ||
| 328 | }; | ||
| 329 | int arg; | ||
| 330 | uint16_t id, proto; | ||
| 331 | struct ifla_vlan_flags flags = {}; | ||
| 332 | |||
| 333 | while (*argv) { | ||
| 334 | arg = index_in_substrings(keywords, *argv); | ||
| 335 | if (arg < 0) | ||
| 336 | invarg(*argv, "type vlan"); | ||
| 337 | |||
| 338 | NEXT_ARG(); | ||
| 339 | if (arg == ARG_id) { | ||
| 340 | id = get_u16(*argv, "id"); | ||
| 341 | addattr_l(n, size, IFLA_VLAN_ID, &id, sizeof(id)); | ||
| 342 | } else if (arg == ARG_protocol) { | ||
| 343 | arg = index_in_substrings(protocols, *argv); | ||
| 344 | if (arg == PROTO_8021Q) | ||
| 345 | proto = ETH_P_8021Q; | ||
| 346 | else if (arg == PROTO_8021AD) | ||
| 347 | proto = ETH_P_8021AD; | ||
| 348 | else | ||
| 349 | bb_error_msg_and_die("unknown VLAN encapsulation protocol '%s'", | ||
| 350 | *argv); | ||
| 351 | addattr_l(n, size, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto)); | ||
| 352 | } else { | ||
| 353 | int param = index_in_strings(str_on_off, *argv); | ||
| 354 | if (param < 0) | ||
| 355 | die_must_be_on_off(nth_string(keywords, arg)); | ||
| 356 | |||
| 357 | if (arg == ARG_reorder_hdr) { | ||
| 358 | flags.mask |= VLAN_FLAG_REORDER_HDR; | ||
| 359 | flags.flags &= ~VLAN_FLAG_REORDER_HDR; | ||
| 360 | if (param == PARM_on) | ||
| 361 | flags.flags |= VLAN_FLAG_REORDER_HDR; | ||
| 362 | } else if (arg == ARG_gvrp) { | ||
| 363 | flags.mask |= VLAN_FLAG_GVRP; | ||
| 364 | flags.flags &= ~VLAN_FLAG_GVRP; | ||
| 365 | if (param == PARM_on) | ||
| 366 | flags.flags |= VLAN_FLAG_GVRP; | ||
| 367 | } else if (arg == ARG_mvrp) { | ||
| 368 | flags.mask |= VLAN_FLAG_MVRP; | ||
| 369 | flags.flags &= ~VLAN_FLAG_MVRP; | ||
| 370 | if (param == PARM_on) | ||
| 371 | flags.flags |= VLAN_FLAG_MVRP; | ||
| 372 | } else { /*if (arg == ARG_loose_binding) */ | ||
| 373 | flags.mask |= VLAN_FLAG_LOOSE_BINDING; | ||
| 374 | flags.flags &= ~VLAN_FLAG_LOOSE_BINDING; | ||
| 375 | if (param == PARM_on) | ||
| 376 | flags.flags |= VLAN_FLAG_LOOSE_BINDING; | ||
| 377 | } | ||
| 378 | } | ||
| 379 | argv++; | ||
| 380 | } | ||
| 381 | |||
| 382 | if (flags.mask) | ||
| 383 | addattr_l(n, size, IFLA_VLAN_FLAGS, &flags, sizeof(flags)); | ||
| 384 | } | ||
| 385 | |||
| 280 | #ifndef NLMSG_TAIL | 386 | #ifndef NLMSG_TAIL |
| 281 | #define NLMSG_TAIL(nmsg) \ | 387 | #define NLMSG_TAIL(nmsg) \ |
| 282 | ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) | 388 | ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) |
| 283 | #endif | 389 | #endif |
| 284 | /* Return value becomes exitcode. It's okay to not return at all */ | 390 | /* Return value becomes exitcode. It's okay to not return at all */ |
| 285 | static int do_change(char **argv, const unsigned rtm) | 391 | static int do_add_or_delete(char **argv, const unsigned rtm) |
| 286 | { | 392 | { |
| 287 | static const char keywords[] ALIGN1 = | 393 | static const char keywords[] ALIGN1 = |
| 288 | "link\0""name\0""type\0""dev\0"; | 394 | "link\0""name\0""type\0""dev\0"; |
| @@ -312,15 +418,17 @@ static int do_change(char **argv, const unsigned rtm) | |||
| 312 | 418 | ||
| 313 | while (*argv) { | 419 | while (*argv) { |
| 314 | arg = index_in_substrings(keywords, *argv); | 420 | arg = index_in_substrings(keywords, *argv); |
| 421 | if (arg == ARG_type) { | ||
| 422 | NEXT_ARG(); | ||
| 423 | type_str = *argv++; | ||
| 424 | break; | ||
| 425 | } | ||
| 315 | if (arg == ARG_link) { | 426 | if (arg == ARG_link) { |
| 316 | NEXT_ARG(); | 427 | NEXT_ARG(); |
| 317 | link_str = *argv; | 428 | link_str = *argv; |
| 318 | } else if (arg == ARG_name) { | 429 | } else if (arg == ARG_name) { |
| 319 | NEXT_ARG(); | 430 | NEXT_ARG(); |
| 320 | name_str = *argv; | 431 | name_str = *argv; |
| 321 | } else if (arg == ARG_type) { | ||
| 322 | NEXT_ARG(); | ||
| 323 | type_str = *argv; | ||
| 324 | } else { | 432 | } else { |
| 325 | if (arg == ARG_dev) { | 433 | if (arg == ARG_dev) { |
| 326 | if (dev_str) | 434 | if (dev_str) |
| @@ -339,6 +447,17 @@ static int do_change(char **argv, const unsigned rtm) | |||
| 339 | addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); | 447 | addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); |
| 340 | addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str, | 448 | addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str, |
| 341 | strlen(type_str)); | 449 | strlen(type_str)); |
| 450 | |||
| 451 | if (*argv) { | ||
| 452 | struct rtattr *data = NLMSG_TAIL(&req.n); | ||
| 453 | addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); | ||
| 454 | |||
| 455 | if (strcmp(type_str, "vlan") == 0) | ||
| 456 | vlan_parse_opt(argv, &req.n, sizeof(req)); | ||
| 457 | |||
| 458 | data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; | ||
| 459 | } | ||
| 460 | |||
| 342 | linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; | 461 | linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; |
| 343 | } | 462 | } |
| 344 | if (rtm != RTM_NEWLINK) { | 463 | if (rtm != RTM_NEWLINK) { |
| @@ -370,13 +489,13 @@ int FAST_FUNC do_iplink(char **argv) | |||
| 370 | static const char keywords[] ALIGN1 = | 489 | static const char keywords[] ALIGN1 = |
| 371 | "add\0""delete\0""set\0""show\0""lst\0""list\0"; | 490 | "add\0""delete\0""set\0""show\0""lst\0""list\0"; |
| 372 | if (*argv) { | 491 | if (*argv) { |
| 373 | smalluint key = index_in_substrings(keywords, *argv); | 492 | int key = index_in_substrings(keywords, *argv); |
| 374 | if (key > 5) /* invalid argument */ | 493 | if (key < 0) /* invalid argument */ |
| 375 | bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); | 494 | invarg(*argv, applet_name); |
| 376 | argv++; | 495 | argv++; |
| 377 | if (key <= 1) /* add/delete */ | 496 | if (key <= 1) /* add/delete */ |
| 378 | return do_change(argv, key ? RTM_DELLINK : RTM_NEWLINK); | 497 | return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK); |
| 379 | else if (key == 2) /* set */ | 498 | if (key == 2) /* set */ |
| 380 | return do_set(argv); | 499 | return do_set(argv); |
| 381 | } | 500 | } |
| 382 | /* show, lst, list */ | 501 | /* show, lst, list */ |
diff --git a/networking/libiproute/iprule.c b/networking/libiproute/iprule.c index 241a6bf9d..8dbe6bd92 100644 --- a/networking/libiproute/iprule.c +++ b/networking/libiproute/iprule.c | |||
| @@ -215,7 +215,7 @@ static int iprule_modify(int cmd, char **argv) | |||
| 215 | while (*argv) { | 215 | while (*argv) { |
| 216 | key = index_in_substrings(keywords, *argv) + 1; | 216 | key = index_in_substrings(keywords, *argv) + 1; |
| 217 | if (key == 0) /* no match found in keywords array, bail out. */ | 217 | if (key == 0) /* no match found in keywords array, bail out. */ |
| 218 | bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); | 218 | invarg(*argv, applet_name); |
| 219 | if (key == ARG_from) { | 219 | if (key == ARG_from) { |
| 220 | inet_prefix dst; | 220 | inet_prefix dst; |
| 221 | NEXT_ARG(); | 221 | NEXT_ARG(); |
| @@ -308,9 +308,9 @@ int FAST_FUNC do_iprule(char **argv) | |||
| 308 | static const char ip_rule_commands[] ALIGN1 = | 308 | static const char ip_rule_commands[] ALIGN1 = |
| 309 | "add\0""delete\0""list\0""show\0"; | 309 | "add\0""delete\0""list\0""show\0"; |
| 310 | if (*argv) { | 310 | if (*argv) { |
| 311 | smalluint cmd = index_in_substrings(ip_rule_commands, *argv); | 311 | int cmd = index_in_substrings(ip_rule_commands, *argv); |
| 312 | if (cmd > 3) | 312 | if (cmd < 0) |
| 313 | bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); | 313 | invarg(*argv, applet_name); |
| 314 | argv++; | 314 | argv++; |
| 315 | if (cmd < 2) | 315 | if (cmd < 2) |
| 316 | return iprule_modify((cmd == 0) ? RTM_NEWRULE : RTM_DELRULE, argv); | 316 | return iprule_modify((cmd == 0) ? RTM_NEWRULE : RTM_DELRULE, argv); |
diff --git a/networking/libiproute/iptunnel.c b/networking/libiproute/iptunnel.c index 2b651b926..b54c3c53f 100644 --- a/networking/libiproute/iptunnel.c +++ b/networking/libiproute/iptunnel.c | |||
| @@ -561,9 +561,9 @@ int FAST_FUNC do_iptunnel(char **argv) | |||
| 561 | enum { ARG_add = 0, ARG_change, ARG_del, ARG_show, ARG_list, ARG_lst }; | 561 | enum { ARG_add = 0, ARG_change, ARG_del, ARG_show, ARG_list, ARG_lst }; |
| 562 | 562 | ||
| 563 | if (*argv) { | 563 | if (*argv) { |
| 564 | smalluint key = index_in_substrings(keywords, *argv); | 564 | int key = index_in_substrings(keywords, *argv); |
| 565 | if (key > 5) | 565 | if (key < 0) |
| 566 | bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); | 566 | invarg(*argv, applet_name); |
| 567 | argv++; | 567 | argv++; |
| 568 | if (key == ARG_add) | 568 | if (key == ARG_add) |
| 569 | return do_add(SIOCADDTUNNEL, argv); | 569 | return do_add(SIOCADDTUNNEL, argv); |
diff --git a/networking/nc.c b/networking/nc.c index 126bec906..2f9e17466 100644 --- a/networking/nc.c +++ b/networking/nc.c | |||
| @@ -261,7 +261,7 @@ int nc_main(int argc, char **argv) | |||
| 261 | if (nread < 1) { | 261 | if (nread < 1) { |
| 262 | /* Close outgoing half-connection so they get EOF, | 262 | /* Close outgoing half-connection so they get EOF, |
| 263 | * but leave incoming alone so we can see response */ | 263 | * but leave incoming alone so we can see response */ |
| 264 | shutdown(cfd, 1); | 264 | shutdown(cfd, SHUT_WR); |
| 265 | FD_CLR(STDIN_FILENO, &readfds); | 265 | FD_CLR(STDIN_FILENO, &readfds); |
| 266 | } | 266 | } |
| 267 | ofd = cfd; | 267 | ofd = cfd; |
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 00ba6f114..b9eff3da4 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
| @@ -48,6 +48,12 @@ | |||
| 48 | * - TCP connects from wrong ip/ports (if peer ip:port is specified | 48 | * - TCP connects from wrong ip/ports (if peer ip:port is specified |
| 49 | * on the command line, but accept() says that it came from different addr) | 49 | * on the command line, but accept() says that it came from different addr) |
| 50 | * are closed, but we don't exit - we continue to listen/accept. | 50 | * are closed, but we don't exit - we continue to listen/accept. |
| 51 | * Since bbox 1.22: | ||
| 52 | * - nc exits when _both_ stdin and network are closed. | ||
| 53 | * This makes these two commands: | ||
| 54 | * echo "Yes" | nc 127.0.0.1 1234 | ||
| 55 | * echo "no" | nc -lp 1234 | ||
| 56 | * exchange their data _and exit_ instead of being stuck. | ||
| 51 | */ | 57 | */ |
| 52 | 58 | ||
| 53 | /* done in nc.c: #include "libbb.h" */ | 59 | /* done in nc.c: #include "libbb.h" */ |
| @@ -134,8 +140,6 @@ struct globals { | |||
| 134 | 140 | ||
| 135 | jmp_buf jbuf; /* timer crud */ | 141 | jmp_buf jbuf; /* timer crud */ |
| 136 | 142 | ||
| 137 | fd_set ding1; /* for select loop */ | ||
| 138 | fd_set ding2; | ||
| 139 | char bigbuf_in[BIGSIZ]; /* data buffers */ | 143 | char bigbuf_in[BIGSIZ]; /* data buffers */ |
| 140 | char bigbuf_net[BIGSIZ]; | 144 | char bigbuf_net[BIGSIZ]; |
| 141 | }; | 145 | }; |
| @@ -147,8 +151,6 @@ struct globals { | |||
| 147 | #define themaddr (G.themaddr ) | 151 | #define themaddr (G.themaddr ) |
| 148 | #define remend (G.remend ) | 152 | #define remend (G.remend ) |
| 149 | #define jbuf (G.jbuf ) | 153 | #define jbuf (G.jbuf ) |
| 150 | #define ding1 (G.ding1 ) | ||
| 151 | #define ding2 (G.ding2 ) | ||
| 152 | #define bigbuf_in (G.bigbuf_in ) | 154 | #define bigbuf_in (G.bigbuf_in ) |
| 153 | #define bigbuf_net (G.bigbuf_net) | 155 | #define bigbuf_net (G.bigbuf_net) |
| 154 | #define o_verbose (G.o_verbose ) | 156 | #define o_verbose (G.o_verbose ) |
| @@ -590,26 +592,27 @@ static int readwrite(void) | |||
| 590 | unsigned rzleft; | 592 | unsigned rzleft; |
| 591 | unsigned rnleft; | 593 | unsigned rnleft; |
| 592 | unsigned netretry; /* net-read retry counter */ | 594 | unsigned netretry; /* net-read retry counter */ |
| 593 | unsigned wretry; /* net-write sanity counter */ | 595 | unsigned fds_open; |
| 594 | unsigned wfirst; /* one-shot flag to skip first net read */ | ||
| 595 | 596 | ||
| 596 | /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to | 597 | /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to |
| 597 | either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */ | 598 | either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */ |
| 598 | FD_SET(netfd, &ding1); /* global: the net is open */ | 599 | fd_set ding1; /* for select loop */ |
| 600 | fd_set ding2; | ||
| 601 | FD_ZERO(&ding1); | ||
| 602 | FD_SET(netfd, &ding1); | ||
| 603 | FD_SET(STDIN_FILENO, &ding1); | ||
| 604 | fds_open = 2; | ||
| 605 | |||
| 599 | netretry = 2; | 606 | netretry = 2; |
| 600 | wfirst = 0; | ||
| 601 | rzleft = rnleft = 0; | 607 | rzleft = rnleft = 0; |
| 602 | if (o_interval) | 608 | if (o_interval) |
| 603 | sleep(o_interval); /* pause *before* sending stuff, too */ | 609 | sleep(o_interval); /* pause *before* sending stuff, too */ |
| 604 | 610 | ||
| 605 | errno = 0; /* clear from sleep, close, whatever */ | ||
| 606 | /* and now the big ol' select shoveling loop ... */ | 611 | /* and now the big ol' select shoveling loop ... */ |
| 607 | while (FD_ISSET(netfd, &ding1)) { /* i.e. till the *net* closes! */ | 612 | /* nc 1.10 has "while (FD_ISSET(netfd)" here */ |
| 608 | wretry = 8200; /* more than we'll ever hafta write */ | 613 | while (fds_open) { |
| 609 | if (wfirst) { /* any saved stdin buffer? */ | 614 | unsigned wretry = 8200; /* net-write sanity counter */ |
| 610 | wfirst = 0; /* clear flag for the duration */ | 615 | |
| 611 | goto shovel; /* and go handle it first */ | ||
| 612 | } | ||
| 613 | ding2 = ding1; /* FD_COPY ain't portable... */ | 616 | ding2 = ding1; /* FD_COPY ain't portable... */ |
| 614 | /* some systems, notably linux, crap into their select timers on return, so | 617 | /* some systems, notably linux, crap into their select timers on return, so |
| 615 | we create a expendable copy and give *that* to select. */ | 618 | we create a expendable copy and give *that* to select. */ |
| @@ -629,13 +632,14 @@ static int readwrite(void) | |||
| 629 | /* if we have a timeout AND stdin is closed AND we haven't heard anything | 632 | /* if we have a timeout AND stdin is closed AND we haven't heard anything |
| 630 | from the net during that time, assume it's dead and close it too. */ | 633 | from the net during that time, assume it's dead and close it too. */ |
| 631 | if (rr == 0) { | 634 | if (rr == 0) { |
| 632 | if (!FD_ISSET(STDIN_FILENO, &ding1)) | 635 | if (!FD_ISSET(STDIN_FILENO, &ding1)) { |
| 633 | netretry--; /* we actually try a coupla times. */ | 636 | netretry--; /* we actually try a coupla times. */ |
| 634 | if (!netretry) { | 637 | if (!netretry) { |
| 635 | if (o_verbose > 1) /* normally we don't care */ | 638 | if (o_verbose > 1) /* normally we don't care */ |
| 636 | fprintf(stderr, "net timeout\n"); | 639 | fprintf(stderr, "net timeout\n"); |
| 637 | close(netfd); | 640 | /*close(netfd); - redundant, exit will do it */ |
| 638 | return 0; /* not an error! */ | 641 | return 0; /* not an error! */ |
| 642 | } | ||
| 639 | } | 643 | } |
| 640 | } /* select timeout */ | 644 | } /* select timeout */ |
| 641 | /* xxx: should we check the exception fds too? The read fds seem to give | 645 | /* xxx: should we check the exception fds too? The read fds seem to give |
| @@ -649,7 +653,8 @@ static int readwrite(void) | |||
| 649 | /* nc 1.10 doesn't do this */ | 653 | /* nc 1.10 doesn't do this */ |
| 650 | bb_perror_msg("net read"); | 654 | bb_perror_msg("net read"); |
| 651 | } | 655 | } |
| 652 | FD_CLR(netfd, &ding1); /* net closed, we'll finish up... */ | 656 | FD_CLR(netfd, &ding1); /* net closed */ |
| 657 | fds_open--; | ||
| 653 | rzleft = 0; /* can't write anymore: broken pipe */ | 658 | rzleft = 0; /* can't write anymore: broken pipe */ |
| 654 | } else { | 659 | } else { |
| 655 | rnleft = rr; | 660 | rnleft = rr; |
| @@ -669,11 +674,12 @@ Debug("got %d from the net, errno %d", rr, errno); | |||
| 669 | /* Considered making reads here smaller for UDP mode, but 8192-byte | 674 | /* Considered making reads here smaller for UDP mode, but 8192-byte |
| 670 | mobygrams are kinda fun and exercise the reassembler. */ | 675 | mobygrams are kinda fun and exercise the reassembler. */ |
| 671 | if (rr <= 0) { /* at end, or fukt, or ... */ | 676 | if (rr <= 0) { /* at end, or fukt, or ... */ |
| 672 | FD_CLR(STDIN_FILENO, &ding1); /* disable and close stdin */ | 677 | FD_CLR(STDIN_FILENO, &ding1); /* disable stdin */ |
| 673 | close(STDIN_FILENO); | 678 | /*close(STDIN_FILENO); - not really necessary */ |
| 674 | // Does it make sense to shutdown(net_fd, SHUT_WR) | 679 | /* Let peer know we have no more data */ |
| 675 | // to let other side know that we won't write anything anymore? | 680 | /* nc 1.10 doesn't do this: */ |
| 676 | // (and what about keeping compat if we do that?) | 681 | shutdown(netfd, SHUT_WR); |
| 682 | fds_open--; | ||
| 677 | } else { | 683 | } else { |
| 678 | rzleft = rr; | 684 | rzleft = rr; |
| 679 | zp = bigbuf_in; | 685 | zp = bigbuf_in; |
| @@ -684,24 +690,14 @@ Debug("got %d from the net, errno %d", rr, errno); | |||
| 684 | Geez, why does this look an awful lot like the big loop in "rsh"? ... | 690 | Geez, why does this look an awful lot like the big loop in "rsh"? ... |
| 685 | not sure if the order of this matters, but write net -> stdout first. */ | 691 | not sure if the order of this matters, but write net -> stdout first. */ |
| 686 | 692 | ||
| 687 | /* sanity check. Works because they're both unsigned... */ | ||
| 688 | if ((rzleft > 8200) || (rnleft > 8200)) { | ||
| 689 | holler_error("bogus buffers: %u, %u", rzleft, rnleft); | ||
| 690 | rzleft = rnleft = 0; | ||
| 691 | } | ||
| 692 | /* net write retries sometimes happen on UDP connections */ | ||
| 693 | if (!wretry) { /* is something hung? */ | ||
| 694 | holler_error("too many output retries"); | ||
| 695 | return 1; | ||
| 696 | } | ||
| 697 | if (rnleft) { | 693 | if (rnleft) { |
| 698 | rr = write(STDOUT_FILENO, np, rnleft); | 694 | rr = write(STDOUT_FILENO, np, rnleft); |
| 699 | if (rr > 0) { | 695 | if (rr > 0) { |
| 700 | if (o_ofile) /* log the stdout */ | 696 | if (o_ofile) /* log the stdout */ |
| 701 | oprint('<', (unsigned char *)np, rr); | 697 | oprint('<', (unsigned char *)np, rr); |
| 702 | np += rr; /* fix up ptrs and whatnot */ | 698 | np += rr; |
| 703 | rnleft -= rr; /* will get sanity-checked above */ | 699 | rnleft -= rr; |
| 704 | wrote_out += rr; /* global count */ | 700 | wrote_out += rr; /* global count */ |
| 705 | } | 701 | } |
| 706 | Debug("wrote %d to stdout, errno %d", rr, errno); | 702 | Debug("wrote %d to stdout, errno %d", rr, errno); |
| 707 | } /* rnleft */ | 703 | } /* rnleft */ |
| @@ -716,20 +712,24 @@ Debug("wrote %d to stdout, errno %d", rr, errno); | |||
| 716 | oprint('>', (unsigned char *)zp, rr); | 712 | oprint('>', (unsigned char *)zp, rr); |
| 717 | zp += rr; | 713 | zp += rr; |
| 718 | rzleft -= rr; | 714 | rzleft -= rr; |
| 719 | wrote_net += rr; /* global count */ | 715 | wrote_net += rr; /* global count */ |
| 720 | } | 716 | } |
| 721 | Debug("wrote %d to net, errno %d", rr, errno); | 717 | Debug("wrote %d to net, errno %d", rr, errno); |
| 722 | } /* rzleft */ | 718 | } /* rzleft */ |
| 723 | if (o_interval) { /* cycle between slow lines, or ... */ | 719 | if (o_interval) { /* cycle between slow lines, or ... */ |
| 724 | sleep(o_interval); | 720 | sleep(o_interval); |
| 725 | errno = 0; /* clear from sleep */ | ||
| 726 | continue; /* ...with hairy select loop... */ | 721 | continue; /* ...with hairy select loop... */ |
| 727 | } | 722 | } |
| 728 | if ((rzleft) || (rnleft)) { /* shovel that shit till they ain't */ | 723 | if (rzleft || rnleft) { /* shovel that shit till they ain't */ |
| 729 | wretry--; /* none left, and get another load */ | 724 | wretry--; /* none left, and get another load */ |
| 725 | /* net write retries sometimes happen on UDP connections */ | ||
| 726 | if (!wretry) { /* is something hung? */ | ||
| 727 | holler_error("too many output retries"); | ||
| 728 | return 1; | ||
| 729 | } | ||
| 730 | goto shovel; | 730 | goto shovel; |
| 731 | } | 731 | } |
| 732 | } /* while ding1:netfd is open */ | 732 | } /* while (fds_open) */ |
| 733 | 733 | ||
| 734 | /* XXX: maybe want a more graceful shutdown() here, or screw around with | 734 | /* XXX: maybe want a more graceful shutdown() here, or screw around with |
| 735 | linger times?? I suspect that I don't need to since I'm always doing | 735 | linger times?? I suspect that I don't need to since I'm always doing |
| @@ -876,9 +876,8 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
| 876 | } | 876 | } |
| 877 | #endif | 877 | #endif |
| 878 | 878 | ||
| 879 | FD_SET(STDIN_FILENO, &ding1); /* stdin *is* initially open */ | ||
| 880 | if (proggie) { | 879 | if (proggie) { |
| 881 | close(0); /* won't need stdin */ | 880 | close(STDIN_FILENO); /* won't need stdin */ |
| 882 | option_mask32 &= ~OPT_o; /* -o with -e is meaningless! */ | 881 | option_mask32 &= ~OPT_o; /* -o with -e is meaningless! */ |
| 883 | } | 882 | } |
| 884 | #if ENABLE_NC_EXTRA | 883 | #if ENABLE_NC_EXTRA |
diff --git a/networking/nslookup.c b/networking/nslookup.c index f4fd407dd..dd4b1ffed 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c | |||
| @@ -138,6 +138,9 @@ static void set_default_dns(const char *server) | |||
| 138 | { | 138 | { |
| 139 | len_and_sockaddr *lsa; | 139 | len_and_sockaddr *lsa; |
| 140 | 140 | ||
| 141 | if (!server) | ||
| 142 | return; | ||
| 143 | |||
| 141 | /* NB: this works even with, say, "[::1]:5353"! :) */ | 144 | /* NB: this works even with, say, "[::1]:5353"! :) */ |
| 142 | lsa = xhost2sockaddr(server, 53); | 145 | lsa = xhost2sockaddr(server, 53); |
| 143 | 146 | ||
| @@ -181,9 +184,17 @@ int nslookup_main(int argc, char **argv) | |||
| 181 | /* (but it also says "may be enabled in /etc/resolv.conf") */ | 184 | /* (but it also says "may be enabled in /etc/resolv.conf") */ |
| 182 | /*_res.options |= RES_USE_INET6;*/ | 185 | /*_res.options |= RES_USE_INET6;*/ |
| 183 | 186 | ||
| 184 | if (argv[2]) | 187 | set_default_dns(argv[2]); |
| 185 | set_default_dns(argv[2]); | ||
| 186 | 188 | ||
| 187 | server_print(); | 189 | server_print(); |
| 190 | |||
| 191 | /* getaddrinfo and friends are free to request a resolver | ||
| 192 | * reinitialization. Just in case, set_default_dns() again | ||
| 193 | * after getaddrinfo (in server_print). This reportedly helps | ||
| 194 | * with bug 675 "nslookup does not properly use second argument" | ||
| 195 | * at least on Debian Wheezy and Openwrt AA (eglibc based). | ||
| 196 | */ | ||
| 197 | set_default_dns(argv[2]); | ||
| 198 | |||
| 188 | return print_host(argv[1], "Name:"); | 199 | return print_host(argv[1], "Name:"); |
| 189 | } | 200 | } |
diff --git a/networking/ntpd.c b/networking/ntpd.c index 0f4319ef2..99817e83b 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
| @@ -95,6 +95,7 @@ | |||
| 95 | #define RETRY_INTERVAL 5 /* on error, retry in N secs */ | 95 | #define RETRY_INTERVAL 5 /* on error, retry in N secs */ |
| 96 | #define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */ | 96 | #define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */ |
| 97 | #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ | 97 | #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ |
| 98 | #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this */ | ||
| 98 | 99 | ||
| 99 | /* Clock discipline parameters and constants */ | 100 | /* Clock discipline parameters and constants */ |
| 100 | 101 | ||
| @@ -227,8 +228,8 @@ typedef struct { | |||
| 227 | uint8_t lastpkt_status; | 228 | uint8_t lastpkt_status; |
| 228 | uint8_t lastpkt_stratum; | 229 | uint8_t lastpkt_stratum; |
| 229 | uint8_t reachable_bits; | 230 | uint8_t reachable_bits; |
| 230 | /* when to send new query (if p_fd == -1) | 231 | /* when to send new query (if p_fd == -1) |
| 231 | * or when receive times out (if p_fd >= 0): */ | 232 | * or when receive times out (if p_fd >= 0): */ |
| 232 | double next_action_time; | 233 | double next_action_time; |
| 233 | double p_xmttime; | 234 | double p_xmttime; |
| 234 | double lastpkt_recv_time; | 235 | double lastpkt_recv_time; |
| @@ -804,22 +805,34 @@ send_query_to_peer(peer_t *p) | |||
| 804 | p->p_xmt_msg.m_xmttime.fractionl = random(); | 805 | p->p_xmt_msg.m_xmttime.fractionl = random(); |
| 805 | p->p_xmttime = gettime1900d(); | 806 | p->p_xmttime = gettime1900d(); |
| 806 | 807 | ||
| 808 | /* Were doing it only if sendto worked, but | ||
| 809 | * loss of sync detection needs reachable_bits updated | ||
| 810 | * even if sending fails *locally*: | ||
| 811 | * "network is unreachable" because cable was pulled? | ||
| 812 | * We still need to declare "unsync" if this condition persists. | ||
| 813 | */ | ||
| 814 | p->reachable_bits <<= 1; | ||
| 815 | |||
| 807 | if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len, | 816 | if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len, |
| 808 | &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1 | 817 | &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1 |
| 809 | ) { | 818 | ) { |
| 810 | close(p->p_fd); | 819 | close(p->p_fd); |
| 811 | p->p_fd = -1; | 820 | p->p_fd = -1; |
| 821 | /* | ||
| 822 | * We know that we sent nothing. | ||
| 823 | * We can retry *soon* without fearing | ||
| 824 | * that we are flooding the peer. | ||
| 825 | */ | ||
| 812 | set_next(p, RETRY_INTERVAL); | 826 | set_next(p, RETRY_INTERVAL); |
| 813 | return; | 827 | return; |
| 814 | } | 828 | } |
| 815 | 829 | ||
| 816 | p->reachable_bits <<= 1; | ||
| 817 | set_next(p, RESPONSE_INTERVAL); | 830 | set_next(p, RESPONSE_INTERVAL); |
| 818 | } | 831 | } |
| 819 | 832 | ||
| 820 | 833 | ||
| 821 | /* Note that there is no provision to prevent several run_scripts | 834 | /* Note that there is no provision to prevent several run_scripts |
| 822 | * to be done in quick succession. In fact, it happens rather often | 835 | * to be started in quick succession. In fact, it happens rather often |
| 823 | * if initial syncronization results in a step. | 836 | * if initial syncronization results in a step. |
| 824 | * You will see "step" and then "stratum" script runs, sometimes | 837 | * You will see "step" and then "stratum" script runs, sometimes |
| 825 | * as close as only 0.002 seconds apart. | 838 | * as close as only 0.002 seconds apart. |
| @@ -830,6 +843,8 @@ static void run_script(const char *action, double offset) | |||
| 830 | char *argv[3]; | 843 | char *argv[3]; |
| 831 | char *env1, *env2, *env3, *env4; | 844 | char *env1, *env2, *env3, *env4; |
| 832 | 845 | ||
| 846 | G.last_script_run = G.cur_time; | ||
| 847 | |||
| 833 | if (!G.script_name) | 848 | if (!G.script_name) |
| 834 | return; | 849 | return; |
| 835 | 850 | ||
| @@ -866,8 +881,6 @@ static void run_script(const char *action, double offset) | |||
| 866 | free(env2); | 881 | free(env2); |
| 867 | free(env3); | 882 | free(env3); |
| 868 | free(env4); | 883 | free(env4); |
| 869 | |||
| 870 | G.last_script_run = G.cur_time; | ||
| 871 | } | 884 | } |
| 872 | 885 | ||
| 873 | static NOINLINE void | 886 | static NOINLINE void |
| @@ -1616,6 +1629,7 @@ recv_and_process_peer_pkt(peer_t *p) | |||
| 1616 | ssize_t size; | 1629 | ssize_t size; |
| 1617 | msg_t msg; | 1630 | msg_t msg; |
| 1618 | double T1, T2, T3, T4; | 1631 | double T1, T2, T3, T4; |
| 1632 | double dv; | ||
| 1619 | unsigned interval; | 1633 | unsigned interval; |
| 1620 | datapoint_t *datapoint; | 1634 | datapoint_t *datapoint; |
| 1621 | peer_t *q; | 1635 | peer_t *q; |
| @@ -1665,9 +1679,8 @@ recv_and_process_peer_pkt(peer_t *p) | |||
| 1665 | // TODO: stratum 0 responses may have commands in 32-bit m_refid field: | 1679 | // TODO: stratum 0 responses may have commands in 32-bit m_refid field: |
| 1666 | // "DENY", "RSTR" - peer does not like us at all | 1680 | // "DENY", "RSTR" - peer does not like us at all |
| 1667 | // "RATE" - peer is overloaded, reduce polling freq | 1681 | // "RATE" - peer is overloaded, reduce polling freq |
| 1668 | interval = poll_interval(0); | 1682 | bb_error_msg("reply from %s: peer is unsynced", p->p_dotted); |
| 1669 | bb_error_msg("reply from %s: peer is unsynced, next query in %us", p->p_dotted, interval); | 1683 | goto pick_normal_interval; |
| 1670 | goto set_next_and_ret; | ||
| 1671 | } | 1684 | } |
| 1672 | 1685 | ||
| 1673 | // /* Verify valid root distance */ | 1686 | // /* Verify valid root distance */ |
| @@ -1700,21 +1713,31 @@ recv_and_process_peer_pkt(peer_t *p) | |||
| 1700 | T4 = G.cur_time; | 1713 | T4 = G.cur_time; |
| 1701 | 1714 | ||
| 1702 | p->lastpkt_recv_time = T4; | 1715 | p->lastpkt_recv_time = T4; |
| 1703 | |||
| 1704 | VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); | 1716 | VERB5 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); |
| 1705 | p->datapoint_idx = p->reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0; | 1717 | |
| 1706 | datapoint = &p->filter_datapoint[p->datapoint_idx]; | ||
| 1707 | datapoint->d_recv_time = T4; | ||
| 1708 | datapoint->d_offset = ((T2 - T1) + (T3 - T4)) / 2; | ||
| 1709 | /* The delay calculation is a special case. In cases where the | 1718 | /* The delay calculation is a special case. In cases where the |
| 1710 | * server and client clocks are running at different rates and | 1719 | * server and client clocks are running at different rates and |
| 1711 | * with very fast networks, the delay can appear negative. In | 1720 | * with very fast networks, the delay can appear negative. In |
| 1712 | * order to avoid violating the Principle of Least Astonishment, | 1721 | * order to avoid violating the Principle of Least Astonishment, |
| 1713 | * the delay is clamped not less than the system precision. | 1722 | * the delay is clamped not less than the system precision. |
| 1714 | */ | 1723 | */ |
| 1724 | dv = p->lastpkt_delay; | ||
| 1715 | p->lastpkt_delay = (T4 - T1) - (T3 - T2); | 1725 | p->lastpkt_delay = (T4 - T1) - (T3 - T2); |
| 1716 | if (p->lastpkt_delay < G_precision_sec) | 1726 | if (p->lastpkt_delay < G_precision_sec) |
| 1717 | p->lastpkt_delay = G_precision_sec; | 1727 | p->lastpkt_delay = G_precision_sec; |
| 1728 | /* | ||
| 1729 | * If this packet's delay is much bigger than the last one, | ||
| 1730 | * it's better to just ignore it than use its much less precise value. | ||
| 1731 | */ | ||
| 1732 | if (p->reachable_bits && p->lastpkt_delay > dv * BAD_DELAY_GROWTH) { | ||
| 1733 | bb_error_msg("reply from %s: delay %f is too high, ignoring", p->p_dotted, p->lastpkt_delay); | ||
| 1734 | goto pick_normal_interval; | ||
| 1735 | } | ||
| 1736 | |||
| 1737 | p->datapoint_idx = p->reachable_bits ? (p->datapoint_idx + 1) % NUM_DATAPOINTS : 0; | ||
| 1738 | datapoint = &p->filter_datapoint[p->datapoint_idx]; | ||
| 1739 | datapoint->d_recv_time = T4; | ||
| 1740 | datapoint->d_offset = ((T2 - T1) + (T3 - T4)) / 2; | ||
| 1718 | datapoint->d_dispersion = LOG2D(msg.m_precision_exp) + G_precision_sec; | 1741 | datapoint->d_dispersion = LOG2D(msg.m_precision_exp) + G_precision_sec; |
| 1719 | if (!p->reachable_bits) { | 1742 | if (!p->reachable_bits) { |
| 1720 | /* 1st datapoint ever - replicate offset in every element */ | 1743 | /* 1st datapoint ever - replicate offset in every element */ |
| @@ -1811,6 +1834,7 @@ recv_and_process_peer_pkt(peer_t *p) | |||
| 1811 | } | 1834 | } |
| 1812 | 1835 | ||
| 1813 | /* Decide when to send new query for this peer */ | 1836 | /* Decide when to send new query for this peer */ |
| 1837 | pick_normal_interval: | ||
| 1814 | interval = poll_interval(0); | 1838 | interval = poll_interval(0); |
| 1815 | 1839 | ||
| 1816 | set_next_and_ret: | 1840 | set_next_and_ret: |
| @@ -2159,12 +2183,14 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 2159 | did_poll: | 2183 | did_poll: |
| 2160 | gettime1900d(); /* sets G.cur_time */ | 2184 | gettime1900d(); /* sets G.cur_time */ |
| 2161 | if (nfds <= 0) { | 2185 | if (nfds <= 0) { |
| 2162 | if (G.script_name && G.cur_time - G.last_script_run > 11*60) { | 2186 | if (!bb_got_signal /* poll wasn't interrupted by a signal */ |
| 2187 | && G.cur_time - G.last_script_run > 11*60 | ||
| 2188 | ) { | ||
| 2163 | /* Useful for updating battery-backed RTC and such */ | 2189 | /* Useful for updating battery-backed RTC and such */ |
| 2164 | run_script("periodic", G.last_update_offset); | 2190 | run_script("periodic", G.last_update_offset); |
| 2165 | gettime1900d(); /* sets G.cur_time */ | 2191 | gettime1900d(); /* sets G.cur_time */ |
| 2166 | } | 2192 | } |
| 2167 | continue; | 2193 | goto check_unsync; |
| 2168 | } | 2194 | } |
| 2169 | 2195 | ||
| 2170 | /* Process any received packets */ | 2196 | /* Process any received packets */ |
| @@ -2195,6 +2221,21 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 2195 | gettime1900d(); /* sets G.cur_time */ | 2221 | gettime1900d(); /* sets G.cur_time */ |
| 2196 | } | 2222 | } |
| 2197 | } | 2223 | } |
| 2224 | |||
| 2225 | check_unsync: | ||
| 2226 | if (G.ntp_peers && G.stratum != MAXSTRAT) { | ||
| 2227 | for (item = G.ntp_peers; item != NULL; item = item->link) { | ||
| 2228 | peer_t *p = (peer_t *) item->data; | ||
| 2229 | if (p->reachable_bits) | ||
| 2230 | goto have_reachable_peer; | ||
| 2231 | } | ||
| 2232 | /* No peer responded for last 8 packets, panic */ | ||
| 2233 | G.polladj_count = 0; | ||
| 2234 | G.poll_exp = MINPOLL; | ||
| 2235 | G.stratum = MAXSTRAT; | ||
| 2236 | run_script("unsync", 0.0); | ||
| 2237 | have_reachable_peer: ; | ||
| 2238 | } | ||
| 2198 | } /* while (!bb_got_signal) */ | 2239 | } /* while (!bb_got_signal) */ |
| 2199 | 2240 | ||
| 2200 | remove_pidfile(CONFIG_PID_FILE_PATH "/ntpd.pid"); | 2241 | remove_pidfile(CONFIG_PID_FILE_PATH "/ntpd.pid"); |
diff --git a/networking/ping.c b/networking/ping.c index e919b3a09..f27e2143d 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
| @@ -149,8 +149,33 @@ enum { | |||
| 149 | MAX_DUP_CHK = (8 * 128), | 149 | MAX_DUP_CHK = (8 * 128), |
| 150 | MAXWAIT = 10, | 150 | MAXWAIT = 10, |
| 151 | PINGINTERVAL = 1, /* 1 second */ | 151 | PINGINTERVAL = 1, /* 1 second */ |
| 152 | pingsock = 0, | ||
| 152 | }; | 153 | }; |
| 153 | 154 | ||
| 155 | static void | ||
| 156 | #if ENABLE_PING6 | ||
| 157 | create_icmp_socket(len_and_sockaddr *lsa) | ||
| 158 | #else | ||
| 159 | create_icmp_socket(void) | ||
| 160 | #define create_icmp_socket(lsa) create_icmp_socket() | ||
| 161 | #endif | ||
| 162 | { | ||
| 163 | int sock; | ||
| 164 | #if ENABLE_PING6 | ||
| 165 | if (lsa->u.sa.sa_family == AF_INET6) | ||
| 166 | sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); | ||
| 167 | else | ||
| 168 | #endif | ||
| 169 | sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */ | ||
| 170 | if (sock < 0) { | ||
| 171 | if (errno == EPERM) | ||
| 172 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | ||
| 173 | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); | ||
| 174 | } | ||
| 175 | |||
| 176 | xmove_fd(sock, pingsock); | ||
| 177 | } | ||
| 178 | |||
| 154 | #if !ENABLE_FEATURE_FANCY_PING | 179 | #if !ENABLE_FEATURE_FANCY_PING |
| 155 | 180 | ||
| 156 | /* Simple version */ | 181 | /* Simple version */ |
| @@ -171,12 +196,10 @@ static void noresp(int ign UNUSED_PARAM) | |||
| 171 | static void ping4(len_and_sockaddr *lsa) | 196 | static void ping4(len_and_sockaddr *lsa) |
| 172 | { | 197 | { |
| 173 | struct icmp *pkt; | 198 | struct icmp *pkt; |
| 174 | int pingsock, c; | 199 | int c; |
| 175 | |||
| 176 | pingsock = create_icmp_socket(); | ||
| 177 | 200 | ||
| 178 | pkt = (struct icmp *) G.packet; | 201 | pkt = (struct icmp *) G.packet; |
| 179 | memset(pkt, 0, sizeof(G.packet)); | 202 | /*memset(pkt, 0, sizeof(G.packet)); already is */ |
| 180 | pkt->icmp_type = ICMP_ECHO; | 203 | pkt->icmp_type = ICMP_ECHO; |
| 181 | pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); | 204 | pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); |
| 182 | 205 | ||
| @@ -184,11 +207,15 @@ static void ping4(len_and_sockaddr *lsa) | |||
| 184 | 207 | ||
| 185 | /* listen for replies */ | 208 | /* listen for replies */ |
| 186 | while (1) { | 209 | while (1) { |
| 210 | #if 0 | ||
| 187 | struct sockaddr_in from; | 211 | struct sockaddr_in from; |
| 188 | socklen_t fromlen = sizeof(from); | 212 | socklen_t fromlen = sizeof(from); |
| 189 | 213 | ||
| 190 | c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, | 214 | c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, |
| 191 | (struct sockaddr *) &from, &fromlen); | 215 | (struct sockaddr *) &from, &fromlen); |
| 216 | #else | ||
| 217 | c = recv(pingsock, G.packet, sizeof(G.packet), 0); | ||
| 218 | #endif | ||
| 192 | if (c < 0) { | 219 | if (c < 0) { |
| 193 | if (errno != EINTR) | 220 | if (errno != EINTR) |
| 194 | bb_perror_msg("recvfrom"); | 221 | bb_perror_msg("recvfrom"); |
| @@ -210,13 +237,11 @@ static void ping4(len_and_sockaddr *lsa) | |||
| 210 | static void ping6(len_and_sockaddr *lsa) | 237 | static void ping6(len_and_sockaddr *lsa) |
| 211 | { | 238 | { |
| 212 | struct icmp6_hdr *pkt; | 239 | struct icmp6_hdr *pkt; |
| 213 | int pingsock, c; | 240 | int c; |
| 214 | int sockopt; | 241 | int sockopt; |
| 215 | 242 | ||
| 216 | pingsock = create_icmp6_socket(); | ||
| 217 | |||
| 218 | pkt = (struct icmp6_hdr *) G.packet; | 243 | pkt = (struct icmp6_hdr *) G.packet; |
| 219 | memset(pkt, 0, sizeof(G.packet)); | 244 | /*memset(pkt, 0, sizeof(G.packet)); already is */ |
| 220 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; | 245 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; |
| 221 | 246 | ||
| 222 | sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); | 247 | sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); |
| @@ -226,18 +251,21 @@ static void ping6(len_and_sockaddr *lsa) | |||
| 226 | 251 | ||
| 227 | /* listen for replies */ | 252 | /* listen for replies */ |
| 228 | while (1) { | 253 | while (1) { |
| 254 | #if 0 | ||
| 229 | struct sockaddr_in6 from; | 255 | struct sockaddr_in6 from; |
| 230 | socklen_t fromlen = sizeof(from); | 256 | socklen_t fromlen = sizeof(from); |
| 231 | 257 | ||
| 232 | c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, | 258 | c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, |
| 233 | (struct sockaddr *) &from, &fromlen); | 259 | (struct sockaddr *) &from, &fromlen); |
| 260 | #else | ||
| 261 | c = recv(pingsock, G.packet, sizeof(G.packet), 0); | ||
| 262 | #endif | ||
| 234 | if (c < 0) { | 263 | if (c < 0) { |
| 235 | if (errno != EINTR) | 264 | if (errno != EINTR) |
| 236 | bb_perror_msg("recvfrom"); | 265 | bb_perror_msg("recvfrom"); |
| 237 | continue; | 266 | continue; |
| 238 | } | 267 | } |
| 239 | if (c >= ICMP_MINLEN) { /* icmp6_hdr */ | 268 | if (c >= ICMP_MINLEN) { /* icmp6_hdr */ |
| 240 | pkt = (struct icmp6_hdr *) G.packet; | ||
| 241 | if (pkt->icmp6_type == ICMP6_ECHO_REPLY) | 269 | if (pkt->icmp6_type == ICMP6_ECHO_REPLY) |
| 242 | break; | 270 | break; |
| 243 | } | 271 | } |
| @@ -285,6 +313,7 @@ static int common_ping_main(sa_family_t af, char **argv) | |||
| 285 | signal(SIGALRM, noresp); | 313 | signal(SIGALRM, noresp); |
| 286 | alarm(5); /* give the host 5000ms to respond */ | 314 | alarm(5); /* give the host 5000ms to respond */ |
| 287 | 315 | ||
| 316 | create_icmp_socket(lsa); | ||
| 288 | #if ENABLE_PING6 | 317 | #if ENABLE_PING6 |
| 289 | if (lsa->u.sa.sa_family == AF_INET6) | 318 | if (lsa->u.sa.sa_family == AF_INET6) |
| 290 | ping6(lsa); | 319 | ping6(lsa); |
| @@ -318,7 +347,6 @@ enum { | |||
| 318 | 347 | ||
| 319 | 348 | ||
| 320 | struct globals { | 349 | struct globals { |
| 321 | int pingsock; | ||
| 322 | int if_index; | 350 | int if_index; |
| 323 | char *str_I; | 351 | char *str_I; |
| 324 | len_and_sockaddr *source_lsa; | 352 | len_and_sockaddr *source_lsa; |
| @@ -344,10 +372,9 @@ struct globals { | |||
| 344 | struct sockaddr_in6 sin6; | 372 | struct sockaddr_in6 sin6; |
| 345 | #endif | 373 | #endif |
| 346 | } pingaddr; | 374 | } pingaddr; |
| 347 | char rcvd_tbl[MAX_DUP_CHK / 8]; | 375 | unsigned char rcvd_tbl[MAX_DUP_CHK / 8]; |
| 348 | } FIX_ALIASING; | 376 | } FIX_ALIASING; |
| 349 | #define G (*(struct globals*)&bb_common_bufsiz1) | 377 | #define G (*(struct globals*)&bb_common_bufsiz1) |
| 350 | #define pingsock (G.pingsock ) | ||
| 351 | #define if_index (G.if_index ) | 378 | #define if_index (G.if_index ) |
| 352 | #define source_lsa (G.source_lsa ) | 379 | #define source_lsa (G.source_lsa ) |
| 353 | #define str_I (G.str_I ) | 380 | #define str_I (G.str_I ) |
| @@ -369,20 +396,17 @@ void BUG_ping_globals_too_big(void); | |||
| 369 | #define INIT_G() do { \ | 396 | #define INIT_G() do { \ |
| 370 | if (sizeof(G) > COMMON_BUFSIZE) \ | 397 | if (sizeof(G) > COMMON_BUFSIZE) \ |
| 371 | BUG_ping_globals_too_big(); \ | 398 | BUG_ping_globals_too_big(); \ |
| 372 | pingsock = -1; \ | ||
| 373 | datalen = DEFDATALEN; \ | 399 | datalen = DEFDATALEN; \ |
| 374 | timeout = MAXWAIT; \ | 400 | timeout = MAXWAIT; \ |
| 375 | tmin = UINT_MAX; \ | 401 | tmin = UINT_MAX; \ |
| 376 | } while (0) | 402 | } while (0) |
| 377 | 403 | ||
| 378 | 404 | ||
| 379 | #define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ | 405 | #define BYTE(bit) rcvd_tbl[(bit)>>3] |
| 380 | #define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ | 406 | #define MASK(bit) (1 << ((bit) & 7)) |
| 381 | #define SET(bit) (A(bit) |= B(bit)) | 407 | #define SET(bit) (BYTE(bit) |= MASK(bit)) |
| 382 | #define CLR(bit) (A(bit) &= (~B(bit))) | 408 | #define CLR(bit) (BYTE(bit) &= (~MASK(bit))) |
| 383 | #define TST(bit) (A(bit) & B(bit)) | 409 | #define TST(bit) (BYTE(bit) & MASK(bit)) |
| 384 | |||
| 385 | /**************************************************************************/ | ||
| 386 | 410 | ||
| 387 | static void print_stats_and_exit(int junk) NORETURN; | 411 | static void print_stats_and_exit(int junk) NORETURN; |
| 388 | static void print_stats_and_exit(int junk UNUSED_PARAM) | 412 | static void print_stats_and_exit(int junk UNUSED_PARAM) |
| @@ -552,11 +576,10 @@ static void unpack_tail(int sz, uint32_t *tp, | |||
| 552 | const char *from_str, | 576 | const char *from_str, |
| 553 | uint16_t recv_seq, int ttl) | 577 | uint16_t recv_seq, int ttl) |
| 554 | { | 578 | { |
| 579 | unsigned char *b, m; | ||
| 555 | const char *dupmsg = " (DUP!)"; | 580 | const char *dupmsg = " (DUP!)"; |
| 556 | unsigned triptime = triptime; /* for gcc */ | 581 | unsigned triptime = triptime; /* for gcc */ |
| 557 | 582 | ||
| 558 | ++G.nreceived; | ||
| 559 | |||
| 560 | if (tp) { | 583 | if (tp) { |
| 561 | /* (int32_t) cast is for hypothetical 64-bit unsigned */ | 584 | /* (int32_t) cast is for hypothetical 64-bit unsigned */ |
| 562 | /* (doesn't hurt 32-bit real-world anyway) */ | 585 | /* (doesn't hurt 32-bit real-world anyway) */ |
| @@ -568,11 +591,15 @@ static void unpack_tail(int sz, uint32_t *tp, | |||
| 568 | tmax = triptime; | 591 | tmax = triptime; |
| 569 | } | 592 | } |
| 570 | 593 | ||
| 571 | if (TST(recv_seq % MAX_DUP_CHK)) { | 594 | b = &BYTE(recv_seq % MAX_DUP_CHK); |
| 595 | m = MASK(recv_seq % MAX_DUP_CHK); | ||
| 596 | /*if TST(recv_seq % MAX_DUP_CHK):*/ | ||
| 597 | if (*b & m) { | ||
| 572 | ++G.nrepeats; | 598 | ++G.nrepeats; |
| 573 | --G.nreceived; | ||
| 574 | } else { | 599 | } else { |
| 575 | SET(recv_seq % MAX_DUP_CHK); | 600 | /*SET(recv_seq % MAX_DUP_CHK):*/ |
| 601 | *b |= m; | ||
| 602 | ++G.nreceived; | ||
| 576 | dupmsg += 7; | 603 | dupmsg += 7; |
| 577 | } | 604 | } |
| 578 | 605 | ||
| @@ -655,7 +682,6 @@ static void ping4(len_and_sockaddr *lsa) | |||
| 655 | { | 682 | { |
| 656 | int sockopt; | 683 | int sockopt; |
| 657 | 684 | ||
| 658 | pingsock = create_icmp_socket(); | ||
| 659 | pingaddr.sin = lsa->u.sin; | 685 | pingaddr.sin = lsa->u.sin; |
| 660 | if (source_lsa) { | 686 | if (source_lsa) { |
| 661 | if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF, | 687 | if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF, |
| @@ -663,8 +689,6 @@ static void ping4(len_and_sockaddr *lsa) | |||
| 663 | bb_error_msg_and_die("can't set multicast source interface"); | 689 | bb_error_msg_and_die("can't set multicast source interface"); |
| 664 | xbind(pingsock, &source_lsa->u.sa, source_lsa->len); | 690 | xbind(pingsock, &source_lsa->u.sa, source_lsa->len); |
| 665 | } | 691 | } |
| 666 | if (str_I) | ||
| 667 | setsockopt_bindtodevice(pingsock, str_I); | ||
| 668 | 692 | ||
| 669 | /* enable broadcast pings */ | 693 | /* enable broadcast pings */ |
| 670 | setsockopt_broadcast(pingsock); | 694 | setsockopt_broadcast(pingsock); |
| @@ -713,13 +737,9 @@ static void ping6(len_and_sockaddr *lsa) | |||
| 713 | struct iovec iov; | 737 | struct iovec iov; |
| 714 | char control_buf[CMSG_SPACE(36)]; | 738 | char control_buf[CMSG_SPACE(36)]; |
| 715 | 739 | ||
| 716 | pingsock = create_icmp6_socket(); | ||
| 717 | pingaddr.sin6 = lsa->u.sin6; | 740 | pingaddr.sin6 = lsa->u.sin6; |
| 718 | /* untested whether "-I addr" really works for IPv6: */ | ||
| 719 | if (source_lsa) | 741 | if (source_lsa) |
| 720 | xbind(pingsock, &source_lsa->u.sa, source_lsa->len); | 742 | xbind(pingsock, &source_lsa->u.sa, source_lsa->len); |
| 721 | if (str_I) | ||
| 722 | setsockopt_bindtodevice(pingsock, str_I); | ||
| 723 | 743 | ||
| 724 | #ifdef ICMP6_FILTER | 744 | #ifdef ICMP6_FILTER |
| 725 | { | 745 | { |
| @@ -806,6 +826,11 @@ static void ping(len_and_sockaddr *lsa) | |||
| 806 | } | 826 | } |
| 807 | printf(": %d data bytes\n", datalen); | 827 | printf(": %d data bytes\n", datalen); |
| 808 | 828 | ||
| 829 | create_icmp_socket(lsa); | ||
| 830 | /* untested whether "-I addr" really works for IPv6: */ | ||
| 831 | if (str_I) | ||
| 832 | setsockopt_bindtodevice(pingsock, str_I); | ||
| 833 | |||
| 809 | G.sizeof_rcv_packet = datalen + MAXIPLEN + MAXICMPLEN; | 834 | G.sizeof_rcv_packet = datalen + MAXIPLEN + MAXICMPLEN; |
| 810 | G.rcv_packet = xzalloc(G.sizeof_rcv_packet); | 835 | G.rcv_packet = xzalloc(G.sizeof_rcv_packet); |
| 811 | #if ENABLE_PING6 | 836 | #if ENABLE_PING6 |
diff --git a/networking/tc.c b/networking/tc.c index f968707a9..b9a4d16cc 100644 --- a/networking/tc.c +++ b/networking/tc.c | |||
| @@ -65,7 +65,7 @@ struct globals { | |||
| 65 | } FIX_ALIASING; | 65 | } FIX_ALIASING; |
| 66 | #define G (*(struct globals*)&bb_common_bufsiz1) | 66 | #define G (*(struct globals*)&bb_common_bufsiz1) |
| 67 | struct BUG_G_too_big { | 67 | struct BUG_G_too_big { |
| 68 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; | 68 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; |
| 69 | }; | 69 | }; |
| 70 | #define filter_ifindex (G.filter_ifindex) | 70 | #define filter_ifindex (G.filter_ifindex) |
| 71 | #define filter_qdisc (G.filter_qdisc) | 71 | #define filter_qdisc (G.filter_qdisc) |
diff --git a/networking/telnet.c b/networking/telnet.c index 58a691916..a25579773 100644 --- a/networking/telnet.c +++ b/networking/telnet.c | |||
| @@ -125,12 +125,10 @@ static void subneg(byte c); | |||
| 125 | 125 | ||
| 126 | static void iac_flush(void) | 126 | static void iac_flush(void) |
| 127 | { | 127 | { |
| 128 | write(netfd, G.iacbuf, G.iaclen); | 128 | full_write(netfd, G.iacbuf, G.iaclen); |
| 129 | G.iaclen = 0; | 129 | G.iaclen = 0; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | #define write_str(fd, str) write(fd, str, sizeof(str) - 1) | ||
| 133 | |||
| 134 | static void doexit(int ev) NORETURN; | 132 | static void doexit(int ev) NORETURN; |
| 135 | static void doexit(int ev) | 133 | static void doexit(int ev) |
| 136 | { | 134 | { |
| @@ -145,7 +143,7 @@ static void con_escape(void) | |||
| 145 | if (bb_got_signal) /* came from line mode... go raw */ | 143 | if (bb_got_signal) /* came from line mode... go raw */ |
| 146 | rawmode(); | 144 | rawmode(); |
| 147 | 145 | ||
| 148 | write_str(1, "\r\nConsole escape. Commands are:\r\n\n" | 146 | full_write1_str("\r\nConsole escape. Commands are:\r\n\n" |
| 149 | " l go to line mode\r\n" | 147 | " l go to line mode\r\n" |
| 150 | " c go to character mode\r\n" | 148 | " c go to character mode\r\n" |
| 151 | " z suspend telnet\r\n" | 149 | " z suspend telnet\r\n" |
| @@ -176,7 +174,7 @@ static void con_escape(void) | |||
| 176 | doexit(EXIT_SUCCESS); | 174 | doexit(EXIT_SUCCESS); |
| 177 | } | 175 | } |
| 178 | 176 | ||
| 179 | write_str(1, "continuing...\r\n"); | 177 | full_write1_str("continuing...\r\n"); |
| 180 | 178 | ||
| 181 | if (bb_got_signal) | 179 | if (bb_got_signal) |
| 182 | cookmode(); | 180 | cookmode(); |
| @@ -383,10 +381,11 @@ static void put_iac_naws(byte c, int x, int y) | |||
| 383 | put_iac(SB); | 381 | put_iac(SB); |
| 384 | put_iac(c); | 382 | put_iac(c); |
| 385 | 383 | ||
| 386 | put_iac((x >> 8) & 0xff); | 384 | /* "... & 0xff" implicitly done below */ |
| 387 | put_iac(x & 0xff); | 385 | put_iac(x >> 8); |
| 388 | put_iac((y >> 8) & 0xff); | 386 | put_iac(x); |
| 389 | put_iac(y & 0xff); | 387 | put_iac(y >> 8); |
| 388 | put_iac(y); | ||
| 390 | 389 | ||
| 391 | put_iac(IAC); | 390 | put_iac(IAC); |
| 392 | put_iac(SE); | 391 | put_iac(SE); |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index ae0e0d306..11b7b1f06 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
| @@ -371,20 +371,23 @@ static NOINLINE void attach_option( | |||
| 371 | char *buffer, | 371 | char *buffer, |
| 372 | int length) | 372 | int length) |
| 373 | { | 373 | { |
| 374 | struct option_set *existing, *new, **curr; | 374 | struct option_set *existing; |
| 375 | char *allocated = NULL; | 375 | char *allocated; |
| 376 | 376 | ||
| 377 | existing = udhcp_find_option(*opt_list, optflag->code); | 377 | allocated = allocate_tempopt_if_needed(optflag, buffer, &length); |
| 378 | if (!existing) { | ||
| 379 | log2("Attaching option %02x to list", optflag->code); | ||
| 380 | allocated = allocate_tempopt_if_needed(optflag, buffer, &length); | ||
| 381 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 378 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 382 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { | 379 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { |
| 383 | /* reuse buffer and length for RFC1035-formatted string */ | 380 | /* reuse buffer and length for RFC1035-formatted string */ |
| 384 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); | 381 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); |
| 385 | } | 382 | } |
| 386 | #endif | 383 | #endif |
| 384 | |||
| 385 | existing = udhcp_find_option(*opt_list, optflag->code); | ||
| 386 | if (!existing) { | ||
| 387 | struct option_set *new, **curr; | ||
| 388 | |||
| 387 | /* make a new option */ | 389 | /* make a new option */ |
| 390 | log2("Attaching option %02x to list", optflag->code); | ||
| 388 | new = xmalloc(sizeof(*new)); | 391 | new = xmalloc(sizeof(*new)); |
| 389 | new->data = xmalloc(length + OPT_DATA); | 392 | new->data = xmalloc(length + OPT_DATA); |
| 390 | new->data[OPT_CODE] = optflag->code; | 393 | new->data[OPT_CODE] = optflag->code; |
| @@ -405,14 +408,7 @@ static NOINLINE void attach_option( | |||
| 405 | 408 | ||
| 406 | /* add it to an existing option */ | 409 | /* add it to an existing option */ |
| 407 | log2("Attaching option %02x to existing member of list", optflag->code); | 410 | log2("Attaching option %02x to existing member of list", optflag->code); |
| 408 | allocated = allocate_tempopt_if_needed(optflag, buffer, &length); | ||
| 409 | old_len = existing->data[OPT_LEN]; | 411 | old_len = existing->data[OPT_LEN]; |
| 410 | #if ENABLE_FEATURE_UDHCP_RFC3397 | ||
| 411 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { | ||
| 412 | /* reuse buffer and length for RFC1035-formatted string */ | ||
| 413 | allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length); | ||
| 414 | } | ||
| 415 | #endif | ||
| 416 | if (old_len + length < 255) { | 412 | if (old_len + length < 255) { |
| 417 | /* actually 255 is ok too, but adding a space can overlow it */ | 413 | /* actually 255 is ok too, but adding a space can overlow it */ |
| 418 | 414 | ||
| @@ -424,7 +420,7 @@ static NOINLINE void attach_option( | |||
| 424 | existing->data[OPT_DATA + old_len] = ' '; | 420 | existing->data[OPT_DATA + old_len] = ' '; |
| 425 | old_len++; | 421 | old_len++; |
| 426 | } | 422 | } |
| 427 | memcpy(existing->data + OPT_DATA + old_len, buffer, length); | 423 | memcpy(existing->data + OPT_DATA + old_len, (allocated ? allocated : buffer), length); |
| 428 | existing->data[OPT_LEN] = old_len + length; | 424 | existing->data[OPT_LEN] = old_len + length; |
| 429 | } /* else, ignore the data, we could put this in a second option in the future */ | 425 | } /* else, ignore the data, we could put this in a second option in the future */ |
| 430 | } /* else, ignore the new data */ | 426 | } /* else, ignore the new data */ |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 086228871..53d8a5e08 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
| @@ -1135,34 +1135,35 @@ static void client_background(void) | |||
| 1135 | //usage:# define IF_UDHCP_VERBOSE(...) | 1135 | //usage:# define IF_UDHCP_VERBOSE(...) |
| 1136 | //usage:#endif | 1136 | //usage:#endif |
| 1137 | //usage:#define udhcpc_trivial_usage | 1137 | //usage:#define udhcpc_trivial_usage |
| 1138 | //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" | 1138 | //usage: "[-fbq"IF_UDHCP_VERBOSE("v")IF_FEATURE_UDHCPC_ARPING("a")"RB] [-t N] [-T SEC] [-A SEC/-n]\n" |
| 1139 | //usage: " [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") | 1139 | //usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" |
| 1140 | //usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." | ||
| 1140 | //usage:#define udhcpc_full_usage "\n" | 1141 | //usage:#define udhcpc_full_usage "\n" |
| 1141 | //usage: IF_LONG_OPTS( | 1142 | //usage: IF_LONG_OPTS( |
| 1142 | //usage: "\n -i,--interface IFACE Interface to use (default eth0)" | 1143 | //usage: "\n -i,--interface IFACE Interface to use (default eth0)" |
| 1143 | //usage: "\n -p,--pidfile FILE Create pidfile" | 1144 | //usage: IF_FEATURE_UDHCP_PORT( |
| 1145 | //usage: "\n -P,--client-port PORT Use PORT (default 68)" | ||
| 1146 | //usage: ) | ||
| 1144 | //usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" | 1147 | //usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" |
| 1148 | //usage: "\n -p,--pidfile FILE Create pidfile" | ||
| 1145 | //usage: "\n -B,--broadcast Request broadcast replies" | 1149 | //usage: "\n -B,--broadcast Request broadcast replies" |
| 1146 | //usage: "\n -t,--retries N Send up to N discover packets" | 1150 | //usage: "\n -t,--retries N Send up to N discover packets (default 3)" |
| 1147 | //usage: "\n -T,--timeout N Pause between packets (default 3 seconds)" | 1151 | //usage: "\n -T,--timeout SEC Pause between packets (default 3)" |
| 1148 | //usage: "\n -A,--tryagain N Wait N seconds after failure (default 20)" | 1152 | //usage: "\n -A,--tryagain SEC Wait if lease is not obtained (default 20)" |
| 1153 | //usage: "\n -n,--now Exit if lease is not obtained" | ||
| 1154 | //usage: "\n -q,--quit Exit after obtaining lease" | ||
| 1155 | //usage: "\n -R,--release Release IP on exit" | ||
| 1149 | //usage: "\n -f,--foreground Run in foreground" | 1156 | //usage: "\n -f,--foreground Run in foreground" |
| 1150 | //usage: USE_FOR_MMU( | 1157 | //usage: USE_FOR_MMU( |
| 1151 | //usage: "\n -b,--background Background if lease is not obtained" | 1158 | //usage: "\n -b,--background Background if lease is not obtained" |
| 1152 | //usage: ) | 1159 | //usage: ) |
| 1153 | //usage: "\n -n,--now Exit if lease is not obtained" | ||
| 1154 | //usage: "\n -q,--quit Exit after obtaining lease" | ||
| 1155 | //usage: "\n -R,--release Release IP on exit" | ||
| 1156 | //usage: "\n -S,--syslog Log to syslog too" | 1160 | //usage: "\n -S,--syslog Log to syslog too" |
| 1157 | //usage: IF_FEATURE_UDHCP_PORT( | ||
| 1158 | //usage: "\n -P,--client-port N Use port N (default 68)" | ||
| 1159 | //usage: ) | ||
| 1160 | //usage: IF_FEATURE_UDHCPC_ARPING( | 1161 | //usage: IF_FEATURE_UDHCPC_ARPING( |
| 1161 | //usage: "\n -a,--arping Use arping to validate offered address" | 1162 | //usage: "\n -a,--arping Use arping to validate offered address" |
| 1162 | //usage: ) | 1163 | //usage: ) |
| 1163 | //usage: "\n -O,--request-option OPT Request option OPT from server (cumulative)" | ||
| 1164 | //usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" | ||
| 1165 | //usage: "\n -r,--request IP Request this IP address" | 1164 | //usage: "\n -r,--request IP Request this IP address" |
| 1165 | //usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" | ||
| 1166 | //usage: "\n -O,--request-option OPT Request option OPT from server (cumulative)" | ||
| 1166 | //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" | 1167 | //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" |
| 1167 | //usage: "\n Examples of string, numeric, and hex byte opts:" | 1168 | //usage: "\n Examples of string, numeric, and hex byte opts:" |
| 1168 | //usage: "\n -x hostname:bbox - option 12" | 1169 | //usage: "\n -x hostname:bbox - option 12" |
| @@ -1177,29 +1178,29 @@ static void client_background(void) | |||
| 1177 | //usage: ) | 1178 | //usage: ) |
| 1178 | //usage: IF_NOT_LONG_OPTS( | 1179 | //usage: IF_NOT_LONG_OPTS( |
| 1179 | //usage: "\n -i IFACE Interface to use (default eth0)" | 1180 | //usage: "\n -i IFACE Interface to use (default eth0)" |
| 1180 | //usage: "\n -p FILE Create pidfile" | 1181 | //usage: IF_FEATURE_UDHCP_PORT( |
| 1182 | //usage: "\n -P PORT Use PORT (default 68)" | ||
| 1183 | //usage: ) | ||
| 1181 | //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" | 1184 | //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" |
| 1185 | //usage: "\n -p FILE Create pidfile" | ||
| 1182 | //usage: "\n -B Request broadcast replies" | 1186 | //usage: "\n -B Request broadcast replies" |
| 1183 | //usage: "\n -t N Send up to N discover packets" | 1187 | //usage: "\n -t N Send up to N discover packets (default 3)" |
| 1184 | //usage: "\n -T N Pause between packets (default 3 seconds)" | 1188 | //usage: "\n -T SEC Pause between packets (default 3)" |
| 1185 | //usage: "\n -A N Wait N seconds (default 20) after failure" | 1189 | //usage: "\n -A SEC Wait if lease is not obtained (default 20)" |
| 1190 | //usage: "\n -n Exit if lease is not obtained" | ||
| 1191 | //usage: "\n -q Exit after obtaining lease" | ||
| 1192 | //usage: "\n -R Release IP on exit" | ||
| 1186 | //usage: "\n -f Run in foreground" | 1193 | //usage: "\n -f Run in foreground" |
| 1187 | //usage: USE_FOR_MMU( | 1194 | //usage: USE_FOR_MMU( |
| 1188 | //usage: "\n -b Background if lease is not obtained" | 1195 | //usage: "\n -b Background if lease is not obtained" |
| 1189 | //usage: ) | 1196 | //usage: ) |
| 1190 | //usage: "\n -n Exit if lease is not obtained" | ||
| 1191 | //usage: "\n -q Exit after obtaining lease" | ||
| 1192 | //usage: "\n -R Release IP on exit" | ||
| 1193 | //usage: "\n -S Log to syslog too" | 1197 | //usage: "\n -S Log to syslog too" |
| 1194 | //usage: IF_FEATURE_UDHCP_PORT( | ||
| 1195 | //usage: "\n -P N Use port N (default 68)" | ||
| 1196 | //usage: ) | ||
| 1197 | //usage: IF_FEATURE_UDHCPC_ARPING( | 1198 | //usage: IF_FEATURE_UDHCPC_ARPING( |
| 1198 | //usage: "\n -a Use arping to validate offered address" | 1199 | //usage: "\n -a Use arping to validate offered address" |
| 1199 | //usage: ) | 1200 | //usage: ) |
| 1200 | //usage: "\n -O OPT Request option OPT from server (cumulative)" | ||
| 1201 | //usage: "\n -o Don't request any options (unless -O is given)" | ||
| 1202 | //usage: "\n -r IP Request this IP address" | 1201 | //usage: "\n -r IP Request this IP address" |
| 1202 | //usage: "\n -o Don't request any options (unless -O is given)" | ||
| 1203 | //usage: "\n -O OPT Request option OPT from server (cumulative)" | ||
| 1203 | //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" | 1204 | //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" |
| 1204 | //usage: "\n Examples of string, numeric, and hex byte opts:" | 1205 | //usage: "\n Examples of string, numeric, and hex byte opts:" |
| 1205 | //usage: "\n -x hostname:bbox - option 12" | 1206 | //usage: "\n -x hostname:bbox - option 12" |
diff --git a/networking/wget.c b/networking/wget.c index 4eafebe40..5dac2b500 100644 --- a/networking/wget.c +++ b/networking/wget.c | |||
| @@ -62,14 +62,14 @@ struct globals { | |||
| 62 | const char *curfile; /* Name of current file being transferred */ | 62 | const char *curfile; /* Name of current file being transferred */ |
| 63 | bb_progress_t pmt; | 63 | bb_progress_t pmt; |
| 64 | #endif | 64 | #endif |
| 65 | char *dir_prefix; | 65 | char *dir_prefix; |
| 66 | #if ENABLE_FEATURE_WGET_LONG_OPTIONS | 66 | #if ENABLE_FEATURE_WGET_LONG_OPTIONS |
| 67 | char *post_data; | 67 | char *post_data; |
| 68 | char *extra_headers; | 68 | char *extra_headers; |
| 69 | #endif | 69 | #endif |
| 70 | char *fname_out; /* where to direct output (-O) */ | 70 | char *fname_out; /* where to direct output (-O) */ |
| 71 | const char *proxy_flag; /* Use proxies if env vars are set */ | 71 | const char *proxy_flag; /* Use proxies if env vars are set */ |
| 72 | const char *user_agent; /* "User-Agent" header field */ | 72 | const char *user_agent; /* "User-Agent" header field */ |
| 73 | #if ENABLE_FEATURE_WGET_TIMEOUT | 73 | #if ENABLE_FEATURE_WGET_TIMEOUT |
| 74 | unsigned timeout_seconds; | 74 | unsigned timeout_seconds; |
| 75 | #endif | 75 | #endif |
| @@ -86,7 +86,7 @@ struct globals { | |||
| 86 | } FIX_ALIASING; | 86 | } FIX_ALIASING; |
| 87 | #define G (*ptr_to_globals) | 87 | #define G (*ptr_to_globals) |
| 88 | #define INIT_G() do { \ | 88 | #define INIT_G() do { \ |
| 89 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 89 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
| 90 | IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \ | 90 | IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \ |
| 91 | } while (0) | 91 | } while (0) |
| 92 | 92 | ||
| @@ -328,8 +328,16 @@ static char *gethdr(FILE *fp) | |||
| 328 | return NULL; | 328 | return NULL; |
| 329 | 329 | ||
| 330 | /* convert the header name to lower case */ | 330 | /* convert the header name to lower case */ |
| 331 | for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) { | 331 | for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.' || *s == '_'; ++s) { |
| 332 | /* tolower for "A-Z", no-op for "0-9a-z-." */ | 332 | /* |
| 333 | * No-op for 20-3f and 60-7f. "0-9a-z-." are in these ranges. | ||
| 334 | * 40-5f range ("@A-Z[\]^_") maps to 60-7f. | ||
| 335 | * "A-Z" maps to "a-z". | ||
| 336 | * "@[\]" can't occur in header names. | ||
| 337 | * "^_" maps to "~,DEL" (which is wrong). | ||
| 338 | * "^" was never seen yet, "_" was seen from web.archive.org | ||
| 339 | * (x-archive-orig-x_commoncrawl_Signature: HEXSTRING). | ||
| 340 | */ | ||
| 333 | *s |= 0x20; | 341 | *s |= 0x20; |
| 334 | } | 342 | } |
| 335 | 343 | ||
diff --git a/procps/lsof.c b/procps/lsof.c index 7e0ffa4e5..b0156a538 100644 --- a/procps/lsof.c +++ b/procps/lsof.c | |||
| @@ -61,9 +61,12 @@ int lsof_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
| 61 | d_fd = opendir(name); | 61 | d_fd = opendir(name); |
| 62 | if (d_fd) { | 62 | if (d_fd) { |
| 63 | while ((entry = readdir(d_fd)) != NULL) { | 63 | while ((entry = readdir(d_fd)) != NULL) { |
| 64 | if (entry->d_type == DT_LNK) { | 64 | /* Skip entries '.' and '..' (and any hidden file) */ |
| 65 | safe_strncpy(name + baseofs, entry->d_name, 10); | 65 | if (entry->d_name[0] == '.') |
| 66 | fdlink = xmalloc_readlink(name); | 66 | continue; |
| 67 | |||
| 68 | safe_strncpy(name + baseofs, entry->d_name, 10); | ||
| 69 | if ((fdlink = xmalloc_readlink(name)) != NULL) { | ||
| 67 | printf("%d\t%s\t%s\n", proc->pid, proc->exe, fdlink); | 70 | printf("%d\t%s\t%s\n", proc->pid, proc->exe, fdlink); |
| 68 | free(fdlink); | 71 | free(fdlink); |
| 69 | } | 72 | } |
diff --git a/procps/pstree.c b/procps/pstree.c index 8ba30795d..ed1a41289 100644 --- a/procps/pstree.c +++ b/procps/pstree.c | |||
| @@ -34,8 +34,15 @@ | |||
| 34 | 34 | ||
| 35 | struct child; | 35 | struct child; |
| 36 | 36 | ||
| 37 | #ifdef ENABLE_FEATURE_SHOW_THREADS | ||
| 38 | /* For threads, we add {...} around the comm, so we need two extra bytes */ | ||
| 39 | # define COMM_DISP_LEN (COMM_LEN + 2) | ||
| 40 | #else | ||
| 41 | # define COMM_DISP_LEN COMM_LEN | ||
| 42 | #endif | ||
| 43 | |||
| 37 | typedef struct proc { | 44 | typedef struct proc { |
| 38 | char comm[COMM_LEN + 1]; | 45 | char comm[COMM_DISP_LEN + 1]; |
| 39 | // char flags; - unused, delete? | 46 | // char flags; - unused, delete? |
| 40 | pid_t pid; | 47 | pid_t pid; |
| 41 | uid_t uid; | 48 | uid_t uid; |
| @@ -341,8 +348,8 @@ static void dump_by_user(PROC *current, uid_t uid) | |||
| 341 | #if ENABLE_FEATURE_SHOW_THREADS | 348 | #if ENABLE_FEATURE_SHOW_THREADS |
| 342 | static void handle_thread(const char *comm, pid_t pid, pid_t ppid, uid_t uid) | 349 | static void handle_thread(const char *comm, pid_t pid, pid_t ppid, uid_t uid) |
| 343 | { | 350 | { |
| 344 | char threadname[COMM_LEN + 2]; | 351 | char threadname[COMM_DISP_LEN + 1]; |
| 345 | sprintf(threadname, "{%.*s}", COMM_LEN - 2, comm); | 352 | sprintf(threadname, "{%.*s}", (int)sizeof(threadname) - 3, comm); |
| 346 | add_proc(threadname, pid, ppid, uid/*, 1*/); | 353 | add_proc(threadname, pid, ppid, uid/*, 1*/); |
| 347 | } | 354 | } |
| 348 | #endif | 355 | #endif |
diff --git a/runit/svlogd.c b/runit/svlogd.c index b7a0a6e71..8b8a6d858 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c | |||
| @@ -745,11 +745,6 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn) | |||
| 745 | ld->inst = new; | 745 | ld->inst = new; |
| 746 | break; | 746 | break; |
| 747 | case 's': { | 747 | case 's': { |
| 748 | static const struct suffix_mult km_suffixes[] = { | ||
| 749 | { "k", 1024 }, | ||
| 750 | { "m", 1024*1024 }, | ||
| 751 | { "", 0 } | ||
| 752 | }; | ||
| 753 | ld->sizemax = xatou_sfx(&s[1], km_suffixes); | 748 | ld->sizemax = xatou_sfx(&s[1], km_suffixes); |
| 754 | break; | 749 | break; |
| 755 | } | 750 | } |
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index bd2d70e19..303df0be7 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c | |||
| @@ -474,7 +474,11 @@ int conf_write(const char *name) | |||
| 474 | fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); | 474 | fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); |
| 475 | /* bbox */ | 475 | /* bbox */ |
| 476 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); | 476 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); |
| 477 | fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name); | 477 | fprintf(out_h, "#ifdef MAKE_SUID\n"); |
| 478 | fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name); | ||
| 479 | fprintf(out_h, "#else\n"); | ||
| 480 | fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name); | ||
| 481 | fprintf(out_h, "#endif\n"); | ||
| 478 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); | 482 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); |
| 479 | } | 483 | } |
| 480 | break; | 484 | break; |
| @@ -506,7 +510,11 @@ int conf_write(const char *name) | |||
| 506 | fputs("\"\n", out_h); | 510 | fputs("\"\n", out_h); |
| 507 | /* bbox */ | 511 | /* bbox */ |
| 508 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); | 512 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); |
| 509 | fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name); | 513 | fprintf(out_h, "#ifdef MAKE_SUID\n"); |
| 514 | fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name); | ||
| 515 | fprintf(out_h, "#else\n"); | ||
| 516 | fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name); | ||
| 517 | fprintf(out_h, "#endif\n"); | ||
| 510 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); | 518 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); |
| 511 | } | 519 | } |
| 512 | break; | 520 | break; |
| @@ -518,7 +526,11 @@ int conf_write(const char *name) | |||
| 518 | fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); | 526 | fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); |
| 519 | /* bbox */ | 527 | /* bbox */ |
| 520 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); | 528 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); |
| 521 | fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name); | 529 | fprintf(out_h, "#ifdef MAKE_SUID\n"); |
| 530 | fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name); | ||
| 531 | fprintf(out_h, "#else\n"); | ||
| 532 | fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name); | ||
| 533 | fprintf(out_h, "#endif\n"); | ||
| 522 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); | 534 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); |
| 523 | } | 535 | } |
| 524 | break; | 536 | break; |
| @@ -532,7 +544,11 @@ int conf_write(const char *name) | |||
| 532 | fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); | 544 | fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); |
| 533 | /* bbox */ | 545 | /* bbox */ |
| 534 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); | 546 | fprintf(out_h, "#define ENABLE_%s 1\n", sym->name); |
| 535 | fprintf(out_h, "#define IF_%s(...) __VA_ARGS__\n", sym->name); | 547 | fprintf(out_h, "#ifdef MAKE_SUID\n"); |
| 548 | fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name); | ||
| 549 | fprintf(out_h, "#else\n"); | ||
| 550 | fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name); | ||
| 551 | fprintf(out_h, "#endif\n"); | ||
| 536 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); | 552 | fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name); |
| 537 | } | 553 | } |
| 538 | break; | 554 | break; |
diff --git a/shell/ash.c b/shell/ash.c index 8f59dccda..6e6fc6a71 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -9501,6 +9501,9 @@ static int getoptscmd(int, char **) FAST_FUNC; | |||
| 9501 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET | 9501 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET |
| 9502 | static int helpcmd(int, char **) FAST_FUNC; | 9502 | static int helpcmd(int, char **) FAST_FUNC; |
| 9503 | #endif | 9503 | #endif |
| 9504 | #if MAX_HISTORY | ||
| 9505 | static int historycmd(int, char **) FAST_FUNC; | ||
| 9506 | #endif | ||
| 9504 | #if ENABLE_SH_MATH_SUPPORT | 9507 | #if ENABLE_SH_MATH_SUPPORT |
| 9505 | static int letcmd(int, char **) FAST_FUNC; | 9508 | static int letcmd(int, char **) FAST_FUNC; |
| 9506 | #endif | 9509 | #endif |
| @@ -9574,6 +9577,9 @@ static const struct builtincmd builtintab[] = { | |||
| 9574 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET | 9577 | #if !ENABLE_FEATURE_SH_EXTRA_QUIET |
| 9575 | { BUILTIN_NOSPEC "help" , helpcmd }, | 9578 | { BUILTIN_NOSPEC "help" , helpcmd }, |
| 9576 | #endif | 9579 | #endif |
| 9580 | #if MAX_HISTORY | ||
| 9581 | { BUILTIN_NOSPEC "history" , historycmd }, | ||
| 9582 | #endif | ||
| 9577 | #if JOBS | 9583 | #if JOBS |
| 9578 | { BUILTIN_REGULAR "jobs" , jobscmd }, | 9584 | { BUILTIN_REGULAR "jobs" , jobscmd }, |
| 9579 | { BUILTIN_REGULAR "kill" , killcmd }, | 9585 | { BUILTIN_REGULAR "kill" , killcmd }, |
| @@ -10155,7 +10161,12 @@ preadfd(void) | |||
| 10155 | * _during_ shell execution, not only if it was set when | 10161 | * _during_ shell execution, not only if it was set when |
| 10156 | * shell was started. Therefore, re-check LANG every time: | 10162 | * shell was started. Therefore, re-check LANG every time: |
| 10157 | */ | 10163 | */ |
| 10158 | reinit_unicode(lookupvar("LANG")); | 10164 | { |
| 10165 | const char *s = lookupvar("LC_ALL"); | ||
| 10166 | if (!s) s = lookupvar("LC_CTYPE"); | ||
| 10167 | if (!s) s = lookupvar("LANG"); | ||
| 10168 | reinit_unicode(s); | ||
| 10169 | } | ||
| 10159 | nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout); | 10170 | nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout); |
| 10160 | if (nr == 0) { | 10171 | if (nr == 0) { |
| 10161 | /* Ctrl+C pressed */ | 10172 | /* Ctrl+C pressed */ |
| @@ -13163,6 +13174,15 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
| 13163 | } | 13174 | } |
| 13164 | #endif /* FEATURE_SH_EXTRA_QUIET */ | 13175 | #endif /* FEATURE_SH_EXTRA_QUIET */ |
| 13165 | 13176 | ||
| 13177 | #if MAX_HISTORY | ||
| 13178 | static int FAST_FUNC | ||
| 13179 | historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | ||
| 13180 | { | ||
| 13181 | show_history(line_input_state); | ||
| 13182 | return EXIT_SUCCESS; | ||
| 13183 | } | ||
| 13184 | #endif | ||
| 13185 | |||
| 13166 | /* | 13186 | /* |
| 13167 | * The export and readonly commands. | 13187 | * The export and readonly commands. |
| 13168 | */ | 13188 | */ |
diff --git a/shell/hush.c b/shell/hush.c index b23325725..912ecf15f 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -850,6 +850,9 @@ static int builtin_jobs(char **argv) FAST_FUNC; | |||
| 850 | #if ENABLE_HUSH_HELP | 850 | #if ENABLE_HUSH_HELP |
| 851 | static int builtin_help(char **argv) FAST_FUNC; | 851 | static int builtin_help(char **argv) FAST_FUNC; |
| 852 | #endif | 852 | #endif |
| 853 | #if MAX_HISTORY && ENABLE_FEATURE_EDITING | ||
| 854 | static int builtin_history(char **argv) FAST_FUNC; | ||
| 855 | #endif | ||
| 853 | #if ENABLE_HUSH_LOCAL | 856 | #if ENABLE_HUSH_LOCAL |
| 854 | static int builtin_local(char **argv) FAST_FUNC; | 857 | static int builtin_local(char **argv) FAST_FUNC; |
| 855 | #endif | 858 | #endif |
| @@ -919,6 +922,9 @@ static const struct built_in_command bltins1[] = { | |||
| 919 | #if ENABLE_HUSH_HELP | 922 | #if ENABLE_HUSH_HELP |
| 920 | BLTIN("help" , builtin_help , NULL), | 923 | BLTIN("help" , builtin_help , NULL), |
| 921 | #endif | 924 | #endif |
| 925 | #if MAX_HISTORY && ENABLE_FEATURE_EDITING | ||
| 926 | BLTIN("history" , builtin_history , "Show command history"), | ||
| 927 | #endif | ||
| 922 | #if ENABLE_HUSH_JOB | 928 | #if ENABLE_HUSH_JOB |
| 923 | BLTIN("jobs" , builtin_jobs , "List jobs"), | 929 | BLTIN("jobs" , builtin_jobs , "List jobs"), |
| 924 | #endif | 930 | #endif |
| @@ -1383,7 +1389,7 @@ static void restore_G_args(save_arg_t *sv, char **argv) | |||
| 1383 | * are set to '' (ignore) are NOT reset to defaults. We do the same. | 1389 | * are set to '' (ignore) are NOT reset to defaults. We do the same. |
| 1384 | * | 1390 | * |
| 1385 | * Problem: the above approach makes it unwieldy to catch signals while | 1391 | * Problem: the above approach makes it unwieldy to catch signals while |
| 1386 | * we are in read builtin, of while we read commands from stdin: | 1392 | * we are in read builtin, or while we read commands from stdin: |
| 1387 | * masked signals are not visible! | 1393 | * masked signals are not visible! |
| 1388 | * | 1394 | * |
| 1389 | * New implementation | 1395 | * New implementation |
| @@ -2038,7 +2044,10 @@ static void get_user_input(struct in_str *i) | |||
| 2038 | * _during_ shell execution, not only if it was set when | 2044 | * _during_ shell execution, not only if it was set when |
| 2039 | * shell was started. Therefore, re-check LANG every time: | 2045 | * shell was started. Therefore, re-check LANG every time: |
| 2040 | */ | 2046 | */ |
| 2041 | reinit_unicode(get_local_var_value("LANG")); | 2047 | const char *s = get_local_var_value("LC_ALL"); |
| 2048 | if (!s) s = get_local_var_value("LC_CTYPE"); | ||
| 2049 | if (!s) s = get_local_var_value("LANG"); | ||
| 2050 | reinit_unicode(s); | ||
| 2042 | 2051 | ||
| 2043 | G.flag_SIGINT = 0; | 2052 | G.flag_SIGINT = 0; |
| 2044 | /* buglet: SIGINT will not make new prompt to appear _at once_, | 2053 | /* buglet: SIGINT will not make new prompt to appear _at once_, |
| @@ -7354,7 +7363,7 @@ static int run_list(struct pipe *pi) | |||
| 7354 | * and we should not execute CMD */ | 7363 | * and we should not execute CMD */ |
| 7355 | debug_printf_exec("skipped cmd because of || or &&\n"); | 7364 | debug_printf_exec("skipped cmd because of || or &&\n"); |
| 7356 | last_followup = pi->followup; | 7365 | last_followup = pi->followup; |
| 7357 | continue; | 7366 | goto dont_check_jobs_but_continue; |
| 7358 | } | 7367 | } |
| 7359 | } | 7368 | } |
| 7360 | last_followup = pi->followup; | 7369 | last_followup = pi->followup; |
| @@ -7493,8 +7502,10 @@ static int run_list(struct pipe *pi) | |||
| 7493 | G.flag_break_continue = 0; | 7502 | G.flag_break_continue = 0; |
| 7494 | /* else: e.g. "continue 2" should *break* once, *then* continue */ | 7503 | /* else: e.g. "continue 2" should *break* once, *then* continue */ |
| 7495 | } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */ | 7504 | } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */ |
| 7496 | if (G.depth_break_continue != 0 || fbc == BC_BREAK) | 7505 | if (G.depth_break_continue != 0 || fbc == BC_BREAK) { |
| 7497 | goto check_jobs_and_break; | 7506 | checkjobs(NULL); |
| 7507 | break; | ||
| 7508 | } | ||
| 7498 | /* "continue": simulate end of loop */ | 7509 | /* "continue": simulate end of loop */ |
| 7499 | rword = RES_DONE; | 7510 | rword = RES_DONE; |
| 7500 | continue; | 7511 | continue; |
| @@ -7502,7 +7513,6 @@ static int run_list(struct pipe *pi) | |||
| 7502 | #endif | 7513 | #endif |
| 7503 | #if ENABLE_HUSH_FUNCTIONS | 7514 | #if ENABLE_HUSH_FUNCTIONS |
| 7504 | if (G.flag_return_in_progress == 1) { | 7515 | if (G.flag_return_in_progress == 1) { |
| 7505 | /* same as "goto check_jobs_and_break" */ | ||
| 7506 | checkjobs(NULL); | 7516 | checkjobs(NULL); |
| 7507 | break; | 7517 | break; |
| 7508 | } | 7518 | } |
| @@ -7544,6 +7554,9 @@ static int run_list(struct pipe *pi) | |||
| 7544 | if (rword == RES_IF || rword == RES_ELIF) | 7554 | if (rword == RES_IF || rword == RES_ELIF) |
| 7545 | cond_code = rcode; | 7555 | cond_code = rcode; |
| 7546 | #endif | 7556 | #endif |
| 7557 | check_jobs_and_continue: | ||
| 7558 | checkjobs(NULL); | ||
| 7559 | dont_check_jobs_but_continue: ; | ||
| 7547 | #if ENABLE_HUSH_LOOPS | 7560 | #if ENABLE_HUSH_LOOPS |
| 7548 | /* Beware of "while false; true; do ..."! */ | 7561 | /* Beware of "while false; true; do ..."! */ |
| 7549 | if (pi->next | 7562 | if (pi->next |
| @@ -7555,22 +7568,17 @@ static int run_list(struct pipe *pi) | |||
| 7555 | /* "while false; do...done" - exitcode 0 */ | 7568 | /* "while false; do...done" - exitcode 0 */ |
| 7556 | G.last_exitcode = rcode = EXIT_SUCCESS; | 7569 | G.last_exitcode = rcode = EXIT_SUCCESS; |
| 7557 | debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n"); | 7570 | debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n"); |
| 7558 | goto check_jobs_and_break; | 7571 | break; |
| 7559 | } | 7572 | } |
| 7560 | } | 7573 | } |
| 7561 | if (rword == RES_UNTIL) { | 7574 | if (rword == RES_UNTIL) { |
| 7562 | if (!rcode) { | 7575 | if (!rcode) { |
| 7563 | debug_printf_exec(": until expr is true: breaking\n"); | 7576 | debug_printf_exec(": until expr is true: breaking\n"); |
| 7564 | check_jobs_and_break: | ||
| 7565 | checkjobs(NULL); | ||
| 7566 | break; | 7577 | break; |
| 7567 | } | 7578 | } |
| 7568 | } | 7579 | } |
| 7569 | } | 7580 | } |
| 7570 | #endif | 7581 | #endif |
| 7571 | |||
| 7572 | check_jobs_and_continue: | ||
| 7573 | checkjobs(NULL); | ||
| 7574 | } /* for (pi) */ | 7582 | } /* for (pi) */ |
| 7575 | 7583 | ||
| 7576 | #if ENABLE_HUSH_JOB | 7584 | #if ENABLE_HUSH_JOB |
| @@ -8628,6 +8636,14 @@ static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) | |||
| 8628 | } | 8636 | } |
| 8629 | #endif | 8637 | #endif |
| 8630 | 8638 | ||
| 8639 | #if MAX_HISTORY && ENABLE_FEATURE_EDITING | ||
| 8640 | static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) | ||
| 8641 | { | ||
| 8642 | show_history(G.line_input_state); | ||
| 8643 | return EXIT_SUCCESS; | ||
| 8644 | } | ||
| 8645 | #endif | ||
| 8646 | |||
| 8631 | #if ENABLE_HUSH_JOB | 8647 | #if ENABLE_HUSH_JOB |
| 8632 | static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) | 8648 | static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) |
| 8633 | { | 8649 | { |
diff --git a/shell/hush_test/hush-misc/while4.right b/shell/hush_test/hush-misc/while4.right new file mode 100644 index 000000000..7b24a35ff --- /dev/null +++ b/shell/hush_test/hush-misc/while4.right | |||
| @@ -0,0 +1 @@ | |||
| Ok:0 | |||
diff --git a/shell/hush_test/hush-misc/while4.tests b/shell/hush_test/hush-misc/while4.tests new file mode 100755 index 000000000..ba80e603a --- /dev/null +++ b/shell/hush_test/hush-misc/while4.tests | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | false | ||
| 2 | while false && echo Not reached; do | ||
| 3 | echo BUG | ||
| 4 | break | ||
| 5 | done | ||
| 6 | echo Ok:$? | ||
diff --git a/shell/shell_common.c b/shell/shell_common.c index f7503cac5..84e0604ed 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
| @@ -39,7 +39,7 @@ int FAST_FUNC is_well_formed_var_name(const char *s, char terminator) | |||
| 39 | 39 | ||
| 40 | /* read builtin */ | 40 | /* read builtin */ |
| 41 | 41 | ||
| 42 | /* Needs to be interruptible: shell mush handle traps and shell-special signals | 42 | /* Needs to be interruptible: shell must handle traps and shell-special signals |
| 43 | * while inside read. To implement this, be sure to not loop on EINTR | 43 | * while inside read. To implement this, be sure to not loop on EINTR |
| 44 | * and return errno == EINTR reliably. | 44 | * and return errno == EINTR reliably. |
| 45 | */ | 45 | */ |
diff --git a/sysklogd/logread.c b/sysklogd/logread.c index 993956904..2b6415f47 100644 --- a/sysklogd/logread.c +++ b/sysklogd/logread.c | |||
| @@ -52,7 +52,7 @@ struct globals { | |||
| 52 | static void error_exit(const char *str) NORETURN; | 52 | static void error_exit(const char *str) NORETURN; |
| 53 | static void error_exit(const char *str) | 53 | static void error_exit(const char *str) |
| 54 | { | 54 | { |
| 55 | //release all acquired resources | 55 | /* Release all acquired resources */ |
| 56 | shmdt(shbuf); | 56 | shmdt(shbuf); |
| 57 | bb_perror_msg_and_die(str); | 57 | bb_perror_msg_and_die(str); |
| 58 | } | 58 | } |
| @@ -66,11 +66,10 @@ static void sem_up(int semid) | |||
| 66 | error_exit("semop[SMrup]"); | 66 | error_exit("semop[SMrup]"); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static void interrupted(int sig UNUSED_PARAM) | 69 | static void interrupted(int sig) |
| 70 | { | 70 | { |
| 71 | signal(SIGINT, SIG_IGN); | ||
| 72 | shmdt(shbuf); | 71 | shmdt(shbuf); |
| 73 | exit(EXIT_SUCCESS); | 72 | kill_myself_with_sig(sig); |
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | int logread_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 75 | int logread_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| @@ -96,7 +95,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv) | |||
| 96 | if (log_semid == -1) | 95 | if (log_semid == -1) |
| 97 | error_exit("can't get access to semaphores for syslogd buffer"); | 96 | error_exit("can't get access to semaphores for syslogd buffer"); |
| 98 | 97 | ||
| 99 | signal(SIGINT, interrupted); | 98 | bb_signals(BB_FATAL_SIGS, interrupted); |
| 100 | 99 | ||
| 101 | /* Suppose atomic memory read */ | 100 | /* Suppose atomic memory read */ |
| 102 | /* Max possible value for tail is shbuf->size - 1 */ | 101 | /* Max possible value for tail is shbuf->size - 1 */ |
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 4f45b4f7f..a6a4ff25c 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c | |||
| @@ -58,6 +58,9 @@ | |||
| 58 | #define SYSLOG_NAMES_CONST | 58 | #define SYSLOG_NAMES_CONST |
| 59 | #include <syslog.h> | 59 | #include <syslog.h> |
| 60 | */ | 60 | */ |
| 61 | #ifndef _PATH_LOG | ||
| 62 | #define _PATH_LOG "/dev/log" | ||
| 63 | #endif | ||
| 61 | 64 | ||
| 62 | #include <sys/un.h> | 65 | #include <sys/un.h> |
| 63 | #include <sys/uio.h> | 66 | #include <sys/uio.h> |
| @@ -824,8 +827,8 @@ static NOINLINE int create_socket(void) | |||
| 824 | 827 | ||
| 825 | /* Unlink old /dev/log or object it points to. */ | 828 | /* Unlink old /dev/log or object it points to. */ |
| 826 | /* (if it exists, bind will fail) */ | 829 | /* (if it exists, bind will fail) */ |
| 827 | strcpy(sunx.sun_path, "/dev/log"); | 830 | strcpy(sunx.sun_path, _PATH_LOG); |
| 828 | dev_log_name = xmalloc_follow_symlinks("/dev/log"); | 831 | dev_log_name = xmalloc_follow_symlinks(_PATH_LOG); |
| 829 | if (dev_log_name) { | 832 | if (dev_log_name) { |
| 830 | safe_strncpy(sunx.sun_path, dev_log_name, sizeof(sunx.sun_path)); | 833 | safe_strncpy(sunx.sun_path, dev_log_name, sizeof(sunx.sun_path)); |
| 831 | free(dev_log_name); | 834 | free(dev_log_name); |
| @@ -834,7 +837,7 @@ static NOINLINE int create_socket(void) | |||
| 834 | 837 | ||
| 835 | sock_fd = xsocket(AF_UNIX, SOCK_DGRAM, 0); | 838 | sock_fd = xsocket(AF_UNIX, SOCK_DGRAM, 0); |
| 836 | xbind(sock_fd, (struct sockaddr *) &sunx, sizeof(sunx)); | 839 | xbind(sock_fd, (struct sockaddr *) &sunx, sizeof(sunx)); |
| 837 | chmod("/dev/log", 0666); | 840 | chmod(_PATH_LOG, 0666); |
| 838 | 841 | ||
| 839 | return sock_fd; | 842 | return sock_fd; |
| 840 | } | 843 | } |
| @@ -905,7 +908,7 @@ static void do_syslogd(void) | |||
| 905 | sz = read(sock_fd, recvbuf, MAX_READ - 1); | 908 | sz = read(sock_fd, recvbuf, MAX_READ - 1); |
| 906 | if (sz < 0) { | 909 | if (sz < 0) { |
| 907 | if (!bb_got_signal) | 910 | if (!bb_got_signal) |
| 908 | bb_perror_msg("read from /dev/log"); | 911 | bb_perror_msg("read from %s", _PATH_LOG); |
| 909 | break; | 912 | break; |
| 910 | } | 913 | } |
| 911 | 914 | ||
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index dad49c3f5..6af6072b8 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
| @@ -24,7 +24,7 @@ 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\"}'" "" "" "" | 24 | testing "awk if string == " "awk 'BEGIN{if(\"a\"==\"ab\") print \"bar\"}'" "" "" "" |
| 25 | 25 | ||
| 26 | # 4294967295 = 0xffffffff | 26 | # 4294967295 = 0xffffffff |
| 27 | testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4.29497e+09\n" "" "\n" | 27 | testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4294967295\n" "" "\n" |
| 28 | 28 | ||
| 29 | # we were testing for a non-empty body when deciding if a function was | 29 | # we were testing for a non-empty body when deciding if a function was |
| 30 | # defined or not. The testcase below caused: | 30 | # defined or not. The testcase below caused: |
| @@ -44,9 +44,37 @@ testing "awk handles empty function f(arg){}" \ | |||
| 44 | "L1\n\nL2\n\n" \ | 44 | "L1\n\nL2\n\n" \ |
| 45 | "" "" | 45 | "" "" |
| 46 | 46 | ||
| 47 | prg=' | ||
| 48 | function outer_fun() { | ||
| 49 | return 1 | ||
| 50 | } | ||
| 51 | END { | ||
| 52 | i=1 | ||
| 53 | print "L" i "\n" | ||
| 54 | i += outer_fun() | ||
| 55 | print "L" i "\n" | ||
| 56 | }' | ||
| 57 | testing "awk properly handles function from other scope" \ | ||
| 58 | "awk '$prg'" \ | ||
| 59 | "L1\n\nL2\n\n" \ | ||
| 60 | "" "" | ||
| 61 | |||
| 62 | prg=' | ||
| 63 | END { | ||
| 64 | i=1 | ||
| 65 | print "L" i "\n" | ||
| 66 | i + trigger_error_fun() | ||
| 67 | print "L" i "\n" | ||
| 68 | }' | ||
| 69 | testing "awk properly handles undefined function" \ | ||
| 70 | "awk '$prg' 2>&1" \ | ||
| 71 | "L1\n\nawk: cmd. line:5: Call to undefined function\n" \ | ||
| 72 | "" "" | ||
| 73 | |||
| 74 | |||
| 47 | optional DESKTOP | 75 | optional DESKTOP |
| 48 | testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4.29497e+09\n" "" "\n" | 76 | testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n" |
| 49 | testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2.14748e+09\n" "" "\n" | 77 | testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2147483649\n" "" "\n" |
| 50 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" | 78 | testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n" |
| 51 | SKIP= | 79 | SKIP= |
| 52 | 80 | ||
| @@ -241,6 +269,11 @@ testing "awk FS assignment" "awk '{FS=\":\"; print \$1}'" \ | |||
| 241 | "" \ | 269 | "" \ |
| 242 | "a:b c:d\ne:f g:h" | 270 | "a:b c:d\ne:f g:h" |
| 243 | 271 | ||
| 272 | testing "awk large integer" \ | ||
| 273 | "awk 'BEGIN{n=(2^31)-1; print n, int(n), n%1, ++n, int(n), n%1}'" \ | ||
| 274 | "2147483647 2147483647 0 2147483648 2147483648 0\n" \ | ||
| 275 | "" "" | ||
| 276 | |||
| 244 | # testing "description" "command" "result" "infile" "stdin" | 277 | # testing "description" "command" "result" "infile" "stdin" |
| 245 | 278 | ||
| 246 | exit $FAILCOUNT | 279 | exit $FAILCOUNT |
diff --git a/testsuite/grep.tests b/testsuite/grep.tests index 4781f2284..64d99a905 100755 --- a/testsuite/grep.tests +++ b/testsuite/grep.tests | |||
| @@ -82,6 +82,20 @@ testing "grep -F handles -i" "grep -F -i foo input ; echo \$?" \ | |||
| 82 | testing "grep can read regexps from stdin" "grep -f - input ; echo \$?" \ | 82 | testing "grep can read regexps from stdin" "grep -f - input ; echo \$?" \ |
| 83 | "two\nthree\n0\n" "tw\ntwo\nthree\n" "tw.\nthr\n" | 83 | "two\nthree\n0\n" "tw\ntwo\nthree\n" "tw.\nthr\n" |
| 84 | 84 | ||
| 85 | # -x (whole line match) | ||
| 86 | testing "grep -x (full match)" "grep -x foo input ; echo \$?" \ | ||
| 87 | "foo\n0\n" "foo\n" "" | ||
| 88 | testing "grep -x (partial match 1)" "grep -x foo input ; echo \$?" \ | ||
| 89 | "1\n" "foo bar\n" "" | ||
| 90 | testing "grep -x (partial match 2)" "grep -x foo input ; echo \$?" \ | ||
| 91 | "1\n" "bar foo\n" "" | ||
| 92 | testing "grep -x -F (full match)" "grep -x -F foo input ; echo \$?" \ | ||
| 93 | "foo\n0\n" "foo\n" "" | ||
| 94 | testing "grep -x -F (partial match 1)" "grep -x -F foo input ; echo \$?" \ | ||
| 95 | "1\n" "foo bar\n" "" | ||
| 96 | testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \ | ||
| 97 | "1\n" "bar foo\n" "" | ||
| 98 | |||
| 85 | optional FEATURE_GREP_EGREP_ALIAS | 99 | optional FEATURE_GREP_EGREP_ALIAS |
| 86 | testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \ | 100 | testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \ |
| 87 | "b\ar\nfoo\nbaz" | 101 | "b\ar\nfoo\nbaz" |
| @@ -127,6 +141,12 @@ testing "grep -Fw doesn't stop on 1st mismatch" \ | |||
| 127 | "foop foo\n" \ | 141 | "foop foo\n" \ |
| 128 | "" | 142 | "" |
| 129 | 143 | ||
| 144 | testing "grep -w doesn't stop on 1st mismatch" \ | ||
| 145 | "grep -w foo input" \ | ||
| 146 | "foop foo\n" \ | ||
| 147 | "foop foo\n" \ | ||
| 148 | "" | ||
| 149 | |||
| 130 | # testing "test name" "commands" "expected result" "file input" "stdin" | 150 | # testing "test name" "commands" "expected result" "file input" "stdin" |
| 131 | # file input will be file called "input" | 151 | # file input will be file called "input" |
| 132 | # test can create a file "actual" instead of writing to stdout | 152 | # test can create a file "actual" instead of writing to stdout |
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 468565f47..2af1e4c97 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
| @@ -310,6 +310,27 @@ testing "sed zero chars match/replace logic must not falsely trigger here 2" \ | |||
| 310 | "sed 's/ *$/_/g'" \ | 310 | "sed 's/ *$/_/g'" \ |
| 311 | "qwerty_\n" "" "qwerty\n" | 311 | "qwerty_\n" "" "qwerty\n" |
| 312 | 312 | ||
| 313 | testing "sed /\$_in_regex/ should not match newlines, only end-of-line" \ | ||
| 314 | "sed ': testcont; /\\\\$/{ =; N; b testcont }'" \ | ||
| 315 | "\ | ||
| 316 | this is a regular line | ||
| 317 | 2 | ||
| 318 | line with \\ | ||
| 319 | continuation | ||
| 320 | more regular lines | ||
| 321 | 5 | ||
| 322 | line with \\ | ||
| 323 | continuation | ||
| 324 | " \ | ||
| 325 | "" "\ | ||
| 326 | this is a regular line | ||
| 327 | line with \\ | ||
| 328 | continuation | ||
| 329 | more regular lines | ||
| 330 | line with \\ | ||
| 331 | continuation | ||
| 332 | " | ||
| 333 | |||
| 313 | # testing "description" "commands" "result" "infile" "stdin" | 334 | # testing "description" "commands" "result" "infile" "stdin" |
| 314 | 335 | ||
| 315 | exit $FAILCOUNT | 336 | exit $FAILCOUNT |
diff --git a/util-linux/Config.src b/util-linux/Config.src index 6c1b928da..5a8b0063b 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src | |||
| @@ -699,250 +699,6 @@ config FEATURE_MTAB_SUPPORT | |||
| 699 | About the only reason to use this is if you've removed /proc from | 699 | About the only reason to use this is if you've removed /proc from |
| 700 | your kernel. | 700 | your kernel. |
| 701 | 701 | ||
| 702 | config VOLUMEID | 702 | source util-linux/volume_id/Config.in |
| 703 | bool #No description makes it a hidden option | ||
| 704 | default n | ||
| 705 | |||
| 706 | menu "Filesystem/Volume identification" | ||
| 707 | depends on VOLUMEID | ||
| 708 | |||
| 709 | config FEATURE_VOLUMEID_EXT | ||
| 710 | bool "Ext filesystem" | ||
| 711 | default y | ||
| 712 | depends on VOLUMEID | ||
| 713 | help | ||
| 714 | TODO | ||
| 715 | |||
| 716 | config FEATURE_VOLUMEID_BTRFS | ||
| 717 | bool "btrfs filesystem" | ||
| 718 | default y | ||
| 719 | depends on VOLUMEID | ||
| 720 | help | ||
| 721 | TODO | ||
| 722 | |||
| 723 | config FEATURE_VOLUMEID_REISERFS | ||
| 724 | bool "Reiser filesystem" | ||
| 725 | default y | ||
| 726 | depends on VOLUMEID | ||
| 727 | help | ||
| 728 | TODO | ||
| 729 | |||
| 730 | config FEATURE_VOLUMEID_FAT | ||
| 731 | bool "fat filesystem" | ||
| 732 | default y | ||
| 733 | depends on VOLUMEID | ||
| 734 | help | ||
| 735 | TODO | ||
| 736 | |||
| 737 | config FEATURE_VOLUMEID_EXFAT | ||
| 738 | bool "exFAT filesystem" | ||
| 739 | default y | ||
| 740 | depends on VOLUMEID | ||
| 741 | help | ||
| 742 | exFAT (extended FAT) is a proprietary file system designed especially | ||
| 743 | for flash drives. It has many features from NTFS, but with less | ||
| 744 | overhead. exFAT is used on most SDXC cards for consumer electronics. | ||
| 745 | |||
| 746 | config FEATURE_VOLUMEID_HFS | ||
| 747 | bool "hfs filesystem" | ||
| 748 | default y | ||
| 749 | depends on VOLUMEID | ||
| 750 | help | ||
| 751 | TODO | ||
| 752 | |||
| 753 | config FEATURE_VOLUMEID_JFS | ||
| 754 | bool "jfs filesystem" | ||
| 755 | default y | ||
| 756 | depends on VOLUMEID | ||
| 757 | help | ||
| 758 | TODO | ||
| 759 | |||
| 760 | ### config FEATURE_VOLUMEID_UFS | ||
| 761 | ### bool "ufs filesystem" | ||
| 762 | ### default y | ||
| 763 | ### depends on VOLUMEID | ||
| 764 | ### help | ||
| 765 | ### TODO | ||
| 766 | |||
| 767 | config FEATURE_VOLUMEID_XFS | ||
| 768 | bool "xfs filesystem" | ||
| 769 | default y | ||
| 770 | depends on VOLUMEID | ||
| 771 | help | ||
| 772 | TODO | ||
| 773 | |||
| 774 | config FEATURE_VOLUMEID_NILFS | ||
| 775 | bool "nilfs filesystem" | ||
| 776 | default y | ||
| 777 | depends on VOLUMEID | ||
| 778 | help | ||
| 779 | TODO | ||
| 780 | |||
| 781 | config FEATURE_VOLUMEID_NTFS | ||
| 782 | bool "ntfs filesystem" | ||
| 783 | default y | ||
| 784 | depends on VOLUMEID | ||
| 785 | help | ||
| 786 | TODO | ||
| 787 | |||
| 788 | config FEATURE_VOLUMEID_ISO9660 | ||
| 789 | bool "iso9660 filesystem" | ||
| 790 | default y | ||
| 791 | depends on VOLUMEID | ||
| 792 | help | ||
| 793 | TODO | ||
| 794 | |||
| 795 | config FEATURE_VOLUMEID_UDF | ||
| 796 | bool "udf filesystem" | ||
| 797 | default y | ||
| 798 | depends on VOLUMEID | ||
| 799 | help | ||
| 800 | TODO | ||
| 801 | |||
| 802 | config FEATURE_VOLUMEID_LUKS | ||
| 803 | bool "luks filesystem" | ||
| 804 | default y | ||
| 805 | depends on VOLUMEID | ||
| 806 | help | ||
| 807 | TODO | ||
| 808 | |||
| 809 | config FEATURE_VOLUMEID_LINUXSWAP | ||
| 810 | bool "linux swap filesystem" | ||
| 811 | default y | ||
| 812 | depends on VOLUMEID | ||
| 813 | help | ||
| 814 | TODO | ||
| 815 | |||
| 816 | ### config FEATURE_VOLUMEID_LVM | ||
| 817 | ### bool "lvm" | ||
| 818 | ### default y | ||
| 819 | ### depends on VOLUMEID | ||
| 820 | ### help | ||
| 821 | ### TODO | ||
| 822 | |||
| 823 | config FEATURE_VOLUMEID_CRAMFS | ||
| 824 | bool "cramfs filesystem" | ||
| 825 | default y | ||
| 826 | depends on VOLUMEID | ||
| 827 | help | ||
| 828 | TODO | ||
| 829 | |||
| 830 | ### config FEATURE_VOLUMEID_HPFS | ||
| 831 | ### bool "hpfs filesystem" | ||
| 832 | ### default y | ||
| 833 | ### depends on VOLUMEID | ||
| 834 | ### help | ||
| 835 | ### TODO | ||
| 836 | |||
| 837 | config FEATURE_VOLUMEID_ROMFS | ||
| 838 | bool "romfs filesystem" | ||
| 839 | default y | ||
| 840 | depends on VOLUMEID | ||
| 841 | help | ||
| 842 | TODO | ||
| 843 | |||
| 844 | config FEATURE_VOLUMEID_SQUASHFS | ||
| 845 | bool "SquashFS filesystem" | ||
| 846 | default y | ||
| 847 | depends on VOLUMEID && FEATURE_BLKID_TYPE | ||
| 848 | help | ||
| 849 | Squashfs is a compressed read-only filesystem for Linux. Squashfs is | ||
| 850 | intended for general read-only filesystem use and in constrained block | ||
| 851 | device/memory systems (e.g. embedded systems) where low overhead is | ||
| 852 | needed. | ||
| 853 | |||
| 854 | config FEATURE_VOLUMEID_SYSV | ||
| 855 | bool "sysv filesystem" | ||
| 856 | default y | ||
| 857 | depends on VOLUMEID | ||
| 858 | help | ||
| 859 | TODO | ||
| 860 | |||
| 861 | ### config FEATURE_VOLUMEID_MINIX | ||
| 862 | ### bool "minix filesystem" | ||
| 863 | ### default y | ||
| 864 | ### depends on VOLUMEID | ||
| 865 | ### help | ||
| 866 | ### TODO | ||
| 867 | |||
| 868 | ### These only detect partition tables - not used (yet?) | ||
| 869 | ### config FEATURE_VOLUMEID_MAC | ||
| 870 | ### bool "mac filesystem" | ||
| 871 | ### default y | ||
| 872 | ### depends on VOLUMEID | ||
| 873 | ### help | ||
| 874 | ### TODO | ||
| 875 | ### | ||
| 876 | ### config FEATURE_VOLUMEID_MSDOS | ||
| 877 | ### bool "msdos filesystem" | ||
| 878 | ### default y | ||
| 879 | ### depends on VOLUMEID | ||
| 880 | ### help | ||
| 881 | ### TODO | ||
| 882 | |||
| 883 | config FEATURE_VOLUMEID_OCFS2 | ||
| 884 | bool "ocfs2 filesystem" | ||
| 885 | default y | ||
| 886 | depends on VOLUMEID | ||
| 887 | help | ||
| 888 | TODO | ||
| 889 | |||
| 890 | ### config FEATURE_VOLUMEID_HIGHPOINTRAID | ||
| 891 | ### bool "highpoint raid" | ||
| 892 | ### default y | ||
| 893 | ### depends on VOLUMEID | ||
| 894 | ### help | ||
| 895 | ### TODO | ||
| 896 | |||
| 897 | ### config FEATURE_VOLUMEID_ISWRAID | ||
| 898 | ### bool "intel raid" | ||
| 899 | ### default y | ||
| 900 | ### depends on VOLUMEID | ||
| 901 | ### help | ||
| 902 | ### TODO | ||
| 903 | |||
| 904 | ### config FEATURE_VOLUMEID_LSIRAID | ||
| 905 | ### bool "lsi raid" | ||
| 906 | ### default y | ||
| 907 | ### depends on VOLUMEID | ||
| 908 | ### help | ||
| 909 | ### TODO | ||
| 910 | |||
| 911 | ### config FEATURE_VOLUMEID_VIARAID | ||
| 912 | ### bool "via raid" | ||
| 913 | ### default y | ||
| 914 | ### depends on VOLUMEID | ||
| 915 | ### help | ||
| 916 | ### TODO | ||
| 917 | |||
| 918 | ### config FEATURE_VOLUMEID_SILICONRAID | ||
| 919 | ### bool "silicon raid" | ||
| 920 | ### default y | ||
| 921 | ### depends on VOLUMEID | ||
| 922 | ### help | ||
| 923 | ### TODO | ||
| 924 | |||
| 925 | ### config FEATURE_VOLUMEID_NVIDIARAID | ||
| 926 | ### bool "nvidia raid" | ||
| 927 | ### default y | ||
| 928 | ### depends on VOLUMEID | ||
| 929 | ### help | ||
| 930 | ### TODO | ||
| 931 | |||
| 932 | ### config FEATURE_VOLUMEID_PROMISERAID | ||
| 933 | ### bool "promise raid" | ||
| 934 | ### default y | ||
| 935 | ### depends on VOLUMEID | ||
| 936 | ### help | ||
| 937 | ### TODO | ||
| 938 | |||
| 939 | config FEATURE_VOLUMEID_LINUXRAID | ||
| 940 | bool "linuxraid" | ||
| 941 | default y | ||
| 942 | depends on VOLUMEID | ||
| 943 | help | ||
| 944 | TODO | ||
| 945 | |||
| 946 | endmenu | ||
| 947 | 703 | ||
| 948 | endmenu | 704 | endmenu |
diff --git a/util-linux/fdisk_gpt.c b/util-linux/fdisk_gpt.c index d43d9c709..f45f68af0 100644 --- a/util-linux/fdisk_gpt.c +++ b/util-linux/fdisk_gpt.c | |||
| @@ -95,7 +95,7 @@ gpt_list_table(int xtra UNUSED_PARAM) | |||
| 95 | 95 | ||
| 96 | numstr6[5] = '\0'; | 96 | numstr6[5] = '\0'; |
| 97 | 97 | ||
| 98 | smart_ulltoa5(total_number_of_sectors, numstr6, " KMGTPEZY"); | 98 | smart_ulltoa5(total_number_of_sectors * sector_size, numstr6, " KMGTPEZY"); |
| 99 | printf("Disk %s: %llu sectors, %s\n", disk_device, | 99 | printf("Disk %s: %llu sectors, %s\n", disk_device, |
| 100 | (unsigned long long)total_number_of_sectors, | 100 | (unsigned long long)total_number_of_sectors, |
| 101 | numstr6); | 101 | numstr6); |
| @@ -112,7 +112,7 @@ gpt_list_table(int xtra UNUSED_PARAM) | |||
| 112 | for (i = 0; i < n_parts; i++) { | 112 | for (i = 0; i < n_parts; i++) { |
| 113 | gpt_partition *p = gpt_part(i); | 113 | gpt_partition *p = gpt_part(i); |
| 114 | if (p->lba_start) { | 114 | if (p->lba_start) { |
| 115 | smart_ulltoa5(1 + SWAP_LE64(p->lba_end) - SWAP_LE64(p->lba_start), | 115 | smart_ulltoa5((1 + SWAP_LE64(p->lba_end) - SWAP_LE64(p->lba_start)) * sector_size, |
| 116 | numstr6, " KMGTPEZY"); | 116 | numstr6, " KMGTPEZY"); |
| 117 | printf("%4u %15llu %15llu %11s %04x ", | 117 | printf("%4u %15llu %15llu %11s %04x ", |
| 118 | i + 1, | 118 | i + 1, |
diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 4d998b916..ac7e24ff8 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c | |||
| @@ -66,13 +66,6 @@ static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\""; | |||
| 66 | 66 | ||
| 67 | static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v" IF_FEATURE_HEXDUMP_REVERSE("R"); | 67 | static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v" IF_FEATURE_HEXDUMP_REVERSE("R"); |
| 68 | 68 | ||
| 69 | static const struct suffix_mult suffixes[] = { | ||
| 70 | { "b", 512 }, | ||
| 71 | { "k", 1024 }, | ||
| 72 | { "m", 1024*1024 }, | ||
| 73 | { "", 0 } | ||
| 74 | }; | ||
| 75 | |||
| 76 | int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 69 | int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 77 | int hexdump_main(int argc, char **argv) | 70 | int hexdump_main(int argc, char **argv) |
| 78 | { | 71 | { |
| @@ -120,7 +113,7 @@ int hexdump_main(int argc, char **argv) | |||
| 120 | optarg, | 113 | optarg, |
| 121 | /*base:*/ 0, | 114 | /*base:*/ 0, |
| 122 | /*lo:*/ 0, /*hi:*/ OFF_T_MAX, | 115 | /*lo:*/ 0, /*hi:*/ OFF_T_MAX, |
| 123 | suffixes | 116 | bkm_suffixes |
| 124 | ); | 117 | ); |
| 125 | } /* else */ | 118 | } /* else */ |
| 126 | if (ch == 'v') { | 119 | if (ch == 'v') { |
diff --git a/util-linux/losetup.c b/util-linux/losetup.c index c69763335..d450b5a78 100644 --- a/util-linux/losetup.c +++ b/util-linux/losetup.c | |||
| @@ -10,12 +10,12 @@ | |||
| 10 | //usage:#define losetup_trivial_usage | 10 | //usage:#define losetup_trivial_usage |
| 11 | //usage: "[-r] [-o OFS] {-f|LOOPDEV} FILE - associate loop devices\n" | 11 | //usage: "[-r] [-o OFS] {-f|LOOPDEV} FILE - associate loop devices\n" |
| 12 | //usage: " losetup -d LOOPDEV - disassociate\n" | 12 | //usage: " losetup -d LOOPDEV - disassociate\n" |
| 13 | //usage: " losetup -a - show status of all\n" | 13 | //usage: " losetup -a - show status\n" |
| 14 | //usage: " losetup -f - show next available" | 14 | //usage: " losetup -f - show next free loop device" |
| 15 | //usage:#define losetup_full_usage "\n\n" | 15 | //usage:#define losetup_full_usage "\n\n" |
| 16 | //usage: " -o OFS Start OFS bytes into FILE" | 16 | //usage: " -o OFS Start OFS bytes into FILE" |
| 17 | //usage: "\n -r Read-only" | 17 | //usage: "\n -r Read-only" |
| 18 | //usage: "\n -f Show/find first free loop device" | 18 | //usage: "\n -f Show/use next free loop device" |
| 19 | //usage: | 19 | //usage: |
| 20 | //usage:#define losetup_notes_usage | 20 | //usage:#define losetup_notes_usage |
| 21 | //usage: "One argument (losetup /dev/loop1) will display the current association\n" | 21 | //usage: "One argument (losetup /dev/loop1) will display the current association\n" |
| @@ -27,6 +27,10 @@ | |||
| 27 | 27 | ||
| 28 | #include "libbb.h" | 28 | #include "libbb.h" |
| 29 | 29 | ||
| 30 | /* 1048575 is a max possible minor number in Linux circa 2010 */ | ||
| 31 | /* for now use something less extreme */ | ||
| 32 | #define MAX_LOOP_NUM 1023 | ||
| 33 | |||
| 30 | int losetup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 34 | int losetup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 31 | int losetup_main(int argc UNUSED_PARAM, char **argv) | 35 | int losetup_main(int argc UNUSED_PARAM, char **argv) |
| 32 | { | 36 | { |
| @@ -59,7 +63,7 @@ int losetup_main(int argc UNUSED_PARAM, char **argv) | |||
| 59 | } | 63 | } |
| 60 | 64 | ||
| 61 | /* -d LOOPDEV */ | 65 | /* -d LOOPDEV */ |
| 62 | if (opt == OPT_d) { | 66 | if (opt == OPT_d && argv[0]) { |
| 63 | if (del_loop(argv[0])) | 67 | if (del_loop(argv[0])) |
| 64 | bb_simple_perror_msg_and_die(argv[0]); | 68 | bb_simple_perror_msg_and_die(argv[0]); |
| 65 | return EXIT_SUCCESS; | 69 | return EXIT_SUCCESS; |
| @@ -68,15 +72,14 @@ int losetup_main(int argc UNUSED_PARAM, char **argv) | |||
| 68 | /* -a */ | 72 | /* -a */ |
| 69 | if (opt == OPT_a) { | 73 | if (opt == OPT_a) { |
| 70 | int n; | 74 | int n; |
| 71 | for (n = 0; n < 10; n++) { | 75 | for (n = 0; n < MAX_LOOP_NUM; n++) { |
| 72 | char *s; | 76 | char *s; |
| 73 | 77 | ||
| 74 | sprintf(dev, LOOP_FORMAT, n); | 78 | sprintf(dev, LOOP_FORMAT, n); |
| 75 | s = query_loop(dev); | 79 | s = query_loop(dev); |
| 76 | if (s) { | 80 | if (s) { |
| 77 | printf("%s: %s\n", dev, s); | 81 | printf("%s: %s\n", dev, s); |
| 78 | if (ENABLE_FEATURE_CLEAN_UP) | 82 | free(s); |
| 79 | free(s); | ||
| 80 | } | 83 | } |
| 81 | } | 84 | } |
| 82 | return EXIT_SUCCESS; | 85 | return EXIT_SUCCESS; |
| @@ -88,11 +91,13 @@ int losetup_main(int argc UNUSED_PARAM, char **argv) | |||
| 88 | int n = 0; | 91 | int n = 0; |
| 89 | 92 | ||
| 90 | do { | 93 | do { |
| 91 | sprintf(dev, LOOP_FORMAT, n); | 94 | if (n > MAX_LOOP_NUM) |
| 95 | bb_error_msg_and_die("no free loop devices"); | ||
| 96 | sprintf(dev, LOOP_FORMAT, n++); | ||
| 92 | s = query_loop(dev); | 97 | s = query_loop(dev); |
| 93 | if (s && ENABLE_FEATURE_CLEAN_UP) | 98 | free(s); |
| 94 | free(s); | ||
| 95 | } while (s); | 99 | } while (s); |
| 100 | /* now: dev is next free "/dev/loopN" */ | ||
| 96 | if ((opt == OPT_f) && !argv[0]) { | 101 | if ((opt == OPT_f) && !argv[0]) { |
| 97 | puts(dev); | 102 | puts(dev); |
| 98 | return EXIT_SUCCESS; | 103 | return EXIT_SUCCESS; |
| @@ -104,18 +109,18 @@ int losetup_main(int argc UNUSED_PARAM, char **argv) | |||
| 104 | unsigned long long offset = 0; | 109 | unsigned long long offset = 0; |
| 105 | char *d = dev; | 110 | char *d = dev; |
| 106 | 111 | ||
| 107 | if (opt == OPT_o) | 112 | if (opt & OPT_o) |
| 108 | offset = xatoull(opt_o); | 113 | offset = xatoull(opt_o); |
| 109 | if (opt != OPT_f) | 114 | if (!(opt & OPT_f)) |
| 110 | d = *(argv++); | 115 | d = *argv++; |
| 111 | 116 | ||
| 112 | if (argv[0]) { | 117 | if (argv[0]) { |
| 113 | if (set_loop(&d, argv[0], offset, (opt / OPT_r)) < 0) | 118 | if (set_loop(&d, argv[0], offset, (opt & OPT_r)) < 0) |
| 114 | bb_simple_perror_msg_and_die(argv[0]); | 119 | bb_simple_perror_msg_and_die(argv[0]); |
| 115 | return EXIT_SUCCESS; | 120 | return EXIT_SUCCESS; |
| 116 | } | 121 | } |
| 117 | } | 122 | } |
| 118 | 123 | ||
| 119 | bb_show_usage(); | 124 | bb_show_usage(); /* does not return */ |
| 120 | return EXIT_FAILURE; | 125 | /*return EXIT_FAILURE;*/ |
| 121 | } | 126 | } |
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 1d741367e..e80b58f2e 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
| @@ -295,8 +295,8 @@ struct globals { | |||
| 295 | /* Prevent infinite loops in /sys symlinks */ | 295 | /* Prevent infinite loops in /sys symlinks */ |
| 296 | #define MAX_SYSFS_DEPTH 3 | 296 | #define MAX_SYSFS_DEPTH 3 |
| 297 | 297 | ||
| 298 | /* We use additional 64+ bytes in make_device() */ | 298 | /* We use additional bytes in make_device() */ |
| 299 | #define SCRATCH_SIZE 80 | 299 | #define SCRATCH_SIZE 128 |
| 300 | 300 | ||
| 301 | #if ENABLE_FEATURE_MDEV_CONF | 301 | #if ENABLE_FEATURE_MDEV_CONF |
| 302 | 302 | ||
| @@ -541,7 +541,7 @@ static char *build_alias(char *alias, const char *device_name) | |||
| 541 | 541 | ||
| 542 | /* mknod in /dev based on a path like "/sys/block/hda/hda1" | 542 | /* mknod in /dev based on a path like "/sys/block/hda/hda1" |
| 543 | * NB1: path parameter needs to have SCRATCH_SIZE scratch bytes | 543 | * NB1: path parameter needs to have SCRATCH_SIZE scratch bytes |
| 544 | * after NUL, but we promise to not mangle (IOW: to restore if needed) | 544 | * after NUL, but we promise to not mangle (IOW: to restore NUL if needed) |
| 545 | * path string. | 545 | * path string. |
| 546 | * NB2: "mdev -s" may call us many times, do not leak memory/fds! | 546 | * NB2: "mdev -s" may call us many times, do not leak memory/fds! |
| 547 | * | 547 | * |
| @@ -551,6 +551,7 @@ static char *build_alias(char *alias, const char *device_name) | |||
| 551 | static void make_device(char *device_name, char *path, int operation) | 551 | static void make_device(char *device_name, char *path, int operation) |
| 552 | { | 552 | { |
| 553 | int major, minor, type, len; | 553 | int major, minor, type, len; |
| 554 | char *path_end = path + strlen(path); | ||
| 554 | 555 | ||
| 555 | /* Try to read major/minor string. Note that the kernel puts \n after | 556 | /* Try to read major/minor string. Note that the kernel puts \n after |
| 556 | * the data, so we don't need to worry about null terminating the string | 557 | * the data, so we don't need to worry about null terminating the string |
| @@ -559,17 +560,15 @@ static void make_device(char *device_name, char *path, int operation) | |||
| 559 | */ | 560 | */ |
| 560 | major = -1; | 561 | major = -1; |
| 561 | if (operation == OP_add) { | 562 | if (operation == OP_add) { |
| 562 | char *dev_maj_min = path + strlen(path); | 563 | strcpy(path_end, "/dev"); |
| 563 | 564 | len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1); | |
| 564 | strcpy(dev_maj_min, "/dev"); | 565 | *path_end = '\0'; |
| 565 | len = open_read_close(path, dev_maj_min + 1, 64); | ||
| 566 | *dev_maj_min = '\0'; | ||
| 567 | if (len < 1) { | 566 | if (len < 1) { |
| 568 | if (!ENABLE_FEATURE_MDEV_EXEC) | 567 | if (!ENABLE_FEATURE_MDEV_EXEC) |
| 569 | return; | 568 | return; |
| 570 | /* no "dev" file, but we can still run scripts | 569 | /* no "dev" file, but we can still run scripts |
| 571 | * based on device name */ | 570 | * based on device name */ |
| 572 | } else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) == 2) { | 571 | } else if (sscanf(path_end + 1, "%u:%u", &major, &minor) == 2) { |
| 573 | dbg1("dev %u,%u", major, minor); | 572 | dbg1("dev %u,%u", major, minor); |
| 574 | } else { | 573 | } else { |
| 575 | major = -1; | 574 | major = -1; |
| @@ -577,9 +576,33 @@ static void make_device(char *device_name, char *path, int operation) | |||
| 577 | } | 576 | } |
| 578 | /* else: for delete, -1 still deletes the node, but < -1 suppresses that */ | 577 | /* else: for delete, -1 still deletes the node, but < -1 suppresses that */ |
| 579 | 578 | ||
| 580 | /* Determine device name, type, major and minor */ | 579 | /* Determine device name */ |
| 581 | if (!device_name) | 580 | if (!device_name) { |
| 582 | device_name = (char*) bb_basename(path); | 581 | /* |
| 582 | * There was no $DEVNAME envvar (for example, mdev -s never has). | ||
| 583 | * But it is very useful: it contains the *path*, not only basename, | ||
| 584 | * Thankfully, uevent file has it. | ||
| 585 | * Example of .../sound/card0/controlC0/uevent file on Linux-3.7.7: | ||
| 586 | * MAJOR=116 | ||
| 587 | * MINOR=7 | ||
| 588 | * DEVNAME=snd/controlC0 | ||
| 589 | */ | ||
| 590 | strcpy(path_end, "/uevent"); | ||
| 591 | len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1); | ||
| 592 | if (len < 0) | ||
| 593 | len = 0; | ||
| 594 | *path_end = '\0'; | ||
| 595 | path_end[1 + len] = '\0'; | ||
| 596 | device_name = strstr(path_end + 1, "\nDEVNAME="); | ||
| 597 | if (device_name) { | ||
| 598 | device_name += sizeof("\nDEVNAME=")-1; | ||
| 599 | strchrnul(device_name, '\n')[0] = '\0'; | ||
| 600 | } else { | ||
| 601 | /* Fall back to just basename */ | ||
| 602 | device_name = (char*) bb_basename(path); | ||
| 603 | } | ||
| 604 | } | ||
| 605 | /* Determine device type */ | ||
| 583 | /* | 606 | /* |
| 584 | * http://kernel.org/doc/pending/hotplug.txt says that only | 607 | * http://kernel.org/doc/pending/hotplug.txt says that only |
| 585 | * "/sys/block/..." is for block devices. "/sys/bus" etc is not. | 608 | * "/sys/block/..." is for block devices. "/sys/bus" etc is not. |
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c index 54867ec36..afad4ab8f 100644 --- a/util-linux/swaponoff.c +++ b/util-linux/swaponoff.c | |||
| @@ -95,6 +95,20 @@ static int do_em_all(void) | |||
| 95 | if (applet_name[5] != 'n' | 95 | if (applet_name[5] != 'n' |
| 96 | || hasmntopt(m, MNTOPT_NOAUTO) == NULL | 96 | || hasmntopt(m, MNTOPT_NOAUTO) == NULL |
| 97 | ) { | 97 | ) { |
| 98 | #if ENABLE_FEATURE_SWAPON_PRI | ||
| 99 | char *p; | ||
| 100 | g_flags = 0; /* each swap space might have different flags */ | ||
| 101 | p = strstr(m->mnt_opts, "pri="); | ||
| 102 | if (p) { | ||
| 103 | /* Max allowed 32767 (==SWAP_FLAG_PRIO_MASK) */ | ||
| 104 | int swap_prio = MIN(bb_strtoull(p + 4 , NULL, 10), SWAP_FLAG_PRIO_MASK); | ||
| 105 | /* We want to allow "NNNN,foo", thus errno == EINVAL is allowed too */ | ||
| 106 | if (errno != ERANGE) { | ||
| 107 | g_flags = SWAP_FLAG_PREFER | | ||
| 108 | (swap_prio << SWAP_FLAG_PRIO_SHIFT); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | #endif | ||
| 98 | err += swap_enable_disable(m->mnt_fsname); | 112 | err += swap_enable_disable(m->mnt_fsname); |
| 99 | } | 113 | } |
| 100 | } | 114 | } |
diff --git a/util-linux/volume_id/Config.src b/util-linux/volume_id/Config.src new file mode 100644 index 000000000..ac208c9cc --- /dev/null +++ b/util-linux/volume_id/Config.src | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | # | ||
| 2 | # For a description of the syntax of this configuration file, | ||
| 3 | # see scripts/kbuild/config-language.txt. | ||
| 4 | # | ||
| 5 | |||
| 6 | config VOLUMEID | ||
| 7 | bool #No description makes it a hidden option | ||
| 8 | default n | ||
| 9 | |||
| 10 | menu "Filesystem/Volume identification" | ||
| 11 | depends on VOLUMEID | ||
| 12 | |||
| 13 | INSERT | ||
| 14 | |||
| 15 | endmenu | ||
diff --git a/util-linux/volume_id/Kbuild.src b/util-linux/volume_id/Kbuild.src index 759fdaae5..6b4fb7470 100644 --- a/util-linux/volume_id/Kbuild.src +++ b/util-linux/volume_id/Kbuild.src | |||
| @@ -7,41 +7,3 @@ | |||
| 7 | lib-y:= | 7 | lib-y:= |
| 8 | 8 | ||
| 9 | INSERT | 9 | INSERT |
| 10 | |||
| 11 | lib-$(CONFIG_BLKID) += get_devname.o | ||
| 12 | lib-$(CONFIG_FINDFS) += get_devname.o | ||
| 13 | lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o | ||
| 14 | |||
| 15 | lib-$(CONFIG_VOLUMEID) += volume_id.o util.o | ||
| 16 | lib-$(CONFIG_FEATURE_VOLUMEID_BTRFS) += btrfs.o | ||
| 17 | lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o | ||
| 18 | lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o | ||
| 19 | lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o | ||
| 20 | ### lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o | ||
| 21 | ### lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o | ||
| 22 | ### lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o | ||
| 23 | ### lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o | ||
| 24 | ### lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o | ||
| 25 | ### lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o | ||
| 26 | ### lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o | ||
| 27 | lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o | ||
| 28 | lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o | ||
| 29 | lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o | ||
| 30 | lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o | ||
| 31 | ### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o | ||
| 32 | ### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o | ||
| 33 | ### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o | ||
| 34 | lib-$(CONFIG_FEATURE_VOLUMEID_NILFS) += nilfs.o | ||
| 35 | lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o | ||
| 36 | lib-$(CONFIG_FEATURE_VOLUMEID_EXFAT) += exfat.o | ||
| 37 | lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o | ||
| 38 | lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o | ||
| 39 | ### lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o | ||
| 40 | lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o | ||
| 41 | lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o | ||
| 42 | ### lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o | ||
| 43 | lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o | ||
| 44 | lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o | ||
| 45 | ### lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o | ||
| 46 | lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o | ||
| 47 | lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o | ||
diff --git a/util-linux/volume_id/btrfs.c b/util-linux/volume_id/btrfs.c index ee71d2e00..e4dddf26d 100644 --- a/util-linux/volume_id/btrfs.c +++ b/util-linux/volume_id/btrfs.c | |||
| @@ -19,6 +19,17 @@ | |||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BTRFS) += btrfs.o | ||
| 23 | |||
| 24 | //config: | ||
| 25 | //config:config FEATURE_VOLUMEID_BTRFS | ||
| 26 | //config: bool "btrfs filesystem" | ||
| 27 | //config: default y | ||
| 28 | //config: depends on VOLUMEID | ||
| 29 | //config: help | ||
| 30 | //config: TODO | ||
| 31 | //config: | ||
| 32 | |||
| 22 | #include "volume_id_internal.h" | 33 | #include "volume_id_internal.h" |
| 23 | 34 | ||
| 24 | #define BTRFS_UUID_SIZE 16 | 35 | #define BTRFS_UUID_SIZE 16 |
diff --git a/util-linux/volume_id/cramfs.c b/util-linux/volume_id/cramfs.c index 28e997043..aeb7f20ac 100644 --- a/util-linux/volume_id/cramfs.c +++ b/util-linux/volume_id/cramfs.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_CRAMFS | ||
| 25 | //config: bool "cramfs filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct cramfs_super { | 34 | struct cramfs_super { |
diff --git a/util-linux/volume_id/exfat.c b/util-linux/volume_id/exfat.c index a38a8916d..c3aa36804 100644 --- a/util-linux/volume_id/exfat.c +++ b/util-linux/volume_id/exfat.c | |||
| @@ -18,6 +18,19 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXFAT) += exfat.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_EXFAT | ||
| 25 | //config: bool "exFAT filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: exFAT (extended FAT) is a proprietary file system designed especially | ||
| 30 | //config: for flash drives. It has many features from NTFS, but with less | ||
| 31 | //config: overhead. exFAT is used on most SDXC cards for consumer electronics. | ||
| 32 | //config: | ||
| 33 | |||
| 21 | #include "volume_id_internal.h" | 34 | #include "volume_id_internal.h" |
| 22 | 35 | ||
| 23 | #define EXFAT_SB_OFFSET 0 | 36 | #define EXFAT_SB_OFFSET 0 |
diff --git a/util-linux/volume_id/ext.c b/util-linux/volume_id/ext.c index 97451067f..df39d9342 100644 --- a/util-linux/volume_id/ext.c +++ b/util-linux/volume_id/ext.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_EXT | ||
| 25 | //config: bool "Ext filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | #include "bb_e2fs_defs.h" | 33 | #include "bb_e2fs_defs.h" |
| 23 | 34 | ||
diff --git a/util-linux/volume_id/f2fs.c b/util-linux/volume_id/f2fs.c new file mode 100644 index 000000000..bf0b66278 --- /dev/null +++ b/util-linux/volume_id/f2fs.c | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | /* | ||
| 2 | * volume_id - reads filesystem label and uuid | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 S-G Bergh <sgb@systemasis.org> | ||
| 5 | * | ||
| 6 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 7 | */ | ||
| 8 | |||
| 9 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_F2FS) += f2fs.o | ||
| 10 | |||
| 11 | //config: | ||
| 12 | //config:config FEATURE_VOLUMEID_F2FS | ||
| 13 | //config: bool "f2fs filesystem" | ||
| 14 | //config: default y | ||
| 15 | //config: depends on VOLUMEID | ||
| 16 | //config: help | ||
| 17 | //config: F2FS (aka Flash-Friendly File System) is a log-structured file system, | ||
| 18 | //config: which is adapted to newer forms of storage. F2FS also remedies some | ||
| 19 | //config: known issues of the older log structured file systems, such as high | ||
| 20 | //config: cleaning overhead. | ||
| 21 | //config: | ||
| 22 | |||
| 23 | #include "volume_id_internal.h" | ||
| 24 | |||
| 25 | #define F2FS_MAGIC 0xF2F52010 // F2FS Magic Number | ||
| 26 | #define F2FS_UUID_SIZE 16 | ||
| 27 | #define F2FS_LABEL_SIZE 512 | ||
| 28 | #define F2FS_LABEL_BYTES 1024 | ||
| 29 | #define F2FS_SB1_OFFSET 0x400 // offset for 1:st super block | ||
| 30 | /* | ||
| 31 | #define F2FS_SB2_OFFSET 0x1400 // offset for 2:nd super block | ||
| 32 | */ | ||
| 33 | |||
| 34 | struct f2fs_super_block { // According to version 1.1 | ||
| 35 | /* 0x00 */ uint32_t magic; // Magic Number | ||
| 36 | /* 0x04 */ uint16_t major_ver; // Major Version | ||
| 37 | /* 0x06 */ uint16_t minor_ver; // Minor Version | ||
| 38 | /* 0x08 */ uint32_t log_sectorsize; // log2 sector size in bytes | ||
| 39 | /* 0x0C */ uint32_t log_sectors_per_block; // log2 # of sectors per block | ||
| 40 | /* 0x10 */ uint32_t log_blocksize; // log2 block size in bytes | ||
| 41 | /* 0x14 */ uint32_t log_blocks_per_seg; // log2 # of blocks per segment | ||
| 42 | /* 0x18 */ uint32_t segs_per_sec; // # of segments per section | ||
| 43 | /* 0x1C */ uint32_t secs_per_zone; // # of sections per zone | ||
| 44 | /* 0x20 */ uint32_t checksum_offset; // checksum offset inside super block | ||
| 45 | /* 0x24 */ uint64_t block_count; // total # of user blocks | ||
| 46 | /* 0x2C */ uint32_t section_count; // total # of sections | ||
| 47 | /* 0x30 */ uint32_t segment_count; // total # of segments | ||
| 48 | /* 0x34 */ uint32_t segment_count_ckpt; // # of segments for checkpoint | ||
| 49 | /* 0x38 */ uint32_t segment_count_sit; // # of segments for SIT | ||
| 50 | /* 0x3C */ uint32_t segment_count_nat; // # of segments for NAT | ||
| 51 | /* 0x40 */ uint32_t segment_count_ssa; // # of segments for SSA | ||
| 52 | /* 0x44 */ uint32_t segment_count_main; // # of segments for main area | ||
| 53 | /* 0x48 */ uint32_t segment0_blkaddr; // start block address of segment 0 | ||
| 54 | /* 0x4C */ uint32_t cp_blkaddr; // start block address of checkpoint | ||
| 55 | /* 0x50 */ uint32_t sit_blkaddr; // start block address of SIT | ||
| 56 | /* 0x54 */ uint32_t nat_blkaddr; // start block address of NAT | ||
| 57 | /* 0x58 */ uint32_t ssa_blkaddr; // start block address of SSA | ||
| 58 | /* 0x5C */ uint32_t main_blkaddr; // start block address of main area | ||
| 59 | /* 0x60 */ uint32_t root_ino; // root inode number | ||
| 60 | /* 0x64 */ uint32_t node_ino; // node inode number | ||
| 61 | /* 0x68 */ uint32_t meta_ino; // meta inode number | ||
| 62 | /* 0x6C */ uint8_t uuid[F2FS_UUID_SIZE]; // 128-bit uuid for volume | ||
| 63 | /* 0x7C */ uint16_t volume_name[F2FS_LABEL_SIZE]; // volume name | ||
| 64 | // /* 0x47C */ uint32_t extension_count; // # of extensions below | ||
| 65 | // /* 0x480 */ uint8_t extension_list[64][8]; // extension array | ||
| 66 | } PACKED; | ||
| 67 | |||
| 68 | |||
| 69 | int FAST_FUNC volume_id_probe_f2fs(struct volume_id *id /*,uint64_t off*/) | ||
| 70 | { | ||
| 71 | struct f2fs_super_block *sb; | ||
| 72 | |||
| 73 | // Go for primary super block (ignore second sb) | ||
| 74 | dbg("f2fs: probing at offset 0x%x", F2FS_SB1_OFFSET); | ||
| 75 | sb = volume_id_get_buffer(id, F2FS_SB1_OFFSET, sizeof(*sb)); | ||
| 76 | |||
| 77 | if (!sb) | ||
| 78 | return -1; | ||
| 79 | |||
| 80 | if (sb->magic != cpu_to_le32(F2FS_MAGIC)) | ||
| 81 | return -1; | ||
| 82 | |||
| 83 | IF_FEATURE_BLKID_TYPE(id->type = "f2fs"); | ||
| 84 | |||
| 85 | // For version 1.0 we don't know sb structure and can't set label/uuid | ||
| 86 | if (sb->major_ver == cpu_to_le16(1) && sb->minor_ver == cpu_to_le16(0)) | ||
| 87 | return 0; | ||
| 88 | |||
| 89 | volume_id_set_label_unicode16(id, (uint8_t *)sb->volume_name, | ||
| 90 | LE, MIN(F2FS_LABEL_BYTES, VOLUME_ID_LABEL_SIZE)); | ||
| 91 | |||
| 92 | volume_id_set_uuid(id, sb->uuid, UUID_DCE); | ||
| 93 | |||
| 94 | return 0; | ||
| 95 | } | ||
diff --git a/util-linux/volume_id/fat.c b/util-linux/volume_id/fat.c index 904fbb201..476d500a6 100644 --- a/util-linux/volume_id/fat.c +++ b/util-linux/volume_id/fat.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_FAT | ||
| 25 | //config: bool "fat filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | /* linux/msdos_fs.h says: */ | 34 | /* linux/msdos_fs.h says: */ |
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c index 665cb9b6e..0c6bdfddf 100644 --- a/util-linux/volume_id/get_devname.c +++ b/util-linux/volume_id/get_devname.c | |||
| @@ -7,6 +7,11 @@ | |||
| 7 | * | 7 | * |
| 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| 9 | */ | 9 | */ |
| 10 | |||
| 11 | //kbuild:lib-$(CONFIG_BLKID) += get_devname.o | ||
| 12 | //kbuild:lib-$(CONFIG_FINDFS) += get_devname.o | ||
| 13 | //kbuild:lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o | ||
| 14 | |||
| 10 | #include <sys/mount.h> /* BLKGETSIZE64 */ | 15 | #include <sys/mount.h> /* BLKGETSIZE64 */ |
| 11 | #if !defined(BLKGETSIZE64) | 16 | #if !defined(BLKGETSIZE64) |
| 12 | # define BLKGETSIZE64 _IOR(0x12,114,size_t) | 17 | # define BLKGETSIZE64 _IOR(0x12,114,size_t) |
diff --git a/util-linux/volume_id/hfs.c b/util-linux/volume_id/hfs.c index 3d9704d12..8d34aaf68 100644 --- a/util-linux/volume_id/hfs.c +++ b/util-linux/volume_id/hfs.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_HFS | ||
| 25 | //config: bool "hfs filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct hfs_finder_info{ | 34 | struct hfs_finder_info{ |
diff --git a/util-linux/volume_id/iso9660.c b/util-linux/volume_id/iso9660.c index 1d7693a9c..3848de453 100644 --- a/util-linux/volume_id/iso9660.c +++ b/util-linux/volume_id/iso9660.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_ISO9660 | ||
| 25 | //config: bool "iso9660 filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | #define ISO_SUPERBLOCK_OFFSET 0x8000 | 34 | #define ISO_SUPERBLOCK_OFFSET 0x8000 |
diff --git a/util-linux/volume_id/jfs.c b/util-linux/volume_id/jfs.c index 5333af2c3..a6eaff45b 100644 --- a/util-linux/volume_id/jfs.c +++ b/util-linux/volume_id/jfs.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_JFS | ||
| 25 | //config: bool "jfs filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct jfs_super_block { | 34 | struct jfs_super_block { |
diff --git a/util-linux/volume_id/linux_raid.c b/util-linux/volume_id/linux_raid.c index 209eaabe9..f20823a6e 100644 --- a/util-linux/volume_id/linux_raid.c +++ b/util-linux/volume_id/linux_raid.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_LINUXRAID | ||
| 25 | //config: bool "linuxraid" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct mdp_super_block { | 34 | struct mdp_super_block { |
diff --git a/util-linux/volume_id/linux_swap.c b/util-linux/volume_id/linux_swap.c index 1ee534ab0..39470d48c 100644 --- a/util-linux/volume_id/linux_swap.c +++ b/util-linux/volume_id/linux_swap.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_LINUXSWAP | ||
| 25 | //config: bool "linux swap filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct swap_header_v1_2 { | 34 | struct swap_header_v1_2 { |
diff --git a/util-linux/volume_id/luks.c b/util-linux/volume_id/luks.c index f9b376672..42bf87659 100644 --- a/util-linux/volume_id/luks.c +++ b/util-linux/volume_id/luks.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_LUKS | ||
| 25 | //config: bool "luks filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | #define LUKS_MAGIC_L 6 | 34 | #define LUKS_MAGIC_L 6 |
diff --git a/util-linux/volume_id/nilfs.c b/util-linux/volume_id/nilfs.c index b88a9e435..f3a9ef58d 100644 --- a/util-linux/volume_id/nilfs.c +++ b/util-linux/volume_id/nilfs.c | |||
| @@ -19,6 +19,26 @@ | |||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NILFS) += nilfs.o | ||
| 23 | |||
| 24 | //config: | ||
| 25 | //config:config FEATURE_VOLUMEID_NILFS | ||
| 26 | //config: bool "nilfs filesystem" | ||
| 27 | //config: default y | ||
| 28 | //config: depends on VOLUMEID | ||
| 29 | //config: help | ||
| 30 | //config: NILFS is a New Implementation of a Log-Structured File System (LFS) | ||
| 31 | //config: that supports continuous snapshots. This provides features like | ||
| 32 | //config: versioning of the entire filesystem, restoration of files that | ||
| 33 | //config: were deleted a few minutes ago. NILFS keeps consistency like | ||
| 34 | //config: conventional LFS, so it provides quick recovery after system crashes. | ||
| 35 | //config: | ||
| 36 | //config: The possible use of NILFS includes versioning, tamper detection, | ||
| 37 | //config: SOX compliance logging, and so forth. It can serve as an alternative | ||
| 38 | //config: filesystem for Linux desktop environment, or as a basis of advanced | ||
| 39 | //config: storage appliances. | ||
| 40 | //config: | ||
| 41 | |||
| 22 | #include "volume_id_internal.h" | 42 | #include "volume_id_internal.h" |
| 23 | 43 | ||
| 24 | #define NILFS_UUID_SIZE 16 | 44 | #define NILFS_UUID_SIZE 16 |
diff --git a/util-linux/volume_id/ntfs.c b/util-linux/volume_id/ntfs.c index 7b2612f01..46f687a56 100644 --- a/util-linux/volume_id/ntfs.c +++ b/util-linux/volume_id/ntfs.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_NTFS | ||
| 25 | //config: bool "ntfs filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct ntfs_super_block { | 34 | struct ntfs_super_block { |
| @@ -150,7 +161,7 @@ int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/) | |||
| 150 | 161 | ||
| 151 | attr = (struct file_attribute*) &buf[attr_off]; | 162 | attr = (struct file_attribute*) &buf[attr_off]; |
| 152 | attr_type = le32_to_cpu(attr->type); | 163 | attr_type = le32_to_cpu(attr->type); |
| 153 | attr_len = le16_to_cpu(attr->len); | 164 | attr_len = le32_to_cpu(attr->len); |
| 154 | val_off = le16_to_cpu(attr->value_offset); | 165 | val_off = le16_to_cpu(attr->value_offset); |
| 155 | val_len = le32_to_cpu(attr->value_len); | 166 | val_len = le32_to_cpu(attr->value_len); |
| 156 | attr_off += attr_len; | 167 | attr_off += attr_len; |
diff --git a/util-linux/volume_id/ocfs2.c b/util-linux/volume_id/ocfs2.c index fcdb15192..415e0bf61 100644 --- a/util-linux/volume_id/ocfs2.c +++ b/util-linux/volume_id/ocfs2.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_OCFS2 | ||
| 25 | //config: bool "ocfs2 filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | /* All these values are taken from ocfs2-tools's ocfs2_fs.h */ | 34 | /* All these values are taken from ocfs2-tools's ocfs2_fs.h */ |
diff --git a/util-linux/volume_id/reiserfs.c b/util-linux/volume_id/reiserfs.c index 67b4a1877..24979fb1c 100644 --- a/util-linux/volume_id/reiserfs.c +++ b/util-linux/volume_id/reiserfs.c | |||
| @@ -19,6 +19,17 @@ | |||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o | ||
| 23 | |||
| 24 | //config: | ||
| 25 | //config:config FEATURE_VOLUMEID_REISERFS | ||
| 26 | //config: bool "Reiser filesystem" | ||
| 27 | //config: default y | ||
| 28 | //config: depends on VOLUMEID | ||
| 29 | //config: help | ||
| 30 | //config: TODO | ||
| 31 | //config: | ||
| 32 | |||
| 22 | #include "volume_id_internal.h" | 33 | #include "volume_id_internal.h" |
| 23 | 34 | ||
| 24 | struct reiserfs_super_block { | 35 | struct reiserfs_super_block { |
diff --git a/util-linux/volume_id/romfs.c b/util-linux/volume_id/romfs.c index 15653bedf..4754fdb37 100644 --- a/util-linux/volume_id/romfs.c +++ b/util-linux/volume_id/romfs.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_ROMFS | ||
| 25 | //config: bool "romfs filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct romfs_super { | 34 | struct romfs_super { |
diff --git a/util-linux/volume_id/squashfs.c b/util-linux/volume_id/squashfs.c index c5b4f9ced..079b6cc31 100644 --- a/util-linux/volume_id/squashfs.c +++ b/util-linux/volume_id/squashfs.c | |||
| @@ -8,6 +8,18 @@ | |||
| 8 | 8 | ||
| 9 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SQUASHFS) += squashfs.o | 9 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SQUASHFS) += squashfs.o |
| 10 | 10 | ||
| 11 | //config: | ||
| 12 | //config:config FEATURE_VOLUMEID_SQUASHFS | ||
| 13 | //config: bool "SquashFS filesystem" | ||
| 14 | //config: default y | ||
| 15 | //config: depends on VOLUMEID && FEATURE_BLKID_TYPE | ||
| 16 | //config: help | ||
| 17 | //config: Squashfs is a compressed read-only filesystem for Linux. Squashfs is | ||
| 18 | //config: intended for general read-only filesystem use and in constrained block | ||
| 19 | //config: device/memory systems (e.g. embedded systems) where low overhead is | ||
| 20 | //config: needed. | ||
| 21 | //config: | ||
| 22 | |||
| 11 | #include "volume_id_internal.h" | 23 | #include "volume_id_internal.h" |
| 12 | 24 | ||
| 13 | struct squashfs_superblock { | 25 | struct squashfs_superblock { |
diff --git a/util-linux/volume_id/sysv.c b/util-linux/volume_id/sysv.c index 6eb96464d..7b4b5360b 100644 --- a/util-linux/volume_id/sysv.c +++ b/util-linux/volume_id/sysv.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_SYSV | ||
| 25 | //config: bool "sysv filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | #define SYSV_NICINOD 100 | 34 | #define SYSV_NICINOD 100 |
diff --git a/util-linux/volume_id/udf.c b/util-linux/volume_id/udf.c index d3747fb8e..921454503 100644 --- a/util-linux/volume_id/udf.c +++ b/util-linux/volume_id/udf.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_UDF | ||
| 25 | //config: bool "udf filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct volume_descriptor { | 34 | struct volume_descriptor { |
diff --git a/util-linux/volume_id/unused_highpoint.c b/util-linux/volume_id/unused_highpoint.c index 17b7b3291..7231a1db2 100644 --- a/util-linux/volume_id/unused_highpoint.c +++ b/util-linux/volume_id/unused_highpoint.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_HIGHPOINTRAID | ||
| 25 | //config:### bool "highpoint raid" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct hpt37x_meta { | 34 | struct hpt37x_meta { |
diff --git a/util-linux/volume_id/unused_hpfs.c b/util-linux/volume_id/unused_hpfs.c index 442952464..a87c89fb3 100644 --- a/util-linux/volume_id/unused_hpfs.c +++ b/util-linux/volume_id/unused_hpfs.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_HPFS | ||
| 25 | //config:### bool "hpfs filesystem" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct hpfs_super { | 34 | struct hpfs_super { |
diff --git a/util-linux/volume_id/unused_isw_raid.c b/util-linux/volume_id/unused_isw_raid.c index 7ab47b3a1..851bd2f8f 100644 --- a/util-linux/volume_id/unused_isw_raid.c +++ b/util-linux/volume_id/unused_isw_raid.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_ISWRAID | ||
| 25 | //config:### bool "intel raid" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct isw_meta { | 34 | struct isw_meta { |
diff --git a/util-linux/volume_id/unused_lsi_raid.c b/util-linux/volume_id/unused_lsi_raid.c index e6cc8edd3..52d68deab 100644 --- a/util-linux/volume_id/unused_lsi_raid.c +++ b/util-linux/volume_id/unused_lsi_raid.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_LSIRAID | ||
| 25 | //config:### bool "lsi raid" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct lsi_meta { | 34 | struct lsi_meta { |
diff --git a/util-linux/volume_id/unused_lvm.c b/util-linux/volume_id/unused_lvm.c index 2206498bf..08fa05243 100644 --- a/util-linux/volume_id/unused_lvm.c +++ b/util-linux/volume_id/unused_lvm.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_LVM | ||
| 25 | //config:### bool "lvm" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct lvm1_super_block { | 34 | struct lvm1_super_block { |
diff --git a/util-linux/volume_id/unused_mac.c b/util-linux/volume_id/unused_mac.c index e8deb9720..a1a53d1fb 100644 --- a/util-linux/volume_id/unused_mac.c +++ b/util-linux/volume_id/unused_mac.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_MAC | ||
| 25 | //config:### bool "mac filesystem" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct mac_driver_desc { | 34 | struct mac_driver_desc { |
diff --git a/util-linux/volume_id/unused_minix.c b/util-linux/volume_id/unused_minix.c index a3e1077b0..50afd5c3e 100644 --- a/util-linux/volume_id/unused_minix.c +++ b/util-linux/volume_id/unused_minix.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_MINIX | ||
| 25 | //config:### bool "minix filesystem" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct minix_super_block { | 34 | struct minix_super_block { |
diff --git a/util-linux/volume_id/unused_msdos.c b/util-linux/volume_id/unused_msdos.c index 2e8cb196a..d2fc66caa 100644 --- a/util-linux/volume_id/unused_msdos.c +++ b/util-linux/volume_id/unused_msdos.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_MSDOS | ||
| 25 | //config:### bool "msdos filesystem" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct msdos_partition_entry { | 34 | struct msdos_partition_entry { |
diff --git a/util-linux/volume_id/unused_nvidia_raid.c b/util-linux/volume_id/unused_nvidia_raid.c index 9e8472921..d99a108f3 100644 --- a/util-linux/volume_id/unused_nvidia_raid.c +++ b/util-linux/volume_id/unused_nvidia_raid.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_NVIDIARAID | ||
| 25 | //config:### bool "nvidia raid" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct nvidia_meta { | 34 | struct nvidia_meta { |
diff --git a/util-linux/volume_id/unused_promise_raid.c b/util-linux/volume_id/unused_promise_raid.c index 0b0d0063c..cebebe35f 100644 --- a/util-linux/volume_id/unused_promise_raid.c +++ b/util-linux/volume_id/unused_promise_raid.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_PROMISERAID | ||
| 25 | //config:### bool "promise raid" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct promise_meta { | 34 | struct promise_meta { |
diff --git a/util-linux/volume_id/unused_silicon_raid.c b/util-linux/volume_id/unused_silicon_raid.c index 878b88197..40c8faa9e 100644 --- a/util-linux/volume_id/unused_silicon_raid.c +++ b/util-linux/volume_id/unused_silicon_raid.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_SILICONRAID | ||
| 25 | //config:### bool "silicon raid" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct silicon_meta { | 34 | struct silicon_meta { |
diff --git a/util-linux/volume_id/unused_ufs.c b/util-linux/volume_id/unused_ufs.c index 9f925d983..d33c10fc4 100644 --- a/util-linux/volume_id/unused_ufs.c +++ b/util-linux/volume_id/unused_ufs.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_UFS | ||
| 25 | //config:### bool "ufs filesystem" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct ufs_super_block { | 34 | struct ufs_super_block { |
diff --git a/util-linux/volume_id/unused_via_raid.c b/util-linux/volume_id/unused_via_raid.c index a11eec13a..258f93a4f 100644 --- a/util-linux/volume_id/unused_via_raid.c +++ b/util-linux/volume_id/unused_via_raid.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:### config FEATURE_VOLUMEID_VIARAID | ||
| 25 | //config:### bool "via raid" | ||
| 26 | //config:### default y | ||
| 27 | //config:### depends on VOLUMEID | ||
| 28 | //config:### help | ||
| 29 | //config:### TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct via_meta { | 34 | struct via_meta { |
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c index f0fc84c05..5c459a0e2 100644 --- a/util-linux/volume_id/volume_id.c +++ b/util-linux/volume_id/volume_id.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_VOLUMEID) += volume_id.o util.o | ||
| 22 | |||
| 21 | #include "volume_id_internal.h" | 23 | #include "volume_id_internal.h" |
| 22 | 24 | ||
| 23 | 25 | ||
| @@ -136,6 +138,9 @@ static const probe_fptr fs2[] = { | |||
| 136 | #if ENABLE_FEATURE_VOLUMEID_UFS | 138 | #if ENABLE_FEATURE_VOLUMEID_UFS |
| 137 | volume_id_probe_ufs, | 139 | volume_id_probe_ufs, |
| 138 | #endif | 140 | #endif |
| 141 | #if ENABLE_FEATURE_VOLUMEID_F2FS | ||
| 142 | volume_id_probe_f2fs, | ||
| 143 | #endif | ||
| 139 | #if ENABLE_FEATURE_VOLUMEID_NILFS | 144 | #if ENABLE_FEATURE_VOLUMEID_NILFS |
| 140 | volume_id_probe_nilfs, | 145 | volume_id_probe_nilfs, |
| 141 | #endif | 146 | #endif |
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h index 3f02bd50d..6e2dbd7bb 100644 --- a/util-linux/volume_id/volume_id_internal.h +++ b/util-linux/volume_id/volume_id_internal.h | |||
| @@ -96,44 +96,24 @@ void FAST_FUNC free_volume_id(struct volume_id *id); | |||
| 96 | /* size of seek buffer, FAT cluster is 32k max */ | 96 | /* size of seek buffer, FAT cluster is 32k max */ |
| 97 | #define SEEK_BUFFER_SIZE 0x10000 | 97 | #define SEEK_BUFFER_SIZE 0x10000 |
| 98 | 98 | ||
| 99 | #define bswap16(x) (uint16_t) ( \ | ||
| 100 | (((uint16_t)(x) & 0x00ffu) << 8) | \ | ||
| 101 | (((uint16_t)(x) & 0xff00u) >> 8)) | ||
| 102 | |||
| 103 | #define bswap32(x) (uint32_t) ( \ | ||
| 104 | (((uint32_t)(x) & 0xff000000u) >> 24) | \ | ||
| 105 | (((uint32_t)(x) & 0x00ff0000u) >> 8) | \ | ||
| 106 | (((uint32_t)(x) & 0x0000ff00u) << 8) | \ | ||
| 107 | (((uint32_t)(x) & 0x000000ffu) << 24)) | ||
| 108 | |||
| 109 | #define bswap64(x) (uint64_t) ( \ | ||
| 110 | (((uint64_t)(x) & 0xff00000000000000ull) >> 56) | \ | ||
| 111 | (((uint64_t)(x) & 0x00ff000000000000ull) >> 40) | \ | ||
| 112 | (((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) | \ | ||
| 113 | (((uint64_t)(x) & 0x000000ff00000000ull) >> 8) | \ | ||
| 114 | (((uint64_t)(x) & 0x00000000ff000000ull) << 8) | \ | ||
| 115 | (((uint64_t)(x) & 0x0000000000ff0000ull) << 24) | \ | ||
| 116 | (((uint64_t)(x) & 0x000000000000ff00ull) << 40) | \ | ||
| 117 | (((uint64_t)(x) & 0x00000000000000ffull) << 56)) | ||
| 118 | |||
| 119 | #if BB_LITTLE_ENDIAN | 99 | #if BB_LITTLE_ENDIAN |
| 120 | #define le16_to_cpu(x) (x) | 100 | # define le16_to_cpu(x) (uint16_t)(x) |
| 121 | #define le32_to_cpu(x) (x) | 101 | # define le32_to_cpu(x) (uint32_t)(x) |
| 122 | #define le64_to_cpu(x) (x) | 102 | # define le64_to_cpu(x) (uint64_t)(x) |
| 123 | #define be16_to_cpu(x) bswap16(x) | 103 | # define be16_to_cpu(x) (uint16_t)(bswap_16(x)) |
| 124 | #define be32_to_cpu(x) bswap32(x) | 104 | # define be32_to_cpu(x) (uint32_t)(bswap_32(x)) |
| 125 | #define cpu_to_le16(x) (x) | 105 | # define cpu_to_le16(x) (uint16_t)(x) |
| 126 | #define cpu_to_le32(x) (x) | 106 | # define cpu_to_le32(x) (uint32_t)(x) |
| 127 | #define cpu_to_be32(x) bswap32(x) | 107 | # define cpu_to_be32(x) (uint32_t)(bswap_32(x)) |
| 128 | #else | 108 | #else |
| 129 | #define le16_to_cpu(x) bswap16(x) | 109 | # define le16_to_cpu(x) (uint16_t)(bswap_16(x)) |
| 130 | #define le32_to_cpu(x) bswap32(x) | 110 | # define le32_to_cpu(x) (uint32_t)(bswap_32(x)) |
| 131 | #define le64_to_cpu(x) bswap64(x) | 111 | # define le64_to_cpu(x) (uint64_t)(bb_bswap_64(x)) |
| 132 | #define be16_to_cpu(x) (x) | 112 | # define be16_to_cpu(x) (uint16_t)(x) |
| 133 | #define be32_to_cpu(x) (x) | 113 | # define be32_to_cpu(x) (uint32_t)(x) |
| 134 | #define cpu_to_le16(x) bswap16(x) | 114 | # define cpu_to_le16(x) (uint16_t)(bswap_16(x)) |
| 135 | #define cpu_to_le32(x) bswap32(x) | 115 | # define cpu_to_le32(x) (uint32_t)(bswap_32(x)) |
| 136 | #define cpu_to_be32(x) (x) | 116 | # define cpu_to_be32(x) (uint32_t)(x) |
| 137 | #endif | 117 | #endif |
| 138 | 118 | ||
| 139 | /* volume_id_set_uuid(id,buf,fmt) assumes size of uuid buf | 119 | /* volume_id_set_uuid(id,buf,fmt) assumes size of uuid buf |
| @@ -215,6 +195,8 @@ int FAST_FUNC volume_id_probe_luks(struct volume_id *id /*,uint64_t off*/); | |||
| 215 | 195 | ||
| 216 | //int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id /*,uint64_t off*/); | 196 | //int FAST_FUNC volume_id_probe_msdos_part_table(struct volume_id *id /*,uint64_t off*/); |
| 217 | 197 | ||
| 198 | int FAST_FUNC volume_id_probe_f2fs(struct volume_id *id /*,uint64_t off*/); | ||
| 199 | |||
| 218 | int FAST_FUNC volume_id_probe_nilfs(struct volume_id *id /*,uint64_t off*/); | 200 | int FAST_FUNC volume_id_probe_nilfs(struct volume_id *id /*,uint64_t off*/); |
| 219 | 201 | ||
| 220 | int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/); | 202 | int FAST_FUNC volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/); |
diff --git a/util-linux/volume_id/xfs.c b/util-linux/volume_id/xfs.c index 84746020e..5eefc201d 100644 --- a/util-linux/volume_id/xfs.c +++ b/util-linux/volume_id/xfs.c | |||
| @@ -18,6 +18,17 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o | ||
| 22 | |||
| 23 | //config: | ||
| 24 | //config:config FEATURE_VOLUMEID_XFS | ||
| 25 | //config: bool "xfs filesystem" | ||
| 26 | //config: default y | ||
| 27 | //config: depends on VOLUMEID | ||
| 28 | //config: help | ||
| 29 | //config: TODO | ||
| 30 | //config: | ||
| 31 | |||
| 21 | #include "volume_id_internal.h" | 32 | #include "volume_id_internal.h" |
| 22 | 33 | ||
| 23 | struct xfs_super_block { | 34 | struct xfs_super_block { |
