summaryrefslogtreecommitdiffstats
path: root/lib/libfetch/ftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libfetch/ftp.c')
-rw-r--r--lib/libfetch/ftp.c55
1 files changed, 41 insertions, 14 deletions
diff --git a/lib/libfetch/ftp.c b/lib/libfetch/ftp.c
index 0f45bfa..3426f8c 100644
--- a/lib/libfetch/ftp.c
+++ b/lib/libfetch/ftp.c
@@ -62,6 +62,7 @@
#include <ctype.h>
#include <errno.h>
+#include <netdb.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -86,6 +87,7 @@
#define FTP_FILE_ACTION_OK 250
#define FTP_NEED_PASSWORD 331
#define FTP_NEED_ACCOUNT 332
+#define FTP_FILE_OK 350
#define FTP_SYNTAX_ERROR 500
static char ENDL[2] = "\r\n";
@@ -160,7 +162,7 @@ _ftp_cmd(int cd, char *fmt, ...)
iov[0].iov_base = msg;
iov[0].iov_len = strlen(msg);
iov[1].iov_base = ENDL;
- iov[1].iov_len = sizeof(ENDL);
+ iov[1].iov_len = sizeof ENDL;
r = writev(cd, iov, 2);
free(msg);
if (r == -1) {
@@ -175,7 +177,8 @@ _ftp_cmd(int cd, char *fmt, ...)
* Transfer 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;
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);
}
+ /* 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 */
- l = sizeof(sin);
+ l = sizeof sin;
if (getpeername(cd, (struct sockaddr *)&sin, &l) == -1)
goto sysouch;
bcopy(addr, (char *)&sin.sin_addr, 4);
@@ -252,9 +260,9 @@ _ftp_transfer(int cd, char *oper, char *file, char *mode, char *flags)
/* connect to data port */
if (verbose)
_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;
-
+
/* make the server initiate the transfer */
if (verbose)
_fetch_info("initiating transfer");
@@ -268,13 +276,13 @@ _ftp_transfer(int cd, char *oper, char *file, char *mode, char *flags)
int arg, d;
/* find our own address, bind, and listen */
- l = sizeof(sin);
+ l = sizeof sin;
if (getsockname(cd, (struct sockaddr *)&sin, &l) == -1)
goto sysouch;
sin.sin_port = 0;
arg = high ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
- (char *)&arg, sizeof(arg)) == -1)
+ (char *)&arg, sizeof arg) == -1)
goto sysouch;
if (verbose)
_fetch_info("binding data socket");
@@ -331,7 +339,7 @@ ouch:
static int
_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;
direct = (flags && strchr(flags, 'd'));
@@ -340,8 +348,21 @@ _ftp_connect(char *host, int port, char *user, char *pwd, char *flags)
/* check for proxy */
if (!direct && (p = getenv("FTP_PROXY")) != 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);
+ 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)
*q = 0;
@@ -437,8 +458,14 @@ _ftp_cached_connect(struct url *url, char *flags)
cd = -1;
/* set default port */
- if (!url->port)
- url->port = FTP_DEFAULT_PORT;
+ if (!url->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 */
if (_ftp_isconnected(url)) {
@@ -455,7 +482,7 @@ _ftp_cached_connect(struct url *url, char *flags)
if (cached_socket)
_ftp_disconnect(cached_socket);
cached_socket = cd;
- memcpy(&cached_host, url, sizeof(struct url));
+ memcpy(&cached_host, url, sizeof *url);
}
return cd;
@@ -474,7 +501,7 @@ fetchGetFTP(struct url *url, char *flags)
return NULL;
/* 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 */
return _ftp_transfer(cd, (flags && strchr(flags, 'a')) ? "APPE" : "STOR",
- url->doc, "w", flags);
+ url->doc, "w", url->offset, flags);
}
/*
OpenPOWER on IntegriCloud