diff options
author | des <des@FreeBSD.org> | 2002-10-27 15:15:13 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2002-10-27 15:15:13 +0000 |
commit | c1a42364827f8d2ce4bf20e6dd26748340a78c0a (patch) | |
tree | dc64809e151c6bee4963af78c58a7d8562acf9f2 | |
parent | cd8380e0b156cfdccb144d199ab89d1e0758125b (diff) | |
download | FreeBSD-src-c1a42364827f8d2ce4bf20e6dd26748340a78c0a.zip FreeBSD-src-c1a42364827f8d2ce4bf20e6dd26748340a78c0a.tar.gz |
Add an ETA timer that kicks in after 30 seconds.
Re-add alarm(2) calls around the calls to fetchStat(3) and fetchXGet(3),
since these calls can still time out on DNS lookups or TCP connect(2).
Remove the alarm(2) calls in the main loop, since all methods properly
handle transfer timeouts (as opposed to connection timeouts).
Set the sigalrm flag if a timeout occurs in the main loop.
Move the signal: label up a little so we still set the atime and mtime
when the transfer times out or is interrupted, so that restarted transfers
will work as expected (as long as the file still exists).
MFC after: 2 weeks
-rw-r--r-- | usr.bin/fetch/fetch.c | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c index 3ae311a..6b237f3 100644 --- a/usr.bin/fetch/fetch.c +++ b/usr.bin/fetch/fetch.c @@ -142,11 +142,27 @@ stat_display(struct xferstat *xs, int force) xs->last = now; fprintf(stderr, "\rReceiving %s", xs->name); - if (xs->size <= 0) + if (xs->size <= 0) { fprintf(stderr, ": %lld bytes", (long long)xs->rcvd); - else + } else { + long elapsed; + fprintf(stderr, " (%lld bytes): %d%%", (long long)xs->size, (int)((100.0 * xs->rcvd) / xs->size)); + elapsed = xs->last.tv_sec - xs->start.tv_sec; + if (elapsed > 30) { + long remaining; + + remaining = ((xs->size * elapsed) / xs->rcvd) - elapsed; + fprintf(stderr, " (ETA "); + if (remaining > 3600) { + fprintf(stderr, "%02ld:", remaining / 3600); + remaining %= 3600; + } + fprintf(stderr, "%02ld:%02ld) ", + remaining / 60, remaining % 60); + } + } } /* @@ -328,8 +344,17 @@ fetch(char *URL, const char *path) /* just print size */ if (s_flag) { - if (fetchStat(url, &us, flags) == -1) + if (timeout) + alarm(timeout); + r = fetchStat(url, &us, flags); + if (timeout) + alarm(0); + if (sigalrm || sigint) + goto signal; + if (r == -1) { + warnx("%s", fetchLastErrString); goto failure; + } if (us.size == -1) printf("Unknown\n"); else @@ -359,7 +384,12 @@ fetch(char *URL, const char *path) url->offset = sb.st_size; /* start the transfer */ - if ((f = fetchXGet(url, &us, flags)) == NULL) { + if (timeout) + alarm(timeout); + f = fetchXGet(url, &us, flags); + if (sigalrm || sigint) + goto signal; + if (f == NULL) { warnx("%s: %s", path, fetchLastErrString); goto failure; } @@ -501,30 +531,25 @@ fetch(char *URL, const char *path) /* suck in the data */ signal(SIGINFO, sig_handler); - while (!sigint && !sigalrm) { + while (!sigint) { if (us.size != -1 && us.size - count < B_size) size = us.size - count; else size = B_size; - if (timeout) - alarm(timeout); if (siginfo) { stat_end(&xs); siginfo = 0; } if ((size = fread(buf, 1, size, f)) == 0) { - if (ferror(f) && errno == EINTR && !sigalrm && !sigint) + if (ferror(f) && errno == EINTR && !sigint) clearerr(f); else break; } - if (timeout) - alarm(0); stat_update(&xs, count += size); for (ptr = buf; size > 0; ptr += wr, size -= wr) if ((wr = fwrite(ptr, 1, size, of)) < size) { - if (ferror(of) && errno == EINTR && - !sigalrm && !sigint) + if (ferror(of) && errno == EINTR && !sigint) clearerr(of); else break; @@ -532,13 +557,18 @@ fetch(char *URL, const char *path) if (size != 0) break; } + if (!sigalrm) + sigalrm = ferror(f) && errno == ETIMEDOUT; signal(SIGINFO, SIG_DFL); - if (timeout) - alarm(0); - stat_end(&xs); + /* + * If the transfer timed out or was interrupted, we still want to + * set the mtime in case the file is not removed (-r or -R) and + * the user later restarts the transfer. + */ + signal: /* set mtime of local file */ if (!n_flag && us.mtime && !o_stdout && (stat(path, &sb) != -1) && sb.st_mode & S_IFREG) { @@ -553,7 +583,6 @@ fetch(char *URL, const char *path) } /* timed out or interrupted? */ - signal: if (sigalrm) warnx("transfer timed out"); if (sigint) { |