1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
--- busybox-1.18.3/networking/wget.c
+++ busybox-1.18.3-wget/networking/wget.c
@@ -446,7 +446,7 @@ static FILE* prepare_ftp_session(FILE **
static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
{
- char buf[512];
+ char buf[4*1024]; /* made bigger to speed up local xfers */
#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
# if ENABLE_FEATURE_WGET_TIMEOUT
unsigned second_cnt;
@@ -455,7 +455,6 @@ static void NOINLINE retrieve_file_data(
polldata.fd = fileno(dfp);
polldata.events = POLLIN | POLLPRI;
- ndelay_on(polldata.fd);
#endif
progress_meter(PROGRESS_START);
@@ -464,6 +463,10 @@ static void NOINLINE retrieve_file_data(
/* Loops only if chunked */
while (1) {
+
+#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
+ ndelay_on(polldata.fd);
+#endif
while (1) {
int n;
unsigned rdsz;
@@ -493,22 +496,46 @@ static void NOINLINE retrieve_file_data(
progress_meter(PROGRESS_BUMP);
}
#endif
+ /* fread internally uses read loop, which in our case
+ * is usually exited when we get EAGAIN.
+ * In this case, libc sets error marker on the stream.
+ * Need to clear it before next fread to avoid possible
+ * rare false positive ferror below. Rare because usually
+ * fread gets more than zero bytes, and we don't fall
+ * into if (n <= 0) ...
+ */
+ clearerr(dfp);
+ errno = 0;
n = safe_fread(buf, rdsz, dfp);
+ /* man fread:
+ * If error occurs, or EOF is reached, the return value
+ * is a short item count (or zero).
+ * fread does not distinguish between EOF and error.
+ */
if (n <= 0) {
- if (ferror(dfp)) {
- /* perror will not work: ferror doesn't set errno */
- bb_error_msg_and_die(bb_msg_read_error);
- }
- break;
+#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
+ if (errno == EAGAIN) /* poll lied, there is no data? */
+ continue; /* yes */
+#endif
+ if (ferror(dfp))
+ bb_perror_msg_and_die(bb_msg_read_error);
+ break; /* EOF, not error */
}
+
xwrite(output_fd, buf, n);
#if ENABLE_FEATURE_WGET_STATUSBAR
G.transferred += n;
progress_meter(PROGRESS_BUMP);
#endif
- if (G.got_clen)
+ if (G.got_clen) {
G.content_len -= n;
+ if (G.content_len == 0)
+ break;
+ }
}
+#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
+ ndelay_off(polldata.fd);
+#endif
if (!G.chunked)
break;
@@ -706,6 +733,11 @@ int wget_main(int argc UNUSED_PARAM, cha
fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
target.host, user_agent);
+ /* Ask server to close the connection as soon as we are done
+ * (IOW: we do not intend to send more requests)
+ */
+ fprintf(sfp, "Connection: close\r\n");
+
#if ENABLE_FEATURE_WGET_AUTHENTICATION
if (target.user) {
fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
@@ -719,22 +751,25 @@ int wget_main(int argc UNUSED_PARAM, cha
if (G.beg_range)
fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
+
#if ENABLE_FEATURE_WGET_LONG_OPTIONS
if (extra_headers)
fputs(extra_headers, sfp);
if (opt & WGET_OPT_POST_DATA) {
char *estr = URL_escape(post_data);
- fprintf(sfp, "Content-Type: application/x-www-form-urlencoded\r\n");
- fprintf(sfp, "Content-Length: %u\r\n" "\r\n" "%s",
- (int) strlen(estr), estr);
- /*fprintf(sfp, "Connection: Keep-Alive\r\n\r\n");*/
- /*fprintf(sfp, "%s\r\n", estr);*/
+ fprintf(sfp,
+ "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Content-Length: %u\r\n"
+ "\r\n"
+ "%s",
+ (int) strlen(estr), estr
+ );
free(estr);
} else
#endif
- { /* If "Connection:" is needed, document why */
- fprintf(sfp, /* "Connection: close\r\n" */ "\r\n");
+ {
+ fprintf(sfp, "\r\n");
}
fflush(sfp);
|