diff options
| author | Ron Yorston <rmy@pobox.com> | 2017-01-08 08:56:43 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2017-01-08 08:56:43 +0000 |
| commit | 3ef86d069577b8a44ebe3aa890c6e97ea31d0d56 (patch) | |
| tree | 064587c9b2080dba963bf8d93861b8019cb306ed | |
| parent | c66975af0b5335b9cdd156206767756237bd814b (diff) | |
| parent | 86584e134eec1a81298149f8c04c77727f6dccb9 (diff) | |
| download | busybox-w32-3ef86d069577b8a44ebe3aa890c6e97ea31d0d56.tar.gz busybox-w32-3ef86d069577b8a44ebe3aa890c6e97ea31d0d56.tar.bz2 busybox-w32-3ef86d069577b8a44ebe3aa890c6e97ea31d0d56.zip | |
Merge branch 'busybox' into merge
| -rwxr-xr-x | applets/usage_compressed | 3 | ||||
| -rw-r--r-- | archival/unzip.c | 286 | ||||
| -rw-r--r-- | libbb/appletlib.c | 26 | ||||
| -rw-r--r-- | modutils/modprobe-small.c | 4 | ||||
| -rw-r--r-- | modutils/modutils.c | 16 | ||||
| -rw-r--r-- | networking/ntpd.c | 73 | ||||
| -rw-r--r-- | networking/udhcp/Config.src | 54 | ||||
| -rw-r--r-- | networking/udhcp/d6_dhcpc.c | 2 | ||||
| -rw-r--r-- | shell/Config.src | 27 | ||||
| -rw-r--r-- | shell/ash.c | 18 | ||||
| -rw-r--r-- | shell/ash_test/ash-redir/redir_leak.right | 6 | ||||
| -rwxr-xr-x | shell/ash_test/ash-redir/redir_leak.tests | 10 | ||||
| -rw-r--r-- | shell/hush_test/hush-redir/redir_leak.right | 6 | ||||
| -rwxr-xr-x | shell/hush_test/hush-redir/redir_leak.tests | 10 | ||||
| -rwxr-xr-x | testsuite/unzip.tests | 6 |
15 files changed, 337 insertions, 210 deletions
diff --git a/applets/usage_compressed b/applets/usage_compressed index 186fcde77..36fc2a007 100755 --- a/applets/usage_compressed +++ b/applets/usage_compressed | |||
| @@ -36,6 +36,9 @@ echo '' | |||
| 36 | #0000040 114 105 135 040 133 055 141 040 101 103 124 111 117 116 106 111 | 36 | #0000040 114 105 135 040 133 055 141 040 101 103 124 111 117 116 106 111 |
| 37 | # 042514 020135 026533 020141 041501 044524 047117 044506 | 37 | # 042514 020135 026533 020141 041501 044524 047117 044506 |
| 38 | 38 | ||
| 39 | echo "#define UNPACKED_USAGE_LENGTH `$loc/usage | wc -c`" | ||
| 40 | echo | ||
| 41 | |||
| 39 | echo '#define PACKED_USAGE \' | 42 | echo '#define PACKED_USAGE \' |
| 40 | ## Breaks on big-endian systems! | 43 | ## Breaks on big-endian systems! |
| 41 | ## # Extra effort to avoid using "od -t x1": -t is not available | 44 | ## # Extra effort to avoid using "od -t x1": -t is not available |
diff --git a/archival/unzip.c b/archival/unzip.c index 27adb3420..7029f66c3 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * TODO | 16 | * TODO |
| 17 | * Zip64 + other methods | 17 | * Zip64 + other methods |
| 18 | */ | 18 | */ |
| 19 | |||
| 20 | //config:config UNZIP | 19 | //config:config UNZIP |
| 21 | //config: bool "unzip" | 20 | //config: bool "unzip" |
| 22 | //config: default y | 21 | //config: default y |
| @@ -24,8 +23,17 @@ | |||
| 24 | //config: unzip will list or extract files from a ZIP archive, | 23 | //config: unzip will list or extract files from a ZIP archive, |
| 25 | //config: commonly found on DOS/WIN systems. The default behavior | 24 | //config: commonly found on DOS/WIN systems. The default behavior |
| 26 | //config: (with no options) is to extract the archive into the | 25 | //config: (with no options) is to extract the archive into the |
| 27 | //config: current directory. Use the `-d' option to extract to a | 26 | //config: current directory. |
| 28 | //config: directory of your choice. | 27 | //config: |
| 28 | //config:config FEATURE_UNZIP_CDF | ||
| 29 | //config: bool "Read and use Central Directory data" | ||
| 30 | //config: default y | ||
| 31 | //config: depends on UNZIP | ||
| 32 | //config: help | ||
| 33 | //config: If you know that you only need to deal with simple | ||
| 34 | //config: ZIP files without deleted/updated files, SFX archives etc, | ||
| 35 | //config: you can reduce code size by unselecting this option. | ||
| 36 | //config: To support less trivial ZIPs, say Y. | ||
| 29 | 37 | ||
| 30 | //applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) | 38 | //applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) |
| 31 | //kbuild:lib-$(CONFIG_UNZIP) += unzip.o | 39 | //kbuild:lib-$(CONFIG_UNZIP) += unzip.o |
| @@ -83,30 +91,20 @@ typedef union { | |||
| 83 | uint32_t ucmpsize PACKED; /* 18-21 */ | 91 | uint32_t ucmpsize PACKED; /* 18-21 */ |
| 84 | uint16_t filename_len; /* 22-23 */ | 92 | uint16_t filename_len; /* 22-23 */ |
| 85 | uint16_t extra_len; /* 24-25 */ | 93 | uint16_t extra_len; /* 24-25 */ |
| 94 | /* filename follows (not NUL terminated) */ | ||
| 95 | /* extra field follows */ | ||
| 96 | /* data follows */ | ||
| 86 | } formatted PACKED; | 97 | } formatted PACKED; |
| 87 | } zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ | 98 | } zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ |
| 88 | 99 | ||
| 89 | /* Check the offset of the last element, not the length. This leniency | 100 | #define FIX_ENDIANNESS_ZIP(zip_header) \ |
| 90 | * allows for poor packing, whereby the overall struct may be too long, | 101 | do { if (BB_BIG_ENDIAN) { \ |
| 91 | * even though the elements are all in the right place. | ||
| 92 | */ | ||
| 93 | struct BUG_zip_header_must_be_26_bytes { | ||
| 94 | char BUG_zip_header_must_be_26_bytes[ | ||
| 95 | offsetof(zip_header_t, formatted.extra_len) + 2 | ||
| 96 | == ZIP_HEADER_LEN ? 1 : -1]; | ||
| 97 | }; | ||
| 98 | |||
| 99 | #define FIX_ENDIANNESS_ZIP(zip_header) do { \ | ||
| 100 | (zip_header).formatted.version = SWAP_LE16((zip_header).formatted.version ); \ | ||
| 101 | (zip_header).formatted.method = SWAP_LE16((zip_header).formatted.method ); \ | ||
| 102 | (zip_header).formatted.modtime = SWAP_LE16((zip_header).formatted.modtime ); \ | ||
| 103 | (zip_header).formatted.moddate = SWAP_LE16((zip_header).formatted.moddate ); \ | ||
| 104 | (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \ | 102 | (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \ |
| 105 | (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \ | 103 | (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \ |
| 106 | (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \ | 104 | (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \ |
| 107 | (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \ | 105 | (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \ |
| 108 | (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \ | 106 | (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \ |
| 109 | } while (0) | 107 | }} while (0) |
| 110 | 108 | ||
| 111 | #define CDF_HEADER_LEN 42 | 109 | #define CDF_HEADER_LEN 42 |
| 112 | 110 | ||
| @@ -118,8 +116,8 @@ typedef union { | |||
| 118 | uint16_t version_needed; /* 2-3 */ | 116 | uint16_t version_needed; /* 2-3 */ |
| 119 | uint16_t cdf_flags; /* 4-5 */ | 117 | uint16_t cdf_flags; /* 4-5 */ |
| 120 | uint16_t method; /* 6-7 */ | 118 | uint16_t method; /* 6-7 */ |
| 121 | uint16_t mtime; /* 8-9 */ | 119 | uint16_t modtime; /* 8-9 */ |
| 122 | uint16_t mdate; /* 10-11 */ | 120 | uint16_t moddate; /* 10-11 */ |
| 123 | uint32_t crc32; /* 12-15 */ | 121 | uint32_t crc32; /* 12-15 */ |
| 124 | uint32_t cmpsize; /* 16-19 */ | 122 | uint32_t cmpsize; /* 16-19 */ |
| 125 | uint32_t ucmpsize; /* 20-23 */ | 123 | uint32_t ucmpsize; /* 20-23 */ |
| @@ -130,27 +128,27 @@ typedef union { | |||
| 130 | uint16_t internal_file_attributes; /* 32-33 */ | 128 | uint16_t internal_file_attributes; /* 32-33 */ |
| 131 | uint32_t external_file_attributes PACKED; /* 34-37 */ | 129 | uint32_t external_file_attributes PACKED; /* 34-37 */ |
| 132 | uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ | 130 | uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ |
| 131 | /* filename follows (not NUL terminated) */ | ||
| 132 | /* extra field follows */ | ||
| 133 | /* comment follows */ | ||
| 133 | } formatted PACKED; | 134 | } formatted PACKED; |
| 134 | } cdf_header_t; | 135 | } cdf_header_t; |
| 135 | 136 | ||
| 136 | struct BUG_cdf_header_must_be_42_bytes { | 137 | #define FIX_ENDIANNESS_CDF(cdf_header) \ |
| 137 | char BUG_cdf_header_must_be_42_bytes[ | 138 | do { if (BB_BIG_ENDIAN) { \ |
| 138 | offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4 | 139 | (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \ |
| 139 | == CDF_HEADER_LEN ? 1 : -1]; | 140 | (cdf_header).formatted.version_needed = SWAP_LE16((cdf_header).formatted.version_needed); \ |
| 140 | }; | 141 | (cdf_header).formatted.method = SWAP_LE16((cdf_header).formatted.method ); \ |
| 141 | 142 | (cdf_header).formatted.modtime = SWAP_LE16((cdf_header).formatted.modtime ); \ | |
| 142 | #define FIX_ENDIANNESS_CDF(cdf_header) do { \ | 143 | (cdf_header).formatted.moddate = SWAP_LE16((cdf_header).formatted.moddate ); \ |
| 143 | (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \ | 144 | (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \ |
| 144 | (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \ | 145 | (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \ |
| 145 | (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \ | 146 | (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \ |
| 146 | (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \ | 147 | (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \ |
| 147 | (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \ | 148 | (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \ |
| 148 | (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \ | 149 | (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \ |
| 149 | IF_DESKTOP( \ | ||
| 150 | (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \ | ||
| 151 | (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \ | 150 | (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \ |
| 152 | ) \ | 151 | }} while (0) |
| 153 | } while (0) | ||
| 154 | 152 | ||
| 155 | #define CDE_HEADER_LEN 16 | 153 | #define CDE_HEADER_LEN 16 |
| 156 | 154 | ||
| @@ -169,20 +167,38 @@ typedef union { | |||
| 169 | } formatted PACKED; | 167 | } formatted PACKED; |
| 170 | } cde_header_t; | 168 | } cde_header_t; |
| 171 | 169 | ||
| 172 | struct BUG_cde_header_must_be_16_bytes { | 170 | #define FIX_ENDIANNESS_CDE(cde_header) \ |
| 171 | do { if (BB_BIG_ENDIAN) { \ | ||
| 172 | (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \ | ||
| 173 | }} while (0) | ||
| 174 | |||
| 175 | struct BUG { | ||
| 176 | /* Check the offset of the last element, not the length. This leniency | ||
| 177 | * allows for poor packing, whereby the overall struct may be too long, | ||
| 178 | * even though the elements are all in the right place. | ||
| 179 | */ | ||
| 180 | char BUG_zip_header_must_be_26_bytes[ | ||
| 181 | offsetof(zip_header_t, formatted.extra_len) + 2 | ||
| 182 | == ZIP_HEADER_LEN ? 1 : -1]; | ||
| 183 | char BUG_cdf_header_must_be_42_bytes[ | ||
| 184 | offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4 | ||
| 185 | == CDF_HEADER_LEN ? 1 : -1]; | ||
| 173 | char BUG_cde_header_must_be_16_bytes[ | 186 | char BUG_cde_header_must_be_16_bytes[ |
| 174 | sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1]; | 187 | sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1]; |
| 175 | }; | 188 | }; |
| 176 | 189 | ||
| 177 | #define FIX_ENDIANNESS_CDE(cde_header) do { \ | ||
| 178 | (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \ | ||
| 179 | } while (0) | ||
| 180 | 190 | ||
| 181 | enum { zip_fd = 3 }; | 191 | enum { zip_fd = 3 }; |
| 182 | 192 | ||
| 183 | 193 | ||
| 184 | #if ENABLE_DESKTOP | 194 | /* This value means that we failed to find CDF */ |
| 195 | #define BAD_CDF_OFFSET ((uint32_t)0xffffffff) | ||
| 196 | |||
| 197 | #if !ENABLE_FEATURE_UNZIP_CDF | ||
| 198 | |||
| 199 | # define find_cdf_offset() BAD_CDF_OFFSET | ||
| 185 | 200 | ||
| 201 | #else | ||
| 186 | /* Seen in the wild: | 202 | /* Seen in the wild: |
| 187 | * Self-extracting PRO2K3XP_32.exe contains 19078464 byte zip archive, | 203 | * Self-extracting PRO2K3XP_32.exe contains 19078464 byte zip archive, |
| 188 | * where CDE was nearly 48 kbytes before EOF. | 204 | * where CDE was nearly 48 kbytes before EOF. |
| @@ -191,25 +207,26 @@ enum { zip_fd = 3 }; | |||
| 191 | * To make extraction work, bumped PEEK_FROM_END from 16k to 64k. | 207 | * To make extraction work, bumped PEEK_FROM_END from 16k to 64k. |
| 192 | */ | 208 | */ |
| 193 | #define PEEK_FROM_END (64*1024) | 209 | #define PEEK_FROM_END (64*1024) |
| 194 | |||
| 195 | /* This value means that we failed to find CDF */ | ||
| 196 | #define BAD_CDF_OFFSET ((uint32_t)0xffffffff) | ||
| 197 | |||
| 198 | /* NB: does not preserve file position! */ | 210 | /* NB: does not preserve file position! */ |
| 199 | static uint32_t find_cdf_offset(void) | 211 | static uint32_t find_cdf_offset(void) |
| 200 | { | 212 | { |
| 201 | cde_header_t cde_header; | 213 | cde_header_t cde_header; |
| 214 | unsigned char *buf; | ||
| 202 | unsigned char *p; | 215 | unsigned char *p; |
| 203 | off_t end; | 216 | off_t end; |
| 204 | unsigned char *buf = xzalloc(PEEK_FROM_END); | ||
| 205 | uint32_t found; | 217 | uint32_t found; |
| 206 | 218 | ||
| 207 | end = xlseek(zip_fd, 0, SEEK_END); | 219 | end = lseek(zip_fd, 0, SEEK_END); |
| 220 | if (end == (off_t) -1) | ||
| 221 | return BAD_CDF_OFFSET; | ||
| 222 | |||
| 208 | end -= PEEK_FROM_END; | 223 | end -= PEEK_FROM_END; |
| 209 | if (end < 0) | 224 | if (end < 0) |
| 210 | end = 0; | 225 | end = 0; |
| 226 | |||
| 211 | dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end); | 227 | dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end); |
| 212 | xlseek(zip_fd, end, SEEK_SET); | 228 | xlseek(zip_fd, end, SEEK_SET); |
| 229 | buf = xzalloc(PEEK_FROM_END); | ||
| 213 | full_read(zip_fd, buf, PEEK_FROM_END); | 230 | full_read(zip_fd, buf, PEEK_FROM_END); |
| 214 | 231 | ||
| 215 | found = BAD_CDF_OFFSET; | 232 | found = BAD_CDF_OFFSET; |
| @@ -254,31 +271,32 @@ static uint32_t find_cdf_offset(void) | |||
| 254 | 271 | ||
| 255 | static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) | 272 | static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) |
| 256 | { | 273 | { |
| 257 | off_t org; | 274 | uint32_t magic; |
| 258 | 275 | ||
| 259 | org = xlseek(zip_fd, 0, SEEK_CUR); | 276 | if (cdf_offset == BAD_CDF_OFFSET) |
| 260 | 277 | return cdf_offset; | |
| 261 | if (!cdf_offset) | 278 | |
| 262 | cdf_offset = find_cdf_offset(); | 279 | dbg("Reading CDF at 0x%x", (unsigned)cdf_offset); |
| 263 | 280 | xlseek(zip_fd, cdf_offset, SEEK_SET); | |
| 264 | if (cdf_offset != BAD_CDF_OFFSET) { | 281 | xread(zip_fd, &magic, 4); |
| 265 | dbg("Reading CDF at 0x%x", (unsigned)cdf_offset); | 282 | /* Central Directory End? */ |
| 266 | xlseek(zip_fd, cdf_offset + 4, SEEK_SET); | 283 | if (magic == ZIP_CDE_MAGIC) { |
| 267 | xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); | 284 | dbg("got ZIP_CDE_MAGIC"); |
| 268 | FIX_ENDIANNESS_CDF(*cdf_ptr); | 285 | return 0; /* EOF */ |
| 269 | dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u", | ||
| 270 | (unsigned)cdf_ptr->formatted.file_name_length, | ||
| 271 | (unsigned)cdf_ptr->formatted.extra_field_length, | ||
| 272 | (unsigned)cdf_ptr->formatted.file_comment_length | ||
| 273 | ); | ||
| 274 | cdf_offset += 4 + CDF_HEADER_LEN | ||
| 275 | + cdf_ptr->formatted.file_name_length | ||
| 276 | + cdf_ptr->formatted.extra_field_length | ||
| 277 | + cdf_ptr->formatted.file_comment_length; | ||
| 278 | } | 286 | } |
| 287 | xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); | ||
| 288 | |||
| 289 | FIX_ENDIANNESS_CDF(*cdf_ptr); | ||
| 290 | dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u", | ||
| 291 | (unsigned)cdf_ptr->formatted.file_name_length, | ||
| 292 | (unsigned)cdf_ptr->formatted.extra_field_length, | ||
| 293 | (unsigned)cdf_ptr->formatted.file_comment_length | ||
| 294 | ); | ||
| 295 | cdf_offset += 4 + CDF_HEADER_LEN | ||
| 296 | + cdf_ptr->formatted.file_name_length | ||
| 297 | + cdf_ptr->formatted.extra_field_length | ||
| 298 | + cdf_ptr->formatted.file_comment_length; | ||
| 279 | 299 | ||
| 280 | dbg("Returning file position to 0x%"OFF_FMT"x", org); | ||
| 281 | xlseek(zip_fd, org, SEEK_SET); | ||
| 282 | return cdf_offset; | 300 | return cdf_offset; |
| 283 | }; | 301 | }; |
| 284 | #endif | 302 | #endif |
| @@ -327,6 +345,7 @@ static void unzip_extract(zip_header_t *zip_header, int dst_fd) | |||
| 327 | bb_error_msg("bad length"); | 345 | bb_error_msg("bad length"); |
| 328 | } | 346 | } |
| 329 | } | 347 | } |
| 348 | /* TODO? method 12: bzip2, method 14: LZMA */ | ||
| 330 | } | 349 | } |
| 331 | 350 | ||
| 332 | static void my_fgets80(char *buf80) | 351 | static void my_fgets80(char *buf80) |
| @@ -342,15 +361,12 @@ int unzip_main(int argc, char **argv) | |||
| 342 | { | 361 | { |
| 343 | enum { O_PROMPT, O_NEVER, O_ALWAYS }; | 362 | enum { O_PROMPT, O_NEVER, O_ALWAYS }; |
| 344 | 363 | ||
| 345 | zip_header_t zip_header; | ||
| 346 | smallint quiet = 0; | 364 | smallint quiet = 0; |
| 347 | IF_NOT_DESKTOP(const) smallint verbose = 0; | 365 | IF_NOT_FEATURE_UNZIP_CDF(const) smallint verbose = 0; |
| 348 | smallint listing = 0; | 366 | smallint listing = 0; |
| 349 | smallint overwrite = O_PROMPT; | 367 | smallint overwrite = O_PROMPT; |
| 350 | smallint x_opt_seen; | 368 | smallint x_opt_seen; |
| 351 | #if ENABLE_DESKTOP | ||
| 352 | uint32_t cdf_offset; | 369 | uint32_t cdf_offset; |
| 353 | #endif | ||
| 354 | unsigned long total_usize; | 370 | unsigned long total_usize; |
| 355 | unsigned long total_size; | 371 | unsigned long total_size; |
| 356 | unsigned total_entries; | 372 | unsigned total_entries; |
| @@ -433,7 +449,7 @@ int unzip_main(int argc, char **argv) | |||
| 433 | break; | 449 | break; |
| 434 | 450 | ||
| 435 | case 'v': /* Verbose list */ | 451 | case 'v': /* Verbose list */ |
| 436 | IF_DESKTOP(verbose++;) | 452 | IF_FEATURE_UNZIP_CDF(verbose++;) |
| 437 | listing = 1; | 453 | listing = 1; |
| 438 | break; | 454 | break; |
| 439 | 455 | ||
| @@ -548,78 +564,102 @@ int unzip_main(int argc, char **argv) | |||
| 548 | total_usize = 0; | 564 | total_usize = 0; |
| 549 | total_size = 0; | 565 | total_size = 0; |
| 550 | total_entries = 0; | 566 | total_entries = 0; |
| 551 | #if ENABLE_DESKTOP | 567 | cdf_offset = find_cdf_offset(); /* try to seek to the end, find CDE and CDF start */ |
| 552 | cdf_offset = 0; | ||
| 553 | #endif | ||
| 554 | while (1) { | 568 | while (1) { |
| 555 | uint32_t magic; | 569 | zip_header_t zip_header; |
| 556 | mode_t dir_mode = 0777; | 570 | mode_t dir_mode = 0777; |
| 557 | #if ENABLE_DESKTOP | 571 | #if ENABLE_FEATURE_UNZIP_CDF |
| 558 | mode_t file_mode = 0666; | 572 | mode_t file_mode = 0666; |
| 559 | #endif | 573 | #endif |
| 560 | 574 | ||
| 561 | /* Check magic number */ | 575 | if (!ENABLE_FEATURE_UNZIP_CDF || cdf_offset == BAD_CDF_OFFSET) { |
| 562 | xread(zip_fd, &magic, 4); | 576 | /* Normally happens when input is unseekable. |
| 563 | /* Central directory? It's at the end, so exit */ | 577 | * |
| 564 | if (magic == ZIP_CDF_MAGIC) { | 578 | * Valid ZIP file has Central Directory at the end |
| 565 | dbg("got ZIP_CDF_MAGIC"); | 579 | * with central directory file headers (CDFs). |
| 566 | break; | 580 | * After it, there is a Central Directory End structure. |
| 567 | } | 581 | * CDFs identify what files are in the ZIP and where |
| 568 | #if ENABLE_DESKTOP | 582 | * they are located. This allows ZIP readers to load |
| 569 | /* Data descriptor? It was a streaming file, go on */ | 583 | * the list of files without reading the entire ZIP archive. |
| 570 | if (magic == ZIP_DD_MAGIC) { | 584 | * ZIP files may be appended to, only files specified in |
| 571 | dbg("got ZIP_DD_MAGIC"); | 585 | * the CD are valid. Scanning for local file headers is |
| 572 | /* skip over duplicate crc32, cmpsize and ucmpsize */ | 586 | * not a correct algorithm. |
| 573 | unzip_skip(3 * 4); | 587 | * |
| 574 | continue; | 588 | * We try to do the above, and resort to "linear" reading |
| 575 | } | 589 | * of ZIP file only if seek failed or CDE wasn't found. |
| 576 | #endif | 590 | */ |
| 577 | if (magic != ZIP_FILEHEADER_MAGIC) | 591 | uint32_t magic; |
| 578 | bb_error_msg_and_die("invalid zip magic %08X", (int)magic); | ||
| 579 | dbg("got ZIP_FILEHEADER_MAGIC"); | ||
| 580 | |||
| 581 | /* Read the file header */ | ||
| 582 | xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); | ||
| 583 | FIX_ENDIANNESS_ZIP(zip_header); | ||
| 584 | if ((zip_header.formatted.method != 0) && (zip_header.formatted.method != 8)) { | ||
| 585 | bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method); | ||
| 586 | } | ||
| 587 | #if !ENABLE_DESKTOP | ||
| 588 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) { | ||
| 589 | bb_error_msg_and_die("zip flags 1 and 8 are not supported"); | ||
| 590 | } | ||
| 591 | #else | ||
| 592 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) { | ||
| 593 | /* 0x0001 - encrypted */ | ||
| 594 | bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); | ||
| 595 | } | ||
| 596 | 592 | ||
| 597 | if (cdf_offset != BAD_CDF_OFFSET) { | 593 | /* Check magic number */ |
| 594 | xread(zip_fd, &magic, 4); | ||
| 595 | /* Central directory? It's at the end, so exit */ | ||
| 596 | if (magic == ZIP_CDF_MAGIC) { | ||
| 597 | dbg("got ZIP_CDF_MAGIC"); | ||
| 598 | break; | ||
| 599 | } | ||
| 600 | /* Data descriptor? It was a streaming file, go on */ | ||
| 601 | if (magic == ZIP_DD_MAGIC) { | ||
| 602 | dbg("got ZIP_DD_MAGIC"); | ||
| 603 | /* skip over duplicate crc32, cmpsize and ucmpsize */ | ||
| 604 | unzip_skip(3 * 4); | ||
| 605 | continue; | ||
| 606 | } | ||
| 607 | if (magic != ZIP_FILEHEADER_MAGIC) | ||
| 608 | bb_error_msg_and_die("invalid zip magic %08X", (int)magic); | ||
| 609 | dbg("got ZIP_FILEHEADER_MAGIC"); | ||
| 610 | |||
| 611 | xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); | ||
| 612 | FIX_ENDIANNESS_ZIP(zip_header); | ||
| 613 | if ((zip_header.formatted.method != 0) | ||
| 614 | && (zip_header.formatted.method != 8) | ||
| 615 | ) { | ||
| 616 | /* TODO? method 12: bzip2, method 14: LZMA */ | ||
| 617 | bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method); | ||
| 618 | } | ||
| 619 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) { | ||
| 620 | bb_error_msg_and_die("zip flags 1 and 8 are not supported"); | ||
| 621 | } | ||
| 622 | } | ||
| 623 | #if ENABLE_FEATURE_UNZIP_CDF | ||
| 624 | else { | ||
| 625 | /* cdf_offset is valid (and we know the file is seekable) */ | ||
| 598 | cdf_header_t cdf_header; | 626 | cdf_header_t cdf_header; |
| 599 | cdf_offset = read_next_cdf(cdf_offset, &cdf_header); | 627 | cdf_offset = read_next_cdf(cdf_offset, &cdf_header); |
| 600 | /* | 628 | if (cdf_offset == 0) /* EOF? */ |
| 601 | * Note: cdf_offset can become BAD_CDF_OFFSET after the above call. | 629 | break; |
| 602 | */ | 630 | # if 0 |
| 631 | xlseek(zip_fd, | ||
| 632 | SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4, | ||
| 633 | SEEK_SET); | ||
| 634 | xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); | ||
| 635 | FIX_ENDIANNESS_ZIP(zip_header); | ||
| 603 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { | 636 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { |
| 604 | /* 0x0008 - streaming. [u]cmpsize can be reliably gotten | 637 | /* 0x0008 - streaming. [u]cmpsize can be reliably gotten |
| 605 | * only from Central Directory. See unzip_doc.txt | 638 | * only from Central Directory. |
| 606 | */ | 639 | */ |
| 607 | zip_header.formatted.crc32 = cdf_header.formatted.crc32; | 640 | zip_header.formatted.crc32 = cdf_header.formatted.crc32; |
| 608 | zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; | 641 | zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; |
| 609 | zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; | 642 | zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; |
| 610 | } | 643 | } |
| 644 | # else | ||
| 645 | /* CDF has the same data as local header, no need to read the latter */ | ||
| 646 | memcpy(&zip_header.formatted.version, | ||
| 647 | &cdf_header.formatted.version_needed, ZIP_HEADER_LEN); | ||
| 648 | xlseek(zip_fd, | ||
| 649 | SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4 + ZIP_HEADER_LEN, | ||
| 650 | SEEK_SET); | ||
| 651 | # endif | ||
| 611 | if ((cdf_header.formatted.version_made_by >> 8) == 3) { | 652 | if ((cdf_header.formatted.version_made_by >> 8) == 3) { |
| 612 | /* This archive is created on Unix */ | 653 | /* This archive is created on Unix */ |
| 613 | dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); | 654 | dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); |
| 614 | } | 655 | } |
| 615 | } | 656 | } |
| 616 | if (cdf_offset == BAD_CDF_OFFSET | ||
| 617 | && (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) | ||
| 618 | ) { | ||
| 619 | /* If it's a streaming zip, we _require_ CDF */ | ||
| 620 | bb_error_msg_and_die("can't find file table"); | ||
| 621 | } | ||
| 622 | #endif | 657 | #endif |
| 658 | |||
| 659 | if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) { | ||
| 660 | /* 0x0001 - encrypted */ | ||
| 661 | bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); | ||
| 662 | } | ||
| 623 | dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", | 663 | dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", |
| 624 | (unsigned)zip_header.formatted.cmpsize, | 664 | (unsigned)zip_header.formatted.cmpsize, |
| 625 | (unsigned)zip_header.formatted.extra_len, | 665 | (unsigned)zip_header.formatted.extra_len, |
| @@ -754,7 +794,7 @@ int unzip_main(int argc, char **argv) | |||
| 754 | overwrite = O_ALWAYS; | 794 | overwrite = O_ALWAYS; |
| 755 | case 'y': /* Open file and fall into unzip */ | 795 | case 'y': /* Open file and fall into unzip */ |
| 756 | unzip_create_leading_dirs(dst_fn); | 796 | unzip_create_leading_dirs(dst_fn); |
| 757 | #if ENABLE_DESKTOP | 797 | #if ENABLE_FEATURE_UNZIP_CDF |
| 758 | dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); | 798 | dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); |
| 759 | #else | 799 | #else |
| 760 | dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); | 800 | dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f11384962..6732f89a9 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
| @@ -52,6 +52,32 @@ | |||
| 52 | 52 | ||
| 53 | #include "usage_compressed.h" | 53 | #include "usage_compressed.h" |
| 54 | 54 | ||
| 55 | |||
| 56 | /* "Do not compress usage text if uncompressed text is small | ||
| 57 | * and we don't include bunzip2 code for other reasons" | ||
| 58 | * | ||
| 59 | * Useful for mass one-applet rebuild (bunzip2 code is ~2.7k). | ||
| 60 | * | ||
| 61 | * Unlike BUNZIP2, if FEATURE_SEAMLESS_BZ2 is on, bunzip2 code is built but | ||
| 62 | * still may be unused if none of the selected applets calls open_zipped() | ||
| 63 | * or its friends; we test for (FEATURE_SEAMLESS_BZ2 && <APPLET>) instead. | ||
| 64 | * For example, only if TAR and FEATURE_SEAMLESS_BZ2 are both selected, | ||
| 65 | * then bunzip2 code will be linked in anyway, and disabling help compression | ||
| 66 | * would be not optimal: | ||
| 67 | */ | ||
| 68 | #if UNPACKED_USAGE_LENGTH < 4*1024 \ | ||
| 69 | && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_TAR) \ | ||
| 70 | && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_MODPROBE) \ | ||
| 71 | && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_INSMOD) \ | ||
| 72 | && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_DEPMOD) \ | ||
| 73 | && !(ENABLE_FEATURE_SEAMLESS_BZ2 && ENABLE_MAN) \ | ||
| 74 | && !ENABLE_BUNZIP2 \ | ||
| 75 | && !ENABLE_BZCAT | ||
| 76 | # undef ENABLE_FEATURE_COMPRESS_USAGE | ||
| 77 | # define ENABLE_FEATURE_COMPRESS_USAGE 0 | ||
| 78 | #endif | ||
| 79 | |||
| 80 | |||
| 55 | #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE | 81 | #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE |
| 56 | static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; | 82 | static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; |
| 57 | #else | 83 | #else |
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 652ff4dfa..0fc9ea454 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
| @@ -39,8 +39,8 @@ | |||
| 39 | #include <fnmatch.h> | 39 | #include <fnmatch.h> |
| 40 | #include <sys/syscall.h> | 40 | #include <sys/syscall.h> |
| 41 | 41 | ||
| 42 | extern int init_module(void *module, unsigned long len, const char *options); | 42 | #define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) |
| 43 | extern int delete_module(const char *module, unsigned flags); | 43 | #define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) |
| 44 | #ifdef __NR_finit_module | 44 | #ifdef __NR_finit_module |
| 45 | # define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags) | 45 | # define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags) |
| 46 | #endif | 46 | #endif |
diff --git a/modutils/modutils.c b/modutils/modutils.c index d36caaf68..4204f06fe 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c | |||
| @@ -7,17 +7,13 @@ | |||
| 7 | */ | 7 | */ |
| 8 | #include "modutils.h" | 8 | #include "modutils.h" |
| 9 | 9 | ||
| 10 | #ifdef __UCLIBC__ | 10 | #include <sys/syscall.h> |
| 11 | extern int init_module(void *module, unsigned long len, const char *options); | 11 | |
| 12 | extern int delete_module(const char *module, unsigned int flags); | 12 | #define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) |
| 13 | #else | 13 | #if defined(__NR_finit_module) |
| 14 | # include <sys/syscall.h> | 14 | # define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags) |
| 15 | # define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) | ||
| 16 | # if defined(__NR_finit_module) | ||
| 17 | # define finit_module(fd, uargs, flags) syscall(__NR_finit_module, fd, uargs, flags) | ||
| 18 | # endif | ||
| 19 | # define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) | ||
| 20 | #endif | 15 | #endif |
| 16 | #define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) | ||
| 21 | 17 | ||
| 22 | static module_entry *helper_get_module(module_db *db, const char *module, int create) | 18 | static module_entry *helper_get_module(module_db *db, const char *module, int create) |
| 23 | { | 19 | { |
diff --git a/networking/ntpd.c b/networking/ntpd.c index b7fa5dce9..bfd5705fc 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c | |||
| @@ -155,6 +155,7 @@ | |||
| 155 | #define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ | 155 | #define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ |
| 156 | #define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */ | 156 | #define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */ |
| 157 | #define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */ | 157 | #define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */ |
| 158 | #define HOSTNAME_INTERVAL 5 /* hostname lookup failed. Wait N secs for next try */ | ||
| 158 | 159 | ||
| 159 | /* Step threshold (sec). std ntpd uses 0.128. | 160 | /* Step threshold (sec). std ntpd uses 0.128. |
| 160 | */ | 161 | */ |
| @@ -790,28 +791,20 @@ reset_peer_stats(peer_t *p, double offset) | |||
| 790 | VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); | 791 | VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); |
| 791 | } | 792 | } |
| 792 | 793 | ||
| 793 | static void | 794 | static len_and_sockaddr* |
| 794 | resolve_peer_hostname(peer_t *p, int loop_on_fail) | 795 | resolve_peer_hostname(peer_t *p) |
| 795 | { | 796 | { |
| 796 | len_and_sockaddr *lsa; | 797 | len_and_sockaddr *lsa = host2sockaddr(p->p_hostname, 123); |
| 797 | 798 | if (lsa) { | |
| 798 | again: | 799 | free(p->p_lsa); |
| 799 | lsa = host2sockaddr(p->p_hostname, 123); | 800 | free(p->p_dotted); |
| 800 | if (!lsa) { | 801 | p->p_lsa = lsa; |
| 801 | /* error message already emitted by host2sockaddr() */ | 802 | p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); |
| 802 | if (!loop_on_fail) | 803 | } else { |
| 803 | return; | 804 | /* error message is emitted by host2sockaddr() */ |
| 804 | //FIXME: do this to avoid infinite looping on typo in a hostname? | 805 | set_next(p, HOSTNAME_INTERVAL); |
| 805 | //well... in which case, what is a good value for loop_on_fail? | ||
| 806 | //if (--loop_on_fail == 0) | ||
| 807 | // xfunc_die(); | ||
| 808 | sleep(5); | ||
| 809 | goto again; | ||
| 810 | } | 806 | } |
| 811 | free(p->p_lsa); | 807 | return lsa; |
| 812 | free(p->p_dotted); | ||
| 813 | p->p_lsa = lsa; | ||
| 814 | p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); | ||
| 815 | } | 808 | } |
| 816 | 809 | ||
| 817 | static void | 810 | static void |
| @@ -822,28 +815,28 @@ add_peers(const char *s) | |||
| 822 | 815 | ||
| 823 | p = xzalloc(sizeof(*p) + strlen(s)); | 816 | p = xzalloc(sizeof(*p) + strlen(s)); |
| 824 | strcpy(p->p_hostname, s); | 817 | strcpy(p->p_hostname, s); |
| 825 | resolve_peer_hostname(p, /*loop_on_fail=*/ 1); | 818 | p->p_fd = -1; |
| 819 | p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); | ||
| 820 | p->next_action_time = G.cur_time; /* = set_next(p, 0); */ | ||
| 821 | reset_peer_stats(p, STEP_THRESHOLD); | ||
| 826 | 822 | ||
| 827 | /* Names like N.<country2chars>.pool.ntp.org are randomly resolved | 823 | /* Names like N.<country2chars>.pool.ntp.org are randomly resolved |
| 828 | * to a pool of machines. Sometimes different N's resolve to the same IP. | 824 | * to a pool of machines. Sometimes different N's resolve to the same IP. |
| 829 | * It is not useful to have two peers with same IP. We skip duplicates. | 825 | * It is not useful to have two peers with same IP. We skip duplicates. |
| 830 | */ | 826 | */ |
| 831 | for (item = G.ntp_peers; item != NULL; item = item->link) { | 827 | if (resolve_peer_hostname(p)) { |
| 832 | peer_t *pp = (peer_t *) item->data; | 828 | for (item = G.ntp_peers; item != NULL; item = item->link) { |
| 833 | if (strcmp(p->p_dotted, pp->p_dotted) == 0) { | 829 | peer_t *pp = (peer_t *) item->data; |
| 834 | bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted); | 830 | if (pp->p_dotted && strcmp(p->p_dotted, pp->p_dotted) == 0) { |
| 835 | free(p->p_lsa); | 831 | bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted); |
| 836 | free(p->p_dotted); | 832 | free(p->p_lsa); |
| 837 | free(p); | 833 | free(p->p_dotted); |
| 838 | return; | 834 | free(p); |
| 835 | return; | ||
| 836 | } | ||
| 839 | } | 837 | } |
| 840 | } | 838 | } |
| 841 | 839 | ||
| 842 | p->p_fd = -1; | ||
| 843 | p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); | ||
| 844 | p->next_action_time = G.cur_time; /* = set_next(p, 0); */ | ||
| 845 | reset_peer_stats(p, STEP_THRESHOLD); | ||
| 846 | |||
| 847 | llist_add_to(&G.ntp_peers, p); | 840 | llist_add_to(&G.ntp_peers, p); |
| 848 | G.peer_cnt++; | 841 | G.peer_cnt++; |
| 849 | } | 842 | } |
| @@ -871,6 +864,11 @@ do_sendto(int fd, | |||
| 871 | static void | 864 | static void |
| 872 | send_query_to_peer(peer_t *p) | 865 | send_query_to_peer(peer_t *p) |
| 873 | { | 866 | { |
| 867 | if (!p->p_lsa) { | ||
| 868 | if (!resolve_peer_hostname(p)) | ||
| 869 | return; | ||
| 870 | } | ||
| 871 | |||
| 874 | /* Why do we need to bind()? | 872 | /* Why do we need to bind()? |
| 875 | * See what happens when we don't bind: | 873 | * See what happens when we don't bind: |
| 876 | * | 874 | * |
| @@ -2238,7 +2236,7 @@ static NOINLINE void ntp_init(char **argv) | |||
| 2238 | IF_FEATURE_NTPD_SERVER("I:") /* compat */ | 2236 | IF_FEATURE_NTPD_SERVER("I:") /* compat */ |
| 2239 | "d" /* compat */ | 2237 | "d" /* compat */ |
| 2240 | "46aAbgL", /* compat, ignored */ | 2238 | "46aAbgL", /* compat, ignored */ |
| 2241 | &peers,&G.script_name, | 2239 | &peers, &G.script_name, |
| 2242 | #if ENABLE_FEATURE_NTPD_SERVER | 2240 | #if ENABLE_FEATURE_NTPD_SERVER |
| 2243 | &G.if_name, | 2241 | &G.if_name, |
| 2244 | #endif | 2242 | #endif |
| @@ -2263,9 +2261,6 @@ static NOINLINE void ntp_init(char **argv) | |||
| 2263 | if (opts & OPT_N) | 2261 | if (opts & OPT_N) |
| 2264 | setpriority(PRIO_PROCESS, 0, -15); | 2262 | setpriority(PRIO_PROCESS, 0, -15); |
| 2265 | 2263 | ||
| 2266 | /* add_peers() calls can retry DNS resolution (possibly forever). | ||
| 2267 | * Daemonize before them, or else boot can stall forever. | ||
| 2268 | */ | ||
| 2269 | if (!(opts & OPT_n)) { | 2264 | if (!(opts & OPT_n)) { |
| 2270 | bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); | 2265 | bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); |
| 2271 | logmode = LOGMODE_NONE; | 2266 | logmode = LOGMODE_NONE; |
| @@ -2400,7 +2395,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) | |||
| 2400 | 2395 | ||
| 2401 | /* What if don't see it because it changed its IP? */ | 2396 | /* What if don't see it because it changed its IP? */ |
| 2402 | if (p->reachable_bits == 0) | 2397 | if (p->reachable_bits == 0) |
| 2403 | resolve_peer_hostname(p, /*loop_on_fail=*/ 0); | 2398 | resolve_peer_hostname(p); |
| 2404 | 2399 | ||
| 2405 | set_next(p, timeout); | 2400 | set_next(p, timeout); |
| 2406 | } | 2401 | } |
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 90fb313b5..7bc13a719 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src | |||
| @@ -6,29 +6,13 @@ | |||
| 6 | INSERT | 6 | INSERT |
| 7 | 7 | ||
| 8 | config UDHCPD | 8 | config UDHCPD |
| 9 | bool "udhcp server (udhcpd)" | 9 | bool "udhcpd (DHCP server)" |
| 10 | default y | 10 | default y |
| 11 | select PLATFORM_LINUX | 11 | select PLATFORM_LINUX |
| 12 | help | 12 | help |
| 13 | udhcpd is a DHCP server geared primarily toward embedded systems, | 13 | udhcpd is a DHCP server geared primarily toward embedded systems, |
| 14 | while striving to be fully functional and RFC compliant. | 14 | while striving to be fully functional and RFC compliant. |
| 15 | 15 | ||
| 16 | config DHCPRELAY | ||
| 17 | bool "dhcprelay" | ||
| 18 | default y | ||
| 19 | help | ||
| 20 | dhcprelay listens for dhcp requests on one or more interfaces | ||
| 21 | and forwards these requests to a different interface or dhcp | ||
| 22 | server. | ||
| 23 | |||
| 24 | config DUMPLEASES | ||
| 25 | bool "Lease display utility (dumpleases)" | ||
| 26 | default y | ||
| 27 | help | ||
| 28 | dumpleases displays the leases written out by the udhcpd server. | ||
| 29 | Lease times are stored in the file by time remaining in lease, or | ||
| 30 | by the absolute time that it expires in seconds from epoch. | ||
| 31 | |||
| 32 | config FEATURE_UDHCPD_WRITE_LEASES_EARLY | 16 | config FEATURE_UDHCPD_WRITE_LEASES_EARLY |
| 33 | bool "Rewrite the lease file at every new acknowledge" | 17 | bool "Rewrite the lease file at every new acknowledge" |
| 34 | default y | 18 | default y |
| @@ -61,8 +45,24 @@ config DHCPD_LEASES_FILE | |||
| 61 | udhcpd stores addresses in a lease file. This is the absolute path | 45 | udhcpd stores addresses in a lease file. This is the absolute path |
| 62 | of the file. Normally it is safe to leave it untouched. | 46 | of the file. Normally it is safe to leave it untouched. |
| 63 | 47 | ||
| 48 | config DUMPLEASES | ||
| 49 | bool "dumpleases" | ||
| 50 | default y | ||
| 51 | help | ||
| 52 | dumpleases displays the leases written out by the udhcpd. | ||
| 53 | Lease times are stored in the file by time remaining in lease, or | ||
| 54 | by the absolute time that it expires in seconds from epoch. | ||
| 55 | |||
| 56 | config DHCPRELAY | ||
| 57 | bool "dhcprelay" | ||
| 58 | default y | ||
| 59 | help | ||
| 60 | dhcprelay listens for dhcp requests on one or more interfaces | ||
| 61 | and forwards these requests to a different interface or dhcp | ||
| 62 | server. | ||
| 63 | |||
| 64 | config UDHCPC | 64 | config UDHCPC |
| 65 | bool "udhcp client (udhcpc)" | 65 | bool "udhcpc (DHCP client)" |
| 66 | default y | 66 | default y |
| 67 | select PLATFORM_LINUX | 67 | select PLATFORM_LINUX |
| 68 | help | 68 | help |
| @@ -93,6 +93,15 @@ config FEATURE_UDHCPC_SANITIZEOPT | |||
| 93 | they will be replaced with string "bad" when exporting | 93 | they will be replaced with string "bad" when exporting |
| 94 | to the environment. | 94 | to the environment. |
| 95 | 95 | ||
| 96 | config UDHCPC_DEFAULT_SCRIPT | ||
| 97 | string "Absolute path to config script" | ||
| 98 | default "/usr/share/udhcpc/default.script" | ||
| 99 | depends on UDHCPC | ||
| 100 | help | ||
| 101 | This script is called after udhcpc receives an answer. See | ||
| 102 | examples/udhcp for a working example. Normally it is safe | ||
| 103 | to leave this untouched. | ||
| 104 | |||
| 96 | config FEATURE_UDHCP_PORT | 105 | config FEATURE_UDHCP_PORT |
| 97 | bool "Enable '-P port' option for udhcpd and udhcpc" | 106 | bool "Enable '-P port' option for udhcpd and udhcpc" |
| 98 | default n | 107 | default n |
| @@ -130,15 +139,6 @@ config FEATURE_UDHCP_8021Q | |||
| 130 | If selected, both client and server will support passing of VLAN | 139 | If selected, both client and server will support passing of VLAN |
| 131 | ID and priority via options 132 and 133 as per 802.1Q. | 140 | ID and priority via options 132 and 133 as per 802.1Q. |
| 132 | 141 | ||
| 133 | config UDHCPC_DEFAULT_SCRIPT | ||
| 134 | string "Absolute path to config script" | ||
| 135 | default "/usr/share/udhcpc/default.script" | ||
| 136 | depends on UDHCPC | ||
| 137 | help | ||
| 138 | This script is called after udhcpc receives an answer. See | ||
| 139 | examples/udhcp for a working example. Normally it is safe | ||
| 140 | to leave this untouched. | ||
| 141 | |||
| 142 | config UDHCPC_SLACK_FOR_BUGGY_SERVERS | 142 | config UDHCPC_SLACK_FOR_BUGGY_SERVERS |
| 143 | int "DHCP options slack buffer size" | 143 | int "DHCP options slack buffer size" |
| 144 | default 80 | 144 | default 80 |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index ddf3412a0..64339c9b5 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | //config:config UDHCPC6 | 14 | //config:config UDHCPC6 |
| 15 | //config: bool "udhcp client for DHCPv6 (udhcpc6)" | 15 | //config: bool "udhcpc6 (DHCPv6 client, NOT READY)" |
| 16 | //config: default n # not yet ready | 16 | //config: default n # not yet ready |
| 17 | //config: depends on FEATURE_IPV6 | 17 | //config: depends on FEATURE_IPV6 |
| 18 | //config: help | 18 | //config: help |
diff --git a/shell/Config.src b/shell/Config.src index 7f5f67050..3545f05dd 100644 --- a/shell/Config.src +++ b/shell/Config.src | |||
| @@ -17,9 +17,19 @@ choice | |||
| 17 | config SH_IS_ASH | 17 | config SH_IS_ASH |
| 18 | depends on !NOMMU | 18 | depends on !NOMMU |
| 19 | bool "ash" | 19 | bool "ash" |
| 20 | help | ||
| 21 | Choose ash to be the shell executed by 'sh' name. | ||
| 22 | The ash code will be built into busybox. If you don't select | ||
| 23 | "ash" choice (CONFIG_ASH), this shell may only be invoked by | ||
| 24 | the name 'sh' (and not 'ash'). | ||
| 20 | 25 | ||
| 21 | config SH_IS_HUSH | 26 | config SH_IS_HUSH |
| 22 | bool "hush" | 27 | bool "hush" |
| 28 | help | ||
| 29 | Choose hush to be the shell executed by 'sh' name. | ||
| 30 | The hush code will be built into busybox. If you don't select | ||
| 31 | "hush" choice (CONFIG_HUSH), this shell may only be invoked by | ||
| 32 | the name 'sh' (and not 'hush'). | ||
| 23 | 33 | ||
| 24 | config SH_IS_NONE | 34 | config SH_IS_NONE |
| 25 | bool "none" | 35 | bool "none" |
| @@ -31,7 +41,8 @@ choice | |||
| 31 | default BASH_IS_NONE | 41 | default BASH_IS_NONE |
| 32 | help | 42 | help |
| 33 | Choose which shell you want to be executed by 'bash' alias. | 43 | Choose which shell you want to be executed by 'bash' alias. |
| 34 | The ash shell is the most bash compatible and full featured one. | 44 | The ash shell is the most bash compatible and full featured one, |
| 45 | although compatibility is far from being complete. | ||
| 35 | 46 | ||
| 36 | Note that selecting this option does not switch on any bash | 47 | Note that selecting this option does not switch on any bash |
| 37 | compatibility code. It merely makes it possible to install | 48 | compatibility code. It merely makes it possible to install |
| @@ -46,9 +57,19 @@ choice | |||
| 46 | config BASH_IS_ASH | 57 | config BASH_IS_ASH |
| 47 | depends on !NOMMU | 58 | depends on !NOMMU |
| 48 | bool "ash" | 59 | bool "ash" |
| 60 | help | ||
| 61 | Choose ash to be the shell executed by 'bash' name. | ||
| 62 | The ash code will be built into busybox. If you don't select | ||
| 63 | "ash" choice (CONFIG_ASH), this shell may only be invoked by | ||
| 64 | the name 'bash' (and not 'ash'). | ||
| 49 | 65 | ||
| 50 | config BASH_IS_HUSH | 66 | config BASH_IS_HUSH |
| 51 | bool "hush" | 67 | bool "hush" |
| 68 | help | ||
| 69 | Choose hush to be the shell executed by 'bash' name. | ||
| 70 | The hush code will be built into busybox. If you don't select | ||
| 71 | "hush" choice (CONFIG_HUSH), this shell may only be invoked by | ||
| 72 | the name 'bash' (and not 'hush'). | ||
| 52 | 73 | ||
| 53 | config BASH_IS_NONE | 74 | config BASH_IS_NONE |
| 54 | bool "none" | 75 | bool "none" |
| @@ -59,6 +80,9 @@ endchoice | |||
| 59 | INSERT | 80 | INSERT |
| 60 | 81 | ||
| 61 | 82 | ||
| 83 | comment "Options common to all shells" | ||
| 84 | if ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH | ||
| 85 | |||
| 62 | config FEATURE_SH_MATH | 86 | config FEATURE_SH_MATH |
| 63 | bool "POSIX math support" | 87 | bool "POSIX math support" |
| 64 | default y | 88 | default y |
| @@ -142,5 +166,6 @@ config FEATURE_SH_HISTFILESIZE | |||
| 142 | to set shell history size. Note that its max value is capped | 166 | to set shell history size. Note that its max value is capped |
| 143 | by "History size" setting in library tuning section. | 167 | by "History size" setting in library tuning section. |
| 144 | 168 | ||
| 169 | endif # Options common to all shells | ||
| 145 | 170 | ||
| 146 | endmenu | 171 | endmenu |
diff --git a/shell/ash.c b/shell/ash.c index 35618937a..fe185f5d9 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -41,6 +41,11 @@ | |||
| 41 | //config: shell (by Herbert Xu), which was created by porting the 'ash' shell | 41 | //config: shell (by Herbert Xu), which was created by porting the 'ash' shell |
| 42 | //config: (written by Kenneth Almquist) from NetBSD. | 42 | //config: (written by Kenneth Almquist) from NetBSD. |
| 43 | //config: | 43 | //config: |
| 44 | //config:# ash options | ||
| 45 | //config:# note: Don't remove !NOMMU part in the next line; it would break | ||
| 46 | //config:# menuconfig's indenting. | ||
| 47 | //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH) | ||
| 48 | //config: | ||
| 44 | //config:config ASH_OPTIMIZE_FOR_SIZE | 49 | //config:config ASH_OPTIMIZE_FOR_SIZE |
| 45 | //config: bool "Optimize for size instead of speed" | 50 | //config: bool "Optimize for size instead of speed" |
| 46 | //config: default y | 51 | //config: default y |
| @@ -155,6 +160,8 @@ | |||
| 155 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH | 160 | //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH |
| 156 | //config: help | 161 | //config: help |
| 157 | //config: Enable "check for new mail" function in the ash shell. | 162 | //config: Enable "check for new mail" function in the ash shell. |
| 163 | //config: | ||
| 164 | //config:endif # ash options | ||
| 158 | 165 | ||
| 159 | //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) | 166 | //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) |
| 160 | //applet:IF_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) | 167 | //applet:IF_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) |
| @@ -5778,11 +5785,11 @@ redirect(union node *redir, int flags) | |||
| 5778 | /* Careful to not accidentally "save" | 5785 | /* Careful to not accidentally "save" |
| 5779 | * to the same fd as right side fd in N>&M */ | 5786 | * to the same fd as right side fd in N>&M */ |
| 5780 | int minfd = right_fd < 10 ? 10 : right_fd + 1; | 5787 | int minfd = right_fd < 10 ? 10 : right_fd + 1; |
| 5788 | #if defined(F_DUPFD_CLOEXEC) | ||
| 5789 | i = fcntl(fd, F_DUPFD_CLOEXEC, minfd); | ||
| 5790 | #else | ||
| 5781 | i = fcntl(fd, F_DUPFD, minfd); | 5791 | i = fcntl(fd, F_DUPFD, minfd); |
| 5782 | /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds | 5792 | #endif |
| 5783 | * are closed in popredir() in the child, preventing them from leaking | ||
| 5784 | * into child. (popredir() also cleans up the mess in case of failures) | ||
| 5785 | */ | ||
| 5786 | if (i == -1) { | 5793 | if (i == -1) { |
| 5787 | i = errno; | 5794 | i = errno; |
| 5788 | if (i != EBADF) { | 5795 | if (i != EBADF) { |
| @@ -5797,6 +5804,9 @@ redirect(union node *redir, int flags) | |||
| 5797 | remember_to_close: | 5804 | remember_to_close: |
| 5798 | i = CLOSED; | 5805 | i = CLOSED; |
| 5799 | } else { /* fd is open, save its copy */ | 5806 | } else { /* fd is open, save its copy */ |
| 5807 | #if !defined(F_DUPFD_CLOEXEC) | ||
| 5808 | fcntl(i, F_SETFD, FD_CLOEXEC); | ||
| 5809 | #endif | ||
| 5800 | /* "exec fd>&-" should not close fds | 5810 | /* "exec fd>&-" should not close fds |
| 5801 | * which point to script file(s). | 5811 | * which point to script file(s). |
| 5802 | * Force them to be restored afterwards */ | 5812 | * Force them to be restored afterwards */ |
diff --git a/shell/ash_test/ash-redir/redir_leak.right b/shell/ash_test/ash-redir/redir_leak.right new file mode 100644 index 000000000..b1c48292b --- /dev/null +++ b/shell/ash_test/ash-redir/redir_leak.right | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | 4 | ||
| 2 | 4 | ||
| 3 | 4 | ||
| 4 | 4 | ||
| 5 | 4 | ||
| 6 | 4 | ||
diff --git a/shell/ash_test/ash-redir/redir_leak.tests b/shell/ash_test/ash-redir/redir_leak.tests new file mode 100755 index 000000000..c8a9c6343 --- /dev/null +++ b/shell/ash_test/ash-redir/redir_leak.tests | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | # Each of these should show only four lines: | ||
| 2 | # fds 0,1,2 are stdio; fd 3 is open by opendir() in ls. | ||
| 3 | # This test detects bugs where redirects leave stray open fds. | ||
| 4 | |||
| 5 | ls -1 /proc/self/fd | wc -l | ||
| 6 | ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l | ||
| 7 | ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l | ||
| 8 | echo "`ls -1 /proc/self/fd `" | wc -l | ||
| 9 | echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l | ||
| 10 | echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l | ||
diff --git a/shell/hush_test/hush-redir/redir_leak.right b/shell/hush_test/hush-redir/redir_leak.right new file mode 100644 index 000000000..b1c48292b --- /dev/null +++ b/shell/hush_test/hush-redir/redir_leak.right | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | 4 | ||
| 2 | 4 | ||
| 3 | 4 | ||
| 4 | 4 | ||
| 5 | 4 | ||
| 6 | 4 | ||
diff --git a/shell/hush_test/hush-redir/redir_leak.tests b/shell/hush_test/hush-redir/redir_leak.tests new file mode 100755 index 000000000..c8a9c6343 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_leak.tests | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | # Each of these should show only four lines: | ||
| 2 | # fds 0,1,2 are stdio; fd 3 is open by opendir() in ls. | ||
| 3 | # This test detects bugs where redirects leave stray open fds. | ||
| 4 | |||
| 5 | ls -1 /proc/self/fd | wc -l | ||
| 6 | ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l | ||
| 7 | ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l | ||
| 8 | echo "`ls -1 /proc/self/fd `" | wc -l | ||
| 9 | echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l | ||
| 10 | echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l | ||
diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests index d8738a3bd..d9c45242c 100755 --- a/testsuite/unzip.tests +++ b/testsuite/unzip.tests | |||
| @@ -31,11 +31,10 @@ rmdir foo | |||
| 31 | rm foo.zip | 31 | rm foo.zip |
| 32 | 32 | ||
| 33 | # File containing some damaged encrypted stream | 33 | # File containing some damaged encrypted stream |
| 34 | optional FEATURE_UNZIP_CDF | ||
| 34 | testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \ | 35 | testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \ |
| 35 | "Archive: bad.zip | 36 | "Archive: bad.zip |
| 36 | inflating: ]3j½r«IK-%Ix | 37 | unzip: short read |
| 37 | unzip: corrupted data | ||
| 38 | unzip: inflate error | ||
| 39 | 1 | 38 | 1 |
| 40 | " \ | 39 | " \ |
| 41 | "" "\ | 40 | "" "\ |
| @@ -49,6 +48,7 @@ BDYAAAAMAAEADQAAADIADQAAAEEAAAASw73Ct1DKokohPXQiNzA+FAI1HCcW | |||
| 49 | NzITNFBLBQUKAC4JAA04Cw0EOhZQSwUGAQAABAIAAgCZAAAAeQAAAAIALhM= | 48 | NzITNFBLBQUKAC4JAA04Cw0EOhZQSwUGAQAABAIAAgCZAAAAeQAAAAIALhM= |
| 50 | ==== | 49 | ==== |
| 51 | " | 50 | " |
| 51 | SKIP= | ||
| 52 | 52 | ||
| 53 | rm * | 53 | rm * |
| 54 | 54 | ||
