1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

Factor out some gethttp code

* src/http.c (gethttp): Move some code in...
(check_file_output): ... a new function.
This commit is contained in:
Giuseppe Scrivano 2015-03-16 01:13:11 +01:00
parent 0bc2757713
commit 8aa63e482e

View File

@ -2002,6 +2002,118 @@ establish_connection (struct url *u, struct url **conn_ref,
return RETROK; return RETROK;
} }
static uerr_t
check_file_output (struct url *u, struct http_stat *hs,
struct response *resp, char *hdrval, size_t hdrsize)
{
/* Determine the local filename if needed. Notice that if -O is used
* hstat.local_file is set by http_loop to the argument of -O. */
if (!hs->local_file)
{
char *local_file = NULL;
/* Honor Content-Disposition whether possible. */
if (!opt.content_disposition
|| !resp_header_copy (resp, "Content-Disposition",
hdrval, hdrsize)
|| !parse_content_disposition (hdrval, &local_file))
{
/* The Content-Disposition header is missing or broken.
* Choose unique file name according to given URL. */
hs->local_file = url_file_name (u, NULL);
}
else
{
DEBUGP (("Parsed filename from Content-Disposition: %s\n",
local_file));
hs->local_file = url_file_name (u, local_file);
}
xfree (local_file);
}
/* TODO: perform this check only once. */
if (!hs->existence_checked && file_exists_p (hs->local_file))
{
if (opt.noclobber && !opt.output_document)
{
/* If opt.noclobber is turned on and file already exists, do not
retrieve the file. But if the output_document was given, then this
test was already done and the file didn't exist. Hence the !opt.output_document */
return RETRUNNEEDED;
}
else if (!ALLOW_CLOBBER)
{
char *unique = unique_name (hs->local_file, true);
if (unique != hs->local_file)
xfree (hs->local_file);
hs->local_file = unique;
}
}
hs->existence_checked = true;
/* Support timestamping */
if (opt.timestamping && !hs->timestamp_checked)
{
size_t filename_len = strlen (hs->local_file);
char *filename_plus_orig_suffix = alloca (filename_len + sizeof (ORIG_SFX));
bool local_dot_orig_file_exists = false;
char *local_filename = NULL;
struct_stat st;
if (opt.backup_converted)
/* If -K is specified, we'll act on the assumption that it was specified
last time these files were downloaded as well, and instead of just
comparing local file X against server file X, we'll compare local
file X.orig (if extant, else X) against server file X. If -K
_wasn't_ specified last time, or the server contains files called
*.orig, -N will be back to not operating correctly with -k. */
{
/* Would a single s[n]printf() call be faster? --dan
Definitely not. sprintf() is horribly slow. It's a
different question whether the difference between the two
affects a program. Usually I'd say "no", but at one
point I profiled Wget, and found that a measurable and
non-negligible amount of time was lost calling sprintf()
in url.c. Replacing sprintf with inline calls to
strcpy() and number_to_string() made a difference.
--hniksic */
memcpy (filename_plus_orig_suffix, hs->local_file, filename_len);
memcpy (filename_plus_orig_suffix + filename_len,
ORIG_SFX, sizeof (ORIG_SFX));
/* Try to stat() the .orig file. */
if (stat (filename_plus_orig_suffix, &st) == 0)
{
local_dot_orig_file_exists = true;
local_filename = filename_plus_orig_suffix;
}
}
if (!local_dot_orig_file_exists)
/* Couldn't stat() <file>.orig, so try to stat() <file>. */
if (stat (hs->local_file, &st) == 0)
local_filename = hs->local_file;
if (local_filename != NULL)
/* There was a local file, so we'll check later to see if the version
the server has is the same version we already have, allowing us to
skip a download. */
{
hs->orig_file_name = xstrdup (local_filename);
hs->orig_file_size = st.st_size;
hs->orig_file_tstamp = st.st_mtime;
#ifdef WINDOWS
/* Modification time granularity is 2 seconds for Windows, so
increase local time by 1 second for later comparison. */
++hs->orig_file_tstamp;
#endif
}
}
return RETROK;
}
/* Retrieve a document through HTTP protocol. It recognizes status /* Retrieve a document through HTTP protocol. It recognizes status
code, and correctly handles redirections. It closes the network code, and correctly handles redirections. It closes the network
socket. If it receives an error from the functions below it, it socket. If it receives an error from the functions below it, it
@ -2566,118 +2678,17 @@ read_header:
} }
/* Determine the local filename if needed. Notice that if -O is used
* hstat.local_file is set by http_loop to the argument of -O. */
if (!hs->local_file)
{ {
char *local_file = NULL; uerr_t ret = check_file_output (u, hs, resp, hdrval, sizeof hdrval);
if (ret != RETROK)
/* Honor Content-Disposition whether possible. */
if (!opt.content_disposition
|| !resp_header_copy (resp, "Content-Disposition",
hdrval, sizeof (hdrval))
|| !parse_content_disposition (hdrval, &local_file))
{ {
/* The Content-Disposition header is missing or broken.
* Choose unique file name according to given URL. */
hs->local_file = url_file_name (u, NULL);
}
else
{
DEBUGP (("Parsed filename from Content-Disposition: %s\n",
local_file));
hs->local_file = url_file_name (u, local_file);
}
xfree (local_file);
}
/* TODO: perform this check only once. */
if (!hs->existence_checked && file_exists_p (hs->local_file))
{
if (opt.noclobber && !opt.output_document)
{
/* If opt.noclobber is turned on and file already exists, do not
retrieve the file. But if the output_document was given, then this
test was already done and the file didn't exist. Hence the !opt.output_document */
get_file_flags (hs->local_file, dt);
request_free (req); request_free (req);
resp_free (resp); resp_free (resp);
xfree (head); xfree (head);
xfree (message); xfree (message);
return RETRUNNEEDED; return ret;
}
else if (!ALLOW_CLOBBER)
{
char *unique = unique_name (hs->local_file, true);
if (unique != hs->local_file)
xfree (hs->local_file);
hs->local_file = unique;
} }
} }
hs->existence_checked = true;
/* Support timestamping */
/* TODO: move this code out of gethttp. */
if (opt.timestamping && !hs->timestamp_checked)
{
size_t filename_len = strlen (hs->local_file);
char *filename_plus_orig_suffix = alloca (filename_len + sizeof (ORIG_SFX));
bool local_dot_orig_file_exists = false;
char *local_filename = NULL;
struct_stat st;
if (opt.backup_converted)
/* If -K is specified, we'll act on the assumption that it was specified
last time these files were downloaded as well, and instead of just
comparing local file X against server file X, we'll compare local
file X.orig (if extant, else X) against server file X. If -K
_wasn't_ specified last time, or the server contains files called
*.orig, -N will be back to not operating correctly with -k. */
{
/* Would a single s[n]printf() call be faster? --dan
Definitely not. sprintf() is horribly slow. It's a
different question whether the difference between the two
affects a program. Usually I'd say "no", but at one
point I profiled Wget, and found that a measurable and
non-negligible amount of time was lost calling sprintf()
in url.c. Replacing sprintf with inline calls to
strcpy() and number_to_string() made a difference.
--hniksic */
memcpy (filename_plus_orig_suffix, hs->local_file, filename_len);
memcpy (filename_plus_orig_suffix + filename_len,
ORIG_SFX, sizeof (ORIG_SFX));
/* Try to stat() the .orig file. */
if (stat (filename_plus_orig_suffix, &st) == 0)
{
local_dot_orig_file_exists = true;
local_filename = filename_plus_orig_suffix;
}
}
if (!local_dot_orig_file_exists)
/* Couldn't stat() <file>.orig, so try to stat() <file>. */
if (stat (hs->local_file, &st) == 0)
local_filename = hs->local_file;
if (local_filename != NULL)
/* There was a local file, so we'll check later to see if the version
the server has is the same version we already have, allowing us to
skip a download. */
{
hs->orig_file_name = xstrdup (local_filename);
hs->orig_file_size = st.st_size;
hs->orig_file_tstamp = st.st_mtime;
#ifdef WINDOWS
/* Modification time granularity is 2 seconds for Windows, so
increase local time by 1 second for later comparison. */
++hs->orig_file_tstamp;
#endif
}
}
request_free (req); request_free (req);
hs->statcode = statcode; hs->statcode = statcode;