ftp: allocate the wildcard struct on demand

The feature is rarely used so this frees up data for the vast majority
of easy handles that don't use it.

Rename "protdata" to "ftpwc" since it is always an FTP wildcard struct
pointer. Made the state struct field an unsigned char to save space.

Closes #10639
This commit is contained in:
Daniel Stenberg 2023-02-27 23:57:23 +01:00
parent c84c0f9aa3
commit 9c188e771c
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
7 changed files with 33 additions and 24 deletions

View File

@ -3761,7 +3761,7 @@ static CURLcode init_wc_data(struct Curl_easy *data)
char *last_slash;
struct FTP *ftp = data->req.p.ftp;
char *path = ftp->path;
struct WildcardData *wildcard = &(data->wildcard);
struct WildcardData *wildcard = data->wildcard;
CURLcode result = CURLE_OK;
struct ftp_wc *ftpwc = NULL;
@ -3809,7 +3809,7 @@ static CURLcode init_wc_data(struct Curl_easy *data)
goto fail;
}
wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
wildcard->ftpwc = ftpwc; /* put it to the WildcardData tmp pointer */
wildcard->dtor = wc_data_dtor;
/* wildcard does not support NOCWD option (assert it?) */
@ -3847,13 +3847,13 @@ static CURLcode init_wc_data(struct Curl_easy *data)
}
Curl_safefree(wildcard->pattern);
wildcard->dtor = ZERO_NULL;
wildcard->protdata = NULL;
wildcard->ftpwc = NULL;
return result;
}
static CURLcode wc_statemach(struct Curl_easy *data)
{
struct WildcardData * const wildcard = &(data->wildcard);
struct WildcardData * const wildcard = data->wildcard;
struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
@ -3870,7 +3870,7 @@ static CURLcode wc_statemach(struct Curl_easy *data)
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;
struct ftp_wc *ftpwc = wildcard->ftpwc;
data->set.fwrite_func = ftpwc->backup.write_function;
data->set.out = ftpwc->backup.file_descriptor;
ftpwc->backup.write_function = ZERO_NULL;
@ -3959,7 +3959,7 @@ static CURLcode wc_statemach(struct Curl_easy *data)
}
case CURLWC_CLEAN: {
struct ftp_wc *ftpwc = wildcard->protdata;
struct ftp_wc *ftpwc = wildcard->ftpwc;
result = CURLE_OK;
if(ftpwc)
result = Curl_ftp_parselist_geterror(ftpwc->parser);
@ -3972,7 +3972,7 @@ static CURLcode wc_statemach(struct Curl_easy *data)
case CURLWC_ERROR:
case CURLWC_CLEAR:
if(wildcard->dtor)
wildcard->dtor(wildcard->protdata);
wildcard->dtor(wildcard->ftpwc);
return result;
}
}
@ -3999,8 +3999,8 @@ static CURLcode ftp_do(struct Curl_easy *data, bool *done)
if(data->state.wildcardmatch) {
result = wc_statemach(data);
if(data->wildcard.state == CURLWC_SKIP ||
data->wildcard.state == CURLWC_DONE) {
if(data->wildcard->state == CURLWC_SKIP ||
data->wildcard->state == CURLWC_DONE) {
/* do not call ftp_regular_transfer */
return CURLE_OK;
}

View File

@ -274,8 +274,8 @@ static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
struct fileinfo *infop)
{
curl_fnmatch_callback compare;
struct WildcardData *wc = &data->wildcard;
struct ftp_wc *ftpwc = wc->protdata;
struct WildcardData *wc = data->wildcard;
struct ftp_wc *ftpwc = wc->ftpwc;
struct Curl_llist *llist = &wc->filelist;
struct ftp_parselist_data *parser = ftpwc->parser;
bool add = TRUE;
@ -330,7 +330,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
{
size_t bufflen = size*nmemb;
struct Curl_easy *data = (struct Curl_easy *)connptr;
struct ftp_wc *ftpwc = data->wildcard.protdata;
struct ftp_wc *ftpwc = data->wildcard->ftpwc;
struct ftp_parselist_data *parser = ftpwc->parser;
struct fileinfo *infop;
struct curl_fileinfo *finfo;

View File

@ -2192,7 +2192,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
#ifndef CURL_DISABLE_FTP
/* some steps needed for wildcard matching */
if(data->state.wildcardmatch) {
struct WildcardData *wc = &data->wildcard;
struct WildcardData *wc = data->wildcard;
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
/* skip some states if it is important */
multi_done(data, CURLE_OK, FALSE);
@ -2344,7 +2344,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
#ifndef CURL_DISABLE_FTP
if(data->state.wildcardmatch &&
((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
data->wildcard.state = CURLWC_DONE;
data->wildcard->state = CURLWC_DONE;
}
#endif
multistate(data, MSTATE_DONE);
@ -2574,7 +2574,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
#ifndef CURL_DISABLE_FTP
if(data->state.wildcardmatch) {
if(data->wildcard.state != CURLWC_DONE) {
if(data->wildcard->state != CURLWC_DONE) {
/* if a wildcard is set and we are not ending -> lets start again
with MSTATE_INIT */
multistate(data, MSTATE_INIT);

View File

@ -1402,7 +1402,13 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
#ifndef CURL_DISABLE_FTP
data->state.wildcardmatch = data->set.wildcard_enabled;
if(data->state.wildcardmatch) {
struct WildcardData *wc = &data->wildcard;
struct WildcardData *wc;
if(!data->wildcard) {
data->wildcard = calloc(1, sizeof(struct WildcardData));
if(!data->wildcard)
return CURLE_OUT_OF_MEMORY;
}
wc = data->wildcard;
if(wc->state < CURLWC_INIT) {
result = Curl_wildcard_init(wc); /* init wildcard structures */
if(result)

View File

@ -1939,7 +1939,7 @@ struct Curl_easy {
struct UrlState state; /* struct for fields used for state info and
other dynamic purposes */
#ifndef CURL_DISABLE_FTP
struct WildcardData wildcard; /* wildcard download state info */
struct WildcardData *wildcard; /* wildcard download state info */
#endif
struct PureInfo info; /* stats, reports and info data */
struct curl_tlssessioninfo tsi; /* Information about the TLS session, only

View File

@ -48,17 +48,18 @@ CURLcode Curl_wildcard_init(struct WildcardData *wc)
return CURLE_OK;
}
void Curl_wildcard_dtor(struct WildcardData *wc)
void Curl_wildcard_dtor(struct WildcardData **wcp)
{
struct WildcardData *wc = *wcp;
if(!wc)
return;
if(wc->dtor) {
wc->dtor(wc->protdata);
wc->dtor(wc->ftpwc);
wc->dtor = ZERO_NULL;
wc->protdata = NULL;
wc->ftpwc = NULL;
}
DEBUGASSERT(wc->protdata == NULL);
DEBUGASSERT(wc->ftpwc == NULL);
Curl_llist_destroy(&wc->filelist, NULL);
free(wc->path);
@ -66,6 +67,8 @@ void Curl_wildcard_dtor(struct WildcardData *wc)
free(wc->pattern);
wc->pattern = NULL;
wc->state = CURLWC_INIT;
free(wc);
*wcp = NULL;
}
#endif /* if disabled */

View File

@ -48,16 +48,16 @@ typedef void (*wildcard_dtor)(void *ptr);
/* struct keeping information about wildcard download process */
struct WildcardData {
wildcard_states state;
char *path; /* path to the directory, where we trying wildcard-match */
char *pattern; /* wildcard pattern */
struct Curl_llist filelist; /* llist with struct Curl_fileinfo */
void *protdata; /* pointer to protocol specific temporary data */
struct ftp_wc *ftpwc; /* pointer to FTP wildcard data */
wildcard_dtor dtor;
unsigned char state; /* wildcard_states */
};
CURLcode Curl_wildcard_init(struct WildcardData *wc);
void Curl_wildcard_dtor(struct WildcardData *wc);
void Curl_wildcard_dtor(struct WildcardData **wcp);
struct Curl_easy;