diff options
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | ftp.c | 292 | ||||
-rw-r--r-- | ftp.h | 14 | ||||
-rw-r--r-- | install.c | 99 | ||||
-rw-r--r-- | lib/query.c | 27 | ||||
-rw-r--r-- | lib/rpmio.h | 2 | ||||
-rw-r--r-- | po/rpm.pot | 176 | ||||
-rw-r--r-- | popt/po/popt.pot | 2 | ||||
-rw-r--r-- | url.c | 324 | ||||
-rw-r--r-- | url.h | 19 | ||||
-rw-r--r-- | verify.c | 38 |
11 files changed, 594 insertions, 404 deletions
@@ -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"). @@ -34,6 +35,10 @@ - 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. @@ -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"); } } @@ -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 @@ -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); } diff --git a/lib/query.c b/lib/query.c index 10d3db31a..65e33e73b 100644 --- a/lib/query.c +++ b/lib/query.c @@ -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; } diff --git a/lib/rpmio.h b/lib/rpmio.h index a4ef31fdd..25804b49d 100644 --- a/lib/rpmio.h +++ b/lib/rpmio.h @@ -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; diff --git a/po/rpm.pot b/po/rpm.pot index 8e16d7eda..d40233531 100644 --- a/po/rpm.pot +++ b/po/rpm.pot @@ -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" diff --git a/popt/po/popt.pot b/popt/po/popt.pot index 8c3b4118d..51c452b5a 100644 --- a/popt/po/popt.pot +++ b/popt/po/popt.pot @@ -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" @@ -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; } @@ -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 } @@ -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; |