svn commit: r339250 - in stable/11: lib/libfetch usr.bin/fetch
Dag-Erling Smørgrav
des at FreeBSD.org
Tue Oct 9 10:49:21 UTC 2018
Author: des
Date: Tue Oct 9 10:49:19 2018
New Revision: 339250
URL: https://svnweb.freebsd.org/changeset/base/339250
Log:
MFH (r314778): use reallocarray(3) for extra bounds checks
MFH (r333306): fix typo in man page
MFH (r333571, r333572): preserve if-modified-since across redirects
MFH (r334317): simplify the DEBUG macro
MFH (r334319): style bug roundup
MFH (r334326): fix netrc file location logic, improve netrcfd handling
MFH (r338572): fix end-of-transfer statistics, improve no-tty display
PR: 202424, 224426, 228017
Modified:
stable/11/lib/libfetch/common.c
stable/11/lib/libfetch/common.h
stable/11/lib/libfetch/fetch.c
stable/11/lib/libfetch/ftp.c
stable/11/lib/libfetch/http.c
stable/11/usr.bin/fetch/fetch.1
stable/11/usr.bin/fetch/fetch.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/lib/libfetch/common.c
==============================================================================
--- stable/11/lib/libfetch/common.c Tue Oct 9 07:22:14 2018 (r339249)
+++ stable/11/lib/libfetch/common.c Tue Oct 9 10:49:19 2018 (r339250)
@@ -345,7 +345,7 @@ fetch_connect(const char *host, int port, int af, int
conn_t *conn = NULL;
int err = 0, sd = -1;
- DEBUG(fprintf(stderr, "---> %s:%d\n", host, port));
+ DEBUGF("---> %s:%d\n", host, port);
/* resolve server address */
if (verbose)
@@ -1156,7 +1156,7 @@ fetch_getln(conn_t *conn)
} while (c != '\n');
conn->buf[conn->buflen] = '\0';
- DEBUG(fprintf(stderr, "<<< %s", conn->buf));
+ DEBUGF("<<< %s", conn->buf);
return (0);
}
@@ -1261,7 +1261,7 @@ fetch_putln(conn_t *conn, const char *str, size_t len)
struct iovec iov[2];
int ret;
- DEBUG(fprintf(stderr, ">>> %s\n", str));
+ DEBUGF(">>> %s\n", str);
iov[0].iov_base = __DECONST(char *, str);
iov[0].iov_len = len;
iov[1].iov_base = __DECONST(char *, ENDL);
@@ -1323,7 +1323,7 @@ fetch_add_entry(struct url_ent **p, int *size, int *le
}
if (*len >= *size - 1) {
- tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p));
+ tmp = reallocarray(*p, *size * 2 + 1, sizeof(**p));
if (tmp == NULL) {
errno = ENOMEM;
fetch_syserr();
@@ -1359,19 +1359,20 @@ fetch_read_word(FILE *f)
static int
fetch_netrc_open(void)
{
- const char *p;
+ struct passwd *pwd;
char fn[PATH_MAX];
+ const char *p;
+ int fd, serrno;
if ((p = getenv("NETRC")) != NULL) {
+ DEBUGF("NETRC=%s\n", p);
if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) {
fetch_info("$NETRC specifies a file name "
"longer than PATH_MAX");
return (-1);
}
} else {
- if ((p = getenv("HOME")) != NULL) {
- struct passwd *pwd;
-
+ if ((p = getenv("HOME")) == NULL) {
if ((pwd = getpwuid(getuid())) == NULL ||
(p = pwd->pw_dir) == NULL)
return (-1);
@@ -1380,7 +1381,12 @@ fetch_netrc_open(void)
return (-1);
}
- return (open(fn, O_RDONLY));
+ if ((fd = open(fn, O_RDONLY)) < 0) {
+ serrno = errno;
+ DEBUGF("%s: %s\n", fn, strerror(serrno));
+ errno = serrno;
+ }
+ return (fd);
}
/*
@@ -1390,24 +1396,32 @@ int
fetch_netrc_auth(struct url *url)
{
const char *word;
+ int serrno;
FILE *f;
- if (url->netrcfd == -2)
+ if (url->netrcfd < 0)
url->netrcfd = fetch_netrc_open();
if (url->netrcfd < 0)
return (-1);
- if ((f = fdopen(url->netrcfd, "r")) == NULL)
+ if ((f = fdopen(url->netrcfd, "r")) == NULL) {
+ serrno = errno;
+ DEBUGF("fdopen(netrcfd): %s", strerror(errno));
+ close(url->netrcfd);
+ url->netrcfd = -1;
+ errno = serrno;
return (-1);
+ }
rewind(f);
+ DEBUGF("searching netrc for %s\n", url->host);
while ((word = fetch_read_word(f)) != NULL) {
if (strcmp(word, "default") == 0) {
- DEBUG(fetch_info("Using default .netrc settings"));
+ DEBUGF("using default netrc settings\n");
break;
}
if (strcmp(word, "machine") == 0 &&
(word = fetch_read_word(f)) != NULL &&
strcasecmp(word, url->host) == 0) {
- DEBUG(fetch_info("Using .netrc settings for %s", word));
+ DEBUGF("using netrc settings for %s\n", word);
break;
}
}
@@ -1439,9 +1453,13 @@ fetch_netrc_auth(struct url *url)
}
}
fclose(f);
+ url->netrcfd = -1;
return (0);
- ferr:
+ferr:
+ serrno = errno;
fclose(f);
+ url->netrcfd = -1;
+ errno = serrno;
return (-1);
}
Modified: stable/11/lib/libfetch/common.h
==============================================================================
--- stable/11/lib/libfetch/common.h Tue Oct 9 07:22:14 2018 (r339249)
+++ stable/11/lib/libfetch/common.h Tue Oct 9 10:49:19 2018 (r339250)
@@ -102,9 +102,16 @@ int fetch_no_proxy_match(const char *);
#define url_seterr(n) fetch_seterr(url_errlist, n)
#ifndef NDEBUG
-#define DEBUG(x) do { if (fetchDebug) { x; } } while (0)
+#define DEBUGF(...) \
+ do { \
+ if (fetchDebug) \
+ fprintf(stderr, __VA_ARGS__); \
+ } while (0)
#else
-#define DEBUG(x) do { } while (0)
+#define DEBUGF(...) \
+ do { \
+ /* nothing */ \
+ } while (0)
#endif
/*
Modified: stable/11/lib/libfetch/fetch.c
==============================================================================
--- stable/11/lib/libfetch/fetch.c Tue Oct 9 07:22:14 2018 (r339249)
+++ stable/11/lib/libfetch/fetch.c Tue Oct 9 10:49:19 2018 (r339250)
@@ -270,6 +270,7 @@ fetchMakeURL(const char *scheme, const char *host, int
fetch_syserr();
return (NULL);
}
+ u->netrcfd = -1;
if ((u->doc = strdup(doc ? doc : "/")) == NULL) {
fetch_syserr();
@@ -284,7 +285,6 @@ fetchMakeURL(const char *scheme, const char *host, int
seturl(pwd);
#undef seturl
u->port = port;
- u->netrcfd = -2;
return (u);
}
@@ -350,7 +350,7 @@ fetchParseURL(const char *URL)
fetch_syserr();
return (NULL);
}
- u->netrcfd = -2;
+ u->netrcfd = -1;
/* scheme name */
if ((p = strstr(URL, ":/"))) {
@@ -442,15 +442,14 @@ nohost:
goto ouch;
}
- DEBUG(fprintf(stderr,
- "scheme: \"%s\"\n"
- "user: \"%s\"\n"
- "password: \"%s\"\n"
- "host: \"%s\"\n"
- "port: \"%d\"\n"
- "document: \"%s\"\n",
- u->scheme, u->user, u->pwd,
- u->host, u->port, u->doc));
+ DEBUGF("scheme: \"%s\"\n"
+ "user: \"%s\"\n"
+ "password: \"%s\"\n"
+ "host: \"%s\"\n"
+ "port: \"%d\"\n"
+ "document: \"%s\"\n",
+ u->scheme, u->user, u->pwd,
+ u->host, u->port, u->doc);
return (u);
Modified: stable/11/lib/libfetch/ftp.c
==============================================================================
--- stable/11/lib/libfetch/ftp.c Tue Oct 9 07:22:14 2018 (r339249)
+++ stable/11/lib/libfetch/ftp.c Tue Oct 9 10:49:19 2018 (r339250)
@@ -257,7 +257,7 @@ ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen)
return (FTP_PROTOCOL_ERROR);
*dst = '\0';
#if 0
- DEBUG(fprintf(stderr, "pwd: [%s]\n", pwd));
+ DEBUGF("pwd: [%s]\n", pwd);
#endif
return (FTP_OK);
}
@@ -289,8 +289,8 @@ ftp_cwd(conn_t *conn, const char *file)
if (pwd[i] != file[i])
break;
#if 0
- DEBUG(fprintf(stderr, "have: [%.*s|%s]\n", i, pwd, pwd + i));
- DEBUG(fprintf(stderr, "want: [%.*s|%s]\n", i, file, file + i));
+ DEBUGF("have: [%.*s|%s]\n", i, pwd, pwd + i);
+ DEBUGF("want: [%.*s|%s]\n", i, file, file + i);
#endif
/* Keep going up a dir until we have a matching prefix. */
if (pwd[i] == '\0' && (file[i - 1] == '/' || file[i] == '/'))
@@ -431,7 +431,7 @@ ftp_stat(conn_t *conn, const char *file, struct url_st
}
if (us->size == 0)
us->size = -1;
- DEBUG(fprintf(stderr, "size: [%lld]\n", (long long)us->size));
+ DEBUGF("size: [%lld]\n", (long long)us->size);
e = ftp_cmd(conn, "MDTM %.*s", filenamelen, filename);
if (e != FTP_FILE_STATUS) {
@@ -466,10 +466,9 @@ ftp_stat(conn_t *conn, const char *file, struct url_st
t = time(NULL);
us->mtime = t;
us->atime = t;
- DEBUG(fprintf(stderr,
- "last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n",
+ DEBUGF("last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec));
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
return (0);
}
@@ -583,7 +582,7 @@ ftp_closefn(void *v)
fetch_close(io->dconn);
io->dir = -1;
io->dconn = NULL;
- DEBUG(fprintf(stderr, "Waiting for final status\n"));
+ DEBUGF("Waiting for final status\n");
r = ftp_chkerr(io->cconn);
if (io->cconn == cached_connection && io->cconn->ref == 1)
cached_connection = NULL;
@@ -913,7 +912,8 @@ ftp_authenticate(conn_t *conn, struct url *url, struct
fetch_netrc_auth(url);
user = url->user;
if (*user == '\0')
- user = getenv("FTP_LOGIN");
+ if ((user = getenv("FTP_LOGIN")) != NULL)
+ DEBUGF("FTP_LOGIN=%s\n", user);
if (user == NULL || *user == '\0')
user = FTP_ANONYMOUS_USER;
if (purl && url->port == fetch_default_port(url->scheme))
@@ -927,7 +927,8 @@ ftp_authenticate(conn_t *conn, struct url *url, struct
if (e == FTP_NEED_PASSWORD) {
pwd = url->pwd;
if (*pwd == '\0')
- pwd = getenv("FTP_PASSWORD");
+ if ((pwd = getenv("FTP_PASSWORD")) != NULL)
+ DEBUGF("FTP_PASSWORD=%s\n", pwd);
if (pwd == NULL || *pwd == '\0') {
if ((logname = getlogin()) == NULL)
logname = FTP_ANONYMOUS_USER;
Modified: stable/11/lib/libfetch/http.c
==============================================================================
--- stable/11/lib/libfetch/http.c Tue Oct 9 07:22:14 2018 (r339249)
+++ stable/11/lib/libfetch/http.c Tue Oct 9 10:49:19 2018 (r339250)
@@ -778,9 +778,9 @@ http_parse_authenticate(const char *cp, http_auth_chal
goto out;
}
init_http_auth_challenge(cs->challenges[cs->count]);
- if (!strcasecmp(key, "basic")) {
+ if (strcasecmp(key, "basic") == 0) {
cs->challenges[cs->count]->scheme = HTTPAS_BASIC;
- } else if (!strcasecmp(key, "digest")) {
+ } else if (strcasecmp(key, "digest") == 0) {
cs->challenges[cs->count]->scheme = HTTPAS_DIGEST;
} else {
cs->challenges[cs->count]->scheme = HTTPAS_UNKNOWN;
@@ -809,25 +809,27 @@ http_parse_authenticate(const char *cp, http_auth_chal
if (lex != HTTPHL_WORD && lex != HTTPHL_STRING)
goto out;
- if (!strcasecmp(key, "realm"))
+ if (strcasecmp(key, "realm") == 0) {
cs->challenges[cs->count]->realm =
- strdup(value);
- else if (!strcasecmp(key, "qop"))
+ strdup(value);
+ } else if (strcasecmp(key, "qop") == 0) {
cs->challenges[cs->count]->qop =
- strdup(value);
- else if (!strcasecmp(key, "nonce"))
+ strdup(value);
+ } else if (strcasecmp(key, "nonce") == 0) {
cs->challenges[cs->count]->nonce =
- strdup(value);
- else if (!strcasecmp(key, "opaque"))
+ strdup(value);
+ } else if (strcasecmp(key, "opaque") == 0) {
cs->challenges[cs->count]->opaque =
- strdup(value);
- else if (!strcasecmp(key, "algorithm"))
+ strdup(value);
+ } else if (strcasecmp(key, "algorithm") == 0) {
cs->challenges[cs->count]->algo =
- strdup(value);
- else if (!strcasecmp(key, "stale"))
+ strdup(value);
+ } else if (strcasecmp(key, "stale") == 0) {
cs->challenges[cs->count]->stale =
- strcasecmp(value, "no");
- /* Else ignore unknown attributes */
+ strcasecmp(value, "no");
+ } else {
+ /* ignore unknown attributes */
+ }
/* Comma or Next challenge or End */
lex = http_header_lex(&cp, key);
@@ -889,10 +891,9 @@ http_parse_mtime(const char *p, time_t *mtime)
setlocale(LC_TIME, locale);
if (r == NULL)
return (-1);
- DEBUG(fprintf(stderr, "last modified: [%04d-%02d-%02d "
- "%02d:%02d:%02d]\n",
- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec));
+ DEBUGF("last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
*mtime = timegm(&tm);
return (0);
}
@@ -909,8 +910,7 @@ http_parse_length(const char *p, off_t *length)
len = len * 10 + (*p - '0');
if (*p)
return (-1);
- DEBUG(fprintf(stderr, "content length: [%lld]\n",
- (long long)len));
+ DEBUGF("content length: [%lld]\n", (long long)len);
*length = len;
return (0);
}
@@ -944,12 +944,11 @@ http_parse_range(const char *p, off_t *offset, off_t *
if (*p || len < last - first + 1)
return (-1);
if (first == -1) {
- DEBUG(fprintf(stderr, "content range: [*/%lld]\n",
- (long long)len));
+ DEBUGF("content range: [*/%lld]\n", (long long)len);
*length = 0;
} else {
- DEBUG(fprintf(stderr, "content range: [%lld-%lld/%lld]\n",
- (long long)first, (long long)last, (long long)len));
+ DEBUGF("content range: [%lld-%lld/%lld]\n",
+ (long long)first, (long long)last, (long long)len);
*length = last - first + 1;
}
*offset = first;
@@ -1185,9 +1184,10 @@ DigestCalcResponse(
OUT HASHHEX Response /* request-digest or response-digest */
)
{
-/* DEBUG(fprintf(stderr,
- "Calc: HA1[%s] Nonce[%s] qop[%s] method[%s] URI[%s]\n",
- HA1, pszNonce, pszQop, pszMethod, pszDigestUri));*/
+#if 0
+ DEBUGF("Calc: HA1[%s] Nonce[%s] qop[%s] method[%s] URI[%s]\n",
+ HA1, pszNonce, pszQop, pszMethod, pszDigestUri);
+#endif
MD5_CTX Md5Ctx;
HASH HA2;
HASH RespHash;
@@ -1255,15 +1255,15 @@ http_digest_auth(conn_t *conn, const char *hdr, http_a
char *options = NULL;
if (!c->realm || !c->nonce) {
- DEBUG(fprintf(stderr, "realm/nonce not set in challenge\n"));
+ DEBUGF("realm/nonce not set in challenge\n");
return(-1);
}
if (!c->algo)
c->algo = strdup("");
if (asprintf(&options, "%s%s%s%s",
- *c->algo? ",algorithm=" : "", c->algo,
- c->opaque? ",opaque=" : "", c->opaque?c->opaque:"")== -1)
+ *c->algo? ",algorithm=" : "", c->algo,
+ c->opaque? ",opaque=" : "", c->opaque?c->opaque:"") < 0)
return (-1);
if (!c->qop) {
@@ -1280,7 +1280,7 @@ http_digest_auth(conn_t *conn, const char *hdr, http_a
HASHHEX HA1;
DigestCalcHA1(c->algo, parms->user, c->realm,
parms->password, c->nonce, cnonce, HA1);
- DEBUG(fprintf(stderr, "HA1: [%s]\n", HA1));
+ DEBUGF("HA1: [%s]\n", HA1);
HASHHEX digest;
DigestCalcResponse(HA1, c->nonce, noncecount, cnonce, c->qop,
"GET", url->doc, "", digest);
@@ -1312,8 +1312,8 @@ http_basic_auth(conn_t *conn, const char *hdr, const c
char *upw, *auth;
int r;
- DEBUG(fprintf(stderr, "basic: usr: [%s]\n", usr));
- DEBUG(fprintf(stderr, "basic: pwd: [%s]\n", pwd));
+ DEBUGF("basic: usr: [%s]\n", usr);
+ DEBUGF("basic: pwd: [%s]\n", pwd);
if (asprintf(&upw, "%s:%s", usr, pwd) == -1)
return (-1);
auth = http_base64(upw);
@@ -1338,7 +1338,7 @@ http_authorize(conn_t *conn, const char *hdr, http_aut
/* If user or pass are null we're not happy */
if (!parms->user || !parms->password) {
- DEBUG(fprintf(stderr, "NULL usr or pass\n"));
+ DEBUGF("NULL usr or pass\n");
return (-1);
}
@@ -1349,10 +1349,9 @@ http_authorize(conn_t *conn, const char *hdr, http_aut
}
/* Error if "Digest" was specified and there is no Digest challenge */
- if (!digest && (parms->scheme &&
- !strcasecmp(parms->scheme, "digest"))) {
- DEBUG(fprintf(stderr,
- "Digest auth in env, not supported by peer\n"));
+ if (!digest &&
+ (parms->scheme && strcasecmp(parms->scheme, "digest") == 0)) {
+ DEBUGF("Digest auth in env, not supported by peer\n");
return (-1);
}
/*
@@ -1360,7 +1359,8 @@ http_authorize(conn_t *conn, const char *hdr, http_aut
* challenge, do the basic thing. Don't need a challenge for this,
* so no need to check basic!=NULL
*/
- if (!digest || (parms->scheme && !strcasecmp(parms->scheme,"basic")))
+ if (!digest ||
+ (parms->scheme && strcasecmp(parms->scheme, "basic") == 0))
return (http_basic_auth(conn,hdr,parms->user,parms->password));
/* Else, prefer digest. We just checked that it's not NULL */
@@ -1852,26 +1852,29 @@ http_request_body(struct url *URL, const char *op, str
if (new)
free(new);
if (verbose)
- fetch_info("%d redirect to %s", conn->err, p);
+ fetch_info("%d redirect to %s",
+ conn->err, p);
if (*p == '/')
/* absolute path */
- new = fetchMakeURL(url->scheme, url->host, url->port, p,
- url->user, url->pwd);
+ new = fetchMakeURL(url->scheme, url->host,
+ url->port, p, url->user, url->pwd);
else
new = fetchParseURL(p);
if (new == NULL) {
/* XXX should set an error code */
- DEBUG(fprintf(stderr, "failed to parse new URL\n"));
+ DEBUGF("failed to parse new URL\n");
goto ouch;
}
/* Only copy credentials if the host matches */
- if (!strcmp(new->host, url->host) && !*new->user && !*new->pwd) {
+ if (strcmp(new->host, url->host) == 0 &&
+ !*new->user && !*new->pwd) {
strcpy(new->user, url->user);
strcpy(new->pwd, url->pwd);
}
new->offset = url->offset;
new->length = url->length;
+ new->ims_time = url->ims_time;
break;
case hdr_transfer_encoding:
/* XXX weak test*/
@@ -1906,7 +1909,7 @@ http_request_body(struct url *URL, const char *op, str
(conn->err == HTTP_NEED_PROXY_AUTH &&
!proxy_challenges.valid)) {
/* 401/7 but no www/proxy-authenticate ?? */
- DEBUG(fprintf(stderr, "401/7 and no auth header\n"));
+ DEBUGF("%03d without auth header\n", conn->err);
goto ouch;
}
fetch_close(conn);
@@ -1941,7 +1944,7 @@ http_request_body(struct url *URL, const char *op, str
fetch_close(conn);
conn = NULL;
if (!new) {
- DEBUG(fprintf(stderr, "redirect with no new location\n"));
+ DEBUGF("redirect with no new location\n");
break;
}
if (url != URL)
@@ -1955,10 +1958,9 @@ http_request_body(struct url *URL, const char *op, str
goto ouch;
}
- DEBUG(fprintf(stderr, "offset %lld, length %lld,"
- " size %lld, clength %lld\n",
- (long long)offset, (long long)length,
- (long long)size, (long long)clength));
+ DEBUGF("offset %lld, length %lld, size %lld, clength %lld\n",
+ (long long)offset, (long long)length,
+ (long long)size, (long long)clength);
if (conn->err == HTTP_NOT_MODIFIED) {
http_seterr(HTTP_NOT_MODIFIED);
Modified: stable/11/usr.bin/fetch/fetch.1
==============================================================================
--- stable/11/usr.bin/fetch/fetch.1 Tue Oct 9 07:22:14 2018 (r339249)
+++ stable/11/usr.bin/fetch/fetch.1 Tue Oct 9 10:49:19 2018 (r339250)
@@ -30,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 18, 2016
+.Dd May 6, 2018
.Dt FETCH 1
.Os
.Sh NAME
@@ -241,7 +241,7 @@ certificate presented by the server.
.It Fl -no-verify-peer
[SSL]
Do not verify the peer certificate against trusted CAs.
-.It Fl o Ar file , Fl output= Ns Ar file
+.It Fl o Ar file , Fl -output= Ns Ar file
Set the output file name to
.Ar file .
By default, a ``pathname'' is extracted from the specified URI, and
Modified: stable/11/usr.bin/fetch/fetch.c
==============================================================================
--- stable/11/usr.bin/fetch/fetch.c Tue Oct 9 07:22:14 2018 (r339249)
+++ stable/11/usr.bin/fetch/fetch.c Tue Oct 9 10:49:19 2018 (r339250)
@@ -85,6 +85,7 @@ static int t_flag; /*! -t: workaround TCP bug */
static int U_flag; /* -U: do not use high ports */
static int v_level = 1; /* -v: verbosity level */
static int v_tty; /* stdout is a tty */
+static int v_progress; /* whether to display progress */
static pid_t pgrp; /* our process group */
static long w_secs; /* -w: retry delay */
static int family = PF_UNSPEC; /* -[46]: address family to use */
@@ -199,12 +200,33 @@ struct xferstat {
};
/*
+ * Format a number of seconds as either XXdYYh, XXhYYm, XXmYYs, or XXs
+ * depending on its magnitude
+ */
+static void
+stat_seconds(char *str, size_t strsz, long seconds)
+{
+
+ if (seconds > 86400)
+ snprintf(str, strsz, "%02ldd%02ldh",
+ seconds / 86400, (seconds % 86400) / 3600);
+ else if (seconds > 3600)
+ snprintf(str, strsz, "%02ldh%02ldm",
+ seconds / 3600, (seconds % 3600) / 60);
+ else if (seconds > 60)
+ snprintf(str, strsz, "%02ldm%02lds",
+ seconds / 60, seconds % 60);
+ else
+ snprintf(str, strsz, " %02lds",
+ seconds);
+}
+
+/*
* Compute and display ETA
*/
-static const char *
-stat_eta(struct xferstat *xs)
+static void
+stat_eta(char *str, size_t strsz, const struct xferstat *xs)
{
- static char str[16];
long elapsed, eta;
off_t received, expected;
@@ -212,55 +234,47 @@ stat_eta(struct xferstat *xs)
received = xs->rcvd - xs->offset;
expected = xs->size - xs->rcvd;
eta = (long)((double)elapsed * expected / received);
- if (eta > 3600)
- snprintf(str, sizeof str, "%02ldh%02ldm",
- eta / 3600, (eta % 3600) / 60);
- else if (eta > 0)
- snprintf(str, sizeof str, "%02ldm%02lds",
- eta / 60, eta % 60);
+ if (eta > 0)
+ stat_seconds(str, strsz, eta);
else
- snprintf(str, sizeof str, "%02ldm%02lds",
- elapsed / 60, elapsed % 60);
- return (str);
+ stat_seconds(str, strsz, elapsed);
}
/*
* Format a number as "xxxx YB" where Y is ' ', 'k', 'M'...
*/
static const char *prefixes = " kMGTP";
-static const char *
-stat_bytes(off_t bytes)
+static void
+stat_bytes(char *str, size_t strsz, off_t bytes)
{
- static char str[16];
const char *prefix = prefixes;
while (bytes > 9999 && prefix[1] != '\0') {
bytes /= 1024;
prefix++;
}
- snprintf(str, sizeof str, "%4jd %cB", (intmax_t)bytes, *prefix);
- return (str);
+ snprintf(str, strsz, "%4ju %cB", (uintmax_t)bytes, *prefix);
}
/*
* Compute and display transfer rate
*/
-static const char *
-stat_bps(struct xferstat *xs)
+static void
+stat_bps(char *str, size_t strsz, struct xferstat *xs)
{
- static char str[16];
+ char bytes[16];
double delta, bps;
- delta = (xs->last.tv_sec + (xs->last.tv_usec / 1.e6))
- - (xs->last2.tv_sec + (xs->last2.tv_usec / 1.e6));
+ delta = ((double)xs->last.tv_sec + (xs->last.tv_usec / 1.e6))
+ - ((double)xs->last2.tv_sec + (xs->last2.tv_usec / 1.e6));
if (delta == 0.0) {
- snprintf(str, sizeof str, "?? Bps");
+ snprintf(str, strsz, "?? Bps");
} else {
bps = (xs->rcvd - xs->lastrcvd) / delta;
- snprintf(str, sizeof str, "%sps", stat_bytes((off_t)bps));
+ stat_bytes(bytes, sizeof bytes, (off_t)bps);
+ snprintf(str, strsz, "%sps", bytes);
}
- return (str);
}
/*
@@ -269,11 +283,12 @@ stat_bps(struct xferstat *xs)
static void
stat_display(struct xferstat *xs, int force)
{
+ char bytes[16], bps[16], eta[16];
struct timeval now;
int ctty_pgrp;
/* check if we're the foreground process */
- if (ioctl(STDERR_FILENO, TIOCGPGRP, &ctty_pgrp) == -1 ||
+ if (ioctl(STDERR_FILENO, TIOCGPGRP, &ctty_pgrp) != 0 ||
(pid_t)ctty_pgrp != pgrp)
return;
@@ -284,26 +299,31 @@ stat_display(struct xferstat *xs, int force)
xs->last = now;
fprintf(stderr, "\r%-46.46s", xs->name);
- if (xs->size <= 0) {
- setproctitle("%s [%s]", xs->name, stat_bytes(xs->rcvd));
- fprintf(stderr, " %s", stat_bytes(xs->rcvd));
+ if (xs->rcvd >= xs->size) {
+ stat_bytes(bytes, sizeof bytes, xs->rcvd);
+ setproctitle("%s [%s]", xs->name, bytes);
+ fprintf(stderr, " %s", bytes);
} else {
+ stat_bytes(bytes, sizeof bytes, xs->size);
setproctitle("%s [%d%% of %s]", xs->name,
(int)((100.0 * xs->rcvd) / xs->size),
- stat_bytes(xs->size));
+ bytes);
fprintf(stderr, "%3d%% of %s",
(int)((100.0 * xs->rcvd) / xs->size),
- stat_bytes(xs->size));
+ bytes);
}
if (force == 2) {
xs->lastrcvd = xs->offset;
xs->last2 = xs->start;
}
- fprintf(stderr, " %s", stat_bps(xs));
+ stat_bps(bps, sizeof bps, xs);
+ fprintf(stderr, " %s", bps);
if ((xs->size > 0 && xs->rcvd > 0 &&
xs->last.tv_sec >= xs->start.tv_sec + 3) ||
- force == 2)
- fprintf(stderr, " %s", stat_eta(xs));
+ force == 2) {
+ stat_eta(eta, sizeof eta, xs);
+ fprintf(stderr, " %s", eta);
+ }
xs->lastrcvd = xs->rcvd;
}
@@ -313,14 +333,16 @@ stat_display(struct xferstat *xs, int force)
static void
stat_start(struct xferstat *xs, const char *name, off_t size, off_t offset)
{
+
+ memset(xs, 0, sizeof *xs);
snprintf(xs->name, sizeof xs->name, "%s", name);
gettimeofday(&xs->start, NULL);
- xs->last.tv_sec = xs->last.tv_usec = 0;
+ xs->last2 = xs->last = xs->start;
xs->size = size;
xs->offset = offset;
xs->rcvd = offset;
xs->lastrcvd = offset;
- if (v_tty && v_level > 0)
+ if (v_progress)
stat_display(xs, 1);
else if (v_level > 0)
fprintf(stderr, "%-46s", xs->name);
@@ -332,8 +354,9 @@ stat_start(struct xferstat *xs, const char *name, off_
static void
stat_update(struct xferstat *xs, off_t rcvd)
{
+
xs->rcvd = rcvd;
- if (v_tty && v_level > 0)
+ if (v_progress)
stat_display(xs, 0);
}
@@ -343,13 +366,17 @@ stat_update(struct xferstat *xs, off_t rcvd)
static void
stat_end(struct xferstat *xs)
{
+ char bytes[16], bps[16], eta[16];
+
gettimeofday(&xs->last, NULL);
- if (v_tty && v_level > 0) {
+ if (v_progress) {
stat_display(xs, 2);
putc('\n', stderr);
} else if (v_level > 0) {
- fprintf(stderr, " %s %s\n",
- stat_bytes(xs->size), stat_bps(xs));
+ stat_bytes(bytes, sizeof bytes, xs->rcvd);
+ stat_bps(bps, sizeof bps, xs);
+ stat_eta(eta, sizeof eta, xs);
+ fprintf(stderr, " %s %s %s\n", bytes, bps, eta);
}
}
@@ -552,9 +579,10 @@ fetch(char *URL, const char *path)
goto signal;
if (f == NULL) {
warnx("%s: %s", URL, fetchLastErrString);
- if (i_flag && strcmp(url->scheme, SCHEME_HTTP) == 0
- && fetchLastErrCode == FETCH_OK
- && strcmp(fetchLastErrString, "Not Modified") == 0) {
+ if (i_flag && (strcmp(url->scheme, SCHEME_HTTP) == 0 ||
+ strcmp(url->scheme, SCHEME_HTTPS) == 0) &&
+ fetchLastErrCode == FETCH_OK &&
+ strcmp(fetchLastErrString, "Not Modified") == 0) {
/* HTTP Not Modified Response, return OK. */
r = 0;
goto done;
@@ -1109,7 +1137,8 @@ main(int argc, char *argv[])
/* check if output is to a tty (for progress report) */
v_tty = isatty(STDERR_FILENO);
- if (v_tty)
+ v_progress = v_tty && v_level > 0;
+ if (v_progress)
pgrp = getpgrp();
r = 0;
More information about the svn-src-stable
mailing list