1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

[svn] Remove the "rbuf" buffering layer. Provide peeking primitives instead.

This commit is contained in:
hniksic 2003-11-20 17:48:11 -08:00
parent 0716c335a0
commit d9fea91a0a
20 changed files with 461 additions and 652 deletions

View File

@ -1,3 +1,25 @@
2003-11-21 Hrvoje Niksic <hniksic@xemacs.org>
* rbuf.c: Removed.
* ftp-basic.c (ftp_response): Use fd_read_line. No longer use
struct rbuf. Updated all callers.
* http.c (gethttp): Use fd_read_head to read all the headers in
one go.
(next_header): New function.
* retr.c (fd_read_line): New function: reads a line from FD,
leaving the rest of the data unread.
(fd_read_head): New function.
* connect.c (fd_peek): New function, implements peeking.
(poll_internal): New function.
(fd_read): Use it.
(fd_write): Ditto.
(fd_peek): Ditto.
(fd_register_transport): Allow registering a "peeker" callback.
2003-11-20 Hrvoje Niksic <hniksic@xemacs.org> 2003-11-20 Hrvoje Niksic <hniksic@xemacs.org>
* connect.c: Renamed xread/xwrite/xclose to * connect.c: Renamed xread/xwrite/xclose to

View File

@ -75,7 +75,7 @@ GETOPT_OBJ = @GETOPT_OBJ@
OBJ = $(ALLOCA) cmpt$o connect$o convert$o cookies$o \ OBJ = $(ALLOCA) cmpt$o connect$o convert$o cookies$o \
ftp$o ftp-basic$o ftp-ls$o $(OPIE_OBJ) $(GETOPT_OBJ) hash$o \ ftp$o ftp-basic$o ftp-ls$o $(OPIE_OBJ) $(GETOPT_OBJ) hash$o \
headers$o host$o html-parse$o html-url$o http$o init$o \ headers$o host$o html-parse$o html-url$o http$o init$o \
log$o main$o $(MD5_OBJ) netrc$o progress$o rbuf$o recur$o \ log$o main$o $(MD5_OBJ) netrc$o progress$o recur$o \
res$o retr$o safe-ctype$o snprintf$o $(SSL_OBJ) url$o \ res$o retr$o safe-ctype$o snprintf$o $(SSL_OBJ) url$o \
utils$o version$o xmalloc$o utils$o version$o xmalloc$o
@ -157,12 +157,12 @@ cmpt$o: wget.h sysdep.h options.h safe-ctype.h
connect$o: wget.h sysdep.h options.h safe-ctype.h utils.h connect.h host.h connect$o: wget.h sysdep.h options.h safe-ctype.h utils.h connect.h host.h
convert$o: wget.h convert.h url.h recur.h utils.h hash.h convert$o: wget.h convert.h url.h recur.h utils.h hash.h
cookies$o: wget.h sysdep.h options.h safe-ctype.h cookies.h hash.h url.h utils.h cookies$o: wget.h sysdep.h options.h safe-ctype.h cookies.h hash.h url.h utils.h
ftp-basic$o: wget.h sysdep.h options.h safe-ctype.h utils.h rbuf.h connect.h \ ftp-basic$o: wget.h sysdep.h options.h safe-ctype.h utils.h connect.h \
host.h ftp.h host.h ftp.h
ftp-ls$o: wget.h sysdep.h options.h safe-ctype.h utils.h ftp.h rbuf.h host.h \ ftp-ls$o: wget.h sysdep.h options.h safe-ctype.h utils.h ftp.h host.h \
url.h url.h
ftp-opie$o: wget.h sysdep.h options.h safe-ctype.h gen-md5.h ftp-opie$o: wget.h sysdep.h options.h safe-ctype.h gen-md5.h
ftp$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h rbuf.h retr.h \ ftp$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h retr.h \
ftp.h host.h connect.h netrc.h ftp.h host.h connect.h netrc.h
gen-md5$o: wget.h sysdep.h options.h safe-ctype.h gen-md5.h gen-md5$o: wget.h sysdep.h options.h safe-ctype.h gen-md5.h
gen_sslfunc$o: wget.h sysdep.h options.h safe-ctype.h utils.h connect.h host.h \ gen_sslfunc$o: wget.h sysdep.h options.h safe-ctype.h utils.h connect.h host.h \
@ -170,30 +170,27 @@ gen_sslfunc$o: wget.h sysdep.h options.h safe-ctype.h utils.h connect.h host.h \
getopt$o: wget.h sysdep.h options.h safe-ctype.h getopt.h getopt$o: wget.h sysdep.h options.h safe-ctype.h getopt.h
gnu-md5$o: wget.h sysdep.h options.h safe-ctype.h gnu-md5.h gnu-md5$o: wget.h sysdep.h options.h safe-ctype.h gnu-md5.h
hash$o: wget.h sysdep.h options.h safe-ctype.h utils.h hash.h hash$o: wget.h sysdep.h options.h safe-ctype.h utils.h hash.h
headers$o: wget.h sysdep.h options.h safe-ctype.h connect.h host.h rbuf.h \ headers$o: wget.h sysdep.h options.h safe-ctype.h connect.h host.h \
headers.h headers.h
host$o: wget.h sysdep.h options.h safe-ctype.h utils.h host.h url.h hash.h host$o: wget.h sysdep.h options.h safe-ctype.h utils.h host.h url.h hash.h
html-parse$o: wget.h sysdep.h options.h safe-ctype.h html-parse.h html-parse$o: wget.h sysdep.h options.h safe-ctype.h html-parse.h
html-url$o: wget.h sysdep.h options.h safe-ctype.h html-parse.h url.h utils.h html-url$o: wget.h sysdep.h options.h safe-ctype.h html-parse.h url.h utils.h
http$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h host.h rbuf.h \ http$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h host.h \
retr.h headers.h connect.h host.h netrc.h gen_sslfunc.h \ retr.h headers.h connect.h host.h netrc.h gen_sslfunc.h \
cookies.h gen-md5.h cookies.h gen-md5.h
init$o: wget.h sysdep.h options.h safe-ctype.h utils.h init.h host.h recur.h \ init$o: wget.h sysdep.h options.h safe-ctype.h utils.h init.h host.h recur.h \
netrc.h cookies.h progress.h netrc.h cookies.h progress.h
log$o: wget.h sysdep.h options.h safe-ctype.h utils.h log$o: wget.h sysdep.h options.h safe-ctype.h utils.h
main$o: wget.h sysdep.h options.h safe-ctype.h utils.h init.h retr.h rbuf.h \ main$o: wget.h sysdep.h options.h safe-ctype.h utils.h init.h retr.h \
recur.h host.h cookies.h url.h progress.h gen_sslfunc.h getopt.h recur.h host.h cookies.h url.h progress.h gen_sslfunc.h getopt.h
gnu-md5$o: wget.h sysdep.h options.h safe-ctype.h gnu-md5.h gnu-md5$o: wget.h sysdep.h options.h safe-ctype.h gnu-md5.h
mswindows$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h mswindows$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h
netrc$o: wget.h sysdep.h options.h safe-ctype.h utils.h netrc.h init.h netrc$o: wget.h sysdep.h options.h safe-ctype.h utils.h netrc.h init.h
progress$o: wget.h sysdep.h options.h safe-ctype.h progress.h utils.h retr.h \ progress$o: wget.h sysdep.h options.h safe-ctype.h progress.h utils.h retr.h
rbuf.h
rbuf$o: wget.h sysdep.h options.h safe-ctype.h rbuf.h connect.h host.h \
gen_sslfunc.h
recur$o: wget.h sysdep.h options.h safe-ctype.h url.h recur.h utils.h retr.h \ recur$o: wget.h sysdep.h options.h safe-ctype.h url.h recur.h utils.h retr.h \
rbuf.h ftp.h host.h hash.h ftp.h host.h hash.h
res$o: wget.h sysdep.h options.h safe-ctype.h utils.h hash.h url.h retr.h res.h res$o: wget.h sysdep.h options.h safe-ctype.h utils.h hash.h url.h retr.h res.h
retr$o: wget.h sysdep.h options.h safe-ctype.h utils.h retr.h rbuf.h url.h \ retr$o: wget.h sysdep.h options.h safe-ctype.h utils.h retr.h url.h \
recur.h ftp.h host.h connect.h hash.h recur.h ftp.h host.h connect.h hash.h
snprintf$o: safe-ctype.h snprintf$o: safe-ctype.h
safe-ctype$o: safe-ctype.h safe-ctype$o: safe-ctype.h

View File

