aboutsummaryrefslogtreecommitdiff
path: root/networking/wget.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-02-11 21:42:00 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2011-02-11 21:42:00 +0100
commit8766a791e847fdf1f3f00222f18c18833f40abda (patch)
treec62762ba0d933cb38e25b8c0f00686841b9cf63f /networking/wget.c
parentab8d00d64fc23602875952c08c030f05f206686c (diff)
downloadbusybox-w32-8766a791e847fdf1f3f00222f18c18833f40abda.tar.gz
busybox-w32-8766a791e847fdf1f3f00222f18c18833f40abda.tar.bz2
busybox-w32-8766a791e847fdf1f3f00222f18c18833f40abda.zip
wget: correctly handle rare case when we get EAGAIN _on first_ read
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/wget.c')
-rw-r--r--networking/wget.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/networking/wget.c b/networking/wget.c
index f2d7daf2f..48688640a 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -487,6 +487,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
487 rdsz = (unsigned)G.content_len; 487 rdsz = (unsigned)G.content_len;
488 } 488 }
489 } 489 }
490
490#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT 491#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
491# if ENABLE_FEATURE_WGET_TIMEOUT 492# if ENABLE_FEATURE_WGET_TIMEOUT
492 second_cnt = G.timeout_seconds; 493 second_cnt = G.timeout_seconds;
@@ -497,22 +498,41 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
497# if ENABLE_FEATURE_WGET_TIMEOUT 498# if ENABLE_FEATURE_WGET_TIMEOUT
498 if (second_cnt != 0 && --second_cnt == 0) { 499 if (second_cnt != 0 && --second_cnt == 0) {
499 progress_meter(PROGRESS_END); 500 progress_meter(PROGRESS_END);
500 bb_perror_msg_and_die("download timed out"); 501 bb_error_msg_and_die("download timed out");
501 } 502 }
502# endif 503# endif
503 /* Needed for "stalled" indicator */ 504 /* Needed for "stalled" indicator */
504 progress_meter(PROGRESS_BUMP); 505 progress_meter(PROGRESS_BUMP);
505 } 506 }
506#endif 507#endif
508 /* fread internally uses read loop, which in our case
509 * is usually exited when we get EAGAIN.
510 * In this case, libc sets error marker on the stream.
511 * Need to clear it before next fread to avoid possible
512 * rare false positive ferror below. Rare because usually
513 * fread gets more than zero bytes, and we don't fall
514 * into if (n <= 0) ...
515 */
516 clearerr(dfp);
517 errno = 0;
507 n = fread(G.wget_buf, 1, rdsz, dfp); 518 n = fread(G.wget_buf, 1, rdsz, dfp);
519 /* man fread:
520 * If error occurs, or EOF is reached, the return value
521 * is a short item count (or zero).
522 * fread does not distinguish between EOF and error.
523 */
508 if (n <= 0) { 524 if (n <= 0) {
509 if (ferror(dfp)) { 525#if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT
510 /* perror will not work: ferror doesn't set errno */ 526 if (errno == EAGAIN) /* poll lied, there is no data? */
511 bb_error_msg_and_die(bb_msg_read_error); 527 continue; /* yes */
512 } 528#endif
513 break; 529 if (ferror(dfp))
530 bb_perror_msg_and_die(bb_msg_read_error);
531 break; /* EOF, not error */
514 } 532 }
533
515 xwrite(output_fd, G.wget_buf, n); 534 xwrite(output_fd, G.wget_buf, n);
535
516#if ENABLE_FEATURE_WGET_STATUSBAR 536#if ENABLE_FEATURE_WGET_STATUSBAR
517 G.transferred += n; 537 G.transferred += n;
518 progress_meter(PROGRESS_BUMP); 538 progress_meter(PROGRESS_BUMP);