summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--applets/applets.c7
-rw-r--r--archival/bbunzip.c2
-rw-r--r--archival/libunarchive/Kbuild60
-rw-r--r--archival/libunarchive/get_header_tar_bz2.c2
-rw-r--r--archival/libunarchive/get_header_tar_gz.c9
-rw-r--r--archival/libunarchive/get_header_tar_lzma.c2
-rw-r--r--archival/libunarchive/open_transformer.c31
-rw-r--r--archival/rpm.c26
-rw-r--r--archival/tar.c2
-rw-r--r--include/libbb.h9
-rw-r--r--include/unarchive.h6
-rw-r--r--libbb/copy_file.c191
-rw-r--r--libbb/xreadlink.c22
-rw-r--r--networking/isrv.c18
-rw-r--r--runit/runsv.c36
-rwxr-xr-xscripts/trylink58
17 files changed, 283 insertions, 200 deletions
diff --git a/Makefile b/Makefile
index 9e35e517a..5ac88313c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
1VERSION = 1 1VERSION = 1
2PATCHLEVEL = 7 2PATCHLEVEL = 7
3SUBLEVEL = 1 3SUBLEVEL = 1
4EXTRAVERSION = .svn 4EXTRAVERSION =
5NAME = Unnamed 5NAME = Unnamed
6 6
7# *DOCUMENTATION* 7# *DOCUMENTATION*
diff --git a/applets/applets.c b/applets/applets.c
index 6de6db3cd..b40f01836 100644
--- a/applets/applets.c
+++ b/applets/applets.c
@@ -546,7 +546,7 @@ static int busybox_main(char **argv)
546 help: 546 help:
547 output_width = 80; 547 output_width = 80;
548 if (ENABLE_FEATURE_AUTOWIDTH) { 548 if (ENABLE_FEATURE_AUTOWIDTH) {
549 /* Obtain the terminal width. */ 549 /* Obtain the terminal width */
550 get_terminal_width_height(0, &output_width, NULL); 550 get_terminal_width_height(0, &output_width, NULL);
551 } 551 }
552 /* leading tab and room to wrap */ 552 /* leading tab and room to wrap */
@@ -580,12 +580,11 @@ static int busybox_main(char **argv)
580 580
581 if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { 581 if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) {
582 const char *busybox; 582 const char *busybox;
583 busybox = xmalloc_readlink_or_warn(bb_busybox_exec_path); 583 busybox = xmalloc_readlink(bb_busybox_exec_path);
584 if (!busybox) 584 if (!busybox)
585 busybox = bb_busybox_exec_path; 585 busybox = bb_busybox_exec_path;
586 /* -s makes symlinks */ 586 /* -s makes symlinks */
587 install_links(busybox, 587 install_links(busybox, argv[2] && strcmp(argv[2], "-s") == 0);
588 argv[2] && strcmp(argv[2], "-s") == 0);
589 return 0; 588 return 0;
590 } 589 }
591 590
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index 56c742a49..a4e525f2e 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -298,7 +298,7 @@ USE_DESKTOP(long long) int unpack_unlzma(void)
298int unlzma_main(int argc, char **argv); 298int unlzma_main(int argc, char **argv);
299int unlzma_main(int argc, char **argv) 299int unlzma_main(int argc, char **argv)
300{ 300{
301 getopt32(argv, "c"); 301 getopt32(argv, "cf");
302 argv += optind; 302 argv += optind;
303 /* lzmacat? */ 303 /* lzmacat? */
304 if (applet_name[4] == 'c') 304 if (applet_name[4] == 'c')
diff --git a/archival/libunarchive/Kbuild b/archival/libunarchive/Kbuild
index 3c29d541a..d104524e4 100644
--- a/archival/libunarchive/Kbuild
+++ b/archival/libunarchive/Kbuild
@@ -35,36 +35,34 @@ DPKG_FILES:= \
35 get_header_tar.o \ 35 get_header_tar.o \
36 filter_accept_list_reassign.o 36 filter_accept_list_reassign.o
37 37
38# open_transformer uses fork(). Compile it only if absolutely necessary
39lib-$(CONFIG_RPM) += open_transformer.o 38lib-$(CONFIG_RPM) += open_transformer.o
40lib-$(CONFIG_FEATURE_TAR_BZIP2) += open_transformer.o 39lib-$(CONFIG_FEATURE_TAR_BZIP2) += open_transformer.o
41lib-$(CONFIG_FEATURE_TAR_LZMA) += open_transformer.o 40lib-$(CONFIG_FEATURE_TAR_LZMA) += open_transformer.o
42lib-$(CONFIG_FEATURE_TAR_GZIP) += open_transformer.o 41lib-$(CONFIG_FEATURE_TAR_GZIP) += open_transformer.o
43lib-$(CONFIG_FEATURE_TAR_COMPRESS) += open_transformer.o 42lib-$(CONFIG_FEATURE_TAR_COMPRESS) += open_transformer.o
44lib-$(CONFIG_FEATURE_DEB_TAR_GZ) += open_transformer.o 43lib-$(CONFIG_FEATURE_DEB_TAR_GZ) += open_transformer.o
45lib-$(CONFIG_FEATURE_DEB_TAR_BZ2) += open_transformer.o 44lib-$(CONFIG_FEATURE_DEB_TAR_BZ2) += open_transformer.o
46lib-$(CONFIG_FEATURE_DEB_TAR_LZMA) += open_transformer.o 45lib-$(CONFIG_FEATURE_DEB_TAR_LZMA) += open_transformer.o
47
48lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
49lib-$(CONFIG_BUNZIP2) += decompress_bunzip2.o
50lib-$(CONFIG_UNLZMA) += decompress_unlzma.o
51lib-$(CONFIG_CPIO) += get_header_cpio.o
52lib-$(CONFIG_DPKG) += $(DPKG_FILES)
53lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
54lib-$(CONFIG_FEATURE_DEB_TAR_GZ) += $(GUNZIP_FILES) get_header_tar_gz.o
55lib-$(CONFIG_FEATURE_DEB_TAR_BZ2) += decompress_bunzip2.o get_header_tar_bz2.o
56lib-$(CONFIG_FEATURE_DEB_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
57lib-$(CONFIG_GUNZIP) += $(GUNZIP_FILES)
58lib-$(CONFIG_FEATURE_GUNZIP_UNCOMPRESS) += decompress_uncompress.o
59lib-$(CONFIG_RPM2CPIO) += $(GUNZIP_FILES) get_header_cpio.o
60lib-$(CONFIG_RPM) += $(GUNZIP_FILES) get_header_cpio.o
61lib-$(CONFIG_FEATURE_RPM_BZ2) += decompress_bunzip2.o
62lib-$(CONFIG_TAR) += get_header_tar.o
63lib-$(CONFIG_FEATURE_TAR_BZIP2) += decompress_bunzip2.o get_header_tar_bz2.o
64lib-$(CONFIG_FEATURE_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
65lib-$(CONFIG_FEATURE_TAR_GZIP) += $(GUNZIP_FILES) get_header_tar_gz.o
66lib-$(CONFIG_FEATURE_TAR_COMPRESS) += decompress_uncompress.o
67lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
68lib-$(CONFIG_UNZIP) += $(GUNZIP_FILES)
69lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o
70 46
47lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
48lib-$(CONFIG_BUNZIP2) += decompress_bunzip2.o
49lib-$(CONFIG_UNLZMA) += decompress_unlzma.o
50lib-$(CONFIG_CPIO) += get_header_cpio.o
51lib-$(CONFIG_DPKG) += $(DPKG_FILES)
52lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
53lib-$(CONFIG_FEATURE_DEB_TAR_GZ) += $(GUNZIP_FILES) get_header_tar_gz.o
54lib-$(CONFIG_FEATURE_DEB_TAR_BZ2) += decompress_bunzip2.o get_header_tar_bz2.o
55lib-$(CONFIG_FEATURE_DEB_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
56lib-$(CONFIG_GUNZIP) += $(GUNZIP_FILES)
57lib-$(CONFIG_FEATURE_GUNZIP_UNCOMPRESS) += decompress_uncompress.o
58lib-$(CONFIG_RPM2CPIO) += $(GUNZIP_FILES) get_header_cpio.o
59lib-$(CONFIG_RPM) += $(GUNZIP_FILES) get_header_cpio.o
60lib-$(CONFIG_FEATURE_RPM_BZ2) += decompress_bunzip2.o
61lib-$(CONFIG_TAR) += get_header_tar.o
62lib-$(CONFIG_FEATURE_TAR_BZIP2) += decompress_bunzip2.o get_header_tar_bz2.o
63lib-$(CONFIG_FEATURE_TAR_LZMA) += decompress_unlzma.o get_header_tar_lzma.o
64lib-$(CONFIG_FEATURE_TAR_GZIP) += $(GUNZIP_FILES) get_header_tar_gz.o
65lib-$(CONFIG_FEATURE_TAR_COMPRESS) += decompress_uncompress.o
66lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
67lib-$(CONFIG_UNZIP) += $(GUNZIP_FILES)
68lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o
diff --git a/archival/libunarchive/get_header_tar_bz2.c b/archival/libunarchive/get_header_tar_bz2.c
index e11f44cad..8f7f83fc2 100644
--- a/archival/libunarchive/get_header_tar_bz2.c
+++ b/archival/libunarchive/get_header_tar_bz2.c
@@ -11,7 +11,7 @@ char get_header_tar_bz2(archive_handle_t *archive_handle)
11 /* Can't lseek over pipes */ 11 /* Can't lseek over pipes */
12 archive_handle->seek = seek_by_read; 12 archive_handle->seek = seek_by_read;
13 13
14 archive_handle->src_fd = open_transformer(archive_handle->src_fd, unpack_bz2_stream); 14 archive_handle->src_fd = open_transformer(archive_handle->src_fd, unpack_bz2_stream, "bunzip2", "bunzip2", "-cf", "-", NULL);
15 archive_handle->offset = 0; 15 archive_handle->offset = 0;
16 while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/; 16 while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/;
17 17
diff --git a/archival/libunarchive/get_header_tar_gz.c b/archival/libunarchive/get_header_tar_gz.c
index 85070d978..a99061411 100644
--- a/archival/libunarchive/get_header_tar_gz.c
+++ b/archival/libunarchive/get_header_tar_gz.c
@@ -8,19 +8,26 @@
8 8
9char get_header_tar_gz(archive_handle_t *archive_handle) 9char get_header_tar_gz(archive_handle_t *archive_handle)
10{ 10{
11#if BB_MMU
11 unsigned char magic[2]; 12 unsigned char magic[2];
13#endif
12 14
13 /* Can't lseek over pipes */ 15 /* Can't lseek over pipes */
14 archive_handle->seek = seek_by_read; 16 archive_handle->seek = seek_by_read;
15 17
18 /* Check gzip magic only if open_transformer will invoke unpack_gz_stream (MMU case).
19 * Otherwise, it will invoke an external helper "gunzip -cf" (NOMMU case) which will
20 * need the header. */
21#if BB_MMU
16 xread(archive_handle->src_fd, &magic, 2); 22 xread(archive_handle->src_fd, &magic, 2);
17 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { 23 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
18 bb_error_msg_and_die("invalid gzip magic"); 24 bb_error_msg_and_die("invalid gzip magic");
19 } 25 }
20 26
21 check_header_gzip_or_die(archive_handle->src_fd); 27 check_header_gzip_or_die(archive_handle->src_fd);
28#endif
22 29
23 archive_handle->src_fd = open_transformer(archive_handle->src_fd, unpack_gz_stream); 30 archive_handle->src_fd = open_transformer(archive_handle->src_fd, unpack_gz_stream, "gunzip", "gunzip", "-cf", "-", NULL);
24 archive_handle->offset = 0; 31 archive_handle->offset = 0;
25 while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/; 32 while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/;
26 33
diff --git a/archival/libunarchive/get_header_tar_lzma.c b/archival/libunarchive/get_header_tar_lzma.c
index 771f664f2..f0e45f2c5 100644
--- a/archival/libunarchive/get_header_tar_lzma.c
+++ b/archival/libunarchive/get_header_tar_lzma.c
@@ -14,7 +14,7 @@ char get_header_tar_lzma(archive_handle_t * archive_handle)
14 /* Can't lseek over pipes */ 14 /* Can't lseek over pipes */
15 archive_handle->seek = seek_by_read; 15 archive_handle->seek = seek_by_read;
16 16
17 archive_handle->src_fd = open_transformer(archive_handle->src_fd, unpack_lzma_stream); 17 archive_handle->src_fd = open_transformer(archive_handle->src_fd, unpack_lzma_stream, "unlzma", "unlzma", "-cf", "-", NULL);
18 archive_handle->offset = 0; 18 archive_handle->offset = 0;
19 while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/; 19 while (get_header_tar(archive_handle) == EXIT_SUCCESS) /**/;
20 20
diff --git a/archival/libunarchive/open_transformer.c b/archival/libunarchive/open_transformer.c
index 0ee080621..f8f587e8d 100644
--- a/archival/libunarchive/open_transformer.c
+++ b/archival/libunarchive/open_transformer.c
@@ -7,27 +7,48 @@
7#include "unarchive.h" 7#include "unarchive.h"
8 8
9/* transformer(), more than meets the eye */ 9/* transformer(), more than meets the eye */
10/*
11 * On MMU machine, the transform_prog and ... are stripped
12 * by a macro in include/unarchive.h. On NOMMU, transformer is stripped.
13 */
10int open_transformer(int src_fd, 14int open_transformer(int src_fd,
11 USE_DESKTOP(long long) int (*transformer)(int src_fd, int dst_fd)) 15 USE_DESKTOP(long long) int (*transformer)(int src_fd, int dst_fd),
16 const char *transform_prog, ...)
12{ 17{
13 int fd_pipe[2]; 18 int fd_pipe[2];
14 int pid; 19 int pid;
15 20
16 xpipe(fd_pipe); 21 xpipe(fd_pipe);
17 22
23#if BB_MMU
18 pid = fork(); 24 pid = fork();
19 if (pid == -1) { 25#else
26 pid = vfork();
27#endif
28 if (pid == -1)
20 bb_perror_msg_and_die("fork failed"); 29 bb_perror_msg_and_die("fork failed");
21 }
22 30
23 if (pid == 0) { 31 if (pid == 0) {
32#if !BB_MMU
33 va_list ap;
34#endif
24 /* child process */ 35 /* child process */
25 close(fd_pipe[0]); /* We don't wan't to read from the parent */ 36 close(fd_pipe[0]); /* We don't wan't to read from the parent */
26 // FIXME: error check? 37 // FIXME: error check?
38#if BB_MMU
27 transformer(src_fd, fd_pipe[1]); 39 transformer(src_fd, fd_pipe[1]);
28 close(fd_pipe[1]); /* Send EOF */ 40 if (ENABLE_FEATURE_CLEAN_UP) {
29 close(src_fd); 41 close(fd_pipe[1]); /* Send EOF */
42 close(src_fd);
43 }
30 exit(0); 44 exit(0);
45#else
46 xmove_fd(src_fd, 0);
47 xmove_fd(fd_pipe[1], 1);
48 va_start(ap, transform_prog);
49 BB_EXECVP(transform_prog, ap);
50 bb_perror_and_die("exec failed");
51#endif
31 /* notreached */ 52 /* notreached */
32 } 53 }
33 54
diff --git a/archival/rpm.c b/archival/rpm.c
index 674ee2640..4d723b73f 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -187,9 +187,15 @@ int rpm_main(int argc, char **argv)
187 187
188static void extract_cpio_gz(int fd) 188static void extract_cpio_gz(int fd)
189{ 189{
190 USE_DESKTOP(long long) int (*xformer)(int src_fd, int dst_fd);
191 archive_handle_t *archive_handle; 190 archive_handle_t *archive_handle;
192 unsigned char magic[2]; 191 unsigned char magic[2];
192#if BB_MMU
193 USE_DESKTOP(long long) int (*xformer)(int src_fd, int dst_fd);
194 enum { xformer_prog = 0 };
195#else
196 enum { xformer = 0 };
197 const char *xformer_prog;
198#endif
193 199
194 /* Initialize */ 200 /* Initialize */
195 archive_handle = init_handle(); 201 archive_handle = init_handle();
@@ -202,11 +208,19 @@ static void extract_cpio_gz(int fd)
202 archive_handle->offset = 0; 208 archive_handle->offset = 0;
203 209
204 xread(archive_handle->src_fd, &magic, 2); 210 xread(archive_handle->src_fd, &magic, 2);
211#if BB_MMU
205 xformer = unpack_gz_stream; 212 xformer = unpack_gz_stream;
213#else
214 xformer_prog = "gunzip";
215#endif
206 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { 216 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
207 if (ENABLE_FEATURE_RPM_BZ2 217 if (ENABLE_FEATURE_RPM_BZ2
208 && (magic[0] == 0x42) && (magic[1] == 0x5a)) { 218 && (magic[0] == 0x42) && (magic[1] == 0x5a)) {
219#if BB_MMU
209 xformer = unpack_bz2_stream; 220 xformer = unpack_bz2_stream;
221#else
222 xformer_prog = "bunzip2";
223#endif
210 /* We can do better, need modifying unpack_bz2_stream to not require 224 /* We can do better, need modifying unpack_bz2_stream to not require
211 * first 2 bytes. Not very hard to do... I mean, TODO :) */ 225 * first 2 bytes. Not very hard to do... I mean, TODO :) */
212 xlseek(archive_handle->src_fd, -2, SEEK_CUR); 226 xlseek(archive_handle->src_fd, -2, SEEK_CUR);
@@ -214,11 +228,17 @@ static void extract_cpio_gz(int fd)
214 bb_error_msg_and_die("no gzip" 228 bb_error_msg_and_die("no gzip"
215 USE_FEATURE_RPM_BZ2("/bzip") 229 USE_FEATURE_RPM_BZ2("/bzip")
216 " magic"); 230 " magic");
217 } else 231 } else {
218 check_header_gzip_or_die(archive_handle->src_fd); 232 check_header_gzip_or_die(archive_handle->src_fd);
233#if !BB_MMU
234 /* NOMMU version of open_transformer execs an external unzipper that should
235 * have the file position at the start of the file */
236 xlseek(archive_handle->src_fd, 0, SEEK_SET);
237#endif
238 }
219 239
220 xchdir("/"); /* Install RPM's to root */ 240 xchdir("/"); /* Install RPM's to root */
221 archive_handle->src_fd = open_transformer(archive_handle->src_fd, xformer); 241 archive_handle->src_fd = open_transformer(archive_handle->src_fd, xformer, xformer_prog, xformer_prog, "-cf", "-", NULL);
222 archive_handle->offset = 0; 242 archive_handle->offset = 0;
223 while (get_header_cpio(archive_handle) == EXIT_SUCCESS) 243 while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
224 continue; 244 continue;
diff --git a/archival/tar.c b/archival/tar.c
index 9bf9058d8..7235616cf 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -648,7 +648,7 @@ static char get_header_tar_Z(archive_handle_t *archive_handle)
648 bb_error_msg_and_die("invalid magic"); 648 bb_error_msg_and_die("invalid magic");
649 } 649 }
650 650
651 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress); 651 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress, "uncompress", "uncompress", "-cf", "-", NULL);
652 archive_handle->offset = 0; 652 archive_handle->offset = 0;
653 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 653 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
654 /* nothing */; 654 /* nothing */;
diff --git a/include/libbb.h b/include/libbb.h
index e514fe2f2..140e21dea 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -248,9 +248,10 @@ void xmove_fd(int, int);
248DIR *xopendir(const char *path); 248DIR *xopendir(const char *path);
249DIR *warn_opendir(const char *path); 249DIR *warn_opendir(const char *path);
250 250
251char *xrealloc_getcwd_or_warn(char *cwd); 251/* UNUSED: char *xmalloc_realpath(const char *path); */
252char *xmalloc_readlink(const char *path);
252char *xmalloc_readlink_or_warn(const char *path); 253char *xmalloc_readlink_or_warn(const char *path);
253char *xmalloc_realpath(const char *path); 254char *xrealloc_getcwd_or_warn(char *cwd);
254 255
255 256
256//TODO: signal(sid, f) is the same? then why? 257//TODO: signal(sid, f) is the same? then why?
@@ -316,8 +317,8 @@ enum {
316}; 317};
317/* Create stream socket, and allocate suitable lsa. 318/* Create stream socket, and allocate suitable lsa.
318 * (lsa of correct size and lsa->sa.sa_family (AF_INET/AF_INET6)) 319 * (lsa of correct size and lsa->sa.sa_family (AF_INET/AF_INET6))
319 * af == AF_UNSPEC will result in trying to create IPv6, and 320 * af == AF_UNSPEC will result in trying to create IPv6 socket,
320 * if kernel doesn't support it, IPv4. 321 * and if kernel doesn't support it, IPv4.
321 */ 322 */
322int xsocket_type(len_and_sockaddr **lsap, USE_FEATURE_IPV6(int af,) int sock_type); 323int xsocket_type(len_and_sockaddr **lsap, USE_FEATURE_IPV6(int af,) int sock_type);
323int xsocket_stream(len_and_sockaddr **lsap); 324int xsocket_stream(len_and_sockaddr **lsap);
diff --git a/include/unarchive.h b/include/unarchive.h
index bea055852..51ec89cc0 100644
--- a/include/unarchive.h
+++ b/include/unarchive.h
@@ -115,7 +115,13 @@ extern USE_DESKTOP(long long) int inflate_unzip(inflate_unzip_result *res, unsig
115extern USE_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd); 115extern USE_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd);
116extern USE_DESKTOP(long long) int unpack_lzma_stream(int src_fd, int dst_fd); 116extern USE_DESKTOP(long long) int unpack_lzma_stream(int src_fd, int dst_fd);
117 117
118#if BB_MMU
118extern int open_transformer(int src_fd, 119extern int open_transformer(int src_fd,
119 USE_DESKTOP(long long) int (*transformer)(int src_fd, int dst_fd)); 120 USE_DESKTOP(long long) int (*transformer)(int src_fd, int dst_fd));
121#define open_transformer(src_fd, transformer, transform_prog, ...) open_transformer(src_fd, transformer)
122#else
123extern int open_transformer(int src_fd, const char *transform_prog, ...);
124#define open_transformer(src_fd, transformer, transform_prog, ...) open_transformer(src_fd, transform_prog, __VA_ARGS__)
125#endif
120 126
121#endif 127#endif
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index b68a257b5..3da8a3531 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -19,28 +19,31 @@
19// (or fail, if it points to dir/nonexistent location/etc). 19// (or fail, if it points to dir/nonexistent location/etc).
20// This is strange, but POSIX-correct. 20// This is strange, but POSIX-correct.
21// coreutils cp has --remove-destination to override this... 21// coreutils cp has --remove-destination to override this...
22//
23// NB: we have special code which still allows for "cp file /dev/node"
24// to work POSIX-ly (the only realistic case where it makes sense)
22 25
23#define DO_POSIX_CP 0 /* 1 - POSIX behavior, 0 - safe behavior */ 26#define DO_POSIX_CP 0 /* 1 - POSIX behavior, 0 - safe behavior */
24 27
25 28// errno must be set to relevant value ("why we cannot create dest?")
29// for POSIX mode to give reasonable error message
26static int ask_and_unlink(const char *dest, int flags) 30static int ask_and_unlink(const char *dest, int flags)
27{ 31{
28 // If !DO_POSIX_CP, act as if -f is always in effect - we don't want
29 // "'file' exists" msg, we want unlink to be done (silently unless -i
30 // is also in effect).
31 // This prevents safe way from asking more questions than POSIX does.
32#if DO_POSIX_CP 32#if DO_POSIX_CP
33 if (!(flags & (FILEUTILS_FORCE|FILEUTILS_INTERACTIVE))) { 33 if (!(flags & (FILEUTILS_FORCE|FILEUTILS_INTERACTIVE))) {
34 fprintf(stderr, "'%s' exists\n", dest); 34 // Either it exists, or the *path* doesnt exist
35 bb_perror_msg("cannot create '%s'", dest);
35 return -1; 36 return -1;
36 } 37 }
37#endif 38#endif
39 // If !DO_POSIX_CP, act as if -f is always in effect - we don't want
40 // "cannot create" msg, we want unlink to be done (silently unless -i).
38 41
39 // TODO: maybe we should do it only if ctty is present? 42 // TODO: maybe we should do it only if ctty is present?
40 if (flags & FILEUTILS_INTERACTIVE) { 43 if (flags & FILEUTILS_INTERACTIVE) {
41 // We would not do POSIX insanity. -i asks, 44 // We would not do POSIX insanity. -i asks,
42 // then _unlinks_ the offender. Presto. 45 // then _unlinks_ the offender. Presto.
43 // (No opening without O_EXCL, no unlinks only if -f) 46 // (No "opening without O_EXCL", no "unlink only if -f")
44 // Or else we will end up having 3 open()s! 47 // Or else we will end up having 3 open()s!
45 fprintf(stderr, "%s: overwrite '%s'? ", applet_name, dest); 48 fprintf(stderr, "%s: overwrite '%s'? ", applet_name, dest);
46 if (!bb_ask_confirmation()) 49 if (!bb_ask_confirmation())
@@ -60,9 +63,11 @@ static int ask_and_unlink(const char *dest, int flags)
60 */ 63 */
61int copy_file(const char *source, const char *dest, int flags) 64int copy_file(const char *source, const char *dest, int flags)
62{ 65{
66 /* This is a recursive function, try to minimize stack usage */
67 /* NB: each struct stat is ~100 bytes */
63 struct stat source_stat; 68 struct stat source_stat;
64 struct stat dest_stat; 69 struct stat dest_stat;
65 int status = 0; 70 signed char retval = 0;
66 signed char dest_exists = 0; 71 signed char dest_exists = 0;
67 signed char ovr; 72 signed char ovr;
68 73
@@ -112,6 +117,7 @@ int copy_file(const char *source, const char *dest, int flags)
112 117
113 if (S_ISDIR(source_stat.st_mode)) { 118 if (S_ISDIR(source_stat.st_mode)) {
114 DIR *dp; 119 DIR *dp;
120 const char *tp;
115 struct dirent *d; 121 struct dirent *d;
116 mode_t saved_umask = 0; 122 mode_t saved_umask = 0;
117 123
@@ -120,12 +126,23 @@ int copy_file(const char *source, const char *dest, int flags)
120 return -1; 126 return -1;
121 } 127 }
122 128
123 /* Create DEST. */ 129 /* Did we ever create source ourself before? */
130 tp = is_in_ino_dev_hashtable(&source_stat);
131 if (tp) {
132 /* We did! it's a recursion! man the lifeboats... */
133 bb_error_msg("recursion detected, omitting directory '%s'",
134 source);
135 return -1;
136 }
137
138 /* Create DEST */
124 if (dest_exists) { 139 if (dest_exists) {
125 if (!S_ISDIR(dest_stat.st_mode)) { 140 if (!S_ISDIR(dest_stat.st_mode)) {
126 bb_error_msg("target '%s' is not a directory", dest); 141 bb_error_msg("target '%s' is not a directory", dest);
127 return -1; 142 return -1;
128 } 143 }
144 /* race here: user can substitute a symlink between
145 * this check and actual creation of files inside dest */
129 } else { 146 } else {
130 mode_t mode; 147 mode_t mode;
131 saved_umask = umask(0); 148 saved_umask = umask(0);
@@ -133,22 +150,29 @@ int copy_file(const char *source, const char *dest, int flags)
133 mode = source_stat.st_mode; 150 mode = source_stat.st_mode;
134 if (!(flags & FILEUTILS_PRESERVE_STATUS)) 151 if (!(flags & FILEUTILS_PRESERVE_STATUS))
135 mode = source_stat.st_mode & ~saved_umask; 152 mode = source_stat.st_mode & ~saved_umask;
153 /* Allow owner to access new dir (at least for now) */
136 mode |= S_IRWXU; 154 mode |= S_IRWXU;
137
138 if (mkdir(dest, mode) < 0) { 155 if (mkdir(dest, mode) < 0) {
139 umask(saved_umask); 156 umask(saved_umask);
140 bb_perror_msg("cannot create directory '%s'", dest); 157 bb_perror_msg("cannot create directory '%s'", dest);
141 return -1; 158 return -1;
142 } 159 }
143
144 umask(saved_umask); 160 umask(saved_umask);
161 /* need stat info for add_to_ino_dev_hashtable */
162 if (lstat(dest, &dest_stat) < 0) {
163 bb_perror_msg("cannot stat '%s'", dest);
164 return -1;
165 }
145 } 166 }
167 /* remember (dev,inode) of each created dir.
168 * NULL: name is not remembered */
169 add_to_ino_dev_hashtable(&dest_stat, NULL);
146 170
147 /* Recursively copy files in SOURCE. */ 171 /* Recursively copy files in SOURCE */
148 dp = opendir(source); 172 dp = opendir(source);
149 if (dp == NULL) { 173 if (dp == NULL) {
150 status = -1; 174 retval = -1;
151 goto preserve_status; 175 goto preserve_mode_ugid_time;
152 } 176 }
153 177
154 while ((d = readdir(dp)) != NULL) { 178 while ((d = readdir(dp)) != NULL) {
@@ -159,7 +183,7 @@ int copy_file(const char *source, const char *dest, int flags)
159 continue; 183 continue;
160 new_dest = concat_path_file(dest, d->d_name); 184 new_dest = concat_path_file(dest, d->d_name);
161 if (copy_file(new_source, new_dest, flags) < 0) 185 if (copy_file(new_source, new_dest, flags) < 0)
162 status = -1; 186 retval = -1;
163 free(new_source); 187 free(new_source);
164 free(new_dest); 188 free(new_dest);
165 } 189 }
@@ -168,11 +192,13 @@ int copy_file(const char *source, const char *dest, int flags)
168 if (!dest_exists 192 if (!dest_exists
169 && chmod(dest, source_stat.st_mode & ~saved_umask) < 0 193 && chmod(dest, source_stat.st_mode & ~saved_umask) < 0
170 ) { 194 ) {
171 bb_perror_msg("cannot change permissions of '%s'", dest); 195 bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest);
172 status = -1; 196 /* retval = -1; - WRONG! copy *WAS* made */
173 } 197 }
198 goto preserve_mode_ugid_time;
199 }
174 200
175 } else if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) { 201 if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
176 int (*lf)(const char *oldpath, const char *newpath); 202 int (*lf)(const char *oldpath, const char *newpath);
177 make_links: 203 make_links:
178 // Hmm... maybe 204 // Hmm... maybe
@@ -188,47 +214,52 @@ int copy_file(const char *source, const char *dest, int flags)
188 return -1; 214 return -1;
189 } 215 }
190 } 216 }
217 /* _Not_ jumping to preserve_mode_ugid_time:
218 * hard/softlinks don't have those */
191 return 0; 219 return 0;
220 }
192 221
193 } else if (S_ISREG(source_stat.st_mode) 222 if (S_ISREG(source_stat.st_mode)
194 /* Huh? DEREF uses stat, which never returns links! */ 223 /* DEREF uses stat, which never returns S_ISLNK() == true. */
195 /* || (FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) */ 224 /* || (FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) */
196 ) { 225 ) {
197 int src_fd; 226 int src_fd;
198 int dst_fd; 227 int dst_fd;
199 if (ENABLE_FEATURE_PRESERVE_HARDLINKS) {
200 char *link_target;
201 228
202 if (!FLAGS_DEREF) { 229 if (ENABLE_FEATURE_PRESERVE_HARDLINKS && !FLAGS_DEREF) {
203 link_target = is_in_ino_dev_hashtable(&source_stat); 230 const char *link_target;
204 if (link_target) { 231 link_target = is_in_ino_dev_hashtable(&source_stat);
232 if (link_target) {
233 if (link(link_target, dest) < 0) {
234 ovr = ask_and_unlink(dest, flags);
235 if (ovr <= 0)
236 return ovr;
205 if (link(link_target, dest) < 0) { 237 if (link(link_target, dest) < 0) {
206 ovr = ask_and_unlink(dest, flags); 238 bb_perror_msg("cannot create link '%s'", dest);
207 if (ovr <= 0) 239 return -1;
208 return ovr;
209 if (link(link_target, dest) < 0) {
210 bb_perror_msg("cannot create link '%s'", dest);
211 return -1;
212 }
213 } 240 }
214 return 0;
215 } 241 }
242 return 0;
216 } 243 }
217 add_to_ino_dev_hashtable(&source_stat, dest); 244 add_to_ino_dev_hashtable(&source_stat, dest);
218 } 245 }
219 246
220 src_fd = open_or_warn(source, O_RDONLY); 247 src_fd = open_or_warn(source, O_RDONLY);
221 if (src_fd < 0) { 248 if (src_fd < 0)
222 return -1; 249 return -1;
223 }
224 250
225#if DO_POSIX_CP /* POSIX way (a security problem versus symlink attacks!): */ 251 /* POSIX way is a security problem versus symlink attacks,
226 dst_fd = open(dest, (flags & FILEUTILS_INTERACTIVE) 252 * we do it only for non-symlinks, and only for non-recursive,
227 ? O_WRONLY|O_CREAT|O_EXCL 253 * non-interactive cp. NB: it is still racy
228 : O_WRONLY|O_CREAT|O_TRUNC, source_stat.st_mode); 254 * for "cp file /home/bad_user/file" case
229#else /* safe way: */ 255 * (user can rm file and create a link to /etc/passwd) */
230 dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, source_stat.st_mode); 256 if (DO_POSIX_CP
231#endif 257 || (dest_exists && !(flags & (FILEUTILS_RECUR|FILEUTILS_INTERACTIVE))
258 && !S_ISLNK(dest_stat.st_mode))
259 ) {
260 dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, source_stat.st_mode);
261 } else /* safe way: */
262 dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, source_stat.st_mode);
232 if (dst_fd == -1) { 263 if (dst_fd == -1) {
233 ovr = ask_and_unlink(dest, flags); 264 ovr = ask_and_unlink(dest, flags);
234 if (ovr <= 0) { 265 if (ovr <= 0) {
@@ -264,60 +295,55 @@ int copy_file(const char *source, const char *dest, int flags)
264 } 295 }
265#endif 296#endif
266 if (bb_copyfd_eof(src_fd, dst_fd) == -1) 297 if (bb_copyfd_eof(src_fd, dst_fd) == -1)
267 status = -1; 298 retval = -1;
299 /* Ok, writing side I can understand... */
268 if (close(dst_fd) < 0) { 300 if (close(dst_fd) < 0) {
269 bb_perror_msg("cannot close '%s'", dest); 301 bb_perror_msg("cannot close '%s'", dest);
270 status = -1; 302 retval = -1;
271 }
272 if (close(src_fd) < 0) {
273 bb_perror_msg("cannot close '%s'", source);
274 status = -1;
275 } 303 }
304 /* ...but read size is already checked by bb_copyfd_eof */
305 close(src_fd);
306 goto preserve_mode_ugid_time;
307 }
276 308
277 } else if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) 309 /* Source is a symlink or a special file */
278 || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) 310 /* We are lazy here, a bit lax with races... */
279 || S_ISLNK(source_stat.st_mode) 311 if (dest_exists) {
280 ) { 312 errno = EEXIST;
281 // We are lazy here, a bit lax with races... 313 ovr = ask_and_unlink(dest, flags);
282 if (dest_exists) { 314 if (ovr <= 0)
283 ovr = ask_and_unlink(dest, flags); 315 return ovr;
284 if (ovr <= 0) 316 }
285 return ovr; 317 if (S_ISLNK(source_stat.st_mode)) {
286 } 318 char *lpath = xmalloc_readlink_or_warn(source);
287 if (S_ISFIFO(source_stat.st_mode)) { 319 if (lpath) {
288 if (mkfifo(dest, source_stat.st_mode) < 0) { 320 int r = symlink(lpath, dest);
289 bb_perror_msg("cannot create fifo '%s'", dest); 321 free(lpath);
290 return -1; 322 if (r < 0) {
291 }
292 } else if (S_ISLNK(source_stat.st_mode)) {
293 char *lpath;
294
295 lpath = xmalloc_readlink_or_warn(source);
296 if (lpath && symlink(lpath, dest) < 0) {
297 bb_perror_msg("cannot create symlink '%s'", dest); 323 bb_perror_msg("cannot create symlink '%s'", dest);
298 free(lpath);
299 return -1; 324 return -1;
300 } 325 }
301 free(lpath);
302
303 if (flags & FILEUTILS_PRESERVE_STATUS) 326 if (flags & FILEUTILS_PRESERVE_STATUS)
304 if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0) 327 if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0)
305 bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest); 328 bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);
306 329 }
307 return 0; 330 /* _Not_ jumping to preserve_mode_ugid_time:
308 331 * symlinks don't have those */
309 } else { 332 return 0;
310 if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) { 333 }
311 bb_perror_msg("cannot create '%s'", dest); 334 if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode)
312 return -1; 335 || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode)
313 } 336 ) {
337 if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) {
338 bb_perror_msg("cannot create '%s'", dest);
339 return -1;
314 } 340 }
315 } else { 341 } else {
316 bb_error_msg("internal error: unrecognized file type"); 342 bb_error_msg("unrecognized file '%s' with mode %x", source, source_stat.st_mode);
317 return -1; 343 return -1;
318 } 344 }
319 345
320 preserve_status: 346 preserve_mode_ugid_time:
321 347
322 if (flags & FILEUTILS_PRESERVE_STATUS 348 if (flags & FILEUTILS_PRESERVE_STATUS
323 /* Cannot happen: */ 349 /* Cannot happen: */
@@ -327,6 +353,7 @@ int copy_file(const char *source, const char *dest, int flags)
327 353
328 times.actime = source_stat.st_atime; 354 times.actime = source_stat.st_atime;
329 times.modtime = source_stat.st_mtime; 355 times.modtime = source_stat.st_mtime;
356 /* BTW, utimes sets usec-precision time - just FYI */
330 if (utime(dest, &times) < 0) 357 if (utime(dest, &times) < 0)
331 bb_perror_msg("cannot preserve %s of '%s'", "times", dest); 358 bb_perror_msg("cannot preserve %s of '%s'", "times", dest);
332 if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) { 359 if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) {
@@ -337,5 +364,5 @@ int copy_file(const char *source, const char *dest, int flags)
337 bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest); 364 bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest);
338 } 365 }
339 366
340 return status; 367 return retval;
341} 368}
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index 18a8b9467..4d87b944d 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -10,8 +10,7 @@
10 * NOTE: This function returns a malloced char* that you will have to free 10 * NOTE: This function returns a malloced char* that you will have to free
11 * yourself. You have been warned. 11 * yourself. You have been warned.
12 */ 12 */
13 13char *xmalloc_readlink(const char *path)
14char *xmalloc_readlink_or_warn(const char *path)
15{ 14{
16 enum { GROWBY = 80 }; /* how large we will grow strings by */ 15 enum { GROWBY = 80 }; /* how large we will grow strings by */
17 16
@@ -20,20 +19,30 @@ char *xmalloc_readlink_or_warn(const char *path)
20 19
21 do { 20 do {
22 buf = xrealloc(buf, bufsize += GROWBY); 21 buf = xrealloc(buf, bufsize += GROWBY);
23 readsize = readlink(path, buf, bufsize); /* 1st try */ 22 readsize = readlink(path, buf, bufsize);
24 if (readsize == -1) { 23 if (readsize == -1) {
25 bb_perror_msg("%s", path);
26 free(buf); 24 free(buf);
27 return NULL; 25 return NULL;
28 } 26 }
29 } 27 } while (bufsize < readsize + 1);
30 while (bufsize < readsize + 1);
31 28
32 buf[readsize] = '\0'; 29 buf[readsize] = '\0';
33 30
34 return buf; 31 return buf;
35} 32}
36 33
34char *xmalloc_readlink_or_warn(const char *path)
35{
36 char *buf = xmalloc_readlink(path);
37 if (!buf) {
38 /* EINVAL => "file: Invalid argument" => puzzled user */
39 bb_error_msg("%s: cannot read link (not a symlink?)", path);
40 }
41 return buf;
42}
43
44/* UNUSED */
45#if 0
37char *xmalloc_realpath(const char *path) 46char *xmalloc_realpath(const char *path)
38{ 47{
39#if defined(__GLIBC__) && !defined(__UCLIBC__) 48#if defined(__GLIBC__) && !defined(__UCLIBC__)
@@ -46,3 +55,4 @@ char *xmalloc_realpath(const char *path)
46 return xstrdup(realpath(path, buf)); 55 return xstrdup(realpath(path, buf));
47#endif 56#endif
48} 57}
58#endif
diff --git a/networking/isrv.c b/networking/isrv.c
index 1a41dd4fb..080c60fbd 100644
--- a/networking/isrv.c
+++ b/networking/isrv.c
@@ -21,20 +21,6 @@
21 21
22/* Helpers */ 22/* Helpers */
23 23
24/* Even if _POSIX_MONOTONIC_CLOCK is defined, this
25 * may require librt */
26#if 0 /*def _POSIX_MONOTONIC_CLOCK*/
27static time_t monotonic_time(void)
28{
29 struct timespec ts;
30 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
31 time(&ts.tv_sec);
32 return ts.tv_sec;
33}
34#else
35#define monotonic_time() (time(NULL))
36#endif
37
38/* Opaque structure */ 24/* Opaque structure */
39 25
40struct isrv_state_t { 26struct isrv_state_t {
@@ -258,7 +244,7 @@ static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void *
258 /* this peer is gone */ 244 /* this peer is gone */
259 remove_peer(state, peer); 245 remove_peer(state, peer);
260 } else if (TIMEOUT) { 246 } else if (TIMEOUT) {
261 TIMEO_TBL[peer] = monotonic_time(); 247 TIMEO_TBL[peer] = monotonic_sec();
262 } 248 }
263 } 249 }
264} 250}
@@ -335,7 +321,7 @@ void isrv_run(
335 break; 321 break;
336 322
337 if (timeout) { 323 if (timeout) {
338 time_t t = monotonic_time(); 324 time_t t = monotonic_sec();
339 if (t != CURTIME) { 325 if (t != CURTIME) {
340 CURTIME = t; 326 CURTIME = t;
341 handle_timeout(state, do_timeout); 327 handle_timeout(state, do_timeout);
diff --git a/runit/runsv.c b/runit/runsv.c
index baef6e13f..b35c26630 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -33,6 +33,34 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33#include "libbb.h" 33#include "libbb.h"
34#include "runit_lib.h" 34#include "runit_lib.h"
35 35
36#if ENABLE_MONOTONIC_SYSCALL
37#include <sys/syscall.h>
38
39/* libc has incredibly messy way of doing this,
40 * typically requiring -lrt. We just skip all this mess */
41static void gettimeofday_ns(struct timespec *ts)
42{
43 syscall(__NR_clock_gettime, CLOCK_REALTIME, ts);
44}
45#else
46static void gettimeofday_ns(struct timespec *ts)
47{
48 if (sizeof(struct timeval) == sizeof(struct timespec)
49 && sizeof(((struct timeval*)ts)->tv_usec) == sizeof(ts->tv_nsec)
50 ) {
51 /* Cheat */
52 gettimeofday((void*)ts, NULL);
53 ts->tv_nsec *= 1000;
54 } else {
55 extern void BUG_need_to_implement_gettimeofday_ns(void);
56 BUG_need_to_implement_gettimeofday_ns();
57 }
58}
59#endif
60
61/* Compare possibly overflowing unsigned counters */
62#define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0)
63
36static int selfpipe[2]; 64static int selfpipe[2];
37 65
38/* state */ 66/* state */
@@ -126,14 +154,6 @@ static int rename_or_warn(const char *old, const char *new)
126 return 0; 154 return 0;
127} 155}
128 156
129#define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0)
130
131#include <sys/syscall.h>
132static void gettimeofday_ns(struct timespec *ts)
133{
134 syscall(__NR_clock_gettime, CLOCK_REALTIME, ts);
135}
136
137static void update_status(struct svdir *s) 157static void update_status(struct svdir *s)
138{ 158{
139 ssize_t sz; 159 ssize_t sz;
diff --git a/scripts/trylink b/scripts/trylink
index 4eaa334d5..0b8f6c062 100755
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -14,37 +14,30 @@ try() {
14BBOX_LIB_LIST=`echo "$BBOX_LIB_LIST" | xargs -n1 | sort | uniq | xargs` 14BBOX_LIB_LIST=`echo "$BBOX_LIB_LIST" | xargs -n1 | sort | uniq | xargs`
15 15
16# First link with all libs. If it fails, bail out 16# First link with all libs. If it fails, bail out
17l_list=`echo "$BBOX_LIB_LIST" | sed -e 's/ / -l/g' -e 's/^/-l/'`
18echo "Trying libraries: $BBOX_LIB_LIST" 17echo "Trying libraries: $BBOX_LIB_LIST"
19try "-Wl,--start-group $l_list -Wl,--end-group" "$@" \ 18l_list=`echo "$BBOX_LIB_LIST" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
19test "x$l_list" != "x" && l_list="-Wl,--start-group $l_list -Wl,--end-group"
20try "$l_list" "$@" \
20|| { 21|| {
21 echo "Failed: $* -Wl,--start-group $l_list -Wl,--end-group" 22 echo "Failed: $* -Wl,--start-group $l_list -Wl,--end-group"
22 cat busybox_ld.err 23 cat busybox_ld.err
23 exit 1 24 exit 1
24} 25}
25 26
26#### Hack disabled: conflicts with ld --verbose flag in last link phase
27
28##### Hack: we are not supposed to know executable name,
29##### but this hack cuts down link time
30####mv busybox_unstripped busybox_unstripped.tmp
31####mv busybox.map busybox.map.tmp
32
33# Now try to remove each lib and build without it. 27# Now try to remove each lib and build without it.
34# Stop when no lib can be removed. 28# Stop when no lib can be removed.
35####ever_discarded=false
36while test "$BBOX_LIB_LIST"; do 29while test "$BBOX_LIB_LIST"; do
37 $debug && echo "Trying libraries: $BBOX_LIB_LIST" 30 $debug && echo "Trying libraries: $BBOX_LIB_LIST"
38 all_needed=true 31 all_needed=true
39 for one in $BBOX_LIB_LIST; do 32 for one in $BBOX_LIB_LIST; do
40 without_one=`echo " $BBOX_LIB_LIST " | sed "s/ $one / /g" | xargs` 33 without_one=`echo " $BBOX_LIB_LIST " | sed "s/ $one / /g" | xargs`
41 l_list=`echo "$without_one" | sed -e 's/ / -l/g' -e 's/^/-l/'` 34 l_list=`echo "$without_one" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
42 $debug && echo "Trying -l options: $l_list" 35 test "x$l_list" != "x" && l_list="-Wl,--start-group $l_list -Wl,--end-group"
43 if try "-Wl,--start-group $l_list -Wl,--end-group" "$@"; then 36 $debug && echo "Trying -l options: '$l_list'"
37 if try "$l_list" "$@"; then
44 echo "Library $one is not needed" 38 echo "Library $one is not needed"
45 BBOX_LIB_LIST="$without_one" 39 BBOX_LIB_LIST="$without_one"
46 all_needed=false 40 all_needed=false
47#### ever_discarded=true
48 else 41 else
49 echo "Library $one is needed" 42 echo "Library $one is needed"
50 fi 43 fi
@@ -57,24 +50,19 @@ while test "$BBOX_LIB_LIST"; do
57 #{ echo "$BBOX_LIB_LIST" | grep -q ' '; } || break 50 #{ echo "$BBOX_LIB_LIST" | grep -q ' '; } || break
58done 51done
59 52
60####mv busybox_unstripped.tmp busybox_unstripped 53# Make the binary with final, minimal list of libs
61####mv busybox.map.tmp busybox.map 54echo "Final link with: $BBOX_LIB_LIST"
62####$ever_discarded && { 55l_list=`echo "$BBOX_LIB_LIST" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
63 # Make the binary with final, minimal list of libs 56test "x$l_list" != "x" && l_list="-Wl,--start-group $l_list -Wl,--end-group -Wl,--verbose"
64 echo "Final link with: $BBOX_LIB_LIST" 57# --verbose gives us gobs of info to stdout (e.g. linker script used)
65 l_list=`echo "$BBOX_LIB_LIST" | sed -e 's/ / -l/g' -e 's/^/-l/'` 58if ! test -f busybox_ldscript; then
66 # --verbose gives us gobs of info to stdout (e.g. linker script used) 59 try "$l_list -Wl,--verbose" "$@" >busybox_ld.out
67 if ! test -f busybox_ldscript; then 60else
68 try "-Wl,--start-group $l_list -Wl,--end-group -Wl,--verbose" "$@" >busybox_ld.out ####|| exit 1 61 echo "Custom linker script 'busybox_ldscript' found, using it"
69 else 62 # Add SORT_BY_ALIGNMENT to linker script (found in busybox_ld.out):
70 echo "Custom linker script 'busybox_ldscript' found, using it" 63 # .rodata : { *(.rodata SORT_BY_ALIGNMENT(.rodata.*) .gnu.linkonce.r.*) }
71 # Add SORT_BY_ALIGNMENT to linker script (found in busybox_ld.out): 64 # *(.data SORT_BY_ALIGNMENT(.data.*) .gnu.linkonce.d.*)
72 # .rodata : { *(.rodata SORT_BY_ALIGNMENT(.rodata.*) .gnu.linkonce.r.*) } 65 # *(.bss SORT_BY_ALIGNMENT(.bss.*) .gnu.linkonce.b.*)
73 # *(.data SORT_BY_ALIGNMENT(.data.*) .gnu.linkonce.d.*) 66 # This will eliminate most of the data padding (~3kb).
74 # *(.bss SORT_BY_ALIGNMENT(.bss.*) .gnu.linkonce.b.*) 67 try "$l_list -Wl,--verbose -Wl,-T -Wl,busybox_ldscript" "$@" >busybox_ld.out
75 # This will eliminate most of the data padding (~3kb). 68fi
76 try "-Wl,--start-group $l_list -Wl,--end-group -Wl,--verbose -Wl,-T -Wl,busybox_ldscript" "$@" >busybox_ld.out
77 fi
78####}
79####rm busybox_ld.err
80####exit 0 # Ensure "success" exit code