@ -735,6 +735,16 @@ sock_poll (int fd, double timeout, int wait_for)
return select_fd (fd, timeout, wait_for); return select_fd (fd, timeout, wait_for);
} }
static int
sock_peek (int fd, char *buf, int bufsize)
{
int res;
do
res = recv (fd, buf, bufsize, MSG_PEEK);
while (res == -1 && errno == EINTR);
return res;
}
static void static void
sock_close (int fd) sock_close (int fd)
{ {
@ -760,6 +770,7 @@ struct transport_info {
fd_reader_t reader; fd_reader_t reader;
fd_writer_t writer; fd_writer_t writer;
fd_poller_t poller; fd_poller_t poller;
fd_peeker_t peeker;
fd_closer_t closer; fd_closer_t closer;
void *ctx; void *ctx;
}; };
@ -773,7 +784,8 @@ struct transport_info {
void void
fd_register_transport (int fd, fd_reader_t reader, fd_writer_t writer, fd_register_transport (int fd, fd_reader_t reader, fd_writer_t writer,
fd_poller_t poller, fd_closer_t closer, void *ctx) fd_poller_t poller, fd_peeker_t peeker,
fd_closer_t closer, void *ctx)
{ {
struct transport_info *info; struct transport_info *info;
@ -786,6 +798,7 @@ fd_register_transport (int fd, fd_reader_t reader, fd_writer_t writer,
info->reader = reader; info->reader = reader;
info->writer = writer; info->writer = writer;
info->poller = poller; info->poller = poller;
info->peeker = peeker;
info->closer = closer; info->closer = closer;
info->ctx = ctx; info->ctx = ctx;
if (!transport_map) if (!transport_map)
@ -819,6 +832,26 @@ fd_register_transport (int fd, fd_reader_t reader, fd_writer_t writer,
} \ } \
} while (0) } while (0)
static int
poll_internal (int fd, struct transport_info *info, int wf, double timeout)
{
if (timeout == -1)
timeout = opt.read_timeout;
if (timeout)
{
int test;
if (info && info->poller)
test = info->poller (fd, timeout, wf, info->ctx);
else
test = sock_poll (fd, timeout, wf);
if (test == 0)
errno = ETIMEDOUT;
if (test <= 0)
return 0;
}
return 1;
}
/* Read no more than BUFSIZE bytes of data from FD, storing them to /* Read no more than BUFSIZE bytes of data from FD, storing them to
BUF. If TIMEOUT is non-zero, the operation aborts if no data is BUF. If TIMEOUT is non-zero, the operation aborts if no data is
received after that many seconds. If TIMEOUT is -1, the value of received after that many seconds. If TIMEOUT is -1, the value of
@ -829,26 +862,30 @@ fd_read (int fd, char *buf, int bufsize, double timeout)
{ {
struct transport_info *info; struct transport_info *info;
LAZY_RETRIEVE_INFO (info); LAZY_RETRIEVE_INFO (info);
if (timeout == -1) if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
timeout = opt.read_timeout; return -1;
if (timeout)
{
int test;
if (info && info->poller)
test = info->poller (fd, timeout, WAIT_FOR_READ, info->ctx);
else
test = sock_poll (fd, timeout, WAIT_FOR_READ);
if (test == 0)
errno = ETIMEDOUT;
if (test <= 0)
return -1;
}
if (info && info->reader) if (info && info->reader)
return info->reader (fd, buf, bufsize, info->ctx); return info->reader (fd, buf, bufsize, info->ctx);
else else
return sock_read (fd, buf, bufsize); return sock_read (fd, buf, bufsize);
} }
/* The same as xread, but don't actually read the data, just copy it
instead. */
int
fd_peek (int fd, char *buf, int bufsize, double timeout)
{
struct transport_info *info;
LAZY_RETRIEVE_INFO (info);
if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
return -1;
if (info && info->peeker)
return info->peeker (fd, buf, bufsize, info->ctx);
else
return sock_peek (fd, buf, bufsize);
}
/* Write the entire contents of BUF to FD. If TIMEOUT is non-zero, /* Write the entire contents of BUF to FD. If TIMEOUT is non-zero,
the operation aborts if no data is received after that many the operation aborts if no data is received after that many
seconds. If TIMEOUT is -1, the value of opt.timeout is used for seconds. If TIMEOUT is -1, the value of opt.timeout is used for
@ -860,26 +897,14 @@ fd_write (int fd, char *buf, int bufsize, double timeout)
int res; int res;
struct transport_info *info; struct transport_info *info;
LAZY_RETRIEVE_INFO (info); LAZY_RETRIEVE_INFO (info);
if (timeout == -1)
timeout = opt.read_timeout;
/* `write' may write less than LEN bytes, thus the loop keeps trying /* `write' may write less than LEN bytes, thus the loop keeps trying
it until all was written, or an error occurred. */ it until all was written, or an error occurred. */
res = 0; res = 0;
while (bufsize > 0) while (bufsize > 0)
{ {
if (timeout) if (!poll_internal (fd, info, WAIT_FOR_WRITE, timeout))
{ return -1;
int test;
if (info && info->poller)
test = info->poller (fd, timeout, WAIT_FOR_WRITE, info->ctx);
else
test = sock_poll (fd, timeout, WAIT_FOR_WRITE);
if (test == 0)
errno = ETIMEDOUT;
if (test <= 0)
return -1;
}
if (info && info->writer) if (info && info->writer)
res = info->writer (fd, buf, bufsize, info->ctx); res = info->writer (fd, buf, bufsize, info->ctx);
else else

View File

@ -70,13 +70,14 @@ int socket_has_inet6 PARAMS ((void));
typedef int (*fd_reader_t) PARAMS ((int, char *, int, void *)); typedef int (*fd_reader_t) PARAMS ((int, char *, int, void *));
typedef int (*fd_writer_t) PARAMS ((int, char *, int, void *)); typedef int (*fd_writer_t) PARAMS ((int, char *, int, void *));
typedef int (*fd_poller_t) PARAMS ((int, double, int, void *)); typedef int (*fd_poller_t) PARAMS ((int, double, int, void *));
typedef int (*fd_peeker_t) PARAMS ((int, char *, int, void *));
typedef void (*fd_closer_t) PARAMS ((int, void *)); typedef void (*fd_closer_t) PARAMS ((int, void *));
void fd_register_transport PARAMS ((int, void fd_register_transport PARAMS ((int, fd_reader_t, fd_writer_t,
fd_reader_t, fd_writer_t, fd_poller_t, fd_peeker_t, fd_closer_t,
fd_poller_t, fd_closer_t,
void *)); void *));
int fd_read PARAMS ((int, char *, int, double)); int fd_read PARAMS ((int, char *, int, double));
int fd_write PARAMS ((int, char *, int, double)); int fd_write PARAMS ((int, char *, int, double));
int fd_peek PARAMS ((int, char *, int, double));
void fd_close PARAMS ((int)); void fd_close PARAMS ((int));
#endif /* CONNECT_H */ #endif /* CONNECT_H */

View File

@ -6,7 +6,7 @@ This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
GNU Wget is distributed in the hope that it will be useful, GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -46,10 +46,10 @@ so, delete this exception statement from your version. */
#include "wget.h" #include "wget.h"
#include "utils.h" #include "utils.h"
#include "rbuf.h"
#include "connect.h" #include "connect.h"
#include "host.h" #include "host.h"
#include "ftp.h" #include "ftp.h"
#include "retr.h"
char ftp_last_respline[128]; char ftp_last_respline[128];
@ -59,45 +59,32 @@ char ftp_last_respline[128];
line is 0-terminated. All the response lines but the last one are line is 0-terminated. All the response lines but the last one are
skipped. The last line is determined as described in RFC959. */ skipped. The last line is determined as described in RFC959. */
uerr_t uerr_t
ftp_response (struct rbuf *rbuf, char **line) ftp_response (int fd, char **ret_line)
{ {
int i; while (1)
int bufsize = 40;
*line = (char *)xmalloc (bufsize);
do
{ {
for (i = 0; 1; i++) char *line = fd_read_line (fd);
{ if (!line)
int res; return FTPRERR;
if (i > bufsize - 1)
*line = (char *)xrealloc (*line, (bufsize <<= 1));
res = RBUF_READCHAR (rbuf, *line + i);
/* RES is number of bytes read. */
if (res == 1)
{
if ((*line)[i] == '\n')
{
(*line)[i] = '\0';
/* Get rid of \r. */
if (i > 0 && (*line)[i - 1] == '\r')
(*line)[i - 1] = '\0';
break;
}
}
else
return FTPRERR;
}
if (opt.server_response) if (opt.server_response)
logprintf (LOG_ALWAYS, "%s\n", *line); logputs (LOG_NOTQUIET, line);
else else
DEBUGP (("%s\n", *line)); DEBUGP (("%s", line));
if (ISDIGIT (line[0]) && ISDIGIT (line[1]) && ISDIGIT (line[2])
&& line[3] == ' ')
{
char *p = line + strlen (line);
if (p > line && p[-1] == '\n')
*--p = '\0';
if (p > line && p[-1] == '\r')
*--p = '\0';
strncpy (ftp_last_respline, line, sizeof (ftp_last_respline));
ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
*ret_line = line;
return FTPOK;
}
xfree (line);
} }
while (!(i >= 3 && ISDIGIT (**line) && ISDIGIT ((*line)[1]) &&
ISDIGIT ((*line)[2]) && (*line)[3] == ' '));
strncpy (ftp_last_respline, *line, sizeof (ftp_last_respline));
ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
return FTPOK;
} }
/* Returns the malloc-ed FTP request, ending with <CR><LF>, printing /* Returns the malloc-ed FTP request, ending with <CR><LF>, printing
@ -126,14 +113,14 @@ ftp_request (const char *command, const char *value)
/* Sends the USER and PASS commands to the server, to control /* Sends the USER and PASS commands to the server, to control
connection socket csock. */ connection socket csock. */
uerr_t uerr_t
ftp_login (struct rbuf *rbuf, const char *acc, const char *pass) ftp_login (int csock, const char *acc, const char *pass)
{ {
uerr_t err; uerr_t err;
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
/* Get greeting. */ /* Get greeting. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -147,7 +134,7 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
xfree (respline); xfree (respline);
/* Send USER username. */ /* Send USER username. */
request = ftp_request ("USER", acc); request = ftp_request ("USER", acc);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -155,7 +142,7 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -214,7 +201,7 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
xfree (respline); xfree (respline);
/* Send PASS password. */ /* Send PASS password. */
request = ftp_request ("PASS", pass); request = ftp_request ("PASS", pass);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -222,7 +209,7 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -260,7 +247,7 @@ ip_address_to_port_repr (const ip_address *addr, int port, char *buf,
server. Use acceptport after RETR, to get the socket of data server. Use acceptport after RETR, to get the socket of data
connection. */ connection. */
uerr_t uerr_t
ftp_port (struct rbuf *rbuf, int *local_sock) ftp_port (int csock, int *local_sock)
{ {
uerr_t err; uerr_t err;
char *request, *respline; char *request, *respline;
@ -270,11 +257,8 @@ ftp_port (struct rbuf *rbuf, int *local_sock)
/* Must contain the argument of PORT (of the form a,b,c,d,e,f). */ /* Must contain the argument of PORT (of the form a,b,c,d,e,f). */
char bytes[6 * 4 + 1]; char bytes[6 * 4 + 1];
assert (rbuf != NULL);
assert (rbuf_initialized_p (rbuf));
/* Get the address of this side of the connection. */ /* Get the address of this side of the connection. */
if (!socket_ip_address (RBUF_FD (rbuf), &addr, ENDPOINT_LOCAL)) if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
return FTPSYSERR; return FTPSYSERR;
assert (addr.type == IPV4_ADDRESS); assert (addr.type == IPV4_ADDRESS);
@ -292,7 +276,7 @@ ftp_port (struct rbuf *rbuf, int *local_sock)
/* Send PORT request. */ /* Send PORT request. */
request = ftp_request ("PORT", bytes); request = ftp_request ("PORT", bytes);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -302,7 +286,7 @@ ftp_port (struct rbuf *rbuf, int *local_sock)
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -357,7 +341,7 @@ ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf,
server. Use acceptport after RETR, to get the socket of data server. Use acceptport after RETR, to get the socket of data
connection. */ connection. */
uerr_t uerr_t
ftp_lprt (struct rbuf *rbuf, int *local_sock) ftp_lprt (int csock, int *local_sock)
{ {
uerr_t err; uerr_t err;
char *request, *respline; char *request, *respline;
@ -367,11 +351,8 @@ ftp_lprt (struct rbuf *rbuf, int *local_sock)
/* Must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */ /* Must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
char bytes[21 * 4 + 1]; char bytes[21 * 4 + 1];
assert (rbuf != NULL);
assert (rbuf_initialized_p (rbuf));
/* Get the address of this side of the connection. */ /* Get the address of this side of the connection. */
if (!socket_ip_address (RBUF_FD (rbuf), &addr, ENDPOINT_LOCAL)) if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
return FTPSYSERR; return FTPSYSERR;
assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS); assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
@ -389,7 +370,7 @@ ftp_lprt (struct rbuf *rbuf, int *local_sock)
/* Send PORT request. */ /* Send PORT request. */
request = ftp_request ("LPRT", bytes); request = ftp_request ("LPRT", bytes);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -398,7 +379,7 @@ ftp_lprt (struct rbuf *rbuf, int *local_sock)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -439,7 +420,7 @@ ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf,
server. Use acceptport after RETR, to get the socket of data server. Use acceptport after RETR, to get the socket of data
connection. */ connection. */
uerr_t uerr_t
ftp_eprt (struct rbuf *rbuf, int *local_sock) ftp_eprt (int csock, int *local_sock)
{ {
uerr_t err; uerr_t err;
char *request, *respline; char *request, *respline;
@ -451,11 +432,8 @@ ftp_eprt (struct rbuf *rbuf, int *local_sock)
* 1 char for af (1-2) and 5 chars for port (0-65535) */ * 1 char for af (1-2) and 5 chars for port (0-65535) */
char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1]; char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1];
assert (rbuf != NULL);
assert (rbuf_initialized_p(rbuf));
/* Get the address of this side of the connection. */ /* Get the address of this side of the connection. */
if (!socket_ip_address (RBUF_FD (rbuf), &addr, ENDPOINT_LOCAL)) if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
return FTPSYSERR; return FTPSYSERR;
assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS); assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
@ -473,7 +451,7 @@ ftp_eprt (struct rbuf *rbuf, int *local_sock)
/* Send PORT request. */ /* Send PORT request. */
request = ftp_request ("EPRT", bytes); request = ftp_request ("EPRT", bytes);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -482,7 +460,7 @@ ftp_eprt (struct rbuf *rbuf, int *local_sock)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -504,15 +482,13 @@ ftp_eprt (struct rbuf *rbuf, int *local_sock)
transfer. Reads the response from server and parses it. Reads the transfer. Reads the response from server and parses it. Reads the
host and port addresses and returns them. */ host and port addresses and returns them. */
uerr_t uerr_t
ftp_pasv (struct rbuf *rbuf, ip_address *addr, int *port) ftp_pasv (int csock, ip_address *addr, int *port)
{ {
char *request, *respline, *s; char *request, *respline, *s;
int nwritten, i; int nwritten, i;
uerr_t err; uerr_t err;
unsigned char tmp[6]; unsigned char tmp[6];
assert (rbuf != NULL);
assert (rbuf_initialized_p (rbuf));
assert (addr != NULL); assert (addr != NULL);
assert (port != NULL); assert (port != NULL);
@ -521,7 +497,7 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
/* Form the request. */ /* Form the request. */
request = ftp_request ("PASV", NULL); request = ftp_request ("PASV", NULL);
/* And send it. */ /* And send it. */
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -529,7 +505,7 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
} }
xfree (request); xfree (request);
/* Get the server response. */ /* Get the server response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -573,7 +549,7 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
transfer. Reads the response from server and parses it. Reads the transfer. Reads the response from server and parses it. Reads the
host and port addresses and returns them. */ host and port addresses and returns them. */
uerr_t uerr_t
ftp_lpsv (struct rbuf *rbuf, ip_address *addr, int *port) ftp_lpsv (int csock, ip_address *addr, int *port)
{ {
char *request, *respline, *s; char *request, *respline, *s;
int nwritten, i, af, addrlen, portlen; int nwritten, i, af, addrlen, portlen;
@ -581,8 +557,6 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, int *port)
unsigned char tmp[16]; unsigned char tmp[16];
unsigned char tmpprt[2]; unsigned char tmpprt[2];
assert (rbuf != NULL);
assert (rbuf_initialized_p(rbuf));
assert (addr != NULL); assert (addr != NULL);
assert (port != NULL); assert (port != NULL);
@ -592,7 +566,7 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, int *port)
request = ftp_request ("LPSV", NULL); request = ftp_request ("LPSV", NULL);
/* And send it. */ /* And send it. */
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -601,7 +575,7 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, int *port)
xfree (request); xfree (request);
/* Get the server response. */ /* Get the server response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -739,15 +713,13 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, int *port)
transfer. Reads the response from server and parses it. Reads the transfer. Reads the response from server and parses it. Reads the
host and port addresses and returns them. */ host and port addresses and returns them. */
uerr_t uerr_t
ftp_epsv (struct rbuf *rbuf, ip_address *ip, int *port) ftp_epsv (int csock, ip_address *ip, int *port)
{ {
char *request, *respline, *start, delim, *s; char *request, *respline, *start, delim, *s;
int nwritten, i; int nwritten, i;
uerr_t err; uerr_t err;
int tport; int tport;
assert (rbuf != NULL);
assert (rbuf_initialized_p(rbuf));
assert (ip != NULL); assert (ip != NULL);
assert (port != NULL); assert (port != NULL);
@ -759,7 +731,7 @@ ftp_epsv (struct rbuf *rbuf, ip_address *ip, int *port)
request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2")); request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2"));
/* And send it. */ /* And send it. */
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -768,7 +740,7 @@ ftp_epsv (struct rbuf *rbuf, ip_address *ip, int *port)
xfree (request); xfree (request);
/* Get the server response. */ /* Get the server response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -847,7 +819,7 @@ ftp_epsv (struct rbuf *rbuf, ip_address *ip, int *port)
/* Sends the TYPE request to the server. */ /* Sends the TYPE request to the server. */
uerr_t uerr_t
ftp_type (struct rbuf *rbuf, int type) ftp_type (int csock, int type)
{ {
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
@ -859,7 +831,7 @@ ftp_type (struct rbuf *rbuf, int type)
stype[1] = 0; stype[1] = 0;
/* Send TYPE request. */ /* Send TYPE request. */
request = ftp_request ("TYPE", stype); request = ftp_request ("TYPE", stype);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -867,7 +839,7 @@ ftp_type (struct rbuf *rbuf, int type)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -886,7 +858,7 @@ ftp_type (struct rbuf *rbuf, int type)
/* Changes the working directory by issuing a CWD command to the /* Changes the working directory by issuing a CWD command to the
server. */ server. */
uerr_t uerr_t
ftp_cwd (struct rbuf *rbuf, const char *dir) ftp_cwd (int csock, const char *dir)
{ {
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
@ -894,7 +866,7 @@ ftp_cwd (struct rbuf *rbuf, const char *dir)
/* Send CWD request. */ /* Send CWD request. */
request = ftp_request ("CWD", dir); request = ftp_request ("CWD", dir);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -902,7 +874,7 @@ ftp_cwd (struct rbuf *rbuf, const char *dir)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -925,7 +897,7 @@ ftp_cwd (struct rbuf *rbuf, const char *dir)
/* Sends REST command to the FTP server. */ /* Sends REST command to the FTP server. */
uerr_t uerr_t
ftp_rest (struct rbuf *rbuf, long offset) ftp_rest (int csock, long offset)
{ {
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
@ -934,7 +906,7 @@ ftp_rest (struct rbuf *rbuf, long offset)
number_to_string (numbuf, offset); number_to_string (numbuf, offset);
request = ftp_request ("REST", numbuf); request = ftp_request ("REST", numbuf);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -942,7 +914,7 @@ ftp_rest (struct rbuf *rbuf, long offset)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -960,7 +932,7 @@ ftp_rest (struct rbuf *rbuf, long offset)
/* Sends RETR command to the FTP server. */ /* Sends RETR command to the FTP server. */
uerr_t uerr_t
ftp_retr (struct rbuf *rbuf, const char *file) ftp_retr (int csock, const char *file)
{ {
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
@ -968,7 +940,7 @@ ftp_retr (struct rbuf *rbuf, const char *file)
/* Send RETR request. */ /* Send RETR request. */
request = ftp_request ("RETR", file); request = ftp_request ("RETR", file);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -976,7 +948,7 @@ ftp_retr (struct rbuf *rbuf, const char *file)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -1000,7 +972,7 @@ ftp_retr (struct rbuf *rbuf, const char *file)
/* Sends the LIST command to the server. If FILE is NULL, send just /* Sends the LIST command to the server. If FILE is NULL, send just
`LIST' (no space). */ `LIST' (no space). */
uerr_t uerr_t
ftp_list (struct rbuf *rbuf, const char *file) ftp_list (int csock, const char *file)
{ {
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
@ -1008,7 +980,7 @@ ftp_list (struct rbuf *rbuf, const char *file)
/* Send LIST request. */ /* Send LIST request. */
request = ftp_request ("LIST", file); request = ftp_request ("LIST", file);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -1016,7 +988,7 @@ ftp_list (struct rbuf *rbuf, const char *file)
} }
xfree (request); xfree (request);
/* Get appropriate respone. */ /* Get appropriate respone. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -1039,7 +1011,7 @@ ftp_list (struct rbuf *rbuf, const char *file)
/* Sends the SYST command to the server. */ /* Sends the SYST command to the server. */
uerr_t uerr_t
ftp_syst (struct rbuf *rbuf, enum stype *server_type) ftp_syst (int csock, enum stype *server_type)
{ {
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
@ -1047,7 +1019,7 @@ ftp_syst (struct rbuf *rbuf, enum stype *server_type)
/* Send SYST request. */ /* Send SYST request. */
request = ftp_request ("SYST", NULL); request = ftp_request ("SYST", NULL);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -1056,7 +1028,7 @@ ftp_syst (struct rbuf *rbuf, enum stype *server_type)
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -1096,7 +1068,7 @@ ftp_syst (struct rbuf *rbuf, enum stype *server_type)
/* Sends the PWD command to the server. */ /* Sends the PWD command to the server. */
uerr_t uerr_t
ftp_pwd (struct rbuf *rbuf, char **pwd) ftp_pwd (int csock, char **pwd)
{ {
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
@ -1104,7 +1076,7 @@ ftp_pwd (struct rbuf *rbuf, char **pwd)
/* Send PWD request. */ /* Send PWD request. */
request = ftp_request ("PWD", NULL); request = ftp_request ("PWD", NULL);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -1112,7 +1084,7 @@ ftp_pwd (struct rbuf *rbuf, char **pwd)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -1142,7 +1114,7 @@ ftp_pwd (struct rbuf *rbuf, char **pwd)
/* Sends the SIZE command to the server, and returns the value in 'size'. /* Sends the SIZE command to the server, and returns the value in 'size'.
* If an error occurs, size is set to zero. */ * If an error occurs, size is set to zero. */
uerr_t uerr_t
ftp_size (struct rbuf *rbuf, const char *file, long int *size) ftp_size (int csock, const char *file, long int *size)
{ {
char *request, *respline; char *request, *respline;
int nwritten; int nwritten;
@ -1150,7 +1122,7 @@ ftp_size (struct rbuf *rbuf, const char *file, long int *size)
/* Send PWD request. */ /* Send PWD request. */
request = ftp_request ("SIZE", file); request = ftp_request ("SIZE", file);
nwritten = fd_write (RBUF_FD (rbuf), request, strlen (request), -1); nwritten = fd_write (csock, request, strlen (request), -1);
if (nwritten < 0) if (nwritten < 0)
{ {
xfree (request); xfree (request);
@ -1159,7 +1131,7 @@ ftp_size (struct rbuf *rbuf, const char *file, long int *size)
} }
xfree (request); xfree (request);
/* Get appropriate response. */ /* Get appropriate response. */
err = ftp_response (rbuf, &respline); err = ftp_response (csock, &respline);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);

132
src/ftp.c
View File

@ -47,7 +47,6 @@ so, delete this exception statement from your version. */
#include "wget.h" #include "wget.h"
#include "utils.h" #include "utils.h"
#include "url.h" #include "url.h"
#include "rbuf.h"
#include "retr.h" #include "retr.h"
#include "ftp.h" #include "ftp.h"
#include "connect.h" #include "connect.h"
@ -71,7 +70,7 @@ typedef struct
{ {
int st; /* connection status */ int st; /* connection status */
int cmd; /* command code */ int cmd; /* command code */
struct rbuf rbuf; /* control connection buffer */ int csock; /* control connection socket */
double dltime; /* time of the download in msecs */ double dltime; /* time of the download in msecs */
enum stype rs; /* remote system reported by ftp server */ enum stype rs; /* remote system reported by ftp server */
char *id; /* initial directory */ char *id; /* initial directory */
@ -128,14 +127,14 @@ ftp_expected_bytes (const char *s)
* It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv. * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
*/ */
static uerr_t static uerr_t
ftp_do_pasv (struct rbuf *rbuf, ip_address *addr, int *port) ftp_do_pasv (int csock, ip_address *addr, int *port)
{ {
uerr_t err; uerr_t err;
/* We need to determine the address family and need to call /* We need to determine the address family and need to call
getpeername, so while we're at it, store the address to ADDR. getpeername, so while we're at it, store the address to ADDR.
ftp_pasv and ftp_lpsv can simply override it. */ ftp_pasv and ftp_lpsv can simply override it. */
if (!socket_ip_address (RBUF_FD (rbuf), addr, ENDPOINT_PEER)) if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
abort (); abort ();
/* If our control connection is over IPv6, then we first try EPSV and then /* If our control connection is over IPv6, then we first try EPSV and then
@ -146,19 +145,19 @@ ftp_do_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
case IPV4_ADDRESS: case IPV4_ADDRESS:
if (!opt.server_response) if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PASV ... "); logputs (LOG_VERBOSE, "==> PASV ... ");
err = ftp_pasv (rbuf, addr, port); err = ftp_pasv (csock, addr, port);
break; break;
case IPV6_ADDRESS: case IPV6_ADDRESS:
if (!opt.server_response) if (!opt.server_response)
logputs (LOG_VERBOSE, "==> EPSV ... "); logputs (LOG_VERBOSE, "==> EPSV ... ");
err = ftp_epsv (rbuf, addr, port); err = ftp_epsv (csock, addr, port);
/* If EPSV is not supported try LPSV */ /* If EPSV is not supported try LPSV */
if (err == FTPNOPASV) if (err == FTPNOPASV)
{ {
if (!opt.server_response) if (!opt.server_response)
logputs (LOG_VERBOSE, "==> LPSV ... "); logputs (LOG_VERBOSE, "==> LPSV ... ");
err = ftp_lpsv (rbuf, addr, port); err = ftp_lpsv (csock, addr, port);
} }
break; break;
default: default:
@ -173,15 +172,12 @@ ftp_do_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
* It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port. * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
*/ */
static uerr_t static uerr_t
ftp_do_port (struct rbuf *rbuf, int *local_sock) ftp_do_port (int csock, int *local_sock)
{ {
uerr_t err; uerr_t err;
ip_address cip; ip_address cip;
assert (rbuf != NULL); if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
assert (rbuf_initialized_p (rbuf));
if (!socket_ip_address (RBUF_FD (rbuf), &cip, ENDPOINT_PEER))
abort (); abort ();
/* If our control connection is over IPv6, then we first try EPRT and then /* If our control connection is over IPv6, then we first try EPRT and then
@ -192,19 +188,19 @@ ftp_do_port (struct rbuf *rbuf, int *local_sock)
case IPV4_ADDRESS: case IPV4_ADDRESS:
if (!opt.server_response) if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PORT ... "); logputs (LOG_VERBOSE, "==> PORT ... ");
err = ftp_port (rbuf, local_sock); err = ftp_port (csock, local_sock);
break; break;
case IPV6_ADDRESS: case IPV6_ADDRESS:
if (!opt.server_response) if (!opt.server_response)
logputs (LOG_VERBOSE, "==> EPRT ... "); logputs (LOG_VERBOSE, "==> EPRT ... ");
err = ftp_eprt (rbuf, local_sock); err = ftp_eprt (csock, local_sock);
/* If EPRT is not supported try LPRT */ /* If EPRT is not supported try LPRT */
if (err == FTPPORTERR) if (err == FTPPORTERR)
{ {
if (!opt.server_response) if (!opt.server_response)
logputs (LOG_VERBOSE, "==> LPRT ... "); logputs (LOG_VERBOSE, "==> LPRT ... ");
err = ftp_lprt (rbuf, local_sock); err = ftp_lprt (csock, local_sock);
} }
break; break;
default: default:
@ -215,19 +211,19 @@ ftp_do_port (struct rbuf *rbuf, int *local_sock)
#else #else
static uerr_t static uerr_t
ftp_do_pasv (struct rbuf *rbuf, ip_address *addr, int *port) ftp_do_pasv (int csock, ip_address *addr, int *port)
{ {
if (!opt.server_response) if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PASV ... "); logputs (LOG_VERBOSE, "==> PASV ... ");
return ftp_pasv (rbuf, addr, port); return ftp_pasv (csock, addr, port);
} }
static uerr_t static uerr_t
ftp_do_port (struct rbuf *rbuf, int *local_sock) ftp_do_port (int csock, int *local_sock)
{ {
if (!opt.server_response) if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PORT ... "); logputs (LOG_VERBOSE, "==> PORT ... ");
return ftp_port (rbuf, local_sock); return ftp_port (csock, local_sock);
} }
#endif #endif
@ -268,7 +264,7 @@ getftp (struct url *u, long *len, long restval, ccon *con)
con->dltime = 0; con->dltime = 0;
if (!(cmd & DO_LOGIN)) if (!(cmd & DO_LOGIN))
csock = RBUF_FD (&con->rbuf); csock = con->csock;
else /* cmd & DO_LOGIN */ else /* cmd & DO_LOGIN */
{ {
char type_char; char type_char;
@ -294,20 +290,11 @@ getftp (struct url *u, long *len, long restval, ccon *con)
return (retryable_socket_connect_error (errno) return (retryable_socket_connect_error (errno)
? CONERROR : CONIMPOSSIBLE); ? CONERROR : CONIMPOSSIBLE);
if (cmd & LEAVE_PENDING)
rbuf_initialize (&con->rbuf, csock);
else
rbuf_uninitialize (&con->rbuf);
/* Since this is a new connection, we may safely discard
anything left in the buffer. */
rbuf_discard (&con->rbuf);
/* Second: Login with proper USER/PASS sequence. */ /* Second: Login with proper USER/PASS sequence. */
logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user); logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
if (opt.server_response) if (opt.server_response)
logputs (LOG_ALWAYS, "\n"); logputs (LOG_ALWAYS, "\n");
err = ftp_login (&con->rbuf, logname, passwd); err = ftp_login (csock, logname, passwd);
if (con->proxy) if (con->proxy)
xfree (logname); xfree (logname);
@ -320,14 +307,12 @@ getftp (struct url *u, long *len, long restval, ccon *con)
logputs (LOG_NOTQUIET, _("\ logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n")); Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPSRVERR: case FTPSRVERR:
logputs (LOG_VERBOSE, "\n"); logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("Error in server greeting.\n")); logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case WRITEFAILED: case WRITEFAILED:
@ -335,21 +320,18 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, logputs (LOG_NOTQUIET,
_("Write failed, closing control connection.\n")); _("Write failed, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPLOGREFUSED: case FTPLOGREFUSED:
logputs (LOG_VERBOSE, "\n"); logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("The server refuses login.\n")); logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return FTPLOGREFUSED; return FTPLOGREFUSED;
break; break;
case FTPLOGINC: case FTPLOGINC:
logputs (LOG_VERBOSE, "\n"); logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("Login incorrect.\n")); logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return FTPLOGINC; return FTPLOGINC;
break; break;
case FTPOK: case FTPOK:
@ -364,7 +346,7 @@ Error in server response, closing control connection.\n"));
/* Third: Get the system type */ /* Third: Get the system type */
if (!opt.server_response) if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> SYST ... "); logprintf (LOG_VERBOSE, "==> SYST ... ");
err = ftp_syst (&con->rbuf, &con->rs); err = ftp_syst (csock, &con->rs);
/* FTPRERR */ /* FTPRERR */
switch (err) switch (err)
{ {
@ -373,7 +355,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, _("\ logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n")); Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPSRVERR: case FTPSRVERR:
@ -395,7 +376,7 @@ Error in server response, closing control connection.\n"));
if (!opt.server_response) if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> PWD ... "); logprintf (LOG_VERBOSE, "==> PWD ... ");
err = ftp_pwd(&con->rbuf, &con->id); err = ftp_pwd(csock, &con->id);
/* FTPRERR */ /* FTPRERR */
switch (err) switch (err)
{ {
@ -404,7 +385,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, _("\ logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n")); Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPSRVERR : case FTPSRVERR :
@ -449,7 +429,7 @@ Error in server response, closing control connection.\n"));
type_char = ftp_process_type (u->params); type_char = ftp_process_type (u->params);
if (!opt.server_response) if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char); logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
err = ftp_type (&con->rbuf, type_char); err = ftp_type (csock, type_char);
/* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */ /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
switch (err) switch (err)
{ {
@ -458,7 +438,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, _("\ logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n")); Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case WRITEFAILED: case WRITEFAILED:
@ -466,7 +445,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, logputs (LOG_NOTQUIET,
_("Write failed, closing control connection.\n")); _("Write failed, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPUNKNOWNTYPE: case FTPUNKNOWNTYPE:
@ -475,7 +453,6 @@ Error in server response, closing control connection.\n"));
_("Unknown type `%c', closing control connection.\n"), _("Unknown type `%c', closing control connection.\n"),
type_char); type_char);
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
case FTPOK: case FTPOK:
/* Everything is OK. */ /* Everything is OK. */
@ -564,7 +541,7 @@ Error in server response, closing control connection.\n"));
if (!opt.server_response) if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> CWD %s ... ", target); logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
err = ftp_cwd (&con->rbuf, target); err = ftp_cwd (csock, target);
/* FTPRERR, WRITEFAILED, FTPNSFOD */ /* FTPRERR, WRITEFAILED, FTPNSFOD */
switch (err) switch (err)
{ {
@ -573,7 +550,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, _("\ logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n")); Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case WRITEFAILED: case WRITEFAILED:
@ -581,7 +557,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, logputs (LOG_NOTQUIET,
_("Write failed, closing control connection.\n")); _("Write failed, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPNSFOD: case FTPNSFOD:
@ -589,7 +564,6 @@ Error in server response, closing control connection.\n"));
logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"), logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
u->dir); u->dir);
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPOK: case FTPOK:
@ -614,7 +588,7 @@ Error in server response, closing control connection.\n"));
logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file); logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
} }
err = ftp_size(&con->rbuf, u->file, len); err = ftp_size(csock, u->file, len);
/* FTPRERR */ /* FTPRERR */
switch (err) switch (err)
{ {
@ -624,7 +598,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, _("\ logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n")); Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPOK: case FTPOK:
@ -645,7 +618,7 @@ Error in server response, closing control connection.\n"));
{ {
ip_address passive_addr; ip_address passive_addr;
int passive_port; int passive_port;
err = ftp_do_pasv (&con->rbuf, &passive_addr, &passive_port); err = ftp_do_pasv (csock, &passive_addr, &passive_port);
/* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */ /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
switch (err) switch (err)
{ {
@ -654,7 +627,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, _("\ logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n")); Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case WRITEFAILED: case WRITEFAILED:
@ -662,7 +634,6 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, logputs (LOG_NOTQUIET,
_("Write failed, closing control connection.\n")); _("Write failed, closing control connection.\n"));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPNOPASV: case FTPNOPASV:
@ -690,7 +661,6 @@ Error in server response, closing control connection.\n"));
{ {
int save_errno = errno; int save_errno = errno;
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
logprintf (LOG_VERBOSE, _("couldn't connect to %s port %hu: %s\n"), logprintf (LOG_VERBOSE, _("couldn't connect to %s port %hu: %s\n"),
pretty_print_address (&passive_addr), passive_port, pretty_print_address (&passive_addr), passive_port,
strerror (save_errno)); strerror (save_errno));
@ -706,7 +676,7 @@ Error in server response, closing control connection.\n"));
if (!pasv_mode_open) /* Try to use a port command if PASV failed */ if (!pasv_mode_open) /* Try to use a port command if PASV failed */
{ {
err = ftp_do_port (&con->rbuf, &local_sock); err = ftp_do_port (csock, &local_sock);
/* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR, /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
FTPPORTERR */ FTPPORTERR */
switch (err) switch (err)
@ -718,7 +688,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case WRITEFAILED: case WRITEFAILED:
@ -728,7 +697,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case CONSOCKERR: case CONSOCKERR:
@ -737,7 +705,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPSYSERR: case FTPSYSERR:
@ -753,7 +720,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPOK: case FTPOK:
@ -773,7 +739,7 @@ Error in server response, closing control connection.\n"));
{ {
if (!opt.server_response) if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval); logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
err = ftp_rest (&con->rbuf, restval); err = ftp_rest (csock, restval);
/* FTPRERR, WRITEFAILED, FTPRESTFAIL */ /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
switch (err) switch (err)
@ -785,7 +751,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case WRITEFAILED: case WRITEFAILED:
@ -795,7 +760,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPRESTFAIL: case FTPRESTFAIL:
@ -810,7 +774,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return CONTNOTSUPPORTED; return CONTNOTSUPPORTED;
} }
logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n")); logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
@ -838,7 +801,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return RETRFINISHED; return RETRFINISHED;
} }
@ -852,7 +814,7 @@ Error in server response, closing control connection.\n"));
} }
} }
err = ftp_retr (&con->rbuf, u->file); err = ftp_retr (csock, u->file);
/* FTPRERR, WRITEFAILED, FTPNSFOD */ /* FTPRERR, WRITEFAILED, FTPNSFOD */
switch (err) switch (err)
{ {
@ -863,7 +825,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case WRITEFAILED: case WRITEFAILED:
@ -873,7 +834,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPNSFOD: case FTPNSFOD:
@ -903,7 +863,7 @@ Error in server response, closing control connection.\n"));
/* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST' /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
without arguments is better than `LIST .'; confirmed by without arguments is better than `LIST .'; confirmed by
RFC959. */ RFC959. */
err = ftp_list (&con->rbuf, NULL); err = ftp_list (csock, NULL);
/* FTPRERR, WRITEFAILED */ /* FTPRERR, WRITEFAILED */
switch (err) switch (err)
{ {
@ -914,7 +874,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case WRITEFAILED: case WRITEFAILED:
@ -924,7 +883,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock); fd_close (csock);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
rbuf_uninitialize (&con->rbuf);
return err; return err;
break; break;
case FTPNSFOD: case FTPNSFOD:
@ -987,7 +945,6 @@ Error in server response, closing control connection.\n"));
{ {
logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno)); logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
fd_close (dtsock); fd_close (dtsock);
fd_close (local_sock); fd_close (local_sock);
return FOPENERR; return FOPENERR;
@ -1031,8 +988,8 @@ Error in server response, closing control connection.\n"));
} }
/* Get the contents of the document. */ /* Get the contents of the document. */
res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, res = fd_read_body (dtsock, fp, len, restval, expected_bytes, 0,
0, &con->dltime); &con->dltime);
tms = time_str (NULL); tms = time_str (NULL);
tmrate = retr_rate (*len - restval, con->dltime, 0); tmrate = retr_rate (*len - restval, con->dltime, 0);
/* Close data connection socket. */ /* Close data connection socket. */
@ -1058,7 +1015,6 @@ Error in server response, closing control connection.\n"));
logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"), logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
con->target, strerror (errno)); con->target, strerror (errno));
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return FWRITEERR; return FWRITEERR;
} }
else if (res == -1) else if (res == -1)
@ -1070,9 +1026,7 @@ Error in server response, closing control connection.\n"));
} }
/* Get the server to tell us if everything is retrieved. */ /* Get the server to tell us if everything is retrieved. */
err = ftp_response (&con->rbuf, &respline); err = ftp_response (csock, &respline);
/* ...and empty the buffer. */
rbuf_discard (&con->rbuf);
if (err != FTPOK) if (err != FTPOK)
{ {
xfree (respline); xfree (respline);
@ -1086,7 +1040,6 @@ Error in server response, closing control connection.\n"));
whole file was retrieved nevertheless (but that is for whole file was retrieved nevertheless (but that is for
ftp_loop_internal to decide). */ ftp_loop_internal to decide). */
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
return FTPRETRINT; return FTPRETRINT;
} /* err != FTPOK */ } /* err != FTPOK */
/* If retrieval failed for any reason, return FTPRETRINT, but do not /* If retrieval failed for any reason, return FTPRETRINT, but do not
@ -1115,7 +1068,6 @@ Error in server response, closing control connection.\n"));
/* I should probably send 'QUIT' and check for a reply, but this /* I should probably send 'QUIT' and check for a reply, but this
is faster. #### Is it OK, though? */ is faster. #### Is it OK, though? */
fd_close (csock); fd_close (csock);
rbuf_uninitialize (&con->rbuf);
} }
/* If it was a listing, and opt.server_response is true, /* If it was a listing, and opt.server_response is true,
print it out. */ print it out. */
@ -1192,14 +1144,14 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
{ {
con->cmd = 0; con->cmd = 0;
con->cmd |= (DO_RETR | LEAVE_PENDING); con->cmd |= (DO_RETR | LEAVE_PENDING);
if (rbuf_initialized_p (&con->rbuf)) if (con->csock != -1)
con->cmd &= ~ (DO_LOGIN | DO_CWD); con->cmd &= ~ (DO_LOGIN | DO_CWD);
else else
con->cmd |= (DO_LOGIN | DO_CWD); con->cmd |= (DO_LOGIN | DO_CWD);
} }
else /* not on your own */ else /* not on your own */
{ {
if (rbuf_initialized_p (&con->rbuf)) if (con->csock != -1)
con->cmd &= ~DO_LOGIN; con->cmd &= ~DO_LOGIN;
else else
con->cmd |= DO_LOGIN; con->cmd |= DO_LOGIN;
@ -1248,7 +1200,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
len = 0; len = 0;
err = getftp (u, &len, restval, con); err = getftp (u, &len, restval, con);
if (!rbuf_initialized_p (&con->rbuf)) if (con->csock != -1)
con->st &= ~DONE_CWD; con->st &= ~DONE_CWD;
else else
con->st |= DONE_CWD; con->st |= DONE_CWD;
@ -1294,8 +1246,8 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
if (con->st & ON_YOUR_OWN) if (con->st & ON_YOUR_OWN)
{ {
fd_close (RBUF_FD (&con->rbuf)); fd_close (con->csock);
rbuf_uninitialize (&con->rbuf); con->csock = -1;
} }
if (!opt.spider) if (!opt.spider)
logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"), logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
@ -1354,10 +1306,10 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
return RETROK; return RETROK;
} while (!opt.ntry || (count < opt.ntry)); } while (!opt.ntry || (count < opt.ntry));
if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN)) if (con->csock != -1 && (con->st & ON_YOUR_OWN))
{ {
fd_close (RBUF_FD (&con->rbuf)); fd_close (con->csock);
rbuf_uninitialize (&con->rbuf); con->csock = -1;
} }
return TRYLIMEXC; return TRYLIMEXC;
} }
@ -1448,7 +1400,7 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
con->cmd &= ~DO_CWD; con->cmd &= ~DO_CWD;
con->cmd |= (DO_RETR | LEAVE_PENDING); con->cmd |= (DO_RETR | LEAVE_PENDING);
if (!rbuf_initialized_p (&con->rbuf)) if (con->csock < 0)
con->cmd |= DO_LOGIN; con->cmd |= DO_LOGIN;
else else
con->cmd &= ~DO_LOGIN; con->cmd &= ~DO_LOGIN;
@ -1849,7 +1801,7 @@ ftp_loop (struct url *u, int *dt, struct url *proxy)
memset (&con, 0, sizeof (con)); memset (&con, 0, sizeof (con));
rbuf_uninitialize (&con.rbuf); con.csock = -1;
con.st = ON_YOUR_OWN; con.st = ON_YOUR_OWN;
con.rs = ST_UNIX; con.rs = ST_UNIX;
con.id = NULL; con.id = NULL;
@ -1916,8 +1868,8 @@ ftp_loop (struct url *u, int *dt, struct url *proxy)
if (res == RETROK) if (res == RETROK)
*dt |= RETROKF; *dt |= RETROKF;
/* If a connection was left, quench it. */ /* If a connection was left, quench it. */
if (rbuf_initialized_p (&con.rbuf)) if (con.csock != -1)
fd_close (RBUF_FD (&con.rbuf)); fd_close (con.csock);
xfree_null (con.id); xfree_null (con.id);
con.id = NULL; con.id = NULL;
xfree_null (con.target); xfree_null (con.target);

