permit http:// and file:// url's as well as ftp://.
authorjbj <devnull@localhost>
Mon, 14 Dec 1998 21:34:11 +0000 (21:34 +0000)
committerjbj <devnull@localhost>
Mon, 14 Dec 1998 21:34:11 +0000 (21:34 +0000)
attempt ftp ABOR on query/verify url's.
cache open ftp control descriptor with password.
verify needed same realpath semantics as query.
plug fd leak in urlGetFile().

CVS patchset: 2598
CVS date: 1998/12/14 21:34:11

CHANGES
ftp.c
ftp.h
install.c
lib/query.c
lib/rpmio.h
po/rpm.pot
popt/po/popt.pot
url.c
url.h
verify.c

diff --git a/CHANGES b/CHANGES
index bd0bd65..68f3307 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,5 @@
 2.5.6 -> 2.90
+       - permit http:// and file:// url's as well as ftp://.
        - change --rcfile to permit colon separated file list.
        - compile in defaults from rpmrc/macros.
        - finish hiding rpmdb index record data ("matches").
        - there must be a { between two % in a query format (unless %% is used)
 
 2.5.5 -> 2.5.6:
+       - attempt ftp ABOR on query/verify url's.
+       - cache open ftp control descriptor with password.
+       - verify needed same realpath semantics as query.
+       - plug fd leak in urlGetFile().
        - translate cpio errors using cpioStrerror.
        - display "..?....." rather than "..5....." for unreadable files.
        - run time (rather than compile time) host endian check.
diff --git a/ftp.c b/ftp.c
index c2c8b76..5d9c84a 100644 (file)
--- a/ftp.c
+++ b/ftp.c
@@ -27,6 +27,7 @@ extern int h_errno;
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include <arpa/inet.h>
+#include <arpa/telnet.h>
 
 #include "rpmio.h"
 
@@ -48,12 +49,15 @@ int inet_aton(const char *cp, struct in_addr *inp);
 #include "url.h"
 #include "ftp.h"
 
-static int ftpCheckResponse(int sock, char ** str);
-static int ftpCommand(int sock, char * command, ...);
-static int ftpReadData(int sock, FD_t fdo);
+static int ftpDebug = 0;
+static int ftpTimeoutSecs = TIMEOUT_SECS;
+
+static int ftpCheckResponse(urlinfo *u, char ** str);
+static int ftpCommand(urlinfo *u, char * command, ...);
+static int copyData(FD_t sfd, FD_t tfd);
 static int getHostAddress(const char * host, struct in_addr * address);
 
-static int ftpCheckResponse(int sock, char ** str) {
+static int ftpCheckResponse(urlinfo *u, char ** str) {
     static char buf[BUFFER_SIZE + 1];
     int bufLength = 0; 
     fd_set emptySet, readSet;
@@ -68,12 +72,12 @@ static int ftpCheckResponse(int sock, char ** str) {
     do {
        FD_ZERO(&emptySet);
        FD_ZERO(&readSet);
-       FD_SET(sock, &readSet);
+       FD_SET(u->ftpControl, &readSet);
 
-       timeout.tv_sec = TIMEOUT_SECS;
+       timeout.tv_sec = ftpTimeoutSecs;
        timeout.tv_usec = 0;
     
-       rc = select(sock + 1, &readSet, &emptySet, &emptySet, &timeout);
+       rc = select(u->ftpControl + 1, &readSet, &emptySet, &emptySet, &timeout);
        if (rc < 1) {
            if (rc==0) 
                return FTPERR_BAD_SERVER_RESPONSE;
@@ -82,7 +86,7 @@ static int ftpCheckResponse(int sock, char ** str) {
        } else
            rc = 0;
 
-       bytesRead = read(sock, buf + bufLength, sizeof(buf) - bufLength - 1);
+       bytesRead = read(u->ftpControl, buf + bufLength, sizeof(buf) - bufLength - 1);
 
        bufLength += bytesRead;
 
@@ -127,10 +131,14 @@ static int ftpCheckResponse(int sock, char ** str) {
        }
     } while (doesContinue && !rc);
 
+if (ftpDebug)
+fprintf(stderr, "<- %s\n", buf);
+
     if (*errorCode == '4' || *errorCode == '5') {
-       if (!strncmp(errorCode, "550", 3)) {
+       if (!strncmp(errorCode, "550", 3))
            return FTPERR_FILE_NOT_FOUND;
-       }
+       if (!strncmp(errorCode, "552", 3))
+           return FTPERR_NIC_ABORT_IN_PROGRESS;
 
        return FTPERR_BAD_SERVER_RESPONSE;
     }
@@ -140,7 +148,7 @@ static int ftpCheckResponse(int sock, char ** str) {
     return 0;
 }
 
-int ftpCommand(int sock, char * command, ...) {
+int ftpCommand(urlinfo *u, char * command, ...) {
     va_list ap;
     int len;
     char * s;
@@ -171,12 +179,14 @@ int ftpCommand(int sock, char * command, ...) {
     buf[len - 2] = '\r';
     buf[len - 1] = '\n';
     buf[len] = '\0';
-     
-    if (write(sock, buf, len) != len) {
+
+if (ftpDebug)
+fprintf(stderr, "-> %s", buf);
+    if (write(u->ftpControl, buf, len) != len) {
         return FTPERR_SERVER_IO_ERROR;
     }
 
-    return ftpCheckResponse(sock, NULL);
+    return ftpCheckResponse(u, NULL);
 }
 
 #if !defined(USE_ALT_DNS) || !USE_ALT_DNS 
@@ -208,28 +218,44 @@ static int getHostAddress(const char * host, struct in_addr * address) {
 
 static int tcpConnect(const char *host, int port)
 {
-    int sock;
     struct sockaddr_in sin;
+    int sock = -1;
+    int rc;
 
     sin.sin_family = AF_INET;
     sin.sin_port = htons(port);
-    if ((sock = getHostAddress(host, &sin.sin_addr)) < 0)
-       return sock;
+    sin.sin_addr.s_addr = INADDR_ANY;
+    
+  do {
+    if ((rc = getHostAddress(host, &sin.sin_addr)) < 0)
+       break;
 
-    if ((sock = socket(sin.sin_family, SOCK_STREAM, IPPROTO_IP)) < 0)
-        return FTPERR_FAILED_CONNECT;
+    if ((sock = socket(sin.sin_family, SOCK_STREAM, IPPROTO_IP)) < 0) {
+        rc = FTPERR_FAILED_CONNECT;
+       break;
+    }
 
     if (connect(sock, (struct sockaddr *) &sin, sizeof(sin))) {
+        rc = FTPERR_FAILED_CONNECT;
+       break;
+    }
+  } while (0);
+
+    if (rc < 0 && sock >= 0) {
        close(sock);
-        return FTPERR_FAILED_CONNECT;
+       return rc;
     }
+
+if (ftpDebug)
+fprintf(stderr,"++ connect %s:%d on fd %d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), sock);
+
     return sock;
 }
 
 int httpOpen(urlinfo *u)
 {
     int sock;
-    char *host;
+    const char *host;
     int port;
     char *buf;
     size_t len;
@@ -247,21 +273,23 @@ int httpOpen(urlinfo *u)
     strcpy(buf, "GET ");
     strcat(buf, u->path);
     strcat(buf, "\r\n");
+
     if (write(sock, buf, len) != len) {
        close(sock);
        return FTPERR_SERVER_IO_ERROR;
     }
 
+if (ftpDebug)
+fprintf(stderr, "-> %s", buf);
     return sock;
 }
 
 int ftpOpen(urlinfo *u)
 {
-    char * host;
-    char * user;
-    char * password;
+    const char * host;
+    const char * user;
+    const char * password;
     int port;
-    int sock;
     int rc;
 
     if (u == NULL || ((host = u->host) == NULL))
@@ -274,85 +302,132 @@ int ftpOpen(urlinfo *u)
 
     if ((password = u->password) == NULL) {
        if (getuid()) {
-           struct passwd * pw;
-           pw = getpwuid(getuid());
-           password = alloca(strlen(pw->pw_name) + 2);
-           strcpy(password, pw->pw_name);
-           strcat(password, "@");
+           struct passwd * pw = getpwuid(getuid());
+           char *myp = alloca(strlen(pw->pw_name) + sizeof("@"));
+           strcpy(myp, pw->pw_name);
+           strcat(myp, "@");
+           password = myp;
        } else {
            password = "root@";
        }
     }
 
-    if ((sock = tcpConnect(host, port)) < 0)
-       return sock;
+    if ((u->ftpControl = tcpConnect(host, port)) < 0)
+       return u->ftpControl;
 
     /* ftpCheckResponse() assumes the socket is nonblocking */
-    if (fcntl(sock, F_SETFL, O_NONBLOCK)) {
-       close(sock);
+    if (fcntl(u->ftpControl, F_SETFL, O_NONBLOCK)) {
+       close(u->ftpControl);
+       u->ftpControl = -1;
         return FTPERR_FAILED_CONNECT;
     }
 
-    if ((rc = ftpCheckResponse(sock, NULL))) {
+    if ((rc = ftpCheckResponse(u, NULL))) {
         return rc;     
     }
 
-    if ((rc = ftpCommand(sock, "USER", user, NULL))) {
-       close(sock);
+    if ((rc = ftpCommand(u, "USER", user, NULL))) {
+       close(u->ftpControl);
+       u->ftpControl = -1;
        return rc;
     }
 
-    if ((rc = ftpCommand(sock, "PASS", password, NULL))) {
-       close(sock);
+    if ((rc = ftpCommand(u, "PASS", password, NULL))) {
+       close(u->ftpControl);
+       u->ftpControl = -1;
        return rc;
     }
 
-    if ((rc = ftpCommand(sock, "TYPE", "I", NULL))) {
-       close(sock);
+    if ((rc = ftpCommand(u, "TYPE", "I", NULL))) {
+       close(u->ftpControl);
+       u->ftpControl = -1;
        return rc;
     }
 
-    return sock;
+    return u->ftpControl;
 }
 
-int ftpReadData(int sock, FD_t fdo) {
+int copyData(FD_t sfd, FD_t tfd) {
     char buf[BUFFER_SIZE];
     fd_set emptySet, readSet;
     struct timeval timeout;
-    int bytesRead, rc;
+    int bytesRead;
+    int bytesCopied = 0;
+    int rc;
     
     while (1) {
        FD_ZERO(&emptySet);
        FD_ZERO(&readSet);
-       FD_SET(sock, &readSet);
+       FD_SET(fdFileno(sfd), &readSet);
 
-       timeout.tv_sec = TIMEOUT_SECS;
+       timeout.tv_sec = ftpTimeoutSecs;
        timeout.tv_usec = 0;
     
-       rc = select(sock + 1, &readSet, &emptySet, &emptySet, &timeout);
+       rc = select(fdFileno(sfd) + 1, &readSet, &emptySet, &emptySet, &timeout);
        if (rc == 0) {
-           close(sock);
-           return FTPERR_SERVER_TIMEOUT;
+           rc = FTPERR_SERVER_TIMEOUT;
+           break;
        } else if (rc < 0) {
-           close(sock);
-           return FTPERR_UNKNOWN;
+           rc = FTPERR_UNKNOWN;
+           break;
        }
 
-       bytesRead = read(sock, buf, sizeof(buf));
+       bytesRead = fdRead(sfd, buf, sizeof(buf));
        if (bytesRead == 0) {
-           close(sock);
-           return 0;
+           rc = 0;
+           break;
        }
 
-       if (fdWrite(fdo, buf, bytesRead) != bytesRead) {
-           close(sock);
-           return FTPERR_FILE_IO_ERROR;
+       if (fdWrite(tfd, buf, bytesRead) != bytesRead) {
+           rc = FTPERR_FILE_IO_ERROR;
+           break;
        }
+       bytesCopied += bytesRead;
     }
+
+if (ftpDebug)
+fprintf(stderr, "++ copied %d bytes: %s\n", bytesCopied, ftpStrerror(rc));
+
+    fdClose(sfd);
+    return rc;
 }
 
-int ftpGetFileDesc(int sock, char * remotename) {
-    int dataSocket;
+int ftpAbort(FD_t fd) {
+    urlinfo *u = (urlinfo *)fd->fd_url;
+    char buf[BUFFER_SIZE];
+    int rc;
+    int tosecs = ftpTimeoutSecs;
+
+if (ftpDebug)
+fprintf(stderr, "-> ABOR\n");
+
+    sprintf(buf, "%c%c%c", IAC, IP, IAC);
+    send(u->ftpControl, buf, 3, MSG_OOB);
+    sprintf(buf, "%cABOR\r\n", DM);
+    if (write(u->ftpControl, buf, 7) != 7) {
+        return FTPERR_SERVER_IO_ERROR;
+    }
+    if (fdFileno(fd) >= 0) {
+       while(read(fdFileno(fd), buf, sizeof(buf)) > 0)
+           ;
+    }
+
+    ftpTimeoutSecs = 10;
+    if ((rc = ftpCheckResponse(u, NULL)) == FTPERR_NIC_ABORT_IN_PROGRESS) {
+       rc = ftpCheckResponse(u, NULL);
+    }
+    rc = ftpCheckResponse(u, NULL);
+    ftpTimeoutSecs = tosecs;
+
+    if (fdFileno(fd) >= 0)
+       fdClose(fd);
+    return 0;
+}
+
+int ftpGetFileDesc(FD_t fd)
+{
+    urlinfo *u;
+    const char *remotename;
     struct sockaddr_in dataAddress;
     int i, j;
     char * passReply;
@@ -360,10 +435,15 @@ int ftpGetFileDesc(int sock, char * remotename) {
     char * retrCommand;
     int rc;
 
-    if (write(sock, "PASV\r\n", 6) != 6) {
+    u = (urlinfo *)fd->fd_url;
+    remotename = u->path;
+
+if (ftpDebug)
+fprintf(stderr, "-> PASV\n");
+    if (write(u->ftpControl, "PASV\r\n", 6) != 6) {
         return FTPERR_SERVER_IO_ERROR;
     }
-    if ((rc = ftpCheckResponse(sock, &passReply)))
+    if ((rc = ftpCheckResponse(u, &passReply)))
        return FTPERR_PASSIVE_ERROR;
 
     chptr = passReply;
@@ -399,8 +479,8 @@ int ftpGetFileDesc(int sock, char * remotename) {
     if (!inet_aton(passReply, &dataAddress.sin_addr)) 
        return FTPERR_PASSIVE_ERROR;
 
-    dataSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
-    if (dataSocket < 0) {
+    fd->fd_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+    if (fdFileno(fd) < 0) {
         return FTPERR_FAILED_CONNECT;
     }
 
@@ -408,72 +488,91 @@ int ftpGetFileDesc(int sock, char * remotename) {
     sprintf(retrCommand, "RETR %s\r\n", remotename);
     i = strlen(retrCommand);
    
-    if (write(sock, retrCommand, i) != i) {
-        return FTPERR_SERVER_IO_ERROR;
+    while (connect(fdFileno(fd), (struct sockaddr *) &dataAddress, 
+               sizeof(dataAddress)) < 0) {
+       if (errno == EINTR)
+           continue;
+       fdClose(fd);
+        return FTPERR_FAILED_DATA_CONNECT;
     }
 
-    if (connect(dataSocket, (struct sockaddr *) &dataAddress, 
-               sizeof(dataAddress))) {
-       close(dataSocket);
-        return FTPERR_FAILED_DATA_CONNECT;
+if (ftpDebug)
+fprintf(stderr, "-> %s", retrCommand);
+    if (write(u->ftpControl, retrCommand, i) != i) {
+        return FTPERR_SERVER_IO_ERROR;
     }
 
-    if ((rc = ftpCheckResponse(sock, NULL))) {
-       close(dataSocket);
+    if ((rc = ftpCheckResponse(u, NULL))) {
+       fdClose(fd);
        return rc;
     }
 
-    return dataSocket;
+    return 0;
 }
 
-int ftpGetFileDone(int sock) {
-    if (ftpCheckResponse(sock, NULL)) {
+static int ftpGetFileDone(urlinfo *u) {
+    if (ftpCheckResponse(u, NULL))
        return FTPERR_BAD_SERVER_RESPONSE;
-    }
-
     return 0;
 }
 
-int ftpGetFile(int sock, char * remotename, FD_t dest) {
-    int dataSocket, rc;
+int httpGetFile(FD_t sfd, FD_t tfd) {
+    return copyData(sfd, tfd);
+}
 
-    dataSocket = ftpGetFileDesc(sock, remotename);
-    if (dataSocket < 0) return dataSocket;
+int ftpGetFile(FD_t sfd, FD_t tfd)
+{
+    urlinfo *u;
+    int rc;
 
-    rc = ftpReadData(dataSocket, dest);
-    close(dataSocket);
-    
-    if (rc) return rc;
+    /* XXX sfd will be freed by copyData -- grab sfd->fd_url now */
+    u = (urlinfo *)sfd->fd_url;
 
-    return ftpGetFileDone(sock);
+    /* XXX normally sfd = ufdOpen(...) and this code does not execute */
+    if (fdFileno(sfd) < 0 && (rc = ftpGetFileDesc(sfd)) < 0) {
+       fdClose(sfd);
+       return rc;
+    }
+
+    rc = copyData(sfd, tfd);
+    if (rc < 0)
+       return rc;
+
+    return ftpGetFileDone(u);
 }
 
-void ftpClose(int sock) {
-    close(sock);
+int ftpClose(FD_t fd) {
+    int fdno = ((urlinfo *)fd->fd_url)->ftpControl;
+    if (fdno >= 0)
+       close(fdno);
+    return 0;
 }
 
 const char *ftpStrerror(int errorNumber) {
   switch (errorNumber) {
+    case 0:
+       return _("Success");
+
     case FTPERR_BAD_SERVER_RESPONSE:
-      return _("Bad FTP server response");
+      return _("Bad server response");
 
     case FTPERR_SERVER_IO_ERROR:
-      return _("FTP IO error");
+      return _("Server IO error");
 
     case FTPERR_SERVER_TIMEOUT:
-      return _("FTP server timeout");
+      return _("Server timeout");
 
     case FTPERR_BAD_HOST_ADDR:
-      return _("Unable to lookup FTP server host address");
+      return _("Unable to lookup server host address");
 
     case FTPERR_BAD_HOSTNAME:
-      return _("Unable to lookup FTP server host name");
+      return _("Unable to lookup server host name");
 
     case FTPERR_FAILED_CONNECT:
-      return _("Failed to connect to FTP server");
+      return _("Failed to connect to server");
 
     case FTPERR_FAILED_DATA_CONNECT:
-      return _("Failed to establish data connection to FTP server");
+      return _("Failed to establish data connection to server");
 
     case FTPERR_FILE_IO_ERROR:
       return _("IO error to local file");
@@ -484,9 +583,12 @@ const char *ftpStrerror(int errorNumber) {
     case FTPERR_FILE_NOT_FOUND:
       return _("File not found on server");
 
+    case FTPERR_NIC_ABORT_IN_PROGRESS:
+      return _("Abort in progress");
+
     case FTPERR_UNKNOWN:
     default:
-      return _("FTP Unknown or unexpected error");
+      return _("Unknown or unexpected error");
   }
 }
   
diff --git a/ftp.h b/ftp.h
index 3a2510f..54eefe8 100644 (file)
--- a/ftp.h
+++ b/ftp.h
@@ -13,14 +13,16 @@ const char * ftpStrerror(int ftpErrno);
 #define FTPERR_PASSIVE_ERROR         -8
 #define FTPERR_FAILED_DATA_CONNECT   -9
 #define FTPERR_FILE_NOT_FOUND        -10
+#define FTPERR_NIC_ABORT_IN_PROGRESS -11
 #define FTPERR_UNKNOWN               -100
 
-int httpOpen(urlinfo *u);
+int    httpOpen(urlinfo *u);
+int    ftpOpen(urlinfo *u);
 
-int ftpOpen(urlinfo *u);
-int ftpGetFile(int sock, char * remotename, FD_t dest);
-int ftpGetFileDesc(int sock, char * remotename);
-int ftpGetFileDone(int sock);
-void ftpClose(int sock);
+int    httpGetFile(FD_t sfd, FD_t tfd);
+int    ftpGetFile(FD_t sfd, FD_t tfd);
+int    ftpGetFileDesc(FD_t);
+int    ftpAbort(FD_t fd);
+int    ftpClose(FD_t fd);
 
 #endif
index a5f74a2..e8084ac 100644 (file)
--- a/install.c
+++ b/install.c
@@ -4,6 +4,7 @@
 
 #include "install.h"
 #include "url.h"
+#include "ftp.h"
 
 static int hashesPrinted = 0;
 
@@ -64,7 +65,7 @@ static int installPackages(char * rootdir, char ** packages,
 
        fd = fdOpen(*filename, O_RDONLY, 0);
        if (fdFileno(fd) < 0) {
-           fprintf(stderr, _("error: cannot open file %s\n"), *filename);
+           rpmMessage(RPMMESS_ERROR, _("cannot open file %s\n"), *filename);
            numFailed++;
            *filename = NULL;
            continue;
@@ -98,13 +99,13 @@ static int installPackages(char * rootdir, char ** packages,
        } 
 
        if (rc == 1) {
-           fprintf(stderr
-                   _("error: %s does not appear to be a RPM package\n"), 
+           rpmMessage(RPMMESS_ERROR
+                   _("%s does not appear to be a RPM package\n"), 
                    *filename);
        }
            
        if (rc) {
-           fprintf(stderr, _("error: %s cannot be installed\n"), *filename);
+           rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *filename);
            numFailed++;
        }
 
@@ -128,13 +129,13 @@ int doInstall(char * rootdir, char ** argv, int installFlags,
     Header * binaryHeaders;
     int isSource;
     int tmpnum = 0;
-    const char *tmppath = rpmGetVar(RPMVAR_TMPPATH);
-    int tmppathlen = strlen(tmppath);
-    int rootdirlen = strlen(rootdir);
     rpmDependencies rpmdep;
     struct rpmDependencyConflict * conflicts;
     int numConflicts;
     int stopInstall = 0;
+    size_t nb;
+    const char *tmppath = rpmGetVar(RPMVAR_TMPPATH);
+    const char *myroot;
 
     if (installFlags & RPMINSTALL_TEST) 
        mode = O_RDONLY;
@@ -146,53 +147,67 @@ int doInstall(char * rootdir, char ** argv, int installFlags,
        ;
 
     rpmMessage(RPMMESS_DEBUG, _("found %d packages\n"), numPackages);
-    packages = alloca((numPackages + 1) * sizeof(char *));
-    packages[numPackages] = NULL;
-    tmpPackages = alloca((numPackages + 1) * sizeof(char *));
-    binaryHeaders = alloca((numPackages + 1) * sizeof(Header));
-       
+
+    nb = (numPackages + 1) * sizeof(char *);
+    packages = alloca(nb);
+    memset(packages, 0, nb);
+    tmpPackages = alloca(nb);
+    memset(tmpPackages, 0, nb);
+    nb = (numPackages + 1) * sizeof(Header);
+    binaryHeaders = alloca(nb);
+    memset(binaryHeaders, 0, nb);
+
+    myroot = rootdir;
+    if (myroot[0] == '/' && myroot[1] == '\0' && tmppath[0] == '/')
+       myroot = "";
+
     rpmMessage(RPMMESS_DEBUG, _("looking for packages to download\n"));
     for (filename = argv, i = 0; *filename; filename++) {
 
        switch (urlIsURL(*filename)) {
        case URL_IS_FTP:
+       case URL_IS_HTTP:
+       case URL_IS_PATH:
        {   int myrc;
+           char *tfn;
            if (rpmIsVerbose()) {
                fprintf(stdout, _("Retrieving %s\n"), *filename);
            }
-           packages[i] =
-               alloca(strlen(*filename) + 30 + rootdirlen + tmppathlen);
-           sprintf(packages[i], "%s%s/rpm-ftp-%d-%d.tmp", rootdir, 
-                   tmppath, tmpnum++, (int) getpid());
-           rpmMessage(RPMMESS_DEBUG, 
-                       _("getting %s as %s\n"), *filename, packages[i]);
-           myrc = urlGetFile(*filename, packages[i]);
+
+           nb = strlen(myroot) + strlen(tmppath) +
+               sizeof("/rpm-12345-12345");
+           tfn = malloc(nb);
+           sprintf(tfn, "%s%s/rpm-%.5u-%.5u", myroot,
+               tmppath, (int) getpid(), tmpnum++);
+
+           rpmMessage(RPMMESS_DEBUG, _(" ... as %s\n"), tfn);
+           myrc = urlGetFile(*filename, tfn);
            if (myrc < 0) {
-               fprintf(stderr
-                       _("error: skipping %s - transfer failed - %s\n"), 
+               rpmMessage(RPMMESS_ERROR
+                       _("skipping %s - transfer failed - %s\n"), 
                        *filename, ftpStrerror(myrc));
                numFailed++;
+               packages[i] = NULL;
+               free(tfn);
            } else {
-               tmpPackages[numTmpPackages++] = packages[i];
-               i++;
+               tmpPackages[numTmpPackages++] = packages[i++] = tfn;
            }
        }   break;
        default:
            packages[i++] = *filename;
            break;
        }
-
     }
 
     rpmMessage(RPMMESS_DEBUG, _("retrieved %d packages\n"), numTmpPackages);
 
     rpmMessage(RPMMESS_DEBUG, _("finding source and binary packages\n"));
-    for (filename = packages; *filename; filename++) {
+    for (filename = packages, i = 0; *filename; filename++, i++) {
        fd = fdOpen(*filename, O_RDONLY, 0);
        if (fdFileno(fd) < 0) {
-           fprintf(stderr, _("error: cannot open file %s\n"), *filename);
+           rpmMessage(RPMMESS_ERROR, _("cannot open file %s\n"), *filename);
            numFailed++;
-           *filename = NULL;
+           packages[i] = NULL;
            continue;
        }
 
@@ -202,15 +217,15 @@ int doInstall(char * rootdir, char ** argv, int installFlags,
        fdClose(fd);
        
        if (rc == 1) {
-           fprintf(stderr
-                       _("error: %s does not appear to be a RPM package\n"), 
+           rpmMessage(RPMMESS_ERROR
+                       _("%s does not appear to be a RPM package\n"), 
                        *filename);
        }
            
        if (rc) {
-           fprintf(stderr, _("error: %s cannot be installed\n"), *filename);
+           rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *filename);
            numFailed++;
-           *filename = NULL;
+           packages[i] = NULL;
        } else if (isSource) {
            /* the header will be NULL if this is a v1 source package */
            if (binaryHeaders[numBinaryPackages] != NULL)
@@ -228,7 +243,7 @@ int doInstall(char * rootdir, char ** argv, int installFlags,
     if (numBinaryPackages) {
        rpmMessage(RPMMESS_DEBUG, _("opening database mode: 0%o\n"), mode);
        if (rpmdbOpen(rootdir, &db, mode, 0644)) {
-           fprintf(stderr, _("error: cannot open %s%s/packages.rpm\n"), 
+           rpmMessage(RPMMESS_ERROR, _("cannot open %s%s/packages.rpm\n"), 
                        rootdir, rpmGetVar(RPMVAR_DBPATH));
            exit(EXIT_FAILURE);
        }
@@ -249,7 +264,7 @@ int doInstall(char * rootdir, char ** argv, int installFlags,
            }
 
            if (!stopInstall && conflicts) {
-               fprintf(stderr, _("failed dependencies:\n"));
+               rpmMessage(RPMMESS_ERROR, _("failed dependencies:\n"));
                printDepProblems(stderr, conflicts, numConflicts);
                rpmdepFreeConflicts(conflicts, numConflicts);
                numFailed = numPackages;
@@ -276,8 +291,10 @@ int doInstall(char * rootdir, char ** argv, int installFlags,
                                     relocations);
     }
 
-    for (i = 0; i < numTmpPackages; i++)
+    for (i = 0; i < numTmpPackages; i++) {
        unlink(tmpPackages[i]);
+       free(tmpPackages[i]);
+    }
 
     for (i = 0; i < numBinaryPackages; i++) 
        headerFree(binaryHeaders[i]);
@@ -317,7 +334,7 @@ int doUninstall(char * rootdir, char ** argv, int uninstallFlags,
        mode = O_RDWR | O_EXCL;
        
     if (rpmdbOpen(rootdir, &db, mode, 0644)) {
-       fprintf(stderr, _("error: cannot open %s%s/packages.rpm\n"), 
+       rpmMessage(RPMMESS_ERROR, _("cannot open %s%s/packages.rpm\n"), 
                rootdir, rpmGetVar(RPMVAR_DBPATH));
        exit(EXIT_FAILURE);
     }
@@ -327,10 +344,10 @@ int doUninstall(char * rootdir, char ** argv, int uninstallFlags,
     for (arg = argv; *arg; arg++) {
        rc = rpmdbFindByLabel(db, *arg, &matches);
        if (rc == 1) {
-           fprintf(stderr, _("package %s is not installed\n"), *arg);
+           rpmMessage(RPMMESS_ERROR, _("package %s is not installed\n"), *arg);
            numFailed++;
        } else if (rc == 2) {
-           fprintf(stderr, _("error searching for package %s\n"), *arg);
+           rpmMessage(RPMMESS_ERROR, _("searching for package %s\n"), *arg);
            numFailed++;
        } else {
            count = 0;
@@ -338,7 +355,7 @@ int doUninstall(char * rootdir, char ** argv, int uninstallFlags,
                if (dbiIndexRecordOffset(matches, i)) count++;
 
            if (count > 1 && !(interfaceFlags & UNINSTALL_ALLMATCHES)) {
-               fprintf(stderr, _("\"%s\" specifies multiple packages\n"), 
+               rpmMessage(RPMMESS_ERROR, _("\"%s\" specifies multiple packages\n"), 
                        *arg);
                numFailed++;
            }
@@ -376,7 +393,7 @@ int doUninstall(char * rootdir, char ** argv, int uninstallFlags,
        rpmdepDone(rpmdep);
 
        if (!stopUninstall && conflicts) {
-           fprintf(stderr, _("removing these packages would break "
+           rpmMessage(RPMMESS_ERROR, _("removing these packages would break "
                              "dependencies:\n"));
            printDepProblems(stderr, conflicts, numConflicts);
            rpmdepFreeConflicts(conflicts, numConflicts);
@@ -409,7 +426,7 @@ int doSourceInstall(char * rootdir, char * arg, char ** specFile,
 
     fd = fdOpen(arg, O_RDONLY, 0);
     if (fdFileno(fd) < 0) {
-       fprintf(stderr, _("error: cannot open %s\n"), arg);
+       rpmMessage(RPMMESS_ERROR, _("cannot open %s\n"), arg);
        return 1;
     }
 
@@ -418,7 +435,7 @@ int doSourceInstall(char * rootdir, char * arg, char ** specFile,
 
     rc = rpmInstallSourcePackage(rootdir, fd, specFile, NULL, NULL, cookie);
     if (rc == 1) {
-       fprintf(stderr, _("error: %s cannot be installed\n"), arg);
+       rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg);
        if (specFile) FREE(*specFile);
        if (cookie) FREE(*cookie);
     }
index 10d3db3..65e33e7 100644 (file)
@@ -454,17 +454,14 @@ int rpmQuery(char * prefix, enum rpmQuerySources source, int queryFlags,
       { FD_t fd;
 
        fd = ufdOpen(arg, O_RDONLY, 0);
-       if (fd == NULL) {
+       if (fdFileno(fd) < 0) {
            fprintf(stderr, _("open of %s failed\n"), arg);
            ufdClose(fd);
            retcode = 1;
            break;
        }
 
-       if (fdFileno(fd) >= 0) {
-           rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
-       } else
-           rc = 2;
+       rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
 
        ufdClose(fd);
 
@@ -576,22 +573,22 @@ int rpmQuery(char * prefix, enum rpmQuerySources source, int queryFlags,
 
       case QUERY_PATH:
        if (*arg != '/') {
-               /* Using realpath on the arg isn't correct if the arg is a symlink,
-                * especially if the symlink is a dangling link.  What we should
-                * instead do is use realpath() on `.' and then append arg to
-                * it.
-                */
+           /* Using realpath on the arg isn't correct if the arg is a symlink,
+            * especially if the symlink is a dangling link.  What we should
+            * instead do is use realpath() on `.' and then append arg to
+            * it.
+            */
            if (realpath(".", path) != NULL) {
                if (path[strlen(path)] != '/') {
-                       if (strncat(path, "/", PATH_MAX - strlen(path) - 1) == NULL) {
+                   if (strncat(path, "/", sizeof(path) - strlen(path) - 1) == NULL) {
                        fprintf(stderr, _("maximum path length exceeded\n"));
                        return 1;
-                       }
+                   }
                }
                /* now append the original file name to the real path */
-               if (strncat(path, arg, PATH_MAX - strlen(path) - 1) == NULL) {
-                       fprintf(stderr, _("maximum path length exceeded\n"));
-                       return 1;
+               if (strncat(path, arg, sizeof(path) - strlen(path) - 1) == NULL) {
+                   fprintf(stderr, _("maximum path length exceeded\n"));
+                   return 1;
                }
                arg = path;
            }
index a4ef31f..25804b4 100644 (file)
@@ -126,7 +126,6 @@ extern inline int gzdClose(/*@only@*/ FD_t fd) {
        fd->fd_fd = -1;
        fd->fd_bzd = NULL;
        fd->fd_gzd = NULL;
-       fd->fd_url = NULL;
        free(fd);
        zerror = gzclose(gzfile);
        return 0;
@@ -199,7 +198,6 @@ extern inline int bzdClose(/*@only@*/ FD_t fd) {
        fd->fd_fd = -1;
        fd->fd_bzd = NULL;
        fd->fd_gzd = NULL;
-       fd->fd_url = NULL;
        free(fd);
        bzclose(bzfile);
        return 0;
index 8e16d7e..d402335 100644 (file)
@@ -7,7 +7,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 1998-12-05 18:16-0500\n"
+"POT-Creation-Date: 1998-12-14 16:12-0500\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -171,56 +171,64 @@ msgstr ""
 msgid "OK"
 msgstr ""
 
-#: ../ftp.c:458
-msgid "Bad FTP server response"
+#: ../ftp.c:554
+msgid "Success"
 msgstr ""
 
-#: ../ftp.c:461
-msgid "FTP IO error"
+#: ../ftp.c:557
+msgid "Bad server response"
 msgstr ""
 
-#: ../ftp.c:464
-msgid "FTP server timeout"
+#: ../ftp.c:560
+msgid "Server IO error"
 msgstr ""
 
-#: ../ftp.c:467
-msgid "Unable to lookup FTP server host address"
+#: ../ftp.c:563
+msgid "Server timeout"
 msgstr ""
 
-#: ../ftp.c:470
-msgid "Unable to lookup FTP server host name"
+#: ../ftp.c:566
+msgid "Unable to lookup server host address"
 msgstr ""
 
-#: ../ftp.c:473
-msgid "Failed to connect to FTP server"
+#: ../ftp.c:569
+msgid "Unable to lookup server host name"
 msgstr ""
 
-#: ../ftp.c:476
-msgid "Failed to establish data connection to FTP server"
+#: ../ftp.c:572
+msgid "Failed to connect to server"
 msgstr ""
 
-#: ../ftp.c:479
+#: ../ftp.c:575
+msgid "Failed to establish data connection to server"
+msgstr ""
+
+#: ../ftp.c:578
 msgid "IO error to local file"
 msgstr ""
 
-#: ../ftp.c:482
+#: ../ftp.c:581
 msgid "Error setting remote server to passive mode"
 msgstr ""
 
-#: ../ftp.c:485
+#: ../ftp.c:584
 msgid "File not found on server"
 msgstr ""
 
-#: ../ftp.c:489
-msgid "FTP Unknown or unexpected error"
+#: ../ftp.c:587
+msgid "Abort in progress"
+msgstr ""
+
+#: ../ftp.c:591
+msgid "Unknown or unexpected error"
 msgstr ""
 
-#: ../install.c:67 ../install.c:193
+#: ../install.c:67 ../install.c:207
 #, c-format
-msgid "error: cannot open file %s\n"
+msgid "cannot open file %s\n"
 msgstr ""
 
-#: ../install.c:84 ../install.c:417
+#: ../install.c:84 ../install.c:433
 #, c-format
 msgid "Installing %s\n"
 msgstr ""
@@ -229,14 +237,14 @@ msgstr ""
 msgid "stopping source install as we're just testing\n"
 msgstr ""
 
-#: ../install.c:102 ../install.c:206
+#: ../install.c:102 ../install.c:220 ../lib/query.c:479
 #, c-format
-msgid "error: %s does not appear to be a RPM package\n"
+msgid "%s does not appear to be a RPM package\n"
 msgstr ""
 
-#: ../install.c:107 ../install.c:211 ../install.c:421
+#: ../install.c:107 ../install.c:225 ../install.c:437
 #, c-format
-msgid "error: %s cannot be installed\n"
+msgid "%s cannot be installed\n"
 msgstr ""
 
 #: ../install.c:144
@@ -248,101 +256,101 @@ msgstr ""
 msgid "found %d packages\n"
 msgstr ""
 
-#: ../install.c:154
+#: ../install.c:163
 msgid "looking for packages to download\n"
 msgstr ""
 
-#: ../install.c:161
+#: ../install.c:173
 #, c-format
 msgid "Retrieving %s\n"
 msgstr ""
 
-#: ../install.c:168
+#: ../install.c:182
 #, c-format
-msgid "getting %s as %s\n"
+msgid " ... as %s\n"
 msgstr ""
 
-#: ../install.c:172
+#: ../install.c:186
 #, c-format
-msgid "error: skipping %s - transfer failed - %s\n"
+msgid "skipping %s - transfer failed - %s\n"
 msgstr ""
 
-#: ../install.c:187
+#: ../install.c:201
 #, c-format
 msgid "retrieved %d packages\n"
 msgstr ""
 
-#: ../install.c:189
+#: ../install.c:203
 msgid "finding source and binary packages\n"
 msgstr ""
 
-#: ../install.c:225
+#: ../install.c:239
 #, c-format
 msgid "found %d source and %d binary packages\n"
 msgstr ""
 
-#: ../install.c:229
+#: ../install.c:243
 #, c-format
 msgid "opening database mode: 0%o\n"
 msgstr ""
 
-#: ../install.c:231 ../install.c:320
+#: ../install.c:245 ../install.c:336
 #, c-format
-msgid "error: cannot open %s%s/packages.rpm\n"
+msgid "cannot open %s%s/packages.rpm\n"
 msgstr ""
 
-#: ../install.c:252
+#: ../install.c:266
 msgid "failed dependencies:\n"
 msgstr ""
 
-#: ../install.c:273
+#: ../install.c:287
 msgid "installing binary packages\n"
 msgstr ""
 
-#: ../install.c:307
+#: ../install.c:323
 msgid "counting packages to uninstall\n"
 msgstr ""
 
-#: ../install.c:330 ../lib/query.c:639 ../verify.c:248
+#: ../install.c:346 ../lib/query.c:636 ../verify.c:266
 #, c-format
 msgid "package %s is not installed\n"
 msgstr ""
 
-#: ../install.c:333
+#: ../install.c:349
 #, c-format
-msgid "error searching for package %s\n"
+msgid "searching for package %s\n"
 msgstr ""
 
-#: ../install.c:341
+#: ../install.c:357
 #, c-format
 msgid "\"%s\" specifies multiple packages\n"
 msgstr ""
 
-#: ../install.c:364
+#: ../install.c:380
 #, c-format
 msgid "found %d packages to uninstall\n"
 msgstr ""
 
-#: ../install.c:379
+#: ../install.c:395
 msgid "removing these packages would break dependencies:\n"
 msgstr ""
 
-#: ../install.c:390
+#: ../install.c:406
 #, c-format
 msgid "uninstalling record number %d\n"
 msgstr ""
 
-#: ../install.c:412
+#: ../install.c:428
 #, c-format
-msgid "error: cannot open %s\n"
+msgid "cannot open %s\n"
 msgstr ""
 
-#: ../install.c:460
+#: ../install.c:476
 #, c-format
 msgid " is needed by %s-%s-%s\n"
 msgstr ""
 
-#: ../install.c:463
+#: ../install.c:479
 #, c-format
 msgid " conflicts with %s-%s-%s\n"
 msgstr ""
@@ -1326,30 +1334,30 @@ msgstr ""
 msgid "no arguments given for verify"
 msgstr ""
 
-#: ../url.c:83
+#: ../url.c:104
 #, c-format
 msgid "Password for %s@%s: "
 msgstr ""
 
-#: ../url.c:97 ../url.c:301
-#, c-format
-msgid "getting %s via anonymous ftp\n"
+#: ../url.c:168
+msgid "url port must be a number\n"
 msgstr ""
 
-#: ../url.c:102
+#: ../url.c:206
 #, c-format
 msgid "logging into %s as %s, pw %s\n"
 msgstr ""
 
-#: ../url.c:120
+#: ../url.c:229
 msgid "error: ftpport must be a number\n"
 msgstr ""
 
-#: ../url.c:202
-msgid "error: url port must be a number\n"
+#: ../lib/rpmdb.c:124 ../url.c:333
+#, c-format
+msgid "failed to open %s\n"
 msgstr ""
 
-#: ../url.c:307
+#: ../url.c:348
 #, c-format
 msgid "failed to create %s\n"
 msgstr ""
@@ -1373,7 +1381,7 @@ msgstr ""
 msgid "error: could not read database record\n"
 msgstr ""
 
-#: ../lib/query.c:528 ../verify.c:181
+#: ../lib/query.c:525 ../verify.c:181
 msgid "could not read database record!\n"
 msgstr ""
 
@@ -1387,17 +1395,21 @@ msgstr ""
 msgid "%s is not an RPM\n"
 msgstr ""
 
-#: ../lib/query.c:539 ../verify.c:223
+#: ../lib/query.c:536 ../verify.c:223
 #, c-format
 msgid "group %s does not contain any packages\n"
 msgstr ""
 
-#: ../lib/query.c:608 ../verify.c:237
+#: ../lib/query.c:584 ../lib/query.c:590 ../verify.c:241 ../verify.c:247
+msgid "maximum path length exceeded\n"
+msgstr ""
+
+#: ../lib/query.c:605 ../verify.c:255
 #, c-format
 msgid "file %s is not owned by any package\n"
 msgstr ""
 
-#: ../lib/query.c:642 ../verify.c:250
+#: ../lib/query.c:639 ../verify.c:268
 #, c-format
 msgid "error looking for package %s\n"
 msgstr ""
@@ -2792,60 +2804,51 @@ msgstr ""
 msgid "rpmQuery: rpmdbOpen() failed\n"
 msgstr ""
 
-#: ../lib/query.c:474
+#: ../lib/query.c:471
 msgid "old format source packages cannot be queried\n"
 msgstr ""
 
 #: ../lib/query.c:482
 #, c-format
-msgid "%s does not appear to be a RPM package\n"
-msgstr ""
-
-#: ../lib/query.c:485
-#, c-format
 msgid "query of %s failed\n"
 msgstr ""
 
-#: ../lib/query.c:504
+#: ../lib/query.c:501
 #, c-format
 msgid "query of specfile %s failed, can't parse\n"
 msgstr ""
 
-#: ../lib/query.c:549
+#: ../lib/query.c:546
 #, c-format
 msgid "no package provides %s\n"
 msgstr ""
 
-#: ../lib/query.c:559
+#: ../lib/query.c:556
 #, c-format
 msgid "no package triggers %s\n"
 msgstr ""
 
-#: ../lib/query.c:569
+#: ../lib/query.c:566
 #, c-format
 msgid "no package requires %s\n"
 msgstr ""
 
-#: ../lib/query.c:587 ../lib/query.c:593
-msgid "maximum path length exceeded\n"
-msgstr ""
-
-#: ../lib/query.c:605
+#: ../lib/query.c:602
 #, c-format
 msgid "file %s: %s\n"
 msgstr ""
 
-#: ../lib/query.c:621
+#: ../lib/query.c:618
 #, c-format
 msgid "invalid package number: %s\n"
 msgstr ""
 
-#: ../lib/query.c:624
+#: ../lib/query.c:621
 #, c-format
 msgid "showing package: %d\n"
 msgstr ""
 
-#: ../lib/query.c:627
+#: ../lib/query.c:624
 #, c-format
 msgid "record %d could not be read\n"
 msgstr ""
@@ -2915,11 +2918,6 @@ msgstr ""
 msgid "opening database in %s\n"
 msgstr ""
 
-#: ../lib/rpmdb.c:124
-#, c-format
-msgid "failed to open %s\n"
-msgstr ""
-
 #: ../lib/rpmdb.c:137 ../lib/rpmdb.c:144
 #, c-format
 msgid "cannot get %s lock on database"
index 8c3b411..51c452b 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 1998-12-05 12:58-0500\n"
+"POT-Creation-Date: 1998-12-11 12:08-0500\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
diff --git a/url.c b/url.c
index a24585f..9986389 100644 (file)
--- a/url.c
+++ b/url.c
@@ -7,12 +7,6 @@
 #include "url.h"
 #include "ftp.h"
 
-struct pwcacheEntry {
-    char * machine;
-    char * account;
-    char * pw;
-} ;
-
 static struct urlstring {
     const char *leadin;
     urltype    ret;
@@ -24,13 +18,10 @@ static struct urlstring {
     { NULL,            URL_IS_UNKNOWN }
 };
 
-#if DYING
-static char * getFtpPassword(char * machine, char * account, int mustAsk);
-static int urlFtpLogin(const char * url, char ** fileNamePtr);
-#endif
-
 void freeUrlinfo(urlinfo *u)
 {
+    if (u->ftpControl >= 0)
+       close(u->ftpControl);
     FREE(u->service);
     FREE(u->user);
     FREE(u->password);
@@ -52,97 +43,69 @@ urlinfo *newUrlinfo(void)
     return u;
 }
 
-static char * getFtpPassword(char * machine, char * account, int mustAsk)
-{
-    static /*@only@*/ struct pwcacheEntry * pwCache = NULL;
-    static int pwCount = 0;
-    int i;
-    char * prompt;
-
-    for (i = 0; i < pwCount; i++) {
-       if (!strcmp(pwCache[i].machine, machine) &&
-           !strcmp(pwCache[i].account, account))
-               break;
-    }
-
-    if (i < pwCount && !mustAsk) {
-       return pwCache[i].pw;
-    } else if (i == pwCount) {
-       pwCount++;
-       if (pwCache)
-           pwCache = realloc(pwCache, sizeof(*pwCache) * pwCount);
-       else
-           pwCache = malloc(sizeof(*pwCache));
-
-       pwCache[i].machine = strdup(machine);
-       pwCache[i].account = strdup(account);
-    } else
-       free(pwCache[i].pw);
-
-    prompt = alloca(strlen(machine) + strlen(account) + 50);
-    sprintf(prompt, _("Password for %s@%s: "), account, machine);
-
-    pwCache[i].pw = strdup(getpass(prompt));
-
-    return pwCache[i].pw;
-}
-
-static int urlFtpLogin(const char * url, char ** fileNamePtr)
+static void findUrlinfo(urlinfo **uret, int mustAsk)
 {
     urlinfo *u;
-    char *proxy;
-    char *proxyport;
-    int ftpconn;
-   
-    rpmMessage(RPMMESS_DEBUG, _("getting %s via anonymous ftp\n"), url);
+    urlinfo **empty;
+    static urlinfo **uCache = NULL;
+    static int uCount = 0;
+    int i;
 
-    if (urlSplit(url, &u))
-       return -1;
+    if (uret == NULL)
+       return;
 
-    rpmMessage(RPMMESS_DEBUG, _("logging into %s as %s, pw %s\n"),
-               u->host,
-               u->user ? u->user : "ftp", 
-               u->password ? u->password : "(username)");
+    u = *uret;
 
-    if ((proxy = rpmGetVar(RPMVAR_FTPPROXY)) != NULL) {
-       u->user = realloc(u->user, (strlen(u->user) + strlen(u->host) + 2) );
-       strcat(u->user, "@");
-       strcat(u->user, u->host);
-       free(u->host);
-       u->host = strdup(proxy);
+    empty = NULL;
+    for (i = 0; i < uCount; i++) {
+       urlinfo *ou;
+       if ((ou = uCache[i]) == NULL) {
+           if (empty == NULL)
+               empty = &uCache[i];
+           continue;
+       }
+       if (u->service && ou->service && strcmp(ou->service, u->service))
+           continue;
+       if (u->host && ou->host && strcmp(ou->host, u->host))
+           continue;
+       if (u->user && ou->user && strcmp(ou->user, u->user))
+           continue;
+       if (u->password && ou->password && strcmp(ou->password, u->password))
+           continue;
+       if (u->portstr && ou->portstr && strcmp(ou->portstr, u->portstr))
+           continue;
+       break;
     }
 
-    if ((proxyport = rpmGetVar(RPMVAR_FTPPORT)) != NULL) {
-       int port;
-       char *end;
-       port = strtol(proxyport, &end, 0);
-       if (*end) {
-           fprintf(stderr, _("error: ftpport must be a number\n"));
-           return -1;
+    if (i == uCount) {
+       if (empty == NULL) {
+           uCount++;
+           if (uCache)
+               uCache = realloc(uCache, sizeof(*uCache) * uCount);
+           else
+               uCache = malloc(sizeof(*uCache));
+           empty = &uCache[i];
        }
-       u->port = port;
+       *empty = u;
+    } else {
+       const char *up = uCache[i]->path;
+       uCache[i]->path = u->path;
+       u->path = up;
+       freeUrlinfo(u);
     }
 
-    ftpconn = ftpOpen(u);
-
-    if (fileNamePtr && ftpconn >= 0)
-       *fileNamePtr = strdup(u->path);
+    *uret = u = uCache[i];
 
-    freeUrlinfo(u);
-    return ftpconn;
-}
-
-urltype urlIsURL(const char * url)
-{
-    struct urlstring *us;
-
-    for (us = urlstrings; us->leadin != NULL; us++) {
-       if (strncmp(url, us->leadin, strlen(us->leadin)))
-           continue;
-       return us->ret;
+    if (!strcmp(u->service, "ftp")) {
+       if (mustAsk || (u->user != NULL && u->password == NULL)) {
+           char * prompt;
+           FREE(u->password);
+           prompt = alloca(strlen(u->host) + strlen(u->user) + 40);
+           sprintf(prompt, _("Password for %s@%s: "), u->user, u->host);
+           u->password = strdup(getpass(prompt));
+       }
     }
-    
-    return URL_IS_UNKNOWN;
+    return;
 }
 
 int urlSplit(const char * url, urlinfo **uret)
@@ -151,6 +114,8 @@ int urlSplit(const char * url, urlinfo **uret)
     char *myurl;
     char *s, *se, *f, *fe;
 
+    if (uret == NULL)
+       return -1;
     if ((u = newUrlinfo()) == NULL)
        return -1;
 
@@ -161,6 +126,7 @@ int urlSplit(const char * url, urlinfo **uret)
     do {
        while (*se && *se != '/') se++;
        if (*se == '\0') {
+           /* XXX can't find path */
            if (myurl) free(myurl);
            freeUrlinfo(u);
            return -1;
@@ -199,7 +165,7 @@ int urlSplit(const char * url, urlinfo **uret)
            char *end;
            u->port = strtol(u->portstr, &end, 0);
            if (*end) {
-               fprintf(stderr, _("error: url port must be a number\n"));
+               rpmMessage(RPMMESS_ERROR, _("url port must be a number\n"));
                if (myurl) free(myurl);
                freeUrlinfo(u);
                return -1;
@@ -216,31 +182,99 @@ int urlSplit(const char * url, urlinfo **uret)
            u->port = IPPORT_FTP;
        else if (!strcasecmp(u->service, "http"))
            u->port = IPPORT_HTTP;
+    }
+
+    if (myurl) free(myurl);
+    if (uret) {
+       *uret = u;
+       findUrlinfo(uret, 0);
+    }
+    return 0;
+}
+
+static int urlConnect(const char * url, urlinfo ** uret)
+{
+    urlinfo *u;
+
+    if (urlSplit(url, &u) < 0)
+       return -1;
+
+    if (!strcmp(u->service, "ftp") && u->ftpControl < 0) {
+       char *proxy;
+       char *proxyport;
+
+       rpmMessage(RPMMESS_DEBUG, _("logging into %s as %s, pw %s\n"),
+               u->host,
+               u->user ? u->user : "ftp",
+               u->password ? u->password : "(username)");
 
-       /* XXX move elsewhere */
-       if (!strcmp(u->service, "ftp") && u->user && u->password == NULL) {
-           u->password = getFtpPassword(u->host, u->user, 0);
-           if (u->password)
-               u->password = strdup(u->password);
+       /* XXX FIXME: this doesn't work with urlinfo caching */
+       if ((proxy = rpmGetVar(RPMVAR_FTPPROXY)) != NULL) {
+           char *nu = malloc(strlen(u->user) + strlen(u->host) + sizeof("@"));
+           strcpy(nu, u->user);
+           strcat(nu, "@");
+           strcat(nu, u->host);
+           free((void *)u->user);
+           u->user = nu;
+           free((void *)u->host);
+           u->host = strdup(proxy);
        }
+
+       /* XXX FIXME: this doesn't work with urlinfo caching */
+       if ((proxyport = rpmGetVar(RPMVAR_FTPPORT)) != NULL) {
+           int port;
+           char *end;
+           port = strtol(proxyport, &end, 0);
+           if (*end) {
+               fprintf(stderr, _("error: ftpport must be a number\n"));
+               return -1;
+           }
+           u->port = port;
+       }
+
+       u->ftpControl = ftpOpen(u);
+
+       if (u->ftpControl < 0)
+           return u->ftpControl;
+
     }
 
-    if (myurl) free(myurl);
-    if (uret)
+    if (uret != NULL)
        *uret = u;
-    else
-       freeUrlinfo(u);
+
     return 0;
 }
 
+urltype urlIsURL(const char * url)
+{
+    struct urlstring *us;
+
+    for (us = urlstrings; us->leadin != NULL; us++) {
+       if (strncmp(url, us->leadin, strlen(us->leadin)))
+           continue;
+       return us->ret;
+    }
+
+    return URL_IS_UNKNOWN;
+}
+
+#ifdef NOTYET
+int urlAbort(FD_t fd)
+{
+    if (fd != NULL && fd->fd_url) {
+       urlinfo *u = (urlinfo *)fd->fd_url;
+       if (u->ftpControl >= 0)
+           ftpAbort(fd);
+    }
+}
+#endif
+
 int ufdClose(FD_t fd)
 {
     if (fd != NULL && fd->fd_url) {
-       int fdno = ((urlinfo *)fd->fd_url)->ftpControl;
-       if (fdno >= 0)
-           ftpClose(fdno);
-       free(fd->fd_url);
-       fd->fd_url = NULL;
+       urlinfo *u = (urlinfo *)fd->fd_url;
+       if (u->ftpControl >= 0)
+           ftpAbort(fd);
     }
     return fdClose(fd);
 }
@@ -252,21 +286,19 @@ FD_t ufdOpen(const char *url, int flags, mode_t mode)
 
     switch (urlIsURL(url)) {
     case URL_IS_FTP:
-       if ((fd = fdNew()) == NULL)
+       if (urlConnect(url, &u) < 0)
            break;
-       if ((u = newUrlinfo()) == NULL)
+       if ((fd = fdNew()) == NULL)
            break;
-    {  char * fileName;
-       if ((u->ftpControl = urlFtpLogin(url, &fileName)) < 0)
+       fd->fd_url = u;
+       if (ftpGetFileDesc(fd) < 0)
            break;
-       fd->fd_fd = ftpGetFileDesc(u->ftpControl, fileName);
-       free(fileName);
-    }  break;
+       break;
     case URL_IS_HTTP:
-       if ((fd = fdNew()) == NULL)
-           break;
        if (urlSplit(url, &u))
            break;
+       if ((fd = fdNew()) == NULL)
+           break;
        fd->fd_url = u;
        fd->fd_fd = httpOpen(u);
        break;
@@ -274,7 +306,6 @@ FD_t ufdOpen(const char *url, int flags, mode_t mode)
        if (urlSplit(url, &u))
            break;
        fd = fdOpen(u->path, flags, mode);
-       freeUrlinfo(u);
        break;
     case URL_IS_DASH:
        fd = fdDup(STDIN_FILENO);
@@ -292,35 +323,58 @@ FD_t ufdOpen(const char *url, int flags, mode_t mode)
     return fd;
 }
 
-int urlGetFile(char * url, char * dest) {
-    char * fileName;
-    int ftpconn;
+int urlGetFile(const char * url, const char * dest) {
     int rc;
-    FD_t fd;
+    FD_t sfd = NULL;
+    FD_t tfd = NULL;
 
-    rpmMessage(RPMMESS_DEBUG, _("getting %s via anonymous ftp\n"), url);
+    sfd = ufdOpen(url, O_RDONLY, 0);
+    if (sfd == NULL || fdFileno(sfd) < 0) {
+       rpmMessage(RPMMESS_DEBUG, _("failed to open %s\n"), url);
+       ufdClose(sfd);
+       return FTPERR_UNKNOWN;
+    }
 
-    if ((ftpconn = urlFtpLogin(url, &fileName)) < 0) return ftpconn;
+    if (sfd->fd_url != NULL && dest == NULL) {
+       const char *fileName = ((urlinfo *)sfd->fd_url)->path;
+       if ((dest = strrchr(fileName, '/')) != NULL)
+           dest++;
+       else
+           dest = fileName;
+    }
 
-    fd = fdOpen(dest, O_CREAT|O_WRONLY|O_TRUNC, 0600);
-    if (fdFileno(fd) < 0) {
+    tfd = fdOpen(dest, O_CREAT|O_WRONLY|O_TRUNC, 0600);
+    if (fdFileno(tfd) < 0) {
        rpmMessage(RPMMESS_DEBUG, _("failed to create %s\n"), dest);
-       ftpClose(ftpconn);
-       free(fileName);
+       fdClose(tfd);
+       ufdClose(sfd);
        return FTPERR_UNKNOWN;
     }
 
-    if ((rc = ftpGetFile(ftpconn, fileName, fd))) {
-       free(fileName);
-       unlink(dest);
-       fdClose(fd);
-       ftpClose(ftpconn);
-       return rc;
-    }    
-
-    free(fileName);
+    switch (urlIsURL(url)) {
+    case URL_IS_FTP:
+       if ((rc = ftpGetFile(sfd, tfd))) {
+           unlink(dest);
+           ufdClose(sfd);
+       }
+       /* XXX fdClose(sfd) done by copyData */
+       break;
+    case URL_IS_HTTP:
+    case URL_IS_PATH:
+    case URL_IS_DASH:
+       if ((rc = httpGetFile(sfd, tfd))) {
+           unlink(dest);
+           ufdClose(sfd);
+       }
+       /* XXX fdClose(sfd) done by copyData */
+       break;
+    case URL_IS_UNKNOWN:
+    default:
+       rc = FTPERR_UNKNOWN;
+       break;
+    }
 
-    ftpClose(ftpconn);
+    fdClose(tfd);
 
     return rc;
 }
diff --git a/url.h b/url.h
index 532e520..63e0772 100644 (file)
--- a/url.h
+++ b/url.h
@@ -5,18 +5,17 @@ typedef enum {
     URL_IS_UNKNOWN     = 0,
     URL_IS_DASH                = 1,
     URL_IS_PATH                = 2,
-    URL_IS_FILE                = 3,
-    URL_IS_FTP         = 4,
-    URL_IS_HTTP                = 5,
+    URL_IS_FTP         = 3,
+    URL_IS_HTTP                = 4,
 } urltype;
 
 typedef struct urlinfo {
-    char *service;
-    char *user;
-    char *password;
-    char *host;
-    char *portstr;
-    char *path;
+    const char *service;
+    const char *user;
+    const char *password;
+    const char *host;
+    const char *portstr;
+    const char *path;
     int        port;
     int ftpControl;
 } urlinfo;
@@ -37,7 +36,7 @@ void  freeUrlinfo(urlinfo *u);
 FD_t   ufdOpen(const char * pathname, int flags, mode_t mode);
 int    ufdClose(FD_t fd);
 
-int urlGetFile(char * url, char * dest);
+int    urlGetFile(const char * url, const char * dest);
 
 #ifdef __cplusplus
 }
index 16c0ae9..732a605 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -161,7 +161,7 @@ int doVerify(char * prefix, enum verifysources source, char ** argv,
     rpmdb db;
     dbiIndexSet matches;
     char * arg;
-    char path[255];
+    char path[PATH_MAX];
 
     ec = 0;
     if (source == VERIFY_RPM && !(verifyFlags & VERIFY_DEPS)) {
@@ -191,7 +191,7 @@ int doVerify(char * prefix, enum verifysources source, char ** argv,
 
            rc = 0;
            switch (source) {
-             case VERIFY_RPM:
+           case VERIFY_RPM:
              { FD_t fd;
 
                fd = ufdOpen(arg, O_RDONLY, 0);
@@ -217,7 +217,7 @@ int doVerify(char * prefix, enum verifysources source, char ** argv,
                }
              } break;
 
-             case VERIFY_GRP:
+           case VERIFY_GRP:
                if (rpmdbFindByGroup(db, arg, &matches)) {
                    fprintf(stderr, 
                                _("group %s does not contain any packages\n"), 
@@ -228,11 +228,29 @@ int doVerify(char * prefix, enum verifysources source, char ** argv,
                }
                break;
 
-             case VERIFY_PATH:
-               if (*arg != '/') {
-                   if (realpath(arg, path) != NULL)
-                       arg = path;
+           case VERIFY_PATH:
+             if (*arg != '/') {
+               /* Using realpath on the arg isn't correct if the arg is a symlink,
+                * especially if the symlink is a dangling link.  What we should
+                * instead do is use realpath() on `.' and then append arg to
+                * it.
+                */
+              if (realpath(".", path) != NULL) {
+               if (path[strlen(path)] != '/') {
+                   if (strncat(path, "/", sizeof(path) - strlen(path) - 1) == NULL) {
+                       fprintf(stderr, _("maximum path length exceeded\n"));
+                       return 1;
+                   }
                }
+               /* now append the original file name to the real path */
+               if (strncat(path, arg, sizeof(path) - strlen(path) - 1) == NULL) {
+                   fprintf(stderr, _("maximum path length exceeded\n"));
+                   return 1;
+               }
+               arg = path;
+              }
+             }
+
                if (rpmdbFindByFile(db, arg, &matches)) {
                    fprintf(stderr, _("file %s is not owned by any package\n"), 
                                arg);
@@ -242,7 +260,7 @@ int doVerify(char * prefix, enum verifysources source, char ** argv,
                }
                break;
 
-             case VERIFY_PACKAGE:
+           case VERIFY_PACKAGE:
                rc = rpmdbFindByLabel(db, arg, &matches);
                if (rc == 1) 
                    fprintf(stderr, _("package %s is not installed\n"), arg);
@@ -254,8 +272,8 @@ int doVerify(char * prefix, enum verifysources source, char ** argv,
                }
                break;
 
-               case VERIFY_EVERY:
-                   ; /* nop */
+           case VERIFY_EVERY:
+               break;
            }
            if (rc)
                ec = rc;