Add new option --keep-badhash to keep Metalink's files with a bad hash

* src/init.c: Add keepbadhash
* src/main.c: Add keep-badhash
* src/options.h: Add keep_badhash
* doc/wget.texi: Add docs for --keep-badhash
* src/metalink.h: Add prototypes badhash_suffix(), badhash_or_remove()
* src/metalink.c: New functions badhash_suffix(), badhash_or_remove().
  (retrieve_from_metalink): Call badhash_or_remove() on download error

With --keep-badhash, append .badhash to Metalink's files with checksum
mismatch. (retrieve_from_metalink): unique_create() may append another
suffix to avoid overwriting existing files.

Without --keep-badhash, remove downloaded files with checksum mismatch
(this conforms to the old behaviour).
This commit is contained in:
Matthew White
2016-07-28 20:21:48 +02:00
committed by Tim Rühsen
parent 7fad76db4c
commit 943a6d585f
6 changed files with 67 additions and 7 deletions

View File

@@ -512,6 +512,12 @@ href if none was specified.
Downloads files covered in local Metalink @var{file}. Metalink version 3
and 4 are supported.
@cindex keep-badhash
@item --keep-badhash
Keeps downloaded Metalink's files with a bad hash. It appends .badhash
to the name of Metalink's files which have a checksum mismatch, except
without overwriting existing files.
@cindex metalink-over-http
@item --metalink-over-http
Issues HTTP HEAD request instead of GET and extracts Metalink metadata

View File

@@ -237,6 +237,7 @@ static const struct {
{ "input-metalink", &opt.input_metalink, cmd_file },
#endif
{ "iri", &opt.enable_iri, cmd_boolean },
{ "keepbadhash", &opt.keep_badhash, cmd_boolean },
{ "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean },
{ "limitrate", &opt.limit_rate, cmd_bytes },
{ "loadcookies", &opt.cookies_input, cmd_file },

View File

@@ -343,6 +343,7 @@ static struct cmdline_option option_data[] =
{ "input-metalink", 0, OPT_VALUE, "input-metalink", -1 },
#endif
{ "iri", 0, OPT_BOOLEAN, "iri", -1 },
{ "keep-badhash", 0, OPT_BOOLEAN, "keepbadhash", -1 },
{ "keep-session-cookies", 0, OPT_BOOLEAN, "keepsessioncookies", -1 },
{ "level", 'l', OPT_VALUE, "reclevel", -1 },
{ "limit-rate", 0, OPT_VALUE, "limitrate", -1 },
@@ -702,6 +703,8 @@ Download:\n"),
N_("\
--unlink remove file before clobber\n"),
#ifdef HAVE_METALINK
N_("\
--keep-badhash keep files with checksum mismatch (append .badhash)\n"),
N_("\
--metalink-over-http use Metalink metadata from HTTP response headers\n"),
N_("\

View File

@@ -120,13 +120,20 @@ retrieve_from_metalink (const metalink_t* metalink)
retr_err = METALINK_RETR_ERROR;
/* If output_stream is not NULL, then we have failed on
previous resource and are retrying. Thus, remove the file. */
previous resource and are retrying. Thus, rename/remove
the file. */
if (output_stream)
{
fclose (output_stream);
output_stream = NULL;
if (unlink (filename))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
badhash_or_remove (filename);
xfree (filename);
}
else if (filename)
{
/* Rename/remove the file downloaded previously before
downloading it again. */
badhash_or_remove (filename);
xfree (filename);
}
@@ -525,15 +532,13 @@ gpg_skip_verification:
#endif
last_retr_err = retr_err == RETROK ? last_retr_err : retr_err;
/* Remove the file if error encountered or if option specified.
/* Rename the file if error encountered; remove if option specified.
Note: the file has been downloaded using *_loop. Therefore, it
is not necessary to keep the file for continuated download. */
if ((retr_err != RETROK || opt.delete_after)
&& filename != NULL && file_exists_p (filename))
{
logprintf (LOG_VERBOSE, _("Removing %s.\n"), quote (filename));
if (unlink (filename))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
badhash_or_remove (filename);
}
if (output_stream)
{
@@ -551,6 +556,47 @@ gpg_skip_verification:
return last_retr_err;
}
/* Append the suffix ".badhash" to the file NAME, except without
overwriting an existing file with that name and suffix. */
void
badhash_suffix (char *name)
{
char *bhash, *uname;
bhash = concat_strings (name, ".badhash", (char *)0);
uname = unique_name (bhash, false);
logprintf (LOG_VERBOSE, _("Renaming %s to %s.\n"), name, uname);
if (link (name, uname))
logprintf (LOG_NOTQUIET, "link: %s\n", strerror (errno));
else if (unlink (name))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
xfree (bhash);
xfree (uname);
}
/* Append the suffix ".badhash" to the file NAME, except without
overwriting an existing file with that name and suffix.
Remove the file NAME if the option --delete-after is specified, or
if the option --keep-badhash isn't set. */
void
badhash_or_remove (char *name)
{
if (opt.delete_after || !opt.keep_badhash)
{
logprintf (LOG_VERBOSE, _("Removing %s.\n"), quote (name));
if (unlink (name))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
}
else
{
badhash_suffix(name);
}
}
int metalink_res_cmp (const void* v1, const void* v2)
{
const metalink_resource_t *res1 = *(metalink_resource_t **) v1,

View File

@@ -47,6 +47,9 @@ uerr_t retrieve_from_metalink (const metalink_t *metalink);
int metalink_res_cmp (const void *res1, const void *res2);
void badhash_suffix (char *name);
void badhash_or_remove (char *name);
bool find_key_value (const char *start,
const char *end,
const char *key,

View File

@@ -260,6 +260,7 @@ struct options
bool cookies; /* whether cookies are used. */
char *cookies_input; /* file we're loading the cookies from. */
char *cookies_output; /* file we're saving the cookies to. */
bool keep_badhash; /* Keep files with checksum mismatch. */
bool keep_session_cookies; /* whether session cookies should be
saved and loaded. */