* src/ftp.c (ftp_retrieve_glob): Refactor to prevent looping over listing multiple times

This commit is contained in:
Darshit Shah 2018-11-13 00:29:46 +01:00
parent d3383d619b
commit 8c741da256

132
src/ftp.c
View File

@ -2578,96 +2578,94 @@ ftp_retrieve_glob (struct url *u, struct url *original_url,
res = ftp_get_listing (u, original_url, con, &start);
if (res != RETROK)
return res;
/* First: weed out that do not conform the global rules given in
opt.accepts and opt.rejects. */
if (opt.accepts || opt.rejects)
{
f = start;
while (f)
{
if (f->type != FT_DIRECTORY && !acceptable (f->name))
{
logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
quote (f->name));
f = delelement (f, &start);
}
else
f = f->next;
}
}
/* Remove all files with possible harmful names or invalid entries. */
// Set the function used for glob matching.
int (*matcher) (const char *, const char *, int)
= opt.ignore_case ? fnmatch_nocase : fnmatch;
// Set the function used to compare strings
#ifdef __VMS
/* 2009-09-09 SMS.
* Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
* bug causes spurious %CC-E-BADCONDIT complaint with this
* "?:" statement. (Different linkage attributes for strcmp()
* and strcasecmp().) Converting to "if" changes the
* complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;". Adding
* the senseless type cast clears the complaint, and looks
* harmless.
*/
int (*cmp) (const char *, const char *)
= opt.ignore_case ? strcasecmp : (int (*)())strcmp;
#else /* def __VMS */
int (*cmp) (const char *, const char *)
= opt.ignore_case ? strcasecmp : strcmp;
#endif /* def __VMS [else] */
f = start;
while (f)
{
if (has_insecure_name_p (f->name) || is_invalid_entry (f))
// Weed out files that do not confirm to the global rules given in
// opt.accepts and opt.rejects
if ((opt.accepts || opt.rejects) &&
f->type != FT_DIRECTORY && !acceptable (f->name))
{
logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
quote (f->name));
f = delelement (f, &start);
continue;
}
else
f = f->next;
}
/* Now weed out the files that do not match our globbing pattern.
If we are dealing with a globbing pattern, that is. */
if (*u->file)
{
if (action == GLOB_GLOBALL)
{
int (*matcher) (const char *, const char *, int)
= opt.ignore_case ? fnmatch_nocase : fnmatch;
int matchres = 0;
f = start;
while (f)
// Identify and eliminate possibly harmful names or invalid entries.
if (has_insecure_name_p (f->name) || is_invalid_entry (f))
{
logprintf (LOG_VERBOSE, _("Rejecting %s (Invalid Entry).\n"),
quote (f->name));
f = delelement (f, &start);
continue;
}
/* Now weed out the files that do not match our globbing pattern.
If we are dealing with a globbing pattern, that is. */
if (*u->file)
{
if (action == GLOB_GLOBALL)
{
matchres = matcher (u->file, f->name, 0);
int matchres = matcher (u->file, f->name, 0);
if (matchres == -1)
{
logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
u->file, quotearg_style (escape_quoting_style, f->name),
strerror (errno));
break;
freefileinfo (start);
return RETRBADPATTERN;
}
if (matchres == FNM_NOMATCH)
f = delelement (f, &start); /* delete the element from the list */
else
f = f->next; /* leave the element in the list */
{
f = delelement (f, &start); /* delete the element from the list */
continue;
}
}
if (matchres == -1)
{
freefileinfo (start);
return RETRBADPATTERN;
}
}
else if (action == GLOB_GETONE)
{
#ifdef __VMS
/* 2009-09-09 SMS.
* Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
* bug causes spurious %CC-E-BADCONDIT complaint with this
* "?:" statement. (Different linkage attributes for strcmp()
* and strcasecmp().) Converting to "if" changes the
* complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;". Adding
* the senseless type cast clears the complaint, and looks
* harmless.
*/
int (*cmp) (const char *, const char *)
= opt.ignore_case ? strcasecmp : (int (*)())strcmp;
#else /* def __VMS */
int (*cmp) (const char *, const char *)
= opt.ignore_case ? strcasecmp : strcmp;
#endif /* def __VMS [else] */
f = start;
while (f)
else if (action == GLOB_GETONE)
{
if (0 != cmp(u->file, f->name))
f = delelement (f, &start);
else
f = f->next;
{
f = delelement (f, &start);
continue;
}
}
}
f = f->next;
}
/*
* Now that preprocessing of the file listing is over, let's try to download
* all the remaining files in our listing.
*/
if (start)
{
/* Just get everything. */