View File

@ -30,9 +30,6 @@ so, delete this exception statement from your version. */
#ifndef FTP_H #ifndef FTP_H
#define FTP_H #define FTP_H
/* Need it for struct rbuf. */
#include "rbuf.h"
#include "host.h" #include "host.h"
/* System types. */ /* System types. */
@ -46,24 +43,24 @@ enum stype
ST_OTHER ST_OTHER
}; };
uerr_t ftp_response PARAMS ((struct rbuf *, char **)); uerr_t ftp_response PARAMS ((int, char **));
uerr_t ftp_login PARAMS ((struct rbuf *, const char *, const char *)); uerr_t ftp_login PARAMS ((int, const char *, const char *));
uerr_t ftp_port PARAMS ((struct rbuf *, int *)); uerr_t ftp_port PARAMS ((int, int *));
uerr_t ftp_pasv PARAMS ((struct rbuf *, ip_address *, int *)); uerr_t ftp_pasv PARAMS ((int, ip_address *, int *));
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
uerr_t ftp_lprt PARAMS ((struct rbuf *, int *)); uerr_t ftp_lprt PARAMS ((int, int *));
uerr_t ftp_lpsv PARAMS ((struct rbuf *, ip_address *, int *)); uerr_t ftp_lpsv PARAMS ((int, ip_address *, int *));
uerr_t ftp_eprt PARAMS ((struct rbuf *, int *)); uerr_t ftp_eprt PARAMS ((int, int *));
uerr_t ftp_epsv PARAMS ((struct rbuf *, ip_address *, int *)); uerr_t ftp_epsv PARAMS ((int, ip_address *, int *));
#endif #endif
uerr_t ftp_type PARAMS ((struct rbuf *, int)); uerr_t ftp_type PARAMS ((int, int));
uerr_t ftp_cwd PARAMS ((struct rbuf *, const char *)); uerr_t ftp_cwd PARAMS ((int, const char *));
uerr_t ftp_retr PARAMS ((struct rbuf *, const char *)); uerr_t ftp_retr PARAMS ((int, const char *));
uerr_t ftp_rest PARAMS ((struct rbuf *, long)); uerr_t ftp_rest PARAMS ((int, long));
uerr_t ftp_list PARAMS ((struct rbuf *, const char *)); uerr_t ftp_list PARAMS ((int, const char *));
uerr_t ftp_syst PARAMS ((struct rbuf *, enum stype *)); uerr_t ftp_syst PARAMS ((int, enum stype *));
uerr_t ftp_pwd PARAMS ((struct rbuf *, char **)); uerr_t ftp_pwd PARAMS ((int, char **));
uerr_t ftp_size PARAMS ((struct rbuf *, const char *, long int *)); uerr_t ftp_size PARAMS ((int, const char *, long int *));
#ifdef USE_OPIE #ifdef USE_OPIE
const char *skey_response PARAMS ((int, const char *, const char *)); const char *skey_response PARAMS ((int, const char *, const char *));

