Fix: incomplete partfile gets renamed to distfile
Abuild-fetch uses curl (fallback to wget) to download files. They are saved with a ".part" extension first, so they can be resumed if necessary. When the download is through, the ".part" extension gets removed. However, when the server does not support resume of downloads (e.g. GitHub's on the fly generated tarballs), then the ".part" extension got removed anyway. Abuild aborts in that case. But when running a third time, the distfile exists and it is assumed that this is the full download. Changes: * abuild-fetch: * Only remove the ".part" extension, when curl/wget exit with 0 * Pass the exit code from curl/wget as exit code of abuild-fetch * Wherever abuild-fetch would return an exit code on its own, the codes have been changed to be > 200 (so they don't collide with curl's as of now 92 exit codes) * Remove undocumented feature of downloading multiple source URLs at a time. This doesn't match with the usage description, was not used in abuild at all and it would have made it impossible to pass the exit code. * abuild: * After downloading, when curl is installed and abuild-fetch has 33 as exit code (curl's HTTP range error), then delete the partfile and try the download again.
This commit is contained in:
parent
3d0080de5e
commit
07d9f3bf6b
|
@ -50,7 +50,7 @@ void add_opt(struct cmdarray *cmd, char *opt)
|
||||||
|
|
||||||
int usage(int eval)
|
int usage(int eval)
|
||||||
{
|
{
|
||||||
printf("usage: %s [-d DESTDIR] URL\n", program);
|
printf("usage: %s [-h] [-d DESTDIR] URL\n", program);
|
||||||
return eval;
|
return eval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ int fetch(char *url, const char *destdir)
|
||||||
|
|
||||||
childpid = fork();
|
childpid = fork();
|
||||||
if (childpid < 0 )
|
if (childpid < 0 )
|
||||||
err(1, "fork");
|
err(200, "fork");
|
||||||
|
|
||||||
if (childpid == 0) {
|
if (childpid == 0) {
|
||||||
execvp(curlcmd.argv[0], curlcmd.argv);
|
execvp(curlcmd.argv[0], curlcmd.argv);
|
||||||
|
@ -132,9 +132,18 @@ int fetch(char *url, const char *destdir)
|
||||||
execvp(wgetcmd.argv[0], wgetcmd.argv);
|
execvp(wgetcmd.argv[0], wgetcmd.argv);
|
||||||
warn("%s", wgetcmd.argv[0]);
|
warn("%s", wgetcmd.argv[0]);
|
||||||
unlink(lockfile);
|
unlink(lockfile);
|
||||||
_exit(1);
|
_exit(201);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wait for curl/wget and get the exit code */
|
||||||
wait(&status);
|
wait(&status);
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
status = WEXITSTATUS(status);
|
||||||
|
else
|
||||||
|
status = 202;
|
||||||
|
|
||||||
|
/* don't rename partial downloads that we can't continue */
|
||||||
|
if (status == 0)
|
||||||
rename(partfile, outfile);
|
rename(partfile, outfile);
|
||||||
|
|
||||||
fetch_done:
|
fetch_done:
|
||||||
|
@ -142,7 +151,6 @@ fetch_done:
|
||||||
close(lockfd);
|
close(lockfd);
|
||||||
lockfile[0] = '\0';
|
lockfile[0] = '\0';
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sighandler(int sig)
|
void sighandler(int sig)
|
||||||
|
@ -160,9 +168,15 @@ void sighandler(int sig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* exit codes get passed through from curl/wget (so we can check in abuild
|
||||||
|
whether the server does not support resuming). Additional exit codes:
|
||||||
|
200: fork failed
|
||||||
|
201: curl/wget could not be started
|
||||||
|
202: curl/wget did not terminate normally
|
||||||
|
203: usage displayed */
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt, r=0, i;
|
int opt;
|
||||||
char *destdir = "/var/cache/distfiles";
|
char *destdir = "/var/cache/distfiles";
|
||||||
|
|
||||||
program = argv[0];
|
program = argv[0];
|
||||||
|
@ -184,17 +198,13 @@ int main(int argc, char *argv[])
|
||||||
argv += optind;
|
argv += optind;
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
|
|
||||||
if (argc < 1)
|
if (argc != 1)
|
||||||
return usage(1);
|
return usage(203);
|
||||||
|
|
||||||
signal(SIGABRT, sighandler);
|
signal(SIGABRT, sighandler);
|
||||||
signal(SIGINT, sighandler);
|
signal(SIGINT, sighandler);
|
||||||
signal(SIGQUIT, sighandler);
|
signal(SIGQUIT, sighandler);
|
||||||
signal(SIGTERM, sighandler);
|
signal(SIGTERM, sighandler);
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
return fetch(argv[0], destdir);
|
||||||
if (fetch(argv[i], destdir))
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
13
abuild.in
13
abuild.in
|
@ -332,9 +332,20 @@ sourcecheck() {
|
||||||
|
|
||||||
uri_fetch() {
|
uri_fetch() {
|
||||||
local uri="$1"
|
local uri="$1"
|
||||||
|
local status=0
|
||||||
mkdir -p "$SRCDEST"
|
mkdir -p "$SRCDEST"
|
||||||
msg "Fetching $uri"
|
msg "Fetching $uri"
|
||||||
abuild-fetch -d "$SRCDEST" "$uri"
|
abuild-fetch -d "$SRCDEST" "$uri" || status=$?
|
||||||
|
|
||||||
|
# try again when server does not support resume
|
||||||
|
if [ "$status" -eq 33 ] && command -v curl > /dev/null; then
|
||||||
|
local partfile="$SRCDEST/$(filename_from_uri $uri).part"
|
||||||
|
msg "Removing partial download and trying again: $partfile"
|
||||||
|
rm "$partfile"
|
||||||
|
uri_fetch "$uri"
|
||||||
|
else
|
||||||
|
return $status
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
is_remote() {
|
is_remote() {
|
||||||
|
|
Loading…
Reference in New Issue