summaryrefslogtreecommitdiff
path: root/lib/libfetch
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2001-12-18 09:44:50 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2001-12-18 09:44:50 +0000
commit8442833a0216fb360923c7a6ebb2936cee5b7104 (patch)
tree87c3419ff0f8c2d1ac5f6928c6d00020f5cf790e /lib/libfetch
parent42aca1696991632c266a1a25074668b04ee5ccf3 (diff)
Notes
Diffstat (limited to 'lib/libfetch')
-rw-r--r--lib/libfetch/Makefile45
-rw-r--r--lib/libfetch/common.c16
-rw-r--r--lib/libfetch/common.h34
-rw-r--r--lib/libfetch/fetch.325
-rw-r--r--lib/libfetch/fetch.c20
-rw-r--r--lib/libfetch/fetch.h9
-rw-r--r--lib/libfetch/file.c15
-rw-r--r--lib/libfetch/ftp.c164
-rw-r--r--lib/libfetch/http.c76
9 files changed, 232 insertions, 172 deletions
diff --git a/lib/libfetch/Makefile b/lib/libfetch/Makefile
index 14b03316ce7d..9dc1b9f03655 100644
--- a/lib/libfetch/Makefile
+++ b/lib/libfetch/Makefile
@@ -2,18 +2,18 @@
MAINTAINER= des@freebsd.org
LIB= fetch
-CFLAGS+= -I. -Wall -pedantic
+WARNS?= 2
+CFLAGS+= -I.
CFLAGS+= -DINET6
-.if !defined(DEBUG)
-CFLAGS+= -DNDEBUG
-.endif
SRCS= fetch.c common.c ftp.c http.c file.c \
ftperr.h httperr.h
INCS= fetch.h
MAN= fetch.3
CLEANFILES= ftperr.h httperr.h
-SHLIB_MAJOR= 2
+NO_WERROR= yes
+
+SHLIB_MAJOR= 3
SHLIB_MINOR= 0
ftperr.h: ftp.errors
@@ -38,12 +38,33 @@ httperr.h: http.errors
@echo " { -1, FETCH_UNKNOWN, \"Unknown HTTP error\" }" >> ${.TARGET}
@echo "};" >> ${.TARGET}
-.for MP in fetchFreeURL fetchGet fetchGetFTP fetchGetFile fetchGetHTTP \
-fetchGetURL fetchList fetchListFTP fetchListFile fetchListHTTP fetchListURL \
-fetchMakeURL fetchParseURL fetchPut fetchPutFTP fetchPutFile fetchPutHTTP \
-fetchPutURL fetchStat fetchStatFTP fetchStatFile fetchStatHTTP fetchStatURL \
-fetchXGet fetchXGetFTP fetchXGetFile fetchXGetHTTP fetchXGetURL
-MLINKS+= fetch.3 ${MP}.3
-.endfor
+MLINKS+= fetch.3 fetchFreeURL.3
+MLINKS+= fetch.3 fetchGet.3
+MLINKS+= fetch.3 fetchGetFTP.3
+MLINKS+= fetch.3 fetchGetFile.3
+MLINKS+= fetch.3 fetchGetHTTP.3
+MLINKS+= fetch.3 fetchGetURL.3
+MLINKS+= fetch.3 fetchList.3
+MLINKS+= fetch.3 fetchListFTP.3
+MLINKS+= fetch.3 fetchListFile.3
+MLINKS+= fetch.3 fetchListHTTP.3
+MLINKS+= fetch.3 fetchListURL.3
+MLINKS+= fetch.3 fetchMakeURL.3
+MLINKS+= fetch.3 fetchParseURL.3
+MLINKS+= fetch.3 fetchPut.3
+MLINKS+= fetch.3 fetchPutFTP.3
+MLINKS+= fetch.3 fetchPutFile.3
+MLINKS+= fetch.3 fetchPutHTTP.3
+MLINKS+= fetch.3 fetchPutURL.3
+MLINKS+= fetch.3 fetchStat.3
+MLINKS+= fetch.3 fetchStatFTP.3
+MLINKS+= fetch.3 fetchStatFile.3
+MLINKS+= fetch.3 fetchStatHTTP.3
+MLINKS+= fetch.3 fetchStatURL.3
+MLINKS+= fetch.3 fetchXGet.3
+MLINKS+= fetch.3 fetchXGetFTP.3
+MLINKS+= fetch.3 fetchXGetFile.3
+MLINKS+= fetch.3 fetchXGetHTTP.3
+MLINKS+= fetch.3 fetchXGetURL.3
.include <bsd.lib.mk>
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c
index 34981e94ac3a..b39839aa39e6 100644
--- a/lib/libfetch/common.c
+++ b/lib/libfetch/common.c
@@ -24,10 +24,11 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
@@ -343,9 +344,12 @@ _fetch_putln(int fd, const char *str, size_t len)
iov[0].iov_len = len;
iov[1].iov_base = (char *)ENDL;
iov[1].iov_len = sizeof ENDL;
+ len += sizeof ENDL;
wlen = writev(fd, iov, 2);
+ if (wlen < 0 || (size_t)wlen != len)
+ return -1;
DEBUG(fprintf(stderr, "\033[1m>>> %s\n\033[m", str));
- return (wlen != len);
+ return 0;
}
@@ -353,7 +357,7 @@ _fetch_putln(int fd, const char *str, size_t len)
int
_fetch_add_entry(struct url_ent **p, int *size, int *len,
- const char *name, struct url_stat *stat)
+ const char *name, struct url_stat *us)
{
struct url_ent *tmp;
@@ -381,8 +385,8 @@ _fetch_add_entry(struct url_ent **p, int *size, int *len,
}
tmp = *p + *len;
- snprintf(tmp->name, MAXPATHLEN, "%s", name);
- bcopy(stat, &tmp->stat, sizeof *stat);
+ snprintf(tmp->name, PATH_MAX, "%s", name);
+ bcopy(us, &tmp->stat, sizeof *us);
(*len)++;
(++tmp)->name[0] = 0;
diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h
index 0c67b28e8cec..84b2e01478e7 100644
--- a/lib/libfetch/common.h
+++ b/lib/libfetch/common.h
@@ -42,16 +42,16 @@ struct fetcherr {
const char *string;
};
-void _fetch_seterr(struct fetcherr *p, int e);
+void _fetch_seterr(struct fetcherr *, int);
void _fetch_syserr(void);
-void _fetch_info(const char *fmt, ...);
+void _fetch_info(const char *, ...);
int _fetch_default_port(const char *);
int _fetch_default_proxy_port(const char *);
-int _fetch_connect(const char *host, int port, int af, int verbose);
-int _fetch_getln(int fd, char **buf, size_t *size, size_t *len);
-int _fetch_putln(int fd, const char *str, size_t len);
-int _fetch_add_entry(struct url_ent **p, int *size, int *len,
- const char *name, struct url_stat *stat);
+int _fetch_connect(const char *, int, int, int);
+int _fetch_getln(int, char **, size_t *, size_t *);
+int _fetch_putln(int, const char *, size_t);
+int _fetch_add_entry(struct url_ent **, int *, int *,
+ const char *, struct url_stat *);
#define _ftp_seterr(n) _fetch_seterr(_ftp_errlist, n)
#define _http_seterr(n) _fetch_seterr(_http_errlist, n)
@@ -59,22 +59,26 @@ int _fetch_add_entry(struct url_ent **p, int *size, int *len,
#define _url_seterr(n) _fetch_seterr(_url_errlist, n)
#ifndef NDEBUG
-#define DEBUG(x) do x; while (0)
+#define DEBUG(x) do { if (fetchDebug) { x; } } while (0)
#else
#define DEBUG(x) do { } while (0)
#endif
/*
- * I don't really like exporting _http_request() from http.c, but ftp.c
- * occasionally needs to use an HTTP proxy, and this saves me from adding
- * a lot of special-case code to http.c to handle those cases.
+ * I don't really like exporting _http_request() and _ftp_request(),
+ * but the HTTP and FTP code occasionally needs to cross-call
+ * eachother, and this saves me from adding a lot of special-case code
+ * to handle those cases.
*
- * Note that _http_request() frees purl, which is way ugly but saves us a
+ * Note that _*_request() free purl, which is way ugly but saves us a
* whole lot of trouble.
*/
-FILE *_http_request(struct url *URL, const char *op,
- struct url_stat *us, struct url *purl,
- const char *flags);
+FILE *_http_request(struct url *, const char *,
+ struct url_stat *, struct url *,
+ const char *);
+FILE *_ftp_request(struct url *, const char *,
+ struct url_stat *, struct url *,
+ const char *);
/*
* Check whether a particular flag is set
diff --git a/lib/libfetch/fetch.3 b/lib/libfetch/fetch.3
index f8e87c4f548c..fe7c175e0690 100644
--- a/lib/libfetch/fetch.3
+++ b/lib/libfetch/fetch.3
@@ -358,6 +358,31 @@ method in a manner consistent with the rest of the
library,
.Fn fetchPutHTTP
is currently unimplemented.
+.Sh AUTHENTICATION
+Apart from setting the appropriate environment variables and
+specifying the user name and password in the URL or the
+.Vt struct url ,
+the calling program has the option of defining an authentication
+function with the following prototype:
+.Pp
+.Ft int
+.Fn myAuthMethod "struct url *u"
+.Pp
+The callback function should fill in the
+.Fa user
+and
+.Fa pwd
+fields in the provided
+.Vt struct url
+and return 0 on success, or any other value to indicate failure.
+.Pp
+To register the authentication callback, simply set
+.Va fetchAuthMethod
+to point at it.
+The callback will be used whenever a site requires authentication and
+the appropriate environment variables aren't set.
+.Pp
+This interface is experimental and may be subject to change.
.Sh RETURN VALUES
.Fn fetchParseURL
returns a pointer to a
diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c
index de23f0045246..9941ab528bde 100644
--- a/lib/libfetch/fetch.c
+++ b/lib/libfetch/fetch.c
@@ -24,10 +24,11 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/errno.h>
@@ -39,11 +40,12 @@
#include "fetch.h"
#include "common.h"
-
+auth_t fetchAuthMethod;
int fetchLastErrCode;
char fetchLastErrString[MAXERRSTRING];
int fetchTimeout;
int fetchRestartCalls = 1;
+int fetchDebug;
/*** Local data **************************************************************/
@@ -307,7 +309,7 @@ fetchParseURL(const char *URL)
/* scheme name */
if ((p = strstr(URL, ":/"))) {
- snprintf(u->scheme, URL_SCHEMELEN+1, "%.*s", p - URL, URL);
+ snprintf(u->scheme, URL_SCHEMELEN+1, "%.*s", (int)(p - URL), URL);
URL = ++p;
/*
* Only one slash: no host, leave slash as part of document
@@ -318,7 +320,9 @@ fetchParseURL(const char *URL)
} else {
p = URL;
}
- if (!*URL || *URL == '/')
+ if (!*URL || *URL == '/' || *URL == '.' ||
+ (u->scheme[0] == '\0' &&
+ strchr(URL, '/') == NULL && strchr(URL, ':') == NULL))
goto nohost;
p = strpbrk(URL, "/@");
@@ -335,8 +339,10 @@ fetchParseURL(const char *URL)
u->pwd[i++] = *q;
p++;
- } else p = URL;
-
+ } else {
+ p = URL;
+ }
+
/* hostname */
#ifdef INET6
if (*p == '[' && (q = strchr(p + 1, ']')) != NULL &&
diff --git a/lib/libfetch/fetch.h b/lib/libfetch/fetch.h
index dc5fc05b4702..3899ccac3cfe 100644
--- a/lib/libfetch/fetch.h
+++ b/lib/libfetch/fetch.h
@@ -55,7 +55,7 @@ struct url_stat {
};
struct url_ent {
- char name[MAXPATHLEN];
+ char name[PATH_MAX];
struct url_stat stat;
};
@@ -125,6 +125,10 @@ struct url *fetchMakeURL(const char *, const char *, int,
struct url *fetchParseURL(const char *);
void fetchFreeURL(struct url *);
+/* Authentication */
+typedef int (*auth_t)(struct url *);
+extern auth_t fetchAuthMethod;
+
/* Last error code */
extern int fetchLastErrCode;
#define MAXERRSTRING 256
@@ -132,4 +136,7 @@ extern char fetchLastErrString[MAXERRSTRING];
extern int fetchTimeout;
extern int fetchRestartCalls;
+/* Extra verbosity */
+extern int fetchDebug;
+
#endif
diff --git a/lib/libfetch/file.c b/lib/libfetch/file.c
index 2db091db3f25..73ff4d2bb1d3 100644
--- a/lib/libfetch/file.c
+++ b/lib/libfetch/file.c
@@ -24,10 +24,11 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/stat.h>
@@ -51,7 +52,7 @@ fetchXGetFile(struct url *u, struct url_stat *us, const char *flags)
if (f == NULL)
_fetch_syserr();
- if (u->offset && fseek(f, u->offset, SEEK_SET) == -1) {
+ if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) {
fclose(f);
_fetch_syserr();
}
@@ -78,7 +79,7 @@ fetchPutFile(struct url *u, const char *flags)
if (f == NULL)
_fetch_syserr();
- if (u->offset && fseek(f, u->offset, SEEK_SET) == -1) {
+ if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) {
fclose(f);
_fetch_syserr();
}
@@ -104,20 +105,20 @@ _fetch_stat_file(const char *fn, struct url_stat *us)
}
int
-fetchStatFile(struct url *u, struct url_stat *us, const char *flags)
+fetchStatFile(struct url *u, struct url_stat *us, const char *flags __unused)
{
return _fetch_stat_file(u->doc, us);
}
struct url_ent *
-fetchListFile(struct url *u, const char *flags)
+fetchListFile(struct url *u, const char *flags __unused)
{
DIR *dir;
struct dirent *de;
struct url_stat us;
struct url_ent *ue;
int size, len;
- char fn[MAXPATHLEN], *p;
+ char fn[PATH_MAX], *p;
int l;
if ((dir = opendir(u->doc)) == NULL) {
diff --git a/lib/libfetch/ftp.c b/lib/libfetch/ftp.c
index f1ffbf2dda0a..28861b57316a 100644
--- a/lib/libfetch/ftp.c
+++ b/lib/libfetch/ftp.c
@@ -24,10 +24,11 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* Portions of this code were taken from or based on ftpio.c:
*
@@ -266,7 +267,7 @@ _ftp_stat(int cd, const char *file, struct url_stat *us)
}
if (us->size == 0)
us->size = -1;
- DEBUG(fprintf(stderr, "size: [\033[1m%lld\033[m]\n", us->size));
+ DEBUG(fprintf(stderr, "size: [\033[1m%lld\033[m]\n", (long long)us->size));
if ((e = _ftp_cmd(cd, "MDTM %s", s)) != FTP_FILE_STATUS) {
_ftp_seterr(e);
@@ -384,7 +385,7 @@ _ftp_writefn(void *v, const char *buf, int len)
}
static fpos_t
-_ftp_seekfn(void *v, fpos_t pos, int whence)
+_ftp_seekfn(void *v, fpos_t pos __unused, int whence __unused)
{
struct ftpio *io;
@@ -449,7 +450,7 @@ static FILE *
_ftp_transfer(int cd, const char *oper, const char *file,
int mode, off_t offset, const char *flags)
{
- struct sockaddr_storage sin;
+ struct sockaddr_storage sa;
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin4;
int low, pasv, verbose;
@@ -469,14 +470,14 @@ _ftp_transfer(int cd, const char *oper, const char *file,
strncasecmp(s, "no", 2) != 0);
/* find our own address, bind, and listen */
- l = sizeof sin;
- if (getsockname(cd, (struct sockaddr *)&sin, &l) == -1)
+ l = sizeof sa;
+ if (getsockname(cd, (struct sockaddr *)&sa, &l) == -1)
goto sysouch;
- if (sin.ss_family == AF_INET6)
- unmappedaddr((struct sockaddr_in6 *)&sin);
+ if (sa.ss_family == AF_INET6)
+ unmappedaddr((struct sockaddr_in6 *)&sa);
/* open data socket */
- if ((sd = socket(sin.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ if ((sd = socket(sa.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
_fetch_syserr();
return NULL;
}
@@ -484,13 +485,13 @@ _ftp_transfer(int cd, const char *oper, const char *file,
if (pasv) {
u_char addr[64];
char *ln, *p;
- int i;
+ unsigned int i;
int port;
/* send PASV command */
if (verbose)
_fetch_info("setting passive mode");
- switch (sin.ss_family) {
+ switch (sa.ss_family) {
case AF_INET:
if ((e = _ftp_cmd(cd, "PASV")) != FTP_PASSIVE_MODE)
goto ouch;
@@ -554,14 +555,14 @@ _ftp_transfer(int cd, const char *oper, const char *file,
goto sysouch;
/* construct sockaddr for data socket */
- l = sizeof sin;
- if (getpeername(cd, (struct sockaddr *)&sin, &l) == -1)
+ l = sizeof sa;
+ if (getpeername(cd, (struct sockaddr *)&sa, &l) == -1)
goto sysouch;
- if (sin.ss_family == AF_INET6)
- unmappedaddr((struct sockaddr_in6 *)&sin);
- switch (sin.ss_family) {
+ if (sa.ss_family == AF_INET6)
+ unmappedaddr((struct sockaddr_in6 *)&sa);
+ switch (sa.ss_family) {
case AF_INET6:
- sin6 = (struct sockaddr_in6 *)&sin;
+ sin6 = (struct sockaddr_in6 *)&sa;
if (e == FTP_EPASSIVE_MODE)
sin6->sin6_port = htons(port);
else {
@@ -570,7 +571,7 @@ _ftp_transfer(int cd, const char *oper, const char *file,
}
break;
case AF_INET:
- sin4 = (struct sockaddr_in *)&sin;
+ sin4 = (struct sockaddr_in *)&sa;
if (e == FTP_EPASSIVE_MODE)
sin4->sin_port = htons(port);
else {
@@ -586,7 +587,7 @@ _ftp_transfer(int cd, const char *oper, const char *file,
/* connect to data port */
if (verbose)
_fetch_info("opening data connection");
- if (connect(sd, (struct sockaddr *)&sin, sin.ss_len) == -1)
+ if (connect(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
goto sysouch;
/* make the server initiate the transfer */
@@ -603,9 +604,9 @@ _ftp_transfer(int cd, const char *oper, const char *file,
char *ap;
char hname[INET6_ADDRSTRLEN];
- switch (sin.ss_family) {
+ switch (sa.ss_family) {
case AF_INET6:
- ((struct sockaddr_in6 *)&sin)->sin6_port = 0;
+ ((struct sockaddr_in6 *)&sa)->sin6_port = 0;
#ifdef IPV6_PORTRANGE
arg = low ? IPV6_PORTRANGE_DEFAULT : IPV6_PORTRANGE_HIGH;
if (setsockopt(sd, IPPROTO_IPV6, IPV6_PORTRANGE,
@@ -614,7 +615,7 @@ _ftp_transfer(int cd, const char *oper, const char *file,
#endif
break;
case AF_INET:
- ((struct sockaddr_in *)&sin)->sin_port = 0;
+ ((struct sockaddr_in *)&sa)->sin_port = 0;
arg = low ? IP_PORTRANGE_DEFAULT : IP_PORTRANGE_HIGH;
if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
(char *)&arg, sizeof arg) == -1)
@@ -623,17 +624,17 @@ _ftp_transfer(int cd, const char *oper, const char *file,
}
if (verbose)
_fetch_info("binding data socket");
- if (bind(sd, (struct sockaddr *)&sin, sin.ss_len) == -1)
+ if (bind(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
goto sysouch;
if (listen(sd, 1) == -1)
goto sysouch;
/* find what port we're on and tell the server */
- if (getsockname(sd, (struct sockaddr *)&sin, &l) == -1)
+ if (getsockname(sd, (struct sockaddr *)&sa, &l) == -1)
goto sysouch;
- switch (sin.ss_family) {
+ switch (sa.ss_family) {
case AF_INET:
- sin4 = (struct sockaddr_in *)&sin;
+ sin4 = (struct sockaddr_in *)&sa;
a = ntohl(sin4->sin_addr.s_addr);
p = ntohs(sin4->sin_port);
e = _ftp_cmd(cd, "PORT %d,%d,%d,%d,%d,%d",
@@ -644,8 +645,8 @@ _ftp_transfer(int cd, const char *oper, const char *file,
case AF_INET6:
#define UC(b) (((int)b)&0xff)
e = -1;
- sin6 = (struct sockaddr_in6 *)&sin;
- if (getnameinfo((struct sockaddr *)&sin, sin.ss_len,
+ sin6 = (struct sockaddr_in6 *)&sa;
+ if (getnameinfo((struct sockaddr *)&sa, sa.ss_len,
hname, sizeof(hname),
NULL, 0, NI_NUMERICHOST) == 0) {
e = _ftp_cmd(cd, "EPRT |%d|%s|%d|", 2, hname,
@@ -717,7 +718,7 @@ ouch:
static int
_ftp_authenticate(int cd, struct url *url, struct url *purl)
{
- char *user, *pwd, *logname;
+ const char *user, *pwd, *logname;
char pbuf[MAXHOSTNAMELEN + MAXLOGNAME + 1];
int e, len;
@@ -744,7 +745,10 @@ _ftp_authenticate(int cd, struct url *url, struct url *purl)
if (!pwd || !*pwd) {
if ((logname = getlogin()) == 0)
logname = FTP_ANONYMOUS_USER;
- len = snprintf(pbuf, MAXLOGNAME + 1, "%s@", logname);
+ if ((len = snprintf(pbuf, MAXLOGNAME + 1, "%s@", logname)) < 0)
+ len = 0;
+ else if (len > MAXLOGNAME)
+ len = MAXLOGNAME;
gethostname(pbuf + len, sizeof pbuf - len);
pwd = pbuf;
}
@@ -902,22 +906,26 @@ _ftp_get_proxy(void)
}
/*
- * Get and stat file
+ * Process an FTP request
*/
FILE *
-fetchXGetFTP(struct url *url, struct url_stat *us, const char *flags)
+_ftp_request(struct url *url, const char *op, struct url_stat *us,
+ struct url *purl, const char *flags)
{
- struct url *purl;
int cd;
-
- /* get the proxy URL, and check if we should use HTTP instead */
- if (!CHECK_FLAG('d') && (purl = _ftp_get_proxy()) != NULL) {
- if (strcasecmp(purl->scheme, SCHEME_HTTP) == 0)
+
+ /* check if we should use HTTP instead */
+ if (purl && strcasecmp(purl->scheme, SCHEME_HTTP) == 0) {
+ if (strcmp(op, "STAT") == 0)
+ return _http_request(url, "HEAD", us, purl, flags);
+ else if (strcmp(op, "RETR") == 0)
return _http_request(url, "GET", us, purl, flags);
- } else {
- purl = NULL;
+ /*
+ * Our HTTP code doesn't support PUT requests yet, so try a
+ * direct connection.
+ */
}
-
+
/* connect to server */
cd = _ftp_cached_connect(url, purl, flags);
if (purl)
@@ -934,9 +942,22 @@ fetchXGetFTP(struct url *url, struct url_stat *us, const char *flags)
&& fetchLastErrCode != FETCH_PROTO
&& fetchLastErrCode != FETCH_UNAVAIL)
return NULL;
+
+ /* just a stat */
+ if (strcmp(op, "STAT") == 0)
+ return (FILE *)1; /* bogus return value */
/* initiate the transfer */
- return _ftp_transfer(cd, "RETR", url->doc, O_RDONLY, url->offset, flags);
+ return _ftp_transfer(cd, op, url->doc, O_RDONLY, url->offset, flags);
+}
+
+/*
+ * Get and stat file
+ */
+FILE *
+fetchXGetFTP(struct url *url, struct url_stat *us, const char *flags)
+{
+ return _ftp_request(url, "RETR", us, _ftp_get_proxy(), flags);
}
/*
@@ -954,32 +975,9 @@ fetchGetFTP(struct url *url, const char *flags)
FILE *
fetchPutFTP(struct url *url, const char *flags)
{
- struct url *purl;
- int cd;
- /* get the proxy URL, and check if we should use HTTP instead */
- if (!CHECK_FLAG('d') && (purl = _ftp_get_proxy()) != NULL) {
- if (strcasecmp(purl->scheme, SCHEME_HTTP) == 0)
- /* XXX HTTP PUT is not implemented, so try without the proxy */
- purl = NULL;
- } else {
- purl = NULL;
- }
-
- /* connect to server */
- cd = _ftp_cached_connect(url, purl, flags);
- if (purl)
- fetchFreeURL(purl);
- if (cd == NULL)
- return NULL;
-
- /* change directory */
- if (_ftp_cwd(cd, url->doc) == -1)
- return NULL;
-
- /* initiate the transfer */
- return _ftp_transfer(cd, CHECK_FLAG('a') ? "APPE" : "STOR",
- url->doc, O_WRONLY, url->offset, flags);
+ return _ftp_request(url, CHECK_FLAG('a') ? "APPE" : "STOR", NULL,
+ _ftp_get_proxy(), flags);
}
/*
@@ -988,43 +986,17 @@ fetchPutFTP(struct url *url, const char *flags)
int
fetchStatFTP(struct url *url, struct url_stat *us, const char *flags)
{
- struct url *purl;
- int cd;
-
- /* get the proxy URL, and check if we should use HTTP instead */
- if (!CHECK_FLAG('d') && (purl = _ftp_get_proxy()) != NULL) {
- if (strcasecmp(purl->scheme, SCHEME_HTTP) == 0) {
- FILE *f;
-
- if ((f = _http_request(url, "HEAD", us, purl, flags)) == NULL)
- return -1;
- fclose(f);
- return 0;
- }
- } else {
- purl = NULL;
- }
- /* connect to server */
- cd = _ftp_cached_connect(url, purl, flags);
- if (purl)
- fetchFreeURL(purl);
- if (cd == NULL)
- return NULL;
-
- /* change directory */
- if (_ftp_cwd(cd, url->doc) == -1)
+ if (_ftp_request(url, "STAT", us, _ftp_get_proxy(), flags) == NULL)
return -1;
-
- /* stat file */
- return _ftp_stat(cd, url->doc, us);
+ return 0;
}
/*
* List a directory
*/
struct url_ent *
-fetchListFTP(struct url *url, const char *flags)
+fetchListFTP(struct url *url __unused, const char *flags __unused)
{
warnx("fetchListFTP(): not implemented");
return NULL;
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index e1e0721c4d8d..10c3a78501be 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -24,10 +24,11 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
/*
* The following copyright applies to the base64 code:
*
@@ -91,7 +92,7 @@ extern char *__progname; /* XXX not portable */
#define HTTP_MOVED_TEMP 302
#define HTTP_SEE_OTHER 303
#define HTTP_NEED_AUTH 401
-#define HTTP_NEED_PROXY_AUTH 403
+#define HTTP_NEED_PROXY_AUTH 407
#define HTTP_PROTOCOL_ERROR 999
#define HTTP_REDIRECT(xyz) ((xyz) == HTTP_MOVED_PERM \
@@ -109,13 +110,13 @@ struct cookie
int fd;
char *buf;
size_t b_size;
- size_t b_len;
+ ssize_t b_len;
int b_pos;
int eof;
int error;
- long chunksize;
+ size_t chunksize;
#ifndef NDEBUG
- long total;
+ size_t total;
#endif
};
@@ -142,13 +143,16 @@ _http_new_chunk(struct cookie *c)
c->chunksize = c->chunksize * 16 + 10 + tolower(*p) - 'a';
#ifndef NDEBUG
- c->total += c->chunksize;
- if (c->chunksize == 0)
- fprintf(stderr, "\033[1m_http_fillbuf(): "
- "end of last chunk\033[m\n");
- else
- fprintf(stderr, "\033[1m_http_fillbuf(): "
- "new chunk: %ld (%ld)\033[m\n", c->chunksize, c->total);
+ if (fetchDebug) {
+ c->total += c->chunksize;
+ if (c->chunksize == 0)
+ fprintf(stderr, "\033[1m_http_fillbuf(): "
+ "end of last chunk\033[m\n");
+ else
+ fprintf(stderr, "\033[1m_http_fillbuf(): "
+ "new chunk: %lu (%lu)\033[m\n",
+ (unsigned long)c->chunksize, (unsigned long)c->total);
+ }
#endif
return c->chunksize;
@@ -296,11 +300,11 @@ typedef enum {
hdr_location,
hdr_transfer_encoding,
hdr_www_authenticate
-} hdr;
+} hdr_t;
/* Names of interesting headers */
static struct {
- hdr num;
+ hdr_t num;
const char *name;
} hdr_names[] = {
{ hdr_content_length, "Content-Length" },
@@ -403,7 +407,7 @@ _http_match(const char *str, const char *hdr)
/*
* Get the next header and return the appropriate symbolic code.
*/
-static hdr
+static hdr_t
_http_next_header(int fd, const char **p)
{
int i;
@@ -461,7 +465,10 @@ _http_parse_length(const char *p, off_t *length)
for (len = 0; *p && isdigit(*p); ++p)
len = len * 10 + (*p - '0');
- DEBUG(fprintf(stderr, "content length: [\033[1m%lld\033[m]\n", len));
+ if (*p)
+ return -1;
+ DEBUG(fprintf(stderr, "content length: [\033[1m%lld\033[m]\n",
+ (long long)len));
*length = len;
return 0;
}
@@ -472,7 +479,7 @@ _http_parse_length(const char *p, off_t *length)
static int
_http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size)
{
- int first, last, len;
+ off_t first, last, len;
if (strncasecmp(p, "bytes ", 6) != 0)
return -1;
@@ -486,10 +493,10 @@ _http_parse_range(const char *p, off_t *offset, off_t *length, off_t *size)
return -1;
for (len = 0, ++p; *p && isdigit(*p); ++p)
len = len * 10 + *p - '0';
- if (len < last - first + 1)
+ if (*p || len < last - first + 1)
return -1;
- DEBUG(fprintf(stderr, "content range: [\033[1m%d-%d/%d\033[m]\n",
- first, last, len));
+ DEBUG(fprintf(stderr, "content range: [\033[1m%lld-%lld/%lld\033[m]\n",
+ (long long)first, (long long)last, (long long)len));
*offset = first;
*length = last - first + 1;
*size = len;
@@ -687,7 +694,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us,
time_t mtime;
const char *p;
FILE *f;
- hdr h;
+ hdr_t h;
char *host;
#ifdef INET6
char hbuf[MAXHOSTNAMELEN + 1];
@@ -723,6 +730,14 @@ _http_request(struct url *URL, const char *op, struct url_stat *us,
if (!url->port)
url->port = _fetch_default_port(url->scheme);
+ /* were we redirected to an FTP URL? */
+ if (purl == NULL && strcmp(url->scheme, SCHEME_FTP) == 0) {
+ if (strcmp(op, "GET") == 0)
+ return _ftp_request(url, "RETR", us, purl, flags);
+ else if (strcmp(op, "HEAD") == 0)
+ return _ftp_request(url, "STAT", us, purl, flags);
+ }
+
/* connect to server or proxy */
if ((fd = _http_connect(url, purl, flags)) == -1)
goto ouch;
@@ -768,7 +783,9 @@ _http_request(struct url *URL, const char *op, struct url_stat *us,
_http_basic_auth(fd, "Authorization", url->user, url->pwd);
else if ((p = getenv("HTTP_AUTH")) != NULL && *p != '\0')
_http_authorize(fd, "Authorization", p);
- else {
+ else if (fetchAuthMethod && fetchAuthMethod(url) == 0) {
+ _http_basic_auth(fd, "Authorization", url->user, url->pwd);
+ } else {
_http_seterr(HTTP_NEED_AUTH);
goto ouch;
}
@@ -780,7 +797,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us,
else
_http_cmd(fd, "User-Agent: %s " _LIBFETCH_VER, __progname);
if (url->offset)
- _http_cmd(fd, "Range: bytes=%lld-", url->offset);
+ _http_cmd(fd, "Range: bytes=%lld-", (long long)url->offset);
_http_cmd(fd, "Connection: close");
_http_cmd(fd, "");
@@ -792,6 +809,7 @@ _http_request(struct url *URL, const char *op, struct url_stat *us,
break;
case HTTP_MOVED_PERM:
case HTTP_MOVED_TEMP:
+ case HTTP_SEE_OTHER:
/*
* Not so fine, but we still have to read the headers to
* get the new location.
@@ -918,8 +936,10 @@ _http_request(struct url *URL, const char *op, struct url_stat *us,
goto ouch;
}
- DEBUG(fprintf(stderr, "offset %lld, length %lld, size %lld, clength %lld\n",
- offset, length, size, clength));
+ DEBUG(fprintf(stderr, "offset %lld, length %lld,"
+ " size %lld, clength %lld\n",
+ (long long)offset, (long long)length,
+ (long long)size, (long long)clength));
/* check for inconsistencies */
if (clength != -1 && length != -1 && clength != length) {
@@ -1003,7 +1023,7 @@ fetchGetHTTP(struct url *URL, const char *flags)
* Store a file by HTTP
*/
FILE *
-fetchPutHTTP(struct url *URL, const char *flags)
+fetchPutHTTP(struct url *URL __unused, const char *flags __unused)
{
warnx("fetchPutHTTP(): not implemented");
return NULL;
@@ -1027,7 +1047,7 @@ fetchStatHTTP(struct url *URL, struct url_stat *us, const char *flags)
* List a directory
*/
struct url_ent *
-fetchListHTTP(struct url *url, const char *flags)
+fetchListHTTP(struct url *url __unused, const char *flags __unused)
{
warnx("fetchListHTTP(): not implemented");
return NULL;