View File

@ -300,6 +300,19 @@ ssl_poll (int fd, double timeout, int wait_for, void *ctx)
return select_fd (fd, timeout, wait_for); return select_fd (fd, timeout, wait_for);
} }
static int
ssl_peek (int fd, char *buf, int bufsize, void *ctx)
{
int ret;
SSL *ssl = (SSL *) ctx;
do
ret = SSL_peek (ssl, buf, bufsize);
while (ret == -1
&& SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
&& errno == EINTR);
return ret;
}
static void static void
ssl_close (int fd, void *ctx) ssl_close (int fd, void *ctx)
{ {
@ -335,9 +348,10 @@ ssl_connect (int fd)
/* Register FD with Wget's transport layer, i.e. arrange that /* Register FD with Wget's transport layer, i.e. arrange that
SSL-enabled functions are used for reading, writing, and polling. SSL-enabled functions are used for reading, writing, and polling.
That way the rest of Wget can use fd_read, fd_write, and friends That way the rest of Wget can keep using xread, xwrite, and
and not care what happens underneath. */ friends and not care what happens underneath. */
fd_register_transport (fd, ssl_read, ssl_write, ssl_poll, ssl_close, ssl); fd_register_transport (fd, ssl_read, ssl_write, ssl_poll, ssl_peek,
ssl_close, ssl);
DEBUGP (("Connected %d to SSL 0x%0lx\n", fd, (unsigned long) ssl)); DEBUGP (("Connected %d to SSL 0x%0lx\n", fd, (unsigned long) ssl));
return ssl; return ssl;

View File

@ -39,7 +39,6 @@ so, delete this exception statement from your version. */
#include "wget.h" #include "wget.h"
#include "connect.h" #include "connect.h"
#include "rbuf.h"
#include "headers.h" #include "headers.h"
/* This file contains the generic routines for work with headers. /* This file contains the generic routines for work with headers.
@ -62,74 +61,7 @@ so, delete this exception statement from your version. */
The public functions are header_get() and header_process(), which The public functions are header_get() and header_process(), which
see. */ see. */
/* Get a header from read-buffer RBUF and return it in *HDR.
As defined in RFC2068 and elsewhere, a header can be folded into
multiple lines if the continuation line begins with a space or
horizontal TAB. Also, this function will accept a header ending
with just LF instead of CRLF.
The header may be of arbitrary length; the function will allocate
as much memory as necessary for it to fit. It need not contain a
`:', thus you can use it to retrieve, say, HTTP status line.
All trailing whitespace is stripped from the header, and it is
zero-terminated. */
int
header_get (struct rbuf *rbuf, char **hdr, enum header_get_flags flags)
{
int i;
int bufsize = 80;
*hdr = (char *)xmalloc (bufsize);
for (i = 0; 1; i++)
{
int res;
/* #### Use DO_REALLOC? */
if (i > bufsize - 1)
*hdr = (char *)xrealloc (*hdr, (bufsize <<= 1));
res = RBUF_READCHAR (rbuf, *hdr + i);
if (res == 1)
{
if ((*hdr)[i] == '\n')
{
if (!((flags & HG_NO_CONTINUATIONS)
|| i == 0
|| (i == 1 && (*hdr)[0] == '\r')))
{
char next;
/* If the header is non-empty, we need to check if
it continues on to the other line. We do that by
peeking at the next character. */
res = rbuf_peek (rbuf, &next);
if (res == 0)
return HG_EOF;
else if (res == -1)
return HG_ERROR;
/* If the next character is HT or SP, just continue. */
if (next == '\t' || next == ' ')
continue;
}
/* Strip trailing whitespace. (*hdr)[i] is the newline;
decrement I until it points to the last available
whitespace. */
while (i > 0 && ISSPACE ((*hdr)[i - 1]))
--i;
(*hdr)[i] = '\0';
break;
}
}
else if (res == 0)
return HG_EOF;
else
return HG_ERROR;
}
DEBUGP (("%s\n", *hdr));
return HG_OK;
}
/* Check whether HEADER begins with NAME and, if yes, skip the `:' and /* Check whether HEADER begins with NAME and, if yes, skip the `:' and
the whitespace, and call PROCFUN with the arguments of HEADER's the whitespace, and call PROCFUN with the arguments of HEADER's
contents (after the `:' and space) and ARG. Otherwise, return 0. */ contents (after the `:' and space) and ARG. Otherwise, return 0. */

View File

@ -37,7 +37,6 @@ enum {
enum header_get_flags { HG_NONE = 0, enum header_get_flags { HG_NONE = 0,
HG_NO_CONTINUATIONS = 0x2 }; HG_NO_CONTINUATIONS = 0x2 };
int header_get PARAMS ((struct rbuf *, char **, enum header_get_flags));
int header_process PARAMS ((const char *, const char *, int header_process PARAMS ((const char *, const char *,
int (*) (const char *, void *), int (*) (const char *, void *),
void *)); void *));

View File

@ -61,7 +61,6 @@ extern int errno;
#include "utils.h" #include "utils.h"
#include "url.h" #include "url.h"
#include "host.h" #include "host.h"
#include "rbuf.h"
#include "retr.h" #include "retr.h"
#include "headers.h" #include "headers.h"
#include "connect.h" #include "connect.h"
@ -233,6 +232,24 @@ post_file (int sock, const char *file_name, long promised_size)
DEBUGP (("done]\n")); DEBUGP (("done]\n"));
return 0; return 0;
} }
static const char *
next_header (const char *h)
{
const char *end = NULL;
const char *p = h;
do
{
p = strchr (p, '\n');
if (!p)
return end;
end = ++p;
}
while (*p == ' ' || *p == '\t');
return end;
}
/* Functions to be used as arguments to header_process(): */ /* Functions to be used as arguments to header_process(): */
@ -598,19 +615,20 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
char *pragma_h, *referer, *useragent, *range, *wwwauth; char *pragma_h, *referer, *useragent, *range, *wwwauth;
char *authenticate_h; char *authenticate_h;
char *proxyauth; char *proxyauth;
char *all_headers;
char *port_maybe; char *port_maybe;
char *request_keep_alive; char *request_keep_alive;
int sock, hcount, all_length, statcode; int sock, hcount, statcode;
int write_error; int write_error;
long contlen, contrange; long contlen, contrange;
struct url *conn; struct url *conn;
FILE *fp; FILE *fp;
int auth_tried_already; int auth_tried_already;
struct rbuf rbuf;
int using_ssl = 0; int using_ssl = 0;
char *cookies = NULL; char *cookies = NULL;
char *head;
const char *hdr_beg, *hdr_end;
/* Whether this connection will be kept alive after the HTTP request /* Whether this connection will be kept alive after the HTTP request
is done. */ is done. */
int keep_alive; int keep_alive;
@ -989,70 +1007,43 @@ Accept: %s\r\n\
statcode = -1; statcode = -1;
*dt &= ~RETROKF; *dt &= ~RETROKF;
/* Before reading anything, initialize the rbuf. */
rbuf_initialize (&rbuf, sock);
all_headers = NULL;
all_length = 0;
DEBUGP (("\n---response begin---\n")); DEBUGP (("\n---response begin---\n"));
/* Header-fetching loop. */ head = fd_read_head (sock);
hcount = 0; if (!head)
while (1)
{ {
char *hdr; logputs (LOG_VERBOSE, "\n");
int status; if (errno == 0)
++hcount;
/* Get the header. */
status = header_get (&rbuf, &hdr,
/* Disallow continuations for status line. */
(hcount == 1 ? HG_NO_CONTINUATIONS : HG_NONE));
/* Check for errors. */
if (status == HG_EOF && *hdr)
{ {
/* This used to be an unconditional error, but that was logputs (LOG_NOTQUIET, _("No data received.\n"));
somewhat controversial, because of a large number of
broken CGI's that happily "forget" to send the second EOL
before closing the connection of a HEAD request.
So, the deal is to check whether the header is empty
(*hdr is zero if it is); if yes, it means that the
previous header was fully retrieved, and that -- most
probably -- the request is complete. "...be liberal in
what you accept." Oh boy. */
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("End of file while parsing headers.\n"));
xfree (hdr);
xfree_null (type);
xfree_null (all_headers);
CLOSE_INVALIDATE (sock); CLOSE_INVALIDATE (sock);
return HEOF; return HEOF;
} }
else if (status == HG_ERROR) else
{ {
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("Read error (%s) in headers.\n"), logprintf (LOG_NOTQUIET, _("Read error (%s) in headers.\n"),
strerror (errno)); strerror (errno));
xfree (hdr);
xfree_null (type);
xfree_null (all_headers);
CLOSE_INVALIDATE (sock); CLOSE_INVALIDATE (sock);
return HERR; return HERR;
} }
}
/* If the headers are to be saved to a file later, save them to /* Loop through the headers and process them. */
memory now. */
if (opt.save_headers) hcount = 0;
{ for (hdr_beg = head;
int lh = strlen (hdr); (hdr_end = next_header (hdr_beg));
all_headers = (char *)xrealloc (all_headers, all_length + lh + 2); hdr_beg = hdr_end)
memcpy (all_headers + all_length, hdr, lh); {
all_length += lh; char *hdr = strdupdelim (hdr_beg, hdr_end);
all_headers[all_length++] = '\n'; {
all_headers[all_length] = '\0'; char *tmp = hdr + strlen (hdr);
} if (tmp > hdr && tmp[-1] == '\n')
*--tmp = '\0';
if (tmp > hdr && tmp[-1] == '\r')
*--tmp = '\0';
}
++hcount;
/* Check for status line. */ /* Check for status line. */
if (hcount == 1) if (hcount == 1)
@ -1257,7 +1248,6 @@ Accept: %s\r\n\
CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there
might be more bytes in the body. */ might be more bytes in the body. */
xfree_null (type); xfree_null (type);
xfree_null (all_headers);
return NEWLOCATION; return NEWLOCATION;
} }
} }
@ -1328,7 +1318,6 @@ Accept: %s\r\n\
/* Mark as successfully retrieved. */ /* Mark as successfully retrieved. */
*dt |= RETROKF; *dt |= RETROKF;
xfree_null (type); xfree_null (type);
xfree_null (all_headers);
CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there
might be more bytes in the body. */ might be more bytes in the body. */
return RETRUNNEEDED; return RETRUNNEEDED;
@ -1343,7 +1332,6 @@ Accept: %s\r\n\
Continued download failed on this file, which conflicts with `-c'.\n\ Continued download failed on this file, which conflicts with `-c'.\n\
Refusing to truncate existing file `%s'.\n\n"), *hs->local_file); Refusing to truncate existing file `%s'.\n\n"), *hs->local_file);
xfree_null (type); xfree_null (type);
xfree_null (all_headers);
CLOSE_INVALIDATE (sock); CLOSE_INVALIDATE (sock);
return CONTNOTSUPPORTED; return CONTNOTSUPPORTED;
} }
@ -1359,7 +1347,6 @@ Refusing to truncate existing file `%s'.\n\n"), *hs->local_file);
/* This means the whole request was somehow misunderstood by the /* This means the whole request was somehow misunderstood by the
server. Bail out. */ server. Bail out. */
xfree_null (type); xfree_null (type);
xfree_null (all_headers);
CLOSE_INVALIDATE (sock); CLOSE_INVALIDATE (sock);
return RANGEERR; return RANGEERR;
} }
@ -1408,7 +1395,6 @@ Refusing to truncate existing file `%s'.\n\n"), *hs->local_file);
hs->len = 0L; hs->len = 0L;
hs->res = 0; hs->res = 0;
xfree_null (type); xfree_null (type);
xfree_null (all_headers);
CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there
might be more bytes in the body. */ might be more bytes in the body. */
return RETRFINISHED; return RETRFINISHED;
@ -1426,7 +1412,6 @@ Refusing to truncate existing file `%s'.\n\n"), *hs->local_file);
logprintf (LOG_NOTQUIET, "%s: %s\n", *hs->local_file, strerror (errno)); logprintf (LOG_NOTQUIET, "%s: %s\n", *hs->local_file, strerror (errno));
CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there
might be more bytes in the body. */ might be more bytes in the body. */
xfree_null (all_headers);
return FOPENERR; return FOPENERR;
} }
} }
@ -1466,12 +1451,12 @@ Refusing to truncate existing file `%s'.\n\n"), *hs->local_file);
/* #### This confuses the code that checks for file size. There /* #### This confuses the code that checks for file size. There
should be some overhead information. */ should be some overhead information. */
if (opt.save_headers) if (opt.save_headers)
fwrite (all_headers, 1, all_length, fp); fwrite (head, 1, strlen (head), fp);
/* Get the contents of the document. */ /* Get the contents of the document. */
hs->res = get_contents (sock, fp, &hs->len, hs->restval, hs->res = fd_read_body (sock, fp, &hs->len, hs->restval,
(contlen != -1 ? contlen : 0), (contlen != -1 ? contlen : 0),
&rbuf, keep_alive, &hs->dltime); keep_alive, &hs->dltime);
if (hs->res >= 0) if (hs->res >= 0)
CLOSE_FINISH (sock); CLOSE_FINISH (sock);
@ -1490,7 +1475,6 @@ Refusing to truncate existing file `%s'.\n\n"), *hs->local_file);
if (flush_res == EOF) if (flush_res == EOF)
hs->res = -2; hs->res = -2;
} }
xfree_null (all_headers);
if (hs->res == -2) if (hs->res == -2)
return FWRITEERR; return FWRITEERR;
return RETRFINISHED; return RETRFINISHED;

View File

@ -1,127 +0,0 @@
/* Buffering read.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Wget; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
In addition, as a special exception, the Free Software Foundation
gives permission to link the code of its release of Wget with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables. You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL". If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version. */
/* This is a simple implementation of buffering IO-read functions. */
#include <config.h>
#include <stdio.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
#include "wget.h"
#include "rbuf.h"
#include "connect.h"
void
rbuf_initialize (struct rbuf *rbuf, int fd)
{
rbuf->fd = fd;
rbuf->buffer_pos = rbuf->buffer;
rbuf->buffer_left = 0;
}
int
rbuf_initialized_p (struct rbuf *rbuf)
{
return rbuf->fd != -1;
}
void
rbuf_uninitialize (struct rbuf *rbuf)
{
rbuf->fd = -1;
}
int
rbuf_read_bufferful (struct rbuf *rbuf)
{
return fd_read (rbuf->fd, rbuf->buffer, sizeof (rbuf->buffer), -1);
}
/* Currently unused -- see RBUF_READCHAR. */
#if 0
/* Function version of RBUF_READCHAR. */
int
rbuf_readchar (struct rbuf *rbuf, char *store)
{
return RBUF_READCHAR (rbuf, store);
}
#endif
/* Like rbuf_readchar(), only don't move the buffer position. */
int
rbuf_peek (struct rbuf *rbuf, char *store)
{
if (!rbuf->buffer_left)
{
int res;
rbuf->buffer_pos = rbuf->buffer;
rbuf->buffer_left = 0;
res = fd_read (rbuf->fd, rbuf->buffer, sizeof (rbuf->buffer), -1);
if (res <= 0)
return res;
rbuf->buffer_left = res;
}
*store = *rbuf->buffer_pos;
return 1;
}
#define MIN(p,q) (((p) <= (q)) ? (p) : (q))
/* Flush RBUF's buffer to WHERE. Flush MAXSIZE bytes at most.
Returns the number of bytes actually copied. If the buffer is
empty, 0 is returned. */
int
rbuf_flush (struct rbuf *rbuf, char *where, int maxsize)
{
if (!rbuf->buffer_left)
return 0;
else
{
int howmuch = MIN (rbuf->buffer_left, maxsize);
if (where)
memcpy (where, rbuf->buffer_pos, howmuch);
rbuf->buffer_left -= howmuch;
rbuf->buffer_pos += howmuch;
return howmuch;
}
}
/* Discard any cached data in RBUF. */
void
rbuf_discard (struct rbuf *rbuf)
{
rbuf->buffer_left = 0;
rbuf->buffer_pos = rbuf->buffer;
}

View File

@ -1,83 +0,0 @@
/* Declarations for rbuf.c.
Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Wget; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
In addition, as a special exception, the Free Software Foundation
gives permission to link the code of its release of Wget with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables. You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL". If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version. */
#ifndef RBUF_H
#define RBUF_H
/* Retrieval stream */
struct rbuf
{
int fd;
char buffer[4096]; /* the input buffer */
char *buffer_pos; /* current position in the buffer */
size_t buffer_left; /* number of bytes left in the buffer:
buffer_left = buffer_end - buffer_pos */
int internal_dont_touch_this; /* used by RBUF_READCHAR macro */
};
/* Read a character from RBUF. If there is anything in the buffer,
the character is returned from the buffer. Otherwise, refill the
buffer and return the first character.
The return value is the same as with read(2). On buffered read,
the function returns 1.
#### That return value is totally screwed up, and is a direct
result of historical implementation of header code. The macro
should return the character or EOF, and in case of error store it
to rbuf->err or something. */
#define RBUF_READCHAR(rbuf, store) \
((rbuf)->buffer_left \
? (--(rbuf)->buffer_left, \
*((char *) (store)) = *(rbuf)->buffer_pos++, 1) \
: ((rbuf)->buffer_pos = (rbuf)->buffer, \
((((rbuf)->internal_dont_touch_this \
= rbuf_read_bufferful (rbuf)) <= 0) \
? (rbuf)->internal_dont_touch_this \
: ((rbuf)->buffer_left = (rbuf)->internal_dont_touch_this - 1, \
*((char *) (store)) = *(rbuf)->buffer_pos++, \
1))))
/* Return the file descriptor of RBUF. */
#define RBUF_FD(rbuf) ((rbuf)->fd)
/* Function declarations */
void rbuf_initialize PARAMS ((struct rbuf *, int));
int rbuf_initialized_p PARAMS ((struct rbuf *));
void rbuf_uninitialize PARAMS ((struct rbuf *));
int rbuf_readchar PARAMS ((struct rbuf *, char *));
int rbuf_peek PARAMS ((struct rbuf *, char *));
int rbuf_flush PARAMS ((struct rbuf *, char *, int));
void rbuf_discard PARAMS ((struct rbuf *));
/* Internal, but used by the macro. */
int rbuf_read_bufferful PARAMS ((struct rbuf *));
#endif /* RBUF_H */

View File

@ -133,9 +133,7 @@ limit_bandwidth (long bytes, struct wget_timer *timer)
/* Reads the contents of file descriptor FD, until it is closed, or a /* Reads the contents of file descriptor FD, until it is closed, or a
read error occurs. The data is read in 8K chunks, and stored to read error occurs. The data is read in 8K chunks, and stored to
stream fp, which should have been open for writing. If BUF is stream fp, which should have been open for writing.
non-NULL and its file descriptor is equal to FD, flush RBUF first.
This function will *not* use the rbuf_* functions!
The EXPECTED argument is passed to show_progress() unchanged, but The EXPECTED argument is passed to show_progress() unchanged, but
otherwise ignored. otherwise ignored.
@ -147,14 +145,11 @@ limit_bandwidth (long bytes, struct wget_timer *timer)
The function exits and returns codes of 0, -1 and -2 if the The function exits and returns codes of 0, -1 and -2 if the
connection was closed, there was a read error, or if it could not connection was closed, there was a read error, or if it could not
write to the output stream, respectively. write to the output stream, respectively. */
IMPORTANT: The function flushes the contents of the buffer in
rbuf_flush() before actually reading from fd. If you wish to read
from fd immediately, flush or discard the buffer. */
int int
get_contents (int fd, FILE *fp, long *len, long restval, long expected, fd_read_body (int fd, FILE *out, long *len, long restval, long expected,
struct rbuf *rbuf, int use_expected, double *elapsed) int use_expected, double *elapsed)
{ {
int res = 0; int res = 0;
@ -181,26 +176,6 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
progress_interactive = progress_interactive_p (progress); progress_interactive = progress_interactive_p (progress);
} }
if (rbuf && RBUF_FD (rbuf) == fd)
{
int sz = 0;
while ((res = rbuf_flush (rbuf, dlbuf, sizeof (dlbuf))) != 0)
{
fwrite (dlbuf, 1, res, fp);
*len += res;
sz += res;
}
if (sz)
fflush (fp);
if (ferror (fp))
{
res = -2;
goto out;
}
if (progress)
progress_update (progress, sz, 0);
}
if (opt.limit_rate) if (opt.limit_rate)
limit_bandwidth_reset (); limit_bandwidth_reset ();
wtimer_reset (timer); wtimer_reset (timer);
@ -253,14 +228,14 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
wtimer_update (timer); wtimer_update (timer);
if (res > 0) if (res > 0)
{ {
fwrite (dlbuf, 1, res, fp); fwrite (dlbuf, 1, res, out);
/* Always flush the contents of the network packet. This /* Always flush the contents of the network packet. This
should not hinder performance: fast downloads will be should not hinder performance: fast downloads will be
received in 16K chunks (which stdio would write out received in 16K chunks (which stdio would write out
anyway), and slow downloads won't be limited by disk anyway), and slow downloads won't be limited by disk
performance. */ performance. */
fflush (fp); fflush (out);
if (ferror (fp)) if (ferror (out))
{ {
res = -2; res = -2;
goto out; goto out;
@ -292,6 +267,157 @@ get_contents (int fd, FILE *fp, long *len, long restval, long expected,
return res; return res;
} }
typedef const char *(*finder_t) PARAMS ((const char *, int, int));
/* Driver for fd_read_line and fd_read_head: keeps reading data until
a terminator (as decided by FINDER) occurs in the data. The trick
is that the data is first peeked at, and only then actually read.
That way the data after the terminator is never read. */
static char *
fd_read_until (int fd, finder_t finder, int bufsize)
{
int size = bufsize, tail = 0;
char *buf = xmalloc (size);
while (1)
{
const char *end;
int pklen, rdlen, remain;
/* First, peek at the available data. */
pklen = fd_peek (fd, buf + tail, size - tail, -1);
if (pklen < 0)
{
xfree (buf);
return NULL;
}
end = finder (buf, tail, pklen);
if (end)
{
/* The data contains the terminator: we'll read the data up
to the end of the terminator. */
remain = end - (buf + tail);
/* Note +1 for trailing \0. */
if (size < tail + remain + 1)
{
size = tail + remain + 1;
buf = xrealloc (buf, size);
}
}
else
/* No terminator: simply read the data we know is (or should
be) available. */
remain = pklen;
/* Now, read the data. Note that we make no assumptions about
how much data we'll get. (Some TCP stacks are notorious for
read returning less data than the previous MSG_PEEK.) */
rdlen = fd_read (fd, buf + tail, remain, 0);
if (rdlen < 0)
{
xfree_null (buf);
return NULL;
}
if (rdlen == 0)
{
if (tail == 0)
{
/* EOF without anything having been read */
xfree (buf);
errno = 0;
return NULL;
}
/* Return what we received so far. */
if (size < tail + 1)
{
size = tail + 1; /* expand the buffer to receive the
terminating \0 */
buf = xrealloc (buf, size);
}
buf[tail] = '\0';
return buf;
}
tail += rdlen;
if (end && rdlen == remain)
{
/* The end was seen and the data read -- we got what we came
for. */
buf[tail] = '\0';
return buf;
}
/* Keep looping until all the data arrives. */
if (tail == size)
{
size <<= 1;
buf = xrealloc (buf, size);
}
}
}
static const char *
line_terminator (const char *buf, int tail, int peeklen)
{
const char *p = memchr (buf + tail, '\n', peeklen);
if (p)
/* p+1 because we want the line to include '\n' */
return p + 1;
return NULL;
}
/* Read one line from FD and return it. The line is allocated using
malloc.
If an error occurs, or if no data can be read, NULL is returned.
In the former case errno indicates the error condition, and in the
latter case, errno is NULL. */
char *
fd_read_line (int fd)
{
return fd_read_until (fd, line_terminator, 128);
}
static const char *
head_terminator (const char *buf, int tail, int peeklen)
{
const char *start, *end;
if (tail < 4)
start = buf;
else
start = buf + tail - 4;
end = buf + tail + peeklen;
for (; start < end - 1; start++)
if (*start == '\n')
{
if (start < end - 2
&& start[1] == '\r'
&& start[2] == '\n')
return start + 3;
if (start[1] == '\n')
return start + 2;
}
return NULL;
}
/* Read the request head from FD and return it. The chunk of data is
allocated using malloc.
If an error occurs, or if no data can be read, NULL is returned.
In the former case errno indicates the error condition, and in the
latter case, errno is NULL. */
char *
fd_read_head (int fd)
{
return fd_read_until (fd, head_terminator, 512);
}
/* Return a printed representation of the download rate, as /* Return a printed representation of the download rate, as
appropriate for the speed. If PAD is non-zero, strings will be appropriate for the speed. If PAD is non-zero, strings will be
padded to the width of 7 characters (xxxx.xx). */ padded to the width of 7 characters (xxxx.xx). */

View File

@ -30,10 +30,10 @@ so, delete this exception statement from your version. */
#ifndef RETR_H #ifndef RETR_H
#define RETR_H #define RETR_H
#include "rbuf.h" char *fd_read_line PARAMS ((int));
char *fd_read_head PARAMS ((int));
int get_contents PARAMS ((int, FILE *, long *, long, long, struct rbuf *, int fd_read_body PARAMS ((int, FILE *, long *, long, long, int, double *));
int, double *));
uerr_t retrieve_url PARAMS ((const char *, char **, char **, uerr_t retrieve_url PARAMS ((const char *, char **, char **,
const char *, int *)); const char *, int *));

View File

@ -67,13 +67,13 @@ SRC = cmpt.c safe-ctype.c convert.c connect.c host.c http.c netrc.c \
ftp-basic.c ftp.c ftp-ls.c ftp-opie.c getopt.c hash.c headers.c \ ftp-basic.c ftp.c ftp-ls.c ftp-opie.c getopt.c hash.c headers.c \
html-parse.c html-url.c progress.c retr.c recur.c res.c url.c cookies.c \ html-parse.c html-url.c progress.c retr.c recur.c res.c url.c cookies.c \
init.c utils.c main.c version.c xmalloc.c mswindows.c \ init.c utils.c main.c version.c xmalloc.c mswindows.c \
gen-md5.c gnu-md5.c rbuf.c log.c $(SSLSRC) gen-md5.c gnu-md5.c log.c $(SSLSRC)
OBJ = cmpt$o safe-ctype$o convert$o connect$o host$o http$o netrc$o \ OBJ = cmpt$o safe-ctype$o convert$o connect$o host$o http$o netrc$o \
ftp-basic$o ftp$o ftp-ls$o ftp-opie$o getopt$o hash$o headers$o \ ftp-basic$o ftp$o ftp-ls$o ftp-opie$o getopt$o hash$o headers$o \
html-parse$o html-url$o progress$o retr$o recur$o res$o url$o cookies$o \ html-parse$o html-url$o progress$o retr$o recur$o res$o url$o cookies$o \
init$o utils$o main$o version$o xmalloc$o mswindows$o \ init$o utils$o main$o version$o xmalloc$o mswindows$o \
gen-md5$o gnu-md5$o rbuf$o log$o $(SSLOBJ) gen-md5$o gnu-md5$o log$o $(SSLOBJ)
.SUFFIXES: .c .obj .SUFFIXES: .c .obj

View File

@ -10,7 +10,7 @@ CFLAGS=-DWINDOWS -DHAVE_CONFIG_H -I. -w- -O2
## variables ## variables
OBJS=cmpt.obj connect.obj convert.obj ftp.obj ftp-basic.obj \ OBJS=cmpt.obj connect.obj convert.obj ftp.obj ftp-basic.obj \
ftp-ls.obj ftp-opie.obj getopt.obj headers.obj host.obj html-parse.obj html-url.obj \ ftp-ls.obj ftp-opie.obj getopt.obj headers.obj host.obj html-parse.obj html-url.obj \
http.obj init.obj log.obj main.obj gnu-md5.obj netrc.obj rbuf.obj \ http.obj init.obj log.obj main.obj gnu-md5.obj netrc.obj \
safe-ctype.obj hash.obj progress.obj gen-md5.obj cookies.obj \ safe-ctype.obj hash.obj progress.obj gen-md5.obj cookies.obj \
recur.obj res.obj retr.obj url.obj utils.obj version.obj xmalloc.obj \ recur.obj res.obj retr.obj url.obj utils.obj version.obj xmalloc.obj \
mswindows.obj mswindows.obj
@ -44,7 +44,6 @@ main.obj+
mswindows.obj+ mswindows.obj+
netrc.obj+ netrc.obj+
progress.obj+ progress.obj+
rbuf.obj+
recur.obj+ recur.obj+
res.obj+ res.obj+
retr.obj+ retr.obj+

View File

@ -23,7 +23,7 @@ LIBS= -lwsock32
OBJ_EXT=.o OBJ_EXT=.o
OBJS=cmpt${OBJ_EXT} convert${OBJ_EXT} connect${OBJ_EXT} ftp${OBJ_EXT} ftp-basic${OBJ_EXT} \ OBJS=cmpt${OBJ_EXT} convert${OBJ_EXT} connect${OBJ_EXT} ftp${OBJ_EXT} ftp-basic${OBJ_EXT} \
ftp-ls${OBJ_EXT} ftp-opie${OBJ_EXT} getopt${OBJ_EXT} headers${OBJ_EXT} host${OBJ_EXT} html-parse${OBJ_EXT} html-url${OBJ_EXT} \ ftp-ls${OBJ_EXT} ftp-opie${OBJ_EXT} getopt${OBJ_EXT} headers${OBJ_EXT} host${OBJ_EXT} html-parse${OBJ_EXT} html-url${OBJ_EXT} \
http${OBJ_EXT} init${OBJ_EXT} log${OBJ_EXT} main${OBJ_EXT} gnu-md5${OBJ_EXT} netrc${OBJ_EXT} rbuf${OBJ_EXT} \ http${OBJ_EXT} init${OBJ_EXT} log${OBJ_EXT} main${OBJ_EXT} gnu-md5${OBJ_EXT} netrc${OBJ_EXT} \
safe-ctype${OBJ_EXT} hash${OBJ_EXT} progress${OBJ_EXT} gen-md5${OBJ_EXT} cookies${OBJ_EXT} \ safe-ctype${OBJ_EXT} hash${OBJ_EXT} progress${OBJ_EXT} gen-md5${OBJ_EXT} cookies${OBJ_EXT} \
recur${OBJ_EXT} res${OBJ_EXT} retr${OBJ_EXT} url${OBJ_EXT} utils${OBJ_EXT} \ recur${OBJ_EXT} res${OBJ_EXT} retr${OBJ_EXT} url${OBJ_EXT} utils${OBJ_EXT} \
version${OBJ_EXT} xmalloc${OBJ_EXT} mswindows${OBJ_EXT} version${OBJ_EXT} xmalloc${OBJ_EXT} mswindows${OBJ_EXT}

View File

@ -53,7 +53,7 @@ CFLAGS+= /os /d2
OBJS = cmpt.obj convert.obj connect.obj cookies.obj ftp.obj ftp-basic.obj & OBJS = cmpt.obj convert.obj connect.obj cookies.obj ftp.obj ftp-basic.obj &
ftp-ls.obj ftp-opie.obj getopt.obj hash.obj headers.obj host.obj html-parse.obj html-url.obj & ftp-ls.obj ftp-opie.obj getopt.obj hash.obj headers.obj host.obj html-parse.obj html-url.obj &
http.obj init.obj log.obj main.obj gen-md5.obj gnu-md5.obj netrc.obj progress.obj rbuf.obj & http.obj init.obj log.obj main.obj gen-md5.obj gnu-md5.obj netrc.obj progress.obj &
recur.obj res.obj retr.obj safe-ctype.obj url.obj utils.obj version.obj mswindows.obj recur.obj res.obj retr.obj safe-ctype.obj url.obj utils.obj version.obj mswindows.obj
LIBFILES = LIBFILES =

View File

@ -4,29 +4,28 @@ cmpt$o: cmpt.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h
connect$o: connect.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h connect.h host.h connect$o: connect.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h connect.h host.h
convert$o: convert.c config.h wget.h convert.h url.h recur.h utils.h hash.h convert$o: convert.c config.h wget.h convert.h url.h recur.h utils.h hash.h
cookies$o: cookies.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h cookies.h hash.h url.h utils.h cookies$o: cookies.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h cookies.h hash.h url.h utils.h
ftp-basic$o: ftp-basic.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h rbuf.h connect.h host.h ftp.h ftp-basic$o: ftp-basic.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h connect.h host.h ftp.h
ftp-ls$o: ftp-ls.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h ftp.h url.h ftp-ls$o: ftp-ls.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h ftp.h url.h
ftp-opie$o: ftp-opie.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h gen-md5.h ftp-opie$o: ftp-opie.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h gen-md5.h
ftp$o: ftp.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h rbuf.h retr.h ftp.h connect.h host.h netrc.h ftp$o: ftp.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h retr.h ftp.h connect.h host.h netrc.h
gen-md5$o: gen-md5.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h gen-md5.h gen-md5$o: gen-md5.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h gen-md5.h
gen_sslfunc$o: gen_sslfunc.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h connect.h host.h url.h gen_sslfunc$o: gen_sslfunc.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h connect.h host.h url.h
getopt$o: getopt.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h getopt.h getopt$o: getopt.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h getopt.h
gnu-md5$o: gnu-md5.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h gnu-md5.h gnu-md5$o: gnu-md5.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h gnu-md5.h
hash$o: hash.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h hash.h hash$o: hash.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h hash.h
headers$o: headers.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h connect.h host.h rbuf.h headers.h headers$o: headers.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h connect.h host.h headers.h
host$o: host.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h host.h url.h hash.h host$o: host.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h host.h url.h hash.h
html-parse$o: html-parse.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h html-parse.h html-parse$o: html-parse.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h html-parse.h
html-url$o: html-url.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h html-parse.h url.h utils.h html-url$o: html-url.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h html-parse.h url.h utils.h
http$o: http.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h host.h rbuf.h retr.h headers.h connect.h netrc.h gen-md5.h http$o: http.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h host.h retr.h headers.h connect.h netrc.h gen-md5.h
init$o: init.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h init.h host.h recur.h netrc.h cookies.h progress.h init$o: init.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h init.h host.h recur.h netrc.h cookies.h progress.h
log$o: log.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h log$o: log.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h
main$o: main.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h getopt.h init.h retr.h rbuf.h recur.h host.h gen_sslfunc.h getopt.h main$o: main.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h getopt.h init.h retr.h recur.h host.h gen_sslfunc.h getopt.h
mswindows$o: mswindows.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h mswindows$o: mswindows.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h
netrc$o: netrc.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h netrc.h init.h netrc$o: netrc.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h netrc.h init.h
progress$o: progress.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h retr.h rbuf.h progress$o: progress.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h retr.h
rbuf$o: rbuf.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h rbuf.h connect.h host.h recur$o: recur.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h url.h recur.h utils.h retr.h ftp.h host.h hash.h
recur$o: recur.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h url.h recur.h utils.h retr.h rbuf.h ftp.h host.h hash.h retr$o: retr.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h retr.h url.h recur.h ftp.h host.h connect.h hash.h
retr$o: retr.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h retr.h rbuf.h url.h recur.h ftp.h host.h connect.h hash.h
safe-ctype$o: safe-ctype.c config.h safe-ctype.h safe-ctype$o: safe-ctype.c config.h safe-ctype.h
snprintf$o: snprintf.c config.h safe-ctype.h snprintf$o: snprintf.c config.h safe-ctype.h
url$o: url.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h host.h hash.h url$o: url.c config.h wget.h sysdep.h mswindows.h options.h safe-ctype.h utils.h url.h host.h hash.h