From 779043f7a3847cc9a502487e3df93f601b9adaeb Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 3 Dec 2001 13:48:59 +0000 Subject: [PATCH] As Eric Lavigne pointed out, the ftp response reader MUST cache data that is not dealt with when we find an end-of-response line, as there might be important stuff even after the correct line. So on subsequent invokes, the cached data must be used! --- lib/ftp.c | 71 +++++++++++++++++++++++++++++++++++++++------------ lib/urldata.h | 3 +++ 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/lib/ftp.c b/lib/ftp.c index c84c056a5..7091e9f8e 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -197,6 +197,8 @@ int Curl_GetFTPResponse(char *buf, #define SELECT_TIMEOUT 2 int error = SELECT_OK; + struct FTP *ftp = conn->proto.ftp; + if (ftpcode) *ftpcode = 0; /* 0 for errors */ @@ -229,23 +231,41 @@ int Curl_GetFTPResponse(char *buf, interval.tv_sec = timeout; interval.tv_usec = 0; - 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"); - break; - case 0: /* timeout */ - error = SELECT_TIMEOUT; - failf(data, "Transfer aborted due to timeout"); - break; - default: + if(!ftp->cache) + 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"); + break; + case 0: /* timeout */ + error = SELECT_TIMEOUT; + failf(data, "Transfer aborted due to timeout"); + break; + default: + error = SELECT_OK; + break; + } + if(SELECT_OK == error) { /* * 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 * that this is still ok and then remove this comment! */ - if(CURLE_OK != Curl_read(conn, sockfd, ptr, BUFSIZE-nread, &gotbytes)) + if(ftp->cache) { + /* we had data in the "cache", copy that instead of doing an actual + read */ + memcpy(ptr, ftp->cache, ftp->cache_size); + gotbytes = ftp->cache_size; + free(ftp->cache); /* free the cache */ + ftp->cache = NULL; /* clear the pointer */ + ftp->cache_size = 0; /* zero the size just in case */ + } + else if(CURLE_OK != Curl_read(conn, sockfd, ptr, + BUFSIZE-nread, &gotbytes)) keepon = FALSE; + + if(!keepon) + ; else if(gotbytes <= 0) { keepon = FALSE; error = SELECT_ERROR; @@ -279,20 +299,35 @@ int Curl_GetFTPResponse(char *buf, * line to the start of the buffer and zero terminate, * for old times sake (and krb4)! */ char *meow; - int i; - for(meow=line_start, i=0; meowcache_size = gotbytes - i; + ftp->cache = (char *)malloc(ftp->cache_size); + if(ftp->cache) + memcpy(ftp->cache, line_start, ftp->cache_size); + else + return CURLE_OUT_OF_MEMORY; /**BANG**/ + } + } /* there was data */ + } /* if(no error) */ } /* while there's buffer left and loop is requested */ if(!error) @@ -2028,6 +2063,8 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn) if(ftp) { if(ftp->entrypath) free(ftp->entrypath); + if(ftp->cache) + free(ftp->cache); } return CURLE_OK; } diff --git a/lib/urldata.h b/lib/urldata.h index 8f12e8705..3a7509dcd 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -175,6 +175,9 @@ struct FTP { char *file; /* decoded file */ char *entrypath; /* the PWD reply when we logged on */ + + char *cache; /* data cache between getresponse()-calls */ + size_t cache_size; /* size of cache in bytes */ }; /****************************************************************************