diff options
Diffstat (limited to 'libs/libcurl/src/ftp.c')
-rw-r--r-- | libs/libcurl/src/ftp.c | 250 |
1 files changed, 131 insertions, 119 deletions
diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c index 11031da6fb..bc35574217 100644 --- a/libs/libcurl/src/ftp.c +++ b/libs/libcurl/src/ftp.c @@ -9,7 +9,7 @@ * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms - * are also available at https://curl.haxx.se/docs/copyright.html. + * are also available at https://curl.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is @@ -901,7 +901,6 @@ typedef enum { static CURLcode ftp_state_use_port(struct connectdata *conn, ftpport fcmd) /* start with this */ - { CURLcode result = CURLE_OK; struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -1337,7 +1336,7 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn) static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.protop; + struct FTP *ftp = conn->data->req.p.ftp; struct Curl_easy *data = conn->data; if(ftp->transfer != FTPTRANSFER_BODY) { @@ -1380,7 +1379,7 @@ static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) static CURLcode ftp_state_rest(struct connectdata *conn) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.protop; + struct FTP *ftp = conn->data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { @@ -1401,7 +1400,7 @@ static CURLcode ftp_state_rest(struct connectdata *conn) static CURLcode ftp_state_size(struct connectdata *conn) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.protop; + struct FTP *ftp = conn->data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { @@ -1422,7 +1421,7 @@ static CURLcode ftp_state_list(struct connectdata *conn) { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; + struct FTP *ftp = data->req.p.ftp; /* If this output is to be machine-parsed, the NLST command might be better to use, since the LIST command output is not specified or standard in any @@ -1498,7 +1497,7 @@ static CURLcode ftp_state_stor_prequote(struct connectdata *conn) static CURLcode ftp_state_type(struct connectdata *conn) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.protop; + struct FTP *ftp = conn->data->req.p.ftp; struct Curl_easy *data = conn->data; struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -1556,7 +1555,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, bool sizechecked) { CURLcode result = CURLE_OK; - struct FTP *ftp = conn->data->req.protop; + struct FTP *ftp = conn->data->req.p.ftp; struct Curl_easy *data = conn->data; struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -1656,7 +1655,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn, { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; bool quote = FALSE; struct curl_slist *item; @@ -1941,6 +1940,17 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, #endif { /* normal, direct, ftp connection */ + DEBUGASSERT(ftpc->newhost); + + /* postponed address resolution in case of tcp fastopen */ + if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) { + Curl_conninfo_remote(conn, conn->sock[FIRSTSOCKET]); + Curl_safefree(ftpc->newhost); + ftpc->newhost = strdup(control_address(conn)); + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + } + rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr); if(rc == CURLRESOLV_PENDING) /* BLOCKING */ @@ -2031,7 +2041,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; switch(ftpcode) { @@ -2164,7 +2174,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn, { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if(data->set.max_filesize && (filesize > data->set.max_filesize)) { @@ -2382,7 +2392,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn, { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; + struct FTP *ftp = data->req.p.ftp; if((ftpcode == 150) || (ftpcode == 125)) { @@ -3133,7 +3143,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, bool premature) { struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; ssize_t nread; @@ -3498,7 +3508,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) bool complete = FALSE; /* the ftp struct is inited in ftp_connect() */ - struct FTP *ftp = data->req.protop; + struct FTP *ftp = data->req.p.ftp; /* if the second connection isn't done yet, wait for it */ if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { @@ -3663,7 +3673,7 @@ CURLcode ftp_perform(struct connectdata *conn, if(conn->data->set.opt_no_body) { /* requested no body means no transfer... */ - struct FTP *ftp = conn->data->req.protop; + struct FTP *ftp = conn->data->req.p.ftp; ftp->transfer = FTPTRANSFER_INFO; } @@ -3698,7 +3708,7 @@ static void wc_data_dtor(void *ptr) static CURLcode init_wc_data(struct connectdata *conn) { char *last_slash; - struct FTP *ftp = conn->data->req.protop; + struct FTP *ftp = conn->data->req.p.ftp; char *path = ftp->path; struct WildcardData *wildcard = &(conn->data->wildcard); CURLcode result = CURLE_OK; @@ -3790,129 +3800,131 @@ static CURLcode init_wc_data(struct connectdata *conn) return result; } -/* This is called recursively */ static CURLcode wc_statemach(struct connectdata *conn) { struct WildcardData * const wildcard = &(conn->data->wildcard); CURLcode result = CURLE_OK; - switch(wildcard->state) { - case CURLWC_INIT: - result = init_wc_data(conn); - if(wildcard->state == CURLWC_CLEAN) - /* only listing! */ - break; - wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; - break; + for(;;) { + switch(wildcard->state) { + case CURLWC_INIT: + result = init_wc_data(conn); + if(wildcard->state == CURLWC_CLEAN) + /* only listing! */ + return result; + wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; + return result; - case CURLWC_MATCHING: { - /* In this state is LIST response successfully parsed, so lets restore - previous WRITEFUNCTION callback and WRITEDATA pointer */ - struct ftp_wc *ftpwc = wildcard->protdata; - conn->data->set.fwrite_func = ftpwc->backup.write_function; - conn->data->set.out = ftpwc->backup.file_descriptor; - ftpwc->backup.write_function = ZERO_NULL; - ftpwc->backup.file_descriptor = NULL; - wildcard->state = CURLWC_DOWNLOADING; - - if(Curl_ftp_parselist_geterror(ftpwc->parser)) { - /* error found in LIST parsing */ - wildcard->state = CURLWC_CLEAN; - return wc_statemach(conn); - } - if(wildcard->filelist.size == 0) { - /* no corresponding file */ - wildcard->state = CURLWC_CLEAN; - return CURLE_REMOTE_FILE_NOT_FOUND; + case CURLWC_MATCHING: { + /* In this state is LIST response successfully parsed, so lets restore + previous WRITEFUNCTION callback and WRITEDATA pointer */ + struct ftp_wc *ftpwc = wildcard->protdata; + conn->data->set.fwrite_func = ftpwc->backup.write_function; + conn->data->set.out = ftpwc->backup.file_descriptor; + ftpwc->backup.write_function = ZERO_NULL; + ftpwc->backup.file_descriptor = NULL; + wildcard->state = CURLWC_DOWNLOADING; + + if(Curl_ftp_parselist_geterror(ftpwc->parser)) { + /* error found in LIST parsing */ + wildcard->state = CURLWC_CLEAN; + continue; + } + if(wildcard->filelist.size == 0) { + /* no corresponding file */ + wildcard->state = CURLWC_CLEAN; + return CURLE_REMOTE_FILE_NOT_FOUND; + } + continue; } - return wc_statemach(conn); - } - case CURLWC_DOWNLOADING: { - /* filelist has at least one file, lets get first one */ - struct ftp_conn *ftpc = &conn->proto.ftpc; - struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; - struct FTP *ftp = conn->data->req.protop; + case CURLWC_DOWNLOADING: { + /* filelist has at least one file, lets get first one */ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; + struct FTP *ftp = conn->data->req.p.ftp; - char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); - if(!tmp_path) - return CURLE_OUT_OF_MEMORY; + char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); + if(!tmp_path) + return CURLE_OUT_OF_MEMORY; - /* switch default ftp->path and tmp_path */ - free(ftp->pathalloc); - ftp->pathalloc = ftp->path = tmp_path; - - infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); - if(conn->data->set.chunk_bgn) { - long userresponse; - Curl_set_in_callback(conn->data, true); - userresponse = conn->data->set.chunk_bgn( - finfo, wildcard->customptr, (int)wildcard->filelist.size); - Curl_set_in_callback(conn->data, false); - switch(userresponse) { - case CURL_CHUNK_BGN_FUNC_SKIP: - infof(conn->data, "Wildcard - \"%s\" skipped by user\n", - finfo->filename); - wildcard->state = CURLWC_SKIP; - return wc_statemach(conn); - case CURL_CHUNK_BGN_FUNC_FAIL: - return CURLE_CHUNK_FAILED; + /* switch default ftp->path and tmp_path */ + free(ftp->pathalloc); + ftp->pathalloc = ftp->path = tmp_path; + + infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); + if(conn->data->set.chunk_bgn) { + long userresponse; + Curl_set_in_callback(conn->data, true); + userresponse = conn->data->set.chunk_bgn( + finfo, wildcard->customptr, (int)wildcard->filelist.size); + Curl_set_in_callback(conn->data, false); + switch(userresponse) { + case CURL_CHUNK_BGN_FUNC_SKIP: + infof(conn->data, "Wildcard - \"%s\" skipped by user\n", + finfo->filename); + wildcard->state = CURLWC_SKIP; + continue; + case CURL_CHUNK_BGN_FUNC_FAIL: + return CURLE_CHUNK_FAILED; + } } - } - if(finfo->filetype != CURLFILETYPE_FILE) { - wildcard->state = CURLWC_SKIP; - return wc_statemach(conn); - } + if(finfo->filetype != CURLFILETYPE_FILE) { + wildcard->state = CURLWC_SKIP; + continue; + } - if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) - ftpc->known_filesize = finfo->size; + if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) + ftpc->known_filesize = finfo->size; - result = ftp_parse_url_path(conn); - if(result) - return result; + result = ftp_parse_url_path(conn); + if(result) + return result; - /* we don't need the Curl_fileinfo of first file anymore */ - Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + /* we don't need the Curl_fileinfo of first file anymore */ + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); - if(wildcard->filelist.size == 0) { /* remains only one file to down. */ - wildcard->state = CURLWC_CLEAN; - /* after that will be ftp_do called once again and no transfer - will be done because of CURLWC_CLEAN state */ - return CURLE_OK; + if(wildcard->filelist.size == 0) { /* remains only one file to down. */ + wildcard->state = CURLWC_CLEAN; + /* after that will be ftp_do called once again and no transfer + will be done because of CURLWC_CLEAN state */ + return CURLE_OK; + } + return result; } - } break; - case CURLWC_SKIP: { - if(conn->data->set.chunk_end) { - Curl_set_in_callback(conn->data, true); - conn->data->set.chunk_end(conn->data->wildcard.customptr); - Curl_set_in_callback(conn->data, false); + case CURLWC_SKIP: { + if(conn->data->set.chunk_end) { + Curl_set_in_callback(conn->data, true); + conn->data->set.chunk_end(conn->data->wildcard.customptr); + Curl_set_in_callback(conn->data, false); + } + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + wildcard->state = (wildcard->filelist.size == 0) ? + CURLWC_CLEAN : CURLWC_DOWNLOADING; + continue; } - Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); - wildcard->state = (wildcard->filelist.size == 0) ? - CURLWC_CLEAN : CURLWC_DOWNLOADING; - return wc_statemach(conn); - } - case CURLWC_CLEAN: { - struct ftp_wc *ftpwc = wildcard->protdata; - result = CURLE_OK; - if(ftpwc) - result = Curl_ftp_parselist_geterror(ftpwc->parser); + case CURLWC_CLEAN: { + struct ftp_wc *ftpwc = wildcard->protdata; + result = CURLE_OK; + if(ftpwc) + result = Curl_ftp_parselist_geterror(ftpwc->parser); - wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; - } break; + wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; + return result; + } - case CURLWC_DONE: - case CURLWC_ERROR: - case CURLWC_CLEAR: - if(wildcard->dtor) - wildcard->dtor(wildcard->protdata); - break; + case CURLWC_DONE: + case CURLWC_ERROR: + case CURLWC_CLEAR: + if(wildcard->dtor) + wildcard->dtor(wildcard->protdata); + return result; + } } - - return result; + /* UNREACHABLE */ } /*********************************************************************** @@ -4039,7 +4051,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) { struct Curl_easy *data = conn->data; /* the ftp struct is already inited in ftp_connect() */ - struct FTP *ftp = data->req.protop; + struct FTP *ftp = data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; const char *slashPos = NULL; const char *fileName = NULL; @@ -4184,7 +4196,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) static CURLcode ftp_dophase_done(struct connectdata *conn, bool connected) { - struct FTP *ftp = conn->data->req.protop; + struct FTP *ftp = conn->data->req.p.ftp; struct ftp_conn *ftpc = &conn->proto.ftpc; if(connected) { @@ -4281,7 +4293,7 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) char *type; struct FTP *ftp; - conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1); + conn->data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1); if(NULL == ftp) return CURLE_OUT_OF_MEMORY; |