Implement restart.
Use sizeof more consistently. Outline sanity checking of server port spec.
This commit is contained in:
parent
5ff28c822b
commit
32425dafcd
@ -62,6 +62,7 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -86,6 +87,7 @@
|
|||||||
#define FTP_FILE_ACTION_OK 250
|
#define FTP_FILE_ACTION_OK 250
|
||||||
#define FTP_NEED_PASSWORD 331
|
#define FTP_NEED_PASSWORD 331
|
||||||
#define FTP_NEED_ACCOUNT 332
|
#define FTP_NEED_ACCOUNT 332
|
||||||
|
#define FTP_FILE_OK 350
|
||||||
#define FTP_SYNTAX_ERROR 500
|
#define FTP_SYNTAX_ERROR 500
|
||||||
|
|
||||||
static char ENDL[2] = "\r\n";
|
static char ENDL[2] = "\r\n";
|
||||||
@ -160,7 +162,7 @@ _ftp_cmd(int cd, char *fmt, ...)
|
|||||||
iov[0].iov_base = msg;
|
iov[0].iov_base = msg;
|
||||||
iov[0].iov_len = strlen(msg);
|
iov[0].iov_len = strlen(msg);
|
||||||
iov[1].iov_base = ENDL;
|
iov[1].iov_base = ENDL;
|
||||||
iov[1].iov_len = sizeof(ENDL);
|
iov[1].iov_len = sizeof ENDL;
|
||||||
r = writev(cd, iov, 2);
|
r = writev(cd, iov, 2);
|
||||||
free(msg);
|
free(msg);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
@ -175,7 +177,8 @@ _ftp_cmd(int cd, char *fmt, ...)
|
|||||||
* Transfer file
|
* Transfer file
|
||||||
*/
|
*/
|
||||||
static FILE *
|
static FILE *
|
||||||
_ftp_transfer(int cd, char *oper, char *file, char *mode, char *flags)
|
_ftp_transfer(int cd, char *oper, char *file,
|
||||||
|
char *mode, off_t offset, char *flags)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int pasv, high, verbose;
|
int pasv, high, verbose;
|
||||||
@ -242,8 +245,13 @@ _ftp_transfer(int cd, char *oper, char *file, char *mode, char *flags)
|
|||||||
addr[i] = strtol(p, &p, 10);
|
addr[i] = strtol(p, &p, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* seek to required offset */
|
||||||
|
if (offset)
|
||||||
|
if (_ftp_cmd(cd, "REST %lu", (u_long)offset) != FTP_FILE_OK)
|
||||||
|
goto sysouch;
|
||||||
|
|
||||||
/* construct sockaddr for data socket */
|
/* construct sockaddr for data socket */
|
||||||
l = sizeof(sin);
|
l = sizeof sin;
|
||||||
if (getpeername(cd, (struct sockaddr *)&sin, &l) == -1)
|
if (getpeername(cd, (struct sockaddr *)&sin, &l) == -1)
|
||||||
goto sysouch;
|
goto sysouch;
|
||||||
bcopy(addr, (char *)&sin.sin_addr, 4);
|
bcopy(addr, (char *)&sin.sin_addr, 4);
|
||||||
@ -252,7 +260,7 @@ _ftp_transfer(int cd, char *oper, char *file, char *mode, char *flags)
|
|||||||
/* connect to data port */
|
/* connect to data port */
|
||||||
if (verbose)
|
if (verbose)
|
||||||
_fetch_info("opening data connection");
|
_fetch_info("opening data connection");
|
||||||
if (connect(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
|
if (connect(sd, (struct sockaddr *)&sin, sizeof sin) == -1)
|
||||||
goto sysouch;
|
goto sysouch;
|
||||||
|
|
||||||
/* make the server initiate the transfer */
|
/* make the server initiate the transfer */
|
||||||
@ -268,13 +276,13 @@ _ftp_transfer(int cd, char *oper, char *file, char *mode, char *flags)
|
|||||||
int arg, d;
|
int arg, d;
|
||||||
|
|
||||||
/* find our own address, bind, and listen */
|
/* find our own address, bind, and listen */
|
||||||
l = sizeof(sin);
|
l = sizeof sin;
|
||||||
if (getsockname(cd, (struct sockaddr *)&sin, &l) == -1)
|
if (getsockname(cd, (struct sockaddr *)&sin, &l) == -1)
|
||||||
goto sysouch;
|
goto sysouch;
|
||||||
sin.sin_port = 0;
|
sin.sin_port = 0;
|
||||||
arg = high ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
|
arg = high ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
|
||||||
if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
|
if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
|
||||||
(char *)&arg, sizeof(arg)) == -1)
|
(char *)&arg, sizeof arg) == -1)
|
||||||
goto sysouch;
|
goto sysouch;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
_fetch_info("binding data socket");
|
_fetch_info("binding data socket");
|
||||||
@ -331,7 +339,7 @@ ouch:
|
|||||||
static int
|
static int
|
||||||
_ftp_connect(char *host, int port, char *user, char *pwd, char *flags)
|
_ftp_connect(char *host, int port, char *user, char *pwd, char *flags)
|
||||||
{
|
{
|
||||||
int cd, e, pp = FTP_DEFAULT_PORT, direct, verbose;
|
int cd, e, pp = 0, direct, verbose;
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
|
|
||||||
direct = (flags && strchr(flags, 'd'));
|
direct = (flags && strchr(flags, 'd'));
|
||||||
@ -340,8 +348,21 @@ _ftp_connect(char *host, int port, char *user, char *pwd, char *flags)
|
|||||||
/* check for proxy */
|
/* check for proxy */
|
||||||
if (!direct && (p = getenv("FTP_PROXY")) != NULL) {
|
if (!direct && (p = getenv("FTP_PROXY")) != NULL) {
|
||||||
if ((q = strchr(p, ':')) != NULL) {
|
if ((q = strchr(p, ':')) != NULL) {
|
||||||
/* XXX check that it's a valid number */
|
if (strspn(q+1, "0123456789") != strlen(q+1) || strlen(q+1) > 5) {
|
||||||
|
/* XXX we should emit some kind of warning */
|
||||||
|
}
|
||||||
pp = atoi(q+1);
|
pp = atoi(q+1);
|
||||||
|
if (pp < 1 || pp > 65535) {
|
||||||
|
/* XXX we should emit some kind of warning */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pp) {
|
||||||
|
struct servent *se;
|
||||||
|
|
||||||
|
if ((se = getservbyname("ftp", "tcp")) != NULL)
|
||||||
|
pp = ntohs(se->s_port);
|
||||||
|
else
|
||||||
|
pp = FTP_DEFAULT_PORT;
|
||||||
}
|
}
|
||||||
if (q)
|
if (q)
|
||||||
*q = 0;
|
*q = 0;
|
||||||
@ -437,8 +458,14 @@ _ftp_cached_connect(struct url *url, char *flags)
|
|||||||
cd = -1;
|
cd = -1;
|
||||||
|
|
||||||
/* set default port */
|
/* set default port */
|
||||||
if (!url->port)
|
if (!url->port) {
|
||||||
url->port = FTP_DEFAULT_PORT;
|
struct servent *se;
|
||||||
|
|
||||||
|
if ((se = getservbyname("ftp", "tcp")) != NULL)
|
||||||
|
url->port = ntohs(se->s_port);
|
||||||
|
else
|
||||||
|
url->port = FTP_DEFAULT_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
/* try to use previously cached connection */
|
/* try to use previously cached connection */
|
||||||
if (_ftp_isconnected(url)) {
|
if (_ftp_isconnected(url)) {
|
||||||
@ -455,7 +482,7 @@ _ftp_cached_connect(struct url *url, char *flags)
|
|||||||
if (cached_socket)
|
if (cached_socket)
|
||||||
_ftp_disconnect(cached_socket);
|
_ftp_disconnect(cached_socket);
|
||||||
cached_socket = cd;
|
cached_socket = cd;
|
||||||
memcpy(&cached_host, url, sizeof(struct url));
|
memcpy(&cached_host, url, sizeof *url);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cd;
|
return cd;
|
||||||
@ -474,7 +501,7 @@ fetchGetFTP(struct url *url, char *flags)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* initiate the transfer */
|
/* initiate the transfer */
|
||||||
return _ftp_transfer(cd, "RETR", url->doc, "r", flags);
|
return _ftp_transfer(cd, "RETR", url->doc, "r", url->offset, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -491,7 +518,7 @@ fetchPutFTP(struct url *url, char *flags)
|
|||||||
|
|
||||||
/* initiate the transfer */
|
/* initiate the transfer */
|
||||||
return _ftp_transfer(cd, (flags && strchr(flags, 'a')) ? "APPE" : "STOR",
|
return _ftp_transfer(cd, (flags && strchr(flags, 'a')) ? "APPE" : "STOR",
|
||||||
url->doc, "w", flags);
|
url->doc, "w", url->offset, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user