summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am15
-rw-r--r--lib/ftp.c350
-rw-r--r--lib/header.c2
-rw-r--r--lib/query.c34
-rw-r--r--lib/rpminstall.c4
-rw-r--r--lib/rpmio.h8
-rw-r--r--lib/rpmurl.h19
-rw-r--r--lib/tufdio.c162
-rw-r--r--lib/url.c73
9 files changed, 474 insertions, 193 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index de979e44d..5b3049db5 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -16,6 +16,12 @@ noinst_HEADERS = \
lookup.h md5.h oldheader.h oldrpmdb.h rpm_malloc.h \
rpmdb.h rpmlead.h signature.h
+mylibs= $(top_builddir)/lib/.libs/librpm.a \
+ $(top_builddir)/popt/.libs/libpopt.a \
+ @INTLLIBS@ \
+ @LIBMISC@
+
+
lib_LTLIBRARIES = librpm.la
librpm_la_SOURCES = \
cpio.c dbindex.c depends.c falloc.c \
@@ -42,11 +48,14 @@ BUILT_SOURCES = tagtable.c
.PHONY: lclint
.PHONY: lclint
lclint:
- lclint ${DEFS} ${INCLUDES} ${librpm_la_SOURCES}
+ lclint $(DEFS) $(INCLUDES) $(librpm_la_SOURCES)
tmacro: macro.c
- $(CC) $(CFLAGS) ${DEFS} -DDEBUG_MACROS ${INCLUDES} -o $@ $<
+ $(CC) $(CFLAGS) $(DEFS) -DDEBUG_MACROS $(INCLUDES) -o $@ $<
rpmeval: macro.c
- $(CC) $(CFLAGS) ${DEFS} -DDEBUG_MACROS -DEVAL_MACROS ${INCLUDES} -o $@ $<
+ $(CC) $(CFLAGS) $(DEFS) -DDEBUG_MACROS -DEVAL_MACROS $(INCLUDES) -o $@ $<
+
+tufdio: tufdio.c
+ $(CC) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs) $(LIBS)
diff --git a/lib/ftp.c b/lib/ftp.c
index ff3b67c17..a2455a642 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -67,58 +67,41 @@ int inet_aton(const char *cp, struct in_addr *inp);
int _ftp_debug = 0;
#define DBG(_f, _x) if ((_ftp_debug | (_f))) fprintf _x
-static int checkResponse(urlinfo u, int fdno, int secs, int *ecp,
- /*@out@*/ char ** str)
+static int checkResponse(urlinfo u, /*@out@*/ int *ecp, /*@out@*/ char ** str)
{
- static char buf[BUFSIZ + 1]; /* XXX Yuk! */
+ char *buf;
+ size_t bufAlloced;
int bufLength = 0;
- fd_set emptySet, readSet;
const char *s;
char *se;
- struct timeval timeout, *tvp = (secs < 0 ? NULL : &timeout);
- int bytesRead, rc = 0;
- int doesContinue = 1;
+ int ec = 0;
+ int moretodo = 1;
char errorCode[4];
- assert(secs > 0);
+ URLSANE(u);
+ buf = u->buf;
+ bufAlloced = u->bufAlloced;
+
errorCode[0] = '\0';
- u->httpContentLength = -1;
do {
+ int rc;
+
/*
- * XXX In order to preserve both getFile and getFd methods with
- * XXX HTTP, the response is read 1 char at a time with breaks on
- * XXX newlines.
+ * Read next line from server.
*/
- do {
- FD_ZERO(&emptySet);
- FD_ZERO(&readSet);
- FD_SET(fdno, &readSet);
-
- if (tvp) {
- tvp->tv_sec = secs;
- tvp->tv_usec = 0;
- }
-
- rc = select(fdno + 1, &readSet, &emptySet, &emptySet, tvp);
- if (rc < 1) {
- if (rc == 0)
- return FTPERR_BAD_SERVER_RESPONSE;
- else
- rc = FTPERR_UNKNOWN;
- } else
- rc = 0;
-
- se = buf + bufLength;
- bytesRead = read(fdno, se, 1);
- bufLength += bytesRead;
- buf[bufLength] = '\0';
- } while (bufLength < sizeof(buf) && *se != '\n');
+ se = buf + bufLength;
+ rc = fdRdline(u->ctrl, se, (bufAlloced - bufLength));
+ if (rc < 0) {
+ ec = FTPERR_BAD_SERVER_RESPONSE;
+ continue;
+ } else if (rc == 0 || fdWritable(u->ctrl, 0) < 1)
+ moretodo = 0;
/*
- * Divide the response into lines. Skip continuation lines.
+ * Process next line from server.
*/
- for (s = se = buf; *s != '\0'; s = se) {
+ for (s = se; *s != '\0'; s = se) {
const char *e;
while (*se && *se != '\n') se++;
@@ -132,18 +115,21 @@ static int checkResponse(urlinfo u, int fdno, int secs, int *ecp,
/* HTTP: header termination on empty line */
if (*s == '\0') {
- doesContinue = 0;
+ moretodo = 0;
break;
}
*se++ = '\0';
/* HTTP: look for "HTTP/1.1 123 ..." */
if (!strncmp(s, "HTTP", sizeof("HTTP")-1)) {
+ u->httpContentLength = -1;
if ((e = strchr(s, '.')) != NULL) {
e++;
u->httpVersion = *e - '0';
if (u->httpVersion < 1 || u->httpVersion > 2)
u->httpPersist = u->httpVersion = 0;
+ else
+ u->httpPersist = 1;
}
if ((e = strchr(s, ' ')) != NULL) {
e++;
@@ -154,7 +140,7 @@ static int checkResponse(urlinfo u, int fdno, int secs, int *ecp,
continue;
}
- /* HTTP: look for "<token>: ..." */
+ /* HTTP: look for "token: ..." */
for (e = s; *e && !(*e == ' ' || *e == ':'); e++)
;
if (e > s && *e++ == ':') {
@@ -196,40 +182,46 @@ static int checkResponse(urlinfo u, int fdno, int secs, int *ecp,
continue;
}
+ /* HTTP: look for "<TITLE>501 ... </TITLE>" */
+ if (!strncmp(s, "<TITLE>", sizeof("<TITLE>")-1))
+ s += sizeof("<TITLE>") - 1;
+
/* FTP: look for "123-" and/or "123 " */
if (strchr("0123456789", *s)) {
if (errorCode[0]) {
if (!strncmp(s, errorCode, sizeof("123")-1) && s[3] == ' ')
- doesContinue = 0;
+ moretodo = 0;
} else {
strncpy(errorCode, s, sizeof("123")-1);
errorCode[3] = '\0';
if (s[3] != '-')
- doesContinue = 0;
+ moretodo = 0;
}
}
}
- if (doesContinue && se > s) {
+ if (moretodo && se > s) {
bufLength = se - s - 1;
if (s != buf)
memcpy(buf, s, bufLength);
} else {
bufLength = 0;
}
- } while (doesContinue && !rc);
+ } while (moretodo && ec == 0);
if (str) *str = buf;
if (ecp) *ecp = atoi(errorCode);
- return rc;
+ return ec;
}
int ftpCheckResponse(urlinfo u, /*@out@*/ char ** str)
{
int ec = 0;
- int secs = fdGetRdTimeoutSecs(u->ftpControl);
- int rc = checkResponse(u, fdio->fileno(u->ftpControl), secs, &ec, str);
+ int rc;
+
+ URLSANE(u);
+ rc = checkResponse(u, &ec, str);
switch (ec) {
case 550:
@@ -246,42 +238,35 @@ int ftpCheckResponse(urlinfo u, /*@out@*/ char ** str)
return rc;
}
-int ftpCommand(urlinfo u, char * command, ...)
+int ftpCommand(urlinfo u, ...)
{
va_list ap;
- int len;
- char * s;
- char * req;
+ int len = 0;
+ const char * s, * t;
+ char * te;
int rc;
- va_start(ap, command);
- len = strlen(command) + 2;
- s = va_arg(ap, char *);
- while (s) {
- len += strlen(s) + 1;
- s = va_arg(ap, char *);
+ URLSANE(u);
+ va_start(ap, u);
+ while ((s = va_arg(ap, const char *)) != NULL) {
+ if (len) len++;
+ len += strlen(s);
}
+ len += sizeof("\r\n")-1;
va_end(ap);
- req = alloca(len + 1);
+ t = te = alloca(len + 1);
- va_start(ap, command);
- strcpy(req, command);
- strcat(req, " ");
- s = va_arg(ap, char *);
- while (s) {
- strcat(req, s);
- strcat(req, " ");
- s = va_arg(ap, char *);
+ va_start(ap, u);
+ while ((s = va_arg(ap, const char *)) != NULL) {
+ if (te > t) *te++ = ' ';
+ te = stpcpy(te, s);
}
+ te = stpcpy(te, "\r\n");
va_end(ap);
- req[len - 2] = '\r';
- req[len - 1] = '\n';
- req[len] = '\0';
-
- DBG(0, (stderr, "-> %s", req));
- if (fdio->write(u->ftpControl, req, len) != len)
+ DBG(0, (stderr, "-> %s", t));
+ if (fdio->write(u->ctrl, t, (te-t)) != (te-t))
return FTPERR_SERVER_IO_ERROR;
rc = ftpCheckResponse(u, NULL);
@@ -320,7 +305,7 @@ static int getHostAddress(const char * host, struct in_addr * address)
static int tcpConnect(const char *host, int port)
{
struct sockaddr_in sin;
- int sock = -1;
+ int fdno = -1;
int rc;
sin.sin_family = AF_INET;
@@ -331,46 +316,70 @@ static int tcpConnect(const char *host, int port)
if ((rc = getHostAddress(host, &sin.sin_addr)) < 0)
break;
- if ((sock = socket(sin.sin_family, SOCK_STREAM, IPPROTO_IP)) < 0) {
+ if ((fdno = socket(sin.sin_family, SOCK_STREAM, IPPROTO_IP)) < 0) {
rc = FTPERR_FAILED_CONNECT;
break;
}
- if (connect(sock, (struct sockaddr *) &sin, sizeof(sin))) {
+ if (connect(fdno, (struct sockaddr *) &sin, sizeof(sin))) {
rc = FTPERR_FAILED_CONNECT;
break;
}
} while (0);
- if (rc < 0 && sock >= 0) {
- close(sock);
- return rc;
- }
+ if (rc < 0)
+ goto errxit;
- DBG(0, (stderr,"++ connect %s:%d on fd %d\n",
+ DBG(0, (stderr,"++ connect %s:%d on fdno %d\n",
/*@-unrecog@*/ inet_ntoa(sin.sin_addr) /*@=unrecog@*/ ,
- ntohs(sin.sin_port), sock));
+ ntohs(sin.sin_port), fdno));
- return sock;
+ return fdno;
+
+errxit:
+ if (fdno >= 0)
+ close(fdno);
+ return rc;
}
int httpOpen(urlinfo u, const char *httpcmd)
{
- int sock;
const char *host;
const char *path;
int port;
+ int rc;
char *req;
size_t len;
+ int retrying = 0;
- if (u == NULL || ((host = (u->proxyh ? u->proxyh : u->host)) == NULL))
+ URLSANE(u);
+ assert(u->ctrl != NULL);
+
+ if (((host = (u->proxyh ? u->proxyh : u->host)) == NULL))
return FTPERR_BAD_HOSTNAME;
if ((port = (u->proxyp > 0 ? u->proxyp : u->port)) < 0) port = 80;
-
path = (u->proxyh || u->proxyp > 0) ? u->url : u->path;
- if ((sock = tcpConnect(host, port)) < 0)
- return sock;
+
+reopen:
+ if (fdio->fileno(u->ctrl) >= 0 && fdWritable(u->ctrl, 0) < 1)
+ fdio->close(u->ctrl);
+
+ if (fdio->fileno(u->ctrl) < 0) {
+ rc = tcpConnect(host, port);
+ fdSetFdno(u->ctrl, (rc >= 0 ? rc : -1));
+ if (rc < 0)
+ goto errxit;
+
+#ifdef DYING
+ /* checkResponse() assumes the socket is nonblocking */
+ if (fcntl(fdio->fileno(u->ctrl), F_SETFL, O_NONBLOCK)) {
+ rc = FTPERR_FAILED_CONNECT;
+ goto errxit;
+ }
+#endif
+ u->ctrl = fdLink(u->ctrl, "open ctrl (httpOpen)");
+ }
len = sizeof("\
req x HTTP/1.0\r\n\
@@ -391,32 +400,43 @@ Accept: text/plain\r\n\
\r\n\
", httpcmd, path, (u->httpVersion ? 1 : 0), VERSION, host, port);
- if (write(sock, req, len) != len) {
- close(sock);
- return FTPERR_SERVER_IO_ERROR;
- }
-
DBG(0, (stderr, "-> %s", req));
+ if (fdio->write(u->ctrl, req, len) != len) {
+ rc = FTPERR_SERVER_IO_ERROR;
+ goto errxit;
+ }
+
{ int ec = 0;
- int secs = fdGetRdTimeoutSecs(u->ftpControl);
- int rc;
- rc = checkResponse(u, sock, secs, &ec, NULL);
+ rc = checkResponse(u, &ec, NULL);
- switch (ec) {
- default:
- if (rc == 0 && ec != 200) /* not HTTP_OK */
- rc = FTPERR_FILE_NOT_FOUND;
- break;
- }
+if (_ftp_debug && !(rc == 0 && ec == 200))
+fprintf(stderr, "*** httpOpen: rc %d ec %d\n", rc, ec);
- if (rc < 0) {
- close(sock);
- return rc;
+ switch (rc) {
+ case 0:
+ if (ec == 200)
+ break;
+ /*@fallthrough@*/
+ default:
+ if (!retrying) { /* not HTTP_OK */
+ retrying = 1;
+ fdio->close(u->ctrl);
+ goto reopen;
+ }
+ rc = FTPERR_FILE_NOT_FOUND;
+ goto errxit;
+ /*@notreached@*/ break;
}
}
- return sock;
+ u->ctrl = fdLink(u->ctrl, "open data (httpOpen)");
+ return fdio->fileno(u->ctrl);
+
+errxit:
+ if (fdio->fileno(u->ctrl) >= 0)
+ fdio->close(u->ctrl);
+ return rc;
}
int ftpOpen(urlinfo u)
@@ -425,10 +445,10 @@ int ftpOpen(urlinfo u)
const char * user;
const char * password;
int port;
- int secs;
int rc;
- if (u == NULL || ((host = (u->proxyh ? u->proxyh : u->host)) == NULL))
+ URLSANE(u);
+ if (((host = (u->proxyh ? u->proxyh : u->host)) == NULL))
return FTPERR_BAD_HOSTNAME;
if ((port = (u->proxyp > 0 ? u->proxyp : u->port)) < 0) port = IPPORT_FTP;
@@ -448,19 +468,26 @@ int ftpOpen(urlinfo u)
}
}
- secs = fdGetRdTimeoutSecs(u->ftpControl);
- fdSetFdno(u->ftpControl, tcpConnect(host, port));
- if (fdio->fileno(u->ftpControl) < 0)
- return fdio->fileno(u->ftpControl);
+ if (fdio->fileno(u->ctrl) >= 0 && fdWritable(u->ctrl, 0) < 1)
+ fdio->close(u->ctrl);
+
+ if (fdio->fileno(u->ctrl) < 0) {
+ rc = tcpConnect(host, port);
+ fdSetFdno(u->ctrl, (rc >= 0 ? rc : -1));
+ if (rc < 0)
+ goto errxit;
+ }
- /* ftpCheckResponse() assumes the socket is nonblocking */
- if (fcntl(fdio->fileno(u->ftpControl), F_SETFL, O_NONBLOCK)) {
+#ifdef DYING
+ /* checkResponse() assumes the socket is nonblocking */
+ if (fcntl(fdio->fileno(u->ctrl), F_SETFL, O_NONBLOCK)) {
rc = FTPERR_FAILED_CONNECT;
goto errxit;
}
+#endif
if ((rc = ftpCheckResponse(u, NULL)))
- return rc;
+ goto errxit;
if ((rc = ftpCommand(u, "USER", user, NULL)))
goto errxit;
@@ -471,11 +498,12 @@ int ftpOpen(urlinfo u)
if ((rc = ftpCommand(u, "TYPE", "I", NULL)))
goto errxit;
- fdLink(u->ftpControl, "open ftpControl");
- return fdio->fileno(u->ftpControl);
+ u->ctrl = fdLink(u->ctrl, "open ctrl");
+ return fdio->fileno(u->ctrl);
errxit:
- fdio->close(u->ftpControl);
+ if (fdio->fileno(u->ctrl) >= 0)
+ fdio->close(u->ctrl);
return rc;
}
@@ -483,37 +511,46 @@ int ftpFileDone(urlinfo u)
{
int rc = 0;
- if (u == NULL)
- return FTPERR_UNKNOWN; /* XXX W2DO? */
+ URLSANE(u);
+ assert(u->ftpFileDoneNeeded);
if (u->ftpFileDoneNeeded) {
u->ftpFileDoneNeeded = 0;
- fdFree(u->ftpControl, "ftpFileDone (from ftpFileDone)");
+ u->ctrl = fdFree(u->ctrl, "open data (ftpFileDone)");
+ u->ctrl = fdFree(u->ctrl, "grab data (ftpFileDone)");
rc = ftpCheckResponse(u, NULL);
}
return rc;
}
-int ftpFileDesc(urlinfo u, const char *cmd, FD_t fd)
+int ftpFileDesc(urlinfo u, const char *cmd)
{
struct sockaddr_in dataAddress;
int cmdlen;
char * passReply;
char * chptr;
int rc;
+ FD_t fd;
- if (u == NULL || cmd == NULL || fd == NULL)
+ URLSANE(u);
+ if (cmd == NULL)
return FTPERR_UNKNOWN; /* XXX W2DO? */
cmdlen = strlen(cmd);
+ fd = u->data;
+
+#ifdef DYING
/*
* XXX When ftpFileDesc() is called, there may be a lurking
* XXX transfer complete message (if ftpFileDone() was not
* XXX called to clear that message). Clear that message now.
*/
-
if (u->ftpFileDoneNeeded)
rc = ftpFileDone(u); /* XXX return code ignored */
+#else
+ assert(u->ftpFileDoneNeeded == 0);
+#endif
+
/*
* Get the ftp version of the Content-Length.
*/
@@ -523,22 +560,30 @@ int ftpFileDesc(urlinfo u, const char *cmd, FD_t fd)
memcpy(req, "SIZE", 4);
DBG(0, (stderr, "-> %s", req));
- if (fdio->write(u->ftpControl, req, cmdlen) != cmdlen)
- return FTPERR_SERVER_IO_ERROR;
+ if (fdio->write(u->ctrl, req, cmdlen) != cmdlen) {
+ rc = FTPERR_SERVER_IO_ERROR;
+ goto errxit;
+ }
if ((rc = ftpCheckResponse(u, &passReply)))
- return rc;
- if (sscanf(passReply, "%d %u", &rc, &cl) != 2)
- return FTPERR_BAD_SERVER_RESPONSE;
+ goto errxit;
+ if (sscanf(passReply, "%d %u", &rc, &cl) != 2) {
+ rc = FTPERR_BAD_SERVER_RESPONSE;
+ goto errxit;
+ }
rc = 0;
u->httpContentLength = cl;
}
DBG(0, (stderr, "-> PASV\n"));
- if (fdio->write(u->ftpControl, "PASV\r\n", 6) != 6)
- return FTPERR_SERVER_IO_ERROR;
+ if (fdio->write(u->ctrl, "PASV\r\n", 6) != 6) {
+ rc = FTPERR_SERVER_IO_ERROR;
+ goto errxit;
+ }
- if ((rc = ftpCheckResponse(u, &passReply)))
- return FTPERR_PASSIVE_ERROR;
+ if ((rc = ftpCheckResponse(u, &passReply))) {
+ rc = FTPERR_PASSIVE_ERROR;
+ goto errxit;
+ }
chptr = passReply;
while (*chptr && *chptr != '(') chptr++;
@@ -561,8 +606,10 @@ int ftpFileDesc(urlinfo u, const char *cmd, FD_t fd)
{ int i, j;
dataAddress.sin_family = AF_INET;
- if (sscanf(chptr, "%d,%d", &i, &j) != 2)
- return FTPERR_PASSIVE_ERROR;
+ if (sscanf(chptr, "%d,%d", &i, &j) != 2) {
+ rc = FTPERR_PASSIVE_ERROR;
+ goto errxit;
+ }
dataAddress.sin_port = htons((((unsigned)i) << 8) + j);
}
@@ -571,12 +618,19 @@ int ftpFileDesc(urlinfo u, const char *cmd, FD_t fd)
if (*chptr == ',') *chptr = '.';
}
- if (!inet_aton(passReply, &dataAddress.sin_addr))
- return FTPERR_PASSIVE_ERROR;
+ if (!inet_aton(passReply, &dataAddress.sin_addr)) {
+ rc = FTPERR_PASSIVE_ERROR;
+ goto errxit;
+ }
+
+ rc = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+ fdSetFdno(fd, (rc >= 0 ? rc : -1));
+ if (rc < 0) {
+ rc = FTPERR_FAILED_CONNECT;
+ goto errxit;
+ }
+ fd = fdLink(fd, "open data (ftpFileDesc)");
- fdSetFdno(fd, socket(AF_INET, SOCK_STREAM, IPPROTO_IP));
- if (fdio->fileno(fd) < 0)
- return FTPERR_FAILED_CONNECT;
/* XXX setsockopt SO_LINGER */
/* XXX setsockopt SO_KEEPALIVE */
/* XXX setsockopt SO_TOS IPTOS_THROUGHPUT */
@@ -586,19 +640,27 @@ int ftpFileDesc(urlinfo u, const char *cmd, FD_t fd)
if (errno == EINTR)
continue;
fdio->close(fd);
- return FTPERR_FAILED_DATA_CONNECT;
+ rc = FTPERR_FAILED_DATA_CONNECT;
+ goto errxit;
}
DBG(0, (stderr, "-> %s", cmd));
- if (fdio->write(u->ftpControl, cmd, cmdlen) != cmdlen)
- return FTPERR_SERVER_IO_ERROR;
+ if (fdio->write(u->ctrl, cmd, cmdlen) != cmdlen) {
+ fdio->close(fd);
+ rc = FTPERR_SERVER_IO_ERROR;
+ goto errxit;
+ }
if ((rc = ftpCheckResponse(u, NULL))) {
fdio->close(fd);
- return rc;
+ goto errxit;
}
u->ftpFileDoneNeeded = 1;
- fdLink(u->ftpControl, "ftpFileDone");
+ u->ctrl = fdLink(u->ctrl, "grab data (ftpFileDesc)");
+ u->ctrl = fdLink(u->ctrl, "open data (ftpFileDesc)");
return 0;
+
+errxit:
+ return rc;
}
diff --git a/lib/header.c b/lib/header.c
index ca7f52bad..27893745e 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -761,7 +761,7 @@ void headerDump(Header h, FILE *f, int flags,
}
break;
default:
- fprintf(stderr, _("Data type %d not supprted\n"),
+ fprintf(stderr, _("Data type %d not supported\n"),
(int) p->info.type);
exit(EXIT_FAILURE);
/*@notreached@*/ break;
diff --git a/lib/query.c b/lib/query.c
index f9a6b3664..79d42cc6f 100644
--- a/lib/query.c
+++ b/lib/query.c
@@ -454,11 +454,14 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
int retcode = 0;
char *end = NULL;
- switch (source) {
- case RPMQV_RPM:
- { FD_t fd;
+ switch (source) {
+ case RPMQV_RPM:
+ { const char *myargv[2], **argv = myargv;;
- fd = Fopen(arg, "r.ufdio");
+ argv[0] = arg;
+ argv[1] = NULL;
+ while ((arg = *argv++) != NULL) {
+ FD_t fd = Fopen(arg, "r.ufdio");
if (Ferror(fd)) {
/* XXX Fstrerror */
fprintf(stderr, _("open of %s failed: %s\n"), arg,urlStrerror(arg));
@@ -490,9 +493,10 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
retcode = 1;
break;
}
- } break;
+ }
+ } break;
- case RPMQV_SPECFILE:
+ case RPMQV_SPECFILE:
if (showPackage != showQueryPackage)
return 1;
@@ -532,7 +536,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
freeSpecVec(spec);
} break;
- case RPMQV_ALL:
+ case RPMQV_ALL:
for (offset = rpmdbFirstRecNum(db);
offset != 0;
offset = rpmdbNextRecNum(db, offset)) {
@@ -547,7 +551,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
}
break;
- case RPMQV_GROUP:
+ case RPMQV_GROUP:
if (rpmdbFindByGroup(db, arg, &matches)) {
fprintf(stderr, _("group %s does not contain any packages\n"), arg);
retcode = 1;
@@ -557,7 +561,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
}
break;
- case RPMQV_WHATPROVIDES:
+ case RPMQV_WHATPROVIDES:
if (rpmdbFindByProvides(db, arg, &matches)) {
fprintf(stderr, _("no package provides %s\n"), arg);
retcode = 1;
@@ -567,7 +571,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
}
break;
- case RPMQV_TRIGGEREDBY:
+ case RPMQV_TRIGGEREDBY:
if (rpmdbFindByTriggeredBy(db, arg, &matches)) {
fprintf(stderr, _("no package triggers %s\n"), arg);
retcode = 1;
@@ -577,7 +581,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
}
break;
- case RPMQV_WHATREQUIRES:
+ case RPMQV_WHATREQUIRES:
if (rpmdbFindByRequiredBy(db, arg, &matches)) {
fprintf(stderr, _("no package requires %s\n"), arg);
retcode = 1;
@@ -587,7 +591,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
}
break;
- case RPMQV_PATH:
+ case RPMQV_PATH:
if (rpmdbFindByFile(db, arg, &matches)) {
int myerrno = 0;
if (access(arg, F_OK) != 0)
@@ -607,7 +611,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
}
break;
- case RPMQV_DBOFFSET:
+ case RPMQV_DBOFFSET:
recNumber = strtoul(arg, &end, 10);
if ((*end) || (end == arg) || (recNumber == ULONG_MAX)) {
fprintf(stderr, _("invalid package number: %s\n"), arg);
@@ -624,7 +628,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
}
break;
- case RPMQV_PACKAGE:
+ case RPMQV_PACKAGE:
rc = rpmdbFindByLabel(db, arg, &matches);
if (rc == 1) {
retcode = 1;
@@ -637,7 +641,7 @@ int rpmQueryVerify(QVA_t *qva, enum rpmQVSources source, const char * arg,
dbiFreeIndexRecord(matches);
}
break;
- }
+ }
return retcode;
}
diff --git a/lib/rpminstall.c b/lib/rpminstall.c
index 11a18e8f2..567847e4b 100644
--- a/lib/rpminstall.c
+++ b/lib/rpminstall.c
@@ -46,7 +46,7 @@ static void * showProgress(const Header h, const rpmCallbackType what,
switch (what) {
case RPMCALLBACK_INST_OPEN_FILE:
- fd = Fopen(filename, "r.fdio");
+ fd = Fopen(filename, "r.ufdio");
return fd;
case RPMCALLBACK_INST_CLOSE_FILE:
@@ -186,7 +186,7 @@ int rpmInstall(const char * rootdir, const char ** argv, int transFlags,
would create all sorts of confusion later. */
for (filename = packages; *filename; filename++) {
- fd = Fopen(*filename, "r.fdio");
+ fd = Fopen(*filename, "r.ufdio");
if (Ferror(fd)) {
/* XXX Fstrerror */
rpmMessage(RPMMESS_ERROR, _("cannot open file %s\n"), *filename);
diff --git a/lib/rpmio.h b/lib/rpmio.h
index abd4d2462..5f1b3c306 100644
--- a/lib/rpmio.h
+++ b/lib/rpmio.h
@@ -78,8 +78,6 @@ int Unlink (const char * path);
/*@observer@*/ extern FDIO_t gzdio;
-int timedRead(FD_t fd, /*@out@*/void * bufptr, int length);
-
void fdSetFdno(FD_t fd, int fdno);
/*@null@*/ const FDIO_t fdGetIoCookie(FD_t fd);
void fdSetIoCookie(FD_t fd, FDIO_t iop);
@@ -142,6 +140,12 @@ const char *const ftpStrerror(int errorNumber);
#define ufdUnlink ufdio->unlink
#endif
+int fdWritable(FD_t fd, int secs);
+int fdReadable(FD_t fd, int secs);
+int fdRdline(FD_t fd, /*@out@*/ char * buf, size_t len);
+
+int timedRead(FD_t fd, /*@out@*/ void * bufptr, int length);
+
/*@observer@*/ extern FDIO_t ufdio;
#define timedRead ufdio->read
diff --git a/lib/rpmurl.h b/lib/rpmurl.h
index 03d6cb9fb..ff09868cb 100644
--- a/lib/rpmurl.h
+++ b/lib/rpmurl.h
@@ -1,6 +1,8 @@
#ifndef H_RPMURL
#define H_RPMURL
+#include <assert.h>
+
#ifndef IPPORT_FTP
#define IPPORT_FTP 21
#endif
@@ -29,6 +31,9 @@ typedef enum {
URL_IS_HTTP = 4
} urltype;
+#define URLMAGIC 0xd00b1ed0
+#define URLSANE(u) assert(u && u->magic == URLMAGIC)
+
typedef /*@abstract@*/ /*@refcounted@*/ struct urlinfo {
/*@refs@*/ int nrefs;
const char * url; /* copy of original url */
@@ -42,13 +47,17 @@ typedef /*@abstract@*/ /*@refcounted@*/ struct urlinfo {
const char * proxyh; /* FTP/HTTP: proxy host */
int proxyp; /* FTP/HTTP: proxy port */
int port;
- FD_t ftpControl;
+ FD_t ctrl; /* control channel */
+ FD_t data; /* per-xfer data channel */
+ int bufAlloced; /* sizeof I/O buffer */
+ char *buf; /* I/O buffer */
int ftpFileDoneNeeded;
int openError; /* Type of open failure */
int httpVersion;
int httpHasRange;
int httpContentLength;
int httpPersist;
+ int magic;
} *urlinfo;
#ifdef __cplusplus
@@ -56,10 +65,12 @@ extern "C" {
#endif
int ftpCheckResponse(urlinfo u, /*@out@*/ char ** str);
+int ftpCommand(urlinfo u, ...);
+
int httpOpen(urlinfo u, const char * httpcmd);
int ftpOpen(urlinfo u);
int ftpFileDone(urlinfo u);
-int ftpFileDesc(urlinfo u, const char * cmd, FD_t fd);
+int ftpFileDesc(urlinfo u, const char * cmd);
urlinfo urlLink(urlinfo u, const char * msg);
urlinfo XurlLink(urlinfo u, const char * msg, const char * file, unsigned line);
@@ -69,8 +80,8 @@ urlinfo urlNew(const char * msg);
urlinfo XurlNew(const char * msg, const char * file, unsigned line);
#define urlNew(_msg) XurlNew(_msg, __FILE__, __LINE__)
-void urlFree( /*@killref@*/ urlinfo u, const char * msg);
-void XurlFree( /*@killref@*/ urlinfo u, const char * msg, const char * file, unsigned line);
+urlinfo urlFree( /*@killref@*/ urlinfo u, const char * msg);
+urlinfo XurlFree( /*@killref@*/ urlinfo u, const char * msg, const char * file, unsigned line);
#define urlFree(_u, _msg) XurlFree(_u, _msg, __FILE__, __LINE__)
void urlFreeCache(void);
diff --git a/lib/tufdio.c b/lib/tufdio.c
new file mode 100644
index 000000000..ab2363afe
--- /dev/null
+++ b/lib/tufdio.c
@@ -0,0 +1,162 @@
+#include "system.h"
+
+#include <rpmlib.h>
+#include <rpmurl.h>
+
+#include <stdarg.h>
+#include <err.h>
+
+extern int _ftp_debug;
+extern int _url_debug;
+extern int _rpmio_debug;
+
+#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
+
+const char *tmpdir = "/tmp";
+const char *dio_xxxxxx = "/dio.XXXXXX";
+#define DIO_XXXXXX alloca_strdup(dio_xxxxxx)
+const char *fio_xxxxxx = "/fio.XXXXXX";
+#define FIO_XXXXXX alloca_strdup(fio_xxxxxx)
+
+static const char * xstrconcat(const char * arg, ...)
+{
+ const char *s;
+ char *t, *te;
+ size_t nt = 0;
+ va_list ap;
+
+ if (arg == NULL) return xstrdup("");
+
+ va_start(ap, arg);
+ for (s = arg; s != NULL; s = va_arg(ap, const char *))
+ nt += strlen(s);
+ va_end(ap);
+
+ te = t = xmalloc(nt+1);
+
+ va_start(ap, arg);
+ for (s = arg; s != NULL; s = va_arg(ap, const char *))
+ te = stpcpy(te, s);
+ va_end(ap);
+ *te = '\0';
+ return t;
+}
+
+static int doFIO(const char *ofn, const char *rfmode, const char *wfmode)
+{
+ FD_t fd;
+ int rc = 0;
+ char buf[8192];
+
+ if ((fd = Fopen(ofn, wfmode)) == NULL)
+ warn("Fopen: write %s (%s) %s\n", wfmode, rfmode, ofn);
+ else if ((rc = Fwrite(ofn, 1, strlen(ofn), fd)) != strlen(ofn))
+ warn("Fwrite: write %s (%s) %s\n", wfmode, rfmode, ofn);
+ else if ((rc = Fclose(fd)) != 0)
+ warn("Fclose: write %s (%s) %s\n", wfmode, rfmode, ofn);
+ else if ((fd = Fopen(ofn, rfmode)) == NULL)
+ warn("Fopen: read %s (%s) %s\n", rfmode, wfmode, ofn);
+ else if ((rc = Fread(buf, 1, sizeof(buf), fd)) != strlen(ofn))
+ warn("Fread: read %s (%s) %s\n", rfmode, wfmode, ofn);
+ else if ((rc = Fclose(fd)) != 0)
+ warn("Fclose: read %s (%s) %s\n", rfmode, wfmode, ofn);
+ else if (strcmp(ofn, buf))
+ warn("Compare: write(%s) \"%s\" != read(%s) \"%s\" for %s\n", wfmode, ofn, rfmode, buf, ofn);
+ else
+ rc = 0;
+ if (ufdio->unlink(ofn) != 0)
+ warn("Unlink: write(%s) read(%s) for %s\n", wfmode, rfmode, ofn);
+ return rc;
+}
+
+static int doFile(const char * url, const char * odn, const char * ndn)
+{
+ const char * ofn = xstrconcat(odn, mktemp(FIO_XXXXXX), NULL);
+ const char * nfn = xstrconcat(ndn, mktemp(FIO_XXXXXX), NULL);
+ FD_t fd;
+ int rc;
+
+ if ((fd = Fopen(ofn, "r.ufdio")) != NULL)
+ err(1, "Fopen: r !exists %s fail\n", ofn);
+
+ rc = doFIO(ofn, "r.ufdio", "w.ufdio");
+ rc = doFIO(nfn, "r.ufdio", "w.ufdio");
+
+ return rc;
+}
+
+static int doDir(const char *url)
+{
+ const char * odn = xstrconcat(url, tmpdir, mktemp(DIO_XXXXXX), NULL);
+ const char * ndn = xstrconcat(url, tmpdir, mktemp(DIO_XXXXXX), NULL);
+
+fprintf(stderr, "*** Rename #1 %s -> %s fail\n", ndn, odn);
+ if (!ufdio->rename(ndn, odn))
+ err(1, "Rename: dir !exists %s !exists %s fail\n", ndn, odn);
+fprintf(stderr, "*** Chdir #1 %s fail\n", odn);
+ if (!ufdio->chdir(odn)) err(1, "Chdir: !exists %s fail\n", odn);
+
+fprintf(stderr, "*** Mkdir #1 %s\n", odn);
+ if (ufdio->mkdir(odn, 0755)) err(1, "Mkdir: !exists %s\n", odn);
+fprintf(stderr, "*** Mkdir %s fail\n", odn);
+ if (!ufdio->mkdir(odn, 0755)) err(1, "Mkdir: exists %s fail\n", odn);
+
+fprintf(stderr, "*** Chdir #2 %s\n", odn);
+ if (ufdio->chdir(odn)) err(1, "Chdir: exists %s\n", odn);
+
+fprintf(stderr, "*** Rename #2 %s -> %s fail\n", ndn, odn);
+ if (!ufdio->rename(ndn, odn))
+ err(1, "Rename: dir !exists %s exists %s fail\n", ndn, odn);
+fprintf(stderr, "*** Rename #3 %s -> %s\n", odn, ndn);
+ if (ufdio->rename(odn, ndn))
+ err(1, "Rename: dir exists %s !exists %s\n", odn, ndn);
+
+fprintf(stderr, "*** Mkdir #2 %s\n", ndn);
+ if (ufdio->mkdir(odn, 0755)) err(1, "Mkdir: #2 !exists %s\n", odn);
+
+fprintf(stderr, "*** Rename #4 %s -> %s fail\n", odn, ndn);
+ if (!ufdio->rename(odn, ndn))
+ err(1, "Rename: dir exists %s exists %s fail\n", odn, ndn);
+
+ doFile(url, odn, ndn);
+
+fprintf(stderr, "*** Rmdir #1 %s\n", odn);
+ if (ufdio->rmdir(odn)) err(1, "Rmdir: exists %s\n", odn);
+fprintf(stderr, "*** Rmdir #1 %s fail\n", odn);
+ if (!ufdio->rmdir(odn)) err(1, "Rmdir: !exists %s fail\n", odn);
+
+fprintf(stderr, "*** Rmdir #3 %s\n", ndn);
+ if (ufdio->rmdir(ndn)) err(1, "Rmdir: exists %s\n", ndn);
+fprintf(stderr, "*** Rmdir #4 %s fail\n", ndn);
+ if (!ufdio->rmdir(ndn)) err(1, "Rmdir: !exists %s fail\n", ndn);
+
+ return 0;
+}
+
+static int doUrl(const char *url)
+{
+ int rc;
+
+ rc = doDir(url);
+
+ return rc;
+
+}
+
+int main (int argc, char * argv[])
+{
+ int rc;
+
+ _ftp_debug = -1;
+ _url_debug = -1;
+ _rpmio_debug = -1;
+
+ if (argc != 2) {
+ fprintf(stderr, "%s: url ...\n", argv[0]);
+ exit(1);
+ }
+
+ rc = doUrl(argv[1]);
+
+ return 0;
+}
diff --git a/lib/url.c b/lib/url.c
index 049602f7d..1e75ed515 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -15,11 +15,13 @@
/*@access urlinfo@*/
+#define URL_IOBUF_SIZE 4096
+
#define RPMURL_DEBUG_IO 0x40000000
#define RPMURL_DEBUG_REFS 0x20000000
-static int url_debug = 0;
-#define DBG(_f, _m, _x) if ((url_debug | (_f)) & (_m)) fprintf _x
+int _url_debug = 0;
+#define DBG(_f, _m, _x) if ((_url_debug | (_f)) & (_m)) fprintf _x
#define DBGIO(_f, _x) DBG((_f), RPMURL_DEBUG_IO, _x)
#define DBGREFS(_f, _x) DBG((_f), RPMURL_DEBUG_REFS, _x)
@@ -29,6 +31,7 @@ static int uCount = 0;
urlinfo XurlLink(urlinfo u, const char *msg, const char *file, unsigned line)
{
+ URLSANE(u);
u->nrefs++;
DBGREFS(0, (stderr, "--> url %p ++ %d %s at %s:%u\n", u, u->nrefs, msg, file, line));
return u;
@@ -42,26 +45,44 @@ urlinfo XurlNew(const char *msg, const char *file, unsigned line)
memset(u, 0, sizeof(*u));
u->proxyp = -1;
u->port = -1;
- u->ftpControl = fdio->new(fdio, "url ftpControl", __FILE__, __LINE__);
+ u->ctrl = NULL;
+ u->data = NULL;
+ u->bufAlloced = 0;
+ u->buf = NULL;
u->ftpFileDoneNeeded = 0;
- u->httpVersion = 0;
u->httpHasRange = 1;
u->httpContentLength = 0;
- u->httpPersist = 1;
+ u->httpPersist = u->httpVersion = 0;
u->nrefs = 0;
+ u->magic = URLMAGIC;
return XurlLink(u, msg, file, line);
}
-void XurlFree(urlinfo u, const char *msg, const char *file, unsigned line)
+urlinfo XurlFree(urlinfo u, const char *msg, const char *file, unsigned line)
{
+ URLSANE(u);
DBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, line));
if (--u->nrefs > 0)
- return;
- if (u->ftpControl) {
- if (fdio->fileno(u->ftpControl) >= 0)
- fdio->close(u->ftpControl);
- fdio->deref(u->ftpControl, "url ftpControl (from urlFree)", __FILE__, __LINE__);
- u->ftpControl = NULL;
+ return u;
+ if (u->ctrl) {
+ if (fdio->fileno(u->ctrl) >= 0)
+ fdio->close(u->ctrl);
+ u->ctrl = fdio->deref(u->ctrl, "persist ctrl (urlFree)", file, line);
+ if (u->ctrl)
+ fprintf(stderr, "warning: ctrl nrefs != 0 (%s %s)\n",
+ u->host, u->service);
+ }
+ if (u->data) {
+ if (fdio->fileno(u->data) >= 0)
+ fdio->close(u->data);
+ u->data = fdio->deref(u->data, "persist data (urlFree)", file, line);
+ if (u->data)
+ fprintf(stderr, "warning: data nrefs != 0 (%s %s)\n",
+ u->host, u->service);
+ }
+ if (u->buf) {
+ free(u->buf);
+ u->buf = NULL;
}
FREE(u->url);
FREE(u->service);
@@ -74,6 +95,7 @@ DBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, li
FREE(u->proxyh);
/*@-refcounttrans@*/ FREE(u); /*@-refcounttrans@*/
+ return NULL;
}
void urlFreeCache(void)
@@ -81,10 +103,10 @@ void urlFreeCache(void)
int i;
for (i = 0; i < uCount; i++) {
if (uCache[i] == NULL) continue;
- if (uCache[i]->nrefs != 1)
- fprintf(stderr, "==> nrefs(%d) != 1 (%s %s)\n", uCache[i]->nrefs,
+ uCache[i] = urlFree(uCache[i], "uCache");
+ if (uCache[i])
+ fprintf(stderr, "warning: nrefs(%d) != 1 (%s %s)\n", uCache[i]->nrefs,
uCache[i]->host, uCache[i]->service);
- urlFree(uCache[i], "uCache");
}
if (uCache)
free(uCache);
@@ -111,6 +133,7 @@ static void urlFind(urlinfo *uret, int mustAsk)
return;
u = *uret;
+ URLSANE(u);
ucx = -1;
for (i = 0; i < uCount; i++) {
@@ -149,7 +172,10 @@ static void urlFind(urlinfo *uret, int mustAsk)
uCache = xmalloc(sizeof(*uCache));
}
uCache[i] = urlLink(u, "uCache (miss)");
- urlFree(u, "urlSplit (from urlFind miss)");
+ u->ctrl = fdNew(fdio, "persist ctrl");
+ u->bufAlloced = URL_IOBUF_SIZE;
+ u->buf = xcalloc(u->bufAlloced, sizeof(char));
+ u = urlFree(u, "urlSplit (urlFind miss)");
} else {
/* XXX Swap original url and path into the cached structure */
const char *up = uCache[i]->path;
@@ -159,14 +185,14 @@ static void urlFind(urlinfo *uret, int mustAsk)
up = uCache[ucx]->url;
uCache[ucx]->url = u->url;
u->url = up;
- urlFree(u, "urlSplit (from urlFind hit)");
+ u = urlFree(u, "urlSplit (urlFind hit)");
}
/* This URL is now cached. */
u = urlLink(uCache[i], "uCache");
*uret = u;
- urlFree(u, "uCache (from urlFind)");
+ u = urlFree(u, "uCache (urlFind)");
/* Zap proxy host and port in case they have been reset */
u->proxyp = -1;
@@ -283,7 +309,7 @@ int urlSplit(const char * url, urlinfo *uret)
return -1;
if ((se = s = myurl = xstrdup(url)) == NULL) {
- urlFree(u, "urlSplit (error #1)");
+ u = urlFree(u, "urlSplit (error #1)");
return -1;
}
@@ -295,7 +321,7 @@ int urlSplit(const char * url, urlinfo *uret)
if (*se == '\0') {
/* XXX can't find path */
if (myurl) free(myurl);
- urlFree(u, "urlSplit (error #2)");
+ u = urlFree(u, "urlSplit (error #2)");
return -1;
}
/* Item was service. Save service and go for the rest ...*/
@@ -340,7 +366,7 @@ int urlSplit(const char * url, urlinfo *uret)
if (!(end && *end == '\0')) {
rpmMessage(RPMMESS_ERROR, _("url port must be a number\n"));
if (myurl) free(myurl);
- urlFree(u, "urlSplit (error #3)");
+ u = urlFree(u, "urlSplit (error #3)");
return -1;
}
}
@@ -381,7 +407,6 @@ int urlGetFile(const char * url, const char * dest) {
}
sfu = ufdGetUrlinfo(sfd);
-
if (sfu != NULL && dest == NULL) {
const char *fileName = sfu->path;
if ((dest = strrchr(fileName, '/')) != NULL)
@@ -389,6 +414,10 @@ int urlGetFile(const char * url, const char * dest) {
else
dest = fileName;
}
+ if (sfu != NULL) {
+ (void) urlFree(sfu, "ufdGetUrlinfo (urlGetFile)");
+ sfu = NULL;
+ }
tfd = Fopen(dest, "w.fdio");
if (Ferror(tfd)) {