aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
Diffstat (limited to 'networking')
-rw-r--r--networking/wget.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/networking/wget.c b/networking/wget.c
index 0db9b3365..afe0d3ab7 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -446,7 +446,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
446 446
447static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) 447static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
448{ 448{
449 char buf[512]; 449 char buf[4*1024]; /* made bigger to speed up local xfers */
450#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT 450#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
451# if ENABLE_FEATURE_WGET_TIMEOUT 451# if ENABLE_FEATURE_WGET_TIMEOUT
452 unsigned second_cnt; 452 unsigned second_cnt;
@@ -455,7 +455,6 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
455 455
456 polldata.fd = fileno(dfp); 456 polldata.fd = fileno(dfp);
457 polldata.events = POLLIN | POLLPRI; 457 polldata.events = POLLIN | POLLPRI;
458 ndelay_on(polldata.fd);
459#endif 458#endif
460 progress_meter(PROGRESS_START); 459 progress_meter(PROGRESS_START);
461 460
@@ -464,6 +463,10 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
464 463
465 /* Loops only if chunked */ 464 /* Loops only if chunked */
466 while (1) { 465 while (1) {
466
467#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
468 ndelay_on(polldata.fd);
469#endif
467 while (1) { 470 while (1) {
468 int n; 471 int n;
469 unsigned rdsz; 472 unsigned rdsz;
@@ -493,22 +496,46 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
493 progress_meter(PROGRESS_BUMP); 496 progress_meter(PROGRESS_BUMP);
494 } 497 }
495#endif 498#endif
499 /* fread internally uses read loop, which in our case
500 * is usually exited when we get EAGAIN.
501 * In this case, libc sets error marker on the stream.
502 * Need to clear it before next fread to avoid possible
503 * rare false positive ferror below. Rare because usually
504 * fread gets more than zero bytes, and we don't fall
505 * into if (n <= 0) ...
506 */
507 clearerr(dfp);
508 errno = 0;
496 n = safe_fread(buf, rdsz, dfp); 509 n = safe_fread(buf, rdsz, dfp);
510 /* man fread:
511 * If error occurs, or EOF is reached, the return value
512 * is a short item count (or zero).
513 * fread does not distinguish between EOF and error.
514 */
497 if (n <= 0) { 515 if (n <= 0) {
498 if (ferror(dfp)) { 516#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
499 /* perror will not work: ferror doesn't set errno */ 517 if (errno == EAGAIN) /* poll lied, there is no data? */
500 bb_error_msg_and_die(bb_msg_read_error); 518 continue; /* yes */
501 } 519#endif
502 break; 520 if (ferror(dfp))
521 bb_perror_msg_and_die(bb_msg_read_error);
522 break; /* EOF, not error */
503 } 523 }
524
504 xwrite(output_fd, buf, n); 525 xwrite(output_fd, buf, n);
505#if ENABLE_FEATURE_WGET_STATUSBAR 526#if ENABLE_FEATURE_WGET_STATUSBAR
506 G.transferred += n; 527 G.transferred += n;
507 progress_meter(PROGRESS_BUMP); 528 progress_meter(PROGRESS_BUMP);
508#endif 529#endif
509 if (G.got_clen) 530 if (G.got_clen) {
510 G.content_len -= n; 531 G.content_len -= n;
532 if (G.content_len == 0)
533 break;
534 }
511 } 535 }
536#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
537 ndelay_off(polldata.fd);
538#endif
512 539
513 if (!G.chunked) 540 if (!G.chunked)
514 break; 541 break;
@@ -706,6 +733,11 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
706 fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n", 733 fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
707 target.host, user_agent); 734 target.host, user_agent);
708 735
736 /* Ask server to close the connection as soon as we are done
737 * (IOW: we do not intend to send more requests)
738 */
739 fprintf(sfp, "Connection: close\r\n");
740
709#if ENABLE_FEATURE_WGET_AUTHENTICATION 741#if ENABLE_FEATURE_WGET_AUTHENTICATION
710 if (target.user) { 742 if (target.user) {
711 fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, 743 fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
@@ -719,22 +751,25 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
719 751
720 if (G.beg_range) 752 if (G.beg_range)
721 fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range); 753 fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
754
722#if ENABLE_FEATURE_WGET_LONG_OPTIONS 755#if ENABLE_FEATURE_WGET_LONG_OPTIONS
723 if (extra_headers) 756 if (extra_headers)
724 fputs(extra_headers, sfp); 757 fputs(extra_headers, sfp);
725 758
726 if (opt & WGET_OPT_POST_DATA) { 759 if (opt & WGET_OPT_POST_DATA) {
727 char *estr = URL_escape(post_data); 760 char *estr = URL_escape(post_data);
728 fprintf(sfp, "Content-Type: application/x-www-form-urlencoded\r\n"); 761 fprintf(sfp,
729 fprintf(sfp, "Content-Length: %u\r\n" "\r\n" "%s", 762 "Content-Type: application/x-www-form-urlencoded\r\n"
730 (int) strlen(estr), estr); 763 "Content-Length: %u\r\n"
731 /*fprintf(sfp, "Connection: Keep-Alive\r\n\r\n");*/ 764 "\r\n"
732 /*fprintf(sfp, "%s\r\n", estr);*/ 765 "%s",
766 (int) strlen(estr), estr
767 );
733 free(estr); 768 free(estr);
734 } else 769 } else
735#endif 770#endif
736 { /* If "Connection:" is needed, document why */ 771 {
737 fprintf(sfp, /* "Connection: close\r\n" */ "\r\n"); 772 fprintf(sfp, "\r\n");
738 } 773 }
739 774
740 fflush(sfp); 775 fflush(sfp);