A resumed transfer asks for the tail of whatever the server has now.
If the file changed in between, the caller cannot tell and ends up
with a corrupt copy.
Record the strong entity tag of each successful HTTP response in a new
validator field appended to struct url, and send it as If-Range
whenever the same struct url is reused with a non-zero offset. A
server that no longer has that version then answers 200 with the full
document, which is reported through url->offset as today. A 206 with
a different entity tag, or a 416 to a conditional request, fails with
the new FETCH_RESTART error code; the former catches servers that
honor Range but ignore If-Range.
Only a caller that reuses the struct url benefits: fetch -a retries
do, a later fetch -r run starts without a validator and does not.
struct url is part of the ABI, so bump SHLIB_MAJOR to 7 and take the
occasion to enable symbol versioning: only the interfaces declared in
fetch.h are exported now, tagged FBSD_1.8.
fetch(1): resume each -a retry from the bytes written so far, into the
file being written. A retry used to take its offset from stat(2) of
the destination, which misses buffered output and names the wrong file
when a temporary file is in use, so resumed data could land at the
wrong offset. Keep that file open across retries, discard whatever
the server does not resume, and start over on FETCH_RESTART. A -r
run whose local mtime did not match the server's went on reading the
stream it had just closed when the server ignored the range or the
local file was empty; refetch in that case too.
Relnotes: yes
Sponsored by: Rubicon Communications, LLC ("Netgate")