2000-08-28 02:34:02 +08:00
|
|
|
/** \ingroup rpmio
|
|
|
|
* \file rpmio/url.c
|
|
|
|
*/
|
|
|
|
|
1999-07-04 07:36:35 +08:00
|
|
|
#include "system.h"
|
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
#if !defined(__LCLINT__)
|
1999-07-04 07:36:35 +08:00
|
|
|
#include <netinet/in.h>
|
1999-09-13 04:43:23 +08:00
|
|
|
#endif /* __LCLINT__ */
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2000-06-10 05:24:37 +08:00
|
|
|
#include <rpmmacro.h>
|
|
|
|
#include <rpmmessages.h>
|
2000-06-10 02:57:23 +08:00
|
|
|
#include <rpmio_internal.h>
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
/*@access FD_t@*/ /* XXX compared with NULL */
|
|
|
|
/*@access urlinfo@*/
|
2000-11-01 00:18:34 +08:00
|
|
|
|
2000-02-24 13:41:47 +08:00
|
|
|
#ifndef IPPORT_FTP
|
|
|
|
#define IPPORT_FTP 21
|
|
|
|
#endif
|
1999-12-06 05:22:45 +08:00
|
|
|
#ifndef IPPORT_HTTP
|
|
|
|
#define IPPORT_HTTP 80
|
|
|
|
#endif
|
|
|
|
|
1999-11-10 04:57:38 +08:00
|
|
|
#define URL_IOBUF_SIZE 4096
|
1999-11-19 02:07:46 +08:00
|
|
|
int url_iobuf_size = URL_IOBUF_SIZE;
|
1999-11-10 04:57:38 +08:00
|
|
|
|
1999-11-02 22:33:14 +08:00
|
|
|
#define RPMURL_DEBUG_IO 0x40000000
|
|
|
|
#define RPMURL_DEBUG_REFS 0x20000000
|
|
|
|
|
1999-11-10 04:57:38 +08:00
|
|
|
int _url_debug = 0;
|
2000-06-10 05:24:37 +08:00
|
|
|
#define URLDBG(_f, _m, _x) if ((_url_debug | (_f)) & (_m)) fprintf _x
|
1999-11-02 22:33:14 +08:00
|
|
|
|
2000-06-10 05:24:37 +08:00
|
|
|
#define URLDBGIO(_f, _x) URLDBG((_f), RPMURL_DEBUG_IO, _x)
|
|
|
|
#define URLDBGREFS(_f, _x) URLDBG((_f), RPMURL_DEBUG_REFS, _x)
|
1999-11-02 22:33:14 +08:00
|
|
|
|
|
|
|
/*@only@*/ /*@null@*/ static urlinfo *uCache = NULL;
|
1999-10-31 00:43:29 +08:00
|
|
|
static int uCount = 0;
|
|
|
|
|
2001-05-04 05:00:18 +08:00
|
|
|
/**
|
|
|
|
* Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
|
2001-06-04 21:55:58 +08:00
|
|
|
* @param p memory to free
|
2001-05-04 05:00:18 +08:00
|
|
|
* @retval NULL always
|
|
|
|
*/
|
2001-06-04 21:55:58 +08:00
|
|
|
/*@unused@*/ static inline /*@null@*/ void *
|
|
|
|
_free(/*@only@*/ /*@null@*/ const void * p) /*@modifies p@*/
|
|
|
|
{
|
|
|
|
if (p != NULL) free((void *)p);
|
2001-05-04 05:00:18 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
1999-11-02 22:33:14 +08:00
|
|
|
urlinfo XurlLink(urlinfo u, const char *msg, const char *file, unsigned line)
|
|
|
|
{
|
1999-11-10 04:57:38 +08:00
|
|
|
URLSANE(u);
|
1999-11-02 22:33:14 +08:00
|
|
|
u->nrefs++;
|
2000-06-10 05:24:37 +08:00
|
|
|
URLDBGREFS(0, (stderr, "--> url %p ++ %d %s at %s:%u\n", u, u->nrefs, msg, file, line));
|
1999-11-02 22:33:14 +08:00
|
|
|
return u;
|
|
|
|
}
|
|
|
|
|
|
|
|
urlinfo XurlNew(const char *msg, const char *file, unsigned line)
|
1999-10-31 00:43:29 +08:00
|
|
|
{
|
1999-11-02 22:33:14 +08:00
|
|
|
urlinfo u;
|
1999-10-31 00:43:29 +08:00
|
|
|
if ((u = xmalloc(sizeof(*u))) == NULL)
|
|
|
|
return NULL;
|
|
|
|
memset(u, 0, sizeof(*u));
|
|
|
|
u->proxyp = -1;
|
|
|
|
u->port = -1;
|
1999-11-24 08:03:54 +08:00
|
|
|
u->urltype = URL_IS_UNKNOWN;
|
1999-11-10 04:57:38 +08:00
|
|
|
u->ctrl = NULL;
|
|
|
|
u->data = NULL;
|
|
|
|
u->bufAlloced = 0;
|
|
|
|
u->buf = NULL;
|
1999-11-06 04:00:26 +08:00
|
|
|
u->httpHasRange = 1;
|
1999-11-19 02:07:46 +08:00
|
|
|
u->httpVersion = 0;
|
1999-11-02 22:33:14 +08:00
|
|
|
u->nrefs = 0;
|
1999-11-10 04:57:38 +08:00
|
|
|
u->magic = URLMAGIC;
|
1999-11-02 22:33:14 +08:00
|
|
|
return XurlLink(u, msg, file, line);
|
1999-10-31 00:43:29 +08:00
|
|
|
}
|
1999-09-18 05:51:23 +08:00
|
|
|
|
1999-11-10 04:57:38 +08:00
|
|
|
urlinfo XurlFree(urlinfo u, const char *msg, const char *file, unsigned line)
|
1999-07-04 07:36:35 +08:00
|
|
|
{
|
1999-11-10 04:57:38 +08:00
|
|
|
URLSANE(u);
|
2000-06-10 05:24:37 +08:00
|
|
|
URLDBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, line));
|
1999-11-02 22:33:14 +08:00
|
|
|
if (--u->nrefs > 0)
|
2000-11-01 00:18:34 +08:00
|
|
|
/*@-refcounttrans@*/ return u; /*@=refcounttrans@*/
|
1999-11-10 04:57:38 +08:00
|
|
|
if (u->ctrl) {
|
1999-11-16 06:16:54 +08:00
|
|
|
#ifndef NOTYET
|
1999-12-02 04:00:39 +08:00
|
|
|
void * fp = fdGetFp(u->ctrl);
|
1999-11-16 06:16:54 +08:00
|
|
|
if (fp) {
|
1999-12-02 03:57:17 +08:00
|
|
|
fdPush(u->ctrl, fpio, fp, -1); /* Push fpio onto stack */
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) Fclose(u->ctrl);
|
1999-12-02 03:57:17 +08:00
|
|
|
} else if (fdio->_fileno(u->ctrl) >= 0)
|
1999-11-10 04:57:38 +08:00
|
|
|
fdio->close(u->ctrl);
|
1999-11-16 06:16:54 +08:00
|
|
|
#else
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) Fclose(u->ctrl);
|
1999-11-16 06:16:54 +08:00
|
|
|
#endif
|
|
|
|
|
1999-12-17 05:58:19 +08:00
|
|
|
u->ctrl = fdio->_fdderef(u->ctrl, "persist ctrl (urlFree)", file, line);
|
2000-11-01 00:18:34 +08:00
|
|
|
/*@-usereleased@*/
|
1999-11-10 04:57:38 +08:00
|
|
|
if (u->ctrl)
|
1999-11-15 03:15:18 +08:00
|
|
|
fprintf(stderr, _("warning: u %p ctrl %p nrefs != 0 (%s %s)\n"),
|
2001-05-04 05:00:18 +08:00
|
|
|
u, u->ctrl, (u->host ? u->host : ""),
|
|
|
|
(u->service ? u->service : ""));
|
2000-11-01 00:18:34 +08:00
|
|
|
/*@=usereleased@*/
|
1999-11-10 04:57:38 +08:00
|
|
|
}
|
|
|
|
if (u->data) {
|
1999-11-16 06:16:54 +08:00
|
|
|
#ifndef NOTYET
|
1999-12-02 04:00:39 +08:00
|
|
|
void * fp = fdGetFp(u->data);
|
1999-11-16 06:16:54 +08:00
|
|
|
if (fp) {
|
1999-12-02 03:57:17 +08:00
|
|
|
fdPush(u->data, fpio, fp, -1); /* Push fpio onto stack */
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) Fclose(u->data);
|
1999-12-02 03:57:17 +08:00
|
|
|
} else if (fdio->_fileno(u->data) >= 0)
|
1999-11-10 04:57:38 +08:00
|
|
|
fdio->close(u->data);
|
1999-11-16 06:16:54 +08:00
|
|
|
#else
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) Fclose(u->ctrl);
|
1999-11-16 06:16:54 +08:00
|
|
|
#endif
|
|
|
|
|
1999-12-17 05:58:19 +08:00
|
|
|
u->data = fdio->_fdderef(u->data, "persist data (urlFree)", file, line);
|
2000-11-01 00:18:34 +08:00
|
|
|
/*@-usereleased@*/
|
1999-11-10 04:57:38 +08:00
|
|
|
if (u->data)
|
1999-11-15 03:15:18 +08:00
|
|
|
fprintf(stderr, _("warning: u %p data %p nrefs != 0 (%s %s)\n"),
|
2001-05-04 05:00:18 +08:00
|
|
|
u, u->data, (u->host ? u->host : ""),
|
|
|
|
(u->service ? u->service : ""));
|
2000-11-01 00:18:34 +08:00
|
|
|
/*@=usereleased@*/
|
1999-11-10 04:57:38 +08:00
|
|
|
}
|
2001-05-04 05:00:18 +08:00
|
|
|
u->buf = _free(u->buf);
|
|
|
|
u->url = _free(u->url);
|
|
|
|
u->service = _free((void *)u->service);
|
|
|
|
u->user = _free((void *)u->user);
|
|
|
|
u->password = _free((void *)u->password);
|
|
|
|
u->host = _free((void *)u->host);
|
|
|
|
u->portstr = _free((void *)u->portstr);
|
|
|
|
u->proxyu = _free((void *)u->proxyu);
|
|
|
|
u->proxyh = _free((void *)u->proxyh);
|
|
|
|
|
|
|
|
/*@-refcounttrans@*/ u = _free(u); /*@-refcounttrans@*/
|
1999-11-10 04:57:38 +08:00
|
|
|
return NULL;
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
1999-11-02 22:33:14 +08:00
|
|
|
void urlFreeCache(void)
|
1999-07-04 07:36:35 +08:00
|
|
|
{
|
2001-05-04 05:00:18 +08:00
|
|
|
if (uCache) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < uCount; i++) {
|
|
|
|
if (uCache[i] == NULL) continue;
|
|
|
|
uCache[i] = urlFree(uCache[i], "uCache");
|
|
|
|
if (uCache[i])
|
|
|
|
fprintf(stderr,
|
|
|
|
_("warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"),
|
|
|
|
i, uCache[i], uCache[i]->nrefs,
|
|
|
|
(uCache[i]->host ? uCache[i]->host : ""),
|
|
|
|
(uCache[i]->service ? uCache[i]->service : ""));
|
|
|
|
}
|
1999-10-31 00:43:29 +08:00
|
|
|
}
|
2001-05-04 05:00:18 +08:00
|
|
|
uCache = _free(uCache);
|
1999-10-31 00:43:29 +08:00
|
|
|
uCount = 0;
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
2001-05-04 05:00:18 +08:00
|
|
|
static int urlStrcmp(/*@null@*/ const char * str1, /*@null@*/ const char * str2)
|
1999-07-04 07:36:35 +08:00
|
|
|
{
|
1999-10-31 00:43:29 +08:00
|
|
|
if (str1 && str2)
|
2001-05-04 05:00:18 +08:00
|
|
|
/*@-nullpass@*/ /* LCL: 2nd arg claims to be NULL */
|
|
|
|
return strcmp(str1, str2);
|
|
|
|
/*@=nullpass@*/
|
1999-10-31 00:43:29 +08:00
|
|
|
if (str1 != str2)
|
|
|
|
return -1;
|
1999-07-04 07:36:35 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-05-04 05:00:18 +08:00
|
|
|
static void urlFind(/*@null@*/ /*@in@*/ /*@out@*/ urlinfo *uret, int mustAsk)
|
1999-07-04 07:36:35 +08:00
|
|
|
{
|
1999-11-02 22:33:14 +08:00
|
|
|
urlinfo u;
|
|
|
|
int ucx;
|
2001-06-02 06:00:07 +08:00
|
|
|
int i = 0;
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
if (uret == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
u = *uret;
|
1999-11-10 04:57:38 +08:00
|
|
|
URLSANE(u);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
1999-11-02 22:33:14 +08:00
|
|
|
ucx = -1;
|
1999-07-04 07:36:35 +08:00
|
|
|
for (i = 0; i < uCount; i++) {
|
2001-06-02 06:00:07 +08:00
|
|
|
urlinfo ou = NULL;
|
|
|
|
if (uCache == NULL || (ou = uCache[i]) == NULL) {
|
1999-11-02 22:33:14 +08:00
|
|
|
if (ucx < 0)
|
|
|
|
ucx = i;
|
1999-07-04 07:36:35 +08:00
|
|
|
continue;
|
|
|
|
}
|
1999-10-31 00:43:29 +08:00
|
|
|
|
1999-07-04 07:36:35 +08:00
|
|
|
/* Check for cache-miss condition. A cache miss is
|
|
|
|
* a) both items are not NULL and don't compare.
|
|
|
|
* b) either of the items is not NULL.
|
|
|
|
*/
|
|
|
|
if (urlStrcmp(u->service, ou->service))
|
|
|
|
continue;
|
|
|
|
if (urlStrcmp(u->host, ou->host))
|
|
|
|
continue;
|
|
|
|
if (urlStrcmp(u->user, ou->user))
|
|
|
|
continue;
|
|
|
|
if (urlStrcmp(u->portstr, ou->portstr))
|
|
|
|
continue;
|
|
|
|
break; /* Found item in cache */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == uCount) {
|
1999-11-02 22:33:14 +08:00
|
|
|
if (ucx < 0) {
|
|
|
|
ucx = uCount++;
|
2001-06-02 06:00:07 +08:00
|
|
|
uCache = xrealloc(uCache, sizeof(*uCache) * uCount);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
2001-06-02 06:00:07 +08:00
|
|
|
if (uCache) /* XXX always true */
|
|
|
|
uCache[ucx] = urlLink(u, "uCache (miss)");
|
1999-11-10 04:57:38 +08:00
|
|
|
u = urlFree(u, "urlSplit (urlFind miss)");
|
1999-07-04 07:36:35 +08:00
|
|
|
} else {
|
1999-12-13 01:46:22 +08:00
|
|
|
ucx = i;
|
1999-11-10 04:57:38 +08:00
|
|
|
u = urlFree(u, "urlSplit (urlFind hit)");
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This URL is now cached. */
|
1999-11-02 22:33:14 +08:00
|
|
|
|
2001-06-02 06:00:07 +08:00
|
|
|
if (uCache) /* XXX always true */
|
|
|
|
u = urlLink(uCache[ucx], "uCache");
|
1999-11-02 22:33:14 +08:00
|
|
|
*uret = u;
|
2001-05-01 06:32:22 +08:00
|
|
|
/*@-usereleased@*/
|
1999-11-10 04:57:38 +08:00
|
|
|
u = urlFree(u, "uCache (urlFind)");
|
2001-05-01 06:32:22 +08:00
|
|
|
/*@=usereleased@*/
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
/* Zap proxy host and port in case they have been reset */
|
|
|
|
u->proxyp = -1;
|
2001-05-04 05:00:18 +08:00
|
|
|
u->proxyh = _free(u->proxyh);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
/* Perform one-time FTP initialization */
|
1999-11-24 08:03:54 +08:00
|
|
|
if (u->urltype == URL_IS_FTP) {
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
if (mustAsk || (u->user != NULL && u->password == NULL)) {
|
2001-06-02 06:00:07 +08:00
|
|
|
const char * host = (u->host ? u->host : "");
|
|
|
|
const char * user = (u->user ? u->user : "");
|
1999-07-04 07:36:35 +08:00
|
|
|
char * prompt;
|
2001-05-04 05:00:18 +08:00
|
|
|
prompt = alloca(strlen(host) + strlen(user) + 256);
|
|
|
|
sprintf(prompt, _("Password for %s@%s: "), user, host);
|
|
|
|
u->password = _free(u->password);
|
2000-09-27 06:28:09 +08:00
|
|
|
u->password = /*@-unrecog@*/ getpass(prompt) /*@=unrecog@*/;
|
2000-09-30 03:50:29 +08:00
|
|
|
u->password = xstrdup(u->password); /* XXX xstrdup has side effects. */
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (u->proxyh == NULL) {
|
|
|
|
const char *proxy = rpmExpand("%{_ftpproxy}", NULL);
|
|
|
|
if (proxy && *proxy != '%') {
|
2001-05-04 05:00:18 +08:00
|
|
|
/*@observer@*/ const char * host = (u->host ? u->host : "");
|
1999-07-04 07:36:35 +08:00
|
|
|
const char *uu = (u->user ? u->user : "anonymous");
|
2001-05-04 05:00:18 +08:00
|
|
|
char *nu = xmalloc(strlen(uu) + sizeof("@") + strlen(host));
|
|
|
|
(void) stpcpy( stpcpy( stpcpy(nu, uu), "@"), host);
|
1999-07-04 07:36:35 +08:00
|
|
|
u->proxyu = nu;
|
1999-09-21 11:22:53 +08:00
|
|
|
u->proxyh = xstrdup(proxy);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
2001-05-04 05:00:18 +08:00
|
|
|
proxy = _free(proxy);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (u->proxyp < 0) {
|
|
|
|
const char *proxy = rpmExpand("%{_ftpport}", NULL);
|
|
|
|
if (proxy && *proxy != '%') {
|
|
|
|
char *end;
|
|
|
|
int port = strtol(proxy, &end, 0);
|
|
|
|
if (!(end && *end == '\0')) {
|
|
|
|
fprintf(stderr, _("error: %sport must be a number\n"),
|
2001-05-04 05:00:18 +08:00
|
|
|
(u->service ? u->service : ""));
|
1999-07-04 07:36:35 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
u->proxyp = port;
|
|
|
|
}
|
2001-05-04 05:00:18 +08:00
|
|
|
proxy = _free(proxy);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Perform one-time HTTP initialization */
|
1999-11-24 08:03:54 +08:00
|
|
|
if (u->urltype == URL_IS_HTTP) {
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
if (u->proxyh == NULL) {
|
|
|
|
const char *proxy = rpmExpand("%{_httpproxy}", NULL);
|
|
|
|
if (proxy && *proxy != '%')
|
1999-09-21 11:22:53 +08:00
|
|
|
u->proxyh = xstrdup(proxy);
|
2001-05-04 05:00:18 +08:00
|
|
|
proxy = _free(proxy);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (u->proxyp < 0) {
|
|
|
|
const char *proxy = rpmExpand("%{_httpport}", NULL);
|
|
|
|
if (proxy && *proxy != '%') {
|
|
|
|
char *end;
|
|
|
|
int port = strtol(proxy, &end, 0);
|
|
|
|
if (!(end && *end == '\0')) {
|
|
|
|
fprintf(stderr, _("error: %sport must be a number\n"),
|
2001-05-04 05:00:18 +08:00
|
|
|
(u->service ? u->service : ""));
|
1999-07-04 07:36:35 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
u->proxyp = port;
|
|
|
|
}
|
2001-05-04 05:00:18 +08:00
|
|
|
proxy = _free(proxy);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1999-10-31 00:43:29 +08:00
|
|
|
static struct urlstring {
|
|
|
|
const char *leadin;
|
|
|
|
urltype ret;
|
|
|
|
} urlstrings[] = {
|
|
|
|
{ "file://", URL_IS_PATH },
|
|
|
|
{ "ftp://", URL_IS_FTP },
|
|
|
|
{ "http://", URL_IS_HTTP },
|
|
|
|
{ "-", URL_IS_DASH },
|
|
|
|
{ NULL, URL_IS_UNKNOWN }
|
|
|
|
};
|
|
|
|
|
1999-11-13 01:20:49 +08:00
|
|
|
urltype urlIsURL(const char * url) {
|
1999-10-31 00:43:29 +08:00
|
|
|
struct urlstring *us;
|
|
|
|
|
1999-11-13 01:20:49 +08:00
|
|
|
if (url && *url) {
|
|
|
|
for (us = urlstrings; us->leadin != NULL; us++) {
|
|
|
|
if (strncmp(url, us->leadin, strlen(us->leadin)))
|
|
|
|
continue;
|
|
|
|
return us->ret;
|
|
|
|
}
|
1999-10-31 00:43:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return URL_IS_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
1999-11-20 02:19:41 +08:00
|
|
|
/* Return path portion of url (or pointer to NUL if url == NULL) */
|
2000-08-28 02:34:02 +08:00
|
|
|
urltype urlPath(const char * url, const char ** pathp)
|
1999-11-13 01:20:49 +08:00
|
|
|
{
|
1999-11-19 02:07:46 +08:00
|
|
|
const char *path;
|
|
|
|
int urltype;
|
1999-11-13 01:20:49 +08:00
|
|
|
|
1999-11-19 02:07:46 +08:00
|
|
|
path = url;
|
|
|
|
urltype = urlIsURL(url);
|
1999-11-13 01:20:49 +08:00
|
|
|
switch (urltype) {
|
|
|
|
case URL_IS_FTP:
|
1999-11-24 08:03:54 +08:00
|
|
|
url += sizeof("ftp://") - 1;
|
|
|
|
path = strchr(url, '/');
|
|
|
|
if (path == NULL) path = url + strlen(url);
|
1999-11-13 01:20:49 +08:00
|
|
|
break;
|
|
|
|
case URL_IS_HTTP:
|
|
|
|
case URL_IS_PATH:
|
1999-11-24 08:03:54 +08:00
|
|
|
url += sizeof("file://") - 1;
|
|
|
|
path = strchr(url, '/');
|
|
|
|
if (path == NULL) path = url + strlen(url);
|
1999-11-13 01:20:49 +08:00
|
|
|
break;
|
|
|
|
case URL_IS_UNKNOWN:
|
1999-11-24 08:03:54 +08:00
|
|
|
if (path == NULL) path = "";
|
1999-11-13 01:20:49 +08:00
|
|
|
break;
|
|
|
|
case URL_IS_DASH:
|
|
|
|
path = "";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pathp)
|
2000-11-01 00:18:34 +08:00
|
|
|
/*@-observertrans@*/
|
1999-11-13 01:20:49 +08:00
|
|
|
*pathp = path;
|
2000-11-01 00:18:34 +08:00
|
|
|
/*@=observertrans@*/
|
1999-11-13 01:20:49 +08:00
|
|
|
return urltype;
|
|
|
|
}
|
|
|
|
|
1999-07-04 07:36:35 +08:00
|
|
|
/*
|
|
|
|
* Split URL into components. The URL can look like
|
|
|
|
* service://user:password@host:port/path
|
|
|
|
*/
|
1999-11-02 22:33:14 +08:00
|
|
|
int urlSplit(const char * url, urlinfo *uret)
|
1999-07-04 07:36:35 +08:00
|
|
|
{
|
1999-11-02 22:33:14 +08:00
|
|
|
urlinfo u;
|
1999-07-04 07:36:35 +08:00
|
|
|
char *myurl;
|
|
|
|
char *s, *se, *f, *fe;
|
|
|
|
|
|
|
|
if (uret == NULL)
|
|
|
|
return -1;
|
1999-11-02 22:33:14 +08:00
|
|
|
if ((u = urlNew("urlSplit")) == NULL)
|
1999-07-04 07:36:35 +08:00
|
|
|
return -1;
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
if ((se = s = myurl = xstrdup(url)) == NULL) {
|
1999-11-10 04:57:38 +08:00
|
|
|
u = urlFree(u, "urlSplit (error #1)");
|
1999-07-04 07:36:35 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
u->url = xstrdup(url);
|
1999-11-24 08:03:54 +08:00
|
|
|
u->urltype = urlIsURL(url);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
1999-10-21 05:40:10 +08:00
|
|
|
while (1) {
|
1999-07-04 07:36:35 +08:00
|
|
|
/* Point to end of next item */
|
|
|
|
while (*se && *se != '/') se++;
|
|
|
|
/* Item was service. Save service and go for the rest ...*/
|
1999-11-19 02:07:46 +08:00
|
|
|
if (*se && (se != s) && se[-1] == ':' && se[0] == '/' && se[1] == '/') {
|
1999-07-04 07:36:35 +08:00
|
|
|
se[-1] = '\0';
|
1999-09-21 11:22:53 +08:00
|
|
|
u->service = xstrdup(s);
|
1999-07-04 07:36:35 +08:00
|
|
|
se += 2; /* skip over "//" */
|
|
|
|
s = se++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
1999-12-13 05:14:05 +08:00
|
|
|
/* Item was everything-but-path. Continue parse on rest */
|
1999-07-04 07:36:35 +08:00
|
|
|
*se = '\0';
|
|
|
|
break;
|
1999-10-21 05:40:10 +08:00
|
|
|
}
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
/* Look for ...@host... */
|
|
|
|
fe = f = s;
|
|
|
|
while (*fe && *fe != '@') fe++;
|
|
|
|
if (*fe == '@') {
|
|
|
|
s = fe + 1;
|
|
|
|
*fe = '\0';
|
|
|
|
/* Look for user:password@host... */
|
|
|
|
while (fe > f && *fe != ':') fe--;
|
|
|
|
if (*fe == ':') {
|
|
|
|
*fe++ = '\0';
|
1999-09-21 11:22:53 +08:00
|
|
|
u->password = xstrdup(fe);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
1999-09-21 11:22:53 +08:00
|
|
|
u->user = xstrdup(f);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Look for ...host:port */
|
|
|
|
fe = f = s;
|
|
|
|
while (*fe && *fe != ':') fe++;
|
|
|
|
if (*fe == ':') {
|
|
|
|
*fe++ = '\0';
|
1999-09-21 11:22:53 +08:00
|
|
|
u->portstr = xstrdup(fe);
|
1999-07-04 07:36:35 +08:00
|
|
|
if (u->portstr != NULL && u->portstr[0] != '\0') {
|
|
|
|
char *end;
|
|
|
|
u->port = strtol(u->portstr, &end, 0);
|
|
|
|
if (!(end && *end == '\0')) {
|
|
|
|
rpmMessage(RPMMESS_ERROR, _("url port must be a number\n"));
|
2001-05-04 05:00:18 +08:00
|
|
|
myurl = _free(myurl);
|
1999-11-10 04:57:38 +08:00
|
|
|
u = urlFree(u, "urlSplit (error #3)");
|
1999-07-04 07:36:35 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-09-21 11:22:53 +08:00
|
|
|
u->host = xstrdup(f);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
if (u->port < 0 && u->service != NULL) {
|
1999-09-18 05:51:23 +08:00
|
|
|
struct servent *serv;
|
1999-09-23 02:17:41 +08:00
|
|
|
serv = /*@-unrecog@*/ getservbyname(u->service, "tcp") /*@=unrecog@*/;
|
|
|
|
if (serv != NULL)
|
1999-09-18 05:51:23 +08:00
|
|
|
u->port = ntohs(serv->s_port);
|
1999-11-24 08:03:54 +08:00
|
|
|
else if (u->urltype == URL_IS_FTP)
|
1999-07-04 07:36:35 +08:00
|
|
|
u->port = IPPORT_FTP;
|
1999-11-24 08:03:54 +08:00
|
|
|
else if (u->urltype == URL_IS_HTTP)
|
1999-07-04 07:36:35 +08:00
|
|
|
u->port = IPPORT_HTTP;
|
|
|
|
}
|
|
|
|
|
2001-05-04 05:00:18 +08:00
|
|
|
myurl = _free(myurl);
|
1999-07-04 07:36:35 +08:00
|
|
|
if (uret) {
|
|
|
|
*uret = u;
|
1999-11-02 22:33:14 +08:00
|
|
|
urlFind(uret, 0);
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-11-04 04:33:53 +08:00
|
|
|
int urlGetFile(const char * url, const char * dest) {
|
1999-07-04 07:36:35 +08:00
|
|
|
int rc;
|
|
|
|
FD_t sfd = NULL;
|
|
|
|
FD_t tfd = NULL;
|
1999-12-13 01:46:22 +08:00
|
|
|
const char * sfuPath = NULL;
|
|
|
|
int urlType = urlPath(url, &sfuPath);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
1999-12-13 01:46:22 +08:00
|
|
|
if (*sfuPath == '\0')
|
|
|
|
return FTPERR_UNKNOWN;
|
|
|
|
|
1999-11-05 05:26:08 +08:00
|
|
|
sfd = Fopen(url, "r.ufdio");
|
1999-10-31 00:43:29 +08:00
|
|
|
if (sfd == NULL || Ferror(sfd)) {
|
1999-11-11 06:09:49 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("failed to open %s: %s\n"), url, Fstrerror(sfd));
|
1999-12-13 01:46:22 +08:00
|
|
|
rc = FTPERR_UNKNOWN;
|
|
|
|
goto exit;
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
1999-12-13 01:46:22 +08:00
|
|
|
if (dest == NULL) {
|
|
|
|
if ((dest = strrchr(sfuPath, '/')) != NULL)
|
|
|
|
dest++;
|
|
|
|
else
|
|
|
|
dest = sfuPath;
|
|
|
|
}
|
1999-07-04 07:36:35 +08:00
|
|
|
|
2001-05-04 05:00:18 +08:00
|
|
|
if (dest == NULL)
|
|
|
|
return FTPERR_UNKNOWN;
|
|
|
|
|
1999-11-11 06:09:49 +08:00
|
|
|
tfd = Fopen(dest, "w.ufdio");
|
|
|
|
if (_url_debug)
|
2001-05-04 05:00:18 +08:00
|
|
|
fprintf(stderr, "*** urlGetFile sfd %p %s tfd %p %s\n", sfd, url, (tfd ? tfd : NULL), dest);
|
1999-12-12 09:46:13 +08:00
|
|
|
if (tfd == NULL || Ferror(tfd)) {
|
1999-10-31 00:43:29 +08:00
|
|
|
/* XXX Fstrerror */
|
1999-11-11 06:09:49 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("failed to create %s: %s\n"), dest, Fstrerror(tfd));
|
1999-12-13 01:46:22 +08:00
|
|
|
rc = FTPERR_UNKNOWN;
|
|
|
|
goto exit;
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
|
|
|
|
1999-12-13 01:46:22 +08:00
|
|
|
switch (urlType) {
|
1999-07-04 07:36:35 +08:00
|
|
|
case URL_IS_FTP:
|
|
|
|
case URL_IS_HTTP:
|
|
|
|
case URL_IS_PATH:
|
|
|
|
case URL_IS_DASH:
|
1999-11-11 06:09:49 +08:00
|
|
|
case URL_IS_UNKNOWN:
|
1999-11-13 01:20:49 +08:00
|
|
|
if ((rc = ufdGetFile(sfd, tfd))) {
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) Unlink(dest);
|
1999-11-11 06:09:49 +08:00
|
|
|
/* XXX FIXME: sfd possibly closed by copyData */
|
2001-05-01 06:32:22 +08:00
|
|
|
/*@-usereleased@*/ (void) Fclose(sfd) /*@=usereleased@*/ ;
|
1999-07-04 07:36:35 +08:00
|
|
|
}
|
1999-12-13 01:46:22 +08:00
|
|
|
sfd = NULL; /* XXX Fclose(sfd) done by ufdGetFile */
|
1999-07-04 07:36:35 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
rc = FTPERR_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-12-13 01:46:22 +08:00
|
|
|
exit:
|
|
|
|
if (tfd)
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) Fclose(tfd);
|
1999-12-13 01:46:22 +08:00
|
|
|
if (sfd)
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) Fclose(sfd);
|
1999-07-04 07:36:35 +08:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|