Here is my attempt at adding large file support to Wget in a manner I think is fairly portable. I'd be interested to know if this breaks compilation for anyone.
The patch is purely experimental; I haven't even written the ChangeLog entries yet. After applying it, don't forget to run autoheaders and autoconf and to re-run configure. The patch basically replaces all uses of `long' with `wgint', a type that is defined as (LFS version of) off_t, except under Windows, where it is simply `long long'. Systems with LFS and Windows will have 64-bit wgint, whereas others will have a 32-bit type. number_to_string has been modified to accept a wgint argument, and a new function print_number_as_string has been added to facilitate printing of wgints. Index: configure.in =================================================================== RCS file: /pack/anoncvs/wget/configure.in,v retrieving revision 1.73 diff -u -r1.73 configure.in --- configure.in 2003/11/26 22:46:13 1.73 +++ configure.in 2005/02/18 23:25:36 @@ -183,6 +183,14 @@ AC_CHECK_SIZEOF(long long) dnl +dnl Check for large file support. This check needs to come fairly +dnl early because it could (in principle) affect whether functions and +dnl headers are available, whether they work, etc. +dnl +AC_SYS_LARGEFILE +AC_CHECK_SIZEOF(off_t) + +dnl dnl Checks for non-universal or system-specific types. dnl AC_TYPE_SIZE_T Index: src/ftp-basic.c =================================================================== RCS file: /pack/anoncvs/wget/src/ftp-basic.c,v retrieving revision 1.36 diff -u -r1.36 ftp-basic.c --- src/ftp-basic.c 2003/11/21 01:48:05 1.36 +++ src/ftp-basic.c 2005/02/18 23:25:37 @@ -897,15 +897,13 @@ /* Sends REST command to the FTP server. */ uerr_t -ftp_rest (int csock, long offset) +ftp_rest (int csock, wgint offset) { char *request, *respline; int nwritten; uerr_t err; - static char numbuf[24]; /* Buffer for the number */ - number_to_string (numbuf, offset); - request = ftp_request ("REST", numbuf); + request = ftp_request ("REST", print_number_as_string (offset)); nwritten = fd_write (csock, request, strlen (request), -1); if (nwritten < 0) { @@ -1114,7 +1112,7 @@ /* Sends the SIZE command to the server, and returns the value in 'size'. * If an error occurs, size is set to zero. */ uerr_t -ftp_size (int csock, const char *file, long int *size) +ftp_size (int csock, const char *file, wgint *size) { char *request, *respline; int nwritten; @@ -1150,7 +1148,7 @@ } errno = 0; - *size = strtol (respline + 4, NULL, 0); + *size = str_to_wgint (respline + 4, NULL, 0); if (errno) { /* Index: src/ftp-ls.c =================================================================== RCS file: /pack/anoncvs/wget/src/ftp-ls.c,v retrieving revision 1.28 diff -u -r1.28 ftp-ls.c --- src/ftp-ls.c 2004/12/09 01:20:39 1.28 +++ src/ftp-ls.c 2005/02/18 23:25:39 @@ -213,7 +213,7 @@ if (i != 12) { char *t = tok - 2; - long mul = 1; + wgint mul = 1; for (cur.size = 0; t > line && ISDIGIT (*t); mul *= 10, t--) cur.size += mul * (*t - '0'); @@ -519,7 +519,7 @@ cur.type = FT_PLAINFILE; cur.size = atoi(tok); cur.perms = 0644; - DEBUGP(("File, size %ld bytes\n", cur.size)); + DEBUGP(("File, size %s bytes\n", print_number_as_string (cur.size))); } cur.linkto = NULL; Index: src/ftp.c =================================================================== RCS file: /pack/anoncvs/wget/src/ftp.c,v retrieving revision 1.88 diff -u -r1.88 ftp.c --- src/ftp.c 2004/02/25 23:45:24 1.88 +++ src/ftp.c 2005/02/18 23:25:41 @@ -83,12 +83,12 @@ /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in - the string S, and return the number converted to long, if found, 0 + the string S, and return the number converted to wgint, if found, 0 otherwise. */ -static long +static wgint ftp_expected_bytes (const char *s) { - long res; + wgint res; while (1) { @@ -234,7 +234,7 @@ connection to the server. It always closes the data connection, and closes the control connection in case of error. */ static uerr_t -getftp (struct url *u, long *len, long restval, ccon *con) +getftp (struct url *u, wgint *len, wgint restval, ccon *con) { int csock, dtsock, local_sock, res; uerr_t err; @@ -243,10 +243,10 @@ char *tms, *tmrate; int cmd = con->cmd; int pasv_mode_open = 0; - long expected_bytes = 0L; + wgint expected_bytes = 0L; int rest_failed = 0; int flags; - long rd_size; + wgint rd_size; assert (con != NULL); assert (con->target != NULL); @@ -770,7 +770,7 @@ if (restval && (cmd & DO_RETR)) { if (!opt.server_response) - logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval); + logprintf (LOG_VERBOSE, "==> REST %s ... ", print_number_as_string (restval)); err = ftp_rest (csock, restval); /* FTPRERR, WRITEFAILED, FTPRESTFAIL */ @@ -1123,7 +1123,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con) { int count, orig_lp; - long restval, len = 0; + wgint restval, len = 0; char *tms, *locf; char *tmrate = NULL; uerr_t err; @@ -1263,16 +1263,16 @@ con->csock = -1; } if (!opt.spider) - logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"), - tms, tmrate, locf, len); + logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"), + tms, tmrate, locf, print_number_as_string (len)); if (!opt.verbose && !opt.quiet) { /* Need to hide the password from the URL. The `if' is here so that we don't do the needless allocation every time. */ char *hurl = url_string (u, 1); - logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n", - tms, hurl, len, locf, count); + logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n", + tms, hurl, print_number_as_string (len), locf, count); xfree (hurl); } @@ -1389,7 +1389,7 @@ static int depth = 0; uerr_t err; struct fileinfo *orig; - long local_size; + wgint local_size; time_t tml; int dlthis; @@ -1482,7 +1482,8 @@ { /* Sizes do not match */ logprintf (LOG_VERBOSE, _("\ -The sizes do not match (local %ld) -- retrieving.\n\n"), local_size); +The sizes do not match (local %s) -- retrieving.\n\n"), + print_number_as_string (local_size)); } } } /* opt.timestamping && f->type == FT_PLAINFILE */ @@ -1843,14 +1844,14 @@ if (!opt.output_document) { struct stat st; - long sz; + wgint sz; if (stat (filename, &st) == 0) sz = st.st_size; else sz = -1; logprintf (LOG_NOTQUIET, - _("Wrote HTML-ized index to `%s' [%ld].\n"), - filename, sz); + _("Wrote HTML-ized index to `%s' [%s].\n"), + filename, print_number_as_string (sz)); } else logprintf (LOG_NOTQUIET, Index: src/ftp.h =================================================================== RCS file: /pack/anoncvs/wget/src/ftp.h,v retrieving revision 1.23 diff -u -r1.23 ftp.h --- src/ftp.h 2003/11/30 23:39:04 1.23 +++ src/ftp.h 2005/02/18 23:25:41 @@ -56,11 +56,11 @@ uerr_t ftp_type PARAMS ((int, int)); uerr_t ftp_cwd PARAMS ((int, const char *)); uerr_t ftp_retr PARAMS ((int, const char *)); -uerr_t ftp_rest PARAMS ((int, long)); +uerr_t ftp_rest PARAMS ((int, wgint)); uerr_t ftp_list PARAMS ((int, const char *)); uerr_t ftp_syst PARAMS ((int, enum stype *)); uerr_t ftp_pwd PARAMS ((int, char **)); -uerr_t ftp_size PARAMS ((int, const char *, long int *)); +uerr_t ftp_size PARAMS ((int, const char *, wgint *)); #ifdef USE_OPIE const char *skey_response PARAMS ((int, const char *, const char *)); @@ -89,7 +89,7 @@ { enum ftype type; /* file type */ char *name; /* file name */ - long size; /* file size */ + wgint size; /* file size */ long tstamp; /* time-stamp */ int perms; /* file permissions */ char *linkto; /* link to which file points */ Index: src/html-url.c =================================================================== RCS file: /pack/anoncvs/wget/src/html-url.c,v retrieving revision 1.41 diff -u -r1.41 html-url.c --- src/html-url.c 2003/11/26 16:37:04 1.41 +++ src/html-url.c 2005/02/18 23:25:42 @@ -599,7 +599,7 @@ logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno)); return NULL; } - DEBUGP (("Loaded %s (size %ld).\n", file, fm->length)); + DEBUGP (("Loaded %s (size %s).\n", file, print_number_as_string (fm->length))); ctx.text = fm->content; ctx.head = ctx.tail = NULL; @@ -651,7 +651,7 @@ logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno)); return NULL; } - DEBUGP (("Loaded %s (size %ld).\n", file, fm->length)); + DEBUGP (("Loaded %s (size %s).\n", file, print_number_as_string (fm->length))); head = tail = NULL; text = fm->content; Index: src/http.c =================================================================== RCS file: /pack/anoncvs/wget/src/http.c,v retrieving revision 1.144 diff -u -r1.144 http.c --- src/http.c 2004/11/19 00:44:38 1.144 +++ src/http.c 2005/02/18 23:25:47 @@ -219,7 +219,8 @@ request_set_header (req, "Referer", opt.referer, rel_none); // Value freshly allocated, free it when done. - request_set_header (req, "Range", aprintf ("bytes=%ld-", hs->restval), + request_set_header (req, "Range", + aprintf ("bytes=%s-", print_number_as_string (hs->restval)), rel_value); */ @@ -359,10 +360,10 @@ longer, read only that much; if the file is shorter, report an error. */ static int -post_file (int sock, const char *file_name, long promised_size) +post_file (int sock, const char *file_name, wgint promised_size) { static char chunk[8192]; - long written = 0; + wgint written = 0; int write_error; FILE *fp; @@ -705,10 +706,10 @@ /* Parse the `Content-Range' header and extract the information it contains. Returns 1 if successful, -1 otherwise. */ static int -parse_content_range (const char *hdr, long *first_byte_ptr, - long *last_byte_ptr, long *entity_length_ptr) +parse_content_range (const char *hdr, wgint *first_byte_ptr, + wgint *last_byte_ptr, wgint *entity_length_ptr) { - long num; + wgint num; /* Ancient versions of Netscape proxy server, presumably predating rfc2068, sent out `Content-Range' without the "bytes" @@ -751,7 +752,7 @@ which need to be read anyway. */ static void -skip_short_body (int fd, long contlen) +skip_short_body (int fd, wgint contlen) { /* Skipping the body doesn't make sense if the content length is unknown because, in that case, persistent connections cannot be @@ -759,7 +760,7 @@ still be used with the magic of the "chunked" transfer!) */ if (contlen == -1) return; - DEBUGP (("Skipping %ld bytes of body data... ", contlen)); + DEBUGP (("Skipping %s bytes of body data... ", print_number_as_string (contlen))); while (contlen > 0) { @@ -974,15 +975,15 @@ struct http_stat { - long len; /* received length */ - long contlen; /* expected length */ - long restval; /* the restart value */ + wgint len; /* received length */ + wgint contlen; /* expected length */ + wgint restval; /* the restart value */ int res; /* the result of last read */ char *newloc; /* new location (redirection) */ char *remote_time; /* remote time-stamp string */ char *error; /* textual HTTP error */ int statcode; /* status code */ - long rd_size; /* amount of data read from socket */ + wgint rd_size; /* amount of data read from socket */ double dltime; /* time it took to download the data */ const char *referer; /* value of the referer header. */ char **local_file; /* local file. */ @@ -1034,7 +1035,7 @@ char *proxyauth; int statcode; int write_error; - long contlen, contrange; + wgint contlen, contrange; struct url *conn; FILE *fp; @@ -1060,7 +1061,7 @@ int inhibit_keep_alive = !opt.http_keep_alive || opt.ignore_length; /* Headers sent when using POST. */ - long post_data_size = 0; + wgint post_data_size = 0; int host_lookup_failed = 0; @@ -1134,7 +1135,9 @@ request_set_header (req, "Pragma", "no-cache", rel_none); if (hs->restval) request_set_header (req, "Range", - aprintf ("bytes=%ld-", hs->restval), rel_value); + aprintf ("bytes=%s-", + print_number_as_string (hs->restval)), + rel_value); if (opt.useragent) request_set_header (req, "User-Agent", opt.useragent, rel_none); else @@ -1259,7 +1262,8 @@ } } request_set_header (req, "Content-Length", - aprintf ("%ld", post_data_size), rel_value); + xstrdup (print_number_as_string (post_data_size)), + rel_value); } /* Add the user headers. */ @@ -1463,7 +1467,7 @@ if (!opt.ignore_length && response_header_copy (resp, "Content-Length", hdrval, sizeof (hdrval))) - contlen = strtol (hdrval, NULL, 10); + contlen = str_to_wgint (hdrval, NULL, 10); /* Check for keep-alive related responses. */ if (!inhibit_keep_alive && contlen != -1) @@ -1562,7 +1566,7 @@ } if (response_header_copy (resp, "Content-Range", hdrval, sizeof (hdrval))) { - long first_byte_pos, last_byte_pos, entity_length; + wgint first_byte_pos, last_byte_pos, entity_length; if (parse_content_range (hdrval, &first_byte_pos, &last_byte_pos, &entity_length)) contrange = first_byte_pos; @@ -1768,7 +1772,7 @@ char *tms, *locf, *tmrate; uerr_t err; time_t tml = -1, tmr = -1; /* local and remote time-stamps */ - long local_size = 0; /* the size of the local file */ + wgint local_size = 0; /* the size of the local file */ size_t filename_len; struct http_stat hstat; /* HTTP status */ struct stat st; @@ -1864,7 +1868,7 @@ point I profiled Wget, and found that a measurable and non-negligible amount of time was lost calling sprintf() in url.c. Replacing sprintf with inline calls to - strcpy() and long_to_string() made a difference. + strcpy() and number_to_string() made a difference. --hniksic */ memcpy (filename_plus_orig_suffix, *hstat.local_file, filename_len); memcpy (filename_plus_orig_suffix + filename_len, @@ -2097,7 +2101,8 @@ } else if (tml >= tmr) logprintf (LOG_VERBOSE, _("\ -The sizes do not match (local %ld) -- retrieving.\n"), local_size); +The sizes do not match (local %s) -- retrieving.\n"), + print_number_as_string (local_size)); else logputs (LOG_VERBOSE, _("Remote file is newer, retrieving.\n")); @@ -2141,11 +2146,16 @@ if (*dt & RETROKF) { logprintf (LOG_VERBOSE, - _("%s (%s) - `%s' saved [%ld/%ld]\n\n"), - tms, tmrate, locf, hstat.len, hstat.contlen); + _("%s (%s) - `%s' saved [%s/%s]\n\n"), + tms, tmrate, locf, + print_number_as_string (hstat.len), + print_second_number_as_string (hstat.contlen)); logprintf (LOG_NONVERBOSE, - "%s URL:%s [%ld/%ld] -> \"%s\" [%d]\n", - tms, u->url, hstat.len, hstat.contlen, locf, count); + "%s URL:%s [%s/%s] -> \"%s\" [%d]\n", + tms, u->url, + print_number_as_string (hstat.len), + print_second_number_as_string (hstat.contlen), + locf, count); } ++opt.numurls; total_downloaded_bytes += hstat.len; @@ -2168,11 +2178,13 @@ if (*dt & RETROKF) { logprintf (LOG_VERBOSE, - _("%s (%s) - `%s' saved [%ld]\n\n"), - tms, tmrate, locf, hstat.len); + _("%s (%s) - `%s' saved [%s]\n\n"), + tms, tmrate, locf, + print_number_as_string (hstat.len)); logprintf (LOG_NONVERBOSE, - "%s URL:%s [%ld] -> \"%s\" [%d]\n", - tms, u->url, hstat.len, locf, count); + "%s URL:%s [%s] -> \"%s\" [%d]\n", + tms, u->url, print_number_as_string (hstat.len), + locf, count); } ++opt.numurls; total_downloaded_bytes += hstat.len; @@ -2191,8 +2203,8 @@ connection too soon */ { logprintf (LOG_VERBOSE, - _("%s (%s) - Connection closed at byte %ld. "), - tms, tmrate, hstat.len); + _("%s (%s) - Connection closed at byte %s. "), + tms, tmrate, print_number_as_string (hstat.len)); printwhat (count, opt.ntry); free_hstat (&hstat); continue; @@ -2200,11 +2212,16 @@ else if (!opt.kill_longer) /* meaning we got more than expected */ { logprintf (LOG_VERBOSE, - _("%s (%s) - `%s' saved [%ld/%ld])\n\n"), - tms, tmrate, locf, hstat.len, hstat.contlen); + _("%s (%s) - `%s' saved [%s/%s])\n\n"), + tms, tmrate, locf, + print_number_as_string (hstat.len), + print_second_number_as_string (hstat.contlen)); logprintf (LOG_NONVERBOSE, - "%s URL:%s [%ld/%ld] -> \"%s\" [%d]\n", - tms, u->url, hstat.len, hstat.contlen, locf, count); + "%s URL:%s [%s/%s] -> \"%s\" [%d]\n", + tms, u->url, + print_number_as_string (hstat.len), + print_second_number_as_string (hstat.contlen), + locf, count); ++opt.numurls; total_downloaded_bytes += hstat.len; @@ -2221,8 +2238,10 @@ else /* the same, but not accepted */ { logprintf (LOG_VERBOSE, - _("%s (%s) - Connection closed at byte %ld/%ld. "), - tms, tmrate, hstat.len, hstat.contlen); + _("%s (%s) - Connection closed at byte %s/%s. "), + tms, tmrate, + print_number_as_string (hstat.len), + print_second_number_as_string (hstat.contlen)); printwhat (count, opt.ntry); free_hstat (&hstat); continue; @@ -2233,8 +2252,9 @@ if (hstat.contlen == -1) { logprintf (LOG_VERBOSE, - _("%s (%s) - Read error at byte %ld (%s)."), - tms, tmrate, hstat.len, strerror (errno)); + _("%s (%s) - Read error at byte %s (%s)."), + tms, tmrate, print_number_as_string (hstat.len), + strerror (errno)); printwhat (count, opt.ntry); free_hstat (&hstat); continue; @@ -2242,8 +2262,10 @@ else /* hstat.res == -1 and contlen is given */ { logprintf (LOG_VERBOSE, - _("%s (%s) - Read error at byte %ld/%ld (%s). "), - tms, tmrate, hstat.len, hstat.contlen, + _("%s (%s) - Read error at byte %s/%s (%s). "), + tms, tmrate, + print_number_as_string (hstat.len), + print_second_number_as_string (hstat.contlen), strerror (errno)); printwhat (count, opt.ntry); free_hstat (&hstat); Index: src/init.c =================================================================== RCS file: /pack/anoncvs/wget/src/init.c,v retrieving revision 1.92 diff -u -r1.92 init.c --- src/init.c 2004/02/17 15:37:31 1.92 +++ src/init.c 2005/02/18 23:25:49 @@ -852,8 +852,8 @@ static int simple_atof PARAMS ((const char *, const char *, double *)); -/* Enginge for cmd_bytes and cmd_bytes_large: converts a string such - as "100k" or "2.5G" to a floating point number. */ +/* Engine for cmd_bytes and cmd_bytes_large: converts a string such as + "100k" or "2.5G" to a floating point number. */ static int parse_bytes_helper (const char *val, double *result) @@ -910,7 +910,7 @@ } /* Parse VAL as a number and set its value to CLOSURE (which should - point to a long int). + point to a wgint). By default, the value is assumed to be in bytes. If "K", "M", or "G" are appended, the value is multiplied with 1<<10, 1<<20, or @@ -933,7 +933,7 @@ exec_name, com, val); return 0; } - *(long *)closure = (long)byte_value; + *(wgint *)closure = (wgint)byte_value; return 1; } Index: src/progress.c =================================================================== RCS file: /pack/anoncvs/wget/src/progress.c,v retrieving revision 1.43 diff -u -r1.43 progress.c --- src/progress.c 2004/01/28 01:02:26 1.43 +++ src/progress.c 2005/02/18 23:25:50 @@ -52,21 +52,21 @@ struct progress_implementation { const char *name; int interactive; - void *(*create) PARAMS ((long, long)); - void (*update) PARAMS ((void *, long, double)); + void *(*create) PARAMS ((wgint, wgint)); + void (*update) PARAMS ((void *, wgint, double)); void (*finish) PARAMS ((void *, double)); void (*set_params) PARAMS ((const char *)); }; /* Necessary forward declarations. */ -static void *dot_create PARAMS ((long, long)); -static void dot_update PARAMS ((void *, long, double)); +static void *dot_create PARAMS ((wgint, wgint)); +static void dot_update PARAMS ((void *, wgint, double)); static void dot_finish PARAMS ((void *, double)); static void dot_set_params PARAMS ((const char *)); -static void *bar_create PARAMS ((long, long)); -static void bar_update PARAMS ((void *, long, double)); +static void *bar_create PARAMS ((wgint, wgint)); +static void bar_update PARAMS ((void *, wgint, double)); static void bar_finish PARAMS ((void *, double)); static void bar_set_params PARAMS ((const char *)); @@ -156,7 +156,7 @@ advance. */ void * -progress_create (long initial, long total) +progress_create (wgint initial, wgint total) { /* Check if the log status has changed under our feet. */ if (output_redirected) @@ -184,7 +184,7 @@ time in milliseconds since the beginning of the download. */ void -progress_update (void *progress, long howmuch, double dltime) +progress_update (void *progress, wgint howmuch, double dltime) { current_impl->update (progress, howmuch, dltime); } @@ -201,9 +201,9 @@ /* Dot-printing. */ struct dot_progress { - long initial_length; /* how many bytes have been downloaded + wgint initial_length; /* how many bytes have been downloaded previously. */ - long total_length; /* expected total byte count when the + wgint total_length; /* expected total byte count when the download finishes */ int accumulated; @@ -216,7 +216,7 @@ /* Dot-progress backend for progress_create. */ static void * -dot_create (long initial, long total) +dot_create (wgint initial, wgint total) { struct dot_progress *dp = xnew0 (struct dot_progress); dp->initial_length = initial; @@ -225,10 +225,10 @@ if (dp->initial_length) { int dot_bytes = opt.dot_bytes; - long row_bytes = opt.dot_bytes * opt.dots_in_line; + wgint row_bytes = opt.dot_bytes * opt.dots_in_line; int remainder = (int) (dp->initial_length % row_bytes); - long skipped = dp->initial_length - remainder; + wgint skipped = dp->initial_length - remainder; if (skipped) { @@ -244,7 +244,7 @@ 2 + skipped_k_len, "", skipped_k); } - logprintf (LOG_VERBOSE, "\n%5ldK", skipped / 1024); + logprintf (LOG_VERBOSE, "\n%5ldK", (long) (skipped / 1024)); for (; remainder >= dot_bytes; remainder -= dot_bytes) { if (dp->dots % opt.dot_spacing == 0) @@ -262,14 +262,14 @@ } static void -print_percentage (long bytes, long expected) +print_percentage (wgint bytes, wgint expected) { int percentage = (int)(100.0 * bytes / expected); logprintf (LOG_VERBOSE, "%3d%%", percentage); } static void -print_download_speed (struct dot_progress *dp, long bytes, double dltime) +print_download_speed (struct dot_progress *dp, wgint bytes, double dltime) { logprintf (LOG_VERBOSE, " %s", retr_rate (bytes, dltime - dp->last_timer_value, 1)); @@ -279,11 +279,11 @@ /* Dot-progress backend for progress_update. */ static void -dot_update (void *progress, long howmuch, double dltime) +dot_update (void *progress, wgint howmuch, double dltime) { struct dot_progress *dp = progress; int dot_bytes = opt.dot_bytes; - long row_bytes = opt.dot_bytes * opt.dots_in_line; + wgint row_bytes = opt.dot_bytes * opt.dots_in_line; log_set_flush (0); @@ -291,7 +291,7 @@ for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes) { if (dp->dots == 0) - logprintf (LOG_VERBOSE, "\n%5ldK", dp->rows * row_bytes / 1024); + logprintf (LOG_VERBOSE, "\n%5ldK", (long) (dp->rows * row_bytes / 1024)); if (dp->dots % opt.dot_spacing == 0) logputs (LOG_VERBOSE, " "); @@ -300,7 +300,7 @@ ++dp->dots; if (dp->dots >= opt.dots_in_line) { - long row_qty = row_bytes; + wgint row_qty = row_bytes; if (dp->rows == dp->initial_length / row_bytes) row_qty -= dp->initial_length % row_bytes; @@ -323,13 +323,13 @@ { struct dot_progress *dp = progress; int dot_bytes = opt.dot_bytes; - long row_bytes = opt.dot_bytes * opt.dots_in_line; + wgint row_bytes = opt.dot_bytes * opt.dots_in_line; int i; log_set_flush (0); if (dp->dots == 0) - logprintf (LOG_VERBOSE, "\n%5ldK", dp->rows * row_bytes / 1024); + logprintf (LOG_VERBOSE, "\n%5ldK", (long) (dp->rows * row_bytes / 1024)); for (i = dp->dots; i < opt.dots_in_line; i++) { if (i % opt.dot_spacing == 0) @@ -345,7 +345,7 @@ } { - long row_qty = dp->dots * dot_bytes + dp->accumulated; + wgint row_qty = dp->dots * dot_bytes + dp->accumulated; if (dp->rows == dp->initial_length / row_bytes) row_qty -= dp->initial_length % row_bytes; print_download_speed (dp, row_qty, dltime); @@ -443,11 +443,11 @@ #define STALL_START_TIME 5000 struct bar_progress { - long initial_length; /* how many bytes have been downloaded + wgint initial_length; /* how many bytes have been downloaded previously. */ - long total_length; /* expected total byte count when the + wgint total_length; /* expected total byte count when the download finishes */ - long count; /* bytes downloaded so far */ + wgint count; /* bytes downloaded so far */ double last_screen_update; /* time of the last screen update, measured since the beginning of @@ -470,18 +470,18 @@ details. */ struct bar_progress_hist { int pos; - long times[DLSPEED_HISTORY_SIZE]; - long bytes[DLSPEED_HISTORY_SIZE]; + wgint times[DLSPEED_HISTORY_SIZE]; + wgint bytes[DLSPEED_HISTORY_SIZE]; /* The sum of times and bytes respectively, maintained for efficiency. */ - long total_time; - long total_bytes; + wgint total_time; + wgint total_bytes; } hist; double recent_start; /* timestamp of beginning of current position. */ - long recent_bytes; /* bytes downloaded so far. */ + wgint recent_bytes; /* bytes downloaded so far. */ int stalled; /* set when no data arrives for longer than STALL_START_TIME, then reset @@ -492,14 +492,14 @@ double last_eta_time; /* time of the last update to download speed and ETA, measured since the beginning of download. */ - long last_eta_value; + wgint last_eta_value; }; static void create_image PARAMS ((struct bar_progress *, double)); static void display_image PARAMS ((char *)); static void * -bar_create (long initial, long total) +bar_create (wgint initial, wgint total) { struct bar_progress *bp = xnew0 (struct bar_progress); @@ -536,10 +536,10 @@ return bp; } -static void update_speed_ring PARAMS ((struct bar_progress *, long, double)); +static void update_speed_ring PARAMS ((struct bar_progress *, wgint, double)); static void -bar_update (void *progress, long howmuch, double dltime) +bar_update (void *progress, wgint howmuch, double dltime) { struct bar_progress *bp = progress; int force_screen_update = 0; @@ -622,7 +622,7 @@ 3-second average would be too erratic. */ static void -update_speed_ring (struct bar_progress *bp, long howmuch, double dltime) +update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime) { struct bar_progress_hist *hist = &bp->hist; double recent_age = dltime - bp->recent_start; @@ -719,7 +719,7 @@ create_image (struct bar_progress *bp, double dl_total_time) { char *p = bp->buffer; - long size = bp->initial_length + bp->count; + wgint size = bp->initial_length + bp->count; char *size_legible = legible (size); int size_legible_len = strlen (size_legible); @@ -838,7 +838,7 @@ int units = 0; /* Calculate the download speed using the history ring and recent data that hasn't made it to the ring yet. */ - long dlquant = hist->total_bytes + bp->recent_bytes; + wgint dlquant = hist->total_bytes + bp->recent_bytes; double dltime = hist->total_time + (dl_total_time - bp->recent_start); double dlspeed = calc_rate (dlquant, dltime, &units); sprintf (p, " %7.2f%s", dlspeed, short_units[units]); @@ -852,7 +852,7 @@ reliable. */ if (bp->total_length > 0 && bp->count > 0 && dl_total_time > 3000) { - long eta; + wgint eta; int eta_hrs, eta_min, eta_sec; /* Don't change the value of ETA more than approximately once @@ -871,8 +871,8 @@ I found that doing that results in a very jerky and ultimately unreliable ETA. */ double time_sofar = (double)dl_total_time / 1000; - long bytes_remaining = bp->total_length - size; - eta = (long) (time_sofar * bytes_remaining / bp->count); + wgint bytes_remaining = bp->total_length - size; + eta = (wgint) (time_sofar * bytes_remaining / bp->count); bp->last_eta_value = eta; bp->last_eta_time = dl_total_time; } Index: src/progress.h =================================================================== RCS file: /pack/anoncvs/wget/src/progress.h,v retrieving revision 1.7 diff -u -r1.7 progress.h --- src/progress.h 2003/11/08 16:56:52 1.7 +++ src/progress.h 2005/02/18 23:25:50 @@ -34,9 +34,9 @@ void set_progress_implementation PARAMS ((const char *)); void progress_schedule_redirect PARAMS ((void)); -void *progress_create PARAMS ((long, long)); +void *progress_create PARAMS ((wgint, wgint)); int progress_interactive_p PARAMS ((void *)); -void progress_update PARAMS ((void *, long, double)); +void progress_update PARAMS ((void *, wgint, double)); void progress_finish PARAMS ((void *, double)); RETSIGTYPE progress_handle_sigwinch PARAMS ((int)); Index: src/retr.c =================================================================== RCS file: /pack/anoncvs/wget/src/retr.c,v retrieving revision 1.86 diff -u -r1.86 retr.c --- src/retr.c 2004/11/18 21:05:30 1.86 +++ src/retr.c 2005/02/18 23:25:52 @@ -75,7 +75,7 @@ int output_stream_regular; static struct { - long chunk_bytes; + wgint chunk_bytes; double chunk_start; double sleep_adjust; } limit_data; @@ -92,7 +92,7 @@ is the timer that started at the beginning of download. */ static void -limit_bandwidth (long bytes, struct wget_timer *timer) +limit_bandwidth (wgint bytes, struct wget_timer *timer) { double delta_t = wtimer_read (timer) - limit_data.chunk_start; double expected; @@ -110,12 +110,14 @@ double t0, t1; if (slp < 200) { - DEBUGP (("deferring a %.2f ms sleep (%ld/%.2f).\n", - slp, limit_data.chunk_bytes, delta_t)); + DEBUGP (("deferring a %.2f ms sleep (%s/%.2f).\n", + slp, print_number_as_string (limit_data.chunk_bytes), + delta_t)); return; } - DEBUGP (("\nsleeping %.2f ms for %ld bytes, adjust %.2f ms\n", - slp, limit_data.chunk_bytes, limit_data.sleep_adjust)); + DEBUGP (("\nsleeping %.2f ms for %s bytes, adjust %.2f ms\n", + slp, print_number_as_string (limit_data.chunk_bytes), + limit_data.sleep_adjust)); t0 = wtimer_read (timer); xsleep (slp / 1000); @@ -142,8 +144,8 @@ of data written. */ static int -write_data (FILE *out, const char *buf, int bufsize, long *skip, - long *written) +write_data (FILE *out, const char *buf, int bufsize, wgint *skip, + wgint *written) { if (!out) return 1; @@ -192,8 +194,8 @@ writing data, -2 is returned. */ int -fd_read_body (int fd, FILE *out, long toread, long startpos, - long *qtyread, long *qtywritten, double *elapsed, int flags) +fd_read_body (int fd, FILE *out, wgint toread, wgint startpos, + wgint *qtyread, wgint *qtywritten, double *elapsed, int flags) { int ret = 0; @@ -213,11 +215,11 @@ int progress_interactive = 0; int exact = flags & rb_read_exactly; - long skip = 0; + wgint skip = 0; /* How much data we've read/written. */ - long sum_read = 0; - long sum_written = 0; + wgint sum_read = 0; + wgint sum_written = 0; if (flags & rb_skip_startpos) skip = startpos; @@ -489,7 +491,7 @@ appropriate for the speed. If PAD is non-zero, strings will be padded to the width of 7 characters (xxxx.xx). */ char * -retr_rate (long bytes, double msecs, int pad) +retr_rate (wgint bytes, double msecs, int pad) { static char res[20]; static const char *rate_names[] = {"B/s", "KB/s", "MB/s", "GB/s" }; @@ -509,7 +511,7 @@ UNITS is zero for B/s, one for KB/s, two for MB/s, and three for GB/s. */ double -calc_rate (long bytes, double msecs, int *units) +calc_rate (wgint bytes, double msecs, int *units) { double dlrate; Index: src/retr.h =================================================================== RCS file: /pack/anoncvs/wget/src/retr.h,v retrieving revision 1.19 diff -u -r1.19 retr.h --- src/retr.h 2003/12/06 02:32:57 1.19 +++ src/retr.h 2005/02/18 23:25:52 @@ -36,7 +36,7 @@ rb_skip_startpos = 2 }; -int fd_read_body PARAMS ((int, FILE *, long, long, long *, long *, double *, +int fd_read_body PARAMS ((int, FILE *, wgint, wgint, wgint *, wgint *, double *, int)); typedef const char *(*hunk_terminator_t) PARAMS ((const char *, int, int)); @@ -48,8 +48,8 @@ const char *, int *)); uerr_t retrieve_from_file PARAMS ((const char *, int, int *)); -char *retr_rate PARAMS ((long, double, int)); -double calc_rate PARAMS ((long, double, int *)); +char *retr_rate PARAMS ((wgint, double, int)); +double calc_rate PARAMS ((wgint, double, int *)); void printwhat PARAMS ((int, int)); void sleep_between_retrievals PARAMS ((int)); Index: src/utils.c =================================================================== RCS file: /pack/anoncvs/wget/src/utils.c,v retrieving revision 1.77 diff -u -r1.77 utils.c --- src/utils.c 2004/01/29 12:38:52 1.77 +++ src/utils.c 2005/02/18 23:25:55 @@ -383,10 +383,10 @@ /* Return the size of file named by FILENAME, or -1 if it cannot be opened or seeked into. */ -long +wgint file_size (const char *filename) { - long size; + wgint size; /* We use fseek rather than stat to determine the file size because that way we can also verify whether the file is readable. Inspired by the POST patch by Arnaud Wylie. */ @@ -799,7 +799,7 @@ { int fd; struct file_memory *fm; - long size; + wgint size; int inhibit_close = 0; /* Some magic in the finest tradition of Perl and its kin: if FILE @@ -851,7 +851,7 @@ fm->content = xmalloc (size); while (1) { - long nread; + wgint nread; if (fm->length > size / 2) { /* #### I'm not sure whether the whole exponential-growth @@ -1148,10 +1148,10 @@ return outbuf; } -/* Legible -- return a static pointer to the legibly printed long. */ +/* Legible -- return a static pointer to the legibly printed wgint. */ char * -legible (long l) +legible (wgint l) { char inbuf[24]; /* Print the number into the buffer. */ @@ -1185,9 +1185,9 @@ return legible_1 (inbuf); } -/* Count the digits in a (long) integer. */ +/* Count the digits in an integer number. */ int -numdigit (long number) +numdigit (wgint number) { int cnt = 1; if (number < 0) @@ -1200,13 +1200,28 @@ return cnt; } -/* Attempt to calculate INT_MAX on machines that don't bother to - define it. */ -#ifndef INT_MAX -# ifndef CHAR_BIT -# define CHAR_BIT 8 +/* Attempt to determine WGINT_MAX. */ + +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif + +#if SIZEOF_WGINT == SIZEOF_LONG +# ifdef LONG_MAX +# define WGINT_MAX LONG_MAX +# else +# define WGINT_MAX ((wgint) ~((unsigned long)1 << (CHAR_BIT * sizeof (long) - 1))) # endif -# define INT_MAX ((int) ~((unsigned)1 << CHAR_BIT * sizeof (int) - 1)) +#else +# if SIZEOF_WGINT == SIZEOF_LONG_LONG +# ifdef LONG_LONG_MAX +# define WGINT_MAX LONG_LONG_MAX +# else +# define WGINT_MAX ((wgint) ~((unsigned long long)1 << (CHAR_BIT * sizeof (long long) - 1))) +# endif +# else +# define WGINT_MAX ((wgint) ~((unsigned)1 << (CHAR_BIT * sizeof (int) - 1))) +# endif #endif #define ONE_DIGIT(figure) *p++ = n / (figure) + '0' @@ -1223,7 +1238,7 @@ #define DIGITS_9(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_8 ((figure) / 10) #define DIGITS_10(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_9 ((figure) / 10) -/* DIGITS_<11-20> are only used on machines with 64-bit longs. */ +/* DIGITS_<11-20> are only used on machines with 64-bit numbers. */ #define DIGITS_11(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_10 ((figure) / 10) #define DIGITS_12(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_11 ((figure) / 10) @@ -1235,13 +1250,22 @@ #define DIGITS_18(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_17 ((figure) / 10) #define DIGITS_19(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_18 ((figure) / 10) -/* Print NUMBER to BUFFER in base 10. This should be completely - equivalent to `sprintf(buffer, "%ld", number)', only much faster. +#if SIZEOF_LONG_LONG != 0 +# define N2S_COERCE_FMT "%lld" +# define N2S_COERCE_TYPE long long +#else +# define N2S_COERCE_FMT "%ld" +# define N2S_COERCE_TYPE long +#endif +/* Print NUMBER to BUFFER in base 10. This is equivalent to + `sprintf(buffer, "%lld", (long long) number)', only much faster and + portable to machines without long long. + The speedup may make a difference in programs that frequently convert numbers to strings. Some implementations of sprintf, particularly the one in GNU libc, have been known to be extremely - slow compared to this function. + slow when converting integers to strings. Return the pointer to the location where the terminating zero was printed. (Equivalent to calling buffer+strlen(buffer) after the @@ -1254,25 +1278,25 @@ terminating '\0'. */ char * -number_to_string (char *buffer, long number) +number_to_string (char *buffer, wgint number) { char *p = buffer; - long n = number; + wgint n = number; -#if (SIZEOF_LONG != 4) && (SIZEOF_LONG != 8) +#if (SIZEOF_WGINT != 4) && (SIZEOF_WGINT != 8) /* We are running in a strange or misconfigured environment. Let sprintf cope with it. */ - sprintf (buffer, "%ld", n); + sprintf (buffer, N2S_COERCE_FMT, (N2S_COERCE_TYPE) n); p += strlen (buffer); -#else /* (SIZEOF_LONG == 4) || (SIZEOF_LONG == 8) */ +#else /* (SIZEOF_WGINT == 4) || (SIZEOF_WGINT == 8) */ if (n < 0) { - if (n < -INT_MAX) + if (n < -WGINT_MAX) { /* We cannot print a '-' and assign -n to n because -n would overflow. Let sprintf deal with this border case. */ - sprintf (buffer, "%ld", n); + sprintf (buffer, N2S_COERCE_FMT, (N2S_COERCE_TYPE) n); p += strlen (buffer); return p; } @@ -1281,33 +1305,46 @@ n = -n; } - if (n < 10) { DIGITS_1 (1); } - else if (n < 100) { DIGITS_2 (10); } - else if (n < 1000) { DIGITS_3 (100); } - else if (n < 10000) { DIGITS_4 (1000); } - else if (n < 100000) { DIGITS_5 (10000); } - else if (n < 1000000) { DIGITS_6 (100000); } - else if (n < 10000000) { DIGITS_7 (1000000); } - else if (n < 100000000) { DIGITS_8 (10000000); } - else if (n < 1000000000) { DIGITS_9 (100000000); } -#if SIZEOF_LONG == 4 + if (n < 10) { DIGITS_1 (1); } + else if (n < 100) { DIGITS_2 (10); } + else if (n < 1000) { DIGITS_3 (100); } + else if (n < 10000) { DIGITS_4 (1000); } + else if (n < 100000) { DIGITS_5 (10000); } + else if (n < 1000000) { DIGITS_6 (100000); } + else if (n < 10000000) { DIGITS_7 (1000000); } + else if (n < 100000000) { DIGITS_8 (10000000); } + else if (n < 1000000000) { DIGITS_9 (100000000); } +#if SIZEOF_WGINT == 4 + /* ``if (1)'' serves only to preserve editor indentation. */ + else if (1) { DIGITS_10 (1000000000); } +#elif SIZEOF_WGINT == SIZEOF_LONG + else if (n < 10000000000L) { DIGITS_10 (1000000000L); } + else if (n < 100000000000L) { DIGITS_11 (10000000000L); } + else if (n < 1000000000000L) { DIGITS_12 (100000000000L); } + else if (n < 10000000000000L) { DIGITS_13 (1000000000000L); } + else if (n < 100000000000000L) { DIGITS_14 (10000000000000L); } + else if (n < 1000000000000000L) { DIGITS_15 (100000000000000L); } + else if (n < 10000000000000000L) { DIGITS_16 (1000000000000000L); } + else if (n < 100000000000000000L) { DIGITS_17 (10000000000000000L); } + else if (n < 1000000000000000000L) { DIGITS_18 (100000000000000000L); } /* ``if (1)'' serves only to preserve editor indentation. */ - else if (1) { DIGITS_10 (1000000000); } -#else /* SIZEOF_LONG != 4 */ - else if (n < 10000000000L) { DIGITS_10 (1000000000L); } - else if (n < 100000000000L) { DIGITS_11 (10000000000L); } - else if (n < 1000000000000L) { DIGITS_12 (100000000000L); } - else if (n < 10000000000000L) { DIGITS_13 (1000000000000L); } - else if (n < 100000000000000L) { DIGITS_14 (10000000000000L); } - else if (n < 1000000000000000L) { DIGITS_15 (100000000000000L); } - else if (n < 10000000000000000L) { DIGITS_16 (1000000000000000L); } - else if (n < 100000000000000000L) { DIGITS_17 (10000000000000000L); } - else if (n < 1000000000000000000L) { DIGITS_18 (100000000000000000L); } - else { DIGITS_19 (1000000000000000000L); } -#endif /* SIZEOF_LONG != 4 */ + else if (1) { DIGITS_19 (1000000000000000000L); } +#elif SIZEOF_WGINT == SIZEOF_LONG_LONG + else if (n < 10000000000LL) { DIGITS_10 (1000000000LL); } + else if (n < 100000000000LL) { DIGITS_11 (10000000000LL); } + else if (n < 1000000000000LL) { DIGITS_12 (100000000000LL); } + else if (n < 10000000000000LL) { DIGITS_13 (1000000000000LL); } + else if (n < 100000000000000LL) { DIGITS_14 (10000000000000LL); } + else if (n < 1000000000000000LL) { DIGITS_15 (100000000000000LL); } + else if (n < 10000000000000000LL) { DIGITS_16 (1000000000000000LL); } + else if (n < 100000000000000000LL) { DIGITS_17 (10000000000000000LL); } + else if (n < 1000000000000000000LL) { DIGITS_18 (100000000000000000LL); } + /* ``if (1)'' serves only to preserve editor indentation. */ + else { DIGITS_19 (1000000000000000000LL); } +#endif *p = '\0'; -#endif /* (SIZEOF_LONG == 4) || (SIZEOF_LONG == 8) */ +#endif /* (SIZEOF_WGINT == 4) || (SIZEOF_WGINT == 8) */ return p; } @@ -1334,6 +1371,22 @@ #undef DIGITS_17 #undef DIGITS_18 #undef DIGITS_19 + +char * +print_number_as_string (wgint number) +{ + static char buf[24]; + number_to_string (buf, number); + return buf; +} + +char * +print_second_number_as_string (wgint number) +{ + static char buf[24]; + number_to_string (buf, number); + return buf; +} /* Support for timers. */ Index: src/utils.h =================================================================== RCS file: /pack/anoncvs/wget/src/utils.h,v retrieving revision 1.32 diff -u -r1.32 utils.h --- src/utils.h 2003/11/29 18:40:01 1.32 +++ src/utils.h 2005/02/18 23:25:55 @@ -45,7 +45,7 @@ struct file_memory { char *content; - long length; + wgint length; int mmap_p; }; @@ -79,7 +79,7 @@ int remove_link PARAMS ((const char *)); int file_exists_p PARAMS ((const char *)); int file_non_directory_p PARAMS ((const char *)); -long file_size PARAMS ((const char *)); +wgint file_size PARAMS ((const char *)); int make_directory PARAMS ((const char *)); char *unique_name PARAMS ((const char *, int)); char *file_merge PARAMS ((const char *, const char *)); @@ -109,10 +109,12 @@ void string_set_free PARAMS ((struct hash_table *)); void free_keys_and_values PARAMS ((struct hash_table *)); -char *legible PARAMS ((long)); +char *legible PARAMS ((wgint)); char *legible_large_int PARAMS ((LARGE_INT)); -int numdigit PARAMS ((long)); -char *number_to_string PARAMS ((char *, long)); +int numdigit PARAMS ((wgint)); +char *number_to_string PARAMS ((char *, wgint)); +char *print_number_as_string PARAMS ((wgint)); +char *print_second_number_as_string PARAMS ((wgint)); struct wget_timer *wtimer_allocate PARAMS ((void)); struct wget_timer *wtimer_new PARAMS ((void)); Index: src/wget.h =================================================================== RCS file: /pack/anoncvs/wget/src/wget.h,v retrieving revision 1.52 diff -u -r1.52 wget.h --- src/wget.h 2003/11/29 18:40:01 1.52 +++ src/wget.h 2005/02/18 23:25:56 @@ -107,6 +107,22 @@ # define GCC_FORMAT_ATTR(a, b) #endif /* not __GNUC__ */ +/* Define an integer type that works for LFS. */ +#ifndef WINDOWS +typedef off_t wgint; +# define SIZEOF_WGINT SIZEOF_OFF_T +#else +typedef long long wgint; +# define SIZEOF_WGINT 8 +#endif + +/* Define a strtol/strtoll clone for wgint. */ +#if SIZEOF_WGINT == SIZEOF_LONG +# define str_to_wgint strtol +#else +# define str_to_wgint strtoll +#endif + /* Everything uses this, so include them here directly. */ #include "xmalloc.h"