X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=networking%2Fwget.c;h=ad1770b5803acb7a9b9a812b0fb3770936b7a5a0;hb=695fa51c80047eb25cc82e6e1630b4545a6bc0b6;hp=26b62cc58046a9246562d60c740a5f30f4a91341;hpb=7d5ddf14a3ce2b9c3e8251e40d67333b13287a15;p=oweals%2Fbusybox.git diff --git a/networking/wget.c b/networking/wget.c index 26b62cc58..ad1770b58 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -24,12 +24,9 @@ struct globals { off_t content_len; /* Content-length of the file */ off_t beg_range; /* Range at which continue begins */ #if ENABLE_FEATURE_WGET_STATUSBAR - off_t lastsize; - off_t totalsize; off_t transferred; /* Number of bytes transferred so far */ const char *curfile; /* Name of current file being transferred */ - unsigned lastupdate_sec; - unsigned start_sec; + bb_progress_t pmt; #endif smallint chunked; /* chunked transfer encoding */ smallint got_clen; /* got content-length: from server */ @@ -38,110 +35,28 @@ struct globals { struct BUG_G_too_big { char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; }; -#define content_len (G.content_len ) -#define beg_range (G.beg_range ) -#define lastsize (G.lastsize ) -#define totalsize (G.totalsize ) -#define transferred (G.transferred ) -#define curfile (G.curfile ) -#define lastupdate_sec (G.lastupdate_sec ) -#define start_sec (G.start_sec ) #define INIT_G() do { } while (0) #if ENABLE_FEATURE_WGET_STATUSBAR -enum { - STALLTIME = 5 /* Seconds when xfer considered "stalled" */ -}; - -static unsigned int get_tty2_width(void) -{ - unsigned width; - get_terminal_width_height(2, &width, NULL); - return width; -} static void progress_meter(int flag) { /* We can be called from signal handler */ int save_errno = errno; - off_t abbrevsize; - unsigned since_last_update, elapsed; - unsigned ratio; - int barlength, i; if (flag == -1) { /* first call to progress_meter */ - start_sec = monotonic_sec(); - lastupdate_sec = start_sec; - lastsize = 0; - totalsize = content_len + beg_range; /* as content_len changes.. */ - } - - ratio = 100; - if (totalsize != 0 && !G.chunked) { - /* long long helps to have it working even if !LFS */ - ratio = (unsigned) (100ULL * (transferred+beg_range) / totalsize); - if (ratio > 100) ratio = 100; + bb_progress_init(&G.pmt); } - fprintf(stderr, "\r%-20.20s%4d%% ", curfile, ratio); - - barlength = get_tty2_width() - 49; - if (barlength > 0) { - /* god bless gcc for variable arrays :) */ - i = barlength * ratio / 100; - { - char buf[i+1]; - memset(buf, '*', i); - buf[i] = '\0'; - fprintf(stderr, "|%s%*s|", buf, barlength - i, ""); - } - } - i = 0; - abbrevsize = transferred + beg_range; - while (abbrevsize >= 100000) { - i++; - abbrevsize >>= 10; - } - /* see http://en.wikipedia.org/wiki/Tera */ - fprintf(stderr, "%6d%c ", (int)abbrevsize, " kMGTPEZY"[i]); - -// Nuts! Ain't it easier to update progress meter ONLY when we transferred++? - - elapsed = monotonic_sec(); - since_last_update = elapsed - lastupdate_sec; - if (transferred > lastsize) { - lastupdate_sec = elapsed; - lastsize = transferred; - if (since_last_update >= STALLTIME) { - /* We "cut off" these seconds from elapsed time - * by adjusting start time */ - start_sec += since_last_update; - } - since_last_update = 0; /* we are un-stalled now */ - } - elapsed -= start_sec; /* now it's "elapsed since start" */ - - if (since_last_update >= STALLTIME) { - fprintf(stderr, " - stalled -"); - } else { - off_t to_download = totalsize - beg_range; - if (transferred <= 0 || (int)elapsed <= 0 || transferred > to_download || G.chunked) { - fprintf(stderr, "--:--:-- ETA"); - } else { - /* to_download / (transferred/elapsed) - elapsed: */ - int eta = (int) ((unsigned long long)to_download*elapsed/transferred - elapsed); - /* (long long helps to have working ETA even if !LFS) */ - i = eta % 3600; - fprintf(stderr, "%02d:%02d:%02d ETA", eta / 3600, i / 60, i % 60); - } - } + bb_progress_update(&G.pmt, G.curfile, G.beg_range, G.transferred, + G.chunked ? 0 : G.content_len + G.beg_range); if (flag == 0) { /* last call to progress_meter */ alarm(0); - transferred = 0; fputc('\n', stderr); + G.transferred = 0; } else { if (flag == -1) { /* first call to progress_meter */ signal_SA_RESTART_empty_mask(SIGALRM, progress_meter); @@ -151,41 +66,7 @@ static void progress_meter(int flag) errno = save_errno; } -/* Original copyright notice which applies to the CONFIG_FEATURE_WGET_STATUSBAR stuff, - * much of which was blatantly stolen from openssh. */ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. - * - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ + #else /* FEATURE_WGET_STATUSBAR */ static ALWAYS_INLINE void progress_meter(int flag UNUSED_PARAM) { } @@ -370,8 +251,10 @@ static void parse_url(char *src_url, struct host_info *h) h->path = sp; } + // We used to set h->user to NULL here, but this interferes + // with handling of code 302 ("object was moved") + sp = strrchr(h->host, '@'); - h->user = NULL; if (sp != NULL) { h->user = h->host; *sp = '\0'; @@ -503,8 +386,8 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ * Querying file size */ if (ftpcmd("SIZE ", target->path, sfp, buf) == 213) { - content_len = BB_STRTOOFF(buf+4, NULL, 10); - if (errno || content_len < 0) { + G.content_len = BB_STRTOOFF(buf+4, NULL, 10); + if (G.content_len < 0 || errno) { bb_error_msg_and_die("SIZE value is garbage"); } G.got_clen = 1; @@ -533,10 +416,10 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ *dfpp = open_socket(lsa); - if (beg_range) { - sprintf(buf, "REST %"OFF_FMT"d", beg_range); + if (G.beg_range) { + sprintf(buf, "REST %"OFF_FMT"u", G.beg_range); if (ftpcmd(buf, NULL, sfp, buf) == 350) - content_len -= beg_range; + G.content_len -= G.beg_range; } if (ftpcmd("RETR ", target->path, sfp, buf) > 150) @@ -573,12 +456,18 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) /* Loops only if chunked */ while (1) { - while (content_len > 0 || !G.got_clen) { + while (1) { int n; - unsigned rdsz = sizeof(buf); - - if (content_len < sizeof(buf) && (G.chunked || G.got_clen)) - rdsz = (unsigned)content_len; + unsigned rdsz; + + rdsz = sizeof(buf); + if (G.got_clen) { + if (G.content_len < (off_t)sizeof(buf)) { + if ((int)G.content_len <= 0) + break; + rdsz = (unsigned)G.content_len; + } + } n = safe_fread(buf, rdsz, dfp); if (n <= 0) { if (ferror(dfp)) { @@ -589,10 +478,10 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) } xwrite(output_fd, buf, n); #if ENABLE_FEATURE_WGET_STATUSBAR - transferred += n; + G.transferred += n; #endif if (G.got_clen) - content_len -= n; + G.content_len -= n; } if (!G.chunked) @@ -601,10 +490,11 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */ get_clen: safe_fgets(buf, sizeof(buf), dfp); - content_len = STRTOOFF(buf, NULL, 16); + G.content_len = STRTOOFF(buf, NULL, 16); /* FIXME: error check? */ - if (content_len == 0) + if (G.content_len == 0) break; /* all done! */ + G.got_clen = 1; } if (!(option_mask32 & WGET_OPT_QUIET)) @@ -692,6 +582,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv) /* TODO: compat issue: should handle "wget URL1 URL2..." */ + target.user = NULL; parse_url(argv[optind], &target); /* Use the proxy if necessary */ @@ -733,19 +624,19 @@ int wget_main(int argc UNUSED_PARAM, char **argv) } } #if ENABLE_FEATURE_WGET_STATUSBAR - curfile = bb_get_last_path_component_nostrip(fname_out); + G.curfile = bb_get_last_path_component_nostrip(fname_out); #endif /* Impossible? if ((opt & WGET_OPT_CONTINUE) && !fname_out) - bb_error_msg_and_die("cannot specify continue (-c) without a filename (-O)"); + bb_error_msg_and_die("can't specify continue (-c) without a filename (-O)"); */ /* Determine where to start transfer */ if (opt & WGET_OPT_CONTINUE) { output_fd = open(fname_out, O_WRONLY); if (output_fd >= 0) { - beg_range = xlseek(output_fd, 0, SEEK_END); + G.beg_range = xlseek(output_fd, 0, SEEK_END); } /* File doesn't exist. We do not create file here yet. * We are not sure it exists on remove side */ @@ -796,8 +687,8 @@ int wget_main(int argc UNUSED_PARAM, char **argv) } #endif - if (beg_range) - fprintf(sfp, "Range: bytes=%"OFF_FMT"d-\r\n", beg_range); + 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); @@ -868,7 +759,7 @@ However, in real world it was observed that some web servers case 303: break; case 206: - if (beg_range) + if (G.beg_range) break; /* fall through */ default: @@ -880,10 +771,17 @@ However, in real world it was observed that some web servers */ while ((str = gethdr(buf, sizeof(buf), sfp /*, &n*/)) != NULL) { /* gethdr converted "FOO:" string to lowercase */ - smalluint key = index_in_strings(keywords, buf) + 1; + smalluint key; + /* strip trailing whitespace */ + char *s = strchrnul(str, '\0') - 1; + while (s >= str && (*s == ' ' || *s == '\t')) { + *s = '\0'; + s--; + } + key = index_in_strings(keywords, buf) + 1; if (key == KEY_content_length) { - content_len = BB_STRTOOFF(str, NULL, 10); - if (errno || content_len < 0) { + G.content_len = BB_STRTOOFF(str, NULL, 10); + if (G.content_len < 0 || errno) { bb_error_msg_and_die("content-length %s is garbage", sanitize_string(str)); } G.got_clen = 1; @@ -946,13 +844,14 @@ However, in real world it was observed that some web servers } retrieve_file_data(dfp, output_fd); + xclose(output_fd); if (dfp != sfp) { /* It's ftp. Close it properly */ fclose(dfp); if (ftpcmd(NULL, NULL, sfp, buf) != 226) bb_error_msg_and_die("ftp error: %s", sanitize_string(buf+4)); - ftpcmd("QUIT", NULL, sfp, buf); + /* ftpcmd("QUIT", NULL, sfp, buf); - why bother? */ } return EXIT_SUCCESS;