If only a partial file was transfered, we consider that a fatal problem so
we won't try to QUIT the control connection and risk "hanging" waiting for a response. Test case 161 verifies this. The quit-sending function was also made static.
This commit is contained in:
49
lib/ftp.c
49
lib/ftp.c
@@ -117,6 +117,7 @@ static CURLcode ftp_sendquote(struct connectdata *conn,
|
|||||||
static CURLcode ftp_cwd(struct connectdata *conn, char *path);
|
static CURLcode ftp_cwd(struct connectdata *conn, char *path);
|
||||||
static CURLcode ftp_mkd(struct connectdata *conn, char *path);
|
static CURLcode ftp_mkd(struct connectdata *conn, char *path);
|
||||||
static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path);
|
static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path);
|
||||||
|
static CURLcode ftp_quit(struct connectdata *conn);
|
||||||
|
|
||||||
/* easy-to-use macro: */
|
/* easy-to-use macro: */
|
||||||
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return result
|
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z))) return result
|
||||||
@@ -604,22 +605,22 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
|
|||||||
infof(data, "We have successfully logged in\n");
|
infof(data, "We have successfully logged in\n");
|
||||||
if (conn->ssl[FIRSTSOCKET].use) {
|
if (conn->ssl[FIRSTSOCKET].use) {
|
||||||
#ifdef HAVE_KRB4
|
#ifdef HAVE_KRB4
|
||||||
/* we are logged in (with Kerberos)
|
/* We are logged in with Kerberos, now set the requested protection
|
||||||
* now set the requested protection level
|
* level
|
||||||
*/
|
*/
|
||||||
if(conn->sec_complete)
|
if(conn->sec_complete)
|
||||||
Curl_sec_set_protection_level(conn);
|
Curl_sec_set_protection_level(conn);
|
||||||
|
|
||||||
/* we may need to issue a KAUTH here to have access to the files
|
/* We may need to issue a KAUTH here to have access to the files
|
||||||
* do it if user supplied a password
|
* do it if user supplied a password
|
||||||
*/
|
*/
|
||||||
if(conn->passwd && *conn->passwd) {
|
if(conn->passwd && *conn->passwd) {
|
||||||
result = Curl_krb_kauth(conn);
|
result = Curl_krb_kauth(conn);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
failf(data, "Odd return code after USER");
|
failf(data, "Odd return code after USER");
|
||||||
@@ -743,10 +744,13 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
|
|||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int ftpcode;
|
int ftpcode;
|
||||||
CURLcode result=CURLE_OK;
|
CURLcode result=CURLE_OK;
|
||||||
|
bool was_ctl_valid = ftp->ctl_valid;
|
||||||
|
|
||||||
/* free the dir tree and file parts */
|
/* free the dir tree and file parts */
|
||||||
freedirs(ftp);
|
freedirs(ftp);
|
||||||
|
|
||||||
|
ftp->ctl_valid = FALSE;
|
||||||
|
|
||||||
if(data->set.upload) {
|
if(data->set.upload) {
|
||||||
if((-1 != data->set.infilesize) &&
|
if((-1 != data->set.infilesize) &&
|
||||||
(data->set.infilesize != *ftp->bytecountp) &&
|
(data->set.infilesize != *ftp->bytecountp) &&
|
||||||
@@ -779,6 +783,8 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
|
|||||||
result = CURLE_FTP_COULDNT_RETR_FILE;
|
result = CURLE_FTP_COULDNT_RETR_FILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftp->ctl_valid = was_ctl_valid;
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#ifdef HAVE_KRB4
|
||||||
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
|
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
|
||||||
@@ -2312,7 +2318,7 @@ CURLcode ftp_perform(struct connectdata *conn,
|
|||||||
* The input argument is already checked for validity.
|
* The input argument is already checked for validity.
|
||||||
*
|
*
|
||||||
* ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
|
* ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
|
||||||
* end of the function.
|
* Curl_ftp_done() function without finding any major problem.
|
||||||
*/
|
*/
|
||||||
CURLcode Curl_ftp(struct connectdata *conn)
|
CURLcode Curl_ftp(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
@@ -2419,7 +2425,8 @@ CURLcode Curl_ftp(struct connectdata *conn)
|
|||||||
else
|
else
|
||||||
freedirs(ftp);
|
freedirs(ftp);
|
||||||
|
|
||||||
ftp->ctl_valid = TRUE;
|
ftp->ctl_valid = TRUE; /* seems good */
|
||||||
|
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2474,7 +2481,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
|||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
* Curl_ftp_quit()
|
* ftp_quit()
|
||||||
*
|
*
|
||||||
* This should be called before calling sclose() on an ftp control connection
|
* This should be called before calling sclose() on an ftp control connection
|
||||||
* (not data connections). We should then wait for the response from the
|
* (not data connections). We should then wait for the response from the
|
||||||
@@ -2482,7 +2489,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
|||||||
* connection.
|
* connection.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CURLcode Curl_ftp_quit(struct connectdata *conn)
|
static CURLcode ftp_quit(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int ftpcode;
|
int ftpcode;
|
||||||
@@ -2512,13 +2519,13 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn)
|
|||||||
bad in any way, sending quit and waiting around here will make the
|
bad in any way, sending quit and waiting around here will make the
|
||||||
disconnect wait in vain and cause more problems than we need to.
|
disconnect wait in vain and cause more problems than we need to.
|
||||||
|
|
||||||
Curl_ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
|
ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
|
||||||
will try to send the QUIT command, otherwise it will just return.
|
will try to send the QUIT command, otherwise it will just return.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* The FTP session may or may not have been allocated/setup at this point! */
|
/* The FTP session may or may not have been allocated/setup at this point! */
|
||||||
if(ftp) {
|
if(ftp) {
|
||||||
(void)Curl_ftp_quit(conn); /* ignore errors on the QUIT */
|
(void)ftp_quit(conn); /* ignore errors on the QUIT */
|
||||||
|
|
||||||
if(ftp->entrypath)
|
if(ftp->entrypath)
|
||||||
free(ftp->entrypath);
|
free(ftp->entrypath);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ test80 test81 test82 test83 test84 test85 test86 test87 test507 \
|
|||||||
test149 test88 test89 test90 test508 test91 test92 test203 test93 \
|
test149 test88 test89 test90 test508 test91 test92 test203 test93 \
|
||||||
test94 test95 test509 test510 test97 test98 test99 test150 test151 \
|
test94 test95 test509 test510 test97 test98 test99 test150 test151 \
|
||||||
test152 test153 test154 test155 test156 test157 test158 test159 test511 \
|
test152 test153 test154 test155 test156 test157 test158 test159 test511 \
|
||||||
test160
|
test160 test161
|
||||||
|
|
||||||
# The following tests have been removed from the dist since they no longer
|
# The following tests have been removed from the dist since they no longer
|
||||||
# work. We need to fix the test suite's FTPS server first, then bring them
|
# work. We need to fix the test suite's FTPS server first, then bring them
|
||||||
|
|||||||
39
tests/data/test161
Normal file
39
tests/data/test161
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
1oooooooooooooooooooooooooooooooooooooooooo2
|
||||||
|
</data>
|
||||||
|
<size>
|
||||||
|
10928
|
||||||
|
</size>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
ftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
FTP RETR PASV
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
ftp://%HOSTIP:%FTPPORT/161
|
||||||
|
</command>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
USER anonymous
|
||||||
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
|
EPSV
|
||||||
|
TYPE I
|
||||||
|
SIZE 161
|
||||||
|
RETR 161
|
||||||
|
</protocol>
|
||||||
|
<errorcode>
|
||||||
|
18
|
||||||
|
</errrorcode>
|
||||||
|
</verify>
|
||||||
@@ -258,6 +258,11 @@ while(<FILE>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# GETNAME url.c:1901 getnameinfo()
|
||||||
|
elsif($_ =~ /^GETNAME ([^ ]*):(\d*) (.*)/) {
|
||||||
|
# not much to do
|
||||||
|
}
|
||||||
|
|
||||||
# ADDR url.c:1282 getaddrinfo() = 0x5ddd
|
# ADDR url.c:1282 getaddrinfo() = 0x5ddd
|
||||||
elsif($_ =~ /^ADDR ([^ ]*):(\d*) (.*)/) {
|
elsif($_ =~ /^ADDR ([^ ]*):(\d*) (.*)/) {
|
||||||
# generic match for the filename+linenumber
|
# generic match for the filename+linenumber
|
||||||
|
|||||||
Reference in New Issue
Block a user