summaryrefslogtreecommitdiff
path: root/networking/wget.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-09-26 09:22:12 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-09-26 09:22:12 +0000
commita552eeb498e0270ae9c87ef707865a764df99fb6 (patch)
tree1a385f7c6f1eab36fb66278e48840fe7fdc0b882 /networking/wget.c
parent3312c989e6a145dc38e5bb874e713aa92b2b0698 (diff)
downloadbusybox-w32-a552eeb498e0270ae9c87ef707865a764df99fb6.tar.gz
busybox-w32-a552eeb498e0270ae9c87ef707865a764df99fb6.tar.bz2
busybox-w32-a552eeb498e0270ae9c87ef707865a764df99fb6.zip
wget: add (configurable) large file support. Run tested.
Diffstat (limited to 'networking/wget.c')
-rw-r--r--networking/wget.c116
1 files changed, 63 insertions, 53 deletions
diff --git a/networking/wget.c b/networking/wget.c
index 4b55b93f4..0eb8cd610 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -6,8 +6,28 @@
6 * 6 *
7 */ 7 */
8 8
9/* We want libc to give us xxx64 functions also */
10/* http://www.unix.org/version2/whatsnew/lfs20mar.html */
11#define _LARGEFILE64_SOURCE 1
12
9#include "busybox.h" 13#include "busybox.h"
10#include <getopt.h> 14#include <getopt.h> /* for struct option */
15
16#ifdef CONFIG_LFS
17# define FILEOFF_TYPE off64_t
18# define FILEOFF_FMT "%lld"
19# define LSEEK lseek64
20# define STRTOOFF strtoll
21# define SAFE_STRTOOFF safe_strtoll
22/* stat64 etc as needed... */
23#else
24# define FILEOFF_TYPE off_t
25# define FILEOFF_FMT "%ld"
26# define LSEEK lseek
27# define STRTOOFF strtol
28# define SAFE_STRTOOFF safe_strtol
29/* Do we need to undefine O_LARGEFILE? */
30#endif
11 31
12struct host_info { 32struct host_info {
13 char *host; 33 char *host;
@@ -23,13 +43,13 @@ static char *gethdr(char *buf, size_t bufsiz, FILE *fp, int *istrunc);
23static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf); 43static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf);
24 44
25/* Globals (can be accessed from signal handlers */ 45/* Globals (can be accessed from signal handlers */
26static off_t filesize; /* content-length of the file */ 46static FILEOFF_TYPE filesize; /* content-length of the file */
27static int chunked; /* chunked transfer encoding */ 47static int chunked; /* chunked transfer encoding */
28#ifdef CONFIG_FEATURE_WGET_STATUSBAR 48#ifdef CONFIG_FEATURE_WGET_STATUSBAR
29static void progressmeter(int flag); 49static void progressmeter(int flag);
30static char *curfile; /* Name of current file being transferred. */ 50static char *curfile; /* Name of current file being transferred. */
31static struct timeval start; /* Time a transfer started. */ 51static struct timeval start; /* Time a transfer started. */
32static off_t transferred; /* Number of bytes transferred so far. */ 52static FILEOFF_TYPE transferred; /* Number of bytes transferred so far. */
33/* For progressmeter() -- number of seconds before xfer considered "stalled" */ 53/* For progressmeter() -- number of seconds before xfer considered "stalled" */
34enum { 54enum {
35 STALLTIME = 5 55 STALLTIME = 5
@@ -78,20 +98,20 @@ static char *base64enc(unsigned char *p, char *buf, int len)
78} 98}
79#endif 99#endif
80 100
81#define WGET_OPT_CONTINUE 1 101#define WGET_OPT_CONTINUE 1
82#define WGET_OPT_QUIET 2 102#define WGET_OPT_QUIET 2
83#define WGET_OPT_PASSIVE 4 103#define WGET_OPT_PASSIVE 4
84#define WGET_OPT_OUTNAME 8 104#define WGET_OPT_OUTNAME 8
85#define WGET_OPT_HEADER 16 105#define WGET_OPT_HEADER 16
86#define WGET_OPT_PREFIX 32 106#define WGET_OPT_PREFIX 32
87#define WGET_OPT_PROXY 64 107#define WGET_OPT_PROXY 64
88#define WGET_OPT_USER_AGENT 128 108#define WGET_OPT_USER_AGENT 128
89 109
90#if ENABLE_FEATURE_WGET_LONG_OPTIONS 110#if ENABLE_FEATURE_WGET_LONG_OPTIONS
91static const struct option wget_long_options[] = { 111static const struct option wget_long_options[] = {
92 { "continue", 0, NULL, 'c' }, 112 { "continue", 0, NULL, 'c' },
93 { "quiet", 0, NULL, 'q' }, 113 { "quiet", 0, NULL, 'q' },
94 { "passive-ftp", 0, NULL, 139 }, 114 { "passive-ftp", 0, NULL, 139 }, /* FIXME: what is this - 139?? */
95 { "output-document", 1, NULL, 'O' }, 115 { "output-document", 1, NULL, 'O' },
96 { "header", 1, NULL, 131 }, 116 { "header", 1, NULL, 131 },
97 { "directory-prefix",1, NULL, 'P' }, 117 { "directory-prefix",1, NULL, 'P' },
@@ -116,17 +136,15 @@ int wget_main(int argc, char **argv)
116 struct sockaddr_in s_in; 136 struct sockaddr_in s_in;
117 llist_t *headers_llist = NULL; 137 llist_t *headers_llist = NULL;
118 138
119 FILE *sfp = NULL; /* socket to web/ftp server */ 139 FILE *sfp = NULL; /* socket to web/ftp server */
120 FILE *dfp = NULL; /* socket to ftp server (data) */ 140 FILE *dfp = NULL; /* socket to ftp server (data) */
121 char *fname_out = NULL; /* where to direct output (-O) */ 141 char *fname_out = NULL; /* where to direct output (-O) */
122 int do_continue = 0; /* continue a prev transfer (-c) */ 142 FILEOFF_TYPE beg_range = 0; /* range at which continue begins */
123 off64_t beg_range = 0; /* range at which continue begins */ 143 int got_clen = 0; /* got content-length: from server */
124 int got_clen = 0; /* got content-length: from server */
125 int output_fd = -1; 144 int output_fd = -1;
126 int quiet_flag = FALSE; /* Be verry, verry quiet... */ 145 int use_proxy = 1; /* Use proxies if env vars are set */
127 int use_proxy = 1; /* Use proxies if env vars are set */ 146 char *proxy_flag = "on"; /* Use proxies if env vars are set */
128 char *proxy_flag = "on"; /* Use proxies if env vars are set */ 147 char *user_agent = "Wget"; /* Content of the "User-Agent" header field */
129 char *user_agent = "Wget"; /* Content of the "User-Agent" header field */
130 148
131 /* 149 /*
132 * Crack command line. 150 * Crack command line.
@@ -138,12 +156,6 @@ int wget_main(int argc, char **argv)
138 opt = bb_getopt_ulflags(argc, argv, "cq\213O:\203:P:Y:U:", 156 opt = bb_getopt_ulflags(argc, argv, "cq\213O:\203:P:Y:U:",
139 &fname_out, &headers_llist, 157 &fname_out, &headers_llist,
140 &dir_prefix, &proxy_flag, &user_agent); 158 &dir_prefix, &proxy_flag, &user_agent);
141 if (opt & WGET_OPT_CONTINUE) {
142 ++do_continue;
143 }
144 if (opt & WGET_OPT_QUIET) {
145 quiet_flag = TRUE;
146 }
147 if (strcmp(proxy_flag, "off") == 0) { 159 if (strcmp(proxy_flag, "off") == 0) {
148 /* Use the proxy if necessary. */ 160 /* Use the proxy if necessary. */
149 use_proxy = 0; 161 use_proxy = 0;
@@ -205,7 +217,7 @@ int wget_main(int argc, char **argv)
205 curfile = bb_get_last_path_component(fname_out); 217 curfile = bb_get_last_path_component(fname_out);
206#endif 218#endif
207 } 219 }
208 if (do_continue && !fname_out) 220 if ((opt & WGET_OPT_CONTINUE) && !fname_out)
209 bb_error_msg_and_die("cannot specify continue (-c) without a filename (-O)"); 221 bb_error_msg_and_die("cannot specify continue (-c) without a filename (-O)");
210 222
211 /* 223 /*
@@ -213,13 +225,13 @@ int wget_main(int argc, char **argv)
213 */ 225 */
214 if (!strcmp(fname_out, "-")) { 226 if (!strcmp(fname_out, "-")) {
215 output_fd = 1; 227 output_fd = 1;
216 quiet_flag = TRUE; 228 opt |= WGET_OPT_QUIET;
217 do_continue = 0; 229 opt &= ~WGET_OPT_CONTINUE;
218 } else if (do_continue) { 230 } else if (opt & WGET_OPT_CONTINUE) {
219 output_fd = open(fname_out, O_WRONLY|O_LARGEFILE); 231 output_fd = open(fname_out, O_WRONLY|O_LARGEFILE);
220 if (output_fd >= 0) { 232 if (output_fd >= 0) {
221 beg_range = lseek64(output_fd, 0, SEEK_END); 233 beg_range = LSEEK(output_fd, 0, SEEK_END);
222 if (beg_range == (off64_t)-1) 234 if (beg_range == (FILEOFF_TYPE)-1)
223 bb_perror_msg_and_die("lseek64"); 235 bb_perror_msg_and_die("lseek64");
224 } 236 }
225 /* File doesn't exist. We do not create file here yet. 237 /* File doesn't exist. We do not create file here yet.
@@ -231,7 +243,7 @@ int wget_main(int argc, char **argv)
231 * and we want to connect to only one IP... */ 243 * and we want to connect to only one IP... */
232 bb_lookup_host(&s_in, server.host); 244 bb_lookup_host(&s_in, server.host);
233 s_in.sin_port = server.port; 245 s_in.sin_port = server.port;
234 if (quiet_flag == FALSE) { 246 if (!(opt & WGET_OPT_QUIET)) {
235 printf("Connecting to %s[%s]:%d\n", 247 printf("Connecting to %s[%s]:%d\n",
236 server.host, inet_ntoa(s_in.sin_addr), ntohs(server.port)); 248 server.host, inet_ntoa(s_in.sin_addr), ntohs(server.port));
237 } 249 }
@@ -283,7 +295,7 @@ int wget_main(int argc, char **argv)
283#endif 295#endif
284 296
285 if (beg_range) 297 if (beg_range)
286 fprintf(sfp, "Range: bytes=%lld-\r\n", (long long)beg_range); 298 fprintf(sfp, "Range: bytes="FILEOFF_FMT"-\r\n", beg_range);
287 if(extra_headers_left < sizeof(extra_headers)) 299 if(extra_headers_left < sizeof(extra_headers))
288 fputs(extra_headers,sfp); 300 fputs(extra_headers,sfp);
289 fprintf(sfp,"Connection: close\r\n\r\n"); 301 fprintf(sfp,"Connection: close\r\n\r\n");
@@ -325,11 +337,9 @@ read_response:
325 */ 337 */
326 while ((s = gethdr(buf, sizeof(buf), sfp, &n)) != NULL) { 338 while ((s = gethdr(buf, sizeof(buf), sfp, &n)) != NULL) {
327 if (strcasecmp(buf, "content-length") == 0) { 339 if (strcasecmp(buf, "content-length") == 0) {
328 unsigned long value; 340 if (SAFE_STRTOOFF(s, &filesize) || filesize < 0) {
329 if (safe_strtoul(s, &value)) {
330 bb_error_msg_and_die("content-length %s is garbage", s); 341 bb_error_msg_and_die("content-length %s is garbage", s);
331 } 342 }
332 filesize = value;
333 got_clen = 1; 343 got_clen = 1;
334 continue; 344 continue;
335 } 345 }
@@ -395,11 +405,9 @@ read_response:
395 * Querying file size 405 * Querying file size
396 */ 406 */
397 if (ftpcmd("SIZE ", target.path, sfp, buf) == 213) { 407 if (ftpcmd("SIZE ", target.path, sfp, buf) == 213) {
398 unsigned long value; 408 if (SAFE_STRTOOFF(buf+4, &filesize) || filesize < 0) {
399 if (safe_strtoul(buf+4, &value)) {
400 bb_error_msg_and_die("SIZE value is garbage"); 409 bb_error_msg_and_die("SIZE value is garbage");
401 } 410 }
402 filesize = value;
403 got_clen = 1; 411 got_clen = 1;
404 } 412 }
405 413
@@ -417,7 +425,7 @@ read_response:
417 dfp = open_socket(&s_in); 425 dfp = open_socket(&s_in);
418 426
419 if (beg_range) { 427 if (beg_range) {
420 sprintf(buf, "REST %lld", (long long)beg_range); 428 sprintf(buf, "REST "FILEOFF_FMT, beg_range);
421 if (ftpcmd(buf, NULL, sfp, buf) == 350) 429 if (ftpcmd(buf, NULL, sfp, buf) == 350)
422 filesize -= beg_range; 430 filesize -= beg_range;
423 } 431 }
@@ -432,17 +440,18 @@ read_response:
432 */ 440 */
433 if (chunked) { 441 if (chunked) {
434 fgets(buf, sizeof(buf), dfp); 442 fgets(buf, sizeof(buf), dfp);
435 filesize = strtol(buf, (char **) NULL, 16); 443 filesize = STRTOOFF(buf, (char **) NULL, 16);
444 /* FIXME: error check?? */
436 } 445 }
437 446
438 if (quiet_flag == FALSE) 447 if (!(opt & WGET_OPT_QUIET))
439 progressmeter(-1); 448 progressmeter(-1);
440 449
441 do { 450 do {
442 while (filesize > 0 || !got_clen) { 451 while (filesize > 0 || !got_clen) {
443 unsigned rdsz = sizeof(buf); 452 unsigned rdsz = sizeof(buf);
444 if (filesize < sizeof(buf) && (chunked || got_clen)) 453 if (filesize < sizeof(buf) && (chunked || got_clen))
445 rdsz = filesize; 454 rdsz = (unsigned)filesize;
446 n = safe_fread(buf, 1, rdsz, dfp); 455 n = safe_fread(buf, 1, rdsz, dfp);
447 if (n <= 0) 456 if (n <= 0)
448 break; 457 break;
@@ -462,7 +471,8 @@ read_response:
462 if (chunked) { 471 if (chunked) {
463 safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */ 472 safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */
464 safe_fgets(buf, sizeof(buf), dfp); 473 safe_fgets(buf, sizeof(buf), dfp);
465 filesize = strtol(buf, (char **) NULL, 16); 474 filesize = STRTOOFF(buf, (char **) NULL, 16);
475 /* FIXME: error check? */
466 if (filesize == 0) { 476 if (filesize == 0) {
467 chunked = 0; /* all done! */ 477 chunked = 0; /* all done! */
468 } 478 }
@@ -473,7 +483,7 @@ read_response:
473 } 483 }
474 } while (chunked); 484 } while (chunked);
475 485
476 if (quiet_flag == FALSE) 486 if (!(opt & WGET_OPT_QUIET))
477 progressmeter(1); 487 progressmeter(1);
478 488
479 if ((use_proxy == 0) && target.is_ftp) { 489 if ((use_proxy == 0) && target.is_ftp) {
@@ -662,10 +672,10 @@ static void
662progressmeter(int flag) 672progressmeter(int flag)
663{ 673{
664 static struct timeval lastupdate; 674 static struct timeval lastupdate;
665 static off_t lastsize, totalsize; 675 static FILEOFF_TYPE lastsize, totalsize;
666 676
667 struct timeval now, td, tvwait; 677 struct timeval now, td, tvwait;
668 off_t abbrevsize; 678 FILEOFF_TYPE abbrevsize;
669 int elapsed, ratio, barlength, i; 679 int elapsed, ratio, barlength, i;
670 char buf[256]; 680 char buf[256];
671 681