summaryrefslogtreecommitdiff
path: root/lib/ftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ftp.c')
-rw-r--r--lib/ftp.c177
1 files changed, 87 insertions, 90 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index 4f08a5348..07ae21044 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -173,9 +173,9 @@ static CURLcode AllowServerConnect(struct SessionHandle *data,
* response and extract the relevant return code for the invoking function.
*/
-int Curl_GetFTPResponse(char *buf,
- struct connectdata *conn,
- int *ftpcode)
+CURLcode Curl_GetFTPResponse(int *nreadp, /* return number of bytes read */
+ struct connectdata *conn,
+ int *ftpcode) /* return the ftp-code */
{
/* Brand new implementation.
* We cannot read just one byte per read() and then go back to select()
@@ -190,23 +190,17 @@ int Curl_GetFTPResponse(char *buf,
bool keepon=TRUE;
ssize_t gotbytes;
char *ptr;
- int timeout = 3600; /* default timeout in seconds */
+ int timeout; /* timeout in seconds */
struct timeval interval;
fd_set rkeepfd;
fd_set readfd;
struct SessionHandle *data = conn->data;
char *line_start;
- int code=0; /* default "error code" to return */
-
-#define SELECT_OK 0
-#define SELECT_ERROR 1 /* select() problems */
-#define SELECT_TIMEOUT 2 /* took too long */
-#define SELECT_MEMORY 3 /* no available memory */
-#define SELECT_CALLBACK 4 /* aborted by callback */
-
- int error = SELECT_OK;
-
+ int code=0; /* default ftp "error code" to return */
+ char *buf = data->state.buffer;
+ CURLcode result = CURLE_OK;
struct FTP *ftp = conn->proto.ftp;
+ struct timeval now = Curl_tvnow();
if (ftpcode)
*ftpcode = 0; /* 0 for errors */
@@ -225,16 +219,21 @@ int Curl_GetFTPResponse(char *buf,
perline=0;
keepon=TRUE;
- while((nread<BUFSIZE) && (keepon && !error)) {
+ while((nread<BUFSIZE) && (keepon && !result)) {
/* check and reset timeout value every lap */
- if(data->set.timeout) {
+ if(data->set.timeout)
/* if timeout is requested, find out how much remaining time we have */
timeout = data->set.timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
- if(timeout <=0 ) {
- failf(data, "Transfer aborted due to timeout");
- return -SELECT_TIMEOUT; /* already too little time */
- }
+ else
+ /* Even without a requested timeout, we only wait response_time
+ seconds for the full response to arrive before we bail out */
+ timeout = ftp->response_time -
+ Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */
+
+ if(timeout <=0 ) {
+ failf(data, "Transfer aborted due to timeout");
+ return CURLE_OPERATION_TIMEDOUT; /* already too little time */
}
if(!ftp->cache) {
@@ -244,19 +243,18 @@ int Curl_GetFTPResponse(char *buf,
switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) {
case -1: /* select() error, stop reading */
- error = SELECT_ERROR;
- failf(data, "Transfer aborted due to select() error");
+ result = CURLE_RECV_ERROR;
+ failf(data, "Transfer aborted due to select() error: %d", errno);
break;
case 0: /* timeout */
- error = SELECT_TIMEOUT;
+ result = CURLE_OPERATION_TIMEDOUT;
failf(data, "Transfer aborted due to timeout");
break;
default:
- error = SELECT_OK;
break;
}
}
- if(SELECT_OK == error) {
+ if(CURLE_OK == result) {
/*
* This code previously didn't use the kerberos sec_read() code
* to read, but when we use Curl_read() it may do so. Do confirm
@@ -272,8 +270,7 @@ int Curl_GetFTPResponse(char *buf,
ftp->cache_size = 0; /* zero the size just in case */
}
else {
- int res = Curl_read(conn, sockfd, ptr,
- BUFSIZE-nread, &gotbytes);
+ int res = Curl_read(conn, sockfd, ptr, BUFSIZE-nread, &gotbytes);
if(res < 0)
/* EWOULDBLOCK */
continue; /* go looping again */
@@ -286,7 +283,7 @@ int Curl_GetFTPResponse(char *buf,
;
else if(gotbytes <= 0) {
keepon = FALSE;
- error = SELECT_ERROR;
+ result = CURLE_RECV_ERROR;
failf(data, "Connection aborted");
}
else {
@@ -315,7 +312,7 @@ int Curl_GetFTPResponse(char *buf,
result = Curl_client_write(data, CLIENTWRITE_HEADER,
line_start, perline);
if(result)
- return -SELECT_CALLBACK;
+ return result;
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
isdigit((int)line[2]) && (' ' == line[3]))
@@ -350,13 +347,13 @@ int Curl_GetFTPResponse(char *buf,
if(ftp->cache)
memcpy(ftp->cache, line_start, ftp->cache_size);
else
- return -SELECT_MEMORY; /**BANG**/
+ return CURLE_OUT_OF_MEMORY; /**BANG**/
}
} /* there was data */
} /* if(no error) */
} /* while there's buffer left and loop is requested */
- if(!error)
+ if(!result)
code = atoi(buf);
#ifdef KRB4
@@ -378,13 +375,11 @@ int Curl_GetFTPResponse(char *buf,
}
#endif
- if(error)
- return -error;
-
if(ftpcode)
*ftpcode=code; /* return the initial number like this */
- return nread; /* total amount of bytes read */
+ *nreadp = nread; /* total amount of bytes read */
+ return result;
}
/*
@@ -418,6 +413,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
ftp->user = data->state.user;
ftp->passwd = data->state.passwd;
+ ftp->response_time = 3600; /* default response time-out */
+
if (data->set.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
@@ -436,9 +433,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* The first thing we do is wait for the "220*" line: */
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode != 220) {
failf(data, "This doesn't seem like a nice ftp-server response");
@@ -467,9 +464,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
FTPSENDF(conn, "USER %s", ftp->user);
/* wait for feedback */
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode == 530) {
/* 530 User ... access denied
@@ -481,9 +478,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* 331 Password required for ...
(the server requires to send the user's password too) */
FTPSENDF(conn, "PASS %s", ftp->passwd);
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode == 530) {
/* 530 Login incorrect.
@@ -516,8 +513,11 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* we may need to issue a KAUTH here to have access to the files
* do it if user supplied a password
*/
- if(data->state.passwd && *data->state.passwd)
- Curl_krb_kauth(conn);
+ if(data->state.passwd && *data->state.passwd) {
+ result = Curl_krb_kauth(conn);
+ if(result)
+ return result;
+ }
#endif
}
else {
@@ -529,9 +529,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
FTPSENDF(conn, "PWD", NULL);
/* wait for feedback */
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode == 257) {
char *dir = (char *)malloc(nread+1);
@@ -596,7 +596,6 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
struct SessionHandle *data = conn->data;
struct FTP *ftp = conn->proto.ftp;
ssize_t nread;
- char *buf = data->state.buffer; /* this is our buffer */
int ftpcode;
CURLcode result=CURLE_OK;
@@ -637,9 +636,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
if(!ftp->no_transfer) {
/* now let's see what the server says about the transfer we just
performed: */
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(!ftp->dont_check) {
/* 226 Transfer complete, 250 Requested file action okay, completed. */
@@ -682,9 +681,9 @@ CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
if (item->data) {
FTPSENDF(conn, "%s", item->data);
- nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode);
- if (nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if (result)
+ return result;
if (ftpcode >= 400) {
failf(conn->data, "QUOT string not accepted: %s", item->data);
@@ -713,9 +712,9 @@ CURLcode ftp_cwd(struct connectdata *conn, char *path)
CURLcode result;
FTPSENDF(conn, "CWD %s", path);
- nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode);
- if (nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if (result)
+ return result;
if (ftpcode != 250) {
failf(conn->data, "Couldn't cd to %s", path);
@@ -743,9 +742,9 @@ CURLcode ftp_getfiletime(struct connectdata *conn, char *file)
again a grey area as the MDTM is not kosher RFC959 */
FTPSENDF(conn, "MDTM %s", file);
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode == 213) {
/* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
@@ -780,14 +779,13 @@ static CURLcode ftp_transfertype(struct connectdata *conn,
struct SessionHandle *data = conn->data;
int ftpcode;
ssize_t nread;
- char *buf=data->state.buffer;
CURLcode result;
FTPSENDF(conn, "TYPE %s", ascii?"A":"I");
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode != 200) {
failf(data, "Couldn't set %s mode",
@@ -816,9 +814,9 @@ CURLcode ftp_getsize(struct connectdata *conn, char *file,
CURLcode result;
FTPSENDF(conn, "SIZE %s", file);
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode == 213) {
/* get the size from the ascii string: */
@@ -977,7 +975,6 @@ CURLcode ftp_use_port(struct connectdata *conn)
struct SessionHandle *data=conn->data;
int portsock=-1;
ssize_t nread;
- char *buf = data->state.buffer; /* this is our buffer */
int ftpcode; /* receive FTP response codes in this */
CURLcode result;
@@ -1157,9 +1154,9 @@ CURLcode ftp_use_port(struct connectdata *conn)
return result;
}
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if (ftpcode != 200) {
failf(data, "Server does not grok %s", *modep);
@@ -1303,9 +1300,9 @@ CURLcode ftp_use_port(struct connectdata *conn)
return result;
}
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode != 200) {
failf(data, "Server does not grok PORT, try without it!");
@@ -1377,9 +1374,9 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
result = Curl_ftpsendf(conn, "%s", mode[modeoff]);
if(result)
return result;
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if (ftpcode == results[modeoff])
break;
}
@@ -1524,7 +1521,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
ssize_t nread;
int ftpcode; /* for ftp status */
- /* the ftp struct is already inited in ftp_connect() */
+ /* the ftp struct is already inited in Curl_ftp_connect() */
struct FTP *ftp = conn->proto.ftp;
long *bytecountp = ftp->bytecountp;
@@ -1625,9 +1622,9 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
FTPSENDF(conn, "STOR %s", ftp->file);
}
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode>=400) {
failf(data, "Failed FTP upload:%s", buf+3);
@@ -1801,9 +1798,9 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
FTPSENDF(conn, "REST %d", conn->resume_from);
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if(ftpcode != 350) {
failf(data, "Couldn't use REST: %s", buf+4);
@@ -1814,9 +1811,9 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
FTPSENDF(conn, "RETR %s", ftp->file);
}
- nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
- if(nread < 0)
- return CURLE_OPERATION_TIMEOUTED;
+ result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ if(result)
+ return result;
if((ftpcode == 150) || (ftpcode == 125)) {
@@ -1921,7 +1918,7 @@ CURLcode ftp_perform(struct connectdata *conn,
struct SessionHandle *data=conn->data;
char *buf = data->state.buffer; /* this is our buffer */
- /* the ftp struct is already inited in ftp_connect() */
+ /* the ftp struct is already inited in Curl_ftp_connect() */
struct FTP *ftp = conn->proto.ftp;
/* Send any QUOTE strings? */