From aeab1e959d1fb383a0ff21924bff0edd01404fab Mon Sep 17 00:00:00 2001 From: jbj Date: Tue, 9 Nov 1999 20:57:38 +0000 Subject: fix: typo in error message (#6858). tufdio.c: Create. rpmurl.h: Add ctrl, data, buf, and bufAlloced to urlinfo. UFDSANE assertion. rpmio.h: Add fdWritable(), fdReadable(), fdRdline(), exported (for now) to ftp.c checkResponse(). ftp.c: checkResponse() rewritten to use above. ftp.c: checkResponse() handles html in 501 response on closed http connection. ftp.c: ftpCommand() rewritten to simplify (using stpcpy). ftp.c: httpOpen() now reopens time-out persistent connection. ftp.c: Get rid of O_NONBLOCK reads, not necessary AFAICT. ftp.c: ftpFileDesc() uses u->data rather than passed in fd arg. Use a consistent refcounting scheme to achieve persistent malloc and open ctrl. query.c: get ready for Remglob(). rpmio.c: ftpCmd() functional (using tufdio). CVS patchset: 3420 CVS date: 1999/11/09 20:57:38 --- lib/Makefile.am | 15 ++- lib/ftp.c | 350 ++++++++++++++++++++++++++++++++----------------------- lib/header.c | 2 +- lib/query.c | 34 +++--- lib/rpminstall.c | 4 +- lib/rpmio.h | 8 +- lib/rpmurl.h | 19 ++- lib/tufdio.c | 162 +++++++++++++++++++++++++ lib/url.c | 73 ++++++++---- 9 files changed, 474 insertions(+), 193 deletions(-) create mode 100644 lib/tufdio.c (limited to 'lib') 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 ": ..." */ + /* 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 "501 ... " */ + if (!strncmp(s, "", 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)) { -- cgit v1.2.3